diff --git a/code/web/api/client/config.php.default b/code/web/api/client/config.php.default
index 3c8ca869d..6cdbff401 100644
--- a/code/web/api/client/config.php.default
+++ b/code/web/api/client/config.php.default
@@ -17,4 +17,4 @@
*/
// Url where player_auth.php is located
-define('RYAPI_AUTH_SCRIPT', '');
+define('RYAPI_AUTH_SCRIPT', '');
\ No newline at end of file
diff --git a/code/web/api/client/time.php b/code/web/api/client/time.php
new file mode 100644
index 000000000..4b81db42a
--- /dev/null
+++ b/code/web/api/client/time.php
@@ -0,0 +1,46 @@
+.
+ */
+
+$tick_cache_timeout = 60;
+
+function ryzom_time_tick() {
+ $fn = RYAPI_URL.'data/cache/game_cycle.ticks';
+ $handle = fopen($fn, "r");
+ $version = fread($handle, 1);
+ $raw_tick = fread($handle, 4);
+ fclose($handle);
+ $arr = unpack("V", $raw_tick);
+ $tick = $arr[1];
+ return sprintf("%u", $tick & 0xffffffff);
+}
+
+
+/**
+ * Takes a computed ryzom time array and returns a SimpleXMLElement
+ */
+function ryzom_time_xml($rytime) {
+ global $tick_cache_timeout;
+ $out = ryzom_time_xml_without_cache($rytime);
+ $filename = RYAPI_URL.'data/cache/game_cycle.ticks';
+ $cache = $out->addChild('cache');
+ $cache->addAttribute('created', filemtime($filename));
+ $cache->addAttribute('expire', (filemtime($filename)+$tick_cache_timeout));
+ return $out;
+}
+
+?>
\ No newline at end of file
diff --git a/code/web/api/common/actionPage.php b/code/web/api/common/actionPage.php
new file mode 100644
index 000000000..676012146
--- /dev/null
+++ b/code/web/api/common/actionPage.php
@@ -0,0 +1,158 @@
+.
+ */
+
+class ryActionClass {
+ public $classname;
+ public $instance;
+ public $args;
+ public $requires;
+
+ function __construct($classname, $instance, $args, $requires) {
+ $this->classname = $classname;
+ $this->instance = $instance;
+ $this->args = $args;
+ $this->requires = $requires;
+ }
+
+}
+
+class ryActionPage {
+
+ private static $classesArgs = array();
+ private static $myClasses = array();
+ private static $aliases = array();
+ private static $messages;
+ private static $haveMessage;
+ protected static $id;
+
+ public $instanceName;
+ public $myMethods = array();
+
+ function __construct() {
+ }
+
+ function addMethods($child_class) {
+ if (is_array($child_class)) {
+ foreach ($child_class as $c_class)
+ $this->myMethods = array_merge($this->myMethods, get_class_methods($c_class));
+ } else {
+ $this->myMethods = get_class_methods($child_class);
+ }
+ }
+
+ static function addClass($name, $classname, $args=array(), $requires=NULL) {
+ self::$myClasses[$name] = new ryActionClass($classname, NULL, $args, $requires);
+ }
+
+ static function addAlias($aliasname, $name) {
+ self::$aliases[$aliasname] = $name;
+ }
+
+ static function initInstance($listener) {
+ $i = self::$myClasses[$listener];
+ if (!$i->instance) {
+ // requires
+ if ($i->requires) {
+ self::initInstance($i->requires);
+ }
+ if ($i->args)
+ $i->instance = new $i->classname($listener, $i->args);
+ else
+ $i->instance = new $i->classname($listener);
+ $i->instance->addMethods($i->classname);
+ $i->instance->instanceName = $listener;
+
+ }
+ return $i->instance;
+ }
+
+ static function getInstance($listener) {
+ return self::initInstance($listener);
+ }
+
+ static function _addMSG($type='OK', $message='') {
+ self::$messages[] = array($type, $message);
+ return '';
+ }
+
+ function addMSG($type='OK', $action='', $message='') {
+ self::$messages[] = array($type, $message);
+ $this->haveMessage = $action;
+ return '';
+ }
+
+ static function getMSGs() {
+ return self::$messages;
+ }
+
+ static function call($action, $url_params) {
+ $action_params = explode('_', $action);
+
+ if (count($action_params) != 2)
+ return self::_addMSG('ERR', 'Action call error : bad params of ['.$action.']');
+
+ list($listener, $call) = $action_params;
+ if (array_key_exists($listener,self::$aliases))
+ $listener = self::$aliases[$listener];
+
+ if (!array_key_exists($listener, self::$myClasses))
+ return self::_addMSG('ERR', 'Action call error : class ['. $listener .'] not found');
+
+ $i = self::initInstance($listener);
+
+ if (in_array('action'.$call, $i->myMethods)) {
+ $i->haveMessage = NULL;
+ $ret = call_user_func(array($i, 'action'.$call), $url_params);
+ if (!isset($_SESSION['last_action']) or $action != $_SESSION['last_action'])
+ $_SESSION['last_action'] = $action;
+ $msg = $i->haveMessage;
+ if ($msg and ($msg != $action)) {
+ $ret = self::call($msg, $url_params);
+ return self::_addMSG('OK', $ret);
+ }
+ return self::_addMSG('OK', $ret);
+ } else
+ return self::_addMSG('ERR', 'Action call error : action ['. $call .'] of ['. $listener .'] not found');
+ }
+}
+
+function callAction($action) {
+ $c = '';
+ ryActionPage::call($action, ryzom_get_params());
+ $msgs = ryActionPage::getMSGs();
+
+ foreach ($msgs as $msg) {
+ if ($msg[0] == 'HEADER')
+ $c .= $msg[1];
+ }
+
+ foreach ($msgs as $msg) {
+ if ($msg[0] == 'ERR')
+ $c .= _s('message error', $msg[1]);
+ else if ($msg[0] == 'MSG')
+ $c .= _s('message', $msg[1]);
+ else if ($msg[0] == 'WARNING')
+ $c .= _s('message warning', $msg[1]);
+ else if ($msg[0] != 'HEADER')
+ $c .= $msg[1];
+ }
+ return $c;
+}
+
+?>
diff --git a/code/web/api/common/auth.php b/code/web/api/common/auth.php
index 1d52c5d8e..83c92c70c 100644
--- a/code/web/api/common/auth.php
+++ b/code/web/api/common/auth.php
@@ -1,37 +1,97 @@
.
+ */
+
+
+function ryzom_app_authenticate(&$user, $ask_login=true, $welcome_message='', $webprivs=true) {
$name = ryzom_get_param('name');
- $authserver = ryzom_get_param('authserver');
- $authkey = ryzom_get_param('authkey');
+ $urluser = ryzom_get_param('user'); // user serialization send by auth server
+ $urlusercheksum = ryzom_get_param('checksum'); // user serialization checksum
+ $authkey = ryzom_get_param('authkey'); // InGame authkey
$lang = ryzom_get_param('lang');
- $cid = ryzom_get_param('cid', '');
- $is_ingame = false;
+ $cid = intval(ryzom_get_param('cid'));
+ $is_auth_ingame = false;
// we have to set the $user['lang'] even for anonymous user or we cannot display the test in the right langage
if($lang == '') {
- $l = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
- if($l=='fr'||$l=='en'||$l=='de'||$l=='ru'||$l=='es')
- $lang = $l;
- else
- $lang = 'en';
+ if (!isset($_SESSION['lang'])) {
+ $l = isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])?substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2):'en';
+ if ($l=='fr'||$l=='en'||$l=='de'||$l=='ru'||$l=='es')
+ $lang = $l;
+ else
+ $lang = 'en';
+ } else
+ $lang = $_SESSION['lang'];
}
+ if ($lang!='fr'&&$lang!='en'&&$lang!='de'&&$lang!='ru'&&$lang!='es')
+ $lang = 'en';
+
$user['message'] = '';
$user['lang'] = $lang;
- $user['ig'] = false;
-
- if ((isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'Ryzom')) || ryzom_get_param('ig')) {
+ $user['groups'] = array();
+
+ if ((isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'Ryzom')) || ryzom_get_param('ig'))
$user['ig'] = true;
+ else
+ $user['ig'] = false;
+
+ if (isset($_SESSION['user'])) {
+ if (ryzom_get_param('action') == 'logout')
+ unset($_SESSION['user']);
+ else {
+ $_SESSION['user']['ig'] = $user['ig'];
+ define('RYZOM_IG', $user['ig']);
+ $user = $_SESSION['user'];
+ return true;
+ }
+ }
+
+ if ($urluser && $urlusercheksum) {
+ // Check $authuser (used to test app from another server ingame)
+ if (hash_hmac('sha1', $urluser, RYAPI_AUTH_KEY) == $urlusercheksum) {
+ $ig = $user['ig'];
+ $user = array_merge($user, unserialize(base64_decode($urluser)));
+ $user['ig'] = $ig;
+ if (!isset($user['groups']))
+ $user['groups'] = array();
+ define('RYZOM_IG', $user['ig']);
+ $_SESSION['user'] = $user;
+ return true;
+ }
+ }
+
+ if ($user['ig']) {
// Ingame
$shardid = ryzom_get_param('shardid');
- if (!ryzom_authenticate_ingame($shardid, $cid, $name, $authkey))
- return false;
- $is_ingame = true;
+ $error_message = '';
+ if (ryzom_authenticate_ingame($shardid, $cid, $name, $authkey) || ryzom_authenticate_with_session($name, $cid, $error_message)) {
+ $is_auth_ingame = true;
+ }
} else {
- // Outgame : Use session
+ // Outgame or bad ingame auth (external server) : Use session
$error_message = '';
if (!ryzom_authenticate_with_session($name, $cid, $error_message)) {
+ define('RYZOM_IG', false);
if ($ask_login) {
- $c = '';
+
+ if ($error_message)
+ $c = '
'._t($error_message).'
';
+ else
+ $c = '';
if (!$welcome_message)
$welcome_message = 'The application '._t(APP_NAME).' require authentication. Please enter your credentials';
@@ -47,18 +107,44 @@ function ryzom_app_authenticate(&$user, $ask_login=true, $welcome_message='') {
}
}
- if ($lang)
- $_SESSION['lang'] = $lang;
+ $_SESSION['lang'] = $lang;
+ define('RYZOM_IG', $user['ig']);
// get user informations
- $user = ryzom_user_get_info($cid);
- $user['lang'] = $_SESSION['lang'];
+ $ig = $user['ig'];
+ $user = ryzom_user_get_info($cid, $webprivs, RYAPI_USE_PLAYER_STATS);
+
if (isset($user['creation_date']))
- $user['id'] = ryzom_get_user_id($cid, $user['char_name'], $user['creation_date']);
- if ($is_ingame && $user['last_played_date'] != '0')
- $user['ig'] = true;
+ $user['id'] = ryzom_get_user_id($cid, $user['char_name'], $user['creation_date'], $user);
+
+ $user['gender'] = ryzom_get_user_gender($user['id']);
+
+ $user['ig'] = $ig;
+ $user['lang'] = $_SESSION['lang'];
+ if (!isset($user['groups']))
+ $user['groups'] = array();
+
+ if ($is_auth_ingame && $user['last_played_date'] != '0')
+ $user['auth_ig'] = true;
else
- $user['ig'] = false;
+ $user['auth_ig'] = false;
+
+ if (!isset($_SESSION['translater_mode']) || ryzom_get_param('translate_this') == '0')
+ $_SESSION['translater_mode'] = false;
+
+ // Set/unset translation mode
+ if (in_array('WTRS', $user['groups']) && ryzom_get_param('translate_this') == '1')
+ $_SESSION['translater_mode'] = true;
+
+ $user['translation_mode'] = $_SESSION['translater_mode'];
+
+// $user['after_merge'] = $user['uid'] >= 671686;
+
+ ryzom_unset_url_param('translate_this');
+
+ if (isset($user['last_played_date']))
+ $_SESSION['last_played_date'] = $user['last_played_date'];
+ // don't send this informations to external apps
unset($user['last_played_date']);
unset($user['creation_date']);
return true;
diff --git a/code/web/api/common/bbCode.php b/code/web/api/common/bbCode.php
new file mode 100644
index 000000000..b1597d5b5
--- /dev/null
+++ b/code/web/api/common/bbCode.php
@@ -0,0 +1,998 @@
+.
+ */
+
+// setup bbCode formatter
+
+bbCode::$ig = RYZOM_IG;
+
+/**
+ * Image proxy
+ */
+if(!defined('IMG_PROXY')){
+ $url = 'http://'.$_SERVER['HTTP_HOST'].'/app_forum/tools/imageproxy.php';
+ define('IMG_PROXY', $url);
+}
+if (!function_exists('proxy_image_url')) {
+ function proxy_image_url($href, $attrs=''){
+ return IMG_PROXY.'?'.($attrs != '' ? $attrs.'&' : '').'url='.urlencode($href);
+ }
+}
+
+
+abstract class bbCodeParser {
+
+ /**
+ * @var bool
+ */
+ private $_ig;
+
+ /**
+ * @var array
+ */
+ private $tags_ignore;
+ private $tags_block_open;
+ private $tags_block_close;
+ private $tags_ignore_depth;
+
+ /**
+ * @var array
+ */
+ private $open_tags;
+
+ /**
+ * @var string
+ */
+ private $last_closed_tag;
+
+ /**
+ * @var int
+ */
+ private $current_tag;
+
+ /**
+ * @var array
+ */
+ private $state;
+
+ /**
+ * @param bool $ig if true, use ingame markup
+ */
+ function __construct($ig) {
+ $this->_ig = $ig;
+
+ // ignore bbcode between these tags
+ $this->tags_ignore = array(
+ 'noparse', 'code',
+ 'url', 'img', 'mail', 'page', 'forum', 'topic', 'post', 'wiki', 'time', 'date'
+ );
+
+ // these create block level html code, so '\n' or ' ' or '\t' around them needs to be cleared
+ $this->tags_block_open = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'quote', 'list', 'p');
+ $this->tags_block_close = $this->tags_block_open;
+ if ($this->_ig) {
+ // ingame is not block level when closing, so dont strip there
+ $key = array_search('p', $this->tags_block_close, true);
+ unset($this->tags_block_close[$key]);
+ }
+
+ $this->state = array();
+
+ // reset internals
+ $this->reset();
+ }
+
+ /**
+ * Format bbcode tag
+ *
+ * @param string $tag tag name
+ * @param string $open open markup
+ * @param string $close close markup
+ * @param string $attr tag attributes
+ * @param string $text text between tags
+ */
+ abstract function format($tag, $open, $close, $attr, $text);
+
+ /**
+ * Wrapper to call Child->format(...)
+ *
+ * @param array $tag assoc array with tag info
+ * @return string
+ */
+ function handle_tag($tag) {
+ return $this->format($tag['tag'], $tag['open'], $tag['close'], $tag['attr'], $tag['text']);
+ }
+
+ /**
+ * Reset internals
+ */
+ function reset() {
+ $this->current_tag = 0;
+ $this->tags_ignore_depth = 0;
+
+ // 0'th position is used as result
+ $this->open_tags = array(
+ 0 => array('tag' => '', 'open' => '', 'close' => '', 'attr' => '', 'text' => '')
+ );
+
+ $this->last_closed_tag = false;
+ }
+
+ /**
+ * Save working state
+ */
+ private function _state_save() {
+ $this->state[] = array($this->current_tag, $this->tags_ignore_depth, $this->open_tags, $this->last_closed_tag);
+ $this->reset();
+ }
+
+ /**
+ * Restore working state
+ */
+ private function _state_restore() {
+ if (!empty($this->state)) {
+ list($this->current_tag, $this->tags_ignore_depth, $this->open_tags, $this->last_closed_tag) = array_pop($this->state);
+ }
+ }
+
+ /**
+ * Main worker. Parse $text for bbCode tags
+ *
+ * NOTE: Text must already be safe for HTML, ie. treated with htmlspecialchars()
+ *
+ * @param string $text
+ * @return string formatted string
+ */
+ function bbcode($text) {
+ $text = str_replace("\r\n", "\n", $text);
+
+ $split = preg_split('/(\[[a-zA-Z0-9_\/]*?(?:[= ].*?)?\])/', $text, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
+
+ foreach ($split as $chunk) {
+ if (substr($chunk, 0, 1) == '[' && substr($chunk, -1, 1) == ']') {
+ if (substr($chunk, 0, 2) == '[/') {
+ $this->close($chunk);
+ } else {
+ $this->open($chunk);
+ }
+ } else {
+ $this->text($chunk);
+ }
+ }
+
+ return $this->result();
+ }
+
+ /**
+ * Push tag with args to stack
+ * Do not strip whitespace because tag might be invalid
+ *
+ * @param string $chunk full tag string, eg. [tag=attr]
+ */
+ function open($chunk) {
+ list($tag, $attr) = $this->split_params($chunk);
+
+ // test for [noparse]
+ if ($this->tags_ignore_depth > 0) {
+ $this->text($chunk);
+ } else {
+ $this->current_tag++;
+ // remember tag, attributes and complete string that was used in markup
+ $this->open_tags[$this->current_tag] = array('tag' => $tag, 'attr' => $attr, 'open' => $chunk, 'close' => '', 'text' => '');
+ }
+
+ if (in_array($tag, $this->tags_ignore)) {
+ $this->tags_ignore_depth++;
+ }
+ }
+
+ /**
+ * Close tag and call tag handler to format output
+ *
+ * @param $chunk full tag string, eg. [/tag]
+ */
+ function close($chunk) {
+ // extract tag name from [/name]
+ $tag = strtolower(substr($chunk, 2, -1));
+
+ if ($this->tags_ignore_depth > 0 && in_array($tag, $this->tags_ignore)) {
+ $this->tags_ignore_depth--;
+ }
+
+ // stack underrun
+ if ($this->current_tag < 0) {
+ $this->text($chunk);
+ return;
+ }
+
+ // ignore block
+ if ($this->tags_ignore_depth > 0) {
+ $this->text($chunk);
+ return;
+ }
+
+ // tag mismatch
+ if ($this->open_tags[$this->current_tag]['tag'] !== $tag) {
+ // try to find first open tag for this
+ $key = false;
+ for ($i = $this->current_tag - 1; $i > 0; $i--) {
+ if (isset($this->open_tags[$i]['tag']) && $this->open_tags[$i]['tag'] === $tag) {
+ $key = $i;
+ break;
+ }
+ }
+ if ($key === false) {
+ $this->text($chunk);
+ return;
+ }
+
+ // tag is open so we need to 'rewind' a bit
+ for ($i = $this->current_tag; $i > $key; $i--) {
+ $tmp_tag = $this->pop_stack();
+ $this->text($tmp_tag['open'] . $tmp_tag['text']);
+ }
+ }
+
+ // close tag
+ $open = $this->pop_stack();
+
+ // handle bbcode
+ $open['close'] = $chunk;
+
+ $block_level = false;
+ if (in_array($tag, $this->tags_block_open)) {
+ $block_level = true;
+ // for block level element, trim whitespace from inside tag
+ // [tag]...text...[/tag]
+ $open['text'] = $this->trim_ws($open['text']);
+ }
+ $result = $this->handle_tag($open);
+
+ // strip whitespace from text before tag 'text...[tag]'
+ if ($block_level) {
+ $ts = $this->rtrim_ws($this->open_tags[$this->current_tag]['text']);
+ $this->open_tags[$this->current_tag]['text'] = $ts;
+ }
+
+ $this->text($result);
+
+ $this->last_closed_tag = $open['tag'];
+ }
+
+ function text($text) {
+ // strip whitespace after closing '[/tag]...text'
+ if (in_array($this->last_closed_tag, $this->tags_block_close)) {
+ $text = $this->ltrim_ws($text);
+ }
+ $this->open_tags[$this->current_tag]['text'] .= $text;
+
+ $this->last_closed_tag = false;
+ }
+
+ function result() {
+ // close tags that are still open
+ while ($this->current_tag > 0) {
+ $open = $this->pop_stack();
+
+ if ($this->tags_ignore_depth > 0) {
+ $this->tags_ignore_depth--;
+ // need to reparse text that's after ignore tag
+ $this->_state_save();
+ $text = $open['open'] . $this->bbcode($open['text']);
+ $this->_state_restore();
+ } else {
+ // tag was not closed proprely, include start tag with result
+ $text = $open['open'] . $open['text'];
+ }
+
+ $this->text($text);
+ };
+
+ return $this->open_tags[0]['text'];
+ }
+
+ /**
+ * Pop tag and text from stack and return them
+ *
+ * @return array [0] = tag, [1] = text
+ */
+ function pop_stack() {
+ // remove from stack
+ $open = $this->open_tags[$this->current_tag];
+ unset($this->open_tags[$this->current_tag]);
+ $this->current_tag--;
+
+ return $open;
+ }
+
+ /**
+ * Trim from end of string
+ * 'text...\s{0,}\n{1}\s{0,}'
+ *
+ * @param string $ts
+ * @return string
+ */
+ function rtrim_ws($ts){
+ // we want to get rid of all spaces/tabs, but only single \n, so rtrim($ts, " \t\n\r") would not work
+ $ts = rtrim($ts, " \t");
+ if (substr($ts, -1, 1) === "\n") {
+ $ts = substr($ts, 0, -1);
+ $ts = rtrim($ts, " \t");
+ }
+ return $ts;
+ }
+
+ /**
+ * Trim from start of string
+ * '\s{0,}\n{1}...text'
+ *
+ * @param string $ts
+ * @return string
+ */
+ function ltrim_ws($ts){
+ // we want to get rid of all spaces/tabs, but only single \n, so ltrim($ts, " \t\n\r") would not work
+ $ts = ltrim($ts, " \t");
+ if (substr($ts, 0, 1) === "\n") {
+ $ts = substr($ts, 1);
+ }
+ return $ts;
+ }
+
+ /**
+ * Trim from both sides
+ * '\s{0,}\n{1}...text...\s{0,}\n{1}\s{0,}
+ *
+ * @param string $ts
+ * @return string
+ */
+ function trim_ws($ts){
+ $ts = $this->ltrim_ws($ts);
+ $ts = $this->rtrim_ws($ts);
+ return $ts;
+ }
+
+ /**
+ * Extract tag parameters from [tag=params] or [tag key1=val1 key2=val2]
+ *
+ * @param type $tag
+ * @return type
+ */
+ function split_params($chunk) {
+ if (substr($chunk, 0, 1) == '[') {
+ $b = '\[';
+ $e = '\]';
+ } else {
+ $b = '';
+ $e = '';
+ }
+ // [1] [2] [3]
+ if (preg_match('/^' . $b . '([\*a-zA-Z0-9]*?)' . '(=| )' . '(.*?)' . $e . '$/', $chunk, $match)) {
+ $tagName = strtolower($match[1]);
+ if ($match[2] == '=') {
+ // = means single parameter
+ $tagParam = $match[3];
+ } else {
+ // means multiple parameters
+ $tagParam = array();
+ $args = preg_split('/[ ]/', $match[3], null, PREG_SPLIT_NO_EMPTY);
+ foreach ($args as $arg) {
+ $pairs = explode('=', $arg);
+ // preg_replace will remove possible quotes around value
+ if (isset($pairs[1])) {
+ $tagParam[strtolower($pairs[0])] = preg_replace('@("|\'|)(.*?)\\1@', '$2', $pairs[1]);
+ } else {
+ $tagParam[] = preg_replace('@("|\'|)(.*?)\\1@', '$2', $pairs[0]);
+ }
+ }
+ }
+ } else {
+ if (substr($chunk, 0, 1) == '[' && substr($chunk, -1, 1) == ']') {
+ $chunk = substr($chunk, 1, -1);
+ }
+ $tagName = strtolower($chunk);
+ $tagParam = '';
+ }
+ return array($tagName, $tagParam);
+ }
+
+}
+
+class bbCode extends bbCodeParser {
+ static $legacy_sync = 1348956841;
+ static $legacy_shard = array(
+ 'ani' => 2363920179,
+ 'lea' => 2437578274,
+ 'ari' => 2358620001,
+ );
+
+ static $ig = false;
+ static $timezone = 'UTC';
+ static $clock12h = false;
+ static $shardid = false;
+ static $lang = 'en';
+ static $disabledTags = array();
+ //
+ const COLOR_P = '#d0d0d0'; // normal text
+ //
+ const COLOR_BBCODE_TAG = '#444444';
+
+ static function bbDisabled($tag) {
+ return in_array(strtolower($tag), self::$disabledTags);
+ }
+
+ static function getFontSize($value) {
+ $size = 16;
+ switch (strtolower($value)) {
+ case '1': case 'xx-small': $size = 9; break;
+ case '2': case 'x-small' : $size = 10; break;
+ case '3': case 'small' : $size = 13; break;
+ case '4': case 'medium' : $size = 16; break;
+ case '5': case 'large' : $size = 18; break;
+ case '6': case 'x-large' : $size = 24; break;
+ case '7': case 'xx-large': $size = 32; break;
+ //case '8': case 'smaller' : break;
+ //case '9': case 'larger' : break;
+ }
+ return $size;
+ }
+
+ static function bb_noparse($code) {
+ return preg_replace(array('/\[/', '/\]/'), array('[', ']'), $code);
+ }
+
+ static function bb_code($code) {
+ return '' . self::bb_noparse($code) . '
';
+ }
+
+ static function bb_list($list) {
+ $result = '';
+ $list = str_replace("\n[", '[', $list);
+ $result = '' . preg_replace('/\s*\[\*\]\s*/is', "- ", $list) . '
';
+ return preg_replace('#\s*#is', '', $result);
+ }
+
+ static function bb_quote($author, $text) {
+ if (self::$ig) {
+ // prevents [color] tag to take over color
+ $author = self::bb_color(self::COLOR_P, $author);
+ $text = self::bb_color(self::COLOR_P, $text);
+ // left/right border, top/bottom border height
+ $l = ' | ';
+ $r = ' | ';
+ return // 98% gives bit padding on the right
+ '' .
+ ' | | |
' . // top padding - no border
+ '' . $l . ' | ' . $r . '
' . // top border
+ '' . $l . ' | ' . $r . '
' . // author top padding
+ '' . $l . '' . $author . ' | ' . $r . '
' . // author
+ '' . $l . ' | ' . $r . '
' . // author bottom padding
+ '' . $l . ' | ' . $r . '
' . // quote top padding
+ '' . $l . '' . $text . ' | ' . $r . '
' . // quote
+ '' . $l . ' | ' . $r . '
' . // quote bottom padding
+ '' . $l . ' | ' . $r . '
' . // bottom border
+ ' | | |
' . // bottom padding - no border
+ '
';
+ } else {
+ return '' .
+ '' .
+ '
' . $author . '' .
+ '
' . $text . '
' .
+ '
';
+ }
+ }
+
+ static function bb_h($nr, $color, $text) {
+ $tag = 'h' . $nr;
+
+ if (self::$ig) {
+ if ($color != '') {
+ $text = '' . $text . '';
+ }
+ return '<' . $tag . '>' . $text . '' . $tag . '>';
+ } else {
+ if ($color != '') {
+ $style = ' style="color: ' . $color . ';"';
+ } else {
+ $style = '';
+ }
+ return '<' . $tag . $style . '>' . $text . '' . $tag . '>';
+ }
+ }
+
+ static function bb_url($href, $text) {
+ // "http://..../" remove " if present
+ if (substr($href, 0, 6) == '"') {
+ if (substr($href, -6) == '"') {
+ $href = substr($href, 6, -6);
+ } else {
+ $href = substr($href, 6);
+ }
+ }
+
+ if ($href == '')
+ $href = $text;
+ if ($text == '') {
+ $text = $href;
+ $text = wordwrap($text, 65, ' ', true);
+ }
+
+ $disable = self::bbDisabled('url');
+ // if not disabled and in ryzom and is proper url (:///)
+ if (!$disable && self::$ig) {
+ $url = @parse_url(strtolower($href));
+ $disable = true;
+ if (!empty($url['scheme']) && !empty($url['host'])) {
+ if (in_array($url['scheme'], array('http', 'https'))) {
+ if (in_array($url['host'], array('app.ryzom.com'))) {
+ if (empty($url['query']) || stripos($url['query'], 'redirect') === false) {
+ // http://atys.ryzom.com/
+ // and does not contain redirect
+ // - allow url in game browser
+ $disable = false;
+ }
+ }
+ }
+ } // !empty
+ }// isRYZOM
+
+ if ($disable) {
+ // empty href will give proper link color without 'underline' - perfect for 'disabled' links
+ if ($href == '') {
+ $text = '' . $text . '';
+ } else {
+ $href = wordwrap($href, 65, ' ', true);
+ $text = wordwrap($text, 65, ' ', true);
+ $text = '' . $text . ' ' . self::bb_color(self::COLOR_BBCODE_TAG, '(' . $href . ')');
+ }
+ return $text;
+ }
+
+ // make sure http:// (or ftp:// or mailto:// etc is present), if not, add it
+ if (!preg_match('#://#', $href)) {
+ $href = 'http://' . $href;
+ }
+
+ return sprintf('%s', $href, $text);
+ }
+
+ static function bb_img($attr, $href) {
+ if (self::bbDisabled('img')) {
+ return self::bb_noparse('[img]' . $href . '[/img]');
+ }
+ // $href is treated with htmlspecialchars() so any & in url is &
+ $href = str_replace('&', '&', $href);
+
+ // images from current server directly
+ if ($attr=='src' || strstr($href, $_SERVER['HTTP_HOST']) !== false){
+ return '';
+ }
+ $url = proxy_image_url($href);
+ return '';
+ }
+
+ static function bb_banner($lang, $ckey) {
+ // $lang and $ckey should already be escaped for HTML, so urlencode() in here would double escape them
+ // - channel it thru image proxy. proxy does caching better and uses '304 Not Modified' status
+ $src = 'http://atys.ryzom.com/api/banner.php?ckey=' . $ckey . '&langid=' . $lang . '&size=500';
+ return self::bb_img('', $src);
+ }
+
+ static function bb_mail($user) {
+ $url = 'http://' . $_SERVER['HTTP_HOST'] . '/app_mail/?page=compose/to/' . urlencode($user);
+ return '' . $user . '';
+ }
+
+ static function bb_profile($ptype, $pname) {
+ // types from app_profile
+ $types = array('user', 'player', 'npc', 'fauna', 'entity', 'source');
+ $ptype = array_search($ptype, $types, true);
+ // if type not found, then fall back to player
+ if ($ptype === false)
+ $ptype = 1;
+
+ $url = 'http://' . $_SERVER['HTTP_HOST'] . '/app_profile/?ptype=' . intval($ptype) . '&pname=' . urlencode($pname);
+ return '' . $pname . '';
+ }
+
+ static function bb_color($color, $str) {
+ if ($color == '') {
+ return $str;
+ }
+
+ if (self::$ig) {
+ return '' . $str . '';
+ } else {
+ return '' . $str . '';
+ }
+ }
+
+ static function bb_size($size, $str) {
+ $size = self::getFontSize($size);
+
+ if (self::$ig) {
+ return '' . $str . '';
+ } else {
+ return '' . $str . '';
+ }
+ }
+
+ static function bb_pre($str) {
+ return '' . $str . '
';
+ }
+
+ static function bb_p($str) {
+ return '' . $str . '
';
+ }
+
+ // Added by ulukyn. WebIg compatibility.
+ static function bb_center($str) {
+ if (self::$ig) {
+ return '';
+ } else {
+ return '' . $str . '
';
+ }
+ }
+
+ /** Table format : (added by ulukyn)
+ * A1| A2|A3
+ * B1| B2 |B3
+ * C1|C2 |C3
+ */
+ static function bb_table($attr, $content) {
+ $width = isset($attr['width'])?$attr['width']:'100%';
+ $border = isset($attr['border'])?$attr['border']:'0';
+ $bgcolor = isset($attr['bgcolor'])?' bgcolor="'.$attr['bgcolor'].'" ':'';
+ $ret = '';
+ $lines = explode("\n", $content);
+ foreach ($lines as $line) {
+ if ($line) {
+ $ret .= '';
+ $cols = explode('|', $line);
+ foreach ($cols as $text) {
+ if (!$text)
+ continue;
+ $params = array('valign' => 'middle');
+ if ($text[0] == '#') {
+ $paramsdef = explode(' ', $text);
+ $paramlist = substr(array_shift($paramsdef), 1);
+ $paramlist = explode(',', $paramlist);
+ foreach ($paramlist as $p) {
+ list($name, $value) = explode('=', $p);
+ $params[ _h(str_replace('"', '', $name))] = _h(str_replace('"', '', $value));
+ }
+ if ($paramsdef)
+ $text = implode(' ', $paramsdef);
+ }
+ $param_html = '';
+ foreach ($params as $name => $value)
+ $param_html .= $name.'="'.$value.'" ';
+
+ if ($text && $text[0] == ' ' && $text[strlen($text)-1] == ' ')
+ $align = 'center';
+ else if ($text && $text[0] == ' ')
+ $align = 'right';
+ else
+ $align = 'left';
+
+ $ret .= ''.$text.' | ';
+ }
+ $ret .= '
';
+ }
+ }
+
+ $ret .= '
';
+ return $ret;
+ }
+
+
+ static function bb_page_link($page, $txt) {
+ if ($page == '') {
+ $page = $txt;
+ }
+ $tmp = explode('/', $page);
+ foreach ($tmp as $k => $v) {
+ $tmp[$k] = urlencode($v);
+ }
+ $url = 'http://' . $_SERVER['HTTP_HOST'] . '/app_forum/?page=' . join('/', $tmp);
+ return '' . $txt . '';
+ }
+
+ static function bb_forum_link($page, $id, $txt) {
+ $page = $page . '/view/' . $id;
+ if ($id == '') {
+ $page.= $txt;
+ }
+ return self::bb_page_link($page, $txt);
+ }
+
+ // Added by Ulukyn
+ static function bb_wiki_link($page, $txt) {
+ $need_new_txt = false;
+ if ($page == '') {
+ $page = $txt;
+ $need_new_txt = true;
+ }
+
+ if (substr($page, 0, 22) == 'http://atys.ryzom.com/')
+ $url = 'http://atys.ryzom.com/start/app_wiki.php?page=' . substr($page, 21);
+ else {
+ $tmp = explode('/', $page);
+ if (count($tmp) != 2) {
+ return 'Syntax: [wiki]/[page], ex: en/Chronicles';
+ } else {
+ $wiki = $tmp[0];
+ $page = $tmp[1];
+ }
+ if (self::$ig) {
+ $url = 'http://atys.ryzom.com/start/app_wiki.php?page=/projects/pub' . $wiki . '/wiki/' . $page;
+ }
+ else
+ $url = 'http://atys.ryzom.com/projects/pub' . $wiki . '/wiki/' . $page;
+ if ($need_new_txt)
+ $txt = 'WIKI [' . $page . ']';
+ }
+ return '' . $txt . '';
+ }
+
+ static function bb_biu($tag, $txt) {
+ $tag = strtolower($tag);
+ if (self::$ig) {
+ switch ($tag) {
+ // FIXME: darken/lighter or tint current color
+ case 'b': $txt = self::bb_color('white', $txt);
+ break;
+ case 'i': $txt = self::bb_color('#ffffd0', $txt);
+ break;
+ case 'u': $txt = '' . self::bb_color(self::COLOR_P, $txt) . '';
+ break;
+ default : $txt = self::bb_color(self::COLOR_BBCODE_TAG, $txt);
+ break; // fallback
+ }
+ return $txt;
+ }
+
+ switch ($tag) {
+ case 'b': $tag = 'strong';
+ break;
+ case 'i': $tag = 'em';
+ break;
+ case 'u': $tag = 'u';
+ break;
+ default: $tag = 'span'; // fallback
+ }
+ return '<' . $tag . '>' . $txt . '' . $tag . '>';
+ }
+
+ static function bb_date($attr, $txt) {
+ $time = strtotime($txt);
+
+ $shardid = isset($attr['shard']) ? $attr['shard'] : self::$shardid;
+ if ($time === false || $shardid === false)
+ return 'ERR:[' . $txt . ']';
+
+ if (isset(self::$legacy_shard[$shardid])) {
+ $tick = self::$legacy_shard[$shardid];
+ if (self::$legacy_sync > $time) {
+ // only modify game cycle when asked time is before sync
+ $tick = ($time - self::$legacy_sync) * 10 + $tick;
+ }
+ } else {
+ $tick = ryzom_time_tick($shardid);
+ // tick is for NOW, adjust it to match time given
+ $now = time();
+ $tick = ($time - $now) * 10 + $tick;
+ }
+
+ $rytime = ryzom_time_array($tick, $shardid);
+ $txt = ryzom_time_txt($rytime, self::$lang);
+
+ return $txt;
+ }
+
+ static function bb_lang($attr, $txt) {
+ if (_user()->lang == $attr)
+ return $txt;
+ else
+ return '';
+ }
+
+ static function bb_time($options, $txt) {
+ $time = strtotime($txt);
+
+ if ($time == 0) {
+ return $txt;
+ }
+
+ $timezone = self::$timezone;
+
+ $show_time = '';
+ $show_date = '';
+ $show_timer = '';
+
+ if (is_array($options)) {
+ foreach ($options as $key => $val) {
+ switch ($key) {
+ case 'timezone':
+ // fix some timezones for php
+ switch ($val) {
+ case 'pst': // fall thru
+ case 'pdt': $val = 'US/Pacific';
+ break;
+ }
+ $timezone = $val;
+ break;
+ case 'date' :
+ $show_date = $val == 'off' ? false : $val;
+ break;
+ case 'time' :
+ $show_time = $val == 'off' ? false : $val;
+ break;
+ case 'timer':
+ $show_timer = $val == 'off' ? false : $val;
+ break;
+ }//switch
+ }//foreach
+ }
+
+ $ret = array();
+
+ $old_timezone = date_default_timezone_get();
+ @date_default_timezone_set($timezone);
+ if ($show_date !== false) {
+ $date = ryzom_absolute_time($time);
+ //ryzom_absolute_time does not have year, so we need to add it
+ $current_y = date('Y', time());
+ $y = date('Y', $time);
+ if ($y != $current_y) {
+ $date.= ' ' . $y;
+ }
+ $ret[] = self::bb_color($show_date, $date);
+ }
+ if ($show_time !== false) {
+ $fmtTime = self::$clock12h ? 'g:i:s a T' : 'H:i:s T';
+ $ret[] = self::bb_color($show_time, date($fmtTime, $time));
+ }
+ date_default_timezone_set($old_timezone);
+
+ if ($show_timer !== false) {
+ if ($show_time === false && $show_date === false) {
+ $f = '%s';
+ } else {
+ $f = '(%s)';
+ }
+ $ret[] = self::bb_color($show_timer, sprintf($f, ryzom_relative_time($time)));
+ }
+
+ return join(' ', $ret);
+ }
+
+ /**
+ * This function is called by bbCodeParser class
+ *
+ * @see bbCodeParser::format
+ */
+ public function format($tag, $open, $close, $attr, $text) {
+ // silly functions all have different parameters
+ switch ($tag) {
+ case 'noparse' :
+ $result = self::bb_noparse($text);
+ break;
+ case 'code' :
+ $result = self::bb_code($text);
+ break;
+ case 'quote' :
+ $result = self::bb_quote($attr, $text);
+ break;
+ case 'h1' : // fall thru
+ case 'h2' : // fall thru
+ case 'h3' : // fall thru
+ case 'h4' : // fall thru
+ case 'h5' : // fall thru
+ case 'h6' :
+ $nr = (int) substr($tag, -1);
+ $color = isset($attr['color']) ? $attr['color'] : '';
+ $result = self::bb_h($nr, $color, $text);
+ break;
+ case 'color' :
+ $result = self::bb_color($attr, $text);
+ break;
+ case 'size' :
+ $result = self::bb_size($attr, $text);
+ break;
+ case 'list' :
+ $result = self::bb_list($text);
+ break;
+ case 'img' :
+ $result = self::bb_img($attr, $text);
+ break;
+ case 'banner' :
+ $result = self::bb_banner($attr, $text);
+ break;
+ case 'pre' :
+ $result = self::bb_pre($text);
+ break;
+ case 'p' :
+ $result = self::bb_p($text);
+ break;
+ case 'table' :
+ $result = self::bb_table($attr, $text);
+ break;
+ case 'center' :
+ $result = self::bb_center($text);
+ break;
+ case 'url' :
+ $result = self::bb_url($attr, $text);
+ break;
+ case 'mail' :
+ $result = self::bb_mail($text);
+ break;
+ case 'profile' :
+ $result = self::bb_profile($attr, $text);
+ break;
+ case 'page' :
+ $result = self::bb_page_link($attr, $text);
+ break;
+ case 'forum' : // fall thru
+ case 'topic' : // fall thru
+ case 'post' :
+ $result = self::bb_forum_link($tag, $attr, $text);
+ break;
+ case 'wiki' :
+ $result = self::bb_wiki_link($attr, $text);
+ break;
+ case 'b' : // fall thru
+ case 'i' : // fall thru
+ case 'u' :
+ $result = self::bb_biu($tag, $text);
+ break;
+ case 'time' :
+ $result = self::bb_time($attr, $text);
+ break;
+ case 'date' :
+ $result = self::bb_date($attr, $text);
+ break;
+ case 'lang' :
+ $result = self::bb_lang($attr, $text);
+ break;
+ default :
+ $result = $open . $text . $close;
+ break;
+ }
+ return $result;
+ }
+
+ /**
+ * Replaces some BBcode with HTML code
+ *
+ * NOTE: $text should be already escaped for HTML
+ *
+ * @param string $text html escaped input text
+ * @param array $disabledTags
+ */
+ static function parse($text, $disabledTags = array()) {
+ static $parser = null;
+ if ($parser === null) {
+ $parser = new self(self::$ig);
+ }
+ $parser->reset();
+
+ self::$disabledTags = $disabledTags;
+ return $parser->bbcode($text);
+ }
+
+}
diff --git a/code/web/api/common/config.php.default b/code/web/api/common/config.php.default
index 3a00bb04e..78d4618c6 100644
--- a/code/web/api/common/config.php.default
+++ b/code/web/api/common/config.php.default
@@ -17,6 +17,9 @@
* along with ryzom_api. If not, see .
*/
+define('RYAPI_MODE', 'client');
+define('RYAPI_USE_PLAYER_STATS', false);
+
// Url where the api is
define('RYAPI_URL', 'http://');
if (!defined('RYAPI_PATH'))
@@ -24,5 +27,6 @@ if (!defined('RYAPI_PATH'))
// used by "home" link
if (!defined('RYAPP_URL'))
define('RYAPP_URL', 'http://');
-
+if (!defined('RYAPI_AUTH_KEY'))
+ define('RYAPI_AUTH_KEY', ''); // key gived by AUTH_SERVER
?>
diff --git a/code/web/api/common/db_defs.php b/code/web/api/common/db_defs.php
new file mode 100644
index 000000000..d865df1d0
--- /dev/null
+++ b/code/web/api/common/db_defs.php
@@ -0,0 +1,24 @@
+.
+ */
+
+// init database table used by webig
+$db = ryDB::getInstance('webig');
+$db->setDbDefs('players', array('id' => SQL_DEF_INT, 'cid' => SQL_DEF_INT, 'name' => SQL_DEF_TEXT, 'gender' => SQL_DEF_INT, 'creation_date' => SQL_DEF_DATE, 'deleted' => SQL_DEF_BOOLEAN, 'last_login' => SQL_DEF_TEXT, 'dev_shard' => SQL_DEF_BOOLEAN));
+$db->setDbDefs('accounts', array('uid' => SQL_DEF_INT, 'web_privs' => SQL_DEF_TEXT));
+
+?>
\ No newline at end of file
diff --git a/code/web/api/common/db_lib.php b/code/web/api/common/db_lib.php
index c3c7e8677..5d054b1bb 100644
--- a/code/web/api/common/db_lib.php
+++ b/code/web/api/common/db_lib.php
@@ -43,91 +43,96 @@ class ServerDatabase
}
if (($this->hostname != '') && ($this->username != '') && ($this->database != ''))
- {
- $this->_connection = mysql_connect($this->hostname, $this->username, $this->password)
- or die("ERR1"); // ace . $this->get_error());
- $this->select_db($this->database);
- }
+ $this->_connection = new mysqli($this->hostname, $this->username, $this->password, $this->database);
}
function close()
{
- @mysql_close($this->_connection);
+ $this->_connection->close();
}
function query($sql_statement)
{
- $result = mysql_query($sql_statement, $this->_connection);
+ $result = $this->_connection->query($sql_statement);
+ if (!$result)
+ alert('MYSQL', $this->get_error(), 2);
return $result;
}
function select_db($dbname) {
$this->database = $dbname;
- mysql_select_db($this->database, $this->_connection) or die("Database selection error : " . $this->get_error());
+ $this->_connection->select_db($dbname);
}
function num_rows($result)
{
- return @mysql_num_rows($result);
+ return $result->num_rows;
}
- function fetch_row($result, $result_type=MYSQL_BOTH)
+ function fetch_row($result, $result_type=MYSQLI_BOTH)
{
- return @mysql_fetch_array($result, $result_type);
- }
-
- function fetch_assoc($result)
- {
- return @mysql_fetch_array($result, MYSQL_ASSOC);
+ if (gettype($result) == "object")
+ return $result->fetch_array($result_type);
+ return NULL;
}
+ function fetch_assoc($result)
+ {
+ if (gettype($result) == "object")
+ return $result->fetch_assoc();
+ return NULL;
+ }
function query_single_row($sql_statement)
{
$result = $this->query($sql_statement);
- return @mysql_fetch_array($result);
+ if (gettype($result) == "object")
+ return $result->fetch_array();
+
+ return NULL;
}
function free_result($result)
{
- @mysql_free_result($result);
+ $result->free();
}
function get_error()
{
- return mysql_errno($this->_connection) .": ". mysql_error($this->_connection);
+ return $this->_connection->errno.': '.$this->_connection->error;
}
function last_insert_id()
{
- return @mysql_insert_id();
+ return $this->_connection->insert_id;
+ }
+
+ function escape_string($escapestr) {
+ return $this->_connection->real_escape_string($escapestr);
}
function change_to($host,$user,$pass,$dbname)
{
- $this->close();
+ /*$this->close();
$this->hostname = $host;
$this->username = $user;
$this->password = $pass;
$this->database = $dbname;
- $this->ServerDatabase();
+ $this->ServerDatabase();*/
}
}
-
-
-
class ryDB {
private static $_instances = array();
private $db;
private $defs = array();
private $errors = '';
-
-
+
+
private function __construct($db_name) {
global $_RYZOM_API_CONFIG;
-
+ $this->db_name = $db_name;
$this->db = new ServerDatabase(RYAPI_WEBDB_HOST, RYAPI_WEBDB_LOGIN, RYAPI_WEBDB_PASS, $db_name);
$this->db->query("SET NAMES utf8");
}
@@ -140,20 +145,43 @@ class ryDB {
return self::$_instances[$db_name];
}
- function setDbDefs($table, $defs) {
+ function setDbDefs($table, $defs, $check=true) {
+ if ($check)
+ {
+ $result = $this->db->query('SHOW FIELDS FROM '.$table);
+ if (!$result) {
+ die("Table [$table] not found in database [$this->db_name]");
+
+ }
+
+ $fields = array_keys($defs);
+ while ($row = $this->db->fetch_row($result)) {
+ if (in_array($row['Field'], $fields))
+ unset($fields[array_search($row['Field'], $fields)]);
+ else
+ alert('DbLib', 'Missing field '.$row['Field']." on DbDef of table [$table] of database [$this->db_name] !", 2);
+ }
+ if ($fields)
+ die('Missing fields ['.implode('] [', $fields)."] in table [$table] of database [$this->db_name] !");
+ }
$this->defs[$table] = $defs;
}
-
+
function getDefs($table) {
- if (!array_key_exists($table, $this->defs))
- die("Please add tables defs using setDbDefs('$table', \$defs)");
- return $this->defs[$table];
+ if ($this->hasDbDefs($table))
+ return $this->defs[$table];
+
+ alert('DBLIB', "Please add tables to '$this->db_name' defs using setDbDefs('$table', \$defs)", 2);
}
-
+
+ function hasDbDefs($table) {
+ return array_key_exists($table, $this->defs);
+ }
+
function getErrors() {
return $this->db->get_error();
}
-
+
function now() {
return date('Y-m-d H:i:s', time());
}
@@ -169,18 +197,43 @@ class ryDB {
function addDbTableProp($table, $props) {
$this->props[$table] = $props;
}
-
+
+ function sqlEscape($escapestr) {
+ return $this->db->escape_string($escapestr);
+ }
+
+ function insertID() {
+ return $this->db->last_insert_id();
+ }
+
+
/// DIRECT QUERY
- function sqlQuery($sql) {
+ function sqlQuery($sql, $index = false, $result_type = MYSQLI_BOTH) {
$result = $this->db->query($sql);
+ if (!$result)
+ return NULL;
+ if($index !== false && !is_array($index)){
+ $index = array($index);
+ }
$ret = array();
- while ($row = $this->db->fetch_row($result)) {
- $ret[] = $row;
+ while ($row = $this->db->fetch_row($result, $result_type)) {
+ if($index !== false) {
+ // if $index is ['id1', 'id2'], then this code executes as
+ // $ret[$row['id1']][$row['id2']] = $row
+ $current = &$ret;
+ foreach($index as $key){
+ if(!isset($row[$key]))
+ alert('DBLIB', "Requested index field ($key) was not selected from db");
+ $current = &$current[$row[$key]];
+ }
+ $current = $row;
+ } else
+ $ret[] = $row;
}
return $ret;
}
-
-
+
+
/// QUERY ///
function sqlSelect($table, $props, $values=array(), $extra='') {
if ($table) {
@@ -188,16 +241,16 @@ class ryDB {
$params = array();
$test = array();
if (!$props)
- die("Bad Select on [$table] : missing props");
-
+ alert('DBLIB', "Bad Select on [$table] : missing props");
+
foreach($props as $name => $type)
- $params[] = '`'.addslashes($name).'`';
-
+ $params[] = '`'.$this->sqlEscape($name).'`';
+
foreach($values as $name => $value) {
if ($name[0] == '=')
- $test[] = '('.addslashes(substr($name, 1)).' LIKE '.var_export($value, true).')';
+ $test[] = '('.$this->sqlEscape(substr($name, 1)).' LIKE '.var_export($value, true).')';
else
- $test[] = '('.addslashes($name).' = '.var_export($value, true).')';
+ $test[] = '('.$this->sqlEscape($name).' = '.var_export($value, true).')';
}
$sql .= implode(",\n\t", $params)."\nFROM\n\t".$table."\n";
if ($test)
@@ -209,39 +262,37 @@ class ryDB {
return $sql.';';
}
-
+
function querySingle($table, $values=array(), $extra='') {
$sql = $this->sqlSelect($table, $this->getDefs($table), $values, $extra);
- $result = $this->db->query($sql);
- return $this->db->fetch_row($result);
+ $result = $this->sqlQuery($sql, false, MYSQLI_BOTH);
+ if(empty($result))
+ return NULL;
+ return $result[0];
}
-
+
function querySingleAssoc($table, $values=array(), $extra='') {
$sql = $this->sqlSelect($table, $this->getDefs($table), $values, $extra);
- $result = $this->db->query($sql);
- return $this->db->fetch_row($result, MYSQL_ASSOC);
+ $result = $this->sqlQuery($sql, false, MYSQLI_ASSOC);
+ if(empty($result))
+ return NULL;
+ return $result[0];
}
-
- function query($table, $values=array(), $extra='') {
+
+ function query($table, $values=array(), $extra='', $index = false, $result_type = MYSQLI_BOTH) {
$sql = $this->sqlSelect($table, $this->getDefs($table), $values, $extra);
- $result = $this->db->query($sql);
- $ret = array();
- while ($row = $this->db->fetch_row($result)) {
- $ret[] = $row;
- }
- return $ret;
+ return $this->sqlQuery($sql, $index, $result_type);
}
-
- function queryAssoc($table, $values=array(), $extra='') {
- $sql = $this->sqlSelect($table, $this->getDefs($table), $values, $extra);
- $result = $this->db->query($sql);
- $ret = array();
- while ($row = $this->db->fetch_row($result, MYSQL_ASSOC)) {
- $ret[] = $row;
- }
- return $ret;
+
+ function queryAssoc($table, $values=array(), $extra='', $index = false) {
+ return $this->query($table, $values, $extra, $index, MYSQLI_ASSOC);
}
+ function queryIndex($table, $index, $values=array(), $extra='') {
+ return $this->query($table, $values, $extra, $index, MYSQLI_ASSOC);
+ }
+
+
/// INSERT ///
function sqlInsert($table, $props, $vals) {
$sql = 'INSERT INTO '.$table.' ';
@@ -250,7 +301,7 @@ class ryDB {
foreach($props as $name => $type) {
if (!isset($vals[$name]))
continue;
- $params[] = $name;
+ $params[] = '`'.$name.'`';
switch ($type) {
case SQL_DEF_BOOLEAN:
$values[] = $vals[$name]?1:0;
@@ -260,12 +311,12 @@ class ryDB {
break;
case SQL_DEF_DATE: // date
if (is_string($vals[$name]))
- $values[] = "'".addslashes($vals[$name])."'";
+ $values[] = "'".$this->sqlEscape($vals[$name])."'";
else
$values[] = "'".$this->toDate($vals[$name])."'";
break;
default:
- $values[] = "'".addslashes($vals[$name])."'";
+ $values[] = "'".$this->sqlEscape($vals[$name])."'";
break;
}
}
@@ -284,8 +335,8 @@ class ryDB {
$sql = "DELETE FROM\n\t".$table."\n";
$test = array();
foreach($values as $name => $value)
- $test[] = '('.addslashes($name).' = '.var_export($value, true).')';
-
+ $test[] = '('.$this->sqlEscape($name).' = '.var_export($value, true).')';
+
if ($test or $where)
$sql .= "WHERE\n\t";
if ($test)
@@ -294,7 +345,7 @@ class ryDB {
$sql .= "\n".$where;
return $sql.';';
}
-
+
function delete($table, $values=array(), $where='') {
$sql = $this->sqlDelete($table, $values, $where);
$result = $this->db->query($sql);
@@ -316,23 +367,23 @@ class ryDB {
break;
case SQL_DEF_DATE:
if (is_string($vals[$name]))
- $values[] = '`'.$name.'` = \''.addslashes($vals[$name]).'\'';
+ $values[] = '`'.$name.'` = \''.$this->sqlEscape($vals[$name]).'\'';
else
$values[] = '`'.$name.'` = \''.$this->toDate($vals[$name]).'\'';
break;
default:
- $values[] = '`'.$name.'` = \''.addslashes($vals[$name]).'\'';
+ $values[] = '`'.$name.'` = \''.$this->sqlEscape($vals[$name]).'\'';
break;
}
}
$sql .= "\n\t".implode(",\n\t", $values)."\n";
foreach($tests as $name => $value) {
- $test[] = '('.addslashes($name).' = '.var_export($value, true).')';
+ $test[] = '('.$this->sqlEscape($name).' = '.var_export($value, true).')';
}
if ($test)
$sql .= "WHERE\n\t".implode("\nAND\n\t", $test);
-
+
$sql .= "\n".$extra;
return $sql;
@@ -363,17 +414,17 @@ class ryDB {
continue;
switch ($type) {
case 'trad':
- $values[] = '`'.$name."` = '".addslashes($vals[$name])."'";
+ $values[] = '`'.$name."` = '".$this->sqlEscape($vals[$name])."'";
break;
case 'textarea':
case 'string':
case 'option':
- $values[] = '`'.$name."` = '".addslashes($vals[$name])."'";
+ $values[] = '`'.$name."` = '".$this->sqlEscape($vals[$name])."'";
break;
case 'id':
case 'int':
case 'float':
- $values[] = '`'.$name.'` = '.addslashes($vals[$name]);
+ $values[] = '`'.$name.'` = '.$this->sqlEscape($vals[$name]);
break;
case 'bool':
$values[] = '`'.$name.'` = '.($vals[$name]?'1':'0');
@@ -389,7 +440,7 @@ class ryDB {
return $result;
}
-
+
/// Display
function getTableHtml($name, $params, $values, $order_by='')
{
@@ -417,6 +468,55 @@ class ryDB {
return $ret;
}
+ /// Update Database Structure
+
+ static function updateDatabaseStruct($defs)
+ {
+ if (file_exists(RYAPP_PATH.'database.versions'))
+ $versions = unserialize(file_get_contents(RYAPP_PATH.'database.versions'));
+ else
+ $versions = array();
+
+ $c = "Updating DB Structure...\n";
+ foreach ($defs as $dbname => $tables) {
+ $db = new ServerDatabase(RYAPI_WEBDB_HOST, RYAPI_WEBDB_LOGIN, RYAPI_WEBDB_PASS, $dbname);
+ $db->query("SET NAMES utf8");
+ $c .= "\n Selected DB '$dbname'\n";
+ foreach ($tables as $table => $sql)
+ {
+ $version = count($sql);
+ if (array_key_exists($table, $versions))
+ $diff = $version - $versions[$table];
+ else {
+ $versions[$table] = 0;
+ $diff = $version;
+ }
+
+ $c .= " Table '$table' need v$version (current v".strval($versions[$table].') => ');
+
+ if ($diff > 0) {
+ $sql_to_run = array_slice($sql, $versions[$table], $diff);
+ foreach($sql_to_run as $sql_run) {
+ if ($sql_run) {
+ $c .= "Run sql... ";
+ $result = $db->query($sql_run);
+ } else
+ $c .= "KO!!!";
+ }
+ if ($result) {
+ $c .= "OK";
+ $versions[$table] = $version;
+ }
+ } else
+ $c .= "OK";
+ $c .= "\n";
+ }
+ $c .= "\n";
+ $db->close();
+ }
+ file_put_contents(RYAPP_PATH.'database.versions', serialize($versions));
+ return ''.$c.'';
+ }
}
?>
diff --git a/code/web/api/common/dfm.php b/code/web/api/common/dfm.php
new file mode 100644
index 000000000..57bbe70d3
--- /dev/null
+++ b/code/web/api/common/dfm.php
@@ -0,0 +1,151 @@
+.
+ */
+
+ function getDirLinks($url_params, $path, $getvar, $home) {
+ $ret = '';
+ $dirs = explode('/', $path);
+ $dirpath = '';
+ $ret .= _l($home, $url_params, array($getvar => ''));
+ foreach($dirs as $dirname) {
+ if ($dirname) {
+ $ret .= ' » '._l($dirname, $url_params, array($getvar => '/'.$dirpath.$dirname));
+ $dirpath .= $dirname.'/';
+ }
+ }
+ return $ret;
+}
+
+function isEmptyDir($dir)
+{
+ if (($files = scandir($dir)) && count($files) <= 2) {
+ return true;
+ }
+ return false;
+}
+
+class ryDataFileManager {
+
+ public $id;
+ public $log_dir;
+ public $data_dir;
+ public $user_dir;
+ public $app_name;
+
+ function __construct($id, $app_name=APP_NAME) {
+ $this->app_name = $app_name;
+ $id = (strlen($id) == 0?'0':'').$id;
+ $id = (strlen($id) == 1?'0':'').$id;
+ $this->id = $id;
+ $this->log_dir = RYAPP_PATH.$app_name.'/data/logs/';
+ $this->data_dir = RYAPP_PATH.$app_name.'/data/app/';
+ $this->user_dir = RYAPP_PATH.$app_name.'/data/chars/'.$id[0].'/'.$id[1].'/'.$id.'/';
+
+ if (!is_dir($this->user_dir))
+ @mkdir($this->user_dir, 0777, true);
+
+ if (!is_dir($this->log_dir)) {
+ @mkdir($this->log_dir, 0777, true);
+ @mkdir($this->data_dir, 0777, true);
+ }
+ }
+
+ /*** Generic datafiles access methods ***/
+
+ function getData($name, $default=null) {
+ if (file_exists($name))
+ return unserialize(file_get_contents($name));
+ if ($default !== NULL) {
+ @file_put_contents($name, serialize($default));
+ return $default;
+ }
+ return NULL;
+ }
+
+ function saveData($name, $datas, $create_folders=true) {
+ if ($create_folders) {
+ if (!is_dir(dirname($name)))
+ @mkdir(dirname($name), 0777, true);
+ }
+ if ($datas !== NULL)
+ @file_put_contents($name, serialize($datas));
+ else
+ @unlink($name);
+ }
+
+ function listDataFiles($dir) {
+ $ret = array();
+ if ($handle = @opendir($dir)) {
+ while (false !== ($file = readdir($handle))) {
+ if ($file != '.' && $file != '..' && $file[0] != '.')
+ $ret[] = $file;
+ }
+ }
+ return $ret;
+ }
+
+ /*** App Datas ***/
+
+ function loadAppData($name, $default=null) {
+ return $this->getData($this->data_dir.$name, $default);
+ }
+
+ function saveAppData($name, $datas, $create_folders=true) {
+ return $this->saveData($this->data_dir.$name, $datas, $create_folders);
+ }
+
+ function listAppDataFiles($basedir='') {
+ return $this->listDataFiles($this->data_dir.$basedir);
+ }
+
+
+ /*** User Datas ***/
+
+ function loadUserData($name, $default=null) {
+ return $this->getData($this->user_dir.$name, $default);
+ }
+
+ function saveUserData($name, $datas, $create_folders=true) {
+ return $this->saveData($this->user_dir.$name, $datas, $create_folders);
+ }
+
+ function listUserDataFiles($basedir='') {
+ return $this->listDataFiles($this->user_dir.$basedir);
+ }
+
+ function loadUserDataFromApp($name, $app, $default=null) {
+ $id = $this->id;
+ $file = RYAPP_PATH.$app.'/data/chars/'.$id[0].'/'.$id[1].'/'.$id.'/'.$name;
+ if (file_exists($file))
+ return unserialize(file_get_contents($file));
+ if ($default !== null)
+ return $default;
+ return null;
+ }
+
+ function saveUserDataFromApp($name, $app, $datas) {
+ $id = $this->id;
+ $dir = RYAPP_PATH.$app.'/data/chars/'.$id[0].'/'.$id[1].'/'.$id.'/';
+ if (!is_dir($dir))
+ @mkdir($dir, 0777, true);
+ file_put_contents($dir.$name, serialize($datas));
+ }
+}
+
+
+?>
diff --git a/code/web/api/common/logger.php b/code/web/api/common/logger.php
index 1e5106b54..7599c62c9 100644
--- a/code/web/api/common/logger.php
+++ b/code/web/api/common/logger.php
@@ -1,9 +1,26 @@
.
+ */
+
class ryLogger {
public $enable = false;
- private $logs;
+ private $logs = array();
private static $_instance = NULL;
public static function getInstance() {
@@ -32,12 +49,16 @@ class ryLogger {
function getLogs() {
$ret = '';
- if ($this->logs && $this->enable)
- $ret = "Debug\n\n".implode("\n", $this->logs);
- $this->logs = array();
+ if ($this->logs && $this->enable) {
+ $ret = 'Debug
'. implode('
', $this->logs).'
';
+ $this->logs = array();
+ }
return $ret;
}
}
+function _log() {
+ return ryLogger::getInstance();
+}
?>
diff --git a/code/web/api/common/render.php b/code/web/api/common/render.php
index e086db9dd..29309bfdc 100644
--- a/code/web/api/common/render.php
+++ b/code/web/api/common/render.php
@@ -1,4 +1,5 @@
.
*/
-function ryzom_app_render($title, $content, $ig=false, $bgcolor='', $javascript=array(), $homeLink=false) {
+function ryzom_app_render($title, $content, $style='', $files=array(), $homeLink=false) {
$c = '';
+
+ // get Lua code
+ $c .= ryLua::get(RYZOM_IG);
+ $at_end = ryLua::getEnd(RYZOM_IG);
+
// Render header
$title_prefix = '';
if (ON_IPHONE) {
$title_prefix = 'Ryzom - ';
}
- if (!$bgcolor)
- $bgcolor = '#000000'.($ig?'00':'');
-
- if (!$ig) {
+ if (!RYZOM_IG)
$c .= ''."\n";
- $c .= '
- '."\n";
- $c .= ' '.$title_prefix.(translation_exists($title)?_t($title):$title).''."\n";
+ $c .= ''."\n";
+ $c .= ' '.$title_prefix.(translation_exists($title)?_t($title):$title).''."\n";
+ if (!RYZOM_IG)
$c .= ' '."\n";
+
+ $events = '';
+ if (!RYZOM_IG) {
$c .= ryzom_render_header();
$c .= ryzom_render_header_www();
- $events = ON_IPHONE ? 'onorientationchange="updateOrientation();" ' : '';
- $c .= ' '."\n";
- $c .= ' '."\n";
- // Javascript
- $js_code = '';
- foreach ($javascript as $js)
- $js_code .= '';
- $c .= $js_code;
-
- $c .= ryzom_render_www(ryzom_render_window($title, $content, $homeLink));
- $c .= '';
+ if (function_exists('newrelic_get_browser_timing_header'))
+ $c .= newrelic_get_browser_timing_header();
+ if(ON_IPHONE) $events = 'onorientationchange="updateOrientation();" ';
} else {
- $c .= '';
- $c .= $content;
- $debug = ryLogger::getInstance()->getLogs();
- if ($debug)
- $c .= '
';
- $c .= '';
+ #if (!$style)
+ $style='bgcolor="#00000000"';
}
+
+ if (!RYZOM_IG) {
+ // Javascript
+ $extra_code = '';
+ if (is_string($files))
+ $files = array($files);
+ foreach ($files as $file) {
+ $sfile = explode('.', $file);
+ if ($sfile[count($sfile)-1] == 'js')
+ $extra_code .= ' '."\n";
+ else if ($sfile[count($sfile)-1] == 'css')
+ $extra_code .= ' '."\n";
+ }
+ $c .= $extra_code;
+ }
+
+ $c .= ' '."\n";
+ $c .= ' '."\n";
+
+ if (!RYZOM_IG) {
+ $c .= ryzom_render_www(ryzom_render_window($title, $content, $homeLink));
+ $c .= '';
+ if (function_exists('newrelic_get_browser_timing_header'))
+ $c .= newrelic_get_browser_timing_footer();
+ } else {
+ $c .= $content.'
'.ryLogger::getInstance()->getLogs().' |
';
+ }
+
+ $c .= '