URL과 파일 이름을 안전하게하기 위해 문자열을 삭제 하시겠습니까?


136

특정 문자열을 잘 처리하여 URL에서 사용하는 것이 안전하고 (포스트 슬러그와 같은) 파일 이름으로 안전하게 사용할 수있는 기능을 고안하려고합니다. 예를 들어, 누군가 파일을 업로드 할 때 이름에서 위험한 문자를 모두 제거하고 싶습니다.

지금 까지이 문제를 해결하고 외래 UTF-8 데이터도 허용하는 다음 기능을 생각해 냈습니다.

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

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

누구든지 내가 이것에 대해 실행할 수있는 까다로운 샘플 데이터를 가지고 있습니까? 아니면 나쁜 이름으로부터 앱을 보호하는 더 좋은 방법을 알고 있습니까?

$ is-filename은 temp vim 파일과 같은 추가 문자를 허용합니다

업데이트 : 유효한 사용을 생각할 수 없으므로 별표 문자를 제거했습니다.


[\ w.-]를 제외한 모든 것을 제거하는 것이 좋습니다
elias

3
당신은 찾을 수 노멀 유용한 그것에 의견을.
매트 깁슨

답변:


57

솔루션에 대한 몇 가지 관찰 사항 :

  1. 패턴의 끝에서 'u'는 일치하는 텍스트가 아닌 패턴이 UTF-8로 해석 됨을 의미합니다 (후자를 가정한다고 가정합니까?).
  2. \ w는 밑줄 문자와 일치합니다. URL에 원하지 않는 것으로 가정하는 파일에 대해 구체적으로 포함 시키지만 코드에는 URL에 밑줄을 포함 할 수 있습니다.
  3. "외부 UTF-8"의 포함은 로케일에 따라 다릅니다. 이것이 서버 또는 클라이언트의 로캘인지는 확실하지 않습니다. PHP 문서에서 :

"단어"문자는 문자 또는 숫자 또는 밑줄 문자, 즉 Perl "단어"의 일부가 될 수있는 문자입니다. 문자 및 숫자의 정의는 PCRE의 문자표로 제어되며 로케일 별 일치가 발생하는 경우 달라질 수 있습니다. 예를 들어 "fr"(프랑스어) 로캘에서 128보다 큰 일부 문자 코드는 악센트 부호 문자에 사용되며 \ w와 일치합니다.

슬러그 생성

기술적으로, URL 인코딩 규칙에 따라 백분율로 인코딩되어 못생긴 URL을 볼 수 있기 때문에 포스트 슬러그에 악센트 부호 등을 포함해서는 안됩니다.

따라서 내가 당신이라면 소문자를 뺀 후 '특수'문자를 동등한 것으로 변환하고 (예를 들어 e-> e) 비 [az] 문자를 '-'로 바꾸면 단일 '-'의 실행으로 제한됩니다 당신이 한대로. 여기에 특수 문자를 변환하는 구현이 있습니다 : https://web.archive.org/web/20130208144021/http://neo22s.com/slug

일반적으로 위생

OWASP에는 Enterprise Security 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


당신은 "u"수정 자에 대한 나의 가정에 대해 맞습니다. 나는 그것이 텍스트에 대한 것이라고 생각했습니다. 또한 밑줄을 포함하여 \ w 수정자를 잊어 버렸습니다. 나는 일반적으로 모든 강조 문자를 ASCII로 변환하지만 다른 언어에서도 작동하기를 원합니다. 아랍어 제목조차도 작동하도록 언어의 모든 문자를 URL 슬러그 또는 파일 이름에 사용할 수있는 UTF-8 안전 방법이 있다고 가정했습니다. 결국 리눅스는 UTF-8 파일 이름을 지원하며 브라우저 필요에 따라 HTML 링크를 인코딩 해야 합니다. 입력 해 주셔서 감사합니다.
Xeoncross

