Выбрать главу

Заметим что если для UUEncodeиспользуется подмножество набора символов ASCII (32..96), то для XXEncode это не так.

Для преобразования процедур Triplet2Kwartet и Kwartet2Triplet для поддержки мы вводим дополнительный массив из 64 символов.

Нам также необходимо модифицировать процедуры Triplet2Kwartet и Kwartet2Triplet следующим образом.

const

   XX: Array[0..63] of Char =

      '+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';

 procedure Triplet2Kwartet(const Triplet: TTriplet; var Kwartet: TKwartet);

 var

   i: Integer;

 begin

   Kwartet[0] := (Triplet[0] SHR 2);

   Kwartet[1] := ((Triplet[0] SHL 4) AND $30) +

                 ((Triplet[1] SHR 4) AND $0F);

   Kwartet[2] := ((Triplet[1] SHL 2) AND $3C) +

                 ((Triplet[2] SHR 6) AND $03);

   Kwartet[3] := (Triplet[2] AND $3F);

   for i:=0 to 3 do

     if Kwartet[i] = 0 then Kwartet[i] := $40 + Ord(SP)

     else Inc(Kwartet[i],Ord(SP));

   if XXCode then

     for i:=0 to 3 do Kwartet[i] := Ord(XX[(Kwartet[i] - Ord(SP)) mod $40])

 end {Triplet2Kwartet};

Последние несколько строк новые для процедуры Triplet2Kwartet и мы используем набор символов XXencode для возврата правильно закодированных символов. Помните, что UUEncode возвращает индекс кодированного символа, после чего мы к нему добавляем код #32, так что если XXencode используется после преобразования в UUEncode, то мы должны вычесть 32 и использовать результат как индекс в таблицу символов XXencode.

То же самое относится и к процедуре Kwartet2Triplet, где мы должны преобразовать XXencode символы перед использованием алгоритма UUdecode (заметим, что мы теперь не передаем Kwartet как const).

procedure Kwartet2Triplet(Kwartet: TKwartet; var Triplet: TTriplet);

 var

   i: Integer;

 begin

   if XXCode then

   begin

     for i:=0 to 3 do

     begin

       case Chr(Kwartet[i]) of

             '+': Kwartet[i] := 0 + Ord(SP);

             '-': Kwartet[i] := 1 + Ord(SP);

        '0'..'9': Kwartet[i] := 2 + Kwartet[i]

                                  - Ord('0') + Ord(SP);

        'A'..'Z': Kwartet[i] := 12 + Kwartet[i]

                                   - Ord('A') + Ord(SP);

        'a'..'z': Kwartet[i] := 38 + Kwartet[i]

                                   - Ord('a') + Ord(SP)

       end

     end

   end;

   Triplet[0] :=  ((Kwartet[0] - Ord(SP)) SHL 2) +

                 (((Kwartet[1] - Ord(SP)) AND $30) SHR 4);

   Triplet[1] := (((Kwartet[1] - Ord(SP)) AND $0F) SHL 4) +

                 (((Kwartet[2] - Ord(SP)) AND $3C) SHR 2);

   Triplet[2] := (((Kwartet[2] - Ord(SP)) AND $03) SHL 6) +

                  ((Kwartet[3] - Ord(SP)) AND $3F)

 end {Kwartet2Triplet};

Заметим, что в новой версии этих процедур используется глобальная переменная XXCode логического типа для определения типа кодирования.

1.1.3. Base64

Алгоритм кодирования Base64 отличается от алгоритмов UUencode и XXencode тем, что в нем не используется первый символ как индикатор длины. Общее то что используется алгоритм преобразования триплетов в квартеты с помощью 64 байтной таблицы преобразования.

Набор символов Base64
0 A 8 I 16 Q 24 Y 32 g 40 o 48 w 56 4
1 B 9 J 17 R 25 Z 33 h 41 p 49 x 57 5
2 C 10 K 18 S 26 a 34 I 42 q 50 y 58 6
3 D 11 L 19 T 27 b 35 j 43 r 51 z 59 7
4 E 12 M 20 U 28 c 36 k 44 s 52 0 60 8
5 F 13 N 21 V 29 d 37 l 45 t 53 1 61 9
6 G 14 O 22 W 30 e 38 m 46 u 54 2 62 +
7 H 15 P 23 X 31 f 39 n 47 v 55 3 63 /