diff --git a/includes/config.php b/includes/config.php index acfcd60..967e155 100755 --- a/includes/config.php +++ b/includes/config.php @@ -1,270 +1,270 @@ * @copyright 2010 Sébastien Santoro aka Dereckson * @license http://www.opensource.org/licenses/bsd-license.php BSD * @version 0.1 * @link http://scherzo.dereckson.be/doc/zed * @link http://zed.dereckson.be/ * @filesource */ //////////////////////////////////////////////////////////////////////////////// /// /// /// I. SQL configuration /// /// /// //////////////////////////////////////////////////////////////////////////////// //SQL configuration -$Config['sql']['product'] = 'MySQL'; //Only MySQL is currently implemented -$Config['sql']['host'] = 'localhost'; -$Config['sql']['username'] = 'zed'; -$Config['sql']['password'] = 'zed'; -$Config['sql']['database'] = 'zed'; +$Config['database']['engine'] = 'MySQLi'; //MySQL, MySQLi +$Config['database']['host'] = 'localhost'; +$Config['database']['username'] = 'zed'; +$Config['database']['password'] = 'zed'; +$Config['database']['database'] = 'zed'; //SQL tables $prefix = ''; define('TABLE_API_KEYS', $prefix . 'api_keys'); define('TABLE_COMMENTS', $prefix . 'comments'); define('TABLE_CONTENT_FILES', $prefix . 'content_files'); define('TABLE_CONTENT_LOCATIONS', $prefix . 'content_locations'); define('TABLE_CONTENT_ZONES', $prefix . 'content_zones'); define('TABLE_CONTENT_ZONES_LOCATIONS', $prefix . 'content_zones_locations'); define('TABLE_LOG', $prefix . 'log'); define('TABLE_LOG_SMARTLINE', $prefix . 'log_smartline'); define('TABLE_MESSAGES', $prefix . 'messages'); define('TABLE_MOTD', $prefix . 'motd'); define('TABLE_PAGES', $prefix . 'pages'); define('TABLE_PAGES_EDITS', $prefix . 'pages_edits'); define('TABLE_PERSOS', $prefix . 'persos'); define('TABLE_PERSOS_FLAGS', $prefix . 'persos_flags'); define('TABLE_PERSOS_NOTES', $prefix . 'persos_notes'); define('TABLE_PORTS', $prefix . 'ports'); define('TABLE_PROFILES', $prefix . 'profiles'); define('TABLE_PROFILES_COMMENTS', $prefix . 'profiles_comments'); define('TABLE_PROFILES_PHOTOS', $prefix . 'profiles_photos'); define('TABLE_PROFILES_TAGS', $prefix . 'profiles_tags'); define('TABLE_REGISTRY', $prefix . 'registry'); define('TABLE_REQUESTS', $prefix . 'requests'); define('TABLE_REQUESTS_REPLIES', $prefix . 'requests_replies'); define('TABLE_SESSIONS', $prefix . 'sessions'); define('TABLE_SHIPS', $prefix . 'ships'); define('TABLE_USERS', $prefix . 'users'); define('TABLE_USERS_INVITES', $prefix . 'users_invites'); define('TABLE_USERS_AUTH', $prefix . 'users_auth'); //Geo tables define('TABLE_BODIES', $prefix . 'geo_bodies'); define('TABLE_LOCATIONS', $prefix . 'geo_locations'); //Well... it's a view define('TABLE_PLACES', $prefix . 'geo_places'); //////////////////////////////////////////////////////////////////////////////// /// /// /// II. Site configuration /// /// /// //////////////////////////////////////////////////////////////////////////////// //Default theme $Config['DefaultTheme'] = "Zed"; //Dates date_default_timezone_set("UTC"); //Secret key, used for some verification hashes in URLs or forms. $Config['SecretKey'] = 'Lorem ipsum dolor'; //When reading files, buffer size define('BUFFER_SIZE', 4096); //////////////////////////////////////////////////////////////////////////////// /// /// /// III. Script URLs /// /// /// //////////////////////////////////////////////////////////////////////////////// /* * Apache httpd, without mod_rewrite: * * Subdirectory: * - $Config['SiteURL'] = 'http://zed.dereckson.be/hypership/index.php'; * - $Config['BaseURL'] = '/hypership/index.php'; * * Root directory: * - $Config['SiteURL'] = 'http://zed.dereckson.be/index.php'; * - $Config['BaseURL'] = '/index.php'; * * Apache httpd, with mod_rewrite: * * Subdirectory: * - $Config['SiteURL'] = 'http://zed.dereckson.be/hypership'; * - $Config['BaseURL'] = '/hypership'; * * In .htaccess or your vhost definition: * RewriteEngine On * RewriteBase /hypership/ * RewriteCond %{REQUEST_FILENAME} !-f * RewriteCond %{REQUEST_FILENAME} !-d * RewriteRule . /hypership/index.php [L] * * Root directory: * - $Config['SiteURL'] = 'http://zed.dereckson.be'; * - $Config['BaseURL'] = ''; * * In .htaccess or your vhost definition: * RewriteEngine On * RewriteBase / * RewriteCond %{REQUEST_FILENAME} !-f * RewriteCond %{REQUEST_FILENAME} !-d * RewriteRule . /index.php [L] * * nginx: * * Use same config.php settings than Apache httpd, with mod_rewrite. * * In your server block: * location / { * #Serves static files if they exists, with one month cache * if (-f $request_filename) { * expires 30d; * break; * } * * #Sends all non existing file or directory requests to index.php * if (!-e request_filename) { * rewrite ^(.+)$ /index.php last; * #Or if you use a subdirectory: * #rewrite ^(.+)$ /hypership/index.php last; * } * } * * location ~ \.php$ { * #Your instructions to pass query to your FastCGI process, like: * fastcgi_pass 127.0.0.1:9000; * fastcgi_param SCRIPT_FILENAME /var/www/zed$fastcgi_script_name; * include fastcgi_params; * } * * * If you don't want to specify the server domain, you can use get_server_url: * $Config['SiteURL'] = get_server_url() . '/hypership'; * $Config['SiteURL'] = get_server_url(); * * * * !!! No trailing slash !!! * */ $Config['SiteURL'] = get_server_url(); $Config['BaseURL'] = ''; //AJAX callbacks URL $Config['DoURL'] = $Config['SiteURL'] . "/do.php"; //////////////////////////////////////////////////////////////////////////////// /// /// /// IV. Static content /// /// /// //////////////////////////////////////////////////////////////////////////////// //Where the static content is located? //Static content = 4 directories: js, css, img and content //On default installation, those directories are at site root. //To improve site performance, you can use a CDN for that. // //Recommanded setting: $Config['StaticContentURL'] = $Config['SiteURL']; //Or if Zed is the site root: $Config['StaticContentURL'] = ''; //With CoralCDN: $Config['StaticContentURL'] = . '.nyud.net'; // $Config['StaticContentURL'] = ''; //$Config['StaticContentURL'] = get_server_url() . '.nyud.net'; //Scenes define('SCENE_DIR', 'content/scenes'); define('SCENE_URL', $Config['StaticContentURL'] . '/' . SCENE_DIR); //Stories define('STORIES_DIR', "content/stories"); //Profile's photos define('PHOTOS_DIR', 'content/users/_photos'); define('PHOTOS_URL', $Config['StaticContentURL'] . '/' . PHOTOS_DIR); //ImageMagick paths //Be careful on Windows platform convert could match the NTFS convert command. $Config['ImageMagick']['convert'] = 'convert'; $Config['ImageMagick']['mogrify'] = 'mogrify'; $Config['ImageMagick']['composite'] = 'composite'; $Config['ImageMagick']['identify'] = 'identify'; //////////////////////////////////////////////////////////////////////////////// /// /// /// V. Caching /// /// /// //////////////////////////////////////////////////////////////////////////////// /* * Some data (Smarty, OpenID and sessions) are cached in the cache directory. * * Security tip: you can move this cache directory outside the webserver tree. */ define('CACHE_DIR', 'cache'); /* * Furthermore, you can also enable a cache engine, like memcached, to store * data from heavy database queries, or frequently accessed stuff. * * To use memcached: * - $Config['cache']['engine'] = 'memcached'; * - $Config['cache']['server'] = 'localhost'; * - $Config['cache']['port'] = 11211; * * To disable cache: * - $Config['cache']['engine'] = 'void'; * (or don't write nothing at all) */ $Config['cache']['engine'] = 'void'; //////////////////////////////////////////////////////////////////////////////// /// /// /// VI. Sessions and authentication code /// /// /// //////////////////////////////////////////////////////////////////////////////// //If you want to use a common table of sessions / user handling //with several websites, specify a different resource id for each site. $Config['ResourceID'] = 21; //Enable OpenID authentication //$Config['OpenID'] = true; //Enable YubiKey authentication //API 12940 //For YubiCloud API key - create yours at https://upgrade.yubico.com/getapikey/ //$Config['YubiCloud']['ClientID'] = 12345; //$Config['YubiCloud']['SecretKey'] = 'Base64SecretKeyHere'; //PHP variables ini_set('session.serialize_handler', 'wddx'); ini_set('session.save_path', CACHE_DIR . '/sessions'); ini_set('session.gc_maxlifetime', 345600); //4 days, for week-end story pause and continue url //////////////////////////////////////////////////////////////////////////////// /// /// /// VII. Builder /// /// /// //////////////////////////////////////////////////////////////////////////////// //Zed can invoke a slighty modified version of HOTGLUE to build zones. $Config['builder']['hotglue']['enable'] = true; $Config['builder']['hotglue']['URL'] = '/apps/hotglue/index.php'; diff --git a/includes/core.php b/includes/core.php index ee1c6d6..3ebbd98 100755 --- a/includes/core.php +++ b/includes/core.php @@ -1,664 +1,664 @@ * @copyright 2010 Sébastien Santoro aka Dereckson * @license http://www.opensource.org/licenses/bsd-license.php BSD * @version 0.1 * @link http://scherzo.dereckson.be/doc/zed * @link http://zed.dereckson.be/ * @filesource */ //////////////////////////////////////////////////////////////////////////////// /// /// /// Configures PHP and loads site-wide used libraries /// /// /// //////////////////////////////////////////////////////////////////////////////// -//No register globals -ini_set('register_globals', 'off'); error_reporting(E_ALL & ~E_NOTICE); +include_once("config.php"); +include_once("error.php"); -//Load libraries -include_once("config.php"); //Site config -include_once("error.php"); //Error management -include_once("mysql.php"); //MySQL layer -include_once("sessions.php"); //Sessions handler -include_once("autoload.php"); //__autoload() +include_once("db/Database.php"); +$db = Database::load(); +Database::cleanupConfiguration(); + +include_once("sessions.php"); +include_once("autoload.php"); //////////////////////////////////////////////////////////////////////////////// /// /// /// Information helper methods /// /// /// //////////////////////////////////////////////////////////////////////////////// /** * Gets the nickname from the specified perso ID * * @param integer $perso_id The specified perso ID * @return string The perso's nickname */ function get_name ($perso_id) { global $db; $perso_id = $db->sql_escape($perso_id); $sql = 'SELECT perso_nickname FROM '. TABLE_PERSOS . " WHERE perso_id = '$perso_id'"; if (!$result = $db->sql_query($sql)) message_die(SQL_ERROR, "Can't query persos table.", '', __LINE__, __FILE__, $sql); $row = $db->sql_fetchrow($result); return $row['perso_nickname']; } /** * Gets the user ID from the specified username * * @param string $username The username * @return integer the user ID */ function get_userid ($username) { global $db; $username = $db->sql_escape($username); $sql = 'SELECT user_id FROM '. TABLE_USERS . " WHERE username LIKE '$username'"; if (!$result = $db->sql_query($sql)) message_die(SQL_ERROR, "Can't query users table.", '', __LINE__, __FILE__, $sql); $row = $db->sql_fetchrow($result); return $row['user_id']; } /** * Gets an information from the application global registry * * @param string $key the registry's key * @return string The key value */ function registry_get ($key) { global $db; $key = $db->sql_escape($key); $sql = "SELECT registry_value FROM " . TABLE_REGISTRY . " WHERE registry_key = '$key'"; if (!$result = $db->sql_query($sql)) message_die(SQL_ERROR, "Can't read registry.", '', __LINE__, __FILE__, $sql); $row = $db->sql_fetchrow($result); return $row['registry_value']; } /** * Sets an information in the application global registry * * @param string $key the registry key * @param string $value the value to store at the specified registry key */ function registry_set ($key, $value) { global $db; $key = $db->sql_escape($key); $value = $db->sql_escape($value); $sql = "REPLACE INTO " . TABLE_REGISTRY . " (registry_key, registry_value) VALUES ('$key', '$value')"; if (!$db->sql_query($sql)) message_die(SQL_ERROR, "Can't update registry", '', __LINE__, __FILE__, $sql); } //////////////////////////////////////////////////////////////////////////////// /// /// /// Misc helper methods /// /// /// //////////////////////////////////////////////////////////////////////////////// /** * Generates a random string, according the specified format. * * * echo generate_random_string('AAA111'); //this could output SDQ245. * * * @author Pierre Habart * * @param string $format The format e.g. AAA111 * @return string a random string */ function generate_random_string ($format) { mt_srand((double)microtime()*1000000); $str_to_return=""; $t_alphabet=explode(",","A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z"); $t_number=explode(",","1,2,3,4,5,6,7,8,9,0"); for ($i=0;$i= 2 || $amount <= -2) return "s"; } /** * Returns "x" when the $amount request a plural * This function is a French plural helper. * * @param $amount the amount of objects * @return string 'x' if $amount implies a plural ; '' if it implies a singular. */ function x ($amount) { if ($amount >= 2 || $amount <= -2) return "x"; } //Debug /** * Prints human-readable information about a variable. * * It behaves like the print_r command, but the output is enclosed in pre tags, * to have a preformatted HTML output. * * @param mixed $expression The expression to be printed */ function dprint_r ($expression) { echo '
';
     print_r($expression);
     echo '