두 번째 생각에, 당신은 실제로 옳지 만, 링크를 올바르게 인코딩하는 브라우저의 문제는 아닙니다. 원하는 것에 가장 가까운 방법은 ASCII가 아닌 문자를 가장 가까운 ASCII 문자에 매핑 한 다음 HTML 본문에 링크를 URL 인코딩하는 것입니다. 어려운 방법은 웹 서버, 응용 프로그램 계층 (PHP), 페이지 내용, 웹 브라우저를 통해 데이터 저장소에서 일관된 UTF-8 인코딩 (또는 UTF-16, 일부 중국 방언으로 생각)을 보장하고 URL을 urlencode 하지 않습니다 ( 여전히 '불필요한'문자를 제거하십시오). 이렇게하면 인코딩되지 않은 멋진 링크와 URL이 제공됩니다.
Alan Donnelly

좋은 조언. 순수한 UTF-8 환경을 만들려고합니다. 그런 다음 비 ASCII 언어에서 여러 문자열을 가져 와서 위험한 문자 (./ ;: etc ...)를 제거하고 파일을 만든 다음 해당 파일에 대한 HTML 링크를 클릭하여 해당 파일을 클릭하여 확인할 수 있는지 확인합니다. 공장. 그렇지 않으면 아마도 UTF-8을 허용하기 위해 (raw)? urlencode ()로 다시 돌아 가야 할 것입니다. 여기에 결과를 다시 게시하겠습니다.
Xeoncross

3
라는 파일 สังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่.txt을 만든 다음 링크가있는 UTF-8 HTML 파일을 만들었습니다. 놀랍게도 그것은 심지어 창문에서도 작동했습니다! 그러나 PHP를 사용 file_put_contents('สังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่.txt')하여 해당 문자열에서 바자 파일 이름을 만들지 못했습니다. 그런 다음 그것을 사용 fopen()하여 동일한 엉망인 파일 이름을 얻었습니다. 따라서 PHP (적어도 Windows에서는)는 UTF-8 파일 이름을 만들 수 없습니다. bugs.php.net/bug.php?id=46990&thanks=6
Xeoncross 2016

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 년 9 월 업데이트

Alix Axel 은이 분야에서 놀라운 일을했습니다. 그의 문장 구조에는 몇 가지 훌륭한 텍스트 필터와 변형이 포함되어 있습니다.


23
WordPress 코드는 사용하기 때문에 이식성이 없습니다.apply_filters
Kevin Mark

1
워드 프레스 버전을 대체하는 것이 주 /[\s-]+/-있는이 (만 대체하는 첫 번째 버전보다 더 /\s+/행에 여러 대시를 일으킬 수)
Yotam 오메르

참고 용으로 wordpress apply_filters를 찾을 수 있습니다. 여기 있고 sanitize_file_name이 여기 있습니다 .
Eric

여러 공간은 어떻습니까? 교체
기린 제프리

8
$ anal 변수는 힘 옵션으로 무섭게 들립니다.
viljun

30

이것은 파일 이름을 안전하게 만들어야합니다 ...

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

이에 대한 더 깊은 해결책은 다음과 같습니다.

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

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

파일 이름에 점이 필요하다고 가정합니다. 소문자로 전송하려면 다음을 사용하십시오.

$clean_name = strtolower($clean_name);

마지막 줄에.


1
여전히 체코 어와 슬로바키아어 문자가 일부 누락되었습니다.'ľ' => 'l', 'Ľ' => 'L', 'č' => 'c', 'Č' => 'C', 'ť' => 't', 'Ť' => 'T', 'ň' => 'n', 'Ň' => 'N', 'ĺ' => 'l', 'Ĺ' => 'L', 'Ř' => 'R', 'ř' => 'r', 'ě' => 'e', 'Ě' => 'E', 'ů' => 'u', 'Ů' => 'U'
Jasom Dotnet

22

이 시도:

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

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

Examples:

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

이 글에서 선택된 답변을 바탕으로 : PHP의 URL Friendly Username?


