Uuencode

uuencodeは、バイナリデータをテキストデータに変換するUNIX及びUnix系OSのコマンド。或いは、それによって生成されるテキストデータのフォーマット。デコードにはuudecodeコマンドを用いる。電子メールネットニュースで多用され、現在でも多くのメーラーが対応しているが、MIMEBase64の方が一般的になっている。

概要

初期のUnix系OSではUUCPと呼ばれるプロトコルで電子メールやネットニュースの配送が行なわれた。これらはテキストデータしか扱えないため、バイナリファイルをテキストデータに変換して送る手法としてuuencodeが提供された。uuencodeはUnix to Unix ENCODEの意である。

その後インターネットの環境が整備され、UUCPよりもTCP/IPが一般的となるが、電子メールやネットニュースはSMTPNNTPといった テキストベースの情報交換であったため、uuencodeは依然として広く使われた。

uuencodeはあくまでも添付のためのフォーマットであるため、拡張子は重要ではないが、単一のファイルとして保存する場合は拡張子は.uuか.uueが使われる場合が多い。

uuencodeにはいくつかの派生フォーマットがあるため、MIMEでは意図的にuuencodeを採用せず、新たにBase64を定義した。現在はこちらのBase64が広く使われている。

一般的な変換フォーマット

uuencodeのフォーマットは、一行のヘッダー、複数行のエンコード文字列、一行のフッターからなる。

ヘッダは次の書式である。ここで、<mode>は3桁の8進数であり、UNIXのパーミッションを表す。<decode_pathname>はデコードされたときのファイル名である。パス名を含む事が出来るが一般にはファイル名のみである。

begin <mode> <decode_pathname>

このあと、エンコードされた文字列が続き、以下のフッタで終わる。

end

エンコードは3オクテット(24ビット)毎に行なわれる。これを4つの6ビット値に変換し、ASCII文字に割当てる。次は「Cat」という3オクテットのデータをASCIIの4文字に変換する例である。

元データ C a t
オクテット値 0 1 0 0 0 0 1 1 0 1 1 0 0 0 0 1 0 1 1 1 0 1 0 0
エンコード後のASCII文字 0 V % T

6ビット値に0x20を加えたときの下位6ビットをASCII値とする。この変換を表にすると次のようになる。

データ 文字 データ 文字 データ 文字 データ 文字
0 000000 スペース または ` 16 010000 0 32 100000 @ 48 110000 P
1 000001 ! 17 010001 1 33 100001 A 49 110001 Q
2 000010 " 18 010010 2 34 100010 B 50 110010 R
3 000011 # 19 010011 3 35 100011 C 51 110011 S
4 000100 $ 20 010100 4 36 100100 D 52 110100 T
5 000101 % 21 010101 5 37 100101 E 53 110101 U
6 000110 & 22 010110 6 38 100110 F 54 110110 V
7 000111 ' 23 010111 7 39 100111 G 55 110111 W
8 001000 ( 24 011000 8 40 101000 H 56 111000 X
9 001001 ) 25 011001 9 41 101001 I 57 111001 Y
10 001010 * 26 011010 : 42 101010 J 58 111010 Z
11 001011 + 27 011011 ; 43 101011 K 59 111011 [
12 001100 , 28 011100 < 44 101100 L 60 111100 \
13 001101 - 29 011101 = 45 101101 M 61 111101 ]
14 001110 . 30 011110 > 46 101110 N 62 111110 ^
15 001111 / 31 011111 ? 47 101111 O 63 111111 _

元々「000000」はスペース文字であったが、かつて行末のスペースを取り去る転送系があったため、「`」に置き換えられた。

デコードにおいては、変数 c にエンコードされた文字のASCIIコードが入っているとすると (c XOR 0x20) AND 0x3f でデコードできる(範囲外の文字が入っている可能性は考慮していない)。スペースの「`」への置き換えには、このデコード法に全く変更を必要としないという利点があった。

次は「000000」にスペースを用いているuuencodeの一例である。これはSolaris 10の/usr/bin/uuencodeコマンドの出力である。

begin 644 testimg.png
MB5!.1PT*&@H    -24A$4@   "     @" 8   !S>GKT    !&=!34$  +&/
M"_QA!0   $=)1$%46$?MUK$- " (!$#<?VA$W0 *FR/Y4OU<@RLBLM*>S-'Q
M^^ZYH9TJ,!H%"! @0(  @1CMTO<9F$4! @0($"! X+? !I?UJM5MS!;U    
) $E%3D2N0F""
 
end

行の先頭はその行に含まれるオクテット数を示す。通常は45オクテットなので「M」であり、45オクテットに満たない行は別の文字となる。このケースでは「)」である。そのあとデータの終了を示すため、0オクテットを示す「スペース」のみの行が続き、「end」で終わる。

次は「000000」に「`」を用いている一例である。これはGNU sharutils 4.2.1に含まるuuencodeコマンドの出力である。

