उन्हें 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 अस्थायी अतिरिक्त फ़ाइलों जैसे कुछ अतिरिक्त वर्णों की अनुमति देता है

अपडेट: स्टार चरित्र को हटा दिया गया क्योंकि मैं एक वैध उपयोग के बारे में नहीं सोच सकता था


आप बेहतर सब कुछ [\ w-] को छोड़कर
elias

3
आपको नॉर्मलाइज़र और उस पर टिप्पणी उपयोगी मिल सकती है।
मैट गिब्सन

जवाबों:


57

आपके समाधान पर कुछ अवलोकन:

  1. आपके पैटर्न के अंत में 'u' का मतलब है कि पैटर्न , न कि यह जो मेल खा रहा है उसे UTF-8 के रूप में व्याख्या किया जाएगा (मुझे लगता है कि आपने बाद में मान लिया था?)।
  2. \ w अंडरस्कोर वर्ण से मेल खाता है। आप इसे विशेष रूप से उन फ़ाइलों के लिए शामिल करते हैं, जो इस धारणा की ओर ले जाती हैं कि आप उन्हें URL में नहीं चाहते हैं, लेकिन कोड में आपके पास URLs को एक अंडरस्कोर शामिल करने की अनुमति होगी।
  3. "विदेशी UTF-8" का समावेश स्थानीय-निर्भर प्रतीत होता है। यह स्पष्ट नहीं है कि यह सर्वर या क्लाइंट का स्थान है। PHP डॉक्स से:

एक "शब्द" वर्ण किसी भी अक्षर या अंक या अंडरस्कोर वर्ण है, अर्थात्, कोई भी चरित्र जो एक पर्ल शब्द का हिस्सा हो सकता है "। अक्षरों और अंकों की परिभाषा पीसीआरई के चरित्र तालिकाओं द्वारा नियंत्रित की जाती है, और यदि लोकेल-विशिष्ट मिलान हो रहा है, तो यह भिन्न हो सकता है। उदाहरण के लिए, "fr" (फ्रांसीसी) स्थान में, 128 से अधिक वर्ण कोड उच्चारण अक्षरों के लिए उपयोग किए जाते हैं, और ये \ w द्वारा मेल खाते हैं।

स्लग बनाना

संभवतः आपको अपने पोस्ट स्लग में उच्चारण आदि के अक्षर शामिल नहीं करने चाहिए, क्योंकि तकनीकी रूप से, उन्हें प्रतिशत एन्कोडेड (प्रति URL एन्कोडिंग नियम) होना चाहिए, ताकि आपके पास बदसूरत दिखने वाले URL हों।

इसलिए, यदि मैं लोअरस्किंग करने के बाद, मैं किसी भी 'विशेष' वर्ण को उनके समकक्ष (जैसे é -> e) में बदल दूंगा और गैर [az] वर्णों को '-' के साथ बदल दूंगा, तो एकल '' के रनों तक सीमित रहूँगा। जैसा आपने किया है। यहाँ विशेष वर्णों को परिवर्तित करने का कार्यान्वयन है: https://web.archive.org/web/20130208144021/http://neo22s.com/slug

सामान्य रूप से स्वच्छता

OWASP के पास अपने एंटरप्राइज़ सिक्योरिटी API का PHP कार्यान्वयन है, जिसमें अन्य बातों के अलावा आपके एप्लिकेशन में सुरक्षित एन्कोडिंग और डिकोडिंग इनपुट और आउटपुट के तरीके शामिल हैं।

एनकोडर इंटरफ़ेस प्रदान करता है:

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


आप "यू" संशोधक की मेरी धारणा के बारे में सही हैं - मैंने सोचा कि यह पाठ के लिए था। मैं अंडरस्कोर सहित \ w संशोधक के बारे में भी भूल गया। मैं आमतौर पर सभी उच्चारण पात्रों को ASCII में परिवर्तित करूंगा - लेकिन मैं चाहता हूं कि यह अन्य भाषाओं के लिए भी काम करे। मैं यह मान रहा था कि किसी प्रकार का UTF-8 सुरक्षित तरीका होगा जिससे किसी भाषा के किसी भी चरित्र का उपयोग URL स्लग या फ़ाइल नाम में किया जा सके ताकि अरबी शीर्षक भी काम करें। आखिरकार, Linux UTF-8 फ़ाइलनाम का समर्थन करता है और ब्राउज़रों को आवश्यकतानुसार HTML लिंक को एनकोड करना चाहिए । यहाँ आपके इनपुट के लिए बड़ा धन्यवाद।
Xeoncross

दूसरे विचार पर, आप वास्तव में सही हैं, लेकिन यह ब्राउज़र के साथ लिंक को सही ढंग से एन्कोडिंग करने का मुद्दा नहीं है। आप जो चाहते हैं, उसके करीब पहुंचने का सबसे आसान तरीका है, गैर-एएससीआईआई पात्रों को उनके निकटतम एएससीआईआई के समकक्ष मैप करना और फिर एचटीएमएल निकाय में आपके लिंक को URL-एनकोड करना। मुश्किल तरीके से अपने वेब सर्वर, अनुप्रयोग परत (PHP), पृष्ठ सामग्री, वेब ब्राउज़र के माध्यम से संगत UTF-8 एन्कोडिंग सुनिश्चित अपने डेटा की दुकान से (या UTF-16, मैं कुछ चीनी बोलियों के लिए लगता है), और करने के लिए है नहीं अपने यूआरएल urlencode ( लेकिन अभी भी 'अवांछनीय' वर्णों को छीनते हैं)। यह आपको अच्छे गैर-एन्कोडेड लिंक और URL देगा।
एलन डोनेली

अच्छी सलाह। मैं एक शुद्ध UTF-8 वातावरण बनाने की कोशिश करने जा रहा हूं। फिर, गैर-ASCII भाषाओं से कई स्ट्रिंग्स लेते हुए, मैं खतरनाक वर्ण (./ ?: आदि ...) को हटा दूंगा और उन फ़ाइलों को HTML लिंक बनाता हूं और यह देखने के लिए कि क्या मैं उन्हें क्लिक कर सकता हूं और देख सकता हूं कि क्या यह सब काम करता है। यदि नहीं, तो मुझे UTF-8 की अनुमति देने के लिए (कच्चे) urlencode () पर वापस जाना होगा। मैं यहाँ वापस परिणाम पोस्ट करेंगे।
Xeoncross

3
मैंने एक फाइल बनाई है, जिसे สังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่.txtबनाया है और फिर एक यूटीएफ -8 एचटीएमएल फाइल बनाई है, जिसमें एक लिंक है। आश्चर्यजनक रूप से इसने काम किया - खिड़कियों पर भी! हालाँकि, मेरे पास तब PHP थी file_put_contents('สังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่.txt')और यह उस स्ट्रिंग से एक बाज़ार फ़ाइल नाम बनाने में विफल रहा। फिर मैंने इसे बनाने की कोशिश की fopen()और उसी गड़बड़ को फिल्माया गया। तो जाहिरा तौर पर PHP (कम से कम विंडोज़ पर) 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;
}

और यह वर्डप्रेस कोड में एक है

