Скрипт форума на PHP своими руками. Часть 3
Мы разобрались с показом главной страницы, отдельного форума и конкретной темы. Теперь займемся пользователями сайта. И первый вопрос, который мы рассмотрим - регистрация нового пользователя. За это отвечают три функции: getAddNewUserForm(), addNewUser() и activateUser(). Рассмотрим их все по порядку.
Функция getAddNewUserForm() возвращает html формы для регистрации нового пользователя:
<?php
// Функция возвращает форму для регистрации нового пользователя на форуме
function getAddNewUserForm()
{
if ( isset( $_SESSION['captcha_keystring'] ) ) unset( $_SESSION['captcha_keystring'] );
$html = '';
// Если при заполнении формы были допущены ошибки
if ( isset( $_SESSION['addNewUserForm'] ) ) {
$info = file_get_contents( './templates/infoMessage.html' );
$info = str_replace( '{infoMessage}', $_SESSION['addNewUserForm']['error'], $info );
$html = $html.$info."n";
$name = htmlspecialchars( $_SESSION['addNewUserForm']['name'] );
$email = htmlspecialchars( $_SESSION['addNewUserForm']['email'] );
$timezone = $_SESSION['addNewUserForm']['timezone'];
$icq = htmlspecialchars( $_SESSION['addNewUserForm']['icq'] );
$url = htmlspecialchars( $_SESSION['addNewUserForm']['url'] );
$about = htmlspecialchars( $_SESSION['addNewUserForm']['about'] );
$signature = htmlspecialchars( $_SESSION['addNewUserForm']['signature'] );
unset( $_SESSION['addNewUserForm'] );
} else {
$name = '';
$email = '';
$timezone = 0;
$icq = '';
$url = '';
$about = '';
$signature = '';
}
// Считываем в переменную файл шаблона, содержащего
// форму для добавления нового пользователя
$tpl = file_get_contents( './templates/addNewUserForm.html' );
$action = $_SERVER['PHP_SELF'].'?action=addNewUser';
$tpl = str_replace( '{action}', $action, $tpl);
$tpl = str_replace( '{name}', $name, $tpl);
$tpl = str_replace( '{email}', $email, $tpl);
$tpl = str_replace( '{icq}', $icq, $tpl);
$tpl = str_replace( '{url}', $url, $tpl);
$tpl = str_replace( '{about}', $about, $tpl);
$tpl = str_replace( '{signature}', $signature, $tpl);
$kcaptcha = './kcaptcha/kc.php?'.session_name().'='.session_id();
$tpl = str_replace( '{kcaptcha}', $kcaptcha, $tpl);
$tpl = str_replace( '{keystring}', '', $tpl);
$options = '';
for ( $i = -12; $i <= 12; $i++ ) {
if ( $i < 1 )
$value = $i.' часов';
else
$value = '+'.$i.' часов';
if ( $i == $timezone )
$options = $options . '<option value="'.$i.'" selected>'.$value.'</option>'."n";
else
$options = $options . '<option value="'.$i.'">'.$value.'</option>'."n";
}
$tpl = str_replace( '{options}', $options, $tpl);
$tpl = str_replace( '{servertime}', date( "d.m.Y H:i:s" ), $tpl );
$html = $html . $tpl;
return $html;
}
?>
Файл шаблона addNewUserForm.html:
<form name="addNewUserForm" action="{action}" method="POST" enctype="multipart/form-data">
<table class="showTable">
<tr>
<th colspan="2">Регистрация</th>
</tr>
<tr>
<td width="40%"><strong>Имя:</strong></td>
<td width="60%"><input type="text" name="name" maxlength="30" value="{name}" /></td>
</tr>
<tr>
<td><strong>Адрес e-mail:</strong></td>
<td><input type="text" name="email" maxlength="60" value="{email}" /></td>
</tr>
<tr>
<td><strong>Пароль:</strong></td>
<td><input type="password" name="password" maxlength="30" value="" /></td>
</tr>
<tr>
<td><strong>Подтвердите пароль:</strong></td>
<td><input type="password" name="confirm" maxlength="30" value="" /></td>
</tr>
<tr>
<td><strong>Номер в ICQ:</strong></td>
<td><input type="text" name="icq" maxlength="12" value="{icq}" /></td>
</tr>
<tr>
<td><strong>Домашняя страничка:</strong></td>
<td><input type="text" name="url" maxlength="60" value="{url}" /></td>
</tr>
<tr>
<td><strong>Интересы:</strong></td>
<td><textarea name="about" cols="50" rows="3">{about}</textarea></td>
</tr>
<tr>
<td>
<strong>Подпись:</strong><br/>
Это текст, который будет добавлен к размещаемым вами сообщениям.
</td>
<td><textarea name="signature" cols="50" rows="3">{signature}</textarea></td>
</tr>
<tr>
<td> </td>
<td><img src="{kcaptcha}" alt="" /></td>
</tr>
<tr>
<td><strong>Код подтверждения:</strong></td>
<td><input type="text" name="keystring" maxlength="6" value="{keystring}" /></td>
</tr>
<tr>
<td>
<strong>Коррекция временных зон:</strong><br/>
Введите необходимую разницу в часах относительно времени на форуме, и все время будет отображаться с учетом
разницы в вашей временной зоне.
</td>
<td>
<select name="timezone">
{options}
</select>
Текущее время на сервере: {servertime}
</td>
</tr>
<tr>
<td>
<strong>Аватар:</strong><br/>
Показывает небольшое изображение под информацией о вас в сообщениях.
</td>
<td>
<input type="file" name="avatar" />
</td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" name="submitForm" value="Отправить" /></td>
</tr>
</table>
<form>
Далее в нашем списке - функция addNewUser(), которая добавляет нового пользователя (т.е. новую запись в таблицу TABLE_USERS):
<?php
// Функция добавляет нового пользователя форума (запись в таблице БД TABLE_USERS)
function addNewUser()
{
// Если не переданы данные формы - значит функция была вызвана по ошибке
if ( !isset( $_POST['name'] ) or
!isset( $_POST['password'] ) or
!isset( $_POST['confirm'] ) or
!isset( $_POST['email'] ) or
!isset( $_POST['timezone'] ) or
!isset( $_POST['icq'] ) or
!isset( $_POST['url'] ) or
!isset( $_POST['about'] ) or
!isset( $_POST['signature'] ) or
!isset( $_POST['keystring'] ) or
!isset( $_FILES['avatar'] )
)
{
header( 'Location: '.$_SERVER['PHP_SELF'].'?action=addNewUserForm' );
die();
}
// Обрезаем переменные до длины, указанной в параметре maxlength тега input
$name = substr( $_POST['name'], 0, 30 );
$password = substr( $_POST['password'], 0, 30 );
$confirm = substr( $_POST['confirm'], 0, 30 );
$email = substr( $_POST['email'], 0, 60 );
$icq = substr( $_POST['icq'], 0, 12 );
$url = substr( $_POST['url'], 0, 60 );
$about = substr( $_POST['about'], 0, 1000 );
$signature = substr( $_POST['signature'], 0, 500 );
$keystring = substr( $_POST['keystring'], 0, 6 );
// Обрезаем лишние пробелы
$name = trim( $name );
$password = trim( $password );
$confirm = trim( $confirm );
$email = trim( $email );
$icq = trim( $icq );
$url = trim( $url );
$about = trim( $about );
$signature = trim( $signature );
$keystring = trim( $keystring );
// Проверяем, заполнены ли обязательные поля
$error = '';
if ( empty( $name ) ) $error = $error.'<li>не заполнено поле "Имя"</li>'."n";
if ( empty( $password ) ) $error = $error.'<li>не заполнено поле "Пароль"</li>'."n";
if ( empty( $confirm ) ) $error = $error.'<li>не заполнено поле "Подтвердите пароль"</li>'."n";
if ( empty( $email ) ) $error = $error.'<li>не заполнено поле "Адрес e-mail"</li>'."n";
if ( empty( $keystring ) ) $error = $error.'<li>не заполнено поле "Код"</li>'."n";
// Проверяем, не слишком ли короткий пароль
if ( !empty( $password ) and strlen( $password ) < MIN_PASSWORD_LENGTH )
$error = $error.'<li>длина пароля должна быть не меньше '.MIN_PASSWORD_LENGTH.' символов</li>'."n";
// Проверяем, совпадают ли пароли
if ( !empty( $password ) and !empty( $confirm ) and $password != $confirm )
$error = $error.'<li>не совпадают пароли</li>'."n";
// Проверяем поле "код"
if ( !empty( $keystring ) ) {
// Проверяем поле "код" на недопустимые символы
if ( !ereg( "[23456789abcdeghkmnpqsuvxyz]+", $keystring ) )
$error = $error.'<li>поле "Код" содержит недопустимые символы</li>'."n";
// Проверяем, совпадает ли код с картинки
if ( !isset( $_SESSION['captcha_keystring'] ) or $_SESSION['captcha_keystring'] != $keystring )
$error = $error.'<li>не совпадает код с картинки</li>'."n";
}
unset( $_SESSION['captcha_keystring'] );
// Проверяем поля формы на недопустимые символы
if ( !empty( $name ) and !preg_match( "#^[- _0-9a-zа-я]+$#i", $name ) )
$error = $error.'<li>поле "Имя" содержит недопустимые символы</li>'."n";
if ( !empty( $password ) and !preg_match( "#^[-_0-9a-z]+$#i", $password ) )
$error = $error.'<li>поле "Пароль" содержит недопустимые символы</li>'."n";
if ( !empty( $confirm ) and !preg_match( "#^[-_0-9a-z]+$#i", $confirm ) )
$error = $error.'<li>поле "Подтвердите пароль" содержит недопустимые символы</li>'."n";
if ( !empty( $icq ) and !preg_match( "#^[0-9]+$#", $icq ) )
$error = $error.'<li>поле "ICQ" содержит недопустимые символы</li>'."n";
if ( !empty( $about ) and !preg_match( "#^[-[].;:,?!/)(_"s0-9а-яa-z]+$#i", $about ) )
$error = $error.'<li>поле "Интересы" содержит недопустимые символы</li>'."n";
if ( !empty( $signature ) and !preg_match( "#^[-[].;:,?!/)(_"s0-9а-яa-z]+$#i", $signature ) )
$error = $error.'<li>поле "Подпись" содержит недопустимые символы</li>'."n";
// Проверяем корректность e-mail
if ( !empty( $email ) and !preg_match( "#^[0-9a-z_-.]+@[0-9a-z-.]+.[a-z]{2,6}$#i", $email ) )
$error = $error.'<li>поле "Адрес e-mail" должно соответствовать формату somebody@somewhere.ru</li>'."n";
// Проверяем корректность URL домашней странички
if ( !empty( $url ) and !preg_match( "#^(//)?(www.)?[-0-9a-z]+.[a-z]{2,6}/?$#i", $url ) )
$error = $error.'<li>поле "Домашняя страничка" должно соответствовать формату //www.homepage.ru</li>'."n";
// Выясняем не зарегистрировано ли уже это имя
// Возможно три ситуации, которые необходимо предотвратить:
// 1. Вводится ник, полностью совпадающий с уже существующим
// 2. Вводится уже существующий кирилический ник, в котором
// одна или несколько букв заменены на латинские
// 3. Вводится уже существующий латинский ник, в котором
// одна или несколько букв заменениы на кирилические
// Массив кирилических букв
$rus = array( "А","а","В","Е","е","К","М","Н","О","о","Р","р","С","с","Т","Х","х" );
// Массив латинских букв
$eng = array( "A","a","B","E","e","K","M","H","O","o","P","p","C","c","T","X","x" );
$new_name = preg_replace( "#[^- _0-9a-zа-я]#i", "", $name );
// Заменяем русские буквы латинскими
$eng_new_name = str_replace( $rus, $eng, $new_name );
// Заменяем латинские буквы русскими
$rus_new_name = str_replace( $eng, $rus, $new_name );
// Формируем SQL-запрос
$query = "SELECT * FROM ".TABLE_USERS."
WHERE name LIKE '".mysql_real_escape_string( $new_name )."' OR
name LIKE '".mysql_real_escape_string( $eng_new_name )."' OR
name LIKE '".mysql_real_escape_string( $rus_new_name )."';";
$res = mysql_query( $query );
if ( !$res ) {
$msg = 'Ошибка при регистрации нового пользователя';
$err = 'Ошибка при выполнении запроса: <br/>'.
$query.'<br/>'.mysql_errno().': '.mysql_error().'<br/>'.
'(Файл '. __FILE__ .', строка '. __LINE__ .')';
return showErrorMessage( $msg, $err, true, '' );
}
if ( mysql_num_rows( $res ) > 0 )
$error = $error.'<li>имя "'.$new_name.'" уже зарегистрировано</li>'."n";
if ( !empty( $_FILES['avatar']['name'] ) ) {
$ext = strrchr( $_FILES['avatar']['name'], "." );
$extensions = array( ".jpg", ".gif", ".bmp", ".png" );
if ( !in_array( $ext, $extensions ) )
$error = $error.'<li>недопустимый формат файла аватара</li>'."n";
if ( $_FILES['avatar']['size'] > MAX_AVATAR_SIZE )
$error = $error.'<li>размер файла аватора больше '.(MAX_AVATAR_SIZE/1024).' Кб</li>'."n";
}
$timezone = (int)$_POST['timezone'];
if ( $timezone < -12 or $timezone > 12 ) $timezone = 0;
// Если были допущены ошибки при заполнении формы - перенаправляем посетителя на страницу регистрации
if ( !empty( $error ) ) {
$_SESSION['addNewUserForm'] = array();
$_SESSION['addNewUserForm']['error'] = '<p class="errorMsg">При заполнениии формы были допущены ошибки:</p>'.
"n".'<ul class="errorMsg">'."n".$error.'</ul>'."n";
$_SESSION['addNewUserForm']['name'] = $name;
$_SESSION['addNewUserForm']['email'] = $email;
$_SESSION['addNewUserForm']['timezone'] = $timezone;
$_SESSION['addNewUserForm']['icq'] = $icq;
$_SESSION['addNewUserForm']['url'] = $url;
$_SESSION['addNewUserForm']['about'] = $about;
$_SESSION['addNewUserForm']['signature'] = $signature;
header( 'Location: '.$_SERVER['PHP_SELF'].'?action=addNewUserForm' );
die();
}
if ( !empty( $url ) and substr($url, 0, 7) != '//' ) $url = '//'.$url;
// Уникальный код для активации учетной записи
$code = md5( uniqid( rand(), 1 ) );
// Все поля заполнены правильно - продолжаем регистрацию
$query = "INSERT INTO ".TABLE_USERS."
(
name,
passw,
email,
timezone,
url,
icq,
about,
signature,
photo,
puttime,
last_visit,
themes,
status,
activation
)
VALUES
(
'".mysql_real_escape_string( $name )."',
'".mysql_real_escape_string( md5( $password ) )."',
'".mysql_real_escape_string( $email )."',
".$timezone.",
'".mysql_real_escape_string( $url )."',
'".$icq."',
'".mysql_real_escape_string( $about )."',
'".mysql_real_escape_string( $signature )."',
'',
NOW(),
NOW(),
0,
'user',
'".$code."'
);";
$res = mysql_query( $query );
if ( !$res ) {
$msg = 'Ошибка при регистрации нового пользователя';
$err = 'Ошибка при выполнении запроса: <br/>'.
$query.'<br/>'.mysql_errno().': '.mysql_error().'<br/>'.
'(Файл '. __FILE__ .', строка '. __LINE__ .')';
return showErrorMessage( $msg, $err, true, '' );
}
$id = mysql_insert_id();
if ( !empty( $_FILES['avatar']['name'] ) and
move_uploaded_file ( $_FILES['avatar']['tmp_name'], './photo/'.$id ) ) chmod( './photo/'.$id, 0644 );
// Посылаем письмо пользователю с просьбой активировать учетную запись
$headers = "From: ".$_SERVER['SERVER_NAME']." <".ADMIN_EMAIL.">n";
$headers = $headers."Content-type: text/html; charset="windows-1251"n";
$headers = $headers."Return-path: <".ADMIN_EMAIL.">n";
$message = '<p>Добро пожаловать на форум '.$_SERVER['SERVER_NAME'].'!</p>'."n";
$message = $message.'<p>Пожалуйста сохраните это сообщение. Параметры вашей учётной записи таковы:</p>'."n";
$message = $message.'<p>Логин: '.$name.'<br/>Пароль: '.$password.'</p>'."n";
$message = $message.'<p>Для активации вашей учетной записи перейдите по ссылке:</p>'."n";
$link = '//'.$_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF'].'?action=activateUser&code='.$code;
$message = $message.'<p><a href="'.$link.'">Активировать учетную запись</a></p>'."n";
$message = $message.'<p>Не забывайте свой пароль: он хранится в нашей базе в зашифрованном
виде, и мы не сможем вам его выслать. Если вы всё же забудете пароль, то сможете
запросить новый, который придётся активировать таким же образом, как и вашу
учётную запись.</p>'."n";
$message = $message.'<p>Спасибо за то, что зарегистрировались на нашем форуме.</p>'."n";
$subject = 'Регистрация на форуме '.$_SERVER['SERVER_NAME'];
$subject = '=?koi8-r?B?'.base64_encode(convert_cyr_string($subject, "w","k")).'?=';
mail( $email, $subject, $message, $headers );
$msg = 'На Ваш e-mail выслано письмо с просьбой подтвердить регистрацию.
Чтобы завершить регистрацию и активировать учетную запись, зайдите
по адресу, указанному в письме.';
$html = file_get_contents( './templates/infoMessage.html' );
$html = str_replace( '{infoMessage}', $msg, $html );
return $html;
}
?>
Последняя в нашем списке - функция activateUser(). Как нетрудно догадаться, она активирует учетную запись нового пользователя:
<?php
function activateUser()
{
// Если не передан параметр $code - значит функция вызвана по ошибке
if ( !isset( $_GET['code'] ) ) {
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
// Т.к. код зашифрован с помощью md5, то он представляет собой
// 32-значное шестнадцатеричное число
$code = substr( $_GET['code'], 0, 32 );
$code = preg_replace( "#[^0-9a-f]#i", '', $code );
$query = "SELECT id_author
FROM ".TABLE_USERS."
WHERE activation='".mysql_real_escape_string( $code )."' LIMIT 1";
$res = mysql_query( $query );
if ( !$res ) {
$msg = 'Ошибка при активации учетной записи. Обратитесь к администратору.';
$err = 'Ошибка при выполнении запроса: <br/>'.
$query.'<br/>'.mysql_errno().': '.mysql_error().'<br/>'.
'(Файл '. __FILE__ .', строка '. __LINE__ .')';
return showErrorMessage( $msg, $err, true, '' );
}
if ( mysql_num_rows( $res ) > 0 ) {
$id = mysql_result( $res, 0, 0 );
$query = "UPDATE ".TABLE_USERS."
SET activation='', last_visit=NOW()
WHERE id_author=".$id;
$res = mysql_query( $query );
if ( !$res ) {
$msg = 'Ошибка при активации учетной записи. Обратитесь к администратору.';
$err = 'Ошибка при выполнении запроса: <br/>'.
$query.'<br/>'.mysql_errno().': '.mysql_error().'<br/>'.
'(Файл '. __FILE__ .', строка '. __LINE__ .')';
return showErrorMessage( $msg, $err, true, '' );
}
}
return showInfoMessage( 'Ваша учетная запись активирована.', 'action=loginForum' );
}
?>
Возможно, у вас возник вопрос, а что же это за функция showInfoMessage()? Отвечаю - это небольшая вспомогательная функция. Ее назначение - выдать пользователю информационное сообщение, например "Ваша учетная запись активирована" и сделать редирект на нужную страницу (в случае функции activateUser() - на страницу авторизации). Вот ее исходный код:
<?php
// Вспомогательная функция - после выполнения пользователем каких-либо действий
// выдает информационное сообщение и делает редирект на нужную страницу с задержкой
function showInfoMessage( $message, $queryString )
{
if ( !empty( $queryString ) ) $queryString = '?'.$queryString;
header( 'Refresh: '.REDIRECT_DELAY.'; url='.$_SERVER['PHP_SELF'].$queryString );
$html = file_get_contents( './templates/infoMessage.html' );
$html = str_replace( '{infoMessage}', $message, $html );
return $html;
}
?>
Шаблон infoMessage.html
<table class="showTable">
<tr>
<th>Информация</th>
</tr>
<tr>
<td>
{infoMessage}
</td>
</tr>
</table>
Продолжение следует...
|