Page MenuHomeCode

No OneTemporary

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 @@
<?php
/**
* Autogenerable configuration file
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* @package Zed
* @subpackage Keruald
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @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 @@
<?php
/**
* Core: helper methods and main libraries loader
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* @package Zed
* @subpackage Keruald
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @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.
*
* <code>
* echo generate_random_string('AAA111'); //this could output SDQ245.
* </code>
*
* @author Pierre Habart <p.habart@ifrance.com>
*
* @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<strlen($format);$i++)
{
if (preg_match("/^[a-zA-Z]/",$format[$i]))
{
$add=$t_alphabet[mt_rand() % sizeof($t_alphabet)];
if (preg_match("/^[a-z]/",$format[$i]))
$add=strtolower($add);
}
elseif(preg_match("/^[0-9]/",$format[$i]))
$add=$t_number[mt_rand() % sizeof($t_number)];
else $add="?";
$str_to_return.=$add;
}
return $str_to_return;
}
//Plural management
/**
* Returns "s" when the $amount request a plural
* This function is a French plural helper.
*
* @param $amount the amount of objects
* @return string 's' if $amount implies a plural ; '' if it implies a singular.
*/
function s ($amount) {
if ($amount >= 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 '<pre>';
print_r($expression);
echo '</pre>';
}
//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:
* <code>
* $url = get_url('ship', $ship);
* echo $url; //if $ship contains S00001, this should print /ship/S00001
* </code>
*
* @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<br /><strong>Current value:</strong> $Config[SiteURL]<br /><strong>Expected value:</strong> 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 @@
+<?php
+
+/**
+ * Database calling class.
+ *
+ * Zed. The immensity of stars. The HyperShip. The people.
+ *
+ * (c) 2015, Dereckson, some rights reserved.
+ * Released under BSD license.
+ *
+ * This file provides a calling class, which read the configuration, ensures
+ * the database class for the db engine given in config exists and initializes
+ * it.
+ *
+ * The class to call is determined from the following preference:
+ * <code>
+ * $Config['database']['engine'] = 'MySQL'; //will use DatabaseMySQL class.
+ * </code>
+ *
+ * @package Zed
+ * @subpackage Database
+ * @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
+ * @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:
+ * <code>
+ * $Config['database']['engine'] = 'quux';
+ * $db = Database::load(); //Database:load() will call DatabaseQuux:load();
+ * </code>
+ *
+ * @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.<br />$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.<br />$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 @@
+<?php
+
+/**
+ * MySQL layer and helper class
+ *
+ * Zed. The immensity of stars. The HyperShip. The people.
+ *
+ * (c) 2010, Dereckson, some rights reserved.
+ * Released under BSD license.
+ *
+ * @package Zed
+ * @subpackage Keruald
+ * @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
+ * @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 @@
+<?php
+
+/**
+ * MySQLi layer and helper class
+ *
+ * Zed. The immensity of stars. The HyperShip. The people.
+ *
+ * (c) 2010, 2014, Dereckson, some rights reserved.
+ * Released under BSD license.
+ *
+ * @package Zed
+ * @subpackage Keruald
+ * @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
+ * @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 @@
-<?php
-
-/**
- * MySQL layer and helper class
- *
- * Zed. The immensity of stars. The HyperShip. The people.
- *
- * (c) 2010, Dereckson, some rights reserved.
- * Released under BSD license.
- *
- * @package Zed
- * @subpackage Keruald
- * @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
- * @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']);
-}

File Metadata

Mime Type
text/x-diff
Expires
Fri, Nov 15, 19:37 (1 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
20922
Default Alt Text
(55 KB)

Event Timeline