decaptcha 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +11 -0
- data/.gitignore +42 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +42 -0
- data/LICENSE +20 -0
- data/README.rdoc +17 -0
- data/Rakefile +2 -0
- data/autotest/discover.rb +1 -0
- data/decaptcha.gemspec +21 -0
- data/lib/decaptcha.rb +13 -0
- data/lib/decaptcha/client.rb +19 -0
- data/lib/decaptcha/provider.rb +3 -0
- data/lib/decaptcha/provider/base.rb +20 -0
- data/lib/decaptcha/provider/death_by_captcha/base.rb +18 -0
- data/lib/decaptcha/provider/death_by_captcha/http.rb +114 -0
- data/lib/decaptcha/provider/death_by_captcha/http_old.rb +75 -0
- data/lib/decaptcha/provider/death_by_captcha/socket.rb +156 -0
- data/lib/decaptcha/provider/error.rb +10 -0
- data/lib/decaptcha/response.rb +20 -0
- data/spec/.rspec +1 -0
- data/spec/decaptcha_provider_death_by_captcha_http_spec.rb +48 -0
- data/spec/decaptcha_provider_death_by_captcha_socket_spec.rb +51 -0
- data/spec/decaptcha_spec.rb +18 -0
- data/spec/fixtures/captchas/recaptcha1.jpg +0 -0
- data/spec/fixtures/captchas/recaptcha2.jpg +0 -0
- data/spec/fixtures/captchas/recaptcha3.jpg +0 -0
- data/spec/spec_helper.rb +22 -0
- metadata +100 -0
data/.document
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# .document is used by rdoc and yard to know how to generate documentation
|
2
|
+
# for example, it can be used to control how rdoc gets built when you do `gem install foo`
|
3
|
+
|
4
|
+
README.rdoc
|
5
|
+
lib/**/*.rb
|
6
|
+
bin/*
|
7
|
+
|
8
|
+
# Files below this - are treated as 'extra files', and aren't parsed for ruby code
|
9
|
+
-
|
10
|
+
features/**/*.feature
|
11
|
+
LICENSE
|
data/.gitignore
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# rcov generated
|
2
|
+
coverage
|
3
|
+
|
4
|
+
# rdoc generated
|
5
|
+
rdoc
|
6
|
+
|
7
|
+
# yard generated
|
8
|
+
doc
|
9
|
+
.yardoc
|
10
|
+
|
11
|
+
# bundler
|
12
|
+
.bundle
|
13
|
+
|
14
|
+
# jeweler generated
|
15
|
+
pkg
|
16
|
+
|
17
|
+
# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
|
18
|
+
#
|
19
|
+
# * Create a file at ~/.gitignore
|
20
|
+
# * Include files you want ignored
|
21
|
+
# * Run: git config --global core.excludesfile ~/.gitignore
|
22
|
+
#
|
23
|
+
# After doing this, these files will be ignored in all your git projects,
|
24
|
+
# saving you from having to 'pollute' every project you touch with them
|
25
|
+
#
|
26
|
+
# Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
|
27
|
+
#
|
28
|
+
# For MacOS:
|
29
|
+
#
|
30
|
+
#.DS_Store
|
31
|
+
#
|
32
|
+
# For TextMate
|
33
|
+
#*.tmproj
|
34
|
+
#tmtags
|
35
|
+
#
|
36
|
+
# For emacs:
|
37
|
+
#*~
|
38
|
+
#\#*
|
39
|
+
#.\#*
|
40
|
+
#
|
41
|
+
# For vim:
|
42
|
+
#*.swp
|
data/Gemfile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
gem 'rest-client'
|
7
|
+
gem 'json'
|
8
|
+
|
9
|
+
# Add dependencies to develop your gem here.
|
10
|
+
# Include everything needed to run rake, tests, features, etc.
|
11
|
+
group :development do
|
12
|
+
gem "rspec", ">= 2.0.0.beta.19"
|
13
|
+
gem "autotest"
|
14
|
+
gem "autotest-growl"
|
15
|
+
gem "yard", "~> 0.6.0"
|
16
|
+
gem "bundler", "~> 1.0.0"
|
17
|
+
gem "jeweler", "~> 1.5.0.pre3"
|
18
|
+
gem "rcov", ">= 0"
|
19
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
autotest (4.3.2)
|
5
|
+
autotest-growl (0.2.6)
|
6
|
+
diff-lcs (1.1.2)
|
7
|
+
git (1.2.5)
|
8
|
+
jeweler (1.5.0.pre3)
|
9
|
+
bundler (~> 1.0.0)
|
10
|
+
git (>= 1.2.5)
|
11
|
+
rake
|
12
|
+
json (1.4.6)
|
13
|
+
mime-types (1.16)
|
14
|
+
rake (0.8.7)
|
15
|
+
rcov (0.9.9)
|
16
|
+
rest-client (1.6.0)
|
17
|
+
mime-types (>= 1.16)
|
18
|
+
rspec (2.0.0.beta.22)
|
19
|
+
rspec-core (= 2.0.0.beta.22)
|
20
|
+
rspec-expectations (= 2.0.0.beta.22)
|
21
|
+
rspec-mocks (= 2.0.0.beta.22)
|
22
|
+
rspec-core (2.0.0.beta.22)
|
23
|
+
rspec-expectations (2.0.0.beta.22)
|
24
|
+
diff-lcs (>= 1.1.2)
|
25
|
+
rspec-mocks (2.0.0.beta.22)
|
26
|
+
rspec-core (= 2.0.0.beta.22)
|
27
|
+
rspec-expectations (= 2.0.0.beta.22)
|
28
|
+
yard (0.6.1)
|
29
|
+
|
30
|
+
PLATFORMS
|
31
|
+
ruby
|
32
|
+
|
33
|
+
DEPENDENCIES
|
34
|
+
autotest
|
35
|
+
autotest-growl
|
36
|
+
bundler (~> 1.0.0)
|
37
|
+
jeweler (~> 1.5.0.pre3)
|
38
|
+
json
|
39
|
+
rcov
|
40
|
+
rest-client
|
41
|
+
rspec (>= 2.0.0.beta.19)
|
42
|
+
yard (~> 0.6.0)
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Dirty Sánchez
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
= decaptcha
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
== Note on Patches/Pull Requests
|
6
|
+
|
7
|
+
* Fork the project.
|
8
|
+
* Make your feature addition or bug fix.
|
9
|
+
* Add tests for it. This is important so I don't break it in a
|
10
|
+
future version unintentionally.
|
11
|
+
* Commit, do not mess with rakefile, version, or history.
|
12
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
13
|
+
* Send me a pull request. Bonus points for topic branches.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2010 Dirty Sánchez. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Autotest.add_discovery { "rspec2" }
|
data/decaptcha.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "decaptcha"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "decaptcha"
|
7
|
+
s.version = Decaptcha::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Dirty Sánchez"]
|
10
|
+
s.email = ["rmoriz@gmail.com"]
|
11
|
+
s.homepage = "http://rubygems.org/gems/decaptcha"
|
12
|
+
s.summary = %q{helps poor senior data entry specialists in developing countries}
|
13
|
+
s.description = %q{helps poor senior data entry specialists in developing countries}
|
14
|
+
|
15
|
+
s.rubyforge_project = "decaptcha"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
end
|
data/lib/decaptcha.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'decaptcha/provider'
|
2
|
+
require 'decaptcha/provider/error'
|
3
|
+
require 'decaptcha/provider/base'
|
4
|
+
|
5
|
+
require 'decaptcha/provider/death_by_captcha/base'
|
6
|
+
require 'decaptcha/provider/death_by_captcha/http'
|
7
|
+
require 'decaptcha/provider/death_by_captcha/socket'
|
8
|
+
require 'decaptcha/response'
|
9
|
+
require 'decaptcha/client'
|
10
|
+
|
11
|
+
module Decaptcha
|
12
|
+
VERSION = "0.0.0"
|
13
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Decaptcha
|
4
|
+
class Client
|
5
|
+
extend Forwardable
|
6
|
+
attr_accessor :provider
|
7
|
+
|
8
|
+
PROVIDERS = {
|
9
|
+
:dbc_http => Decaptcha::Provider::DeathByCaptcha::HTTP,
|
10
|
+
:dbc_socket => Decaptcha::Provider::DeathByCaptcha::Socket,
|
11
|
+
}
|
12
|
+
|
13
|
+
def initialize(provider_name, provider_options = {})
|
14
|
+
@provider = PROVIDERS[provider_name.to_sym].new provider_options
|
15
|
+
end
|
16
|
+
|
17
|
+
def_delegators :@provider, :connect, :upload, :upload_and_poll, :result, :invalid, :delete, :balance
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Decaptcha
|
2
|
+
module Provider
|
3
|
+
class Base
|
4
|
+
include Error
|
5
|
+
|
6
|
+
def mime_type(filename)
|
7
|
+
filename = File.basename(filename)
|
8
|
+
|
9
|
+
if filename =~ /.jp(e)g$/
|
10
|
+
"image/jpeg"
|
11
|
+
elsif filename =~ /.png$/
|
12
|
+
"image/png"
|
13
|
+
elsif filename =~ /.gif$/
|
14
|
+
"image/gif"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Decaptcha
|
2
|
+
module Provider
|
3
|
+
module DeathByCaptcha
|
4
|
+
class Base < Decaptcha::Provider::Base
|
5
|
+
attr_accessor :login
|
6
|
+
attr_accessor :password
|
7
|
+
attr_accessor :timeout
|
8
|
+
|
9
|
+
def initialize(args = {})
|
10
|
+
@login = args[:login]
|
11
|
+
@password = args[:password]
|
12
|
+
@timeout = args[:timeout] ? args[:timeout] : '120' # seconds
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
#require 'uri'
|
2
|
+
require 'digest/sha1'
|
3
|
+
require 'json'
|
4
|
+
require 'rest_client'
|
5
|
+
|
6
|
+
module Decaptcha
|
7
|
+
module Provider
|
8
|
+
module DeathByCaptcha
|
9
|
+
class HTTP < Decaptcha::Provider::DeathByCaptcha::Base
|
10
|
+
API_SERVER_URL = 'http://www.deathbycaptcha.com/api/captcha'
|
11
|
+
API_VERSION = 'DBC/Ruby v3.0'
|
12
|
+
SOFTWARE_VENDOR_ID = 0
|
13
|
+
DEFAULT_TIMEOUT = 60
|
14
|
+
POLLS_PERIOD = 15
|
15
|
+
|
16
|
+
def upload(args = {})
|
17
|
+
filename = args[:filename]
|
18
|
+
|
19
|
+
params = {
|
20
|
+
:captchafile => File.new(filename, 'rb'),
|
21
|
+
:username => @login,
|
22
|
+
:password => Digest::SHA1.hexdigest(@password),
|
23
|
+
:is_hashed => 1,
|
24
|
+
:swid => SOFTWARE_VENDOR_ID,
|
25
|
+
:version => API_VERSION
|
26
|
+
}
|
27
|
+
|
28
|
+
RestClient.post API_SERVER_URL, params, :accept => :json do |response, request, result|
|
29
|
+
if response.code == 303
|
30
|
+
return Decaptcha::Response.new_from_location response.headers[:location]
|
31
|
+
else
|
32
|
+
raise UploadError
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def upload_and_poll(args = {})
|
38
|
+
user_timeout = args[:timeout] || DEFAULT_TIMEOUT
|
39
|
+
response = upload(args)
|
40
|
+
kill_time = Time.now + user_timeout
|
41
|
+
|
42
|
+
while (Time.now < kill_time) do
|
43
|
+
if result = result(response)
|
44
|
+
break
|
45
|
+
else
|
46
|
+
sleep POLLS_PERIOD
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# remove...
|
51
|
+
|
52
|
+
result
|
53
|
+
end
|
54
|
+
|
55
|
+
def result(response_obj)
|
56
|
+
RestClient.get response_obj.location, :accept => :json do |response, request, result|
|
57
|
+
if response.code == 200
|
58
|
+
data = JSON.parse response
|
59
|
+
response_obj.text = data['text']
|
60
|
+
response_obj.invalid = !data['is_correct']
|
61
|
+
return response_obj
|
62
|
+
else
|
63
|
+
raise ResultError
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def delete(response_obj)
|
69
|
+
params = {
|
70
|
+
:username => @login,
|
71
|
+
:password => Digest::SHA1.hexdigest(@password),
|
72
|
+
:is_hashed => 1,
|
73
|
+
:swid => SOFTWARE_VENDOR_ID,
|
74
|
+
:version => API_VERSION
|
75
|
+
}
|
76
|
+
|
77
|
+
delete_url = "#{response_obj.location}/remove"
|
78
|
+
|
79
|
+
RestClient.post delete_url, params, :accept => :json do |response, request, result|
|
80
|
+
if response.code == 200
|
81
|
+
response_obj.deleted = true
|
82
|
+
else
|
83
|
+
raise DeletionError
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
response_obj
|
88
|
+
end
|
89
|
+
|
90
|
+
def invalid(response_obj)
|
91
|
+
params = {
|
92
|
+
:username => @login,
|
93
|
+
:password => Digest::SHA1.hexdigest(@password),
|
94
|
+
:is_hashed => 1,
|
95
|
+
:swid => SOFTWARE_VENDOR_ID,
|
96
|
+
:version => API_VERSION
|
97
|
+
}
|
98
|
+
|
99
|
+
invalidation_url = "#{response_obj.location}/report"
|
100
|
+
|
101
|
+
RestClient.post invalidation_url, params, :accept => :json do |response, request, result|
|
102
|
+
if response.code == 200
|
103
|
+
response_obj.invalid = true
|
104
|
+
else
|
105
|
+
raise InvalidationError, response
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
response_obj
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'digest/sha1'
|
3
|
+
require 'net/http'
|
4
|
+
require 'net/http/post/multipart'
|
5
|
+
|
6
|
+
module Decaptcha
|
7
|
+
module Provider
|
8
|
+
class DeathByCaptcha
|
9
|
+
class HTTP < Decaptcha::Provider::DeathByCaptcha::Base
|
10
|
+
API_SERVER_URL = 'http://www.deathbycaptcha.com/api/captcha'
|
11
|
+
API_VERSION = 'DBC/Ruby v3.0'
|
12
|
+
SOFTWARE_VENDOR_ID = 0
|
13
|
+
DEFAULT_TIMEOUT = 60
|
14
|
+
POLLS_PERIOD = 15
|
15
|
+
|
16
|
+
def upload(args = {})
|
17
|
+
filename = args[:filename]
|
18
|
+
url = URI.parse(API_SERVER_URL)
|
19
|
+
|
20
|
+
request = Net::HTTP::Post::Multipart.new url.path,
|
21
|
+
'captchafile' => UploadIO.new(filename, mime_type(filename), File.basename(filename)),
|
22
|
+
'username' => @login,
|
23
|
+
'password' => Digest::SHA1.hexdigest(@password),
|
24
|
+
'is_hashed' => 1,
|
25
|
+
'swid' => SOFTWARE_VENDOR_ID,
|
26
|
+
'version' => API_VERSION
|
27
|
+
|
28
|
+
http = Net::HTTP.new(url.host, url.port)
|
29
|
+
response = http.start {|con|
|
30
|
+
con.request(request)
|
31
|
+
}
|
32
|
+
|
33
|
+
case response
|
34
|
+
when Net::HTTPSeeOther
|
35
|
+
response.header['location'] =~ /(\d+)\z/
|
36
|
+
cid = $1
|
37
|
+
else
|
38
|
+
response.error! # raises Exception
|
39
|
+
end
|
40
|
+
|
41
|
+
cid
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
def upload_and_poll(args = {})
|
46
|
+
user_timeout = args[:timeout] || DEFAULT_TIMEOUT
|
47
|
+
cid = upload(args)
|
48
|
+
kill_time = Time.now + user_timeout
|
49
|
+
|
50
|
+
while (Time.now < kill_time) do
|
51
|
+
if result = scan(cid)
|
52
|
+
break
|
53
|
+
else
|
54
|
+
puts "waiting"
|
55
|
+
sleep POLLS_PERIOD
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
def scan(cid)
|
62
|
+
request = Net::HTTP::Post.new url.path,
|
63
|
+
'username' => @login,
|
64
|
+
'password' => Digest::SHA1.hexdigest(@password),
|
65
|
+
'is_hashed' => 1,
|
66
|
+
'swid' => SOFTWARE_VENDOR_ID,
|
67
|
+
'version' => API_VERSION
|
68
|
+
end
|
69
|
+
|
70
|
+
def remove(cid)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
require 'json'
|
3
|
+
require 'socket'
|
4
|
+
require 'base64'
|
5
|
+
|
6
|
+
module Decaptcha
|
7
|
+
module Provider
|
8
|
+
module DeathByCaptcha
|
9
|
+
class Socket < Decaptcha::Provider::DeathByCaptcha::Base
|
10
|
+
API_SERVER_HOST = 'deathbycaptcha.com'
|
11
|
+
API_SERVER_FIRST_PORT = 8123
|
12
|
+
API_SERVER_LAST_PORT = 8130
|
13
|
+
API_VERSION = 'DBC/Ruby v3.0'
|
14
|
+
SOFTWARE_VENDOR_ID = 0
|
15
|
+
|
16
|
+
DEFAULT_TIMEOUT = 60
|
17
|
+
POLLS_COUNT = 4
|
18
|
+
POLLS_PERIOD = 15
|
19
|
+
POLLS_INTERVAL = 5
|
20
|
+
|
21
|
+
def upload(args = {})
|
22
|
+
filename = args[:filename]
|
23
|
+
|
24
|
+
options = { :cmd => 'upload',
|
25
|
+
:captcha => Base64::encode64(File.read(filename)) }
|
26
|
+
|
27
|
+
data = make_request(options)
|
28
|
+
|
29
|
+
if data.nil? || data.empty?
|
30
|
+
raise UploadError
|
31
|
+
end
|
32
|
+
|
33
|
+
build_response(data)
|
34
|
+
end
|
35
|
+
|
36
|
+
def upload_and_poll(args = {})
|
37
|
+
user_timeout = args[:timeout] || DEFAULT_TIMEOUT
|
38
|
+
response = upload(args)
|
39
|
+
kill_time = Time.now + user_timeout
|
40
|
+
|
41
|
+
response = ''
|
42
|
+
while (Time.now < kill_time) do
|
43
|
+
response = result(response)
|
44
|
+
|
45
|
+
if response.text
|
46
|
+
break
|
47
|
+
elsif response.invalid
|
48
|
+
raise InvalidationError, response
|
49
|
+
else
|
50
|
+
sleep POLLS_PERIOD
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# remove...
|
55
|
+
|
56
|
+
response
|
57
|
+
end
|
58
|
+
|
59
|
+
def result(response_obj)
|
60
|
+
options = { :cmd => 'get_text', :captcha => response_obj.id }
|
61
|
+
data = make_request(options)
|
62
|
+
|
63
|
+
if data.nil? || data.empty?
|
64
|
+
raise ResultError
|
65
|
+
end
|
66
|
+
|
67
|
+
build_response(data)
|
68
|
+
end
|
69
|
+
|
70
|
+
def delete(response_obj)
|
71
|
+
params = {
|
72
|
+
:username => @login,
|
73
|
+
:password => Digest::SHA1.hexdigest(@password),
|
74
|
+
:is_hashed => 1,
|
75
|
+
:swid => SOFTWARE_VENDOR_ID,
|
76
|
+
:version => API_VERSION
|
77
|
+
}
|
78
|
+
|
79
|
+
delete_url = "#{response_obj.location}/remove"
|
80
|
+
|
81
|
+
RestClient.post delete_url, params, :accept => :json do |response, request, result|
|
82
|
+
if response.code == 200
|
83
|
+
response_obj.deleted = true
|
84
|
+
else
|
85
|
+
raise DeletionError
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
response_obj
|
90
|
+
end
|
91
|
+
|
92
|
+
def invalid(response_obj)
|
93
|
+
params = {
|
94
|
+
:username => @login,
|
95
|
+
:password => Digest::SHA1.hexdigest(@password),
|
96
|
+
:is_hashed => 1,
|
97
|
+
:swid => SOFTWARE_VENDOR_ID,
|
98
|
+
:version => API_VERSION
|
99
|
+
}
|
100
|
+
|
101
|
+
invalidation_url = "#{response_obj.location}/report"
|
102
|
+
|
103
|
+
RestClient.post invalidation_url, params, :accept => :json do |response, request, result|
|
104
|
+
if response.code == 200
|
105
|
+
response_obj.invalid = true
|
106
|
+
else
|
107
|
+
raise InvalidationError, response
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
response_obj
|
112
|
+
end
|
113
|
+
|
114
|
+
def make_request(options)
|
115
|
+
host = TCPSocket.getaddress API_SERVER_HOST
|
116
|
+
port = API_SERVER_FIRST_PORT + rand(API_SERVER_LAST_PORT - API_SERVER_FIRST_PORT + 1)
|
117
|
+
|
118
|
+
connection = TCPSocket.new(host, port)
|
119
|
+
connection.write compile_params(options).to_json
|
120
|
+
|
121
|
+
buffer = ""
|
122
|
+
|
123
|
+
while data = connection.read(1000)
|
124
|
+
buffer = buffer + data
|
125
|
+
end
|
126
|
+
|
127
|
+
connection.close
|
128
|
+
|
129
|
+
JSON.parse buffer rescue nil
|
130
|
+
end
|
131
|
+
|
132
|
+
def build_response(data)
|
133
|
+
response = Decaptcha::Response.new
|
134
|
+
response.id = data['captcha']
|
135
|
+
response.text = data['text']
|
136
|
+
response.invalid = !data['is_correct']
|
137
|
+
response.banned = data['banned']
|
138
|
+
response.balance = data['balance']
|
139
|
+
response
|
140
|
+
end
|
141
|
+
|
142
|
+
def compile_params(additional_params)
|
143
|
+
params = {
|
144
|
+
:username => @login,
|
145
|
+
:password => Digest::SHA1.hexdigest(@password),
|
146
|
+
:is_hashed => 1,
|
147
|
+
:swid => SOFTWARE_VENDOR_ID,
|
148
|
+
:version => API_VERSION
|
149
|
+
}
|
150
|
+
|
151
|
+
params.merge additional_params
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Decaptcha
|
2
|
+
class Response
|
3
|
+
attr_accessor :id
|
4
|
+
attr_accessor :location
|
5
|
+
attr_accessor :text
|
6
|
+
attr_accessor :status
|
7
|
+
attr_accessor :invalid
|
8
|
+
attr_accessor :deleted
|
9
|
+
attr_accessor :balance
|
10
|
+
attr_accessor :banned
|
11
|
+
|
12
|
+
def self.new_from_location location
|
13
|
+
r = Response.new
|
14
|
+
r.location = location
|
15
|
+
location =~ /(\d+)\Z/
|
16
|
+
r.id = $1
|
17
|
+
r
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/spec/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
describe "Decaptcha::Provider::DeathByCaptcha" do
|
6
|
+
it "should should be able to log in" do
|
7
|
+
client = Decaptcha::Client.new('dbc_http', { :login => '', :password => '' })
|
8
|
+
|
9
|
+
client.provider.login.should == ''
|
10
|
+
client.provider.password.should == ''
|
11
|
+
end
|
12
|
+
|
13
|
+
before(:each) do
|
14
|
+
@client = Decaptcha::Client.new :dbc_http, :login => '', :password => ''
|
15
|
+
end
|
16
|
+
|
17
|
+
# it "should be able to upload a captcha filename" do
|
18
|
+
# result = @client.upload :filename => CAPCHTA_FIXTURES_DIR + 'recaptcha1.jpg'
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# it "should be able to upload a captcha filename" do
|
22
|
+
# result = @client.upload_and_poll :filename => CAPCHTA_FIXTURES_DIR + 'recaptcha1.jpg'
|
23
|
+
# end
|
24
|
+
|
25
|
+
it "should query a response" do
|
26
|
+
response = @client.result Decaptcha::Response.new_from_location "http://www.deathbycaptcha.com/api/captcha/35703609"
|
27
|
+
response.text.should == 'retch vileteed'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should query a response which was marked as invalid" do
|
31
|
+
response = @client.result Decaptcha::Response.new_from_location "http://www.deathbycaptcha.com/api/captcha/35605900"
|
32
|
+
response.text.should == 'Lwis disherve'
|
33
|
+
response.status.should be_false
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should delete a captcha" do
|
37
|
+
response = @client.delete Decaptcha::Response.new_from_location "http://www.deathbycaptcha.com/api/captcha/35711664"
|
38
|
+
response.deleted.should be_true
|
39
|
+
end
|
40
|
+
|
41
|
+
#it "should mark a captcha as invalid" do
|
42
|
+
# upload = @client.upload :filename => CAPCHTA_FIXTURES_DIR + 'recaptcha3.jpg'
|
43
|
+
# response = @client.invalid upload
|
44
|
+
# response.invalid.should be_true
|
45
|
+
#end
|
46
|
+
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
describe "Decaptcha::Provider::DeathByCaptcha" do
|
6
|
+
it "should should be able to log in" do
|
7
|
+
client = Decaptcha::Client.new('dbc_socket', { :login => '', :password => '' })
|
8
|
+
|
9
|
+
client.provider.login.should == ''
|
10
|
+
client.provider.password.should == ''
|
11
|
+
end
|
12
|
+
|
13
|
+
before(:each) do
|
14
|
+
@client = Decaptcha::Client.new :dbc_socket, :login => '', :password => ''
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should be able to upload a captcha filename" do
|
18
|
+
result = @client.upload :filename => CAPCHTA_FIXTURES_DIR + 'recaptcha1.jpg'
|
19
|
+
result.id.should == 35703609
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
it "should be able to upload a captcha filename" do
|
24
|
+
result = @client.upload_and_poll :filename => CAPCHTA_FIXTURES_DIR + 'recaptcha1.jpg'
|
25
|
+
result.id.should == 35703609
|
26
|
+
end
|
27
|
+
|
28
|
+
#it "should query a response" do
|
29
|
+
# response = @client.result Decaptcha::Response.new_from_location "http://www.deathbycaptcha.com/api/captcha/35703609"
|
30
|
+
# response.text.should == 'retch vileteed'
|
31
|
+
#end
|
32
|
+
#
|
33
|
+
#it "should query a response which was marked as invalid" do
|
34
|
+
# response = @client.result Decaptcha::Response.new_from_location "http://www.deathbycaptcha.com/api/captcha/35605900"
|
35
|
+
# response.text.should == 'Lwis disherve'
|
36
|
+
# response.status.should be_false
|
37
|
+
#end
|
38
|
+
#
|
39
|
+
#it "should delete a captcha" do
|
40
|
+
# response = @client.delete Decaptcha::Response.new_from_location "http://www.deathbycaptcha.com/api/captcha/35711664"
|
41
|
+
# response.deleted.should be_true
|
42
|
+
#end
|
43
|
+
|
44
|
+
#it "should mark a captcha as invalid" do
|
45
|
+
# upload = @client.upload :filename => CAPCHTA_FIXTURES_DIR + 'recaptcha3.jpg'
|
46
|
+
# response = @client.invalid upload
|
47
|
+
# response.invalid.should be_true
|
48
|
+
#end
|
49
|
+
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "Decaptcha::Client" do
|
4
|
+
it "should instantiate" do
|
5
|
+
Decaptcha::Client.new(:dbc_http).should be_a_kind_of(Decaptcha::Client)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should set a provider by class name" do
|
9
|
+
client = Decaptcha::Client.new :dbc_http
|
10
|
+
client.provider.should be_a_kind_of(Decaptcha::Provider::DeathByCaptcha::HTTP)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should set a provider with provider instance" do
|
14
|
+
client = Decaptcha::Client.new :dbc_http
|
15
|
+
client.provider.should be_a_kind_of(Decaptcha::Provider::DeathByCaptcha::HTTP)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
begin
|
3
|
+
Bundler.setup(:default, :development)
|
4
|
+
rescue Bundler::BundlerError => e
|
5
|
+
$stderr.puts e.message
|
6
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
7
|
+
exit e.status_code
|
8
|
+
end
|
9
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
10
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
11
|
+
require 'decaptcha'
|
12
|
+
require 'rspec'
|
13
|
+
|
14
|
+
CAPCHTA_FIXTURES_DIR = File.join(File.dirname(__FILE__), 'fixtures', 'captchas', '/')
|
15
|
+
|
16
|
+
# Requires supporting files with custom matchers and macros, etc,
|
17
|
+
# in ./support/ and its subdirectories.
|
18
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
19
|
+
|
20
|
+
RSpec.configure do |config|
|
21
|
+
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: decaptcha
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 31
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 0.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- "Dirty S\xC3\xA1nchez"
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-10-23 00:00:00 +02:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: helps poor senior data entry specialists in developing countries
|
23
|
+
email:
|
24
|
+
- rmoriz@gmail.com
|
25
|
+
executables: []
|
26
|
+
|
27
|
+
extensions: []
|
28
|
+
|
29
|
+
extra_rdoc_files: []
|
30
|
+
|
31
|
+
files:
|
32
|
+
- .document
|
33
|
+
- .gitignore
|
34
|
+
- Gemfile
|
35
|
+
- Gemfile.lock
|
36
|
+
- LICENSE
|
37
|
+
- README.rdoc
|
38
|
+
- Rakefile
|
39
|
+
- autotest/discover.rb
|
40
|
+
- decaptcha.gemspec
|
41
|
+
- lib/decaptcha.rb
|
42
|
+
- lib/decaptcha/client.rb
|
43
|
+
- lib/decaptcha/provider.rb
|
44
|
+
- lib/decaptcha/provider/base.rb
|
45
|
+
- lib/decaptcha/provider/death_by_captcha/base.rb
|
46
|
+
- lib/decaptcha/provider/death_by_captcha/http.rb
|
47
|
+
- lib/decaptcha/provider/death_by_captcha/http_old.rb
|
48
|
+
- lib/decaptcha/provider/death_by_captcha/socket.rb
|
49
|
+
- lib/decaptcha/provider/error.rb
|
50
|
+
- lib/decaptcha/response.rb
|
51
|
+
- spec/.rspec
|
52
|
+
- spec/decaptcha_provider_death_by_captcha_http_spec.rb
|
53
|
+
- spec/decaptcha_provider_death_by_captcha_socket_spec.rb
|
54
|
+
- spec/decaptcha_spec.rb
|
55
|
+
- spec/fixtures/captchas/recaptcha1.jpg
|
56
|
+
- spec/fixtures/captchas/recaptcha2.jpg
|
57
|
+
- spec/fixtures/captchas/recaptcha3.jpg
|
58
|
+
- spec/spec_helper.rb
|
59
|
+
has_rdoc: true
|
60
|
+
homepage: http://rubygems.org/gems/decaptcha
|
61
|
+
licenses: []
|
62
|
+
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
hash: 3
|
74
|
+
segments:
|
75
|
+
- 0
|
76
|
+
version: "0"
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
hash: 3
|
83
|
+
segments:
|
84
|
+
- 0
|
85
|
+
version: "0"
|
86
|
+
requirements: []
|
87
|
+
|
88
|
+
rubyforge_project: decaptcha
|
89
|
+
rubygems_version: 1.3.7
|
90
|
+
signing_key:
|
91
|
+
specification_version: 3
|
92
|
+
summary: helps poor senior data entry specialists in developing countries
|
93
|
+
test_files:
|
94
|
+
- spec/decaptcha_provider_death_by_captcha_http_spec.rb
|
95
|
+
- spec/decaptcha_provider_death_by_captcha_socket_spec.rb
|
96
|
+
- spec/decaptcha_spec.rb
|
97
|
+
- spec/fixtures/captchas/recaptcha1.jpg
|
98
|
+
- spec/fixtures/captchas/recaptcha2.jpg
|
99
|
+
- spec/fixtures/captchas/recaptcha3.jpg
|
100
|
+
- spec/spec_helper.rb
|