Скрипт форума на PHP своими руками. Часть 4
Итак, продолжаем наш разговор о пользователях сайта. Если пользователь забыл свой пароль, он может получить новый,
заполнив форму, которую формирует функция newPasswordForm():
<?php
// Если пользователь забыл свой пароль, он может получить новый,
// заполнив эту форму (свой логин и e-mail)
function newPasswordForm()
{
$html = '';
if ( isset( $_SESSION['newPasswordForm']['error'] ) ) {
$info = file_get_contents( './templates/infoMessage.html' );
$info = str_replace( '{infoMessage}', $_SESSION['newPasswordForm']['error'], $info );
$html = $html.$info."n";
unset( $_SESSION['newPasswordForm']['error'] );
}
$action = $_SERVER['PHP_SELF'].'?action=sendNewPassword';
$tpl = file_get_contents( './templates/newPasswordForm.html' );
$tpl = str_replace( '{action}', $action, $tpl );
$html = $html . $tpl;
return $html;
}
?>
Обработчик этой формы - функция sendNewPassword() высылает на e-mail пользователя новый пароль.
<?php
// Функция высылает на e-mail пользователя новый пароль
function sendNewPassword()
{
// Если не переданы методом POST логин и e-mail - перенаправляем пользователя
if ( !isset( $_POST['username'] ) or
!isset( $_POST['email'] )
)
{
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
// Обрезаем переменные до длины, указанной в параметре maxlength тега input
$name = substr( $_POST['username'], 0, 30 );
$email = substr( $_POST['email'], 0, 60 );
// Обрезаем лишние пробелы
$name = trim( $name );
$email = trim( $email );
// Проверяем, заполнены ли обязательные поля
$error = "";
if ( empty( $name ) ) $error = $error.'<li>не заполнено поле "Имя"</li>'."n";
if ( empty( $email ) ) $error = $error.'<li>не заполнено поле "Адрес e-mail"</li>'."n";
// Проверяем поля формы на недопустимые символы
if ( !empty( $name ) and !ereg( "[-_[:blank:]0-9a-zA-Zа-яА-Я]+", $name ) )
$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";
// Проверять существование такого пользователя есть смысл только в том
// случае, если поля не пустые и не содержат недопустимых символов
if ( empty( $error ) ) {
$query = "SELECT id_author FROM ".TABLE_USERS."
WHERE name='".mysql_real_escape_string( $name )."'
AND email='".mysql_real_escape_string( $email )."'";
$res = mysql_query( $query );
if ( !$res ) {
$msg = 'Ошибка при создании нового пароля.';
$err = 'Ошибка при выполнении запроса: <br/>'.
$query.'<br/>'.mysql_errno().': '.mysql_error().'<br/>'.
'(Файл '. __FILE__ .', строка '. __LINE__ .')';
return showErrorMessage( $msg, $err, true, 'action=newPasswordForm' );
}
// Если пользователь с таким логином и e-mail существует
if ( mysql_num_rows( $res ) > 0 ) {
// Небольшой код, который читает содержимое директории activate
// и удаляет старые файлы для активации пароля (были созданы более суток назад)
if ( $dir = opendir( './activate' ) ) {
chdir( './activate' );
$tmp = 24*60*60;
while ( false !== ( $file = readdir($dir) ) ) {
if ( is_file( $file ) )
if ( ( time() - filemtime( $file ) ) > $tmp ) unlink( $file );
}
chdir( '..' );
closedir( $dir );
}
// Как происходит процедура восстановления пароля? Пользователь ввел свой логин
// и e-mail, мы проверяем существование такого пользователя в таблице БД. Потом
// генерируем с помощью функции getNewPassword() новый пароль, создаем файл с именем
// md5( $newPassword ) в директории activate. Файл содержит ID пользователя.
// В качестве кода активации выступает хэш пароля - md5( $newPassword ).
// Когда пользователь перейдет по ссылке в письме для активации своего нового пароля,
// мы проверяем наличие в директории activate файла с именем кода активации,
// и если он существует, активируем новый пароль.
$id = mysql_result( $res, 0, 0 );
$newPassword = getNewPassword();
$code = md5( $newPassword );
// file_put_contents( './activate/'.$code, $id );
$fp = fopen( './activate/'.$code, "w" );
fwrite($fp, $id);
fclose($fp);
// Посылаем письмо пользователю с просьбой активировать пароль
$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>Добрый день, '.$name.'!</p>'."n";
$message = $message.'<p>Вы получили это письмо потому, что вы (либо кто-то, выдающий себя
за вас) попросили выслать новый пароль к вашей учётной записи на форуме '.
$_SERVER['SERVER_NAME'].'. Если вы не просили выслать пароль, то не обращайте
внимания на это письмо, если же подобные письма будут продолжать приходить,
обратитесь к администратору форума</p>'."n";
$message = $message.'<p>Прежде чем использовать новый пароль, вы должны его активировать.
Для этого перейдите по ссылке:</p>'."n";
$link = '//'.$_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF'].
'?action=activatePassword&code='.$code;
$message = $message.'<p><a href="'.$link.'">Активировать пароль</a></p>'."n";
$message = $message.'<p>В случае успешной активации вы сможете входить в систему, используя
следующий пароль: '.$newPassword.'</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;
} else {
$error = $error.'<li>неправильный логин или e-mail</li>'."n";
}
}
// Если были допущены ошибки при заполнении формы - перенаправляем посетителя
if ( !empty( $error ) ) {
$_SESSION['newPasswordForm'] = array();
$_SESSION['newPasswordForm']['error'] = '<p class="errorMsg">При заполнениии формы были допущены
ошибки:</p>'."n".'<ul class="errorMsg">'."n".$error.'</ul>'."n";
header( 'Location: '.$_SERVER['PHP_SELF'].'?action=newPasswordForm' );
die();
}
}
?>
Как происходит процедура восстановления пароля? Пользователь вводит свой логин и e-mail, мы проверяем существование такого пользователя в таблице БД. Потом генерируем с помощью функции getNewPassword() новый пароль, создаем файл с именем md5( $newPassword ) в директории activate. Файл содержит ID пользователя. В качестве кода активации выступает хэш пароля - md5( $newPassword ). Когда пользователь перейдет по ссылке в письме для активации своего нового пароля, мы проверяем наличие в директории activate файла с именем кода активации, и если он существует, активируем новый пароль.
<?php
// Активация нового пароля
function activatePassword()
{
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 );
if ( is_file( './activate/'.$code ) and ( ( time() - filemtime('./activate/'.$code) ) < 24*60*60 ) ) {
$file = file( './activate/'.$code );
unlink( './activate/'.$code );
$id_user = (int)trim( $file[0] );
$query = "UPDATE ".TABLE_USERS."
SET passw='".mysql_real_escape_string( $code )."'
WHERE id_author=".$id_user;
$res = mysql_query( $query );
if ( !$res ) {
$msg = 'Ошибка при активации нового пароля. Обратитесь к администратору.';
$err = 'Ошибка при выполнении запроса: <br/>'.
$query.'<br/>'.mysql_errno().': '.mysql_error().'<br/>'.
'(Файл '. __FILE__ .', строка '. __LINE__ .')';
return showErrorMessage( $msg, $err, true, 'action=newPasswordForm' );
}
$message = 'Ваш новый пароль успешно активирован.';
} else {
$message = 'Ошибка при активации нового пароля. Обратитесь к администратору.';
}
$html = file_get_contents( './templates/infoMessage.html' );
$html = str_replace( '{infoMessage}', $message, $html );
return $html;
}
?>
Функция getNewPassword() возвращает случайно сгенерированный пароль:
<?php
// Функция возвращает случайно сгенерированный пароль
function getNewPassword()
{
$length = rand( 10, 30 );
$password = '';
for( $i = 0; $i < $length; $i++ ) {
$range = rand(1, 3);
switch( $range ) {
case 1: $password = $password.chr( rand(48, 57) ); break;
case 2: $password = $password.chr( rand(65, 90) ); break;
case 3: $password = $password.chr( rand(97, 122) ); break;
}
}
return $password;
}
?>
Пользователь должен иметь возможность изменить свои данные - за это отвечают функции getEditUserForm() и updateUser().
<?php
// Функция возвращает html формы для редактирования данных о пользователе
function getEditUserForm()
{
// Если информацию о пользователе пытается редактировать
// не зарегистрированный пользователь
if ( !isset( $_SESSION['user'] ) ) {
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
$html = '';
// Если при заполнении формы были допущены ошибки
if ( isset( $_SESSION['editUserForm'] ) ) {
$info = file_get_contents( './templates/infoMessage.html' );
$info = str_replace( '{infoMessage}', $_SESSION['editUserForm']['error'], $info );
$html = $html.$info."n";
$email = htmlspecialchars( $_SESSION['editUserForm']['email'] );
$timezone = $_SESSION['editUserForm']['timezone'];
$icq = htmlspecialchars( $_SESSION['editUserForm']['icq'] );
$url = htmlspecialchars( $_SESSION['editUserForm']['url'] );
$about = htmlspecialchars( $_SESSION['editUserForm']['about'] );
$signature = htmlspecialchars( $_SESSION['editUserForm']['signature'] );
unset( $_SESSION['editUserForm'] );
} else {
$email = htmlspecialchars( $_SESSION['user']['email'] );
$timezone = 0;
$icq = htmlspecialchars( $_SESSION['user']['icq'] );
$url = htmlspecialchars( $_SESSION['user']['url'] );
$about = htmlspecialchars( $_SESSION['user']['about'] );
$signature = htmlspecialchars( $_SESSION['user']['signature'] );
}
$action = $_SERVER['PHP_SELF'].'?action=updateUser';
$tpl = file_get_contents( './templates/editUserForm.html' );
$tpl = str_replace( '{action}', $action, $tpl );
$tpl = str_replace( '{email}', htmlspecialchars( $email ), $tpl );
$tpl = str_replace( '{icq}', htmlspecialchars( $icq ), $tpl );
$tpl = str_replace( '{url}', htmlspecialchars( $url ), $tpl );
$tpl = str_replace( '{about}', htmlspecialchars( $about ), $tpl );
$tpl = str_replace( '{signature}', htmlspecialchars( $signature ), $tpl );
$options = '';
for ( $i = -12; $i <= 12; $i++ ) {
if ( $i < 1 )
$value = $i.' часов';
else
$value = '+'.$i.' часов';
if ( $i == $_SESSION['user']['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 );
// Если ранее был загружен файл - надо предоставить возможность удалить его
$unlinkfile = '';
if ( is_file( './photo/'.$_SESSION['user']['id_author'] ) ) {
$unlinkfile = '<br/><input type="checkbox" name="unlink" value="1" />
Удалить загруженный ранее файл'."n";
}
$tpl = str_replace( '{unlinkfile}', $unlinkfile, $tpl );
$html = $html.$tpl;
return $html;
}
?>
Обработчик формы:
<?php
// Функция обновляет данные пользователя (обновляет запись в таблице TABLE_USERS)
function updateUser()
{
// Если это не зарегистрированный пользователь - функция вызвана по ошибке
if ( !isset( $_SESSION['user'] ) ) {
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
// Если не переданы данные формы - функция вызвана по ошибке
if ( !isset( $_POST['timezone'] ) or
!isset( $_POST['icq'] ) or
!isset( $_POST['url'] ) or
!isset( $_POST['about'] ) or
!isset( $_POST['signature'] ) or
!isset( $_FILES['avatar'] )
)
{
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
// Обрезаем переменные до длины, указанной в параметре maxlength тега input
$password = substr( $_POST['password'], 0, 30 );
$newpassword = substr( $_POST['newpassword'], 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 );
// Обрезаем лишние пробелы
$password = trim( $password );
$newpassword = trim( $newpassword );
$confirm = trim( $confirm );
$email = trim( $email );
$icq = trim( $icq );
$url = trim( $url );
$about = trim( $about );
$signature = trim( $signature );
// Проверяем, заполнены ли обязательные поля
$error = '';
// Если заполнено поле "Текущий пароль" - значит пользователь
// хочет изменить его или поменять свой e-mail
$changePassword = false;
$changeEmail = false;
if ( !empty( $_POST['password'] ) ) {
if ( md5( $_POST['password'] ) != $_SESSION['user']['passw'] )
$error = $error.'<li>текущий пароль введен не верно</li>'."n";
// Надо выяснить, что хочет сделать пользователь:
// поменять свой e-mail, изменить пароль или и то и другое
if ( !empty( $newpassword ) ) { // хочет изменить пароль
$changePassword = true;
if ( empty( $confirm ) ) $error = $error.'<li>не заполнено поле "Подтвердите пароль"</li>'."n";
// Проверяем, не слишком ли короткий новый пароль
if ( strlen( $newpassword ) < MIN_PASSWORD_LENGTH )
$error = $error.'<li>длина пароля должна быть не меньше '.MIN_PASSWORD_LENGTH.' символов</li>'."n";
// Проверяем, совпадают ли пароли
if ( !empty( $confirm ) and $newpassword != $confirm )
$error = $error.'<li>не совпадают пароли</li>'."n";
// Проверяем поля формы на недопустимые символы
if ( !preg_match( "#^[-_0-9a-z]+$#i", $newpassword ) )
$error = $error.'<li>поле "Новый пароль" содержит недопустимые символы</li>'."n";
if ( !empty( $confirm ) and !preg_match( "#^[-_0-9a-z]+$#i", $confirm ) )
$error = $error.'<li>поле "Подтвердите пароль" содержит недопустимые символы</li>'."n";
}
if ( $email != $_SESSION['user']['email'] ) { // хочет изменить e-mail
$changeEmail = true;
if ( empty( $email ) ) $error = $error.'<li>не заполнено поле "Адрес e-mail"</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";
}
}
// Проверяем поля формы на недопустимые символы
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";
// Проверяем корректность 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";
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['editUserForm'] = array();
$_SESSION['editUserForm']['error'] = '<p class="errorMsg">При заполнениии формы были допущены ошибки:</p>'.
"n".'<ul class="errorMsg">'."n".$error.'</ul>'."n";
$_SESSION['editUserForm']['email'] = $email;
$_SESSION['editUserForm']['timezone'] = $timezone;
$_SESSION['editUserForm']['icq'] = $icq;
$_SESSION['editUserForm']['url'] = $url;
$_SESSION['editUserForm']['about'] = $about;
$_SESSION['editUserForm']['signature'] = $signature;
header( 'Location: '.$_SERVER['PHP_SELF'].'?action=editUserForm' );
die();
}
// Если выставлен флажок "Удалить загруженный ранее файл"
if ( isset( $_POST['unlink'] ) and is_file( './photo/'.$_SESSION['user']['id_author'] ) ) {
unlink( './photo/'.$_SESSION['user']['id_author'] );
}
if ( !empty( $_FILES['avatar']['name'] ) and
move_uploaded_file ( $_FILES['avatar']['tmp_name'], './photo/'.$_SESSION['user']['id_author'] ) ) {
chmod( './photo/'.$_SESSION['user']['id_author'], 0644 );
}
// Все поля заполнены правильно - записываем изменения в БД
$tmp = '';
if ( $changePassword ) {
$tmp = $tmp."passw='".mysql_real_escape_string( md5( $newpassword ) )."', ";
$_SESSION['user']['passw'] = md5( $newpassword );
}
if ( $changeEmail ) {
$tmp = $tmp."email='".mysql_real_escape_string( $email )."', ";
$_SESSION['user']['email'] = $email;
}
$query = "UPDATE ".TABLE_USERS." SET ".$tmp."
timezone=".$timezone.",
url='".mysql_real_escape_string( $url )."',
icq='".$icq."',
about='".mysql_real_escape_string( $about )."',
signature='".mysql_real_escape_string( $signature )."'
WHERE id_author=".$_SESSION['user']['id_author'];
//echo $query;
//die();
$res = mysql_query( $query );
if ( !$res ) {
$msg = 'Ошибка при обновлении профиля';
$err = 'Ошибка при выполнении запроса: <br/>'.
$query.'<br/>'.mysql_errno().': '.mysql_error().'<br/>'.
'(Файл '. __FILE__ .', строка '. __LINE__ .')';
return showErrorMessage( $msg, $err, true, '' );
}
// Теперь надо обновить данные о пользователе в массиве $_SESSION['user']
if ( $changePassword ) $_SESSION['user']['passw'] = md5( $newpassword );
if ( $changeEmail ) $_SESSION['user']['email'] = $email;
$_SESSION['user']['timezone'] = $timezone;
$_SESSION['user']['url'] = $url;
$_SESSION['user']['icq'] = $icq;
$_SESSION['user']['about'] = $about;
$_SESSION['user']['signature'] = $signature;
// ... и в массиве $_COOKIES
if ( isset( $_COOKIE['autologin'] ) ) {
$tmppos = strrpos( $_SERVER['PHP_SELF'], '/' ) + 1;
$path = substr( $_SERVER['PHP_SELF'], 0, $tmppos );
setcookie( 'autologin', 'yes', time() + 3600*24*COOKIE_TIME, $path );
setcookie( 'username', $_SESSION['user']['name'], time() + 3600*24*COOKIE_TIME, $path );
setcookie( 'password', $_SESSION['user']['passw'], time() + 3600*24*COOKIE_TIME, $path );
}
return showInfoMessage( 'Ваш профиль был изменён', '' );
}
?>
Продолжение следует...
Если вы хотите в казино Фараон запускать видеослоты и зарабатывать реальные деньги, не стоит торопиться. Получить максимум информации про игровые автоматы казино Фараон доступно на популярном сайте Casinozforum. Обязательно воспользуйтесь важными сведениями, которыми владеют постоянные посетители ресурса, они помогут сохранить депозит и отлично провести время.
|