home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 December / Chip_2001-12_cd1.bin / zkuste / delphi / unity / d23456 / SYNAPSE.ZIP / source / lib / SynaCode.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2001-08-25  |  25.1 KB  |  692 lines

  1. {==============================================================================|
  2. | Project : Delphree - Synapse                                   | 001.004.001 |
  3. |==============================================================================|
  4. | Content: Coding and decoding support                                         |
  5. |==============================================================================|
  6. | The contents of this file are subject to the Mozilla Public License Ver. 1.1 |
  7. | (the "License"); you may not use this file except in compliance with the     |
  8. | License. You may obtain a Copy of the License at http://www.mozilla.org/MPL/ |
  9. |                                                                              |
  10. | Software distributed under the License is distributed on an "AS IS" basis,   |
  11. | WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for |
  12. | the specific language governing rights and limitations under the License.    |
  13. |==============================================================================|
  14. | The Original Code is Synapse Delphi Library.                                 |
  15. |==============================================================================|
  16. | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
  17. | Portions created by Lukas Gebauer are Copyright (c)2000, 2001.               |
  18. | All Rights Reserved.                                                         |
  19. |==============================================================================|
  20. | Contributor(s):                                                              |
  21. |==============================================================================|
  22. | History: see HISTORY.HTM from distribution package                           |
  23. |          (Found at URL: http://www.ararat.cz/synapse/)                       |
  24. |==============================================================================}
  25.  
  26. {$Q-}
  27. {$WEAKPACKAGEUNIT ON}
  28.  
  29. unit SynaCode;
  30.  
  31. interface
  32.  
  33. uses
  34.   SysUtils;
  35.  
  36. type
  37.   TSpecials = set of Char;
  38.  
  39. const
  40.  
  41.   SpecialChar: TSpecials =
  42.   ['=', '(', ')', '[', ']', '<', '>', ':', ';', '.', ',', '@', '/', '?', '\',
  43.     '"', '_'];
  44.   URLFullSpecialChar: TSpecials =
  45.   [';', '/', '?', ':', '@', '=', '&', '#'];
  46.   URLSpecialChar: TSpecials =
  47.   [#$00..#$20, '_', '<', '>', '"', '%', '{', '}', '|', '\', '^', '~', '[', ']',
  48.     '`', #$7F..#$FF];
  49.   TableBase64 =
  50.     'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
  51.   TableUU =
  52.     '`!"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_';
  53.   TableXX =
  54.     '+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_';
  55.  
  56.  
  57. function DecodeTriplet(const Value: string; Delimiter: Char): string;
  58. function DecodeQuotedPrintable(const Value: string): string;
  59. function DecodeURL(const Value: string): string;
  60. function EncodeTriplet(const Value: string; Delimiter: Char;
  61.   Specials: TSpecials): string;
  62. function EncodeQuotedPrintable(const Value: string): string;
  63. function EncodeURLElement(const Value: string): string;
  64. function EncodeURL(const Value: string): string;
  65. function Decode4to3(const Value, Table: string): string;
  66. function DecodeBase64(const Value: string): string;
  67. function EncodeBase64(const Value: string): string;
  68. function DecodeUU(const Value: string): string;
  69. function DecodeXX(const Value: string): string;
  70. function UpdateCrc32(Value: Byte; Crc32: Integer): Integer;
  71. function Crc32(const Value: string): Integer;
  72. function UpdateCrc16(Value: Byte; Crc16: Word): Word;
  73. function Crc16(const Value: string): Word;
  74. function MD5(const Value: string): string;
  75. function HMAC_MD5(Text, Key: string): string;
  76.  
  77. implementation
  78.  
  79. const
  80.  
  81.   Crc32Tab: array[0..255] of Integer = (
  82.     Integer($00000000), Integer($77073096), Integer($EE0E612C), Integer($990951BA),
  83.     Integer($076DC419), Integer($706AF48F), Integer($E963A535), Integer($9E6495A3),
  84.     Integer($0EDB8832), Integer($79DCB8A4), Integer($E0D5E91E), Integer($97D2D988),
  85.     Integer($09B64C2B), Integer($7EB17CBD), Integer($E7B82D07), Integer($90BF1D91),
  86.     Integer($1DB71064), Integer($6AB020F2), Integer($F3B97148), Integer($84BE41DE),
  87.     Integer($1ADAD47D), Integer($6DDDE4EB), Integer($F4D4B551), Integer($83D385C7),
  88.     Integer($136C9856), Integer($646BA8C0), Integer($FD62F97A), Integer($8A65C9EC),
  89.     Integer($14015C4F), Integer($63066CD9), Integer($FA0F3D63), Integer($8D080DF5),
  90.     Integer($3B6E20C8), Integer($4C69105E), Integer($D56041E4), Integer($A2677172),
  91.     Integer($3C03E4D1), Integer($4B04D447), Integer($D20D85FD), Integer($A50AB56B),
  92.     Integer($35B5A8FA), Integer($42B2986C), Integer($DBBBC9D6), Integer($ACBCF940),
  93.     Integer($32D86CE3), Integer($45DF5C75), Integer($DCD60DCF), Integer($ABD13D59),
  94.     Integer($26D930AC), Integer($51DE003A), Integer($C8D75180), Integer($BFD06116),
  95.     Integer($21B4F4B5), Integer($56B3C423), Integer($CFBA9599), Integer($B8BDA50F),
  96.     Integer($2802B89E), Integer($5F058808), Integer($C60CD9B2), Integer($B10BE924),
  97.     Integer($2F6F7C87), Integer($58684C11), Integer($C1611DAB), Integer($B6662D3D),
  98.     Integer($76DC4190), Integer($01DB7106), Integer($98D220BC), Integer($EFD5102A),
  99.     Integer($71B18589), Integer($06B6B51F), Integer($9FBFE4A5), Integer($E8B8D433),
  100.     Integer($7807C9A2), Integer($0F00F934), Integer($9609A88E), Integer($E10E9818),
  101.     Integer($7F6A0DBB), Integer($086D3D2D), Integer($91646C97), Integer($E6635C01),
  102.     Integer($6B6B51F4), Integer($1C6C6162), Integer($856530D8), Integer($F262004E),
  103.     Integer($6C0695ED), Integer($1B01A57B), Integer($8208F4C1), Integer($F50FC457),
  104.     Integer($65B0D9C6), Integer($12B7E950), Integer($8BBEB8EA), Integer($FCB9887C),
  105.     Integer($62DD1DDF), Integer($15DA2D49), Integer($8CD37CF3), Integer($FBD44C65),
  106.     Integer($4DB26158), Integer($3AB551CE), Integer($A3BC0074), Integer($D4BB30E2),
  107.     Integer($4ADFA541), Integer($3DD895D7), Integer($A4D1C46D), Integer($D3D6F4FB),
  108.     Integer($4369E96A), Integer($346ED9FC), Integer($AD678846), Integer($DA60B8D0),
  109.     Integer($44042D73), Integer($33031DE5), Integer($AA0A4C5F), Integer($DD0D7CC9),
  110.     Integer($5005713C), Integer($270241AA), Integer($BE0B1010), Integer($C90C2086),
  111.     Integer($5768B525), Integer($206F85B3), Integer($B966D409), Integer($CE61E49F),
  112.     Integer($5EDEF90E), Integer($29D9C998), Integer($B0D09822), Integer($C7D7A8B4),
  113.     Integer($59B33D17), Integer($2EB40D81), Integer($B7BD5C3B), Integer($C0BA6CAD),
  114.     Integer($EDB88320), Integer($9ABFB3B6), Integer($03B6E20C), Integer($74B1D29A),
  115.     Integer($EAD54739), Integer($9DD277AF), Integer($04DB2615), Integer($73DC1683),
  116.     Integer($E3630B12), Integer($94643B84), Integer($0D6D6A3E), Integer($7A6A5AA8),
  117.     Integer($E40ECF0B), Integer($9309FF9D), Integer($0A00AE27), Integer($7D079EB1),
  118.     Integer($F00F9344), Integer($8708A3D2), Integer($1E01F268), Integer($6906C2FE),
  119.     Integer($F762575D), Integer($806567CB), Integer($196C3671), Integer($6E6B06E7),
  120.     Integer($FED41B76), Integer($89D32BE0), Integer($10DA7A5A), Integer($67DD4ACC),
  121.     Integer($F9B9DF6F), Integer($8EBEEFF9), Integer($17B7BE43), Integer($60B08ED5),
  122.     Integer($D6D6A3E8), Integer($A1D1937E), Integer($38D8C2C4), Integer($4FDFF252),
  123.     Integer($D1BB67F1), Integer($A6BC5767), Integer($3FB506DD), Integer($48B2364B),
  124.     Integer($D80D2BDA), Integer($AF0A1B4C), Integer($36034AF6), Integer($41047A60),
  125.     Integer($DF60EFC3), Integer($A867DF55), Integer($316E8EEF), Integer($4669BE79),
  126.     Integer($CB61B38C), Integer($BC66831A), Integer($256FD2A0), Integer($5268E236),
  127.     Integer($CC0C7795), Integer($BB0B4703), Integer($220216B9), Integer($5505262F),
  128.     Integer($C5BA3BBE), Integer($B2BD0B28), Integer($2BB45A92), Integer($5CB36A04),
  129.     Integer($C2D7FFA7), Integer($B5D0CF31), Integer($2CD99E8B), Integer($5BDEAE1D),
  130.     Integer($9B64C2B0), Integer($EC63F226), Integer($756AA39C), Integer($026D930A),
  131.     Integer($9C0906A9), Integer($EB0E363F), Integer($72076785), Integer($05005713),
  132.     Integer($95BF4A82), Integer($E2B87A14), Integer($7BB12BAE), Integer($0CB61B38),
  133.     Integer($92D28E9B), Integer($E5D5BE0D), Integer($7CDCEFB7), Integer($0BDBDF21),
  134.     Integer($86D3D2D4), Integer($F1D4E242), Integer($68DDB3F8), Integer($1FDA836E),
  135.     Integer($81BE16CD), Integer($F6B9265B), Integer($6FB077E1), Integer($18B74777),
  136.     Integer($88085AE6), Integer($FF0F6A70), Integer($66063BCA), Integer($11010B5C),
  137.     Integer($8F659EFF), Integer($F862AE69), Integer($616BFFD3), Integer($166CCF45),
  138.     Integer($A00AE278), Integer($D70DD2EE), Integer($4E048354), Integer($3903B3C2),
  139.     Integer($A7672661), Integer($D06016F7), Integer($4969474D), Integer($3E6E77DB),
  140.     Integer($AED16A4A), Integer($D9D65ADC), Integer($40DF0B66), Integer($37D83BF0),
  141.     Integer($A9BCAE53), Integer($DEBB9EC5), Integer($47B2CF7F), Integer($30B5FFE9),
  142.     Integer($BDBDF21C), Integer($CABAC28A), Integer($53B39330), Integer($24B4A3A6),
  143.     Integer($BAD03605), Integer($CDD70693), Integer($54DE5729), Integer($23D967BF),
  144.     Integer($B3667A2E), Integer($C4614AB8), Integer($5D681B02), Integer($2A6F2B94),
  145.     Integer($B40BBE37), Integer($C30C8EA1), Integer($5A05DF1B), Integer($2D02EF8D)
  146.     );
  147.  
  148.   Crc16Tab: array[0..255] of Word = (
  149.     $0000, $1189, $2312, $329B, $4624, $57AD, $6536, $74BF,
  150.     $8C48, $9DC1, $AF5A, $BED3, $CA6C, $DBE5, $E97E, $F8F7,
  151.     $1081, $0108, $3393, $221A, $56A5, $472C, $75B7, $643E,
  152.     $9CC9, $8D40, $BFDB, $AE52, $DAED, $CB64, $F9FF, $E876,
  153.     $2102, $308B, $0210, $1399, $6726, $76AF, $4434, $55BD,
  154.     $AD4A, $BCC3, $8E58, $9FD1, $EB6E, $FAE7, $C87C, $D9F5,
  155.     $3183, $200A, $1291, $0318, $77A7, $662E, $54B5, $453C,
  156.     $BDCB, $AC42, $9ED9, $8F50, $FBEF, $EA66, $D8FD, $C974,
  157.     $4204, $538D, $6116, $709F, $0420, $15A9, $2732, $36BB,
  158.     $CE4C, $DFC5, $ED5E, $FCD7, $8868, $99E1, $AB7A, $BAF3,
  159.     $5285, $430C, $7197, $601E, $14A1, $0528, $37B3, $263A,
  160.     $DECD, $CF44, $FDDF, $EC56, $98E9, $8960, $BBFB, $AA72,
  161.     $6306, $728F, $4014, $519D, $2522, $34AB, $0630, $17B9,
  162.     $EF4E, $FEC7, $CC5C, $DDD5, $A96A, $B8E3, $8A78, $9BF1,
  163.     $7387, $620E, $5095, $411C, $35A3, $242A, $16B1, $0738,
  164.     $FFCF, $EE46, $DCDD, $CD54, $B9EB, $A862, $9AF9, $8B70,
  165.     $8408, $9581, $A71A, $B693, $C22C, $D3A5, $E13E, $F0B7,
  166.     $0840, $19C9, $2B52, $3ADB, $4E64, $5FED, $6D76, $7CFF,
  167.     $9489, $8500, $B79B, $A612, $D2AD, $C324, $F1BF, $E036,
  168.     $18C1, $0948, $3BD3, $2A5A, $5EE5, $4F6C, $7DF7, $6C7E,
  169.     $A50A, $B483, $8618, $9791, $E32E, $F2A7, $C03C, $D1B5,
  170.     $2942, $38CB, $0A50, $1BD9, $6F66, $7EEF, $4C74, $5DFD,
  171.     $B58B, $A402, $9699, $8710, $F3AF, $E226, $D0BD, $C134,
  172.     $39C3, $284A, $1AD1, $0B58, $7FE7, $6E6E, $5CF5, $4D7C,
  173.     $C60C, $D785, $E51E, $F497, $8028, $91A1, $A33A, $B2B3,
  174.     $4A44, $5BCD, $6956, $78DF, $0C60, $1DE9, $2F72, $3EFB,
  175.     $D68D, $C704, $F59F, $E416, $90A9, $8120, $B3BB, $A232,
  176.     $5AC5, $4B4C, $79D7, $685E, $1CE1, $0D68, $3FF3, $2E7A,
  177.     $E70E, $F687, $C41C, $D595, $A12A, $B0A3, $8238, $93B1,
  178.     $6B46, $7ACF, $4854, $59DD, $2D62, $3CEB, $0E70, $1FF9,
  179.     $F78F, $E606, $D49D, $C514, $B1AB, $A022, $92B9, $8330,
  180.     $7BC7, $6A4E, $58D5, $495C, $3DE3, $2C6A, $1EF1, $0F78
  181.     );
  182.  
  183. type
  184.   TMD5Ctx = record
  185.     State: array[0..3] of Integer;
  186.     Count: array[0..1] of Integer;
  187.     case Integer of
  188.       0: (BufChar: array[0..63] of Byte);
  189.       1: (BufLong: array[0..15] of Integer);
  190.   end;
  191.  
  192. {==============================================================================}
  193.  
  194. function DecodeTriplet(const Value: string; Delimiter: Char): string;
  195. var
  196.   x: Integer;
  197.   c: Char;
  198.   s: string;
  199. begin
  200.   Result := '';
  201.   x := 1;
  202.   while x <= Length(Value) do
  203.   begin
  204.     c := Value[x];
  205.     Inc(x);
  206.     if c <> Delimiter then
  207.       Result := Result + c
  208.     else
  209.       if x < Length(Value) then
  210.       begin
  211.         s := Copy(Value, x, 2);
  212.         Inc(x, 2);
  213.         if pos(#13, s) + pos(#10, s) = 0 then
  214.           Result := Result + Char(StrToIntDef('$' + s, 32));
  215.       end;
  216.   end;
  217. end;
  218.  
  219. {==============================================================================}
  220.  
  221. function DecodeQuotedPrintable(const Value: string): string;
  222. begin
  223.   Result := DecodeTriplet(Value, '=');
  224. end;
  225.  
  226. {==============================================================================}
  227.  
  228. function DecodeURL(const Value: string): string;
  229. begin
  230.   Result := DecodeTriplet(Value, '%');
  231. end;
  232.  
  233. {==============================================================================}
  234.  
  235. function EncodeTriplet(const Value: string; Delimiter: Char;
  236.   Specials: TSpecials): string;
  237. var
  238.   n: Integer;
  239.   s: string;
  240. begin
  241.   Result := '';
  242.   for n := 1 to Length(Value) do
  243.   begin
  244.     s := Value[n];
  245.     if s[1] in Specials then
  246.       s := Delimiter + IntToHex(Ord(s[1]), 2);
  247.     Result := Result + s;
  248.   end;
  249. end;
  250.  
  251. {==============================================================================}
  252.  
  253. function EncodeQuotedPrintable(const Value: string): string;
  254. begin
  255.   Result := EncodeTriplet(Value, '=', SpecialChar +
  256.     [Char(1)..Char(31), Char(128)..Char(255)]);
  257. end;
  258.  
  259. {==============================================================================}
  260.  
  261. function EncodeURLElement(const Value: string): string;
  262. begin
  263.   Result := EncodeTriplet(Value, '%', URLSpecialChar + URLFullSpecialChar);
  264. end;
  265.  
  266. {==============================================================================}
  267.  
  268. function EncodeURL(const Value: string): string;
  269. begin
  270.   Result := EncodeTriplet(Value, '%', URLSpecialChar);
  271. end;
  272.  
  273. {==============================================================================}
  274.  
  275. function Decode4to3(const Value, Table: string): string;
  276. var
  277.   x, y, n: Integer;
  278.   d: array[0..3] of Byte;
  279. begin
  280.   Result := '';
  281.   x := 1;
  282.   while x < Length(Value) do
  283.   begin
  284.     for n := 0 to 3 do
  285.     begin
  286.       if x > Length(Value) then
  287.         d[n] := 64
  288.       else
  289.       begin
  290.         y := Pos(Value[x], Table);
  291.         if y < 1 then
  292.           y := 65;
  293.         d[n] := y - 1;
  294.       end;
  295.       Inc(x);
  296.     end;
  297.     Result := Result + Char((D[0] and $3F) shl 2 + (D[1] and $30) shr 4);
  298.     if d[2] <> 64 then
  299.     begin
  300.       Result := Result + Char((D[1] and $0F) shl 4 + (D[2] and $3C) shr 2);
  301.       if d[3] <> 64 then
  302.         Result := Result + Char((D[2] and $03) shl 6 + (D[3] and $3F));
  303.     end;
  304.   end;
  305. end;
  306.  
  307. {==============================================================================}
  308.  
  309. function DecodeBase64(const Value: string): string;
  310. begin
  311.   Result := Decode4to3(Value, TableBase64);
  312. end;
  313.  
  314. {==============================================================================}
  315.  
  316. function EncodeBase64(const Value: string): string;
  317. var
  318.   c: Byte;
  319.   n: Integer;
  320.   Count: Integer;
  321.   DOut: array[0..3] of Byte;
  322. begin
  323.   Result := '';
  324.   Count := 1;
  325.   while Count <= Length(Value) do
  326.   begin
  327.     c := Ord(Value[Count]);
  328.     Inc(Count);
  329.     DOut[0] := (c and $FC) shr 2;
  330.     DOut[1] := (c and $03) shl 4;
  331.     if Count <= Length(Value) then
  332.     begin
  333.       c := Ord(Value[Count]);
  334.       Inc(Count);
  335.       DOut[1] := DOut[1] + (c and $F0) shr 4;
  336.       DOut[2] := (c and $0F) shl 2;
  337.       if Count <= Length(Value) then
  338.       begin
  339.         c := Ord(Value[Count]);
  340.         Inc(Count);
  341.         DOut[2] := DOut[2] + (c and $C0) shr 6;
  342.         DOut[3] := (c and $3F);
  343.       end
  344.       else
  345.       begin
  346.         DOut[3] := $40;
  347.       end;
  348.     end
  349.     else
  350.     begin
  351.       DOut[2] := $40;
  352.       DOut[3] := $40;
  353.     end;
  354.     for n := 0 to 3 do
  355.       Result := Result + TableBase64[DOut[n] + 1];
  356.   end;
  357. end;
  358.  
  359. {==============================================================================}
  360.  
  361. function DecodeUU(const Value: string): string;
  362. var
  363.   s: string;
  364.   uut: string;
  365.   x: Integer;
  366. begin
  367.   Result := '';
  368.   uut := TableUU;
  369.   s := trim(UpperCase(Value));
  370.   if s = '' then Exit;
  371.   if Pos('BEGIN', s) = 1 then
  372.     Exit;
  373.   if Pos('END', s) = 1 then
  374.     Exit;
  375.   if Pos('TABLE', s) = 1 then
  376.     Exit; //ignore Table yet (set custom UUT)
  377.   //begin decoding
  378.   x := Pos(Value[1], uut) - 1;
  379.   x := Round((x / 3) * 4);
  380.   //x - lenght UU line
  381.   s := Copy(Value, 2, x);
  382.   if s = '' then
  383.     Exit;
  384.   Result := Decode4to3(s, uut);
  385. end;
  386.  
  387. {==============================================================================}
  388.  
  389. function DecodeXX(const Value: string): string;
  390. var
  391.   s: string;
  392.   x: Integer;
  393. begin
  394.   Result := '';
  395.   s := trim(UpperCase(Value));
  396.   if s = '' then
  397.     Exit;
  398.   if Pos('BEGIN', s) = 1 then
  399.     Exit;
  400.   if Pos('END', s) = 1 then
  401.     Exit;
  402.   //begin decoding
  403.   x := Pos(Value[1], TableXX) - 1;
  404.   x := Round((x / 3) * 4);
  405.   //x - lenght XX line
  406.   s := Copy(Value, 2, x);
  407.   if s = '' then
  408.     Exit;
  409.   Result := Decode4to3(s, TableXX);
  410. end;
  411.  
  412. {==============================================================================}
  413.  
  414. function UpdateCrc32(Value: Byte; Crc32: Integer): Integer;
  415. begin
  416.   Result := ((Crc32 shr 8) and Integer($00FFFFFF)) xor
  417.     crc32tab[Byte(Crc32 xor Integer(Value)) and Integer($000000FF)];
  418. end;
  419.  
  420. {==============================================================================}
  421.  
  422. function Crc32(const Value: string): Integer;
  423. var
  424.   n: Integer;
  425. begin
  426.   Result := Integer($FFFFFFFF);
  427.   for n := 1 to Length(Value) do
  428.     Result := UpdateCrc32(Ord(Value[n]), Result);
  429. end;
  430.  
  431. {==============================================================================}
  432.  
  433. function UpdateCrc16(Value: Byte; Crc16: Word): Word;
  434. begin
  435.   Result := ((Crc16 shr 8) and $00FF) xor
  436.     crc16tab[Byte(Crc16 xor (Word(Value)) and $00FF)];
  437. end;
  438.  
  439. {==============================================================================}
  440.  
  441. function Crc16(const Value: string): Word;
  442. var
  443.   n: Integer;
  444. begin
  445.   Result := $FFFF;
  446.   for n := 1 to Length(Value) do
  447.     Result := UpdateCrc16(Ord(Value[n]), Result);
  448. end;
  449.  
  450. {==============================================================================}
  451.  
  452. procedure MD5Init(var MD5Context: TMD5Ctx);
  453. begin
  454.   FillChar(MD5Context, SizeOf(TMD5Ctx), #0);
  455.   with MD5Context do
  456.   begin
  457.     State[0] := Integer($67452301);
  458.     State[1] := Integer($EFCDAB89);
  459.     State[2] := Integer($98BADCFE);
  460.     State[3] := Integer($10325476);
  461.   end;
  462. end;
  463.  
  464. procedure MD5Transform(var Buf: array of LongInt; const Data: array of LongInt);
  465. var
  466.   A, B, C, D: LongInt;
  467.  
  468.   procedure Round1(var W: LongInt; X, Y, Z, Data: LongInt; S: Byte);
  469.   begin
  470.     Inc(W, (Z xor (X and (Y xor Z))) + Data);
  471.     W := (W shl S) or (W shr (32 - S));
  472.     Inc(W, X);
  473.   end;
  474.  
  475.   procedure Round2(var W: LongInt; X, Y, Z, Data: LongInt; S: Byte);
  476.   begin
  477.     Inc(W, (Y xor (Z and (X xor Y))) + Data);
  478.     W := (W shl S) or (W shr (32 - S));
  479.     Inc(W, X);
  480.   end;
  481.  
  482.   procedure Round3(var W: LongInt; X, Y, Z, Data: LongInt; S: Byte);
  483.   begin
  484.     Inc(W, (X xor Y xor Z) + Data);
  485.     W := (W shl S) or (W shr (32 - S));
  486.     Inc(W, X);
  487.   end;
  488.  
  489.   procedure Round4(var W: LongInt; X, Y, Z, Data: LongInt; S: Byte);
  490.   begin
  491.     Inc(W, (Y xor (X or not Z)) + Data);
  492.     W := (W shl S) or (W shr (32 - S));
  493.     Inc(W, X);
  494.   end;
  495. begin
  496.   A := Buf[0];
  497.   B := Buf[1];
  498.   C := Buf[2];
  499.   D := Buf[3];
  500.  
  501.   Round1(A, B, C, D, Data[0] + Longint($D76AA478), 7);
  502.   Round1(D, A, B, C, Data[1] + Longint($E8C7B756), 12);
  503.   Round1(C, D, A, B, Data[2] + Longint($242070DB), 17);
  504.   Round1(B, C, D, A, Data[3] + Longint($C1BDCEEE), 22);
  505.   Round1(A, B, C, D, Data[4] + Longint($F57C0FAF), 7);
  506.   Round1(D, A, B, C, Data[5] + Longint($4787C62A), 12);
  507.   Round1(C, D, A, B, Data[6] + Longint($A8304613), 17);
  508.   Round1(B, C, D, A, Data[7] + Longint($FD469501), 22);
  509.   Round1(A, B, C, D, Data[8] + Longint($698098D8), 7);
  510.   Round1(D, A, B, C, Data[9] + Longint($8B44F7AF), 12);
  511.   Round1(C, D, A, B, Data[10] + Longint($FFFF5BB1), 17);
  512.   Round1(B, C, D, A, Data[11] + Longint($895CD7BE), 22);
  513.   Round1(A, B, C, D, Data[12] + Longint($6B901122), 7);
  514.   Round1(D, A, B, C, Data[13] + Longint($FD987193), 12);
  515.   Round1(C, D, A, B, Data[14] + Longint($A679438E), 17);
  516.   Round1(B, C, D, A, Data[15] + Longint($49B40821), 22);
  517.  
  518.   Round2(A, B, C, D, Data[1] + Longint($F61E2562), 5);
  519.   Round2(D, A, B, C, Data[6] + Longint($C040B340), 9);
  520.   Round2(C, D, A, B, Data[11] + Longint($265E5A51), 14);
  521.   Round2(B, C, D, A, Data[0] + Longint($E9B6C7AA), 20);
  522.   Round2(A, B, C, D, Data[5] + Longint($D62F105D), 5);
  523.   Round2(D, A, B, C, Data[10] + Longint($02441453), 9);
  524.   Round2(C, D, A, B, Data[15] + Longint($D8A1E681), 14);
  525.   Round2(B, C, D, A, Data[4] + Longint($E7D3FBC8), 20);
  526.   Round2(A, B, C, D, Data[9] + Longint($21E1CDE6), 5);
  527.   Round2(D, A, B, C, Data[14] + Longint($C33707D6), 9);
  528.   Round2(C, D, A, B, Data[3] + Longint($F4D50D87), 14);
  529.   Round2(B, C, D, A, Data[8] + Longint($455A14ED), 20);
  530.   Round2(A, B, C, D, Data[13] + Longint($A9E3E905), 5);
  531.   Round2(D, A, B, C, Data[2] + Longint($FCEFA3F8), 9);
  532.   Round2(C, D, A, B, Data[7] + Longint($676F02D9), 14);
  533.   Round2(B, C, D, A, Data[12] + Longint($8D2A4C8A), 20);
  534.  
  535.   Round3(A, B, C, D, Data[5] + Longint($FFFA3942), 4);
  536.   Round3(D, A, B, C, Data[8] + Longint($8771F681), 11);
  537.   Round3(C, D, A, B, Data[11] + Longint($6D9D6122), 16);
  538.   Round3(B, C, D, A, Data[14] + Longint($FDE5380C), 23);
  539.   Round3(A, B, C, D, Data[1] + Longint($A4BEEA44), 4);
  540.   Round3(D, A, B, C, Data[4] + Longint($4BDECFA9), 11);
  541.   Round3(C, D, A, B, Data[7] + Longint($F6BB4B60), 16);
  542.   Round3(B, C, D, A, Data[10] + Longint($BEBFBC70), 23);
  543.   Round3(A, B, C, D, Data[13] + Longint($289B7EC6), 4);
  544.   Round3(D, A, B, C, Data[0] + Longint($EAA127FA), 11);
  545.   Round3(C, D, A, B, Data[3] + Longint($D4EF3085), 16);
  546.   Round3(B, C, D, A, Data[6] + Longint($04881D05), 23);
  547.   Round3(A, B, C, D, Data[9] + Longint($D9D4D039), 4);
  548.   Round3(D, A, B, C, Data[12] + Longint($E6DB99E5), 11);
  549.   Round3(C, D, A, B, Data[15] + Longint($1FA27CF8), 16);
  550.   Round3(B, C, D, A, Data[2] + Longint($C4AC5665), 23);
  551.  
  552.   Round4(A, B, C, D, Data[0] + Longint($F4292244), 6);
  553.   Round4(D, A, B, C, Data[7] + Longint($432AFF97), 10);
  554.   Round4(C, D, A, B, Data[14] + Longint($AB9423A7), 15);
  555.   Round4(B, C, D, A, Data[5] + Longint($FC93A039), 21);
  556.   Round4(A, B, C, D, Data[12] + Longint($655B59C3), 6);
  557.   Round4(D, A, B, C, Data[3] + Longint($8F0CCC92), 10);
  558.   Round4(C, D, A, B, Data[10] + Longint($FFEFF47D), 15);
  559.   Round4(B, C, D, A, Data[1] + Longint($85845DD1), 21);
  560.   Round4(A, B, C, D, Data[8] + Longint($6FA87E4F), 6);
  561.   Round4(D, A, B, C, Data[15] + Longint($FE2CE6E0), 10);
  562.   Round4(C, D, A, B, Data[6] + Longint($A3014314), 15);
  563.   Round4(B, C, D, A, Data[13] + Longint($4E0811A1), 21);
  564.   Round4(A, B, C, D, Data[4] + Longint($F7537E82), 6);
  565.   Round4(D, A, B, C, Data[11] + Longint($BD3AF235), 10);
  566.   Round4(C, D, A, B, Data[2] + Longint($2AD7D2BB), 15);
  567.   Round4(B, C, D, A, Data[9] + Longint($EB86D391), 21);
  568.  
  569.   Inc(Buf[0], A);
  570.   Inc(Buf[1], B);
  571.   Inc(Buf[2], C);
  572.   Inc(Buf[3], D);
  573. end;
  574.  
  575. procedure MD5Update(var MD5Context: TMD5Ctx; const Data: string);
  576. var
  577.   Index, t, len: Integer;
  578. begin
  579.   len := Length(Data);
  580.   with MD5Context do
  581.   begin
  582.     T := Count[0];
  583.     Inc(Count[0], Len shl 3);
  584.     if Count[0] < T then
  585.       Inc(Count[1]);
  586.     Inc(Count[1], Len shr 29);
  587.     T := (T shr 3) and $3F;
  588.     Index := 0;
  589.     if T <> 0 then
  590.     begin
  591.       Index := T;
  592.       T := 64 - T;
  593.       if Len < T then
  594.       begin
  595.         Move(Data, Bufchar[Index], Len);
  596.         Exit;
  597.       end;
  598.       Move(Data, Bufchar[Index], T);
  599.       MD5Transform(State, Buflong);
  600.       Dec(Len, T);
  601.       Index := T;
  602.     end;
  603.     while Len >= 64 do
  604.     begin
  605.       Move(Data[Index + 1], Bufchar, 64);
  606.       MD5Transform(State, Buflong);
  607.       Inc(Index, 64);
  608.       Dec(Len, 64);
  609.     end;
  610.     Move(Data[Index + 1], Bufchar, Len);
  611.   end
  612. end;
  613.  
  614. function MD5Final(var MD5Context: TMD5Ctx): string;
  615. var
  616.   Cnt: Word;
  617.   P: Byte;
  618.   digest: array[0..15] of Char;
  619.   i: Integer;
  620. begin
  621.   for I := 0 to 15 do
  622.     Byte(Digest[I]) := I + 1;
  623.   with MD5Context do
  624.   begin
  625.     Cnt := (Count[0] shr 3) and $3F;
  626.     P := Cnt;
  627.     BufChar[P] := $80;
  628.     Inc(P);
  629.     Cnt := 64 - 1 - Cnt;
  630.     if Cnt < 8 then
  631.     begin
  632.       FillChar(BufChar[P], Cnt, #0);
  633.       MD5Transform(State, BufLong);
  634.       FillChar(BufChar, 56, #0);
  635.     end
  636.     else
  637.       FillChar(BufChar[P], Cnt - 8, #0);
  638.     BufLong[14] := Count[0];
  639.     BufLong[15] := Count[1];
  640.     MD5Transform(State, BufLong);
  641.     Move(State, Digest, 16);
  642.     Result := '';
  643.     for i := 0 to 15 do
  644.       Result := Result + Char(digest[i]);
  645.   end;
  646.   FillChar(MD5Context, SizeOf(TMD5Ctx), #0)
  647. end;
  648.  
  649. {==============================================================================}
  650.  
  651. function MD5(const Value: string): string;
  652. var
  653.   MD5Context: TMD5Ctx;
  654. begin
  655.   MD5Init(MD5Context);
  656.   MD5Update(MD5Context, Value);
  657.   Result := MD5Final(MD5Context);
  658. end;
  659.  
  660. {==============================================================================}
  661.  
  662. function HMAC_MD5(Text, Key: string): string;
  663. var
  664.   ipad, opad, s: string;
  665.   n: Integer;
  666.   MD5Context: TMD5Ctx;
  667. begin
  668.   if Length(Key) > 64 then
  669.     Key := md5(Key);
  670.   ipad := '';
  671.   for n := 1 to 64 do
  672.     ipad := ipad + #$36;
  673.   opad := '';
  674.   for n := 1 to 64 do
  675.     opad := opad + #$5C;
  676.   for n := 1 to Length(Key) do
  677.   begin
  678.     ipad[n] := Char(Byte(ipad[n]) xor Byte(Key[n]));
  679.     opad[n] := Char(Byte(opad[n]) xor Byte(Key[n]));
  680.   end;
  681.   MD5Init(MD5Context);
  682.   MD5Update(MD5Context, ipad);
  683.   MD5Update(MD5Context, Text);
  684.   s := MD5Final(MD5Context);
  685.   MD5Init(MD5Context);
  686.   MD5Update(MD5Context, opad);
  687.   MD5Update(MD5Context, s);
  688.   Result := MD5Final(MD5Context);
  689. end;
  690.  
  691. end.
  692.