매우 훌륭합니다-워드 프레스와 같은 변환 표 없이는 이것을 본 적이 없습니다. 그러나이 기능은 특수 문자 만 번역하지만 위험한 문자는 제거하지 않기 때문에 충분하지 않다고 생각합니다. 어쩌면 그것은 위에 추가 할 수 있습니다 ...
Xeoncross

4
하아! 해킹을 암호화하는 엔터티는 달콤합니다! 언뜻보기 에이 방법이 어떻게 작동하는지는 분명하지 않습니다. 그래도 문제가 있습니다. "Frédéric & Éric"이 "Frederic amp Eric"으로 바뀌지 않습니까?
Alan Donnelly

@AlanDonnelly : 사실, 나는 (링크 확인) 내 원래의 대답에 기능을 업데이트했습니다의는 trim()또한해야한다 trim($string, '-').
Alix Axel

@ Xeoncross : 마지막 preg_replace()은 위험한 모든 문자를 제거해야합니다.
Alix Axel

@AlixAxel, 당신의 모든 곳이 아닙니다. 방금 PHP AWS SDK를 읽고 있었고 UUID 용 코드가 있습니다. 펑션의 멋진 코드는 이길 수 없습니다.
Xeoncross

13

이것은 해결책을 제공하지 않기 때문에 정확한 대답은 아니지만 (아직!) 주석에 맞추기에는 너무 큽니다 ...


Windows 7 및 Ubuntu 12.04에서 몇 가지 테스트 (파일 이름 관련)를 수행했으며 그 결과는 다음과 같습니다.

1. PHP는 비 ASCII 파일 이름을 처리 할 수 ​​없습니다

Windows와 Ubuntu는 유니 코드 파일 이름 (RTL 파일도 포함)을 처리 할 수 ​​있지만 PHP 5.3에서는 오래된 ISO-8859-1을 처리하기 위해 해킹이 필요하므로 안전을 위해서만 ASCII를 유지하는 것이 좋습니다.

2. 파일 이름의 길이 (특히 Windows의 경우)

우분투에서 파일 이름이 가질 수있는 최대 길이 (확장명 포함)는 255 (경로 제외)입니다.

/var/www/uploads/123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345/

그러나 Windows 7 (NTFS)에서 파일 이름의 최대 길이는 절대 경로에 따라 다릅니다.

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

Wikipedia 는 다음과 같이 말합니다.

NTFS를 사용하면 경로 구성 요소 (디렉토리 또는 파일 이름)의 길이가 255 자일 수 있습니다.

내가 아는 한 (그리고 테스트) 이것은 잘못된 것입니다.

C:\256 자 (255가 아닙니까!)를 제공 하는 줄을 제거하면이 모든 예에는 총 259 개의 문자가 포함됩니다 . 탐색기를 사용하여 생성 된 디렉토리는 디렉토리 이름에 사용 가능한 모든 공간을 사용하지 못하도록합니다. 그 이유는 8.3 파일 명명 규칙을 사용하여 파일을 만들 수 있기 때문입니다 . 다른 파티션에서도 마찬가지입니다.

파일은 물론 8.3 길이 요구 사항을 예약 할 필요가 없습니다.

(255 chars) E:\12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901.txt

부모 디렉토리의 절대 경로가 242자를 초과하면 하위 디렉토리를 더 이상 만들 수 없습니다 256 = 242 + 1 + \ + 8 + . + 3. Windows 탐색기를 사용하면 상위 디렉토리의 시스템 로케일에 따라 233 자 이상인 경우 다른 디렉토리를 작성할 수 없습니다 256 = 233 + 10 + \ + 8 + . + 3. 는 10여기 문자열의 길이입니다 New folder.

파일 시스템간에 상호 운용성을 보장하려는 경우 Windows 파일 시스템에 심각한 문제가 발생합니다.

3. 예약 된 문자 및 키워드에주의하십시오

