20:39

негодяй и извращенец (С)
Доброго времени суток!
Есть форма, посетители вводят свои ответы, результаты php-скрипт отправляет на почту админа и заносит в mySQL БД.
Вопрос: возможно ли в ту же БД вместе с прочими результатами записывать ip голосующего? Или хотя бы на почту его сбрасывать? Нужно для мониторинга накруток.
Дисклеймер: не программист ни разу, только начинаю разбираться по мере надобности. Сваять работающую форму удалось, а вот попытка найти пример записывающего ip скрипта результатов не дала. Буду благодарен за помощь.

@темы: MySQL, PHP, Вопросы

Комментарии
06.02.2010 в 20:41

мы так воодушевлены, что светимся
Необходимо расширить таблицу дополнительным строковым полем, куда сохранять $_SERVER['REMOTE_ADDR'].
06.02.2010 в 20:48

Sanctus Satanas
Вообще подробнее о том, что есть в массиве $_SERVER — тут.
06.02.2010 в 21:41

Всё будет Кока-Кола.
krystal можно, только почитайте заодно про прозрачные прокси и про то как провайдеры раздают ip. ;) У меня за день 5 раз менялся.
07.02.2010 в 02:26

маленькое щячло
function GetRealIp() {
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip=$_SERVER['HTTP_CLIENT_IP'];
}
elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
}
else {
$ip=$_SERVER['REMOTE_ADDR'];
}
return $ip;
}

Создавай новое пое в таблице и пользуйся на здоровье,)
07.02.2010 в 13:47

негодяй и извращенец (С)
unsigned, большое спасибо! Заработало!
Но возник еще один вопрос. Пока разбирался с ['REMOTE_ADDR'], обнаружил очень много интересного по массивам, решил, что стоит заодно записывать, откуда пришел юзер и какой у него браузер. Вот тут и пошли баги. IP я сохранял простейшим $ip = $_SERVER['REMOTE_ADDR']; с добавлением парамерта ip в $ip = $_SERVER['REMOTE_ADDR']; В таком варианте все работает. Но стоит добавить еще пару параметров:

$ip = $_SERVER['REMOTE_ADDR'];
$from = $_SERVER['HTTP_REFERER'];
$browser = $_SERVER['HTTP_USER_AGENT'];

И соответственно
$query="INSERT IGNORE INTO ... (...ip, from, browser) VALUES (...'$ip', '$from', '$browser')";

- как форма перестает функционировать. Никаких ошибок не выдает, пишет, что информация принята, но в БД пусто. Что я делаю не так?
07.02.2010 в 14:10

негодяй и извращенец (С)
--==SS==--, спасибо, только что увидел ваш ответ, пошел изучать!

Джей Ди, именно поэтому не хочу ставить защиту по айпи - кому надо, все равно обойдут. Информация о том, с каких айпишников отвечали (а также откуда пришли и каким браузером пользуются), вкупе с ответами юзеров вполне может помочь определить накрутки. Имхо, это вернее, чем автоматическая защита по айпи и куки - при условии, что есть желание копаться в результатах вручную, конечно. В данном случае оно есть.

Мохнорыл, спасибо! Эх, в следующий раз буду перезагружать утром дискуссию, сэкономил бы время. А для чего в скрипте 'HTTP_X_FORWARDED_FOR?
07.02.2010 в 16:31

Sanctus Satanas
krystal
HTTP_X_FORWARDED_FOR там для определения IP пользователей, сидящих за неанонимными прокси.
07.02.2010 в 22:03

Sanctus Satanas
$query="INSERT IGNORE INTO ... (...ip, from, browser) VALUES (...'$ip', '$from', '$browser')";
Я бы сначала убедился, что в таблице созданы соответствующие поля.
И ещё. Переменные, которые начинаются с HTTP_, получены PHP из заголовков HTTP-запроса. Эти заголовки явно указываются клиентом и потому могут быть легко подделаны — т.е. в них может быть совершенно произвольная информация, либо они могут отсутствовать вовсе.
Без предварительной обработки их также не следует использовать в SQL-запросе. Очень советую почитать про атаки типа SQL-injection.
По тем же причинам я не рекомендую вообще использовать код Мохнорыл'а: X-Forwarded-For или Client-IP это всего лишь HTTP-заголовки и в них может быть что угодно. Кроме того, они не определены в RFC и совершенно не обязательно, что будут использоваться тем или иным прокси (либо вместо них могут быть совершенно другие с похожим смыслом).
Можно доверять только $_SERVER['REMOTE_ADDR'] — это, по крайней мере, тот IP-адрес, с которого было установлено соединение с сервером.
07.02.2010 в 23:13

негодяй и извращенец (С)
--==SS==--, соответствующие поля созданы, параметры один в один такие же, как у ip, который работает нормально, если не добавлять последние два параметра.
Насчет атаки спасибо, пока буду придерживаться стандартного массива, т.к. с предварительной обработкой мне пока явно рано разбираться, сначала азы освоить.
08.02.2010 в 02:37

