Subversion Repositories decoder

Rev

Blame | Last modification | View Log | RSS feed

  1. {Copyright:      Hagen Reddmann  HaReddmann at T-Online dot de
  2.  Author:         Hagen Reddmann
  3.  Version:        5.1, Delphi Encryption Compendium
  4.                  Delphi 5-7, BCB 3-4, designed and testet under D5
  5.  Description:    Format Konvertion Utilitys for the DEC Packages
  6.  known Problems: none
  7.  Remarks:        freeware, but this Copyright must be included
  8.                  add about 10Kb code if all TFormats used
  9.                  designed to made universal code, not very fast implementations
  10.                  use lookup tables and formats can contains special chars
  11.  
  12.  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
  13.  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  14.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  15.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
  16.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  17.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  18.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  19.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  20.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  21.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  22.  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. }
  24.  
  25. unit DECFmt;
  26.  
  27. interface
  28.  
  29. uses Windows, SysUtils, Classes, DECUtil;
  30.  
  31. {$I VER.INC}
  32.  
  33. type
  34.   TDECFormat      = class;
  35.  
  36.   TFormat_Copy    = class;    // copy input to output, it's the Default Format, eg FormaClass = nil
  37.   TFormat_HEX     = class;    // HEXadecimal in UpperCase
  38.   TFormat_HEXL    = class;    // HEXadecimal in Lowercase
  39.   TFormat_MIME32  = class;    // MIME like format for Base 32
  40.   TFormat_MIME64  = class;    // MIME Base 64 format
  41.   TFormat_PGP     = class;    // PGP's MIME Base 64 with PGP's Checksums
  42.   TFormat_UU      = class;    // Unix UU Base 64
  43.   TFormat_XX      = class;    // Unix XX base 64
  44.   TFormat_ESCAPE  = class;    // Escaped Strings
  45.  
  46.   TDECFormatClass = class of TDECFormat;
  47.  
  48.   TDECFormat = class(TDECObject) // for binary one to one convert = fmtCOPY
  49.   protected
  50.     class function DoEncode(const Value; Size: Integer): Binary; virtual; abstract;
  51.     class function DoDecode(const Value; Size: Integer): Binary; virtual; abstract;
  52.     class function DoIsValid(const Value; Size: Integer): Boolean; virtual; abstract;
  53.   public
  54.     class function Encode(const Value: Binary): Binary; overload;
  55.     class function Encode(const Value; Size: Integer): Binary; overload;
  56.     class function Decode(const Value: Binary): Binary; overload;
  57.     class function Decode(const Value; Size: Integer): Binary; overload;
  58.     class function IsValid(const Value: Binary): Boolean; overload;
  59.     class function IsValid(const Value; Size: Integer): Boolean; overload;
  60.   end;
  61.  
  62.   TFormat_Copy = class(TDECFormat)
  63.   protected
  64.     class function DoEncode(const Value; Size: Integer): Binary; override;
  65.     class function DoDecode(const Value; Size: Integer): Binary; override;
  66.     class function DoIsValid(const Value; Size: Integer): Boolean; override;
  67.   end;
  68.  
  69.   TFormat_HEX = class(TDECFormat) // Hexadecimal = fmtHEX
  70.   protected
  71.     class function DoEncode(const Value; Size: Integer): Binary; override;
  72.     class function DoDecode(const Value; Size: Integer): Binary; override;
  73.     class function DoIsValid(const Value; Size: Integer): Boolean; override;
  74.   public
  75.     class function CharTable: PChar; virtual;
  76.   end;
  77.  
  78.   TFormat_HEXL = class(TFormat_HEX) // Hexadecimal lowercase = fmtHEXL
  79.   public
  80.     class function CharTable: PChar; override;
  81.   end;
  82.  
  83.   TFormat_MIME32 = class(TFormat_HEX)  // MIME Base 32 = fmtMIME32
  84.   protected
  85.     class function DoEncode(const Value; Size: Integer): Binary; override;
  86.     class function DoDecode(const Value; Size: Integer): Binary; override;
  87.   public
  88.     class function CharTable: PChar; override;
  89.   end;
  90.  
  91.   TFormat_MIME64 = class(TFormat_HEX)  // MIME Base 64 = fmtMIME64
  92.   protected
  93.     class function DoEncode(const Value; Size: Integer): Binary; override;
  94.     class function DoDecode(const Value; Size: Integer): Binary; override;
  95.   public
  96.     class function CharTable: PChar; override;
  97.   end;
  98.  
  99.   TFormat_PGP = class(TFormat_MIME64)
  100.   protected
  101.     class function DoExtractCRC(const Value; var Size: Integer): LongWord;
  102.     class function DoEncode(const Value; Size: Integer): Binary; override;
  103.     class function DoDecode(const Value; Size: Integer): Binary; override;
  104.   end;
  105.  
  106.   TFormat_UU = class(TDECFormat) // UU Encode = fmtUU
  107.   protected
  108.     class function DoEncode(const Value; Size: Integer): Binary; override;
  109.     class function DoDecode(const Value; Size: Integer): Binary; override;
  110.     class function DoIsValid(const Value; Size: Integer): Boolean; override;
  111.   public
  112.     class function CharTable: PChar; virtual;
  113.   end;
  114.  
  115.   TFormat_XX = class(TFormat_UU) // XX Encode = fmtXX
  116.   public
  117.     class function CharTable: PChar; override;
  118.   end;
  119.  
  120.   TFormat_ESCAPE = class(TDECFormat)
  121.   protected
  122.     class function DoEncode(const Value; Size: Integer): Binary; override;
  123.     class function DoDecode(const Value; Size: Integer): Binary; override;
  124.   end;
  125.  
  126. function  ValidFormat(FormatClass: TDECFormatClass = nil): TDECFormatClass;
  127. function  FormatByName(const Name: String): TDECFormatClass;
  128. function  FormatByIdentity(Identity: LongWord): TDECFormatClass;
  129. // insert #13#10 Chars in Blocks from BlockSize
  130. function InsertCR(const Value: String; BlockSize: Integer): String;
  131. // delete all #13 and #10 Chars
  132. function DeleteCR(const Value: String): String;
  133. // format any String to a Block
  134. function InsertBlocks(const Value, BlockStart, BlockEnd: String; BlockSize: Integer): String;
  135. // remove any Block format
  136. function RemoveBlocks(const Value, BlockStart, BlockEnd: String): String;
  137.  
  138. var
  139.   PGPCharsPerLine: Integer = 80;
  140.  
  141. implementation
  142.  
  143. uses CRC;
  144.  
  145. resourcestring
  146.   sStringFormatExists     = 'String format "%d" not exists.';
  147.   sInvalidStringFormat    = 'Input is not an valid %s Format.';
  148.   sInvalidFormatString    = 'Input can not be convert to %s Format.';
  149.   sFormatNotRegistered    = 'String format not registered.';
  150.  
  151. function ValidFormat(FormatClass: TDECFormatClass = nil): TDECFormatClass;
  152. begin
  153.   if FormatClass <> nil then Result := FormatClass
  154.     else Result := TFormat_Copy;
  155. end;
  156.  
  157. function FormatByName(const Name: String): TDECFormatClass;
  158. begin
  159.   Result := TDECFormatClass(DECClassByName(Name, TDECFormat));
  160. end;
  161.  
  162. function FormatByIdentity(Identity: LongWord): TDECFormatClass;
  163. begin
  164.   Result := TDECFormatClass(DECClassByIdentity(Identity, TDECFormat));
  165. end;
  166.  
  167. class function TDECFormat.Encode(const Value: Binary): Binary;
  168. begin
  169.   Result := DoEncode(Value[1], Length(Value));
  170. end;
  171.  
  172. class function TDECFormat.Encode(const Value; Size: Integer): Binary;
  173. begin
  174.   Result := DoEncode(Value, Size);
  175. end;
  176.  
  177. class function TDECFormat.Decode(const Value: Binary): Binary;
  178. begin
  179.   Result := DoDecode(Value[1], Length(Value));
  180. end;
  181.  
  182. class function TDECFormat.Decode(const Value; Size: Integer): Binary;
  183. begin
  184.   Result := DoDecode(Value, Size);
  185. end;
  186.  
  187. class function TDECFormat.IsValid(const Value: Binary): Boolean;
  188. begin
  189.   Result := DoIsValid(Value[1], Length(Value));
  190. end;
  191.  
  192. class function TDECFormat.IsValid(const Value; Size: Integer): Boolean;
  193. begin
  194.   Result := DoIsValid(Value, Size);
  195. end;
  196.  
  197. // .TFormat_Copy
  198. class function TFormat_Copy.DoEncode(const Value; Size: Integer): Binary;
  199. begin
  200.   SetLength(Result, Size);
  201.   Move(Value, Result[1], Size);
  202. end;
  203.  
  204. class function  TFormat_Copy.DoDecode(const Value; Size: Integer): Binary;
  205. begin
  206.   SetLength(Result, Size);
  207.   Move(Value, Result[1], Size);
  208. end;
  209.  
  210. class function  TFormat_Copy.DoIsValid(const Value; Size: Integer): Boolean;
  211. begin
  212.   Result := Size >= 0;
  213. end;
  214.  
  215. function TableFind(Value: Char; Table: PChar; Len: Integer): Integer; assembler;
  216. asm // Utility for TStringFormat_XXXXX
  217.       PUSH  EDI
  218.       MOV   EDI,EDX
  219.       REPNE SCASB
  220.       MOV   EAX,0
  221.       JNE   @@1
  222.       MOV   EAX,EDI
  223.       SUB   EAX,EDX
  224. @@1:  DEC   EAX
  225.       POP   EDI
  226. end;
  227.  
  228. class function TFormat_HEX.DoEncode(const Value; Size: Integer): Binary;
  229. var
  230.   S: PByte;
  231.   D,T: PChar;
  232. begin
  233.   Result := '';
  234.   if Size <= 0 then Exit;
  235.   SetLength(Result, Size * 2);
  236.   T := CharTable;
  237.   D := PChar(Result);
  238.   S := PByte(@Value);
  239.   while Size > 0 do
  240.   begin
  241.     D[0] := T[S^ shr  4];
  242.     D[1] := T[S^ and $F];
  243.     Inc(D, 2);
  244.     Inc(S);
  245.     Dec(Size);
  246.   end;
  247. end;
  248.  
  249. class function TFormat_HEX.DoDecode(const Value; Size: Integer): Binary;
  250. var
  251.   S: PChar;
  252.   D: PByte;
  253.   T: PChar;
  254.   I,P: Integer;
  255.   HasIdent: Boolean;
  256. begin
  257.   Result := '';
  258.   if Size <= 0 then Exit;
  259.   SetLength(Result, Size div 2 +1);
  260.   T := CharTable;
  261.   D := PByte(Result);
  262.   S := PChar(@Value);
  263.   I := 0;
  264.   HasIdent := False;
  265.   while Size > 0 do
  266.   begin
  267.     P := TableFind(S^, T, 18);
  268.     if P < 0 then P := TableFind(UpCase(S^), T, 16);
  269.     if P < 0 then
  270.       raise EDECException.CreateFmt(sInvalidStringFormat, [DECClassname(Self)]);
  271.     Inc(S);
  272.     if P >= 0 then
  273.       if P > 16 then
  274.       begin
  275.         if not HasIdent then
  276.         begin
  277.           HasIdent := True;
  278.           I := 0;
  279.           D := PByte(Result);
  280.         end;
  281.       end else
  282.       begin
  283.         if Odd(I) then
  284.         begin
  285.           D^ := D^ or P;
  286.           Inc(D);
  287.         end else D^ := P shl 4;
  288.         Inc(I);
  289.       end;
  290.     Dec(Size);
  291.   end;
  292.   SetLength(Result, PChar(D) - PChar(Result));
  293. end;
  294.  
  295. class function TFormat_HEX.DoIsValid(const Value; Size: Integer): Boolean;
  296. var
  297.   S,T: PChar;
  298.   L: Integer;
  299. begin
  300.   Result := True;
  301.   T := CharTable;
  302.   L := StrLen(T);
  303.   S := PChar(@Value);
  304.   while Result and (Size > 0) do
  305.     if TableFind(S^, T, L) >= 0 then
  306.     begin
  307.       Dec(Size);
  308.       Inc(S);
  309.     end else Result := False;
  310. end;
  311.  
  312. class function TFormat_HEX.CharTable: PChar; assembler;
  313. asm
  314.       MOV  EAX,OFFSET @@1
  315.       RET
  316. @@1:  DB   '0123456789ABCDEF'     // Table must be >= 18 Chars
  317.       DB   'X$ abcdefhHx()[]{},;:-_/\*+"''',9,10,13,0
  318. end;
  319.  
  320. class function TFormat_HEXL.CharTable: PChar;
  321. asm
  322.       MOV  EAX,OFFSET @@1
  323.       RET
  324. @@1:  DB   '0123456789abcdef'     // Table must be >= 18 Chars
  325.       DB   'X$ ABCDEFhHx()[]{},;:-_/\*+"''',9,10,13,0
  326. end;
  327.  
  328. class function TFormat_MIME32.DoEncode(const Value; Size: Integer): Binary;
  329. var
  330.   S: PByteArray;
  331.   D,T: PChar;
  332.   I: Integer;
  333. begin
  334.   Result := '';
  335.   if Size <= 0 then Exit;
  336.   Size := Size * 8;
  337.   SetLength(Result, Size div 5 + 5);
  338.   D := PChar(Result);
  339.   T := CharTable;
  340.   S := PByteArray(@Value);
  341.   I := 0;
  342.   while I < Size do
  343.   begin
  344.     D^ := T[PWord(@S[I shr 3])^ shr (I and $7) and $1F];
  345.     Inc(D);
  346.     Inc(I, 5);
  347.   end;
  348.   SetLength(Result, D - PChar(Result));
  349. end;
  350.  
  351. class function TFormat_MIME32.DoDecode(const Value; Size: Integer): Binary;
  352. var
  353.   S,T,D: PChar;
  354.   I,V: Integer;
  355. begin
  356.   Result := '';
  357.   if Size <= 0 then Exit;
  358.   T := CharTable;
  359.   SetLength(Result, Size * 5 div 8);
  360.   D := PChar(Result);
  361.   FillChar(D^, Length(Result), 0);
  362.   S := PChar(@Value);
  363.   Size := Size * 5;
  364.   I := 0;
  365.   while I < Size do
  366.   begin
  367.     V := TableFind(S^, T, 32);
  368.     if V < 0 then V := TableFind(UpCase(S^), T, 32);
  369.     if V >= 0 then
  370.     begin
  371.       PWord(@D[I shr 3])^ := PWord(@D[I shr 3])^ or (V shl (I and $7));
  372.       Inc(I, 5);
  373.     end else Dec(Size, 5);
  374.     Inc(S);
  375.   end;
  376.   SetLength(Result, Size div 8);
  377. end;
  378.  
  379. class function TFormat_MIME32.CharTable: PChar;
  380. asm
  381.       MOV  EAX,OFFSET @@1
  382.       RET  // must be >= 32 Chars
  383. @@1:  DB  'abcdefghijklnpqrstuwxyz123456789'
  384.       DB  ' =$()[]{},;:-_\*"''',9,10,13,0  // special and skipped chars
  385. end;
  386.  
  387. class function TFormat_MIME64.DoEncode(const Value; Size: Integer): Binary;
  388. var
  389.   B: Cardinal;
  390.   I: Integer;
  391.   D,T: PChar;
  392.   S: PByteArray;
  393. begin
  394.   Result := '';
  395.   if Size <= 0 then Exit;
  396.   SetLength(Result, Size * 4 div 3 + 4);
  397.   D := PChar(Result);
  398.   T := CharTable;
  399.   S := PByteArray(@Value);
  400.   while Size >= 3 do
  401.   begin
  402.     Dec(Size, 3);
  403.     B := S[0] shl 16 or S[1] shl 8 or S[2];
  404.     D[0] := T[B shr 18 and $3F];
  405.     D[1] := T[B shr 12 and $3F];
  406.     D[2] := T[B shr  6 and $3F];
  407.     D[3] := T[B        and $3F];
  408.     Inc(D, 4);
  409.     S := @S[3];
  410.   end;
  411.   while Size > 0 do
  412.   begin
  413.     B := 0;
  414.     for I := 0 to 2 do
  415.     begin
  416.       B := B shl 8;
  417.       if Size > 0 then
  418.       begin
  419.         B := B or S[0];
  420.         S := @S[1];
  421.       end;
  422.       Dec(Size);
  423.     end;
  424.     for I := 3 downto 0 do
  425.     begin
  426.       if Size < 0 then
  427.       begin
  428.         D[I] := T[64];
  429.         Inc(Size);
  430.       end else D[I] := T[B and $3F];
  431.       B := B shr 6;
  432.     end;
  433.     Inc(D, 4);
  434.   end;
  435.   SetLength(Result, D - PChar(Result));
  436. end;
  437.  
  438. class function TFormat_MIME64.DoDecode(const Value; Size: Integer): Binary;
  439. var
  440.   B: Cardinal;
  441.   J,I: Integer;
  442.   S,D,L,T: PChar;
  443. begin
  444.   Result := '';
  445.   if Size <= 0 then Exit;
  446.   SetLength(Result, Size);
  447.   Move(Value, PChar(Result)^, Size);
  448.   T := CharTable;
  449.   D := PChar(Result);
  450.   S := D;
  451.   L := S + Size;
  452.   J := 0;
  453.   while S < L do
  454.   begin
  455.     B := 0;
  456.     J := 4;
  457.     while (J > 0) and (S < L) do
  458.     begin
  459.       I := TableFind(S^, T, 65);
  460.       Inc(S);
  461.       if I >= 0 then
  462.         if I < 64 then
  463.         begin
  464.           B := B shl 6 or Byte(I);
  465.           Dec(J);
  466.         end else L := S;
  467.     end;
  468.     if J > 0 then
  469.       if J >= 4 then
  470.       begin
  471.         J := 0;
  472.         Break;
  473.       end else B := B shl (6 * J);
  474.     I := 2;
  475.     while I >= 0 do
  476.     begin
  477.       D[I] := Char(B);
  478.       B := B shr 8;
  479.       Dec(I);
  480.     end;
  481.     Inc(D, 3);
  482.   end;
  483.   SetLength(Result, D - PChar(Result) - J);
  484. end;
  485.  
  486. class function TFormat_MIME64.CharTable: PChar; assembler;
  487. asm
  488.       MOV  EAX,OFFSET @@1
  489.       RET  // must be >= 65 Chars
  490. @@1:  DB  'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
  491.       DB  ' $()[]{},;:-_\*"''',9,10,13,0  // special and skipped chars
  492. end;
  493.  
  494. class function TFormat_PGP.DoExtractCRC(const Value; var Size: Integer): LongWord;
  495. var
  496.   L: PChar;
  497.   C: Char;
  498.   R: String;
  499. begin
  500.   Result := $FFFFFFFF;
  501.   C := CharTable[64];                      // get padding char, per default '='
  502.   L := PChar(@Value) + Size;
  503.   while L <> PChar(@Value) do
  504.     if L^ = C then Break else Dec(L);      // scan reverse for padding char
  505.   if L - PChar(@Value) >= Size - 5 then    // remaining chars must be > 4 ,i.e. '=XQRT'
  506.   try
  507.     Inc(L);
  508.     R := inherited DoDecode(L^, Size - (L - PChar(@Value)));
  509.     if Length(R) >= 3 then
  510.     begin
  511.       Result := 0;
  512.       Move(PChar(R)^, Result, 3);
  513.       Size := L - PChar(@Value);
  514.     end;
  515.   except
  516.   end;
  517. end;
  518.  
  519. class function TFormat_PGP.DoEncode(const Value; Size: Integer): Binary;
  520. var
  521.   CRC: LongWord;
  522. begin
  523.   Result := '';
  524.   if Size <= 0 then Exit;
  525.   Result := InsertCR(inherited DoEncode(Value, Size), PGPCharsPerLine); // 80 chars per line
  526.   CRC := CRCCalc(CRC_24, Value, Size);                               // calculate 24Bit Checksum
  527.   SwapBytes(CRC, 3);                                                 // PGP use Big Endian
  528.   if Result[Length(Result)] <> #10 then Result := Result + #13#10;   // insert CR iff needed, CRC must be in next line
  529.   Result := Result + '=' + inherited DoEncode(CRC, 3);                 // append CRC
  530. end;
  531.  
  532. class function TFormat_PGP.DoDecode(const Value; Size: Integer): Binary;
  533. var
  534.   CRC: LongWord;
  535. begin
  536.   Result := '';
  537.   if Size <= 0 then Exit;
  538.   CRC := DoExtractCRC(Value, Size);
  539.   Result := inherited DoDecode(Value, Size);
  540.   if CRC <> $FFFFFFFF then // iff CRC found check it
  541.   begin
  542.     SwapBytes(CRC, 3);
  543.     if CRC <> CRCCalc(CRC_24, PChar(Result)^, Length(Result)) then
  544.       raise EDECException.CreateFmt(sInvalidStringFormat, [DECClassname(Self)]);
  545.   end;
  546. end;
  547.  
  548. class function TFormat_UU.DoEncode(const Value; Size: Integer): Binary;
  549. var
  550.   S,T,D: PChar;
  551.   L,I: Integer;
  552.   B: Cardinal;
  553. begin
  554.   Result := '';
  555.   if Size <= 0 then Exit;
  556.   SetLength(Result, Size * 4 div 3 + Size div 45 + 10);
  557.   D := PChar(Result);
  558.   T := CharTable;
  559.   S := PChar(@Value);
  560.   while Size > 0 do
  561.   begin
  562.     L := Size;
  563.     if L > 45 then L := 45;
  564.     Dec(Size, L);
  565.     D^ := T[L];
  566.     while L > 0 do
  567.     begin
  568.       B := 0;
  569.       for I := 0 to 2 do
  570.       begin
  571.         B := B shl 8;
  572.         if L > 0 then
  573.         begin
  574.           B := B or Byte(S^);
  575.           Inc(S);
  576.         end;
  577.         Dec(L);
  578.       end;
  579.       for I := 4 downto 1 do
  580.       begin
  581.         D[I] := T[B and $3F];
  582.         B := B shr 6;
  583.       end;
  584.       Inc(D, 4);
  585.     end;
  586.     Inc(D);
  587.   end;
  588.   SetLength(Result, D - PChar(Result));
  589. end;
  590.  
  591. class function TFormat_UU.DoDecode(const Value; Size: Integer): Binary;
  592. var
  593.   T,D,L,S: PChar;
  594.   I,E: Integer;
  595.   B: Cardinal;
  596. begin
  597.   Result := '';
  598.   if Size <= 0 then Exit;
  599.   SetLength(Result, Size);
  600.   S := PChar(@Value);
  601.   L := S + Size;
  602.   D := PChar(Result);
  603.   T := CharTable;
  604.   repeat
  605.     Size := TableFind(S^, T, 64);
  606.     if (Size < 0) or (Size > 45) then
  607.       raise EDECException.CreateFmt(sInvalidStringFormat, [DECClassName(Self)]);
  608.     Inc(S);
  609.     while Size > 0 do
  610.     begin
  611.       B := 0;
  612.       I := 4;
  613.       while (I > 0) and (S <= L) do
  614.       begin
  615.         E := TableFind(S^, T, 64);
  616.         if E >= 0 then
  617.         begin
  618.           B := B shl 6 or Byte(E);
  619.           Dec(I);
  620.         end;
  621.         Inc(S);
  622.       end;
  623.       I := 2;
  624.       repeat
  625.         D[I] := Char(B);
  626.         B    := B shr 8;
  627.         Dec(I);
  628.       until I < 0;
  629.       if Size > 3 then Inc(D, 3) else Inc(D, Size);
  630.       Dec(Size, 3);
  631.     end;
  632.   until S >= L;
  633.   SetLength(Result, D - PChar(Result));
  634. end;
  635.  
  636. class function TFormat_UU.DoIsValid(const Value; Size: Integer): Boolean;
  637. var
  638.   S,T: PChar;
  639.   L,I,P: Integer;
  640. begin
  641.   Result := False;
  642.   T := CharTable;
  643.   L := StrLen(T);
  644.   S := PChar(@Value);
  645.   P := 0;
  646.   while Size > 0 do
  647.   begin
  648.     I := TableFind(S^, T, L);
  649.     if I >= 0 then
  650.     begin
  651.       Dec(Size);
  652.       Inc(S);
  653.       if P = 0 then
  654.       begin
  655.         if I > 45 then Exit;
  656.         P := (I * 4 + 2) div 3;
  657.       end else
  658.         if I < 64 then Dec(P);
  659.     end else Exit;
  660.   end;
  661.   if P <> 0 then Exit;
  662.   Result := True;
  663. end;
  664.  
  665. class function TFormat_UU.CharTable: PChar;
  666. asm
  667.       MOV  EAX,OFFSET @@1
  668.       RET  // must be >= 64 Chars
  669. @@1:  DB   '`!"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_'
  670.       DB   ' ',9,10,13,0
  671. end;
  672.  
  673. class function TFormat_XX.CharTable: PChar;
  674. asm
  675.       MOV  EAX,OFFSET @@1
  676.       RET
  677. @@1:  DB   '+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
  678.       DB   ' "()[]''',9,10,13,0
  679. end;
  680.  
  681. const
  682.   ESCAPE_CodesL: PChar = 'abtnvfr';
  683.   ESCAPE_CodesU: PChar = 'ABTNVFR';
  684.  
  685. class function TFormat_ESCAPE.DoDecode(const Value; Size: Integer): Binary;
  686. var
  687.   D,S,T: PChar;
  688.   I: Integer;
  689. begin
  690.   Result := '';
  691.   if Size <= 0 then Exit;
  692.   SetLength(Result, Size);
  693.   D := PChar(Result);
  694.   S := PChar(@Value);
  695.   T := S + Size;
  696.   while S < T do
  697.   begin
  698.     if S^ = '\' then
  699.     begin
  700.       Inc(S);
  701.       if S > T then Break;
  702.       if UpCase(S^) = 'X' then
  703.       begin
  704.         if S + 2 > T then
  705.           raise EDECException.CreateFmt(sInvalidStringFormat, [DECClassName(Self)]);
  706.         I := TableFind(UpCase(S[1]), TFormat_HEX.CharTable, 16);
  707.         if I < 0 then
  708.           raise EDECException.CreateFmt(sInvalidStringFormat, [DECClassName(Self)]);
  709.         D^ := Char(I shl 4);
  710.         I := TableFind(UpCase(S[2]), TFormat_HEX.CharTable, 16);
  711.         if I < 0 then
  712.           raise EDECException.CreateFmt(sInvalidStringFormat, [DECClassName(Self)]);
  713.         D^ := Char(Byte(D^) or I);
  714.         Inc(S, 2);
  715.       end else
  716.       begin
  717.         I := TableFind(UpCase(S^), ESCAPE_CodesU, 7);
  718.         if I >= 0 then D^ := Char(I + 7)
  719.           else D^ := S^;
  720.       end;
  721.     end else D^ := S^;
  722.     Inc(D);
  723.     Inc(S);
  724.   end;
  725.   SetLength(Result, D - PChar(Result));
  726. end;
  727.  
  728. class function TFormat_ESCAPE.DoEncode(const Value; Size: Integer): Binary;
  729. var
  730.   S: PByte;
  731.   D,T: PChar;
  732.   I: Integer;
  733. begin
  734.   Result := '';
  735.   if Size = 0 then Exit;
  736.   SetLength(Result, Size + 8);
  737.   I := Size;
  738.   D := PChar(Result);
  739.   S := PByte(@Value);
  740.   T := TFormat_HEX.CharTable;
  741.   while Size > 0 do
  742.   begin
  743.     if I <= 0 then
  744.     begin
  745.       I := D - PChar(Result);
  746.       SetLength(Result, I + Size + 8);
  747.       D := PChar(Result) + I;
  748.       I := Size;
  749.     end;
  750.     if (S^ < 32) {or (S^ > $7F)} then
  751.       if (S^ >= 7) and (S^ <= 13) then
  752.       begin
  753.         D[0] := '\';
  754.         D[1] := ESCAPE_CodesL[S^ - 7];
  755.         Inc(D, 2);
  756.         Dec(I, 2);
  757.       end else
  758.       begin
  759.         D[0] := '\';
  760.         D[1] := 'x';
  761.         D[2] := T[S^ shr 4];
  762.         D[3] := T[S^ and $F];
  763.         Inc(D, 4);
  764.         Dec(I, 4);
  765.       end
  766.     else
  767.       if S^ = Ord('\') then
  768.       begin
  769.         D[0] := '\';
  770.         D[1] := '\';
  771.         Inc(D, 2);
  772.         Dec(I, 2);
  773.       end else
  774.         if S^ = Ord('"') then
  775.         begin
  776.           D[0] := '\';
  777.           D[1] := '"';
  778.           Inc(D, 2);
  779.           Dec(I, 2);
  780.         end else
  781.         begin
  782.           D^ := Char(S^);
  783.           Inc(D);
  784.           Dec(I);
  785.         end;
  786.     Dec(Size);
  787.     Inc(S);
  788.   end;
  789.   SetLength(Result, D - PChar(Result));
  790. end;
  791.  
  792. function InsertCR(const Value: String; BlockSize: Integer): String;
  793. var
  794.   I: Integer;
  795.   S,D: PChar;
  796. begin
  797.   if (BlockSize <= 0) or (Length(Value) <= BlockSize) then
  798.   begin
  799.     Result := Value;
  800.     Exit;
  801.   end;
  802.   I := Length(Value);
  803.   SetLength(Result, I + I * 2 div BlockSize + 2);
  804.   S := PChar(Value);
  805.   D := PChar(Result);
  806.   repeat
  807.     Move(S^, D^, BlockSize);
  808.     Inc(S, BlockSize);
  809.     Inc(D, BlockSize);
  810.     D^ := #13; Inc(D);
  811.     D^ := #10; Inc(D);
  812.     Dec(I, BlockSize);
  813.   until I < BlockSize;
  814.   Move(S^, D^, I);
  815.   Inc(D, I);
  816.   SetLength(Result, D - PChar(Result));
  817. end;
  818.  
  819. function DeleteCR(const Value: String): String;
  820. var
  821.   S,D: PChar;
  822.   I: Integer;
  823. begin
  824.   I := Length(Value);
  825.   SetLength(Result, I);
  826.   D := PChar(Result);
  827.   S := PChar(Value);
  828.   while I > 0 do
  829.   begin
  830.     if (S^ <> #10) and (S^ <> #13) then
  831.     begin
  832.       D^ := S^;
  833.       Inc(D);
  834.     end;
  835.     Inc(S);
  836.     Dec(I);
  837.   end;
  838.   SetLength(Result, D - PChar(Result));
  839. end;
  840.  
  841. function InsertBlocks(const Value, BlockStart, BlockEnd: String; BlockSize: Integer): String;
  842. var
  843.   I,LS,LE: Integer;
  844.   D,S: PChar;
  845. begin
  846.   if (BlockSize <= 0) or (Length(Value) <= BlockSize) then
  847.   begin
  848.     Result := Value;
  849.     Exit;
  850.   end;
  851.   I := Length(Value);
  852.   LS := Length(BlockStart);
  853.   LE := Length(BlockEnd);
  854.   SetLength(Result, I + (I div BlockSize + 1) * (LS + LE));
  855.   S := PChar(Value);
  856.   D := PChar(Result);
  857.   repeat
  858.     Move(PChar(BlockStart)^, D^, LS); Inc(D, LS);
  859.     Move(S^, D^, BlockSize);          Inc(D, BlockSize);
  860.     Move(PChar(BlockEnd)^, D^, LE);   Inc(D, LE);
  861.     Dec(I, BlockSize);
  862.     Inc(S, BlockSize);
  863.   until I < BlockSize;
  864.   if I > 0 then
  865.   begin
  866.     Move(PChar(BlockStart)^, D^, LS); Inc(D, LS);
  867.     Move(S^, D^, I);                  Inc(D, I);
  868.     Move(PChar(BlockEnd)^, D^, LE);   Inc(D, LE);
  869.   end;
  870.   SetLength(Result, D - PChar(Result));
  871. end;
  872.  
  873. function RemoveBlocks(const Value, BlockStart, BlockEnd: String): String;
  874. var
  875.   LS,LE: Integer;
  876.   S,D,L,K: PChar;
  877. begin
  878.   SetLength(Result, Length(Value));
  879.   LS := Length(BlockStart);
  880.   LE := Length(BlockEnd);
  881.   D := PChar(Result);
  882.   S := PChar(Value);
  883.   L := S + Length(Value);
  884.   repeat
  885.     if S > L then Break;
  886.     if LS > 0 then
  887.     begin
  888.       S := StrPos(S, PChar(BlockStart));
  889.       if S = nil then Break;
  890.       Inc(S, LS);
  891.       if S > L then Break;
  892.     end;
  893.     K := StrPos(S, PChar(BlockEnd));
  894.     if K = nil then K := L;
  895.     Move(S^, D^, K - S);
  896.     Inc(D, K - S);
  897.     S := K + LE;
  898.   until S >= L;
  899.   SetLength(Result, D - PChar(Result));
  900. end;
  901.  
  902. end.
  903.  
  904.