1require 'digest.so'
2
3module Digest
4  def self.const_missing(name) # :nodoc:
5    case name
6    when :SHA256, :SHA384, :SHA512
7      lib = 'digest/sha2.so'
8    else
9      lib = File.join('digest', name.to_s.downcase)
10    end
11
12    begin
13      require lib
14    rescue LoadError
15      raise LoadError, "library not found for class Digest::#{name} -- #{lib}", caller(1)
16    end
17    unless Digest.const_defined?(name)
18      raise NameError, "uninitialized constant Digest::#{name}", caller(1)
19    end
20    Digest.const_get(name)
21  end
22
23  class ::Digest::Class
24    # creates a digest object and reads a given file, _name_.
25    #
26    #   p Digest::SHA256.file("X11R6.8.2-src.tar.bz2").hexdigest
27    #   # => "f02e3c85572dc9ad7cb77c2a638e3be24cc1b5bea9fdbb0b0299c9668475c534"
28    def self.file(name)
29      new.file(name)
30    end
31
32    # Returns the base64 encoded hash value of a given _string_.  The
33    # return value is properly padded with '=' and contains no line
34    # feeds.
35    def self.base64digest(str, *args)
36      [digest(str, *args)].pack('m0')
37    end
38  end
39
40  module Instance
41    # updates the digest with the contents of a given file _name_ and
42    # returns self.
43    def file(name)
44      File.open(name, "rb") {|f|
45        buf = ""
46        while f.read(16384, buf)
47          update buf
48        end
49      }
50      self
51    end
52
53    # If none is given, returns the resulting hash value of the digest
54    # in a base64 encoded form, keeping the digest's state.
55    #
56    # If a +string+ is given, returns the hash value for the given
57    # +string+ in a base64 encoded form, resetting the digest to the
58    # initial state before and after the process.
59    #
60    # In either case, the return value is properly padded with '=' and
61    # contains no line feeds.
62    def base64digest(str = nil)
63      [str ? digest(str) : digest].pack('m0')
64    end
65
66    # Returns the resulting hash value and resets the digest to the
67    # initial state.
68    def base64digest!
69      [digest!].pack('m0')
70    end
71  end
72end
73
74# call-seq:
75#   Digest(name) -> digest_subclass
76#
77# Returns a Digest subclass by +name+.
78#
79#   require 'digest'
80#
81#   Digest("MD5")
82#   # => Digest::MD5
83#
84#   Digest("Foo")
85#   # => LoadError: library not found for class Digest::Foo -- digest/foo
86def Digest(name)
87  Digest.const_get(name)
88end
89