Detecting russian characters on a form in PHP
I have a site where people can submit links to sites about iPhone apps. The guy submits the application name, description, category and URL. This site has years and never received any constructive submission from a russian developer but, unfortunately it was discovered by russian spammers that annoys the hell out of me. Even with all measures against spam, as caption boxes, etc., some guys insist on sending porn russian stuff that has nothing to do with iPhone. I would like to ban completely any URL or post that is done using russian characters. For URLs I have not much to do, except checking if the URL contains «.ru». But for descriptions, I would like to detect russian characters. How do I do that in PHP? thanks.
7 Answers 7
Да очень просто It is easy to do with UTF-8 regular expressions (assuming your site uses UTF-8 encoding):
I tested all 3 methods. Yours is the one that works in my case. And I see by your name, that you are probably from there! 🙂 Thanks.
Thanks. I also found it useful to do preg_match_all and count the number of Russian characters, and use that to get a percentage. Kind of quasi-Bayesian.
That works perfectly, thanks. We already stop form submissions using a list of «ever growing» stop words, but suddenly we have been hit with dozens of junk emails containing Russian characters. This is short, sweet and works 100%!
According to the PHP documentation, since version 5.1.0 it has been possible to look for specific (writing) scripts in utf-8 PCRE regular expressions by using \p. For Rusian that is
There is a warning on the page:
Matching characters by Unicode property is not fast, because PCRE has to search a structure that contains data for over fifteen thousand characters.
Thanks. Very interesting reference to PCRE/REGEX/UNICODE documentation. This answer has been the most useful for me.
now.. this code is about 5 years old, and ‘worked for me’ back when I had a similar problem
function detect_cyr_utf8($content) < return preg_match('/
[78]\d/', mb_encode_numericentity($content, array(0x0, 0x2FFFF, 0, 0xFFFF), 'UTF-8')); >
thus no warranty, no any of the kind — but it may help you out (basically it encodes all foreign entities then checks for common cyrillic chars)
I would download the Russian alphabet and then check the input string with strstr() . For example:
$russianChars = array('з', 'я'.. etc); foreach($russianChars as $char) < if(strstr($input, $char)) < // russian char found in input, do something >>
A good algorithm would probably do something after finding 3 Russian chars or so, to be sure that the language is actually Russian (since Russian chars may show up in other languages, I suggest doing some research if that’s the case).
function ru2lat($str) < $tr = array( "А"=>"a", "Б"=>"b", "В"=>"v", "Г"=>"g", "Д"=>"d", "Е"=>"e", "Ё"=>"yo", "Ж"=>"zh", "З"=>"z", "И"=>"i", "Й"=>"j", "К"=>"k", "Л"=>"l", "М"=>"m", "Н"=>"n", "О"=>"o", "П"=>"p", "Р"=>"r", "С"=>"s", "Т"=>"t", "У"=>"u", "Ф"=>"f", "Х"=>"kh", "Ц"=>"ts", "Ч"=>"ch", "Ш"=>"sh", "Щ"=>"sch", "Ъ"=>"", "Ы"=>"y", "Ь"=>"", "Э"=>"e", "Ю"=>"yu", "Я"=>"ya", "а"=>"a", "б"=>"b", "в"=>"v", "г"=>"g", "д"=>"d", "е"=>"e", "ё"=>"yo", "ж"=>"zh", "з"=>"z", "и"=>"i", "й"=>"j", "к"=>"k", "л"=>"l", "м"=>"m", "н"=>"n", "о"=>"o", "п"=>"p", "р"=>"r", "с"=>"s", "т"=>"t", "у"=>"u", "ф"=>"f", "х"=>"kh", "ц"=>"ts", "ч"=>"ch", "ш"=>"sh", "щ"=>"sch", "ъ"=>"", "ы"=>"y", "ь"=>"", "э"=>"e", "ю"=>"yu", "я"=>"ya", " "=>"-", "."=>"", ","=>"", "/"=>"-", ":"=>"", ";"=>"","—"=>"", "–"=>"-" ); return strtr($str,$tr); >
echo ru2lat( "текст по-русски"); --------------> "tekst po-russki"
If you have an input for your description called description like this :
Add a condition in your mailer file like phpmailer or other like this :
if (preg_match("/[А-Яа-яЁё]/u", $_POST['description']))
While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer’s long-term value.
I know this is a little unrelated to php, but I had a similar problem with spam from a contact form. If your site is behind Cloudflare, then you can limit the spam by checking what country the request is coming from. You can then flag it as potential spam and verify later if it is publishable.
I eventually started to mark as spam everything that came from a different country than mine, and I take a quick look to see if there is anything valuable there, and delete the rest. I also return the information to the potential spammer that he solved the recaptcha incorrectly, although it was solved correctly. With time the number of spam messages dropped significantly.
Cloudflare returns the country code in the header and this value is available in the $_SERVER[‘HTTP_CF_IPCOUNTRY’] variable.
Проверка строки на присутствие кириллицы?
Есть-ли стандартная функция в php которая возвращает true/false в зависимости от того есть ли в строке кириллица?
Гугл ответа не дал.
Ведь никакой магии, просто копипаст — и все О_О
Искал в гугле, все ответы в данных ссылках работают через регулярки. Такое решения я и сам могу написать. Стало интересно может быть уже есть реализованная функция в php и не нужно писать новую функцию.
Борис Якушев: что за глупость вы только что написали? fi2.php.net/manual/ru/ref.strings.php — вот вам список уже реализованных функций
IceJOKER: Вы не поверите, но раньше я только тут смотрел функции. fi2.php.net/manual/ru/function.addcslashes.php И если честно было очень лень перечитывать описание каждой функции .
Не знал что есть страница с кратким описанием функций. Спасибо.
$str = 'test string for cyrillic зюя'; $contains_cyrillic = (bool) preg_match('/[\p]/u', $str);
Если из стандартного набора Вам выше написали варианты с preg_match, а так нашёл функцию которая проверяет наличие в строке русских букв в кодировке UTF-8 и windows-1251(cp1251) и возвращает true или файле
$string = "Строка с русскими буквами"; $res = isContainsRussianLetters($string);//получаем true или false в зависимости есть ли русские буквы в строке
Сам код функции по ссылке blog.ivru.net/?id=232
В моём случаи нужно было чтобы проверка работала без настройки локали и работала для 2-х кодировок, поэтому выбрал именно эту функцию, поскольку она проверяет жёстко по кодам символов и теоретически для указанных кодировок должна работать на любом хостинге с любыми настройками.
PHP проверка имени
вопрос как добавить сюда русские символы и украинские,потому что получается как:можно вводить англ буквы, пробел, подчеркивание, дефис, а как добавить еще туда другие символы. И объясните как вы это делайте, немного не понятно. И еще есть один вопрос. Есть же функция mail(), так вот когда я отправляю письмо на гугл почту, оно якобы приходит от скажем «X@gmail.com», а как сделать чтобы отправителем указывался постоянно один и тот же мэйл «Y@gmail.com». Поскольку google выдает следующие: «Возможно, это письмо не было отправлено с адреса X@gmail.com Подробнее. Сообщить о фишинге»
А почему бы не пойти от принципа KISS? Если у вас разрешены только буквы и цифры, воспользуйтесь простым шаблоном: [\w\d]+ . Что к какому алфавиту оно само разберётся.
3 ответа 3
как добавить сюда русские символы и украинские,потому что получается как:можно вводить англ буквы, пробел, подчеркивание, дефис, а как добавить еще туда другие символы.
Давайте исходить из KISS (сделай это проще, так-то). Тримнули ввод (удалили начальные/конечные пробелы, не забываем про это), а потом:
Так сгодится? Ну и про модификатор u не забывайте.
Впрочем, при таком подходе не совсем понятно, зачем вам вообще эта проверка. Или вам нужно другое: отсечь что-то, что не входит в конкретный алфавит?
В квадратных скобках вашего выражения перечисляется символы которые необходимо найти, сейчас правило найдет все маленькие и большие буквы английского алфавита, цифры от 0 до 9, тире и знак подчеркивания. По аналогии вы можете добавить русские буквы — аА-яЯ , они же будут и для украинского алфавита, плюс необходимо добавить буквы которые являются специфическими — ЁёІіЇїЄєҐґ . В итоге вы получите нечто вроде:
preg_match("#^[aA-zZаА-яЯЁёІіЇїЄєҐґ0-9\-_]+$#",$fullName);
Как правильно написал Pink Tux, можно заменить все перечисления символов, на метасимвол \w он ищет «буквенный или цифровой символ или знак подчёркивания», и добавить флаг u. В итоге получится:
Как проверить наличие русских букв в строке?
Какое регулярное выражение поможет узнать, есть ли хоть одна русская буква в строке среди латинницы? Пробовал:
preg_match("/^[а-я]/i",$this->open_metka_value,$matches, PREG_OFFSET_CAPTURE);
2 ответа 2
В вашем регулярном выражении есть три проблемы:
- Вы используете символ ^ , который привязывает регулярное выражение к началу строки. Например выражению /^abc/ будут соответствовать строки abcd и abc def , но не defabc .
- PHP не совсем корректно работает кириллицей (как, впрочем, и с рядом других UTF символов). А для того, чтобы все-таки заставить его работать корректно, нужно использовать модификатор u , включающий поддержку Unicode в регулярном выражении.
- Диапазон символов а-я не включает в себя символ ё (код этой буквы в кодировке UTF не попадает в диапазон между кодами букв а и я ).
Таким образом, корректное регулярное выражение имеет вид:
$string = "Строка с русскими буквами"; //получаем true или false в зависимости есть ли русские буквы в строке $res = isContainsRussianLetters($string);
function isContainsRussianLetters($text = false) < if ($text !== "") < $len = strlen($text)-1; for ($i=0;$i<=$len;$i++) < if (($i < $len) and (((($ord = ord(substr($text,$i,1))) == 208) and (($ord2 = ord(substr($text,($i+1),1))) == 129) or (($ord2 >= 144) and ($ord2 = 128) and ($ord2 elseif (((($ord = ord(substr($text,$i,1))) >= 192) and (($ord > > return false; >
работает для кодировок UTF-8 и windows=1251(cp1251) не зависимо от регистра и не требует установки локали, последнее для меня как раз и было важно, единственное Вы простили регулярку, а это не регулярка.