Санітизувати рядки, щоб зробити їх безпечними URL-адреса та ім’я файлу?


136

Я намагаюся придумати функцію, яка добре працює з дезінфекцією певних рядків, щоб вони були безпечними для використання в URL-адресі (як поштовий слуп), а також безпечними для використання в якості імен файлів. Наприклад, коли хтось завантажує файл, я хочу переконатися, що я видалив усі небезпечні символи з імені.

Поки я придумав таку функцію, яка, сподіваюся, вирішує цю проблему і дозволяє також іноземні дані UTF-8.

/**
 * Convert a string to the file/URL safe "slug" form
 *
 * @param string $string the string to clean
 * @param bool $is_filename TRUE will allow additional filename characters
 * @return string
 */
function sanitize($string = '', $is_filename = FALSE)
{
 // Replace all weird characters with dashes
 $string = preg_replace('/[^\w\-'. ($is_filename ? '~_\.' : ''). ']+/u', '-', $string);

 // Only allow one dash separator at a time (and make string lowercase)
 return mb_strtolower(preg_replace('/--+/u', '-', $string), 'UTF-8');
}

Хтось має якісь хитрі зразкові дані, з якими я можу протистояти - чи знаю кращий спосіб захистити наші програми від невірних імен?

$ is-filename дозволяє отримати деякі додаткові символи, такі як файли temp vim

update: видалено зірковий символ, оскільки я не міг придумати правильне використання


Краще видалити всі , крім [\ w.-]
Elias

3
Ви можете вважати Нормалізатор та коментарі до нього корисними.
Метт Гібсон

Відповіді:


57

Деякі зауваження щодо вашого рішення:

  1. "u" в кінці вашого шаблону означає, що шаблон , а не текст, який він відповідає, буде трактуватися як UTF-8 (я припускаю, що ви припускали останнє?).
  2. \ w відповідає символу підкреслення. Ви спеціально включаєте його до файлів, що призводить до припущення, що ви не хочете їх в URL-адресах, але в коді у вас URL-адреси буде дозволено включати підкреслення.
  3. Включення "іноземного UTF-8", здається, залежить від локальної залежності. Не ясно, чи це локальний сервер чи клієнт. З документів PHP:

Символ "слова" - це будь-яка літера або цифра або символ підкреслення, тобто будь-який символ, який може бути частиною слова "Perl". Визначення букв і цифр контролюється таблицями символів PCRE, і може змінюватись, якщо відбувається відповідність для конкретних локалів. Наприклад, в мові "fr" (французька мова) деякі символьні коди, що перевищують 128, використовуються для букв з наголосом, і вони відповідають \ w.

Створення слизу

Ви, ймовірно, не повинні включати символи з наголосом тощо у своєму поштовому слизі, оскільки, технічно, вони повинні бути кодовані у відсотках (за правилами кодування URL-адрес), щоб у вас були некрасиві URL-адреси.

Отже, якби я був ти, після нижнього регістру я перетворив би будь-які «спеціальні» символи в їх еквівалент (наприклад, é -> e) і замінив символи, що не [az], на '-', обмежуючи кількість пробілів '-' як ви зробили. Тут реалізовано перетворення спеціальних символів: https://web.archive.org/web/20130208144021/http://neo22s.com/slug

Санітарія загалом

OWASP мають PHP-реалізацію свого Enterprise Security API, який, крім усього іншого, включає методи безпечного кодування та декодування вводу та виводу у вашій програмі.

Інтерфейс Encoder забезпечує:

canonicalize (string $input, [bool $strict = true])
decodeFromBase64 (string $input)
decodeFromURL (string $input)
encodeForBase64 (string $input, [bool $wrap = false])
encodeForCSS (string $input)
encodeForHTML (string $input)
encodeForHTMLAttribute (string $input)
encodeForJavaScript (string $input)
encodeForOS (Codec $codec, string $input)
encodeForSQL (Codec $codec, string $input)
encodeForURL (string $input)
encodeForVBScript (string $input)
encodeForXML (string $input)
encodeForXMLAttribute (string $input)
encodeForXPath (string $input)

https://github.com/OWASP/PHP-ESAPI https://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API


Ви вірно ставитесь до мого припущення про модифікатор "u" - я подумав, що це стосується тексту. Я також забув про модифікатор \ w, включаючи підкреслення. Я б зазвичай конвертував усі наголошені символи в ASCII - але я хочу, щоб це працювало і для інших мов. Я припускав, що існує якийсь безпечний спосіб UTF-8, щоб будь-який символ мови міг використовуватися в URL-службі або імені файлу, щоб навіть арабські назви працювали. Зрештою, Linux підтримує назви файлів UTF-8, а браузери повинні кодувати HTML-посилання за потребою. Велика подяка за ваш внесок тут.
Xeoncross

По-друге, ви насправді маєте рацію, але це не лише проблема з браузером, що кодує посилання правильно. Найпростіший спосіб наблизитись до того, що ви хочете, - це зіставлення символів, що не належать до ASCII, до їх найближчого еквівалента ASCII, а потім URL-кодування вашого посилання в тілі HTML. Важкий спосіб - забезпечити послідовне кодування UTF-8 (або UTF-16, я думаю, для деяких китайських діалектів) зі свого сховища даних, через веб-сервер, рівень програми (PHP), вміст сторінки, веб-браузер, а не urlencode ваших URL-адрес ( але все ж знімайте "небажані" символи). Це дасть вам непогані некодовані посилання та URL-адреси.
Алан Доннеллі

Хороша порада. Я спробую створити чисте середовище UTF-8. Потім, взявши кілька рядків з мов, що не належать до ASCII, я видаляю небезпечні символи (./ ;: тощо ...) та створюю файли, а потім посилання HTML на ці файли, щоб побачити, чи можу я натиснути їх і побачити, чи все це працює. Якщо ні, то, ймовірно, мені доведеться повернутися до (raw)? Urlencode (), щоб дозволити UTF-8. Я опублікую результати тут.
Xeoncross

3
Я створив файл під назвою, สังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่.txtа потім створив HTML-файл UTF-8 із посиланням на нього. Дивовижно це спрацювало - навіть на вікнах! Однак у мене тоді був PHP, file_put_contents('สังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่.txt')і він не зміг створити ім'я файлу bazaar з цього рядка. Потім я спробував створити його fopen()і отримав те саме ім'я файлу. Отже, очевидно, що PHP (як мінімум, у Windows) не може створити імена файлів UTF-8. bugs.php.net/bug.php?id=46990&thanks=6
Xeoncross

