Fixed: #1378 Imported nimetu's WebIG reference implementation.
This commit is contained in:
parent
ae10726b98
commit
548740bafc
7 changed files with 796 additions and 0 deletions
29
code/ryzom/tools/server/www/webig/app_hello.php
Normal file
29
code/ryzom/tools/server/www/webig/app_hello.php
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once 'lib/functions.php';
|
||||||
|
|
||||||
|
$user = app_authenticate();
|
||||||
|
if(empty($user)){
|
||||||
|
// redirect to login page
|
||||||
|
$url = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
|
||||||
|
header('Location: index.php?redirect='.urlencode($url));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get more info about character - race, civlization, cult, guild, etc
|
||||||
|
$character = webig_load_character($user['cid']);
|
||||||
|
|
||||||
|
?>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>App Hello World!</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>APP Hello World!</h1>
|
||||||
|
|
||||||
|
<a href="index.php">index</a><?=(!isWEBIG ? '| <a href="?logout">logout</a>' : '')?>
|
||||||
|
|
||||||
|
<h2>Character</h2>
|
||||||
|
<pre><?php print_r($character);?></pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
133
code/ryzom/tools/server/www/webig/index.php
Normal file
133
code/ryzom/tools/server/www/webig/index.php
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$__start = microtime(true);
|
||||||
|
require_once 'lib/functions.php';
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
// do user login
|
||||||
|
$user = app_authenticate();
|
||||||
|
|
||||||
|
if(empty($user)){
|
||||||
|
// user not verified
|
||||||
|
//
|
||||||
|
$error = is($_SESSION['login']['error'], '');
|
||||||
|
if(!empty($error)){
|
||||||
|
$error = '<p style="color: red;">login error</p>';
|
||||||
|
}
|
||||||
|
echo '
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>WebIG - Login</title>
|
||||||
|
</head>
|
||||||
|
<body
|
||||||
|
<h1>Login</h1>
|
||||||
|
<form method="post" action="">
|
||||||
|
<input type="hidden" name="login[shardid]" value="302" />
|
||||||
|
Char name <input type="text" name="login[name]" value="" /><br />
|
||||||
|
Password <input type="password" name="login[passwd]" value="" /><br />
|
||||||
|
<input type="submit" name="login[submit]" value="Login" />
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this was login request from app, then redirect back there
|
||||||
|
$redirect = is($_GET['redirect'], '');
|
||||||
|
if(!empty($redirect)){
|
||||||
|
header('Location: '.$redirect);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check user privileges
|
||||||
|
$is_admin = webig_is_admin($user['cid']>>4);
|
||||||
|
|
||||||
|
// get more info about character - race, civlization, cult, guild, etc
|
||||||
|
$character = webig_load_character($user['cid']);
|
||||||
|
|
||||||
|
// user is verified
|
||||||
|
?>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>App Index</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Hello "<?=h($user['name'])?>"!</h1>
|
||||||
|
|
||||||
|
<a href="index.php">index</a> | <a href="app_hello.php">Hello APP</a><?=(!isWEBIG ? '| <a href="?logout">logout</a>' : '')?>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
if($is_admin){
|
||||||
|
if(isWEBIG){
|
||||||
|
display_teleport_list();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '<h2>User info</h2>';
|
||||||
|
echo 'USER:'.dump_array($user);
|
||||||
|
echo 'CHARACTER:'.dump_array($character);
|
||||||
|
|
||||||
|
$__end = microtime(true);
|
||||||
|
echo "<pre>\n---\npage created ".sprintf("%.5fsec", $__end - $__start).'</pre>';
|
||||||
|
|
||||||
|
?>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function dump_array($array){
|
||||||
|
ob_start();
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<table cellspacing="2" cellpadding="0" bgcolor="#4f4f4f">
|
||||||
|
<tr><td>
|
||||||
|
<table cellspacing="0" cellpadding="0">
|
||||||
|
';
|
||||||
|
$c=0;
|
||||||
|
foreach($array as $k => $v){
|
||||||
|
if(is_array($v)){
|
||||||
|
$v = dump_array($v);
|
||||||
|
}else{
|
||||||
|
// make value safe for html
|
||||||
|
$v = h($v);
|
||||||
|
}
|
||||||
|
echo '
|
||||||
|
<tr valign="middle" bgcolor="'.($c%2 ? '#9f9f9f' : '#909090').'">
|
||||||
|
<td height="20">'.h($k).'</td><td>'.$v.'</td>
|
||||||
|
</tr>
|
||||||
|
';
|
||||||
|
$c++;
|
||||||
|
}
|
||||||
|
echo '
|
||||||
|
</table>
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
||||||
|
';
|
||||||
|
|
||||||
|
return ob_get_clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
function display_teleport_list(){
|
||||||
|
$places = array(
|
||||||
|
'Ranger Camp' => array(10314,-11734),
|
||||||
|
'Shining Lake' => array(9056, -10822),
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
<h2>Teleport destinations</h2>
|
||||||
|
<table cellspacing="2" cellpadding="0" bgcolor="#4f4f4f">
|
||||||
|
<tr><td>
|
||||||
|
<table cellspacing="0" cellpadding="0">
|
||||||
|
<?php $c=0; foreach($places as $txt => $xyz){
|
||||||
|
echo '
|
||||||
|
<tr valign="middle" bgcolor="'.($c%2 ? '#3f3f3f' : '#303030').'">
|
||||||
|
<td height="20">'.h($txt).'</td><td><a href="ah:command&a&Position&'.join(',', $xyz).'">'.join(',', $xyz).'</a></td>
|
||||||
|
</tr>
|
||||||
|
';
|
||||||
|
$c++;
|
||||||
|
} ?>
|
||||||
|
</table>
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
||||||
|
<?php
|
||||||
|
}
|
23
code/ryzom/tools/server/www/webig/lib/config.php
Normal file
23
code/ryzom/tools/server/www/webig/lib/config.php
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
// Variables for PdrUtil class
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
define('CMD_PDR_UTIL', 'C:/RyzomCore/ryzom_core_server/ryzom/tools/pdr_util');
|
||||||
|
define('SHARD_SAVE', 'C:/RyzomCore/ryzom_core_server/ryzom/server/save_shard');
|
||||||
|
define('SHEETID_DIR', 'C:/RyzomCore/ryzom_core_server/ryzom/common/data_leveldesign/leveldesign/Game_elem');
|
||||||
|
define('TEMP_UNPACK', 'c:/temp');
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
// Variables for nel database access
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// where we can find the mysql database
|
||||||
|
$DBHost = 'localhost';
|
||||||
|
$DBUserName = 'shard';
|
||||||
|
$DBPassword = '';
|
||||||
|
$DBName = 'nel';
|
||||||
|
|
||||||
|
//
|
||||||
|
$RingDBUserName = 'shard';
|
||||||
|
$RingDBName = 'ring_open';
|
||||||
|
$RingDBPassword = '';
|
394
code/ryzom/tools/server/www/webig/lib/functions.php
Normal file
394
code/ryzom/tools/server/www/webig/lib/functions.php
Normal file
|
@ -0,0 +1,394 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
if(strstr($_SERVER['HTTP_USER_AGENT'], 'Ryzom')){
|
||||||
|
define('isWEBIG', true);
|
||||||
|
}else{
|
||||||
|
define('isWEBIG', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
require_once 'config.php';
|
||||||
|
require_once 'pdr_util.php';
|
||||||
|
require_once 'pdr_util_character.php';
|
||||||
|
require_once 'pdr_util_guild.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton wrapper class for PDO database connection
|
||||||
|
*/
|
||||||
|
class DB {
|
||||||
|
private $_pdo = null;
|
||||||
|
|
||||||
|
private function __construct(){
|
||||||
|
$this->_pdo = new PDO('mysql:host='.$GLOBALS['DBHost'].';dbname='.$GLOBALS['DBName'].';charset=utf-8', $GLOBALS['DBUserName'], $GLOBALS['DBPassword'], array(PDO::MYSQL_ATTR_INIT_COMMAND => 'set names utf8'));
|
||||||
|
$this->_pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInstance(){
|
||||||
|
static $instance = null;
|
||||||
|
if($instance === null){
|
||||||
|
$instance = new DB();
|
||||||
|
}
|
||||||
|
return $instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sql
|
||||||
|
* @param array $params (optional)
|
||||||
|
* @return PDOStatement
|
||||||
|
*/
|
||||||
|
function query($sql, $params=array()){
|
||||||
|
if(empty($params)){
|
||||||
|
$stmt = $this->_pdo->query($sql);
|
||||||
|
}else{
|
||||||
|
$stmt = $this->_pdo->prepare($sql);
|
||||||
|
$stmt->execute($params);
|
||||||
|
}
|
||||||
|
return $stmt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify and log-in user
|
||||||
|
*
|
||||||
|
* @return mixed user info array or boolean FALSE when user was not verified
|
||||||
|
*/
|
||||||
|
function app_authenticate(){
|
||||||
|
// mask possible double session_start() warning
|
||||||
|
@session_start();
|
||||||
|
|
||||||
|
if(isWEBIG){
|
||||||
|
// ingame login
|
||||||
|
|
||||||
|
// gather user from $_GET or $_POST variables
|
||||||
|
$user = webig_user();
|
||||||
|
|
||||||
|
// verify it against database
|
||||||
|
$user = webig_auth($user);
|
||||||
|
}else{
|
||||||
|
// outgame login
|
||||||
|
|
||||||
|
if(isset($_POST['login'])){
|
||||||
|
// login request
|
||||||
|
$shardid = is($_POST['login']['shardid'], '');
|
||||||
|
$name = is($_POST['login']['name'], '');
|
||||||
|
$passwd = is($_POST['login']['passwd'], '');
|
||||||
|
|
||||||
|
// verify character and password against database and populate $_GET with user info
|
||||||
|
$user = login_auth($shardid, $name, $passwd);
|
||||||
|
$_SESSION['login']['error'] = ($user === false);
|
||||||
|
}elseif(isset($_GET['logout'])){
|
||||||
|
// logout request
|
||||||
|
unset($_SESSION['user']);
|
||||||
|
unset($_SESSION['authkey']);
|
||||||
|
|
||||||
|
// redirect to self without URL parameters
|
||||||
|
header('Location: '.$_SERVER['PHP_SELF']);
|
||||||
|
exit;
|
||||||
|
}else{
|
||||||
|
// continue session
|
||||||
|
$user = is($_SESSION['user'], false);
|
||||||
|
|
||||||
|
// verify user in session against database (e.g. user might be deleted)
|
||||||
|
$user = load_user($user['shardid'], null, $user['cid']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// auth failed?
|
||||||
|
if(empty($user)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove values we do not need to keep in session
|
||||||
|
unset($user['password']);
|
||||||
|
unset($user['cookie']);
|
||||||
|
|
||||||
|
// return user info array on success
|
||||||
|
$_SESSION['user'] = $user;
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get user info that WebIG sends us
|
||||||
|
function webig_user(){
|
||||||
|
$user = array();
|
||||||
|
|
||||||
|
// shard id (302)
|
||||||
|
$user['shardid'] = ryzom_get_param('shardid');
|
||||||
|
|
||||||
|
// character name (User)
|
||||||
|
$user['name'] = ryzom_get_param('name');
|
||||||
|
|
||||||
|
// character id (16), user id is calculated as 'uid = cid >> 4';
|
||||||
|
$user['cid'] = ryzom_get_param('cid');
|
||||||
|
|
||||||
|
// language
|
||||||
|
$user['lang'] = ryzom_get_param('lang');
|
||||||
|
|
||||||
|
$user['authkey'] = ryzom_get_param('authkey');
|
||||||
|
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify character using info from ig browser
|
||||||
|
*
|
||||||
|
* @param array $user
|
||||||
|
* @return bool return user info array on success and FALSE on error
|
||||||
|
*/
|
||||||
|
function webig_auth($user){
|
||||||
|
// find user by shard and character id (name might be temporarily changed in game)
|
||||||
|
$result = load_user($user['shardid'], null, $user['cid']);
|
||||||
|
if(empty($result)){
|
||||||
|
// should not happen, but user was not found
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create auth key by using cookie from DB and user info from user
|
||||||
|
$authkey = webig_create_authkey($user, $result['cookie']);
|
||||||
|
if($user['authkey'] !== $authkey){
|
||||||
|
// something is out of sync - either user info or cookie
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return result from DB
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify character
|
||||||
|
*
|
||||||
|
* @param int $shardid character shard id
|
||||||
|
* @param string $name character name
|
||||||
|
* @param string $passwd plain text password
|
||||||
|
* @return mixed return user info array on success or boolean false on error
|
||||||
|
*/
|
||||||
|
function login_auth($shardid, $name, $passwd){
|
||||||
|
// get character from db
|
||||||
|
$user = load_user($shardid, $name);
|
||||||
|
if(empty($user)){
|
||||||
|
// user was not found
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$passwd = crypt($passwd, substr($user['password'], 0, 2));
|
||||||
|
if($passwd !== $user['password']){
|
||||||
|
// password failed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch user info from db
|
||||||
|
*
|
||||||
|
* If name is NULL, then $cid is used
|
||||||
|
*
|
||||||
|
* @param int $shardid
|
||||||
|
* @param string $name
|
||||||
|
* @param int $cid
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function load_user($shardid, $name, $cid = null){
|
||||||
|
// `nel`.`user` has password
|
||||||
|
// `ring_open`.`ring_users` has cookie
|
||||||
|
// `ring_open`.`characters` has char_id, char_name, home_mainland_session_id(==shardid)
|
||||||
|
|
||||||
|
$sql = 'SELECT c.`char_id` cid, c.`char_name` name, c.`home_mainland_session_id` shardid, n.`password`, u.`cookie`
|
||||||
|
FROM `ring_open`.`characters` c
|
||||||
|
JOIN `ring_open`.`ring_users` u on u.`user_id` = c.`user_id`
|
||||||
|
JOIN `nel`.`user` n on n.`uid` = c.`user_id`
|
||||||
|
WHERE c.`home_mainland_session_id` = :shardid';
|
||||||
|
$params = array('shardid' => $shardid);
|
||||||
|
if($name !== null){
|
||||||
|
$sql .= ' AND c.`char_name` = :name';
|
||||||
|
$params['name'] = $name;
|
||||||
|
}elseif($cid !== null){
|
||||||
|
$sql .= ' AND c.`char_id` = :cid';
|
||||||
|
$params['cid'] = $cid;
|
||||||
|
}else{
|
||||||
|
// $name or $cid both empty
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = DB::getInstance()->query($sql, $params)->fetch(PDO::FETCH_ASSOC);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify user info that ig browser sent us using cookie from database
|
||||||
|
*
|
||||||
|
* @param array $user user info array
|
||||||
|
* @param string $cookie User login cookie from database
|
||||||
|
* @return string md5 hash
|
||||||
|
*/
|
||||||
|
function webig_create_authkey($user, $cookie){
|
||||||
|
return md5($user['shardid'].$user['name'].$user['cid'].'\''.$cookie.'\'');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return user privileges from DB
|
||||||
|
*
|
||||||
|
* @param int $uid user id (uid = cid >> 4)
|
||||||
|
* @return mixed array of user privileges or boolean FALSE when user was not found
|
||||||
|
*/
|
||||||
|
function webig_get_privileges($uid){
|
||||||
|
$sql = 'select `privilege` from `nel`.`user` where `uid` = :id';
|
||||||
|
$params = array('id' => $uid);
|
||||||
|
|
||||||
|
$result = DB::getInstance()->query($sql, $params)->fetchColumn(0);
|
||||||
|
|
||||||
|
if($result !== false){
|
||||||
|
$result = explode(':', $result);
|
||||||
|
$ret = array();
|
||||||
|
foreach($result as $k=>$v){
|
||||||
|
if($v != ''){
|
||||||
|
$ret[]=$v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$result = $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test user privileges
|
||||||
|
*
|
||||||
|
* @param int $uid user id
|
||||||
|
* @param array $priv array of privileges, like array('DEV', 'GM')
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function webig_has_privileges($uid, $priv){
|
||||||
|
$userpriv = webig_get_privileges($uid);
|
||||||
|
$result = array_intersect($priv, $userpriv);
|
||||||
|
return !empty($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test user privileges against (DEV, SGM, GM)
|
||||||
|
*
|
||||||
|
* @param int $uid user id
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function webig_is_admin($uid){
|
||||||
|
// entities_game_service/player_manager/player_manager.cpp defines order
|
||||||
|
// DEV > SGM > EM > GM > EG > VG > SG > G > OBSERVER > PR
|
||||||
|
return webig_has_privileges($uid, array('DEV', 'SGM', 'EM', 'GM'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load character from shard save binary file
|
||||||
|
*
|
||||||
|
* @param int $cid
|
||||||
|
* @return mixed array with character info or boolean FALSE on error
|
||||||
|
*/
|
||||||
|
function webig_load_character($cid){
|
||||||
|
$pdr = CharacterPdr::createDefault();
|
||||||
|
$char = $pdr->load($cid);
|
||||||
|
if(empty($char)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = array(
|
||||||
|
'id' => (int) $cid,
|
||||||
|
'name' => (string) $char->EntityBase->_Name['value'],
|
||||||
|
'title' => (string) $char->_Title['value'],
|
||||||
|
'race' => (string) $char->EntityBase->_Race['value'],
|
||||||
|
'gender' => (int) $char->EntityBase->_Gender['value'] == '0' ? 'male' : 'female',
|
||||||
|
'cult' => (string) $char->DeclaredCult['value'],
|
||||||
|
'civ' => (string) $char->DeclaredCiv['value'],
|
||||||
|
'guild' => false,
|
||||||
|
);
|
||||||
|
|
||||||
|
$guild_id = (int) $char->_GuildId['value'];
|
||||||
|
if($guild_id>0){
|
||||||
|
// if char is in guild, then also get guild info
|
||||||
|
$result['guild'] = webig_load_guild($guild_id);
|
||||||
|
|
||||||
|
// get guild rank (also from guild file)
|
||||||
|
$result['guild_membership'] = webig_load_guild_membership($guild_id, $cid);
|
||||||
|
}
|
||||||
|
unset($char);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load basic guild info (name, description, motd, culv, civ)
|
||||||
|
*
|
||||||
|
* @param int $guild_id
|
||||||
|
* @return mixed array with guild info or boolean FALSE on error
|
||||||
|
*/
|
||||||
|
function webig_load_guild($guild_id){
|
||||||
|
$pdr = GuildPdr::createDefault();
|
||||||
|
$guild = $pdr->load($guild_id);
|
||||||
|
if(empty($guild)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = array(
|
||||||
|
'id' => (int) $guild_id,
|
||||||
|
'icon' => (string) $guild->Icon['value'],
|
||||||
|
'name' => (string) $guild->_Name['value'],
|
||||||
|
'description' => (string) $guild->_Description['value'],
|
||||||
|
'motd' => (string) $guild->_MessageOfTheDay['value'],
|
||||||
|
'cult' => (string) $guild->DeclaredCult['value'],
|
||||||
|
'civ' => (string) $guild->DeclaredCiv['value'],
|
||||||
|
);
|
||||||
|
unset($guild);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load guild member info
|
||||||
|
*
|
||||||
|
* @param int $guild_id
|
||||||
|
* @param int $char_id
|
||||||
|
* @return mixed array with guild member info or boolean FALSE if guild or character not found
|
||||||
|
*/
|
||||||
|
function webig_load_guild_membership($guild_id, $char_id){
|
||||||
|
$pdr = GuildPdr::createDefault();
|
||||||
|
$guild = $pdr->load($guild_id);
|
||||||
|
if(empty($guild)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = false;
|
||||||
|
|
||||||
|
// test for 'id' and type (CHAR == 0), ignore creator (should be 0x00) and dynamic
|
||||||
|
// 0x0000000013:00:00:87
|
||||||
|
$eid = sprintf('0x%010x:00:', $char_id);
|
||||||
|
$i = 0;
|
||||||
|
while(isset($guild->Members->__Key__[$i])){
|
||||||
|
$key = $guild->Members->__Key__[$i];
|
||||||
|
$pos = strpos((string)$key['value'], $eid);
|
||||||
|
if($pos === 1){
|
||||||
|
$val = $guild->Members->__Val__[$i];
|
||||||
|
$result = array(
|
||||||
|
'grade' => (string) $val->Members->Grade['value'],
|
||||||
|
'joined' => (int) $val->Members->EnterTime['value'],
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
unset($guild);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// shortcut for 'isset() ? .. : ..'
|
||||||
|
function is(&$var, $default = null){
|
||||||
|
return isset($var) ? $var : $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
// escape string so it's safe for HTML
|
||||||
|
function h($str){
|
||||||
|
return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
|
||||||
|
}
|
||||||
|
|
||||||
|
// return $_GET[var] or $_POST[var] or $default
|
||||||
|
function ryzom_get_param($var, $default=''){
|
||||||
|
return is($_GET[$var], is($_POST[$var], $default));
|
||||||
|
}
|
124
code/ryzom/tools/server/www/webig/lib/pdr_util.php
Normal file
124
code/ryzom/tools/server/www/webig/lib/pdr_util.php
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class PdrUtil {
|
||||||
|
/**
|
||||||
|
* Shard seems to be saving guild file every few seconds.
|
||||||
|
* Increase cache valid timer a bit.
|
||||||
|
*
|
||||||
|
* @const int cache expire in seconds
|
||||||
|
*/
|
||||||
|
const CACHE_MIN_TIME = 15;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Where does shard keep it's character, guild files
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_shard_save;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Directory where sheet_id.bin is
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_sheetid_dir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Directory for extracted character, guild xml files
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_unpack_dir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public Constructor for PdrUtil
|
||||||
|
*
|
||||||
|
* @param string $save_path
|
||||||
|
* @param string $unpack temp unpack directory, default is /tmp/
|
||||||
|
*/
|
||||||
|
function __construct($shard_save, $sheetid_dir, $unpack = '/tmp/'){
|
||||||
|
$this->_shard_save = $shard_save;
|
||||||
|
$this->_sheetid_dir = $sheetid_dir;
|
||||||
|
|
||||||
|
$this->_unpack_dir = $unpack;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setShardSaveDirectory($dir){
|
||||||
|
$this->_shard_save = $dir;
|
||||||
|
}
|
||||||
|
function getShardSaveDirectory(){
|
||||||
|
return $this->_shard_save;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSheetIdDirectory($dir){
|
||||||
|
$this->_sheetid_dir = $dir;
|
||||||
|
}
|
||||||
|
function getSheetIdDirectory(){
|
||||||
|
return $this->_sheetid_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setUnpackDirectory($dir){
|
||||||
|
$this->_unpack_dir = $dir;
|
||||||
|
}
|
||||||
|
function getUnpackDirectory(){
|
||||||
|
return $this->_unpack_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract $pdr file to $xml file
|
||||||
|
*
|
||||||
|
* @param string $pdr
|
||||||
|
* @param string $xml
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function extract($pdr, $xml){
|
||||||
|
if(!file_exists($pdr)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdr_mtime = filemtime($pdr);
|
||||||
|
if(file_exists($xml)){
|
||||||
|
$xml_mtime = filemtime($xml);
|
||||||
|
}else{
|
||||||
|
$xml_mtime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$diff = $pdr_mtime - $xml_mtime;
|
||||||
|
if($diff > self::CACHE_MIN_TIME){
|
||||||
|
// remove expired xml file
|
||||||
|
@unlink($xml);
|
||||||
|
|
||||||
|
// change working directory to unpack directory to keep pdr_util log file in one place
|
||||||
|
$pwd = getcwd();
|
||||||
|
chdir($this->_unpack_dir);
|
||||||
|
|
||||||
|
// run pdr_util
|
||||||
|
$cmd = sprintf(' -s%s -x -o%s %s', $this->_sheetid_dir, $xml, $pdr);
|
||||||
|
exec(CMD_PDR_UTIL.' '.$cmd);
|
||||||
|
|
||||||
|
// change working directory back what it was before
|
||||||
|
chdir($pwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if pdr_util failed, then there is no xml file
|
||||||
|
return file_exists($xml);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $fname
|
||||||
|
* @return string ShardSaveDirectory + fname
|
||||||
|
*/
|
||||||
|
function getSaveFileName($fname){
|
||||||
|
return $this->getShardSaveDirectory().'/'.$fname;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $fname
|
||||||
|
* return string TempDirectory + $fname
|
||||||
|
*/
|
||||||
|
function getXmlFileName($fname){
|
||||||
|
return $this->getUnpackDirectory().'/'.$fname;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
46
code/ryzom/tools/server/www/webig/lib/pdr_util_character.php
Normal file
46
code/ryzom/tools/server/www/webig/lib/pdr_util_character.php
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class CharacterPdr extends PdrUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method to create new instance using default path values from config.php
|
||||||
|
*/
|
||||||
|
static public function createDefault(){
|
||||||
|
return new self(SHARD_SAVE, SHEETID_DIR, TEMP_UNPACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load character from shard binary file
|
||||||
|
*
|
||||||
|
* @param int $char_id
|
||||||
|
* @return SimpleXML object or boolean FALSE on error
|
||||||
|
*/
|
||||||
|
function load($char_id){
|
||||||
|
$char_save = $this->getSaveFileName($char_id >> 4, $char_id & 0x0F);
|
||||||
|
$xml_file = $this->getXmlFileName($char_id);
|
||||||
|
|
||||||
|
if($this->extract($char_save, $xml_file)){
|
||||||
|
return simplexml_load_file($xml_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract failed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $uid user id
|
||||||
|
* @param int $slot character slot, starting from 0
|
||||||
|
* @return string character save path + filename
|
||||||
|
*/
|
||||||
|
function getSaveFileName($uid, $slot){
|
||||||
|
return parent::getSaveFileName(sprintf('characters/%03d/account_%d_%d_pdr.bin', $uid, $uid, $slot));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $char_id
|
||||||
|
* return string character xml file in unpack directory
|
||||||
|
*/
|
||||||
|
function getXmlFileName($char_id){
|
||||||
|
return parent::getXmlFileName(sprintf('character_%d.xml', $char_id));
|
||||||
|
}
|
||||||
|
}
|
47
code/ryzom/tools/server/www/webig/lib/pdr_util_guild.php
Normal file
47
code/ryzom/tools/server/www/webig/lib/pdr_util_guild.php
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class GuildPdr extends PdrUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method to create new instance using default path values from config.php
|
||||||
|
*/
|
||||||
|
static public function createDefault(){
|
||||||
|
return new self(SHARD_SAVE, SHEETID_DIR, TEMP_UNPACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load guild info from shard binary file
|
||||||
|
*
|
||||||
|
* @param int $guild_id
|
||||||
|
* @return SimpleXML object or boolean FALSE on error
|
||||||
|
*/
|
||||||
|
function load($guild_id){
|
||||||
|
$guild_save = $this->getSaveFileName($guild_id);
|
||||||
|
$xml_file = $this->getXmlFileName($guild_id);
|
||||||
|
|
||||||
|
if($this->extract($guild_save, $xml_file)){
|
||||||
|
return simplexml_load_file($xml_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract failed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $guild_id
|
||||||
|
* @return string full path to guild binary file
|
||||||
|
*/
|
||||||
|
function getSaveFileName($guild_id){
|
||||||
|
// chop off shard component from guild id
|
||||||
|
return parent::getSaveFileName(sprintf('guilds/guild_%05d.bin', $guild_id & 0xFFFFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $guild_id
|
||||||
|
* return string full path to extracted guild xml file
|
||||||
|
*/
|
||||||
|
function getXmlFileName($guild_id){
|
||||||
|
return parent::getXmlFileName(sprintf('guild_%d.xml', $guild_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue