फ़ाइल नाम के लिए स्ट्रिंग सैनिटाइज़र


113

मैं एक php फंक्शन की तलाश में हूँ जो एक स्ट्रिंग को सैनिटाइज़ करेगा और इसे एक फ़ाइल नाम के लिए उपयोग करने के लिए तैयार करेगा। किसी को भी एक काम का पता है?

(मैं एक लिख सकता था, लेकिन मुझे चिंता है कि मैं एक चरित्र को देख लूंगा!)

संपादित करें: Windows NTFS फाइल सिस्टम पर फाइलों को सहेजने के लिए।


1
क्या आप अधिक विशिष्ट हो सकते हैं: उमलाट्स के साथ क्या होना है (आधार वर्ण को हटाएं या परिवर्तित करें?) विशेष वर्णों के साथ क्या होना है?
पेका

किस फाइलसिस्टम के लिए? वे अलग हैं। देखें en.wikipedia.org/wiki/...
गॉर्डन

Windows :) 15 वर्णों की आवश्यकता है।
user151841

1
मैं यह बताना चाहता हूं कि कुछ उत्तरों में सुझाए गए "ब्लैकलिस्ट" समाधान पर्याप्त नहीं हैं, क्योंकि यह हर संभव अवांछनीय चरित्र (विशेष वर्णों के अलावा, लहजे और umlauts के साथ वर्णों के लिए जाँच करने के लिए संभव है) गैर-अंग्रेजी / लैटिन वर्णमाला, नियंत्रण वर्ण, आदि से निपटने के लिए)। इसलिए मेरा तर्क है कि "वाइटेलिस्ट" दृष्टिकोण हमेशा बेहतर होता है, और स्ट्रिंग को सामान्य करता है (जैसा कि ब्लेयर मैकमिलन की डोमिनिक रॉजर के जवाब पर टिप्पणी द्वारा सुझाया गया है) लहजे, umlauts, आदि के साथ किसी भी पत्र के प्राकृतिक हैंडलिंग के लिए अनुमति देगा
सीन बीन

नियमित रूप से अभिव्यक्ति का उपयोग करने का एक अच्छा तरीका, इस अजगर स्क्रिप्ट को देखें जिसे मैंने बनाया था: github.com/gsscoder/normalize-fn
gsscoder

जवाबों:


42

पात्रों की अनदेखी के बारे में चिंता करने के बजाय - कैसे पात्रों के श्वेतसूची का उपयोग करने के बारे में आप उपयोग किए जाने से खुश हैं? उदाहरण के लिए, तुम सिर्फ अच्छा ol अनुमति दे सकता है ' a-z, 0-9, _, और अवधि का एक उदाहरण ( .)। यह स्पष्ट रूप से अधिकांश फाइल सिस्टम की तुलना में अधिक सीमित है, लेकिन आपको सुरक्षित रखना चाहिए।


40
उमलाट्स वाली भाषाओं के लिए अच्छा नहीं है। इसके परिणामस्वरूप क्यूबेक के लिए क्यूबेक, डसेलडोर्फ के लिए डसेलडोर्फ, और इसी तरह के अन्य परिणाम होंगे।
पकाका

15
सच - लेकिन जैसा मैंने कहा: "उदाहरण के लिए"।
डोमिनिक रॉजर

5
जो ओपी के लिए पूरी तरह स्वीकार्य हो सकता है। अन्यथा, php.net/manual/en/class.normalizer.php
ब्लेयर मैकमिलन

3
जो वास्तव में नहीं पूछा गया था। सेशन स्ट्रिंग को सैनिटाइज करने के लिए एक फंक्शन मांगता है, न कि कोई विकल्प।
I..m.michiel

3
@ i.am.michiel, शायद, लेकिन ओपी ने इसे स्वीकार कर लिया, मुझे लगता है कि वे इसे मददगार पाएंगे।
डोमिनिक रॉगर

157

डोमिनिक रॉजर द्वारा देखी गई समस्या को ठीक करने के लिए टोर वालोमा के समाधान के लिए एक छोटा सा समायोजन करना, आप उपयोग कर सकते हैं:

// Remove anything which isn't a word, whitespace, number
// or any of the following caracters -_~,;[]().
// If you don't need to handle multi-byte characters
// you can use preg_replace rather than mb_ereg_replace
// Thanks @Łukasz Rysiak!
$file = mb_ereg_replace("([^\w\s\d\-_~,;\[\]\(\).])", '', $file);
// Remove any runs of periods (thanks falstro!)
$file = mb_ereg_replace("([\.]{2,})", '', $file);

43
मैं regex नशेड़ियों से प्यार करता हूँ! -_ ~
AVProgrammer

2
@ iim.hlk - हाँ, यह रैपिंग कोष्ठक गायब था। मैंने अब उन्हें जोड़ा है। धन्यवाद!
सीन विएरा