begin 644 testimg.png
MB5!.1PT*&@H````-24A$4@```"`````@"`8```!S>GKT````!&=!34$``+&/
M"_QA!0```$=)1$%46$?MUK$-`"`(!$#<?VA$W0`*FR/Y4OU<@RLBLM*>S-'Q
M^^ZYH9TJ,!H%"!`@0(``@1CMTO<9F$4!`@0($"!`X+?`!I?UJM5MS!;U````
)`$E%3D2N0F""
`
end

行末にスペースが現れない。この他に、スペースと「`」が混在しているケースも存在する。

これらのフォーマットは多くのデコーダでデコード出来る。

派生フォーマット

(初期のフォーマットには)以下のような問題が存在した。

  • メールなどで行末などのスペースを削除するシステムがある
  • 転送エラーによる文字化けが検出できない
  • ASCIIを前提としているため、EBCDICなどのシステムで問題がある

これらの問題を解決するため、多くの派生フォーマットが誕生した。

スペースの問題は、スペースを「`」に置き換える事で解決された。また、現在多用されているTCP/IPでは、転送エラーはTCPで検出される。同じく多用されているSMTPやNNTPも同様にASCIIを前提としている。よってそれらの環境で問題になることは稀である。

行末のスペースの問題を回避するもの

次はMINIX 3.1.2aのuueコマンドの出力である。

table
 !"#$%&'()*+,-./0123456789:;<=>?
@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
begin 644 testimg.png
MB5!.1PT*&@H    -24A$4@   "     @" 8   !S>GKT    !&=!34$  +&/z
M"_QA!0   $=)1$%46$?MUK$- " (!$#<?VA$W0 *FR/Y4OU<@RLBLM*>S-'Qy
M^^ZYH9TJ,!H%"! @0(  @1CMTO<9F$4! @0($"! X+? !I?UJM5MS!;U    x
) $E%3D2N0F""w
 v
end

行の最後に1文字追加する事で、行末のスペースの問題を回避している。また、追加された文字はアルファベットの小文字の逆順になっており、行を分割して転送した場合に元に戻すときの目印となる。行の先頭文字でオクテット数が示されているため、デコード時に最後に付加された文字が無視されれば、正常にデコードされる可能性がある。

最初のテーブルは、使っている文字を列挙することで、文字が正常に使えるかどうかを確認するためのものである。

チェックサムの追加

次はMark Hortonによって書かれ、Alan J Rosenthatlによって行末にチェックサムが追加されるようになったuuencode.c 5.3-2 (Berkeley) 3/1/88の出力である。最後に元データのオクテット数も追加している。

