# Copyright (C) 2003-2005 Kouichirou Eto, All rights reserved.

$LOAD_PATH << "../../lib" unless $LOAD_PATH.include?("../../lib")
require "qwik/config"
require "qwik/util-path"
require "qwik/util-string"

module Qwik
  class PasswordGenerator
    DEFAULT_SITE_PASSWORD = ""

    def initialize(config)
      @config = config
      @pass = DEFAULT_SITE_PASSWORD
      file = @config.pass_file.path
      @pass = file.open("rb"){|f| f.gets }.to_s.chomp if file.exist?
      generation_init
    end

    def generation_init
      @generation_file = @config.generation_file.path
      generation_get
    end

    def generation_get
      if ! @generation_file.exist?
	@generation_file.open("wb"){|f| f.print "" }	
      end
      str = @generation_file.open("rb"){|f| f.read }
      h = {}
      str.each {|line|
	next unless line[0] == ?,
	dummy, user, gen = line.chomp.split(",")
	h[user] = gen.to_i
      }
      @generation = h
    end

    def generation_store
      @generation_file.open("ab") {|f|
	@generation.each {|user, generation|
	  f.puts(","+user+","+generation.to_s)
	}
      }
    end

    def generation_add(user, generation)
      @generation_file.open("ab") {|f|
	f.puts(","+user+","+generation.to_s)
      }
    end

    def generation_inc(user)
      generation_get
      generation = 0
      generation = @generation[user] if @generation[user]
      generation += 1 # inc
      generation_add(user, generation)
      generation
    end

    # ============================== Password generate
    def generate_hex(user)
      generation = 0
      generation = @generation[user] if @generation[user]
      generate_md5hex(user, generation).upcase[0, 8]
    end

    def generate(user)
      generation = 0
      generation = @generation[user] if @generation[user]
      generate_md5hex(user, generation).hex.to_s[-8, 8]
    end

    def match?(user, pass)
      return false if user.nil? || user == ""
      return false if pass.nil? || pass == ""

      pa = generate(user)
      return true if pa == pass
      pa = generate_hex(user)
      return true if pa == pass
      return true if pa == pass.upcase
      false
    end

    private
    def generate_md5hex(user, generation=0)
      (user.to_s+":"+@pass+":"+generation.to_s).md5hex
    end
  end
end

if $0 == __FILE__
  require "test/unit"
  require "qwik/util-path"
  $debug = true
end

if $debug
  class TC_PasswordGenerator < Test::Unit::TestCase
    def test_password
      @config = Qwik::Config.new(true)
      @config.pass_file = "./password.txt"
      @config.generation_file = "./generation.txt"
      @config.generation_file.path.open("wb"){|f|
	f.puts ""
      }
      pw = Qwik::PasswordGenerator.new(@config)
      assert_equal("95988593", pw.generate("user@e.com"))
      assert_equal("68246775", pw.generate_hex("user@e.com"))
      assert_equal(true,  pw.match?("user@e.com", "95988593"))
      # generation 0
      assert_equal(false, pw.match?("user@e.com", "64006086"))
      assert_equal(true,  pw.match?("user@e.com", "68246775"))

      @config.generation_file.path.open("wb"){|f|
	f.puts ",user@e.com,1"
      }
      pw.generation_get
      assert_equal(false,  pw.match?("user@e.com", "95988593"))
      # generation 1
      assert_equal("85127862", pw.generate("user@e.com"))
      assert_equal(true, pw.match?("user@e.com", "85127862"))
    end
  end
end