1
Я нагороджую цією відповіддю, тому що вона мене найбільше задумала, а також включила корисне посилання на проект, про який я ніколи не чув, про який варто заглянути. Я опублікую, як тільки знайду відповідь.
Xeoncross

87

Я знайшов цю більшу функцію в коді Chyrp :

/**
 * Function: sanitize
 * Returns a sanitized string, typically for URLs.
 *
 * Parameters:
 *     $string - The string to sanitize.
 *     $force_lowercase - Force the string to lowercase?
 *     $anal - If set to *true*, will remove all non-alphanumeric characters.
 */
function sanitize($string, $force_lowercase = true, $anal = false) {
    $strip = array("~", "`", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "=", "+", "[", "{", "]",
                   "}", "\\", "|", ";", ":", "\"", "'", "‘", "’", "“", "”", "–", "—",
                   "—", "–", ",", "<", ".", ">", "/", "?");
    $clean = trim(str_replace($strip, "", strip_tags($string)));
    $clean = preg_replace('/\s+/', "-", $clean);
    $clean = ($anal) ? preg_replace("/[^a-zA-Z0-9]/", "", $clean) : $clean ;
    return ($force_lowercase) ?
        (function_exists('mb_strtolower')) ?
            mb_strtolower($clean, 'UTF-8') :
            strtolower($clean) :
        $clean;
}

і цей у коді wordpress

/**
 * Sanitizes a filename replacing whitespace with dashes
 *
 * Removes special characters that are illegal in filenames on certain
 * operating systems and special characters requiring special escaping
 * to manipulate at the command line. Replaces spaces and consecutive
 * dashes with a single dash. Trim period, dash and underscore from beginning
 * and end of filename.
 *
 * @since 2.1.0
 *
 * @param string $filename The filename to be sanitized
 * @return string The sanitized filename
 */
function sanitize_file_name( $filename ) {
    $filename_raw = $filename;
    $special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}");
    $special_chars = apply_filters('sanitize_file_name_chars', $special_chars, $filename_raw);
    $filename = str_replace($special_chars, '', $filename);
    $filename = preg_replace('/[\s-]+/', '-', $filename);
    $filename = trim($filename, '.-_');
    return apply_filters('sanitize_file_name', $filename, $filename_raw);
}

Оновлення вересня 2012 року

Алікс Аксель зробив неймовірну роботу в цій галузі. Його рамка функціонування включає кілька чудових текстових фільтрів та перетворень.


23
Код WordPress не є портативним, оскільки він використовуєapply_filters
Кевін Марк

1
Зверніть увагу , що WordPress версія замінює /[\s-]+/з , -який краще , ніж перша версія (яка замінює тільки /\s+/) , які можуть викликати кілька тире поспіль
Yotam Омер

Тільки для довідок wordpress apply_filters можна знайти тут, і sanitize_file_name тут .
Ерік

як щодо кількох пробілів? Замініть
Джефрі Жирафа

8
Варіант $ аналогічно звучить для мене дуже лякаючо з можливістю застосування сили.
viljun

30

Це повинно зробити ваші імена файлів безпечними ...

$string = preg_replace(array('/\s/', '/\.[\.]+/', '/[^\w_\.\-]/'), array('_', '.', ''), $string);

і більш глибоким рішенням цього є:

// Remove special accented characters - ie. sí.
$clean_name = strtr($string, array('Š' => 'S','Ž' => 'Z','š' => 's','ž' => 'z','Ÿ' => 'Y','À' => 'A','Á' => 'A','Â' => 'A','Ã' => 'A','Ä' => 'A','Å' => 'A','Ç' => 'C','È' => 'E','É' => 'E','Ê' => 'E','Ë' => 'E','Ì' => 'I','Í' => 'I','Î' => 'I','Ï' => 'I','Ñ' => 'N','Ò' => 'O','Ó' => 'O','Ô' => 'O','Õ' => 'O','Ö' => 'O','Ø' => 'O','Ù' => 'U','Ú' => 'U','Û' => 'U','Ü' => 'U','Ý' => 'Y','à' => 'a','á' => 'a','â' => 'a','ã' => 'a','ä' => 'a','å' => 'a','ç' => 'c','è' => 'e','é' => 'e','ê' => 'e','ë' => 'e','ì' => 'i','í' => 'i','î' => 'i','ï' => 'i','ñ' => 'n','ò' => 'o','ó' => 'o','ô' => 'o','õ' => 'o','ö' => 'o','ø' => 'o','ù' => 'u','ú' => 'u','û' => 'u','ü' => 'u','ý' => 'y','ÿ' => 'y'));
$clean_name = strtr($clean_name, array('Þ' => 'TH', 'þ' => 'th', 'Ð' => 'DH', 'ð' => 'dh', 'ß' => 'ss', 'Œ' => 'OE', 'œ' => 'oe', 'Æ' => 'AE', 'æ' => 'ae', 'µ' => 'u'));

$clean_name = preg_replace(array('/\s/', '/\.[\.]+/', '/[^\w_\.\-]/'), array('_', '.', ''), $clean_name);

Це передбачає, що ви хочете крапку в імені файлу. якщо ви хочете, щоб він перейшов у малі регістри, просто використовуйте

$clean_name = strtolower($clean_name);

для останнього рядка


1
Досі відсутні деякі чеські та словацькі символи:'ľ' => 'l', 'Ľ' => 'L', 'č' => 'c', 'Č' => 'C', 'ť' => 't', 'Ť' => 'T', 'ň' => 'n', 'Ň' => 'N', 'ĺ' => 'l', 'Ĺ' => 'L', 'Ř' => 'R', 'ř' => 'r', 'ě' => 'e', 'Ě' => 'E', 'ů' => 'u', 'Ů' => 'U'
Jasom Dotnet

22

Спробуйте це:

function normal_chars($string)
{
    $string = htmlentities($string, ENT_QUOTES, 'UTF-8');
    $string = preg_replace('~&([a-z]{1,2})(acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml);~i', '$1', $string);
    $string = html_entity_decode($string, ENT_QUOTES, 'UTF-8');
    $string = preg_replace(array('~[^0-9a-z]~i', '~[ -]+~'), ' ', $string);

    return trim($string, ' -');
}

