Спамят битым POST

Вурдалак

Продвинутый новичок
zerkms, OMG, да я сначала написал real, потом исправил — один хрен. Я так пишу, поскольку так советует, во-первых, мануал, во-вторых, так просто как-то удобнее было написать (запрос с SET NAMES тупо длиннее). Давно уже обмусоленная тема, давайте не начинать, суть не в этом.
 

Toxic_Cat

Новичок
Ура, получил я злополучный коммент. Да, в общем там CP-1251 (ANSII, само текстовое поле), а часть UTF-8 (текст кнопки и аналогичные переменные, которые с сайта). Я не знаю как точно определить кодировку, но думаю все верно. file_put_contents(); отлично сохранил разношёрстные данные...

В общем какой тут выход? Брать каждое поле, делать iconv('UTF-8', 'UTF-8//IGNORE', $text); ? И если после этого поле остается пустое, то удалять нафиг... Но это ресурсоемко. А больше вариантов я не вижу. Определять кодировку это тоже костыли, которые работают через раз...

P.S. ну и да, у меня каждый раз MySQL переводится в UTF-8 банальным запросом: "SET NAMES 'utf8'", ибо хостер изначально без этого все хранит с CP1251


Содержимое MySQL:
PHP:
text===The dildo. Ruth worked the prowl. Afterabout <a href= http://site.com/643.html >
Содержимое текстового файла:
PHP:
text===The dildo. Ruth worked the prowl. Afterabout <a href= http://site.com/643.html >********** ***** ******* *******</a>  three minutes, i was supposed to see.|||
Submit===Отправить|||
s===70|||
c===159|||
p===1711|||
name===negwemcinu|||
[email protected]|||
site===http://site.com/529.html|||
quote_button===Цитата|||
spoiler_button===Спойлер|||
bold_button===Жирный|||
ment_date===1304351843|||
ment_ip===200.251.58.190|||
 

fixxxer

К.О.
Партнер клуба
Хостер-фигостер. Это _твоя_ обязанность задать кодировку и клиента, и базы данных, и удостовериться в том, что данные, которые ты шлешь, валидны.

Для проверки, собственно, два варианта, либо iconv (ignore даже ни к чему, можно просто проверять ошибку), либо перевести mysql в strict mode - тогда невалидная строка не обрежется, а будет еррор.

Также фраза "у меня каждый раз MySQL переводится в UTF-8", хотя может быть не совсем корректной формулировкой, но все же наводит на подозрения, что тебе надо ознакомиться с разделом "подробные объяснения" страницы phpfaq.ru/charset
 

zerkms

TDD infected
Команда форума
Вурдалак
Мануал правильно советует, но в этом случае необходимо использовать функцию экранирования real
 

Вурдалак

Продвинутый новичок
zerkms, ну а к чему ты это всё? Ты же прекрасно знаешь, что UTF-8 это не касается.
 

zerkms

TDD infected
Команда форума
Вурдалак
Ы? Вот как раз utf-8 это и касается больше, потому как он многобайтный.
 

Вурдалак

Продвинутый новичок
zerkms, мне казалось, что ты должен быть в курсе таких вещей. real нужен в том случае, если в кодировке возможна последовательность символов, заканчивающаяся на 0x5c (бекслеш). Стандартный механизм экранирования поставит этот 0x5c перед апострофом/кавычкой и MySQL при парсинге может посчитать этот 0x5c за часть символа и не будет считать его служебным символом, а следующий за этим «символом» апостроф/кавычка будет считать служебным и литерал закончится. В UTF-8 по определению такая ситуация невозможна.

http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string

Давно известно, что такой фигней страдают немногие кодировки (некоторые китайские/японские) и UCS-2/UCS-4, как тут недавно упоминали. С ними нужно работать только с real_escape.
 

zerkms

TDD infected
Команда форума
Вурдалак
Я знаю что ascii-safe биты не могут быть частью символа в utf-8, но мало ли.
 

whirlwind

TDD infected, paranoid
Вурдалак или это коллективная галюцинация или кто то из нас ошибается

PHP:
$utf = 'test тест test';
$win = iconv('utf-8', 'windows-1251', $utf) . ' windows encoding';

mysql_connect('localhost', 'root', 'root');
mysql_select_db('test');
$utf_q = sprintf('INSERT INTO utf_table (name) VALUES ("%s")', mysql_escape_string($utf));
$win_q = sprintf('INSERT INTO win_table (name) VALUES ("%s")', mysql_escape_string($win));

mysql_set_charset('utf8');
mysql_query($utf_q);
mysql_query($win_q);
mysql_set_charset('cp1251');
mysql_query($utf_q);
mysql_query($win_q);

PHP:
mysql> select * from win_table;
+-------------------------------------+
| name                                |
+-------------------------------------+
| test ???? test windows encoding     |
| test тест test windows encoding |
+-------------------------------------+
2 rows in set (0.00 sec)

mysql> select * from utf_table;
+------------------------------+
| name                         |
+------------------------------+
| test тест test           |
| test тест test |
+------------------------------+
2 rows in set (0.00 sec)