2
वहाँ एक दोष है, आपको इसे दो में विभाजित करना चाहिए और ..बाद में चेक चलाना चाहिए । उदाहरण के लिए .?.समाप्त हो जाएगा ..। हालाँकि जब से आप फ़िल्टर करते हैं, तो /मैं यह नहीं देख सकता कि आप उस समय का और अधिक दोहन कैसे करेंगे, लेकिन यह दिखाता है कि ..यहाँ चेक अप्रभावी क्यों है। बेहतर अभी तक शायद, बदल नहीं है, सिर्फ अगर यह योग्य नहीं है अस्वीकार।
फॉल्सट्रो

2
क्योंकि उन में से कोई भी मूल्य विंडोज फाइल सिस्टम पर अवैध नहीं है और आपकी तुलना में अधिक जानकारी क्यों ढीली है? आप नियमित अभिव्यक्ति को बदल सकते हैं बस [^a-z0-9_-]अगर आप वास्तव में प्रतिबंधात्मक होना चाहते हैं - या बस एक उत्पन्न नाम का उपयोग करें और दिए गए नाम को फेंक दें और इन सभी समस्याओं से बचें । :-)
सीन विएरा

3
ध्यान दें: अवैध है।
जेसनएक्सए

49

यह है कि आप एक फ़ाइल सिस्टम के लिए कैसे पूछ सकते हैं

function filter_filename($name) {
    // remove illegal file system characters https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words
    $name = str_replace(array_merge(
        array_map('chr', range(0, 31)),
        array('<', '>', ':', '"', '/', '\\', '|', '?', '*')
    ), '', $name);
    // maximise filename length to 255 bytes http://serverfault.com/a/9548/44086
    $ext = pathinfo($name, PATHINFO_EXTENSION);
    $name= mb_strcut(pathinfo($name, PATHINFO_FILENAME), 0, 255 - ($ext ? strlen($ext) + 1 : 0), mb_detect_encoding($name)) . ($ext ? '.' . $ext : '');
    return $name;
}

एक फाइलसिस्टम में बाकी सभी चीजों की अनुमति है, इसलिए प्रश्न पूरी तरह से उत्तर दिया गया है ...

... लेकिन फ़ाइल नाम में एकल उद्धरण के लिए अनुमति देना खतरनाक हो सकता है 'यदि आप इसे बाद में असुरक्षित HTML संदर्भ में उपयोग करते हैं क्योंकि यह बिल्कुल कानूनी फ़ाइल नाम है:

 ' onerror= 'alert(document.cookie).jpg

एक XSS छेद बन जाता है :

<img src='<? echo $image ?>' />
// output:
<img src=' ' onerror= 'alert(document.cookie)' />

उसके कारण, लोकप्रिय सीएमएस सॉफ्टवेयर Wordpress उन्हें हटा देता है, लेकिन उन्होंने कुछ अपडेट के बाद ही सभी प्रासंगिक वर्णों को कवर किया :

$special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", "%", "+", chr(0));
// ... a few rows later are whitespaces removed as well ...
preg_replace( '/[\r\n\t -]+/', '-', $filename )

अंत में उनकी सूची में अब वे अधिकांश वर्ण शामिल हैं जो URI rerserved-characters और URL असुरक्षित वर्णों का हिस्सा हैं सूची का हिस्सा हैं।

बेशक आप बस HTML आउटपुट पर इन सभी वर्णों को एन्कोड कर सकते हैं, लेकिन अधिकांश डेवलपर्स और मुझे भी, मुहावरे का पालन करें "सॉरी से बेहतर" और उन्हें पहले से हटा दें।

तो अंत में मैं इसका उपयोग करने का सुझाव दूंगा:

