ファイル名の文字列サニタイザー


113

文字列をサニタイズし、ファイル名に使用できるようにするphp関数を探しています。誰かが便利なものを知っていますか?

(書けますが、キャラクターを見逃してしまうのではないかと心配です!)

編集:Windows NTFSファイルシステムにファイルを保存します。


1
より具体的に言えますか:ウムラウトで何が起こりますか(削除またはベースキャラクターに変換しますか?)特殊文字で何が起こりますか?
ペッカ

どのファイルシステムですか?それらは異なります。en.wikipedia.org/wiki/…を
Gordon

Windows :) 15文字必要です。
user151841

1
可能性のあるすべての望ましくない文字をチェックすることは不可能であるため、一部の回答で提案されている「ブラックリスト」ソリューションでは不十分であることを指摘しておきます(特殊文字に加えて、アクセントやウムラウトを含む文字があり、全体が非英語/ラテン語のアルファベット、制御文字などを処理する)。したがって、「ホワイトリスト」アプローチの方が常に優れており、文字列を正規化すると(ドミニクロジャーの回答に関するブレアマクミランのコメントで示唆されているように)、アクセント、ウムラウトなどの文字を自然に処理できるようになります
Sean the Bean

おそらく正規表現を使用する良い方法です。私が作成した次のpythonスクリプトを参照してください:github.com/gsscoder/normalize-fn
gsscoder

回答:


41

文字を見落とすことを心配する代わりに、使用して喜んでいる文字のホワイトリストを使用するのはどうですか?たとえば、あなただけの古き良き可能性がありa-z0-9_、および期間(の単一のインスタンス.)。これは明らかにほとんどのファイルシステムよりも制限がありますが、あなたを安全に保つはずです。


40
ウムラウトを使用する言語には適していません。これにより、ケベックではケベック、デュッセルドルフではデュッセルドルフなどになります。
Pekka

15
確かに-しかし私が言ったように:「例えば」。
ドミニクロジャー2010年

5
これはOPに完全に受け入れられるかもしれません。それ以外の場合は、php.net / manual / en / class.normalizer.php
Blair McMillan

3
それは実際に尋ねられたことではありません。opは、代替ではなく文字列をサニタイズする関数を要求します。
i.am.michiel 2013

3
@ i.am.michiel、たぶん、しかしOPがそれを受け入れたなら、私は彼らがそれが役に立ったと思ったと思います。
ドミニクロジャー2013

157

ドミニク・ロジャーが気づいた問題を修正するためにTor Valamoのソリューションを少し調整すると、次のように使用できます。

// 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
私は正規表現中毒が大好きです!-_〜
AVProgrammer

2
@ iim.hlk-はい、ラッピング括弧がありませんでした。今追加しました。ありがとう!
Sean Vieira 2013年

2
そこに欠陥があります。それを2つに分割して、..後でチェックを実行する必要があります。たとえば、.?.最終的にになり..ます。あなたがフィルター/をかけているので、今それをどのように活用するかはわかりませんが、..ここではチェックが効果がない理由を示しています。おそらくより良いですが、置き換えないでください。適格でない場合は拒否してください。
falstro 2014年

2
Windowsファイルシステムではこれらの値はどれも違法ではなく、なぜ必要以上の情報を失うのですか?[^a-z0-9_-]本当に制限したい場合は、正規表現を単純に変更できます。または、生成された名前を使用して、指定された名前を破棄しこれらすべての問題を回避できます。:-)
Sean Vieira

3
注意:は違法です。
JasonXA 2016年

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)' />

そのため、人気のあるCMSソフトウェアのWordpressはそれらを削除しますが、いくつかの更新を行った後にのみ、関連するすべての文字をカバーしました

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

最後に、それらのリストには、URI予約文字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文字をエンコードするかどうかを決定できます。ただし、Webホスティングコンテキストで使用されるすべてのファイルシステムでUTF-8が許可されているため、これは必要ありません。

あなたがしなければならない唯一のことは使用することですurlencode()(あなたがうまくいけばあなたはすべてのURLでそれをするので)、ファイル名საბეჭდი_მანქანა.jpgはあなた<img src>またはとして次のURLになります<a href>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.jpg

Stackoverflowがそれを行うので、ユーザーが行うようにこのリンクを投稿できます。http
//www.maxrev.de/html/img/საბეჭდი_მანქანა。jpg

