Saya mencoba untuk menemukan fungsi yang melakukan pekerjaan yang baik untuk membersihkan string tertentu sehingga aman digunakan di URL (seperti siput pos) dan juga aman digunakan sebagai nama file. Misalnya, ketika seseorang mengupload file, saya ingin memastikan bahwa saya menghapus semua karakter berbahaya dari namanya.
Sejauh ini saya telah menemukan fungsi berikut yang saya harap dapat memecahkan masalah ini dan juga memungkinkan data UTF-8 asing.
/**
* 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');
}
Adakah yang punya data sampel rumit yang dapat saya gunakan untuk melawan ini - atau mengetahui cara yang lebih baik untuk melindungi aplikasi kita dari nama yang buruk?
$ is-filename memungkinkan beberapa karakter tambahan seperti file temp vim
pembaruan: menghapus karakter bintang karena saya tidak dapat memikirkan penggunaan yang valid
sumber
Jawaban:
Beberapa pengamatan tentang solusi Anda:
Menciptakan siput
Anda mungkin tidak boleh memasukkan karakter beraksen dll dalam siput posting Anda karena, secara teknis, mereka harus dikodekan persen (per aturan pengkodean URL) sehingga Anda akan memiliki URL yang terlihat jelek.
Jadi, jika saya jadi Anda, setelah huruf kecil, saya akan mengonversi karakter 'khusus' apa pun ke padanannya (misalnya é -> e) dan mengganti karakter non [az] dengan '-', membatasi berjalannya satu '-' seperti yang Anda lakukan. Ada implementasi untuk mengonversi karakter khusus di sini: https://web.archive.org/web/20130208144021/http://neo22s.com/slug
Sanitasi secara umum
OWASP memiliki implementasi PHP untuk Enterprise Security API mereka yang antara lain mencakup metode untuk encoding dan decoding input dan output yang aman dalam aplikasi Anda.
Antarmuka Encoder menyediakan:
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
sumber
สังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่.txt
dan kemudian membuat file HTML UTF-8 dengan tautan ke sana. Hebatnya itu berhasil - bahkan di windows! Namun, saya kemudian memiliki PHPfile_put_contents('สังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่.txt')
dan gagal membuat nama file bazaar dari string itu. Kemudian saya mencoba membuatnya denganfopen()
dan mendapatkan nama file yang sama. Jadi rupanya PHP (setidaknya di windows) tidak mampu membuat nama file UTF-8. bugs.php.net/bug.php?id=46990&thanks=6Saya menemukan fungsi yang lebih besar ini dalam kode 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; }
dan yang ini di kode 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); }
Perbarui Sept 2012
Alix Axel telah melakukan beberapa pekerjaan luar biasa di bidang ini. Kerangka kerja fungsinya mencakup beberapa filter dan transformasi teks yang hebat.
sumber
apply_filters
/[\s-]+/
dengan-
yang lebih baik dari versi pertama (yang hanya menggantikan/\s+/
) yang dapat menyebabkan beberapa tanda hubung berturutIni harus membuat nama file Anda aman ...
$string = preg_replace(array('/\s/', '/\.[\.]+/', '/[^\w_\.\-]/'), array('_', '.', ''), $string);
dan solusi yang lebih dalam untuk ini adalah:
// 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);
Ini mengasumsikan bahwa Anda menginginkan titik di nama file. kalau mau dipindahkan ke huruf kecil, pakai saja
untuk baris terakhir.
sumber
'ľ' => 'l', 'Ľ' => 'L', 'č' => 'c', 'Č' => 'C', 'ť' => 't', 'Ť' => 'T', 'ň' => 'n', 'Ň' => 'N', 'ĺ' => 'l', 'Ĺ' => 'L', 'Ř' => 'R', 'ř' => 'r', 'ě' => 'e', 'Ě' => 'E', 'ů' => 'u', 'Ů' => 'U'
Coba ini:
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
Berdasarkan jawaban yang dipilih di utas ini: Nama Pengguna URL Ramah di PHP?
sumber
trim()
seharusnya juga begitutrim($string, '-')
.preg_replace()
harus menghapus semua karakter berbahaya.Ini bukan jawaban yang tepat karena belum memberikan solusi apa pun (belum!), Tapi terlalu besar untuk muat dalam komentar ...
Saya melakukan beberapa pengujian (mengenai nama file) pada Windows 7 dan Ubuntu 12.04 dan yang saya temukan adalah:
1. PHP Tidak Dapat Menangani Nama File non-ASCII
Meskipun Windows dan Ubuntu dapat menangani nama file Unicode (bahkan yang RTL seperti yang terlihat) PHP 5.3 memerlukan peretasan untuk menangani bahkan dengan ISO-8859-1 yang biasa saja, jadi lebih baik menyimpannya ASCII hanya untuk keamanan.
2. The Lenght of the Filename Matters (Khusus di Windows)
Di Ubuntu, panjang maksimum nama file yang dapat dimiliki (termasuk ekstensi) adalah 255 (tidak termasuk jalur):
/var/www/uploads/123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345/
Namun, pada Windows 7 (NTFS), panjang maksimum nama file bergantung pada jalur absolutnya:
(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
Wikipedia mengatakan bahwa:
Sejauh pengetahuan saya (dan pengujian), ini salah.
Secara total (menghitung garis miring) semua contoh ini memiliki 259 karakter, jika Anda menghapus
C:\
yang memberikan 256 karakter (bukan 255 ?!). Direktori di mana dibuat menggunakan Explorer dan Anda akan melihat bahwa itu menahan diri dari menggunakan semua ruang yang tersedia untuk nama direktori. Alasannya adalah untuk memungkinkan pembuatan file menggunakan konvensi penamaan file 8.3 . Hal yang sama terjadi untuk partisi lain.File tidak perlu memiliki persyaratan panjang 8.3 tentu saja:
(255 chars) E:\12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901.txt
Anda tidak dapat membuat lebih banyak sub-direktori jika path absolut dari direktori induk memiliki lebih dari 242 karakter, karena
256 = 242 + 1 + \ + 8 + . + 3
. Dengan menggunakan Windows Explorer, Anda tidak dapat membuat direktori lain jika direktori induk memiliki lebih dari 233 karakter (tergantung pada sistem lokal), karena256 = 233 + 10 + \ + 8 + . + 3
; yang10
di sini adalah panjang stringNew folder
.Sistem file Windows menimbulkan masalah besar jika Anda ingin memastikan interoperabilitas antar sistem file.
3. Waspadai Karakter dan Kata Kunci yang Dicadangkan
Selain menghapus karakter non-ASCII, tidak dapat dicetak, dan kontrol , Anda juga perlu kembali (tempat / pindahkan):
"*/:<>?\|
Hanya menghapus karakter ini mungkin bukan ide terbaik karena nama file mungkin kehilangan sebagian artinya. Saya pikir, setidaknya, beberapa kemunculan karakter ini harus diganti dengan satu garis bawah (
_
), atau mungkin sesuatu yang lebih representatif (ini hanya sebuah ide):"*?
->_
/\|
->-
:
->[ ]-[ ]
<
->(
>
->)
Ada juga kata kunci khusus yang harus dihindari (like
NUL
), walaupun saya tidak yakin bagaimana cara mengatasinya. Mungkin daftar hitam dengan penggantian nama acak akan menjadi pendekatan yang baik untuk menyelesaikannya.4. Sensitivitas Kasus
Ini seharusnya tidak perlu dikatakan lagi, tetapi jika Anda ingin memastikan keunikan file di berbagai sistem operasi yang berbeda Anda harus mengubah nama file menjadi kasus yang dinormalisasi, dengan cara itu
my_file.txt
danMy_File.txt
di Linux tidak akan keduanya menjadimy_file.txt
file yang sama di Windows.5. Pastikan Itu Unik
Jika nama file sudah ada, pengenal unik harus ditambahkan ke nama file dasarnya.
Pengenal unik yang umum termasuk stempel waktu UNIX, intisari konten file, atau string acak.
6. File Tersembunyi
Hanya karena bisa diberi nama bukan berarti harus ...
Titik biasanya tercantum dalam daftar putih dalam nama file, tetapi di Linux, file tersembunyi diwakili oleh titik di depan.
7. Pertimbangan Lain
Jika Anda harus menghapus beberapa karakter dari nama file, ekstensi biasanya lebih penting daripada nama dasar file. Membiarkan sejumlah besar karakter maksimum untuk ekstensi file (8-16) seseorang harus menghapus karakter dari nama dasar. Penting juga untuk dicatat bahwa jika memiliki lebih dari satu ekstensi panjang - seperti
_.graphmlz.tag.gz
-_.graphmlz.tag
hanya_
harus dianggap sebagai nama basis file dalam kasus ini.8. Sumberdaya
Kaliber menangani nama file yang rusak dengan cukup baik:
Halaman Wikipedia tentang mangling nama file dan bab terkait dari Menggunakan Samba .
Misalnya, jika Anda mencoba membuat file yang melanggar salah satu aturan 1/2/3, Anda akan mendapatkan kesalahan yang sangat berguna:
Warning: touch(): Unable to create file ... because No error in ... on line ...
sumber
Saya selalu berpikir Kohana melakukan pekerjaannya dengan cukup baik .
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); }
Berguna
UTF8::transliterate_to_ascii()
akan mengubah hal-hal seperti ñ => n.Tentu saja, Anda bisa mengganti
UTF8::*
barang lain dengan fungsi mb_ *.sumber
Dalam hal unggahan file, paling aman Anda adalah mencegah pengguna mengontrol nama file. Seperti yang telah diisyaratkan, simpan nama file yang dikanonikalisasi dalam database bersama dengan nama yang dipilih secara acak dan unik yang akan Anda gunakan sebagai nama file yang sebenarnya.
Menggunakan OWASP ESAPI, nama-nama ini dapat dibuat sebagai berikut:
Anda dapat menambahkan stempel waktu ke $ safeFilename untuk membantu memastikan bahwa nama file yang dibuat secara acak itu unik bahkan tanpa memeriksa file yang ada.
Dalam hal pengkodean untuk URL, dan sekali lagi menggunakan ESAPI:
Metode ini melakukan kanonikalisasi sebelum mengenkode string dan akan menangani semua encoding karakter.
sumber
Saya merekomendasikan * URLify untuk PHP (480+ bintang di Github) - "port PHP URLify.js dari proyek Django. Menerjemahkan karakter non-ascii untuk digunakan dalam URL".
Penggunaan dasar:
Untuk menghasilkan siput untuk 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" ?>
Untuk menghasilkan siput untuk nama file:
<?php echo URLify::filter ('фото.jpg', 60, "", true); // "foto.jpg" ?>
* Tidak ada saran lain yang cocok dengan kriteria saya:
Sebagai bonus, URLify juga menghapus kata-kata tertentu dan menghapus semua karakter yang tidak ditransliterasi.
Berikut adalah kasus uji dengan banyak karakter asing yang ditransliterasi dengan benar menggunakan URLify: https://gist.github.com/motin/a65e6c1cc303e46900d10894bf2da87f
sumber
Saya telah mengadaptasi dari sumber lain dan menambahkan beberapa tambahan, mungkin sedikit berlebihan
/** * 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; }
sumber
dan ini adalah versi 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)); }
sumber
Menurut saya memiliki daftar karakter untuk dihapus tidak aman. Saya lebih suka menggunakan yang berikut ini:
Untuk nama file: Gunakan ID internal atau hash dari konten file. Simpan nama dokumen dalam database. Dengan cara ini Anda dapat menyimpan nama file asli dan tetap menemukan file tersebut.
Untuk parameter url: Gunakan
urlencode()
untuk menyandikan karakter khusus apa pun.sumber
Bergantung pada bagaimana Anda akan menggunakannya, Anda mungkin ingin menambahkan batas panjang untuk melindungi dari buffer overflows.
sumber
Ini adalah cara yang bagus untuk mengamankan nama file unggahan:
$file_name = trim(basename(stripslashes($name)), ".\x00..\x20");
sumber
.\x00..\x20
dapat direduksi menjadi.\x00\x20
..\x00..\x20
menghapus titik-titik dan setiap karakter antara\x00
dan\x20
, sedangkan.\x00\x20
seharusnya hanya menghapus 3 byte tersebut.Berikut implementasi 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)); }
Dan
remove_invisible_characters
ketergantungan.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; }
sumber
mengapa tidak menggunakan php saja
urlencode
? itu menggantikan karakter "berbahaya" dengan representasi hex mereka untuk url (yaitu%20
untuk spasi)sumber
Sudah ada beberapa solusi yang disediakan untuk pertanyaan ini tetapi saya telah membaca dan menguji sebagian besar kode di sini dan saya berakhir dengan solusi ini yang merupakan campuran dari apa yang saya pelajari di sini:
Fungsinya
Fungsi ini dibundel di sini dalam bundel Symfony2 tetapi dapat diekstrak untuk digunakan sebagai PHP biasa , itu hanya memiliki ketergantungan dengan
iconv
fungsi yang harus diaktifkan: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; } }
Tes unit
Yang menarik adalah saya telah membuat tes PHPUnit, pertama untuk menguji kasus edge dan Anda dapat memeriksa apakah itu sesuai dengan kebutuhan Anda: (Jika Anda menemukan bug, silakan tambahkan kasus uji)
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'); } }
Hasil pengujian: (diperiksa di Ubuntu dengan PHP 5.3.2 dan MacOsX dengan 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)
sumber
Saya memiliki judul entri dengan semua jenis karakter latin yang aneh serta beberapa tag HTML yang perlu saya terjemahkan ke dalam format nama file yang dipisahkan tanda hubung. Saya menggabungkan jawaban @ SoLoGHoST dengan beberapa item dari jawaban @ Xeoncross dan menyesuaikan sedikit.
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; }
Saya perlu menambahkan karakter em dash (-) ke array terjemahan secara manual. Mungkin ada yang lain, tetapi sejauh ini nama file saya terlihat bagus.
Begitu:
Bagian 1: "Žurburts" ayahku? - mereka (bukan) yang terbaik!
menjadi:
bagian-1-ayah-saya-zurburts-mereka-bukan-yang-terbaik
Saya hanya menambahkan ".html" ke string yang dikembalikan.
sumber
'ľ' => 'l', 'Ľ' => 'L', 'č' => 'c', 'Č' => 'C', 'ť' => 't', 'Ť' => 'T', 'ň' => 'n', 'Ň' => 'N', 'ĺ' => 'l', 'Ĺ' => 'L', 'Ř' => 'R', 'ř' => 'r', 'ě' => 'e', 'Ě' => 'E', 'ů' => 'u', 'Ů' => 'U'
$string = transliterator_transliterate('Any-Latin;Latin-ASCII;', $string);
Lihat jawaban saya di bawah ini atau baca posting blog yang ditautkan.Solusi # 1: Anda memiliki kemampuan untuk menginstal ekstensi PHP di server (hosting)
Untuk transliterasi dari "hampir setiap bahasa di planet Bumi" ke karakter ASCII.
Instal ekstensi PHP Intl terlebih dahulu. Ini adalah perintah untuk Debian (Ubuntu):
sudo aptitude install php5-intl
Ini adalah fungsi nama file saya (buat test.php dan tempelkan kode berikut di sana):
<!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>
Baris ini adalah inti:
// transliterate $clean = transliterator_transliterate('Any-Latin;Latin-ASCII;', $clean);
Jawaban berdasarkan posting ini .
Solusi # 2: Anda tidak memiliki kemampuan untuk menginstal ekstensi PHP di server (hosting)
Pekerjaan yang cukup bagus dilakukan dalam modul transliterasi untuk CMS Drupal. Ini mendukung hampir setiap bahasa di planet Bumi. Saya sarankan untuk memeriksa repositori plugin jika Anda ingin memiliki solusi yang benar-benar lengkap membersihkan string.
sumber
Posting ini tampaknya bekerja paling baik di antara semua yang telah saya ikat. http://gsynuh.com/php-string-filename-url-safe/205
sumber
Ini adalah fungsi yang bagus:
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; }
sumber
\\s+
berarti garis miring terbalik diikuti dengan satu atau lebih spasi. Tentang apa itu? Selain itu, ini menggunakan daftar hitam daripada memasukkan daftar putih mengabaikan hal-hal sepertiCMD
, null, atauBEL
./blog/2014-02/just-in-time
tidak diperbolehkan. Silakan gunakan kode yang diuji di atas atau gunakanphunction
kode kerangka PHP.preg_replace('~[^\-\pL\pN\s]+~u', '-', $string)
Ini adalah kode yang digunakan oleh PrestaShop untuk membersihkan url:
digunakan oleh
untuk menghilangkan diakritik
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; }
sumber
Ada 2 jawaban bagus untuk memangkas data Anda, gunakan https://stackoverflow.com/a/3987966/971619 atau https://stackoverflow.com/a/7610586/971619
sumber
// 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); }
sumber