function filter_filename($filename, $beautify=true) {
    // sanitize filename
    $filename = preg_replace(
        '~
        [<>:"/\\|?*]|            # file system reserved https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words
        [\x00-\x1F]|             # control characters http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx
        [\x7F\xA0\xAD]|          # non-printing characters DEL, NO-BREAK SPACE, SOFT HYPHEN
        [#\[\]@!$&\'()+,;=]|     # URI reserved https://tools.ietf.org/html/rfc3986#section-2.2
        [{}^\~`]                 # URL unsafe characters https://www.ietf.org/rfc/rfc1738.txt
        ~x',
        '-', $filename);
    // avoids ".", ".." or ".hiddenFiles"
    $filename = ltrim($filename, '.-');
    // optional beautification
    if ($beautify) $filename = beautify_filename($filename);
    // maximize filename length to 255 bytes http://serverfault.com/a/9548/44086
    $ext = pathinfo($filename, PATHINFO_EXTENSION);
    $filename = mb_strcut(pathinfo($filename, PATHINFO_FILENAME), 0, 255 - ($ext ? strlen($ext) + 1 : 0), mb_detect_encoding($filename)) . ($ext ? '.' . $ext : '');
    return $filename;
}

सब कुछ जो फ़ाइल सिस्टम के साथ समस्याएं पैदा नहीं करता है, एक अतिरिक्त फ़ंक्शन का हिस्सा होना चाहिए:

function beautify_filename($filename) {
    // reduce consecutive characters
    $filename = preg_replace(array(
        // "file   name.zip" becomes "file-name.zip"
        '/ +/',
        // "file___name.zip" becomes "file-name.zip"
        '/_+/',
        // "file---name.zip" becomes "file-name.zip"
        '/-+/'
    ), '-', $filename);
    $filename = preg_replace(array(
        // "file--.--.-.--name.zip" becomes "file.name.zip"
        '/-*\.-*/',
        // "file...name..zip" becomes "file.name.zip"
        '/\.{2,}/'
    ), '.', $filename);
    // lowercase for windows/unix interoperability http://support.microsoft.com/kb/100625
    $filename = mb_strtolower($filename, mb_detect_encoding($filename));
    // ".file-name.-" becomes "file-name"
    $filename = trim($filename, '.-');
    return $filename;
}

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

केवल एक चीज जो आपको करनी है, वह है urlencode()(जैसा कि आप उम्मीद करते हैं कि यह आपके सभी URL के साथ है) इसलिए फ़ाइल नाम საბეჭდი_მანქანა.jpgइस URL के रूप में आपके <img src>या <a href>: http://www.maxrev.de/html/img/%E1%83% पर आता है ए 1% ई 1% 83% 90% ई 1% 83% 91% ई 1% 83% 94% ई 1% 83% ई% ई 1% 83% 93% ई 1% 83% 98_% ई 1% 83% 9B% ई 1% 83% 90% ई 1% 83% 9% ई 1% 83% A5% ई 1% 83% 90% ई 1% 83% 9% ई 1% 83% 90.jpg

Stackoverflow करता है, इसलिए मैं इस लिंक को पोस्ट कर सकता हूं क्योंकि एक उपयोगकर्ता यह करेगा:
http://www.maxrev.de/html/img/ im_მანქანა। Jpg

तो यह पूरी तरह से कानूनी फ़ाइल नाम और है नहीं एक समस्या के रूप में अपने जवाब में बताया गया @ SequenceDigitale.com


3
बहुत बढ़िया। मेरे लिए सबसे मददगार जवाब। +1

ओह ... यह फ़ंक्शन अच्छी तरह से काम करता है, लेकिन कुछ समय के बाद से यह शुरू हुआ - हर चरित्र के बीच, जैसे r-u-l-e-sऔर मुझे नहीं पता कि ऐसा क्यों होता है। यकीन है कि यह फ़ंक्शन की गलती नहीं है, लेकिन बस पूछ रहा है - इस तरह के व्यवहार का कारण क्या हो सकता है? गलत एन्कोडिंग?

1
ओह ठीक है ... बस एक डिबग बनाया और यह बस के बाद होता preg_replaceहै filter_filename()

इन टिप्पणियों को हटाने के बाद, इसने फिर से काम करना शुरू कर दिया।

आपने कौन सी टिप्पणियाँ निकालीं? अगर यह आसान है तो मुझे एक ईमेल भेजें: gutt.it/contact.htm
mgutt

43

Rawurlencode () का उपयोग करने के बारे में क्या? http://www.php.net/manual/en/function.rawurlencode.php

यहां एक समारोह है जो चीनी चार्ट को भी साफ करता है:

public static function normalizeString ($str = '')
{
    $str = strip_tags($str); 
    $str = preg_replace('/[\r\n\t ]+/', ' ', $str);
    $str = preg_replace('/[\"\*\/\:\<\>\?\'\|]+/', ' ', $str);
    $str = strtolower($str);
    $str = html_entity_decode( $str, ENT_QUOTES, "utf-8" );
    $str = htmlentities($str, ENT_QUOTES, "utf-8");
    $str = preg_replace("/(&)([a-z])([a-z]+;)/i", '$2', $str);
    $str = str_replace(' ', '-', $str);
    $str = rawurlencode($str);
    $str = str_replace('%', '-', $str);
    return $str;
}

यहाँ व्याख्या है

  1. HTML टैग्स को स्ट्रिप करें
  2. ब्रेक / टैब्स / रिटर्न कैरिज निकालें
  3. फ़ोल्डर और फ़ाइल नाम के लिए अवैध चार्ट निकालें
  4. स्ट्रिंग को लोअर केस में रखें
  5. Removeàû जैसे विदेशी लहजे को html संस्थाओं में रूपांतरित करके निकालें और फिर कोड हटाकर पत्र रखें।
  6. स्थान को डैश के साथ बदलें
  7. विशेष वर्णों को एनकोड करें जो पिछले चरणों को पारित कर सकते हैं और सर्वर पर संघर्ष फ़ाइल नाम में दर्ज कर सकते हैं। पूर्व। "中文 百强 网"
  8. यह सुनिश्चित करने के लिए कि फ़ाइल को लिंक करते समय "%" को डैश के साथ बदलें, फ़ाइल का लिंक ब्राउज़र द्वारा फिर से नहीं लिखा जाएगा।

ठीक है, कुछ फ़ाइलनाम releavant नहीं होगा लेकिन ज्यादातर मामलों में यह काम करेगा।

पूर्व। मूल नाम: "Name-და-:। Jpg"

आउटपुट नाम: "-E1-83- A1-83-90-90- E1-83-91-91-83-94- E1-83-AD-E1-83-93-E1-83-98 - E1- 83-93-E1-83-90 - E1-83-A2-E1-83-98-E1-83-9E-E1-83-9D-E1-83-92-E1-83-A0-E1-83 -90-E1-83-ए 4-E1-83-98-E1-83-ए 3-E1-83-9A-E1-83-98.jpg "

यह 404 त्रुटि की तरह बेहतर है।

आशा है कि सहायक था।

कार्ल।


1
आप NULL और Control वर्ण नहीं निकाल रहे हैं। 0 से 32 के ASCII को स्ट्रिंग से हटा दिया जाना चाहिए।
तुलसी मूसा

फ़ाइल सिस्टम में UTF-8 की अनुमति है और इसे URL में अनुमति दी गई है, इसलिए इसे 404 त्रुटि क्यों उत्पन्न करनी चाहिए? केवल एक चीज आपको बस इतना करना यूआरएल एन्कोड करने के लिए है http://www.maxrev.de/html/img/საბეჭდი_მანქანა.jpgकरने के लिए http://www.maxrev.de/html/img/%E1%83%A1%E1%83%90%E1%83%91%E1%83%94%E1%83%AD%E1%83%93%E1%83%98_%E1%83%9B%E1%83%90%E1%83%9C%E1%83%A5%E1%83%90%E1%83%9C%E1%83%90.jpgHTML स्रोत कोड में के रूप में आप उम्मीद है कि अपने सभी URL के साथ क्या।
mgutt

1
कुछ अन्य बिंदु: आप HTML टैग को इसके माध्यम से strip_tags()और उसके बाद हटाते हैं [<>]। कि strip_tags()वास्तव में बिल्कुल भी जरूरत नहीं है। वही बिंदु उद्धरण हैं। आपके द्वारा डिकोड किए जाने पर कोई उद्धरण नहीं बचा है ENT_QUOTES। और str_replace()लगातार सफेद रिक्त स्थान को नहीं हटाता है और फिर आप strtolower()मल्टी-बाइट स्ट्रिंग के लिए उपयोग करते हैं। और आप लोअरकेस में आखिर क्यों परिवर्तित होते हैं? और अंत में आपने @BasilMusa के रूप में किसी भी आरक्षित चरित्र को नहीं पकड़ा। मेरे जवाब में अधिक जानकारी: stackoverflow.com/a/42058764/318765
mgutt

इससे प्यार हो गया!
यश कुमार वर्मा

39

समाधान 1 - सरल और प्रभावी

$file_name = preg_replace( '/[^a-z0-9]+/', '-', strtolower( $url ) );

  • strtolower () गारंटी फ़ाइल नाम लोअरकेस है (क्योंकि मामला URL के अंदर मायने नहीं रखता है, लेकिन NTFSMenen में)
  • [^a-z0-9]+ यह सुनिश्चित करेगा कि फ़ाइल नाम केवल अक्षर और संख्या रखता है
  • '-'फ़ाइल नाम को पठनीय रखने के साथ अमान्य वर्ण

उदाहरण:

URL:  http://stackoverflow.com/questions/2021624/string-sanitizer-for-filename
File: http-stackoverflow-com-questions-2021624-string-sanitizer-for-filename

समाधान 2 - बहुत लंबे URL के लिए

आप URL सामग्री को कैश करना चाहते हैं और इसके लिए आपको केवल अद्वितीय फ़ाइल नाम रखना होगा। मैं इस फ़ंक्शन का उपयोग करूंगा:

$file_name = md5( strtolower( $url ) )

यह निश्चित लंबाई के साथ एक फ़ाइल नाम बनाएगा। MD5 हैश ज्यादातर मामलों में इस तरह के उपयोग के लिए पर्याप्त अद्वितीय है।

उदाहरण:

URL:  https://www.amazon.com/Interstellar-Matthew-McConaughey/dp/B00TU9UFTS/ref=s9_nwrsa_gw_g318_i10_r?_encoding=UTF8&fpl=fresh&pf_rd_m=ATVPDKIKX0DER&pf_rd_s=desktop-1&pf_rd_r=BS5M1H560SMAR2JDKYX3&pf_rd_r=BS5M1H560SMAR2JDKYX3&pf_rd_t=36701&pf_rd_p=6822bacc-d4f0-466d-83a8-2c5e1d703f8e&pf_rd_p=6822bacc-d4f0-466d-83a8-2c5e1d703f8e&pf_rd_i=desktop
File: 51301f3edb513f6543779c3a5433b01c

4
शायद MD5 एक समस्या से हो सकता है: URL के साथ हैश का उपयोग करते समय सावधान रहें। जबकि URL की संख्या skrenta.com/2007/2007/08/md5_tutorial.html का वर्गमूल अभी भी बहुत बड़ा है, तो वर्तमान वेब आकार यदि आप टकराव प्राप्त करते हैं तो आप ब्रिटनी स्पीयर्स के बारे में पृष्ठों को प्राप्त करने जा रहे हैं जब आप पृष्ठों की उम्मीद कर रहे थे बुग्जिला के बारे में। हमारे मामले में शायद यह एक गैर मुद्दा है, लेकिन अरबों पन्नों के लिए मैं बहुत बड़े हैशिंग एल्गोरिथ्म जैसे SHA 256 या पूरी तरह से इससे बचने का विकल्प चुनूंगा। स्रोत: boyter.org/2013/01/code-for-a-search-engine-in-php-part-1
adilbo

15

खैर, tempnam () यह आपके लिए करेगा।

http://us2.php.net/manual/en/function.tempnam.php

लेकिन यह एक पूरी तरह से नया नाम बनाता है।

एक मौजूदा स्ट्रिंग को पवित्र करने के लिए केवल अपने उपयोगकर्ताओं को दर्ज करने और इसे अक्षर, संख्या, अवधि, हाइफ़न और अंडरस्कोर बनाने के लिए प्रतिबंधित करें, फिर एक सरल रेगेक्स के साथ sanitize करें। जांच करें कि किन वर्णों से बचने की आवश्यकता है या आप झूठी सकारात्मकता प्राप्त कर सकते हैं।

$sanitized = preg_replace('/[^a-zA-Z0-9\-\._]/','', $filename);

13
preg_replace("[^\w\s\d\.\-_~,;:\[\]\(\]]", '', $file)

आपके सिस्टम के लिए अनुमति के आधार पर अधिक मान्य वर्ण जोड़ें / निकालें।

वैकल्पिक रूप से आप फ़ाइल बनाने की कोशिश कर सकते हैं और फिर खराब होने पर वापस लौटा सकते हैं।


5
यह फ़ाइल नाम के माध्यम से अनुमति देता है .., जैसे कि एक समस्या हो सकती है या नहीं।
डोमिनिक रॉगर

@Dom - बस इसके लिए अलग से जाँच करें, क्योंकि यह एक निश्चित मूल्य है।
टॉर वालामो

10

PHP एक पाठ को अलग प्रारूप में साफ करने के लिए एक फ़ंक्शन प्रदान करता है

filter.filters.sanitize

कैसे :

echo filter_var(
   "Lorem Ipsum has been the industry's",FILTER_SANITIZE_URL
); 

Blockquote LoremIpsumhasbeentheindustry's


1
अच्छा है, लेकिन यह स्लैश को दूर नहीं करेगा, जो एक समस्या हो सकती है: निर्देशिका ट्रैवर्सिंग।
func0der

7

सुरक्षित: डैश के लिए "a-zA-Z0-9_-" के हर अनुक्रम को न बदलें; स्वयं एक एक्सटेंशन जोड़ें।

$name = preg_replace('/[^a-zA-Z0-9_-]+/', '-', strtolower($name)).'.'.$extension;

1
आपको फ़ाइल एक्सटेंशन को एक "।": $ Name = preg_replace ('/ / ^ a-zA-Z0-9 _-] + /', '-', strtolower ($ name)) से जोड़ना होगा। '' । $ विस्तार;
स्मिथ

6

निम्नलिखित अभिव्यक्ति एक अच्छा, स्वच्छ और प्रयोग करने योग्य स्ट्रिंग बनाती है:

/[^a-z0-9\._-]+/gi

टर्निंग आज के वित्तीय: बिलिंग में आज-स-वित्तीय-बिलिंग


तो एक फ़ाइल नाम में एक अवधि या अंडरस्कोर, या ऐसा कुछ भी नहीं हो सकता है?
तोर वालामो

2
@ जोनाथन - इटैलिक के साथ क्या है?
डोमिनिक रॉगर

@, हाँ, क्षमा करें। अपडेट किया गया। @ मुख्य, सिर्फ पाठ पर जोर देने के लिए।
सैमप्सन

जिस्म क्या है? मुझे "चेतावनी: preg_replace () [function.preg-प्रतिस्थापित]: अज्ञात संशोधक 'जी'"
user151841

1
@ user151841 preg_replaceवैश्विक ध्वज के लिए निहित है। इसलिए अगर gg का कोई ज़रूरत नहीं है अगर preg_replace का उपयोग किया जा रहा है। जब हम प्रतिस्थापन की संख्या को नियंत्रित करना चाहते हैं तो preg_replace के लिए एक limitपैरामीटर है। अधिक के लिए preg_replace प्रलेखन पढ़ें।
rineez

6

सिंगल डॉट्स के लिए अनुमति देने के लिए सीन विएरा के समाधान के लिए एक छोटा सा समायोजन करना, आप उपयोग कर सकते हैं:

preg_replace("([^\w\s\d\.\-_~,;:\[\]\(\)]|[\.]{2,})", '', $file)

2

ये थोड़े भारी हो सकते हैं, लेकिन वे काफी लचीले होते हैं जो किसी भी स्ट्रिंग को "सुरक्षित" enस्टाइल फ़ाइलनाम या फ़ोल्डर नाम (या बिल्ली, यहां तक ​​कि अगर आप इसे झुकाते हैं, तो स्क्रब किए गए और) को साफ करें ।

1) एक पूर्ण फ़ाइल नाम का निर्माण (केस इनपुट में फ़ॉलबैक नाम पूरी तरह से छोटा है):

str_file($raw_string, $word_separator, $file_extension, $fallback_name, $length);

2) या एक पूर्ण फ़ाइल नाम के निर्माण के बिना केवल फ़िल्टर उपयोग का उपयोग करना (सख्त मोड फ़ाइल नाम में true[] या) की अनुमति नहीं देगा):

str_file_filter($string, $separator, $strict, $length);

3) और यहाँ ये कार्य हैं:

// Returns filesystem-safe string after cleaning, filtering, and trimming input
function str_file_filter(
    $str,
    $sep = '_',
    $strict = false,
    $trim = 248) {

    $str = strip_tags(htmlspecialchars_decode(strtolower($str))); // lowercase -> decode -> strip tags
    $str = str_replace("%20", ' ', $str); // convert rogue %20s into spaces
    $str = preg_replace("/%[a-z0-9]{1,2}/i", '', $str); // remove hexy things
    $str = str_replace("&nbsp;", ' ', $str); // convert all nbsp into space
    $str = preg_replace("/&#?[a-z0-9]{2,8};/i", '', $str); // remove the other non-tag things
    $str = preg_replace("/\s+/", $sep, $str); // filter multiple spaces
    $str = preg_replace("/\.+/", '.', $str); // filter multiple periods
    $str = preg_replace("/^\.+/", '', $str); // trim leading period

    if ($strict) {
        $str = preg_replace("/([^\w\d\\" . $sep . ".])/", '', $str); // only allow words and digits
    } else {
        $str = preg_replace("/([^\w\d\\" . $sep . "\[\]\(\).])/", '', $str); // allow words, digits, [], and ()
    }

    $str = preg_replace("/\\" . $sep . "+/", $sep, $str); // filter multiple separators
    $str = substr($str, 0, $trim); // trim filename to desired length, note 255 char limit on windows

    return $str;
}


// Returns full file name including fallback and extension
function str_file(
    $str,
    $sep = '_',
    $ext = '',
    $default = '',
    $trim = 248) {

    // Run $str and/or $ext through filters to clean up strings
    $str = str_file_filter($str, $sep);
    $ext = '.' . str_file_filter($ext, '', true);

    // Default file name in case all chars are trimmed from $str, then ensure there is an id at tail
    if (empty($str) && empty($default)) {
        $str = 'no_name__' . date('Y-m-d_H-m_A') . '__' . uniqid();
    } elseif (empty($str)) {
        $str = $default;
    }

    // Return completed string
    if (!empty($ext)) {
        return $str . $ext;
    } else {
        return $str;
    }
}

तो चलिए बताते हैं कुछ उपयोगकर्ता इनपुट हैं: .....&lt;div&gt;&lt;/div&gt;<script></script>&amp; Weiß Göbel 中文百强网File name %20 %20 %21 %2C Décor \/. /. . z \... y \...... x ./ “This name” is & 462^^ not &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = that grrrreat -][09]()1234747) საბეჭდი-და-ტიპოგრაფიული

और हम 255 वर्णों की फ़ाइल नाम लंबाई के साथ एक tar.gz बनाने के लिए इसे कुछ फ्रेंडली में बदलना चाहते हैं। यहाँ एक उदाहरण उपयोग है। ध्यान दें: इस उदाहरण में अवधारणा के प्रमाण के रूप में एक विकृत टारगेट एक्सटेंशन शामिल है, आपको अभी भी अपने वाइटेलिस्ट (एस) के खिलाफ स्ट्रिंग के निर्माण के बाद एक्सट्रीम को फ़िल्टर करना चाहिए।

$raw_str = '.....&lt;div&gt;&lt;/div&gt;<script></script>&amp; Weiß Göbel 中文百强网File name  %20   %20 %21 %2C Décor  \/.  /. .  z \... y \...... x ./  “This name” is & 462^^ not &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = that grrrreat -][09]()1234747) საბეჭდი-და-ტიპოგრაფიული';
$fallback_str = 'generated_' . date('Y-m-d_H-m_A');
$bad_extension = '....t&+++a()r.gz[]';

echo str_file($raw_str, '_', $bad_extension, $fallback_str);

उत्पादन होगा: _wei_gbel_file_name_dcor_._._._z_._y_._x_._this_name_is_462_not_that_grrrreat_][09]()1234747)_.tar.gz

आप इसके साथ यहां खेल सकते हैं: https://3v4l.org/iSgi8

या एक जिस्ट: https://gist.github.com/dhaupin/b109d3a8464239b7754a

संपादित करें: अद्यतन स्क्रिप्ट फ़िल्टर &nbsp;स्थान के बजाय, अद्यतन 3v4l लिंक


1

आज मुझे जो सबसे अच्छी जानकारी है वह है स्टैटिक विधि स्ट्रिंग्स :: नेटलेट फ्रेमवर्क से वेबलाइज़ करना

BTW, यह सभी diacritic संकेतों को उनके मूल .. š => s ü => u s = s s आदि से अनुवादित करता है।

फ़ाइल नाम के लिए आपको डॉट जोड़ना होगा "।" वर्ण पैरामीटर की अनुमति देने के लिए।

/**
 * Converts to ASCII.
 * @param  string  UTF-8 encoding
 * @return string  ASCII
 */
public static function toAscii($s)
{
    static $transliterator = NULL;
    if ($transliterator === NULL && class_exists('Transliterator', FALSE)) {
        $transliterator = \Transliterator::create('Any-Latin; Latin-ASCII');
    }

    $s = preg_replace('#[^\x09\x0A\x0D\x20-\x7E\xA0-\x{2FF}\x{370}-\x{10FFFF}]#u', '', $s);
    $s = strtr($s, '`\'"^~?', "\x01\x02\x03\x04\x05\x06");
    $s = str_replace(
        array("\xE2\x80\x9E", "\xE2\x80\x9C", "\xE2\x80\x9D", "\xE2\x80\x9A", "\xE2\x80\x98", "\xE2\x80\x99", "\xC2\xB0"),
        array("\x03", "\x03", "\x03", "\x02", "\x02", "\x02", "\x04"), $s
    );
    if ($transliterator !== NULL) {
        $s = $transliterator->transliterate($s);
    }
    if (ICONV_IMPL === 'glibc') {
        $s = str_replace(
            array("\xC2\xBB", "\xC2\xAB", "\xE2\x80\xA6", "\xE2\x84\xA2", "\xC2\xA9", "\xC2\xAE"),
            array('>>', '<<', '...', 'TM', '(c)', '(R)'), $s
        );
        $s = @iconv('UTF-8', 'WINDOWS-1250//TRANSLIT//IGNORE', $s); // intentionally @
        $s = strtr($s, "\xa5\xa3\xbc\x8c\xa7\x8a\xaa\x8d\x8f\x8e\xaf\xb9\xb3\xbe\x9c\x9a\xba\x9d\x9f\x9e"
            . "\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3"
            . "\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8"
            . "\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf8\xf9\xfa\xfb\xfc\xfd\xfe"
            . "\x96\xa0\x8b\x97\x9b\xa6\xad\xb7",
            'ALLSSSSTZZZallssstzzzRAAAALCCCEEEEIIDDNNOOOOxRUUUUYTsraaaalccceeeeiiddnnooooruuuuyt- <->|-.');
        $s = preg_replace('#[^\x00-\x7F]++#', '', $s);
    } else {
        $s = @iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $s); // intentionally @
    }
    $s = str_replace(array('`', "'", '"', '^', '~', '?'), '', $s);
    return strtr($s, "\x01\x02\x03\x04\x05\x06", '`\'"^~?');
}


/**
 * Converts to web safe characters [a-z0-9-] text.
 * @param  string  UTF-8 encoding
 * @param  string  allowed characters
 * @param  bool
 * @return string
 */
public static function webalize($s, $charlist = NULL, $lower = TRUE)
{
    $s = self::toAscii($s);
    if ($lower) {
        $s = strtolower($s);
    }
    $s = preg_replace('#[^a-z0-9' . preg_quote($charlist, '#') . ']+#i', '-', $s);
    $s = trim($s, '-');
    return $s;
}

तुम क्यों विकृति विज्ञान की जगह लेना चाहते हो? सीधे शब्दों में उपयोग करने urlencode()से पहले आप एक के रूप में फ़ाइल नाम का उपयोग srcया href। वर्तमान में उपयोग की जाने वाली एकमात्र फ़ाइल सिस्टम में UTF-8 की समस्या है FATx (XBOX द्वारा प्रयुक्त): en.wikipedia.org/wiki/Comparison_of_file_systems#Limits और मुझे नहीं लगता कि यह वेब सर्वरों द्वारा उपयोग किया जाता है
mgutt

1

ऐसा लगता है कि यह सब सवाल पर टिका है, क्या यह एक फ़ाइल नाम बनाना संभव है जो किसी सर्वर में हैक करने के लिए इस्तेमाल किया जा सकता है (या कुछ-ऐसे अन्य नुकसान)। यदि नहीं, तो ऐसा लगता है कि इसका सरल उत्तर यह है कि फ़ाइल को बनाने की कोशिश करें जहाँ भी, अंततः, उपयोग किया जाएगा (क्योंकि यह पसंद का ऑपरेटिंग सिस्टम होगा, इसमें कोई संदेह नहीं है)। ऑपरेटिंग सिस्टम को इसे छाँटने दें। यदि यह शिकायत करता है, तो उस शिकायत को पोर्ट करें जो उपयोगकर्ता को सत्यापन त्रुटि के रूप में वापस करता है।

यह मज़बूती से पोर्टेबल होने का अतिरिक्त लाभ है, क्योंकि सभी (मुझे पूरा यकीन है) ऑपरेटिंग सिस्टम शिकायत करेंगे कि क्या फ़ाइलनाम ठीक से उस ओएस के लिए नहीं बना है।

यदि यह है उपायों कम एक पूर्ण फ़ाइल नाम के "स्वच्छता" की तुलना में जटिल - एक फ़ाइल नाम के साथ नापाक काम करने के लिए संभव है, शायद वहाँ उपायों निवासी ऑपरेटिंग सिस्टम पर फ़ाइल नाम परीक्षण से पहले लागू किया जा सकता है।


0

एक रास्ता

$bad='/[\/:*?"<>|]/';
$string = 'fi?le*';

function sanitize($str,$pat)
{
    return preg_replace($pat,"",$str);

}
echo sanitize($string,$bad);

गैर-मुद्रण योग्य वर्णों के बारे में क्या? इस मामले में काली सूची दृष्टिकोण की तुलना में सफेद सूची दृष्टिकोण का उपयोग करना बेहतर है। मूल रूप से पाठ्यक्रम के विशेष अक्षरों को छोड़कर केवल मुद्रण योग्य ASCII फ़ाइल नाम की अनुमति दें। लेकिन गैर-अंग्रेजी स्थानों के लिए, यह एक और समस्या है।
TheRealChx101

0

/और ..उपयोगकर्ता द्वारा प्रदान की गई फ़ाइल नाम हानिकारक हो सकता है। तो आपको कुछ इस तरह से छुटकारा पाना चाहिए:

$fname = str_replace('..', '', $fname);
$fname = str_replace('/',  '', $fname);

यह अपर्याप्त है! उदाहरण के लिए, फ़ाइल नाम "./.name" अभी भी वर्तमान निर्देशिका से बाहर हो जाएगा। (हटाना .. यहाँ कुछ भी नहीं करता है, लेकिन हटाने / / ./ में बदल जाएगा .. और इसलिए लक्ष्य निर्देशिका से बाहर तोड़।)
cemper93

3
@ cemper93 नहीं, यह उत्तर केवल स्ट्रिंग को बदल देगा ..nameजिसमें कुछ भी नहीं टूटेगा। किसी भी डायरेक्टरी ट्रैवर्सल को रोकने के लिए सभी पथ विभाजक वर्णों को हटाना पर्याप्त होना चाहिए। (का निष्कासन ..तकनीकी रूप से अनावश्यक है।)
cdhowie

@ LCDhowie हाँ, लेकिन फ़ाइल नाम ./.बन जाता है ..। और अंत में यह उत्तर NULL जैसे अन्य सभी फ़ाइल सिस्टम आरक्षित वर्णों को याद करता है। मेरे जवाब में और अधिक: stackoverflow.com/a/42058764/318765
8

-4

$ fname = str_replace ('/', '', $ fname);

चूंकि उपयोगकर्ता दो शब्दों को अलग करने के लिए स्लैश का उपयोग कर सकते हैं, इसलिए NULL के बजाय डैश से बदलना बेहतर होगा


यह कहाँ कहा जाता है कि वह NULL के साथ बदल रहा होगा? इसके अलावा, यह सभी विशेष वर्णों को नहीं संभालता है।
ट्रैविस पेसेट्टो

युप - अन्य विशेष वर्ण हैं जिन्हें संभालने की भी आवश्यकता है। str_replace वैसे भी यहाँ सबसे अच्छी बोली नहीं होगी।
मार्टिन कोवाचेव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.