Wordpress를 사용하다보면 UTF-8과 EUC-KR로 인코딩된 블로그간에 트랙백을 받거나 보낼때 글씨가 깨지게 된다. 이 hack은 다르게 인코딩된 블로그 사이의 트랙백이 깨지지 않게 하기 위한 것이다. Wordpress 1.5 버전을 기준으로 작성되었다.
2.0 버전
새로 포스트를 작성하였습니다
http://www.windlike.net/blog/236/
2005.12.27 15:57
1.5.2 버전(UTF-8 전용) TE
unfusion님이 SE버전에서 트랙백이 깨지는 현상에 대해 보고해 주셨습니다. 여러가지 테스트 결과 트랙백 hack의 문제가 아닌 워드프레스 자체의 결함으로 밝혀졌습니다. 워드프레스에서 트랙백을 보낼때 substr이란 함수로 포스트의 내용중에서 253바이트를 자르고 …을 더해서 보내게 됩니다. 1바이트의 문자일때는 상관이 없는데 UTF-8같은 멀티바이트의 문자에선 글자 중간을 자르게 되는 경우도 발생합니다. 그래서 마지막 문자는 깨진 상태로 보내지는데 트랙백을 받는 쪽에서는 그냥 마지막 한글자만 ?로 나오게 될 뿐입니다. 그렇지만 워드프레스는 mb_convert_encoding이란 함수를 통해 자체적으로 트랙백의 인코딩을 변환합니다. 마지막 깨진 문자때문에 워드프레스는 이 트랙백을 UTF-8이 아닌것으로 인식하고 UTF-8로 재변환을 하게 됩니다. 그래서 결과적으로 트랙백이 깨지게 됩니다.
이 문제를 해결하기 위해 여러가지 방안을 생각했습니다. 기왕이면 워드프레스를 가장 조금 고치고 원래의 코드를 살릴 수 있는 방안. 그리고 버그보고를 통해 정식으로 패치될 수 있는 방안. 다른 블로그툴에서 보낼때 깨져서 들어오는 경우에 대비하기 위해선 받는 쪽에서 수정하는게 좋습니다. 하지만 근본적으로 문제를 해결하는 방법이 아닌데다가 기존 소스의 깔끔함을 해치는 방법이라 보내는 쪽에서 해결하는 방법을 택했습니다. 보내는 쪽을 고치는 방법의 또하나의 장점은 만약 다음 버전에서 이 버그가 수정이 되지 않더라도 이 hack을 쓰지 않은 블로그에 보낼때도 깨지지 않는다는 점입니다.
이 hack은 mbstring 모듈을 설치한 블로그에서만 작동됩니다. 만약 설치가 되지 않았다면 hack을 하지 않은 상태와 같이 작동합니다. mbstring 모듈이 설치가 안되었을 경우 부득이한 경우가 아니라면 호스팅업체에 설치 요청을 할 것을 권장합니다. 워드프레스의 자체의 트랙백 변환은 mbstring에서만 작동하고 제가 만든 트랙백 변환은 iconv에서도 작동하지만 mbstring에서 보다 안정적으로 작동합니다.
만약 mb_strcut 함수를 사용할 수 있는 경우 이 함수를 이용하여 글자를 253바이트 이내에서 자른다. mb_strcut과 substr의 차이점은 mb_strcut은 글자를 인코딩이 깨지지 않게 잘라준다.
/wp-includes/functions.php를 열어 do_trackback함수 내의
$excerpt = substr($excerpt, 0, 252) . '...';
를 아래와 같이 바꾼다
if ( function_exists('mb_strcut') )
$excerpt = mb_strcut($excerpt, 0, 252, get_settings('blog_charset')) . '...';
else $excerpt = substr($excerpt, 0, 252) . '...';
새로 포스트를 열어서 쓰려다 트랙백 변환에 관련된 내용이라 이 포스트에 추가합니다.
1.5.2 SE버전에 위에 있는 새로운 hack을 추가한 1.5.2 TE버전 : 다운로드
2005.9.2 05:16
1.5.2 버전(UTF-8 전용) SE
H.Moon님이 코멘트로 트랙백 hack이 ecto에서 문제를 일으킨다고 알려주셨습니다. 제가 default parameter에 대한 착각을 해서 생긴 문제입니다. 선언된 함수의 parameter보다 호출될 때의 parameter가 적을때 자동으로 부족한 parameter에 null값이 들어간다고 착각을 했습니다. 그래서 function overloading을 하지 않아도 hack을 한 후에도 기존의 함수와 새로 수정한 함수를 모두 쓸수 있다고 생각했는데 default parameter를 사용하려면 선언할때 미리 값을 주어야 합니다. 수정된 부분은 do_trackbakcs함수와 trackback함수의 인코딩관련 parameter에 디폴트로 null값을 주었습니다. 즉 다른 프로그램 또는 워드프레스 내에서 기존의 함수를 그대로 사용하게 될 경우에도 선언된 것보다 호출할 때의 parameter부족때문에 에러를 내지 않습니다. 아래 버전에서 다른 문제점은 보고되지 않았으므로 보통의 경우 굳이 이 버전으로 바꾸실 필요는 없습니다. 하지만 ecto같은 블로깅툴이나 다른 프로그램에 연동해 사용할 경우 필수이며 혹시모를 문제에 대비해 이 버전으로 바꾸실 것을 권장합니다.
다운로드
2005.8.29 03:25
1.5.2 버전(UTF-8 전용)
UNFGroup에서의 트랙백을 보니 워드프레스 1.5.2 버젼이 나왔더군요. 직접 비교해보니 트랙백 내용과 같이 1.5.1.3 버전에서는 post.php만 바뀌었습니다. 놀다보니 방학은 끝나가고.. 플러그인은 아직 손도 안 댔는데..
다운로드
2005.8.15 15:51
1.5.1.3 버전(UTF-8 전용)
심심하다 싶으면 새버전이 나오는 군요.. 이제 방학도 했으니 아예 플러그인으로 만들어봐야 겠습니다. 일단은 좀 놀다가..
다운로드
2005.7.5 14:47
1.5.1.2 버전(UTF-8 전용)
Wordpress 1.5.1.1 버전과 동일합니다. 1.5.1.1 버전용을 받아 사용하세요.
Security Update의 내용만 보고 트랙백 패치파일엔 변화가 없겠구나 했는데 지윤님의 트랙백을 보고 에디터로 직접 비교해보니 /wp-includes/functions.php에 한줄이 추가되었습니다.
다운로드
2005.5.29 21:36
1.5.1.1 버전(UTF-8 전용)
Wordpress 1.5.1.1 버전용으로 mbstring과 iconv 통합입니다. UTF-8 인코딩 전용으로 EUC-KR용은 요청이 있으면 만들겠습니다.
다운로드
2005.5.22 01:58
1.5.1 버전(mbstring사용 UTF-8 전용)
Wordpress 1.5.1 버전이 나왔습니다. 이 패치파일은 1.5.1 버전 용으로 UTF-8로 된 블로그에서 mbstring을 사용하도록 만들었습니다. iconv용과 EUC-KR용은 요청이 있으면 만들겠습니다. 받는 트랙백 부분은 sanulim님이 달아주신 코멘트를 이용하여 만들었으며 보내는 트랙백은 1.5 버전과 동일합니다.
다운로드
2005.5.19 20:00
도움주신분들
이 포스트가 알려지도록 도움 주신 아거님과 테스트에 도움주신 입명이님, H.Moon님, BluedSnow님께 감사드립니다
2005. 4. 6 00:41
통합패치
아래에 있는 4개의 다른 패치적용 파일을 하나로 합한 파일이다. UTF-8과 EUC-KR에 상관없이 작동한다. mbstring이 있으면 mbstring을 사용하고 없을경우 iconv를 사용한다. 만약 둘 다 없는 경우 체크박스가 나오지 않는다. 그러므로 체크박스가 나오지 않는다면 설치를 잘못 하였거나 호스팅 업체에서 지원을 하지 않는 경우이다. 일반적인 경우 통합버젼 사용을 권장한다.
압축을 푼 후 워드프레스가 설치된 폴더에 복사한다. (예 : /blog)
6개의 파일이 덮어쓰기되면 파일 복사가 제대로 된 것임.
통합패치 : 다운
주의사항
적용대상 :
- PHP 4.0.6 이상
- mbstring 모듈이나 iconv 모듈 둘 중 하나가 설치되어 있어야 함
확인방법 :
- 직접 호스팅 업체에 문의
- 다음 코드를 에디터를 이용하여 test.php로 저장한 후 브라우져에서 실행한다(미리 작성된 파일 : 다운)
<?php
echo 'PHP version: ' . phpversion() . '<br />';
if ( function_exists('mb_convert_encoding') ) echo 'mbstring OK!<br />';
else echo 'mbstring fail..<br />';
if ( function_exists('iconv') ) echo 'iconv OK!<br />';
else echo 'iconv fail..<br />';
?>
mbstring OK! 가 나오면 mbstring 모듈을 이용할 수 있다(둘 다 OK일 경우 이방법을 권장)
iconv OK! 가 나오면 iconv 모듈을 이용할 수 있다(mbstring fail 일 경우 이 방법으로 한다)
둘다 fail이면 호스팅 업체에서 둘 중 하나를 설치해 줄때까지 불가능하다
라이센스
Wordpress가 GPL이기 때문에 이 hack 역시 GPL을 따른다. 수정 및 재배포 모두 가능함.
사용방법
받는 트랙백은 자동으로 변환된다.
보내는 트랙백은 트랙백 보내는 주소 오른쪽에 생긴 체크박스를 수동으로 체크함으로서 변환한다. 트랙백 받는 블로그가 내 블로그와 다른 인코딩을 사용할 경우 체크한다. 같은 인코딩인데 체크할 경우 오히려 트랙백이 깨지게 되므로 인코딩이 같을 경우엔 체크하지 않고 트랙백을 보낸다.
상대의 인코딩을 알아내는 방법은 브라우져의 보기 - 인코딩 메뉴를 보면 알 수 있다.
패치적용 파일
이 파일은 아래의 내용을 직접 수정하기 번거로운 사람을 위한 파일로 아래 적힌 수정 방법을 모두 적용하여 압축한 파일이다.
압축을 푼 후 워드프레스가 설치된 폴더에 복사한다. (예 : /blog)
6개의 파일이 덮어쓰기되면 파일 복사가 제대로 된 것임.
Wordpress 1.5 UTF-8 용 수정파일(mbstring 모듈 사용) : 다운
Wordpress 1.5 EUC-KR 용 수정파일(mbstring 모듈 사용) : 다운
Wordpress 1.5 UTF-8 용 수정파일(iconv 모듈 사용) : 다운
Wordpress 1.5 EUC-KR 용 수정파일(iconv 모듈 사용) : 다운
받는 트랙백핑 문제 해결(mbstring)
mb_detect_encoding을 이용하여 들어오는 트랙백핑의 인코딩을 검사한후 blog_charset에 설정된 내 블로그의 인코딩으로 변환해 준다.
/wp-trackback.php를 열어
$title = mb_convert_encoding($title, get_settings('blog_charset'), $charset);
$excerpt = mb_convert_encoding($excerpt, get_settings('blog_charset'), $charset);
$blog_name = mb_convert_encoding($blog_name, get_settings('blog_charset'), $charset);
를 아래와 같이 바꾼다($charset이 수정되는 것임)
$title = mb_convert_encoding($title, get_settings('blog_charset'), mb_detect_encoding($title, 'UTF-8, EUC-KR') );
$excerpt = mb_convert_encoding($excerpt, get_settings('blog_charset'), mb_detect_encoding($excerpt, 'UTF-8, EUC-KR') );
$blog_name = mb_convert_encoding($blog_name, get_settings('blog_charset'), mb_detect_encoding($blog_name, 'UTF-8, EUC-KR') );
받는 트랙백핑 문제 해결(iconv)
정규식을 이용한 is_utf8 함수를 만들어 UTF-8인지 확인한 후 iconv 함수로 인코딩을 변환한다.
/wp-trackback.php를 열어 // trackback is done by a POST 위에 아래의 코드를 추가한다. 이는 이해를 돕기 위치이므로 굳이 이곳이 아니라도 적당한 곳에 추가하면 된다.
// Returns true if $string is valid UTF-8 and false otherwise.
function is_utf8($string) {
return preg_match('%^(?:
[\x09\x0A\x0D\x20-\x7E] # ASCII
| [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
| \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
| \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
)*$%xs’, $string);
} // function is_utf8
같은 파일(/wp-trackback.php)의
if ( function_exists('mb_convert_encoding') ) {
$title = mb_convert_encoding($title, get_settings('blog_charset'), $charset);
$excerpt = mb_convert_encoding($excerpt, get_settings('blog_charset'), $charset);
$blog_name = mb_convert_encoding($blog_name, get_settings('blog_charset'), $charset);
}
를 아래와 같이 바꾼다(UTF-8의 경우)
if ( !is_utf8($title) ) $title = iconv('EUC-KR', get_settings('blog_charset'), $title);
if ( !is_utf8($excerpt) ) $excerpt = iconv('EUC-KR', get_settings('blog_charset'), $excerpt);
if ( !is_utf8($blog_name) ) $blog_name = iconv('EUC-KR', get_settings('blog_charset'), $blog_name);
EUC-KR의 경우는 아래와 같이 바꾼다 (if문 조건에서 !이 빠지고 ‘EUC-KR’이 ‘UTF-8′로 바뀜)
if ( is_utf8($title) ) $title = iconv('UTF-8', get_settings('blog_charset'), $title);
if ( is_utf8($excerpt) ) $excerpt = iconv('UTF-8', get_settings('blog_charset'), $excerpt);
if ( is_utf8($blog_name) ) $blog_name = iconv('UTF-8', get_settings('blog_charset'), $blog_name);
보내는 트랙백핑 문제 해결
1. 먼저 EUC-KR로 트랙백핑을 보낼지를 선택하는 체크박스를 만든다. 체크박스를 체크하면 char_encoding에 value값인 “EUC-KR”이 전달된다. 일반폼과 advanced폼 모두 바꿔주기 위해 두개의 파일을 수정한다. (EUC-KR 사용자 : 이 단계에서 “EUC-KR”을 “UTF-8″로 바꿔서 수정한다. 나머지 부분은 UTF-8 사용자와 같이 수정한다.)
/wp-admin/edit-form.php를 열어
<input type="text" name="trackback_url" style="width: 360px" id="trackback" tabindex="7" /></p>
를 아래와 같이 바꾼다 (첫째줄의 </p>이 추가되는 줄로 옮겨가는 것 주의)
<input type="text" name="trackback_url" style="width: 360px" id="trackback" tabindex="7" />
<label for="char_enc"><input type="checkbox" name="char_encoding" id="char_enc" value="EUC-KR" /> EUC-KR</label></p>
/wp-admin/edit-form-advanced.php를 열어
<td>< ?php echo $form_trackback; ?> <br />
를 아래와 같이 바꾼다
<td>< ?php echo $form_trackback; ?> <label for="char_enc"><input type="checkbox" name="char_encoding" id="char_enc" value="EUC-KR" /> EUC-KR</label><br />
2. do_trackbakcs 함수에 폼으로부터 넘겨받은 $char_encoding값을 인수로 전달한다.
/wp-admin/post.php를 열어 do_trackbacks를 찾은 후
do_trackbacks($post_ID);
를 아래와 같이 바꾼다(2곳을 수정해야 함)
do_trackbacks($post_ID, $_POST['char_encoding']);
3. do_trackbacks 함수가 선언된 곳을 찾아서 매개변수 $char_enc를 추가하고 이 값을 trackback 함수의 인수로 넘긴다.
/wp-includes/functions-post.php를 열어
function do_trackbacks($post_id) {
를 아래와 같이 바꾼다
function do_trackbacks($post_id, $char_enc) {
또 몇줄 밑의
trackback($tb_ping, $post_title, $excerpt, $post_id);
를 아래와 같이 바꾼다
trackback($tb_ping, $post_title, $excerpt, $post_id, $char_enc);
4. trackback함수가 선언된 곳을 찾아서 매개변수 $encoding을 추가한다. $encoding에 값이 들어가 있으면 mb_convert_encoding을 이용하여 트랙백핑 보낼 제목, 요약, 블로그이름을 $encoding의 값으로(체크박스의 value값, 여기서는 EUC-KR) 인코딩을 변환한다. 체크박스가 선택되지 않아 $encoding에 값이 없으면 인코딩을 변환하지 않고(여기서는 utf-8) 트래픽핑을 보낸다.
/wp-includes/functions.php를 열어
function trackback($trackback_url, $title, $excerpt, $ID) {
global $wpdb;
$title = urlencode($title);
$excerpt = urlencode($excerpt);
$blog_name = urlencode(get_settings('blogname'));
mbstring 모듈을 사용할 경우에는 아래와 같이 바꾸고
function trackback($trackback_url, $title, $excerpt, $ID, $encoding) {
global $wpdb;
$blog_name = get_settings('blogname');
if($encoding) {
$title = mb_convert_encoding($title, $encoding, get_settings('blog_charset'));
$excerpt = mb_convert_encoding($excerpt, $encoding, get_settings('blog_charset'));
$blog_name = mb_convert_encoding($blog_name, $encoding, get_settings('blog_charset'));
}
$title = urlencode($title);
$excerpt = urlencode($excerpt);
$blog_name = urlencode($blog_name);
iconv 모듈을 사용할 경우에는 아래와 같이 바꾼다
function trackback($trackback_url, $title, $excerpt, $ID, $encoding) {
global $wpdb;
$blog_name = get_settings('blogname');
if($encoding) {
$title = iconv(get_settings('blog_charset'), $encoding, $title);
$excerpt = iconv(get_settings('blog_charset'), $encoding, $excerpt);
$blog_name = iconv(get_settings('blog_charset'), $encoding, $blog_name);
}
$title = urlencode($title);
$excerpt = urlencode($excerpt);
$blog_name = urlencode($blog_name);