Проблем
Вече в няколко сайта уеб директории, забелязвам следния проблем: в уеб формата за качване на сайт полетата имат ограничение в броя на символите, което е нормално, но е проблем, когато пише, че може да въведеш 100 символа, а реално можеш да въведеш само 50. Още по-досадно и времеотнемащо е, ако софтуера създаващ уеб формата не се грижи да запомни всички въведени полета и при грешка в едно от полетата изтрива всички полета - за форми с много полета това е направо кошмар, защото трябва да въвеждаш всичко отначало.
Най-фрапиращ случай за това е сайта bestbgsites.com. Не е лесно да добавиш линк в този сайт. Гърми грешката: "Името на сайта е прекалено дълго! Може да бъде 85 символа" проблема е, че ако заглавието е на кирилица дължината е до 42 символа Описанието пише, че може да бъде до 255 символа, но реално са 127. Има и кратко описание до 30 символа (реално 15), което е трудно за измисляне. Ако сбъркаш някое от полетата всичките въведени данни се изтриват и трябва да се попълват повторно 🙁
Същия проблем има и сайта bglogs.com, като тук формата запомня полетата, но пък има ограничение в броя на грешните опити, след което пак трябва да започнеш на чисто. Полетата Описание и META Description пише, че имат лимит 500 символа и дори има Javascript, който намалява брояча на символите при всяко натискане на клавиш, когато въвеждаш в полето. Проблемът идва, когато изпратиш данните към сървъра, той ги проверява и ти показва, че си превишил доста лимита. В полето Заглавие е още по-трудно, защото лимита е замислен да бъде 100 символа, но на кирилица са само 50.
Обяснение
Тези проблеми се получават, защото представянето на всеки символ на кирилица при UTF8 е в 2 байта. Сайтовете ползват готов безплатен софтуер писан от англо-говорящи, които са свикнали при проверка държина на низ да използват PHP функцията strlen(), която работи на ниво байтове и затова тази функция преброява низ на кирилица с дължина 50 символа, като низ с дължина 100 символа.
Решение
Решението е много лесно, но трябва да бъде извършено от собственика на сайта. Трябва функцията strlen() да се замени с функцията mb_strlen(), която се съобразява с енкодинга и правилно преброява низ независимо на какъв език е написан. Тази функция се осигурява от библиотеката mbstring (Multibyte String), която за щастие отдавна се поддържа от всички български хостинг доставчици.
Отрязване на низ на кирилица
Подобен проблем се получава, ако отрязваш низ на кирилица в енкодинг UTF8 например показване на извадка от новина. Ако искаш да покажеш първите 200 символа от новина и направиш
$text = substr($text, 0, 200);
като резултат ще имаш първите 100 символа, като е възможно последния символ да бъде "срязан по средата", в смисъл, че от двата байта, с които е представен ще остане само първия и в резултат на това в страницата ще бъде показан странен символ, който е невалиден UTF8 символ и чупи страницата. В резултат на това страницата няма да може да бъде валидирана, като XHTML документ. Нямам лични наблюдения как се отразява това на SEO, но предполагам, че е проблем за ботовете на много от търсачките.
За да решиш този проблем трябва просто да замениш функцията substr() с функцията mb_substr(), като разбира се библиотеката mbstring трябва да е предварително инсталирана.
Заключение
Изрично искам да отбележа, че нямам нищо против споменатите два сайта и целта на статията ми не е да ги злепостави, а да помогне на тях и на всички, които имат сайт, който ползва готов софтуер, в който не е помислено, че ще се въвежда нещо различно от латински символи.
Прочетена:17854
Има и по-лесен начин за справяне с проблема и то е с предварителното декодиране на стринга в utf8. Просто се добавя една функция, ето кода:
int strlen(utf8_decode($str));
Супер, ама към функцията mb_strlen, mb_substr трябва да зададеш и като какъв енкодинг да се смята:
mb_strlen($string,'UTF-8');
mb_substr($string,0,150,'UTF-8);
Примерно 🙂
@Мартин понеже съм мързелив и не обичам да пиша много параметри. Използвам функцията mb_internal_encoding("UTF-8"), която се изпълнява в скрипт, който се извиква при зареждане на всяка страница. При пропускане на параметър 'UTF-8' във функциите mb_strlen и mb_substr се взема под внимание енкодинга зададен с mb_internal_encoding 😉
Досега не се бях сещал за тази функция. Направо ще я включвам и аз май в един файл, който инклудвам навсякъде - примерно файлът за връзка към база данни. Ще е хубаво скоро да напишеш една статия (поне аз ще се радвам) за php сигурност, защото доста възможности за защита съм разглеждал. Разгледай най-използваните - xss и sql inj.. Също ще ми е интересно какво можеш да кажеш за бинарните инжекции. Благоря 🙂
@Мартин тук вече ме уцели 😉 Въпросите за уеб сигурност е тема, която силно ме вълнува от години и (ще ти издам една тайна) смятам да създам отделен сайт на тази тематика.
Аз ползвам iconv_substr(), iconv_strlen(), към които също трябва да добавиш и параметър за енкодинга.