« Previous -
Version 2/12
(diff) -
Next » -
Current version
Botanic, 07/18/2012 10:39 pm
DrupalModule¶
Here is the current code and progress on the drupal 7 ryzom core module
done
configurable server options
write user to shard db
write permissions to shard db
create block for login
registration from in game
write user to drupal db
unnecessary
register user form
login form
forgot username/pass links
captcha - use drupal module
todo
cron to fix and sync database if create_user then insert, if get_UId then insert r2 and ryzom_open permissions
password reset hook
disable user hook
delete user hook
menu items that do stuff
limit drupal password to 5-20 chars
limit username to 5-12 chars
<?php
/*
Drupal 7 ryzom core module
Copyright (C) 2012 Matthew Lagoe (Botanic)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
function ryzommanage_admin() {
$form = array();
$form['ryzommanage_serverurl'] = array(
'#type' => 'textfield',
'#title' => t('Server url'),
'#default_value' => variable_get('ryzommanage_serverurl', 'localhost'),
'#description' => t("The url of the ryzom server to integrate with."),
'#required' => TRUE,
);
$form['ryzommanage_mysqlport'] = array(
'#type' => 'textfield',
'#title' => t('Port for MySQL'),
'#size' => 5,
'#maxlength' => 5,
'#default_value' => variable_get('ryzommanage_mysqlport', '3306'),
'#description' => t("The MySQL port of the ryzom server to integrate with."),
'#required' => TRUE,
'#element_validate' => array('_check_port_value'),
);
$form['ryzommanage_dbname'] = array(
'#type' => 'textfield',
'#title' => t('Database Name'),
'#default_value' => variable_get('ryzommanage_dbname', 'nel'),
'#description' => t("The MySQL database name to connect to."),
'#required' => TRUE,
);
$form['ryzommanage_username'] = array(
'#type' => 'textfield',
'#title' => t('MySQL Username'),
'#default_value' => variable_get('ryzommanage_username', 'root'),
'#description' => t("The MySQL username to connect with."),
'#required' => TRUE,
);
$form['ryzommanage_password'] = array(
'#type' => 'password_confirm',
'#title' => t('MySQL Password'),
'#description' => t("Confirm the MySQL password."),
);
return system_settings_form($form);
}
function ryzommanage_menu() {
$items = array();
$items['admin/settings/ryzommanage'] = array(
'title' => 'Ryzom Server Integration',
'description' => 'Ryzom integration information.',
'page callback' => 'drupal_get_form',
'page arguments' => array('ryzommanage_admin'),
'access arguments' => array('administer site configuration'),
'type' => MENU_NORMAL_ITEM,
);
$items['register'] = array(
'title' => 'register',
'page callback' => '_collect_register',
'page arguments' => array(1, 2),
'access callback' => 'user_access',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
return $items;
}
function _check_port_value($element, &$form_state) {
if (!is_numeric(parse_size($element['#value']))) {
form_error($element, t($element['#value'].' is not a valid value for the MySQL port, it must be a valid value. You must choose a number between 1 and 65535.'));
}
}
function ryzommanage_block_info() {
$blocks['ryzommanage_usersblock'] = array(
// info: The name of the block.
'info' => t('Ryzom Manage User Block'),
'status' => TRUE,
'region' => '-1', // Not usually provided.
'visibility' => BLOCK_VISIBILITY_LISTED, // Not usually provided.
);
return $blocks;
}
function ryzommanage_block_view($delta = '') {
$block = array ();
//The $delta parameter tells us which block is being requested.
switch ($delta) {
case 'ryzommanage_usersblock':
$block['subject'] = t("uppercase this please");
$block['content'] = top_bar();
break;
}
return $block;
}
function _collect_register($nids, $collection) {
//if not using blank USER_AGENT redirect to mainpage
if (!isset($_SERVER['HTTP_USER_AGENT'])) {
return_client_httpdata();
exit;
} else {
header("Location: /");
}
}
function return_client_httpdata () {
//check values
$user = checkUser($_POST["Username"]);
$pass = checkPassword($_POST["Password"]);
$cpass = confirmPassword();
$email = checkEmail($_POST["Email"]);
//if all are good then create user
if (($user == "success") and ($pass == "success") and ($cpass == "success") and ($email == "success") and (isset($_POST["TaC"]))) {
$edit = array(
'name' => $_POST["Username"],
'pass' => $_POST["Password"],
'mail' => $_POST["Email"],
'init' => $_POST["Email"],
'unhashpass' => $_POST["Password"],
'status' => 1,
'access' => REQUEST_TIME,
);
user_save(NULL, $edit);
header('Location: email_sent.php');
exit;
} else {
//check if the client is the request
if (!isset($_SERVER['HTTP_USER_AGENT'])) {
echo '
<div class="title">TEMPEST IN THE AETHER REGISTRATION</div>
<div>Welcome! Please fill in the following fields to get your new Tempest in the Aether account:</div>
<form name=\'Page1\' method=\'post\' action=\'register\'>
<table>
<tr>
<td width="33%" ';
if ($user != "success") {
echo 'class="error" ';
}
echo 'id="caption-Username" >Desired Username: </td>
<td width="25%" >
<input type=\'text\' name=\'Username\' value="" maxlength="12" onfocus="javascript:showTooltip(\'5-12 lower-case characters and numbers. The login (username) you create here will be your login name. The name of your game characters will be chosen later on.\', this);" /></td>
';
if ($user != "success") {
echo '<td id="comment-Username" class="error" width="42%">'.$user.'</td>';
} else {
'<td width="42%" id="comment-Username" >';
}
echo '</td>
</tr>
<tr>
<td width="33%" ';
if ($pass != "success") {
echo 'class="error" ';
}
echo 'id="caption-Password" >Desired Password: </td>
<td width="25%" ><input type=\'password\' name=\'Password\' value="" maxlength="8" onkeyup="testPassword(document.Page1.Password.value, \'comment-Password\')" onfocus="javascript:showTooltip(\' 5-8 alpha-numerical characters.\', this);" /></td>
';
if ($pass != "success") {
echo '<td id="comment-Password" class="error" width="42%">'.$pass.'</td>';
} else {
'<td width="42%" id="comment-Password" >';
}
echo '
</tr>
<tr>
<td width="33%" ';
if ($cpass != "success") {
echo 'class="error" ';
}
echo 'id="caption-ConfirmPass" >Confirm Password: </td>
<td width="25%" >
<input type=\'password\' name=\'ConfirmPass\' value="" maxlength="8" onfocus="javascript:showTooltip(\'Retype your Password\', this);" />
</td>
';
if ($cpass != "success") {
echo '<td id="comment-ConfirmPass" class="error" width="42%">'.$cpass.'</td>';
} else {
'<td width="42%" id="comment-ConfirmPass" >';
}
echo '
</td>
</tr>
<tr>
<td width="33%" ';
if ($email != "success") {
echo 'class="error" ';
}
echo 'id="caption-Email" >Email Address (to which a confirmation email will be sent):
</td><td width="25%" ><input type=\'text\' name=\'Email\' value="" maxlength="255" onfocus="javascript:showTooltip(\'Please verify that the e-mail address you enter here is valid and will remain valid in the future. It will only be used to manage your Tempest in the Aether account.\', this);" /></td>';
if ($email != "success") {
echo '<td id="comment-Email" class="error" width="42%">'.$email.'</td>';
} else {
'<td width="42%" id="comment-Email" >';
}
echo '</td>
</tr>
<tr><td width="33%" ';
if (!isset($_POST["TaC"])) {
echo 'class="error" ';
}
echo 'colspan=2 ><input type=\'checkbox\' name=\'TaC\' value="1" onfocus="javascript:showTooltip(\'\', this);" /><span id="caption-TaC">YES, I agree to the terms of use</span></td>';
if (!isset($_POST["TaC"])) {
echo '<td id="comment-TaC" class="error" width="42%">You must accept the Terms of Service</td>';
} else {
'<td width="42%" id="comment-TaC" >';
}
echo '</td>
</tr>
</table>
<div style=\'text-align:left; padding-top:0.5em; padding-bottom:0.5em;\'>
<input type=\'submit\' name=\'Submit\' value=\'Continue\' />
</div>
</form>
<div id=signupTooltip style=\'border: 1px inset white;\'></div>
<div id=tooltip-Username>5-12 lower-case characters and numbers. The login (username) you create here will be your login name. The name of your game characters will be chosen later on.</div>
<div id=tooltip-Password>5-8 alpha-numerical characters.</div>
<div id=tooltip-ConfirmPass>Retype your Password</div>
<div id=tooltip-Email>Please verify that the e-mail address you enter here is valid and will remain valid in the future. It will only be used to manage your Tempest in the Aether account.</div>
<div id=tooltip-TaC></div>';
} else {
//return to mainpage if not client
header("Location: /");
}
}
}
function checkUser ($username) {
if (isset($username)) {
if (strlen($username)>12) {
return "Username must be no more than 12 characters.";
} elseif (strlen($username)<5) {
return "Username must be 5 or more characters.";
} elseif (!preg_match('/^[a-z0-9\.]*$/', $username)) {
return "Username can only contain numbers and letters.";
} elseif (db_query("SELECT COUNT(*) FROM {users} WHERE name = :name", array(':name' => $username))->fetchField()) {
return "Username ".$username." is in use.";
} else {
return "success";
}
} else {
return "success";
}
}
function checkPassword ($pass) {
if (isset($pass)) {
if (strlen($pass)>8) {
return "Password must be no more than 8 characters.";
} elseif (strlen($pass)<5) {
return "Password must be more than 5 characters.";
} else {
return "success";
}
}
}
function confirmPassword () {
if (($_POST["Password"]) != ($_POST["ConfirmPass"])) {
return "Passwords do not match.";
} else {
return "success";
}
}
function checkEmail ($email) {
if (isset($email)) {
if (!validEmail($email)) {
return "Email address is not valid.";
} elseif (db_query("SELECT COUNT(*) FROM {users} WHERE mail = :mail", array(':mail' => $email))->fetchField()) {
return "Email is in use.";
} else {
return "success";
}
} else {
return "success";
}
}
function validEmail($email)
{
$isValid = true;
$atIndex = strrpos($email, "@");
if (is_bool($atIndex) && !$atIndex)
{
$isValid = false;
}
else
{
$domain = substr($email, $atIndex+1);
$local = substr($email, 0, $atIndex);
$localLen = strlen($local);
$domainLen = strlen($domain);
if ($localLen < 1 || $localLen > 64)
{
// local part length exceeded
$isValid = false;
}
else if ($domainLen < 1 || $domainLen > 255)
{
// domain part length exceeded
$isValid = false;
}
else if ($local[0] == '.' || $local[$localLen-1] == '.')
{
// local part starts or ends with '.'
$isValid = false;
}
else if (preg_match('/\\.\\./', $local))
{
// local part has two consecutive dots
$isValid = false;
}
else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain))
{
// character not valid in domain part
$isValid = false;
}
else if (preg_match('/\\.\\./', $domain))
{
// domain part has two consecutive dots
$isValid = false;
}
else if
(!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/',
str_replace("\\\\","",$local)))
{
// character not valid in local part unless
// local part is quoted
if (!preg_match('/^"(\\\\"|[^"])+"$/',
str_replace("\\\\","",$local)))
{
$isValid = false;
}
}
if ($isValid && !(checkdnsrr($domain,"MX") || checkdnsrr($domain,"A")))
{
// domain not found in DNS
$isValid = false;
}
}
return $isValid;
}
function generateSALT ($length = 2)
{
// start with a blank salt
$salt = "";
// define possible characters - any character in this string can be
// picked for use in the salt, so if you want to put vowels back in
// or add special characters such as exclamation marks, this is where
// you should do it
$possible = "2346789bcdfghjkmnpqrtvwxyzBCDFGHJKLMNPQRTVWXYZ";
// we refer to the length of $possible a few times, so let's grab it now
$maxlength = strlen($possible);
// check for length overflow and truncate if necessary
if ($length > $maxlength) {
$length = $maxlength;
}
// set up a counter for how many characters are in the salt so far
$i = 0;
// add random characters to $salt until $length is reached
while ($i < $length) {
// pick a random character from the possible ones
$char = substr($possible, mt_rand(0, $maxlength-1), 1);
// have we already used this character in $salt?
if (!strstr($salt, $char)) {
// no, so it's OK to add it onto the end of whatever we've already got...
$salt .= $char;
// ... and increase the counter by one
$i++;
}
}
// done!
return $salt;
}
function createUser ( $login, $pass, $email) {
$salt = generateSALT();
$pass = crypt($pass, $salt);
try {
$hostname = variable_get('ryzommanage_serverurl', 'localhost');
$port = variable_get('ryzommanage_mysqlport', '3306');
$dbname = variable_get('ryzommanage_dbname', 'nel');
$username = variable_get('ryzommanage_username', 'root');
$password = variable_get('ryzommanage_password', '');
$dbh = new PDO ("mysql:host=$hostname;port=$port;dbname=$dbname",$username,$password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e)
{
error_log($e->getMessage());
$nid = db_insert('ryzommanage_querycache')
->fields(array(
"type" => "create_user",
"query" => "INSERT INTO user (Login, Password, Email) VALUES (".$params[0].", ".$params[1].", ".$params[2].");",
))
->execute();
}
_insert_newuser ($dbh, $params = array($login, $pass, $email));
}
function _insert_newuser ($dbh, $params = array()) {
try {
$statement = $dbh->prepare("INSERT INTO user (Login, Password, Email) VALUES (?, ?, ?)");
} catch (Exception $e) {
error_log($dbh->errorInfo());
return false;
}
try {
$statement->execute($params);
} catch (Exception $e) {
$nid = db_insert('ryzommanage_querycache')
->fields(array(
"type" => "create_user",
"query" => "INSERT INTO user (Login, Password, Email) VALUES (".$params[0].", ".$params[1].", ".$params[2].");",
))
->execute();
}
try {
$sth = $dbh->prepare("SELECT UId FROM user WHERE Login='".$params[0]."';");
$sth->execute();
$result = $sth->fetchAll();
foreach($result as $UId)
{
$statement = $dbh->prepare("INSERT INTO permission (UId, ClientApplication, AccessPrivilege) VALUES ('".$UId[UId]."', 'r2', 'OPEN');");
$statement->execute($params);
$statement = $dbh->prepare("INSERT INTO permission (UId, ClientApplication, AccessPrivilege) VALUES ('".$UId[UId]."', 'ryzom_open', 'OPEN');");
$statement->execute($params);
}
} catch (Exception $e) {
$nid = db_insert('ryzommanage_querycache')
->fields(array(
"type" => "get_UId",
"query" => "SELECT UId FROM user WHERE Login='".$params[0]."';",
))
->execute();
}
return true;
}
function login_form($login_form) {
$login_form['#action'] = url(current_path(), array('query' => drupal_get_destination(), 'external' => FALSE));
$login_form['#id'] = 'user-login-form';
$login_form['#validate'] = user_login_default_validators();
$login_form['#submit'][] = 'user_login_submit';
$login_form['name'] = array('#type' => 'textfield',
'#title' => t('Username'),
'#maxlength' => USERNAME_MAX_LENGTH,
'#size' => 15,
'#required' => TRUE,
);
$login_form['pass'] = array('#type' => 'password',
'#title' => t('Password'),
'#maxlength' => 60,
'#size' => 15,
'#required' => TRUE,
);
$items = array();
if (variable_get('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL)) {
$items[] = l(t('Create new account'), 'user/register', array('attributes' => array('title' => t('Create a new user account.'))));
}
$items[] = l(t('Request new password'), 'user/password', array('attributes' => array('title' => t('Request new password via e-mail.'))));
$login_form['links'] = array('#markup' => theme('item_list', array('items' => $items)));
$login_form['remember_me'] = array(
'#type' => 'checkbox',
'#title' => t('Remember Me'),
'#default_value' => 0,
);
$login_form['actions'] = array('#type' => 'actions');
$login_form['actions']['submit'] = array('#type' => 'submit',
'#value' => t('Log in'),
);
return $login_form;
}
function top_bar() {
if (user_is_logged_in()) {
// Logged in user
return "Notepad | Mail | Wiki | Profile | Craft Recipe-Book | Occupations | News/Events | RyzHome";
} else {
return drupal_get_form('login_form');
// Not logged in
}
}
function ryzommanage_user_presave(&$edit, $account, $category) {
createUser($edit[name],$edit[unhashpass],$edit[mail]);
}
?>

