# -*- coding: utf-8 -*-
#
# alone : web application framework for small embedded systems.
#               Copyright (c) 2009 Inas Co Ltd. All Rights Reserved.
#
# This file is destributed under BSD License. Please read the COPYRIGHT file.
#
#
# apache httpd用 digest認証ファイル編集サンプル　モデルクラス
#
# ファイルパーミッションを調整して、cgi経由で
# パスワードファイルを更新できるようにしておく必要がある。
# テンポラリファイル経由で更新する戦略を採用しているので、
# ディレクトリにも書き込み権限が必要なことに注意すること。

require 'digest/md5'

##
# htdigest 管理クラス
#
class Htdigest
  PASSWORD_FILE = "/tmp/htdigest.passwd"
  attr_accessor :values

  ##
  # ファクトリ　リスト
  #
  #@return [Array]       Htdigestオブジェクトの配列
  #@note
  # 全アカウントをオブジェクトの配列にして返す。
  #
  def self.list()
    users = []
    begin
      File.open( PASSWORD_FILE, "r" ) do |file|
        file.each do |text|
          (user,realm,pass) = text.split(':')
          a = Htdigest.new
          a.values = {:username=>user,:realm=>realm,:pass=>''}
          users << a
        end
      end

    rescue
      File.open( PASSWORD_FILE, "w" ) {}

    end

    return users
  end


  ##
  # constructor
  #
  def initialize()
    @values = {}
  end


  ##
  # getter
  #
  def [](key)
    return @values[key.to_sym]
  end


  ##
  # READ (dummy, now)
  #
  def read()
  end


  ##
  # CREATE, UPDATE
  #
  #@note
  # valuesにセットされた値を使って、パスワードファイルを書き換える。
  #
  def entry()
    # make new entry
    user_realm = @values[:username] + ':' + @values[:realm] + ':'
    pass = Digest::MD5.hexdigest( user_realm + @values[:password] )

    return rewrite_password_file( user_realm + pass )
  end


  ##
  # DELETE
  #
  #@note
  # valuesにセットされた値を使って、パスワードファイルを書き換える。
  #
  def delete()
    return rewrite_password_file()
  end

  
  private
  ##
  # パスワードファイルの更新
  #
  #@param  new_entry    追加するエントリ(option)
  #@note
  # ・valuesにセットされた値のエントリを消去する。
  # ・new_entry で与えられたエントリを追加する。
  #
  def rewrite_password_file( new_entry = nil )
    #
    # make memory cache
    #
    accounts = []
    File.open( PASSWORD_FILE, "r" ) do |file|
      file.each do |text|
        (user,realm,pass) = text.split(':')
        next  if user == @values[:username] && realm == @values[:realm]
        accounts << text
      end
    end

    #
    # make temporary file
    #
    tmpname = PASSWORD_FILE + ".tmp#{$$}"
    File.open( tmpname, "w" ) do |file|
      if( new_entry )
        file.puts( new_entry )
      end
      accounts.each do |text|
        file.write( text )
      end
    end

    #
    # rename to original
    #
    File.rename( tmpname, PASSWORD_FILE )

    return true
  end

end
