kamcaptcha 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,6 +1,7 @@
1
1
  source "http://rubygems.org"
2
2
 
3
3
  group :test do
4
+ gem "rmagick"
4
5
  gem "ruby-debug", "~> 0.10.4", :require => nil, :platforms => :ruby_18
5
6
  gem "debugger", "~> 1.1.1", :require => nil, :platforms => :ruby_19
6
7
  end
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Kamcaptcha
1
+ # Kamcaptcha [![Build Status](https://secure.travis-ci.org/morten/kamcaptcha.png)](http://travis-ci.org/morten/kamcaptcha)
2
2
 
3
3
  A captcha system that uses less ridiculous images than ReCAPTCHA. Kamcaptcha has two somewhat independent parts to it, a generator for building the word images to present, and then a runtime configuration for checking validity of what gets submitted.
4
4
 
data/bin/kamcaptcha CHANGED
@@ -21,7 +21,7 @@ Usage examples:
21
21
  kamcaptcha tmp/
22
22
  kamcaptcha --count 100 tmp/
23
23
  kamcaptcha --height 100 --width 300 tmp/
24
- kamcaptcha --length 8 --format gif tmp/
24
+ kamcaptcha --length 8-10 --source random --format gif tmp/
25
25
 
26
26
  A default run creates a "./tmp" directory and generates 10 random five character word PNG images, each 240x50 pixels in size.
27
27
 
@@ -32,7 +32,8 @@ EOS
32
32
  opt :count, "How many words to generate", :default => 10
33
33
  opt :height, "Height of the word image in pixels", :default => 50
34
34
  opt :width, "Width of the word image in pixesks", :default => 240
35
- opt :length, "Length of the word in number of characters", :default => 5
35
+ opt :source, "How to generate words, [dictionary|random]", :default => "dictionary"
36
+ opt :length, "Length of the word in number of characters, or as a range e.g. 7-9", :default => "5"
36
37
  opt :format, "Image file format", :default => "png"
37
38
  end
38
39
 
@@ -43,10 +44,11 @@ end
43
44
 
44
45
  Kamcaptcha.salt = opts[:salt] || Digest::SHA2.hexdigest((0...64).map { rand(150).chr }.join)
45
46
 
46
- puts "Generating #{opts[:count]} words into #{ARGV[0]}\n\n"
47
+ puts "Generating #{opts[:count]} words into #{ARGV[0]} - hang tight...\n\n"
47
48
 
48
- opts[:count].times do |i|
49
- puts "\t#{i+1}\t"+Kamcaptcha::Generator.generate(ARGV[0], opts)
49
+ files = Kamcaptcha::Generator.generate(ARGV[0], opts)
50
+ files.each_with_index do |file, index|
51
+ puts "\t#{index+1}\t#{file}"
50
52
  end
51
53
 
52
54
  puts "\nRemember to set Kamcaptcha.salt = '#{Kamcaptcha.salt}' in your application\n"
data/kamcaptcha.gemspec CHANGED
@@ -1,4 +1,4 @@
1
- Gem::Specification.new "kamcaptcha", "0.0.1" do |s|
1
+ Gem::Specification.new "kamcaptcha", "0.1.0" do |s|
2
2
  s.summary = "A captcha image generator that's a little less retarded"
3
3
  s.description = "Helps humankind with simpler captchas"
4
4
  s.authors = [ "Morten Primdahl" ]
@@ -1,39 +1,104 @@
1
- require "rubygems"
2
-
3
1
  begin
4
- require "rmagick"
2
+ require "RMagick"
5
3
  rescue LoadError => e
6
4
  puts "RMagick required to run the generator, gem install rmagick"
7
- return
5
+ exit
8
6
  end
9
7
 
10
8
  module Kamcaptcha
11
9
  class Generator
10
+ class WordGenerator
11
+ attr_reader :min, :max
12
+
13
+ def initialize(length)
14
+ if length.to_s =~ /^(\d+)$/
15
+ @min = @max = $1.to_i
16
+ elsif length =~ /^(\d+)-(\d+)$/
17
+ @min = [$1.to_i, $2.to_i].min
18
+ @max = [$1.to_i, $2.to_i].max
19
+ else
20
+ raise ArgumentError.new("Invalid word length specified: #{length}")
21
+ end
22
+ end
23
+ end
24
+
25
+ class RandomWordGenerator < WordGenerator
26
+ CHARS = "23456789ABCDEFGHJKLMNPQRSTUVXYZ".split("")
27
+
28
+ def generate
29
+ length = min
30
+ length += Kernel.rand(max - min) unless max == min
31
+
32
+ (1..length).map { CHARS[rand(CHARS.size)] }.join(" ")
33
+ end
34
+ end
35
+
36
+ class DictionaryWordGenerator < WordGenerator
37
+ class << self
38
+ attr_accessor :dict # Use this to set a custom dictionary or dictionary generating function
39
+ end
40
+
41
+ def generate
42
+ words[rand(words.size)].split("").join(" ")
43
+ end
44
+
45
+ def words
46
+ @words ||= begin
47
+ if self.class.dict
48
+ if self.class.dict.respond_to?(:call)
49
+ w = self.class.dict.call
50
+ else
51
+ w = self.class.dict
52
+ end
53
+ else
54
+ w = default_dict
55
+ end
56
+
57
+ w.each_with_index { |word, i| w[i] = word.upcase }
58
+ w.select { |w| w.size >= min && w.size <= max && w !~ /O/ }
59
+ end
60
+ end
61
+
62
+ def default_dict
63
+ return File.read("/usr/share/dict/words").split("\n") if File.exists?("/usr/share/dict/words")
64
+ return File.read("/usr/dict/words").split("\n") if File.exists?("/usr/dict/words")
65
+
66
+ raise ArgumentError.new("Sorry, need a dictionary file")
67
+ end
68
+ end
69
+
12
70
  DEFAULTS = {
13
- :chars => "23456789ABCDEFGHJKLMNPQRSTUVXYZ".split(""),
14
71
  :width => 240,
15
72
  :height => 50,
16
73
  :length => 5,
17
- :format => "png"
74
+ :format => "png",
75
+ :count => 1
18
76
  }
