# class WEBrick::HTTPAuth::Htpasswd

`Htpasswd` accesses apache-compatible password files. Passwords are matched to a realm where they are valid. For security, the path for a password database should be stored outside of the paths available to the HTTP server.

`Htpasswd` is intended for use with `WEBrick::HTTPAuth::BasicAuth`.

To create an `Htpasswd` database with a single user:

    htpasswd = WEBrick::HTTPAuth::Htpasswd.new 'my_password_file'
    htpasswd.set_passwd 'my realm', 'username', 'password'
    htpasswd.flush

### Public Class Methods

new(path, password_hash: nil) click to toggle source

Open a password database at `path`

    # File lib/webrick/httpauth/htpasswd.rb, line 38
    def initialize(path, password_hash: nil)
      @path = path
      @mtime = Time.at(0)
      @passwd = Hash.new
      @auth_type = BasicAuth
      @password_hash = password_hash

      case @password_hash
      when nil
        # begin
        #   require "string/crypt"
        # rescue LoadError
        #   warn("Unable to load string/crypt, proceeding with deprecated use of String#crypt, consider using password_hash: :bcrypt")
        # end
        @password_hash = :crypt
      when :crypt
        # require "string/crypt"
      when :bcrypt
        require "bcrypt"
      else
        raise ArgumentError, "only :crypt and :bcrypt are supported for password_hash keyword argument"
      end

      File.open(@path,"a").close unless File.exist?(@path)
      reload
    end

### Public Instance Methods

delete_passwd(realm, user) click to toggle source

Removes a password from the database for `user` in `realm`.

    # File lib/webrick/httpauth/htpasswd.rb, line 144
    def delete_passwd(realm, user)
      @passwd.delete(user)
    end

each() { |user, password| ... } click to toggle source

Iterate passwords in the database.

    # File lib/webrick/httpauth/htpasswd.rb, line 151
    def each # :yields: [user, password]
      @passwd.keys.sort.each{|user|
        yield([user, @passwd[user]])
      }
    end

flush(output=nil) click to toggle source

Flush the password database. If `output` is given the database will be written there instead of to the original path.

    # File lib/webrick/httpauth/htpasswd.rb, line 103
    def flush(output=nil)
      output ||= @path
      tmp = Tempfile.create("htpasswd", File::dirname(output))
      renamed = false
      begin
        each{|item| tmp.puts(item.join(":")) }
        tmp.close
        File::rename(tmp.path, output)
        renamed = true
      ensure
        tmp.close
        File.unlink(tmp.path) if !renamed
      end
    end

get_passwd(realm, user, reload_db) click to toggle source

Retrieves a password from the database for `user` in `realm`. If `reload_db` is true the database will be reloaded first.

    # File lib/webrick/httpauth/htpasswd.rb, line 122
    def get_passwd(realm, user, reload_db)
      reload() if reload_db
      @passwd[user]
    end

reload() click to toggle source

Reload passwords from the database

    # File lib/webrick/httpauth/htpasswd.rb, line 68
    def reload
      mtime = File::mtime(@path)
      if mtime > @mtime
        @passwd.clear
        File.open(@path){|io|
          while line = io.gets
            line.chomp!
            case line
            when %r!\A[^:]+:[a-zA-Z0-9./]{13}\z!
              if @password_hash == :bcrypt
                raise StandardError, ".htpasswd file contains crypt password, only bcrypt passwords supported"
              end
              user, pass = line.split(":")
            when %r!\A[^:]+:\$2[aby]\$\d{2}\$.{53}\z!
              if @password_hash == :crypt
                raise StandardError, ".htpasswd file contains bcrypt password, only crypt passwords supported"
              end
              user, pass = line.split(":")
            when /:\$/, /:{SHA}/
              raise NotImplementedError,
                    'MD5, SHA1 .htpasswd file not supported'
            else
              raise StandardError, 'bad .htpasswd file'
            end
            @passwd[user] = pass
          end
        }
        @mtime = mtime
      end
    end

set_passwd(realm, user, pass) click to toggle source

Sets a password in the database for `user` in `realm` to `pass`.

    # File lib/webrick/httpauth/htpasswd.rb, line 130
    def set_passwd(realm, user, pass)
      if @password_hash == :bcrypt
        # Cost of 5 to match Apache default, and because the
        # bcrypt default of 10 will introduce significant delays
        # for every request.
        @passwd[user] = BCrypt::Password.create(pass, :cost=>5)
      else
        @passwd[user] = make_passwd(realm, user, pass)
      end
    end