mysql> \s
--------------
mysql  Ver 14.14 Distrib 5.1.41, for debian-linux-gnu (x86_64) using readline 6.1
Кодировка влияет только на то, как символы будут приведены к серверной кодировке и влияет на порядок сортировки. Никакие данные удалены не будут и пустота там никак появиться не может.
 

Вурдалак

Продвинутый новичок
Вурдалак или это коллективная галюцинация или кто то из нас ошибается
— третьего не дано? Возможно, у нас режимы разные. fixxxer же приводил ссылку. В STRICT_ALL_TABLES просто ошибку выдаст, у меня обрезается, у тебя — пытается считать до конца. Я как-то ничего особо удивительного не вижу. Это так принципиально как MySQL поведёт с левыми данными: обрежет или превратит в вопросики? Мне немного лень в это разбираться, если что нароешь — скажи. Для общего развития.
 

whirlwind

TDD infected, paranoid
Это вопрос более чем принципиальный. Если mysql что то обрезает без моего ведома и без всякого уведомления - это называется повреждение данных. Если база данных повреждает данные (в чем я не уверен) то в топку такую субд. Если ты выдвигаешь такое серьезное утверждение, то будь добр подтвердить его.
 

whirlwind

TDD infected, paranoid
Вурдалак давай выяснять детали. Во первых, каким образом ты смотришь результат? Во вторых, давай посмотрим кодировку сервера и кодировку таблицы.

PS. я 100% уверен что при кодировки utf8 сохраняется все как было передано даже если там был мусор типа копипасты из всяких вордов. За много лет очень частая ситуация - контентщики накопипастят а у нас потом в XML-интерфейсах слеты на невалидных символах.
 

fixxxer

К.О.
Партнер клуба
Ну надо понимать что garbage может быть валидной utf8 последовательностью :)

Если же нет, то в strict mode будет ошибка, а в легаси-режиме - да там что угодно, не включил стрикт - ССЗБ.
 

whirlwind

TDD infected, paranoid
Пока своими глазами не увижу, не поверю. В бинарном виде там все сохраняется, когда на кодировку плевать. Единственная проблема может быть при перекодировании в 7битную кодировку, то есть если установлен latin. И то проверять надо.
 

fixxxer

К.О.
Партнер клуба
Зависит от типа поля и кодировки еще. Ну давай проведем эксперимент :)

У меня все это счастье прекрасно валилось в ерроры, когда в инсерты внезапно попадали строки в 1251 (везде utf8 разумеется - и client, и у поля)
 

Toxic_Cat

Новичок
Может немного отклонюсь от темы, я тут симулировал поведение бота, потому, что он продолжил проходить проверку iconv... итак (для кого-то может показаться нубством, но я только это открыл)...

Базовый код, он возвращает false:
PHP:
	$text1 = iconv('UTF-8', 'WINDOWS-1251', 'привет мир');
	$text2 = iconv('UTF-8', 'UTF-8', 'привет мир');

	$_POST['text'] = $text1 . ' ' . $text2;

	// Проверяем кодировку
	if ( iconv('UTF-8', 'UTF-8', $_POST['text'] ) == false ) {
		echo 'false';
	} else {
		echo 'true';
	}
Возвращает true:
PHP:
	// Проверяем кодировку
	if ( iconv('UTF-8', 'UTF-8', serialize($_POST) ) == false ) {
		echo 'false';
	} else {
		echo 'true';
	}
Возвращает false:
PHP:
	// Проверяем кодировку
	if ( iconv('UTF-8', 'UTF-8', implode(' ', $_POST) ) == false ) {
		echo 'false';
	} else {
		echo 'true';
	}
Возвращает true:
PHP:
    $original = '';
    foreach ( $_POST as $key => $val ) {
        $original .= $key . '===' . $val . "|||\n";
    }

	// Проверяем кодировку
	if ( iconv('UTF-8', 'UTF-8', $original ) == false ) {
		echo 'false';
	} else {
		echo 'true';
	}
 

Single

пилот капсулы
В топике много умных слов но вот я одного понять не могу.
Что мешает принимать только те данные которые соответствуют требованиям? Все остальное - ошибка.
 

whirlwind

TDD infected, paranoid
fixxxer ерроры будут только в тех случаях, в которых iconv выдает при конвертации. Интерфейс к айконву в пыхе есть, так что проверить не составляет труда. Например cp1251 в latin - будет ошибка. Но если муська что то там сохраняет при ошибках, то это проблема около ACID-ная, что само по себе как бы намекает.
 

fixxxer

К.О.
Партнер клуба
ерроры будут только в тех случаях, в которых iconv выдает при конвертации
Именно так. Пример:

~$ echo 'тест тест' | iconv -t cp1251 | iconv -f utf-8 -t utf-8
iconv: (stdin):1:0: cannot convert
Но если муська что то там сохраняет при ошибках, то это проблема около ACID-ная
Ага (без объявленного стрикт мода). И самый прикол в том, что без strict mode это behaviour by design. :) У этого исторические причины. http://habrahabr.ru/blogs/mysql/116922/
 
Сверху