[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Версия решения задачи
alive
Решил уложить сумбур в голове и выполнить условия задачки twin'a - тут

Какие будут замечания?
Свернутый текст


<?php

//------------------- Устанавливаем кодировку и уровень ошибок -------------------
header("Content-Type: text/html; charset=utf-8");
error_reporting(E_ALL);

//------------------- Подключение к СУБД -------------------
$link = mysql_connect('localhost', 'root', '')
or die("MySQL Error: " . mysql_error());
// Выбираем базу данных
mysql_select_db('names', $link);

//Устанавливаем кодировку UTF8
mysql_query('SET NAMES utf8');
mysql_query('SET CHARACTER SET utf8');
mysql_query('SET COLLATION_CONNECTION = "utf8_general_ci"');

//------------------- Создаем таблицу `names` если ее еще нет -------------------
$sql_crt_tbl = "CREATE TABLE IF NOT EXISTS `names` (
`id` INT( 11 ) NOT NULL AUTO_INCREMENT ,
`date` TIMESTAMP NOT NULL ,
`name` VARCHAR( 250 ) NOT NULL ,
PRIMARY KEY ( `id` ) )"
;

mysql_query($sql_crt_tbl) or die(mysql_error() . "<br/>" . $sql_crt_tbl);

//------------------- Защита от SQL-инъекций -------------------
function escapeString($data)
{
if(is_array($data))
$data = array_map("escapeString", $data);
else
$data = mysql_real_escape_string($data);

return $data;
}

//------------------- Защита от XSS атак -------------------
function stripslashesDeep($data)
{
if(is_array($data))
$data = array_map("stripslashesDeep", $data);
else
$data = stripslashes($data);
return $data;
}

if(get_magic_quotes_gpc())
{
$_GET = stripslashesDeep($_GET);
$_POST = stripslashesDeep($_POST);
}

//------------------- Инициализация переменных -------------------
// кнопки

$ok = !empty($_POST['ok'])?true:false;
$search = !empty($_GET['search'])?true:false;

// на всякий случай
$GET['id'] = !empty($_GET['id']) ? (int)$_GET['id'] : NULL;
$GET['usersearch'] = !empty($_GET['usersearch']) ? $_GET['usersearch'] : '';
$POST['username'] = !empty($_POST['username']) ? $_POST['username'] : '';