Examples:

echo normal_chars('Álix----_Ãxel!?!?'); // Alix Axel
echo normal_chars('áéíóúÁÉÍÓÚ'); // aeiouAEIOU
echo normal_chars('üÿÄËÏÖÜŸåÅ'); // uyAEIOUYaA

На основі обраної відповіді в цій темі: URL-адреса, придатна для користувача в PHP?


Дуже приємно - я ніколи не бачив цього робити без таблиці перекладу (як Wordpress використовує). Однак я не вважаю, що ця функція є достатньою, оскільки є лише перекладом спеціальних символів, але не видаляє небезпечних символів. Можливо, його можна додати до одного вище ...
Xeoncross

4
Га! Ця суть, що кодує хакерство, мила! Хоча на перший погляд зовсім не ясно, як цей метод робить те, що робить. Однак є проблема. Чи не "Frédéric & Éric" не перетворяться на "Frederic amp Eric"?
Алан Доннеллі

@AlanDonnelly: Дійсно, я оновив функцію у своїй початковій відповіді (перевірте посилання), так само trim()має бути trim($string, '-').
Алікс Аксель

@Xeoncross: Останній preg_replace()повинен видалити всі небезпечні символи.
Алікс Аксель

@AlixAxel, ти просто скрізь не ти. Я тільки читав PHP AWS SDK, і у них був ваш код для UUID. Дивовижний код функції просто важко перемогти.
Xeoncross

13

Це не зовсім відповідь, оскільки вона не пропонує жодних рішень (поки!), Але вона занадто велика, щоб вмістити коментар ...


Я провів тестування (щодо імен файлів) на Windows 7 та Ubuntu 12.04, і я дізнався, що:

1. PHP не може обробляти файли, що не належать до ASCII

Хоча і Windows, і Ubuntu можуть обробляти імена файлів Unicode (навіть RTL, як здається) PHP 5.3 вимагає хаків для роботи навіть зі старим звичайним ISO-8859-1, тому краще зберігати його ASCII лише для безпеки.

2. Значення тривалості імені файлів (спеціально для Windows)

Для Ubuntu максимальна довжина імені файлу (включення розширення) - 255 (крім шляху):

/var/www/uploads/123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345/

Однак для Windows 7 (NTFS) максимальна довжина імені файлу може залежати від його абсолютного шляху:

(0 + 0 + 244 + 11 chars) C:\1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234\1234567.txt
(0 + 3 + 240 + 11 chars) C:\123\123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\1234567.txt
(3 + 3 + 236 + 11 chars) C:\123\456\12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456\1234567.txt

У Вікіпедії сказано, що:

NTFS дозволяє кожному компоненту шляху (каталогу або імені файлу) бути 255 символів.

Наскільки мені відомо (і тестування), це неправильно.

Загалом (підрахунок косої риски) всі ці приклади мають 259 знаків, якщо ви знімете C:\256 символів (а не 255 ?!). У каталогах, де створено за допомогою Провідника, ви помітите, що він стримує себе використовувати весь доступний простір для імені каталогу. Причиною цього є дозволити створення файлів за допомогою 8.3 . Те ж саме відбувається і з іншими перегородками.

Файли не потрібно резервувати 8,3 довжини вимог звичайно:

(255 chars) E:\12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901.txt

Ви не можете створити більше підкаталогів, якщо абсолютний шлях батьківського каталогу містить більше 242 символів, оскільки 256 = 242 + 1 + \ + 8 + . + 3. Використовуючи Провідник Windows, ви не можете створити інший каталог, якщо батьківський каталог містить більше 233 символів (залежно від локальної системи), оскільки 256 = 233 + 10 + \ + 8 + . + 3; 10тут довжина рядка New folder.

Файлова система Windows створює жахливу проблему, якщо ви хочете забезпечити взаємодію між файловими системами.

3. Остерігайтеся зарезервованих персонажів та ключових слів

Крім видалення символів, що не належать до ASCII, не для друку та керування , вам також потрібно повторно (розмістити / перемістити):

"*/:<>?\|

Просто видалення цих символів може бути не найкращою ідеєю, оскільки ім'я файлу може втратити певний сенс. Я думаю, що, принаймні, кілька випадків виникнення цих символів слід замінити одним підкресленням ( _) або, можливо, чимось більш репрезентативним (це лише ідея):

  • "*? -> _
  • /\| -> -
  • : -> [ ]-[ ]
  • < -> (
  • > -> )

Існують також спеціальні ключові слова, яких слід уникати (як NUL), хоча я не впевнений, як це подолати. Можливо, чорний список із випадковим запасом імені був би хорошим підходом до його вирішення.

4. Чутливість до справи

Це само собою зрозуміло, але якщо ви хочете так забезпечити унікальність файлів у різних операційних системах, ви повинні перетворити імена файлів у нормалізований регістр, таким чином, my_file.txtі My_File.txtв Linux не стане тим самим my_file.txtфайлом у Windows.

5. Переконайтесь, що це унікально

Якщо ім'я файлу вже існує, до його базового імені слід додати унікальний ідентифікатор .

Загальні унікальні ідентифікатори включають часову позначку UNIX, дайджест вмісту файлу або випадковий рядок.

6. Приховані файли

Тільки тому, що його можна назвати не означає, що він повинен ...

Точки, як правило, перелічені білими назвами файлів, але в Linux прихований файл представлений провідною крапкою.

7. Інші міркування

Якщо вам доведеться позбавити деяких символів імені файлу, розширення, як правило, важливіше, ніж базове ім'я файлу. Допускаючи значну максимальну кількість символів для розширення файлу (8-16), слід викреслити символи з базового імені. Також важливо зауважити, що у маловірогідному випадку мати більш ніж одне довге розширення - наприклад, _.graphmlz.tag.gz- _.graphmlz.tagтільки _в цьому випадку слід вважати базовим ім'ям файлу.

8. Ресурси

Калібр досить пристойно обробляє ім'я файлу:

Wikipedia сторінка на ім'я файлу перекручуючи і пов'язаної глави за допомогою Samba .


