<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>.gitignore</filename>
    </added>
    <added>
      <filename>HISTORY</filename>
    </added>
    <added>
      <filename>gemspec.rb</filename>
    </added>
    <added>
      <filename>tasks/config.rb</filename>
    </added>
    <added>
      <filename>tasks/utils.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -2,7 +2,8 @@
 
 * Homepage[http://copiousfreetime.rubyforge.org/htauth]
 * {Rubyforge Project}[http://rubyforge.org/projects/copiousfreetime/]
-* email jeremy at hinegardner dot org
+* Github[http://github.com/copiousfreetime/htauth/tree/master]
+* email jeremy at copiousfreetime dot org
 
 == DESCRIPTION
 </diff>
      <filename>README</filename>
    </modified>
    <modified>
      <diff>@@ -1,14 +1,61 @@
-# make sure our project's ./lib directory is added to the ruby search path
-$: &lt;&lt; File.join(File.dirname(__FILE__),&quot;lib&quot;)
+#--
+# Copyright (c) 2008 Jeremy Hinegardner
+# All rights reserved.  See LICENSE and/or COPYING for details.
+#++
 
+#-------------------------------------------------------------------------------
+# make sure our project's top level directory and the lib directory are added to
+# the ruby search path.
+#-------------------------------------------------------------------------------
+$: &lt;&lt; File.expand_path(File.join(File.dirname(__FILE__),&quot;lib&quot;))
+$: &lt;&lt; File.expand_path(File.dirname(__FILE__))
+
+#-------------------------------------------------------------------------------
+# load the global project configuration and add in the top level clean and
+# clobber tasks so that other tasks can utilize those constants if necessary
+# This loads up the defaults for the whole project configuration
+#-------------------------------------------------------------------------------
 require 'rubygems'
-require 'rake/gempackagetask'
+require 'tasks/config.rb'
+require 'gemspec'
 require 'rake/clean'
+require 'rake/gempackagetask'
 require 'rake/rdoctask'
-require 'rake/contrib/sshpublisher'
-
+require 'spec/rake/spectask'
+#-------------------------------------------------------------------------------
+# Main configuration for the project, these overwrite the items that are in
+# tasks/config.rb
+#-------------------------------------------------------------------------------
 require 'htauth'
+Configuration.for(&quot;project&quot;) {
+  name      &quot;htauth&quot;
+  version   HTAuth::VERSION
+  author    &quot;Jeremy Hinegardner&quot;
+  email     &quot;jeremy@copiousfreetime.org&quot;
+  homepage  &quot;http://copiousfreetime.rubyforge.org/htauth/&quot;
+}
 
-load 'tasks/setup.rb'
-
+#-------------------------------------------------------------------------------
+# load up all the project tasks and setup the default task to be the
+# test:default task.
+#-------------------------------------------------------------------------------
+Configuration.for(&quot;packaging&quot;).files.tasks.each do |tasklib|
+  import tasklib
+end
+task :default =&gt; 'test:default'
 
+#-------------------------------------------------------------------------------
+# Finalize the loading of all pending imports and update the top level clobber
+# task to depend on all possible sub-level tasks that have a name like
+# ':clobber'  in other namespaces.  This allows us to say:
+#
+#   rake clobber
+#
+# and it will get everything.
+#-------------------------------------------------------------------------------
+Rake.application.load_imports
+Rake.application.tasks.each do |t| 
+  if t.name =~ /:clobber/ then
+    task :clobber =&gt; [t.name] 
+  end
+end</diff>
      <filename>Rakefile</filename>
    </modified>
    <modified>
      <diff>@@ -1,12 +1,19 @@
 #!/usr/bin/env ruby
 
+begin 
+  require 'highline'
+rescue LoadError
+  require 'rubygems'
+  require 'highline'
+end
+
 begin
-    require 'htauth'
+  require 'htauth'
 rescue LoadError 
-    path = File.expand_path(File.join(File.dirname(__FILE__),&quot;..&quot;,&quot;lib&quot;))
-    raise if $:.include?(path)
-    $: &lt;&lt; path
-    retry
+  path = File.expand_path(File.join(File.dirname(__FILE__),&quot;..&quot;,&quot;lib&quot;))
+  raise if $:.include?(path)
+  $: &lt;&lt; path
+  retry
 end
 
-HTAuth::Digest.new.run(ARGV)
+HTAuth::Digest.new.run(ARGV, ENV)</diff>
      <filename>bin/htdigest-ruby</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,13 @@
 #!/usr/bin/env ruby
 
 begin
+  require 'highline'
+rescue LoadError
+  require 'rubygems'
+  require 'highline'
+end
+
+begin
     require 'htauth'
 rescue LoadError 
     path = File.expand_path(File.join(File.dirname(__FILE__),&quot;..&quot;,&quot;lib&quot;))
@@ -9,4 +16,4 @@ rescue LoadError
     retry
 end
 
-HTAuth::Passwd.new.run(ARGV)
+HTAuth::Passwd.new.run(ARGV, ENV)</diff>
      <filename>bin/htpasswd-ruby</filename>
    </modified>
    <modified>
      <diff>@@ -1,14 +1,36 @@
+#-- 
+# Copyrigth (c) 2008 Jeremy Hinegardner
+# All rights reserved.  See LICENSE and/or COPYING for details
+#++
+
 module HTAuth
-    
-    ROOT_DIR        = ::File.expand_path(::File.join(::File.dirname(__FILE__),&quot;..&quot;))
-    LIB_DIR         = ::File.join(ROOT_DIR,&quot;lib&quot;).freeze
 
-    class FileAccessError &lt; StandardError ; end
-    class TempFileError &lt; StandardError ; end
-    class PasswordError &lt; StandardError ; end
+  # The root directory of the project is considered to be the parent directory
+  # of the 'lib' directory.
+  #
+  def self.root_dir
+    unless @root_dir
+      path_parts = ::File.expand_path( __FILE__ ).split( ::File::SEPARATOR )
+      lib_index  = path_parts.rindex( 'lib' )
+      @root_dir  = path_parts[ 0...lib_index].join( ::File::SEPARATOR ) + ::File::SEPARATOR
+    end
+    return @root_dir
+  end
+
+  def self.lib_path( *args )
+    self.sub_path( &quot;lib&quot;, *args )
+  end
+
+  def self.sub_path( sub, *args )
+    sp = ::File.join( root_dir, sub ) + ::File::SEPARATOR
+    sp = ::File.join( sp, *args ) if args
+  end
+
+  class FileAccessError &lt; StandardError ; end
+  class TempFileError &lt; StandardError ; end
+  class PasswordError &lt; StandardError ; end
 end
 
 require 'htauth/version'
-require 'htauth/gemspec'
 require 'htauth/passwd'
 require 'htauth/digest'</diff>
      <filename>lib/htauth.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,67 +1,68 @@
 require 'htauth'
 
 module HTAuth
-    class InvalidAlgorithmError &lt; StandardError ; end
-    # base class all the Passwd algorithms derive from
-    class Algorithm
+  class InvalidAlgorithmError &lt; StandardError ; end
+  # base class all the Passwd algorithms derive from
+  class Algorithm
 
-        SALT_CHARS    = (%w[ . / ] + (&quot;0&quot;..&quot;9&quot;).to_a + ('A'..'Z').to_a + ('a'..'z').to_a).freeze
-        DEFAULT       = ( RUBY_PLATFORM !~ /mswin32/ ) ? &quot;crypt&quot; : &quot;md5&quot;
-        EXISTING      = &quot;existing&quot;
+    SALT_CHARS    = (%w[ . / ] + (&quot;0&quot;..&quot;9&quot;).to_a + ('A'..'Z').to_a + ('a'..'z').to_a).freeze
+    DEFAULT       = ( RUBY_PLATFORM !~ /mswin32/ ) ? &quot;crypt&quot; : &quot;md5&quot;
+    EXISTING      = &quot;existing&quot;
 
-        class &lt;&lt; self
-            def algorithm_from_name(a_name, params = {})
-                raise InvalidAlgorithmError, &quot;`#{a_name}' is an invalid encryption algorithm, use one of #{sub_klasses.keys.join(', ')}&quot; unless sub_klasses[a_name.downcase]
-                sub_klasses[a_name.downcase].new(params)
-            end
+    class &lt;&lt; self
+      def algorithm_from_name(a_name, params = {})
+        raise InvalidAlgorithmError, &quot;`#{a_name}' is an invalid encryption algorithm, use one of #{sub_klasses.keys.join(', ')}&quot; unless sub_klasses[a_name.downcase]
+        sub_klasses[a_name.downcase].new(params)
+      end
 
-            def algorithms_from_field(password_field)
-                matches = []
+      def algorithms_from_field(password_field)
+        matches = []
 
-                if password_field.index(sub_klasses['sha1'].new.prefix) then
-                    matches &lt;&lt; sub_klasses['sha1'].new
-                elsif password_field.index(sub_klasses['md5'].new.prefix) then
-                    p = password_field.split(&quot;$&quot;)
-                    matches &lt;&lt; sub_klasses['md5'].new( :salt =&gt; p[2] )
-                else
-                    matches &lt;&lt; sub_klasses['plaintext'].new
-                    matches &lt;&lt; sub_klasses['crypt'].new( :salt =&gt; password_field[0,2] )
-                end
+        if password_field.index(sub_klasses['sha1'].new.prefix) then
+          matches &lt;&lt; sub_klasses['sha1'].new
+        elsif password_field.index(sub_klasses['md5'].new.prefix) then
+          p = password_field.split(&quot;$&quot;)
+          matches &lt;&lt; sub_klasses['md5'].new( :salt =&gt; p[2] )
+        else
+          matches &lt;&lt; sub_klasses['plaintext'].new
+          matches &lt;&lt; sub_klasses['crypt'].new( :salt =&gt; password_field[0,2] )
+        end
 
-                return matches
-            end
+        return matches
+      end
 
-            def inherited(sub_klass)
-                k = sub_klass.name.split(&quot;::&quot;).last.downcase
-                sub_klasses[k] = sub_klass
-            end
+      def inherited(sub_klass)
+        k = sub_klass.name.split(&quot;::&quot;).last.downcase
+        sub_klasses[k] = sub_klass
+      end
 
-            def sub_klasses
-                @sub_klasses ||= {}
-            end
-        end
+      def sub_klasses
+        @sub_klasses ||= {}
+      end
+    end
 
-        def prefix ; end
-        def encode(password) ; end
-        
-        # 8 bytes of random items from SALT_CHARS
-        def gen_salt
-            chars = []
-            8.times { chars &lt;&lt; SALT_CHARS[rand(SALT_CHARS.size)] }
-            chars.join('')     
-        end
+    def prefix ; end
+    def encode(password) ; end
 
-        # this is not the Base64 encoding, this is the to64() method from apr
-        def to_64(number, rounds)
-            r = StringIO.new
-            rounds.times do |x|
-                r.print(SALT_CHARS[number % 64])
-                number &gt;&gt;= 6
-            end
-            return r.string
-        end
+    # 8 bytes of random items from SALT_CHARS
+    def gen_salt
+      chars = []
+      8.times { chars &lt;&lt; SALT_CHARS[rand(SALT_CHARS.size)] }
+      chars.join('')     
+    end
+
+    # this is not the Base64 encoding, this is the to64() method from apr
+    def to_64(number, rounds)
+      r = StringIO.new
+      rounds.times do |x|
+        r.print(SALT_CHARS[number % 64])
+        number &gt;&gt;= 6
+      end
+      return r.string
     end
+  end
 end
+
 require 'htauth/md5'
 require 'htauth/sha1'
 require 'htauth/crypt'</diff>
      <filename>lib/htauth/algorithm.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,19 +2,19 @@ require 'htauth/algorithm'
 
 module HTAuth
 
-    # The basic crypt algorithm
-    class Crypt &lt; Algorithm
-        
-        def initialize(params = {})
-            @salt = params[:salt] || params['salt'] || gen_salt
-        end
+  # The basic crypt algorithm
+  class Crypt &lt; Algorithm
 
-        def prefix
+    def initialize(params = {})
+      @salt = params[:salt] || params['salt'] || gen_salt
+    end
+
+    def prefix
             &quot;&quot;
-        end
+    end
 
-        def encode(password)
-            password.crypt(@salt)
-        end
+    def encode(password)
+      password.crypt(@salt)
     end
+  end
 end</diff>
      <filename>lib/htauth/crypt.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,127 +4,126 @@ require 'htauth/digest_file'
 require 'ostruct'
 require 'optparse'
 
-require 'rubygems'
 require 'highline'
 
 module HTAuth
-    class Digest
+  class Digest
 
-        MAX_PASSWD_LENGTH = 255
+    MAX_PASSWD_LENGTH = 255
 
-        attr_accessor :digest_file
+    attr_accessor :digest_file
 
-        def initialize
-            @digest_file = nil
-        end
+    def initialize
+      @digest_file = nil
+    end
 
-        def options
-            if @options.nil? then
-                @options                = ::OpenStruct.new
-                @options.show_version   = false
-                @options.show_help      = false
-                @options.file_mode      = DigestFile::ALTER
-                @options.passwdfile     = nil
-                @options.realm          = nil
-                @options.username       = nil
-                @options.delete_entry   = false
-            end
-            @options
-        end
+    def options
+      if @options.nil? then
+        @options                = ::OpenStruct.new
+        @options.show_version   = false
+        @options.show_help      = false
+        @options.file_mode      = DigestFile::ALTER
+        @options.passwdfile     = nil
+        @options.realm          = nil
+        @options.username       = nil
+        @options.delete_entry   = false
+      end
+      @options
+    end
 
-        def option_parser
-            if not @option_parser then
-                @option_parser = OptionParser.new do |op|
-                    op.banner = &quot;Usage: #{op.program_name} [options] passwordfile realm username&quot;
-                    op.on(&quot;-c&quot;, &quot;--create&quot;, &quot;Create a new digest password file; this overwrites an existing file.&quot;) do |c|
-                        options.file_mode = DigestFile::CREATE
-                    end
-
-                    op.on(&quot;-D&quot;, &quot;--delete&quot;, &quot;Delete the specified user.&quot;) do |d|
-                        options.delete_entry = d
-                    end
-
-                    op.on(&quot;-h&quot;, &quot;--help&quot;, &quot;Display this help.&quot;) do |h|
-                        options.show_help = h
-                    end
-
-                    op.on(&quot;-v&quot;, &quot;--version&quot;, &quot;Show version info.&quot;) do |v|
-                        options.show_version = v
-                    end
-                end
-            end
-            @option_parser
+    def option_parser
+      if not @option_parser then
+        @option_parser = OptionParser.new do |op|
+          op.banner = &quot;Usage: #{op.program_name} [options] passwordfile realm username&quot;
+          op.on(&quot;-c&quot;, &quot;--create&quot;, &quot;Create a new digest password file; this overwrites an existing file.&quot;) do |c|
+            options.file_mode = DigestFile::CREATE
+          end
+
+          op.on(&quot;-D&quot;, &quot;--delete&quot;, &quot;Delete the specified user.&quot;) do |d|
+            options.delete_entry = d
+          end
+
+          op.on(&quot;-h&quot;, &quot;--help&quot;, &quot;Display this help.&quot;) do |h|
+            options.show_help = h
+          end
+
+          op.on(&quot;-v&quot;, &quot;--version&quot;, &quot;Show version info.&quot;) do |v|
+            options.show_version = v
+          end
         end
+      end
+      @option_parser
+    end
 
-        def show_help
-            $stdout.puts option_parser
-            exit 1
-        end
+    def show_help
+      $stdout.puts option_parser
+      exit 1
+    end
 
-        def show_version
-            $stdout.puts &quot;#{option_parser.program_name}: version #{HTAuth::VERSION}&quot;
-            exit 1
-        end
+    def show_version
+      $stdout.puts &quot;#{option_parser.program_name}: version #{HTAuth::VERSION}&quot;
+      exit 1
+    end
 
-        def parse_options(argv)
-            begin
-                option_parser.parse!(argv)
-                show_version if options.show_version
-                show_help if options.show_help or argv.size &lt; 3
-
-                options.passwdfile = argv.shift
-                options.realm      = argv.shift
-                options.username   = argv.shift
-            rescue ::OptionParser::ParseError =&gt; pe
-                $stderr.puts &quot;ERROR: #{option_parser.program_name} - #{pe}&quot;
-                $stderr.puts &quot;Try `#{option_parser.program_name} --help` for more information&quot;
-                exit 1
-            end
-        end
+    def parse_options(argv)
+      begin
+        option_parser.parse!(argv)
+        show_version if options.show_version
+        show_help if options.show_help or argv.size &lt; 3
+
+        options.passwdfile = argv.shift
+        options.realm      = argv.shift
+        options.username   = argv.shift
+      rescue ::OptionParser::ParseError =&gt; pe
+        $stderr.puts &quot;ERROR: #{option_parser.program_name} - #{pe}&quot;
+        $stderr.puts &quot;Try `#{option_parser.program_name} --help` for more information&quot;
+        exit 1
+      end
+    end
+
+    def run(argv, env)
+      begin
+        parse_options(argv)
+        digest_file = DigestFile.new(options.passwdfile, options.file_mode)
+
+        if options.delete_entry then
+          digest_file.delete(options.username, options.realm)
+        else
+          # initialize here so that if $stdin is overwritten it gets picked up
+          hl = ::HighLine.new
+
+          action = digest_file.has_entry?(options.username, options.realm) ? &quot;Changing&quot; : &quot;Adding&quot;
 
-        def run(argv)
-            begin
-                parse_options(argv)
-                digest_file = DigestFile.new(options.passwdfile, options.file_mode)
-
-                if options.delete_entry then
-                    digest_file.delete(options.username, options.realm)
-                else
-                    # initialize here so that if $stdin is overwritten it gest picked up
-                    hl = ::HighLine.new
-
-                    action = digest_file.has_entry?(options.username, options.realm) ? &quot;Changing&quot; : &quot;Adding&quot;
-
-                    $stdout.puts &quot;#{action} password for #{options.username} in realm #{options.realm}.&quot;
-
-                    pw_in       = hl.ask(&quot;        New password: &quot;) { |q| q.echo = '*' } 
-                    raise PasswordError, &quot;password '#{pw_in}' too long&quot; if pw_in.length &gt;= MAX_PASSWD_LENGTH
-                    
-                    pw_validate = hl.ask(&quot;Re-type new password: &quot;) { |q| q.echo = '*' }
-                    raise PasswordError, &quot;They don't match, sorry.&quot; unless pw_in == pw_validate
-
-                    digest_file.add_or_update(options.username, options.realm, pw_in)
-                end
-
-                digest_file.save!
-
-            rescue HTAuth::FileAccessError =&gt; fae
-                msg = &quot;Could not open password file #{options.passwdfile} &quot;
-                $stderr.puts &quot;#{msg}: #{fae.message}&quot;
-                $stderr.puts fae.backtrace.join(&quot;\n&quot;)
-                exit 1
-            rescue HTAuth::PasswordError =&gt; pe
-                $stderr.puts &quot;#{pe.message}&quot;
-                exit 1
-            rescue HTAuth::DigestFileError =&gt; fe
-                $stderr.puts &quot;#{fe.message}&quot;
-                exit 1
-            rescue SignalException =&gt; se
-                $stderr.puts
-                $stderr.puts &quot;Interrupted&quot;
-                exit 1
-            end
-            exit 0
+          $stdout.puts &quot;#{action} password for #{options.username} in realm #{options.realm}.&quot;
+
+          pw_in       = hl.ask(&quot;        New password: &quot;) { |q| q.echo = '*' } 
+          raise PasswordError, &quot;password '#{pw_in}' too long&quot; if pw_in.length &gt;= MAX_PASSWD_LENGTH
+
+          pw_validate = hl.ask(&quot;Re-type new password: &quot;) { |q| q.echo = '*' }
+          raise PasswordError, &quot;They don't match, sorry.&quot; unless pw_in == pw_validate
+
+          digest_file.add_or_update(options.username, options.realm, pw_in)
         end
+
+        digest_file.save!
+
+      rescue HTAuth::FileAccessError =&gt; fae
+        msg = &quot;Could not open password file #{options.passwdfile} &quot;
+        $stderr.puts &quot;#{msg}: #{fae.message}&quot;
+        $stderr.puts fae.backtrace.join(&quot;\n&quot;)
+        exit 1
+      rescue HTAuth::PasswordError =&gt; pe
+        $stderr.puts &quot;#{pe.message}&quot;
+        exit 1
+      rescue HTAuth::DigestFileError =&gt; fe
+        $stderr.puts &quot;#{fe.message}&quot;
+        exit 1
+      rescue SignalException =&gt; se
+        $stderr.puts
+        $stderr.puts &quot;Interrupted&quot;
+        exit 1
+      end
+      exit 0
     end
+  end
 end</diff>
      <filename>lib/htauth/digest.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,72 +2,72 @@ require 'htauth/entry'
 require 'digest/md5'
 
 module HTAuth
-    class InvalidDigestEntry &lt; StandardError ; end
+  class InvalidDigestEntry &lt; StandardError ; end
 
-    # A single record in an htdigest file.  
-    class DigestEntry
+  # A single record in an htdigest file.  
+  class DigestEntry
 
-        attr_accessor :user
-        attr_accessor :realm
-        attr_accessor :digest
+    attr_accessor :user
+    attr_accessor :realm
+    attr_accessor :digest
 
-        class &lt;&lt; self
-            def from_line(line)
-                parts = is_entry!(line)
-                d = DigestEntry.new(parts[0], parts[1])
-                d.digest = parts[2]
-                return d
-            end
+    class &lt;&lt; self
+      def from_line(line)
+        parts = is_entry!(line)
+        d = DigestEntry.new(parts[0], parts[1])
+        d.digest = parts[2]
+        return d
+      end
 
-            # test if a line is an entry, raise InvalidDigestEntry if it is not.
-            # an entry must be composed of 3 parts, username:realm:md5sum
-            # where username, and realm do not contain the ':' character 
-            # and the md5sum must be 32 characters long.
-            def is_entry!(line)
-                raise InvalidDigestEntry, &quot;line commented out&quot; if line =~ /\A#/
-                parts = line.strip.split(&quot;:&quot;)
-                raise InvalidDigestEntry, &quot;line must be of the format username:realm:md5checksum&quot; if parts.size != 3
-                raise InvalidDigestEntry, &quot;md5 checksum is not 32 characters long&quot; if parts.last.size  != 32
-                raise InvalidDigestEntry, &quot;md5 checksum has invalid characters&quot; if parts.last !~ /\A[[:xdigit:]]{32}\Z/
-                return parts
-            end
+      # test if a line is an entry, raise InvalidDigestEntry if it is not.
+      # an entry must be composed of 3 parts, username:realm:md5sum
+      # where username, and realm do not contain the ':' character 
+      # and the md5sum must be 32 characters long.
+      def is_entry!(line)
+        raise InvalidDigestEntry, &quot;line commented out&quot; if line =~ /\A#/
+          parts = line.strip.split(&quot;:&quot;)
+        raise InvalidDigestEntry, &quot;line must be of the format username:realm:md5checksum&quot; if parts.size != 3
+        raise InvalidDigestEntry, &quot;md5 checksum is not 32 characters long&quot; if parts.last.size  != 32
+        raise InvalidDigestEntry, &quot;md5 checksum has invalid characters&quot; if parts.last !~ /\A[[:xdigit:]]{32}\Z/
+          return parts
+      end
 
-            # test if a line is an entry and return true or false
-            def is_entry?(line)
-                begin
-                    is_entry!(line)
-                    return true
-                rescue InvalidDigestEntry
-                    return false
-                end
-            end
+      # test if a line is an entry and return true or false
+      def is_entry?(line)
+        begin
+          is_entry!(line)
+          return true
+        rescue InvalidDigestEntry
+          return false
         end
+      end
+    end
 
-        def initialize(user, realm, password = &quot;&quot;)
-            @user     = user
-            @realm    = realm
-            @digest   = calc_digest(password)
-        end
+    def initialize(user, realm, password = &quot;&quot;)
+      @user     = user
+      @realm    = realm
+      @digest   = calc_digest(password)
+    end
 
-        def password=(new_password)
-            @digest = calc_digest(new_password)
-        end
+    def password=(new_password)
+      @digest = calc_digest(new_password)
+    end
 
-        def calc_digest(password)
-            ::Digest::MD5.hexdigest(&quot;#{user}:#{realm}:#{password}&quot;)
-        end
+    def calc_digest(password)
+      ::Digest::MD5.hexdigest(&quot;#{user}:#{realm}:#{password}&quot;)
+    end
 
-        def authenticated?(check_password)
-            hd = ::Digest::MD5.hexdigest(&quot;#{user}:#{realm}:#{check_password}&quot;)
-            return hd == digest
-        end
+    def authenticated?(check_password)
+      hd = ::Digest::MD5.hexdigest(&quot;#{user}:#{realm}:#{check_password}&quot;)
+      return hd == digest
+    end
 
-        def key
+    def key
             &quot;#{user}:#{realm}&quot;
-        end
+    end
 
-        def to_s
+    def to_s
             &quot;#{user}:#{realm}:#{digest}&quot;
-        end
     end
+  end
 end</diff>
      <filename>lib/htauth/digest_entry.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,81 +1,80 @@
 require 'stringio'
-require 'tempfile'
 
 require 'htauth/file'
 require 'htauth/digest_entry'
 
 module HTAuth
-    class DigestFileError &lt; StandardError ; end
-    class DigestFile &lt; HTAuth::File
+  class DigestFileError &lt; StandardError ; end
+  class DigestFile &lt; HTAuth::File
 
-        ENTRY_KLASS = HTAuth::DigestEntry
+    ENTRY_KLASS = HTAuth::DigestEntry
 
-        # does the entry the the specified username and realm exist in the file
-        def has_entry?(username, realm)
-            test_entry = DigestEntry.new(username, realm)
-            @entries.has_key?(test_entry.key)
-        end
+    # does the entry the the specified username and realm exist in the file
+    def has_entry?(username, realm)
+      test_entry = DigestEntry.new(username, realm)
+      @entries.has_key?(test_entry.key)
+    end
+
+    # remove an entry from the file
+    def delete(username, realm)
+      if has_entry?(username, realm) then
+        ir = internal_record(username, realm)
+        line_index = ir['line_index']
+        @entries.delete(ir['entry'].key)
+        @lines[line_index] = nil
+        dirty!
+      end
+      nil
+    end
 
-        # remove an entry from the file
-        def delete(username, realm)
-            if has_entry?(username, realm) then
-                ir = internal_record(username, realm)
-                line_index = ir['line_index']
-                @entries.delete(ir['entry'].key)
-                @lines[line_index] = nil
-                dirty!
-            end
-            nil
-        end
+    # add or update an entry as appropriate
+    def add_or_update(username, realm, password)
+      if has_entry?(username, realm) then
+        update(username, realm, password)
+      else
+        add(username, realm, password)
+      end
+    end
 
-        # add or update an entry as appropriate
-        def add_or_update(username, realm, password)
-            if has_entry?(username, realm) then
-                update(username, realm, password)
-            else
-                add(username, realm, password)
-            end
-        end
+    # add an new record.  raises an error if the entry exists.
+    def add(username, realm, password)
+      raise DigestFileError, &quot;Unable to add already existing user #{username} in realm #{realm}&quot; if has_entry?(username, realm)
 
-        # add an new record.  raises an error if the entry exists.
-        def add(username, realm, password)
-            raise DigestFileError, &quot;Unable to add already existing user #{username} in realm #{realm}&quot; if has_entry?(username, realm)
-            
-            new_entry = DigestEntry.new(username, realm, password)
-            new_index = @lines.size
-            @lines &lt;&lt; new_entry.to_s
-            @entries[new_entry.key] = { 'entry' =&gt; new_entry, 'line_index' =&gt; new_index }
-            dirty!
-            return nil
-        end
+      new_entry = DigestEntry.new(username, realm, password)
+      new_index = @lines.size
+      @lines &lt;&lt; new_entry.to_s
+      @entries[new_entry.key] = { 'entry' =&gt; new_entry, 'line_index' =&gt; new_index }
+      dirty!
+      return nil
+    end
 
-        # update an already existing entry with a new password.  raises an error if the entry does not exist
-        def update(username, realm, password)
-            raise DigestFileError, &quot;Unable to update non-existent user #{username} in realm #{realm}&quot; unless has_entry?(username, realm)
-            ir = internal_record(username, realm)
-            ir['entry'].password = password
-            @lines[ir['line_index']] = ir['entry'].to_s
-            dirty!
-            return nil
-        end
+    # update an already existing entry with a new password.  raises an error if the entry does not exist
+    def update(username, realm, password)
+      raise DigestFileError, &quot;Unable to update non-existent user #{username} in realm #{realm}&quot; unless has_entry?(username, realm)
+      ir = internal_record(username, realm)
+      ir['entry'].password = password
+      @lines[ir['line_index']] = ir['entry'].to_s
+      dirty!
+      return nil
+    end
 
-        # fetches a copy of an entry from the file.  Updateing the entry returned from fetch will NOT
-        # propogate back to the file.
-        def fetch(username, realm)
-            return nil unless has_entry?(username, realm)
-            ir = internal_record(username, realm)
-            return ir['entry'].dup
-        end
+    # fetches a copy of an entry from the file.  Updateing the entry returned from fetch will NOT
+    # propogate back to the file.
+    def fetch(username, realm)
+      return nil unless has_entry?(username, realm)
+      ir = internal_record(username, realm)
+      return ir['entry'].dup
+    end
 
-        def entry_klass
-            ENTRY_KLASS
-        end
+    def entry_klass
+      ENTRY_KLASS
+    end
 
-        private
+    private
 
-        def internal_record(username, realm)
-            e = DigestEntry.new(username, realm)
-            @entries[e.key]
-        end
+    def internal_record(username, realm)
+      e = DigestEntry.new(username, realm)
+      @entries[e.key]
     end
+  end
 end</diff>
      <filename>lib/htauth/digest_file.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,9 +1,9 @@
 module HTAuth
 
-    # base class from which all entries are derived
-    class Entry
-        def dup
-            self.class.from_line(self.to_s)
-        end
+  # base class from which all entries are derived
+  class Entry
+    def dup
+      self.class.from_line(self.to_s)
     end
+  end
 end</diff>
      <filename>lib/htauth/entry.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,102 +2,102 @@ require 'stringio'
 require 'htauth'
 
 module HTAuth
-    class FileAccessError &lt; StandardError ; end
-    class File
-        ALTER  = &quot;alter&quot;
-        CREATE = &quot;create&quot;
-        STDOUT_FLAG = &quot;-&quot;
+  class FileAccessError &lt; StandardError ; end
+  class File
+    ALTER  = &quot;alter&quot;
+    CREATE = &quot;create&quot;
+    STDOUT_FLAG = &quot;-&quot;
 
-        attr_reader :filename
-        attr_reader :file
+    attr_reader :filename
+    attr_reader :file
 
-        class &lt;&lt; self
-            # open a file yielding the the file object for use.  The file is saved when 
-            # the block exists, if the file has had alterations made.
-            def open(filename, mode = ALTER) 
-                f = self.new(filename, mode)
-                if block_given?
-                    begin
-                        yield f
-                    ensure
-                        f.save! if f and f.dirty?
-                    end
-                end
-                return f
-            end
+    class &lt;&lt; self
+      # open a file yielding the the file object for use.  The file is saved when 
+      # the block exists, if the file has had alterations made.
+      def open(filename, mode = ALTER) 
+        f = self.new(filename, mode)
+        if block_given?
+          begin
+            yield f
+          ensure
+            f.save! if f and f.dirty?
+          end
         end
+        return f
+      end
+    end
 
-        # Create or Alter a password file.
-        #
-        # Altering a non-existent file is an error.  Creating an existing file results in
-        # a truncation and overwrite of the existing file.
-        def initialize(filename, mode = ALTER)
-            @filename   = filename
-            @mode       = mode
-            @dirty      = false
-            
-            raise FileAccessError, &quot;Invalid mode #{mode}&quot; unless [ ALTER, CREATE ].include?(mode)
+    # Create or Alter a password file.
+    #
+    # Altering a non-existent file is an error.  Creating an existing file results in
+    # a truncation and overwrite of the existing file.
+    def initialize(filename, mode = ALTER)
+      @filename   = filename
+      @mode       = mode
+      @dirty      = false
 
-            if (filename != STDOUT_FLAG) and (mode == ALTER) and (not ::File.exist?(filename)) then
-                raise FileAccessError, &quot;Could not open passwd file #{filename} for reading.&quot; 
-            end
+      raise FileAccessError, &quot;Invalid mode #{mode}&quot; unless [ ALTER, CREATE ].include?(mode)
 
-            begin
-                @entries  = {}
-                @lines    = []
-                load_entries if (@mode == ALTER) and (filename != STDOUT_FLAG)
-            rescue =&gt; e
-                raise FileAccessError, e.message
-            end
-        end
+      if (filename != STDOUT_FLAG) and (mode == ALTER) and (not ::File.exist?(filename)) then
+        raise FileAccessError, &quot;Could not open passwd file #{filename} for reading.&quot; 
+      end
 
-        # return whether or not an alteration to the file has happened
-        def dirty?
-            @dirty
-        end
+      begin
+        @entries  = {}
+        @lines    = []
+        load_entries if (@mode == ALTER) and (filename != STDOUT_FLAG)
+      rescue =&gt; e
+        raise FileAccessError, e.message
+      end
+    end
 
-        # mark the file as dirty
-        def dirty!
-            @dirty = true
-        end
+    # return whether or not an alteration to the file has happened
+    def dirty?
+      @dirty
+    end
 
-        # update the original file with the new contents
-        def save!
-            begin
-                case filename
-                when STDOUT_FLAG
-                    $stdout.write(contents)
-                else
-                    ::File.open(@filename,&quot;w&quot;) do |f|
-                        f.write(contents)
-                    end
-                end
-                @dirty = false
-            rescue =&gt; e
-                raise FileAccessError, &quot;Error saving file #{@filename} : #{e.message}&quot;
-            end
-        end
+    # mark the file as dirty
+    def dirty!
+      @dirty = true
+    end
 
-        # return what should be the contents of the file
-        def contents
-            c = StringIO.new
-            @lines.each do |l| 
-                c.puts l if l
-            end
-            c.string
+    # update the original file with the new contents
+    def save!
+      begin
+        case filename
+        when STDOUT_FLAG
+          $stdout.write(contents)
+        else
+          ::File.open(@filename,&quot;w&quot;) do |f|
+            f.write(contents)
+          end
         end
+        @dirty = false
+      rescue =&gt; e
+        raise FileAccessError, &quot;Error saving file #{@filename} : #{e.message}&quot;
+      end
+    end
+
+    # return what should be the contents of the file
+    def contents
+      c = StringIO.new
+      @lines.each do |l| 
+        c.puts l if l
+      end
+      c.string
+    end
 
-        # load up entries, keep items in the same order and do not trim out any 
-        # items in the file, like commented out lines or empty space
-        def load_entries
-            @lines   = IO.readlines(@filename)
-            @lines.each_with_index do |line,idx|
-                if entry_klass.is_entry?(line) then
-                    entry = entry_klass.from_line(line)
-                    v     = { 'entry' =&gt; entry, 'line_index' =&gt; idx }
-                    @entries[entry.key] = v
-                end
-            end
+    # load up entries, keep items in the same order and do not trim out any 
+    # items in the file, like commented out lines or empty space
+    def load_entries
+      @lines   = IO.readlines(@filename)
+      @lines.each_with_index do |line,idx|
+        if entry_klass.is_entry?(line) then
+          entry = entry_klass.from_line(line)
+          v     = { 'entry' =&gt; entry, 'line_index' =&gt; idx }
+          @entries[entry.key] = v
         end
+      end
     end
+  end
 end</diff>
      <filename>lib/htauth/file.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,80 +3,80 @@ require 'digest/md5'
 
 module HTAuth
 
-    # an implementation of the MD5 based encoding algorithm 
-    # as used in the apache htpasswd -m option
-    class Md5 &lt; Algorithm
-            
-        DIGEST_LENGTH = 16
-
-        def initialize(params = {})
-            @salt = params['salt'] || params[:salt] || gen_salt
-        end
+  # an implementation of the MD5 based encoding algorithm 
+  # as used in the apache htpasswd -m option
+  class Md5 &lt; Algorithm
 
-        def prefix
-            &quot;$apr1$&quot;
-        end
+    DIGEST_LENGTH = 16
+
+    def initialize(params = {})
+      @salt = params['salt'] || params[:salt] || gen_salt
+    end
 
-        # this algorigthm pulled straight from apr_md5_encode() and converted to ruby syntax
-        def encode(password)
-            primary = ::Digest::MD5.new
-            primary &lt;&lt; password
-            primary &lt;&lt; prefix
-            primary &lt;&lt; @salt
-
-            md5_t = ::Digest::MD5.digest(&quot;#{password}#{@salt}#{password}&quot;)
-
-            l = password.length
-            while l &gt; 0 do
-                slice_size = ( l &gt; DIGEST_LENGTH ) ? DIGEST_LENGTH : l
-                primary &lt;&lt; md5_t[0, slice_size]
-                l -= DIGEST_LENGTH
-            end
-
-            # weirdness
-            l = password.length
-            while l != 0
-                case (l &amp; 1)
-                when 1
-                    primary &lt;&lt; 0.chr
-                when 0
-                    primary &lt;&lt; password[0,1]
-                end
-                l &gt;&gt;= 1
-            end
-
-            pd = primary.digest
-            
-            encoded_password = &quot;#{prefix}#{@salt}$&quot;
-
-            # apr_md5_encode has this comment about a 60Mhz Pentium above this loop.
-            1000.times do |x|
-                ctx = ::Digest::MD5.new
-                ctx &lt;&lt; (( ( x &amp; 1 ) == 1 ) ? password : pd[0,DIGEST_LENGTH])
-                (ctx &lt;&lt; @salt) unless ( x % 3 ) == 0
-                (ctx &lt;&lt; password) unless ( x % 7 ) == 0
-                ctx &lt;&lt; (( ( x &amp; 1 ) == 0 ) ? password : pd[0,DIGEST_LENGTH])
-                pd = ctx.digest
-            end
-
-
-            l = (pd[ 0]&lt;&lt;16) | (pd[ 6]&lt;&lt;8) | pd[12]
-            encoded_password &lt;&lt; to_64(l, 4)
-
-            l = (pd[ 1]&lt;&lt;16) | (pd[ 7]&lt;&lt;8) | pd[13]
-            encoded_password &lt;&lt; to_64(l, 4)
-
-            l = (pd[ 2]&lt;&lt;16) | (pd[ 8]&lt;&lt;8) | pd[14]
-            encoded_password &lt;&lt; to_64(l, 4)
-
-            l = (pd[ 3]&lt;&lt;16) | (pd[ 9]&lt;&lt;8) | pd[15]
-            encoded_password &lt;&lt; to_64(l, 4)
-
-            l = (pd[ 4]&lt;&lt;16) | (pd[10]&lt;&lt;8) | pd[ 5]
-            encoded_password &lt;&lt; to_64(l, 4)
-            encoded_password &lt;&lt; to_64(pd[11],2)
-
-            return encoded_password
+    def prefix
+      &quot;$apr1$&quot;
+    end
+
+    # this algorigthm pulled straight from apr_md5_encode() and converted to ruby syntax
+    def encode(password)
+      primary = ::Digest::MD5.new
+      primary &lt;&lt; password
+      primary &lt;&lt; prefix
+      primary &lt;&lt; @salt
+
+      md5_t = ::Digest::MD5.digest(&quot;#{password}#{@salt}#{password}&quot;)
+
+      l = password.length
+      while l &gt; 0 do
+        slice_size = ( l &gt; DIGEST_LENGTH ) ? DIGEST_LENGTH : l
+        primary &lt;&lt; md5_t[0, slice_size]
+        l -= DIGEST_LENGTH
+      end
+
+      # weirdness
+      l = password.length
+      while l != 0
+        case (l &amp; 1)
+        when 1
+          primary &lt;&lt; 0.chr
+        when 0
+          primary &lt;&lt; password[0,1]
         end
+        l &gt;&gt;= 1
+      end
+
+      pd = primary.digest
+
+      encoded_password = &quot;#{prefix}#{@salt}$&quot;
+
+      # apr_md5_encode has this comment about a 60Mhz Pentium above this loop.
+      1000.times do |x|
+        ctx = ::Digest::MD5.new
+        ctx &lt;&lt; (( ( x &amp; 1 ) == 1 ) ? password : pd[0,DIGEST_LENGTH])
+        (ctx &lt;&lt; @salt) unless ( x % 3 ) == 0
+        (ctx &lt;&lt; password) unless ( x % 7 ) == 0
+        ctx &lt;&lt; (( ( x &amp; 1 ) == 0 ) ? password : pd[0,DIGEST_LENGTH])
+        pd = ctx.digest
+      end
+
+
+      l = (pd[ 0]&lt;&lt;16) | (pd[ 6]&lt;&lt;8) | pd[12]
+      encoded_password &lt;&lt; to_64(l, 4)
+
+      l = (pd[ 1]&lt;&lt;16) | (pd[ 7]&lt;&lt;8) | pd[13]
+      encoded_password &lt;&lt; to_64(l, 4)
+
+      l = (pd[ 2]&lt;&lt;16) | (pd[ 8]&lt;&lt;8) | pd[14]
+      encoded_password &lt;&lt; to_64(l, 4)
+
+      l = (pd[ 3]&lt;&lt;16) | (pd[ 9]&lt;&lt;8) | pd[15]
+      encoded_password &lt;&lt; to_64(l, 4)
+
+      l = (pd[ 4]&lt;&lt;16) | (pd[10]&lt;&lt;8) | pd[ 5]
+      encoded_password &lt;&lt; to_64(l, 4)
+      encoded_password &lt;&lt; to_64(pd[11],2)
+
+      return encoded_password
     end
+  end
 end</diff>
      <filename>lib/htauth/md5.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,173 +4,172 @@ require 'htauth/passwd_file'
 require 'ostruct'
 require 'optparse'
 
-require 'rubygems'
 require 'highline'
 
 module HTAuth
-    class Passwd
+  class Passwd
 
-        MAX_PASSWD_LENGTH = 255
+    MAX_PASSWD_LENGTH = 255
 
-        attr_accessor :passwd_file
+    attr_accessor :passwd_file
 
-        def initialize
-            @passwd_file = nil
-        end
+    def initialize
+      @passwd_file = nil
+    end
 
-        def options
-            if @options.nil? then
-                @options                = ::OpenStruct.new
-                @options.batch_mode     = false
-                @options.file_mode      = File::ALTER
-                @options.passwdfile     = nil
-                @options.algorithm      = Algorithm::EXISTING
-                @options.send_to_stdout = false
-                @options.show_version   = false
-                @options.show_help      = false
-                @options.username       = nil
-                @options.delete_entry   = false
-                @options.password       = &quot;&quot;
-            end
-            @options
-        end
+    def options
+      if @options.nil? then
+        @options                = ::OpenStruct.new
+        @options.batch_mode     = false
+        @options.file_mode      = File::ALTER
+        @options.passwdfile     = nil
+        @options.algorithm      = Algorithm::EXISTING
+        @options.send_to_stdout = false
+        @options.show_version   = false
+        @options.show_help      = false
+        @options.username       = nil
+        @options.delete_entry   = false
+        @options.password       = &quot;&quot;
+      end
+      @options
+    end
 
-        def option_parser
-            if not @option_parser then
-                @option_parser = OptionParser.new do |op|
-                    op.banner = &lt;&lt;EOB
+    def option_parser
+      if not @option_parser then
+        @option_parser = OptionParser.new do |op|
+          op.banner = &lt;&lt;EOB
 Usage: 
-    #{op.program_name} [-cmdpsD] passwordfile username
-    #{op.program_name} -b[cmdpsD] passwordfile username password
+          #{op.program_name} [-cmdpsD] passwordfile username
+          #{op.program_name} -b[cmdpsD] passwordfile username password
 
-    #{op.program_name} -n[mdps] username
-    #{op.program_name} -nb[mdps] username password
+          #{op.program_name} -n[mdps] username
+          #{op.program_name} -nb[mdps] username password
 EOB
 
-                    op.separator &quot;&quot;
-
-                    op.on(&quot;-b&quot;, &quot;--batch&quot;, &quot;Batch mode, get the password from the command line, rather than prompt&quot;) do |b|
-                        options.batch_mode = b
-                    end
-
-                    op.on(&quot;-c&quot;, &quot;--create&quot;, &quot;Create a new file; this overwrites an existing file.&quot;) do |c|
-                        options.file_mode = HTAuth::File::CREATE
-                    end
-                    
-                    op.on(&quot;-d&quot;, &quot;--crypt&quot;, &quot;Force CRYPT encryption of the password (default).&quot;) do |c|
-                        options.algorithm = &quot;crypt&quot;
-                    end
-
-                    op.on(&quot;-D&quot;, &quot;--delete&quot;, &quot;Delete the specified user.&quot;) do |d|
-                        options.delete_entry = d
-                    end
-
-                    op.on(&quot;-h&quot;, &quot;--help&quot;, &quot;Display this help.&quot;) do |h|
-                        options.show_help = h
-                    end
-
-                    op.on(&quot;-m&quot;, &quot;--md5&quot;, &quot;Force MD5 encryption of the password (default on Windows).&quot;) do |m|
-                        options.algorithm = &quot;md5&quot;
-                    end
-
-                    op.on(&quot;-n&quot;, &quot;--stdout&quot;, &quot;Do not update the file; Display the results on stdout instead.&quot;) do |n|
-                        options.send_to_stdout = true
-                        options.passwdfile     = HTAuth::File::STDOUT_FLAG
-                    end
-                    
-                    op.on(&quot;-p&quot;, &quot;--plaintext&quot;, &quot;Do not encrypt the password (plaintext).&quot;) do |p|
-                        options.algorithm = &quot;plaintext&quot;
-                    end
-
-                    op.on(&quot;-s&quot;, &quot;--sha1&quot;, &quot;Force SHA encryption of the password.&quot;) do |s|
-                        options.algorithm = &quot;sha1&quot;
-                    end
-
-                    op.on(&quot;-v&quot;, &quot;--version&quot;, &quot;Show version info.&quot;) do |v|
-                        options.show_version = v
-                    end
-               end
-            end
-            @option_parser
-        end
+          op.separator &quot;&quot;
 
-        def show_help
-            $stdout.puts option_parser
-            exit 1
-        end
+          op.on(&quot;-b&quot;, &quot;--batch&quot;, &quot;Batch mode, get the password from the command line, rather than prompt&quot;) do |b|
+            options.batch_mode = b
+          end
 
-        def show_version
-            $stdout.puts &quot;#{option_parser.program_name}: version #{HTAuth::VERSION}&quot;
-            exit 1
-        end
+          op.on(&quot;-c&quot;, &quot;--create&quot;, &quot;Create a new file; this overwrites an existing file.&quot;) do |c|
+            options.file_mode = HTAuth::File::CREATE
+          end
+
+          op.on(&quot;-d&quot;, &quot;--crypt&quot;, &quot;Force CRYPT encryption of the password (default).&quot;) do |c|
+            options.algorithm = &quot;crypt&quot;
+          end
+
+          op.on(&quot;-D&quot;, &quot;--delete&quot;, &quot;Delete the specified user.&quot;) do |d|
+            options.delete_entry = d
+          end
+
+          op.on(&quot;-h&quot;, &quot;--help&quot;, &quot;Display this help.&quot;) do |h|
+            options.show_help = h
+          end
+
+          op.on(&quot;-m&quot;, &quot;--md5&quot;, &quot;Force MD5 encryption of the password (default on Windows).&quot;) do |m|
+            options.algorithm = &quot;md5&quot;
+          end
+
+          op.on(&quot;-n&quot;, &quot;--stdout&quot;, &quot;Do not update the file; Display the results on stdout instead.&quot;) do |n|
+            options.send_to_stdout = true
+            options.passwdfile     = HTAuth::File::STDOUT_FLAG
+          end
+
+          op.on(&quot;-p&quot;, &quot;--plaintext&quot;, &quot;Do not encrypt the password (plaintext).&quot;) do |p|
+            options.algorithm = &quot;plaintext&quot;
+          end
+
+          op.on(&quot;-s&quot;, &quot;--sha1&quot;, &quot;Force SHA encryption of the password.&quot;) do |s|
+            options.algorithm = &quot;sha1&quot;
+          end
 
-        def parse_options(argv)
-            begin
-                option_parser.parse!(argv)
-                show_version if options.show_version
-                show_help if options.show_help 
-
-                raise ::OptionParser::ParseError, &quot;Unable to send to stdout AND create a new file&quot; if options.send_to_stdout and (options.file_mode == File::CREATE)
-                raise ::OptionParser::ParseError, &quot;a username is needed&quot; if options.send_to_stdout and argv.size &lt; 1
-                raise ::OptionParser::ParseError, &quot;a username and password are needed&quot; if options.send_to_stdout and options.batch_mode  and ( argv.size &lt; 2 ) 
-                raise ::OptionParser::ParseError, &quot;a passwordfile, username and password are needed &quot; if not options.send_to_stdout and options.batch_mode and ( argv.size &lt; 3 )
-                raise ::OptionParser::ParseError, &quot;a passwordfile and username are needed&quot; if argv.size &lt; 2
-
-                options.passwdfile = argv.shift unless options.send_to_stdout
-                options.username   = argv.shift
-                options.password   = argv.shift if options.batch_mode
-
-            rescue ::OptionParser::ParseError =&gt; pe
-                $stderr.puts &quot;ERROR: #{option_parser.program_name} - #{pe}&quot;
-                show_help
-                exit 1
-            end
+          op.on(&quot;-v&quot;, &quot;--version&quot;, &quot;Show version info.&quot;) do |v|
+            options.show_version = v
+          end
         end
+      end
+      @option_parser
+    end
+
+    def show_help
+      $stdout.puts option_parser
+      exit 1
+    end
+
+    def show_version
+      $stdout.puts &quot;#{option_parser.program_name}: version #{HTAuth::VERSION}&quot;
+      exit 1
+    end
+
+    def parse_options(argv)
+      begin
+        option_parser.parse!(argv)
+        show_version if options.show_version
+        show_help if options.show_help 
+
+        raise ::OptionParser::ParseError, &quot;Unable to send to stdout AND create a new file&quot; if options.send_to_stdout and (options.file_mode == File::CREATE)
+        raise ::OptionParser::ParseError, &quot;a username is needed&quot; if options.send_to_stdout and argv.size &lt; 1
+        raise ::OptionParser::ParseError, &quot;a username and password are needed&quot; if options.send_to_stdout and options.batch_mode  and ( argv.size &lt; 2 ) 
+        raise ::OptionParser::ParseError, &quot;a passwordfile, username and password are needed &quot; if not options.send_to_stdout and options.batch_mode and ( argv.size &lt; 3 )
+        raise ::OptionParser::ParseError, &quot;a passwordfile and username are needed&quot; if argv.size &lt; 2
+
+        options.passwdfile = argv.shift unless options.send_to_stdout
+        options.username   = argv.shift
+        options.password   = argv.shift if options.batch_mode
+
+      rescue ::OptionParser::ParseError =&gt; pe
+        $stderr.puts &quot;ERROR: #{option_parser.program_name} - #{pe}&quot;
+        show_help
+        exit 1
+      end
+    end
 
-        def run(argv)
-            begin
-                parse_options(argv)
-                passwd_file = PasswdFile.new(options.passwdfile, options.file_mode)
-
-                if options.delete_entry then
-                    passwd_file.delete(options.username)
-                else
-                    unless options.batch_mode 
-                        # initialize here so that if $stdin is overwritten it gest picked up
-                        hl = ::HighLine.new
-
-                        action = passwd_file.has_entry?(options.username) ? &quot;Changing&quot; : &quot;Adding&quot;
-
-                        $stdout.puts &quot;#{action} password for #{options.username}.&quot;
-
-                        pw_in       = hl.ask(&quot;        New password: &quot;) { |q| q.echo = '*' } 
-                        raise PasswordError, &quot;password '#{pw_in}' too long&quot; if pw_in.length &gt;= MAX_PASSWD_LENGTH
-                        
-                        pw_validate = hl.ask(&quot;Re-type new password: &quot;) { |q| q.echo = '*' }
-                        raise PasswordError, &quot;They don't match, sorry.&quot; unless pw_in == pw_validate
-                        options.password = pw_in
-                    end
-                    passwd_file.add_or_update(options.username, options.password, options.algorithm)
-                end
-
-                passwd_file.save! 
-
-            rescue HTAuth::FileAccessError =&gt; fae
-                msg = &quot;Password file failure (#{options.passwdfile}) &quot;
-                $stderr.puts &quot;#{msg}: #{fae.message}&quot;
-                exit 1
-            rescue HTAuth::PasswordError =&gt; pe
-                $stderr.puts &quot;#{pe.message}&quot;
-                exit 1
-            rescue HTAuth::PasswdFileError =&gt; fe
-                $stderr.puts &quot;#{fe.message}&quot;
-                exit 1
-            rescue SignalException =&gt; se
-                $stderr.puts
-                $stderr.puts &quot;Interrupted&quot;
-                exit 1
-            end
-            exit 0
+    def run(argv, env)
+      begin
+        parse_options(argv)
+        passwd_file = PasswdFile.new(options.passwdfile, options.file_mode)
+
+        if options.delete_entry then
+          passwd_file.delete(options.username)
+        else
+          unless options.batch_mode 
+            # initialize here so that if $stdin is overwritten it gest picked up
+            hl = ::HighLine.new
+
+            action = passwd_file.has_entry?(options.username) ? &quot;Changing&quot; : &quot;Adding&quot;
+
+            $stdout.puts &quot;#{action} password for #{options.username}.&quot;
+
+            pw_in       = hl.ask(&quot;        New password: &quot;) { |q| q.echo = '*' } 
+            raise PasswordError, &quot;password '#{pw_in}' too long&quot; if pw_in.length &gt;= MAX_PASSWD_LENGTH
+
+            pw_validate = hl.ask(&quot;Re-type new password: &quot;) { |q| q.echo = '*' }
+            raise PasswordError, &quot;They don't match, sorry.&quot; unless pw_in == pw_validate
+            options.password = pw_in
+          end
+          passwd_file.add_or_update(options.username, options.password, options.algorithm)
         end
+
+        passwd_file.save! 
+
+      rescue HTAuth::FileAccessError =&gt; fae
+        msg = &quot;Password file failure (#{options.passwdfile}) &quot;
+        $stderr.puts &quot;#{msg}: #{fae.message}&quot;
+        exit 1
+      rescue HTAuth::PasswordError =&gt; pe
+        $stderr.puts &quot;#{pe.message}&quot;
+        exit 1
+      rescue HTAuth::PasswdFileError =&gt; fe
+        $stderr.puts &quot;#{fe.message}&quot;
+        exit 1
+      rescue SignalException =&gt; se
+        $stderr.puts
+        $stderr.puts &quot;Interrupted&quot;
+        exit 1
+      end
+      exit 0
     end
+  end
 end</diff>
      <filename>lib/htauth/passwd.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,96 +2,96 @@ require 'htauth/entry'
 require 'htauth/algorithm'
 
 module HTAuth
-    class InvalidPasswdEntry &lt; StandardError ; end
+  class InvalidPasswdEntry &lt; StandardError ; end
 
-    # A single record in an htdigest file.  
-    class PasswdEntry &lt; Entry
+  # A single record in an htdigest file.  
+  class PasswdEntry &lt; Entry
 
-        attr_accessor :user
-        attr_accessor :digest
-        attr_reader   :algorithm
+    attr_accessor :user
+    attr_accessor :digest
+    attr_reader   :algorithm
 
-        class &lt;&lt; self
-            def from_line(line)
-                parts = is_entry!(line)
-                d = PasswdEntry.new(parts[0])
-                d.digest = parts[1]
-                d.algorithm = Algorithm.algorithms_from_field(parts[1])
-                return d
-            end
+    class &lt;&lt; self
+      def from_line(line)
+        parts = is_entry!(line)
+        d = PasswdEntry.new(parts[0])
+        d.digest = parts[1]
+        d.algorithm = Algorithm.algorithms_from_field(parts[1])
+        return d
+      end
 
-            # test if a line is an entry, raise InvalidPasswdEntry if it is not.
-            # an entry must be composed of 2 parts, username:encrypted_password
-            # where username, and password do not contain the ':' character 
-            def is_entry!(line)
-                raise InvalidPasswdEntry, &quot;line commented out&quot; if line =~ /\A#/
-                parts = line.strip.split(&quot;:&quot;)
-                raise InvalidPasswdEntry, &quot;line must be of the format username:pssword&quot; if parts.size != 2
-                return parts
-            end
+      # test if a line is an entry, raise InvalidPasswdEntry if it is not.
+      # an entry must be composed of 2 parts, username:encrypted_password
+      # where username, and password do not contain the ':' character 
+      def is_entry!(line)
+        raise InvalidPasswdEntry, &quot;line commented out&quot; if line =~ /\A#/
+          parts = line.strip.split(&quot;:&quot;)
+        raise InvalidPasswdEntry, &quot;line must be of the format username:pssword&quot; if parts.size != 2
+        return parts
+      end
 
-            # test if a line is an entry and return true or false
-            def is_entry?(line)
-                begin
-                    is_entry!(line)
-                    return true
-                rescue InvalidPasswdEntry
-                    return false
-                end
-            end
+      # test if a line is an entry and return true or false
+      def is_entry?(line)
+        begin
+          is_entry!(line)
+          return true
+        rescue InvalidPasswdEntry
+          return false
         end
+      end
+    end
 
-        def initialize(user, password = &quot;&quot;, alg = Algorithm::DEFAULT, alg_params = {} ) 
-            @user      = user
-            alg = Algorithm::DEFAULT if alg == Algorithm::EXISTING 
-            @algorithm = Algorithm.algorithm_from_name(alg, alg_params)
-            @digest    = algorithm.encode(password)
-        end
+    def initialize(user, password = &quot;&quot;, alg = Algorithm::DEFAULT, alg_params = {} ) 
+      @user      = user
+      alg = Algorithm::DEFAULT if alg == Algorithm::EXISTING 
+      @algorithm = Algorithm.algorithm_from_name(alg, alg_params)
+      @digest    = algorithm.encode(password)
+    end
 
-        def algorithm=(alg)
-            if alg.kind_of?(Array) then
-                if alg.size == 1 then
-                    @algorithm = alg.first
-                else
-                    @algorithm = alg
-                end
-            else
-                @algorithm = Algorithm.algorithm_from_name(alg) unless Algorithm::EXISTING == alg
-            end
-            return @algorithm
+    def algorithm=(alg)
+      if alg.kind_of?(Array) then
+        if alg.size == 1 then
+          @algorithm = alg.first
+        else
+          @algorithm = alg
         end
+      else
+        @algorithm = Algorithm.algorithm_from_name(alg) unless Algorithm::EXISTING == alg
+      end
+      return @algorithm
+    end
 
-        def password=(new_password)
-            if algorithm.kind_of?(Array) then
-                @algorithm = Algorithm.algorithm_from_name(&quot;crypt&quot;)
-            end
-            @digest = algorithm.encode(new_password)
-        end
+    def password=(new_password)
+      if algorithm.kind_of?(Array) then
+        @algorithm = Algorithm.algorithm_from_name(&quot;crypt&quot;)
+      end
+      @digest = algorithm.encode(new_password)
+    end
 
-        # check the password and make sure it works, in the case that the algorithm is unknown it
-        # tries all of the ones that it thinks it could be, and marks the algorithm if it matches
-        def authenticated?(check_password)
-            authed = false
-            if algorithm.kind_of?(Array) then
-                algorithm.each do |alg|
-                    if alg.encode(check_password) == digest then
-                        @algorithm = alg
-                        authed = true
-                        break
-                    end
-                end
-            else
-                authed = digest == algorithm.encode(check_password)
-            end
-            return authed
+    # check the password and make sure it works, in the case that the algorithm is unknown it
+    # tries all of the ones that it thinks it could be, and marks the algorithm if it matches
+    def authenticated?(check_password)
+      authed = false
+      if algorithm.kind_of?(Array) then
+        algorithm.each do |alg|
+          if alg.encode(check_password) == digest then
+            @algorithm = alg
+            authed = true
+            break
+          end
         end
+      else
+        authed = digest == algorithm.encode(check_password)
+      end
+      return authed
+    end
 
-        def key
-            return &quot;#{user}&quot;
-        end
+    def key
+      return &quot;#{user}&quot;
+    end
 
-        def to_s
-            &quot;#{user}:#{digest}&quot;
-        end
+    def to_s
+      &quot;#{user}:#{digest}&quot;
     end
+  end
 end</diff>
      <filename>lib/htauth/passwd_entry.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,19 +1,22 @@
 require 'htauth'
 module HTAuth
-    class Version
-        MAJOR   = 1
-        MINOR   = 0
-        BUILD   = 1
+  module Version
+    MAJOR   = 1
+    MINOR   = 0
+    BUILD   = 2
 
-        class &lt;&lt; self
-            def to_a
-                [MAJOR, MINOR, BUILD]
-            end
+    def to_a
+      [MAJOR, MINOR, BUILD]
+    end
 
-            def to_s
-                to_a.join(&quot;.&quot;)
-            end
-        end
+    def to_s
+      to_a.join(&quot;.&quot;)
     end
-    VERSION = Version.to_s
+
+    module_function :to_a
+    module_function :to_s
+
+    STRING = Version.to_s
+  end
+  VERSION = Version.to_s
 end</diff>
      <filename>lib/htauth/version.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,58 +1,38 @@
-#-----------------------------------------------------------------------
-# Announcement tasks
-#   - create a basic email template that can be used to send email to
-#     rubytalk.
-#-----------------------------------------------------------------------
-def changes
-    change_file = File.expand_path(File.join(HTAuth::ROOT_DIR,&quot;CHANGES&quot;))
-    sections    = File.read(change_file).split(/^(?=== )/)
-end
-
-def last_changeset
-    changes[1]
-end
-
-def announcement
-    puts changes.size
-    urls    = &quot;  #{HTAuth::SPEC.homepage}&quot;
-    subject = &quot;#{HTAuth::SPEC.name} #{HTAuth::VERSION} Released&quot;
-    title   = &quot;#{HTAuth::SPEC.name} version #{HTAuth::VERSION} has been released.&quot;
-    body    = &lt;&lt;BODY
-#{HTAuth::SPEC.description.rstrip}
-
-{{ Changelog for Version #{HTAuth::VERSION} }}
-
-#{last_changeset.rstrip}
-
-BODY
-
-    return subject, title, body, urls
-end
+require 'tasks/config'
+#-------------------------------------------------------------------------------
+# announcement methods
+#-------------------------------------------------------------------------------
 
+proj_config = Configuration.for('project')
 namespace :announce do
-    desc &quot;create email for ruby-talk&quot;
-    task :email do
-        subject, title, body, urls = announcement
-
-        File.open(&quot;email.txt&quot;, &quot;w&quot;) do |mail|
-            mail.puts &quot;From: #{HTAuth::SPEC.author} &lt;#{HTAuth::SPEC.email}&gt;&quot;
-            mail.puts &quot;To: ruby-talk@ruby-lang.org&quot;
-            mail.puts &quot;Date: #{Time.now.rfc2822}&quot;
-            mail.puts &quot;Subject: [ANN] #{subject}&quot;
-            mail.puts
-            mail.puts title
-            mail.puts
-            mail.puts urls
-            mail.puts 
-            mail.puts body
-            mail.puts 
-            mail.puts urls
-        end
-        puts &quot;Created the following as email.txt:&quot;
-        puts &quot;-&quot; * 72
-        puts File.read(&quot;email.txt&quot;)
-        puts &quot;-&quot; * 72
-    end
-    
-    CLOBBER &lt;&lt; &quot;email.txt&quot;
+  desc &quot;create email for ruby-talk&quot;
+  task :email do
+    info = Utils.announcement
+
+    File.open(&quot;email.txt&quot;, &quot;w&quot;) do |mail|
+      mail.puts &quot;From: #{proj_config.author} &lt;#{proj_config.email}&gt;&quot;
+      mail.puts &quot;To: ruby-talk@ruby-lang.org&quot;
+      mail.puts &quot;Date: #{Time.now.rfc2822}&quot;
+      mail.puts &quot;Subject: [ANN] #{info[:subject]}&quot;
+      mail.puts
+      mail.puts info[:title]
+      mail.puts
+      mail.puts info[:urls]
+      mail.puts 
+      mail.puts info[:description]
+      mail.puts 
+      mail.puts &quot;{{ Release notes for Version #{HTAuth::VERSION} }}&quot;
+      mail.puts 
+      mail.puts info[:release_notes]
+      mail.puts
+      mail.puts info[:urls]
+    end 
+    puts &quot;Created the following as email.txt:&quot;
+    puts &quot;-&quot; * 72
+    puts File.read(&quot;email.txt&quot;)
+    puts &quot;-&quot; * 72
+  end 
+
+  CLOBBER &lt;&lt; &quot;email.txt&quot;
 end
+</diff>
      <filename>tasks/announce.rake</filename>
    </modified>
    <modified>
      <diff>@@ -1,39 +1,38 @@
-#-----------------------------------------------------------------------
+require 'tasks/config'
+
+#-------------------------------------------------------------------------------
 # Distribution and Packaging
-#-----------------------------------------------------------------------
-namespace :dist do
+#-------------------------------------------------------------------------------
+if pkg_config = Configuration.for_if_exist?(&quot;packaging&quot;) then
+
+  require 'gemspec'
+  require 'rake/gempackagetask'
+  require 'rake/contrib/sshpublisher'
 
-    GEM_SPEC = eval(HTAuth::SPEC.to_ruby)
+  namespace :dist do
 
-    Rake::GemPackageTask.new(GEM_SPEC) do |pkg|
-        pkg.need_tar = HTAuth::SPEC.need_tar
-        pkg.need_zip = HTAuth::SPEC.need_zip
+    Rake::GemPackageTask.new(HTAuth::GEM_SPEC) do |pkg|
+      pkg.need_tar = pkg_config.formats.tgz
+      pkg.need_zip = pkg_config.formats.zip
     end
 
     desc &quot;Install as a gem&quot;
     task :install =&gt; [:clobber, :package] do
-        sh &quot;sudo gem install pkg/#{HTAuth::SPEC.full_name}.gem&quot;
+      sh &quot;sudo gem install pkg/#{HTAuth::GEM_SPEC.full_name}.gem&quot;
     end
 
-    # uninstall the gem and all executables
     desc &quot;Uninstall gem&quot;
     task :uninstall do 
-        sh &quot;sudo gem uninstall #{HTAuth::SPEC.name} -x&quot;
+      sh &quot;sudo gem uninstall -x #{HTAuth::GEM_SPEC.name}&quot;
     end
 
     desc &quot;dump gemspec&quot;
     task :gemspec do
-        puts HTAuth::SPEC.to_ruby
+      puts HTAuth::GEM_SPEC.to_ruby
     end
 
     desc &quot;reinstall gem&quot;
-    task :reinstall =&gt; [:uninstall, :install]
-
-    desc &quot;distribute copiously&quot;
-    task :copious =&gt; [:package] do
-        Rake::SshFilePublisher.new('jeremy@copiousfreetime.org',
-                               '/var/www/vhosts/www.copiousfreetime.org/htdocs/gems/gems',
-                               'pkg',&quot;#{HTAuth::SPEC.full_name}.gem&quot;).upload
-        sh &quot;ssh jeremy@copiousfreetime.org rake -f /var/www/vhosts/www.copiousfreetime.org/htdocs/gems/Rakefile&quot;
-    end 
+    task :reinstall =&gt; [:uninstall, :repackage, :install]
+
+ end
 end</diff>
      <filename>tasks/distribution.rake</filename>
    </modified>
    <modified>
      <diff>@@ -1,25 +1,31 @@
+require 'tasks/config'
+
 #-----------------------------------------------------------------------
 # Documentation
 #-----------------------------------------------------------------------
 
-namespace :doc do
-    
+if rdoc_config = Configuration.for_if_exist?('rdoc') then
+
+  namespace :doc do
+
+    require 'rake/rdoctask'
+
     # generating documentation locally
     Rake::RDocTask.new do |rdoc|
-        rdoc.rdoc_dir   = HTAuth::SPEC.local_rdoc_dir
-        rdoc.options    = HTAuth::SPEC.rdoc_options 
-        rdoc.rdoc_files = HTAuth::SPEC.rdoc_files
-    end
-
-    desc &quot;Deploy the RDoc documentation to #{HTAuth::SPEC.remote_rdoc_location}&quot;
-    task :deploy =&gt; :rerdoc do
-        sh &quot;rsync -zav --delete #{HTAuth::SPEC.local_rdoc_dir}/ #{HTAuth::SPEC.remote_rdoc_location}&quot;
-    end
-
-    if HAVE_HEEL then
-        desc &quot;View the RDoc documentation locally&quot;
-        task :view =&gt; :rdoc do
-            sh &quot;heel --root  #{HTAuth::SPEC.local_rdoc_dir}&quot;
-        end
-    end
+      rdoc.rdoc_dir   = rdoc_config.output_dir
+      rdoc.options    = rdoc_config.options
+      rdoc.rdoc_files = rdoc_config.files
+      rdoc.title      = rdoc_config.title
+      rdoc.main       = rdoc_config.main_page
+    end 
+
+    if rubyforge_config = Configuration.for_if_exist?('rubyforge') then
+      desc &quot;Deploy the RDoc documentation to #{rubyforge_config.rdoc_location}&quot;
+      task :deploy =&gt; :rerdoc do
+        sh &quot;rsync -zav --delete #{rdoc_config.output_dir}/ #{rubyforge_config.rdoc_location}&quot;
+      end 
+    end 
+
+  end 
 end
+</diff>
      <filename>tasks/documentation.rake</filename>
    </modified>
    <modified>
      <diff>@@ -1,24 +1,29 @@
-require 'spec/rake/spectask'
 
-#-----------------------------------------------------------------------
-# Testing - this is either test or spec, include the appropriate one
-#-----------------------------------------------------------------------
-namespace :test do
+require 'tasks/config'
 
-    task :default =&gt; :spec
+#--------------------------------------------------------------------------------
+# configuration for running rspec.  This shows up as the test:default task
+#--------------------------------------------------------------------------------
+if spec_config = Configuration.for_if_exist?(&quot;test&quot;) then
+  if spec_config.mode == &quot;spec&quot; then
+    namespace :test do
 
-    Spec::Rake::SpecTask.new do |r| 
-        r.rcov      = true
-        r.rcov_dir  = HTAuth::SPEC.local_coverage_dir
-        r.libs      = HTAuth::SPEC.require_paths
-        r.spec_opts = %w(--format specdoc --color)
-    end
+      task :default =&gt; :spec
+
+      require 'spec/rake/spectask'
+      Spec::Rake::SpecTask.new do |r| 
+        r.ruby_opts   = spec_config.ruby_opts
+        r.libs        = [ HTAuth.lib_path, 
+                          HTAuth.root_dir ]
+        r.spec_files  = spec_config.files 
+        r.spec_opts   = spec_config.options
 
-    if HAVE_HEEL then
-        desc &quot;View the code coverage report locally&quot;
-        task :coverage =&gt; [:spec] do
-            sh &quot;heel --root #{HTAuth::SPEC.local_coverage_dir}&quot;
-        end 
+        if rcov_config = Configuration.for_if_exist?('rcov') then
+          r.rcov      = true
+          r.rcov_dir  = rcov_config.output_dir
+          r.rcov_opts = rcov_config.rcov_opts
+        end
+      end
     end
-    
+  end
 end</diff>
      <filename>tasks/rspec.rake</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>CHANGES</filename>
    </removed>
    <removed>
      <filename>lib/htauth/gemspec.rb</filename>
    </removed>
    <removed>
      <filename>lib/htauth/specification.rb</filename>
    </removed>
    <removed>
      <filename>tasks/rubyforge.rake</filename>
    </removed>
    <removed>
      <filename>tasks/setup.rb</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>372f6a5ed44c6eec528c87bffa469a1dae8f2ebc</id>
    </parent>
  </parents>
  <author>
    <name>Jeremy Hinegardner</name>
    <email>jeremy@hinegardner.org</email>
  </author>
  <url>http://github.com/copiousfreetime/htauth/commit/e0e59bf11e9dd19afcd38d276de15a26673259c5</url>
  <id>e0e59bf11e9dd19afcd38d276de15a26673259c5</id>
  <committed-date>2008-11-30T17:35:49-08:00</committed-date>
  <authored-date>2008-11-30T17:35:49-08:00</authored-date>
  <message>conversion to different project layout</message>
  <tree>5f2eca67247522a0a975a3140ef180d73aebaff3</tree>
  <committer>
    <name>Jeremy Hinegardner</name>
    <email>jeremy@hinegardner.org</email>
  </committer>
</commit>