//------------------- Регистрация нового юзера -------------------
if(!empty($ok))
{
if(!empty($POST)&&($POST['username'] != ''))
mysql_query("INSERT INTO `names` SET `name` = '"
. escapeString($POST['username']) . "'")
or die(mysql_error());

// защита от F5
header('location: http://'. $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
exit();
}
//------------------- Поиск по имени -------------------
if(!empty($GET['usersearch']))
{
$get_result = mysql_query("SELECT `date`, `name` FROM `names` WHERE `name` LIKE '%"
. escapeString($GET['usersearch']) . "%'")
or die(mysql_error());

if(mysql_num_rows($get_result) > 0)
{
echo "Find <b>" . mysql_num_rows($get_result) . "</b> num_row<ul>";
while($likeness = mysql_fetch_assoc($get_result))
echo "<li> логин: <b>" . htmlspecialchars($likeness['name'])
.
"</b> дата регистрации: <b>" . $likeness['date']
.
"</b></li><br />";
echo "</ul>";
}
else echo " Найдено -<b> 0 </b>- поиск не дал результатов<br />";
}

//------------------- список зарегистрированных -------------------
$get_all_users = mysql_query("SELECT * FROM `names` ORDER BY `date` DESC")
or die(mysql_error());
if(mysql_num_rows($get_all_users) > 0)
{
$quantity_users = mysql_num_rows($get_all_users);
while($users = mysql_fetch_assoc($get_all_users))
echo "<a href=". $_SERVER['PHP_SELF'] . "?id=" . $users['id'] . ">"
. htmlspecialchars($users['name']) . "</a>" . "<br />";
}
else $quantity_users = 0;
echo "<br />Всего <b>" . $quantity_users . " </b> юзерей <br />";

//------------------- выдача по id -------------------
if(!empty($GET['id']))
{
$query = "SELECT * FROM `names` WHERE `id` =" . $GET['id'];
$get_one_user = mysql_query($query)
or die(mysql_error() . "<br/>" . $query);
if(mysql_num_rows($get_one_user) > 0)
while($user = mysql_fetch_assoc($get_one_user))
echo "<br /> юзер <b>" . htmlspecialchars($user['name']) .
" </b> зарегистрирован <b>"
. $user['date'] . "</b><br />";
}
//------------------- end -------------------
?>

<!--------------форма ввода------------------>
<
br />
<
form action="<?PHP echo($_SERVER['PHP_SELF']);?>" method="post"
enctype="multipart/form-data" >
<
b>logining</b>
<
input name="username" type="text" size="20" />
<
input name="ok" type="submit" value = "enter" />
</
form>
<
br />

<!--------------
форма поиска------------------>
<
form action="<?PHP echo($_SERVER['PHP_SELF']);?>" method="get"
enctype="multipart/form-data" >
<
b>search</b>
<
input name="usersearch" type="text" size="20"
value="<?php echo $GET['usersearch']; ?>" />
<
input name="search" type="submit" value = "go!" />
</
form>





Спустя 1 час, 11 минут, 47 секунд (11.10.2011 - 00:45) Winston написал(а):
Цитата (alive @ 10.10.2011 - 23:33)
mysql_query('SET CHARACTER SET utf8'); 
    mysql_query('SET COLLATION_CONNECTION = "utf8_general_ci"');

Сейчас уже достаточно одного запроса с SET NAMES


function stripslashesDeep
Можно переписать так
Свернутый текст
function stripslashesDeep(&$data)     
{
if(get_magic_quotes_gpc())
{
if(is_array($data))
$data = array_map("stripslashesDeep", $data);
else
$data = stripslashes($data);
}
return $data;
}

+ в том, что обработка идет только в том случае, если включены кавычки и благодаря ссылку (&$a) изменения будут применены везде, а не возвратится копия.
При инициализации переменных будет достаточно написать
stripslashesDeep($_GET);
stripslashesDeep($_POST);
stripslashesDeep($_COOKIE); // Если нужно


if(!empty($ok))

Достаточно простого
if($ok)

При регистрации юзера достаточно
Свернутый текст
if($ok && $POST['username'])
{
mysql_query("INSERT INTO `names` SET `name` = '"
. escapeString($POST['username']) . "'")
or die(mysql_error());

// защита от F5
header('location: http://'. $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
exit();
}

Цитата (alive @ 10.10.2011 - 23:33)
mysql_query("SELECT `date`, `name` FROM `names` WHERE `name` LIKE '%"
                    . escapeString($GET['usersearch']) . "%'")

Поиск будет не корректен. Ты попробуй поискать любой из символов % \ ' _
Переписать запрос так
$get_result = mysql_query("SELECT `date`, `name` FROM `names` WHERE `name` LIKE '%"
. addcslashes(escapeString($GET['usersearch']), '%_\\\'') . "%'")
or die(mysql_error());

Пока это то, что заметил..

Спустя 5 минут, 38 секунд (11.10.2011 - 00:50) imbalance_hero написал(а):
alive
Выложил бы где-нибудь :) Мы бы поклацали :)
Смотри, когда в формочку выводишь данные, то обрабатывай через htmlspecialchars;
Когда проверку на mysql_num_rows делаешь, то можно:
if($num = mysql_num_rows($res))
И проверка, и инициализация переменной, не нужно будет внутри условия ещё раз запускать mysql_num_rows.
!empty($POST) - всегда вернёт TRUE, потому что ранее ты уже создал ранее массив с 1 элементом, вне зависимости, пустой или нет.
action в форме пиши: <form action=""> - это само сабой будет ссылка на себя. Форму можно одну, всё равно ты проверяешь в зависимости от нажатой кнопки...

UPDATE:
А вот ещё что недавно увидел, человек вводит в форму и нажимает просто ENTER, и получается, что кнопка submit не была нажата, но данные отправляются, а ты проверяешь, была ли нажата кнопка... в последних своих проектах я уже делаю проверку на данные, а не на нажатие или не нажатие кнопок!

UPDATE2:
Ты зачем то инициализируешь $_POST данные в $ok, $name... зачем? Чтобы создать лишнюю переменную... это пустая работа, её делать не надо, ты же всё равно обращаешься в итоге к данным... Вот, допустим, кнопку проверяем:
if(!empty($_POST['ok'])), и всё, не за чем создавать отдельную переменную $ok, чтобы потом забывать, что это за переменная. Я последнее время вообще стараюсь не инициализировать входящие глобальные переменные, вот так допустим делаю, хотя некоторым может это и не понравиться, личного минуса никакого нет:
$_POST['num'] = ($_POST['num'] + 10)/5;

Спустя 5 минут, 17 секунд (11.10.2011 - 00:55) neadekvat написал(а):
В продолжение темы о проверке кнопок.
Если формы на странице подразумевалась только одна, то следующая проверка удовлетворяет всем необходимым условиям:
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
...
}

Спустя 3 минуты, 12 секунд (11.10.2011 - 00:59) Winston написал(а):
Цитата (imbalance_hero @ 11.10.2011 - 00:50)
Форму можно одну, всё равно ты проверяешь в зависимости от нажатой кнопки

Форма поиска должна отправляться методом GET

Спустя 14 минут, 57 секунд (11.10.2011 - 01:14) imbalance_hero написал(а):
Winston
Не увидел, но раз так, то enctype="multipart/form-data" лишнее, потому что оно не нужно для метода GET.