비 ASCII, 인쇄 불가능 및 제어 문자 를 제거하는 것 외에도 다음 을 다시 배치해야합니다.

"*/:<>?\|

파일 이름이 의미를 잃을 수 있으므로 이러한 문자를 제거하는 것이 가장 좋은 방법은 아닙니다. 최소한 이러한 문자의 여러 발생은 단일 밑줄 ( _) 또는 더 대표적인 것으로 대체되어야한다고 생각합니다 (이것은 단지 아이디어 일뿐입니다).

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

피하는NUL 방법은 확실하지 않지만 피해야 할 특수 키워드 (예 :)도 있습니다. 임의 이름 대체가있는 블랙리스트가이를 해결하는 좋은 방법 일 수 있습니다.

4. 대소 문자 구분

이 말도없이 가야하지만, 당신이 이렇게 서로 다른 운영 체제에서 파일 고유성을 보장하려는 경우, 정규화 된 경우에 그런 식으로 파일 이름을 변환해야 my_file.txt하고 My_File.txt리눅스에서 모두 같은이되지 않습니다 my_file.txtWindows에서 파일을.

5. 고유한지 확인

파일 이름이 이미 존재하면 고유 한 식별자를 기본 파일 이름에 추가해야합니다 .

일반적인 고유 식별자로는 UNIX 타임 스탬프, 파일 내용 요약 또는 임의 문자열이 있습니다.

6. 숨겨진 파일

이름을 지정할 수 있다고해서 반드시 그렇게해야하는 것은 아닙니다.

점은 일반적으로 파일 이름에 화이트리스트로 표시되지만 Linux에서는 숨겨진 파일이 선행 점으로 표시됩니다.

7. 기타 고려 사항

파일 이름의 일부 문자를 제거해야하는 경우 확장명이 일반적으로 파일의 기본 이름보다 중요합니다. 파일 확장자 (8-16)에 대해 최대 문자 수를 허용하면 기본 이름에서 문자를 제거해야합니다. 같은 - 그것은 하나 이상의 긴 확장자를 갖는 드문 경우에 점에 유의하는 것도 중요합니다 _.graphmlz.tag.gz- _.graphmlz.tag단지 _이 경우 파일 기본 이름으로 고려되어야한다.

자원

Calibre 는 파일 이름이 꽤 깔끔하게 처리되도록 처리합니다.

파일 이름 맹 글링에 위키 백과 페이지 와 링크 된 삼바를 사용하는 장 .


예를 들어, 1/2/3 규칙을 위반하는 파일을 만들려고하면 매우 유용한 오류가 발생합니다.

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

11

나는 항상 Kohana가 꽤 잘 해냈다 고 생각 했습니다 .

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

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

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

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

핸디 UTF8::transliterate_to_ascii()는 ñ => n과 같은 것을 돌립니다.

물론 다른 UTF8::*것들을 mb_ * 함수로 바꿀 수도 있습니다.


5

파일 업로드 측면에서 사용자가 파일 이름을 제어하지 못하게하는 것이 가장 안전합니다. 이미 암시 한 것처럼 정규화 된 파일 이름을 실제 파일 이름으로 사용할 임의로 선택되고 고유 한 이름과 함께 데이터베이스에 저장하십시오.

OWASP ESAPI를 사용하여 다음 이름을 생성 할 수 있습니다.

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

$ safeFilename에 타임 스탬프를 추가하여 기존 파일을 확인하지 않고도 임의로 생성 된 파일 이름이 고유한지 확인할 수 있습니다.

URL 인코딩 및 ESAPI 사용 측면에서 :

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

이 방법은 문자열을 인코딩하기 전에 정규화를 수행하며 모든 문자 인코딩을 처리합니다.


물론, 사용자로부터 파일 이름을 제어하지 않으면 동일한 이름을 가진 2 개의 업로드가 발생할 가능성이 없습니다.
CodeVirtuoso

5

