Integrate Digest-1.00 and Digest-MD5-2.13, from Gisle Aas.
Jarkko Hietaniemi [Fri, 23 Mar 2001 13:20:34 +0000 (13:20 +0000)]
- bump the version to 2.14
- drop the base64 tests since they require MIME::Base64
- drop the rfc1321.txt
- drop the hints/dec_osf.pl since it's only needed for
  pre-5.005_03 Perls
Todo:
- the U32 alignment testing is now removed; it needs to
  be reintroduced as as a Config variable (meaning also
  as a Configure test)
- get the new EBCDIC md5sum for MD5.pm
- test in Win32 to see how badly I botched the makefiles

p4raw-id: //depot/perl@9308

17 files changed:
MANIFEST
configure.com
ext/Digest/MD5/Changes [new file with mode: 0644]
ext/Digest/MD5/MD5.pm [new file with mode: 0644]
ext/Digest/MD5/MD5.xs [new file with mode: 0644]
ext/Digest/MD5/Makefile.PL [new file with mode: 0644]
ext/Digest/MD5/hints/irix_6.pl [new file with mode: 0644]
ext/Digest/MD5/typemap [new file with mode: 0644]
hints/uwin.sh
hints/vmesa.sh
lib/Digest.pm [new file with mode: 0644]
t/lib/digest.t [new file with mode: 0644]
t/lib/md5-aaa.t [new file with mode: 0644]
t/lib/md5-badf.t [new file with mode: 0644]
t/lib/md5-file.t [new file with mode: 0644]
win32/Makefile
win32/makefile.mk

index 3134e93..c92cd4c 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -169,6 +169,13 @@ ext/Devel/Peek/Changes             Data debugging tool, changelog
 ext/Devel/Peek/Makefile.PL     Data debugging tool, makefile writer
 ext/Devel/Peek/Peek.pm         Data debugging tool, module and pod
 ext/Devel/Peek/Peek.xs         Data debugging tool, externals
+ext/Digest/MD5/Changes Digest::MD5 extension changes
+ext/Digest/MD5/MD5.pm  Digest::MD5 extension
+ext/Digest/MD5/MD5.xs  Digest::MD5 extension
+ext/Digest/MD5/Makefile.PL     Digest::MD5 extension makefile writer
+ext/Digest/MD5/hints/dec_osf.pl        Hints for named architecture
+ext/Digest/MD5/hints/irix_6.pl Hints for named architecture
+ext/Digest/MD5/typemap Digest::MD5 extension
 ext/DynaLoader/DynaLoader_pm.PL        Dynamic Loader perl module
 ext/DynaLoader/Makefile.PL     Dynamic Loader makefile writer
 ext/DynaLoader/README          Dynamic Loader notes and intro
@@ -668,6 +675,7 @@ lib/Class/Struct.pm Declare struct-like datatypes as Perl classes
 lib/Cwd.pm             Various cwd routines (getcwd, fastcwd, chdir)
 lib/DB.pm              Debugger API (draft)
 lib/Devel/SelfStubber.pm Generate stubs for SelfLoader.pm
+lib/Digest.pm  Digest extensions
 lib/DirHandle.pm       like FileHandle only for directories
 lib/Dumpvalue.pm       Screen dump of perl values
 lib/English.pm         Readable aliases for short variables
@@ -1411,6 +1419,7 @@ t/lib/compmod.pl  Helper for 1_compile.t
 t/lib/db-btree.t       See if DB_File works
 t/lib/db-hash.t                See if DB_File works
 t/lib/db-recno.t       See if DB_File works
+t/lib/digest.t See if Digest extensions work
 t/lib/dirhand.t                See if DirHandle works
 t/lib/dosglob.t                See if File::DosGlob works
 t/lib/dprof.t          Perl code profiler testsuite driver
@@ -1485,6 +1494,9 @@ t/lib/lc-country.t        See if Locale::Codes work
 t/lib/lc-currency.t    See if Locale::Codes work
 t/lib/lc-language.t    See if Locale::Codes work
 t/lib/lc-uk.t  See if Locale::Codes work
+t/lib/md5-aaa.t        See if Digest::MD5 extension works
+t/lib/md5-badf.t       See if Digest::MD5 extension works
+t/lib/md5-file.t       See if Digest::MD5 extension works
 t/lib/ndbm.t           See if NDBM_File works
 t/lib/net-hostent.t    See if Net::hostent works
 t/lib/odbm.t           See if ODBM_File works
index c27adaf..2dce6d3 100644 (file)
@@ -2392,7 +2392,7 @@ $ echo "SDBM_File if you have the GDBM library built on your machine."
 $ echo ""
 $ echo "Which modules do you want to build into perl?"
 $! we need to add Byteloader to this list:
-$ dflt = "re Fcntl Encode Errno File::Glob Filter::Util::Call IO Opcode Devel::Peek Devel::DProf Data::Dumper attrs VMS::Stdio VMS::DCLsym B SDBM_File Storable Thread Sys::Hostname"
+$ dflt = "re Fcntl Encode Errno File::Glob Filter::Util::Call IO Opcode Devel::Peek Devel::DProf Data::Dumper attrs VMS::Stdio VMS::DCLsym B SDBM_File Storable Thread Sys::Hostname Digest::MD5"
 $ IF ccname .EQS. "DEC" .OR. ccname .EQS. "CXX"
 $ THEN
 $   dflt = dflt + " POSIX"
