(1996.11.09/2003.04.21upd)

quoted printableとJIS変換

quoted printableでエンコードされたメールを読むには、以下の二つのステップの変換が必要。

 @quoted printableデコード
 AJIS→S-JIS変換

【注意】メールをデコードするときは、ヘッダ削除してからデコードすること。quoted printableで特別な意味を持つ「=」がヘッダに含まれていると、正常な変換ができない。

●quoted printable

基本的に、1バイトの記号を表現するためのエンコード手法。主として、異なる環境(パソコンと大型機など)で半角記号キャラクタの整合性を取るためのもの。ただし、通常のアルファベット以外の文字(例えばJIS漢字に使用されるキャラクタなど)はほとんどすべて変換対象になる。

【エンコードの原理】=に続く2文字でASCIIコードを指定。ただし、通常のアルファベット26文字の大文字および小文字は変換しない。

 例)=25 → % (%のASCIIコードは25)

【継続文字】=単体で行末に置かれた場合は継続文字となる。したがって、全体のデコードに掛かる前に、あらかじめ継続行の処理を行っておくことが望ましい。

●JIS→S-JIS変換

全角と半角の切り替えを、モード切り替えキャラクタ(Kin/Kout)によって判別している。=1B$Bと=1B(Bに挟まれた部分が,JISコードの2バイト文字データになっているので,これをシフトJISに変換すれば、PC上で読める文章になる。考え方としては,N88-BASIC(懐かしい…)の漢字処理と同じ。なお、ここで、=1Bはエスケープコード($1Bまたは^[)をquoted printableで表記したもの。したがって、純粋にJISのコードで表記すれば、以下のようになる。

 ^[$B.....^[(B

なお、なぜかKinとKoutは複数の種類があるので注意。

KinKout備 考
^[$B....^[(J 本当はこちらが標準らしい
^[$B....^[(B これも多い
^[$?....^[(? これは少数派かな?

なお、メールのSubject欄などでは、=?iso-2022-jp?B?〜〜?=の形式で表現されることがあるが、この〜〜の部分が実はbase64(quoted printableではない)でエンコードされている。これをデコードしたものが、JISコード形式になる。

また、JIS->S-JISのコード変換は以下のような数学的な変換でOK(以下はREXXで記述されている)。

/***********************************
  Kaji output sub-routine
  JIS >> Shift-JISX convert core
************************************/
toSJIS: Procedure ; c1=Arg(1); c2=Arg(2);

if (C2D(c1)//2)=1 then do
  sj2=C2D(c2)+31;
  if sj2>126 then sj2=sj2+1;
end
else sj2=C2D(c2)+126;

sj1=(C2D(c1)-33)%2+129;
if sj1>159 then sj1=sj1+40;

RETURN D2c(sj1)||D2c(sj2)

●サンプル・スクリプト(OS/2 REXX)

/****************************************************
 quoted printable mail decoder ver.1.1 (03/04/20)
 ISO-2022-J & quoted printable
 (c)1997 Nogure Ten
 2003.04.20 大幅改造、ほぼ完成
*****************************************************/

InFile=arg(1)

if InFile='' then do
  say '-------------------------------'
  say 'QP ver.1.1    (c)2003 NogureTen'
  say 'quoted printable (MIME) decoder'
  say 'usage : qp <input file> [Enter]'
  say '-------------------------------'
  exit
end

if stream(InFile,'C','query exist')='' then do
  say InFile||' : file not found !'
  exit
end

PARSE value InFile with f'.'e
inp=InFile
out=f||'.'||'out'
tmp=f||'.'||'tmp'

/*************************************************
  Decode 0:
  decode line past >> tmpfile
**************************************************/
'@DEL' tmp
CALL STREAM inp,'C','open read'
CALL STREAM tmp,'C','open write'

Do While lines(inp)>0
  st=LineIn(inp);
  IF Right(st,1)='='
  Then Call CharOut tmp, Left(st,Length(st)-1);
  Else Call LineOut tmp, st;
End;
CALL STREAM file,'C','CLOSE'
CALL STREAM file,'C','CLOSE'

/*************************************************
  Decode 1:
  decode quoted printable >> tmp
**************************************************/
CALL LINEOUT ,'decode 1: quoted printable decode'
'@DEL' out
CALL STREAM tmp,'C','open read'
CALL STREAM out,'C','open write'

Do while Lines(tmp)>0
  ch=charin(tmp);
  IF ch='=' THEN
  DO
    ch2=CharIn(tmp,,2);
    Call CharOut out,x2c(ch2);
    CALL CHAROUT ,'.'
  End;
  ELSE CALL CHAROUT out,ch;
end

CALL STREAM tmp,'C','CLOSE'
CALL STREAM out,'C','CLOSE'
CALL LINEOUT ,''


/************************************************
  Decode2 :
  convert Kin/Kout Convert
*************************************************/

SAY 'Do you want JIS -> SJIS convert ? (y/n)'
PULL  yn
IF yn='N' THEN EXIT

'@COPY' out tmp
'@DEL' out

CALL LINEOUT ,'decode 2: Kin/Kout Convert'
CALL STREAM tmp,'C','open read'
CALL STREAM out,'C','open write'

Sin ='0f'x;
Sout='0e'x;
Kin ='1B'x||'$B';
Kout='1B'x||'(J';
Kou2='1B'x||'(B';	/* Koutは何故か2種類ある */

Do While Lines(tmp)>0
  st=LineIn(tmp);

  Do While POS(Kin,st)>0;
    p =POS(Kin,st);
    st=Left(st,p-1)||Sin||Substr(st,p+3);
  End;

  Do While POS(Kout,st)>0;
    p =POS(Kout,st);
    st=Left(st,p-1)||Sout||Substr(st,p+3);
  End;

  Do While POS(Kou2,st)>0;
    p =POS(Kou2,st);
    st=Left(st,p-1)||Sout||Substr(st,p+3);
  End;

  Call LineOut out, st;
  Call CharOut ,'='
End;

CALL STREAM tmp,'C','CLOSE'
CALL STREAM out,'C','CLOSE'
CALL LINEOUT ,''


/************************************************
  Decode3 :
  convert JIS >> Shift-JIS
*************************************************/

'@COPY' out tmp
'@DEL' out

CALL LINEOUT ,'decode 3: JIS >> S-JIS'
CALL STREAM tmp,'C','open read'
CALL STREAM out,'C','open write'

KFlag=0;
Do While Lines(tmp)>0
  ch=CharIn(tmp);
  Select
    When ch=Sin  Then Do; KFlag=1; Call CharOut,'<'; End;
    When ch=Sout Then Do; KFlag=0; Call CharOut,'>'; End;
    Otherwise
      IF KFlag=0 Then Call CharOut out, ch;
      IF KFlag=1 Then
      Do
        ch2=CharIn(tmp);
        SJ=toSJIS(ch,ch2);
        Call CharOut out, SJ;
      End;
  /*End of Otherwise*/
  END;
End;

CALL STREAM tmp,'C','CLOSE'
CALL STREAM out,'C','CLOSE'
CALL LINEOUT ,''

Exit

/***********************************
  Kaji output sub-routine
  JIS >> Shift-JISX convert core
************************************/
toSJIS: Procedure ; c1=Arg(1); c2=Arg(2);

if (C2D(c1)//2)=1 then do
  sj2=C2D(c2)+31;
  if sj2>126 then sj2=sj2+1;
end
else sj2=C2D(c2)+126;

sj1=(C2D(c1)-33)%2+129;
if sj1>159 then sj1=sj1+40;

RETURN D2c(sj1)||D2c(sj2)

【役に立たないPC講座目次】 【ホーム】