Якщо, наприклад, ви спробуєте створити файл, який порушує будь-яке правило 1/2/3, ви отримаєте дуже корисну помилку:

Warning: touch(): Unable to create file ... because No error in ... on line ...

11

Я завжди думав, що Кохана зробив це досить непогано .

public static function title($title, $separator = '-', $ascii_only = FALSE)
{
if ($ascii_only === TRUE)
{
// Transliterate non-ASCII characters
$title = UTF8::transliterate_to_ascii($title);

// Remove all characters that are not the separator, a-z, 0-9, or whitespace
$title = preg_replace('![^'.preg_quote($separator).'a-z0-9\s]+!', '', strtolower($title));
}
else
{
// Remove all characters that are not the separator, letters, numbers, or whitespace
$title = preg_replace('![^'.preg_quote($separator).'\pL\pN\s]+!u', '', UTF8::strtolower($title));
}

// Replace all separator characters and whitespace by a single separator
$title = preg_replace('!['.preg_quote($separator).'\s]+!u', $separator, $title);

// Trim separators from the beginning and end
return trim($title, $separator);
}

Зручний UTF8::transliterate_to_ascii()перетворить такі речі, як ñ => n.

Звичайно, ви можете замінити інші UTF8::*речі функціями mb_ *.


5

Що стосується завантаження файлів, ви б найбезпечніше запобігти користувачеві контролювати його ім'я. Як уже було натякано, зберігайте канонізовану назву файлу в базі даних разом із випадковим чином обраним та унікальним іменем, яке ви будете використовувати як власне ім’я файлу.

Використовуючи OWASP ESAPI, ці імена можна генерувати таким чином:

$userFilename   = ESAPI::getEncoder()->canonicalize($input_string);
$safeFilename   = ESAPI::getRandomizer()->getRandomFilename();

Ви можете додати часову позначку до $ safeFilename, щоб гарантувати унікальність генерованого на довільне ім'я файлу, навіть не перевіряючи наявний файл.

Що стосується кодування URL-адреси та знову використання ESAPI:

$safeForURL     = ESAPI::getEncoder()->encodeForURL($input_string);

Цей метод виконує канонізацію перед кодуванням рядка та обробляє всі кодування символів.


Однозначно - також, зняття контролю над іменем файлів від користувачів запобіжить можливість двох завантажень з тим самим іменем.
CodeVirtuoso

5

Рекомендую * URLify для PHP (480+ зірок у Github) - "порт PHP URLify.js від проекту Django. Транслітерація символів, що не належать до ascii, для використання в URL-адресах".

Основне використання:

Щоб створити слизи для URL-адрес:

<?php

echo URLify::filter (' J\'étudie le français ');
// "jetudie-le-francais"

echo URLify::filter ('Lo siento, no hablo español.');
// "lo-siento-no-hablo-espanol"

?>

Щоб створити кулі для імен файлів:

<?php

echo URLify::filter ('фото.jpg', 60, "", true);
// "foto.jpg"

?>

* Жодна з інших пропозицій не відповідає моїм критеріям:

  • Має бути встановлено через композитор
  • Не повинен залежати від iconv, оскільки він поводиться по-різному в різних системах
  • Повинна бути розширена, щоб дозволити зміни та користувацькі заміни символів
  • Популярні (наприклад, багато зірок на Github)
  • Має тести

Як бонус URLify також видаляє певні слова та позбавляє всіх символів, які не транслітеровані.

Ось тестовий випадок, коли тонни іноземних символів правильно транслітеруються за допомогою URLify: https://gist.github.com/motin/a65e6c1cc303e46900d10894bf2da87f


1
Дякую - це виглядає ідеально для моїх цілей.
Девід Гудвін

5

Я адаптувався з іншого джерела і додав ще кілька зайвих, можливо, трохи зайвих

/**
 * Convert a string into a url safe address.
 *
 * @param string $unformatted
 * @return string
 */