これは完全な法的ファイル名とされるようではない問題として彼の答えで述べた@ SequenceDigitale.com


3
よくやった。私にとって最も役立つ答え。+1

ああ...この機能はうまく機能しますが、しばらくすると、すべてのキャラクターの間に配置され始めましたr-u-l-e-s。確かにそれは機能のせいではなく、ただ尋ねるだけです-そのような振る舞いの理由は何でしょうか?エンコードが間違っていますか?

1
まあ...デバッグを行っただけで、の直後に発生preg_replacefilter_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. Éàûなどの外来のアクセントをhtmlエンティティに変換して削除し、コードを削除して文字を保持します。
  6. スペースをダッシュ​​に置き換えます
  7. 前の手順を通過し、サーバー上で競合するファイル名を入力する可能性がある特殊文字をエンコードします。例。「中文百强网」
  8. "%"をダッシュ​​に置き換えて、ファイルのクエリ時にブラウザがファイルのリンクを書き換えないようにします。

OK、一部のファイル名は関連しませんが、ほとんどの場合は機能します。

例。元の名前:「საბეჭდი-და-ტიპოგრაფიული。jpg」

出力名:「-E1-83-A1-E1-83-90-E1-83-91-E1-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-A4-E1-83-98-E1-83-A3-E1-83-9A-E1-83-98.jpg」

404エラーよりもその方がいいです。

お役に立てば幸いです。

カール。


1
NULLおよび制御文字は削除しません。文字列から0〜32のASCIIをすべて削除する必要があります。
バジルムーサ

UTF-8はファイルシステムで許可されており、URLでも許可されているのに、なぜ404エラーが発生するのでしょうか。あなたがする必要がある唯一のものはURLを符号化することであるhttp://www.maxrev.de/html/img/საბეჭდი_მანქანა.jpghttp://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.jpgあなたがうまくいけば、すべてのURLを行うとHTMLのソースコードに。
mgutt 2017

1
その他のポイント:HTMLタグを削除しstrip_tags()、その後を削除し[<>]ます。それによってstrip_tags()実際にはまったく必要ありません。同じ点が引用です。でデコードしても引用符は残りませんENT_QUOTES。そして、str_replace()連続する空白を削除せずstrtolower()、マルチバイト文字列に使用します。そして、なぜ小文字に変換するのですか?そして最後に、@ BasilMusaが言及したように、予約文字をキャッチしませんでした。私の回答の詳細:stackoverflow.com/a/42058764/318765
mgutt

それに恋した!
Yash Kumar Verma 2017

39