'; } //GUID /** * Generates a GUID, or more precisely an UUID * @link http://en.wikipedia.org/wiki/Universally_Unique_Identifier Wikipedia, Universally Unique Identifier. * * A UUID is a 36 chars string of 32 hexadecimal and 4 dashes, with a * very high probability to be unique. * * @return string the UUID */ function new_guid() { $characters = explode(",","a,b,c,d,e,f,0,1,2,3,4,5,6,7,8,9"); $guid = ""; for ($i = 0 ; $i < 36 ; $i++) { if ($i == 8 || $i == 13 || $i == 18 || $i == 23) { $guid .= "-"; } else { $guid .= $characters[mt_rand() % sizeof($characters)]; } } return $guid; } /** * Determines if the expression is a valid UUID (a guid without {}). * @see new_guid * * @param string $expression the expression to chjeck * @return boolean true if the specified expression is a valid UUID ; otherwise, false. */ function is_guid ($expression) { //We avoid regexp to speed up the check //A guid is a 36 characters string if (strlen($expression) != 36) return false; $expression = strtolower($expression); for ($i = 0 ; $i < 36 ; $i++) { if ($i == 8 || $i == 13 || $i == 18 || $i == 23) { //with dashes if ($expression[$i] != "-") return false; } else { //and numbers if (!is_numeric($expression[$i]) && $expression[$i] != 'a' && $expression[$i] != 'b' && $expression[$i] != 'c' && $expression[$i] != 'd' && $expression[$i] != 'e' && $expression[$i] != 'f' ) return false; } } return true; } /** * Gets file extension * * @param string $file the file to get the extension * @return string the extension froùm the specified tfile */ function get_extension ($file) { $dotPosition = strrpos($file, "."); return substr($file, $dotPosition + 1); } /** * Determines if a string starts with specified substring * * @param string $haystack the string to check * @param string $needle the substring to determines if it's the start * @param boolean $case_sensitive determines if the search must be case sensitive * @return boolean true if $haystack starts with $needle ; otherwise, false. */ function string_starts_with ($haystack, $needle, $case_sensitive = true) { if (!$case_sensitive) { $haystack = strtoupper($haystack); $needle = strtoupper($needle); } if ($haystack == $needle) return true; return strpos($haystack, $needle) === 0; } /** * Inserts a message into the supralog * * @param string $category the entry category * @param string $message the message to log * @param string $source the entry source. */ function supralog ($category, $message, $source = null) { global $db, $CurrentUser, $CurrentPerso; $category = $db->sql_query_express($category); $message = $db->sql_query_express($message); $source = $db->sql_query_express($source ? $source : $_SERVER['SERVER_ADDR']); $ip = $_SERVER['REMOTE_ADDR']; $sql = "INSERT INTO " . TABLE_LOG . " (entry_ip, user_id, perso_id, entry_category, entry_message, entry_source) VALUES ('$ip', $CurrentUser->id, $CurrentPerso->id, '$category', '$message', '$source')"; if ( !($result = $db->sql_query($sql)) ) message_die(SQL_ERROR, "Can't log this entry.", '', __LINE__, __FILE__, $sql); } //////////////////////////////////////////////////////////////////////////////// /// /// /// Localization (l10n) /// /// /// //////////////////////////////////////////////////////////////////////////////// /** * Defines the LANG constant, to lang to print * * This information is contained in the session, or if not yet defined, * it's to determine according the user's browser preferences. * @see find_lang */ function initialize_lang () { //If $_SESSION['lang'] doesn't exist yet, find a common language if (!array_key_exists('lang', $_SESSION)) { $lang = find_lang(); $_SESSION['lang'] = $lang ? $lang : '-'; } if ($_SESSION['lang'] != '-') define('LANG', $_SESSION['lang']); } /** * Gets a common lang spoken by the site and the user's browser * @see get_http_accept_languages * * @return string the language */ function find_lang () { if (file_exists('lang') && is_dir('lang')) { //Gets lang/ subdirectories: this is the list of available languages $handle = opendir('lang'); while ($file = readdir($handle)) { if ($file != '.' && $file != '..' && is_dir("lang/$file")) { $langs[] = $file; } } //The array $langs contains now the language available. //Gets the langs the user should want: if (!$userlangs = get_http_accept_languages()) return; //Gets the intersection between the both languages arrays //If it matches, returns first result $intersect = array_intersect($userlangs, $langs); if (count($intersect)) { return $intersect[0]; } //Now it's okay with Opera and Firefox but Internet Explorer will //by default return en-US and not en or fr-BE and not fr, so second pass foreach ($userlangs as $userlang) { $lang = explode('-', $userlang); if (count($lang) > 1) $userlangs2[] = $lang[0]; } $intersect = array_intersect($userlangs2, $langs); if (count($intersect)) { return $intersect[0]; } } } /** * Gets the languages accepted by the browser, by order of priority. * * This will read the HTTP_ACCEPT_LANGUAGE variable sent by the browser in the * HTTP request. * * @return Array an array of string, each item a language accepted by browser */ function get_http_accept_languages () { //What language to print is sent by browser in HTTP_ACCEPT_LANGUAGE var. //This will be something like en,fr;q=0.8,fr-fr;q=0.5,en-us;q=0.3 if (!array_key_exists('HTTP_ACCEPT_LANGUAGE', $_SERVER)) { return null; } $http_accept_language = explode(',', $_SERVER["HTTP_ACCEPT_LANGUAGE"]); foreach ($http_accept_language as $language) { $userlang = explode(';q=', $language); if (count($userlang) == 1) { $userlangs[] = array(1, $language); } else { $userlangs[] = array($userlang[1], $userlang[0]); } } rsort($userlangs); foreach ($userlangs as $userlang) { $result[] = $userlang[1]; } return $result; } /** * Loads specified language Smarty configuration file * * @param string $file the file to load * @param mixed $sections array of section names, single section or null */ function lang_load ($file, $sections = null) { global $smarty; //Loads English file as fallback if some parameters are missing if (file_exists("lang/en/$file")) $smarty->configLoad("lang/en/$file", $sections); //Loads wanted file (if it exists and a language have been defined) if (defined('LANG') && LANG != 'en' && file_exists('lang/' . LANG . '/' . $file)) $smarty->configLoad('lang/' . LANG . '/' . $file, $sections); } /** * Gets a specified language expression defined in configuration file * * @param string $key the configuration key matching the value to get * @return string The value in the configuration file */ function lang_get ($key) { global $smarty; $smartyConfValue = $smarty->config_vars[$key]; return $smartyConfValue ? $smartyConfValue : "#$key#"; } //////////////////////////////////////////////////////////////////////////////// /// /// /// Zed date and time helper methods /// /// /// //////////////////////////////////////////////////////////////////////////////// /** * Converts a YYYYMMDD or YYYY-MM-DD timestamp to unixtime * @link http://en.wikipedia.org/wiki/Unix_time Unix time * * @param string $timestamp the timestamp to convert * @return inteeger the unixtime */ function to_unixtime ($timestamp) { switch (strlen($timestamp)) { case 8: //YYYYMMDD return mktime(0, 0, 0, substr($timestamp, 4, 2), substr($timestamp, 6, 2), substr($timestamp, 0, 4)); case 10: //YYYY-MM-DD return mktime(0, 0, 0, substr($timestamp, 5, 2), substr($timestamp, 8, 2), substr($timestamp, 0, 4)); default: throw new Exception("timestamp is not a valid YYYYMMDD or YYYY-MM-DD timestamp: $timestamp"); } } /** * Converts a unixtime to the YYYYMMDD or YYYY-MM-DD timestamp format * @see to_unixtime * * @param int $unixtime the time to convert * @param int $format 8 or 10. If 8 (default), will output YYYYMMDD. If 10, YYYY-MM-DD. * @return string the timestamp */ function to_timestamp ($unixtime = null, $format = 8) { //If no parameter is specified (or null, or false), current time is used //==== allows to_timestamp(0) to return correct 1970-1-1 value. if ($unixtime === null || $unixtime === false) $unixtime = time(); switch ($format) { case 8: //YYYYMMDD return date('Ymd', $unixtime); case 10: //YYYY-MM-DD return date('Y-m-d', $unixtime); default: throw new Exception("format must be 8 (YYYYMMDD) or 10 (YYYY-MM-DD) and not $format."); } } /** * Converts a unixtime to the Hypership time format or gets the current hypership time. * @link http://en.wikipedia.org/wiki/Unix_time * @link http://www.purl.org/NET/Zed/blog/HyperShipTime * * @param int $unixtime The unixtime to convert to HyperShip time. If omitted, the current unixtime. * @return string The HyperShip time */ function get_hypership_time ($unixtime = null) { //If unixtime is not specified, it's now if ($unixtime === null) $unixtime = time(); //Hypership time is a count of days since launch @ 2010-07-03 00:00:00 //Followed by a fraction of the current day /1000, like the internet time //but in UTC timezone and not Switzerland CET/CEST. //We don't need to use floor(), as we output the result at int, truncating //automatically decimal values instead of round it (like in C). $seconds = $unixtime - 1278115200; $days = $seconds / 86400; $fraction = (abs($seconds) % 86400) / 86.4; return sprintf("%d.%03d", $days, $fraction); } //////////////////////////////////////////////////////////////////////////////// /// /// /// URL helpers functions /// /// /// //////////////////////////////////////////////////////////////////////////////// /** * Gets the URL matching the specified resource. * * Example: * * $url = get_url('ship', $ship); * echo $url; //if $ship contains S00001, this should print /ship/S00001 * * * @param string $resource,... the resources * @return string the URL matching the specified resource */ function get_url () { global $Config; if (func_num_args() > 0) { $pieces = func_get_args(); return $Config['BaseURL'] . '/' . implode('/', $pieces); } elseif ($Config['BaseURL'] == "" || $Config['BaseURL'] == $_SERVER["PHP_SELF"]) { return "/"; } else { return $Config['BaseURL']; } } /** * Gets the current page URL * * @return string the current page URL */ function get_page_url () { $url = $_SERVER['SCRIPT_NAME'] . $_SERVER['PATH_INFO']; if (substr($url, -10) == $_SERVER["PHP_SELF"]) { return substr($url, 0, -9); } return $url; } /** * Gets the server URL * @todo find a way to detect https:// on non standard port * * @return string the server URL */ function get_server_url () { switch ($port = $_SERVER['SERVER_PORT']) { case '80': return "http://$_SERVER[SERVER_NAME]"; case '443': return "https://$_SERVER[SERVER_NAME]"; default: return "http://$_SERVER[SERVER_NAME]:$_SERVER[SERVER_PORT]"; } } /** * Gets $_SERVER['PATH_INFO'] or computes the equivalent if not defined. * * This function allows the entry point controllers to get the current URL * in a consistent way, for any redirection configuration * * So with /foo/bar, /index.php/foo/bar, /zed/index.php/foo/bar or /zed/foo/bar * get_current_url will return /foo/bar * * @return string the relevant URL part */ function get_current_url () { global $Config; //Gets relevant URL part from relevant $_SERVER variables if (array_key_exists('PATH_INFO', $_SERVER)) { //Without mod_rewrite, and url like /index.php/controller //we use PATH_INFO. It's the easiest case. return $_SERVER["PATH_INFO"]; } //In other cases, we'll need to get the relevant part of the URL $current_url = get_server_url() . $_SERVER['REQUEST_URI']; //Relevant URL part starts after the site URL $len = strlen($Config['SiteURL']); //We need to assert it's the correct site if (substr($current_url, 0, $len) != $Config['SiteURL']) { dieprint_r(GENERAL_ERROR, "Edit includes/config.php and specify the correct site URL
Current value: $Config[SiteURL]
Expected value: a string starting by " . get_server_url(), "Setup"); } if (array_key_exists('REDIRECT_URL', $_SERVER)) { //With mod_rewrite, we can use REDIRECT_URL //We takes the end of the URL, ie *FROM* $len position return substr(get_server_url() . $_SERVER["REDIRECT_URL"], $len); } //Last possibility: use REQUEST_URI, but remove QUERY_STRING //If you need to edit here, use $_SERVER['REQUEST_URI'] //but you need to discard $_SERVER['QUERY_STRING'] //We takes the end of the URL, ie *FROM* $len position $url = substr(get_server_url() . $_SERVER["REQUEST_URI"], $len); //But if there are a query string (?action=... we need to discard it) if ($_SERVER['QUERY_STRING']) { return substr($url, 0, strlen($url) - strlen($_SERVER['QUERY_STRING']) - 1); } return $url; } /** * Gets an array of url fragments to be processed by controller * @see get_current_url * * This method is used by the controllers entry points to know the URL and * call relevant subcontrollers. * * @return Array an array of string, one for each URL fragment */ function get_current_url_fragments () { $url_source = get_current_url(); if ($url_source == $_SERVER["PHP_SELF"]) return array(); return explode('/', substr($url_source, 1)); } //////////////////////////////////////////////////////////////////////////////// /// /// /// URL xmlHttpRequest helpers functions /// /// /// //////////////////////////////////////////////////////////////////////////////// /** * Gets an hash value to check the integrity of URLs in /do.php calls * * @param Array $args the args to compute the hash * @return the hash paramater for your xmlHttpRequest url */ function get_xhr_hash ($args) { global $Config; array_shift($args); return md5($_SESSION['ID'] . $Config['SecretKey'] . implode('', $args)); } /** * Gets the URL to call do.php, the xmlHttpRequest controller * * @return string the xmlHttpRequest url, with an integrity hash */ function get_xhr_hashed_url () { global $Config; $args = func_get_args(); $args[] = get_xhr_hash($args); return $Config['DoURL'] . '/' . implode('/', $args); } /** * Gets the URL to call do.php, the xmlHttpRequest controller * * @return string the xmlHttpRequest url */ function get_xhr_url () { global $Config; $args = func_get_args(); return $Config['DoURL'] . '/' .implode('/', $args); } diff --git a/includes/db/Database.php b/includes/db/Database.php new file mode 100755 index 0000000..f7be960 --- /dev/null +++ b/includes/db/Database.php @@ -0,0 +1,84 @@ + + * $Config['database']['engine'] = 'MySQL'; //will use DatabaseMySQL class. + * + * + * @package Zed + * @subpackage Database + * @author Sébastien Santoro aka Dereckson + * @copyright 2015 Sébastien Santoro aka Dereckson + * @license http://www.opensource.org/licenses/bsd-license.php BSD + * @link http://scherzo.dereckson.be/doc/zed + * @link http://zed.dereckson.be/ + * @filesource + */ + +/** + * Databasecaller + */ +class Database { + /** + * Gets the database instance, initializing it if needed + * + * The correct database instance to initialize will be determined from the + * $Config['database']['engine'] preference. + * + * The database class to use will be Database + (preference engine, capitalized) + * + * This method will creates an instance of the specified object, + * calling the load static method from this object class. + * + * Example: + * + * $Config['database']['engine'] = 'quux'; + * $db = Database::load(); //Database:load() will call DatabaseQuux:load(); + * + * + * @return Database the database instance + */ + static function load () { + global $Config; + if ( + !array_key_exists('database', $Config) || + !array_key_exists('engine', $Config['database']) + ) { + //database is not configured or engine is not specified + message_die(GENERAL_ERROR, 'A database engine (a MySQL variant is recommended) should be configured. Please ensure you have a ["database"]["engine"] value in the configuration.', "Setup issue"); + } else { + //engine is specified in the configuration + $engine = $Config['database']['engine']; + } + + $engine_file = 'includes/db/' . $engine . '.php'; + $engine_class = 'Database' . ucfirst($engine); + + if (!file_exists($engine_file)) { + message_die(GENERAL_ERROR, "Can't initialize $engine database engine.
$engine_file not found.", 'Setup issue'); + } + + require_once($engine_file); + if (!class_exists($engine_class)) { + message_die(GENERAL_ERROR, "Can't initialize $engine database engine.
$engine_class class not found.", 'Setup issue'); + } + return call_user_func(array($engine_class, 'load')); + } + + static function cleanupConfiguration () { + global $Config; + unset($Config['database']['password']); + } +} diff --git a/includes/db/MySQL.php b/includes/db/MySQL.php new file mode 100755 index 0000000..aa4b2f2 --- /dev/null +++ b/includes/db/MySQL.php @@ -0,0 +1,186 @@ + + * @copyright 2010 Sébastien Santoro aka Dereckson + * @license http://www.opensource.org/licenses/bsd-license.php BSD + * @version 0.1 + * @link http://scherzo.dereckson.be/doc/zed + * @link http://zed.dereckson.be/ + * @filesource + */ + +/** + * SQL database class + * + * This is the MySQL implementation of our SQL abstraction layer + */ +class sql_db { + /* + * @var int the connection identifier + */ + private $id; + + /** + * Initializes a new instance of the database abstraction class, for MySQL engine + * + * @param string $host the SQL server to connect [optionnal, by default localhost] + * @param string $username the SQL username [optionnal, by default root] + * @param string $password the SQL password [optionnal, by default blank] + * @param string $database the database to select [optionnal] + */ + function __construct($host = 'localhost', $username = 'root', $password = '' , $database = '') { + //Checks extension requirement + if (!function_exists("mysql_connect")) { + message_die(GENERAL_ERROR, "You've chosen to use a MySQL database engine, but the MySQL extension is missing.", "Setup issue"); + } + + //Connects to the MySQL server + $this->id = @mysql_connect($host, $username, $password) or $this->sql_die(); //or die ("Can't connect to SQL server."); + + //Selects database + if ($database != '') { + mysql_select_db($database, $this->id); + } + } + + + /** + * Outputs a can't connect to the SQL server message and exits. + * It's called on connect failure + */ + function sql_die () { + //You can custom here code when you can't connect to SQL server + //e.g. in a demo or appliance context, include('start.html'); exit; + //die ("Can't connect to SQL server."); + include('start.html'); + exit; + } + + /** + * Sends a unique query to the database + * + * @param string $query the query to execute + * @return resource if the query is successful, a resource identifier ; otherwise, false + */ + function sql_query ($query) { + return mysql_query($query, $this->id); + } + + /** + * Fetches a row of result into an associative array + * + * @param resource $result The result that is being evaluated, from sql_query + * @return array an associative array with columns names as keys and row values as values + */ + function sql_fetchrow ($result) { + return mysql_fetch_array($result); + } + + /** + * Gets last SQL error information + * + * @return array an array with two keys, code and message, containing error information + */ + function sql_error () { + $error['code'] = mysql_errno($this->id); + $error['message'] = mysql_error($this->id); + return $error; + } + + + /** + * Gets the number of rows affected or returned by a query + * + * @return int the number of rows affected (delete/insert/update) or the number of rows in query result + */ + function sql_numrows ($result) { + return mysql_num_rows($result); + } + + /** + * Gets the primary key value of the last query (works only in INSERT context) + * + * @return int the primary key value + */ + function sql_nextid () { + return mysql_insert_id($this->id); + } + + /** + * Express query method, returns an immediate and unique result + * + * @param string $query the query to execute + * @param string $error_message the error message + * @param boolean $return_as_string return result as string, and not as an array + * @return mixed the row or the scalar result + */ + function sql_query_express ($query = '', $error_message = "Impossible d'exécuter cette requête.", $return_as_string = true) { + if ($query === '' || $query === false || $query === null) { + //No query, no value + return ''; + } elseif (!$result = $this->sql_query($query)) { + message_die(SQL_ERROR, $error_message, '', __LINE__, __FILE__, $query); + } else { + //Fetches row + $row = $this->sql_fetchrow($result); + + //If $return_as_string is true, returns first query item (scalar mode) ; otherwise, returns row + return $return_as_string ? $row[0] : $row; + } + } + + /** + * Escapes a SQL expression + * + * @param string $expression The expression to escape + * @return string The escaped expression + */ + function sql_escape ($expression) { + return mysql_real_escape_string($expression); + } + + /* + * Sets the client character set (requires MySQL 5.0.7+). + * + * @param string $encoding the charset encoding to set + */ + function set_charset ($encoding) { + if (function_exists('mysql_set_charset')) { + //>=PHP 5.2.3 + mysql_set_charset($encoding, $this->id); + } else { + //Old PHP version + $this->sql_query("SET NAMES '$encoding'"); + } + } + + /** + * Loads a database instance, connected and ready to process queries. + */ + static function load () { + global $Config; + + //Creates an instance of this database class with configuration values + $db = new self( + $Config['database']['host'], + $Config['database']['username'], + $Config['database']['password'], + $Config['database']['database'] + ); + + //Sets SQL connexion in UTF-8. + $db->set_charset('utf8'); + + return $db; + } +} diff --git a/includes/db/MySQLi.php b/includes/db/MySQLi.php new file mode 100644 index 0000000..d86fc45 --- /dev/null +++ b/includes/db/MySQLi.php @@ -0,0 +1,171 @@ + + * @copyright 2014 Sébastien Santoro aka Dereckson + * @license http://www.opensource.org/licenses/bsd-license.php BSD + * @link http://scherzo.dereckson.be/doc/zed + * @link http://zed.dereckson.be/ + * @filesource + */ + +/** + * SQL layer and helper class: MySQLi + * + * @package Keruald + * @subpackage Keruald + * @copyright Copyright (c) 2010, Sébastien Santoro aka Dereckson + * @license Released under BSD license + * @version 0.1 + */ +class DatabaseMySQLi { + /* + * @var int the connection identifier + */ + private $db; + + /** + * Initializes a new instance of the database abstraction class, for MySQLi engine + */ + function __construct($host = 'localhost', $username = '', $password = '', $database = '') { + //Checks extension requirement + if (!class_exists("mysqli")) { + message_die(GENERAL_ERROR, "You've chosen to use a MySQLi database engine, but the MySQLi extension is missing.", "Setup issue"); + } + + //Connects to MySQL server + $this->db = new mysqli($host, $username, $password) or $this->sql_die(); + + //Selects database + if ($database != '') { + $this->db->select_db($database); + } + } + + /** + * Outputs a can't connect to the SQL server message and exits. + * It's called on connect failure + */ + private function sql_die () { + //You can custom here code when you can't connect to SQL server + //e.g. in a demo or appliance context, include('start.html'); exit; + die ("Can't connect to SQL server."); + } + + /** + * Sends a unique query to the database + * + * @return mixed if the query is successful, a mysqli_result instance ; otherwise, false + */ + function sql_query ($query) { + return $this->db->query($query); + } + + /** + * Fetches a row of result into an associative array + * + * @return array an associative array with columns names as keys and row values as values + */ + function sql_fetchrow ($result) { + return $result->fetch_array(); + } + + /** + * Gets last SQL error information + * + * @return array an array with two keys, code and message, containing error information + */ + function sql_error () { + return [ + 'code' => $this->db->errno, + 'message' => $this->db->error + ]; + } + + /** + * Gets the number of rows affected or returned by a query + * + * @return int the number of rows affected (delete/insert/update) or the number of rows in query result + */ + function sql_numrows ($result) { + return $result->num_rows; + } + + /** + * Gets the primary key value of the last query (works only in INSERT context) + * + * @return int the primary key value + */ + function sql_nextid () { + return $this->db->insert_id; + } + + /** + * Express query method, returns an immediate and unique result + * + * @param string $query the query to execute + * @param string $error_message the error message + * @param boolean $return_as_string return result as string, and not as an array + * @return mixed the row or the scalar result + */ + function sql_query_express ($query = '', $error_message = "Impossible d'exécuter cette requête.", $return_as_string = true) { + if ($query === '' || $query === false || $query === null) { + //No query, no value + return ''; + } elseif (!$result = $this->sql_query($query)) { + //An error have occured + message_die(SQL_ERROR, $error_message, '', '', '', $query); + } else { + //Fetches row + $row = $this->sql_fetchrow($result); + + //If $return_as_string is true, returns first query item (scalar mode) ; otherwise, returns row + return $return_as_string ? $row[0] : $row; + } + } + + /* + * Escapes a SQL expression + * @param string expression The expression to escape + * @return string The escaped expression + */ + function sql_escape ($expression) { + return $this->db->real_escape_string($expression); + } + + /** + * Sets charset + */ + function set_charset ($encoding) { + $this->db->set_charset($encoding); + } + + /** + * Loads a database instance, connected and ready to process queries. + */ + static function load () { + global $Config; + + //Creates an instance of this database class with configuration values + $db = new self( + $Config['database']['host'], + $Config['database']['username'], + $Config['database']['password'], + $Config['database']['database'] + ); + + //Sets SQL connexion in UTF-8. + $db->set_charset('utf8'); + + return $db; + } +} diff --git a/includes/mysql.php b/includes/mysql.php deleted file mode 100755 index 6ae070d..0000000 --- a/includes/mysql.php +++ /dev/null @@ -1,187 +0,0 @@ - - * @copyright 2010 Sébastien Santoro aka Dereckson - * @license http://www.opensource.org/licenses/bsd-license.php BSD - * @version 0.1 - * @link http://scherzo.dereckson.be/doc/zed - * @link http://zed.dereckson.be/ - * @filesource - */ - -if (!defined('SQL_LAYER')) { - /** - * Defines the SQL engine layer implented for our SQL abstraction class: - * MySQL - */ - define('SQL_LAYER', 'mysql'); - - /** - * SQL database class - * - * This is the MySQL implementation of our SQL abstraction layer - */ - class sql_db { - /* - * @var int the connection identifier - */ - private $id; - - /** - * Initializes a new instance of the database abstraction class, for MySQL engine - * - * @param string $host the SQL server to connect [optionnal, by default localhost] - * @param string $username the SQL username [optionnal, by default root] - * @param string $password the SQL password [optionnal, by default blank] - * @param string $database the database to select [optionnal] - */ - function __construct($host = 'localhost', $username = 'root', $password = '' , $database = '') { - //Checks extension requirement - if (!function_exists("mysql_connect")) { - message_die(GENERAL_ERROR, "You've chosen to use a MySQL database engine, but the MySQL extension is missing.", "Setup issue"); - } - - //Connects to the MySQL server - $this->id = @mysql_connect($host, $username, $password) or $this->sql_die(); //or die ("Can't connect to SQL server."); - - //Selects database - if ($database != '') { - mysql_select_db($database, $this->id); - } - } - - - /** - * Outputs a can't connect to the SQL server message and exits. - * It's called on connect failure - */ - function sql_die () { - //You can custom here code when you can't connect to SQL server - //e.g. in a demo or appliance context, include('start.html'); exit; - //die ("Can't connect to SQL server."); - include('start.html'); - exit; - } - - /** - * Sends a unique query to the database - * - * @param string $query the query to execute - * @return resource if the query is successful, a resource identifier ; otherwise, false - */ - function sql_query ($query) { - return mysql_query($query, $this->id); - } - - /** - * Fetches a row of result into an associative array - * - * @param resource $result The result that is being evaluated, from sql_query - * @return array an associative array with columns names as keys and row values as values - */ - function sql_fetchrow ($result) { - return mysql_fetch_array($result); - } - - /** - * Gets last SQL error information - * - * @return array an array with two keys, code and message, containing error information - */ - function sql_error () { - $error['code'] = mysql_errno($this->id); - $error['message'] = mysql_error($this->id); - return $error; - } - - - /** - * Gets the number of rows affected or returned by a query - * - * @return int the number of rows affected (delete/insert/update) or the number of rows in query result - */ - function sql_numrows ($result) { - return mysql_num_rows($result); - } - - /** - * Gets the primary key value of the last query (works only in INSERT context) - * - * @return int the primary key value - */ - function sql_nextid () { - return mysql_insert_id($this->id); - } - - /** - * Express query method, returns an immediate and unique result - * - * @param string $query the query to execute - * @param string $error_message the error message - * @param boolean $return_as_string return result as string, and not as an array - * @return mixed the row or the scalar result - */ - function sql_query_express ($query = '', $error_message = "Impossible d'exécuter cette requête.", $return_as_string = true) { - if ($query === '' || $query === false || $query === null) { - //No query, no value - return ''; - } elseif (!$result = $this->sql_query($query)) { - message_die(SQL_ERROR, $error_message, '', __LINE__, __FILE__, $query); - } else { - //Fetches row - $row = $this->sql_fetchrow($result); - - //If $return_as_string is true, returns first query item (scalar mode) ; otherwise, returns row - return $return_as_string ? $row[0] : $row; - } - } - - /** - * Escapes a SQL expression - * - * @param string $expression The expression to escape - * @return string The escaped expression - */ - function sql_escape ($expression) { - return mysql_real_escape_string($expression); - } - - /* - * Sets the client character set (requires MySQL 5.0.7+). - * - * @param string $encoding the charset encoding to set - */ - function set_charset ($encoding) { - if (function_exists('mysql_set_charset')) { - //>=PHP 5.2.3 - mysql_set_charset($encoding, $this->id); - } else { - //Old PHP version - $this->sql_query("SET NAMES '$encoding'"); - } - } - } - - /** - * The main sql_db instance - * - * @global sql_db $db - */ - $db = new sql_db($Config['sql']['host'], $Config['sql']['username'], $Config['sql']['password'], $Config['sql']['database']); - $db->set_charset('utf8'); - - //By security, we unset the SQL parameters, so you can safely output Zed - //config parts (there's still the problem of the secret key, but it's less - //a security problem than database password) - unset($Config['sql']); -}