/**
 * 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
के रूप में यह का उपयोग करता है वर्डप्रेस कोड पोर्टेबल नहीं हैapply_filters
केविन मार्क

1
ध्यान दें कि वर्डप्रेस वर्शन के स्थान पर /[\s-]+/साथ -जो पहले संस्करण की तुलना में बेहतर (जो केवल बदल देता है /\s+/) कि लगातार एक से अधिक डैश पैदा कर सकता है
Yotam ओमर

बस संदर्भ के लिए wordpress apply_filters यहाँ पाया जा सकता है और sanitize_file_name यहाँ पर
एरिक

कई स्थानों के बारे में क्या? बदलें
जेफरी जिराफ

8
$ गुदा-परिवर्तनीय मुझे बल-विकल्प के साथ बहुत भयावह लगता है।
विल्जुन

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'
जसोम डॉटनेट

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

इस थ्रेड में चयनित उत्तर के आधार पर: PHP में URL फ्रेंडली यूजरनेम?


बहुत अच्छा - मैंने इसे अनुवाद तालिका के बिना कभी नहीं देखा है (जैसे कि वर्डप्रेस उपयोग करता है)। हालाँकि, मुझे नहीं लगता कि यह फ़ंक्शन पर्याप्त है क्योंकि यह केवल विशेष वर्णों का अनुवाद करता है लेकिन खतरनाक पात्रों को नहीं हटाता है। हो सकता है कि इसे ऊपर एक जोड़ा जा सकता है ...
Xeoncross

4
हा! यह इकाई एन्कोडिंग हैक मीठा है! हालाँकि यह पहली नज़र में बिलकुल भी स्पष्ट नहीं है कि यह तरीका क्या करता है। हालांकि एक समस्या है। "फ्रेडेरिक एंड एरिक" "फ्रेडेरिक amp एरिक" में नहीं बदलेगा?
एलन डोनली

@AlanDonnelly: वास्तव में, मैंने अपने मूल उत्तर (लिंक की जाँच करें) में फ़ंक्शन को अपडेट किया है, यह trim()भी होना चाहिए trim($string, '-')
एलिक्स एक्सल

@Xeoncross: आखिरी में preg_replace()सभी खतरनाक वर्णों को हटा देना चाहिए।
एलिक्स एक्सल

@AlixAxel, आपका हर जगह बस आप नहीं हैं। मैं सिर्फ PHP AWS SDK पर पढ़ रहा था और उनके पास UUID के लिए आपका कुछ कोड था। Phunction का भयानक कोड सिर्फ हरा करना मुश्किल है।
Xeoncross

13

यह वास्तव में एक जवाब नहीं है क्योंकि यह कोई समाधान नहीं प्रदान करता है (अभी तक!), लेकिन यह एक टिप्पणी पर फिट होने के लिए बहुत बड़ा है ...


मैंने विंडोज 7 और उबंटू 12.04 पर कुछ परीक्षण (फ़ाइल नामों के बारे में) किया और मुझे जो पता चला वह यह था:

1. PHP गैर-एएससीआईआई फाइलनाम को संभाल नहीं सकती है

यद्यपि विंडोज और उबंटू दोनों यूनिकोड फाइलनाम (यहां तक ​​कि आरटीएल वाले भी लगते हैं) को संभाल सकते हैं, क्योंकि PHP 5.3 को सादे पुराने ISO-8859-1 से भी निपटने के लिए हैक्स की आवश्यकता होती है, इसलिए इसे केवल सुरक्षा के लिए ASCII रखना बेहतर है।

2. फिल्नाम के मामलों का विशेषण (विशेष रूप से विंडोज पर)

उबंटू पर, फ़ाइल नाम में अधिकतम लंबाई हो सकती है (विस्तार को बढ़ाकर) 255 (पथ को छोड़कर):

/var/www/uploads/123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345/

हालाँकि, विंडोज 7 (एनटीएफएस) पर अधिकतम फ़ाइल नाम के साथ यह पूर्ण पथ पर निर्भर करता है:

(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। विंडोज एक्सप्लोरर का उपयोग करते हुए, आप एक और निर्देशिका नहीं बना सकते हैं यदि मूल निर्देशिका में 233 से अधिक वर्ण हैं (सिस्टम लोकेल के आधार पर), क्योंकि 256 = 233 + 10 + \ + 8 + . + 3; 10यहाँ स्ट्रिंग की लंबाई है New folder

यदि आप फ़ाइल सिस्टम के बीच अंतर-संचालन को आश्वस्त करना चाहते हैं, तो विंडोज फ़ाइल सिस्टम एक बुरा समस्या बन गया है।

3. आरक्षित वर्ण और खोजशब्दों से सावधान रहें

गैर-एएससीआईआई, गैर-मुद्रण योग्य और नियंत्रण पात्रों को हटाने के अलावा , आपको भी (स्थान / चाल) फिर से करने की आवश्यकता है:

"*/:<>?\|