Спустя 1 минута (11.10.2011 - 01:15) alive написал(а):
Спасибо всем за такие щедрые комментарии! Очень подробно, и понятно теперь. rolleyes.gif

Спустя 10 минут, 46 секунд (11.10.2011 - 01:25) alive написал(а):
Цитата (imbalance_hero @ 11.10.2011 - 01:50)
...Я последнее время вообще стараюсь не инициализировать входящие глобальные переменные, вот так допустим делаю, хотя некоторым может это и не понравиться, личного минуса никакого нет:
$_POST['num'] = ($_POST['num'] + 10)/5;

это вместо:
$POST['num'] = (int)$_POST['num'];
этого?

Цитата (imbalance_hero)
Выложил бы где-нибудь :) Мы бы поклацали :)
да как вспомню о процедуре регистрации для этого.., все откладываю. :D

Спустя 7 минут, 9 секунд (11.10.2011 - 01:32) neadekvat написал(а):
Цитата (imbalance_hero @ 11.10.2011 - 01:50)
и всё, не за чем создавать отдельную переменную $ok, чтобы потом забывать, что это за переменная. Я последнее время вообще стараюсь не инициализировать входящие глобальные переменные, вот так допустим делаю, хотя некоторым может это и не понравиться, личного минуса никакого нет:

Вот. В одной части продвинулся, в другой - деградировал.
Во-первых, не спроста рекомендуется называть переменные также, как названы имена полей. Чтобы не путаться.
Во-вторых, в какой-то момент настанет ситуация, когда тебе нужны чистые данные, пришедшие от пользователя, а они уже безвозвратно засраны модификациями.
С элементами массивов _GET, _POST делать никогда и ничего не надо - они должны сохраняться в первозданном виде.

Спустя 31 минута, 2 секунды (11.10.2011 - 02:04) alive написал(а):
Спасибо, все исправил вроде.
Цитата (neadekvat)
$_SERVER['REQUEST_METHOD']
пока не разобрался как применить, завтра уже смотреть буду.
Цитата (Winston @ 11.10.2011 - 01:45)
+ в том, что обработка идет только в том случае, если включены кавычки
тут понятно
Цитата (Winston @ 11.10.2011 - 01:45)
и благодаря ссылку (&$a) изменения будут применены везде, а не возвратится копия.
тут не понятно, можно подробностей?
Цитата (imbalance_hero)
Ты зачем то инициализируешь $_POST данные в $ok
для поиска сделал по значению в переменной, в принципе согласен, что для формы регистрации тоже можно убрать по событию только нажатой кнопки, то есть если по значению, получается кнопка дублирует ввод entr на клавиатуре?

Спустя 15 минут, 38 секунд (11.10.2011 - 02:19) imbalance_hero написал(а):
neadekvat
Всё зависит от ситуации, и почему "в одном продвинулся"? Я никогда не создавал отдельные переменные smile.gif
Мне нужна переменная в первозданном виде, что может случиться в 1 из миллиона случаев, поэтому в этом ОДНОМ случае я в начале напишу: $main_name = $_POST['name'], и получу данные в первозданном виде, не парясь над тем, что "а вдруг нужно будет когда-нибудь в далёком-далёком будущем".
В ответ я получаю 1 лишнюю переменную в 1/1000 случаев, а не наоборот, во всех 1000 случаев непонятно зачем.
Будет использоваться лишь на 1 странице, пропишу в самой странице, будет на нескольких внутри модуля, пропишу в общей странице модуля, будет по всему сайту, пропишу в странице общей на весь сайт. Банально и просто, и если спустя 5000 строк я увижу $_POST['text'], то я буду знать, что я работаю с $_POST['text'], вне зависимости от всех обработок, которые были совершены ранее.

Спустя 1 час, 49 минут, 7 секунд (11.10.2011 - 04:08) twin написал(а):
Позвольте и мне несколько соображений. :)

1. С кодировками Winston прав, достаточно SET NAMES. Больше того, безопаснее использовать mysql_set_charset(), если позволит версия PHP.

2. Запрос на создание таблицы совершенно лишний. Таблица создается всего один раз, а запрос вешается на каждый запуск скрипта. Ужасно расточительно.

3.
//------------------- Защита от XSS атак ------------------- 
function stripslashesDeep($data)
{
if(is_array($data))
$data = array_map("stripslashesDeep", $data);
else
$data = stripslashes($data);
return $data;
}

if(get_magic_quotes_gpc())
{
$_GET = stripslashesDeep($_GET);
$_POST = stripslashesDeep($_POST);
}

Это вовсе никакая не защита от XSS. Налицо явное недопонимание ситуации. Хотя сделано все верно.