Sanctus Satanas
krystal
Можно ещё попробовать заменить from на `from`. А вообще я не совсем понял — у вас в случае ошибки в SQL-запросе что-нибудь должно происходить?
08.02.2010 в 21:51

негодяй и извращенец (С)
--==SS==--, попробовал заменить from на `from`, безрезультатно. Все любопытственнее и любопытственнее: убрал $from и $browser, в таблице их удалил, оставил только ip - форма заработала, но ip теперь не сохраняет.

А вообще я не совсем понял — у вас в случае ошибки в SQL-запросе что-нибудь должно происходить?
Стоит вывод ошибки в случае неудавшегося соединения, пока это все. Не очень представляю, как выводить ошибку в случае некорректной отправки данных.
Вообще структура следующая:



UPD Неверно сохраняется выше строчка с method=post :
<*form action=<?php print(basename($_SERVER["PHP_SELF"]));?> method=post enctype=multipart/form-data>
08.02.2010 в 22:36

Sanctus Satanas
krystal
Ну как бы mysql_query на запросах типа insert возвращает либо true, либо false, если возникла ошибка. А саму ошибку можно получить через mysql_error(). Классический вариант это что-то типа:

09.02.2010 в 14:20

негодяй и извращенец (С)
Включил эту строку к скрипт, ошибку не выдает: все данные, кроме ip, сохраняются в таблицу.
На пробу использовал скрипт, который предложил Мохнорыл - та ж фигня, данные идут во все строки таблицы, кроме ip.
Два вопроса: правильно ли я понимаю, что ip должен упоминаться всего три раза: в строке ip = $_SERVER['REMOTE_ADDR']; и $query="INSERT IGNORE INTO ... (...ip, from, browser) VALUES (...'$ip', '$from', '$browser')"; , больше нигде? И какие параметры должны быть у поля в таблице? Пробовал `ip` VARCHAR( 12 ) и `ip` TEXT( 12 ), с и без NOT NULL , остальные параметры не указаны. Может, у меня тут косяк? Уже не знаю, где еще его искать.
09.02.2010 в 19:29

Sanctus Satanas
krystal
Ну если вы так сильно прячете свой код, то я не знаю, где там конкретно ошибка. )
09.02.2010 в 20:24

негодяй и извращенец (С)
--==SS==--, а я его прячу? -) Вон там, выше, привел, вчерашняя мессага. Я ее только чуть сократил: там очень длинный и совершенно однотипный перечень типа
if (isset($_POST['title1'])) {$title1 = $_POST['title1'];}, и таких 40 штук. Все остальное без изменений. Вот целиком, как сейчас выглядит: narod.ru/disk/17749286000/form.txt.html
В тело сообщения не лезет, слишком длинно.
Отчаялся найти ошибку, написал заново. Работает. Со всеми тремя параметрами, полученными через $_SERVER. В чем была ошибка, буду разбираться после того, как запущу страницу, очень любопытно это выяснить, но хочется уже запустить форму в работу. С ней остался один глюк: после отправки данных загружается снова та же страница. Echo или print исправно выводится после отправки, но под ним сразу же выводится и форма ввода, а это лишнее. Подсказанное поиском <*input type="hidden" name="redirect" value="http://..."> почему-то напрочь игнорируется. Не подскажете?
И в любом случае большое спасибо за вашу помощь!
09.02.2010 в 21:41

Sanctus Satanas
krystal
Вообще когда много копипаста — это не есть хорошо. :)
Например, однотипные конструкции типа if (isset($_post['smth'])) $var = $_post['smth']; лучше оформить в виде функции:
function post_var($name){
return isset($_POST[$name]) ? $_POST[$name] : null;
}

Код сразу сократится до $var = post_var('smth');
Во-вторых, раз имена параметров имеют номер, можно использовать цикл:
for ($i = 1; $i <= 8; $i++){
$name = 'title'.$i;
$$name = post_var($name);
for ($j = 1; $j <= 4; $j++){
$name2 = $name.'-'.$j;
$$name2 = post_var($name2);
}
}

Как нетрудно догадаться, можно аналогичным циклом составить сразу SQL-код. Причём, использовать для этого кучу переменных опять же не требуется.
Точно так же циклом можно выводить сам HTML.
В-третьих, если прямо в HTML записать имена параметров, как title[1], title[2] и т.д., то PHP их преобразует в массив $title с соответствующими ключами.

А страница и должна та же самая загружаться. Если хотите перейти на другую - до вывода какого-либо HTML можно вызвать header('Location: http://www.google.com/'); или, если нужно просто скрыть форму на той же странице, — сделать проверку, отправлены ли данные формы (хотя бы через isset()) и если да, то записать в базу и не показывать форму, или, если нет, — просто показать форму.

Расширенная форма

Редактировать

Подписаться на новые комментарии
Получать уведомления о новых комментариях на E-mail