सिर्फ इन पात्रों को हटाने का सबसे अच्छा विचार नहीं हो सकता है क्योंकि फ़ाइल नाम का अर्थ कुछ खो सकता है। मुझे लगता है कि, बहुत कम से कम, इन वर्णों की कई घटनाओं को एक एकल अंडरस्कोर ( _), या शायद कुछ और प्रतिनिधि द्वारा प्रतिस्थापित किया जाना चाहिए (यह सिर्फ एक विचार है):

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

ऐसे विशेष कीवर्ड भी हैं जिन्हें टाला जाना चाहिए (जैसे NUL), हालाँकि मुझे यकीन नहीं है कि इससे कैसे उबरें। शायद एक यादृच्छिक नाम की वापसी के साथ एक काली सूची इसे हल करने के लिए एक अच्छा तरीका होगा।

4. केस सेंसिटिविटी

यह कहे बिना जाना चाहिए, लेकिन यदि आप चाहते हैं कि विभिन्न ऑपरेटिंग सिस्टमों में फ़ाइल विशिष्टता सुनिश्चित करें तो आपको फ़ाइल नामों को एक सामान्यीकृत मामले में बदलना चाहिए, इस तरह my_file.txtऔर My_File.txtलिनक्स पर दोनों my_file.txtविंडोज पर एक ही फाइल नहीं बनेंगे ।

5. सुनिश्चित करें कि यह अद्वितीय है

यदि फ़ाइल नाम पहले से मौजूद है, तो एक विशिष्ट पहचानकर्ता को आधार फ़ाइल नाम से जोड़ा जाना चाहिए

सामान्य विशिष्ट पहचानकर्ताओं में UNIX टाइमस्टैम्प, फ़ाइल सामग्री का पाचन या एक यादृच्छिक स्ट्रिंग शामिल है।

6. छिपी हुई फाइलें

सिर्फ इसलिए कि इसका नाम दिया जा सकता है इसका मतलब यह नहीं होना चाहिए ...

डॉट्स आमतौर पर फ़ाइल नामों में सफेद-सूचीबद्ध होते हैं लेकिन लिनक्स में एक छिपी हुई फ़ाइल को एक प्रमुख डॉट द्वारा दर्शाया जाता है।

7. अन्य विचार

यदि आपको फ़ाइल नाम के कुछ वर्णों को अलग करना है, तो विस्तार आमतौर पर फ़ाइल के आधार नाम से अधिक महत्वपूर्ण होता है। फ़ाइल एक्सटेंशन (8-16) के लिए वर्णों की एक अधिकतम संख्या की अनुमति देते हुए अक्षर को आधार नाम से अलग करना चाहिए। यह भी ध्यान रखना महत्वपूर्ण है कि एक से अधिक लंबे विस्तार होने की संभावना नहीं है - जैसे कि _.graphmlz.tag.gz- _.graphmlz.tagकेवल _इस मामले में फ़ाइल आधार नाम के रूप में माना जाना चाहिए।

8. संसाधन

कैलिबर फ़ाइल नाम को बहुत शालीनता से संभालता है:

विकिपीडिया पेज पर सांबा का उपयोग करने से फ़ाइल नाम मैनिंग और जुड़ा हुआ अध्याय


यदि उदाहरण के लिए, आप एक ऐसी फाइल बनाने की कोशिश करते हैं जो किसी भी नियम 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();