begin 644 testimg.png
MB5!.1PT*&@H````-24A$4@```"`````@"`8```!S>GKT````!&=!34$``+&/`
M"_QA!0```$=)1$%46$?MUK$-`"`(!$#<?VA$W0`*FR/Y4OU<@RLBLM*>S-'QR
M^^ZYH9TJ,!H%"!`@0(``@1CMTO<9F$4!`@0($"!`X+?`!I?UJM5MS!;U````!
)`$E%3D2N0F""R
``
end
size 144

次はRichard MarksによるDOS用のuuencodeに-Lオプションを付けて、チェックサムを追加した例である。チェックサムの演算方法が上記のものと異なるため、互換性がない。行単位だけでなく全体のチェックサムも追加している。

section 1 of 1 of file testimg.png  < uuencode 96 (v50) by R.E.M. >

begin 644 testimg.png
MB5!.1PT*&@H````-24A$4@```"`````@"`8```!S>GKT````!&=!34$``+&/C
M"_QA!0```$=)1$%46$?MUK$-`"`(!$#<?VA$W0`*FR/Y4OU<@RLBLM*>S-'Q9
M^^ZYH9TJ,!H%"!`@0(``@1CMTO<9F$4!`@0($"!`X+?`!I?UJM5MS!;U````7
)`$E%3D2N0F""?
``
end
sum -r/size 58653/233 section (from "begin" to "end")
sum -r/size 18364/144 entire input file

xxencode

次はxxencodeと呼ばれるフォーマットである。xxencode.c 5.3 (Berkeley) 1/22/85による出力である。

begin 644 testimg.png
hWJ-CFko84Uc++++BGIV2IU+++0+++++U0+M+++-nSbfo++++-4R-HI2++94D
h0zlV-E+++2R7F23IK2Thpf2B+0+6-21QTqV2rE+8amDtIjpQUmgWgh8SnB5l
hyyutcNoeA-c30-+UE6++UFXhojQNa2I-+UE620-+s9T+-dTpehJhn-Pp++++
7+2Z3HYGiEa00
+
end

「000000」から「111111」を「+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 」に割当てている。uuencodeはASCIIの文字を用いているが、EBCDICと呼ばれる文字コードを用いる実装では扱えない文字があったため、使う文字を入れ替えたのがxxencodeである。極めて古い転送路のための手法であり、インターネットではASCIIが使えないケースは稀であるため、xxencodeはほとんど使われない。uuencodeとの互換性は全くない。

POSIX IEEE Std 1003.1

POSIXでは、今迄のアルゴリズムを「歴史的なアルゴリズム (uuencode Historical Algorithm)」とし、新たなアルゴリズムを定義した。

begin-base64 644 testimg.png
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAEdJREFU
WEft1rENACAIBEDcf2hE3QAKmyP5Uv1cgysistKezNHx++65oZ0qMBoFCBAgQIAAgRjt0vcZmEUB
AgQIECBA4LfABpf1qtVtzBb1AAAAAElFTkSuQmCC
====

先頭行は「begin-base64 <mode> <decode_pathname>」、最終行は「====」となっているため、今迄のuuencodeと区別出来る。変換アルゴリズムはBase64をそのまま流用している。これはxxencodeと同様、EBCDIC等への対処である。 そもそもMIMEではuuencodeを除外した経緯があるが、逆にMIMEのBase64をuuencodeに取り込んだ形である。現在は通常のBase64が広く使われているため、この方式はあまり使われない。

MIMEへの対応

電子メールやネットニュースでuuencodeを用いる場合、本文中にuuencode文字列を直接貼付ける方法が取られた。MIMEでは意図的にuuencodeを除外したので、uuencodeをマルチパートで扱う手法は定義されていない。しかしながら、マルチパートの枠組みで扱う実装が多数登場した。大きく分けて2つの手法がある。一方はContent-Transfer-Encodingでx-uuencodeを表す。もう一方はContent-Typeでapplication/x-uuencodeを表す。前者の方が実装が多い。

Content-Type: image/png; name="testimg.png"
Content-Transfer-Encoding: x-uuencode
Content-Disposition: inline; filename="testimg.png"

begin 644 testimg.png
MB5!.1PT*&@H````-24A$4@```"`````@"`8```!S>GKT````!&=!34$``+&/
M"_QA!0```$=)1$%46$?MUK$-`"`(!$#<?VA$W0`*FR/Y4OU<@RLBLM*>S-'Q
M^^ZYH9TJ,!H%"!`@0(``@1CMTO<9F$4!`@0($"!`X+?`!I?UJM5MS!;U````
)`$E%3D2N0F""
`
end
Content-Type: application/x-uuencode; name="testimg.png"
Content-Disposition: attachment; filename="testimg.png"
Content-Transfer-Encoding: 7bit

begin 644 testimg.png
MB5!.1PT*&@H````-24A$4@```"`````@"`8```!S>GKT````!&=!34$``+&/
M"_QA!0```$=)1$%46$?MUK$-`"`(!$#<?VA$W0`*FR/Y4OU<@RLBLM*>S-'Q
M^^ZYH9TJ,!H%"!`@0(``@1CMTO<9F$4!`@0($"!`X+?`!I?UJM5MS!;U````
)`$E%3D2N0F""
`
end

参照

関連項目