diff --git a/example_profile.php b/example_profile.php
deleted file mode 100644
index cbada89..0000000
--- a/example_profile.php
+++ /dev/null
@@ -1,196 +0,0 @@
-<?php
-
-require_once('ryzom_api/ryzom_api.php');
-
-if(isset($_POST['key']) && $_POST['key'] != '') header('Location: ?ckey='.ryzom_encrypt($_POST['key']));
-
-ryzom_ckey_handle();
-
-header('Content-Type:text/html; charset=UTF-8');
-
-echo '
-	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-	<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-	<head>
-	<title>Character Profile</title>
-	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
-	'.ryzom_render_header().'
-	'.ryzom_render_header_www().'
-	</head>
-	<body>
-';
-
-if (isset($_GET['ckey']) && $_GET['ckey'] != '') {
-
-	ryzom_log_start('example_profile');
-
-	// Display the profile
-	$ckey = $_GET['ckey'];
-	$key = ryzom_decrypt($ckey);
-
-	$uid=0;$gid=0;$slot=0;$full=false;
-	if(ryzom_character_valid_key($key, $uid, $slot, $full)) {
-		$xml = ryzom_character_simplexml($key, 'full');
-	} else if(ryzom_guild_valid_key($key, $gid)) {
-		$xml = ryzom_guild_simplexml($key);
-	} else {
-		$xml = ryzom_error('Not valid character or guild key', 'simplexml');
-	}
-	if($xml->getName() == 'error') {
-		$content = '<div class="error">'.$xml.'</div>';
-		$content.= '<hr/><a class="ryzom-ui-button" href="?">back</a>';
-		die(ryzom_render_www(ryzom_render_window('API error', $content)));
-	}
-
-    // Display the profile
-	if((string)$xml->getName()=='character') {
-		$title='Character profile';
-		$content=render_character($xml,$key);
-	} else {
-		$title='Guild profile';
-		$content=render_guild($xml);
-	}
-
-	ryzom_log_end();
-} else {
-	// Display the form to enter the API Key
-	$title = 'Profile';
-	$content = '<form action="" method="post">';
-	$content .= 'Please enter the API Key (guild or character) that you can find on <a href="https://secure.ryzom.com/payment_profile">your profile page</a>:</br>';
-	$content .= '<input type="text" name="key"><br/>';
-	$content .= '<input type="submit" value="Submit" />';
-	$content .= '</form>';
-}
-
-echo ryzom_render_www(ryzom_render_window($title, $content));
-echo '</body></html>';
-
-function render_guild($xml){
-	$content = '<h1>'.$xml->name.'</h1>';
-
-	$content .= '<ul>';
-	$content .= '<li>Created: <b>'.ryzom_time_txt(ryzom_time_array($xml->creation_date, '')).'</b></li>';
-	$content .= '<li>Cult: <b>'.$xml->cult.'</b></li>';
-	$content .= '<li>Civilization: <b>'.$xml->civ.'</b></li>';
-
-	$guild_icon = ryzom_guild_icon_image($xml->icon, 'b');
-	$guild_icon_small = ryzom_guild_icon_image($xml->icon, 's');
-	$content .= "<li>Guild Icon: $guild_icon $guild_icon_small</li>";
-
-	$content .= '</ul>';
-
-	// read the members, then sort them by grade and name
-	$result = $xml->xpath('/guild/members/*');
-	$members=array();
-	$s_gk=array();// multi array sort keys
-	$s_nk=array();
-	$key=0;
-	while(list(,$item)=each($result)) {
-		$members[$key]=array(
-			'joined' => intval($item->joined_date), // joined_date is in server tick (ingame date)
-			'grade'  => (string)$item->grade,
-			'name'   => (string)$item->name,
-			);
-		$s_gk[$key]=memberGrade($members[$key]['grade']);
-		$s_nk[$key]=$members[$key]['name'];
-		$key++;
-	}
-	// sort members by grade, then by name
-	array_multisort($s_gk, SORT_ASC, $s_nk, SORT_ASC, $members);
-	$content .= '<h2>Members:'.count($members).'</h2>';
-	$content .= '<table width="500px" border="1" cellpadding="1" cellspacing="0">';
-	$content .= '<thead><tr><td>Name</td><td>Rank</td><td>Joined</td></thead>';
-	foreach($members as $member) {
-		$content .=
-			'<tr>'.
-			'<td>'.$member['name'].'</td>'.
-			'<td>'.$member['grade'].'</td>'.
-			'<td>'.ryzom_time_txt(ryzom_time_array($member['joined'], '')).'</td>'.
-			'</tr>';
-	}
-	$content .= '</table>';
-
-	$content.= '<hr/><a class="ryzom-ui-button" href="?">Back</a>';
-	return $content;
-}
-
-/**
-  * memberGrade will convert memebr grade string value to int for sorting
-  *
-  * @param string $grade one of 'Leader', 'HighOfficer', 'Officer', 'Member'
-  * @return int
-  */
-function memberGrade($grade) {
-	switch(strtolower($grade)) {
-	case 'leader': return 0;
-	case 'highofficer': return 1;
-	case 'officer': return 2;
-	case 'member':
-	default: return 3;
-	}
-}
-
-function render_character($xml, $key) {
-	$content = '<h1>'.$xml->name.'</h1>';
-	$content .= '<ul>';
-	$content .= '<li>Shard: <b>'.$xml->shard.'</b></li>';
-	$content .= '<li>Race: <b>'.$xml->race.'</b></li>';
-	$gender = $xml->gender;
-	$content .= '<li>Gender: <b>'.($gender=='f'?'Female':'Male').'</b></li>';
-	$title = ryzom_title_txt($xml->titleid, 'en', $gender);
-	$content .= '<li>Title: <b>'.$title.'</b></li>';
-	$content .= '</ul>';
-
-	$content .= '<h2>Hands</h2>';
-	$result = $xml->xpath('/character/hands/*');
-	while(list( , $item) = each($result))
-	{
-		$content .= ryzom_item_icon_image_from_simplexml($item).' ';
-	}
-
-	$content .= '<h2>Equipments</h2>';
-	$result = $xml->xpath('/character/equipments/*');
-	while(list( , $item) = each($result))
-	{
-		$content .= ryzom_item_icon_image_from_simplexml($item).' ';
-	}
-
-	if($xml->guild->name != '') {
-		$content .= '<h2>Guild</h2>';
-		$content .= '<ul>';
-		$content .= '<li>Name: <b>'.$xml->guild->name.'</b></li>';
-		$guild_icon = ryzom_guild_icon_image($xml->guild->icon, 'b');
-		$guild_icon_small = ryzom_guild_icon_image($xml->guild->icon, 's');
-		$content .= "<li>Guild Icon: $guild_icon $guild_icon_small</li>";
-		$content .= '</ul>';
-	} else {
-		$content .= '<h2>No Guild</h2>';
-	}
-
-	// inventories
-
-	$inv_xml = ryzom_character_simplexml($key, 'items');
-
-	if(isset($inv_xml->inventories->bag)) {
-		$content .= '<h2>Bag</h2>';
-		$content .= '<p>(leave the mouse on an item to display its custom text, if any)</p>';
-		$result = $inv_xml->xpath('/items/inventories/bag/*');
-		while(list( , $item) = each($result))
-		{
-			$content .= ryzom_item_icon_image_from_simplexml($item);
-		}
-	}
-
-	if(isset($inv_xml->item_in_store)) {
-		$content .= '<h2>Item in store</h2>';
-		$content .= '<p>(leave the mouse on an item to display its price)</p>';
-		$result = $inv_xml->xpath('/items/item_in_store/*');
-		while(list( , $item) = each($result))
-		{
-			$content .= ryzom_item_icon_image_from_simplexml($item, "Price: ".$item['price']);
-		}
-	}
-
-	$content.= '<hr/><a class="ryzom-ui-button" href="?">Back</a>';
-	return $content;
-}
diff --git a/examples/example_profile.php b/examples/example_profile.php
new file mode 100644
index 0000000..dff8e5a
--- /dev/null
+++ b/examples/example_profile.php
@@ -0,0 +1,196 @@
+<?php
+
+require_once('ryzom_api/ryzom_api.php');
+
+if(!empty($_POST['key'])) header('Location: ?ckey='.ryzom_encrypt($_POST['key']));
+
+ryzom_ckey_handle();
+
+header('Content-Type:text/html; charset=UTF-8');
+
+echo '
+	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+	<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+	<head>
+	<title>Character Profile</title>
+	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+	'.ryzom_render_header().'
+	'.ryzom_render_header_www().'
+	</head>
+	<body>
+';
+
+if (isset($_GET['ckey']) && $_GET['ckey'] != '') {
+
+	ryzom_log_start('example_profile');
+
+	// Display the profile
+	$ckey = $_GET['ckey'];
+	$key = ryzom_decrypt($ckey);
+
+	$uid=0;$gid=0;$slot=0;$full=false;
+	if(ryzom_character_valid_key($key, $uid, $slot, $full)) {
+		$xml = ryzom_character_simplexml($key, 'full');
+	} else if(ryzom_guild_valid_key($key, $gid)) {
+		$xml = ryzom_guild_simplexml($key);
+	} else {
+		$xml = ryzom_error('Not valid character or guild key', 'simplexml');
+	}
+	if($xml->getName() == 'error') {
+		$content = '<div class="error">'.$xml.'</div>';
+		$content.= '<hr/><a class="ryzom-ui-button" href="?">back</a>';
+		die(ryzom_render_www(ryzom_render_window('API error', $content)));
+	}
+
+    // Display the profile
+	if((string)$xml->getName()=='character') {
+		$title='Character profile';
+		$content=render_character($xml,$key);
+	} else {
+		$title='Guild profile';
+		$content=render_guild($xml);
+	}
+
+	ryzom_log_end();
+} else {
+	// Display the form to enter the API Key
+	$title = 'Profile';
+	$content = '<form action="" method="post">';
+	$content .= 'Please enter the API Key (guild or character) that you can find on <a href="https://secure.ryzom.com/payment_profile">your profile page</a>:</br>';
+	$content .= '<input type="text" name="key"><br/>';
+	$content .= '<input type="submit" value="Submit" />';
+	$content .= '</form>';
+}
+
+echo ryzom_render_www(ryzom_render_window($title, $content));
+echo '</body></html>';
+
+function render_guild($xml){
+	$content = '<h1>'.$xml->name.'</h1>';
+
+	$content .= '<ul>';
+	$content .= '<li>Created: <b>'.ryzom_time_txt(ryzom_time_array($xml->creation_date, '')).'</b></li>';
+	$content .= '<li>Cult: <b>'.$xml->cult.'</b></li>';
+	$content .= '<li>Civilization: <b>'.$xml->civ.'</b></li>';
+
+	$guild_icon = ryzom_guild_icon_image($xml->icon, 'b');
+	$guild_icon_small = ryzom_guild_icon_image($xml->icon, 's');
+	$content .= "<li>Guild Icon: $guild_icon $guild_icon_small</li>";
+
+	$content .= '</ul>';
+
+	// read the members, then sort them by grade and name
+	$result = $xml->xpath('/guild/members/*');
+	$members=array();
+	$s_gk=array();// multi array sort keys
+	$s_nk=array();
+	$key=0;
+	while(list(,$item)=each($result)) {
+		$members[$key]=array(
+			'joined' => intval($item->joined_date), // joined_date is in server tick (ingame date)
+			'grade'  => (string)$item->grade,
+			'name'   => (string)$item->name,
+			);
+		$s_gk[$key]=memberGrade($members[$key]['grade']);
+		$s_nk[$key]=$members[$key]['name'];
+		$key++;
+	}
+	// sort members by grade, then by name
+	array_multisort($s_gk, SORT_ASC, $s_nk, SORT_ASC, $members);
+	$content .= '<h2>Members:'.count($members).'</h2>';
+	$content .= '<table width="500px" border="1" cellpadding="1" cellspacing="0">';
+	$content .= '<thead><tr><td>Name</td><td>Rank</td><td>Joined</td></thead>';
+	foreach($members as $member) {
+		$content .=
+			'<tr>'.
+			'<td>'.$member['name'].'</td>'.
+			'<td>'.$member['grade'].'</td>'.
+			'<td>'.ryzom_time_txt(ryzom_time_array($member['joined'], '')).'</td>'.
+			'</tr>';
+	}
+	$content .= '</table>';
+
+	$content.= '<hr/><a class="ryzom-ui-button" href="?">Back</a>';
+	return $content;
+}
+
+/**
+  * memberGrade will convert memebr grade string value to int for sorting
+  *
+  * @param string $grade one of 'Leader', 'HighOfficer', 'Officer', 'Member'
+  * @return int
+  */
+function memberGrade($grade) {
+	switch(strtolower($grade)) {
+	case 'leader': return 0;
+	case 'highofficer': return 1;
+	case 'officer': return 2;
+	case 'member':
+	default: return 3;
+	}
+}
+
+function render_character($xml, $key) {
+	$content = '<h1>'.$xml->name.'</h1>';
+	$content .= '<ul>';
+	$content .= '<li>Shard: <b>'.$xml->shard.'</b></li>';
+	$content .= '<li>Race: <b>'.$xml->race.'</b></li>';
+	$gender = $xml->gender;
+	$content .= '<li>Gender: <b>'.($gender=='f'?'Female':'Male').'</b></li>';
+	$title = ryzom_title_txt($xml->titleid, 'en', $gender);
+	$content .= '<li>Title: <b>'.$title.'</b></li>';
+	$content .= '</ul>';
+
+	$content .= '<h2>Hands</h2>';
+	$result = $xml->xpath('/character/hands/*');
+	while(list( , $item) = each($result))
+	{
+		$content .= ryzom_item_icon_image_from_simplexml($item).' ';
+	}
+
+	$content .= '<h2>Equipments</h2>';
+	$result = $xml->xpath('/character/equipments/*');
+	while(list( , $item) = each($result))
+	{
+		$content .= ryzom_item_icon_image_from_simplexml($item).' ';
+	}
+
+	if($xml->guild->name != '') {
+		$content .= '<h2>Guild</h2>';
+		$content .= '<ul>';
+		$content .= '<li>Name: <b>'.$xml->guild->name.'</b></li>';
+		$guild_icon = ryzom_guild_icon_image($xml->guild->icon, 'b');
+		$guild_icon_small = ryzom_guild_icon_image($xml->guild->icon, 's');
+		$content .= "<li>Guild Icon: $guild_icon $guild_icon_small</li>";
+		$content .= '</ul>';
+	} else {
+		$content .= '<h2>No Guild</h2>';
+	}
+
+	// inventories
+
+	$inv_xml = ryzom_character_simplexml($key, 'items');
+
+	if(isset($inv_xml->inventories->bag)) {
+		$content .= '<h2>Bag</h2>';
+		$content .= '<p>(leave the mouse on an item to display its custom text, if any)</p>';
+		$result = $inv_xml->xpath('/items/inventories/bag/*');
+		while(list( , $item) = each($result))
+		{
+			$content .= ryzom_item_icon_image_from_simplexml($item);
+		}
+	}
+
+	if(isset($inv_xml->item_in_store)) {
+		$content .= '<h2>Item in store</h2>';
+		$content .= '<p>(leave the mouse on an item to display its price)</p>';
+		$result = $inv_xml->xpath('/items/item_in_store/*');
+		while(list( , $item) = each($result))
+		{
+			$content .= ryzom_item_icon_image_from_simplexml($item, "Price: ".$item['price']);
+		}
+	}
+
+	$content.= '<hr/><a class="ryzom-ui-button" href="?">Back</a>';
+	return $content;
+}
diff --git a/render/ryzom_ui.css b/render/ryzom_ui.css
new file mode 100644
index 0000000..bda4dea
--- /dev/null
+++ b/render/ryzom_ui.css
@@ -0,0 +1,183 @@
+/* Copyright (C) 2009 Winch Gate Property Limited
+ *
+ * This file is part of ryzom_api.
+ * ryzom_api is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ryzom_api is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with ryzom_api.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Check ryzom_api/functions_render.php for easy php function to render ryzom layout or use this following html:
+ *
+	<div class="ryzom-ui">
+		<div class="ryzom-ui-tl"><div class="ryzom-ui-tr">
+			<div class="ryzom-ui-t"><!-- title --></div>
+		</div></div>
+		<div class="ryzom-ui-l"><div class="ryzom-ui-r"><div class="ryzom-ui-m">
+			<div class="ryzom-ui-body"><!-- content --></div>
+		</div></div></div>
+		<div class="ryzom-ui-bl"><div class="ryzom-ui-br"><div class="ryzom-ui-b"></div></div></div>
+	</div><!-- .ryzom-ui -->
+ */
+
+.ryzom-ui {
+	color: white;
+	opacity: .95;
+}
+.ryzom-ui input, .ryzom-ui select {
+	border-top: 1px solid #030403;
+	border-right: 1px solid #6e7f57;
+	border-bottom: 1px solid #889e6c;
+	border-left: 1px solid #272d1f;
+	background-color: #37402b;
+	color: #ddd;
+	font-size: 12px;
+	margin: 2px 0 5px 0;
+}
+.ryzom-ui input[type=text] {
+	width: 100%;
+}
+/* input[type=submit] will make IE6 to ignore whole CSS rule, so cant combine this with .ryzom-ui-button below */
+input[type=submit] {
+	border-bottom: 1px solid #030403;
+	border-left: 1px solid #6e7f57;
+	border-top: 1px solid #889e6c;
+	border-right: 1px solid #272d1f;
+	background-color: #435120;
+}
+input.ryzom-ui-button, .ryzom-ui-button {
+	border-bottom: 1px solid #030403;
+	border-left: 1px solid #6e7f57;
+	border-top: 1px solid #889e6c;
+	border-right: 1px solid #272d1f;
+	background-color: #435120;
+}
+a.ryzom-ui-button, a.ryzom-ui-button:visited {
+	color: white;
+	padding: 0 .5em;
+	text-decoration: none;
+}
+a.ryzom-ui-button:hover {
+	background: #536130;
+	color: #ddd;
+}
+/* window without title - just borders */
+.ryzom-ui-tl {
+	background-image: url(skin_tl.gif);
+	background-repeat: no-repeat;
+	background-position: left top;
+	width: 100%; height: 8px;
+}
+.ryzom-ui-tr {
+	background-image: url(skin_tr.gif);
+	background-repeat: no-repeat;
+	background-position: right top;
+	height: 8px;
+}
+.ryzom-ui-t {
+	background-image: url(skin_t.gif);
+	background-repeat: repeat-x;
+	background-position: left top;
+	height: 8px;
+	margin: 0 8px;
+}
+/* window with proper header */
+.ryzom-ui-header .ryzom-ui-tl {
+	margin: 0px 0px;
+	line-height: 32px;
+	background-image: url(skin_header_l.gif);
+	background-repeat: no-repeat;
+	background-position: left top;
+	height: 32px;
+}
+.ryzom-ui-header .ryzom-ui-tr {
+	background-image: url(skin_header_r.gif);
+	background-repeat: no-repeat;
+	background-position: right top;
+	height: 32px;
+}
+.ryzom-ui-header .ryzom-ui-t {
+	background-image: url(skin_header_m.gif);
+	background-repeat: repeat-x;
+	background-position: left top;
+	margin-left: 12px;
+	margin-right: 26px;
+	height: 32px;
+	text-transform: uppercase;
+	color: white;
+}
+/* window body */
+.ryzom-ui-l {
+	background-image: url(skin_l.gif);
+	background-position: left top;
+	background-repeat: repeat-y;
+	width: 100%;
+}
+.ryzom-ui-r {
+	background-image: url(skin_r.gif);
+	background-position: right top;
+	background-repeat: repeat-y;
+	width: 100%;
+}
+.ryzom-ui-m {
+	margin: 0 8px;
+	padding: 8px;
+	background-image: url(skin_blank.png);
+	background-repeat: repeat;
+}
+.ryzom-ui-body {
+	background-image: url(skin_blank_inner.png);
+	background-repeat: repeat;
+	/* leave 5px room after bottom border */
+	margin: 0px 0 5px 0;
+	padding: 10px 10px 5px 10px;
+	border-top: 1px solid #030403;
+	border-right: 1px solid #6e7f57;
+	border-bottom: 1px solid #889e6c;
+	border-left: 1px solid #272d1f;
+}
+/* window bottom border */
+.ryzom-ui-bl {
+	background-image: url(skin_bl.gif);
+	background-repeat: no-repeat;
+	background-position: left top;
+	height: 8px;
+}
+.ryzom-ui-br {
+	background-image: url(skin_br.gif);
+	background-repeat: no-repeat;
+	background-position: right top;
+	height: 8px;
+}
+.ryzom-ui-b {
+	background-image: url(skin_b.gif);
+	background-repeat: repeat-x;
+	background-position: left top;
+	height: 8px;
+	margin: 0 8px;
+}
+.ryzom-ui-notice {
+	margin: 0px;
+	padding: 0px;
+	color: #333;
+	text-align: center;
+}
+a.ryzom-ui-notice, a.ryzom-ui-notice:visited {
+	margin: 0px;
+	padding: 0px;
+	color: #555;
+	padding: 0 .5em;
+	text-decoration: underline;
+}
+a.ryzom-ui-notice:hover {
+	color: grey;
+}
diff --git a/render/skin_b.gif b/render/skin_b.gif
new file mode 100644
index 0000000..0345768
Binary files /dev/null and b/render/skin_b.gif differ
diff --git a/render/skin_bl.gif b/render/skin_bl.gif
new file mode 100644
index 0000000..ae9a663
Binary files /dev/null and b/render/skin_bl.gif differ
diff --git a/render/skin_blank.png b/render/skin_blank.png
new file mode 100644
index 0000000..c13bdcc
Binary files /dev/null and b/render/skin_blank.png differ
diff --git a/render/skin_blank_inner.png b/render/skin_blank_inner.png
new file mode 100644
index 0000000..96cb5d4
Binary files /dev/null and b/render/skin_blank_inner.png differ
diff --git a/render/skin_br.gif b/render/skin_br.gif
new file mode 100644
index 0000000..e74bfcf
Binary files /dev/null and b/render/skin_br.gif differ
diff --git a/render/skin_header_l.gif b/render/skin_header_l.gif
new file mode 100644
index 0000000..7a8a347
Binary files /dev/null and b/render/skin_header_l.gif differ
diff --git a/render/skin_header_m.gif b/render/skin_header_m.gif
new file mode 100644
index 0000000..4257f82
Binary files /dev/null and b/render/skin_header_m.gif differ
diff --git a/render/skin_header_r.gif b/render/skin_header_r.gif
new file mode 100644
index 0000000..eaf7674
Binary files /dev/null and b/render/skin_header_r.gif differ
diff --git a/render/skin_l.gif b/render/skin_l.gif
new file mode 100644
index 0000000..f14527c
Binary files /dev/null and b/render/skin_l.gif differ
diff --git a/render/skin_r.gif b/render/skin_r.gif
new file mode 100644
index 0000000..3f07b2b
Binary files /dev/null and b/render/skin_r.gif differ
diff --git a/render/skin_t.gif b/render/skin_t.gif
new file mode 100644
index 0000000..92a5c9a
Binary files /dev/null and b/render/skin_t.gif differ
diff --git a/render/skin_tl.gif b/render/skin_tl.gif
new file mode 100644
index 0000000..4320081
Binary files /dev/null and b/render/skin_tl.gif differ
diff --git a/render/skin_tr.gif b/render/skin_tr.gif
new file mode 100644
index 0000000..0c72c3d
Binary files /dev/null and b/render/skin_tr.gif differ
diff --git a/ryzom_api/client_functions_character.php b/ryzom_api/client_functions_character.php
index b853411..c012ff2 100644
--- a/ryzom_api/client_functions_character.php
+++ b/ryzom_api/client_functions_character.php
@@ -16,8 +16,18 @@
  * along with ryzom_api.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+function ryzom_character_url($key, $part='') {
+	$params = array('key' => $key) ;
+	if(!empty($part))
+		$params['part'] = $part ;
+
+	return ryzom_url('character.php', $params) ;
+}
+
 function ryzom_character_simplexml($key, $part='') {
-	$url = ryzom_api_base_url()."character.php?key=$key".($part!=''?"&part=$part":'');
+
+	$url = ryzom_character_url($key, $part) ;
+
 	$ch = curl_init();
 	curl_setopt($ch, CURLOPT_URL, $url);
 	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
@@ -28,7 +38,7 @@ function ryzom_character_simplexml($key, $part='') {
 }
 
 function ryzom_character_xmlgz($key, $part='') {
-	return file_get_contents(ryzom_api_base_url()."character.php?key=$key".($part!=''?"&part=$part":''));
+	return file_get_contents(ryzom_character_url($key, $part));
 }
 
 function ryzom_character_valid_key($key, &$uid, &$slot, &$full) {
@@ -40,4 +50,4 @@ function ryzom_character_valid_key($key, &$uid, &$slot, &$full) {
 	return true;
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/ryzom_api/client_functions_guild.php b/ryzom_api/client_functions_guild.php
index c99cfe7..d9e2e79 100644
--- a/ryzom_api/client_functions_guild.php
+++ b/ryzom_api/client_functions_guild.php
@@ -24,8 +24,12 @@ function ryzom_guild_valid_key($key, &$gid) {
 	return true;
 }
 
+function ryzom_guild_url($key) {
+	return $ryzom_url('guild.php', array('key' => $key)) ;
+}
+
 function ryzom_guild_simplexml($key) {
-	$url = ryzom_api_base_url()."guild.php?key=$key";
+	$url = ryzom_guild_url($key) ;
 	$ch = curl_init();
 	curl_setopt($ch, CURLOPT_URL, $url);
 	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
@@ -36,7 +40,7 @@ function ryzom_guild_simplexml($key) {
 }
 
 function ryzom_guild_xmlgz($key) {
-	return file_get_contents(ryzom_api_base_url()."guild.php?key=$key");
+	return file_get_contents(ryzom_guild_url($key)) ;
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/ryzom_api/client_functions_guilds.php b/ryzom_api/client_functions_guilds.php
index 2b1d0c6..2653764 100644
--- a/ryzom_api/client_functions_guilds.php
+++ b/ryzom_api/client_functions_guilds.php
@@ -16,8 +16,12 @@
  * along with ryzom_api.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+function ryzom_guilds_url($shardid) {
+	return ryzom_url('guilds.php', array('shardid', $shardid)) ;
+}
+
 function ryzom_guilds_simplexml($shardid) {
-	$url = ryzom_api_base_url()."guilds.php?shardid=$shardid";
+	$url = ryzom_guild_url($shardid) ;
 	$ch = curl_init();
 	curl_setopt($ch, CURLOPT_URL, $url);
 	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
@@ -28,7 +32,7 @@ function ryzom_guilds_simplexml($shardid) {
 }
 
 function ryzom_guilds_xmlgz($shardid) {
-	return file_get_contents(ryzom_api_base_url()."guilds.php?shardid=$shardid");
+	return file_get_contents(ryzom_guild_url('guilds.php', array('shardid' => $shardid)));
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/ryzom_api/client_functions_status.php b/ryzom_api/client_functions_status.php
index 2ebe72a..fea06dd 100644
--- a/ryzom_api/client_functions_status.php
+++ b/ryzom_api/client_functions_status.php
@@ -16,6 +16,10 @@
  * along with ryzom_api.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+function ryzom_status_url($format) {
+	return ryzom_url('status.php', array('format', $format)) ;
+}
+
 function ryzom_status_array() {
 	$xml = ryzom_status_simplexml();
 	$array = array();
@@ -26,8 +30,8 @@ function ryzom_status_array() {
 }
 
 function ryzom_status_simplexml() {
-	$xml_txt = file_get_contents(ryzom_api_base_url().'status.php?format=xml');
+	$xml_txt = file_get_contents(ryzom_status_url($status)) ;
 	return new SimpleXMLElement($xml_txt);
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/ryzom_api/client_functions_time.php b/ryzom_api/client_functions_time.php
index 2d0a6a7..bed1957 100644
--- a/ryzom_api/client_functions_time.php
+++ b/ryzom_api/client_functions_time.php
@@ -16,9 +16,13 @@
  * along with ryzom_api.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+function ryzom_time_url($shardid) {
+	return ryzom_url('time.php', array('shardid', $shardid)) ;
+}
+
 // return the tick for a specific shard
 function ryzom_time_tick($shardid) {
-	return file_get_contents(ryzom_api_base_url()."time.php?shardid=$shardid");
+	return file_get_contents(ryzom_url($shardid));
 }
 
 /**
@@ -28,4 +32,4 @@ function ryzom_time_xml($rytime) {
 	return ryzom_time_xml_without_cache($rytime);
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/ryzom_api/client_functions_title.php b/ryzom_api/client_functions_title.php
index f01896a..08c5ae1 100644
--- a/ryzom_api/client_functions_title.php
+++ b/ryzom_api/client_functions_title.php
@@ -16,12 +16,24 @@
  * along with ryzom_api.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+function ryzom_title_url($titleid, $langid, $gender, $format) {
+	$params = array
+				( 'titleid' => $titleid
+				, 'langid' => $langid
+				) ;
+
+	if(!empty($gender))
+		$params['gender'] = $gender ;
+
+	return ryzom_url('title.php', $params) ;
+}
+
 function ryzom_title_simplexml($titleid, $langid) {
-	return simplexml_load_string(file_get_contents(ryzom_api_base_url()."title.php?titleid=$titleid&langid=$langid&format=xml"));
+	return simplexml_load_string(file_get_contents(ryzom_title_url($titleid, $langid, null, 'xml'))) ;
 }
 
 function ryzom_title_txt($titleid, $langid, $gender) {
-	return file_get_contents(ryzom_api_base_url()."title.php?titleid=$titleid&langid=$langid&gender=$gender&format=txt");
+	return file_get_contents(ryzom_title_url($titleid, $langid, $gender, 'txt'));
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/ryzom_api/functions_banner.php b/ryzom_api/functions_banner.php
index 87b2a49..29ee88f 100644
--- a/ryzom_api/functions_banner.php
+++ b/ryzom_api/functions_banner.php
@@ -16,12 +16,20 @@
  * along with ryzom_api.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+require_once 'ryzom_url.php' ;
+
 function ryzom_banner_image($ckey, $langid, $width=500) {
 	return '<img src="'.ryzom_banner_url($ckey, $langid, $width).'"/>';
 }
 
 function ryzom_banner_url($ckey, $langid, $width=500) {
-	return ryzom_api_base_url()."banner.php?ckey=$ckey&langid=$langid&w=$width";
+	return ryzom_url
+		( 'banner.php', array
+			( 'ckey' => $ckey
+			, 'langid '=> $langid
+			, 'w' => $width
+			)
+		) ;
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/ryzom_api/functions_common.php b/ryzom_api/functions_common.php
index 864282a..76e08ce 100644
--- a/ryzom_api/functions_common.php
+++ b/ryzom_api/functions_common.php
@@ -38,10 +38,6 @@ function ryzom_ckey_handle($passphrase='') {
 	}
 }
 
-function ryzom_api_base_url() {
-	return 'http://atys.ryzom.com/api/';
-}
-
 function ryzom_display_xml_header() {
 	header('Content-Type: application/xml; charset=UTF-8');
 }
@@ -114,4 +110,4 @@ function ryzom_log($str) {
 	if($ryzom_fn!==false) file_put_contents($ryzom_fn, date("Y-m-d H:i:s") .' '. $_SERVER['REMOTE_ADDR'] .' '. $_SERVER['REQUEST_URI'] ." $str\n", FILE_APPEND);
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/ryzom_api/functions_guild_icon.php b/ryzom_api/functions_guild_icon.php
index f375588..6bd75e8 100644
--- a/ryzom_api/functions_guild_icon.php
+++ b/ryzom_api/functions_guild_icon.php
@@ -21,7 +21,8 @@ function ryzom_guild_icon_image($icon, $size) {
 }
 
 function ryzom_guild_icon_url($icon, $size) {
-	return ryzom_api_base_url()."guild_icon.php?icon=$icon&size=$size";
+	return ryzom_url('guild_icon.php?'
+			, array('icon' => $icon, 'size' => $size)) ;
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/ryzom_api/functions_item_icon.php b/ryzom_api/functions_item_icon.php
index d53affc..3951b84 100644
--- a/ryzom_api/functions_item_icon.php
+++ b/ryzom_api/functions_item_icon.php
@@ -21,7 +21,18 @@ function ryzom_item_icon_image($sheetid, $c=-1, $q=-1, $s=-1, $sap=-1, $destroye
 }
 
 function ryzom_item_icon_url($sheetid, $c=-1, $q=-1, $s=-1, $sap=-1, $destroyed=false) {
-	return ryzom_api_base_url()."item_icon.php?sheetid=$sheetid&c=$c&q=$q&s=$s&sap=$sap".($destroyed?'&destroyed=1':'');
+	$params = array
+		( 'sheetid' => $sheetid
+		, 'c' => $c
+		, 'q' => $q
+		, 's' => $s
+		, 'sap' => $sap 
+		) ;
+
+	if($destroyed)
+		$params['destroyed'] = 1 ;
+
+	return ryzom_url('item_icon.php', $params) ;
 }
 
 function ryzom_item_icon_image_from_simplexml($item, $add_text='') {
@@ -39,4 +50,4 @@ function ryzom_item_icon_image_from_simplexml($item, $add_text='') {
 	return "<img title=\"$text\" src=\"$url\"/> ";
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/ryzom_api/functions_render.php b/ryzom_api/functions_render.php
index 28417b2..3187253 100644
--- a/ryzom_api/functions_render.php
+++ b/ryzom_api/functions_render.php
@@ -18,7 +18,7 @@
 
 // Call this inside the <head> part if you wan to use ryzom_render_window()
 function ryzom_render_header() {
-	return '<link type="text/css" href="ryzom_api/render/ryzom_ui.css" rel="stylesheet" media="all" />';
+	return '<link type="text/css" href="render/ryzom_ui.css" rel="stylesheet" media="all" />';
 }
 
 // Render a Ryzom style window
@@ -68,4 +68,4 @@ function ryzom_render_www($content) {
 	';
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/ryzom_api/render/ryzom_ui.css b/ryzom_api/render/ryzom_ui.css
deleted file mode 100644
index bda4dea..0000000
--- a/ryzom_api/render/ryzom_ui.css
+++ /dev/null
@@ -1,183 +0,0 @@
-/* Copyright (C) 2009 Winch Gate Property Limited
- *
- * This file is part of ryzom_api.
- * ryzom_api is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * ryzom_api is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with ryzom_api.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
- * Check ryzom_api/functions_render.php for easy php function to render ryzom layout or use this following html:
- *
-	<div class="ryzom-ui">
-		<div class="ryzom-ui-tl"><div class="ryzom-ui-tr">
-			<div class="ryzom-ui-t"><!-- title --></div>
-		</div></div>
-		<div class="ryzom-ui-l"><div class="ryzom-ui-r"><div class="ryzom-ui-m">
-			<div class="ryzom-ui-body"><!-- content --></div>
-		</div></div></div>
-		<div class="ryzom-ui-bl"><div class="ryzom-ui-br"><div class="ryzom-ui-b"></div></div></div>
-	</div><!-- .ryzom-ui -->
- */
-
-.ryzom-ui {
-	color: white;
-	opacity: .95;
-}
-.ryzom-ui input, .ryzom-ui select {
-	border-top: 1px solid #030403;
-	border-right: 1px solid #6e7f57;
-	border-bottom: 1px solid #889e6c;
-	border-left: 1px solid #272d1f;
-	background-color: #37402b;
-	color: #ddd;
-	font-size: 12px;
-	margin: 2px 0 5px 0;
-}
-.ryzom-ui input[type=text] {
-	width: 100%;
-}
-/* input[type=submit] will make IE6 to ignore whole CSS rule, so cant combine this with .ryzom-ui-button below */
-input[type=submit] {
-	border-bottom: 1px solid #030403;
-	border-left: 1px solid #6e7f57;
-	border-top: 1px solid #889e6c;
-	border-right: 1px solid #272d1f;
-	background-color: #435120;
-}
-input.ryzom-ui-button, .ryzom-ui-button {
-	border-bottom: 1px solid #030403;
-	border-left: 1px solid #6e7f57;
-	border-top: 1px solid #889e6c;
-	border-right: 1px solid #272d1f;
-	background-color: #435120;
-}
-a.ryzom-ui-button, a.ryzom-ui-button:visited {
-	color: white;
-	padding: 0 .5em;
-	text-decoration: none;
-}
-a.ryzom-ui-button:hover {
-	background: #536130;
-	color: #ddd;
-}
-/* window without title - just borders */
-.ryzom-ui-tl {
-	background-image: url(skin_tl.gif);
-	background-repeat: no-repeat;
-	background-position: left top;
-	width: 100%; height: 8px;
-}
-.ryzom-ui-tr {
-	background-image: url(skin_tr.gif);
-	background-repeat: no-repeat;
-	background-position: right top;
-	height: 8px;
-}
-.ryzom-ui-t {
-	background-image: url(skin_t.gif);
-	background-repeat: repeat-x;
-	background-position: left top;
-	height: 8px;
-	margin: 0 8px;
-}
-/* window with proper header */
-.ryzom-ui-header .ryzom-ui-tl {
-	margin: 0px 0px;
-	line-height: 32px;
-	background-image: url(skin_header_l.gif);
-	background-repeat: no-repeat;
-	background-position: left top;
-	height: 32px;
-}
-.ryzom-ui-header .ryzom-ui-tr {
-	background-image: url(skin_header_r.gif);
-	background-repeat: no-repeat;
-	background-position: right top;
-	height: 32px;
-}
-.ryzom-ui-header .ryzom-ui-t {
-	background-image: url(skin_header_m.gif);
-	background-repeat: repeat-x;
-	background-position: left top;
-	margin-left: 12px;
-	margin-right: 26px;
-	height: 32px;
-	text-transform: uppercase;
-	color: white;
-}
-/* window body */
-.ryzom-ui-l {
-	background-image: url(skin_l.gif);
-	background-position: left top;
-	background-repeat: repeat-y;
-	width: 100%;
-}
-.ryzom-ui-r {
-	background-image: url(skin_r.gif);
-	background-position: right top;
-	background-repeat: repeat-y;
-	width: 100%;
-}
-.ryzom-ui-m {
-	margin: 0 8px;
-	padding: 8px;
-	background-image: url(skin_blank.png);
-	background-repeat: repeat;
-}
-.ryzom-ui-body {
-	background-image: url(skin_blank_inner.png);
-	background-repeat: repeat;
-	/* leave 5px room after bottom border */
-	margin: 0px 0 5px 0;
-	padding: 10px 10px 5px 10px;
-	border-top: 1px solid #030403;
-	border-right: 1px solid #6e7f57;
-	border-bottom: 1px solid #889e6c;
-	border-left: 1px solid #272d1f;
-}
-/* window bottom border */
-.ryzom-ui-bl {
-	background-image: url(skin_bl.gif);
-	background-repeat: no-repeat;
-	background-position: left top;
-	height: 8px;
-}
-.ryzom-ui-br {
-	background-image: url(skin_br.gif);
-	background-repeat: no-repeat;
-	background-position: right top;
-	height: 8px;
-}
-.ryzom-ui-b {
-	background-image: url(skin_b.gif);
-	background-repeat: repeat-x;
-	background-position: left top;
-	height: 8px;
-	margin: 0 8px;
-}
-.ryzom-ui-notice {
-	margin: 0px;
-	padding: 0px;
-	color: #333;
-	text-align: center;
-}
-a.ryzom-ui-notice, a.ryzom-ui-notice:visited {
-	margin: 0px;
-	padding: 0px;
-	color: #555;
-	padding: 0 .5em;
-	text-decoration: underline;
-}
-a.ryzom-ui-notice:hover {
-	color: grey;
-}
diff --git a/ryzom_api/render/skin_b.gif b/ryzom_api/render/skin_b.gif
deleted file mode 100644
index 0345768..0000000
Binary files a/ryzom_api/render/skin_b.gif and /dev/null differ
diff --git a/ryzom_api/render/skin_bl.gif b/ryzom_api/render/skin_bl.gif
deleted file mode 100644
index ae9a663..0000000
Binary files a/ryzom_api/render/skin_bl.gif and /dev/null differ
diff --git a/ryzom_api/render/skin_blank.png b/ryzom_api/render/skin_blank.png
deleted file mode 100644
index c13bdcc..0000000
Binary files a/ryzom_api/render/skin_blank.png and /dev/null differ
diff --git a/ryzom_api/render/skin_blank_inner.png b/ryzom_api/render/skin_blank_inner.png
deleted file mode 100644
index 96cb5d4..0000000
Binary files a/ryzom_api/render/skin_blank_inner.png and /dev/null differ
diff --git a/ryzom_api/render/skin_br.gif b/ryzom_api/render/skin_br.gif
deleted file mode 100644
index e74bfcf..0000000
Binary files a/ryzom_api/render/skin_br.gif and /dev/null differ
diff --git a/ryzom_api/render/skin_header_l.gif b/ryzom_api/render/skin_header_l.gif
deleted file mode 100644
index 7a8a347..0000000
Binary files a/ryzom_api/render/skin_header_l.gif and /dev/null differ
diff --git a/ryzom_api/render/skin_header_m.gif b/ryzom_api/render/skin_header_m.gif
deleted file mode 100644
index 4257f82..0000000
Binary files a/ryzom_api/render/skin_header_m.gif and /dev/null differ
diff --git a/ryzom_api/render/skin_header_r.gif b/ryzom_api/render/skin_header_r.gif
deleted file mode 100644
index eaf7674..0000000
Binary files a/ryzom_api/render/skin_header_r.gif and /dev/null differ
diff --git a/ryzom_api/render/skin_l.gif b/ryzom_api/render/skin_l.gif
deleted file mode 100644
index f14527c..0000000
Binary files a/ryzom_api/render/skin_l.gif and /dev/null differ
diff --git a/ryzom_api/render/skin_r.gif b/ryzom_api/render/skin_r.gif
deleted file mode 100644
index 3f07b2b..0000000
Binary files a/ryzom_api/render/skin_r.gif and /dev/null differ
diff --git a/ryzom_api/render/skin_t.gif b/ryzom_api/render/skin_t.gif
deleted file mode 100644
index 92a5c9a..0000000
Binary files a/ryzom_api/render/skin_t.gif and /dev/null differ
diff --git a/ryzom_api/render/skin_tl.gif b/ryzom_api/render/skin_tl.gif
deleted file mode 100644
index 4320081..0000000
Binary files a/ryzom_api/render/skin_tl.gif and /dev/null differ
diff --git a/ryzom_api/render/skin_tr.gif b/ryzom_api/render/skin_tr.gif
deleted file mode 100644
index 0c72c3d..0000000
Binary files a/ryzom_api/render/skin_tr.gif and /dev/null differ
diff --git a/ryzom_api/ryzom_url.php b/ryzom_api/ryzom_url.php
new file mode 100644
index 0000000..d12181e
--- /dev/null
+++ b/ryzom_api/ryzom_url.php
@@ -0,0 +1,31 @@
+<?php
+/* Copyright (C) 2009 Winch Gate Property Limited
+ *
+ * This file is part of ryzom_api.
+ * ryzom_api is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ryzom_api is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with ryzom_api.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+require_once 'url.php' ;
+
+const RYZOM_HOST = 'atys.ryzom.com' ;
+const RYZOM_PATH = 'api' ;
+
+function ryzom_url($filename, $params)
+{
+	return (string) http_url(RYZOM_HOST, RYZOM_PATH, $filename, $params) ;
+}
+
+
+
+
diff --git a/ryzom_api/url.php b/ryzom_api/url.php
new file mode 100644
index 0000000..788348e
--- /dev/null
+++ b/ryzom_api/url.php
@@ -0,0 +1,75 @@
+<?php
+/* Copyright (C) 2009 Winch Gate Property Limited
+ *
+ * This file is part of ryzom_api.
+ * ryzom_api is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ryzom_api is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with ryzom_api.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ *	Tools to secure URL forging.
+ *	\todo	Secure attributes and check for malformed file or path names.
+ */
+
+function http_url($hostname, $pathname = '', $filename = '', $params = array())
+{
+	$url = new http_url ;
+	$url->hostname = $hostname ;
+	$url->pathname = $pathname ;
+	$url->filename = $filename ;
+	$url->params = $params ;
+
+	return $url ;
+}
+
+class http_url
+{
+	public	$hostname = '' ;
+	public	$pathname = '' ;
+	public	$filename = '' ;
+	public	$params = array() ;
+
+	/*
+	public	function __construct()
+	{
+	}
+	*/
+
+	public	function escape($string)
+	{
+		return urlencode($string) ;
+	}
+
+	public	function __tostring()
+	{
+		$searchpart = array() ;
+		foreach($this->params as $name => $value)
+			$searchpart[] = sprintf
+				( '%s=%s'
+				, $this->escape($name)
+				, $this->escape($value)
+				) ;
+		$searchpart = implode('&', $searchpart) ;
+
+		$string = sprintf
+			( 'http://%s/%s/%s?%s'
+			, $this->hostname
+			, $this->pathname
+			, $this->filename
+			, $searchpart
+			) ;
+
+		return $string ;
+	}
+}
+
