Urldecode 엘사의-얼음-성 문제

urldecode 엘사의-얼음-성 문제

1 문제상황[ | ]

  • Yongseok Lee님의 페북 페이지에서 본 문제입니다...
  • 아래 두 문자열을 http://urldecode.org 같은 곳에서 urldecode()하면 둘다 엘사의-얼음-성으로 나온다...
① %EC%97%98%EC%82%AC%EC%9D%98-%EC%96%BC%EC%9D%8C-%EC%84%B1
② %E1%84%8B%E1%85%A6%E1%86%AF%E1%84%89%E1%85%A1%E1%84%8B%E1%85%B4-%E1%84%8B%E1%85%A5%E1%86%AF%E1%84%8B%E1%85%B3%E1%86%B7-%E1%84%89%E1%85%A5%E1%86%BC
  • 이게 어떻게 된 걸까?
  • 첫번째 것은 urlencode('엘사의-얼음-성')의 결과이므로 특이할 것은 없다.
  • 두번째 것은 왜 같은 결과가 되는 것일까?

2 중복 인코딩?[ | ]

  • 가장 흔한 문제상황은 이미 인코딩한 것을 한번 더 인코딩하는 경우이다.
<?php
$str = '엘사의-얼음-성';
var_dump( urlencode($str) );
var_dump( urlencode(urlencode($str)) );
root@zetawiki:~# php elsa1.php 
string(56) "%EC%97%98%EC%82%AC%EC%9D%98-%EC%96%BC%EC%9D%8C-%EC%84%B1"
string(92) "%25EC%2597%2598%25EC%2582%25AC%25EC%259D%2598-%25EC%2596%25BC%25EC%259D%258C-%25EC%2584%25B1"
→ 두번째 것과 맞지 않고, %가 등장하는 패턴 자체가 다르다.
→ 두번째 것의 % 패턴으로 봐서는 인코딩이 한번만 된 것으로 추정된다.

3 인코딩 문제?[ | ]

  • 그 다음으로 흔한 경우가 인코딩이 잘못된 경우...
<?php
$str = '엘사의-얼음-성';
$encodings = ['UCS-4', 'UCS-4BE', 'UCS-4LE', 'UCS-2', 'UCS-2BE', 'UCS-2LE', 'UTF-32', 'UTF-32BE', 'UTF-32LE', 'UTF-16', 'UTF-16BE', 'UTF-16LE', 'UTF-7', 'UTF7-IMAP', 'UTF-8', 'ASCII', 'EUC-JP', 'SJIS', 'eucJP-win', 'SJIS-win', 'ISO-2022-JP', 'ISO-2022-JP-MS', 'CP932', 'CP51932', 'SJIS-mac', 'SJIS-Mobile#DOCOMO', 'SJIS-Mobile#KDDI', 'SJIS-Mobile#SOFTBANK', 'UTF-8-Mobile#DOCOMO', 'UTF-8-Mobile#KDDI-A', 'UTF-8-Mobile#KDDI-B', 'UTF-8-Mobile#SOFTBANK', 'ISO-2022-JP-MOBILE#KDDI', 'JIS', 'JIS-ms', 'CP50220', 'CP50220raw', 'CP50221', 'CP50222', 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', 'ISO-8859-5', 'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8', 'ISO-8859-9', 'ISO-8859-10', 'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'ISO-8859-16', 'byte2be', 'byte2le', 'byte4be', 'byte4le', 'BASE64', 'HTML-ENTITIES', '7bit', '8bit', 'EUC-CN', 'CP936', 'GB18030', 'HZ', 'EUC-TW', 'CP950', 'BIG-5', 'EUC-KR', 'UHC (CP949)', 'ISO-2022-KR', 'Windows-1251 (CP1251)', 'Windows-1252 (CP1252)', 'CP866 (IBM866)', 'KOI8-R', 'KOI8-U', 'ArmSCII-8 (ArmSCII8)'];
foreach( $encodings as $encoding ) {
    var_dump( urlencode(mb_convert_encoding($str, $encoding, 'UTF-8')) );
}
root@zetawiki:~# php elsa2.php
string(86) "%00%00%C5%D8%00%00%C0%AC%00%00%C7X%00%00%00-%00%00%C5%BC%00%00%C7L%00%00%00-%00%00%C11"
string(86) "%00%00%C5%D8%00%00%C0%AC%00%00%C7X%00%00%00-%00%00%C5%BC%00%00%C7L%00%00%00-%00%00%C11"
string(86) "%D8%C5%00%00%AC%C0%00%00X%C7%00%00-%00%00%00%BC%C5%00%00L%C7%00%00-%00%00%001%C1%00%00"
... (생략)
→ 맞는 패턴이 없다...

4 그렇다면?? (정답)[ | ]

  • 애초에 둘의 결과값은 다른 것인데 같게 보이는 것 아닐까?
  • (가설) ZWSP가 섞여 있나?
<?php
$str1 = '%EC%97%98%EC%82%AC%EC%9D%98-%EC%96%BC%EC%9D%8C-%EC%84%B1';
$str2 = '%E1%84%8B%E1%85%A6%E1%86%AF%E1%84%89%E1%85%A1%E1%84%8B%E1%85%B4-%E1%84%8B%E1%85%A5%E1%86%AF%E1%84%8B%E1%85%B3%E1%86%B7-%E1%84%89%E1%85%A5%E1%86%BC';
var_dump( urldecode($str1) );
var_dump( urldecode($str2) );
root@zetawiki:~# php elsa3.php
string(20) "엘사의-얼음-성"
string(50) "엘사의-얼음-성"
→ 일단 문자열의 길이가 다르다!
→ 그리고... 콘솔에서 브라우저로 옮길 때 한글자모가 합쳐지는데... 실제로는 다음과 같다.

Urldecode-elsa.png

→ 20바이트 = 한글6자 × 3바이트 + 빼기2자 × 1바이트
→ 50바이트 = 한글자모16자 × 3바이트 + 빼기2자 × 1바이트

5 결론[ | ]

  • (웹브라우저의 농단) CLI의 우수성
  • 웹브라우저에서는 한글자모는 결합할 수 있다... → 유니코드 정규화
  • 나중에 떠오른 다른 검증방법... 한글이므로 앞에서부터 3단위(한글 1글자)씩 적당히 테스트해봐도 규칙성을 알 수 있었을 듯.
입력 출력
%E1%84%8B
%E1%85%A6
%E1%86%AF
%E1%84%8B%E1%85%A6
%E1%84%8B%E1%85%A6%E1%86%AF

6 같이 보기[ | ]

문서 댓글 ({{ doc_comments.length }})
{{ comment.name }} {{ comment.created | snstime }}