with Ada.Calendar;
with Ada.Characters.Latin_1;
with Ada.Text_IO, Ada.Sequential_IO;
use  Ada.Text_IO;

package body MD5.Driver is

  --====================================================================
  -- Authors   Rolf Ebert,
  --           Christoph Grein <Christ-Usch.Grein@T-Online.de>
  -- Version   1.2
  -- Date      20 January 1999
  --====================================================================
  -- This is a direct translation into Ada of the C language Reference
  -- Implementation given in the official MD5 algorithm description.
  -- It was originally written by Rolf Ebert (unknown address).
  -- [See parent package for a reference to the official description.]
  --====================================================================
  -- History
  -- Author Version   Date    Reason for change
  --  R.E.    1.0  04.06.1997 Original as found in internet
  --  C.G.    1.1  16.01.1999 Implemented Digest_File and Filter;
  --                          bug fix in Time_Trial; minor code changes;
  --                          commented to make publication legal
  --  C.G.    1.2  20.01.1999 Use Float to output Speed in Time_Trial
  --                          (range of Duration may not be big enough)
  --====================================================================

  procedure Digest_String (Text: in String) is

    C : Context;
    FP: Fingerprint;

  begin

    Init   (C);
    Update (C, Text);
    Final  (C, FP);

    Put ("MD5 (""" & Text & """) = " & Digest_To_Text (FP));
    New_Line;

  end Digest_String;

  ----------------------------------------------------------------------

  procedure Digest_File (Filename: in String) is

    package Byte_Sequential_IO is new Ada.Sequential_IO (Byte);
    use     Byte_Sequential_IO;

    File: Byte_Sequential_IO.File_Type;

    Contents: Byte_Array (1 .. 1024);
    Last    : Long_Integer := Contents'Last;

    C : Context;
    FP: Fingerprint;

  begin

    Open (File, In_File, Filename);

    Init (C);

    while not End_of_File (File) loop

      for I in Contents'range loop
        Read (File, Contents (I));
        if End_of_File (File) then
          Last := I;
          exit;
        end if;
      end loop;

      Update (C, Contents (1 .. Last));

    end loop;

    Final (C, FP);

    Close (File);

    Put_Line ("MD5 (" & Filename & ") = " & Digest_To_Text (FP));

  exception
    when Byte_Sequential_IO.Name_Error =>
      Put_Line(Filename & " can't be opened");

  end Digest_File;

  ----------------------------------------------------------------------

  procedure Filter is

    Contents: String (1 .. 16);
    Last    : constant Natural := Contents'Last;

    C : Context;
    FP: Fingerprint;

  begin

    Init (C);

    Whole_File: loop

      for I in Contents'range loop
        begin
          Get_Immediate (Contents (I));  -- for control characters
        exception  -- End_Of_File cannot be used for Standard_Input
          when End_Error =>
            Update (C, Contents (1 .. I - 1));
            exit Whole_File;
        end;
      end loop;

      Update (C, Contents (1 .. Last));

    end loop Whole_File;

    Final (C, FP);

    Put_Line (Digest_To_Text (FP));

  end Filter;

  ----------------------------------------------------------------------

  procedure Time_Trial is

    use Ada.Calendar;

    C  : Context;
    FP : Fingerprint;

    Test_Block_Len  : constant :=  5_000;
    Test_Block_Count: constant := 10_000;

    Block: Byte_Array (1 .. Test_Block_Len);

    Start, Stop: Time;

  begin

    Put ("MD5 time trial. Digesting" & Integer'Image (Test_Block_Count) &
         Integer'Image (Test_Block_Len) & "-byte blocks ...");

    -- Initialize block
    for I in Block'range loop
      Block (I) := Byte (I rem (16#FF# + 1));
    end loop;

    -- Start timer
    Start := Clock;

    -- Digest blocks
    Init (C);
    for I in 1 .. Test_Block_Count loop
      Update (C, Block);
    end loop;
    Final (C, Fp);

    -- Stop timer
    Stop := Clock;

    Put_Line (" done");
    Put_Line ("Digest = " & Digest_To_Text (Fp));
    Put_Line ("Time = " & Duration'Image (Stop - Start) & " seconds");
    Put_Line ("Speed = " & Float'Image (Float (Test_Block_Len * Test_Block_Count) / Float (Stop - Start)) &
              " bytes/second");

  end Time_Trial;

  ----------------------------------------------------------------------

  procedure Test_Suite is
    -- The expected results are:
    -- MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
    -- MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
    -- MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
    -- MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
    -- MD5 ("abcdefghijklmnopqrstuvwxyz") =
    --          c3fcd3d76192e4007dfb496cca67e13b
    -- MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" &
    --      "abcdefghijklmnopqrstuvwxyz0123456789") = 
    --          d174ab98d277d9f5a5611c2c9f419d9f
    -- MD5 ("1234567890123456789012345678901234567890" &
    --      "1234567890123456789012345678901234567890") =
    --          57edf4a22be3c955ac49da2e2107b67a
  begin
    Put_Line ("MD5 test suite:");
    Digest_String ("");
    Digest_String ("a");
    Digest_String ("abc");
    Digest_String ("message digest");
    Digest_String ("abcdefghijklmnopqrstuvwxyz");
    Digest_String ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" &
                   "abcdefghijklmnopqrstuvwxyz0123456789");
    Digest_String ("1234567890123456789012345678901234567890" &
                   "1234567890123456789012345678901234567890");
  end Test_Suite;

end MD5.Driver;


Back eto text.