PHP * 용 URLify (Github의 480 개 이상)를 권장합니다 - "URLify.js의 PHP 포트를 장고 프로젝트로 변환합니다 비 ASCII 문자의 URL에 사용하기 위해.".

기본 사용법 :

URL에 대한 슬러그를 생성하려면

<?php

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

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

?>

파일 이름에 대한 슬러그를 생성하려면

<?php

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

?>

* 다른 제안들 중 어느 것도 나의 기준과 일치하지 않습니다 :

  • 작곡가를 통해 설치 가능
  • iconv는 다른 시스템에서 다르게 작동하기 때문에 의존해서는 안됩니다
  • 재정의 및 사용자 지정 문자 교체를 허용하도록 확장 가능해야합니다.
  • 인기 (예 : Github의 많은 별)
  • 테스트가 있습니다

또한 URLify는 특정 단어를 제거하고 음역하지 않은 모든 문자를 제거합니다.

다음은 URLify를 사용하여 많은 외국 문자가 올바르게 음역되는 테스트 사례입니다. https://gist.github.com/motin/a65e6c1cc303e46900d10894bf2da87f


1
고마워-그것은 내 목적에 이상적으로 보입니다.
David Goodwin

5

나는 다른 출처에서 적응하고 몇 가지를 추가했습니다.

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

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

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

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

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

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

    return $uri;
}

5

그리고 이것은 Joomla 3.3.2 버전입니다. JFile::makeSafe($file)

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

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

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

4

제거 할 문자 목록이 안전하지 않다고 생각합니다. 차라리 다음을 사용합니다.

파일 이름의 경우 : 내부 ID 또는 파일 콘텐츠의 해시를 사용하십시오. 문서 이름을 데이터베이스에 저장하십시오. 이렇게하면 원래 파일 이름을 유지하면서 파일을 찾을 수 있습니다.

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 바이트를 제거해야합니다.
Alix Axel

이 답변을 안전하게 사용하려면 더 많은 설명이 필요합니다. 인터넷상의 charlist에 대한 정확한 구문에 대한 정보는 많지 않습니다.
Manuel Arwed Schmidt

3

다음은 CodeIgniter의 구현입니다.

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

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

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

그리고 remove_invisible_characters의존성.

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

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

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

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

    return $str;
}

2

왜 단순히 PHP를 사용하지 urlencode않습니까? "위험한"문자를 URL의 16 진수 표현으로 대체합니다 (예 : %20공백).


2
파일 이름에는 % 문자를 사용하지 않는 것이 좋으며 16 진수로 인코딩 된 문자는 URL에서 좋지 않습니다. 브라우저는 UTF-8 문자열을 지원할 수 있으며 ASCII가 아닌 언어에서는 훨씬 더 좋고 쉽습니다.
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.2의 Ubuntu 및 PHP 5.3.17의 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

@Xeoncross 동의합니다. Christian이 말했듯이 ID 또는 해시와 원래 파일 이름을 저장해야합니다. 그러나이 기능은 살균 프로세스가 실패 할 때 기본 문자열을 지정할 수 있으므로 대안을 제공합니다. 이 경우에 대한 단위 테스트를 추가했습니다. 버그를보고 해 주셔서 감사합니다.
코일

2

유용한 모든 종류의 라틴 ​​문자와 유용한 대시 구분 파일 이름 형식으로 변환하는 데 필요한 일부 HTML 태그가있는 항목 제목이 있습니다. @SoLoGHoST의 답변과 @Xeoncross의 답변 중 일부 항목을 결합하고 약간 맞춤화했습니다.

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

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

번역 배열에 em 대시 문자 (—)를 수동으로 추가해야했습니다. 다른 사람이있을 수 있지만 지금까지 내 파일 이름이 좋아 보입니다.

그래서:

제 1 부 : 아빠의“지 버트”? — 그들은 최고입니다!

된다 :

1 부-아빠-셔 버트-그들은 최고가 아닙니다

반환 된 문자열에 ".html"을 추가합니다.


