programing

PHP의 UTF-8 문자열에서 4바이트 문자를 대체/제거하는 방법은 무엇입니까?

yellowcard 2023. 7. 29. 08:20
반응형

PHP의 UTF-8 문자열에서 4바이트 문자를 대체/제거하는 방법은 무엇입니까?

MySQL은 기본 UTF-8 문자 집합에서 3바이트 이상의 문자를 지원하지 않는 것 같습니다.

그렇다면 PHP에서 문자열에서 4바이트 이상의 문자를 모두 제거하고 다른 문자와 같은 문자로 대체하려면 어떻게 해야 합니까?

참고: 유니코드 공격(대부분 XSS)을 방지하기 위해 단순히 제거하지 말고 대체 문자 U+FFFD로 대체해야 합니다.

http://unicode.org/reports/tr36/ #비문자 삭제_of_비문자

preg_replace('/[\x{10000}-\x{10FFFF}]/u', "\xEF\xBF\xBD", $value);

4바이트 UTF-8 시퀀스는 항상 바이트로 시작하므로0xF0-0xF7다음이 작동해야 합니다.

$str = preg_replace('/[\xF0-\xF7].../s', '', $str);

또는 다음을 사용할 수 있습니다.preg_replaceUTF-8 모드에서는 속도가 느려집니다.

$str = preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $str);

이것은 4바이트 UTF-8 시퀀스가 다음으로 시작하는 보조 유니코드 평면의 코드 포인트에 사용되기 때문에 작동합니다.0x10000.

다음은 예입니다.

<?php 

 mb_internal_encoding("UTF-8");

 //utf8 string,  13 bytes, 9 utf8 chars, 7 ASCII, 1 in latin1, 1 outside the BMP
 $str = "qué \xF0\x9D\x92\xB3 tal"; 
 $array = mbStringToArray($str);
 print "str: [$str]  strlen:" . strlen($str) . " chars:" . count($array) . "\n";
 $str1 = "";
 foreach($array as $c) {
   //  print "$c : " .  strlen($c)  ."\n";
   $str1 .= strlen($c)<=3? $c : '?';
 }
 print "[$str1]\n";


 function mbStringToArray ($str) {
    if (empty($str)) return false;
    $len = mb_strlen($str);
    $array = array();
    for ($i = 0; $i < $len; $i++) {
        $array[] = mb_substr($str, $i, 1);
    }
    return $array;
 }

또는 좀 더 작고 효율적입니다.

<?php /// 

 mb_internal_encoding("UTF-8");

 //utf8 string,  13 bytes, 9 utf8 chars, 7 ASCII, 1 in latin1, 1 outside the BMP
 $str = "qué \xF0\x9D\x92\xB3 tal";
 $str1 = trimOutsideBMP($str);
 print "original: [$str]\n";
 print "trimmed:  [$str1]\n";


 // Replaces non-BMP characters in the UTF-8 string by a '?' character 
 // Assumes UTF-8 default encoding ( if not sure, call first mb_internal_encoding("UTF-8"); )
 function trimOutsideBMP($str) {
    if (empty($str)) return $str;
    $len = mb_strlen($str);
    $str1 = '';
    for ($i = 0; $i < $len; $i++) {
        $c = mb_substr($str, $i, 1);
        $str1 .= strlen($c) <= 3 ? $c : '?';
    }
    return $str1;
 }

나만의 문제를 해결하려고 할 때 이 질문을 발견했습니다(페이스북은 특정 이모티콘을 4바이트 문자로 뱉습니다, Amazon Mechanical Turk는 4바이트 문자를 허용하지 않습니다).

나는 이것을 사용하게 되었고, mbstring 확장이 필요하지 않습니다.

function remove_4_byte($string) {
    $char_array = preg_split('/(?<!^)(?!$)/u', $string );
    for($x=0;$x<sizeof($char_array);$x++) {
        if(strlen($char_array[$x])>3) {
            $char_array[$x] = "";
        }
    }
    return implode($char_array, "");
}

아래 함수는 3 및 4바이트 문자를 utf8 문자열에서 '#'로 변경합니다.

function remove3and4bytesCharFromUtf8Str($str) {
        return preg_replace('/([\xF0-\xF7]...)|([\xE0-\xEF]..)/s', '#', $str);
    }

다음은 4바이트 문자를 필터링하기 위한 구현입니다.

$string = preg_replace_callback(
    '/./u',
    function (array $match) {
        return strlen($match[0]) >= 4 ? null : $match[0];
    },
    $string
);

당신은 그것을 수정하고 교체할 수 있습니다.null(char를 제거함) 일부 대체 문자열을 사용합니다.교체할 수도 있습니다.>= 4다른 바이트 길이 검사와 함께.

또 다른 필터 구현, 더 복잡합니다.

ASCII 문자로 변환을 시도하고, 그렇지 않으면 유니코드 대체 문자를 사용하여 XSS를 방지합니다.<a href='java\uFEFFscript:alert("XSS")'>

$tr = preg_replace_callback('/([\x{10000}-\x{10FFFF}])/u', function($m){
    $c = iconv('ISO-8859-2', 'UTF-8',iconv('utf-8','ISO-8859-2//TRANSLIT//IGNORE', $m[1]));
    if($c == '')
        return '�';
    return $c;

}, $s);

언급URL : https://stackoverflow.com/questions/8491431/how-to-replace-remove-4-byte-characters-from-a-utf-8-string-in-php

반응형