आप यह सुनिश्चित करने में मदद करने के लिए $ सेफफिलनाम में टाइमस्टैम्प को जोड़ सकते हैं कि बेतरतीब ढंग से उत्पन्न फ़ाइलनाम एक मौजूदा फ़ाइल की जांच के बिना भी अद्वितीय है।

URL के लिए एन्कोडिंग के संदर्भ में, और फिर से ESAPI का उपयोग कर:

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

यह विधि स्ट्रिंग को एन्कोडिंग करने से पहले विहित करती है और सभी वर्ण एन्कोडिंग को संभाल लेगी।


निश्चित रूप से - भी, उपयोगकर्ताओं से दूर फ़ाइल नाम नियंत्रण लेने से एक ही नाम वाले 2 अपलोड की संभावना को रोका जा सकेगा।
CodeVirtuoso

5

मैं PHP के लिए * URLify (Github पर 480+ सितारों) की सलाह देता हूं - "Django प्रोजेक्ट से URLify.js का PHP पोर्ट। URLs में उपयोग के लिए गैर-एससीआई अक्षर का अनुवाद करता है"।

मूल उपयोग:

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"

?>

* अन्य सुझावों में से कोई भी मेरे मानदंडों से मेल नहीं खाता:

  • संगीतकार के माध्यम से स्थापित किया जाना चाहिए
  • आइकॉन पर निर्भर नहीं होना चाहिए क्योंकि यह अलग-अलग प्रणालियों पर अलग-अलग व्यवहार करता है
  • ओवरराइड और कस्टम चरित्र प्रतिस्थापन की अनुमति देने के लिए विस्तार योग्य होना चाहिए
  • लोकप्रिय (उदाहरण के लिए जीथब पर कई सितारे)
  • परीक्षण किया है

एक बोनस के रूप में, 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

और यह जूमला 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? यह यूआरएल के लिए अपने हेक्स प्रतिनिधित्व के साथ "खतरनाक" वर्णों को प्रतिस्थापित करता है (अर्थात %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');
    }
}

परीक्षण के परिणाम: ( PHP 5.3.27 के साथ Ubuntu 5.3.2 और MacOsX के साथ उबंटू पर जाँच की गई :

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 16

@Xeoncross मैं सहमत हूं, जैसा कि ईसाई ने कहा कि एक को एक आईडी या हैश और मूल फ़ाइल नाम को बचाना होगा। लेकिन यह फ़ंक्शन एक विकल्प प्रदान करता है क्योंकि आप एक डिफ़ॉल्ट स्ट्रिंग निर्दिष्ट कर सकते हैं जब सैनिटाइज़ प्रक्रिया विफल हो जाती है। मैंने इस मामले के लिए एक इकाई परीक्षण जोड़ा है। बग की रिपोर्ट करने के लिए धन्यवाद।
०12:

2

मेरे पास सभी प्रकार के अजीब लैटिन वर्णों के साथ ही कुछ HTML टैग्स के साथ प्रविष्टि शीर्षक हैं जिन्हें मुझे एक उपयोगी डैश-सीमांकित फ़ाइल नाम प्रारूप में अनुवाद करने की आवश्यकता थी। मैंने @ Xeoncross के उत्तर के कुछ आइटमों के साथ @ SoLoGHoST का उत्तर जोड़ा और थोड़ा अनुकूलित किया।

    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;
}

मुझे अनुवाद सरणी में मैन्युअल रूप से em डैश वर्ण (-) जोड़ने की आवश्यकता थी। कुछ और भी हो सकते हैं लेकिन अभी तक मेरे फ़ाइल नाम अच्छे दिख रहे हैं।

इसलिए:

भाग 1: मेरे पिताजी के "ururburts"? - वे (नहीं) सबसे अच्छे हैं!

हो जाता है:

भाग-1-मेरी-पिता-zurburts-वे-नहीं-सबसे अच्छा

मैं वापस दिए गए स्ट्रिंग में ".html" जोड़ता हूं।