diff --git a/ext/Digest/MD5/Changes b/ext/Digest/MD5/Changes
new file mode 100644 (file)
index 0000000..62c8280
--- /dev/null
@@ -0,0 +1,439 @@
+2001-03-13   Gisle Aas <gisle@ActiveState.com>
+
+   Release 2.13
+
+   Moved all other Digest:: modules out of the Digest-MD5 dist.
+
+
+
+2000-09-18   Gisle Aas <gisle@ActiveState.com>
+
+   Release 2.12
+
+   Avoid pointer cast warning for machines with bigger ints
+   than pointers.  Patch by Robin Barker <rmb1@cise.npl.co.uk>.
+
+
+
+2000-08-19   Gisle Aas <gisle@ActiveState.com>
+
+   Release 2.11
+   
+   The fallback code introduced in 2.10 did only work for
+   perl-5.6.0.  It should now for for perl5.004 and 5.005
+   as well.  Patch by Ville Skyttä <ville@office.popsystems.com>.
+
+
+
+2000-08-18   Gisle Aas <gisle@ActiveState.com>
+
+   Release 2.10
+
+   Digest::MD5 will now try to fallback to the pure perl
+   implementation of Digest::Perl::MD5 if bootstrap fails.
+
+   Added a bit internal paranoia about casting the IV
+   in the Digest::MD5 object to the MD5_CTX* pointer.
+
+
+
+1999-08-06   Gisle Aas <gisle@aas.no>
+
+   Release 2.09
+
+   Documentation update.
+
+
+
+1999-07-28   Gisle Aas <gisle@aas.no>
+
+   Release 2.08
+
+   The addfile() methods could trigger a core dump when passed
+   a filehandle that had failed to open.
+
+
+
+1999-04-26   Gisle Aas <gisle@aas.no>
+
+   Release 2.07
+
+   The Digest::SHA1 module failed on some 64-bit systems, because I
+   assumed there was a correspondence between the U32 size and
+   BYTEORDER.  This version use 'unsigned long' as Uwe's original
+   SHA module did.
+
+   The module should now work better when liked statically with perl,
+   because we now use a safer module-loaded test in Digest.pm.
+
+   Assume we know the outcome of the alignment test on VMS. Patch by
+   Chuck Lane <lane@duphy4.physics.drexel.edu>
+
+
+
+1999-03-26   Gisle Aas <gisle@aas.no>
+
+   Release 2.06
+
+   Avoid LONG and BYTE types in SHA.xs as they was in conflict
+   with similar definitions in <winnt.h>.
+
+   Patch by Marko Asplund <aspa@hip.fi> to make the the alignment
+   test program link successfully with sfio-perl.
+
+   Fixed a typo in MD5.xs that might have affected 64-bit systems.
+   Spotted by Nick Ing-Simmons
+
+
+
+1999-03-15   Gisle Aas <gisle@aas.no>
+
+   Release 2.05
+
+   Included Digest::SHA1 based on Uwe Hollerbach's SHA module.
+
+
+
+1999-03-05   Gisle Aas <gisle@aas.no>
+
+   Release 2.04
+
+   Avoid the -o option when compiling alignment test program
+   for Win32 as suggested by Gurusamy Sarathy.
+
+   DEC Compiler bug workaround.  Contributed by D Roland Walker
+   <walker@ncbi.nlm.nih.gov>
+
+   Having references to a local variable called "na" was not
+   very safe either.  Some older versions of Perl can apparently
+   macroize this into something completely different.
+
+
+
+1999-02-27   Gisle Aas <gisle@aas.no>
+
+   Release 2.03
+
+   Patch from Christopher J. Madsen <chris_madsen@geocities.com> that
+   should help getting the u32align test program to compile with
+   Visual C++ 5 on Windows NT.
+
+   Got rid of references to PL_na.
+
+
+
+1999-01-31   Gisle Aas <gisle@aas.no>
+
+   Release 2.02
+
+   Added a hints file as workaround for an IRIX compiler bug.
+   Contributed by D Roland Walker <walker@ncbi.nlm.nih.gov>.
+
+   Note that the rfc2202 test can still fail on some DEC Alpha,
+   because of a compiler bug that affects the perl 'x' operator.
+   The Digest:: modules should work and be safe to install anyway.
+
+
+
+1998-12-18   Gisle Aas <aas@sn.no>
+
+   Release 2.01
+
+   Some casts and tweaks to make picky compilers more happy.
+
+
+
+1998-11-04   Gisle Aas <aas@sn.no>
+
+   Release 2.00.
+
+   Taken out Digest::SHA1 as this module will be provided from Uwe
+   Hollerbach later.
+
+   Some tweaks to MD2.xs and MD5.xs since "na" disappeared in
+   perl5.005_53
+
+
+
+1998-10-30   Gisle Aas <aas@sn.no>
+
+   Release 1.99_60
+
+   The 1.99_59 release introduced compilation problems for big-endian
+   systems with free U32 alignment.  Bug reported, and fix suggested
+   by Paul J. Schinder <schinder@pobox.com>.
+
+
+
+1998-10-28   Gisle Aas <aas@sn.no>
+
+   Release 1.99_59
+
+   Makefile.PL will run a test program to find out if U32 values can
+   be aligned anywhere.  This hopefully cures the core dumps reported
+   on Solaris and other big endian systems.  Thanks to Graham Barr for
+   debugging this.
+
+
+
+1998-10-28   Gisle Aas <aas@sn.no>
+
+   Release 1.99_58
+
+   Should be very close to a 2.00 release now.  Need some success
+   reports from people running on big-endian machines first I think.
+
+   Added a Digest::MD2 implementation.
+
+   Wrote Digest.pm documentation.  This define the interface that all
+   Digest:: modules should provide.
+
+   Avoided some code duplication in MD5.xs
+
+   Fixed typo, that prevented Digest::SHA1::sha1_base64() from working.
+
+
+
+1998-10-27   Gisle Aas <aas@sn.no>
+
+   Release 1.99_57
+
+   Rewritten most of the MD5 C code to make it real fast (especially
+   on little-endian machines without alignment restrictions for U32).
+   Compared to MD5-1.7 we can process files 4 times as fast and we
+   digest small stuff in memory 7 times faster.  I came to these
+   conclusions after these tests (gcc -O2, i586, Linux):
+
+   First tested calculation of the digest of a 31 MB file, using
+   perl -le 'print Digest::MD5->new->addfile(*STDIN)->hexdigest'
+   and similar stuff:
+
+      MD5-1.7:                 21.06s
+      Digest::MD5-1.99_57:      5.23s
+      md5sum (GNU textutils):   4.90s
+
+   As you can see, we do nearly as good as the md5sum program.  I
+   think the reason we don't beat md5sum is that perl always insist on
+   loading extra modules like Config.pm, Carp.pm, strict.pm, vars.pm,
+   AutoLoader.pm and DynaLoader.pm.  When I simply wrapped the MD5.xs
+   hasher code in a C program I managed to process the file in 4.68s.
+
+   Then we calculated the digest of the same 6 byte sting, 20000
+   times:
+
+      MD5-1.7:                 11.81s
+      Digest::MD5-1.99_57:      1.68s
+
+   Digest::MD5 benefit from making this into a plain procedure call
+   instead of a static method call.
+
+
+   Other changes in this release are:
+
+   Documentation update
+
+   Internal MD5.xs cleanup.
+
+   $md5->digest will automatically reset now.
+
+   Digest::HMAC methods add() and addfile() did not return the
+   corret object.
+
+   Added Digest.pm loading module.  I am not sure this is a good idea.
+
+   Added Digest::SHA1 and Digest::HMAC_SHA1 module.  The Digest::SHA1
+   module is just a wrapper around SHA.pm.  I hope to get the author
+   of SHA.pm to move his module to the Digest:: category.
+
+
+
+1998-10-25   Gisle Aas <aas@sn.no>
+
+   Release 1.99_56
+
+   Fix memcpy_byteswap() function in MD5.xs.  Must be careful with
+   htovl() as it might evaluate its arguments more than once.
+
+
+
+1998-10-25   Gisle Aas <aas@sn.no>
+
+   Release 1.99_55
+
+   Grahams HMAC_MD5.pm splitted into two modules.  Digest::HMAC and
+   Digest::HMAC_MD5.  Also provide functional interface.  Documentation
+   is still lacking.
+
+   Included RFC 2202 based test for HMAC-MD5.
+
+
+
+1998-10-24   Gisle Aas <aas@sn.no>
+
+   Release 1.99_54
+
+   Included HMAC_MD5.pm, contributed by Graham Barr <gbarr@ti.com>.
+
+   I have a hard time to make up my mind :-)  md5_bin() renamed back
+   to md5().   Functions are not exported by default any more.
+
+   Try to Encode/Decode with memcpy_byteswap for 32-bit big-endian
+   machines.
+
+
+
+1998-10-23   Gisle Aas <aas@sn.no>
+
+   Release 1.99_53
+
+   Renamed core module as Digest::MD5.  Leave a MD5.pm stub for
+   legacy code.
+
+   The md5() function renamed as md5_bin().
+
+   The constructor, Digest::MD5->new, no longer takes any extra
+   arguments.
+
+   Added some new tests.
+
+   Updated the documentation.
+
+   $md5->b64digest implemented with same base64 encoder as md5_base64.
+
+
+
+1998-10-23   Gisle Aas <aas@sn.no>
+
+   Release 1.99_52
+
+   Patch from Graham Barr which make it work for big-endian machines
+   again.
+
+
+
+1998-10-22   Gisle Aas <aas@sn.no>
+
+   Release 1.99_51
+
+   The MD5 class is now subclassable.
+
+   The add() and addfile() methods now return $self.
+
+   The reset() method is just an alias for new().
+
+   The constructor (MD5->new) now takes optional arguments which are
+   automatically added.  It means that we can now write:
+
+      MD5->new($data)->hexdigest;
+
+   New $md5->b64digest method.
+
+   New functions that are exported on request: md5, md5_hex, md5_base64
+
+   Included RFC 1321
+
+   Barely started to update the documentation.
+
+
+
+1998-10-22   Gisle Aas <aas@sn.no>
+
+   Release 1.99_50
+
+   Much better performance (more than twice as fast now).  Mostly
+   because we use Copy/Zero instead of the original MD5_memcpy and
+   MD5_memset functions.
+
+   The addfile() and hexdigest() methods are now XS implemented.
+
+   All RSA functions now included in MD5.xs and made static.
+
+   Use perl's Copy/Zero.
+
+   Random cleanup, simplifications and reformatting.
+   Merged things better with the perl configuration.
+
+
+
+Neil Winton's versions below:
+
+
+*** 96/06/20 Version 1.7
+
+MD5 is now completely 64-bit clean (I hope). The basic MD5 code uses
+32-bit quantities and requires a typedef UINT4 to be defined in
+global.h. Perl configuration data (the value of BYTEORDER) is used to
+determine if unsigned longs have 4 or 8 bytes. On 64-bit platforms (eg
+DEC Alpha) then it assumes that "unsigned int" will be a 32-bit type.
+If this is incorrect then adding -DUINT4_IS_LONG to the DEFINES line in
+Makefile.PL will override this.
+
+On some machines (at least Cray that I know of) there is no 32-bit
+integer type. In this case defining TRUNCATE_UINT4 (which is done
+automatically for a Cray) will ensure that 64-bit values are masked
+down to 32 bits. I have done my best to test this but without easy
+access to a true 64-bit machine I can not totally guarantee it (unless
+anyone wants to lend me a spare Cray :-)
+
+There is one remaining limitation for 64-bit enabled processors. The
+amount of data passed to any single call to the underlying MD5
+routines is limited to (2^32 - 1) bytes -- that's 4 gigabytes. I'm
+sorry if that's a real problem for you ...
+
+And finally, a minor complilation warning (unsigned char * used with
+function having char * prototype) has also been eliminated.
+
+*** 96/04/09 Version 1.6
+
+Re-generated module framework using h2xs to pick up the latest module
+conventions for versions etc. You can now say "use MD5 1.6;" and things
+should work correctly. MD5.pod has been integrated into MD5.pm and
+CHANGES renamed to Changes. There is a fairly comprehensive test.pl
+which can be invoked via "make test". There are no functional changes
+to the MD5 routines themselves.
+
+*** 96/03/14 Version 1.5.3
+
+Fixed addfile method to accept type-glob references for the file-handle
+(eg \*STDOUT). This is more consistent with other routines and is now the
+recommended way of passing file-handles. The documentation now gives more
+examples as to how the routines might be used.
+
+*** 96/03/12 Version 1.5.2
+
+Minor fixes from Christopher J Madsen <madsen@computek.net> to provide
+support for building on OS/2 (and to work arround a perl -w bug).
+
+Remove warning about possible difference between add('foo', 'bar') and
+add('foobar'). This is not true (it may have been true in the earliest
+version of the module but is no longer the case).
+
+*** 96/03/08 Version 1.5.1
+
+Add CHANGES file to make it easier for people to figure out what has
+been going on. (Meant to do this as part of 1.5)
+
+*** 96/03/05 Version 1.5
+
+Add hash() and hexhash() methods at the suggestion/request of Gary
+Howland <gary@kampai.euronet.nl> before inclusion in a wider library
+of cryptography modules.
+
+*** 96/02/27 Version 1.4
+
+Finally fixed the pesky Solaris dynamic loading bug. All kudos to Ken
+Pizzini <kenp@spry.com>!
+
+*** 95/11/29 Version 1.3.1
+
+Add explanations of current known problems.
+
+*** 95/06/02 Version 1.3
+
+Fix problems with scope resolution in addfile() reported by
+Jean-Claude Giese <Jean-Claude.Giese@loria.fr>. Basically ARGV is
+always implicitly in package main while other filehandles aren't.
+*** 95/05/23 Version 1.2.1
+
+[Changes pre 1.2.1 not recorded]
diff --git a/ext/Digest/MD5/MD5.pm b/ext/Digest/MD5/MD5.pm
new file mode 100644 (file)
index 0000000..7a627b8
--- /dev/null
@@ -0,0 +1,264 @@
+package Digest::MD5;
+
+use strict;
+use vars qw($VERSION @ISA @EXPORT_OK);
+
+$VERSION = '2.14';
+
+require Exporter;
+*import = \&Exporter::import;
+@EXPORT_OK = qw(md5 md5_hex md5_base64);
+
+require DynaLoader;
+@ISA=qw(DynaLoader);
+
+eval {
+    Digest::MD5->bootstrap($VERSION);
+};
+if ($@) {
+    # Try to load the pure perl version
+    require Digest::Perl::MD5;
+
+    Digest::Perl::MD5->import(qw(md5 md5_hex md5_base64));
+    push(@ISA, "Digest::Perl::MD5");  # make OO interface work
+}
+else {
+    *reset = \&new;
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Digest::MD5 - Perl interface to the MD5 Algorithm
+
+=head1 SYNOPSIS
+
+ # Functional style
+ use Digest::MD5  qw(md5 md5_hex md5_base64);
+
+ $digest = md5($data);
+ $digest = md5_hex($data);
+ $digest = md5_base64($data);
+
+ # OO style
+ use Digest::MD5;
+
+ $ctx = Digest::MD5->new;
+
+ $ctx->add($data);
+ $ctx->addfile(*FILE);
+
+ $digest = $ctx->digest;
+ $digest = $ctx->hexdigest;
+ $digest = $ctx->b64digest;
+
+=head1 DESCRIPTION
+
+The C<Digest::MD5> module allows you to use the RSA Data Security
+Inc. MD5 Message Digest algorithm from within Perl programs.  The
+algorithm takes as input a message of arbitrary length and produces as
+output a 128-bit "fingerprint" or "message digest" of the input.
+
+The C<Digest::MD5> module provide a procedural interface for simple
+use, as well as an object oriented interface that can handle messages
+of arbitrary length and which can read files directly.
+
+A binary digest will be 16 bytes long.  A hex digest will be 32
+characters long.  A base64 digest will be 22 characters long.
+
+=head1 FUNCTIONS
+
+The following functions can be exported from the C<Digest::MD5>
+module.  No functions are exported by default.
+
+=over 4
+
+=item md5($data,...)
+
+This function will concatenate all arguments, calculate the MD5 digest
+of this "message", and return it in binary form.
+
+=item md5_hex($data,...)
+
+Same as md5(), but will return the digest in hexadecimal form.
+
+=item md5_base64($data,...)
+
+Same as md5(), but will return the digest as a base64 encoded string.
+
+=back
+
+=head1 METHODS
+
+The following methods are available:
+
+=over 4
+
+=item $md5 = Digest::MD5->new
+
+The constructor returns a new C<Digest::MD5> object which encapsulate
+the state of the MD5 message-digest algorithm.  You can add data to
+the object and finally ask for the digest.
+
+If called as a instance method (i.e. $md5->new) it will just reset the
+state the object to the state of a newly created object.  No new
+object is created in this case.
+
+=item $md5->reset
+
+This is just an alias for $md5->new.
+
+=item $md5->add($data,...)
+
+The $data provided as argument are appended to the message we
+calculate the digest for.  The return value is the $md5 object itself.
+
+=item $md5->addfile($io_handle)
+
+The $io_handle is read until EOF and the content is appended to the
+message we calculate the digest for.  The return value is the $md5
+object itself.
+
+In most cases you want to make sure that the $io_handle is set up to
+be in binmode().
+
+=item $md5->digest
+
+Return the binary digest for the message.
+
+Note that the C<digest> operation is effectively a destructive,
+read-once operation. Once it has been performed, the C<Digest::MD5>
+object is automatically C<reset> and can be used to calculate another
+digest value.
+
+=item $md5->hexdigest
+
+Same as $md5->digest, but will return the digest in hexadecimal form.
+
+=item $md5->b64digest
+
+Same as $md5->digest, but will return the digest as a base64 encoded
+string.
+
+=back
+
+
+=head1 EXAMPLES
+
+The simplest way to use this library is to import the md5_hex()
+function (or one of its cousins):
+
+    use Digest::MD5 qw(md5_hex);
+    print "Digest is ", md5_hex("foobarbaz"), "\n";
+
+The above example would print out the message
+
+    Digest is 6df23dc03f9b54cc38a0fc1483df6e21
+
+provided that the implementation is working correctly.  The same
+checksum can also be calculated in OO style:
+
+    use Digest::MD5;
+    
+    $md5 = Digest::MD5->new;
+    $md5->add('foo', 'bar');
+    $md5->add('baz');
+    $digest = $md5->hexdigest;
+    
+    print "Digest is $digest\n";
+
+With OO style you can break the message arbitrary.  This means that we
+are no longer limited to have space for the whole message in memory, i.e.
+we can handle messages of any size.
+
+This is useful when calculating checksum for files:
+
+    use Digest::MD5;
+
+    my $file = shift || "/etc/passwd";
+    open(FILE, $file) or die "Can't open '$file': $!";
+    binmode(FILE);
+
+    $md5 = Digest::MD5->new;
+    while (<FILE>) {
+        $md5->add($_);
+    }
+    close(FILE);
+    print $md5->b64digest, " $file\n";
+
+Or we can use the builtin addfile method for more efficient reading of
+the file:
+
+    use Digest::MD5;
+
+    my $file = shift || "/etc/passwd";
+    open(FILE, $file) or die "Can't open '$file': $!";
+    binmode(FILE);
+
+    print Digest::MD5->new->addfile(*FILE)->hexdigest, " $file\n";
+
+=head1 SEE ALSO
+
+L<Digest>,
+L<Digest::MD2>,
+L<Digest::SHA1>,
+L<Digest::HMAC>
+
+L<md5sum(1)>
+
+RFC 1321
+
+=head1 COPYRIGHT
+
+This library is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+ Copyright 1998-2000 Gisle Aas.
+ Copyright 1995-1996 Neil Winton.
+ Copyright 1991-1992 RSA Data Security, Inc.
+
+The MD5 algorithm is defined in RFC 1321. The basic C code
+implementing the algorithm is derived from that in the RFC and is
+covered by the following copyright:
+
+=over 4
+
+=item
+
+Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+
+=back
+
+This copyright does not prohibit distribution of any version of Perl
+containing this extension under the terms of the GNU or Artistic
+licenses.
+
+=head1 AUTHORS
+
+The original MD5 interface was written by Neil Winton
+(C<N.Winton@axion.bt.co.uk>).
+
+This release was made by Gisle Aas <gisle@ActiveState.com>
+
+=cut
diff --git a/ext/Digest/MD5/MD5.xs b/ext/Digest/MD5/MD5.xs
new file mode 100644 (file)
index 0000000..40110c3
--- /dev/null
@@ -0,0 +1,626 @@
+/* $Id: MD5.xs,v 1.26 2000/09/18 14:27:44 gisle Exp $ */
+
+/* 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the same terms as Perl itself.
+ * 
+ *  Copyright 1998-2000 Gisle Aas.
+ *  Copyright 1995-1996 Neil Winton.
+ *  Copyright 1991-1992 RSA Data Security, Inc.
+ *
+ * This code is derived from Neil Winton's MD5-1.7 Perl module, which in
+ * turn is derived from the reference implementation in RFC 1231 which
+ * comes with this message:
+ *
+ * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD5 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#ifdef __cplusplus
+}
+#endif
+
+/*#define MD5_DEBUG /**/
+
+/* Perl does not guarantee that U32 is exactly 32 bits.  Some system
+ * has no integral type with exactly 32 bits.  For instance, A Cray has
+ * short, int and long all at 64 bits so we need to apply this macro
+ * to reduce U32 values to 32 bits at appropriate places. If U32
+ * really does have 32 bits then this is a no-op.
+ */
+#if BYTEORDER > 0x4321 || defined(TRUNCATE_U32)
+  #define TO32(x)    ((x) &  0xFFFFffff)
+  #define TRUNC32(x) ((x) &= 0xFFFFffff)
+#else
+  #define TO32(x)    (x)
+  #define TRUNC32(x) /*nothing*/
+#endif
+
+/* The MD5 algorithm is defined in terms of little endian 32-bit
+ * values.  The following macros (and functions) allow us to convert
+ * between native integers and such values.
+ */
+#undef BYTESWAP
+#ifndef U32_ALIGNMENT_REQUIRED
+ #if BYTEORDER == 0x1234      /* 32-bit little endian */
+  #define BYTESWAP(x) (x)     /* no-op */
+
+ #elif BYTEORDER == 0x4321    /* 32-bit big endian */
+  #define BYTESWAP(x)  ((((x)&0xFF)<<24)       \
+                       |(((x)>>24)&0xFF)       \
+                       |(((x)&0x0000FF00)<<8)  \
+                       |(((x)&0x00FF0000)>>8)  )
+ #endif
+#endif
+
+#ifndef BYTESWAP
+static void u2s(U32 u, U8* s)
+{
+    *s++ = u         & 0xFF;
+    *s++ = (u >>  8) & 0xFF;
+    *s++ = (u >> 16) & 0xFF;
+    *s   = (u >> 24) & 0xFF;
+}
+
+#define s2u(s,u) ((u) =  (U32)(*s)            |  \
+                        ((U32)(*(s+1)) << 8)  |  \
+                        ((U32)(*(s+2)) << 16) |  \
+                        ((U32)(*(s+3)) << 24))
+#endif
+
+#define MD5_CTX_SIGNATURE 200003165
+
+/* This stucture keeps the current state of algorithm.
+ */
+typedef struct {
+  U32 signature;   /* safer cast in get_md5_ctx() */
+  U32 A, B, C, D;  /* current digest */
+  U32 bytes_low;   /* counts bytes in message */
+  U32 bytes_high;  /* turn it into a 64-bit counter */
+  U8 buffer[128];  /* collect complete 64 byte blocks */
+} MD5_CTX;
+
+
+/* Padding is added at the end of the message in order to fill a
+ * complete 64 byte block (- 8 bytes for the message length).  The
+ * padding is also the reason the buffer in MD5_CTX have to be
+ * 128 bytes.
+ */
+static unsigned char PADDING[64] = {
+  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* Constants for MD5Transform routine.
+ */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & ((y) ^ (z)) ^ (z)))
+#define G(x, y, z) F(z, x, y)
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n) | ((x) >> (32-(n)))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+ * Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, s, ac)                    \
+ (a) += F ((b), (c), (d)) + (NEXTx) + (U32)(ac); \
+ TRUNC32((a));                                   \
+ (a) = ROTATE_LEFT ((a), (s));                   \
+ (a) += (b);                                     \
+ TRUNC32((a));
+
+#define GG(a, b, c, d, x, s, ac)                 \
+ (a) += G ((b), (c), (d)) + X[x] + (U32)(ac);    \
+ TRUNC32((a));                                   \
+ (a) = ROTATE_LEFT ((a), (s));                   \
+ (a) += (b);                                     \
+ TRUNC32((a));
+
+#define HH(a, b, c, d, x, s, ac)                 \
+ (a) += H ((b), (c), (d)) + X[x] + (U32)(ac);    \
+ TRUNC32((a));                                   \
+ (a) = ROTATE_LEFT ((a), (s));                   \
+ (a) += (b);                                     \
+ TRUNC32((a));
+
+#define II(a, b, c, d, x, s, ac)                 \
+ (a) += I ((b), (c), (d)) + X[x] + (U32)(ac);    \
+ TRUNC32((a));                                   \
+ (a) = ROTATE_LEFT ((a), (s));                   \
+ (a) += (b);                                     \
+ TRUNC32((a));
+
+
+static void
+MD5Init(MD5_CTX *ctx)
+{
+  /* Start state */
+  ctx->A = 0x67452301;
+  ctx->B = 0xefcdab89;
+  ctx->C = 0x98badcfe;
+  ctx->D = 0x10325476;
+
+  /* message length */
+  ctx->bytes_low = ctx->bytes_high = 0;
+}
+
+
+static void
+MD5Transform(MD5_CTX* ctx, const U8* buf, STRLEN blocks)
+{
+    static int tcount = 0;
+
+    U32 A = ctx->A;
+    U32 B = ctx->B;
+    U32 C = ctx->C;
+    U32 D = ctx->D;
+
+#ifndef U32_ALIGNMENT_REQUIRED
+    const U32 *x = (U32*)buf;  /* really just type casting */
+#endif
+
+    do {
+       U32 a = A;
+       U32 b = B;
+       U32 c = C;
+       U32 d = D;
+
+#if BYTEORDER == 0x1234 && !defined(U32_ALIGNMENT_REQUIRED)
+       const U32 *X = x;
+        #define NEXTx  (*x++)
+#else
+       U32 X[16];      /* converted values, used in round 2-4 */
+       U32 *uptr = X;
+       U32 tmp;
+ #ifdef BYTESWAP
+        #define NEXTx  (tmp=*x++, *uptr++ = BYTESWAP(tmp))
+ #else
+        #define NEXTx  (s2u(buf,tmp), buf += 4, *uptr++ = tmp)
+ #endif
+#endif
+
+#ifdef MD5_DEBUG
+       if (buf == ctx->buffer)
+           fprintf(stderr,"%5d: Transform ctx->buffer", ++tcount);
+       else 
+           fprintf(stderr,"%5d: Transform %p (%d)", ++tcount, buf, blocks);
+
+       {
+           int i;
+           fprintf(stderr,"[");
+           for (i = 0; i < 16; i++) {
+               fprintf(stderr,"%x,", x[i]);
+           }
+           fprintf(stderr,"]\n");
+       }
+#endif
+
+       /* Round 1 */
+       FF (a, b, c, d, S11, 0xd76aa478); /* 1 */
+       FF (d, a, b, c, S12, 0xe8c7b756); /* 2 */
+       FF (c, d, a, b, S13, 0x242070db); /* 3 */
+       FF (b, c, d, a, S14, 0xc1bdceee); /* 4 */
+       FF (a, b, c, d, S11, 0xf57c0faf); /* 5 */
+       FF (d, a, b, c, S12, 0x4787c62a); /* 6 */
+       FF (c, d, a, b, S13, 0xa8304613); /* 7 */
+       FF (b, c, d, a, S14, 0xfd469501); /* 8 */
+       FF (a, b, c, d, S11, 0x698098d8); /* 9 */
+       FF (d, a, b, c, S12, 0x8b44f7af); /* 10 */
+       FF (c, d, a, b, S13, 0xffff5bb1); /* 11 */
+       FF (b, c, d, a, S14, 0x895cd7be); /* 12 */
+       FF (a, b, c, d, S11, 0x6b901122); /* 13 */
+       FF (d, a, b, c, S12, 0xfd987193); /* 14 */
+       FF (c, d, a, b, S13, 0xa679438e); /* 15 */
+       FF (b, c, d, a, S14, 0x49b40821); /* 16 */
+
+       /* Round 2 */
+       GG (a, b, c, d,  1, S21, 0xf61e2562); /* 17 */
+       GG (d, a, b, c,  6, S22, 0xc040b340); /* 18 */
+       GG (c, d, a, b, 11, S23, 0x265e5a51); /* 19 */
+       GG (b, c, d, a,  0, S24, 0xe9b6c7aa); /* 20 */
+       GG (a, b, c, d,  5, S21, 0xd62f105d); /* 21 */
+       GG (d, a, b, c, 10, S22,  0x2441453); /* 22 */
+       GG (c, d, a, b, 15, S23, 0xd8a1e681); /* 23 */
+       GG (b, c, d, a,  4, S24, 0xe7d3fbc8); /* 24 */
+       GG (a, b, c, d,  9, S21, 0x21e1cde6); /* 25 */
+       GG (d, a, b, c, 14, S22, 0xc33707d6); /* 26 */
+       GG (c, d, a, b,  3, S23, 0xf4d50d87); /* 27 */
+       GG (b, c, d, a,  8, S24, 0x455a14ed); /* 28 */
+       GG (a, b, c, d, 13, S21, 0xa9e3e905); /* 29 */
+       GG (d, a, b, c,  2, S22, 0xfcefa3f8); /* 30 */
+       GG (c, d, a, b,  7, S23, 0x676f02d9); /* 31 */
+       GG (b, c, d, a, 12, S24, 0x8d2a4c8a); /* 32 */
+
+       /* Round 3 */
+       HH (a, b, c, d,  5, S31, 0xfffa3942); /* 33 */
+       HH (d, a, b, c,  8, S32, 0x8771f681); /* 34 */
+       HH (c, d, a, b, 11, S33, 0x6d9d6122); /* 35 */
+       HH (b, c, d, a, 14, S34, 0xfde5380c); /* 36 */
+       HH (a, b, c, d,  1, S31, 0xa4beea44); /* 37 */
+       HH (d, a, b, c,  4, S32, 0x4bdecfa9); /* 38 */
+       HH (c, d, a, b,  7, S33, 0xf6bb4b60); /* 39 */
+       HH (b, c, d, a, 10, S34, 0xbebfbc70); /* 40 */
+       HH (a, b, c, d, 13, S31, 0x289b7ec6); /* 41 */
+       HH (d, a, b, c,  0, S32, 0xeaa127fa); /* 42 */
+       HH (c, d, a, b,  3, S33, 0xd4ef3085); /* 43 */
+       HH (b, c, d, a,  6, S34,  0x4881d05); /* 44 */
+       HH (a, b, c, d,  9, S31, 0xd9d4d039); /* 45 */
+       HH (d, a, b, c, 12, S32, 0xe6db99e5); /* 46 */
+       HH (c, d, a, b, 15, S33, 0x1fa27cf8); /* 47 */
+       HH (b, c, d, a,  2, S34, 0xc4ac5665); /* 48 */
+
+       /* Round 4 */
+       II (a, b, c, d,  0, S41, 0xf4292244); /* 49 */
+       II (d, a, b, c,  7, S42, 0x432aff97); /* 50 */
+       II (c, d, a, b, 14, S43, 0xab9423a7); /* 51 */
+       II (b, c, d, a,  5, S44, 0xfc93a039); /* 52 */
+       II (a, b, c, d, 12, S41, 0x655b59c3); /* 53 */
+       II (d, a, b, c,  3, S42, 0x8f0ccc92); /* 54 */
+       II (c, d, a, b, 10, S43, 0xffeff47d); /* 55 */
+       II (b, c, d, a,  1, S44, 0x85845dd1); /* 56 */
+       II (a, b, c, d,  8, S41, 0x6fa87e4f); /* 57 */
+       II (d, a, b, c, 15, S42, 0xfe2ce6e0); /* 58 */
+       II (c, d, a, b,  6, S43, 0xa3014314); /* 59 */
+       II (b, c, d, a, 13, S44, 0x4e0811a1); /* 60 */
+       II (a, b, c, d,  4, S41, 0xf7537e82); /* 61 */
+       II (d, a, b, c, 11, S42, 0xbd3af235); /* 62 */
+       II (c, d, a, b,  2, S43, 0x2ad7d2bb); /* 63 */
+       II (b, c, d, a,  9, S44, 0xeb86d391); /* 64 */
+
+       A += a;  TRUNC32(A);
+       B += b;  TRUNC32(B);
+       C += c;  TRUNC32(C);
+       D += d;  TRUNC32(D);
+
+    } while (--blocks);
+    ctx->A = A;
+    ctx->B = B;
+    ctx->C = C;
+    ctx->D = D;
+}
+
+
+#ifdef MD5_DEBUG
+static char*
+ctx_dump(MD5_CTX* ctx)
+{
+    static char buf[1024];
+    sprintf(buf, "{A=%x,B=%x,C=%x,D=%x,%d,%d(%d)}",
+           ctx->A, ctx->B, ctx->C, ctx->D,
+           ctx->bytes_low, ctx->bytes_high, (ctx->bytes_low&0x3F));
+    return buf;
+}
+#endif
+
+
+static void
+MD5Update(MD5_CTX* ctx, const U8* buf, STRLEN len)
+{
+    STRLEN blocks;
+    STRLEN fill = ctx->bytes_low & 0x3F;
+
+#ifdef MD5_DEBUG  
+    static int ucount = 0;
+    fprintf(stderr,"%5i: Update(%s, %p, %d)\n", ++ucount, ctx_dump(ctx),
+                                               buf, len);
+#endif
+
+    ctx->bytes_low += len;
+    if (ctx->bytes_low < len) /* wrap around */
+       ctx->bytes_high++;
+
+    if (fill) {
+       STRLEN missing = 64 - fill;
+       if (len < missing) {
+           Copy(buf, ctx->buffer + fill, len, U8);
+           return;
+       }
+       Copy(buf, ctx->buffer + fill, missing, U8);
+       MD5Transform(ctx, ctx->buffer, 1);
+       buf += missing;
+       len -= missing;
+    }
+
+    blocks = len >> 6;
+    if (blocks)
+       MD5Transform(ctx, buf, blocks);
+    if ( (len &= 0x3F)) {
+       Copy(buf + (blocks << 6), ctx->buffer, len, U8);
+    }
+}
+
+
+static void
+MD5Final(U8* digest, MD5_CTX *ctx)
+{
+    STRLEN fill = ctx->bytes_low & 0x3F;
+    STRLEN padlen = (fill < 56 ? 56 : 120) - fill;
+    U32 bits_low, bits_high;
+#ifdef MD5_DEBUG
+    fprintf(stderr,"       Final:  %s\n", ctx_dump(ctx));
+#endif
+    Copy(PADDING, ctx->buffer + fill, padlen, U8);
+    fill += padlen;
+
+    bits_low = ctx->bytes_low << 3;
+    bits_high = (ctx->bytes_high << 3) | (ctx->bytes_low  >> 29);
+#ifdef BYTESWAP
+    *(U32*)(ctx->buffer + fill) = BYTESWAP(bits_low);    fill += 4;
+    *(U32*)(ctx->buffer + fill) = BYTESWAP(bits_high);   fill += 4;
+#else
+    u2s(bits_low,  ctx->buffer + fill);   fill += 4;
+    u2s(bits_high, ctx->buffer + fill);   fill += 4;
+#endif
+
+    MD5Transform(ctx, ctx->buffer, fill >> 6);
+#ifdef MD5_DEBUG
+    fprintf(stderr,"       Result: %s\n", ctx_dump(ctx));
+#endif
+
+#ifdef BYTESWAP
+    *(U32*)digest = BYTESWAP(ctx->A);  digest += 4;
+    *(U32*)digest = BYTESWAP(ctx->B);  digest += 4;
+    *(U32*)digest = BYTESWAP(ctx->C);  digest += 4;
+    *(U32*)digest = BYTESWAP(ctx->D);
+#else
+    u2s(ctx->A, digest);
+    u2s(ctx->B, digest+4);
+    u2s(ctx->C, digest+8);
+    u2s(ctx->D, digest+12);
+#endif
+}
+
+#ifndef INT2PTR
+#define INT2PTR(any,d) (any)(d)
+#endif
+
+static MD5_CTX* get_md5_ctx(SV* sv)
+{
+    if (SvROK(sv)) {
+       sv = SvRV(sv);
+       if (SvIOK(sv)) {
+           MD5_CTX* ctx = INT2PTR(MD5_CTX*, SvIV(sv));
+           if (ctx && ctx->signature == MD5_CTX_SIGNATURE) {
+               return ctx;
+            }
+        }
+    }
+    croak("Not a reference to a Digest::MD5 object");
+    return (MD5_CTX*)0; /* some compilers insist on a return value */
+}
+
+
+static char* hex_16(const unsigned char* from, char* to)
+{
+    static char *hexdigits = "0123456789abcdef";
+    const unsigned char *end = from + 16;
+    char *d = to;
+
+    while (from < end) {
+       *d++ = hexdigits[(*from >> 4)];
+       *d++ = hexdigits[(*from & 0x0F)];
+       from++;
+    }
+    *d = '\0';
+    return to;
+}
+
+static char* base64_16(const unsigned char* from, char* to)
+{
+    static char* base64 =
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+    const unsigned char *end = from + 16;
+    unsigned char c1, c2, c3;
+    char *d = to;
+
+    while (1) {
+       c1 = *from++;
+       *d++ = base64[c1>>2];
+       if (from == end) {
+           *d++ = base64[(c1 & 0x3) << 4];
+           break;
+       }
+       c2 = *from++;
+       c3 = *from++;
+       *d++ = base64[((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)];
+       *d++ = base64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
+       *d++ = base64[c3 & 0x3F];
+    }
+    *d = '\0';
+    return to;
+}
+
+/* Formats */
+#define F_BIN 0
+#define F_HEX 1
+#define F_B64 2
+
+static SV* make_mortal_sv(const unsigned char *src, int type)
+{
+    STRLEN len;
+    char result[33];
+    char *ret;
+    
+    switch (type) {
+    case F_BIN:
+       ret = (char*)src;
+       len = 16;
+       break;
+    case F_HEX:
+       ret = hex_16(src, result);
+       len = 32;
+       break;
+    case F_B64:
+       ret = base64_16(src, result);
+       len = 22;
+       break;
+    default:
+       croak("Bad convertion type (%d)", type);
+       break;
+    }
+    return sv_2mortal(newSVpv(ret,len));
+}
+
+
+/********************************************************************/
+
+typedef PerlIO* InputStream;
+
+MODULE = Digest::MD5           PACKAGE = Digest::MD5
+
+PROTOTYPES: DISABLE
+
+void
+new(xclass)
+       SV* xclass
+    PREINIT:
+       MD5_CTX* context;
+    PPCODE:
+       if (!SvROK(xclass)) {
+           STRLEN my_na;
+           char *sclass = SvPV(xclass, my_na);
+           New(55, context, 1, MD5_CTX);
+           context->signature = MD5_CTX_SIGNATURE;
+           ST(0) = sv_newmortal();
+           sv_setref_pv(ST(0), sclass, (void*)context);
+           SvREADONLY_on(SvRV(ST(0)));
+       } else {
+           context = get_md5_ctx(xclass);
+       }
+        MD5Init(context);
+       XSRETURN(1);
+
+void
+DESTROY(context)
+       MD5_CTX* context
+    CODE:
+        Safefree(context);
+
+void
+add(self, ...)
+       SV* self
+    PREINIT:
+       MD5_CTX* context = get_md5_ctx(self);
+       int i;
+       unsigned char *data;
+       STRLEN len;
+    PPCODE:
+       for (i = 1; i < items; i++) {
+           data = (unsigned char *)(SvPV(ST(i), len));
+           MD5Update(context, data, len);
+       }
+       XSRETURN(1);  /* self */
+
+void
+addfile(self, fh)
+       SV* self
+       InputStream fh
+    PREINIT:
+       MD5_CTX* context = get_md5_ctx(self);
+       STRLEN fill = context->bytes_low & 0x3F;
+       unsigned char buffer[4096];
+       int  n;
+    CODE:
+       if (fh) {
+            if (fill) {
+               /* The MD5Update() function is faster if it can work with
+                * complete blocks.  This will fill up any buffered block
+                * first.
+                */
+               STRLEN missing = 64 - fill;
+               if ( (n = PerlIO_read(fh, buffer, missing)))
+                   MD5Update(context, buffer, n);
+               else
+                   XSRETURN(1);  /* self */
+           }
+
+           /* Process blocks until EOF */
+            while ( (n = PerlIO_read(fh, buffer, sizeof(buffer)))) {
+               MD5Update(context, buffer, n);
+           }
+       }
+       XSRETURN(1);  /* self */
+
+void
+digest(context)
+       MD5_CTX* context
+    ALIAS:
+       Digest::MD5::digest    = F_BIN
+       Digest::MD5::hexdigest = F_HEX
+       Digest::MD5::b64digest = F_B64
+    PREINIT:
+       unsigned char digeststr[16];
+    PPCODE:
+        MD5Final(digeststr, context);
+       MD5Init(context);  /* In case it is reused */
+        ST(0) = make_mortal_sv(digeststr, ix);
+        XSRETURN(1);
+
+void
+md5(...)
+    ALIAS:
+       Digest::MD5::md5        = F_BIN
+       Digest::MD5::md5_hex    = F_HEX
+       Digest::MD5::md5_base64 = F_B64
+    PREINIT:
+       MD5_CTX ctx;
+       int i;
+       unsigned char *data;
+        STRLEN len;
+       unsigned char digeststr[16];
+    PPCODE:
+       MD5Init(&ctx);
+       for (i = 0; i < items; i++) {
+           data = (unsigned char *)(SvPV(ST(i), len));
+           MD5Update(&ctx, data, len);
+       }
+       MD5Final(digeststr, &ctx);
+        ST(0) = make_mortal_sv(digeststr, ix);
+        XSRETURN(1);
diff --git a/ext/Digest/MD5/Makefile.PL b/ext/Digest/MD5/Makefile.PL
new file mode 100644 (file)
index 0000000..9d59dba
--- /dev/null
@@ -0,0 +1,20 @@
+require 5.004;
+use strict;
+use Config qw(%Config);
+use ExtUtils::MakeMaker;
+
+my @extra;
+@extra = (DEFINE => "-DU32_ALIGNMENT_REQUIRED")
+    if $Config{'byteorder'} ne '1234' ||
+       $Config{'byteorder'} ne '4321' ||
+       $^O eq 'VMS' ||
+       $Config{u32_alignment_required};
+
+WriteMakefile(
+    'NAME'        => 'Digest::MD5',
+    'VERSION_FROM' => 'MD5.pm',
+    @extra,
+    'dist'         => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
+);
+exit;
+
diff --git a/ext/Digest/MD5/hints/irix_6.pl b/ext/Digest/MD5/hints/irix_6.pl
new file mode 100644 (file)
index 0000000..e38ae14
--- /dev/null
@@ -0,0 +1,6 @@
+# The Mongoose v7.1 compiler freezes up somewhere in the optimization of
+# MD5Transform() in MD5.c with optimization -O3.  This is a workaround:
+
+if ($Config{cc} =~ /64|n32/ && `$Config{cc} -version 2>&1` =~ /\s7\.1/) {
+    $self->{OPTIMIZE} = "-O1";
+}
diff --git a/ext/Digest/MD5/typemap b/ext/Digest/MD5/typemap
new file mode 100644 (file)
index 0000000..d52827e
--- /dev/null
@@ -0,0 +1,5 @@
+MD5_CTX*       T_MD5_CTX
+
+INPUT
+T_MD5_CTX
+       $var = get_md5_ctx($arg)
index 9141efc..cdab6fb 100644 (file)
@@ -24,7 +24,7 @@ i_utime=undef
 # compile/link flags
 ldflags=-g
 optimize=-g
-static_ext="B Data/Dumper Fcntl Filter::Util::Call IO IPC/SysV Opcode POSIX SDBM_File Socket Storable attrs"
+static_ext="B Data/Dumper Digest/MD5 Fcntl Filter::Util::Call IO IPC/SysV Opcode POSIX SDBM_File Socket Storable attrs"
 #static_ext=none
 # dynamic loading needs work
 usedl=undef
index 2c95fd3..d6d5315 100644 (file)
@@ -218,7 +218,7 @@ dynamic_ext=''
 eagain='EAGAIN'
 ebcdic='define'
 exe_ext=''
-extensions=' Data/Dumper Errno Fcntl Filter::Util:Call GDBM_File IO NDBM_File Opcode POSIX Socket Storable IPC/SysV Thread attrs re'
+extensions='Data/Dumper Digest/MD5 Errno Fcntl Filter::Util:Call GDBM_File IO NDBM_File Opcode POSIX Socket Storable IPC/SysV Thread attrs re'
 fpostype='fpos_t'
 freetype='void'
 groupstype='gid_t'
diff --git a/lib/Digest.pm b/lib/Digest.pm
new file mode 100644 (file)
index 0000000..047380e
--- /dev/null
@@ -0,0 +1,180 @@
+package Digest;
+
+use strict;
+use vars qw($VERSION %MMAP $AUTOLOAD);
+
+$VERSION = "1.00";
+
+%MMAP = (
+  "SHA-1"      => "Digest::SHA1",
+  "HMAC-MD5"   => "Digest::HMAC_MD5",
+  "HMAC-SHA-1" => "Digest::HMAC_SHA1",
+);
+
+sub new
+{
+    shift;  # class ignored
+    my $algorithm = shift;
+    my $class = $MMAP{$algorithm} || "Digest::$algorithm";
+    no strict 'refs';
+    unless (exists ${"$class\::"}{"VERSION"}) {
+       eval "require $class";
+       die $@ if $@;
+    }
+    $class->new(@_);
+}
+
+sub AUTOLOAD
+{
+    my $class = shift;
+    my $algorithm = substr($AUTOLOAD, rindex($AUTOLOAD, '::')+2);
+    $class->new($algorithm, @_);
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Digest:: - Modules that calculate message digests
+
+=head1 SYNOPSIS
+
+  $md2 = Digest->MD2;
+  $md5 = Digest->MD5;
+
+  $sha1 = Digest->SHA1;
+  $sha1 = Digest->new("SHA-1");
+
+  $hmac = Digest->HMAC_MD5($key);
+
+=head1 DESCRIPTION
+
+The C<Digest::> modules calculate digests, also called "fingerprints"
+or "hashes", of some data, called a message.  The digest is (usually)
+some small/fixed size string.  The actual size of the digest depend of
+the algorithm used.  The message is simply a sequence of arbitrary
+bytes.
+
+An important property of the digest algorithms is that the digest is
+I<likely> to change if the message change in some way.  Another
+property is that digest functions are one-way functions, i.e. it
+should be I<hard> to find a message that correspond to some given
+digest.  Algorithms differ in how "likely" and how "hard", as well as
+how efficient they are to compute.
+
+All C<Digest::> modules provide the same programming interface.  A
+functional interface for simple use, as well as an object oriented
+interface that can handle messages of arbitrary length and which can
+read files directly.
+
+The digest can be delivered in three formats:
+
+=over 8
+
+=item I<binary>
+
+This is the most compact form, but it is not well suited for printing
+or embedding in places that can't handle arbitrary data.
+
+=item I<hex>
+
+A twice as long string of (lowercase) hexadecimal digits.
+
+=item I<base64>
+
+A string of portable printable characters.  This is the base64 encoded
+representation of the digest with any trailing padding removed.  The
+string will be about 30% longer than the binary version.
+L<MIME::Base64> tells you more about this encoding.
+
+=back
+
+
+The functional interface is simply importable functions with the same
+name as the algorithm.  The functions take the message as argument and
+return the digest.  Example:
+
+  use Digest::MD5 qw(md5);
+  $digest = md5($message);
+
+There are also versions of the functions with "_hex" or "_base64"
+appended to the name, which returns the digest in the indicated form.
+
+=head1 OO INTERFACE
+
+The following methods are available for all C<Digest::> modules:
+
+=over 4
+
+=item $ctx = Digest->XXX($arg,...)
+
+=item $ctx = Digest->new(XXX => $arg,...)
+
+=item $ctx = Digest::XXX->new($arg,...)
+
+The constructor returns some object that encapsulate the state of the
+message-digest algorithm.  You can add data to the object and finally
+ask for the digest.  The "XXX" should of course be replaced by the proper
+name of the digest algorithm you want to use.
+
+The two first forms are simply syntactic sugar which automatically
+load the right module on first use.  The second form allow you to use
+algorithm names which contains letters which are not legal perl
+identifiers, e.g. "SHA-1".
+
+If new() is called as a instance method (i.e. $ctx->new) it will just
+reset the state the object to the state of a newly created object.  No
+new object is created in this case, and the return value is the
+reference to the object (i.e. $ctx).
+
+=item $ctx->reset
+
+This is just an alias for $ctx->new.
+
+=item $ctx->add($data,...)
+
+The $data provided as argument are appended to the message we
+calculate the digest for.  The return value is the $ctx object itself.
+
+=item $ctx->addfile($io_handle)
+
+The $io_handle is read until EOF and the content is appended to the
+message we calculate the digest for.  The return value is the $ctx
+object itself.
+
+=item $ctx->digest
+
+Return the binary digest for the message.
+
+Note that the C<digest> operation is effectively a destructive,
+read-once operation. Once it has been performed, the $ctx object is
+automatically C<reset> and can be used to calculate another digest
+value.
+
+=item $ctx->hexdigest
+
+Same as $ctx->digest, but will return the digest in hexadecimal form.
+
+=item $ctx->b64digest
+
+Same as $ctx->digest, but will return the digest as a base64 encoded
+string.
+
+=back
+
+=head1 SEE ALSO
+
+L<Digest::MD5>, L<Digest::SHA1>, L<Digest::HMAC>, L<Digest::MD2>
+
+L<MIME::Base64>
+
+=head1 AUTHOR
+
+Gisle Aas <gisle@aas.no>
+
+The C<Digest::> interface is based on the interface originally
+developed by Neil Winton for his C<MD5> module.
+
+=cut
diff --git a/t/lib/digest.t b/t/lib/digest.t
new file mode 100644 (file)
index 0000000..200de2b
--- /dev/null
@@ -0,0 +1,21 @@
+print "1..3\n";
+
+BEGIN {
+    chdir 't' if -d 't';
+    @INC = '../lib';
+}
+
+use Digest;
+
+print "not " unless Digest->MD5->add("abc")->hexdigest eq "900150983cd24fb0d6963f7d28e17f72";
+print "ok 1\n";
+
+print "not " unless Digest->MD5->add("abc")->hexdigest eq "900150983cd24fb0d6963f7d28e17f72";
+print "ok 2\n";
+
+eval {
+    print "not " unless Digest->new("HMAC-MD5" => "Jefe")->add("what do ya want for nothing?")->hexdigest eq "750c783e6ab0b503eaa86e310a5db738";
+    print "ok 3\n";
+};
+print "ok 3\n" if $@ && $@ =~ /^Can't locate/;
+
diff --git a/t/lib/md5-aaa.t b/t/lib/md5-aaa.t
new file mode 100644 (file)
index 0000000..62ae4c6
--- /dev/null
@@ -0,0 +1,287 @@
+BEGIN {
+        chdir 't' if -d 't';
+        @INC = '../lib';
+}
+
+use strict;
+print "1..256\n";
+
+use Digest::MD5 qw(md5_hex);
+
+my $testno = 0;
+while (<DATA>) {
+   my($hexdigest, $message) = split;
+   $message =~ s/\"//g;
+
+   my $failed;
+   $failed++ unless md5_hex($message) eq $hexdigest;
+   $failed++ unless Digest::MD5->new->add(split(//, $message))->digest
+                                              eq pack("H*", $hexdigest);
+
+   print "not " if $failed;
+   print "ok ", ++$testno, "\n";
+}
+
+
+
+# This data was generated with:
+#
+# perl -e 'for (1..256) { system("md5sum --string=" . ("a" x $_)); }'
+#
+__END__
+0cc175b9c0f1b6a831c399e269772661  "a"
+4124bc0a9335c27f086f24ba207a4912  "aa"
+47bce5c74f589f4867dbd57e9ca9f808  "aaa"
+74b87337454200d4d33f80c4663dc5e5  "aaaa"
+594f803b380a41396ed63dca39503542  "aaaaa"
+0b4e7a0e5fe84ad35fb5f95b9ceeac79  "aaaaaa"
+5d793fc5b00a2348c3fb9ab59e5ca98a  "aaaaaaa"
+3dbe00a167653a1aaee01d93e77e730e  "aaaaaaaa"
+552e6a97297c53e592208cf97fbb3b60  "aaaaaaaaa"
+e09c80c42fda55f9d992e59ca6b3307d  "aaaaaaaaaa"
+d57f21e6a273781dbf8b7657940f3b03  "aaaaaaaaaaa"
+45e4812014d83dde5666ebdf5a8ed1ed  "aaaaaaaaaaaa"
+c162de19c4c3731ca3428769d0cd593d  "aaaaaaaaaaaaa"
+451599a5f9afa91a0f2097040a796f3d  "aaaaaaaaaaaaaa"
+12f9cf6998d52dbe773b06f848bb3608  "aaaaaaaaaaaaaaa"
+23ca472302f49b3ea5592b146a312da0  "aaaaaaaaaaaaaaaa"
+88e42e96cc71151b6e1938a1699b0a27  "aaaaaaaaaaaaaaaaa"
+2c60c24e7087e18e45055a33f9a5be91  "aaaaaaaaaaaaaaaaaa"
+639d76897485360b3147e66e0a8a3d6c  "aaaaaaaaaaaaaaaaaaa"
+22d42eb002cefa81e9ad604ea57bc01d  "aaaaaaaaaaaaaaaaaaaa"
+bd049f221af82804c5a2826809337c9b  "aaaaaaaaaaaaaaaaaaaaa"
+ff49cfac3968dbce26ebe7d4823e58bd  "aaaaaaaaaaaaaaaaaaaaaa"
+d95dbfee231e34cccb8c04444412ed7d  "aaaaaaaaaaaaaaaaaaaaaaa"
+40edae4bad0e5bf6d6c2dc5615a86afb  "aaaaaaaaaaaaaaaaaaaaaaaa"
+a5a8bfa3962f49330227955e24a2e67c  "aaaaaaaaaaaaaaaaaaaaaaaaa"
+ae791f19bdf77357ff10bb6b0e97e121  "aaaaaaaaaaaaaaaaaaaaaaaaaa"
+aaab9c59a88bf0bdfcb170546c5459d6  "aaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b0f0545856af1a340acdedce23c54b97  "aaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+f7ce3d7d44f3342107d884bfa90c966a  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+59e794d45697b360e18ba972bada0123  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+3b0845db57c200be6052466f87b2198a  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+5eca9bd3eb07c006cd43ae48dfde7fd3  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b4f13cb081e412f44e99742cb128a1a5  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+4c660346451b8cf91ef50f4634458d41  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+11db24dc3f6c2145701db08625dd6d76  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+80dad3aad8584778352c68ab06250327  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+1227fe415e79db47285cb2689c93963f  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+8e084f489f1bdf08c39f98ff6447ce6d  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+08b2f2b0864bac1ba1585043362cbec9  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+4697843037d962f62a5a429e611e0f5f  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+10c4da18575c092b486f8ab96c01c02f  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+af205d729450b663f48b11d839a1c8df  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0d3f91798fac6ee279ec2485b25f1124  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+4c3c7c067634daec9716a80ea886d123  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+d1e358e6e3b707282cdd06e919f7e08c  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+8c6ded4f0af86e0a7e301f8a716c4363  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+4c2d8bcb02d982d7cb77f649c0a2dea8  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+bdb662f765cd310f2a547cab1cfecef6  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+08ff5f7301d30200ab89169f6afdb7af  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+6eb6a030bcce166534b95bc2ab45d9cf  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+1bb77918e5695c944be02c16ae29b25e  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b6fe77c19f0f0f4946c761d62585bfea  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e9e7e260dce84ffa6e0e7eb5fd9d37fc  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+eced9e0b81ef2bba605cbc5e2e76a1d0  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ef1772b6dff9a122358552954ad0df65  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+3b0c8ac703f828b04c6c197006d17218  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+652b906d60af96844ebd21b674f35e93  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+dc2f2f2462a0d72358b2f99389458606  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+762fc2665994b217c52c3c2eb7d9f406  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+cc7ed669cf88f201c3297c6a91e1d18d  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+cced11f7bbbffea2f718903216643648  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+24612f0ce2c9d2cf2b022ef1e027a54f  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b06521f39153d618550606be297466d5  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+014842d480b571495a4a0363793f7367  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+c743a45e0d2e6a95cb859adae0248435  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+def5d97e01e1219fb2fc8da6c4d6ba2f  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+92cb737f8687ccb93022fdb411a77cca  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+a0d1395c7fb36247bfe2d49376d9d133  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ab75504250558b788f99d1ebd219abf2  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0f5c6c4e740bfcc08c3c26ccb2673d46  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+cddd19bec7f310d8c87149ef47a1828f  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+96b39b8b95e016c79d104d83395b8133  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+f1fc0b14ff8fa674b02344577e23eeb1  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0e8d28a1cafa3ffcff22afd480cce7d8  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+448539ffc17e1e81005b65581855cef4  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+61e39aae7c53e6e77db2e4405d9fb157  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+618a426895ee6133a372bebd1129b63e  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+046c90690c9e36578b9d4a7e1d249c75  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+aadab38075c43296ee7e12466ebb03e3  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b15af9cdabbaea0516866a33d8fd0f98  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+986e6938ed767a8ae9530eef54bfe5f1  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+7ae25a72b71a42ccbc5477fd989cd512  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+98d34e50d4aa7a893cc7919a91acb0e3  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+3fc53fc22ea40f1a0afd78fc2cd9aa0f  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+923e37c738b9d7b1526f70b65229cc3d  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b3966b7a08e5d46fd0774b797ba78dc2  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+f50c7286b540bb181db1d6e05a51a296  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+4efd6c8826e65a61f82af954d431b59b  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ef1031e79e7a15a4470a5e98b23781b5  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+067876bfd0df0f4c5002780ec85e6f8c  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+789851dfa4c03563e9cef5f7bc050a7e  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+baf934720818ee49477e74fc644faa5e  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+9a0ea77ca26d2c121ddcc179edb76308  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+20c825561572e33d026f99ddfd999538  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+464c461455c5a927079a13609c20b637  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+cf37d42f89b6adb0e1a9e99104501b82  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+d266af45e3d06b70d9f52e2df4344186  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+f8b59fa22eb0ba944e2b7aa24d67b681  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0918d7c2f9062743450a86eae9dde1a3  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+36a92cc94a9e0fa21f625f8bfb007adf  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+681d73898dad5685d48b5e8438bc3a66  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+337ccef058459c3c16411381778da0c4  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+6ccdfcc742862036ce07583633c5f77e  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ddfa1adc974649dc5b414be86def7457  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+650ebc28ad85f11aa4b63b6ee565b89d  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e4571793bcaba284017eeabd8df85697  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+4fc040d354ad9ba5e4f62862109d3e17  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+25814274e02aa7cc03d6314eb703e655  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+11378ecaee0089c840d26352704027e3  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+86f950bfcd824d5546da01c40576db31  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+089f243d1e831c5879aa375ee364a06e  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+9146ef3527c7cfcc66dc615c3986e391  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+d727cfdfc9ed0347e6917a68b982f7bc  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+da8f45e1fdc12deecfe56aeb5288796e  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+29cfcf52d8250a253a535cf7989c7bd2  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0f6eb555b8e3c35411eebe9348594193  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+a922439f963e7e59040e4756992c6f1b  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+81f8453cf3f7e5ee5479c777e5a8d80c  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+8a7bd0732ed6a28ce75f6dabc90e1613  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+5f61c0ccad4cac44c75ff505e1f1e537  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+f6acfca2d47c87f2b14ca038234d3614  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+269fc62c517f3d55c368152addca57e7  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+50587cb16413da779b35508018721647  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+5e4a3ecfdaa4636b84a39b6a7be7c047  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+c5339dc2af6bf595580281ffb07353f6  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e51176a47347e167ed0ed766b6de1a0c  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+020406e1d05cdc2aa287641f7ae2cc39  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e510683b3f5ffe4093d021808bc6ff70  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b325dc1c6f5e7a2b7cf465b9feab7948  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e016e4ccc7fdaea56fc377600b58c4cb  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+3870ec709d2fc64b255d65be3123ad69  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+a92bde1f862c3fe797ecd69510bbd266  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+04daa146f3a2256fdcbf015c0f67e168  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+3d13c8bf627421ccc937aa1c9ac87bf1  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+247dc7ffc545e4dda64ae12def481c4e  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+2dfd4def392ee9563241b7db7eb7c346  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+d11a18a4743a1a0a699d1704efb74a0d  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+55b62fabd9c77d44d86e992eeeb093e6  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+9a72cf7d0bd5ae2907c79f91837e3ced  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+d3828cce1835534475029202ebd799e4  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b0bebbf0015658d4740679f263a3f01f  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+02368ebf1f53bc4634211b1693021666  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+04960f7d18960e348372949e4baa9752  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+c6041e7a86d407e9402b175670519260  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+439fd4c056bec1d14acd393746f6ae59  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+81a855120e04494c5a6c874a2360fd57  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ef57bd47a964dc3aadd959c4131e64ac  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0b0ab27b16cbba267c141fe0f4ee9189  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+abccd84f340bfe4ba59095cc3d5ca6ad  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+bc620e8c15265f195c8818e2f3e3c58b  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+fdcd84c4143286f6fc70c69208acd18d  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+50e05071e773b1e9f3009a4a559ce6b2  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+9e69c7a6c1863fbba2532f09ba665bde  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+47a962111aa5187eeef3d17a278d95f2  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+c13e57e33526bc713b5a1825f92651bc  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+72b392f15593e42404b38e5c889fa75e  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+5327acd3278274265d44e22ccfc4042c  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+930dcac6da160b2a4c51879da76d3417  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+41292c326f926f1534ead47fe302f0a0  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+2bdecb5cf6b69a00f7832299ef2fb5a5  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+8bf93e9e8a3e4396de3f211c788e177e  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+eea9cb566e19d6a7f55fbae78d94ef2a  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+3b8452700a829dec78397aa5c0458dd3  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+7950059f699eaea1e0a1759340d7c153  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+40840c5f1de00f17a8e70d5bd4d00af2  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+80f86f6af38be9ca8e40c2dc44491a0a  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+7aab2c2e72c77163e7102412dc332125  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+bfd6869ae2ee2fe2675846d341eaa67d  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+7e4d976f6d552d1d5bac7e2693dc8759  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+37d9884c32abfc6f372ee899434e64ad  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e362cd83a4b49d81ac6788b7839a56fd  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+9203cbb93b25d80b9d1b75e3c6c4b0dc  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+77441eda11554ec5b915d942605f66ed  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e0fe0c02b5c9c5afe10ab9d6a3769efe  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+cc7682cf11b214e928f3df899772e789  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ade0901d347afb25ecf9df4955bb8061  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+987379587cbe8e94b7057269232ff826  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+fd44a60101b04b7ddbc2b4e9b509ca1f  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+53107a7f1e6f13a2e63239b6f2bf0ef1  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0b82cdd562f26aaa2459610a7ba8cd76  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+79f12de7255e9c8c0ec9a9be45ee6210  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+92338d8de02ed7aa8b3adc9120b94e71  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+8fc48efda580fce85b8705d540e8382e  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+63642b027ee89938c922722650f2eb9b  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+fe54daa473502e9cc2c26dd66d564eab  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b90f3d4b7dcd8cdd8d96cb14695f4793  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+3e73392e7a03bca45b67650d79a8fc63  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+7fe51f2642dffbabc33eea2fcc2039ba  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+bc33790e52f99718cf920329961ee753  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+54d1e41ebac5db7886f01ab0afb65b17  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+16e2824f7a3f00ef0028994182071953  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+234c07907df5019d5f40f03936939bce  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+8ea3af1d9476fa0b6c04ce4f3a336c03  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e95b69eae07d498d484afc771d1c45fc  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+f22a673abbc4372544ba37b51a5f5a91  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+7e6161eb1be7b06928c536fada91b7f1  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+4dfe3c301e88fff67822e1cfcfece43f  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+edda210ac6645fbf5815eb4c58821f6d  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+6a514de2bf1926129b08f9234cd0115e  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+887f30b43b2867f4a9accceee7d16e6c  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+15936442c22dab9b685de350bfe75971  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+281a39e10bab29f1f2dead149a1f3f87  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+04d5f8a53b0eeda82d3c0ccafd02c98e  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+a91e6b80fe9d6db74fac76c7a67f065a  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+30334486fa9841044afb07f2573107a5  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0183c0cf15a3c2ed97d326f421b6d62c  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+4dc2a01b2161653753019b5228f765f8  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+71ef2dbdec7f78005354abebbfec8d8f  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+a1d1cd1446c113726ba50cc86d8b6519  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ed6da79cfd13ece051c4cb7c88e80c2e  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+d2047852ce178d4ddb7978da3883f9c5  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+d75382e07dd096b618faeeac033eefff  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+3fb48e286d462dcc237c3335aa63ba14  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+55b959972677ea06c4d0e32f7fb2f10a  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0a479c3623cfb9745e54d3376d0b9ae2  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+7825ad1ba19db7eec57d88b16936f32f  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+833ccf25509cb423a4aa98accb15512d  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+cae9609b05a9782610a5a43d7cd4b8ff  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+6c303e1da7f8a3032d13fe995847a722  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+4c47143a568e30ecde86dafe3bcb0558  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+9c48f0592f504b86360cfb6de00203b3  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e1524f5686f170209366f9723880d9b0  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+a96164a43a192543d40e538b9e9e4ece  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b774a4f788458a60e131d998705e4a06  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+1e97f0a7dfd3fac6ae585acdcf51a549  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b6364c77b6dd495c2a7f6b0211ac6fce  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+5d22315e78df2bc4146aa66f6c405dbb  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+2a773d5b04e910612543a42deeaaaa62  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0165449ac66b086accdec3051e0b691e  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+54884ba571054eae72b2a5271828a1fc  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+520fb61f8625ea916d72a54a37937bc6  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+7717f05d6e424a2c7a20ab7977b21ec8  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b64e4f62e3e14317e3a90f9ff2cde576  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+a49128259cfe50ba3bed80bbd11add7f  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b10cb153b79c2e4af6a8431c265aa82d  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+2e50fee6f574241042bdfabfdd46a153  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+5d5656a09b98c24edd01c530d3aad5e2  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+5ac1e1609d82274371c349d5b7875298  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b7b40d64ffccebd78abcf522376b3aae  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+8619933469d908a2d4a2d890909bea43  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+591a0ee6dccd872b46ae184eb0f9450e  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+8cd256a02c8c5c1676e9220e655d9ac4  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e48c0e2ed3e4e299a6e62e5416eb6d83  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+f30f75dce71e757ee562218c1efa0645  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+06bd7e90c0410dacb155732cf956f520  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+531a0a821a9304c215f1829b880306f1  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+93f4621c0b88499297ec3f8fbb3fb9c4  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+6af3d61e2e3ef8e189cffbea802c7e69  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+df84d21c884f99d6764d9bca4dec26e1  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+1bdbdf1c9087c796394bcda5789f7206  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+21f5b107cda33036590a19419afd7fb6  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0eae304c738191613302fb6721ea3605  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+abed9cdef66dcec954b87124ba18c1ab  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+dfde09457e2017e31d4ecfaea010db8f  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+46bc249a5a8fc5d622cf12c42c463ae0  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+81109eec5aa1a284fb5327b10e9c16b9  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
diff --git a/t/lib/md5-badf.t b/t/lib/md5-badf.t
new file mode 100644 (file)
index 0000000..63effdf
--- /dev/null
@@ -0,0 +1,26 @@
+BEGIN {
+        chdir 't' if -d 't';
+        @INC = '../lib';
+}
+
+# Digest::MD5 2.07 and older used to trigger a core dump when
+# passed an illegal file handle that failed to open.
+
+print "1..2\n";
+
+use Digest::MD5 ();
+
+$md5 = Digest::MD5->new;
+
+eval {
+   use vars qw(*FOO);
+   $md5->addfile(*FOO);
+};
+print "not " unless $@ =~ /^Bad filehandle: FOO/;
+print "ok 1\n";
+
+open(BAR, "none-existing-file.$$");
+$md5->addfile(*BAR);
+
+print "not " unless $md5->hexdigest eq "d41d8cd98f00b204e9800998ecf8427e";
+print "ok 2\n";
diff --git a/t/lib/md5-file.t b/t/lib/md5-file.t
new file mode 100644 (file)
index 0000000..5e6ba33
--- /dev/null
@@ -0,0 +1,111 @@
+BEGIN {
+        chdir 't' if -d 't';
+        @INC = '../lib';
+}
+
+print "1..2\n";
+
+use strict;
+use Digest::MD5 qw(md5 md5_hex);
+
+#
+# This is the output of: 'md5sum MD5.pm MD5.xs'
+#
+my $EXPECT = <<EOT;
+9e1d1183ff41717c91a563c41e08d672  ext/Digest/MD5/MD5.pm
+61debd0ec12e131e1ba220e2f3ad2d26  ext/Digest/MD5/MD5.xs
+EOT
+
+my $testno = 0;
+
+use File::Spec;
+
+for (split /^/, $EXPECT) {
+     my($md5hex, $file) = split ' ';
+     my @path = split(m:/:, $file);
+     my $last = pop @path;
+     my $path = File::Spec->updir;
+     while (@path) {
+        $path = File::Spec->catdir($path, shift @path);
+     }
+     $file = File::Spec->catfile($path, $last);
+     my $md5bin = pack("H*", $md5hex);
+     my $failed;
+
+     if (digest_file($file, 'digest') ne $md5bin) {
+        print "$file: Bad digest\n";
+        $failed++;
+     }
+
+     if (digest_file($file, 'hexdigest') ne $md5hex) {
+        print "$file: Bad hexdigest\n";
+        $failed++;
+     }
+
+     my $data = cat_file($file);
+     if (md5($data) ne $md5bin) {
+        print "$file: md5() failed\n";
+        $failed++;
+     }
+     if (md5_hex($data) ne $md5hex) {
+        print "$file: md5_hex() failed\n";
+        $failed++;
+     }
+
+     if (Digest::MD5->new->add($data)->digest ne $md5bin) {
+        print "$file: MD5->new->add(...)->digest failed\n";
+        $failed++;
+     }
+     if (Digest::MD5->new->add($data)->hexdigest ne $md5hex) {
+        print "$file: MD5->new->add(...)->hexdigest failed\n";
+        $failed++;
+     }
+
+     my @data = split //, $data;
+     if (md5(@data) ne $md5bin) {
+        print "$file: md5(\@data) failed\n";
+        $failed++;
+     }
+     if (Digest::MD5->new->add(@data)->digest ne $md5bin) {
+        print "$file: MD5->new->add(\@data)->digest failed\n";
+        $failed++;
+     }
+     my $md5 = Digest::MD5->new;
+     for (@data) {
+        $md5->add($_);
+     }
+     if ($md5->digest ne $md5bin) {
+        print "$file: $md5->add()-loop failed\n";
+        $failed++;
+     }
+
+     print "not " if $failed;
+     print "ok ", ++$testno, "\n";
+}
+
+
+sub digest_file
+{
+    my($file, $method) = @_;
+    $method ||= "digest";
+    #print "$file $method\n";
+
+    open(FILE, $file) or die "Can't open $file: $!";
+    binmode(FILE);
+    my $digest = Digest::MD5->new->addfile(*FILE)->$method();
+    close(FILE);
+
+    $digest;
+}
+
+sub cat_file
+{
+    my($file) = @_;
+    local $/;  # slurp
+    open(FILE, $file) or die "Can't open $file: $!";
+    binmode(FILE);
+    my $tmp = <FILE>;
+    close(FILE);
+    $tmp;
+}
+
index 9049099..295afc4 100644 (file)
@@ -608,7 +608,7 @@ SETARGV_OBJ = setargv$(o)
 
 DYNAMIC_EXT    = Socket IO Fcntl Opcode SDBM_File POSIX attrs Thread B re \
                Data/Dumper Devel/Peek ByteLoader Devel/DProf File/Glob \
-               Sys/Hostname Storable Filter/Util/Call Encode
+               Sys/Hostname Storable Filter/Util/Call Encode Digest/MD5
 STATIC_EXT     = DynaLoader
 NONXS_EXT      = Errno
 
@@ -633,6 +633,7 @@ HOSTNAME    = $(EXTDIR)\Sys\Hostname\Hostname
 STORABLE       = $(EXTDIR)\Storable\Storable
 FILTER         = $(EXTDIR)\Filter\Util\Call\Call
 ENCODE         = $(EXTDIR)\Encode\Encode
+MD5            = $(EXTDIR)\Digest\MD5\MD5
 
 SOCKET_DLL     = $(AUTODIR)\Socket\Socket.dll
 FCNTL_DLL      = $(AUTODIR)\Fcntl\Fcntl.dll
@@ -653,6 +654,7 @@ HOSTNAME_DLL        = $(AUTODIR)\Sys\Hostname\Hostname.dll
 STORABLE_DLL   = $(AUTODIR)\Storable\Storable.dll
 FILTER_DLL     = $(AUTODIR)\Filter\Util\Call\Call.dll
 ENCODE_DLL     = $(AUTODIR)\Encode\Encode.dll
+MD5_DLL                = $(AUTODIR)\Digest\MD5\MD5.dll
 
 ERRNO_PM       = $(LIBDIR)\Errno.pm
 
@@ -675,7 +677,8 @@ EXTENSION_C =               \
                $(HOSTNAME).c   \
                $(STORABLE).c   \
                $(FILTER).c     \
-               $(ENCODE).c     
+               $(ENCODE).c     \
+               $(MD5).c        
 
 EXTENSION_DLL  =               \
                $(SOCKET_DLL)   \
@@ -696,7 +699,8 @@ EXTENSION_DLL       =               \
                $(HOSTNAME_DLL) \
                $(STORABLE_DLL) \
                $(FILTER_DLL)   \
-               $(ENCODE_DLL)
+               $(ENCODE_DLL)   \
+               $(MD5_DLL)
 
 EXTENSION_PM   =               \
                $(ERRNO_PM)
@@ -980,12 +984,6 @@ $(BYTELOADER_DLL): $(PERLEXE) $(BYTELOADER).xs
        $(MAKE)
        cd ..\..\win32
 
-$(ENCODE_DLL): $(PERLEXE) $(ENCODE).xs
-       cd $(EXTDIR)\$(*B)
-       ..\..\miniperl -I..\..\lib Makefile.PL INSTALLDIRS=perl
-       $(MAKE)
-       cd ..\..\win32
-
 $(STORABLE_DLL): $(PERLEXE) $(STORABLE).xs
        cd $(EXTDIR)\$(*B)
        ..\..\miniperl -I..\..\lib Makefile.PL INSTALLDIRS=perl
@@ -1004,6 +1002,12 @@ $(ENCODE_DLL): $(PERLEXE) $(ENCODE).xs
        $(MAKE)
        cd ..\..\win32
 
+$(MD5_DLL): $(PERLEXE) $(MD5).xs
+       cd $(EXTDIR)\$(*B)
+       ..\..\miniperl -I..\..\lib Makefile.PL INSTALLDIRS=perl
+       $(MAKE)
+       cd ..\..\win32
+
 $(ERRNO_PM): $(PERLEXE) $(ERRNO)_pm.PL
        cd $(EXTDIR)\$(*B)
        ..\..\miniperl -I..\..\lib Makefile.PL INSTALLDIRS=perl
@@ -1058,6 +1062,7 @@ distclean: clean
        -del /f $(LIBDIR)\File\Glob.pm
        -del /f $(LIBDIR)\Storable.pm
        -del /f $(LIBDIR)\Filter\Util\Call\Call.pm
+       -del /f $(LIBDIR)\Digest\MD5.pm
        -if exist $(LIBDIR)\IO rmdir /s /q $(LIBDIR)\IO
        -rmdir /s $(LIBDIR)\IO
        -if exist $(LIBDIR)\Thread rmdir /s /q $(LIBDIR)\Thread
@@ -1068,6 +1073,8 @@ distclean: clean
        -rmdir /s $(LIBDIR)\Data
        -if exist $(LIBDIR)\Filter\Util\Call rmdir /s /q $(LIBDIR)\Filter\Util\Call
        -if exist $(LIBDIR)\Filter\Util rmdir /s /q $(LIBDIR)\Filter\Util
+       -if exist $(LIBDIR)\Digest rmdir /s /q $(LIBDIR)\Digest
+       -rmdir /s $(LIBDIR)\Digest
        -del /f $(PODDIR)\*.html
        -del /f $(PODDIR)\*.bat
        cd ..\utils
index 5c21ebb..6e91bc2 100644 (file)
@@ -743,7 +743,7 @@ SETARGV_OBJ = setargv$(o)
 
 DYNAMIC_EXT    = Socket IO Fcntl Opcode SDBM_File POSIX attrs Thread B re \
                Data/Dumper Devel/Peek ByteLoader Devel/DProf File/Glob \
-               Sys/Hostname Storable Filter/Util/Call Encode
+               Sys/Hostname Storable Filter/Util/Call Encode Digest/MD5
 STATIC_EXT     = DynaLoader
 NONXS_EXT      = Errno
 
@@ -768,6 +768,7 @@ HOSTNAME    = $(EXTDIR)\Sys\Hostname\Hostname
 STORABLE       = $(EXTDIR)\Storable\Storable
 FILTER         = $(EXTDIR)\Filter\Util\Call\Call
 ENCODE          = $(EXTDIR)\Encode\Encode
+MD5            = $(EXTDIR)\Digest\MD5\MD5
 
 SOCKET_DLL     = $(AUTODIR)\Socket\Socket.dll
 FCNTL_DLL      = $(AUTODIR)\Fcntl\Fcntl.dll
@@ -788,6 +789,7 @@ HOSTNAME_DLL        = $(AUTODIR)\Sys\Hostname\Hostname.dll
 STORABLE_DLL   = $(AUTODIR)\Storable\Storable.dll
 FILTER_DLL     = $(AUTODIR)\Filter\Util\Call\Call.dll
 ENCODE_DLL     = $(AUTODIR)\Encode\Encode.dll
+MD5_DLL                = $(AUTODIR)\Digest\MD5\MD5.dll
 
 ERRNO_PM       = $(LIBDIR)\Errno.pm
 
@@ -810,7 +812,8 @@ EXTENSION_C =               \
                $(HOSTNAME).c   \
                $(STORABLE).c   \
                $(FILTER).c     \
-               $(ENCODE).c
+               $(ENCODE).c     \
+               $(MD5).c
 
 EXTENSION_DLL  =               \
                $(SOCKET_DLL)   \
@@ -831,7 +834,8 @@ EXTENSION_DLL       =               \
                $(HOSTNAME_DLL) \
                $(STORABLE_DLL) \
                $(FILTER_DLL)   \
-               $(ENCODE_DLL)
+               $(ENCODE_DLL)   \
+               $(MD5_DLL)
 
 EXTENSION_PM   =               \
                $(ERRNO_PM)
@@ -1230,6 +1234,11 @@ $(FILTER_DLL): $(PERLDEP) $(FILTER).xs
        ..\..\..\..\miniperl -I..\..\..\..\lib Makefile.PL INSTALLDIRS=perl
        cd $(EXTDIR)\Filter\Util\Call && $(MAKE)
 
+$(MD5_DLL): $(PERLDEP) $(FILTER).xs
+       cd $(EXTDIR)\Digest\MD5 && \
+       ..\..\..\miniperl -I..\..\..\lib Makefile.PL INSTALLDIRS=perl
+       cd $(EXTDIR)\Digest\MD5 && $(MAKE)
+
 $(ERRNO_PM): $(PERLDEP) $(ERRNO)_pm.PL
        cd $(EXTDIR)\$(*B) && \
        ..\..\miniperl -I..\..\lib Makefile.PL INSTALLDIRS=perl
@@ -1279,12 +1288,14 @@ distclean: clean
        -del /f $(LIBDIR)\File\Glob.pm
        -del /f $(LIBDIR)\Storable.pm
        -del /f $(LIBDIR)\Filter\Util\Call\Call.pm
+       -del /f $(LIBDIR)\Digest\MD5.pm
        -if exist $(LIBDIR)\IO rmdir /s /q $(LIBDIR)\IO || rmdir /s $(LIBDIR)\IO
        -if exist $(LIBDIR)\Thread rmdir /s /q $(LIBDIR)\Thread || rmdir /s $(LIBDIR)\Thread
        -if exist $(LIBDIR)\B rmdir /s /q $(LIBDIR)\B || rmdir /s $(LIBDIR)\B
        -if exist $(LIBDIR)\Data rmdir /s /q $(LIBDIR)\Data || rmdir /s $(LIBDIR)\Data
        -if exist $(LIBDIR)\Filter\Util\Call rmdir /s /q $(LIBDIR)\Filter\Util\Call || rmdir /s $(LIBDIR)\Filter
        -if exist $(LIBDIR)\Filter\Util rmdir /s /q $(LIBDIR)\Filter\Util || rmdir /s $(LIBDIR)\Filter
+       -if exist $(LIBDIR)\Digest rmdir /s /q $(LIBDIR)\Digest || rmdir /s $(LIBDIR)\Digest
        -del /f $(PODDIR)\*.html
        -del /f $(PODDIR)\*.bat
        -cd ..\utils && del /f h2ph splain perlbug pl2pm c2ph h2xs perldoc \