diff --git a/code/web/api/client/auth.php b/code/web/api/client/auth.php
new file mode 100644
index 000000000..cab8a5886
--- /dev/null
+++ b/code/web/api/client/auth.php
@@ -0,0 +1,49 @@
+.
+ */
+
+require_once(RYAPI_PATH.'client/config.php');
+
+// Og (non-ryzom.com) method
+function ryzom_authenticate_with_serverkey($cid, $name, $authserver, $authkey) {
+ global $_RYZOM_API_CONFIG;
+ $fn = $_RYZOM_API_CONFIG['auth_script'].'?name='.$name.'&cid='.$cid.'&authkey='.$authkey.'&authserver='.$authserver;
+
+ $res = file_get_contents($fn);
+ return $res == '1';
+}
+
+// Ig method
+function ryzom_authenticate_ingame($cid, $name, $authkey) {
+ global $_RYZOM_API_CONFIG;
+ $fn = $_RYZOM_API_CONFIG['auth_script'].'?name='.$name.'&cid='.$cid.'&authkey='.$authkey.'&ig=1';
+
+ $res = file_get_contents($fn);
+ echo $res;
+ return $res == '1';
+}
+
+// Session method
+function ryzom_authenticate_with_session($name, $redirect) {
+ global $_RYZOM_API_CONFIG;
+ $fn = $_RYZOM_API_CONFIG['auth_script'].'?name='.$name;
+
+ $res = file_get_contents($fn);
+ return $res == '1';
+}
+
+?>
diff --git a/code/web/api/client/config.php.default b/code/web/api/client/config.php.default
new file mode 100644
index 000000000..3c8ca869d
--- /dev/null
+++ b/code/web/api/client/config.php.default
@@ -0,0 +1,20 @@
+.
+ */
+
+// Url where player_auth.php is located
+define('RYAPI_AUTH_SCRIPT', '');
diff --git a/code/web/api/client/user.php b/code/web/api/client/user.php
new file mode 100644
index 000000000..de526dcca
--- /dev/null
+++ b/code/web/api/client/user.php
@@ -0,0 +1,23 @@
+.
+ */
+
+function ryzom_user_get_info($cid) {
+ return Array();
+}
+
+?>
diff --git a/code/web/api/client/utils.php b/code/web/api/client/utils.php
new file mode 100644
index 000000000..62a2de0c8
--- /dev/null
+++ b/code/web/api/client/utils.php
@@ -0,0 +1,3 @@
+
diff --git a/code/web/api/common/auth.php b/code/web/api/common/auth.php
new file mode 100644
index 000000000..b6bcdd799
--- /dev/null
+++ b/code/web/api/common/auth.php
@@ -0,0 +1,57 @@
+The application '._t(APP_NAME).' require authentication. Please enter your credentials';
+
+ $c .= '
'.$welcome_message.'
';
+
+ if ($user['message'])
+ $c .= ''._t($user['message']).'
';
+ $c .= ryzom_render_login_form($name, false);
+ echo ryzom_app_render(_t('app_'.APP_NAME), $c);
+ exit;
+ }
+ return false;
+ }
+ }
+
+ if ($lang)
+ $_SESSION['lang'] = $lang;
+
+ // get user informations
+ $user = ryzom_user_get_info($cid);
+ $user['lang'] = $_SESSION['lang'];
+
+ $user['id'] = ryzom_get_user_id($cid, $user['char_name'], $user['creation_date']);
+ unset($user['last_played_date']);
+ unset($user['creation_date']);
+ return true;
+}
+
+?>
diff --git a/code/web/api/common/config.php.default b/code/web/api/common/config.php.default
new file mode 100644
index 000000000..3a00bb04e
--- /dev/null
+++ b/code/web/api/common/config.php.default
@@ -0,0 +1,28 @@
+.
+ */
+
+// Url where the api is
+define('RYAPI_URL', 'http://');
+if (!defined('RYAPI_PATH'))
+ define('RYAPI_PATH', dirname(__FILE__).'/');
+// used by "home" link
+if (!defined('RYAPP_URL'))
+ define('RYAPP_URL', 'http://');
+
+?>
diff --git a/code/web/api/common/db_lib.php b/code/web/api/common/db_lib.php
new file mode 100644
index 000000000..c3c7e8677
--- /dev/null
+++ b/code/web/api/common/db_lib.php
@@ -0,0 +1,422 @@
+.
+ */
+
+define('SQL_DEF_TEXT', 0);
+define('SQL_DEF_BOOLEAN', 1);
+define('SQL_DEF_INT', 2);
+define('SQL_DEF_DATE', 3);
+
+
+// Wrapper for SQL database interactions
+class ServerDatabase
+{
+ var $hostname = '';
+ var $username = '';
+ var $password = '';
+ var $database = '';
+
+ var $_connection = Null;
+
+ function ServerDatabase($host='', $user='', $passwd='', $dbname='')
+ {
+ if (($host != '') && ($user != '') && ($dbname != ''))
+ {
+ $this->hostname = $host;
+ $this->username = $user;
+ $this->password = $passwd;
+ $this->database = $dbname;
+ }
+
+ 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);
+ }
+ }
+
+ function close()
+ {
+ @mysql_close($this->_connection);
+ }
+
+ function query($sql_statement)
+ {
+ $result = mysql_query($sql_statement, $this->_connection);
+ return $result;
+ }
+
+ function select_db($dbname) {
+ $this->database = $dbname;
+ mysql_select_db($this->database, $this->_connection) or die("Database selection error : " . $this->get_error());
+ }
+
+ function num_rows($result)
+ {
+ return @mysql_num_rows($result);
+ }
+
+ function fetch_row($result, $result_type=MYSQL_BOTH)
+ {
+ return @mysql_fetch_array($result, $result_type);
+ }
+
+ function fetch_assoc($result)
+ {
+ return @mysql_fetch_array($result, MYSQL_ASSOC);
+ }
+
+
+ function query_single_row($sql_statement)
+ {
+ $result = $this->query($sql_statement);
+ return @mysql_fetch_array($result);
+ }
+
+ function free_result($result)
+ {
+ @mysql_free_result($result);
+ }
+
+ function get_error()
+ {
+ return mysql_errno($this->_connection) .": ". mysql_error($this->_connection);
+ }
+
+ function last_insert_id()
+ {
+ return @mysql_insert_id();
+ }
+
+ function change_to($host,$user,$pass,$dbname)
+ {
+ $this->close();
+ $this->hostname = $host;
+ $this->username = $user;
+ $this->password = $pass;
+ $this->database = $dbname;
+ $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 = new ServerDatabase(RYAPI_WEBDB_HOST, RYAPI_WEBDB_LOGIN, RYAPI_WEBDB_PASS, $db_name);
+ $this->db->query("SET NAMES utf8");
+ }
+
+ public static function getInstance($db_name) {
+ if (!array_key_exists($db_name, self::$_instances))
+ self::$_instances[$db_name] = new ryDB($db_name);
+
+ self::$_instances[$db_name]->db->select_db($db_name);
+ return self::$_instances[$db_name];
+ }
+
+ function setDbDefs($table, $defs) {
+ $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];
+ }
+
+ function getErrors() {
+ return $this->db->get_error();
+ }
+
+ function now() {
+ return date('Y-m-d H:i:s', time());
+ }
+
+ function toDate($timestamp) {
+ return date('Y-m-d H:i:s', $timestamp);
+ }
+
+ function fromDate($string_date) {
+ return strtotime($string_date);
+ }
+
+ function addDbTableProp($table, $props) {
+ $this->props[$table] = $props;
+ }
+
+ /// DIRECT QUERY
+ function sqlQuery($sql) {
+ $result = $this->db->query($sql);
+ $ret = array();
+ while ($row = $this->db->fetch_row($result)) {
+ $ret[] = $row;
+ }
+ return $ret;
+ }
+
+
+ /// QUERY ///
+ function sqlSelect($table, $props, $values=array(), $extra='') {
+ if ($table) {
+ $sql = "SELECT\n\t";
+ $params = array();
+ $test = array();
+ if (!$props)
+ die("Bad Select on [$table] : missing props");
+
+ foreach($props as $name => $type)
+ $params[] = '`'.addslashes($name).'`';
+
+ foreach($values as $name => $value) {
+ if ($name[0] == '=')
+ $test[] = '('.addslashes(substr($name, 1)).' LIKE '.var_export($value, true).')';
+ else
+ $test[] = '('.addslashes($name).' = '.var_export($value, true).')';
+ }
+ $sql .= implode(",\n\t", $params)."\nFROM\n\t".$table."\n";
+ if ($test)
+ $sql .= "WHERE\n\t".implode("\nAND\n\t", $test);
+ }
+
+ if ($extra)
+ $sql .= "\n".$extra;
+ 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);
+ }
+
+ 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);
+ }
+
+ function query($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)) {
+ $ret[] = $row;
+ }
+ return $ret;
+ }
+
+ 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;
+ }
+
+ /// INSERT ///
+ function sqlInsert($table, $props, $vals) {
+ $sql = 'INSERT INTO '.$table.' ';
+ $params = array();
+ $values = array();
+ foreach($props as $name => $type) {
+ if (!isset($vals[$name]))
+ continue;
+ $params[] = $name;
+ switch ($type) {
+ case SQL_DEF_BOOLEAN:
+ $values[] = $vals[$name]?1:0;
+ break;
+ case SQL_DEF_INT:
+ $values[] = $vals[$name];
+ break;
+ case SQL_DEF_DATE: // date
+ if (is_string($vals[$name]))
+ $values[] = "'".addslashes($vals[$name])."'";
+ else
+ $values[] = "'".$this->toDate($vals[$name])."'";
+ break;
+ default:
+ $values[] = "'".addslashes($vals[$name])."'";
+ break;
+ }
+ }
+ $sql .= "(\n\t".implode(",\n\t", $params)."\n) VALUES (\n\t".implode(",\n\t", $values)."\n);";
+ return $sql;
+ }
+
+ function insert($table, $values) {
+ $sql = $this->sqlInsert($table, $this->getDefs($table), $values);
+ $this->db->query($sql);
+ return $this->db->last_insert_id();
+ }
+
+ /// DELETE ///
+ function sqlDelete($table, $values=array(), $where='') {
+ $sql = "DELETE FROM\n\t".$table."\n";
+ $test = array();
+ foreach($values as $name => $value)
+ $test[] = '('.addslashes($name).' = '.var_export($value, true).')';
+
+ if ($test or $where)
+ $sql .= "WHERE\n\t";
+ if ($test)
+ $sql .= implode("\nAND\n\t", $test);
+ if ($where)
+ $sql .= "\n".$where;
+ return $sql.';';
+ }
+
+ function delete($table, $values=array(), $where='') {
+ $sql = $this->sqlDelete($table, $values, $where);
+ $result = $this->db->query($sql);
+ return $result;
+ }
+
+ /// UPDATE ///
+ function sqlUpdate($table, $props, $vals, $tests, $extra) {
+ $sql = 'UPDATE '.$table.' SET ';
+ $params = array();
+ $test = array();
+ $values = array();
+ foreach($props as $name => $type) {
+ if (!array_key_exists($name, $vals))
+ continue;
+ switch ($type) {
+ case SQL_DEF_BOOLEAN:
+ $values[] = '`'.$name.'` = '.($vals[$name]?'1':'0');
+ break;
+ case SQL_DEF_DATE:
+ if (is_string($vals[$name]))
+ $values[] = '`'.$name.'` = \''.addslashes($vals[$name]).'\'';
+ else
+ $values[] = '`'.$name.'` = \''.$this->toDate($vals[$name]).'\'';
+ break;
+ default:
+ $values[] = '`'.$name.'` = \''.addslashes($vals[$name]).'\'';
+ break;
+ }
+ }
+ $sql .= "\n\t".implode(",\n\t", $values)."\n";
+
+ foreach($tests as $name => $value) {
+ $test[] = '('.addslashes($name).' = '.var_export($value, true).')';
+ }
+ if ($test)
+ $sql .= "WHERE\n\t".implode("\nAND\n\t", $test);
+
+ $sql .= "\n".$extra;
+
+ return $sql;
+ }
+
+
+ function update($table, $values=array(), $test=array(), $extra='') {
+ $sql = $this->sqlUpdate($table, $this->getDefs($table), $values, $test, $extra);
+ $result = $this->db->query($sql);
+ return $result;
+ }
+
+ function sqlInsertOrUpdate($table, $props, $vals) {
+ $sql = $this->sqlInsert($table, $props, $vals);
+ $sql = substr($sql, 0, strlen($sql)-1);
+ $params = array();
+ $test = array();
+ $values = array();
+ foreach($props as $prop) {
+ if (!array_key_exists($prop[2], $vals))
+ continue;
+ $type = $prop[0];
+ $check = $prop[1];
+ $name = $prop[2];
+ if ($type{0} == '#')
+ $type = substr($type, 1);
+ if (($type{0} == '>') or ($type == 'id'))
+ continue;
+ switch ($type) {
+ case 'trad':
+ $values[] = '`'.$name."` = '".addslashes($vals[$name])."'";
+ break;
+ case 'textarea':
+ case 'string':
+ case 'option':
+ $values[] = '`'.$name."` = '".addslashes($vals[$name])."'";
+ break;
+ case 'id':
+ case 'int':
+ case 'float':
+ $values[] = '`'.$name.'` = '.addslashes($vals[$name]);
+ break;
+ case 'bool':
+ $values[] = '`'.$name.'` = '.($vals[$name]?'1':'0');
+ break;
+ }
+ }
+ $sql .= "\nON DUPLICATE KEY UPDATE\n\t".implode(",\n\t", $values)."\n";
+ return $sql;
+ }
+
+ function insertOrUpdate($table, $values) {
+ $sql = $this->sqlInsertOrUpdate($table, $this->getDefs($table), $values);
+ return $result;
+ }
+
+
+ /// Display
+ function getTableHtml($name, $params, $values, $order_by='')
+ {
+ $ret = '';
+ $tr_header = ' ';
+ $tr_header .= implode(' | ', array_keys($params)).' | ';
+ $ret .= _s('t header', $tr_header);
+ $i = 0;
+ if (!$values)
+ return '';
+ $current_section = '';
+ foreach ($values as $rows) {
+ if ($order_by && $rows[$order_by] != $current_section) {
+ $current_section = $rows[$order_by];
+ if ($current_section != '0')
+ $ret .= _s('t row ', ''._s('section', $current_section).' | '.str_repeat(''._s('section', ' ').' | ', count($params)-1));
+ }
+ $td = '';
+ foreach ($params as $test => $param)
+ $td .= ' '.$rows[$param].' | ';
+ $ret .= _s('t row '.strval($i % 2), $td);
+ $i++;
+ }
+ $ret .= '
';
+ return $ret;
+ }
+
+}
+
+?>
diff --git a/code/web/api/common/logger.php b/code/web/api/common/logger.php
new file mode 100644
index 000000000..f4909e721
--- /dev/null
+++ b/code/web/api/common/logger.php
@@ -0,0 +1,43 @@
+log_indent += $indent;
+ if ($log) {
+ $tabs = str_repeat(" ", $this->log_indent);
+ $a = $tabs.str_replace("\n", "\n ".$tabs, $log);
+ $this->logs[] = ''.$a.'';
+ }
+ }
+
+ function addPrint($log, $color='#FFFF00') {
+ $this->logs[] = ''.$log.'';
+ }
+
+ function addError($log) {
+ $this->logs[] = ' ERROR: '.$log.'';
+ }
+
+ function getLogs() {
+ $ret = '';
+ if ($this->logs && $this->enable)
+ $ret = "Debug\n".implode("\n", $this->logs);
+ $this->logs = array();
+ return $ret;
+ }
+}
+
+
+?>
diff --git a/code/web/api/common/render.php b/code/web/api/common/render.php
new file mode 100644
index 000000000..a2ec31795
--- /dev/null
+++ b/code/web/api/common/render.php
@@ -0,0 +1,218 @@
+.
+ */
+
+function ryzom_app_render($title, $content, $bgcolor='', $javascript=array(), $homeLink=false) {
+ $c = '';
+ // Render header
+ $title_prefix = '';
+ if (ON_IPHONE) {
+ $title_prefix = 'Ryzom - ';
+ }
+
+ if (!$bgcolor)
+ $bgcolor = '#000000'.(RYZOM_IG?'00':'');
+
+ $c .= ''."\n";
+ $c .= '
+ '."\n";
+ $c .= ' '.$title_prefix.(translation_exists($title)?_t($title):$title).''."\n";
+ $c .= ' '."\n";
+
+ 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;
+
+ if (RYZOM_IG)
+ $c .= $content;
+ else{
+ $c .= ryzom_render_www(ryzom_render_window($title, $content, $homeLink));
+ }
+
+ $c .= '';
+ return $c;
+}
+
+function ryzom_render_header() {
+ if (ON_IPHONE) {
+ return '';
+ } else {
+ return ' ';
+ }
+}
+
+// Call this inside the part if you want to use ryzom_render_www
+function ryzom_render_header_www() {
+ if (ON_IPHONE) {
+ return '
+
+
+
+
+ ';
+ } else {
+ return '
+
+';
+ }
+}
+
+// Render a Ryzom style window
+function ryzom_render_window($title, $content, $homeLink=false) {
+ return ryzom_render_window_begin($title, $homeLink) . $content . ryzom_render_window_end();
+}
+
+function ryzom_render_window_begin($title, $homeLink=false) {
+
+ if ($homeLink === false)
+ $homeLink = ''._t('home').'';
+
+ return '
+
+ ';
+}
+
+// Render a webpage using www.ryzom.com style
+function ryzom_render_www($content) {
+ return ryzom_render_www_begin() . $content . ryzom_render_www_end();
+}
+
+function ryzom_render_www_begin($url='') {
+ $style1 = 'position: relative; padding-top: 20px; padding-right: 30px; margin-bottom: -3px';
+ $style2 = 'position: absolute; bottom: 0; right: 0; ';
+ if (ON_IPHONE) {
+ $style1 = 'position: relative; padding-top: 30px; padding-right: 30px; ';
+ $style2 = 'position: fixed; top: 0; right: 0; padding-right: 0px;';
+ $marginBottom = '';
+ }
+ if (!$url) {
+ $url_params = parse_query($_SERVER['REQUEST_URI']);
+ unset($url_params['lang']);
+
+ $url = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?'.http_build_query($url_params);
+ }
+ return '
+
+
+
+';
+}
+
+function ryzom_render_www_end() {
+ return '
';
+}
+
+function ryzom_render_login_form($char, $aligned=true) {
+ $c = '';
+ if ($aligned) {
+ $c .= '