1
अभी भी कुछ चेक और स्लोवाक पात्र गायब हैं:'ľ' => 'l', 'Ľ' => 'L', 'č' => 'c', 'Č' => 'C', 'ť' => 't', 'Ť' => 'T', 'ň' => 'n', 'Ň' => 'N', 'ĺ' => 'l', 'Ĺ' => 'L', 'Ř' => 'R', 'ř' => 'r', 'ě' => 'e', 'Ě' => 'E', 'ů' => 'u', 'Ů' => 'U'
जसोम डॉटनेट

1
और कोई संदेह नहीं है। मैं वास्तव में यह पता लगाने की कोशिश कर रहा हूं कि क्या कोई आईएसओ-सेट मौजूद है जिसमें वर्णों का संयोजन शामिल है। यदि सामग्री उन सभी से वर्णों की मांग करती है, तो कोई एक "चयन" कैसे करता है? UTF-8 मैं मान रहा हूँ ...
cbmtrx

मुझे पता चला कि PHP की एक पंक्ति का उपयोग करके किसी भी स्ट्रिंग का अनुवाद कैसे किया जाता है : $string = transliterator_transliterate('Any-Latin;Latin-ASCII;', $string);नीचे दिए गए मेरे उत्तर को देखें या लिंक किए गए ब्लॉग पोस्ट को पढ़ें।
जसोम डॉटनेट

1
नहीं, आपने इसे गलत पढ़ा है: यदि आप अपने सर्वर पर PHP एक्सटेंशन स्थापित कर सकते हैं (या होस्टिंग) :-) यहाँ पोस्ट है
जसोम डॉटनेट

1
आह, समझ गया। धन्यवाद @JasomDotnet --I के पास मेरे वर्तमान समाधान के लिए काम कर रहा है, लेकिन यह एक सीमित चरित्र सेट है, इसलिए यह विस्तार देखने लायक है।
cbmtrx

2

समाधान # 1: आपके पास सर्वर (होस्टिंग) पर PHP एक्सटेंशन स्थापित करने की क्षमता है

ASCII वर्णों के लिए "ग्रह पृथ्वी पर लगभग हर एक भाषा" के लिप्यंतरण के लिए।

  1. पहले PHP Intl एक्सटेंशन इंस्टॉल करें । यह डेबियन (उबंटू) के लिए कमांड है:sudo aptitude install php5-intl

  2. यह मेरा फाइलनेम फ़ंक्शन है (कोड के बाद 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 एक्सटेंशन स्थापित करने की क्षमता नहीं है

यहां छवि विवरण दर्ज करें

सीएमएस ड्रुपल के लिए लिप्यंतरण मॉड्यूल में बहुत अच्छा काम किया जाता है । यह पृथ्वी पर लगभग हर एक भाषा का समर्थन करता है। मैं प्लगइन रिपोजिटरी की जांच करने का सुझाव देता हूं यदि आप वास्तव में संपूर्ण समाधान को स्ट्रेटिंग करना चाहते हैं।



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+एक या अधिक व्हाट्सएप के बाद एक बैकस्लैश का अर्थ है। यह किस बारे में है? इसके अलावा, यह श्वेत सूची को अनदेखा करने की बजाय CMD, अशक्त, या BEL
Xeoncross

अभी भी बुरा है। अब जैसे तार की /blog/2014-02/just-in-timeअनुमति नहीं है। कृपया ऊपर दिए गए परीक्षण कोड का उपयोग करें या phunctionPHP फ्रेमवर्क कोड का उपयोग करें ।
Xeoncross

ये सही है। यह फ़ंक्शन केवल "जस्ट-इन-टाइम" भाग के लिए है। कुछ लोगों के लिए उपयोगी हो सकता है।
joan16v

1
आप regexpreg_replace('~[^\-\pL\pN\s]+~u', '-', $string)
Xeoncross

बहुत बढ़िया! मैंने यह भी जोड़ा: स्ट्रिंग = ट्रिम ($ स्ट्रिंग, "-");
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 Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.