Кстати, neadekvat прав, суперглобальные мссивы модифицировать недопустимо, но это единственный случай, когда их не просто можно, но и нужно обработать. Так как это ошибка разработчика и её желательно исправить. Причем в условиях задачи недвузначно стояло требование самостоятельности скрипта. Многие считают, что "магические кавычки" достаточно отключить в .htaccess, однока отключаются они там флагами. А если PHP стоит как CGI приложение, то такой финт не прокатит. Придется лезть в php.ini, а это дополнительный геморрой, да и не всем юзерам под силу.

И еще, Winston, ссылками не стоит злоупотреблять, был уже горький опыт в PHP4. Кто его знает, что придумают дальше.

4. Инициализация переменных. С кнопками достаточно так:
    $ok       = !empty($_POST['ok']);  
$search = !empty($_GET['search']);
и все верно. Инициализировать их нужно, так как на странице две формы и вариант imbalance_hero с enter не катит. А вот что тут за "всякий случай"
    // на всякий случай
$GET['id'] = !empty($_GET['id']) ? (int)$_GET['id'] : NULL;
$GET['usersearch'] = !empty($_GET['usersearch']) ? $_GET['usersearch'] : '';
$POST['username'] = !empty($_POST['username']) ? $_POST['username'] : '';

не ясно. empty() не удовлетворяет условиям задачи. Попробуй зарегистрировать 0.

5. Вот тут
    if(!empty($ok))
{
if(!empty($POST)&&($POST['username'] != ''))
а) избыточно
б) малофункционально.

Или как предложил Winston (только он сам недотянул)
if($ok && isset($_POST['username']) && $_POST['username'] !=  '')


Winston, ты не прав, так не пойдет:
if($ok && $POST['username'])
, ибо во-первых не удовлетворяет условиям (см. выше), во-вторых нарушает семантику. PHP в этом месте ожидает булево значение, а мы суем черти-чё. И хоть слабая типизация позволяет подобные вольности, это не по джидайски.

А вообще. раз уж так, то можно было извлечь выгоду и сделать махонькою валидацию:
    if($ok)
{
if(isset($_POST['username'])&&($_POST['username'] != ''))
{
mysql_query("INSERT INTO `names` SET `name` = '"
. escapeString($_POST['username']) . "'")
or die(mysql_error());

// защита от F5
header('location: http://'. $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
exit();
}
else
echo 'Введите имя.<br>';
}
тут есть подводный камень с пробелами, в боевых условиях еще trim() желательно сунуть, но в условиях задачи этого не было.

6. С поиском уже указли - он некорректен. Не станет искать % и _

Остальные мелочи уже показали.

Ну и пряники.

Молодец. Очень приятная работа. Как в плане стиля, так и алгоритмов. Ничего лишнего, все к месту. Немного исправить ошибки и будет супер. Вобщем для начала более чем хорошо. Респект.

Спустя 15 часов, 46 минут, 1 секунда (11.10.2011 - 19:54) alive написал(а):
Цитата (twin)
тут есть подводный камень с пробелами, в боевых условиях еще trim() желательно сунуть, но в условиях задачи этого не было.

Ясно теперь. Спасибо за замечания! Исправил. trim() не использовал, потому что эта функция не только крайние пробелы убирает, но и те, что посередине текста. Множественные пробелы заменяет одним, хотя при тесте в PHP ведет себя иначе. Тогда как в базу лезет одним пробелом. С ltrim-rtrim не стал заморачиваться. А что за подводный камень?

Спустя 1 час, 42 минуты, 39 секунд (11.10.2011 - 21:37) imbalance_hero написал(а):
alive
trim только по бокам, в центре не удалял никогда...

Спустя 11 часов, 32 минуты, 42 секунды (12.10.2011 - 09:10) twin написал(а):
Цитата (alive @ 11.10.2011 - 16:54)
Цитата (twin)
тут есть подводный камень с пробелами, в боевых условиях еще trim() желательно сунуть, но в условиях задачи этого не было.

Ясно теперь. Спасибо за замечания! Исправил. trim() не использовал, потому что эта функция не только крайние пробелы убирает, но и те, что посередине текста. Множественные пробелы заменяет одним, хотя при тесте в PHP ведет себя иначе. Тогда как в базу лезет одним пробелом. С ltrim-rtrim не стал заморачиваться. А что за подводный камень?

Внимательней почитай про trim()

А подводный камень такой, что можно регать кучу пробелов. По условиям задачи пробел - исключение. Поэтому нужно было бы использовать эту функцию. Но тут не критично, а в боевых условиях крайне желательно.

Спустя 9 часов, 47 минут, 6 секунд (12.10.2011 - 18:57) alive написал(а):
всё, да ступил. trim() только крайние пробелы убирает, если без доп.параметров. Меня вывод в html смутил, на страницу просто множественные пробелы одним выводит.
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.