19
77
 
20
78
  def self.generate(path, options = {})
21
79
  options = DEFAULTS.merge(options)
22
80
 
23
- word = generate_word(options[:chars], options[:length])
24
- image = build_image(word, options[:width], options[:height])
81
+ if options[:source] != "random"
82
+ source = DictionaryWordGenerator.new(options[:length])
83
+ else
84
+ source = RandomWordGenerator.new(options[:length])
85
+ end
86
+
87
+ files = []
25
88
 
26
- name = word.delete(" ").downcase
27
- file = File.join(path, Kamcaptcha.encrypt(name) + ".#{options[:format]}")
89
+ options[:count].times do
90
+ word = source.generate
91
+ image = build_image(word, options[:width], options[:height])
92
+ name = word.delete(" ").downcase
93
+ file = File.join(path, Kamcaptcha.encrypt(name) + ".#{options[:format]}")
28
94
 
29
- image.write(file)
30
- image.destroy!
95
+ image.write(file)
96
+ image.destroy!
31
97
 
32
- file
33
- end
98
+ files << file
99
+ end
34
100
 
35
- def self.generate_word(chars, size)
36
- (1..size).map { chars[rand(chars.size)] }.join(" ")
101
+ files
37
102
  end
38
103
 
39
104
  def self.build_image(word, width, height)
data/test/test_helper.rb CHANGED
@@ -6,6 +6,7 @@ require "minitest/autorun"
6
6
 
7
7
  Bundler.require
8
8
 
9
+ require "RMagick"
9
10
  require "debugger" unless ENV["TRAVIS"]
10
11
 
11
12
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
@@ -1,15 +1,42 @@
1
+ require File.expand_path("test/test_helper")
2
+
1
3
  describe Kamcaptcha::Generator do
2
- describe "#generate_word" do
3
- it "builds a word by the given chars and length" do
4
- word = Kamcaptcha::Generator.generate_word([ "a", "b" ], 6)
5
- assert_equal 6, word.split(" ").size
6
- assert_match /[ab ]+/, word
4
+
5
+ describe Kamcaptcha::Generator::RandomWordGenerator do
6
+ subject { Kamcaptcha::Generator::RandomWordGenerator.new("3-10") }
7
+
8
+ it "delivers words of the specified size range" do
9
+ 20.times do
10
+ word = subject.generate.delete(" ")
11
+
12
+ assert word.size >= 3, "Size mismatch #{word}"
13
+ assert word.size <= 10, "Size mismatch #{word}"
14
+
15
+ assert_match /[0-9A-Z]+/, word
16
+ end
17
+ end
18
+ end
19
+
20
+ describe Kamcaptcha::Generator::DictionaryWordGenerator do
21
+ after do
22
+ Kamcaptcha::Generator::DictionaryWordGenerator.dict = nil
23
+ end
24
+
25
+ subject { Kamcaptcha::Generator::DictionaryWordGenerator.new("1-5") }
26
+
27
+ it "delivers words from the dict" do
28
+ Kamcaptcha::Generator::DictionaryWordGenerator.dict = [ "foo", "fum" ]
29
+
30
+ 20.times do
31
+ word = subject.generate.delete(" ")
32
+ assert [ "FOO", "FUM" ].member?(word), "Word #{word} not found"
33
+ end
7
34
  end
8
35
  end
9
36
 
10
37
  describe "#generate" do
11
38
  it "generates a file" do
12
- file = Kamcaptcha::Generator.generate("/tmp")
39
+ file = Kamcaptcha::Generator.generate("/tmp", :source => "random").first
13
40
  assert File.exist?(file)
14
41
  File.unlink(file)
15
42
  end
@@ -1,3 +1,5 @@
1
+ require File.expand_path("test/test_helper")
2
+
1
3
  describe Kamcaptcha::Helper do
2
4
  include Kamcaptcha::Helper
3
5
 
@@ -1,3 +1,5 @@
1
+ require File.expand_path("test/test_helper")
2
+
1
3
  describe Kamcaptcha do
2
4
 
3
5
  describe "#images" do
