Shift_JIS ←→ ISO-2022-JP 変換スクリプト

今、きき☆彡はウェブサイトをいろいろ変更しているところです。
その中でいまやっているのがメッセージ送信のページ&CGI変更です。
そこでMIMEエンコードというのが必要になってきたのですが公開されているものには満足のいくものがない・・・
ということで自分で作っちゃいました♪
ついでにコード変換機能もつけています(^-^;

ソースを見たい人は続きをどうぞ~♪

【02/26追記】
 プログラムにいくつか間違いがあってiso→Shift_JISの変換すべてとShift_JISでコードE040以降の文字が正しく変換されませんでした(汗
修正しておきます~(>_<) (赤字のところ)
あぁ・・やはりちゃんとチェックをしておかないとだめですなぁ・・;


#--------------------------------
#  Shift_JIS <-> ISO-2022-JP変換ライブラリ
#    (JIS X 0208-1983 と ASCII のみ対応)
#                                        by きき☆彡 2009/02/26
#--------------------------------
#
#  ●&Kicode::to_iso( Shift_JIS文字列 )
#      ISO-2022-JPに変換した文字列を返す
#
#  ●&Kicode::from_iso( ISO-2022-JP文字列 )
#      Shift_JISに変換した文字列を返す
#
#  ●&Kicode::to_mime( ISO-2022-JP文字列 )
#      mime形式に変換した文字列を返す
#   例:
#   &to_mime('Subject: '.&to_iso('Little Twin Starsのグッズを買ったよ~☆'));
#

package Kicode;

$b64c = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
$encb = '=?ISO-2022-JP?B?';
$ence = '?=';
$fullvoice = 'ウカキクケコサシスセソタチツテトハヒフヘホ';
$semivoice = 'ハヒフヘホ';
@halfmap = (
	[0xa1, 0x2123],
	[0xa2, 0x2156],
	[0xa3, 0x2127],
	[0xa4, 0x2122],
	[0xa5, 0x2126],
	[0xa6, 0x2572],
	[0xa7, 0x2521],
	[0xa8, 0x2523],
	[0xa9, 0x2525],
	[0xaa, 0x2527],
	[0xab, 0x2529],
	[0xac, 0x2563],
	[0xad, 0x2565],
	[0xae, 0x2567],
	[0xaf, 0x2543],
	[0xb0, 0x213c],
	[0xb1, 0x2522],
	[0xb2, 0x2524],
	[0xb3, 0x2526],
	[0xb4, 0x2528],
	[0xb5, 0x252a],
	[0xb6, 0x252b],
	[0xb7, 0x252d],
	[0xb8, 0x252f],
	[0xb9, 0x2531],
	[0xba, 0x2533],
	[0xbb, 0x2535],
	[0xbc, 0x2537],
	[0xbd, 0x2539],
	[0xbe, 0x253b],
	[0xbf, 0x253d],
	[0xc0, 0x253f],
	[0xc1, 0x2541],
	[0xc2, 0x2544],
	[0xc3, 0x2546],
	[0xc4, 0x2548],
	[0xc5, 0x254a],
	[0xc6, 0x254b],
	[0xc7, 0x254c],
	[0xc8, 0x254d],
	[0xc9, 0x254e],
	[0xca, 0x254f],
	[0xcb, 0x2552],
	[0xcc, 0x2555],
	[0xcd, 0x2558],
	[0xce, 0x255b],
	[0xcf, 0x255e],
	[0xd0, 0x255f],
	[0xd1, 0x2560],
	[0xd2, 0x2561],
	[0xd3, 0x2562],
	[0xd4, 0x2564],
	[0xd5, 0x2566],
	[0xd6, 0x2568],
	[0xd7, 0x2569],
	[0xd8, 0x256a],
	[0xd9, 0x256b],
	[0xda, 0x256c],
	[0xdb, 0x256d],
	[0xdc, 0x256f],
	[0xdd, 0x2573],
	[0xde, 0x212b],
	[0xdf, 0x212c]
);

sub from_iso{
	local($a,$l,$m,$r,$s,$t,$u,$v,$x);
	$l = length($s = $_[0]);
	$r = '';
	$m = 0;
	for($a = 0;$a < $l;++$a){
		$t = substr($s,$a,3);
		if($t =~ /^\e\$[\@B]$/){
			$m = 1;
			$a += 3;
		}elsif($t =~ /^\e\([BJ]$/){
			$m = 0;
			$a += 3;
		}
		($t,$u) = split(//,substr($s,$a,2));
		if($m && $a < $l-1){
			($t,$u) = unpack('CC',$t.$u);
			$x = $t;
			$v = int(($x-33)/2);
			$r .= pack('C',$v+($v<31 ? 129 : 193));
			$r .= pack('C',$u+($x & 1 ? ($u < 96 ? 31 : 32) : 126));
			$a++;
		}else{
			$r .= $t;
		}
	}
	return $r;
}

sub to_iso{
	local($a,$l,$m,$r,$s,$t,$u,$x);
	$l = length($s = $_[0]);
	$r = '';
	$m = 0;
	for($a = 0;$a < $l;++$a){
		($t,$u) = split(//,substr($s,$a,2));
		if($a < $l-1 && $t =~ /^[\x81-\x9f\xa1-\xdf\xe0-\xff]$/){
			if(!$m){
				$m = 1;
				$r .= "\e\$B";
			}
			($t,$u) = unpack('CC',$t.$u);
			if($t>=0xa1 && $t<=0xdf){
				$x = 0;
				if($u == 0xde && index($fullvoice,pack('C',$t),0) != -1){
					$x = $t == 0xb3 ? 0x4e : 1;
				}elsif($u == 0xdf && index($semivoice,pack('C',$t),0) != -1){
					$x = 2;
				}
				$r .= pack('n',$halfmap[$t-0xa1][1]+$x);
				++$a if($x != 0);
			}else{
				--$u if($u > 128);
				$x = 0;
				if($u >= 158){
					$x = 1;
					$u -= 94;
				}
				$u -= 0x1f;
				$t = ($t >= 224 ? $t-64 : $t)*2-225+$x;
				$r.= pack('CC',$t,$u);
				++$a;
			}
		}else{
			if($m){
				$m = 0;
				$r .= "\e(B";
			}
			if(($p=ord($t))<128){
				$r .= $t;
			}
		}
	}
	return $r;
}

sub to_mime{
	local($a,$b,$c,$d,$e,$f1,$f2,$l,$lm,$m,$r1,$r2);
	$lm = 78;
	$l = length($_[0]);
	$r1 = '';
	$r2 = '';
	$f1 = 0;
	$f2 = 0;
	$m = 0;
	for($a = 0;$a < $l;){
		if($m == 0){
			for(;$a<$l && ($d=substr($_[0],$a,1)) ne "\e";++$a){
				$d = ' ' if($d eq "\n");
				$r2 .= $d;
				++$f2;
				if($f1+$f2>$lm){
					if($f1<6){
						$b = $lm-$r1;
						$r1 .= substr($r2,0,$b);
						$f2 = length($r2)-$b;
						$r2 = substr($r2,$b,$f2);
					}
					$r1 .= "\n ";
					$f1 = 1;
				}
				if($d eq ' '){
					$r1 .= $r2;
					$r2 = '';
					$f1 += $f2;
					$f2 = 0;
				}
			}
			$r1 .= $r2;
			$f1 += $f2;
		}elsif($m == 1){
			if($lm-$f1<26){
				$r1 .= "\n ";
				$f1 = 1;
			}
			$r2 = "\e\$B";
			$f2 = 6;
			for($b = $a;$b<$l;$b+=2){
				$d = substr($_[0],$b,2);
				last if($d =~ /^\e/);
				$f2 += 2;
				$c = int(($f2+2)/3)*4+18;
				if($f1+$c>$lm){
					if($f1<20){
						$r1 .= $encb.&to_b64($r2."\e(B").$ence;
						$r2 = "\e\$B";
						$f2 = 8;
					}
					$r1 .= "\n ";
					$f1 = 1;
				}
				$r2 .= $d;
			}
			$a = $b;
			if($f2>6){
				$r1 .= $encb.&to_b64($r2."\e(B").$ence;
				$f1 += $c;
			}
		}else{
			for(;$a<$l && substr($_[0],$a,1) ne "\e";++$a){
			}
		}
		$r2 = '';
		$f2 = 0;
		if($a<$l){
			$d = substr($_[0],$a,3);
			if($d =~ /^([^\e]|\e\([BJ])/){
				$m = 0;
			}elsif($d =~ /^\e\$[\@B]/){
				$m = 1;
			}else{
				$m = 2;
			}
			$a += 3;
		}
	}
	return $r1;
}

sub to_b64{
	local($a,$d,$l,$p,$r,@s,@t,$v);
	$v = $_[0]."\x00\x00";
	$l = length($_[0]);
	$r = '';
	for($p = 0;$p < $l;$p+=3){
		@t = unpack('C3',substr($v,$p,3));
		@s = (($t[0] & 252) >> 2,(($t[0] & 3) << 4) + (($t[1] & 240) >> 4),(($t[1] & 15) << 2) + (($t[2] & 192) >> 6),$t[2] & 63);
		$d = $p+3;
		for($a = 0;$a <= 3;++$a){
			if($p + $a > $l){
				$r .= '=';
			}else{
				$r .= substr($b64c,$s[$a],1);
			}
		}
	}
	return $r;
}
sub from_b64{
	local($a,$d,$l,$p,$r,@t,$v);
	$v = $_[0];
	$v =~ s/[^\+\/\=0-9A-Za-z]//g;
	if($l % 4 != 0 || $v !~ /^[^\=]*\={0,2}$/){
		return undef;
	}
	$l = length($v) if (($l = index($v,'=',0)) == -1);
	$v =~ s/\=/A/g;
	$r = '';
	for($p = 0;$p < $l;$p+=4){
		@t = ();
		for($a = 0;$a < 4;++$a){
			push(@t,index($b64c,substr($v,$p+$a,1),0));
		}
		$s = pack('C3',($t[0] << 2) + (($t[1] & 48) >> 4),(($t[1] & 15) << 4) + (($t[2] & 60) >> 2),(($t[2] & 3) << 6) + $t[3]);
		if(($d = $l - $p) < 4){
			$r .= substr($s,0,$d - 1);
		}else{
			$r .= $s;
		}
	}
	return $r;
}
1;

あ、スクリプトの文字コードはShift_JISにしてくださいね(;^▽^A

しっかし、メールヘッダの仕様ってややこしい・・><

コメント☆

アイコン: (未実装)

トラックバック


トップページへ