1
여전히 체코 어와 슬로바키아어 문자가 일부 누락되었습니다.'ľ' => 'l', 'Ľ' => 'L', 'č' => 'c', 'Č' => 'C', 'ť' => 't', 'Ť' => 'T', 'ň' => 'n', 'Ň' => 'N', 'ĺ' => 'l', 'Ĺ' => 'L', 'Ř' => 'R', 'ř' => 'r', 'ě' => 'e', 'Ě' => 'E', 'ů' => 'u', 'Ů' => 'U'
Jasom Dotnet

1
그리고 더 많은 것은 의심의 여지가 없습니다. 실제로 문자 조합을 포함하는 ISO 세트가 있는지 알아 내려고합니다. 내용이 모든 문자에서 문자를 요구하면 어떻게 하나의 세트를 "선택"합니까? UTF-8 I가 있으리라 믿고있어 ...
cbmtrx

내가 발견 PHP의 한 줄을 사용하여 임의의 문자열을 음역하는 방법 : $string = transliterator_transliterate('Any-Latin;Latin-ASCII;', $string);내 대답은 아래를 참조하거나 링크 된 블로그 게시물을 읽어 보시기 바랍니다.
Jasom Dotnet 5

1
아니요, 잘못 읽었습니다. 서버 (또는 호스팅)에 PHP 확장을 설치할 수 있다면 :-) 여기 게시물이 있습니다.
Jasom Dotnet

1
아, 알았다 감사합니다 @JasomDotnet-현재 솔루션을 사용하고 있지만 문자 집합이 제한되어 있으므로 확장 프로그램을 확인할 가치가 있습니다.
cbmtrx

2

솔루션 # 1 : 서버에 PHP 확장을 설치하는 기능이 있습니다 (호스팅)

"지구상의 거의 모든 단일 언어"를 ASCII 문자로 음역합니다.

  1. PHP Intl 확장을 먼저 설치하십시오 . 이것은 데비안 (우분투) 명령입니다 :sudo aptitude install php5-intl

  2. 이것은 내 fileName 함수입니다 (test.php를 만들고 다음 코드를 붙여 넣으십시오).

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

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

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

이 라인은 핵심입니다 :

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

이 게시물을 기반으로 답변하십시오 .

해결 방법 # 2 : 서버에 PHP 확장을 설치할 수 없습니다 (호스팅)

여기에 이미지 설명을 입력하십시오

CMS Drupal을위한 음역 모듈 에서 꽤 잘했습니다 . 지구상의 거의 모든 단일 언어를 지원합니다. 정말 완벽한 솔루션 살균 문자열을 원한다면 플러그인 저장소 를 확인하는 것이 좋습니다 .



1

이것은 좋은 기능입니다.

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

이것은 나빠 보인다. \\s+백 슬래시 뒤에 하나 이상의 공백이 있음을 의미합니다. 그게 뭐야? 또한 이것은 CMD, null 또는 과 같은 것을 무시하고 허용 목록보다 차단 목록을 사용합니다 BEL.
Xeoncross

여전히 나쁘다. 이제 같은 문자열 /blog/2014-02/just-in-time은 허용되지 않습니다. 위의 테스트 코드를 사용하거나 phunctionPHP 프레임 워크 코드를 사용하십시오 .
Xeoncross

맞습니다. 이 기능은 "정시"부품에만 해당됩니다. 일부 사람들에게 유용 할 수 있습니다.
joan16v

1
정규식을 변경할 수 있습니다preg_replace('~[^\-\pL\pN\s]+~u', '-', $string)
Xeoncross

대박! 나는 또한 덧붙였다 : string = trim ($ string, "-");
joan16v

0

다음은 Prestashop이 URL을 삭제하는 데 사용하는 코드입니다.

replaceAccentedChars

에 의해 사용된다

str2url

분음 부호를 제거하려면

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

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

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

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

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

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

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

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

    return $str;
}


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

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

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

} 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.