@@ -1,3 +1,5 @@
1
+ require File.expand_path("test/test_helper")
2
+
1
3
  describe Kamcaptcha::Validation do
2
4
  def params
3
5
  @params
metadata CHANGED
@@ -1,119 +1,118 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: kamcaptcha
3
- version: !ruby/object:Gem::Version
4
- version: 0.0.1
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Morten Primdahl
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2012-09-11 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2012-09-12 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: trollop
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '2.0'
22
- type: :runtime
23
22
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
23
+ requirement: &id001 !ruby/object:Gem::Requirement
25
24
  none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: '2.0'
30
- - !ruby/object:Gem::Dependency
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 2
31
+ - 0
32
+ version: "2.0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
31
36
  name: rake
32
- requirement: !ruby/object:Gem::Requirement
33
- none: false
34
- requirements:
35
- - - ! '>='
36
- - !ruby/object:Gem::Version
37
- version: '0'
38
- type: :development
39
37
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
38
+ requirement: &id002 !ruby/object:Gem::Requirement
41
39
  none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
45
- version: '0'
46
- - !ruby/object:Gem::Dependency
47
- name: bundler
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
50
- requirements:
51
- - - ! '>='
52
- - !ruby/object:Gem::Version
53
- version: '0'
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
54
47
  type: :development
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: bundler
55
51
  prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ! '>='
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- - !ruby/object:Gem::Dependency
63
- name: rmagick
64
- requirement: !ruby/object:Gem::Requirement
52
+ requirement: &id003 !ruby/object:Gem::Requirement
65
53
  none: false
66
- requirements:
67
- - - ! '>='
68
- - !ruby/object:Gem::Version
69
- version: '0'
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
70
61
  type: :development
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: rmagick
71
65
  prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ! '>='
76
- - !ruby/object:Gem::Version
77
- version: '0'
78
- - !ruby/object:Gem::Dependency
79
- name: minitest
80
- requirement: !ruby/object:Gem::Requirement
66
+ requirement: &id004 !ruby/object:Gem::Requirement
81
67
  none: false
82
- requirements:
83
- - - ! '>='
84
- - !ruby/object:Gem::Version
85
- version: '0'
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
86
75
  type: :development
76
+ version_requirements: *id004
77
+ - !ruby/object:Gem::Dependency
78
+ name: minitest
87
79
  prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
80
+ requirement: &id005 !ruby/object:Gem::Requirement
89
81
  none: false
90
- requirements:
91
- - - ! '>='
92
- - !ruby/object:Gem::Version
93
- version: '0'
94
- - !ruby/object:Gem::Dependency
95
- name: uuidtools
96
- requirement: !ruby/object:Gem::Requirement
97
- none: false
98
- requirements:
99
- - - ! '>='
100
- - !ruby/object:Gem::Version
101
- version: 2.1.3
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
102
89
  type: :development
90
+ version_requirements: *id005
91
+ - !ruby/object:Gem::Dependency
92
+ name: uuidtools
103
93
  prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
94
+ requirement: &id006 !ruby/object:Gem::Requirement
105
95
  none: false
106
- requirements:
107
- - - ! '>='
108
- - !ruby/object:Gem::Version
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ hash: 13
100
+ segments:
101
+ - 2
102
+ - 1
103
+ - 3
109
104
  version: 2.1.3
105
+ type: :development
106
+ version_requirements: *id006
110
107
  description: Helps humankind with simpler captchas
111
108
  email: primdahl@me.com
112
- executables:
109
+ executables:
113
110
  - kamcaptcha
114
111
  extensions: []
112
+
115
113
  extra_rdoc_files: []
116
- files:
114
+
115
+ files:
117
116
  - .gitignore
118
117
  - .travis.yml
119
118
  - Gemfile
@@ -132,28 +131,37 @@ files:
132
131
  - test/unit/test_kamcaptcha.rb
133
132
  - test/unit/test_validation.rb
134
133
  homepage: http://github.com/morten/kamcaptcha
135
- licenses:
134
+ licenses:
136
135
  - MIT
137
136
  post_install_message:
138
137
  rdoc_options: []
139
- require_paths:
138
+
139
+ require_paths:
140
140
  - lib
141
- required_ruby_version: !ruby/object:Gem::Requirement
141
+ required_ruby_version: !ruby/object:Gem::Requirement
142
142
  none: false
143
- requirements:
144
- - - ! '>='
145
- - !ruby/object:Gem::Version
146
- version: '0'
147
- required_rubygems_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ hash: 3
147
+ segments:
148
+ - 0
149
+ version: "0"
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
148
151
  none: false
149
- requirements:
150
- - - ! '>='
151
- - !ruby/object:Gem::Version
152
- version: '0'
152
+ requirements:
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ hash: 3
156
+ segments:
157
+ - 0
158
+ version: "0"
153
159
  requirements: []
160
+
154
161
  rubyforge_project:
155
- rubygems_version: 1.8.23
162
+ rubygems_version: 1.8.15
156
163
  signing_key:
157
164
  specification_version: 3
158
165
  summary: A captcha image generator that's a little less retarded
159
166
  test_files: []
167
+