Page MenuHomeCode

No OneTemporary

diff --git a/api.php b/api.php
index d1d1610..8cc5490 100644
--- a/api.php
+++ b/api.php
@@ -1,320 +1,318 @@
<?php
/**
* API entry point
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* @package Zed
* @subpackage EntryPoints
* @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
* @todo Consider to output documentation on / and /ship queries
* @todo /app/getdata
*/
//API Preferences
define('URL', 'http://' . $_SERVER['HTTP_HOST'] . '/index.php');
//Pluton library
require_once('includes/core.php');
require_once('includes/config.php');
//API libs
require_once('includes/api/api_helpers.php');
require_once('includes/api/cerbere.php');
//Use our URL controller method if you want to mod_rewrite the API
$Config['SiteURL'] = get_server_url() . $_SERVER["PHP_SELF"];
$url = get_current_url_fragments();
switch ($module = $url[0]) {
/* -------------------------------------------------------------
Site API
/time
/location
/coordinates
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case '':
//Nothing to do
//TODO: offer documentation instead
die();
case 'time':
//Hypership time
api_output(get_hypership_time(), "time");
break;
case 'location':
//Checks creditentials
cerbere();
//Gets location info
require_once("includes/geo/location.php");
$location = new GeoLocation($url[1], $url[2]);
api_output($location, "location");
break;
case 'coordinates':
//Checks creditentials
cerbere();
//Get coordiantes
api_output(GeoGalaxy::get_coordinates(), 'galaxy', 'object');
break;
/* -------------------------------------------------------------
Ship API
/authenticate
/appauthenticate
/appauthenticated
/move
/land
/flyout
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case 'ship':
//Ship API
//Gets ship from Ship API key (distinct of regular API keys)
require_once('includes/objects/ship.php');
$ship = Ship::from_api_key($_REQUEST['key']) or cerbere_die("Invalid ship API key");
switch ($command = $url[1]) {
case '':
//Nothing to do
//TODO: offer documentation instead
die();
case 'authenticate':
//TODO: web authenticate
break;
case 'appauthenticate':
//Allows desktop application to authenticate an user
$tmp_session_id = $url[2] or cerbere_die("/appauthenticate/ must be followed by any session identifier");
if ($_REQUEST['name']) {
//Perso will be offered auth invite at next login.
//Handy for devices like PDA, where it's not easy to auth.
$perso = new Perso($_REQUEST['name']);
if ($perso->lastError) {
cerbere_die($perso->lastError);
}
if (!$ship->is_perso_authenticated($perso->id)) {
$ship->request_perso_authenticate($perso->id);
}
$ship->request_perso_confirm_session($tmp_session_id, $perso->id);
} else {
//Delivers an URL. App have to redirects user to this URL
//launching a browser or printing the link.
$ship_code = $ship->get_code();
registry_set("api.ship.session.$ship_code.$tmp_session_id", -1);
$url = get_server_url() . get_url() . "?action=api.ship.appauthenticate&session_id=" . $tmp_session_id;
api_output($url, "URL");
}
break;
case 'appauthenticated':
//Checks the user authentication
$tmp_session_id = $url[2] or cerbere_die("/appauthenticated/ must be followed by any session identifier you used in /appauthenticate");
$perso_id = $ship->get_perso_from_session($tmp_session_id);
if (!$isPersoAuth = $ship->is_perso_authenticated($perso_id)) {
//Global auth not ok/revoked.
$auth->status = -1;
} else {
$perso = Perso::get($perso_id);
$auth->status = 1;
$auth->perso->id = $perso->id;
$auth->perso->nickname = $perso->nickname;
$auth->perso->name = $perso->name;
//$auth->perso->location = $perso->location;
//Is the perso on board? Yes if its global location is S...
$auth->perso->onBoard = (
$perso->location_global[0] == 'S' &&
substr($perso->location_global, 1, 5) == $ship->id
);
if ($auth->perso->onBoard) {
//If so, give local location
$auth->perso->location_local = $perso->location_local;
}
}
api_output($auth, "auth");
break;
case 'move':
//Moves the ship to a new location, given absolute coordinates
//TODO: handle relative moves
if (count($url) < 2) cerbere_die("/move/ must be followed by a location expression");
//Gets location class
//It's allow: (1) to normalize locations between formats
// (2) to ensure the syntax
//==> if the ship want to communicate free forms coordinates, must be added on GeoLocation a free format
try {
$location = new GeoLocation($url[2]);
} catch (Exception $ex) {
$reply->success = 0;
$reply->error = $ex->getMessage();
api_output($reply, "move");
break;
}
$ship->location_global = $location->global;
$ship->save_to_database();
$reply->success = 1;
$reply->location = $ship->location;
api_output($reply, "move");
break;
case 'land':
case 'flyin':
//Flies in
try {
$location = new GeoLocation($location);
} catch (Exception $ex) {
$reply->success = 0;
$reply->error = $ex->getMessage();
api_output($reply, "land");
break;
}
break;
case 'flyout':
//Flies out
break;
}
break;
/* -------------------------------------------------------------
Application API
/checkuserkey
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case 'app':
//Application API
require_once("includes/objects/application.php");
$app = Application::from_api_key($_REQUEST['key']) or cerbere_die("Invalid application API key");
switch ($command = $url[1]) {
case '':
//Nothing to do
//TODO: offer documentation instead
die();
case 'checkuserkey':
if (count($url) < 2) cerbere_die("/checkuserkey/ must be followed by an user key");
$reply = (boolean)$app->get_perso_id($url[2]);
api_output($reply, "check");
break;
case 'pushuserdata':
if (count($url) < 3) cerbere_die("/pushuserdata/ must be followed by an user key");
$perso_id = $app->get_perso_id($url[2]) or cerbere_die("Invalid application user key");
//then, falls to 'pushdata'
case 'pushdata':
$data_id = $_REQUEST['data'] ? $_REQUEST['data'] : new_guid();
//Gets data
switch ($mode = $_REQUEST['mode']) {
case '':
cerbere_die("Add in your data posted or in the URL mode=file to read data from the file posted (one file per api call) or mode=request to read data from \$_REQUEST['data'].");
case 'request':
$data = $_REQUEST['data'];
$format = "raw";
break;
case 'file':
$file = $_FILES['datafile']['tmp_name'] or cerbere_die("File is missing");
if (!is_uploaded_file($file)) cerbere_die("Invalid form request");
$data = "";
if (preg_match('/\.tar$/', $file)) {
$format = "tar";
$data = file_get_contents($file);
} elseif (preg_match('/\.tar\.bz2$/', $file)) {
$format = "tar";
} elseif (preg_match('/\.bz2$/', $file)) {
$format = "raw";
} else {
$format = "raw";
$data = file_get_contents($file);
}
if ($data === "") {
//.bz2
$bz = bzopen($file, "r") or cerbere_die("Couldn't open $file");
while (!feof($bz)) {
$data .= bzread($bz, BUFFER_SIZE);
}
bzclose($bz);
}
unlink($file);
break;
default:
cerbere_die("Invalid mode. Expected: file, request");
}
//Saves data
global $db;
$data_id = $db->sql_escape($data_id);
$data = $db->sql_escape($data);
$perso_id = $perso_id ? $perso_id : 'NULL';
$sql = "REPLACE INTO applications_data (application_id, data_id, data_content, data_format, perso_id) VALUES ('$app->id', '$data_id', '$data', '$format', $perso_id)";
if (!$db->sql_query($sql))
message_die(SQL_ERROR, "Can't save data", '', __LINE__, __FILE__, $sql);
//cerbere_die("Can't save data");
//Returns
api_output($data_id);
break;
case 'getuserdata':
// /api.php/getuserdata/data_id/perso_key
// /api.php/getdata/data_id
if (count($url) < 3) cerbere_die("/getuserdata/ must be followed by an user key");
$perso_id = $app->get_perso_id($url[2]) or cerbere_die("Invalid application user key");
//then, falls to 'getdata'
case 'getdata':
if (count($url) < 2) cerbere_die('/' + $url[0] + '/ must be followed by the data ID');
if (!$perso_id) $perso_id = 'NULL';
$data_id = $db->sql_escape($url[1]);
$sql = "SELECT data_content FROM applications_data WHERE application_id = '$app->id' AND data_id = '$data_id' AND perso_id = $perso_id";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Unable to query the table", '', __LINE__, __FILE__, $sql);
}
while ($row = $db->sql_fetchrow($result)) {
}
break;
default:
echo "Unknown module:";
dprint_r($url);
break;
}
break;
default:
echo "Unknown module:";
dprint_r($url);
break;
}
-
-?>
diff --git a/cron.php b/cron.php
index 690abe0..ad3efe7 100644
--- a/cron.php
+++ b/cron.php
@@ -1,57 +1,55 @@
<?php
/**
* Cron
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* This file contains tasks to execute periodically.
* When editing this file, ensure it works from the command line, so it's
* possible to run it from a crontab calling PHP CLI.
*
* @package Zed
* @subpackage Utilities
* @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
* @todo Adds some periodicity (e.g. hourly, daily, monthly)
*/
////////////////////////////////////////////////////////////////////////////////
///
/// Initialization
///
//Pluton library
include('includes/core.php');
//Debug mode?
$debug = false;
////////////////////////////////////////////////////////////////////////////////
///
/// Daily tasks
///
//Orders perso table by nickname.
//Rationale: prints an ordered perso select list, help for new persos, printed at end
$queries[] = "ALTER TABLE " . TABLE_PERSOS . " ORDER BY perso_nickname";
////////////////////////////////////////////////////////////////////////////////
///
/// Executes tasks
///
foreach ($queries as $query) {
if (!$db->sql_query($sql) && $debug)
message_die(SQL_ERROR, "Can't execute query", '', __LINE__, __FILE__, $sql);
}
-
-?>
\ No newline at end of file
diff --git a/do.php b/do.php
index 444446b..2f58859 100644
--- a/do.php
+++ b/do.php
@@ -1,464 +1,462 @@
<?php
/**
* AJAX callbacks
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* As main controller could potentially be interrupted (e.g. if site.requests
* flag is at 1, user is redirected to controllers/userrequest.php), all AJAX
* queries should be handled by this script and not directly by the controllers.
*
* Standard return values:
* -7 user is logged but perso isn't selected,
* -9 user is not logged.
*
* @package Zed
* @subpackage EntryPoints
* @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
*/
////////////////////////////////////////////////////////////////////////////////
///
/// Constants
///
//We define one negative number constant by standard erroneous return value.
/**
* Magic number which indicates the user is not logged in.
*/
define('USER_NOT_LOGGED', -9);
/**
* Magic number which indicates the user is logged in, but haven't selected its perso.
*/
define('PERSO_NOT_SELECTED', -7);
////////////////////////////////////////////////////////////////////////////////
///
/// Initialization
///
//Pluton library
include('includes/core.php');
//Session
$IP = encode_ip($_SERVER["REMOTE_ADDR"]);
require_once('includes/story/story.php'); //this class can be stored in session
session_start();
$_SESSION[ID] = session_id();
session_update(); //updates or creates the session
include("includes/login.php"); //login/logout
$CurrentUser = get_logged_user(); //Gets current user infos
//Gets current perso
require_once('includes/objects/perso.php');
if ($perso_id = $CurrentUser->session['perso_id']) {
$CurrentPerso = new Perso($perso_id);
}
//Requires user and perso
if ($CurrentUser->id < 1000) {
echo USER_NOT_LOGGED;
exit;
}
if (!$CurrentPerso) {
echo PERSO_NOT_SELECTED;
exit;
}
//Loads Smarty (as it handles l10n, it will be used by lang_get)
require('includes/Smarty/Smarty.class.php');
$smarty = new Smarty();
$current_dir = dirname(__FILE__);
$smarty->template_dir = $current_dir . '/skins/zed';
$smarty->compile_dir = $current_dir . '/cache/compiled';
$smarty->cache_dir = $current_dir . '/cache';
$smarty->config_dir = $current_dir;
//Loads language files
initialize_lang();
lang_load('core.conf');
////////////////////////////////////////////////////////////////////////////////
///
/// Actions definitions
///
/**
* Actions class
*
* Each method is called by first part of your URL, other parts are arguments
* e.g. /do.php/validate_quux_request/52 = Actions::validate_quux_request(52);
*
* You can also use $_GET, $_POST or better $_REQUEST.
*
* Don't echo the value but return it, so we can in the future implement custom
* formats like api_output();
*/
class Actions {
/**
* Checks the arguments hash and determines wheter it is valid.
*
* @param Array $args the arguments, the last being the hash
* @return boolean true if the hash is valid ; otherwise, false.
*/
static private function is_hash_valid ($args) {
global $Config;
return array_pop($args) == md5($_SESSION['ID'] . $Config['SecretKey'] . implode('', $args));
}
/**
* Handles a allow/deny perso request.
*
* @param string $request_flag the request flag to clear
* @param string $store 'perso' or 'registry'
* @param string $key the perso flag or registry key
* @param string $value the value to store
* @param string $hash the security hash
* @return boolean true if the request is valid and have been processed ; otherwise, false.
*/
static function perso_request ($request_flag, $store, $key, $value, $hash) {
global $CurrentPerso;
//Ensures we've the correct amount of arguments
if (func_num_args() < 4) return false;
//Checks hash
$args = func_get_args();
if (!self::is_hash_valid($args)) {
return false;
}
//Sets flag
switch ($store) {
case 'perso':
$CurrentPerso->set_flag($key, $value);
break;
case 'registry':
registry_set($key, $value);
break;
default:
//Unknown storage location
return false;
}
//Clears request flag
if ((string)$request_flag !== "0") {
$CurrentPerso->delete_flag($request_flag);
}
return true;
}
/**
* Sets current perso's local location.
*
* We don't require a security hash. If the users want to play with it, no problem.
* You generally move inside a global location as you wish.
* So, if you write a story capturing a perso, use flags to handle this escape!
*
* @param string $location_local the local location
* @return GeoLocation the current perso's GeoLocation object
*/
static function set_local_location ($location_local) {
global $CurrentPerso;
//Ensures we've the correct amount of arguments
if (func_num_args() < 1) return null;
//Moves current perso to specified location
$location_local = urldecode($location_local);
$CurrentPerso->move_to(null, $location_local);
//Returns GeoLocation relevant instance
return $CurrentPerso->location;
}
/**
* Moves the current perso's, setting a new local location.
*
* We don't require a security hash. If the users want to play with it, no problem.
* You generally move inside a global location as you wish.
* So, if you write a story capturing a perso, use flags to handle this escape!
*
* @param string $move the move (coordinates or direction)
* @param int $factor a number multipling the specified move [optional]
* @return GeoLocation the current perso's GeoLocation object
*
* e.g. to move from 2 units to east, you can use one of those instructions:
* local_move('east', 2);
* local_move('2,0,0');
* local_move('1,0,0', 2);
*
* Valid moves string are north, east, south, west, up and down.
* Valid moves coordinates are x,y,z (3 integers, comma as separator)
*/
static function local_move ($move, $factor = 1) {
global $CurrentPerso;
//Ensures we've the correct amount of arguments
if (func_num_args() < 1) return null;
//Parses $move
switch ($move) {
case 'north':
$move = array(0, 1, 0);
break;
case 'east':
$move = array(1, 0, 0);
break;
case 'south':
$move = array(0, -1, 0);
break;
case 'west':
$move = array(-1, 0, 0);
break;
case 'up':
$move = array(0, 0, 1);
break;
case 'down':
$move = array(0, 0, -1);
break;
default:
$move = split(',', $move, 3);
foreach ($move as $coordinate) {
if (!is_numeric($coordinate)) {
return null;
}
}
}
//Moves current perso to specified location
if ($location_local = GeoPoint3D::fromString($CurrentPerso->location->local)) {
$location_local->translate($move[0] * $factor, $move[1] * $factor, $move[2] * $factor);
$CurrentPerso->move_to(null, $location_local->sprintf("(%d, %d, %d)"));
//Returns GeoLocation relevant instance
return $CurrentPerso->location;
}
//Old local location weren't a GeoPoint3D
return null;
}
/**
* Moves the current perso's, setting a new local location, using polar+z coordinates.
* Polar+z coordinates are polar coordinates, plus a cartesian z dimension.
*
* We don't require a security hash. If the users want to play with it, no problem.
* You generally move inside a global location as you wish.
* So, if you write a story capturing a perso, use flags to handle this escape!
*
* @param string $move the move (coordinates or direction)
* @param int $factor a number multipling the specified move [optional]
* @return GeoLocation the current perso's GeoLocation object
*
* Valid moves string are cw, ccw, out, in, up and down.
* r: out = +12 in = -12
* °: cw = +20° ccw = -20
* Valid moves coordinates are r,°,z (3 integers, comma as separator)
* (the medium value can also be integer + °)
*
* e.g. to move of two units (the unit is 20°) clockwise:
* polarz_local_move('cw', 2);
* polarz_local_move('(0, 20°, 0)', 2);
* polarz_local_move('(0, 40°, 0)');
* Or if you really want to use radiants (PI/9 won't be parsed):
* polarz_local_move('(0, 0.6981317007977318, 0)';
*
*/
static function polarz_local_move ($move, $factor = 1) {
global $CurrentPerso;
//Ensures we've the correct amount of arguments
if (func_num_args() < 1) return null;
//Parses $move
$move = urldecode($move);
switch ($move) {
case 'cw':
$move = array(0, '20°', 0);
break;
case 'ccw':
$move = array(0, '-20°', 0);
break;
case 'in':
$move = array(+12, 0, 0);
break;
case 'out':
$move = array(-12, 0, 0);
break;
case 'up':
$move = array(0, 0, 1);
break;
case 'down':
$move = array(0, 0, -1);
break;
default:
$move = split(',', $move, 3);
foreach ($move as $coordinate) {
if (!is_numeric($coordinate) && !preg_match("/^[0-9]+ *°$/", $coordinate)) {
return null;
}
}
}
dieprint_r($move);
//Moves current perso to specified location
if ($location_local = GeoPoint3D::fromString($CurrentPerso->location->local)) {
$location_local->translate($move[0] * $factor, $move[1] * $factor, $move[2] * $factor);
$CurrentPerso->move_to(null, $location_local->sprintf("(%d, %d, %d)"));
//Returns GeoLocation relevant instance
return $CurrentPerso->location;
}
//Old local location weren't a GeoPoint3D
return null;
}
/**
* Moves the current perso's, setting a new global and local location.
*
* @param string $location_global The global location
* @param string $location_local The local location
* @return GeoLocation the current perso's GeoLocation object
*/
static function global_move ($location_global, $location_local = null) {
//Ensures we've the correct amount of arguments
if (func_num_args() < 1) return null;
//Checks hash
$args = func_get_args();
if (!self::is_hash_valid($args)) {
return false;
}
//Moves
global $CurrentPerso;
$CurrentPerso->move_to($location_global, $location_local);
return $CurrentPerso->location;
}
/**
* Handles upload content form.
*
* @return string new content path
*/
static function upload_content () {
global $CurrentPerso, $CurrentUser;
require_once('includes/objects/content.php');
//Initializes a new content instance
$content = new Content();
$content->load_from_form();
$content->user_id = $CurrentUser->id;
$content->perso_id = $CurrentPerso->id;
$content->location_global = $CurrentPerso->location_global;
//Saves file
if ($content->handle_uploaded_file($_FILES['artwork'])) {
$content->save_to_database();
$content->generate_thumbnail();
return true;
}
return false;
}
/**
* Gets multimedia content for the specified location
*
* @param string $location_global The global location (local is to specified in ?location_local parameter)
* @return Array an array of Content instances
*/
static function get_content ($location_global) {
//Ensures we've the correct amount of arguments
if (func_num_args() < 1) return null;
//Checks hash
$args = func_get_args();
if (!self::is_hash_valid($args)) {
return false;
}
//Checks local location is specified somewhere (usually in $_GET)
if (!array_key_exists('location_local', $_REQUEST)) {
return false;
}
//Gets content
require_once('includes/objects/content.php');
return Content::get_local_content($location_global, $_REQUEST['location_local']);
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// Handles request
///
//Parses URL
$Config['SiteURL'] = get_server_url() . $_SERVER["PHP_SELF"];
$args = get_current_url_fragments();
$method = array_shift($args);
if ($_REQUEST['debug']) {
//Debug version
//Most of E_STRICT errors are evaluated at the compile time thus such errors
//are not reported
ini_set('display_errors', 'stderr');
error_reporting(-1);
if (method_exists('Actions', $method)) {
$result = call_user_func_array(array('Actions', $method), $args);
echo json_encode($result);
} else {
echo "<p>Method doesn't exist: $method</p>";
}
if (array_key_exists('redirectTo', $_REQUEST)) {
//If user JS disabled, you can add ?redirectTo= followed by an URL
echo "<p>Instead to print a callback value, redirects to <a href=\"$_REQUEST[redirectTo]\">$_REQUEST[redirectTo]</a></p>";
}
} else {
//Prod version doesn't prints warning <== silence operator
if (method_exists('Actions', $method)) {
$result = @call_user_func_array(array('Actions', $method), $args);
if (array_key_exists('redirectTo', $_REQUEST)) {
//If user JS disabled, you can add ?redirectTo= followed by an URL
header("location: " . $_REQUEST['redirectTo']);
} else {
echo json_encode($result);
}
}
}
-
-?>
diff --git a/includes/config.php b/includes/config.php
index 0b0fde8..acfcd60 100755
--- a/includes/config.php
+++ b/includes/config.php
@@ -1,272 +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';
//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 bafd362..d00d642 100755
--- a/includes/core.php
+++ b/includes/core.php
@@ -1,666 +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);
//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()
////////////////////////////////////////////////////////////////////////////////
/// ///
/// 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/error.php b/includes/error.php
index 1258ba5..6e48239 100755
--- a/includes/error.php
+++ b/includes/error.php
@@ -1,260 +1,258 @@
<?php
/**
* Error handler
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* This error handler uses the same idea and message_die methode signature
* of the phpBB 2 one.
*
* @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
*
* @todo delete old_message_die method and write alternative HTML textual output
* in the message_die method
*/
///
/// Error constants
///
/**
* SQL_ERROR is the constant meaning the error is a SQL error.
*
* As a message_die function parameter, it allows to add SQL specific debug information.
*/
define ("SQL_ERROR", 65);
/**
* HACK_ERROR is the constant meaning access is non authorized to the resource.
*
* It encompasses two problematics:
* the URL points to a resource belonging to another user or for the current user have no access right (for malformed URL, pick instead GENERAL_ERROR) ;
* the user is anonymous, instead to be logged in.
*
* A suggested way to handle the second problematic is to store in hidden input
* fields or better in the session the previous form data, and to print a login
* form.
*
* If you implement this, you don't even need to distinguishes between the two
* cases, as once logged in, the regular HACK_ERROR could also be printed.
*/
define ("HACK_ERROR", 99);
/**
* GENERAL_ERROR is the constant meaning the error is general, ie not covered by
* another more specific error constant.
*/
define ("GENERAL_ERROR", 117);
///
/// Error helper functions
///
/**
* Output a general error, with human-readable information about the specified
* expression as error message ; terminates the current script.
*
* @see message_die
*
* @param mixed $expression the expression to be printed
* @param string $title the message title (optionnal, default will be 'Debug')
*/
function dieprint_r ($expression, $title = '') {
if (!$title) {
$title = 'Debug'; //if title is omitted or false/null, default title
}
message_die(GENERAL_ERROR, '<pre>' . print_r($expression, true) .'</pre>', $title);
}
/**
* Outputs an error message and terminates the current script.
*
* Error will be output through Smarty one of the following templates :
* error_block.tpl if the header have already been printed ;
* error.tpl if the error ocurred before the header were called and printed.
*
* If smarty couldn't be loaded, old_message_die method will be called, which
* produces a table output.
*
* @param int $msg_code an integer constant identifying the error (HACK_ERROR, SQL_ERROR, GENERAL_ERROR)
* @param string $msg_text the error message text (optionnal, but recommanded)
* @param string $msg_title the error message title (optionnal)
* @param int $err_line the line number of the file where the error occured (optionnal, suggested value is __LINE__)
* @param string $err_line the path of file where the error occured (optionnal, suggested value is __FILE__)
* @param string $sql the SQL query (optionnal, used only if msg_code is SQL_ERROR)
*/
function message_die ($msg_code, $msg_text = '', $msg_title = '', $err_line = '', $err_file = '', $sql = '') {
global $smarty, $db;
if ($smarty) {
$debug_text = $msg_text;
if ($err_line && $err_file)
$debug_text .= ' &mdash; ' . $err_file. ', ' . lang_get('line') . ' ' . $err_line ;
switch ($msg_code) {
case HACK_ERROR:
$smarty->assign('TITLE', lang_get('UnauthorizedAccess'));
break;
case SQL_ERROR:
$smarty->assign('TITLE', lang_get('SQLError'));
$sql_error = $db->sql_error();
if ($sql_error['message'] != '') {
$debug_text .= '<br />' . lang_get('Error') . ' n° ' . $sql_error['code'] . lang_get('_t') .
' ' .$sql_error['message'];
}
$debug_text .= "</p><h2>Query:</h2><p>$sql";
break;
default:
$smarty->assign('WAP', "Message code error.<br />Expected: HACK_ERROR, SQL_ERROR, GENERAL_ERROR");
//Falls to GENERAL_ERROR
case GENERAL_ERROR:
if ($msg_title)
$smarty->assign('TITLE', $msg_title);
else
$smarty->assign('TITLE', lang_get('GeneralError'));
break;
}
$smarty->assign('ERROR_TEXT', $debug_text);
$template = (defined('HEADER_PRINTED') && HEADER_PRINTED) ? "error_block.tpl" : "error.tpl";
$smarty->display($template);
exit;
} else {
old_message_die($msg_code, $msg_text, $msg_title, $err_line, $err_file, $sql);
}
}
/**
* Outputs an error message and terminates the current script.
*
* This is the message_die method from Espace Win, used on Zed as fallback if Smarty isn't initialized yet.
*
* @param int $msg_code an integer constant identifying the error (HACK_ERROR, SQL_ERROR, GENERAL_ERROR)
* @param string $msg_text the error message text (optionnal, but recommanded)
* @param string $msg_title the error message title (optionnal)
* @param int $err_line the line number of the file where the error occured (optionnal, suggested value is __LINE__)
* @param string $err_line the path of file where the error occured (optionnal, suggested value is __FILE__)
* @param string $sql the SQL query (optionnal, used only if msg_code is SQL_ERROR)
*
* @deprecated since 0.1
*/
function old_message_die($msg_code, $msg_text = '', $msg_title = '', $err_line = '', $err_file = '', $sql = '')
{
global $db, $Utilisateur;
$sql_store = $sql;
if ($msg_code == HACK_ERROR && $Utilisateur[user_id] < 1000) {
global $LoginResult;
foreach ($_POST as $name => $value) {
$champs .= "<input type=hidden name=$name value=\"$value\" />";
}
$titre = "Qui êtes-vous ?";
$debug_text = "Vous devez être authentifié pour accéder à cette page.";
$debug_text .= "
<FORM method='post'>
$champs
<table border='0'>
<tr>
<td><STRONG>Login</STRONG></td>
<td><input name='Login' type='text' id='Login' value='$_POST[Login]' size='10' /></td>
<td><STRONG>Mot de passe</STRONG></td>
<td>
<input name='MotDePasse' type='password' id='MotDePasse' size='10' />
<input type='submit' name='LoginBox' value='Connexion' />
</td>
</tr>
<tr>
<td align=center COLSPAN=4><a href='/?Topic=My&Article=Enregistrer'>Je d&eacute;sire ouvrir un compte</a></td>
</tr>
</TABLE><span class=error>$LoginResult</span>
</FORM>
";
} elseif ($msg_code == HACK_ERROR) {
$titre = "Accès non autorisé";
$debug_text = $msg_text;
} elseif ($msg_code == SQL_ERROR) {
$titre = "Erreur dans la requête SQL";
$sql_error = $db->sql_error();
$debug_text = $msg_text;
if ( $err_line != '' && $err_file != '') $debug_text .= ' dans ' . $err_file. ', ligne ' . $err_line ;
if ( $sql_error['message'] != '' ) $debug_text .= '<br />Erreur n° ' . $sql_error['code'] . ' : ' . $sql_error['message'];
if ( $sql_store != '' ) $debug_text .= "<br /><strong>$sql_store</strong>";
} elseif ($msg_code == GENERAL_ERROR) {
$titre = $msg_title;
$debug_text = $msg_text;
if ($err_line && $err_file) {
$debug_text .= "<BR />$err_file, ligne $err_line";
}
}
echo "
<TABLE height='100%' cellSpacing=0 cellPadding=0 width='100%' border=0>
<TBODY>
<TR>
<TD vAlign=top align=middle>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD vAlign=top rowSpan=5><IMG height=177 alt=''
src='/_pict/error/notfound.jpg' width=163 border=0></TD>
<TD colSpan=4><IMG height=2 alt='' src='/_pict/error/mrblue.gif'
width=500 border=0></TD>
<TD><IMG height=2 alt='' src='/_pict/error/undercover.gif' width=1
border=0></TD></TR>
<TR>
<TD vAlign=bottom rowSpan=4 bgcolor='#FFFFFF'><IMG height=43 alt=''
src='/_pict/error/ecke.gif' width=14 border=0></TD>
<TD vAlign=center align=middle rowSpan=2 bgcolor='#FFFFFF'>
<TABLE cellSpacing=1 cellPadding=0 width=470 border=0>
<TBODY>
<TR>
<TD><FONT face='Verdana, Helvetica, sans-serif' color=red
size=4><B>$titre</B></FONT><BR>
<IMG height=5 alt=''
src='/_pict/error/undercover.gif' width=14 border=0><BR></TD></TR>
<TR>
<TD><FONT face='Verdana, Helvetica, sans-serif' color=black
size=2>$debug_text</FONT></TD></TR></TBODY></TABLE></TD>
<TD align=right width=2 rowSpan=2 bgcolor='#FFFFFF'><IMG height=146 alt=''
src='/_pict/error/mrblue.gif' width=2 border=0></TD>
<TD bgcolor='#FFFFFF'><IMG height=132 alt='' src='/_pict/error/undercover.gif' width=1
border=0></TD>
</TR>
<TR>
<TD><IMG height=14 alt='' src='/_pict/error/undercover.gif' width=1
border=0></TD></TR>
<TR>
<TD colSpan=2><IMG height=2 alt='' src='/_pict/error/mrblue.gif'
width=486 border=0></TD>
<TD><IMG height=2 alt='' src='/_pict/error/undercover.gif' width=1
border=0></TD></TR>
<TR>
<TD colSpan=2><IMG height=27 alt='' src='/_pict/error/undercover.gif'
width=486 border=0></TD>
<TD><IMG height=27 alt='' src='/_pict/error/undercover.gif' width=1
border=0></TD></TR></TBODY></TABLE>
<P>&nbsp;</P>
</TD></TR></TBODY></TABLE>
";
exit;
}
-
-?>
\ No newline at end of file
diff --git a/includes/login.php b/includes/login.php
index 8436677..280629a 100755
--- a/includes/login.php
+++ b/includes/login.php
@@ -1,156 +1,157 @@
<?php
/**
* Login/logout
*
* 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
*
* @todo Pick between DumbStore and FileStore and cleans the file accordingly.
*/
///
/// OpenID helper code
///
$useOpenID = isset($Config['OpenID']) && $Config['OpenID'];
if ($useOpenID) {
require_once('Auth/OpenID/Consumer.php');
require_once('Auth/OpenID/FileStore.php');
}
/**
* Gets an Auth_OpenID_Consumer instance
*
* @return Auth_OpenID_Consumer the instance
*/
function get_openid_consumer () {
if (!file_exists('/dev/urandom')) {
//We don't have a reliable source of random numbers
define('Auth_OpenID_RAND_SOURCE', null);
}
$fs = new Auth_OpenID_FileStore(CACHE_DIR . '/openid');
return new Auth_OpenID_Consumer($fs);
}
/**
* Logs in the user if the OpenID is recognized.
* Otherwise, sets an error message.
*
* @param string $url The OpenID URL
*/
function openid_login ($url) {
global $db, $_SESSION, $LoginError, $LoginSuccessful;
$url = $db->sql_escape($url);
$sql = 'SELECT user_id FROM ' . TABLE_USERS_AUTH
. " WHERE auth_type = 'OpenID' AND auth_identity LIKE '$url'";
if ($user_id = $db->sql_query_express($sql)) {
$sql = "UPDATE " . TABLE_SESSIONS . " SET user_id = '$user_id' WHERE session_id LIKE '$_SESSION[ID]'";
if (!$db->sql_query($sql)) message_die(SQL_ERROR, "Can't update session table", '', __LINE__, __FILE__, $sql);
$LoginSuccessful = true;
setcookie("LastOpenID", $url, time() + 2592000);
header("location: " . get_url());
} else {
$LoginError = "Read the source to get an invite.";
}
}
///
/// Login procedural code
///
$action = isset($_GET['action']) ? $_GET['action'] : '';
if ($action == 'openid.login') {
//Gets Auth_OpenID_Consumer instance, completes the OpenID transaction
//and processes the result.
if (!$useOpenID()) {
header("Status: 403 Forbidden");
die("OpenID disabled.");
}
$consumer = get_openid_consumer();
$reply = $consumer->complete(get_server_url() . $_SERVER['REQUEST_URI']);
if ($reply->status == Auth_OpenID_SUCCESS) {
openid_login($reply->endpoint->claimed_id);
} elseif ($reply->message) {
//TODO: $reply->message could be rather long and won't fit in the UI
//space. You can wish to add code to print $LoginError elsewhere if
//too long.
$LoginError = "[OpenID] $reply->message";
} else {
$LoginError = "[OpenID] $reply->status";
}
} elseif (isset($_POST['LogIn'])) {
//User have filled login form
if ($_POST['openid'] && $useOpenID) {
//Gets Auth_OpenID_Consumer instance
$consumer = get_openid_consumer();
//Starts the OpenID transaction and redirects user to provider url
if ($request = $consumer->begin($_POST['openid'])) {
$url = $request->redirectURL(get_server_url(), "$Config[SiteURL]/?action=openid.login", false);
header("location: $url");
$LoginError = '<a href="' . $url . '">Click here to continue login</a>';
} else {
$LoginError = 'Invalid OpenID URL.';
}
} else {
//Login
//Authentications way, the user/password in last.
//OpenID is handled by a separate logic.
$Login = $_POST['username'];
$authentications = array();
if ($useYubiCloud = array_key_exists('YubiCloud', $Config) ) {
$authentications[] = new YubiCloudAuthentication($_POST['password'], $Login);
}
if ($Login) {
$authentications[] = new UserPasswordAuthentication($Login, $_POST['password']);
}
$loginSuccessful = false;
foreach ($authentications as $authentication) {
if ($authentication->isValid()) {
$loginSuccessful = true;
//Logs in user
login($authentication->getUserID(), $Login);
} else {
$loginError = $authentication->getError();
}
if (!$authentication->canTryNextAuthenticationMethod()) {
break;
}
}
//Tests if the password wouldn't match an invite code
//If so, redirects people using login page as invitation claim page
if (!$LoginSuccessful) {
$code = $db->sql_escape($_POST['password']);
$sql = "SELECT * FROM " . TABLE_USERS_INVITES . " WHERE invite_code = '$code'";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Can't get invites", '', __LINE__, __FILE__, $sql);
}
if ($row = $db->sql_fetchrow($result)) {
$url = get_url('invite', $_POST['password']);
header('location: ' . $url);
}
}
}
} elseif (isset($_POST['LogOut']) || $action == "user.logout") {
Logout();
}
+
diff --git a/includes/mysql.php b/includes/mysql.php
index 6e15b75..513d200 100755
--- a/includes/mysql.php
+++ b/includes/mysql.php
@@ -1,183 +1,182 @@
<?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 = '') {
//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']);
}
-?>
\ No newline at end of file
diff --git a/includes/sessions.php b/includes/sessions.php
index 25b419c..f2c6618 100755
--- a/includes/sessions.php
+++ b/includes/sessions.php
@@ -1,151 +1,149 @@
<?php
/**
* Sessions
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* This file provides functions to manage sessions. It's not currently properly
* documented, as it's a temporary old session file, which will be updated soon.
*
* @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
*
* @todo Replaces this code by the unified Keruald session class.
*/
function decode_ip ($int_ip) {
$hexipbang = explode('.', chunk_split($int_ip, 2, '.'));
return hexdec($hexipbang[0]). '.' . hexdec($hexipbang[1]) . '.' . hexdec($hexipbang[2]) . '.' . hexdec($hexipbang[3]);
}
function encode_ip ($dotquad_ip) {
$ip_sep = explode('.', $dotquad_ip);
return sprintf('%02x%02x%02x%02x', $ip_sep[0], $ip_sep[1], $ip_sep[2], $ip_sep[3]);
}
function session_update () {
global $db, $IP, $Config;
//Nettoyage de la session
/* Initialisation */
$time_online = 5 * 60; // Temps après lequel l'utilisateur n'est plus considéré comme online
$time_session = 2 * 60 * 60; // Durée de vie de la session
$heureActuelle = time(); //Timestamp UNIX et non MySQL
/* On fait le ménage */
$sql = "UPDATE " . TABLE_SESSIONS . " SET online=0 WHERE HeureLimite < $heureActuelle";
if (!$db->sql_query($sql)) message_die(SQL_ERROR, 'Impossible de mettre à jour les sessions (utilisateurs offline)', '', __LINE__, __FILE__, $sql);
$sql = "DELETE FROM " . TABLE_SESSIONS . " WHERE SessionLimite < $heureActuelle";
if (!$db->sql_query($sql)) message_die(SQL_ERROR, "Impossible d'effacer les sessions expirées", '', __LINE__, __FILE__, $sql);
/* Création / mise à jour de la session utilisateur */
if (!$_SESSION[ID]) {
$_SESSION[ID] = md5(generate_random_string("AAAA1234"));
}
$sql = "SELECT * FROM " . TABLE_SESSIONS . " WHERE session_id LIKE '$_SESSION[ID]'";
if ( !($result = $db->sql_query($sql)) ) message_die(SQL_ERROR, "Problème critique avec les sessions.", '', __LINE__, __FILE__, $sql);
if ($db->sql_numrows($result) == 0) {
$sql = "INSERT INTO " . TABLE_SESSIONS . " (IP, session_id, `Where`, HeureLimite, SessionLimite) VALUES ('$IP', '$_SESSION[ID]', $Config[ResourceID], $heureActuelle + $time_online, $heureActuelle + $time_session)";
if (!$db->sql_query($sql)) message_die(SQL_ERROR, "Impossible de créer une nouvelle session", '', __LINE__, __FILE__, $sql);
} else {
$sql = "UPDATE " . TABLE_SESSIONS . " SET online=1, HeureLimite = $heureActuelle + $time_online, SessionLimite= $heureActuelle + $time_session WHERE session_id = '$_SESSION[ID]'";
if (!$db->sql_query($sql)) message_die(SQL_ERROR, "Impossible de mettre à jour la session", '', __LINE__, __FILE__, $sql);
}
}
function nbc () {
//Renvoi du nombre d'usagers connectés
global $db, $Config;
$sql = "SELECT count(*) FROM " . TABLE_SESSIONS . " WHERE online=1 AND `Where` = $Config[ResourceID]";
if ( !($result = $db->sql_query($sql)) ) message_die(SQL_ERROR, "Impossible d'obtenir le nombre d'utilisateurs connectés sur le site web", '', __LINE__, __FILE__, $sql);
$row = $db->sql_fetchrow($result);
return $row[0];
}
function get_info ($info)
//Renvoie une variable de la session
{
global $db;
$sql = "SELECT $info FROM " . TABLE_SESSIONS . " WHERE session_id LIKE '$_SESSION[ID]'";
if ( !($result = $db->sql_query($sql)) ) message_die(SQL_ERROR, "Impossible d'obtenir $info", '', __LINE__, __FILE__, $sql);
$row = $db->sql_fetchrow($result);
return $row[$info];
}
function get_logged_user ()
//Renvoie toutes les informations d'un utilisateur
{
global $db;
$sql = "SELECT * FROM " . TABLE_SESSIONS . " WHERE session_id LIKE '$_SESSION[ID]'";
if ( !($result = $db->sql_query($sql)) ) message_die(SQL_ERROR, "Impossible d'obtenir les informations de l'utilisateur", '', __LINE__, __FILE__, $sql);
$row = $db->sql_fetchrow($result);
require_once('includes/objects/user.php');
$user = User::get($row['user_id']);
$user->session = $row;
return $user;
}
function set_info ($info, $value)
//Définit une variable session
{
global $db;
$value = ($value === null) ? 'NULL' : "'" . $db->sql_escape($value) . "'";
$sql = "UPDATE " . TABLE_SESSIONS . " SET $info = $value WHERE session_id LIKE '$_SESSION[ID]'";
if (!$db->sql_query($sql)) message_die(SQL_ERROR, "Impossible de définir $info", '', __LINE__, __FILE__, $sql);
}
/**
* Destroys $_SESSION array values, help ID
*/
function clean_session () {
foreach ($_SESSION as $key => $value) {
if ($key != 'ID') unset($_SESSION[$key]);
}
}
/**
* Logs in user
*/
function login ($user_id, $username) {
global $db;
$sql = "UPDATE " . TABLE_SESSIONS . " SET user_id = '$user_id' WHERE session_id LIKE '$_SESSION[ID]'";
if (!$db->sql_query($sql)) message_die(SQL_ERROR, "Impossible de procéder à la connexion", '', __LINE__, __FILE__, $sql);
//We send a cookie to print automatically the last username on the login
//page during 30 days.
if (username) {
setcookie("LastUsername", $username, time() + 2592000);
}
}
/**
* Logs out user
*/
function logout () {
//Anonymous user in session table
global $db;
$sql = "UPDATE " . TABLE_SESSIONS . " SET user_id = '-1', perso_id = NULL WHERE session_id LIKE '$_SESSION[ID]'";
if (!$db->sql_query($sql)) message_die(SQL_ERROR, "Impossible de procéder à la déconnexion", '', __LINE__, __FILE__, $sql);
clean_session();
}
-
-?>
diff --git a/index.php b/index.php
index 8c55cf9..b4750fa 100644
--- a/index.php
+++ b/index.php
@@ -1,202 +1,201 @@
<?php
/**
* Application entry point
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* @package Zed
* @subpackage EntryPoints
* @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
* @todo Consider to split the different tasks (especially
* perso select/create into several files)
*/
////////////////////////////////////////////////////////////////////////////////
///
/// Initialization
///
//Keruald (formelly Pluton) library
include('includes/core.php');
//Session
$IP = encode_ip($_SERVER["REMOTE_ADDR"]);
require_once('includes/story/story.php'); //this class can be stored in session
session_start();
$_SESSION[ID] = session_id();
session_update(); //updates or creates the session
include("includes/login.php"); //login/logout
$CurrentUser = get_logged_user(); //Gets current user infos
//Gets current perso
require_once('includes/objects/perso.php');
if ($perso_id = $CurrentUser->session['perso_id']) {
$CurrentPerso = new Perso($perso_id);
}
//Skin and accent to load
define('THEME', $CurrentUser->session['Skin']);
define('ACCENT', $CurrentUser->session['Skin_accent']);
//Loads Smarty
require('includes/Smarty/Smarty.class.php');
$smarty = new Smarty();
$current_dir = dirname(__FILE__);
$smarty->setTemplateDir($current_dir . '/skins/' . THEME);
$smarty->compile_dir = CACHE_DIR . '/compiled';
$smarty->cache_dir = CACHE_DIR;
$smarty->config_dir = $current_dir;
$smarty->config_vars['StaticContentURL'] = $Config['StaticContentURL'];
//Loads language files
initialize_lang();
lang_load('core.conf');
//Gets URL
$url = get_current_url_fragments();
//If the user isn't logged in (is anonymous), prints login/invite page & dies.
if ($CurrentUser->id < 1000) {
include('controllers/anonymous.php');
exit;
}
////////////////////////////////////////////////////////////////////////////////
///
/// Perso (=character) selector
///
//Handles form
if ($_POST['form'] == 'perso.create') {
$perso = null; $errors = array();
if (Perso::create_perso_from_form($CurrentUser, $perso, $errors)) {
//Notifies and logs in
$smarty->assign('NOTIFY', lang_get('NewCharacterCreated'));
$CurrentPerso = $perso;
set_info('perso_id', $perso->id);
$CurrentPerso->set_flag("site.lastlogin", $_SERVER['REQUEST_TIME']);
} else {
//Prints again perso create form, so the user can fix it
$smarty->assign('WAP', join("<br />", $errors));
$smarty->assign('perso', $perso);
}
}
if ($_GET['action'] == 'perso.logout' && $CurrentPerso != null) {
//User wants to change perso
$CurrentPerso->on_logout();
$CurrentPerso = null;
} elseif ($_GET['action'] == 'perso.select') {
//User has selected a perso
$CurrentPerso = new Perso($_GET['perso_id']);
if ($CurrentPerso->user_id != $CurrentUser->id) {
//User have made an error in the URL
message_die(HACK_ERROR, "This isn't your perso.");
}
$CurrentPerso->on_select();
}
if (!$CurrentPerso) {
switch ($count = Perso::get_persos_count($CurrentUser->id)) {
case 0:
//User have to create a perso
$smarty->display("perso_create.tpl");
exit;
case 1:
//Autoselects only perso
$CurrentPerso = Perso::get_first_perso($CurrentUser->id);
$CurrentPerso->on_select();
break;
default:
//User have to pick a perso
$persos = Perso::get_persos($CurrentUser->id);
$smarty->assign("PERSOS", $persos);
$smarty->display("perso_select.tpl");
$_SESSION['UserWithSeveralPersos'] = true;
exit;
}
}
//Assigns current perso object as Smarty variable
$smarty->assign('CurrentPerso', $CurrentPerso);
////////////////////////////////////////////////////////////////////////////////
///
/// Tasks to execute before calling the URL controller:
/// - assert the perso is somewhere
/// - executes the smartline
///
//If the perso location is unknown, ejects it to an asteroid
if (!$CurrentPerso->location_global) {
require_once('includes/geo/place.php');
$smarty->assign('NOTIFY', lang_get('NewLocationNotify'));
$CurrentPerso->move_to(GeoPlace::get_start_location());
}
//SmartLine
include("includes/SmartLine/ZedSmartLine.php");
//Redirects user to user request controller if site.requests flag on
if (defined('PersoSelected') && array_key_exists('site.requests', $CurrentPerso->flags) && $CurrentPerso->flags['site.requests']) {
include('controllers/persorequest.php');
}
////////////////////////////////////////////////////////////////////////////////
///
/// Calls the specific controller to serve the requested page
///
switch ($controller = $url[0]) {
case '':
include('controllers/home.php');
break;
case 'builder':
case 'explore':
case 'page':
case 'request':
case 'settings':
case 'ship':
include("controllers/$controller.php");
break;
case 'who':
include('controllers/profile.php'); //Azhàr controller
break;
case 'push':
include('controllers/motd.php'); //Azhàr controller
break;
case 'quux':
//It's like a test/debug console/sandbox, you put what you want into
if (file_exists('dev/quux.php')) {
include('dev/quux.php');
} else {
message_die(GENERAL_ERROR, "Quux lost in Hollywood.", "Nay");
}
break;
default:
//TODO: returns a prettier 404 page
header("Status: 404 Not Found");
dieprint_r($url, 'Unknown URL');
}
-?>

File Metadata

Mime Type
text/x-diff
Expires
Mon, Nov 25, 10:12 (9 h, 35 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
20935
Default Alt Text
(96 KB)

Event Timeline