ソリューション1-シンプルで効果的

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

  • strtolower()は、ファイル名が小文字であることを保証します(URL内では大文字と小文字は区別されないため、NTFSファイル名で)
  • [^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/08/md5_tutorial.htmlの平方根は、現在のWebサイズよりもはるかに大きいですが、衝突が発生した場合は、ページを予期していたときにBritney Spearsに関するページが表示されます。 Bugzillaについて。おそらく私たちのケースでは問題ではありませんが、何十億ものページについては、SHA 256などのはるかに大きなハッシュアルゴリズムを選択するか、完全に回避します。出典:boyter.org/2013/01/code-for-a-search-engine-in-php-part-1
adilbo 2018

15

さて、tempnam()が代わりにやってくれます。

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

しかし、それはまったく新しい名前を作成します。

既存の文字列をサニタイズするには、ユーザーが入力できるものを制限し、文字、数字、ピリオド、ハイフン、アンダースコアにしてから、単純な正規表現でサニタイズします。エスケープする必要がある文字を確認してください。そうしないと、誤検知が発生する可能性があります。

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

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

システムで許可されているものに応じて、さらに有効な文字を追加/削除します。

または、ファイルを作成して、それが悪い場合はエラーを返すこともできます。


5
これは..、問題のある場合とない場合のあるのようなファイル名を許可します。
ドミニクロジャー

@Dom-固定値であるため、個別に確認してください。
Tor Valamo、2010年

10

PHPは、テキストを別の形式にサニタイズする機能を提供します

filter.filters.sanitize

方法 :

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

ブロッククォート LoremIpsumhasbeentheindustry's


1
良いですが、スラッシュは削除されません。これは問題になる可能性があります:ディレクトリトラバーシング。
func0der

6

次の式は、きれいで使いやすい文字列を作成します。

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

今日の財務を変える:請求書今日の金融請求に


ファイル名にピリオドやアンダースコアなどを含めることはできませんか?
Tor Valamo、2010年

2
@ジョナサン-イタリックとは何ですか?
ドミニクロジャー

@トール、はい、ごめんなさい。更新しました。@Dominic、テキストを強調するだけ。
サンプソン

ギズムとは?「警告:preg_replace()[function.preg-replace]:不明な修飾子 'g'」が表示されます
user151841

1
@ user151841 preg_replaceグローバルフラグは暗黙的です。したがって、preg_replaceが使用されている場合は、gは必要ありません。置換の数を制御する場合、preg_replaceにはそのためのlimitパラメーターがあります。詳細については、preg_replaceのドキュメントをご覧ください。
rineez 2014

6

単一のドットを可能にするためにSean Vieiraのソリューションを少し調整すると、次のように使用できます。

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

6

安全:NOT "a-zA-Z0-9_-"のすべてのシーケンスをダッシュ​​に置き換えます。自分で拡張子を追加します。

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

1
"。"で区切られたファイル拡張子を追加する必要があります:$ name = preg_replace( '/ [^ a-zA-Z0-9 _-] + /'、 '-'、strtolower($ name))。 '。' 。$ extension;
スミス

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を作成します。以下は使用例です。注:この例には、概念実証として不正なtar.gz拡張が含まれています。ホワイトリストに対して文字列が作成された後も、extをフィルタリングする必要があります。

$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

今日私が知っているのは、Netteフレームワークの静的メソッドStrings :: webalizeです。

ところで、これはすべての分音記号を基本に変換します。š=> sü=> uß=> ssなど

ファイル名については、ドット「。」を追加する必要があります。許可された文字パラメータに。

/**
 * 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で問題を抱えているだけで、現在使用されているファイルシステムは、(XBOXで使用される)FATXあるen.wikipedia.org/wiki/Comparison_of_file_systems#Limits Webサーバで使用され、私はこれを考えていない
mgutt

1

これはすべて問題にかかっているようです。サーバーにハッキングするために使用できるファイル名を作成することは可能ですか(または、その他のダメージを与えることができます)。そうでない場合は、最終的に使用する場所にファイルを作成してみることで簡単に解決できるようです(間違いなく、これが選択したオペレーティングシステムになるためです)。オペレーティングシステムに分類させます。不満がある場合は、そのエラーを検証エラーとしてユーザーに移植します。

これには、確実に移植可能であるという追加の利点があります。これは、そのOSのファイル名が適切に形成されていない場合、すべての(かなり確信している)オペレーティングシステムが文句を言うからです。

それは場合である以下のファイル名の完全な「衛生」よりも複雑な施策-ファイル名で極悪非道なことを行うことができ、おそらく常駐のオペレーティング・システム上のファイル名をテストする前に適用することができ措置があります。


0

一方通行

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

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

}
echo sanitize($string,$bad);

印刷できない文字はどうですか?この場合、ブラックリストアプローチよりもホワイトリストアプローチを使用することをお勧めします。基本的に、もちろん特殊文字を除いて、印刷可能なASCIIファイル名のみを許可します。しかし、英語以外のロケールの場合、それは別の問題です。
TheRealChx101 2018年

0

/そして..、ユーザーが指定したファイル名には有害な可能性があります。したがって、次のような方法でこれらを取り除く必要があります。

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

これでは不十分です!たとえば、ファイル名「./.name」は現在のディレクトリから抜け出します。(ここでは..を削除しても何も
起こり

3
@ cemper93いいえ、この答えは..name、何も壊れない文字列に変えるだけです。すべてのパス区切り文字を削除することで、ディレクトリトラバーサルを防止できます。(の削除..は技術的に不要です。)
cdhowie

@cdhowieはい、ただしファイル名はに./.なり..ます。そして最後に、この回答はNULLのような他のすべてのファイルシステム予約文字を見逃しています。私の回答の詳細:stackoverflow.com/a/42058764/318765
mgutt

-4

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

ユーザーはスラッシュを使用して2つの単語を区切る場合があるため、NULLの代わりにダッシュに置き換える方が良いでしょう。


彼がNULLに置き換えられると言われているのはどこですか?また、これはすべての特殊文字を処理するわけではありません。
Travis Pessetto 2013

うん-あまりにも処理を必要とする他の特殊文字があります。とにかく、ここではstr_replaceが最善の入札とはなりません。
Martin Kovachev 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.