rucaptcha 2.5.2 → 2.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +34 -191
- data/README.md +6 -3
- data/app/controllers/ru_captcha/captcha_controller.rb +4 -3
- data/config/routes.rb +1 -1
- data/ext/rucaptcha/colors.h +265 -18
- data/ext/rucaptcha/extconf.rb +2 -2
- data/ext/rucaptcha/rucaptcha.c +172 -111
- data/lib/rucaptcha/cache.rb +2 -1
- data/lib/rucaptcha/controller_helpers.rb +28 -21
- data/lib/rucaptcha/engine.rb +2 -2
- data/lib/rucaptcha/version.rb +1 -1
- data/lib/rucaptcha/view_helpers.rb +10 -9
- data/lib/rucaptcha.rb +25 -26
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 43b066933f98fbca0c17c9399112a974f4d012bebeaa12975eef9a9e8cd03c74
|
4
|
+
data.tar.gz: 106d354acfaa8850da0f11ae92d2e3268603e3582951aefec484d03d4f2e8635
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0e0389c00e0a44deae317c609eae2a3ff716e125f0c485b37cd32a659ff60b152e945f6c8cf2691f815ee4da5531663d35ec15e8df0b1820d161f0ec7ec7dad
|
7
|
+
data.tar.gz: af4b7c997648efa973e81f19c187ecd8710c5c0e5884b6c9c42ae8d6ac98f48bf49b1ebf867a707c73fbd9ce8629c9d0d9835182463e8effa91bdd8be2e62c83
|
data/CHANGELOG.md
CHANGED
@@ -1,88 +1,89 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
New release please visit:
|
2
|
+
|
3
|
+
https://github.com/huacnlee/rucaptcha/releases
|
4
|
+
|
5
|
+
## 2.5.5
|
6
|
+
|
7
|
+
- Improved image for thicker interference lines.
|
8
|
+
- Add more colors.
|
9
|
+
|
10
|
+
## 2.5.4
|
11
|
+
|
12
|
+
- Fix: rucaptcha input maxlength attribute with config value.
|
13
|
+
|
14
|
+
## 2.5.3
|
15
|
+
|
16
|
+
- Fix session invalid warning, only for development env;
|
17
|
+
|
18
|
+
## 2.5.2
|
3
19
|
|
4
20
|
- Fix session.id error with upgrade Rails 6.0.2.1 or Rack 2.0.8 (#84)
|
5
21
|
|
6
|
-
2.5.1
|
7
|
-
-------
|
22
|
+
## 2.5.1
|
8
23
|
|
9
24
|
- Fix invalid module name error. (#78)
|
10
25
|
|
11
|
-
2.5.0
|
12
|
-
-------
|
26
|
+
## 2.5.0
|
13
27
|
|
14
28
|
- Support click captcha image to refresh new one by default.
|
15
29
|
- Use simple tag helper generate captcha img html, for avoid asset_host (#73).
|
16
30
|
|
17
|
-
2.4.0
|
18
|
-
-------
|
31
|
+
## 2.4.0
|
19
32
|
|
20
33
|
- Add skip_cache_store_check configuration. (#63)
|
21
34
|
- Fix for generate captcha with relative path, not url. (#58)
|
22
35
|
|
23
|
-
2.3.2
|
24
|
-
-------
|
36
|
+
## 2.3.2
|
25
37
|
|
26
38
|
- Change Yellow and Green colors to Pink and Deep Purple to pass WCAG 2.0's contrast test. (#70)
|
27
39
|
|
28
|
-
2.3.1
|
29
|
-
-------
|
40
|
+
## 2.3.1
|
30
41
|
|
31
42
|
- Fix #67 a y chars will invalid error (only in 2.3.0).
|
32
43
|
|
33
|
-
2.3.0
|
34
|
-
-------
|
44
|
+
## 2.3.0
|
35
45
|
|
36
46
|
- Add `config.outline` for use outline style.
|
37
47
|
- Reduce colors down to 5 (red, blue, green, yellow and black).
|
38
48
|
|
39
|
-
2.2.0
|
40
|
-
-----
|
49
|
+
## 2.2.0
|
41
50
|
|
42
51
|
- Add option `config.length` for support change number chars. (#57)
|
43
52
|
- Add option `config.strikethrough` for enable or disable strikethrough. (#57)
|
44
53
|
|
45
|
-
2.1.3
|
46
|
-
-----
|
54
|
+
## 2.1.3
|
47
55
|
|
48
56
|
- Windows support fixed with `send_data` method. (#45)
|
49
57
|
|
50
|
-
2.1.2
|
51
|
-
-----
|
58
|
+
## 2.1.2
|
52
59
|
|
53
60
|
- Do not change captcha when `HEAD /rucaptcha`.
|
54
61
|
|
55
|
-
2.1.1
|
56
|
-
-----
|
62
|
+
## 2.1.1
|
57
63
|
|
58
64
|
- Mount engine use `prepend` method to get high priority in config/routes.rb.
|
59
65
|
|
60
|
-
2.1.0
|
61
|
-
-----
|
66
|
+
## 2.1.0
|
62
67
|
|
63
68
|
- Mount Router by default, not need config now.
|
64
69
|
|
65
70
|
> IMPORTANT: Wen you upgrade this version, you need remove `mount RuCaptcha::Engine` line from your `config/routes.rb`
|
71
|
+
|
66
72
|
- Default use [:file_store, 'tmp/cache/rucaptcha/session'] as RuCaptcha.config.cache_store, now it can work without any configurations.
|
67
73
|
|
68
74
|
> NOTE: But you still need care about `config.cache_store` to setup on a right way.
|
69
75
|
|
70
|
-
|
71
|
-
|
72
|
-
2.0.3
|
73
|
-
-----
|
76
|
+
## 2.0.3
|
74
77
|
|
75
78
|
- Use `ActiveSupport.on_load` to extend ActionController and ActionView.
|
76
79
|
|
77
|
-
2.0.1
|
78
|
-
-----
|
80
|
+
## 2.0.1
|
79
81
|
|
80
82
|
- Fix `/rucaptcha` path issue when `config.action_controller.asset_host` has setup with CDN url.
|
81
83
|
|
82
|
-
2.0.0
|
83
|
-
-----
|
84
|
+
## 2.0.0
|
84
85
|
|
85
|
-
|
86
|
+
_Break Changes!_
|
86
87
|
|
87
88
|
WARNING!: This version have so many break changes!
|
88
89
|
|
@@ -90,161 +91,3 @@ WARNING!: This version have so many break changes!
|
|
90
91
|
- New captcha style.
|
91
92
|
- Remove `len`, `font_size`, `cache_limit` config key, no support now.
|
92
93
|
- Output `GIF` format.
|
93
|
-
|
94
|
-
1.2.0
|
95
|
-
-----
|
96
|
-
|
97
|
-
- Add an `:keep_session` option for `verify_rucaptcha?` method to giva a way for let you keep session on verify, if true, RuCaptcha will not delete the captcha code session after validation.
|
98
|
-
|
99
|
-
1.1.4
|
100
|
-
-----
|
101
|
-
|
102
|
-
- Fix #35 just give a warning message if not setup a right cache_store, only raise on :null_store.
|
103
|
-
|
104
|
-
1.1.2
|
105
|
-
-----
|
106
|
-
|
107
|
-
- Fix #34 rucaptcha.root_url -> root_path, to avoid generate a http url in a https application.
|
108
|
-
- Fix spec to require Ruby 2.0.0, because there have a `Module#prepend` method called.
|
109
|
-
|
110
|
-
1.1.1
|
111
|
-
-----
|
112
|
-
|
113
|
-
- Remove inspect log on verify_rucaptcha
|
114
|
-
|
115
|
-
1.1.0
|
116
|
-
-----
|
117
|
-
|
118
|
-
- Add `cache_store` config key to setup a cache store location for RuCaptcha.
|
119
|
-
- Store captcha in custom cache store.
|
120
|
-
|
121
|
-
## Security Notes
|
122
|
-
|
123
|
-
- Fix Session replay secure issue that when Rails application use CookieStore.
|
124
|
-
|
125
|
-
1.0.0
|
126
|
-
-----
|
127
|
-
|
128
|
-
- Adjust to avoid lighter colors.
|
129
|
-
- Avoid continuous chars have same color.
|
130
|
-
- Use same color for each chars in :black_white mode.
|
131
|
-
|
132
|
-
0.5.1
|
133
|
-
-----
|
134
|
-
|
135
|
-
- Make sure it will render image when ImageMagick stderr have warning messages. (#26)
|
136
|
-
|
137
|
-
0.5.0
|
138
|
-
-----
|
139
|
-
|
140
|
-
- Fix cache with Rails 5.
|
141
|
-
|
142
|
-
0.4.5
|
143
|
-
-----
|
144
|
-
|
145
|
-
- Removed `posix-spawn` dependency, used open3 instead (core funciontality), JRuby compatible (#24)
|
146
|
-
|
147
|
-
0.4.4
|
148
|
-
-----
|
149
|
-
|
150
|
-
- Remove deprecated `width`, `height` config.
|
151
|
-
- Delete session key after verify (#23).
|
152
|
-
- Lighter text color, improve style.
|
153
|
-
|
154
|
-
0.4.2
|
155
|
-
-----
|
156
|
-
|
157
|
-
- Fix NoMethodError bug when params[:_rucaptha] is nil.
|
158
|
-
|
159
|
-
0.4.1
|
160
|
-
-----
|
161
|
-
|
162
|
-
- Add error message to resource when captcha code expired.
|
163
|
-
|
164
|
-
0.4.0
|
165
|
-
-----
|
166
|
-
|
167
|
-
- Add `config.colorize` option, to allow use black text theme.
|
168
|
-
|
169
|
-
0.3.3
|
170
|
-
-----
|
171
|
-
|
172
|
-
- Add `config.expires_in` to allow change captcha code expire time.
|
173
|
-
|
174
|
-
0.3.2.1
|
175
|
-
-------
|
176
|
-
|
177
|
-
- Add Windows development env support.
|
178
|
-
|
179
|
-
0.3.2
|
180
|
-
-----
|
181
|
-
|
182
|
-
- Make better render positions;
|
183
|
-
- Trim blank space.
|
184
|
-
|
185
|
-
0.3.1
|
186
|
-
-----
|
187
|
-
|
188
|
-
- More complex Image render: compact text, strong lines, +/-5 rotate...
|
189
|
-
- [DEPRECATION] config.width, config.height removed, use config.font_size.
|
190
|
-
- Fix the render position in difference font sizes.
|
191
|
-
- Fix input field type, and disable autocorrect, autocapitalize, and limit maxlength with char length;
|
192
|
-
|
193
|
-
0.2.5
|
194
|
-
-----
|
195
|
-
|
196
|
-
- Add `session[:_rucaptcha]` expire time, for protect Rails CookieSession Replay Attack.
|
197
|
-
- Captcha input field disable autocomplete, and set field type as `email` for shown correct keyboard on mobile view.
|
198
|
-
|
199
|
-
0.2.3
|
200
|
-
-----
|
201
|
-
|
202
|
-
- It will raise error when call ImageMagick failed.
|
203
|
-
|
204
|
-
0.2.2
|
205
|
-
-----
|
206
|
-
|
207
|
-
- Added locale for pt-BR language; @ramirovjr
|
208
|
-
|
209
|
-
0.2.1
|
210
|
-
-----
|
211
|
-
|
212
|
-
- Fix issue when cache dir not exist.
|
213
|
-
|
214
|
-
0.2.0
|
215
|
-
-----
|
216
|
-
|
217
|
-
- Added file cache, can setup how many images you want generate by `config.cache_limit`,
|
218
|
-
RuCaptcha will use cache for next requests.
|
219
|
-
When you restart Rails processes it will generate new again and clean the old caches.
|
220
|
-
|
221
|
-
0.1.4
|
222
|
-
-----
|
223
|
-
|
224
|
-
- Fix `verify_rucaptcha?` logic in somecase.
|
225
|
-
- Locales fixed.
|
226
|
-
|
227
|
-
0.1.3
|
228
|
-
-----
|
229
|
-
|
230
|
-
- `zh-TW` translate file fixed.
|
231
|
-
- Use xxx_url to fix bad captcha URL for `config.action_controller.asset_host` enabled case.
|
232
|
-
|
233
|
-
0.1.2
|
234
|
-
-----
|
235
|
-
|
236
|
-
- No case sensitive;
|
237
|
-
- Export config.implode;
|
238
|
-
- Improve image color and style;
|
239
|
-
- Don't generate chars in 'l,o,0,1'.
|
240
|
-
- Render lower case chars on image.
|
241
|
-
|
242
|
-
0.1.1
|
243
|
-
-----
|
244
|
-
|
245
|
-
- Include default validation I18n messages (en, zh-CN, zh-TW).
|
246
|
-
|
247
|
-
0.1.0
|
248
|
-
-----
|
249
|
-
|
250
|
-
- First release.
|
data/README.md
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
# RuCaptcha
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/rucaptcha.svg)](https://badge.fury.io/rb/rucaptcha)
|
4
|
-
[![
|
4
|
+
[![build](https://github.com/huacnlee/rucaptcha/workflows/build/badge.svg)](https://github.com/huacnlee/rucaptcha/actions?query=workflow%3Abuild)
|
5
5
|
|
6
6
|
This is a Captcha gem for Rails Applications which generates captcha image by C code.
|
7
7
|
|
8
|
-
> NOTE: According to the use of Ruby China, the verification code looks like has a lower than 5% probability of being parsed by OCR and the verification code is cracked. It is recommended that you use the IP rate limit to enhance the protection.
|
9
|
-
> NOTE: 以 Ruby China 的使用来看,验证码似乎有低于 5% 的概率被 OCR
|
8
|
+
> NOTE: According to the use of Ruby China, the verification code looks like has a lower than 5% probability of being parsed by OCR and the verification code is cracked (All Image Captcha libs are has same problem). It is recommended that you use the IP rate limit to enhance the protection.
|
9
|
+
> NOTE: 以 Ruby China 的使用来看,验证码似乎有低于 5% 的概率被 OCR 读取解析 (图片验证码都有这个问题) 导致验证码被破解(我们从日志分析绝大多数是成功的,但偶尔一个成功,配合大量机器攻击,导致注册了很多的垃圾账号),建议你额外配合 IP 频率限制的功能来加强保护。
|
10
|
+
|
11
|
+
> 如果你需要更高强度的验证,建议选择商用服务。
|
10
12
|
|
11
13
|
[中文介绍和使用说明](https://ruby-china.org/topics/27832)
|
12
14
|
|
@@ -64,6 +66,7 @@ RuCaptcha 没有使用 Rails Session 来存储验证码信息,因为 Rails 的
|
|
64
66
|
所以,我建议大家使用的时候,配置上 `cache_store` (详见 [Rails Guides 缓存配置部分](https://ruby-china.github.io/rails-guides/caching_with_rails.html#%E9%85%8D%E7%BD%AE)的文档)到一个 Memcached 或 Redis,这才是最佳实践。
|
65
67
|
|
66
68
|
#
|
69
|
+
|
67
70
|
(RuCaptha do not use Rails Session to store captcha information. As the default session is stored in Cookie in Rails, there's a [Replay attack](https://en.wikipedia.org/wiki/Replay_attack) bug which may causes capthcha being destroyed if we store captcha in Rails Session.
|
68
71
|
|
69
72
|
So in my design I require RuCaptcha to configure a distributed backend storage scheme, such as Memcached, Redis or other cache_store schemes which support distribution.
|
@@ -2,10 +2,11 @@ module RuCaptcha
|
|
2
2
|
class CaptchaController < ActionController::Base
|
3
3
|
def index
|
4
4
|
return head :ok if request.head?
|
5
|
-
|
6
|
-
headers[
|
5
|
+
|
6
|
+
headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate"
|
7
|
+
headers["Pragma"] = "no-cache"
|
7
8
|
data = generate_rucaptcha
|
8
|
-
opts = {
|
9
|
+
opts = {disposition: "inline", type: "image/gif"}
|
9
10
|
send_data data, opts
|
10
11
|
end
|
11
12
|
end
|
data/config/routes.rb
CHANGED
data/ext/rucaptcha/colors.h
CHANGED
@@ -40,7 +40,45 @@ static char *colors[] = {
|
|
40
40
|
"\xD5\x00\x00"
|
41
41
|
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
42
42
|
|
43
|
-
//
|
43
|
+
// Red #B71C1C
|
44
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
45
|
+
"\xB7\x1C\x1C"
|
46
|
+
"\xB7\x1C\x1C"
|
47
|
+
"\xB7\x1C\x1C"
|
48
|
+
"\xB7\x1C\x1C"
|
49
|
+
"\xB7\x1C\x1C"
|
50
|
+
"\xB7\x1C\x1C"
|
51
|
+
"\xB7\x1C\x1C"
|
52
|
+
"\xB7\x1C\x1C"
|
53
|
+
"\xB7\x1C\x1C"
|
54
|
+
"\xB7\x1C\x1C"
|
55
|
+
"\xB7\x1C\x1C"
|
56
|
+
"\xB7\x1C\x1C"
|
57
|
+
"\xB7\x1C\x1C"
|
58
|
+
"\xB7\x1C\x1C"
|
59
|
+
"\xB7\x1C\x1C"
|
60
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
61
|
+
|
62
|
+
// Red #E53935
|
63
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
64
|
+
"\xE5\x39\x35"
|
65
|
+
"\xE5\x39\x35"
|
66
|
+
"\xE5\x39\x35"
|
67
|
+
"\xE5\x39\x35"
|
68
|
+
"\xE5\x39\x35"
|
69
|
+
"\xE5\x39\x35"
|
70
|
+
"\xE5\x39\x35"
|
71
|
+
"\xE5\x39\x35"
|
72
|
+
"\xE5\x39\x35"
|
73
|
+
"\xE5\x39\x35"
|
74
|
+
"\xE5\x39\x35"
|
75
|
+
"\xE5\x39\x35"
|
76
|
+
"\xE5\x39\x35"
|
77
|
+
"\xE5\x39\x35"
|
78
|
+
"\xE5\x39\x35"
|
79
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
80
|
+
|
81
|
+
// Orange A700 #DD2C00
|
44
82
|
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
45
83
|
"\xDD\x2C\x00"
|
46
84
|
"\xDD\x2C\x00"
|
@@ -59,7 +97,140 @@ static char *colors[] = {
|
|
59
97
|
"\xDD\x2C\x00"
|
60
98
|
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
61
99
|
|
62
|
-
//
|
100
|
+
// Orange #FF3D00
|
101
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
102
|
+
"\xFF\x3D\x00"
|
103
|
+
"\xFF\x3D\x00"
|
104
|
+
"\xFF\x3D\x00"
|
105
|
+
"\xFF\x3D\x00"
|
106
|
+
"\xFF\x3D\x00"
|
107
|
+
"\xFF\x3D\x00"
|
108
|
+
"\xFF\x3D\x00"
|
109
|
+
"\xFF\x3D\x00"
|
110
|
+
"\xFF\x3D\x00"
|
111
|
+
"\xFF\x3D\x00"
|
112
|
+
"\xFF\x3D\x00"
|
113
|
+
"\xFF\x3D\x00"
|
114
|
+
"\xFF\x3D\x00"
|
115
|
+
"\xFF\x3D\x00"
|
116
|
+
"\xFF\x3D\x00"
|
117
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
118
|
+
|
119
|
+
// Orange #BF360C
|
120
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
121
|
+
"\xBF\x36\x0C"
|
122
|
+
"\xBF\x36\x0C"
|
123
|
+
"\xBF\x36\x0C"
|
124
|
+
"\xBF\x36\x0C"
|
125
|
+
"\xBF\x36\x0C"
|
126
|
+
"\xBF\x36\x0C"
|
127
|
+
"\xBF\x36\x0C"
|
128
|
+
"\xBF\x36\x0C"
|
129
|
+
"\xBF\x36\x0C"
|
130
|
+
"\xBF\x36\x0C"
|
131
|
+
"\xBF\x36\x0C"
|
132
|
+
"\xBF\x36\x0C"
|
133
|
+
"\xBF\x36\x0C"
|
134
|
+
"\xBF\x36\x0C"
|
135
|
+
"\xBF\x36\x0C"
|
136
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
137
|
+
|
138
|
+
// Orange #FF6D00
|
139
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
140
|
+
"\xFF\x6D\x00"
|
141
|
+
"\xFF\x6D\x00"
|
142
|
+
"\xFF\x6D\x00"
|
143
|
+
"\xFF\x6D\x00"
|
144
|
+
"\xFF\x6D\x00"
|
145
|
+
"\xFF\x6D\x00"
|
146
|
+
"\xFF\x6D\x00"
|
147
|
+
"\xFF\x6D\x00"
|
148
|
+
"\xFF\x6D\x00"
|
149
|
+
"\xFF\x6D\x00"
|
150
|
+
"\xFF\x6D\x00"
|
151
|
+
"\xFF\x6D\x00"
|
152
|
+
"\xFF\x6D\x00"
|
153
|
+
"\xFF\x6D\x00"
|
154
|
+
"\xFF\x6D\x00"
|
155
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
156
|
+
|
157
|
+
// Green #00C853
|
158
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
159
|
+
"\x00\xC8\x53"
|
160
|
+
"\x00\xC8\x53"
|
161
|
+
"\x00\xC8\x53"
|
162
|
+
"\x00\xC8\x53"
|
163
|
+
"\x00\xC8\x53"
|
164
|
+
"\x00\xC8\x53"
|
165
|
+
"\x00\xC8\x53"
|
166
|
+
"\x00\xC8\x53"
|
167
|
+
"\x00\xC8\x53"
|
168
|
+
"\x00\xC8\x53"
|
169
|
+
"\x00\xC8\x53"
|
170
|
+
"\x00\xC8\x53"
|
171
|
+
"\x00\xC8\x53"
|
172
|
+
"\x00\xC8\x53"
|
173
|
+
"\x00\xC8\x53"
|
174
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
175
|
+
|
176
|
+
// Green #00C853
|
177
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
178
|
+
"\x00\xC8\x53"
|
179
|
+
"\x00\xC8\x53"
|
180
|
+
"\x00\xC8\x53"
|
181
|
+
"\x00\xC8\x53"
|
182
|
+
"\x00\xC8\x53"
|
183
|
+
"\x00\xC8\x53"
|
184
|
+
"\x00\xC8\x53"
|
185
|
+
"\x00\xC8\x53"
|
186
|
+
"\x00\xC8\x53"
|
187
|
+
"\x00\xC8\x53"
|
188
|
+
"\x00\xC8\x53"
|
189
|
+
"\x00\xC8\x53"
|
190
|
+
"\x00\xC8\x53"
|
191
|
+
"\x00\xC8\x53"
|
192
|
+
"\x00\xC8\x53"
|
193
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
194
|
+
|
195
|
+
// Green #64DD17
|
196
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
197
|
+
"\x64\xDD\x17"
|
198
|
+
"\x64\xDD\x17"
|
199
|
+
"\x64\xDD\x17"
|
200
|
+
"\x64\xDD\x17"
|
201
|
+
"\x64\xDD\x17"
|
202
|
+
"\x64\xDD\x17"
|
203
|
+
"\x64\xDD\x17"
|
204
|
+
"\x64\xDD\x17"
|
205
|
+
"\x64\xDD\x17"
|
206
|
+
"\x64\xDD\x17"
|
207
|
+
"\x64\xDD\x17"
|
208
|
+
"\x64\xDD\x17"
|
209
|
+
"\x64\xDD\x17"
|
210
|
+
"\x64\xDD\x17"
|
211
|
+
"\x64\xDD\x17"
|
212
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
213
|
+
|
214
|
+
// Blue #2E7D32
|
215
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
216
|
+
"\x2E\x7D\x32"
|
217
|
+
"\x2E\x7D\x32"
|
218
|
+
"\x2E\x7D\x32"
|
219
|
+
"\x2E\x7D\x32"
|
220
|
+
"\x2E\x7D\x32"
|
221
|
+
"\x2E\x7D\x32"
|
222
|
+
"\x2E\x7D\x32"
|
223
|
+
"\x2E\x7D\x32"
|
224
|
+
"\x2E\x7D\x32"
|
225
|
+
"\x2E\x7D\x32"
|
226
|
+
"\x2E\x7D\x32"
|
227
|
+
"\x2E\x7D\x32"
|
228
|
+
"\x2E\x7D\x32"
|
229
|
+
"\x2E\x7D\x32"
|
230
|
+
"\x2E\x7D\x32"
|
231
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
232
|
+
|
233
|
+
// Blue #2962FF
|
63
234
|
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
64
235
|
"\x29\x62\xFF"
|
65
236
|
"\x29\x62\xFF"
|
@@ -78,23 +249,61 @@ static char *colors[] = {
|
|
78
249
|
"\x29\x62\xFF"
|
79
250
|
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
80
251
|
|
81
|
-
//
|
252
|
+
// Blue #0D47A1
|
253
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
254
|
+
"\x0D\x47\xA1"
|
255
|
+
"\x0D\x47\xA1"
|
256
|
+
"\x0D\x47\xA1"
|
257
|
+
"\x0D\x47\xA1"
|
258
|
+
"\x0D\x47\xA1"
|
259
|
+
"\x0D\x47\xA1"
|
260
|
+
"\x0D\x47\xA1"
|
261
|
+
"\x0D\x47\xA1"
|
262
|
+
"\x0D\x47\xA1"
|
263
|
+
"\x0D\x47\xA1"
|
264
|
+
"\x0D\x47\xA1"
|
265
|
+
"\x0D\x47\xA1"
|
266
|
+
"\x0D\x47\xA1"
|
267
|
+
"\x0D\x47\xA1"
|
268
|
+
"\x0D\x47\xA1"
|
269
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
270
|
+
|
271
|
+
// Blue #1A237E
|
82
272
|
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
83
|
-
"\
|
84
|
-
"\
|
85
|
-
"\
|
86
|
-
"\
|
87
|
-
"\
|
88
|
-
"\
|
89
|
-
"\
|
90
|
-
"\
|
91
|
-
"\
|
92
|
-
"\
|
93
|
-
"\
|
94
|
-
"\
|
95
|
-
"\
|
96
|
-
"\
|
97
|
-
"\
|
273
|
+
"\x1A\x23\x7E"
|
274
|
+
"\x1A\x23\x7E"
|
275
|
+
"\x1A\x23\x7E"
|
276
|
+
"\x1A\x23\x7E"
|
277
|
+
"\x1A\x23\x7E"
|
278
|
+
"\x1A\x23\x7E"
|
279
|
+
"\x1A\x23\x7E"
|
280
|
+
"\x1A\x23\x7E"
|
281
|
+
"\x1A\x23\x7E"
|
282
|
+
"\x1A\x23\x7E"
|
283
|
+
"\x1A\x23\x7E"
|
284
|
+
"\x1A\x23\x7E"
|
285
|
+
"\x1A\x23\x7E"
|
286
|
+
"\x1A\x23\x7E"
|
287
|
+
"\x1A\x23\x7E"
|
288
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
289
|
+
|
290
|
+
// Blue #0091EA
|
291
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
292
|
+
"\x00\x91\xEA"
|
293
|
+
"\x00\x91\xEA"
|
294
|
+
"\x00\x91\xEA"
|
295
|
+
"\x00\x91\xEA"
|
296
|
+
"\x00\x91\xEA"
|
297
|
+
"\x00\x91\xEA"
|
298
|
+
"\x00\x91\xEA"
|
299
|
+
"\x00\x91\xEA"
|
300
|
+
"\x00\x91\xEA"
|
301
|
+
"\x00\x91\xEA"
|
302
|
+
"\x00\x91\xEA"
|
303
|
+
"\x00\x91\xEA"
|
304
|
+
"\x00\x91\xEA"
|
305
|
+
"\x00\x91\xEA"
|
306
|
+
"\x00\x91\xEA"
|
98
307
|
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
99
308
|
|
100
309
|
// Deep Purple A700 #6200EA
|
@@ -114,5 +323,43 @@ static char *colors[] = {
|
|
114
323
|
"\x62\x00\xEA"
|
115
324
|
"\x62\x00\xEA"
|
116
325
|
"\x62\x00\xEA"
|
326
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
327
|
+
|
328
|
+
// Pink #F50057
|
329
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
330
|
+
"\xF5\x00\x57"
|
331
|
+
"\xF5\x00\x57"
|
332
|
+
"\xF5\x00\x57"
|
333
|
+
"\xF5\x00\x57"
|
334
|
+
"\xF5\x00\x57"
|
335
|
+
"\xF5\x00\x57"
|
336
|
+
"\xF5\x00\x57"
|
337
|
+
"\xF5\x00\x57"
|
338
|
+
"\xF5\x00\x57"
|
339
|
+
"\xF5\x00\x57"
|
340
|
+
"\xF5\x00\x57"
|
341
|
+
"\xF5\x00\x57"
|
342
|
+
"\xF5\x00\x57"
|
343
|
+
"\xF5\x00\x57"
|
344
|
+
"\xF5\x00\x57"
|
345
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
346
|
+
|
347
|
+
// Deep Purple A700 #4A148C
|
348
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
349
|
+
"\x49\x14\x8C"
|
350
|
+
"\x49\x14\x8C"
|
351
|
+
"\x49\x14\x8C"
|
352
|
+
"\x49\x14\x8C"
|
353
|
+
"\x49\x14\x8C"
|
354
|
+
"\x49\x14\x8C"
|
355
|
+
"\x49\x14\x8C"
|
356
|
+
"\x49\x14\x8C"
|
357
|
+
"\x49\x14\x8C"
|
358
|
+
"\x49\x14\x8C"
|
359
|
+
"\x49\x14\x8C"
|
360
|
+
"\x49\x14\x8C"
|
361
|
+
"\x49\x14\x8C"
|
362
|
+
"\x49\x14\x8C"
|
363
|
+
"\x49\x14\x8C"
|
117
364
|
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04"
|
118
365
|
};
|
data/ext/rucaptcha/extconf.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
require
|
2
|
-
create_makefile(
|
1
|
+
require "mkmf"
|
2
|
+
create_makefile("rucaptcha/rucaptcha")
|
data/ext/rucaptcha/rucaptcha.c
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
// http://github.com/ITikhonov/captcha
|
2
2
|
const int gifsize;
|
3
|
-
void captcha(unsigned char im[70*200], unsigned char l[8], int length, int i_line, int i_filter);
|
4
|
-
void makegif(unsigned char im[70*200], unsigned char gif[gifsize], int style);
|
3
|
+
void captcha(unsigned char im[70 * 200], unsigned char l[8], int length, int i_line, int i_filter);
|
4
|
+
void makegif(unsigned char im[70 * 200], unsigned char gif[gifsize], int style);
|
5
5
|
|
6
6
|
#include <unistd.h>
|
7
7
|
#include <stdint.h>
|
@@ -14,75 +14,94 @@ void makegif(unsigned char im[70*200], unsigned char gif[gifsize], int style);
|
|
14
14
|
#include "colors.h"
|
15
15
|
|
16
16
|
static int8_t *lt[];
|
17
|
-
const int gifsize=17646;
|
17
|
+
const int gifsize = 17646;
|
18
18
|
|
19
|
-
void makegif(unsigned char im[70*200], unsigned char gif[gifsize], int style)
|
19
|
+
void makegif(unsigned char im[70 * 200], unsigned char gif[gifsize], int style)
|
20
|
+
{
|
20
21
|
// tag ; widthxheight ; GCT:0:0:7 ; bgcolor + aspect // GCT
|
21
22
|
// Image Separator // left x top // widthxheight // Flags
|
22
23
|
// LZW code size
|
23
24
|
srand(time(NULL));
|
24
|
-
int color_len = (int)
|
25
|
+
int color_len = (int)sizeof(colors) / sizeof(colors[0]);
|
25
26
|
int color_idx = rand() % color_len;
|
26
|
-
if (style == 0)
|
27
|
+
if (style == 0)
|
28
|
+
{
|
27
29
|
color_idx = 0;
|
28
30
|
}
|
29
|
-
memcpy(gif,colors[color_idx],13+48+10+1);
|
30
|
-
|
31
|
-
int x,y;
|
32
|
-
unsigned char *i=im;
|
33
|
-
unsigned char *p=gif+13+48+10+1;
|
34
|
-
for(y=0;y<70;y++)
|
35
|
-
|
36
|
-
|
31
|
+
memcpy(gif, colors[color_idx], 13 + 48 + 10 + 1);
|
32
|
+
|
33
|
+
int x, y;
|
34
|
+
unsigned char *i = im;
|
35
|
+
unsigned char *p = gif + 13 + 48 + 10 + 1;
|
36
|
+
for (y = 0; y < 70; y++)
|
37
|
+
{
|
38
|
+
*p++ = 250; // Data length 5*50=250
|
39
|
+
for (x = 0; x < 50; x++)
|
37
40
|
{
|
38
|
-
unsigned char a=i[0]>>4,b=i[1]>>4,c=i[2]>>4,d=i[3]>>4;
|
39
|
-
|
40
|
-
p[0]=16|(a<<5);
|
41
|
-
p[1]=(a>>3)|64|(b<<7);
|
42
|
-
p[2]=b>>1;
|
43
|
-
p[3]=1|(c<<1);
|
44
|
-
p[4]=4|(d<<3);
|
45
|
-
i+=4;
|
46
|
-
p+=5;
|
41
|
+
unsigned char a = i[0] >> 4, b = i[1] >> 4, c = i[2] >> 4, d = i[3] >> 4;
|
42
|
+
|
43
|
+
p[0] = 16 | (a << 5); // bbb10000
|
44
|
+
p[1] = (a >> 3) | 64 | (b << 7); // b10000xb
|
45
|
+
p[2] = b >> 1; // 0000xbbb
|
46
|
+
p[3] = 1 | (c << 1); // 00xbbbb1
|
47
|
+
p[4] = 4 | (d << 3); // xbbbb100
|
48
|
+
i += 4;
|
49
|
+
p += 5;
|
47
50
|
}
|
48
51
|
}
|
49
52
|
|
50
53
|
// Data length // End of LZW (b10001) // Terminator // GIF End
|
51
|
-
memcpy(gif+gifsize-4,"\x01"
|
54
|
+
memcpy(gif + gifsize - 4, "\x01"
|
55
|
+
"\x11"
|
56
|
+
"\x00"
|
57
|
+
";",
|
58
|
+
4);
|
52
59
|
}
|
53
60
|
|
54
|
-
static const int8_t sw[200]={0, 4, 8, 12, 16, 20, 23, 27, 31, 35, 39, 43, 47, 50, 54, 58, 61, 65, 68, 71, 75, 78, 81, 84, 87, 90, 93, 96, 98, 101, 103, 105, 108, 110, 112, 114, 115, 117, 119, 120, 121, 122, 123, 124, 125, 126, 126, 127, 127, 127, 127, 127, 127, 127, 126, 126, 125, 124, 123, 122, 121, 120, 119, 117, 115, 114, 112, 110, 108, 105, 103, 101, 98, 96, 93, 90, 87, 84, 81, 78, 75, 71, 68, 65, 61, 58, 54, 50, 47, 43, 39, 35, 31, 27, 23, 20, 16, 12, 8, 4, 0, -4, -8, -12, -16, -20, -23, -27, -31, -35, -39, -43, -47, -50, -54, -58, -61, -65, -68, -71, -75, -78, -81, -84, -87, -90, -93, -96, -98, -101, -103, -105, -108, -110, -112, -114, -115, -117, -119, -120, -121, -122, -123, -124, -125, -126, -126, -127, -127, -127, -127, -127, -127, -127, -126, -126, -125, -124, -123, -122, -121, -120, -119, -117, -115, -114, -112, -110, -108, -105, -103, -101, -98, -96, -93, -90, -87, -84, -81, -78, -75, -71, -68, -65, -61, -58, -54, -50, -47, -43, -39, -35, -31, -27, -23, -20, -16, -12, -8, -4};
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
int8_t *p=lt[n];
|
61
|
-
unsigned char *r=im+200*16+pos;
|
62
|
-
unsigned char *i=r;
|
63
|
-
int sk1=s1+pos;
|
64
|
-
int sk2=s2+pos;
|
65
|
-
int mpos=pos;
|
66
|
-
int row=0;
|
67
|
-
for(
|
68
|
-
|
69
|
-
|
70
|
-
|
61
|
+
static const int8_t sw[200] = {0, 4, 8, 12, 16, 20, 23, 27, 31, 35, 39, 43, 47, 50, 54, 58, 61, 65, 68, 71, 75, 78, 81, 84, 87, 90, 93, 96, 98, 101, 103, 105, 108, 110, 112, 114, 115, 117, 119, 120, 121, 122, 123, 124, 125, 126, 126, 127, 127, 127, 127, 127, 127, 127, 126, 126, 125, 124, 123, 122, 121, 120, 119, 117, 115, 114, 112, 110, 108, 105, 103, 101, 98, 96, 93, 90, 87, 84, 81, 78, 75, 71, 68, 65, 61, 58, 54, 50, 47, 43, 39, 35, 31, 27, 23, 20, 16, 12, 8, 4, 0, -4, -8, -12, -16, -20, -23, -27, -31, -35, -39, -43, -47, -50, -54, -58, -61, -65, -68, -71, -75, -78, -81, -84, -87, -90, -93, -96, -98, -101, -103, -105, -108, -110, -112, -114, -115, -117, -119, -120, -121, -122, -123, -124, -125, -126, -126, -127, -127, -127, -127, -127, -127, -127, -126, -126, -125, -124, -123, -122, -121, -120, -119, -117, -115, -114, -112, -110, -108, -105, -103, -101, -98, -96, -93, -90, -87, -84, -81, -78, -75, -71, -68, -65, -61, -58, -54, -50, -47, -43, -39, -35, -31, -27, -23, -20, -16, -12, -8, -4};
|
62
|
+
|
63
|
+
#define MAX(x, y) ((x > y) ? (x) : (y))
|
64
|
+
|
65
|
+
static int letter(int n, int pos, unsigned char im[70 * 200], unsigned char swr[200], uint8_t s1, uint8_t s2)
|
66
|
+
{
|
67
|
+
int8_t *p = lt[n];
|
68
|
+
unsigned char *r = im + 200 * 16 + pos;
|
69
|
+
unsigned char *i = r;
|
70
|
+
int sk1 = s1 + pos;
|
71
|
+
int sk2 = s2 + pos;
|
72
|
+
int mpos = pos;
|
73
|
+
int row = 0;
|
74
|
+
for (; *p != -101; p++)
|
75
|
+
{
|
76
|
+
if (*p < 0)
|
77
|
+
{
|
78
|
+
if (*p == -100)
|
79
|
+
{
|
80
|
+
r += 200;
|
81
|
+
i = r;
|
82
|
+
sk1 = s1 + pos;
|
83
|
+
row++;
|
84
|
+
continue;
|
85
|
+
}
|
86
|
+
i += -*p;
|
71
87
|
continue;
|
72
88
|
}
|
73
89
|
|
74
|
-
if(sk1>=200)
|
75
|
-
|
76
|
-
sk1
|
90
|
+
if (sk1 >= 200)
|
91
|
+
sk1 = sk1 % 200;
|
92
|
+
int skew = sw[sk1] / 16;
|
93
|
+
sk1 += (swr[pos + i - r] & 0x1) + 1;
|
77
94
|
|
78
|
-
if(sk2>=200)
|
79
|
-
|
80
|
-
sk2
|
95
|
+
if (sk2 >= 200)
|
96
|
+
sk2 = sk2 % 200;
|
97
|
+
int skewh = sw[sk2] / 70;
|
98
|
+
sk2 += (swr[row] & 0x1);
|
81
99
|
|
82
|
-
unsigned char *x=i+skew*200+skewh;
|
83
|
-
mpos=MAX(mpos,pos+i-r);
|
100
|
+
unsigned char *x = i + skew * 200 + skewh;
|
101
|
+
mpos = MAX(mpos, pos + i - r);
|
84
102
|
|
85
|
-
if((x-im)<70*200)
|
103
|
+
if ((x - im) < 70 * 200)
|
104
|
+
*x = (*p) << 4;
|
86
105
|
i++;
|
87
106
|
}
|
88
107
|
return mpos + 3;
|
@@ -92,100 +111,141 @@ static int letter(int n, int pos, unsigned char im[70*200], unsigned char swr[20
|
|
92
111
|
|
93
112
|
uint32_t dr[NDOTS];
|
94
113
|
|
95
|
-
static void line(unsigned char im[70*200], unsigned char swr[200], uint8_t s1)
|
114
|
+
static void line(unsigned char im[70 * 200], unsigned char swr[200], uint8_t s1)
|
115
|
+
{
|
96
116
|
int x;
|
97
|
-
int sk1=s1;
|
98
|
-
for(x=0;x<199;x++)
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
117
|
+
int sk1 = s1;
|
118
|
+
for (x = 0; x < 199; x++)
|
119
|
+
{
|
120
|
+
if (sk1 >= 200)
|
121
|
+
sk1 = sk1 % 200;
|
122
|
+
int skew = sw[sk1] / 20;
|
123
|
+
sk1 += swr[x] & 0x3 + 1;
|
124
|
+
unsigned char *i = im + (200 * (45 + skew) + x);
|
125
|
+
i[0] = 0;
|
126
|
+
i[1] = 0;
|
127
|
+
i[2] = 0;
|
128
|
+
i[3] = 0;
|
129
|
+
i[4] = 0;
|
130
|
+
i[195] = 0;
|
131
|
+
i[196] = 0;
|
132
|
+
i[197] = 0;
|
133
|
+
i[198] = 0;
|
134
|
+
i[200] = 0;
|
104
135
|
}
|
105
136
|
}
|
106
137
|
|
107
|
-
static void dots(unsigned char im[70*200])
|
138
|
+
static void dots(unsigned char im[70 * 200])
|
139
|
+
{
|
108
140
|
int n;
|
109
|
-
for(n=0;n<NDOTS;n++)
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
i[
|
115
|
-
i[
|
116
|
-
i[
|
117
|
-
i[
|
118
|
-
i[
|
141
|
+
for (n = 0; n < NDOTS; n++)
|
142
|
+
{
|
143
|
+
uint32_t v = dr[n];
|
144
|
+
unsigned char *i = im + v % (200 * 67);
|
145
|
+
|
146
|
+
i[0] = 0xff;
|
147
|
+
i[1] = 0xff;
|
148
|
+
i[2] = 0xff;
|
149
|
+
i[200] = 0xff;
|
150
|
+
i[201] = 0xff;
|
151
|
+
i[202] = 0xff;
|
119
152
|
}
|
120
153
|
}
|
121
154
|
|
122
|
-
static void blur(unsigned char im[70*200])
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
155
|
+
static void blur(unsigned char im[70 * 200])
|
156
|
+
{
|
157
|
+
unsigned char *i = im;
|
158
|
+
int x, y;
|
159
|
+
for (y = 0; y < 68; y++)
|
160
|
+
{
|
161
|
+
for (x = 0; x < 198; x++)
|
162
|
+
{
|
163
|
+
unsigned int c11 = *i, c12 = i[1], c21 = i[200], c22 = i[201];
|
164
|
+
*i++ = ((c11 + c12 + c21 + c22) / 4);
|
129
165
|
}
|
130
166
|
}
|
131
167
|
}
|
132
168
|
|
133
|
-
static void filter(unsigned char im[70*200])
|
134
|
-
|
135
|
-
unsigned char *
|
136
|
-
unsigned char *
|
169
|
+
static void filter(unsigned char im[70 * 200])
|
170
|
+
{
|
171
|
+
unsigned char om[70 * 200];
|
172
|
+
unsigned char *i = im;
|
173
|
+
unsigned char *o = om;
|
137
174
|
|
138
|
-
memset(om,0xff,sizeof(om));
|
175
|
+
memset(om, 0xff, sizeof(om));
|
139
176
|
|
140
|
-
int x,y;
|
141
|
-
for(y=0;y<70;y++)
|
142
|
-
|
143
|
-
|
144
|
-
|
177
|
+
int x, y;
|
178
|
+
for (y = 0; y < 70; y++)
|
179
|
+
{
|
180
|
+
for (x = 4; x < 200 - 4; x++)
|
181
|
+
{
|
182
|
+
if (i[0] > 0xf0 && i[1] < 0xf0)
|
183
|
+
{
|
184
|
+
o[0] = 0;
|
185
|
+
o[1] = 0;
|
186
|
+
}
|
187
|
+
else if (i[0] < 0xf0 && i[1] > 0xf0)
|
188
|
+
{
|
189
|
+
o[0] = 0;
|
190
|
+
o[1] = 0;
|
191
|
+
}
|
145
192
|
|
146
193
|
i++;
|
147
194
|
o++;
|
148
195
|
}
|
149
196
|
}
|
150
197
|
|
151
|
-
memmove(im,om,sizeof(om));
|
198
|
+
memmove(im, om, sizeof(om));
|
152
199
|
}
|
153
200
|
|
154
|
-
static const char *letters="abcdafahijklmnopqrstuvwxyz";
|
201
|
+
static const char *letters = "abcdafahijklmnopqrstuvwxyz";
|
155
202
|
|
156
|
-
void captcha(unsigned char im[70*200], unsigned char l[8], int length, int i_line, int i_filter)
|
203
|
+
void captcha(unsigned char im[70 * 200], unsigned char l[8], int length, int i_line, int i_filter)
|
204
|
+
{
|
157
205
|
unsigned char swr[200];
|
158
|
-
uint8_t s1,s2;
|
159
|
-
|
160
|
-
int f=open("/dev/urandom",O_RDONLY);
|
161
|
-
read(f,l,5);
|
206
|
+
uint8_t s1, s2;
|
207
|
+
|
208
|
+
int f = open("/dev/urandom", O_RDONLY);
|
209
|
+
read(f, l, 5);
|
210
|
+
read(f, swr, 200);
|
211
|
+
read(f, dr, sizeof(dr));
|
212
|
+
read(f, &s1, 1);
|
213
|
+
read(f, &s2, 1);
|
162
214
|
close(f);
|
163
|
-
memset(im,0xff,200*70);
|
215
|
+
memset(im, 0xff, 200 * 70);
|
216
|
+
s1 = s1 & 0x7f;
|
217
|
+
s2 = s2 & 0x3f;
|
164
218
|
|
165
219
|
int x;
|
166
|
-
for(x=0;x<length;x++)
|
167
|
-
|
220
|
+
for (x = 0; x < length; x++)
|
221
|
+
{
|
222
|
+
l[x] %= 25;
|
168
223
|
}
|
169
|
-
for(x=length;x<8;x++)
|
170
|
-
|
224
|
+
for (x = length; x < 8; x++)
|
225
|
+
{
|
226
|
+
l[length] = 0;
|
171
227
|
}
|
172
228
|
//l[0]%=25; l[1]%=25; l[2]%=25; l[3]%=25; l[4]=0; // l[4]%=25; l[5]=0;
|
173
|
-
int p=30;
|
174
|
-
for(x=0;x<length;x++)
|
175
|
-
|
229
|
+
int p = 30;
|
230
|
+
for (x = 0; x < length; x++)
|
231
|
+
{
|
232
|
+
p = letter(l[x], p, im, swr, s1, s2);
|
176
233
|
}
|
177
234
|
|
178
|
-
if (i_line == 1)
|
179
|
-
|
235
|
+
if (i_line == 1)
|
236
|
+
{
|
237
|
+
line(im, swr, s1);
|
180
238
|
}
|
181
|
-
|
182
|
-
if (i_filter == 1)
|
239
|
+
dots(im);
|
240
|
+
if (i_filter == 1)
|
241
|
+
{
|
183
242
|
blur(im);
|
184
243
|
filter(im);
|
185
244
|
}
|
186
245
|
|
187
|
-
for(x=0;x<length;x++)
|
188
|
-
|
246
|
+
for (x = 0; x < length; x++)
|
247
|
+
{
|
248
|
+
l[x] = letters[l[x]];
|
189
249
|
}
|
190
250
|
//l[1]=letters[l[1]]; l[2]=letters[l[2]]; l[3]=letters[l[3]]; //l[4]=letters[l[4]];
|
191
251
|
}
|
@@ -214,14 +274,16 @@ void Init_rucaptcha();
|
|
214
274
|
|
215
275
|
VALUE create(VALUE self, VALUE style, VALUE length, VALUE line, VALUE filter);
|
216
276
|
|
217
|
-
void Init_rucaptcha()
|
277
|
+
void Init_rucaptcha()
|
278
|
+
{
|
218
279
|
RuCaptcha = rb_define_module("RuCaptcha");
|
219
280
|
rb_define_singleton_method(RuCaptcha, "create", create, 4);
|
220
281
|
}
|
221
282
|
|
222
|
-
VALUE create(VALUE self, VALUE style, VALUE length, VALUE line, VALUE filter)
|
283
|
+
VALUE create(VALUE self, VALUE style, VALUE length, VALUE line, VALUE filter)
|
284
|
+
{
|
223
285
|
char l[8];
|
224
|
-
unsigned char im[80*200];
|
286
|
+
unsigned char im[80 * 200];
|
225
287
|
unsigned char gif[gifsize];
|
226
288
|
int i_style = FIX2INT(style);
|
227
289
|
int i_length = FIX2INT(length);
|
@@ -237,4 +299,3 @@ VALUE create(VALUE self, VALUE style, VALUE length, VALUE line, VALUE filter) {
|
|
237
299
|
|
238
300
|
return result;
|
239
301
|
}
|
240
|
-
|
data/lib/rucaptcha/cache.rb
CHANGED
@@ -6,21 +6,25 @@ module RuCaptcha
|
|
6
6
|
helper_method :verify_rucaptcha?
|
7
7
|
end
|
8
8
|
|
9
|
+
def rucaptcha_session_id
|
10
|
+
cookies[:_rucaptcha_session_id]
|
11
|
+
end
|
12
|
+
|
9
13
|
# session key of rucaptcha
|
10
14
|
def rucaptcha_sesion_key_key
|
11
|
-
|
12
|
-
session_id = session.respond_to?(:id) ? session.id : session[:session_id]
|
13
|
-
warning_when_session_invalid if session_id.blank?
|
15
|
+
warning_when_session_invalid if rucaptcha_session_id.blank?
|
14
16
|
|
15
17
|
# With https://github.com/rack/rack/commit/7fecaee81f59926b6e1913511c90650e76673b38
|
16
18
|
# to protected session_id into secret
|
17
|
-
session_id_digest = Digest::SHA256.hexdigest(
|
18
|
-
[
|
19
|
+
session_id_digest = Digest::SHA256.hexdigest(rucaptcha_session_id.inspect)
|
20
|
+
["rucaptcha-session", session_id_digest].join(":")
|
19
21
|
end
|
20
22
|
|
21
23
|
# Generate a new Captcha
|
22
24
|
def generate_rucaptcha
|
23
|
-
|
25
|
+
generate_rucaptcha_session_id
|
26
|
+
|
27
|
+
res = RuCaptcha.generate
|
24
28
|
session_val = {
|
25
29
|
code: res[0],
|
26
30
|
time: Time.now.to_i
|
@@ -44,7 +48,7 @@ module RuCaptcha
|
|
44
48
|
# verify_rucaptcha?(nil, keep_session: true)
|
45
49
|
# verify_rucaptcha?(nil, captcha: params[:user][:captcha])
|
46
50
|
#
|
47
|
-
def verify_rucaptcha?(
|
51
|
+
def verify_rucaptcha?(_resource = nil, opts = {})
|
48
52
|
opts ||= {}
|
49
53
|
|
50
54
|
store_info = RuCaptcha.cache.read(rucaptcha_sesion_key_key)
|
@@ -52,38 +56,41 @@ module RuCaptcha
|
|
52
56
|
RuCaptcha.cache.delete(rucaptcha_sesion_key_key) unless opts[:keep_session]
|
53
57
|
|
54
58
|
# Make sure session exist
|
55
|
-
if store_info.blank?
|
56
|
-
return add_rucaptcha_validation_error
|
57
|
-
end
|
59
|
+
return add_rucaptcha_validation_error if store_info.blank?
|
58
60
|
|
59
61
|
# Make sure not expire
|
60
|
-
if (Time.now.to_i - store_info[:time]) > RuCaptcha.config.expires_in
|
61
|
-
return add_rucaptcha_validation_error
|
62
|
-
end
|
62
|
+
return add_rucaptcha_validation_error if (Time.now.to_i - store_info[:time]) > RuCaptcha.config.expires_in
|
63
63
|
|
64
64
|
# Make sure parama have captcha
|
65
|
-
captcha = (opts[:captcha] || params[:_rucaptcha] ||
|
66
|
-
if captcha.blank?
|
67
|
-
return add_rucaptcha_validation_error
|
68
|
-
end
|
65
|
+
captcha = (opts[:captcha] || params[:_rucaptcha] || "").downcase.strip
|
66
|
+
return add_rucaptcha_validation_error if captcha.blank?
|
69
67
|
|
70
|
-
if captcha != store_info[:code]
|
71
|
-
return add_rucaptcha_validation_error
|
72
|
-
end
|
68
|
+
return add_rucaptcha_validation_error if captcha != store_info[:code]
|
73
69
|
|
74
70
|
true
|
75
71
|
end
|
76
72
|
|
77
73
|
private
|
78
74
|
|
75
|
+
def generate_rucaptcha_session_id
|
76
|
+
return if rucaptcha_session_id.present?
|
77
|
+
|
78
|
+
cookies[:_rucaptcha_session_id] = {
|
79
|
+
value: SecureRandom.hex(16),
|
80
|
+
expires: 1.day
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
79
84
|
def add_rucaptcha_validation_error
|
80
85
|
if defined?(resource) && resource && resource.respond_to?(:errors)
|
81
|
-
resource.errors.add(:base, t(
|
86
|
+
resource.errors.add(:base, t("rucaptcha.invalid"))
|
82
87
|
end
|
83
88
|
false
|
84
89
|
end
|
85
90
|
|
86
91
|
def warning_when_session_invalid
|
92
|
+
return unless Rails.env.development?
|
93
|
+
|
87
94
|
Rails.logger.warn "
|
88
95
|
WARNING! The session.id is blank, RuCaptcha can't work properly, please keep session available.
|
89
96
|
More details about this: https://github.com/huacnlee/rucaptcha/pull/66
|
data/lib/rucaptcha/engine.rb
CHANGED
@@ -2,11 +2,11 @@ module RuCaptcha
|
|
2
2
|
class Engine < ::Rails::Engine
|
3
3
|
isolate_namespace RuCaptcha
|
4
4
|
|
5
|
-
initializer
|
5
|
+
initializer "rucaptcha.init" do |app|
|
6
6
|
# https://github.com/rails/rails/blob/3-2-stable/actionpack/lib/action_dispatch/routing/route_set.rb#L268
|
7
7
|
# `app.routes.prepend` start from Rails 3.2 - 5.0
|
8
8
|
app.routes.prepend do
|
9
|
-
mount RuCaptcha::Engine =>
|
9
|
+
mount RuCaptcha::Engine => "/rucaptcha"
|
10
10
|
end
|
11
11
|
|
12
12
|
RuCaptcha.check_cache_store! unless RuCaptcha.config.skip_cache_store_check
|
data/lib/rucaptcha/version.rb
CHANGED
@@ -1,19 +1,20 @@
|
|
1
1
|
module RuCaptcha
|
2
2
|
module ViewHelpers
|
3
3
|
def rucaptcha_input_tag(opts = {})
|
4
|
-
opts[:name]
|
5
|
-
opts[:type]
|
6
|
-
opts[:autocorrect]
|
7
|
-
opts[:autocapitalize] =
|
8
|
-
opts[:pattern]
|
9
|
-
opts[:autocomplete]
|
10
|
-
opts[:maxlength]
|
4
|
+
opts[:name] = "_rucaptcha"
|
5
|
+
opts[:type] = "text"
|
6
|
+
opts[:autocorrect] = "off"
|
7
|
+
opts[:autocapitalize] = "off"
|
8
|
+
opts[:pattern] = "[a-zA-Z]*"
|
9
|
+
opts[:autocomplete] = "off"
|
10
|
+
opts[:maxlength] = RuCaptcha.config.length
|
11
11
|
tag(:input, opts)
|
12
12
|
end
|
13
13
|
|
14
14
|
def rucaptcha_image_tag(opts = {})
|
15
|
-
|
16
|
-
opts[:
|
15
|
+
@rucaptcha_image_tag__image_path_in_this_request ||= "#{ru_captcha.root_path}?t=#{Time.now.strftime("%s%L")}"
|
16
|
+
opts[:class] = opts[:class] || "rucaptcha-image"
|
17
|
+
opts[:src] = @rucaptcha_image_tag__image_path_in_this_request
|
17
18
|
opts[:onclick] = "this.src = '#{ru_captcha.root_path}?t=' + Date.now();"
|
18
19
|
tag(:img, opts)
|
19
20
|
end
|
data/lib/rucaptcha.rb
CHANGED
@@ -1,31 +1,32 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
1
|
+
require "rails"
|
2
|
+
require "action_controller"
|
3
|
+
require "active_support/all"
|
4
|
+
require "rucaptcha/rucaptcha"
|
5
|
+
require "rucaptcha/version"
|
6
|
+
require "rucaptcha/configuration"
|
7
|
+
require "rucaptcha/controller_helpers"
|
8
|
+
require "rucaptcha/view_helpers"
|
9
|
+
require "rucaptcha/cache"
|
10
|
+
require "rucaptcha/engine"
|
11
|
+
require "rucaptcha/errors/configuration"
|
12
12
|
|
13
13
|
module RuCaptcha
|
14
14
|
class << self
|
15
15
|
def config
|
16
16
|
return @config if defined?(@config)
|
17
|
+
|
17
18
|
@config = Configuration.new
|
18
|
-
@config.style
|
19
|
-
@config.length
|
19
|
+
@config.style = :colorful
|
20
|
+
@config.length = 5
|
20
21
|
@config.strikethrough = true
|
21
|
-
@config.outline
|
22
|
-
@config.expires_in
|
22
|
+
@config.outline = false
|
23
|
+
@config.expires_in = 2.minutes
|
23
24
|
@config.skip_cache_store_check = false
|
24
25
|
|
25
|
-
if Rails.application
|
26
|
-
|
26
|
+
@config.cache_store = if Rails.application
|
27
|
+
Rails.application.config.cache_store
|
27
28
|
else
|
28
|
-
|
29
|
+
:mem_cache_store
|
29
30
|
end
|
30
31
|
@config.cache_store
|
31
32
|
@config
|
@@ -35,24 +36,22 @@ module RuCaptcha
|
|
35
36
|
config.instance_exec(&block)
|
36
37
|
end
|
37
38
|
|
38
|
-
def generate
|
39
|
+
def generate
|
39
40
|
style = config.style == :colorful ? 1 : 0
|
40
41
|
length = config.length
|
41
42
|
|
42
|
-
unless length.in?(3..7)
|
43
|
-
raise RuCaptcha::Errors::Configuration, 'length config error, value must in 3..7'
|
44
|
-
end
|
43
|
+
raise RuCaptcha::Errors::Configuration, "length config error, value must in 3..7" unless length.in?(3..7)
|
45
44
|
|
46
45
|
strikethrough = config.strikethrough ? 1 : 0
|
47
46
|
outline = config.outline ? 1 : 0
|
48
|
-
|
47
|
+
create(style, length, strikethrough, outline)
|
49
48
|
end
|
50
49
|
|
51
50
|
def check_cache_store!
|
52
51
|
cache_store = RuCaptcha.config.cache_store
|
53
52
|
store_name = cache_store.is_a?(Array) ? cache_store.first : cache_store
|
54
|
-
if [
|
55
|
-
RuCaptcha.config.cache_store = [:file_store, Rails.root.join(
|
53
|
+
if %i[memory_store null_store file_store].include?(store_name)
|
54
|
+
RuCaptcha.config.cache_store = [:file_store, Rails.root.join("tmp/cache/rucaptcha/session")]
|
56
55
|
|
57
56
|
puts "
|
58
57
|
|
@@ -72,7 +71,7 @@ module RuCaptcha
|
|
72
71
|
end
|
73
72
|
|
74
73
|
ActiveSupport.on_load(:action_controller) do
|
75
|
-
ActionController::Base.
|
74
|
+
ActionController::Base.include RuCaptcha::ControllerHelpers
|
76
75
|
end
|
77
76
|
|
78
77
|
ActiveSupport.on_load(:action_view) do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rucaptcha
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Lee
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-02-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -38,7 +38,7 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1'
|
41
|
-
description:
|
41
|
+
description:
|
42
42
|
email: huacnlee@gmail.com
|
43
43
|
executables: []
|
44
44
|
extensions:
|
@@ -69,7 +69,7 @@ homepage: https://github.com/huacnlee/rucaptcha
|
|
69
69
|
licenses:
|
70
70
|
- MIT
|
71
71
|
metadata: {}
|
72
|
-
post_install_message:
|
72
|
+
post_install_message:
|
73
73
|
rdoc_options: []
|
74
74
|
require_paths:
|
75
75
|
- lib
|
@@ -84,8 +84,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
84
|
- !ruby/object:Gem::Version
|
85
85
|
version: '0'
|
86
86
|
requirements: []
|
87
|
-
rubygems_version: 3.
|
88
|
-
signing_key:
|
87
|
+
rubygems_version: 3.2.3
|
88
|
+
signing_key:
|
89
89
|
specification_version: 4
|
90
90
|
summary: This is a Captcha gem for Rails Applications. It drawing captcha image with
|
91
91
|
C code so it no dependencies.
|