Page MenuHomeCode

No OneTemporary

diff --git a/controllers/profile.php b/controllers/profile.php
index 79fb198..b990001 100644
--- a/controllers/profile.php
+++ b/controllers/profile.php
@@ -1,344 +1,344 @@
<?php
/**
* User profile
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* This is a controller allowing user profile view and edit.
*
* It handles the following URLs:
* /who/<perso nickname> views the nickname's profile,
* /who/random views a random profile,
* /who/edit/profile edits its profileq
* /who/edit/account edits its account (disabled on Zed, cf. settings),
* /who/edit/photo(s) manages its profile's photos,
* /who/edit/photo/edit/<photo id> edits a photo properties,
* /who/edit/photo/delete/<photo id> deletes a photo,
* /who/edit/photo/avatar/<photo id> promotes a photo to avatar.
*
* The following views are used:
* profile.tpl,
* profile_edit.tpl,
* user_account.tpl,
* profile_photo.tpl,
* profile_photo_edit.tpl.
*
* The following models are used:
* Profile,
* ProfilePhoto,
* ProfileComment.
*
* The view profile_tags.tpl is indirectly used by the Profile model.
*
* This code is maintained in // with Azhàr.
*
* @package Zed
* @subpackage Controllers
* @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
*/
//Loads language file
lang_load('profile.conf');
//Gets perso nickname from URL
$who = $url[1];
switch ($who) {
case 'edit':
$mode = 'edit';
$who = $CurrentPerso->nickname;
break;
case 'random':
$mode = 'view';
$who = $db->sql_query_express("SELECT perso_id FROM " . TABLE_PROFILES . " ORDER BY rand() LIMIT 1");
break;
default:
$mode = 'view';
}
if (!$who) {
message_die(GENERAL_ERROR, "Who?", "URL error");
}
//Libs
require_once('includes/objects/profile.php');
require_once('includes/objects/profilecomment.php');
require_once('includes/objects/profilephoto.php');
//Gets perso information
require_once('includes/objects/perso.php');
$perso = Perso::get($who);
if ($perso->lastError) {
message_die(GENERAL_ERROR, $perso->lastError, "Error");
}
$smarty->assign('perso', $perso);
//Gets profile
$profile = new Profile($perso->id);
//Handles form
if ($_POST['EditProfile']) {
$profile->load_from_form();
$profile->updated = time();
$profile->save_to_database();
$mode = 'view';
} elseif ($_POST['UserAccount']) {
$smarty->assign('WAP', "This form have been deprecated. You can write instead settings in the SmartLine");
} elseif ($_POST['message_type'] == 'private_message') {
//Sends a message
require_once('includes/objects/message.php');
$msg = new Message();
$msg->from = $CurrentPerso->id;
$msg->to = $perso->id;
$msg->text = $_POST['message'];
$msg->send();
if ($msg->from == $msg->to) {
$smarty->assign('NOTIFY', lang_get('MessageSentSelf'));
} else {
$smarty->assign('NOTIFY', lang_get('MessageSent'));
}
} elseif ($_POST['message_type'] == 'profile_comment') {
//New profile comment
$comment = new ProfileComment();
$comment->author = $CurrentPerso->id;
$comment->perso_id = $perso->id;
$comment->text = $_POST['message'];
$comment->publish();
$smarty->assign('NOTIFY', lang_get('CommentPublished'));
} elseif ($_FILES['photo']) {
#We've a file !
$hash = md5(microtime() . serialize($_FILES));
$extension = get_extension($_FILES['photo']['name']);
$filename = $CurrentPerso->id . '_' . $hash . '.' . $extension;
- #We ignore $_FILES[photo][error] 4, this means no file has been uploaded
- #(so user doesn't want upload a new file)
- #See http:/www.php.net/features.file-upload and http://www.php.net/manual/en/features.file-upload.errors.php about common errors
- #Not valid before PHP 4.2.0
- switch ($_FILES['photo']['error']) {
- case 0:
- #There is no error, the file uploaded with success.
-
- if (!move_uploaded_file($_FILES['photo']['tmp_name'], PHOTOS_DIR . '/' . $filename)) {
- $errors[] = "Upload successful, but error saving it.";
- } else {
- //Attaches the picture to the profile
- $photo = new ProfilePhoto();
- $photo->name = $filename;
- $photo->perso_id = $CurrentPerso->id;
- $photo->description = $_POST['description'];
- if ($photo->avatar) $photo->promote_to_avatar();
- $photo->save_to_database();
-
- //Generates thumbnail
- if (!$photo->generate_thumbnail()) {
+ #We ignore $_FILES[photo][error] 4, this means no file has been uploaded
+ #(so user doesn't want upload a new file)
+ #See http:/www.php.net/features.file-upload and http://www.php.net/manual/en/features.file-upload.errors.php about common errors
+ #Not valid before PHP 4.2.0
+ switch ($_FILES['photo']['error']) {
+ case 0:
+ #There is no error, the file uploaded with success.
+
+ if (!move_uploaded_file($_FILES['photo']['tmp_name'], PHOTOS_DIR . '/' . $filename)) {
+ $errors[] = "Upload successful, but error saving it.";
+ } else {
+ //Attaches the picture to the profile
+ $photo = new ProfilePhoto();
+ $photo->name = $filename;
+ $photo->perso_id = $CurrentPerso->id;
+ $photo->description = $_POST['description'];
+ if ($photo->avatar) $photo->promote_to_avatar();
+ $photo->save_to_database();
+
+ //Generates thumbnail
+ if (!$photo->generate_thumbnail()) {
$smarty->assign('WAP', "Error generating thumbnail.");
}
- $smarty->assign('NOTIFY', lang_get('PhotoUploaded'));
- $mode = 'view';
- }
- break;
+ $smarty->assign('NOTIFY', lang_get('PhotoUploaded'));
+ $mode = 'view';
+ }
+ break;
- case 1:
- $errors[] = "The file is too large.";
- break;
+ case 1:
+ $errors[] = "The file is too large.";
+ break;
- #TODO : more explicit error messages
+ #TODO : more explicit error messages
- default:
- $errors[] = "Unknown error (#" . $_FILES['photo']['error'] . ")";
- break;
- }
+ default:
+ $errors[] = "Unknown error (#" . $_FILES['photo']['error'] . ")";
+ break;
+ }
- if (count($errors)) {
- $smarty->assign('WAP', join($errors, '<br />'));
- }
+ if (count($errors)) {
+ $smarty->assign('WAP', join($errors, '<br />'));
+ }
} elseif ($_POST['id']) {
//Edits photo properties
$photo = new ProfilePhoto($_POST['id']);
if ($photo->lastError) {
$smarty->assign('WAP', $photo->lastError);
$mode = 'view';
} elseif ($photo->perso_id != $CurrentPerso->id) {
$smarty->assign('WAP', lang_get('NotYourPic'));
$mode = 'view';
} else {
//OK
$wereAvatar = $photo->avatar;
$photo->load_from_form();
if (!$wereAvatar && $photo->avatar) {
//Promote to avatar
$photo->promote_to_avatar();
}
$photo->save_to_database();
}
}
//Prepares output
if ($profile->text) {
//Profile
- $smarty->assign('PROFILE_TEXT', $profile->text);
- $smarty->assign('PROFILE_FIXEDWIDTH', $profile->fixedwidth);
+ $smarty->assign('PROFILE_TEXT', $profile->text);
+ $smarty->assign('PROFILE_FIXEDWIDTH', $profile->fixedwidth);
}
if ($mode == 'view') {
require_once('includes/objects/profilephoto.php');
//Self profile?
$self = $CurrentPerso->id == $profile->perso_id;
//Gets profiles comments, photos, tags
$comments = ProfileComment::get_comments($profile->perso_id);
$photos = ProfilePhoto::get_photos($profile->perso_id);
- $tags = $profile->get_cached_tags();
+ $tags = $profile->get_cached_tags();
//Records timestamp, to be able to track new comments
if ($self) $CurrentPerso->set_flag('profile.lastvisit', time());
//Template
$smarty->assign('PROFILE_COMMENTS', $comments);
$smarty->assign('PROFILE_SELF', $self);
- if ($tags) $smarty->assign('PROFILE_TAGS', $tags);
+ if ($tags) $smarty->assign('PROFILE_TAGS', $tags);
$smarty->assign('USERNAME', $perso->username);
$smarty->assign('NAME', $perso->name ? $perso->name : $perso->nickname);
$template = 'profile.tpl';
} elseif ($mode == 'edit') {
switch ($url[2]) {
case 'profile':
$smarty->assign('USERNAME', $perso->name);
$smarty->assign('DIJIT', true);
$css[] = THEME . '/forms.css';
$template = 'profile_edit.tpl';
break;
case 'account':
$smarty->assign('user', $CurrentUser);
$smarty->assign('DIJIT', true);
$css[] = THEME . '/forms.css';
$template = 'user_account.tpl';
break;
case '':
$smarty->assign('NOTIFY', "What do you want to edit ? Append /profile, /account or /photos to the URL");
break;
case 'photo':
case 'photos':
$smarty->assign('USERNAME', $perso->name);
switch ($action = $url[3]) {
case '':
//Nothing to do
break;
case 'delete':
//Deletes a picture
if (!$id = $url[4]) {
$smarty->assign('WAP', "URL error. Parameter missing: picture id.");
} else {
$photo = new ProfilePhoto($id);
if ($photo->lastError) {
//Probably an non existent id (e.g. double F5, photo already deleted)
$smarty->assign('WAP', $photo->lastError);
} elseif ($photo->perso_id != $CurrentPerso->id) {
$smarty->assign('WAP', lang_get('NotYourPic'));
} else {
//OK we can delete it
$photo->delete();
$smarty->assign('NOTIFY', lang_get('PictureDeleted'));
}
}
break;
case 'edit':
if (!$id = $url[4]) {
$smarty->assign('WAP', "URL error. Parameter missing: picture id.");
} else {
$photo = new ProfilePhoto($id);
if ($photo->lastError) {
//Probably an non existent id (e.g. double F5, photo already deleted)
$smarty->assign('WAP', $photo->lastError);
} elseif ($photo->perso_id != $CurrentPerso->id) {
$smarty->assign('WAP', lang_get('NotYourPic'));
} else {
//Photo information edit form
$smarty->assign('photo', $photo);
$template = 'profile_photo_edit.tpl';
}
}
break;
case 'avatar':
//Promotes a picture to avatar
if (!$id = $url[4]) {
$smarty->assign('WAP', "URL error. Parameter missing: picture id.");
} else {
$photo = new ProfilePhoto($id);
if ($photo->lastError) {
$smarty->assign('WAP', $photo->lastError);
} elseif ($photo->perso_id != $CurrentPerso->id) {
$smarty->assign('WAP', lang_get('NotYourPic'));
} else {
//OK, promote it to avatar
$photo->promote_to_avatar();
$photo->save_to_database();
$smarty->assign('NOTIFY', lang_get('PromotedToAvatar'));
}
}
break;
default:
$smarty->assign('WAP', "Unknown URL. To delete a picture it's /delete/<picture id>. To edit it /edit/<picture id>");
break;
}
if (!$template) {
$photos = ProfilePhoto::get_photos($profile->perso_id);
if (!$smarty->tpl_vars['NOTIFY'])
$smarty->assign('NOTIFY', "Your feedback is valued. Report any bug or suggestion on the graffiti wall.");
$template = 'profile_photo.tpl';
}
break;
default:
$smarty->assign('WAP', "URL error. You can use /edit with profile, account or photos.");
break;
}
}
//
// HTML output
//
//Photos
if (count($photos) || $photo) {
$smarty->assign('URL_PICS', PHOTOS_URL);
$css[] = 'lightbox.css';
$smarty->assign('PAGE_JS', array('prototype.js', 'effects.js', 'lightbox.js'));
$smarty->assign('PICS', $photos);
}
//Serves header
$css[] = THEME . "/profile.css";
$smarty->assign('PAGE_CSS', $css);
$smarty->assign('PAGE_TITLE', $perso->name);
include('header.php');
//Serves content
if ($template) $smarty->display($template);
//Serves footer
include('footer.php');
diff --git a/includes/SmartLine/SmartLine.php b/includes/SmartLine/SmartLine.php
index 5440ed0..8929d11 100755
--- a/includes/SmartLine/SmartLine.php
+++ b/includes/SmartLine/SmartLine.php
@@ -1,526 +1,537 @@
<?php
/**
* SmartLine 0.1
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* 0.1 2007-07-28 01:36 [DcK] Initial release
* 2010-07-02 00:39 [Dck] Documentation
*
* @package Zed
* @subpackage SmartLine
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @copyright 2007 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/
* @link http://bitbucket.org/dereckson/smartline
* @filesource
///////////////////////////////////////////////////////////////////////////////
// SECTION I - INITIALIZATION
///////////////////////////////////////////////////////////////////////////////
//Constants
/**
* The standard, regular output (like STDOUT on POSIX systems)
*/
if (!defined('STDOUT')) {
define('STDOUT', 1, true);
}
/**
* The error output (like STDERR on POSIX systems)
*/
if (!defined('STDERR')) {
define('STDERR', -1, true);
}
///////////////////////////////////////////////////////////////////////////////
// SECTION Ibis - L10n
///////////////////////////////////////////////////////////////////////////////
//Ensures $lang is a standard array
if (empty($lang) || !is_array($lang)) {
$lang = array();
}
$lang = array_merge($lang, array(
//Errors
'InvalidCommand' => "Invalid command %s. Use <strong>showcommands</strong> to show all commands.",
'RegisteredButNotExistingCommand' => "[CRITICAL ERROR] The command %s has correctly been registered but its method or class doesn't exist.",
'NotYetHelpForThiscommand' => "This command hasn't been documented yet.",
//Help
'DefaultHelp' => "This SmartLine is a command line interface.
<br /><br /><strong>showcommands</strong> prints the list.
<br /><strong>help &lt;command&gt;</strong> prints help for this command.",
'Help' => array(
'help' => "<strong>help &lt;command&gt;</strong> prints command help.",
'showcommands' => 'show available commands'
)
));
///////////////////////////////////////////////////////////////////////////////
// SECTION II - HELPERS FUNCTIONS
///////////////////////////////////////////////////////////////////////////////
/**
* Error handler called during SmartLine command execution.
*
* Any error occuring during command execution will be set in STDERR.
*
* To get an array with all the errors:
* <code>$errors = $yourSmartLine->gets_all(STDERR)</code>
*
* Or to prints all the error:
* <code>$yourSmartLine->prints_all(STDERR)</code>
*
* Or to pops (gets and deletes) only the last error:
* <code>$lastError = $yourSmartLine->gets(STDERR)</code>
*
* @link http://www.php.net/manual/en/function.set-error-handler.php set_error_handler, PHP manual
* @link http://www.php.net/manual/en/errorfunc.examples.php Error handling examples, PHP manual
*
* @param int $level The PHP error level
* @param string $error The error description
* @param string $file The script where the error occured
* @param int $line The line where the error occured
*/
function SmartLineHandler($level, $error, $file, $line) {
switch ($level) {
case E_NOTICE:
$type = 'Notice';
break;
CASE E_WARNING:
$type = 'Warning';
break;
CASE E_ERROR:
$type = 'Error';
break;
default:
$type = "#$level";
}
$_SESSION['SmartLineOutput'][STDERR][] = "[PHP $type] $error in $file line $line.";
return true;
}
///////////////////////////////////////////////////////////////////////////////
// SECTION III - BASE CLASSES
///////////////////////////////////////////////////////////////////////////////
//SmartLineCommand is a class implemanting a SmartLine command.
//If you want to create a more complex command, extends this class.
/**
* The SmartLine command base class.
*
* To add a command, create an instance of the class, like:
* <code>
* class HelloWorldSmartLineCommand extends SmartLineCommand {
* public function run ($argv, $argc) {
* $this->SmartLine->puts('Hello World!');
* }
* }
* </code>
*
* Then, registers your command:
* <code>
* $yourSmartLine->register_object('hello', 'HelloWorldSmartLineCommand');
* </code>
*
* @see SmartLine::register_object
*/
class SmartLineCommand {
/**
* Initializes a new instance of the SmartLine Command
*
* @param SmartLine $SmartLine the SmartLine the command belongs
*/
- public function __construct ($SmartLine) {
- $this->SmartLine = $SmartLine;
- }
+ public function __construct ($SmartLine) {
+ $this->SmartLine = $SmartLine;
+ }
/**
* Gets the command help text or indicates help should be fetched from $lang array
*
* @return string|bool a string containing the command help or the bool value false, to enable the default behavior (ie prints $lang['help']['nameOfTheCommand'])
*/
- public function help () {
+ public function help () {
return false;
- }
+ }
/**
* Runs the command
*
* @param array $argv an array of string, each item a command argument
* @param int $argc the number of arguments
*/
- public function run ($argv, $argc) {
+ public function run ($argv, $argc) {
- }
+ }
- /**
+ /**
* The SmartLine where this instance of the command is registered
*
* @var SmartLine
*/
- public $SmartLine;
+ public $SmartLine;
}
/**
* This class represents a SmartLine instance
*
* If you use only register_object, you can use it directly.
* If you use register_method, extends this class in your SmartLine.
*/
class SmartLine {
/**
* Initializes a new instance of the SmartLine object.
*/
- public function __construct () {
- //Assumes we've an empty array where store registered commands.
- $this->commands = array();
+ public function __construct () {
+ //Assumes we've an empty array where store registered commands.
+ $this->commands = array();
- //Let's register standard commands
- $this->register_object('showcommands', 'ShowCommandsSmartLineCommand');
- $this->register_object('help', 'HelpSmartLineCommand');
- }
+ //Let's register standard commands
+ $this->register_object('showcommands', 'ShowCommandsSmartLineCommand');
+ $this->register_object('help', 'HelpSmartLineCommand');
+ }
- /**
+ /**
* Registers a private method as command.
*
* @param string $command The name of the command to register
* @param string $method The method to register [OPTIONAL]. If omitted, the method regisered will be the method having the same name as the command.
* @param bool $useArgvArgc If true, indicates the method uses $argv, $argc as parameters. If false, indicates the method uses its parameters (default behavior). [OPTIONAL]
*
* @return bool true if the command have successfully been registered ; otherwise, false.
*/
- public function register_method ($command, $method = null, $useArgvArgc = false) {
- if (is_null($function)) $method = $command;
-
- if (!method_exists($this, $method)) {
- $this->lastError = "Registration failed. Unknown method $method";
- return false;
- }
-
- $className = ucfirst($method) . 'SmartLineCommand';
- //If class exists, add a uniqid after function
- while (class_exists($method)) {
- $className = uniqid(ucfirst($method)) . 'SmartLineCommand';
- }
- //Creates the class
- if ($useArgvArgc) {
- $call = "$this->SmartLine->$method(\$argv, \$argc);";
- } else {
- //We don't know how many args we've, so we use call_user_func_array
- $call = "array_shift(\$argv);
+ public function register_method ($command, $method = null, $useArgvArgc = false) {
+ if (is_null($function)) $method = $command;
+
+ if (!method_exists($this, $method)) {
+ $this->lastError = "Registration failed. Unknown method $method";
+ return false;
+ }
+
+ $className = ucfirst($method) . 'SmartLineCommand';
+ //If class exists, add a uniqid after function
+ while (class_exists($method)) {
+ $className = uniqid(ucfirst($method)) . 'SmartLineCommand';
+ }
+ //Creates the class
+ if ($useArgvArgc) {
+ $call = "$this->SmartLine->$method(\$argv, \$argc);";
+ } else {
+ //We don't know how many args we've, so we use call_user_func_array
+ $call = "array_shift(\$argv);
call_user_func_array(
array(&\$this->SmartLine, '$method'),
\$argv
);";
}
- $code = "class $className extends SmartLineCommand {
+ $code = "class $className extends SmartLineCommand {
public function run (\$argv, \$argc) {
$call
}
}";
- eval($code);
- $this->register_object($command, $className);
- return true;
- }
+ eval($code);
+ $this->register_object($command, $className);
+ return true;
+ }
- /**
+ /**
* Registers an object extending SmartLineCommand as command.
*
* @param string $command The name of the command to register
* @param SmartLineCommand|string $object The object extending SmartLineCommand. This can be the name of the class (string) or an instance already initialized of the object (SmartLineCommand).
* @return bool true if the command have successfully been registered ; otherwise, false.
*/
- public function register_object ($command, $object) {
- if (is_object($object)) {
- //Sets SmartLine property
- $object->SmartLine = $this;
- } elseif (is_string($object)) {
- //Creates a new instance of $object
- $object = new $object($this);
- } else {
- $this->lastError = "Registration failed. register_object second parameter must be a class name (string) or an already initialized instance of such class (object) and not a " . gettype($object);
- return false;
- }
- if (!$this->caseSensitive) $command = strtolower($command);
- $this->commands[$command] = $object;
- return true;
- }
+ public function register_object ($command, $object) {
+ if (is_object($object)) {
+ //Sets SmartLine property
+ $object->SmartLine = $this;
+ } elseif (is_string($object)) {
+ //Creates a new instance of $object
+ $object = new $object($this);
+ } else {
+ $this->lastError = "Registration failed. register_object second parameter must be a class name (string) or an already initialized instance of such class (object) and not a " . gettype($object);
+ return false;
+ }
+ if (!$this->caseSensitive) {
+ $command = strtolower($command);
+ }
+ $this->commands[$command] = $object;
+ return true;
+ }
/**
* Determines wheter the specified command have been registered.
*
* @param string $command The name of the command to check
* @return true if the specified command have been registered ; otherwise, false.
*/
- public function isRegistered ($command) {
- if (!$this->caseSensitive) $command = strtolower($command);
- return array_key_exists($command, $this->commands);
- }
+ public function isRegistered ($command) {
+ if (!$this->caseSensitive) {
+ $command = strtolower($command);
+ }
+ return array_key_exists($command, $this->commands);
+ }
- /**
+ /**
* Executes the specified expression.
*
* If an error occurs during the command execution:
* the STDERR output will contains the errors,
* the value returned by this methos will be false.
*
* To execute the command and prints error:
* <code>
* $fooSmartLine = new SmartLine();
* //...
* $result = $fooSmartLine->execute($expression);
* $fooSmartLine->prints_all();
* if (!$result) {
* //Errors!
* echo "<h3>Errors</h3>";
* $fooSmartLine->prints_all(STDERR);
* }
* </code>
*
* @param string $expression The expression containing the command to execute
* @return bool true if the command have been successfuly executed ; otherwise, false.
*/
- public function execute ($expression) {
- //Does nothing if blank line
- if (!$expression) return;
-
- //Prepares $argv and $argc
- $argv = $this->expression2argv($expression);
- $argc = count($argv);
-
- //Gets command
- $command = $this->caseSensitive ? $argv[0] : strtolower($argv[0]);
-
- //If command doesn't exist, throws an error
- if (!array_key_exists($command, $this->commands)) {
- global $lang;
- $this->puts(sprintf($lang['InvalidCommand'], $command), STDERR);
- return false;
- }
-
- //Executes command, intercepting error and returns result
- set_error_handler("SmartLineHandler");
+ public function execute ($expression) {
+ //Does nothing if blank line
+ if (!$expression) return;
+
+ //Prepares $argv and $argc
+ $argv = $this->expression2argv($expression);
+ $argc = count($argv);
+
+ //Gets command
+ $command = $this->caseSensitive ? $argv[0] : strtolower($argv[0]);
+
+ //If command doesn't exist, throws an error
+ if (!array_key_exists($command, $this->commands)) {
+ global $lang;
+ $this->puts(sprintf($lang['InvalidCommand'], $command), STDERR);
+ return false;
+ }
+
+ //Executes command, intercepting error and returns result
+ set_error_handler("SmartLineHandler");
try {
$result = $this->commands[$command]->run($argv, $argc);
} catch (Exception $ex) {
$this->puts("<pre>$ex</pre>", STDERR);
}
- restore_error_handler();
- return $result;
- }
+ restore_error_handler();
+ return $result;
+ }
/**
* Adds a message to the specified output queue.
*
* @param string $message the message to queue
* @param int $output The output queue (common values are STDERR and STDOUT constants). It's an optionnal parameter ; if ommited, the default value will be STDOUT.
*/
- public function puts ($message, $output = STDOUT) {
- //
- $_SESSION['SmartLineOutput'][$output][] = $message;
- }
+ public function puts ($message, $output = STDOUT) {
+ //
+ $_SESSION['SmartLineOutput'][$output][] = $message;
+ }
/**
* Truncates the specified output queue.
*
* @param int $output The output queue (common values are STDERR and STDOUT constants). It's an optionnal parameter ; if ommited, the default value will be STDOUT.
*/
- public function truncate ($output = STDOUT) {
- unset($_SESSION['SmartLineOutput'][$output]);
- }
+ public function truncate ($output = STDOUT) {
+ unset($_SESSION['SmartLineOutput'][$output]);
+ }
/**
* Pops (gets and clears) the first message from the specified output queue.
*
* @param int $output The output queue (common values are STDERR and STDOUT constants). It's an optionnal parameter ; if ommited, the default value will be STDOUT.
* @return string the message
*/
- public function gets ($output = STDOUT) {
- if (count($_SESSION['SmartLineOutput'][$output] > 0))
- return array_pop($_SESSION['SmartLineOutput'][$output]);
- }
+ public function gets ($output = STDOUT) {
+ if (count($_SESSION['SmartLineOutput'][$output] > 0)) {
+ return array_pop($_SESSION['SmartLineOutput'][$output]);
+ }
+ }
/**
* Gets the number of messages in the specified output queue.
*
* @param int $output The output queue (common values are STDERR and STDOUT constants). It's an optionnal parameter ; if ommited, the default value will be STDOUT.
*/
- public function count ($output = STDOUT) {
- return count($_SESSION['SmartLineOutput'][$output]);
- }
+ public function count ($output = STDOUT) {
+ return count($_SESSION['SmartLineOutput'][$output]);
+ }
/**
* Gets all the message from the specified output queue.
*
* @param int $output The output queue (common values are STDERR and STDOUT constants). It's an optionnal parameter ; if ommited, the default value will be STDOUT.
* @param string $prefix The string to prepend each message with. It's an optionnal parameter ; if ommited, '<p>'.
* @param string $suffix The string to append each message with. It's an optionnal parameter ; if ommited, '</p>'.
* @return Array an array of string, each item a message from the specified output queue
*/
- public function gets_all ($output = STDOUT, $prefix = '<p>', $suffix = '</p>') {
- $count = count($_SESSION['SmartLineOutput'][$output]);
- if ($count == 0) return;
- for ($i = 0 ; $i < $count ; $i++)
- $buffer .= $prefix . $_SESSION['SmartLineOutput'][$output][$i] . $suffix;
- unset ($_SESSION['SmartLineOutput'][$output]);
+ public function gets_all ($output = STDOUT, $prefix = '<p>', $suffix = '</p>') {
+ $count = count($_SESSION['SmartLineOutput'][$output]);
+ if ($count == 0) {
+ return;
+ }
+ for ($i = 0 ; $i < $count ; $i++) {
+ $buffer .= $prefix . $_SESSION['SmartLineOutput'][$output][$i] . $suffix;
+ }
+ unset ($_SESSION['SmartLineOutput'][$output]);
return $buffer;
- }
+ }
/**
* Prints all the message from the specified output queue.
*
* @param int $output The output queue (common values are STDERR and STDOUT constants). It's an optionnal parameter ; if ommited, the default value will be STDOUT.
* @param string $prefix The string to prepend each message with. It's an optionnal parameter ; if ommited, '<p>'.
* @param string $suffix The string to append each message with. It's an optionnal parameter ; if ommited, '</p>'.
*/
- public function prints_all ($output = STDOUT, $prefix = '<p>', $suffix = '</p>') {
- $count = count($_SESSION['SmartLineOutput'][$output]);
- if ($count == 0) return;
- for ($i = 0 ; $i < $count ; $i++)
- echo $prefix, $_SESSION['SmartLineOutput'][$output][$i], $suffix;
- unset ($_SESSION['SmartLineOutput'][$output]);
- }
+ public function prints_all ($output = STDOUT, $prefix = '<p>', $suffix = '</p>') {
+ $count = count($_SESSION['SmartLineOutput'][$output]);
+ if ($count == 0) {
+ return;
+ }
+ for ($i = 0 ; $i < $count ; $i++) {
+ echo $prefix, $_SESSION['SmartLineOutput'][$output][$i], $suffix;
+ }
+ unset ($_SESSION['SmartLineOutput'][$output]);
+ }
/**
* Gets the command help
*
* @param string $command The command to get help from
* @param string The command help
*/
- public function gethelp ($command) {
- return $this->commands[$command]->help();
- }
+ public function gethelp ($command) {
+ return $this->commands[$command]->help();
+ }
/**
* Gets an an argv array from the specified expression
*
* @param string $expression The expression to transform into a argv array
* @return Array An array of string, the first item the command, the others those arguments.
*/
- private function expression2argv ($expression) {
+ private function expression2argv ($expression) {
//Checks if expression contains "
$pos1 = strpos($expression, '"');
//We isolate "subexpression"
if ($pos1 !== false) {
$pos2 = $pos1;
do {
$pos2 = strpos($expression, '"', $pos2 + 1);
} while ($pos2 !== false && ($expression[$pos2 - 1] == "\\" && $expression[$pos2 - 2] != "\\"));
if ($pos2 === false) {
//If final quote is missing, throws a warning and autoadds it.
$this->puts("[Warning] Final \" missing in $expression.", STDERR);
$argv = $this->expression2argv(substr($expression, 0, $pos1));
$argv[] = substr($expression, $pos1 + 1);
return $argv;
}
return array_merge(
$this->expression2argv(substr($expression, 0, $pos1)),
array(substr($expression, $pos1 + 1, $pos2 - $pos1 - 1)),
$this->expression2argv(substr($expression, $pos2 + 1))
);
}
//Standard expression (ie without ")
$argv = array();
$items = explode(' ', $expression);
- foreach ($items as $item) {
- $item = trim($item);
- if (!$item) {
- //blank, we ignore
- continue;
- }
- $argv[] = $item;
- }
- return $argv;
- }
-
- //Contains last error
- public $lastError = '';
-
- //If true, command isn't equal to Command
- public $caseSensitive = true;
+ foreach ($items as $item) {
+ $item = trim($item);
+ if (!$item) {
+ //blank, we ignore
+ continue;
+ }
+ $argv[] = $item;
+ }
+ return $argv;
+ }
+
+ //Contains last error
+ public $lastError = '';
+
+ //If true, command isn't equal to Command
+ public $caseSensitive = true;
}
///////////////////////////////////////////////////////////////////////////////
// SECTION IV - STANDARD COMMANDS
///////////////////////////////////////////////////////////////////////////////
/*
* These commands are availaible in all default smartlines instance
*/
/**
* The standard command "showcommands"
*
* This command returns a list, with all the available commands
*/
class ShowCommandsSmartLineCommand extends SmartLineCommand {
/**
* Runs the command
*
* @param array $argv an array of string, each item a command argument
* @param int $argc the number of arguments
*/
- public function run ($argv, $argc) {
- $commands = array_keys($this->SmartLine->commands);
- sort($commands);
- $this->SmartLine->puts(implode(' ', $commands));
- }
+ public function run ($argv, $argc) {
+ $commands = array_keys($this->SmartLine->commands);
+ sort($commands);
+ $this->SmartLine->puts(implode(' ', $commands));
+ }
}
/**
* The standard command "help"
*
* This command prints command help.
*
* Help could be defined
* in the command classes, as a return value from the help method ;
* in the $lang['Help'] array, at the command key (e.g. $lang['Help']['quux'] for the quux command).
*/
class HelpSmartLineCommand extends SmartLineCommand {
/**
* Runs the command
*
* @param array $argv an array of string, each item a command argument
* @param int $argc the number of arguments
*/
- public function run ($argv, $argc) {
+ public function run ($argv, $argc) {
global $lang;
if ($argc == 1) {
$this->SmartLine->puts($lang['DefaultHelp']);
} elseif (!$this->SmartLine->isRegistered($argv[1])) {
$this->SmartLine->puts(sprintf($lang['InvalidCommand'], str_replace(' ', '&nbsp;', $argv[1])), STDERR);
} else {
$command = strtolower($argv[1]);
if (!$help = $this->SmartLine->gethelp($command)) {
if (array_key_exists($command, $lang['Help'])) {
$help = $lang['Help'][$command];
} else {
$help = $lang['NotYetHelpForThiscommand'];
}
}
$this->SmartLine->puts($help);
}
- }
+ }
}
///////////////////////////////////////////////////////////////////////////////
-;
+
diff --git a/includes/SmartLine/ZedCommands.php b/includes/SmartLine/ZedCommands.php
index e6f53f0..5d4920e 100755
--- a/includes/SmartLine/ZedCommands.php
+++ b/includes/SmartLine/ZedCommands.php
@@ -1,472 +1,472 @@
<?php
/**
* Zed SmartLine commands.
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* This is the SmartLine subcontroller.
*
* The SmartLine is a widget allowing to add some basic CLI capability.
*
* It executes any command given in GET or POST request (parameter C).
*
* This files also provides SmartLine history helper: a method log_C to log
* a SmartLine command and some procedural code assigning a SmartLineHistory.
*
* This code is inspired from Viper, a corporate PHP intranet I wrote in 2004.
* There, the SmartLine allowed to change color theme or to find quickly user,
* account, order or server information in a CRM context.
*
* @package Zed
* @subpackage SmartLine
* @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 SettingsSmartLineCommand - understand why dojo floating pane isn't rendered if we est $controller instead to redirect
*/
///
/// Register commands
///
$smartLine->register_object('goto', 'GotoSmartLineCommand');
$smartLine->register_object('guid', 'GUIDSmartLineCommand');
$smartLine->register_object('invite', 'InviteSmartLineCommand');
$smartLine->register_object('invites', 'InviteSmartLineCommand');
$smartLine->register_object('list', 'ListSmartLineCommand');
$smartLine->register_object('requests', 'RequestsSmartLineCommand');
$smartLine->register_object('settings', 'SettingsSmartLineCommand');
$smartLine->register_object('unixtime', 'UnixTimeSmartLineCommand');
$smartLine->register_object('version', 'VersionSmartLineCommand');
$smartLine->register_object('whereami', 'WhereAmISmartLineCommand');
///
/// Help (todo: move $lang array in lang folder)
///
$lang['Help']['goto'] = "Go to a location";
$lang['Help']['guid'] = "Generate a GUID";
$lang['Help']['invite'] = "Generate an invite. To see the generated invites, invite list.";
$lang['Help']['list'] = "Lists specified objects (bodies, locations or places)";
$lang['Help']['requests'] = "Checks if there are waiting requests";
$lang['Help']['settings'] = 'Go to settings page';
$lang['Help']['unixtime'] = "Prints current unixtime (seconds elapsed since 1970-01-01 00:00, UTC) or the specified unixtime date.";
$lang['Help']['version'] = "Gets Zed's software version info (Mercurial repository version, node id and if you're on the dev or prod site)";
$lang['Help']['whereami'] = "Where am I?";
/**
* The goto command
*
* Moves to the current perso to the specified location.
*/
class GotoSmartLineCommand extends SmartLineCommand {
/**
* Runs the command
*
* @param array $argv an array of string, each item a command argument
* @param int $argc the number of arguments
*
* @todo allow .goto global local (e.g. .goto B0001001 T2C3)
* @todo determine if we allow rewrite rules to bypass can_travel rules
*/
public function run ($argv, $argc) {
global $CurrentPerso;
if ($argc == 1) {
$this->SmartLine->puts("Where do you want to go?", STDERR);
return;
}
if ($argc > 2) {
$ignored_string = implode(" ", array_slice($argv, 2));
$this->SmartLine->puts("Warning: ignoring $ignored_string", STDERR);
}
require_once("includes/geo/location.php");
require_once("includes/travel/travel.php");
$here = new GeoLocation($CurrentPerso->location_global, $CurrentPerso->location_local);
$travel = Travel::load(); //maps content/travel.xml
//Parses the expression, by order of priority, as :
// - a rewrite rule
// - a new global location
// - a new local location (inside the current global location)
if (!$travel->try_parse_rewrite_rule($argv[1], $here, $place)) {
try {
$place = new GeoLocation($argv[1]);
if ($place->equals($CurrentPerso->location_global)) {
$this->SmartLine->puts("You're already there.");
return;
}
} catch (Exception $ex) {
//Global location failed, trying local location
try {
$place = new GeoLocation($CurrentPerso->location_global, $argv[1]);
} catch (Exception $ex) {
$this->SmartLine->puts($ex->getMessage(), STDERR);
return;
}
if ($place->equals($here)) {
$this->SmartLine->puts("You're already there.");
return;
}
}
}
//Could we really go there?
if (!$travel->can_travel($here, $place)) {
$this->SmartLine->puts("You can't reach that location.");
return;
}
//Moves
$CurrentPerso->move_to($place->global, $place->local);
$this->SmartLine->puts("You travel to that location.");
return;
}
}
/**
* The GUID command
*
* Prints a new GUID.
*
* guid 8 will print 8 guid
*/
class GUIDSmartLineCommand extends SmartLineCommand {
/**
* Runs the command
*
* @param array $argv an array of string, each item a command argument
* @param int $argc the number of arguments
*/
public function run ($argv, $argc) {
- if ($argc > 1 && is_numeric($argv[1])) {
- for ($i = 0 ; $i < $argv[1] ; $i++) {
- $this->SmartLine->puts(new_guid());
- }
- return;
- }
-
- $this->SmartLine->puts(new_guid());
+ if ($argc > 1 && is_numeric($argv[1])) {
+ for ($i = 0 ; $i < $argv[1] ; $i++) {
+ $this->SmartLine->puts(new_guid());
+ }
+ return;
+ }
+
+ $this->SmartLine->puts(new_guid());
}
}
/**
* The invite command
*
* Manages invites.
*
* invite [add]
* creates a new invite code
*
* invite del <invite code>
* deletes the specified invite
*
* invite list
* prints current invite codes
*/
class InviteSmartLineCommand extends SmartLineCommand {
/**
* Runs the command
*
* @param array $argv an array of string, each item a command argument
* @param int $argc the number of arguments
*/
public function run ($argv, $argc) {
- require_once('includes/objects/invite.php');
- global $CurrentUser, $CurrentPerso;
-
- $command = ($argc > 1) ? strtolower($argv[1]) : '';
- switch ($command) {
- case 'list':
- $codes = Invite::get_invites_from($CurrentPerso->id);
- if (!count($codes)) {
- $this->SmartLine->puts("No invite code.");
- } else {
- foreach ($codes as $code) {
- $this->SmartLine->puts($code);
- }
- }
- break;
-
- case 'add':
- case '':
- $code = Invite::create($CurrentUser->id, $CurrentPerso->id);
- $url = get_server_url() . get_url('invite', $code);
- $this->SmartLine->puts("New invite code created: $code<br />Invite URL: $url");
- break;
-
- case 'del':
- $code = $argv[2];
- if (!preg_match("/^([A-Z]){3}([0-9]){3}$/i", $code)) {
- $this->SmartLine->puts("Invalid code format. Use invite list to get all your invite codes.", STDERR);
- } else {
- $invite = new Invite($code);
- if ($CurrentPerso->id == $invite->from_perso_id) {
- $invite->delete();
- $this->SmartLine->puts("Deleted");
- } else {
- $this->SmartLine->puts("Invalid code. Use invite list to get all your invite codes.", STDERR);
- }
- }
- break;
-
- default:
- $this->SmartLine->puts("Usage: invite [add|list|del <code>]", STDERR);
- break;
- }
+ require_once('includes/objects/invite.php');
+ global $CurrentUser, $CurrentPerso;
+
+ $command = ($argc > 1) ? strtolower($argv[1]) : '';
+ switch ($command) {
+ case 'list':
+ $codes = Invite::get_invites_from($CurrentPerso->id);
+ if (!count($codes)) {
+ $this->SmartLine->puts("No invite code.");
+ } else {
+ foreach ($codes as $code) {
+ $this->SmartLine->puts($code);
+ }
+ }
+ break;
+
+ case 'add':
+ case '':
+ $code = Invite::create($CurrentUser->id, $CurrentPerso->id);
+ $url = get_server_url() . get_url('invite', $code);
+ $this->SmartLine->puts("New invite code created: $code<br />Invite URL: $url");
+ break;
+
+ case 'del':
+ $code = $argv[2];
+ if (!preg_match("/^([A-Z]){3}([0-9]){3}$/i", $code)) {
+ $this->SmartLine->puts("Invalid code format. Use invite list to get all your invite codes.", STDERR);
+ } else {
+ $invite = new Invite($code);
+ if ($CurrentPerso->id == $invite->from_perso_id) {
+ $invite->delete();
+ $this->SmartLine->puts("Deleted");
+ } else {
+ $this->SmartLine->puts("Invalid code. Use invite list to get all your invite codes.", STDERR);
+ }
+ }
+ break;
+
+ default:
+ $this->SmartLine->puts("Usage: invite [add|list|del <code>]", STDERR);
+ break;
+ }
}
}
/**
* The list command
*
* Prints a list of bodies, locations or places.
*
* This can easily be extended to output any list from any table.
*/
class ListSmartLineCommand extends SmartLineCommand {
/**
* Runs the command
*
* @param array $argv an array of string, each item a command argument
* @param int $argc the number of arguments
*/
public function run ($argv, $argc) {
if ($argc == 1) {
$this->SmartLine->puts("Available lists: bodies, locations, places");
return;
}
switch ($objects = $argv[1]) {
case 'bodies':
$list = $this->get_list(TABLE_BODIES, "CONCAT('B', body_code)", "body_name");
$this->SmartLine->puts($list);
break;
case 'locations':
$list = $this->get_list(TABLE_LOCATIONS, "location_code", "location_name");
$this->SmartLine->puts($list);
break;
case 'places':
if ($argv[2] == "-a" || $argv[2] == "--all") {
//Global bodies places list
$list = $this->get_list(TABLE_PLACES, "CONCAT('B', body_code, place_code)", "place_name");
} else {
//Local places (or equivalent) list
global $CurrentPerso;
switch ($CurrentPerso->location_global[0]) {
case 'B':
$body_code = substr($CurrentPerso->location_global, 1, 5);
$list = $this->get_list(TABLE_PLACES, "CONCAT('B', body_code, place_code)", "place_name", "body_code = $body_code");
break;
case 'S':
$this->SmartLine->puts("I don't have a map of the spaceship.", STDERR);
return;
default:
$this->SmartLine->puts("Unknown location type. Can only handle B or S.", STDERR);
return;
}
}
$this->SmartLine->puts($list);
break;
default:
$this->SmartLine->puts("Unknown objects to list: $objects", STDERR);
}
}
/**
* Gets a custom list from the specified table and fields.
*
* The list will ascendingly ordered by the specified key.
*
* @param $table the table to query from the database
* @param $key the first field to fetch, as key
* @param $value the second field to fetch, as value
* @param $where the WHERE clause, without the WHERE keyword (optionnal)
*/
public function get_list ($table, $key, $value, $where = null) {
global $db;
$sql = "SELECT $key as `key`, $value as value FROM $table ";
if ($where) {
$sql .= "WHERE $where ";
}
$sql .= "ORDER BY `key` ASC";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Unable to fetch list", '', __LINE__, __FILE__, $sql);
}
while ($row = $db->sql_fetchrow($result)) {
$rows .= "<tr><td>$row[key]</td><td>$row[value]</td></tr>";
}
$this->SmartLine->truncate(STDERR); //kludge
return "<table cellspacing=\"8\"><thead style=\"color: white\" scope=\"row\"><tr><th>Key</th><th>Value</th></thead><tbody>$rows</tbody></table>";
}
}
/**
* The requests command
*
* Redirects user the the requests page.
*
* By default only redirect if a flag indicates there's a new request.
*
* To forcefully goes to the request page, requests --force
*/
class RequestsSmartLineCommand extends SmartLineCommand {
/**
* Runs the command
*
* @param array $argv an array of string, each item a command argument
* @param int $argc the number of arguments
*/
public function run ($argv, $argc) {
- global $CurrentPerso;
- $force = ($argc > 1) && ($argv[1] == "-f" || $argv[1] == "--force");
- if ($force || (array_key_exists('site.requests', $CurrentPerso->flags) && $CurrentPerso->flags['site.requests'])) {
- global $controller;
- $controller = 'controllers/persorequest.php';
- } else {
- $this->SmartLine->puts("No request waiting.");
- }
+ global $CurrentPerso;
+ $force = ($argc > 1) && ($argv[1] == "-f" || $argv[1] == "--force");
+ if ($force || (array_key_exists('site.requests', $CurrentPerso->flags) && $CurrentPerso->flags['site.requests'])) {
+ global $controller;
+ $controller = 'controllers/persorequest.php';
+ } else {
+ $this->SmartLine->puts("No request waiting.");
+ }
}
}
/**
* The settings command
*
* Redirects user the the settings page.
*/
class SettingsSmartLineCommand extends SmartLineCommand {
/**
* Runs the command
*
* @param array $argv an array of string, each item a command argument
* @param int $argc the number of arguments
*/
public function run ($argv, $argc) {
- if (headers_sent()) {
- global $controller;
- $controller = 'controllers/settings.php';
- } else {
- header('location: ' . get_url('settings'));
- }
+ if (headers_sent()) {
+ global $controller;
+ $controller = 'controllers/settings.php';
+ } else {
+ header('location: ' . get_url('settings'));
+ }
}
}
/**
* The unixtime command
*
* Prints current unixtime (seconds elapsed since 1970-01-01 00:00, UTC)
* or if an unixtime is specified as argument, the matching date.
*/
class UnixTimeSmartLineCommand extends SmartLineCommand {
/**
* Runs the command
*
* @param array $argv an array of string, each item a command argument
* @param int $argc the number of arguments
*/
public function run ($argv, $argc) {
date_default_timezone_set('UTC');
if ($argc == 1) {
$this->SmartLine->puts(time());
} elseif ($argc == 2 && is_numeric($argv[1])) {
$this->SmartLine->puts(strftime("%Y-%m-%d %X", $argv[1]));
$this->SmartLine->puts(get_hypership_time($argv[1]));
} else {
array_shift($argv);
$date = implode(' ', $argv);
if ($time = strtotime($date) !== false) {
$this->SmartLine->puts("Unixtime from $date: <span class=\"highlight\">$time</span>");
} else {
$this->SmartLine->puts("$date isn't a unixtime nor a valid date strtotime is able to parse.", STDERR);
}
}
}
}
/**
* The version command
*
* Prints current hg revision, if we're in prod or dev environement and
* the current revision's hash.
*
* The version and env information is extracted from
* .hg/tags.cache (indicating we're in a Mercurial repo and so in a dev environment), or from
* version.txt file (indicating we've deployed code in a production environement)
*
* e.g. r130 (development environment)
* Hash: 057bf394741706fd2136541e3bb07c9e60b4963d
*/
class VersionSmartLineCommand extends SmartLineCommand {
/**
* Runs the command
*
* @param array $argv an array of string, each item a command argument
* @param int $argc the number of arguments
*/
public function run ($argv, $argc) {
- //Gets .hg revision
- if (file_exists('.hg/tags.cache')) {
- $content = file_get_contents('.hg/tags.cache');
- $info = explode(' ', $content, 2);
- $info[] = "development environment";
-
- $this->SmartLine->puts("r$info[0] ($info[2])");
- $this->SmartLine->puts("Hash: $info[1]");
- } else if (file_exists('version.txt')) {
- $content = file('version.txt');
+ //Gets .hg revision
+ if (file_exists('.hg/tags.cache')) {
+ $content = file_get_contents('.hg/tags.cache');
+ $info = explode(' ', $content, 2);
+ $info[] = "development environment";
+
+ $this->SmartLine->puts("r$info[0] ($info[2])");
+ $this->SmartLine->puts("Hash: $info[1]");
+ } else if (file_exists('version.txt')) {
+ $content = file('version.txt');
foreach ($content as $line) {
$this->SmartLine->puts($line);
}
- } else {
- $this->SmartLine->puts("No version information available.", STDERR);
- return false;
- }
+ } else {
+ $this->SmartLine->puts("No version information available.", STDERR);
+ return false;
+ }
return true;
- }
+ }
}
/**
* The whereami (Where am I?) command
*
* Prints current position, e.g. B00001001 - Tour, Hypership
*/
class WhereAmISmartLineCommand extends SmartLineCommand {
/**
* Runs the command
*
* @param array $argv an array of string, each item a command argument
* @param int $argc the number of arguments
*/
public function run ($argv, $argc) {
- global $CurrentPerso;
+ global $CurrentPerso;
- require_once("includes/geo/location.php");
- $place = new GeoLocation($CurrentPerso->location_global);
- $this->SmartLine->puts($CurrentPerso->location_global . ' - ' . $place);
+ require_once("includes/geo/location.php");
+ $place = new GeoLocation($CurrentPerso->location_global);
+ $this->SmartLine->puts($CurrentPerso->location_global . ' - ' . $place);
}
}
diff --git a/includes/api/BeautyXML.class.php b/includes/api/BeautyXML.class.php
index 501fc61..3c94cb4 100755
--- a/includes/api/BeautyXML.class.php
+++ b/includes/api/BeautyXML.class.php
@@ -1,162 +1,162 @@
<?php
/**
* XML beautifer
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
*
* This class is simple XML beautifer
* it's very, very, very simple - feature version will be better :-)
*
* IMPORTANT NOTE
* there is no warranty, implied or otherwise with this software.
*
* version 0.1 | August 2004
*
* released under a LGPL licence.
*
* Slawomir Jasinski,
* http://www.jasinski.us (polish only - my home page)
* http://www.cgi.csd.pl (english & polish)
* contact me - sj@gex.pl
*
* @package Zed
* @subpackage API
* @author Slawomir Jasinski <sj@gex.pl>
* @copyright 2004 Slawomir Jasinski, 2010 Sébastien Santoro aka Dereckson
* @license http://www.gnu.org/licenses/lgpl.html LGPL
* @version 0.1
* @link http://scherzo.dereckson.be/doc/zed
* @link http://zed.dereckson.be/
* @filesource
*
* @todo Contact Slawomir Jasinski and ask it if the current code could be
* relicensed under BSD license. If not, rewrite from scratch under BSD license.
*/
/**
* This class is simple XML beautifer.
* It's very, very, very simple - feature version will be better :-)
*
* @author Slawomir Jasinski <sj@gex.pl>
*/
class BeautyXML {
/**
* Indicates what characters to use to indent.
*
* If you wish a regular tabulation, the suggested value is \t ;
* If you wish spaces instead, put the correct amount of spaces as value.
*
* @var string
*/
var $how_to_ident = " "; // you can user also \t or more/less spaces
/**
* Determines if long text have to be wrapped.
*
* If true, the text will be wrapped ; otherwise, long lines will be kept.
*
* @var bool
*/
var $wrap = false;
/**
* If $wrap is true, determines the line lenght.
*
* After this lenght, any text will be wrapped.
*
* @see $wrap
* @var @int
*/
var $wrap_cont = 80; // where wrap words
/**
* Idents the specified string.
*
* @param string $str the string to indent
* @param int $level the ident level, ie the number of identation to prepend the string with
*/
function ident (&$str, $level) {
$spaces = '';
$level--;
for ($a = 0; $a < $level; $a++) {
$spaces .= $this->how_to_ident;
}
return $spaces .= $str;
}
/**
* Formats the specified string, beautifying it, with proper indent.
*
* This is the main class method.
*
* @param $str the XML fragment to beautify
* @return string the beautified XML fragment
*/
function format ($str) {
$str = preg_replace("/<\?[^>]+>/", "", $str);
$tmp = explode("\n", $str); // extracting string into array
// cleaning string from spaces and other stuff like \n \r \t
for ($a = 0, $c = count($tmp); $a < $c; $a++) {
$tmp[$a] = trim($tmp[$a]);
}
// joining to string ;-)
$newstr = join("", $tmp);
$newstr = preg_replace("/>([\s]+)<\//", "></", $newstr);
- // adding \n lines where tags ar near
+ // adding \n lines where tags ar near
$newstr = str_replace("><", ">\n<", $newstr);
- // exploding - each line is one XML tag
+ // exploding - each line is one XML tag
$tmp = explode("\n", $newstr);
// preparing array for list of tags
$stab = array('');
// lets go :-)
for ($a = 0, $c = count($tmp); $a <= $c; $a++) {
$add = true;
preg_match("/<([^\/\s>]+)/", $tmp[$a], $match);
$lan = trim(strtr($match[0], "<>", " "));
$level = count($stab);
if (in_array($lan, $stab) && substr_count($tmp[$a], "</$lan") == 1) {
$level--;
$s = array_pop($stab);
$add = false;
}
if (substr_count($tmp[$a], "<$lan") == 1 && substr_count($tmp[$a], "</$lan") == 1) {
$add = false;
}
if (preg_match("/\/>$/", $tmp[$a], $match)) {
$add = false;
}
$tmp[$a] = $this->ident($tmp[$a], $level);
if ($this->wrap) {
$tmp[$a] = wordwrap($tmp[$a], $this->wrap_cont, "\n" . $this->how_to_ident . $this->how_to_ident . $this->how_to_ident);
}
if ($add && !@in_array($lan, $stab) && $lan != '') {
array_push($stab, $lan);
}
}
return join("\n", $tmp);
}
}
diff --git a/includes/auth/UserPasswordAuthentication.php b/includes/auth/UserPasswordAuthentication.php
index c936e07..ec2bfd8 100644
--- a/includes/auth/UserPasswordAuthentication.php
+++ b/includes/auth/UserPasswordAuthentication.php
@@ -1,141 +1,141 @@
<?php
/**
* User/password authentication class.
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2013, Dereckson, some rights reserved.
* Released under BSD license.
*
* @package Zed
* @subpackage Auth
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @copyright 2013 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
*/
/**
* UserPasswordAuthentication class
*
* Authenticates a user with an username and a password
*/
/**
* Login/pass authentication
*/
class UserPasswordAuthentication implements IAuthentication {
/**
* The username
* @var string
*/
private $username;
/**
* The password in clear text
* @var string
*/
private $password;
/**
* The last authentication error
* @var string
*/
private $error;
/**
* The user_id matching the username
* @var int
*/
private $user_id;
/**
* Indicates if the error MUST be returned to the user
* @var string
*/
private $mustThrowError = false;
/**
* Initializes a new instance of the UserPasswordAuthentication class
*
* @param string $username The username
* @param string $passwordThe password
*/
public function __construct ($username, $password) {
- $this->username = $username;
- $this->password = $password;
+ $this->username = $username;
+ $this->password = $password;
}
/**
* Gets the hash of the password
*
* @param string $password The password in clear text
* @return string The hashed password
*/
function getPasswordHash ($password) {
- return md5($password); //TODO: replace this by a salted MD5 or better, by another algo.
+ return md5($password); //TODO: replace this by a salted MD5 or better, by another algo.
}
/**
* Determines if the login/pass is valid
*
* @return bool true if the login/pass is valid; otherwise, false.
*/
function isValid () {
- global $db;
-
- $sql = "SELECT user_password, user_id FROM " . TABLE_USERS . " WHERE username = '$this->username'";
- if (!$result = $db->sql_query($sql)) {
- message_die(SQL_ERROR, "Can't query users table.", '', __LINE__, __FILE__, $sql);
- }
- if ($row = $db->sql_fetchrow($result)) {
- $this->user_id = $row['user_id'];
- if (!$row['user_password']) {
- $this->error = "This account exists but haven't a password defined. Use OpenID or contact dereckson (at) espace-win.org to fix that.";
- $mustThrowError = true;
- } elseif ($row['user_password'] != $this->getPasswordHash($this->password)) {
- //PASS NOT OK
- $this->error = "Incorrect password.";
- } else {
- return true;
- }
- } else {
- $this->error = "Login not found.";
- $mustThrowError = true;
- }
-
- return false;
+ global $db;
+
+ $sql = "SELECT user_password, user_id FROM " . TABLE_USERS . " WHERE username = '$this->username'";
+ if (!$result = $db->sql_query($sql)) {
+ message_die(SQL_ERROR, "Can't query users table.", '', __LINE__, __FILE__, $sql);
+ }
+ if ($row = $db->sql_fetchrow($result)) {
+ $this->user_id = $row['user_id'];
+ if (!$row['user_password']) {
+ $this->error = "This account exists but haven't a password defined. Use OpenID or contact dereckson (at) espace-win.org to fix that.";
+ $mustThrowError = true;
+ } elseif ($row['user_password'] != $this->getPasswordHash($this->password)) {
+ //PASS NOT OK
+ $this->error = "Incorrect password.";
+ } else {
+ return true;
+ }
+ } else {
+ $this->error = "Login not found.";
+ $mustThrowError = true;
+ }
+
+ return false;
}
/**
* Gets the last authentication error
*
* @return string The last error
*/
function getError () {
- return $this->error;
+ return $this->error;
}
/**
* Gets the user_id matching the username
* You first need to validate the username, calling the isValid method.
*
* @return int The user ID
*/
function getUserID () {
- return $this->user_id;
+ return $this->user_id;
}
/**
* Determines if the next authentication method could be tried if this one failed.
*
* @return bool true if authentication can go on to the next method; otherwise, false
*/
function canTryNextAuthenticationMethod () {
- return !$this->mustThrowError;
+ return !$this->mustThrowError;
}
}
diff --git a/includes/auth/YubiCloudAuthentication.php b/includes/auth/YubiCloudAuthentication.php
index 56444ef..3652d16 100644
--- a/includes/auth/YubiCloudAuthentication.php
+++ b/includes/auth/YubiCloudAuthentication.php
@@ -1,192 +1,192 @@
<?php
/**
* YubiCloud authentication class.
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2013, Dereckson, some rights reserved.
* Released under BSD license.
*
* @package Zed
* @subpackage Auth
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @copyright 2013 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
*/
require_once('Auth/Yubico.php');
/**
* YubiCloudAuthentication class
*
* Authenticates a user through YubiCloud
*/
class YubiCloudAuthentication implements IAuthentication {
/**
* The key
* @var string
*/
private $key;
/**
* The username who should match the key
* @var string
*/
private $username;
/**
* The user_id
* @var int
*/
private $user_id;
/**
* Indicates if the error MUST be returned to the user
* @var string
*/
private $mustThrowError = false;
/**
* The last validation error
* @var string
*/
public $error;
/**
* Initializes a new instance of the key
*
* @param string $key The key
*/
public function __construct ($key, $username = null) {
- $this->username = $username;
- $this->key = $key;
+ $this->username = $username;
+ $this->key = $key;
}
/**
* Validates the specified key's characters to determine if it looks like an OTP
*
* @return boolean true if the input seems an OTP key; otherwise, false.
*/
function looksValidOTP () {
- return preg_match("/^[cbdefghijklnrtuv]{32,48}$/", $this->key);
+ return preg_match("/^[cbdefghijklnrtuv]{32,48}$/", $this->key);
}
/**
* Gets public identity
*
* @return string Public identity
*/
function getPublicIdentity () {
- return substr($this->key, 0, 12);
+ return substr($this->key, 0, 12);
}
/**
* Validates an OTP key against the YubiCloud servers
*
* @return boolean true if the input is a valid OTP key; otherwise, false.
*/
function isValid () {
- global $Config;
-
- //No need to lost time to query server if format is incorrect.
- if (!$this->looksValidOTP()) {
- $this->error = "Not the expected YubiKey OTP format.";
- return false;
- }
-
- //Query YubiCloud. We stop validation tests if that fails.
- $yubi = new Auth_Yubico(
- $Config['YubiCloud']['ClientID'],
- $Config['YubiCloud']['SecreyKey']
- );
- $auth = $yubi->verify($this->key);
- if (@PEAR::isError($auth)) {
- $this->error = $auth->getMessage();
- return false;
- }
-
- //Note: We first query the YubiCloud server, then we check if we can use the key
- // as the key is an OTP (*one time* password), this allow to invalidate it.
- // If we wouldn't do that, an attacker can reuse this password for another site.
- if (!$this->computeUserID()) {
- $this->error = "Valid YubiKey OTP. But the key doesn't match any account.";
- $this->mustThrowError = true;
- return false;
- }
-
- //Finally, if someone puts also a login, we'll check this user ID match this username
- if ($this->username) {
- $user = User::get($this->user_id);
- if ($this->username != $user->name) {
- $this->error = "Valid YubiKey OTP but fix or remove your username.";
- $this->mustThrowError = true;
- return false;
- }
- }
-
- return true;
+ global $Config;
+
+ //No need to lost time to query server if format is incorrect.
+ if (!$this->looksValidOTP()) {
+ $this->error = "Not the expected YubiKey OTP format.";
+ return false;
+ }
+
+ //Query YubiCloud. We stop validation tests if that fails.
+ $yubi = new Auth_Yubico(
+ $Config['YubiCloud']['ClientID'],
+ $Config['YubiCloud']['SecreyKey']
+ );
+ $auth = $yubi->verify($this->key);
+ if (@PEAR::isError($auth)) {
+ $this->error = $auth->getMessage();
+ return false;
+ }
+
+ //Note: We first query the YubiCloud server, then we check if we can use the key
+ // as the key is an OTP (*one time* password), this allow to invalidate it.
+ // If we wouldn't do that, an attacker can reuse this password for another site.
+ if (!$this->computeUserID()) {
+ $this->error = "Valid YubiKey OTP. But the key doesn't match any account.";
+ $this->mustThrowError = true;
+ return false;
+ }
+
+ //Finally, if someone puts also a login, we'll check this user ID match this username
+ if ($this->username) {
+ $user = User::get($this->user_id);
+ if ($this->username != $user->name) {
+ $this->error = "Valid YubiKey OTP but fix or remove your username.";
+ $this->mustThrowError = true;
+ return false;
+ }
+ }
+
+ return true;
}
/**
* Gets the user_id matching the username
*
* You first need to validate the username, calling the isValid method.
*/
function computeUserID () {
- global $db;
-
- /**
- * Here a MySQL record for a valid OTP
- * +---------+-----------+---------------+-----------------+---------+
- * | auth_id | auth_type | auth_identity | auth_properties | user_id |
- * +---------+-----------+---------------+-----------------+---------+
- * | 2 | YubiKey | cccccccccccc | NULL | 1234 |
- * +---------+-----------+---------------+-----------------+---------+
- */
- $authentication_identity = $this->getPublicIdentity();
- $sql = "SELECT user_id FROM " . TABLE_USERS_AUTH
- . " WHERE auth_type = 'YubiKey' AND auth_identity = '$authentication_identity'";
- if (!$result = $db->sql_query($sql)) {
- message_die(SQL_ERROR, "Can't query users authentication table.", '', __LINE__, __FILE__, $sql);
- }
- if ($row = $db->sql_fetchrow($result)) {
- $this->user_id = $row['user_id'];
- return true;
- }
- return false;
+ global $db;
+
+ /**
+ * Here a MySQL record for a valid OTP
+ * +---------+-----------+---------------+-----------------+---------+
+ * | auth_id | auth_type | auth_identity | auth_properties | user_id |
+ * +---------+-----------+---------------+-----------------+---------+
+ * | 2 | YubiKey | cccccccccccc | NULL | 1234 |
+ * +---------+-----------+---------------+-----------------+---------+
+ */
+ $authentication_identity = $this->getPublicIdentity();
+ $sql = "SELECT user_id FROM " . TABLE_USERS_AUTH
+ . " WHERE auth_type = 'YubiKey' AND auth_identity = '$authentication_identity'";
+ if (!$result = $db->sql_query($sql)) {
+ message_die(SQL_ERROR, "Can't query users authentication table.", '', __LINE__, __FILE__, $sql);
+ }
+ if ($row = $db->sql_fetchrow($result)) {
+ $this->user_id = $row['user_id'];
+ return true;
+ }
+ return false;
}
/**
* Gets the last authentication error
*
* @return string The last authentication error
*/
function getError () {
- return $this->error;
+ return $this->error;
}
/**
* Gets the user_id matching the key
*
* You first need to query the authentication table, calling the computeUserID method.
* This is automatically done by IsValid, as we need to validate key matches someone.
*
* @return int the user ID
*/
function getUserID () {
- return $this->user_id;
+ return $this->user_id;
}
/**
* Determines if the next authentication method could be tried if this one failed.
*
* @return bool true if authentication can go on to the next method; otherwise, false
*/
function canTryNextAuthenticationMethod () {
- return !$this->mustThrowError;
+ return !$this->mustThrowError;
}
}
diff --git a/includes/core.php b/includes/core.php
index d00d642..ee1c6d6 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);
//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);
+ 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'];
+ 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'];
+ 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);
+ 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'];
+ 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";
+ 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";
+ 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>';
+ 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;
+ $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;
- }
- }
+ 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 .
+ $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);
+ 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)) {
+ 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
+ //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) {
+ 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':
+ 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 6e48239..14fc371 100755
--- a/includes/error.php
+++ b/includes/error.php
@@ -1,258 +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
+ $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'));
+ $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);
+ $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;
+ 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 .= "
+ 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";
- }
- }
+ } 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 "
+ 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;
+ exit;
}
diff --git a/includes/geo/scene.php b/includes/geo/scene.php
index ae2d4a6..17e51ff 100755
--- a/includes/geo/scene.php
+++ b/includes/geo/scene.php
@@ -1,212 +1,212 @@
<?php
/**
* Geo scene class.
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* @package Zed
* @subpackage Geo
* @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
*/
require_once('location.php');
require_once('octocube.php');
require_once('sceneindex.php');
if (!defined('SCENE_DIR')) {
/**
* The directory containing scenes files
*/
define('SCENE_DIR', 'content/scenes');
}
/**
* Geo scene class
*
* This class provides methods to determine and renders the local scene.
*/
class GeoScene {
/**
* Last error or warning
*
* @var string
*/
public $lastError;
/**
* File scene to serve
*
* @var string
*/
public $sceneFile;
/**
* The location of the scene to print
*
* @var GeoLocation
*/
public $location;
/**
* Initializes a new GeoScene instance
*
* @param GeoLocation $location location the scene is to print
*/
function __construct ($location) {
$this->location = $location;
//Gets local scene
if ($location->containsLocalLocation) {
if ($this->get_local_scene()) return;
}
//Gets global scene
if ($location->containsGlobalLocation) {
if ($this->get_global_scene()) return;
}
//If not scene found, let's set a warning
$this->lastError = "No scene found.";
}
/**
* Gets local scene
*
* @return boolean true if a scene have been found ; otherwise, false.
*/
private function get_local_scene () {
//From the index
$index = GeoSceneIndex::Load(SCENE_DIR);
if ($tpl = $index->get_local_template($this->location->global, $this->location->local)) {
$this->sceneFile = SCENE_DIR . '/' . $tpl;
return true;
}
//From filename
$expression = $this->location->global . ' ' . $this->location->local;
if ($this->try_get_scene($expression)) {
return true;
}
return false;
}
/**
* Gets global scene
*
* @return boolean true if a scene have been found ; otherwise, false.
*/
private function get_global_scene () {
$location = $this->location;
if ($location->place) {
if ($this->try_get_scene($location->global)) {
return true;
}
}
if ($location->body) {
if ($this->try_get_scene('B' . $location->body->code)) {
return true;
}
}
return false;
}
/**
* Gets file extension
*
* @param string $file the file path
* @return string the file extension
*/
public static function get_file_extension ($file) {
$pathinfo = pathinfo($file);
return $pathinfo['extension'];
}
/**
* Renders the file
*
* @todo Add standard code to render .swf Flash/ShockWave files.
*/
public function render () {
if ($file = $this->sceneFile) {
switch ($ext = GeoScene::get_file_extension($file)) {
case 'png':
case 'jpg':
case 'gif':
case 'bmp':
echo "<img src=\"$file\" />";
break;
case 'tpl':
global $smarty, $Config;
$template_dir = $smarty->template_dir;
$smarty->template_dir = array(getcwd(), $template_dir);
//$this->location is the object reference
//Some objects like the hypership move, so we also need to know where there are.
//From the template, this object location is assigned to $location
//To get $this->location from template, use $CurrentPerso->location
if ($this->location->body) {
$smarty->assign("location", new GeoLocation($this->location->body->location));
} elseif ($this->location->ship) {
$smarty->assign("location", new GeoLocation($this->location->ship->location));
}
//Gets zone information
require_once('includes/content/zone.php');
if ($zone = ContentZone::at($this->location->global, $this->location->local)) {
$smarty->assign('zone', $zone);
}
//Scene-specific variables
$smarty->assign("SCENE_URL", defined('SCENE_URL') ? SCENE_URL : '/' . SCENE_DIR);
if ($Config['builder']['hotglue']['enable']) {
$smarty->assign("HOTGLUE", $Config['builder']['hotglue']['URL']);
- }
+ }
lang_load('scenes.conf', $this->location->global);
//Displays scene, then restores regular settings
$smarty->display($file);
$smarty->template_dir = $template_dir;
break;
case 'php':
message_die(HACK_ERROR, ".php scene files not allowed without review", '', __LINE__, __FILE__);
default:
message_die(GENERAL_ERROR, "Can't handle $ext extension for $file scene", 'GeoScene render error', __LINE__, __FILE__);
}
echo "\n\n";
}
}
/**
* Tries to get the scene file.
*
* It will tries to find in the scene directory a file with $code as name,
* and .tpl .png .gif .bmp .swf .html or .php as extension.
*
* @param string the location code (and filename)
* @return bool true if a scene file have been found and set ; otherwise, false.
*/
private function try_get_scene ($code) {
$file = SCENE_DIR . "/$code";
$extensions = array('tpl', 'png', 'jpg', 'gif', 'bmp', 'swf', 'html', 'php');
foreach ($extensions as $ext) {
if (file_exists("$file.$ext")) {
$this->sceneFile = "$file.$ext";
return true;
}
}
return false;
}
}
diff --git a/includes/geo/sceneindex.php b/includes/geo/sceneindex.php
index c9dbd5c..e071354 100755
--- a/includes/geo/sceneindex.php
+++ b/includes/geo/sceneindex.php
@@ -1,214 +1,214 @@
<?php
/**
* Geo scene index class.
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* @package Zed
* @subpackage Geo
* @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
*
* This class implements a singleton pattern.
*/
require_once('includes/cache/cache.php');
/**
* Geo scene class
*
* This class provides an index of available scene template files.
*/
class GeoSceneIndex {
/**
* Global location templates array
*
* Keys are global location codes.
* Values the relevant template file.
*
* @var Array
*/
public $global_templates;
/**
* Rocal location templates 2D array
*
* Keys are global and local ocation codes.
* Values the relevant template file.
*
* e.g. $local_templates['B00017001']['(10, 50, 8)'] => 'B00017_port.tpl'
*
* @var Array
*/
public $local_templates;
/**
* Time of the last updated file in the scenes directory
*
* @var int
*/
public $updated;
/**
* The directory where templates are stored
*
* @var string
*/
public $directory;
/**
* The current index instance array
*
* Keys are scene directories (string)
* Items are GeoSceneIndex instances
*
* @var Array
*/
static $instance = array();
/**
* Gets the index instance, initializing it if needed
*
* @return index the index instance
*/
static function load ($directory) {
//Creates the index object if needed
if (!array_key_exists($directory, self::$instance)) {
self::$instance[$directory] = new GeoSceneIndex($directory);
}
return self::$instance[$directory];
}
/**
* Initializes a new GeoSceneIndex istance
*
* @param string $directory the scene templates directory
*/
public function __construct ($directory) {
$this->directory = $directory;
if (!$this->get_cached_information() || !$this->is_up_to_date()) {
$this->refresh_information();
$this->set_cached_information();
}
}
/**
* Caches index data
*/
public function set_cached_information () {
$cache = Cache::load();
$cache->set('zed_sceneindex', serialize($this));
}
/**
* Gets index from cache
*/
public function get_cached_information () {
$cache = Cache::load();
- $cached_index =$cache->get('zed_sceneindex');
- if ($index = unserialize($cache->get('zed_sceneindex'))) {
- $index = unserialize($cache->get('zed_sceneindex'));
- $this->global_templates = $index->global_templates;
- $this->local_templates = $index->local_templates;
- $this->updated = $index->updated;
- $this->directory = $index->directory;
- return true;
- }
- return false;
+ $cached_index =$cache->get('zed_sceneindex');
+ if ($index = unserialize($cache->get('zed_sceneindex'))) {
+ $index = unserialize($cache->get('zed_sceneindex'));
+ $this->global_templates = $index->global_templates;
+ $this->local_templates = $index->local_templates;
+ $this->updated = $index->updated;
+ $this->directory = $index->directory;
+ return true;
+ }
+ return false;
}
/**
* Reads scene templates and indexes information
*/
public function refresh_information () {
$this->global_templates = array();
$this->local_templates = array();
$this->updated = filemtime($this->directory);
if ($handle = opendir($this->directory)) {
while (false !== ($file = readdir($handle))) {
if (GeoScene::get_file_extension($file) == 'tpl') {
$template = file_get_contents($this->directory . '/' . $file, false, NULL, 0, 1024);
$location = self::get_template_location($template);
if ($location[1] !== NULL) {
$this->local_templates[$location[0]][$location[1]] = $file;
} elseif ($location[0] != NULL) {
$this->global_templates[$location[0]] = $file;
}
}
}
closedir($handle);
}
}
/**
* Determines if the information is still up to date
*
* @return bool true if the information is up to date ; otherwise, false.
*/
public function is_up_to_date () {
return ($this->updated == filemtime($this->directory));
}
/**
* Gets template location
*
* @return Array an string array of the location (two items; global, local)
* At key 0, a string with global location, or NULL if not specified
* At key 1, a string with local location, or NULL if not specified
*/
private static function get_template_location ($template) {
$location = array(NULL, NULL);
//Gets global location
$pos1 = strpos($template, "Global location: ") + 17;
$pos2 = strpos($template, "\n", $pos1);
$location[0] = trim(substr($template, $pos1, $pos2 - $pos1));
//Gets local location
$pos1 = strpos($template, "Local location: ");
if ($pos1 !== false) {
$pos1 += 16;
$pos2 = strpos($template, "\n", $pos1);
$location[1] = trim(substr($template, $pos1, $pos2 - $pos1));
}
return $location;
}
/**
* Gets local template file from index
*
* @param string $location_global the global location
* @param string $location_global the local location
* @return string the relevant template scene file, or NULL if not existant
*/
public function get_local_template ($location_global, $location_local) {
if (isset($this->local_templates[$location_global][$location_local])) {
return $this->local_templates[$location_global][$location_local];
}
return NULL;
}
/**
* Gets global template file from index
*
* @param string $location_global the global location
* @return string the relevant template scene file, or NULL if not existant
*/
public function get_global_template ($location_global) {
if (isset($this->global_templates[$location_global])) {
return $this->global_templates[$location_global];
}
return NULL;
}
}
diff --git a/includes/login.php b/includes/login.php
index 8436677..a3b806c 100755
--- a/includes/login.php
+++ b/includes/login.php
@@ -1,156 +1,156 @@
<?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'";
+ . " 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";
+ //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 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 ($useYubiCloud = array_key_exists('YubiCloud', $Config) ) {
+ $authentications[] = new YubiCloudAuthentication($_POST['password'], $Login);
+ }
if ($Login) {
- $authentications[] = new UserPasswordAuthentication($Login, $_POST['password']);
- }
+ $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;
- }
- }
+ $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
+ //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);
- }
+ $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 513d200..81c016e 100755
--- a/includes/mysql.php
+++ b/includes/mysql.php
@@ -1,182 +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');
+ * 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']);
}
diff --git a/includes/objects/perso.php b/includes/objects/perso.php
index bcc74c5..6507c31 100755
--- a/includes/objects/perso.php
+++ b/includes/objects/perso.php
@@ -1,579 +1,579 @@
<?php
/**
* Perso class
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* 0.1 2010-01-27 00:39 Autogenerated by Pluton Scaffolding
* 0.2 2010-01-29 14:39 Adding flags support
* 0.3 2010-02-06 17:50 Adding static perso hashtable
* 0.4 2012-07-04 11:37 Refactoring: moving code from index.php
*
* @package Zed
* @subpackage Model
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @copyright 2010, 2012 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
*/
require_once("includes/geo/location.php");
/**
* Perso class
*
* This class maps the persos table.
*
* The class also provides methods
* to move or locate a perso,
* to gets and sets perso's flags and notes (tables persos_flags and persos_notes),
* to gets user's perso or check if a perso is online,
* to handle on select and logout events.
*
*/
class Perso {
public $id;
public $user_id;
public $name;
public $nickname;
public $race;
public $sex;
public $avatar;
public $location_global;
public $location_local;
public $flags;
public $lastError;
public static $hashtable_id = array();
public static $hashtable_name = array();
/**
* Initializes a new instance
*
* @param mixed $data perso ID or nickname
*/
function __construct ($data = null) {
if ($data) {
if (is_numeric($data)) {
$this->id = $data;
} else {
$this->nickname = $data;
}
if (!$this->load_from_database()) {
message_die(GENERAL_ERROR, $this->lastError, "Can't authenticate perso");
}
} else {
$this->generate_id();
}
}
/**
* Initializes a new Perso instance if needed or get already available one.
*
* @param mixed $data perso ID or nickname
* @return Perso the perso instance
*/
static function get ($data = null) {
if ($data) {
//Checks in the hashtables if we already have loaded this instance
if (is_numeric($data)) {
if (array_key_exists($data, Perso::$hashtable_id)) {
return Perso::$hashtable_id[$data];
}
} else {
if (array_key_exists($data, Perso::$hashtable_name)) {
return Perso::$hashtable_name[$data];
}
}
}
$perso = new Perso($data);
return $perso;
}
/**
* Loads the object Perso (ie fill the properties) from the $_POST array
*/
function load_from_form () {
if (array_key_exists('user_id', $_POST)) $this->user_id = $_POST['user_id'];
if (array_key_exists('name', $_POST)) $this->name = $_POST['name'];
if (array_key_exists('nickname', $_POST)) $this->nickname = $_POST['nickname'];
if (array_key_exists('race', $_POST)) $this->race = $_POST['race'];
if (array_key_exists('sex', $_POST)) $this->sex = $_POST['sex'];
if (array_key_exists('avatar', $_POST)) $this->avatar = $_POST['avatar'];
if (array_key_exists('location_global', $_POST)) $this->location_global = $_POST['location_global'];
if (array_key_exists('location_local', $_POST)) $this->location_local = $_POST['location_local'];
}
/**
* Loads the object Perso (ie fill the properties) from the database
*/
function load_from_database () {
global $db;
//Gets perso
$sql = "SELECT * FROM " . TABLE_PERSOS;
if ($this->id) {
$id = $db->sql_escape($this->id);
$sql .= " WHERE perso_id = '" . $id . "'";
} else {
$nickname = $db->sql_escape($this->nickname);
$sql .= " WHERE perso_nickname = '" . $nickname . "'";
}
if ( !($result = $db->sql_query($sql)) ) message_die(SQL_ERROR, "Unable to query persos", '', __LINE__, __FILE__, $sql);
if (!$row = $db->sql_fetchrow($result)) {
$this->lastError = "Perso unkwown: " . $this->id;
return false;
}
$this->id = $row['perso_id'];
$this->user_id = $row['user_id'];
$this->name = $row['perso_name'];
$this->nickname = $row['perso_nickname'];
$this->race = $row['perso_race'];
$this->sex = $row['perso_sex'];
$this->avatar = $row['perso_avatar'];
$this->location_global = $row['location_global'];
$this->location_local = $row['location_local'];
//Gets flags
$sql = "SELECT flag_key, flag_value FROM " . TABLE_PERSOS_FLAGS .
" WHERE perso_id = $this->id";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Can't get flags", '', __LINE__, __FILE__, $sql);
}
while ($row = $db->sql_fetchrow($result)) {
$this->flags[$row["flag_key"]] = $row["flag_value"];
}
//Gets location
$this->location = new GeoLocation(
$this->location_global,
$this->location_local
);
//Puts object in hashtables
Perso::$hashtable_id[$this->id] = $this;
Perso::$hashtable_name[$this->nickname] = $this;
return true;
}
/**
* Saves to database
*/
function save_to_database () {
global $db;
$id = $this->id ? "'" . $db->sql_escape($this->id) . "'" : 'NULL';
$user_id = $db->sql_escape($this->user_id);
$name = $db->sql_escape($this->name);
$nickname = $db->sql_escape($this->nickname);
$race = $db->sql_escape($this->race);
$sex = $db->sql_escape($this->sex);
$avatar = $db->sql_escape($this->avatar);
$location_global = $this->location_global ? "'" . $db->sql_escape($this->location_global) . "'" : 'NULL';
$location_local = $this->location_local ? "'" . $db->sql_escape($this->location_local) . "'" : 'NULL';
//Updates or inserts
$sql = "REPLACE INTO " . TABLE_PERSOS . " (`perso_id`, `user_id`, `perso_name`, `perso_nickname`, `perso_race`, `perso_sex`, `perso_avatar`, `location_global`, `location_local`) VALUES ($id, '$user_id', '$name', '$nickname', '$race', '$sex', '$avatar', $location_global, $location_local)";
if (!$db->sql_query($sql)) {
message_die(SQL_ERROR, "Unable to save", '', __LINE__, __FILE__, $sql);
}
if (!$id) {
//Gets new record id value
$this->id = $db->sql_nextid();
}
}
/**
* Updates the specified field in the database record
*
* @param string $field The field to save
*/
function save_field ($field) {
global $db;
if (!$this->id) {
message_die(GENERAL_ERROR, "You're trying to update a perso record not yet saved in the database: $field");
}
$id = $db->sql_escape($this->id);
$value = $db->sql_escape($this->$field);
$sql = "UPDATE " . TABLE_PERSOS . " SET `$field` = '$value' WHERE perso_id = '$id'";
if (!$db->sql_query($sql)) {
message_die(SQL_ERROR, "Unable to save $field field", '', __LINE__, __FILE__, $sql);
}
}
/**
* Gets perso location
*
* @return string The location names
*/
public function where () {
return $this->location->__toString();
}
/**
* Moves the perso to a new location
*
* @param string $global the global target location
* @param string $global the local target location
*/
public function move_to ($global = null, $local = null) {
//Sets global location
if ($global != null) {
$this->location_global = $global;
}
//Sets local location
if ($local != null) {
$this->location_local = $local;
}
//Updates database record
if ($global != null && $local != null) {
global $db;
$perso_id = $db->sql_escape($this->id);
$g = $db->sql_escape($this->location_global);
$l = $db->sql_escape($this->location_local);
$sql = "UPDATE " . TABLE_PERSOS .
" SET location_global = '$g', location_local = '$l'" .
" WHERE perso_id = '$perso_id'";
if (!$db->sql_query($sql))
message_die(SQL_ERROR, "Can't save new $global $local location.", '', __LINE__, __FILE__, $sql);
} elseif ($global != null) {
$this->save_field('location_global');
} elseif ($local != null) {
$this->save_field('location_local');
}
//Updates location member
$this->location = new GeoLocation(
$this->location_global,
$this->location_local
);
}
/**
* Gets the specified flag value
*
* @param string $key flag key
* @param mixed $defaultValue default value if the flag doesn't exist
* @return mixed the flag value (string) or null if not existing
*/
public function get_flag ($key, $defaultValue = null) {
return $this->flag_exists($key) ? $this->flags[$key] : $defaultValue;
}
/**
* Determines if the specified flag exists
*
* @param string $key the flag key to check
* @return boolean true if the specified flag exists ; otherwise, false.
*/
public function flag_exists ($key) {
return array_key_exists($key, $this->flags);
}
/**
* Sets the specified flag
*
* @param string $key flag key
* @param string $value flag value (optional, default value: 1)
*/
public function set_flag ($key, $value = 1) {
//Checks if flag isn't already set at this value
if ($this->flags != null && array_key_exists($key, $this->flags) && $this->flags[$key] === $value)
return;
//Saves flag to database
global $db;
$id = $db->sql_escape($this->id);
$key = $db->sql_escape($key);
$value = $db->sql_escape($value);
$sql = "REPLACE " . TABLE_PERSOS_FLAGS . " SET perso_id = '$id', flag_key = '$key', flag_value = '$value'";
if (!$db->sql_query($sql))
message_die(SQL_ERROR, "Can't save flag", '', __LINE__, __FILE__, $sql);
//Sets flag in this perso instance
$this->flags[$key] = $value;
}
/**
* Deletes the specified flag
*
* @param string $key flag key
*/
public function delete_flag ($key) {
global $db;
if (!array_key_exists($key, $this->flags)) return;
$id = $db->sql_escape($this->id);
$key = $db->sql_escape($key);
$sql = "DELETE FROM " . TABLE_PERSOS_FLAGS .
" WHERE flag_key = '$key' AND perso_id = '$id' LIMIT 1";
if (!$db->sql_query($sql))
message_die(SQL_ERROR, "Can't delete flag", '', __LINE__, __FILE__, $sql);
}
/**
* Ensures the current perso have the specified flag or exits.
*
*
* @param string $flag the flag to assert
* @param int $threshold value the flasg must stricly be greater than (optional, the default value is 0)
*
* Example:
* <code>
* $perso->set_flag('quux.foo', 1);
* //The perso wants to read quux, which we allow with the flag quux.foo
* $perso->request_flag('quux.foo'); //will be okay
*
* //The perso wants also to write quux, which we all allow if quux.foo = 2
* //The threshold will so be 1, as 2 > 1
* $perso->request_flag('quux.foo', 1); //Will exits, with a "You don't have quux.foo permission" message
* </code>
*/
public function request_flag ($flag, $threshold = 0) {
if (!array_key_exists($flag, $this->flags) || $this->flags[$flag] <= $threshold) {
message_die(HACK_ERROR, "You don't have $flag permission.", "Permissions");
}
}
/**
* Gets the specified note
*
* @param string $code the note code
* @return string the note content
*/
public function get_note ($code) {
global $db;
$id = $db->sql_escape($this->id);
$code = $db->sql_escape($code);
$sql = "SELECT note_text FROM " . TABLE_PERSOS_NOTES . " WHERE perso_id = '$id' AND note_code LIKE '$code'";
return $db->sql_query_express($sql);
}
/**
* Sets the specified note
*
* @param string $code the note code
* @param string $text the note content
*/
public function set_note ($code, $text) {
global $db;
$id = $db->sql_escape($this->id);
$code = $db->sql_escape($code);
$text = $db->sql_escape($text);
$sql = "REPLACE INTO " . TABLE_PERSOS_NOTES . " (perso_id, note_code, note_text) VALUES ('$id', '$code', '$text')";
if (!$db->sql_query($sql))
message_die(SQL_ERROR, "Can't save note", '', __LINE__, __FILE__, $sql);
}
/**
* Counts the amount of notes the perso have saved
*
* @return int the amount of notes assigned to the this perso
*/
public function count_notes () {
global $db;
$id = $db->sql_escape($this->id);
$sql = "SELECT COUNT(*) FROM " . TABLE_PERSOS_NOTES . " WHERE perso_id = '$id'";
return $db->sql_query_express($sql);
}
/*
* Determines if the specified ID is available
*
* @param integer $id The perso ID to check
* @return boolean true if the specified ID is available ; otherwise, false
*/
public static function is_available_id ($id) {
global $db;
$sql = "SELECT COUNT(*) FROM " . TABLE_PERSOS . " WHERE perso_id = $id LOCK IN SHARE MODE";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Can't access users table", '', __LINE__, __FILE__, $sql);
}
$row = $db->sql_fetchrow($result);
return ($row[0] == 0);
}
/**
* Generates a unique ID for the current object
*/
private function generate_id () {
do {
$this->id = rand(2001, 5999);
} while (!Perso::is_available_id($this->id));
}
/**
* Checks if the nickname is available
*
* @param string $nickname the nickname to check
*/
public static function is_available_nickname ($nickname) {
global $db;
$nickname = $db->sql_escape($nickname);
$sql = "SELECT COUNT(*) FROM " . TABLE_PERSOS . " WHERE perso_nickname LIKE '$nickname' LOCK IN SHARE MODE;";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Utilisateurs non parsable", '', __LINE__, __FILE__, $sql);
}
$row = $db->sql_fetchrow($result);
return ($row[0] == 0);
}
/**
* Counts the perso a user have
*
* @param int user_id the user ID
* @return the user's perso count
*/
public static function get_persos_count ($user_id) {
global $db;
$sql = "SELECT COUNT(*) FROM " . TABLE_PERSOS . " WHERE user_id = $user_id";
return $db->sql_query_express($sql);
}
/**
* Gets an array with all the perso of the specified user
*
* @param int $user_id the user ID
*/
public static function get_persos ($user_id) {
global $db;
$user_id = $db->sql_escape($user_id);
$sql = "SELECT perso_id FROM " . TABLE_PERSOS . " WHERE user_id = $user_id";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Can't get persos", '', __LINE__, __FILE__, $sql);
}
while ($row = $db->sql_fetchrow($result)) {
$persos[] = Perso::get($row[perso_id]);
}
return $persos;
}
/**
* Gets the first perso a user have
* (typically to be used when get_persos_count returns 1 to autoselect)
*
* @param int user_id the user ID
*/
public static function get_first_perso ($user_id) {
global $db;
$sql = "SELECT perso_id FROM " . TABLE_PERSOS ." WHERE user_id = $user_id LIMIT 1";
if ($perso_id = $db->sql_query_express($sql)) {
return new Perso($perso_id);
}
}
/**
* Determines wheter the perso is online
*
* @return bool true if the perso is online ; otherwise, false.
*/
public function is_online () {
global $db;
$id = $db->sql_escape($this->id);
$sql = "SELECT MAX(online) FROM " . TABLE_SESSIONS ." WHERE perso_id = $id";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Unable to query the table", '', __LINE__, __FILE__, $sql);
}
$row = $db->sql_fetchrow($result);
return ($row[0] == 1);
}
/**
* This event method is called when the user selects a new perso
*/
public function on_select () {
//Session
set_info('perso_id', $this->id);
$this->set_flag("site.lastlogin", $_SERVER['REQUEST_TIME']);
define("PersoSelected", true);
}
/**
* This event method is called when the user logs off its account or perso
*/
public function on_logout () {
//Clears perso information in $_SESSION and session table
set_info('perso_id', null);
clean_session();
}
/**
* This event method is called when the perso is created
*/
public function on_create () {
//Notifies inviter
- $this->notify_inviter();
+ $this->notify_inviter();
}
/**
* Creates a new perso, from a parameter form
*
* @param int $user The user to attach the perso to
* @param Perso $perso A reference to the created perso (don't initialize it, give it a null value)
* @param array $errors A reference to the arrays containing errors (should be an empty array, or the method will always return false)
* @return boolean true if the perso has ben created ; otherwise, false
*/
public static function create_perso_from_form ($user, &$perso, &$errors) {
$perso = new Perso();
$perso->load_from_form();
$perso->user_id = $user->id;
//Validates forms
if (!$perso->name) $errors[] = lang_get("NoFullnameSpecified");
if (!$perso->race) {
$errors[] = lang_get("NoRaceSpecified");
$perso->race = "being";
}
if (!$perso->sex) $errors[] = lang_get("NoSexSpecified");
if (!$perso->nickname) {
$errors[] = lang_get("NoNicknameSpecified");
} else if (!Perso::is_available_nickname($perso->nickname)) {
$errors[] = lang_get("UnavailableNickname");
}
if (count($errors)) return false;
//Creates perso
$perso->save_to_database();
$perso->on_create();
return true;
}
/**
* Notifies the person having invited this perso
*/
public function notify_inviter() {
require_once('includes/objects/message.php');
require_once('includes/objects/invite.php');
$message = new Message();
$message->from = 0;
$message->to = invite::who_invited($this->id);
$message->text = sprintf(
lang_get('InvitePersoCreated'),
$this->name,
get_server_url() . get_url('who', $this->nickname)
);
$message->send();
}
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Nov 11, 11:08 (2 w, 3 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
20928
Default Alt Text
(158 KB)

Event Timeline