# auth_captcha2.rb $ Revision: 1 $
# Copyright (C) 2008 Michitaka Ohno <elpeo@mars.dti.ne.jp>
# You can redistribute it and/or modify it under GPL2.
#
# @options['captcha.secret'] = '秘密の言葉'

require 'digest/md5'

@captcha_lettersize = 4

def auth_captcha_label
	'左の画像に書かれている文字列を入力してください'
end

if @command == 'save' then
	alias :save_orig :save
	def save( *param )
		if @cgi.include?( 'captcha_code' ) && @cgi.include?( 'captcha_digest' ) && @cgi.include?( 'captcha_expire' ) then
			code = @cgi.params['captcha_code'][0]
			digest = @cgi.params['captcha_digest'][0]
			expire = @cgi.params['captcha_expire'][0]
			return true if Time.now.to_i > expire.to_i
			secret = @conf['captcha.secret'] || ''
			return save_orig( *param ) if Digest::MD5.hexdigest( code+secret+expire ) == digest
		end
		true
	end
end

add_edit_proc do
	scan = FONT_WIDTH * @captcha_lettersize + FONT_MARGIN * 2
	height = FONT_HEIGHT + FONT_MARGIN * 2
	bitmap = "0" * scan * height
	letter = []
	sx = Math::PI * 2 * rand
	sy = rand < 0.5 ? Math::PI : 0
	@captcha_lettersize.times do |n|
		letter << rand( 26 )
		c = [FONT_DATA[letter.last]].pack( "H*" ).unpack( "B*" ).first
		FONT_HEIGHT.times do |y|
			FONT_WIDTH.times do |x|
				next unless c[y*FONT_WIDTH+x] == ?1 
				xx = FONT_MARGIN + n * FONT_WIDTH + x + (FONT_MARGIN * Math.sin( sy + y * Math::PI / FONT_HEIGHT )).round
				yy = FONT_MARGIN + y + (FONT_MARGIN * Math.sin( sx + x * Math::PI / FONT_WIDTH )).round
				next unless xx >= 0 && xx < scan && yy >= 0 && yy < height
				bitmap[yy*scan+xx] = ?1
			end
		end
	end
	code = letter.map{|i| (?A+i).chr}.join
	image = '<table cellpadding="0" cellspacing="0" style="border: 1px solid black">'
	image << bitmap.gsub( /[01]{#{scan}}/ ) do |s|
		'<tr style="margin: 0px; padding: 0px; border: 0px">' + s.gsub( /[01]/ ) do |c|
			%Q[<td style="width: 1px; height: 1px; margin: 0px; padding: 0px; border: 0px; background-color: #{PIXEL_COLOR[c.to_i]}"></td>]
		end + '</tr>'
	end
	image << '</table>'
	secret = @conf['captcha.secret'] || ''
	expire = (Time.now.to_i+86400).to_s
	digest = Digest::MD5.hexdigest( code+secret+expire )
	r = %Q[<div style="margin: 5px">]
	r << %Q[<div style="float: left; margin-right: 1ex" class="captcha-image">#{image}</div>]
	r << %Q[ #{auth_captcha_label} ]
	r << %Q[<input class="field" name="captcha_code" value="">]
	r << %Q[<input type="hidden" name="captcha_digest" value="#{digest}">]
	r << %Q[<input type="hidden" name="captcha_expire" value="#{expire}">]
	r << %Q[</div>]
end

FONT_DATA = [
'0000010001000380038004c004c004c008600fe008601030103078fc00000000',
'00003fc00c600c300c300c300c600fc00c600c300c300c300c603fc000000000',
'000003c806380c180c08180818001800180018080c080c10063003e000000000',
'00003fc00c300c180c180c0c0c0c0c0c0c0c0c0c0c180c180c303fc000000000',
'00003ff00c300c100c100c400cc00fc00cc00c400c100c100c303ff000000000',
'00003ff00c300c100c100c400cc00fc00cc00c400c000c000c003f8000000000',
'000007d00c701830181030103000300030fc3030183018300c7007b000000000',
'00007efc183018301830183018301ff0183018301830183018307efc00000000',
'000007e00180018001800180018001800180018001800180018007e000000000',
'000003f000c000c000c000c000c000c000c000c008c01cc018c00f8000000000',
'00007ef818201840188019001b001d80198018c01860186018307e7c00000000',
'00003f000c000c000c000c000c000c000c000c000c100c100c303ff000000000',
'0000f01e3818383838382c382c582c5826582698269823982318fb7e00000000',
'0000787c18101c101610161013101310119010d010d0107010307c3000000000',
'000003c00c3018181818300c300c300c300c300c181818180c3003c000000000',
'00003fc00c600c300c300c300c600fc00c000c000c000c000c003f8000000000',
'000003c00c3018181818300c300c300c300c338c1c5818580c7003c0003c0018',
'00003fc00c600c300c300c300c600fc00d800cc00c600c600c303f3c00000000',
'000007a008e0186018200c000f8003e000601030101018301c2017c000000000',
'00003ffc318c218421840180018001800180018001800180018007e000000000',
'00007e7c18101810181018101810181018101810181018100c2007c000000000',
'00007e7c181018100c200c200c20064006400640038003800100010000000000',
'0000f3ce61846184618432c832c832c814501c701c7008200820082000000000',
'00003e780c2006400640038003000180038002c004c0046008603ef800000000',
'00003f7c0c100c1006200620034003400180018001800180018007e000000000',
'00001ff0186010c010c0018001800300060006000c100c1018303ff000000000',
]
FONT_WIDTH = 16
FONT_HEIGHT = 16
FONT_MARGIN = 3

PIXEL_COLOR = ['silver', 'black']