public function formatURL($unformatted) {

    $url = strtolower(trim($unformatted));

    //replace accent characters, forien languages
    $search = array('À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'ß', 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ', 'Ā', 'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ', 'ĉ', 'Ċ', 'ċ', 'Č', 'č', 'Ď', 'ď', 'Đ', 'đ', 'Ē', 'ē', 'Ĕ', 'ĕ', 'Ė', 'ė', 'Ę', 'ę', 'Ě', 'ě', 'Ĝ', 'ĝ', 'Ğ', 'ğ', 'Ġ', 'ġ', 'Ģ', 'ģ', 'Ĥ', 'ĥ', 'Ħ', 'ħ', 'Ĩ', 'ĩ', 'Ī', 'ī', 'Ĭ', 'ĭ', 'Į', 'į', 'İ', 'ı', 'IJ', 'ij', 'Ĵ', 'ĵ', 'Ķ', 'ķ', 'Ĺ', 'ĺ', 'Ļ', 'ļ', 'Ľ', 'ľ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'Ń', 'ń', 'Ņ', 'ņ', 'Ň', 'ň', 'ʼn', 'Ō', 'ō', 'Ŏ', 'ŏ', 'Ő', 'ő', 'Œ', 'œ', 'Ŕ', 'ŕ', 'Ŗ', 'ŗ', 'Ř', 'ř', 'Ś', 'ś', 'Ŝ', 'ŝ', 'Ş', 'ş', 'Š', 'š', 'Ţ', 'ţ', 'Ť', 'ť', 'Ŧ', 'ŧ', 'Ũ', 'ũ', 'Ū', 'ū', 'Ŭ', 'ŭ', 'Ů', 'ů', 'Ű', 'ű', 'Ų', 'ų', 'Ŵ', 'ŵ', 'Ŷ', 'ŷ', 'Ÿ', 'Ź', 'ź', 'Ż', 'ż', 'Ž', 'ž', 'ſ', 'ƒ', 'Ơ', 'ơ', 'Ư', 'ư', 'Ǎ', 'ǎ', 'Ǐ', 'ǐ', 'Ǒ', 'ǒ', 'Ǔ', 'ǔ', 'Ǖ', 'ǖ', 'Ǘ', 'ǘ', 'Ǚ', 'ǚ', 'Ǜ', 'ǜ', 'Ǻ', 'ǻ', 'Ǽ', 'ǽ', 'Ǿ', 'ǿ'); 
    $replace = array('A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 's', 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'y', 'A', 'a', 'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c', 'D', 'd', 'D', 'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'G', 'g', 'G', 'g', 'G', 'g', 'G', 'g', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'IJ', 'ij', 'J', 'j', 'K', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'l', 'l', 'N', 'n', 'N', 'n', 'N', 'n', 'n', 'O', 'o', 'O', 'o', 'O', 'o', 'OE', 'oe', 'R', 'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'T', 't', 'T', 't', 'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'W', 'w', 'Y', 'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 's', 'f', 'O', 'o', 'U', 'u', 'A', 'a', 'I', 'i', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'A', 'a', 'AE', 'ae', 'O', 'o'); 
    $url = str_replace($search, $replace, $url);

    //replace common characters
    $search = array('&', '£', '$'); 
    $replace = array('and', 'pounds', 'dollars'); 
    $url= str_replace($search, $replace, $url);

    // remove - for spaces and union characters
    $find = array(' ', '&', '\r\n', '\n', '+', ',', '//');
    $url = str_replace($find, '-', $url);

    //delete and replace rest of special chars
    $find = array('/[^a-z0-9\-<>]/', '/[\-]+/', '/<[^>]*>/');
    $replace = array('', '-', '');
    $uri = preg_replace($find, $replace, $url);

    return $uri;
}

5

і це версія Joomla 3.3.2 від JFile::makeSafe($file)

public static function makeSafe($file)
{
    // Remove any trailing dots, as those aren't ever valid file names.
    $file = rtrim($file, '.');

    $regex = array('#(\.){2,}#', '#[^A-Za-z0-9\.\_\- ]#', '#^\.#');

    return trim(preg_replace($regex, '', $file));
}

4

Я не думаю, що безпечний перелік символів для видалення. Я б скоріше скористався наступним:

Для імен файлів: використовуйте внутрішній ідентифікатор або хеш файлового вмісту. Збережіть ім'я документа в базі даних. Таким чином ви можете зберегти оригінальне ім'я файлу і все одно знайти файл.

Для параметрів URL: Використовуйте urlencode()для кодування будь-яких спеціальних символів.


1
Я згоден, більшість перерахованих тут методів видаляють відомих небезпечних символів - мій метод видаляє все, що не є відомим безпечним персонажем. Оскільки більшість системних ковпаків кодує URL-адреси пошти, я б запропонував продовжувати дотримуватися цього перевіреного методу, а не використовувати документально підтверджений UTF-8 небезпечний urlencode ().
Xeoncross

3

Залежно від способу його використання, ви можете додати обмеження довжини для захисту від переповнення буфера.


Так, тестування на mb_strlen () - це завжди важлива річ!
Xeoncross

3

Це хороший спосіб захистити ім'я файлу для завантаження:

$file_name = trim(basename(stripslashes($name)), ".\x00..\x20");

Я не дуже впевнений у цьому, бо .\x00..\x20можна звестись до .\x00\x20.
Xeoncross

@Xeoncross: Я думаю, що .\x00..\x20вилучає точки та кожен символ між \x00і \x20, тоді як .\x00\x20слід видалити лише ці 3 байти.
Алікс Аксель

Ця відповідь вимагає більше пояснень, щоб безпечно її використовувати. Не так багато інформації про точний синтаксис для списку в мережі.
Мануель Арвед Шмідт

3

Ось реалізація CodeIgniter.

/**
 * Sanitize Filename
 *
 * @param   string  $str        Input file name
 * @param   bool    $relative_path  Whether to preserve paths
 * @return  string
 */
public function sanitize_filename($str, $relative_path = FALSE)
{
    $bad = array(
        '../', '<!--', '-->', '<', '>',
        "'", '"', '&', '$', '#',
        '{', '}', '[', ']', '=',
        ';', '?', '%20', '%22',
        '%3c',      // <
        '%253c',    // <
        '%3e',      // >
        '%0e',      // >
        '%28',      // (
        '%29',      // )
        '%2528',    // (
        '%26',      // &
        '%24',      // $
        '%3f',      // ?
        '%3b',      // ;
        '%3d'       // =
    );

    if ( ! $relative_path)
    {
        $bad[] = './';
        $bad[] = '/';
    }

    $str = remove_invisible_characters($str, FALSE);
    return stripslashes(str_replace($bad, '', $str));
}

І remove_invisible_charactersзалежність.

function remove_invisible_characters($str, $url_encoded = TRUE)
{
    $non_displayables = array();

    // every control character except newline (dec 10),
    // carriage return (dec 13) and horizontal tab (dec 09)
    if ($url_encoded)
    {
        $non_displayables[] = '/%0[0-8bcef]/';  // url encoded 00-08, 11, 12, 14, 15
        $non_displayables[] = '/%1[0-9a-f]/';   // url encoded 16-31
    }

    $non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S';   // 00-08, 11, 12, 14-31, 127

    do
    {
        $str = preg_replace($non_displayables, '', $str, -1, $count);
    }
    while ($count);

    return $str;
}

2

чому б просто не використовувати php urlencode? він замінює "небезпечних" символів їх шестигранним поданням для URL-адрес (тобто %20для пробілу)


2
Символ% не рекомендується для імен файлів, а шістнадцяткові кодовані символи не виглядають так добре в URL-адресі. Веб-браузери можуть підтримувати рядки UTF-8, які набагато приємніші та простіші для мов, які не належать до ассії.
Xeoncross

ви могли б зробити urlencode і ТОГО str_replace ('% 20', '-', url)?
Франческо

2

У цьому питанні вже є кілька рішень, але я прочитав і протестував більшу частину коду тут, і закінчив це рішення, яке є сукупністю того, що я дізнався тут:

Функція

Функція поєднана тут у пакеті Symfony2, але її можна дістати для використання в якості простого PHP , вона має лише залежність від iconvфункції, яка повинна бути включена:

Filesystem.php :

<?php

namespace COil\Bundle\COilCoreBundle\Component\HttpKernel\Util;

use Symfony\Component\HttpKernel\Util\Filesystem as BaseFilesystem;

/**
 * Extends the Symfony filesystem object.
 */
class Filesystem extends BaseFilesystem
{
    /**
     * Make a filename safe to use in any function. (Accents, spaces, special chars...)
     * The iconv function must be activated.
     *
     * @param string  $fileName       The filename to sanitize (with or without extension)
     * @param string  $defaultIfEmpty The default string returned for a non valid filename (only special chars or separators)
     * @param string  $separator      The default separator
     * @param boolean $lowerCase      Tells if the string must converted to lower case
     *
     * @author COil <https://github.com/COil>
     * @see    http://stackoverflow.com/questions/2668854/sanitizing-strings-to-make-them-url-and-filename-safe
     *
     * @return string
     */
    public function sanitizeFilename($fileName, $defaultIfEmpty = 'default', $separator = '_', $lowerCase = true)
    {
    // Gather file informations and store its extension
    $fileInfos = pathinfo($fileName);
    $fileExt   = array_key_exists('extension', $fileInfos) ? '.'. strtolower($fileInfos['extension']) : '';

    // Removes accents
    $fileName = @iconv('UTF-8', 'us-ascii//TRANSLIT', $fileInfos['filename']);

    // Removes all characters that are not separators, letters, numbers, dots or whitespaces
    $fileName = preg_replace("/[^ a-zA-Z". preg_quote($separator). "\d\.\s]/", '', $lowerCase ? strtolower($fileName) : $fileName);

    // Replaces all successive separators into a single one
    $fileName = preg_replace('!['. preg_quote($separator).'\s]+!u', $separator, $fileName);

    // Trim beginning and ending seperators
    $fileName = trim($fileName, $separator);

    // If empty use the default string
    if (empty($fileName)) {
        $fileName = $defaultIfEmpty;
    }

    return $fileName. $fileExt;
    }
}

Одиничні тести

Що цікаво, це те, що я створив тести PHPUnit, спочатку для перевірки кращих випадків, щоб ви могли перевірити, чи відповідає вашим потребам: (Якщо ви знайшли помилку, сміливо додайте тестовий випадок)

FilesystemTest.php :

<?php

namespace COil\Bundle\COilCoreBundle\Tests\Unit\Helper;

use COil\Bundle\COilCoreBundle\Component\HttpKernel\Util\Filesystem;

/**
 * Test the Filesystem custom class.
 */
class FilesystemTest extends \PHPUnit_Framework_TestCase
{
    /**
     * test sanitizeFilename()
     */
    public function testFilesystem()
    {
    $fs = new Filesystem();

    $this->assertEquals('logo_orange.gif', $fs->sanitizeFilename('--logö  _  __   ___   ora@@ñ--~gé--.gif'), '::sanitizeFilename() handles complex filename with specials chars');
    $this->assertEquals('coilstack', $fs->sanitizeFilename('cOiLsTaCk'), '::sanitizeFilename() converts all characters to lower case');
    $this->assertEquals('cOiLsTaCk', $fs->sanitizeFilename('cOiLsTaCk', 'default', '_', false), '::sanitizeFilename() lower case can be desactivated, passing false as the 4th argument');
    $this->assertEquals('coil_stack', $fs->sanitizeFilename('coil stack'), '::sanitizeFilename() convert a white space to a separator');
    $this->assertEquals('coil-stack', $fs->sanitizeFilename('coil stack', 'default', '-'), '::sanitizeFilename() can use a different separator as the 3rd argument');
    $this->assertEquals('coil_stack', $fs->sanitizeFilename('coil          stack'), '::sanitizeFilename() removes successive white spaces to a single separator');
    $this->assertEquals('coil_stack', $fs->sanitizeFilename('       coil stack'), '::sanitizeFilename() removes spaces at the beginning of the string');
    $this->assertEquals('coil_stack', $fs->sanitizeFilename('coil   stack         '), '::sanitizeFilename() removes spaces at the end of the string');
    $this->assertEquals('coilstack', $fs->sanitizeFilename('coil,,,,,,stack'), '::sanitizeFilename() removes non-ASCII characters');
    $this->assertEquals('coil_stack', $fs->sanitizeFilename('coil_stack  '), '::sanitizeFilename() keeps separators');
    $this->assertEquals('coil_stack', $fs->sanitizeFilename(' coil________stack'), '::sanitizeFilename() converts successive separators into a single one');
    $this->assertEquals('coil_stack.gif', $fs->sanitizeFilename('cOil Stack.GiF'), '::sanitizeFilename() lower case filename and extension');
    $this->assertEquals('copy_of_coil.stack.exe', $fs->sanitizeFilename('Copy of coil.stack.exe'), '::sanitizeFilename() keeps dots before the extension');
    $this->assertEquals('default.doc', $fs->sanitizeFilename('____________.doc'), '::sanitizeFilename() returns a default file name if filename only contains special chars');
    $this->assertEquals('default.docx', $fs->sanitizeFilename('     ___ -  --_     __%%%%__¨¨¨***____      .docx'), '::sanitizeFilename() returns a default file name if filename only contains special chars');
    $this->assertEquals('logo_edition_1314352521.jpg', $fs->sanitizeFilename('logo_edition_1314352521.jpg'), '::sanitizeFilename() returns the filename untouched if it does not need to be modified');
    $userId = rand(1, 10);
    $this->assertEquals('user_doc_'. $userId. '.doc', $fs->sanitizeFilename('亐亐亐亐亐.doc', 'user_doc_'. $userId), '::sanitizeFilename() returns the default string (the 2nd argument) if it can\'t be sanitized');
    }
}

Результати тестів: (перевірено на Ubuntu з PHP 5.3.2 та MacOsX з PHP 5.3.17:

All tests pass:

phpunit -c app/ src/COil/Bundle/COilCoreBundle/Tests/Unit/Helper/FilesystemTest.php
PHPUnit 3.6.10 by Sebastian Bergmann.

Configuration read from /var/www/strangebuzz.com/app/phpunit.xml.dist

.

Time: 0 seconds, Memory: 5.75Mb

OK (1 test, 17 assertions)

1
Це передбачає в основному введення на латині. Додайте більше символів UTF-8 з інших мов, щоб побачити, де у вас виникнуть проблеми.
Xeoncross

@Xeoncross Я згоден, як Крістіан сказав, що потрібно зберегти Id або хеш І оригінальне ім'я файлу. Але ця функція надає альтернативу, оскільки ви можете вказати рядок за замовчуванням, коли процес санітарії не вдається. Я додав одиничний тест для цього випадку. Дякуємо, що повідомили про помилку.
Згорнутий

2

У мене є заголовки вступу з усіма видами дивних латинських символів, а також деякими тегами HTML, які мені знадобилися перевести у корисний формат імен файлів, обмежених тире. Я поєднав відповідь @ SoLoGHoST з декількома пунктами з відповіді @ Xeoncross і трохи налаштував.

    function sanitize($string,$force_lowercase=true) {
    //Clean up titles for filenames
    $clean = strip_tags($string);
    $clean = strtr($clean, array('Š' => 'S','Ž' => 'Z','š' => 's','ž' => 'z','Ÿ' => 'Y','À' => 'A','Á' => 'A','Â' => 'A','Ã' => 'A','Ä' => 'A','Å' => 'A','Ç' => 'C','È' => 'E','É' => 'E','Ê' => 'E','Ë' => 'E','Ì' => 'I','Í' => 'I','Î' => 'I','Ï' => 'I','Ñ' => 'N','Ò' => 'O','Ó' => 'O','Ô' => 'O','Õ' => 'O','Ö' => 'O','Ø' => 'O','Ù' => 'U','Ú' => 'U','Û' => 'U','Ü' => 'U','Ý' => 'Y','à' => 'a','á' => 'a','â' => 'a','ã' => 'a','ä' => 'a','å' => 'a','ç' => 'c','è' => 'e','é' => 'e','ê' => 'e','ë' => 'e','ì' => 'i','í' => 'i','î' => 'i','ï' => 'i','ñ' => 'n','ò' => 'o','ó' => 'o','ô' => 'o','õ' => 'o','ö' => 'o','ø' => 'o','ù' => 'u','ú' => 'u','û' => 'u','ü' => 'u','ý' => 'y','ÿ' => 'y'));
    $clean = strtr($clean, array('Þ' => 'TH', 'þ' => 'th', 'Ð' => 'DH', 'ð' => 'dh', 'ß' => 'ss', 'Œ' => 'OE', 'œ' => 'oe', 'Æ' => 'AE', 'æ' => 'ae', 'µ' => 'u','—' => '-'));
    $clean = str_replace("--", "-", preg_replace("/[^a-z0-9-]/i", "", preg_replace(array('/\s/', '/[^\w-\.\-]/'), array('-', ''), $clean)));

    return ($force_lowercase) ?
        (function_exists('mb_strtolower')) ?
            mb_strtolower($clean, 'UTF-8') :
            strtolower($clean) :
        $clean;
}

Мені потрібно було вручну додати символ перекладу (-) до масиву перекладу. Можуть бути й інші, але поки мої імена файлів виглядають добре.

Так:

Частина 1: "Журбурти" мого батька? - вони (не) найкращі!

стає:

частина-1-мій тато-зурбуртс-вони-не-найкращі

Я просто додаю ".html" до повернутого рядка.


1
Досі відсутні деякі чеські та словацькі символи:'ľ' => 'l', 'Ľ' => 'L', 'č' => 'c', 'Č' => 'C', 'ť' => 't', 'Ť' => 'T', 'ň' => 'n', 'Ň' => 'N', 'ĺ' => 'l', 'Ĺ' => 'L', 'Ř' => 'R', 'ř' => 'r', 'ě' => 'e', 'Ě' => 'E', 'ů' => 'u', 'Ů' => 'U'
Jasom Dotnet

1
І без сумніву, ще багато. Я насправді намагаюся з'ясувати, чи існує ISO-набір, який включає комбінації символів. Як "обирати" один набір, якщо вміст вимагає символів від усіх них? UTF-8 Я припускаю ...
cbmtrx

Я дізнався, як транслітерувати будь-який рядок, використовуючи один рядок PHP : $string = transliterator_transliterate('Any-Latin;Latin-ASCII;', $string);Дивіться мою відповідь нижче або читайте пов’язане повідомлення в блозі.
Ясом Дотнет

1
Ні, ви неправильно прочитали: ЯКЩО ви можете встановити розширення PHP на свій сервер (або хостинг) :-) Ось повідомлення .
Jasom Dotnet

1
Ах, зрозумів. Дякую @JasomDotnet - У мене зараз працює рішення, але це обмежений набір символів, тому розширення варто перевірити.
cbmtrx

2

Рішення №1: Ви можете встановити розширення PHP на сервер (хостинг)

Для транслітерації "майже кожної мови на планеті Земля" до символів ASCII.

  1. Спершу встановіть розширення PHP Intl . Це команда для Debian (Ubuntu):sudo aptitude install php5-intl

  2. Це моя функція fileName (створіть test.php і вставте туди наступний код):

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test</title>
</head>
<body>
<?php

function pr($string) {
  print '<hr>';
  print '"' . fileName($string) . '"';
  print '<br>';
  print '"' . $string . '"';
}

function fileName($string) {
  // remove html tags
  $clean = strip_tags($string);
  // transliterate
  $clean = transliterator_transliterate('Any-Latin;Latin-ASCII;', $clean);
  // remove non-number and non-letter characters
  $clean = str_replace('--', '-', preg_replace('/[^a-z0-9-\_]/i', '', preg_replace(array(
    '/\s/', 
    '/[^\w-\.\-]/'
  ), array(
    '_', 
    ''
  ), $clean)));
  // replace '-' for '_'
  $clean = strtr($clean, array(
    '-' => '_'
  ));
  // remove double '__'
  $positionInString = stripos($clean, '__');
  while ($positionInString !== false) {
    $clean = str_replace('__', '_', $clean);
    $positionInString = stripos($clean, '__');
  }
  // remove '_' from the end and beginning of the string
  $clean = rtrim(ltrim($clean, '_'), '_');
  // lowercase the string
  return strtolower($clean);
}
pr('_replace(\'~&([a-z]{1,2})(ac134/56f4315981743 8765475[]lt7ňl2ú5äňú138yé73ťž7ýľute|');
pr(htmlspecialchars('<script>alert(\'hacked\')</script>'));
pr('Álix----_Ãxel!?!?');
pr('áéíóúÁÉÍÓÚ');
pr('üÿÄËÏÖÜ.ŸåÅ');
pr('nie4č a a§ôňäääaš');
pr('Мао Цзэдун');
pr('毛泽东');
pr('ماو تسي تونغ');
pr('مائو تسه‌تونگ');
pr('מאו דזה-דונג');
pr('მაო ძედუნი');
pr('Mao Trạch Đông');
pr('毛澤東');
pr('เหมา เจ๋อตง');
?>
</body>
</html>

Цей рядок є основним:

  // transliterate
  $clean = transliterator_transliterate('Any-Latin;Latin-ASCII;', $clean);

Відповідь на основі цієї публікації .

Рішення №2: у вас немає можливості встановлювати розширення PHP на сервер (хостинг)

введіть тут опис зображення

Досить гарна робота робиться в модулі транслітерації для CMS Drupal. Він підтримує майже кожну мову на планеті Земля. Я пропоную перевірити сховище плагінів, якщо ви хочете мати дійсно повне рішення щодо санітарних рядків.



1

Це хороша функція:

public function getFriendlyURL($string) {
    setlocale(LC_CTYPE, 'en_US.UTF8');
    $string = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $string);
    $string = preg_replace('~[^\-\pL\pN\s]+~u', '-', $string);
    $string = str_replace(' ', '-', $string);
    $string = trim($string, "-");
    $string = strtolower($string);
    return $string;
} 

Це виглядає погано. \\s+означає зворотну косу рису, яку супроводжує одна або кілька пробілів. Про що це? Крім того, для цього використовується чорний список, а не білий список, ігноруючи такі речі, як CMDnull або BEL.
Xeoncross

Ще погано. Тепер рядки на зразок /blog/2014-02/just-in-timeзаборонені. Будь ласка, використовуйте тестований код вище або використовуйте phunctionрамковий код PHP.
Xeoncross

Це вірно. Ця функція призначена лише для частини "щойно". Може бути корисним для деяких людей.
joan16v

1
Можна змінити регулярний виразpreg_replace('~[^\-\pL\pN\s]+~u', '-', $string)
Xeoncross

Дивовижно! Я також додав: string = обрізка ($ string, "-");
joan16v

0

Це код, який Prestashop використовує для очищення URL-адрес:

replaceAccentedChars

використовується

str2url

для зняття діакритики

function replaceAccentedChars($str)
{
    $patterns = array(
        /* Lowercase */
        '/[\x{0105}\x{00E0}\x{00E1}\x{00E2}\x{00E3}\x{00E4}\x{00E5}]/u',
        '/[\x{00E7}\x{010D}\x{0107}]/u',
        '/[\x{010F}]/u',
        '/[\x{00E8}\x{00E9}\x{00EA}\x{00EB}\x{011B}\x{0119}]/u',
        '/[\x{00EC}\x{00ED}\x{00EE}\x{00EF}]/u',
        '/[\x{0142}\x{013E}\x{013A}]/u',
        '/[\x{00F1}\x{0148}]/u',
        '/[\x{00F2}\x{00F3}\x{00F4}\x{00F5}\x{00F6}\x{00F8}]/u',
        '/[\x{0159}\x{0155}]/u',
        '/[\x{015B}\x{0161}]/u',
        '/[\x{00DF}]/u',
        '/[\x{0165}]/u',
        '/[\x{00F9}\x{00FA}\x{00FB}\x{00FC}\x{016F}]/u',
        '/[\x{00FD}\x{00FF}]/u',
        '/[\x{017C}\x{017A}\x{017E}]/u',
        '/[\x{00E6}]/u',
        '/[\x{0153}]/u',

        /* Uppercase */
        '/[\x{0104}\x{00C0}\x{00C1}\x{00C2}\x{00C3}\x{00C4}\x{00C5}]/u',
        '/[\x{00C7}\x{010C}\x{0106}]/u',
        '/[\x{010E}]/u',
        '/[\x{00C8}\x{00C9}\x{00CA}\x{00CB}\x{011A}\x{0118}]/u',
        '/[\x{0141}\x{013D}\x{0139}]/u',
        '/[\x{00D1}\x{0147}]/u',
        '/[\x{00D3}]/u',
        '/[\x{0158}\x{0154}]/u',
        '/[\x{015A}\x{0160}]/u',
        '/[\x{0164}]/u',
        '/[\x{00D9}\x{00DA}\x{00DB}\x{00DC}\x{016E}]/u',
        '/[\x{017B}\x{0179}\x{017D}]/u',
        '/[\x{00C6}]/u',
        '/[\x{0152}]/u');

    $replacements = array(
            'a', 'c', 'd', 'e', 'i', 'l', 'n', 'o', 'r', 's', 'ss', 't', 'u', 'y', 'z', 'ae', 'oe',
            'A', 'C', 'D', 'E', 'L', 'N', 'O', 'R', 'S', 'T', 'U', 'Z', 'AE', 'OE'
        );

    return preg_replace($patterns, $replacements, $str);
}

function str2url($str)
{
    if (function_exists('mb_strtolower'))
        $str = mb_strtolower($str, 'utf-8');

    $str = trim($str);
    if (!function_exists('mb_strtolower'))
        $str = replaceAccentedChars($str);

    // Remove all non-whitelist chars.
    $str = preg_replace('/[^a-zA-Z0-9\s\'\:\/\[\]-\pL]/u', '', $str);
    $str = preg_replace('/[\s\'\:\/\[\]-]+/', ' ', $str);
    $str = str_replace(array(' ', '/'), '-', $str);

    // If it was not possible to lowercase the string with mb_strtolower, we do it after the transformations.
    // This way we lose fewer special chars.
    if (!function_exists('mb_strtolower'))
        $str = strtolower($str);

    return $str;
}


-4
// CLEAN ILLEGAL CHARACTERS
function clean_filename($source_file)
{
    $search[] = " ";
    $search[] = "&";
    $search[] = "$";
    $search[] = ",";
    $search[] = "!";
    $search[] = "@";
    $search[] = "#";
    $search[] = "^";
    $search[] = "(";
    $search[] = ")";
    $search[] = "+";
    $search[] = "=";
    $search[] = "[";
    $search[] = "]";

    $replace[] = "_";
    $replace[] = "and";
    $replace[] = "S";
    $replace[] = "_";
    $replace[] = "";
    $replace[] = "";
    $replace[] = "";
    $replace[] = "";
    $replace[] = "";
    $replace[] = "";
    $replace[] = "";
    $replace[] = "";
    $replace[] = "";
    $replace[] = "";

    return str_replace($search,$replace,$source_file);

} 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.