blogs_captcha 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +234 -0
- data/README.md +164 -0
- data/app/controllers/blogs_captcha/captcha_controller.rb +12 -0
- data/config/locales/rucaptcha.en.yml +3 -0
- data/config/locales/rucaptcha.pt-BR.yml +3 -0
- data/config/locales/rucaptcha.zh-CN.yml +3 -0
- data/config/locales/rucaptcha.zh-TW.yml +3 -0
- data/config/routes.rb +3 -0
- data/ext/blogs_captcha/colors.h +118 -0
- data/ext/blogs_captcha/extconf.rb +2 -0
- data/ext/blogs_captcha/font.h +27 -0
- data/ext/blogs_captcha/rucaptcha.c +240 -0
- data/lib/blogs_captcha.rb +80 -0
- data/lib/blogs_captcha/cache.rb +11 -0
- data/lib/blogs_captcha/configuration.rb +19 -0
- data/lib/blogs_captcha/controller_helpers.rb +88 -0
- data/lib/blogs_captcha/engine.rb +15 -0
- data/lib/blogs_captcha/errors/configuration.rb +5 -0
- data/lib/blogs_captcha/version.rb +3 -0
- data/lib/blogs_captcha/view_helpers.rb +19 -0
- metadata +93 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a98ec2683e337c42986878b06c53998653e8f710c3f30bb419ce73bda44028a7
|
4
|
+
data.tar.gz: 8985a2a6bae218ec905c24fa6f4491fc0ee4363b41055fc78be0bd9505408311
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e476e5552dc73c8bcb21368f7a711dc258d4a808e249fd20f5552c9f5e12c6954bf9d3a1e28a9fa8c553ba146875945c8e8aa889987b26971c945462e5368071
|
7
|
+
data.tar.gz: c4ecc445a10458bdce54f1d1cd959d6cccc910ff498e4924fcb3271a0427b71b28a48083f1322ea25fe91c556c9084ed771036ab82d8191bd85c9f7248eba198
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,234 @@
|
|
1
|
+
2.4.0
|
2
|
+
-------
|
3
|
+
|
4
|
+
- Add skip_cache_store_check configuration. (#63)
|
5
|
+
- Fix for generate captcha with relative path, not url. (#58)
|
6
|
+
|
7
|
+
2.3.2
|
8
|
+
-------
|
9
|
+
|
10
|
+
- Change Yellow and Green colors to Pink and Deep Purple to pass WCAG 2.0's contrast test. (#70)
|
11
|
+
|
12
|
+
2.3.1
|
13
|
+
-------
|
14
|
+
|
15
|
+
- Fix #67 a y chars will invalid error (only in 2.3.0).
|
16
|
+
|
17
|
+
2.3.0
|
18
|
+
-------
|
19
|
+
|
20
|
+
- Add `config.outline` for use outline style.
|
21
|
+
- Reduce colors down to 5 (red, blue, green, yellow and black).
|
22
|
+
|
23
|
+
2.2.0
|
24
|
+
-----
|
25
|
+
|
26
|
+
- Add option `config.length` for support change number chars. (#57)
|
27
|
+
- Add option `config.strikethrough` for enable or disable strikethrough. (#57)
|
28
|
+
|
29
|
+
2.1.3
|
30
|
+
-----
|
31
|
+
|
32
|
+
- Windows support fixed with `send_data` method. (#45)
|
33
|
+
|
34
|
+
2.1.2
|
35
|
+
-----
|
36
|
+
|
37
|
+
- Do not change captcha when `HEAD /rucaptcha`.
|
38
|
+
|
39
|
+
2.1.1
|
40
|
+
-----
|
41
|
+
|
42
|
+
- Mount engine use `prepend` method to get high priority in config/routes.rb.
|
43
|
+
|
44
|
+
2.1.0
|
45
|
+
-----
|
46
|
+
|
47
|
+
- Mount Router by default, not need config now.
|
48
|
+
|
49
|
+
> IMPORTANT: Wen you upgrade this version, you need remove `mount RuCaptcha::Engine` line from your `config/routes.rb`
|
50
|
+
- Default use [:file_store, 'tmp/cache/rucaptcha/session'] as RuCaptcha.config.cache_store, now it can work without any configurations.
|
51
|
+
|
52
|
+
> NOTE: But you still need care about `config.cache_store` to setup on a right way.
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
2.0.3
|
57
|
+
-----
|
58
|
+
|
59
|
+
- Use `ActiveSupport.on_load` to extend ActionController and ActionView.
|
60
|
+
|
61
|
+
2.0.1
|
62
|
+
-----
|
63
|
+
|
64
|
+
- Fix `/rucaptcha` path issue when `config.action_controller.asset_host` has setup with CDN url.
|
65
|
+
|
66
|
+
2.0.0
|
67
|
+
-----
|
68
|
+
|
69
|
+
*Break Changes!*
|
70
|
+
|
71
|
+
WARNING!: This version have so many break changes!
|
72
|
+
|
73
|
+
- Use C ext instead of ImageMagick, now it's no dependencies!
|
74
|
+
- New captcha style.
|
75
|
+
- Remove `len`, `font_size`, `cache_limit` config key, no support now.
|
76
|
+
- Output `GIF` format.
|
77
|
+
|
78
|
+
1.2.0
|
79
|
+
-----
|
80
|
+
|
81
|
+
- 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.
|
82
|
+
|
83
|
+
1.1.4
|
84
|
+
-----
|
85
|
+
|
86
|
+
- Fix #35 just give a warning message if not setup a right cache_store, only raise on :null_store.
|
87
|
+
|
88
|
+
1.1.2
|
89
|
+
-----
|
90
|
+
|
91
|
+
- Fix #34 rucaptcha.root_url -> root_path, to avoid generate a http url in a https application.
|
92
|
+
- Fix spec to require Ruby 2.0.0, because there have a `Module#prepend` method called.
|
93
|
+
|
94
|
+
1.1.1
|
95
|
+
-----
|
96
|
+
|
97
|
+
- Remove inspect log on verify_rucaptcha
|
98
|
+
|
99
|
+
1.1.0
|
100
|
+
-----
|
101
|
+
|
102
|
+
- Add `cache_store` config key to setup a cache store location for RuCaptcha.
|
103
|
+
- Store captcha in custom cache store.
|
104
|
+
|
105
|
+
## Security Notes
|
106
|
+
|
107
|
+
- Fix Session replay secure issue that when Rails application use CookieStore.
|
108
|
+
|
109
|
+
1.0.0
|
110
|
+
-----
|
111
|
+
|
112
|
+
- Adjust to avoid lighter colors.
|
113
|
+
- Avoid continuous chars have same color.
|
114
|
+
- Use same color for each chars in :black_white mode.
|
115
|
+
|
116
|
+
0.5.1
|
117
|
+
-----
|
118
|
+
|
119
|
+
- Make sure it will render image when ImageMagick stderr have warning messages. (#26)
|
120
|
+
|
121
|
+
0.5.0
|
122
|
+
-----
|
123
|
+
|
124
|
+
- Fix cache with Rails 5.
|
125
|
+
|
126
|
+
0.4.5
|
127
|
+
-----
|
128
|
+
|
129
|
+
- Removed `posix-spawn` dependency, used open3 instead (core funciontality), JRuby compatible (#24)
|
130
|
+
|
131
|
+
0.4.4
|
132
|
+
-----
|
133
|
+
|
134
|
+
- Remove deprecated `width`, `height` config.
|
135
|
+
- Delete session key after verify (#23).
|
136
|
+
- Lighter text color, improve style.
|
137
|
+
|
138
|
+
0.4.2
|
139
|
+
-----
|
140
|
+
|
141
|
+
- Fix NoMethodError bug when params[:_rucaptha] is nil.
|
142
|
+
|
143
|
+
0.4.1
|
144
|
+
-----
|
145
|
+
|
146
|
+
- Add error message to resource when captcha code expired.
|
147
|
+
|
148
|
+
0.4.0
|
149
|
+
-----
|
150
|
+
|
151
|
+
- Add `config.colorize` option, to allow use black text theme.
|
152
|
+
|
153
|
+
0.3.3
|
154
|
+
-----
|
155
|
+
|
156
|
+
- Add `config.expires_in` to allow change captcha code expire time.
|
157
|
+
|
158
|
+
0.3.2.1
|
159
|
+
-------
|
160
|
+
|
161
|
+
- Add Windows development env support.
|
162
|
+
|
163
|
+
0.3.2
|
164
|
+
-----
|
165
|
+
|
166
|
+
- Make better render positions;
|
167
|
+
- Trim blank space.
|
168
|
+
|
169
|
+
0.3.1
|
170
|
+
-----
|
171
|
+
|
172
|
+
- More complex Image render: compact text, strong lines, +/-5 rotate...
|
173
|
+
- [DEPRECATION] config.width, config.height removed, use config.font_size.
|
174
|
+
- Fix the render position in difference font sizes.
|
175
|
+
- Fix input field type, and disable autocorrect, autocapitalize, and limit maxlength with char length;
|
176
|
+
|
177
|
+
0.2.5
|
178
|
+
-----
|
179
|
+
|
180
|
+
- Add `session[:_rucaptcha]` expire time, for protect Rails CookieSession Replay Attack.
|
181
|
+
- Captcha input field disable autocomplete, and set field type as `email` for shown correct keyboard on mobile view.
|
182
|
+
|
183
|
+
0.2.3
|
184
|
+
-----
|
185
|
+
|
186
|
+
- It will raise error when call ImageMagick failed.
|
187
|
+
|
188
|
+
0.2.2
|
189
|
+
-----
|
190
|
+
|
191
|
+
- Added locale for pt-BR language; @ramirovjr
|
192
|
+
|
193
|
+
0.2.1
|
194
|
+
-----
|
195
|
+
|
196
|
+
- Fix issue when cache dir not exist.
|
197
|
+
|
198
|
+
0.2.0
|
199
|
+
-----
|
200
|
+
|
201
|
+
- Added file cache, can setup how many images you want generate by `config.cache_limit`,
|
202
|
+
RuCaptcha will use cache for next requests.
|
203
|
+
When you restart Rails processes it will generate new again and clean the old caches.
|
204
|
+
|
205
|
+
0.1.4
|
206
|
+
-----
|
207
|
+
|
208
|
+
- Fix `verify_rucaptcha?` logic in somecase.
|
209
|
+
- Locales fixed.
|
210
|
+
|
211
|
+
0.1.3
|
212
|
+
-----
|
213
|
+
|
214
|
+
- `zh-TW` translate file fixed.
|
215
|
+
- Use xxx_url to fix bad captcha URL for `config.action_controller.asset_host` enabled case.
|
216
|
+
|
217
|
+
0.1.2
|
218
|
+
-----
|
219
|
+
|
220
|
+
- No case sensitive;
|
221
|
+
- Export config.implode;
|
222
|
+
- Improve image color and style;
|
223
|
+
- Don't generate chars in 'l,o,0,1'.
|
224
|
+
- Render lower case chars on image.
|
225
|
+
|
226
|
+
0.1.1
|
227
|
+
-----
|
228
|
+
|
229
|
+
- Include default validation I18n messages (en, zh-CN, zh-TW).
|
230
|
+
|
231
|
+
0.1.0
|
232
|
+
-----
|
233
|
+
|
234
|
+
- First release.
|
data/README.md
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
# RuCaptcha
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/rucaptcha.svg)](https://badge.fury.io/rb/rucaptcha)
|
4
|
+
[![Build Status](https://travis-ci.org/huacnlee/rucaptcha.svg)](https://travis-ci.org/huacnlee/rucaptcha)
|
5
|
+
|
6
|
+
This is a Captcha gem for Rails Applications which generates captcha image by C code.
|
7
|
+
|
8
|
+
[中文介绍和使用说明](https://ruby-china.org/topics/27832)
|
9
|
+
|
10
|
+
## Example
|
11
|
+
|
12
|
+
<img src="https://user-images.githubusercontent.com/5518/49985459-f8492f80-ffa6-11e8-9ef5-8f8f522e4707.png" width="579px" />
|
13
|
+
|
14
|
+
## Feature
|
15
|
+
|
16
|
+
- No dependencies. No ImageMagick. No RMagick;
|
17
|
+
- For Rails Application;
|
18
|
+
- Simple, Easy to use;
|
19
|
+
- High performance.
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Put rucaptcha in your `Gemfile`:
|
24
|
+
|
25
|
+
```
|
26
|
+
gem 'rucaptcha'
|
27
|
+
```
|
28
|
+
|
29
|
+
Create `config/initializers/rucaptcha.rb`
|
30
|
+
|
31
|
+
```rb
|
32
|
+
RuCaptcha.configure do
|
33
|
+
# Color style, default: :colorful, allows: [:colorful, :black_white]
|
34
|
+
# self.style = :colorful
|
35
|
+
# Custom captcha code expire time if you need, default: 2 minutes
|
36
|
+
# self.expires_in = 120
|
37
|
+
# [Requirement / 重要]
|
38
|
+
# Store Captcha code where, this config more like Rails config.cache_store
|
39
|
+
# default: Read config info from `Rails.application.config.cache_store`
|
40
|
+
# But RuCaptcha requirements cache_store not in [:null_store, :memory_store, :file_store]
|
41
|
+
# 默认:会从 Rails 配置的 cache_store 里面读取相同的配置信息,并尝试用可以运行的方式,用于存储验证码字符
|
42
|
+
# 但如果是 [:null_store, :memory_store, :file_store] 之类的,你可以通过下面的配置项单独给 RuCaptcha 配置 cache_store
|
43
|
+
self.cache_store = :mem_cache_store
|
44
|
+
# 如果想要 disable cache_store 的 warning,就设置为 true,default false
|
45
|
+
# self.skip_cache_store_check = true
|
46
|
+
# Chars length, default: 5, allows: [3 - 7]
|
47
|
+
# self.length = 5
|
48
|
+
# enable/disable Strikethrough.
|
49
|
+
# self.strikethrough = true
|
50
|
+
# enable/disable Outline style, for hard mode
|
51
|
+
# self.outline = false
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
55
|
+
RuCaptcha 没有使用 Rails Session 来存储验证码信息,因为 Rails 的默认 Session 是存储在 Cookie 里面,如果验证码存在里面会存在 [Replay attack](https://en.wikipedia.org/wiki/Replay_attack) 漏洞,导致验证码关卡被攻破。
|
56
|
+
|
57
|
+
所以我在设计上要求 RuCaptcha 得配置一个可以支持分布式的后端存储方案例如:Memcached 或 Redis 以及其他可以支持分布式的 cache_store 方案。
|
58
|
+
|
59
|
+
同时,为了保障易用性,默认会尝试使用 `:file_store` 的方式,将验证码存在应用程序的 `tmp/cache/rucaptcha/session` 目录(但请注意,多机器部署这样是无法正常运作的)。
|
60
|
+
|
61
|
+
所以,我建议大家使用的时候,配置上 `cache_store` (详见 [Rails Guides 缓存配置部分](https://ruby-china.github.io/rails-guides/caching_with_rails.html#%E9%85%8D%E7%BD%AE)的文档)到一个 Memcached 或 Redis,这才是最佳实践。
|
62
|
+
|
63
|
+
#
|
64
|
+
(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.
|
65
|
+
|
66
|
+
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.
|
67
|
+
|
68
|
+
Meanwhile, for the ease of use, RuCapthca would try to use `:file_store` by default and store the capthca in `tmp/cache/rucaptcha/session` directory (kindly note that it's not working if deploy on multiple machine).
|
69
|
+
|
70
|
+
For recommendation, configure the `cache_store`(more details on [Rails Guides Configuration of Cache Stores](http://guides.rubyonrails.org/caching_with_rails.html#configuration)) to Memcached or Redis, that would be the best practice.)
|
71
|
+
|
72
|
+
#
|
73
|
+
|
74
|
+
Controller `app/controller/account_controller.rb`
|
75
|
+
|
76
|
+
When you called `verify_rucaptcha?`, it uses value from `params[:_rucaptcha]` to validate.
|
77
|
+
|
78
|
+
```rb
|
79
|
+
class AccountController < ApplicationController
|
80
|
+
def create
|
81
|
+
@user = User.new(params[:user])
|
82
|
+
if verify_rucaptcha?(@user) && @user.save
|
83
|
+
redirect_to root_path, notice: 'Sign up successed.'
|
84
|
+
else
|
85
|
+
render 'account/new'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class ForgotPasswordController < ApplicationController
|
91
|
+
def create
|
92
|
+
# without any args
|
93
|
+
if verify_rucaptcha?
|
94
|
+
to_send_email
|
95
|
+
else
|
96
|
+
redirect_to '/forgot-password', alert: 'Invalid captcha code.'
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
```
|
101
|
+
|
102
|
+
> TIP: Sometimes you may need to keep last verified captcha code in session on `verify_rucaptcha?` method call, you can use `keep_session: true`. For example: `verify_rucaptcha? @user, keep_session: true`.
|
103
|
+
|
104
|
+
View `app/views/account/new.html.erb`
|
105
|
+
|
106
|
+
```erb
|
107
|
+
<form method="POST">
|
108
|
+
...
|
109
|
+
<div class="form-group">
|
110
|
+
<%= rucaptcha_input_tag(class: 'form-control', placeholder: 'Input Captcha') %>
|
111
|
+
<%= rucaptcha_image_tag(alt: 'Captcha') %>
|
112
|
+
</div>
|
113
|
+
...
|
114
|
+
|
115
|
+
<div class="form-group">
|
116
|
+
<button type="submit" class="btn btn-primary">Submit</button>
|
117
|
+
</div>
|
118
|
+
</form>
|
119
|
+
```
|
120
|
+
|
121
|
+
And if you are using [Devise](https://github.com/plataformatec/devise), you can read this reference to add validation: [RuCaptcha with Devise](https://github.com/huacnlee/rucaptcha/wiki/Working-with-Devise).
|
122
|
+
|
123
|
+
### Write your test skip captcha validation
|
124
|
+
|
125
|
+
for RSpec
|
126
|
+
|
127
|
+
```rb
|
128
|
+
describe 'sign up and login', type: :feature do
|
129
|
+
before do
|
130
|
+
allow_any_instance_of(ActionController::Base).to receive(:verify_rucaptcha?).and_return(true)
|
131
|
+
end
|
132
|
+
|
133
|
+
it { ... }
|
134
|
+
end
|
135
|
+
```
|
136
|
+
|
137
|
+
for MiniTest
|
138
|
+
|
139
|
+
```rb
|
140
|
+
class ActionDispatch::IntegrationTest
|
141
|
+
def sign_in(user)
|
142
|
+
ActionController::Base.any_instance.stubs(:verify_rucaptcha?).returns(true)
|
143
|
+
post user_session_path \
|
144
|
+
'user[email]' => user.email,
|
145
|
+
'user[password]' => user.password
|
146
|
+
end
|
147
|
+
end
|
148
|
+
```
|
149
|
+
|
150
|
+
### Invalid message without Devise
|
151
|
+
|
152
|
+
When you are using this gem without Devise, you may find out that the invalid message is missing.
|
153
|
+
For this case, use the trick below to add your i18n invalid message manually.
|
154
|
+
|
155
|
+
```rb
|
156
|
+
if verify_rucaptcha?(@user) && @user.save
|
157
|
+
do_whatever_you_want
|
158
|
+
redirect_to someplace_you_want
|
159
|
+
else
|
160
|
+
# this is the trick
|
161
|
+
@user.errors.add(:base, t('rucaptcha.invalid'))
|
162
|
+
render :new
|
163
|
+
end
|
164
|
+
```
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module BlogsCaptcha
|
2
|
+
class CaptchaController < ActionController::Base
|
3
|
+
def index
|
4
|
+
return head :ok if request.head?
|
5
|
+
headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
|
6
|
+
headers['Pragma'] = 'no-cache'
|
7
|
+
data = generate_rucaptcha
|
8
|
+
opts = { disposition: 'inline', type: 'image/gif' }
|
9
|
+
send_data data, opts
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
// Colors from
|
2
|
+
// https://material.io/guidelines/style/color.html#color-ui-color-palette
|
3
|
+
// Color covert HEX RGB to \x??\x??\x??
|
4
|
+
static char *colors[] = {
|
5
|
+
// Black 500 #000000
|
6
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
7
|
+
"\x00\x00\x00"
|
8
|
+
"\x00\x00\x00"
|
9
|
+
"\x00\x00\x00"
|
10
|
+
"\x00\x00\x00"
|
11
|
+
"\x00\x00\x00"
|
12
|
+
"\x00\x00\x00"
|
13
|
+
"\x00\x00\x00"
|
14
|
+
"\x00\x00\x00"
|
15
|
+
"\x00\x00\x00"
|
16
|
+
"\x00\x00\x00"
|
17
|
+
"\x00\x00\x00"
|
18
|
+
"\x00\x00\x00"
|
19
|
+
"\x00\x00\x00"
|
20
|
+
"\x00\x00\x00"
|
21
|
+
"\x00\x00\x00"
|
22
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
23
|
+
|
24
|
+
// Red A700 #D50000
|
25
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
26
|
+
"\xD5\x00\x00"
|
27
|
+
"\xD5\x00\x00"
|
28
|
+
"\xD5\x00\x00"
|
29
|
+
"\xD5\x00\x00"
|
30
|
+
"\xD5\x00\x00"
|
31
|
+
"\xD5\x00\x00"
|
32
|
+
"\xD5\x00\x00"
|
33
|
+
"\xD5\x00\x00"
|
34
|
+
"\xD5\x00\x00"
|
35
|
+
"\xD5\x00\x00"
|
36
|
+
"\xD5\x00\x00"
|
37
|
+
"\xD5\x00\x00"
|
38
|
+
"\xD5\x00\x00"
|
39
|
+
"\xD5\x00\x00"
|
40
|
+
"\xD5\x00\x00"
|
41
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
42
|
+
|
43
|
+
// Deep Orange A700 #DD2C00
|
44
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
45
|
+
"\xDD\x2C\x00"
|
46
|
+
"\xDD\x2C\x00"
|
47
|
+
"\xDD\x2C\x00"
|
48
|
+
"\xDD\x2C\x00"
|
49
|
+
"\xDD\x2C\x00"
|
50
|
+
"\xDD\x2C\x00"
|
51
|
+
"\xDD\x2C\x00"
|
52
|
+
"\xDD\x2C\x00"
|
53
|
+
"\xDD\x2C\x00"
|
54
|
+
"\xDD\x2C\x00"
|
55
|
+
"\xDD\x2C\x00"
|
56
|
+
"\xDD\x2C\x00"
|
57
|
+
"\xDD\x2C\x00"
|
58
|
+
"\xDD\x2C\x00"
|
59
|
+
"\xDD\x2C\x00"
|
60
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
61
|
+
|
62
|
+
// Blue A700 #2962FF
|
63
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
64
|
+
"\x29\x62\xFF"
|
65
|
+
"\x29\x62\xFF"
|
66
|
+
"\x29\x62\xFF"
|
67
|
+
"\x29\x62\xFF"
|
68
|
+
"\x29\x62\xFF"
|
69
|
+
"\x29\x62\xFF"
|
70
|
+
"\x29\x62\xFF"
|
71
|
+
"\x29\x62\xFF"
|
72
|
+
"\x29\x62\xFF"
|
73
|
+
"\x29\x62\xFF"
|
74
|
+
"\x29\x62\xFF"
|
75
|
+
"\x29\x62\xFF"
|
76
|
+
"\x29\x62\xFF"
|
77
|
+
"\x29\x62\xFF"
|
78
|
+
"\x29\x62\xFF"
|
79
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
80
|
+
|
81
|
+
// Pink A700 #C51162
|
82
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
83
|
+
"\xC5\x11\x62"
|
84
|
+
"\xC5\x11\x62"
|
85
|
+
"\xC5\x11\x62"
|
86
|
+
"\xC5\x11\x62"
|
87
|
+
"\xC5\x11\x62"
|
88
|
+
"\xC5\x11\x62"
|
89
|
+
"\xC5\x11\x62"
|
90
|
+
"\xC5\x11\x62"
|
91
|
+
"\xC5\x11\x62"
|
92
|
+
"\xC5\x11\x62"
|
93
|
+
"\xC5\x11\x62"
|
94
|
+
"\xC5\x11\x62"
|
95
|
+
"\xC5\x11\x62"
|
96
|
+
"\xC5\x11\x62"
|
97
|
+
"\xC5\x11\x62"
|
98
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04",
|
99
|
+
|
100
|
+
// Deep Purple A700 #6200EA
|
101
|
+
"GIF89a" "\xc8\0\x46\0" "\x83" "\0\0"
|
102
|
+
"\x62\x00\xEA"
|
103
|
+
"\x62\x00\xEA"
|
104
|
+
"\x62\x00\xEA"
|
105
|
+
"\x62\x00\xEA"
|
106
|
+
"\x62\x00\xEA"
|
107
|
+
"\x62\x00\xEA"
|
108
|
+
"\x62\x00\xEA"
|
109
|
+
"\x62\x00\xEA"
|
110
|
+
"\x62\x00\xEA"
|
111
|
+
"\x62\x00\xEA"
|
112
|
+
"\x62\x00\xEA"
|
113
|
+
"\x62\x00\xEA"
|
114
|
+
"\x62\x00\xEA"
|
115
|
+
"\x62\x00\xEA"
|
116
|
+
"\x62\x00\xEA"
|
117
|
+
"\xff\xff\xff" "," "\0\0\0\0" "\xc8\0\x46\0" "\0" "\x04"
|
118
|
+
};
|
@@ -0,0 +1,27 @@
|
|
1
|
+
static int8_t lt0[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-4,11,7,5,3,1,0,0,0,1,3,7,13,-100,-2,11,3,0,0,0,0,0,0,0,0,0,0,0,0,9,-100,-1,7,0,0,0,0,0,0,3,9,11,9,3,0,0,0,0,13,-100,9,0,0,0,0,0,0,3,-5,3,0,0,0,7,-100,5,0,0,0,0,0,1,13,-5,9,0,0,0,1,-100,7,0,0,0,0,1,13,-6,13,0,0,0,0,-100,-1,9,1,0,5,13,-8,0,0,0,0,13,-100,-14,0,0,0,0,11,-100,-14,0,0,0,0,11,-100,-14,0,0,0,0,11,-100,-12,13,5,0,0,0,0,11,-100,-8,13,9,5,1,0,0,0,0,0,0,11,-100,-4,13,7,3,1,0,0,0,0,1,1,0,0,0,0,11,-100,-2,13,5,0,0,0,0,0,5,9,13,-2,0,0,0,0,11,-100,-1,13,1,0,0,0,0,7,-6,0,0,0,0,11,-100,13,1,0,0,0,0,13,-7,0,0,0,0,11,-100,5,0,0,0,0,5,-8,0,0,0,0,11,-100,0,0,0,0,0,11,-8,0,0,0,0,11,-100,0,0,0,0,0,13,-7,13,0,0,0,0,11,-100,1,0,0,0,0,-7,9,0,0,0,0,0,9,-3,9,-100,5,0,0,0,0,3,13,-3,11,3,0,0,0,0,0,0,0,9,13,3,5,-100,13,0,0,0,0,0,0,1,1,0,0,0,1,11,9,0,0,0,0,0,0,1,13,-100,-1,11,1,0,0,0,0,0,0,0,0,5,-3,9,0,0,0,0,0,11,-100,-2,13,7,3,0,0,0,3,7,13,-5,9,0,1,3,9,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
2
|
+
static int8_t lt1[]={-100,-100,-4,13,5,0,3,-100,-3,11,1,0,0,0,7,-100,-2,7,0,0,0,0,0,3,-100,13,3,0,0,0,0,0,0,5,-100,1,0,0,0,0,0,0,0,9,-100,1,0,0,0,0,0,0,0,13,-100,13,3,0,0,0,0,0,1,-100,-2,5,0,0,0,0,5,-100,-3,0,0,0,0,9,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,9,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,3,13,9,5,3,1,0,0,1,3,5,9,-100,-3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,13,-100,-3,0,0,0,0,0,5,13,-2,13,11,9,5,0,0,0,0,1,13,-100,-3,0,0,0,0,1,-8,13,1,0,0,0,5,-100,-3,3,0,0,0,5,-9,13,0,0,0,0,11,-100,-3,0,0,0,0,9,-10,7,0,0,0,5,-100,-3,1,0,0,0,11,-10,13,0,0,0,0,-100,-3,3,0,0,0,11,-11,3,0,0,0,11,-100,-3,1,0,0,0,11,-11,7,0,0,0,7,-100,-3,0,0,0,0,11,-11,9,0,0,0,3,-100,-3,0,0,0,0,11,-11,11,0,0,0,1,-100,-3,0,0,0,0,11,-11,11,0,0,0,1,-100,-3,0,0,0,0,11,-11,11,0,0,0,0,-100,-3,0,0,0,0,11,-11,9,0,0,0,0,-100,-3,0,0,0,0,11,-11,7,0,0,0,3,-100,-3,0,0,0,0,11,-11,3,0,0,0,7,-100,-3,0,0,0,0,11,-11,0,0,0,0,11,-100,-3,0,0,0,0,11,-10,9,0,0,0,3,-100,-3,0,0,0,0,9,-10,3,0,0,0,11,-100,-3,0,0,0,0,3,-9,11,0,0,0,5,-100,-2,13,0,0,0,0,0,9,-7,11,1,0,0,3,-100,-2,7,0,0,0,0,0,0,7,13,-2,13,9,3,0,0,0,3,13,-100,-2,13,0,0,5,13,11,1,0,0,0,0,0,0,0,0,0,7,-100,-3,9,11,-4,7,3,1,0,0,1,5,9,13,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
3
|
+
static int8_t lt2[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-6,13,7,3,1,0,0,1,3,7,13,-100,-5,9,0,0,0,0,0,0,0,0,0,0,5,13,-100,-3,13,3,0,0,0,5,13,13,7,0,0,0,0,0,1,13,-100,-2,13,1,0,0,0,9,-4,7,0,0,0,0,0,1,-100,-1,13,1,0,0,0,9,-6,5,0,0,0,0,0,13,-100,-1,5,0,0,0,3,-8,1,0,0,0,3,-100,13,0,0,0,0,11,-8,13,3,0,3,-100,7,0,0,0,1,-100,5,0,0,0,5,-100,3,0,0,0,9,-100,1,0,0,0,11,-100,0,0,0,0,11,-100,0,0,0,0,11,-100,0,0,0,0,11,-100,0,0,0,0,9,-100,1,0,0,0,5,-100,5,0,0,0,0,13,-100,11,0,0,0,0,7,-100,-1,3,0,0,0,0,13,-100,-1,11,0,0,0,0,3,-12,9,-100,-2,7,0,0,0,0,3,13,-8,9,1,3,-100,-3,5,0,0,0,0,1,9,-5,9,3,0,0,11,-100,-4,5,0,0,0,0,0,0,1,1,1,0,0,0,0,11,-100,-5,9,1,0,0,0,0,0,0,0,0,0,3,13,-100,-7,11,7,3,1,0,1,3,7,11,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
4
|
+
static int8_t lt3[]={-100,-100,-100,-100,-18,11,3,0,-100,-16,13,3,0,0,0,-100,-14,9,3,0,0,0,0,0,-100,-13,3,0,0,0,0,0,0,0,-100,-13,0,0,0,0,0,0,0,0,-100,-13,9,1,0,0,0,0,0,0,-100,-15,13,5,0,0,0,0,-100,-17,1,0,0,0,-100,-17,3,0,0,0,-100,-17,1,0,0,0,-100,-17,0,0,0,0,-100,-16,13,0,0,0,0,-100,-16,13,0,0,0,0,-100,-6,11,5,3,1,0,0,1,5,9,13,13,0,0,0,0,-100,-4,13,3,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,-100,-3,13,1,0,0,0,0,5,11,-1,13,11,3,0,0,0,0,0,0,-100,-2,13,1,0,0,0,0,7,-6,11,0,0,0,0,0,-100,-2,3,0,0,0,0,9,-8,11,0,0,0,0,-100,-1,9,0,0,0,0,7,-9,11,0,0,0,0,-100,-1,1,0,0,0,0,13,-9,11,0,0,0,0,-100,11,0,0,0,0,3,-10,11,0,0,0,0,-100,5,0,0,0,0,13,-10,11,0,0,0,0,-100,3,0,0,0,3,-11,11,0,0,0,0,-100,0,0,0,0,7,-11,11,0,0,0,0,-100,0,0,0,0,11,-11,11,0,0,0,0,-100,0,0,0,0,11,-11,11,0,0,0,0,-100,0,0,0,0,11,-11,11,0,0,0,0,-100,1,0,0,0,9,-11,11,0,0,0,0,-100,3,0,0,0,7,-11,11,0,0,0,0,-100,7,0,0,0,3,-11,11,0,0,0,0,-100,13,0,0,0,0,13,-10,13,0,0,0,0,-100,-1,3,0,0,0,5,-11,0,0,0,0,-100,-1,13,0,0,0,0,11,-10,0,0,0,0,-100,-2,7,0,0,0,1,13,-8,13,0,0,0,0,13,-100,-3,5,0,0,0,1,11,-7,5,0,0,0,0,9,-100,-4,5,0,0,0,0,3,9,13,-1,13,11,1,0,0,0,0,0,0,0,5,-100,-5,9,1,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,1,13,-100,-7,9,3,1,0,0,3,7,13,-1,11,1,0,1,5,7,11,-100,-18,13,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
5
|
+
static int8_t lt4[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-7,13,5,1,1,0,1,3,9,13,-100,-6,5,0,0,0,0,0,0,0,0,0,9,-100,-4,11,1,0,0,3,11,-1,13,7,1,0,0,0,9,-100,-3,9,0,0,0,1,13,-5,3,0,0,1,-100,-2,9,0,0,0,0,13,-6,11,0,0,0,9,-100,-1,13,0,0,0,0,9,-8,0,0,0,1,-100,-1,5,0,0,0,0,13,-8,3,0,0,0,11,-100,-1,0,0,0,0,0,-8,13,1,0,0,0,5,-100,9,0,0,0,0,0,3,11,-4,13,11,1,0,0,0,0,1,-100,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-100,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,-100,1,0,0,0,1,13,-100,0,0,0,0,11,-100,0,0,0,0,11,-100,1,0,0,0,9,-100,3,0,0,0,7,-100,7,0,0,0,5,-100,13,0,0,0,0,11,-100,-1,5,0,0,0,1,13,-100,-1,13,1,0,0,0,1,13,-10,13,11,-100,-2,11,0,0,0,0,1,13,-8,13,1,1,-100,-3,11,0,0,0,0,0,7,13,-4,11,7,0,0,9,-100,-4,11,1,0,0,0,0,0,1,1,1,0,0,0,0,7,-100,-5,13,5,0,0,0,0,0,0,0,0,0,1,9,-100,-7,13,7,3,0,0,0,1,5,9,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
6
|
+
static int8_t lt5[]={-100,-100,-100,-100,-9,13,9,3,1,0,1,5,13,-100,-8,7,0,0,0,0,0,0,0,3,-100,-7,3,0,0,0,0,0,0,0,0,1,-100,-6,5,0,0,0,0,0,0,0,0,0,3,-100,-5,13,0,0,3,13,9,1,0,0,0,0,11,-100,-5,9,0,0,13,-2,13,5,0,1,9,-100,-5,5,0,0,-100,-5,1,0,1,-100,-5,1,0,0,-100,-5,0,0,0,-100,-5,0,0,0,13,-100,-5,0,0,0,9,-100,-5,0,0,0,7,-100,-5,0,0,0,5,-100,-3,13,7,0,0,0,0,9,-1,13,11,13,-100,3,0,0,0,0,0,0,0,0,0,0,0,0,0,9,-100,3,0,0,0,0,0,0,0,0,0,0,0,0,0,9,-100,-1,11,13,-1,7,0,0,0,0,5,-1,13,11,13,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,11,-100,-5,0,0,0,0,7,-100,-3,13,5,0,0,0,0,0,7,13,-100,-1,5,0,0,0,0,0,0,0,0,0,0,0,1,11,-100,-1,7,1,0,0,0,0,0,0,0,0,1,3,7,13,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
7
|
+
static int8_t lt6[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-7,11,7,3,1,0,0,1,3,7,13,-4,13,7,5,7,11,-100,-5,11,3,0,0,0,0,0,0,0,0,0,0,5,13,13,5,0,0,0,0,0,-100,-4,9,0,0,0,5,13,-1,13,9,3,0,0,0,0,0,0,0,0,0,0,0,1,-100,-3,11,0,0,0,5,-6,5,0,0,0,0,0,11,13,9,3,0,9,-100,-2,13,0,0,0,0,13,-7,1,0,0,0,0,13,-100,-2,1,0,0,0,7,-8,7,0,0,0,0,7,-100,-2,0,0,0,0,9,-8,11,0,0,0,0,3,-100,-2,0,0,0,0,11,-9,0,0,0,0,1,-100,-2,0,0,0,0,11,-9,0,0,0,0,0,-100,-2,0,0,0,0,9,-8,13,0,0,0,0,1,-100,-2,3,0,0,0,5,-8,9,0,0,0,0,7,-100,-2,13,1,0,0,0,13,-7,5,0,0,0,0,13,-100,-3,11,0,0,0,3,13,-5,7,0,0,0,0,11,-100,-4,7,0,0,0,1,9,13,-1,13,7,0,0,0,1,11,-100,-4,13,0,0,0,0,0,0,0,0,0,0,0,5,13,-100,-4,13,0,0,0,0,0,0,1,3,5,9,-100,-2,13,5,0,11,-100,-1,13,1,0,0,-100,-1,3,0,0,0,1,7,13,-100,-1,0,0,0,0,0,0,0,1,3,7,9,11,13,-100,-1,5,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,5,11,-100,-2,11,7,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,11,-100,-4,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,-100,-3,9,1,0,3,9,13,13,11,7,3,0,0,0,0,0,0,0,0,0,13,-100,-1,7,1,0,0,9,-8,11,7,3,0,0,0,0,0,5,-100,9,0,0,0,3,-13,11,1,0,0,1,-100,1,0,0,0,9,-15,0,0,0,-100,0,0,0,0,9,-14,13,0,0,1,-100,3,0,0,0,1,-14,7,0,0,5,-100,11,0,0,0,0,5,-12,11,0,0,0,13,-100,-1,11,1,0,0,0,1,7,11,13,-1,13,13,11,9,5,3,1,0,0,3,13,-100,-3,9,3,0,0,0,0,0,0,0,0,0,0,0,0,0,1,9,-100,-6,9,7,3,1,1,0,0,1,1,3,7,11,-100,-101};
|
8
|
+
static int8_t lt7[]={-100,-100,-100,-100,-4,13,7,1,9,-100,-2,13,7,0,0,0,3,-100,-1,7,0,0,0,0,0,5,-100,1,0,0,0,0,0,0,7,-100,3,0,0,0,0,0,0,7,-100,13,7,0,0,0,0,0,9,-100,-2,5,0,0,0,0,9,-100,-2,11,0,0,0,0,9,-100,-3,0,0,0,0,9,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-5,11,5,1,0,1,7,-100,-3,0,0,0,0,11,-3,13,3,0,0,0,0,0,0,3,-100,-3,0,0,0,0,11,-2,7,0,0,0,0,0,0,0,0,0,9,-100,-3,0,0,0,0,11,11,3,0,5,11,-1,13,9,1,0,0,0,3,-100,-3,0,0,0,0,3,0,1,11,-6,1,0,0,0,13,-100,-3,0,0,0,0,0,5,-8,11,0,0,0,11,-100,-3,0,0,0,0,11,-10,0,0,0,7,-100,-3,0,0,0,0,13,-10,0,0,0,7,-100,-3,0,0,0,0,11,-10,0,0,0,7,-100,-3,0,0,0,0,11,-10,0,0,0,7,-100,-3,0,0,0,0,13,-10,0,0,0,9,-100,-3,0,0,0,0,13,-10,0,0,0,9,-100,-3,0,0,0,0,-11,0,0,0,11,-100,-3,0,0,0,1,-11,0,0,0,13,-100,-3,0,0,0,1,-11,0,0,0,13,-100,-3,0,0,0,3,-11,0,0,0,-100,-3,0,0,0,3,-11,0,0,0,-100,-3,0,0,0,3,-11,0,0,0,-100,-3,0,0,0,3,-10,13,0,0,0,13,-100,-3,0,0,0,1,-10,13,0,0,0,11,-100,-2,9,0,0,0,0,-10,11,0,0,0,5,-100,-1,7,0,0,0,0,0,5,13,-7,13,3,0,0,0,0,7,-100,5,0,0,0,0,0,0,0,0,3,-5,1,0,0,0,0,0,0,1,3,11,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
9
|
+
static int8_t lt8[]={-100,-100,-100,-100,-3,5,1,0,3,11,-100,-2,7,0,0,0,0,0,11,-100,-2,1,0,0,0,0,0,5,-100,-2,0,0,0,0,0,0,5,-100,-2,5,0,0,0,0,0,11,-100,-3,7,0,0,3,9,-100,-4,13,-100,-100,-100,-100,-100,-100,-100,-4,11,3,0,9,-100,-2,9,3,0,0,0,9,-100,11,1,0,0,0,0,0,7,-100,1,0,0,0,0,0,0,7,-100,1,0,0,0,0,0,0,9,-100,-1,11,0,0,0,0,0,9,-100,-2,7,0,0,0,0,11,-100,-3,0,0,0,0,13,-100,-3,1,0,0,0,-100,-3,1,0,0,0,13,-100,-3,1,0,0,0,13,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-2,13,0,0,0,0,7,-100,-2,13,0,0,0,0,1,-100,-2,7,0,0,0,0,0,9,-100,7,0,0,0,0,0,0,0,0,3,-100,9,5,1,1,0,0,1,1,3,5,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
10
|
+
static int8_t lt9[]={-100,-100,-100,-100,-6,5,0,1,5,13,-100,-5,5,0,0,0,0,1,-100,-5,1,0,0,0,0,0,13,-100,-5,0,0,0,0,0,0,-100,-5,5,0,0,0,0,3,-100,-6,7,1,0,5,13,-100,-100,-100,-100,-100,-100,-100,-100,-6,13,7,3,0,13,-100,-5,7,0,0,0,0,11,-100,-3,7,1,0,0,0,0,0,11,-100,-2,13,0,0,0,0,0,0,0,11,-100,-3,11,3,0,0,0,0,0,11,-100,-5,9,0,0,0,0,11,-100,-6,1,0,0,0,11,-100,-6,3,0,0,0,11,-100,-6,5,0,0,0,11,-100,-6,5,0,0,0,11,-100,-6,5,0,0,0,11,-100,-6,5,0,0,0,11,-100,-6,3,0,0,0,11,-100,-6,3,0,0,0,11,-100,-6,1,0,0,0,11,-100,-6,1,0,0,0,13,-100,-6,1,0,0,0,13,-100,-6,1,0,0,0,13,-100,-6,1,0,0,0,13,-100,-6,1,0,0,0,13,-100,-6,1,0,0,0,-100,-6,1,0,0,0,-100,-6,1,0,0,1,-100,-6,1,0,0,3,-100,-6,0,0,0,5,-100,-6,0,0,0,7,-100,-6,0,0,0,11,-100,11,0,0,0,5,5,0,0,5,-100,3,0,0,0,0,0,0,3,-100,0,0,0,0,0,0,0,13,-100,1,0,0,0,0,0,11,-100,13,3,0,0,3,11,-100,-100,-101};
|
11
|
+
static int8_t lt10[]={-100,-100,-100,-100,-6,9,1,13,-100,-3,13,5,0,0,0,11,-100,-1,13,5,0,0,0,0,0,11,-100,13,1,0,0,0,0,0,0,11,-100,3,0,0,0,0,0,0,0,11,-100,11,3,0,0,0,0,0,0,11,-100,-2,13,0,0,0,0,0,11,-100,-3,9,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-7,3,0,0,0,0,0,0,0,0,0,3,-100,-4,0,0,0,0,11,-7,5,0,0,0,0,0,0,0,1,7,13,-100,-4,0,0,0,0,11,-8,9,0,0,0,1,9,-100,-4,0,0,0,0,11,-7,13,1,0,0,7,-100,-4,0,0,0,0,11,-7,5,0,3,13,-100,-4,0,0,0,0,11,-6,5,0,5,-100,-4,0,0,0,0,11,-5,5,1,11,-100,-4,0,0,0,0,11,-3,11,3,1,-100,-4,0,0,0,0,11,-1,11,3,0,0,1,-100,-4,0,0,0,0,11,9,0,0,0,0,0,11,-100,-4,0,0,0,0,0,0,1,0,0,0,0,3,-100,-4,0,0,0,0,0,9,-1,11,1,0,0,0,9,-100,-4,0,0,0,0,5,-4,3,0,0,0,11,-100,-4,0,0,0,0,11,-4,13,1,0,0,0,13,-100,-4,0,0,0,0,11,-5,11,0,0,0,1,13,-100,-4,0,0,0,0,11,-6,3,0,0,0,3,-100,-4,0,0,0,0,11,-6,11,0,0,0,0,7,-100,-4,0,0,0,0,11,-7,3,0,0,0,0,7,-100,-3,13,0,0,0,0,11,-7,13,0,0,0,0,0,7,-100,-2,13,3,0,0,0,0,7,-7,9,0,0,0,0,0,0,3,11,-100,-1,1,0,0,0,0,0,0,0,0,1,3,-4,0,0,0,0,0,0,0,0,0,0,3,-100,-1,7,1,0,0,0,0,0,0,0,0,7,-4,3,0,0,0,0,0,0,1,1,5,9,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
12
|
+
static int8_t lt11[]={-100,-100,-100,-6,11,7,11,-100,-4,11,3,0,0,5,-100,-3,5,0,0,0,0,5,-100,-1,11,1,0,0,0,0,0,7,-100,7,0,0,0,0,0,0,0,7,-100,0,0,0,0,0,0,0,0,9,-100,7,0,0,0,0,0,0,0,9,-100,-2,9,1,0,0,0,0,9,-100,-3,11,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,7,-100,-3,5,0,0,0,0,0,13,-100,-1,9,1,0,0,0,0,0,0,0,1,9,-100,-1,5,1,0,0,0,0,0,0,0,1,11,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
13
|
+
static int8_t lt12[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-5,11,5,0,-21,7,1,0,3,9,-100,-4,7,0,0,0,13,-4,11,5,1,1,0,1,7,-7,11,3,0,0,0,0,0,5,-100,-2,11,1,0,0,0,0,11,-2,9,1,0,0,0,0,0,0,0,9,-4,13,5,0,0,0,0,0,0,0,0,7,-100,13,3,0,0,0,0,0,0,7,13,3,0,0,0,1,0,0,0,0,0,0,7,-1,13,7,0,0,0,0,0,0,0,0,0,0,0,11,-100,3,0,0,0,0,0,0,0,1,0,0,5,11,-3,11,0,0,0,0,0,0,0,3,9,13,13,-3,7,0,0,0,0,5,-100,13,3,0,0,0,0,0,0,0,7,13,-6,3,0,0,0,0,0,9,-8,5,0,0,0,1,-100,-2,11,0,0,0,0,0,3,-8,9,0,0,0,0,7,-9,11,0,0,0,0,-100,-3,3,0,0,0,0,7,-8,13,0,0,0,0,-10,11,0,0,0,0,-100,-3,7,0,0,0,0,11,-9,0,0,0,0,-10,11,0,0,0,1,-100,-3,11,0,0,0,0,11,-9,0,0,0,0,-10,11,0,0,0,3,-100,-3,13,0,0,0,0,11,-8,13,0,0,0,0,-10,11,0,0,0,5,-100,-3,13,0,0,0,0,11,-8,11,0,0,0,0,-10,11,0,0,0,5,-100,-4,0,0,0,0,13,-8,9,0,0,0,0,-10,11,0,0,0,5,-100,-4,0,0,0,0,13,-8,11,0,0,0,0,-10,11,0,0,0,3,-100,-4,0,0,0,0,13,-8,11,0,0,0,0,-10,11,0,0,0,0,-100,-3,13,0,0,0,1,-9,13,0,0,0,0,-10,11,0,0,0,0,-100,-3,11,0,0,0,13,-10,0,0,0,0,-10,11,0,0,0,0,-100,-4,0,0,0,11,-10,0,0,0,0,-10,11,0,0,0,0,-100,-3,13,0,0,0,3,-9,13,0,0,0,0,13,-9,9,0,0,0,0,-100,-3,7,0,0,0,0,13,-8,11,0,0,0,0,11,-9,7,0,0,0,0,13,-100,-3,3,0,0,0,0,9,-8,5,0,0,0,0,5,-9,5,0,0,0,0,7,-100,-1,13,3,0,0,0,0,0,1,11,-6,9,0,0,0,0,0,0,3,-7,11,1,0,0,0,0,1,13,-100,11,0,0,0,0,0,0,0,0,0,3,-4,3,0,0,0,0,0,0,0,0,5,-5,1,0,0,0,0,0,0,0,0,9,-100,13,1,0,0,0,0,0,0,0,1,9,-4,1,0,0,0,0,0,0,0,1,5,-5,1,0,0,0,0,0,0,0,0,7,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
14
|
+
static int8_t lt13[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-3,13,7,3,0,13,-5,13,7,1,0,0,3,7,-100,-2,5,0,0,0,0,-4,13,3,0,0,0,0,0,0,0,7,-100,7,1,0,0,0,0,0,-3,7,0,0,0,0,0,0,0,0,0,0,13,-100,1,0,0,0,0,0,0,13,9,1,0,5,11,13,-1,11,3,0,0,0,0,9,-100,13,3,0,0,0,0,0,1,1,7,-7,3,0,0,0,3,-100,-2,1,0,0,0,0,7,-9,13,0,0,0,1,-100,-2,7,0,0,0,0,-11,1,0,0,0,-100,-2,9,0,0,0,0,-11,1,0,0,0,13,-100,-2,11,0,0,0,0,-11,3,0,0,0,13,-100,-2,11,0,0,0,0,-11,5,0,0,0,11,-100,-2,11,0,0,0,0,-11,3,0,0,0,11,-100,-2,11,0,0,0,0,-11,1,0,0,0,11,-100,-2,11,0,0,0,0,-11,0,0,0,0,11,-100,-2,11,0,0,0,0,-11,0,0,0,0,11,-100,-2,11,0,0,0,0,-11,1,0,0,0,11,-100,-2,11,0,0,0,0,-11,3,0,0,0,11,-100,-2,11,0,0,0,0,-11,3,0,0,0,11,-100,-2,11,0,0,0,0,13,-10,5,0,0,0,11,-100,-2,11,0,0,0,0,13,-10,5,0,0,0,11,-100,-2,11,0,0,0,0,9,-10,5,0,0,0,9,-100,-2,7,0,0,0,0,5,-10,3,0,0,0,7,-100,-1,13,1,0,0,0,0,1,11,-7,11,5,0,0,0,0,0,3,9,-100,-1,1,0,0,0,0,0,0,0,0,3,-4,3,0,0,0,0,0,0,0,0,0,3,-100,-1,0,0,0,0,0,0,0,0,0,3,-4,5,1,0,0,0,0,0,0,0,0,1,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
15
|
+
static int8_t lt14[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-7,13,7,3,1,0,0,1,5,9,-100,-6,7,0,0,0,0,0,0,0,0,0,1,7,-100,-4,11,1,0,0,1,9,13,-1,13,11,5,0,0,0,3,13,-100,-3,11,0,0,0,3,13,-6,13,1,0,0,0,13,-100,-2,11,0,0,0,1,13,-8,13,0,0,0,5,-100,-2,0,0,0,0,9,-10,5,0,0,0,11,-100,-1,7,0,0,0,1,-11,13,0,0,0,1,-100,-1,1,0,0,0,5,-12,1,0,0,0,9,-100,11,0,0,0,0,11,-12,5,0,0,0,3,-100,7,0,0,0,0,13,-12,9,0,0,0,0,-100,3,0,0,0,0,13,-12,11,0,0,0,0,-100,1,0,0,0,0,-13,11,0,0,0,1,-100,0,0,0,0,0,-13,11,0,0,0,1,-100,0,0,0,0,0,13,-12,11,0,0,0,0,-100,1,0,0,0,0,13,-12,9,0,0,0,1,-100,5,0,0,0,0,11,-12,5,0,0,0,3,-100,9,0,0,0,0,9,-12,3,0,0,0,7,-100,-1,1,0,0,0,5,-12,0,0,0,0,11,-100,-1,9,0,0,0,3,-11,13,0,0,0,3,-100,-2,3,0,0,0,13,-10,7,0,0,0,11,-100,-2,13,1,0,0,3,-9,13,0,0,0,7,-100,-3,13,1,0,0,3,13,-6,13,1,0,0,5,-100,-4,13,1,0,0,1,7,13,-3,9,0,0,0,7,-100,-6,7,0,0,0,0,0,0,0,0,0,3,11,-100,-7,13,7,3,0,0,0,0,3,11,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
16
|
+
static int8_t lt15[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-6,11,7,-100,-4,11,3,0,0,7,11,5,3,0,0,0,1,5,9,-100,-2,11,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,-100,13,5,0,0,0,0,0,0,0,1,7,11,13,-1,13,3,0,0,0,5,-100,1,0,0,0,0,0,0,0,3,-7,7,0,0,0,7,-100,1,0,0,0,0,0,0,0,11,-8,7,0,0,0,13,-100,-1,11,5,0,0,0,0,0,11,-9,1,0,0,3,-100,-3,7,0,0,0,0,11,-9,5,0,0,0,11,-100,-3,9,0,0,0,0,11,-9,9,0,0,0,5,-100,-3,11,0,0,0,0,11,-9,11,0,0,0,0,13,-100,-3,11,0,0,0,0,11,-9,13,0,0,0,0,11,-100,-3,13,0,0,0,0,11,-10,0,0,0,0,11,-100,-3,13,0,0,0,0,11,-10,0,0,0,0,11,-100,-3,13,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,0,0,0,0,11,-10,0,0,0,0,13,-100,-4,0,0,0,0,11,-10,0,0,0,0,13,-100,-4,0,0,0,0,13,-10,0,0,0,0,-100,-4,0,0,0,9,-11,0,0,0,3,-100,-4,0,0,0,3,-11,0,0,0,9,-100,-4,0,0,0,0,13,-10,0,0,0,13,-100,-4,0,0,0,0,11,-9,5,0,0,0,-100,-4,0,0,0,0,11,-8,7,0,0,0,7,-100,-4,0,0,0,0,5,-7,9,0,0,0,3,-100,-4,0,0,0,0,0,3,11,13,-3,9,0,0,0,1,-100,-4,0,0,0,0,5,7,0,0,0,1,1,0,0,0,1,13,-100,-4,0,0,0,0,11,-2,9,5,1,0,0,3,7,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,7,-100,-4,0,0,0,0,3,-100,-3,7,0,0,0,0,0,9,-100,-1,5,0,0,0,0,0,0,0,0,0,0,5,-100,-1,3,1,0,0,0,0,0,0,0,0,0,5,-100,-101};
|
17
|
+
static int8_t lt16[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-19,7,11,-100,-6,11,5,1,0,0,1,5,11,-4,5,0,3,-100,-4,13,3,0,0,0,0,0,0,0,0,1,11,13,5,0,0,1,-100,-3,13,1,0,0,1,5,11,-3,11,3,0,0,0,0,0,3,-100,-2,13,1,0,0,3,-8,3,0,0,0,0,5,-100,-1,13,1,0,0,0,13,-8,7,0,0,0,0,5,-100,-1,3,0,0,0,5,-9,11,0,0,0,0,7,-100,9,0,0,0,0,11,-9,13,0,0,0,0,9,-100,3,0,0,0,0,-10,13,0,0,0,0,9,-100,1,0,0,0,1,-11,0,0,0,0,9,-100,0,0,0,0,3,-11,0,0,0,0,11,-100,0,0,0,0,5,-11,0,0,0,0,11,-100,0,0,0,0,9,-11,0,0,0,0,11,-100,0,0,0,0,11,-11,0,0,0,0,11,-100,0,0,0,0,11,-11,0,0,0,0,11,-100,1,0,0,0,11,-11,0,0,0,0,11,-100,3,0,0,0,9,-11,0,0,0,0,11,-100,7,0,0,0,5,-11,0,0,0,0,11,-100,11,0,0,0,0,-11,0,0,0,0,11,-100,-1,1,0,0,0,7,-9,11,0,0,0,0,11,-100,-1,9,0,0,0,0,13,-8,9,0,0,0,0,11,-100,-2,3,0,0,0,1,13,-7,5,0,0,0,0,11,-100,-2,13,3,0,0,0,1,9,13,-3,13,7,0,0,0,0,0,11,-100,-4,9,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,11,-100,-6,11,7,3,1,0,0,5,9,-1,13,0,0,0,0,11,-100,-16,0,0,0,0,13,-100,-16,0,0,0,0,13,-100,-16,0,0,0,0,13,-100,-16,0,0,0,0,13,-100,-15,13,0,0,0,0,13,-100,-15,9,0,0,0,0,11,-100,-15,1,0,0,0,0,5,-100,-12,7,5,1,0,0,0,0,0,0,1,3,9,-100,-11,13,1,0,0,0,0,0,0,0,0,0,0,7,-100,-101};
|
18
|
+
static int8_t lt17[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-3,13,5,0,3,-5,9,3,1,0,0,3,-100,-1,11,3,0,0,0,0,-3,7,0,0,0,0,0,0,0,5,-100,9,0,0,0,0,0,0,-2,3,0,0,0,0,0,0,0,0,1,-100,0,0,0,0,0,0,0,11,3,0,0,0,0,0,0,0,0,0,1,-100,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,-100,-1,7,0,0,0,0,0,0,7,13,-2,11,7,3,1,3,11,-100,-2,3,0,0,0,0,3,-100,-2,7,0,0,0,0,9,-100,-2,11,0,0,0,0,13,-100,-2,13,0,0,0,0,-100,-3,0,0,0,0,-100,-3,0,0,0,0,13,-100,-3,0,0,0,0,13,-100,-3,0,0,0,0,13,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,11,-100,-3,0,0,0,0,9,-100,-1,13,3,0,0,0,0,1,13,-100,3,0,0,0,0,0,0,0,0,0,0,13,-100,5,1,0,0,0,0,0,0,0,0,3,13,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
19
|
+
static int8_t lt18[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-3,13,7,1,0,1,3,9,11,9,9,13,-100,-2,13,1,0,0,0,0,0,0,0,0,0,5,-100,-2,1,0,5,13,-1,13,11,3,0,0,0,1,-100,-1,9,0,1,-6,9,0,0,0,13,-100,-1,3,0,9,-7,11,1,0,9,-100,-1,0,0,-9,13,1,5,-100,-1,0,0,11,-9,13,11,-100,13,0,0,1,13,-100,13,0,0,0,1,9,-100,-1,0,0,0,0,0,0,5,9,-100,-1,5,0,0,0,0,0,0,0,1,7,13,-100,-1,13,0,0,0,0,0,0,0,0,0,0,9,-100,-2,13,1,0,0,0,0,0,0,0,0,0,7,-100,-4,11,5,0,0,0,0,0,0,0,0,7,-100,-7,9,5,0,0,0,0,0,0,13,-100,-9,13,7,0,0,0,0,7,-100,-11,13,3,0,0,3,-100,-13,0,0,0,-100,7,5,-11,1,0,0,-100,1,0,5,-10,1,0,3,-100,0,0,0,3,-9,0,0,9,-100,1,0,0,0,3,13,-6,5,0,3,-100,7,0,0,0,0,1,7,11,13,13,9,3,0,1,13,-100,13,0,0,0,0,0,0,0,0,0,0,0,3,13,-100,-1,5,3,9,7,3,1,0,0,1,5,11,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
20
|
+
static int8_t lt19[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-6,5,0,5,-100,-5,13,0,0,0,7,-100,-5,7,0,0,0,9,-100,-5,3,0,0,0,13,-100,-4,11,0,0,0,0,-100,-4,3,0,0,0,0,-100,-3,5,0,0,0,0,1,-100,-2,3,0,0,0,0,0,7,-100,13,1,0,0,0,0,0,0,1,11,-100,3,0,0,0,0,0,0,0,0,0,0,0,0,0,5,13,-100,1,0,0,0,0,0,0,0,0,0,0,0,0,0,5,-100,-3,9,0,0,0,0,7,13,-100,-4,0,0,0,0,11,-100,-4,1,0,0,0,11,-100,-4,1,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,0,0,0,0,11,-100,-4,1,0,0,0,11,-100,-4,3,0,0,0,11,-100,-4,5,0,0,0,11,-100,-4,3,0,0,0,11,-100,-4,3,0,0,0,11,-100,-4,1,0,0,0,9,-100,-4,0,0,0,0,5,-100,-4,0,0,0,0,1,-100,-4,1,0,0,0,0,11,-100,-4,3,0,0,0,0,1,13,-1,9,5,1,3,-100,-4,9,0,0,0,0,0,0,0,0,0,0,5,-100,-5,5,0,0,0,0,0,0,0,0,5,-100,-6,9,3,1,0,0,1,5,11,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
21
|
+
static int8_t lt20[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-4,13,9,1,0,13,-11,11,5,1,5,-100,-2,11,3,0,0,0,0,11,-8,11,5,0,0,0,0,1,-100,13,3,0,0,0,0,0,0,11,-6,7,1,0,0,0,0,0,0,7,-100,5,0,0,0,0,0,0,0,11,-5,5,0,0,0,0,0,0,0,0,11,-100,11,1,0,0,0,0,0,0,11,-5,9,0,0,0,0,0,0,0,0,11,-100,-2,11,1,0,0,0,0,11,-6,13,7,3,0,0,0,0,0,11,-100,-3,9,0,0,0,0,11,-9,9,0,0,0,0,11,-100,-3,11,0,0,0,0,11,-10,0,0,0,0,11,-100,-3,13,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,0,0,0,0,11,-10,0,0,0,0,11,-100,-4,1,0,0,0,11,-9,13,0,0,0,0,11,-100,-4,1,0,0,0,11,-9,5,0,0,0,0,11,-100,-4,5,0,0,0,7,-8,7,0,0,0,0,0,11,-100,-4,7,0,0,0,0,13,-5,13,5,0,0,0,0,0,0,11,-100,-4,13,0,0,0,0,1,11,-1,13,11,5,0,0,7,5,0,0,0,0,3,13,-100,-5,3,0,0,0,0,0,0,0,0,0,3,13,-2,0,0,0,0,0,0,7,-100,-5,11,0,0,0,0,0,0,0,1,9,-4,0,0,0,0,0,0,0,-100,-6,13,5,1,0,1,3,9,-6,3,1,3,7,9,11,13,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
22
|
+
static int8_t lt21[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-6,13,9,1,3,13,-5,13,1,0,0,0,0,1,3,9,-100,1,0,0,0,0,0,0,0,0,0,1,-5,1,0,0,0,0,0,0,0,0,9,-100,3,0,0,0,0,0,0,0,0,0,5,-5,3,0,0,0,0,0,0,0,0,13,-100,-1,9,3,0,0,0,0,0,5,13,-7,13,9,0,0,0,0,1,11,-100,-3,7,0,0,0,0,-11,7,0,0,5,-100,-4,0,0,0,0,9,-10,9,0,5,-100,-4,5,0,0,0,1,-10,5,0,11,-100,-4,11,0,0,0,0,9,-9,0,1,-100,-5,1,0,0,0,3,-8,9,0,7,-100,-5,7,0,0,0,0,13,-7,3,0,13,-100,-5,13,0,0,0,0,7,-6,13,0,3,-100,-6,3,0,0,0,1,-6,7,0,11,-100,-6,9,0,0,0,0,9,-5,0,1,-100,-6,13,0,0,0,0,3,-4,7,0,7,-100,-7,5,0,0,0,0,11,-3,1,0,13,-100,-7,11,0,0,0,0,1,-2,9,0,5,-100,-8,1,0,0,0,0,5,-1,1,0,11,-100,-8,7,0,0,0,0,0,0,0,3,-100,-8,13,0,0,0,0,0,0,0,9,-100,-9,3,0,0,0,0,0,1,-100,-9,9,0,0,0,0,0,7,-100,-10,0,0,0,0,0,13,-100,-10,5,0,0,0,1,-100,-10,13,1,0,0,7,-100,-11,11,1,5,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
23
|
+
static int8_t lt22[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-29,13,-100,5,0,0,1,1,1,3,3,5,7,-3,7,0,0,0,0,0,0,0,0,0,11,-4,3,0,0,0,0,0,0,1,3,11,-100,5,0,0,0,0,0,0,0,1,7,-3,9,0,0,0,0,0,0,0,0,1,11,-4,9,1,0,0,0,0,0,0,1,13,-100,-1,13,5,0,0,0,0,0,13,-5,13,5,0,0,0,0,0,3,-8,9,0,0,0,0,5,-100,-3,5,0,0,0,0,-8,11,0,0,0,0,9,-9,9,0,0,9,-100,-4,1,0,0,0,13,-8,11,0,0,0,3,-10,0,3,-100,-4,7,0,0,0,11,-8,13,0,0,0,0,13,-8,9,0,11,-100,-4,13,0,0,0,7,-8,11,0,0,0,0,7,-8,1,1,-100,-5,5,0,0,1,-8,7,0,0,0,0,3,-8,5,11,-100,-5,11,0,0,0,9,-7,1,0,0,0,0,0,13,-100,-6,0,0,0,3,-6,9,0,3,13,0,0,0,7,-6,5,-100,-6,3,0,0,0,13,-5,1,0,11,-1,3,0,0,3,-6,1,-100,-6,9,0,0,0,9,-4,11,0,3,-2,7,0,0,0,13,-4,11,1,-100,-6,13,0,0,0,3,-4,5,0,9,-2,13,0,0,0,7,-4,5,3,-100,-7,3,0,0,0,13,-3,1,1,-4,0,0,0,1,-4,1,7,-100,-7,9,0,0,0,5,-2,13,0,7,-4,5,0,0,0,9,-2,9,0,13,-100,-8,1,0,0,0,13,-1,7,1,-5,11,0,0,0,1,-2,1,3,-100,-8,7,0,0,0,1,13,1,5,-6,1,0,0,0,13,9,0,9,-100,-8,13,0,0,0,0,0,0,11,-6,7,0,0,0,1,0,1,-100,-9,3,0,0,0,0,3,-7,13,0,0,0,0,0,9,-100,-9,9,0,0,0,0,5,-8,3,0,0,0,0,13,-100,-9,13,0,0,0,0,11,-8,9,0,0,0,1,-100,-10,3,0,0,0,-10,3,0,0,5,-100,-10,11,0,0,7,-10,13,1,1,13,-100,-11,11,11,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
24
|
+
static int8_t lt23[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-16,13,13,-1,13,9,5,1,0,1,5,13,-100,-1,3,0,0,0,0,0,0,0,0,1,7,-4,1,0,0,0,0,0,0,0,0,0,1,-100,-1,1,0,0,0,0,0,0,0,0,1,11,-4,7,0,0,0,0,0,0,0,0,0,5,-100,-2,13,7,0,0,0,0,0,0,13,-6,13,5,0,0,0,0,5,9,13,-100,-4,13,3,0,0,0,0,3,-7,13,0,0,5,13,-100,-6,3,0,0,0,0,5,-6,7,0,7,-100,-7,3,0,0,0,0,11,-4,11,0,9,-100,-8,5,0,0,0,1,-3,11,0,7,-100,-9,3,0,0,0,1,11,11,0,7,-100,-9,13,1,0,0,0,0,0,7,-100,-10,13,1,0,0,0,0,9,-100,-11,11,0,0,0,0,1,-100,-12,0,0,0,0,0,7,-100,-11,9,0,0,0,0,0,0,11,-100,-10,9,0,5,13,3,0,0,0,1,13,-100,-9,11,0,3,-2,13,1,0,0,0,1,13,-100,-8,11,0,3,13,-3,13,1,0,0,0,1,13,-100,-7,9,0,1,13,-5,11,0,0,0,0,1,13,-100,-6,9,0,0,7,-7,9,0,0,0,0,1,11,-100,-5,5,0,0,0,13,-8,7,0,0,0,0,0,9,-100,-3,13,3,0,0,0,0,13,-8,13,0,0,0,0,0,0,5,-100,9,3,1,0,0,0,0,0,0,1,11,-6,11,1,0,0,0,0,0,0,0,1,3,13,-100,3,0,0,0,0,0,0,0,0,0,3,-6,11,5,3,1,0,0,0,1,1,3,5,-100,13,13,13,13,-100,-100,-100,-100,-100,-100,-100,-100,-100,-101};
|
25
|
+
static int8_t lt24[]={-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-100,-1,13,13,-2,13,13,11,11,11,13,-6,11,11,11,11,11,11,11,11,13,-100,3,0,0,0,0,0,0,0,0,0,0,3,-4,1,0,0,0,0,0,0,0,0,1,-100,7,0,0,0,0,0,0,0,0,0,0,5,-4,3,0,0,0,0,0,0,0,0,9,-100,-2,11,5,0,0,0,0,0,0,11,-6,11,0,0,0,0,1,7,13,-100,-4,11,0,0,0,0,0,-8,9,0,0,1,13,-100,-5,7,0,0,0,0,13,-7,9,0,0,13,-100,-6,1,0,0,0,9,-7,5,0,5,-100,-6,7,0,0,0,3,-7,1,0,13,-100,-6,13,0,0,0,0,13,-5,11,0,1,-100,-7,5,0,0,0,7,-5,7,0,7,-100,-7,11,0,0,0,3,-5,1,0,11,-100,-8,1,0,0,0,13,-3,13,0,3,-100,-8,7,0,0,0,7,-3,7,0,9,-100,-8,13,0,0,0,3,-3,1,1,-100,-9,5,0,0,0,13,-1,9,0,7,-100,-9,11,0,0,0,3,13,1,0,13,-100,-10,1,0,0,0,0,0,3,-100,-10,9,0,0,0,0,0,9,-100,-11,1,0,0,0,1,-100,-11,5,0,0,0,7,-100,-11,9,0,0,0,13,-100,-11,13,0,0,3,-100,-12,0,0,9,-100,-12,0,1,-100,-11,13,0,7,-100,-11,7,0,11,-100,-11,1,0,-100,-2,7,0,1,7,-4,11,0,3,-100,-1,11,0,0,0,0,1,9,13,11,1,0,9,-100,-1,3,0,0,0,0,0,0,0,0,0,3,-100,-1,0,0,0,0,0,0,0,0,0,1,13,-100,-1,7,0,0,0,0,0,0,0,1,13,-100,-2,9,3,0,0,1,3,7,-100,-101};
|
26
|
+
static int8_t *lt[]={lt0,lt1,lt2,lt3,lt0,lt5,lt0,lt7,lt8,lt9,lt10,lt11,lt12,lt13,lt14,lt15,lt16,lt17,lt18,lt19,lt20,lt21,lt22,lt23,lt24,};
|
27
|
+
|
@@ -0,0 +1,240 @@
|
|
1
|
+
// http://github.com/ITikhonov/captcha
|
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);
|
5
|
+
|
6
|
+
#include <unistd.h>
|
7
|
+
#include <stdint.h>
|
8
|
+
#include <stdlib.h>
|
9
|
+
#include <fcntl.h>
|
10
|
+
#include <string.h>
|
11
|
+
#include <time.h>
|
12
|
+
#include <ruby.h>
|
13
|
+
#include "font.h"
|
14
|
+
#include "colors.h"
|
15
|
+
|
16
|
+
static int8_t *lt[];
|
17
|
+
const int gifsize=17646;
|
18
|
+
|
19
|
+
void makegif(unsigned char im[70*200], unsigned char gif[gifsize], int style) {
|
20
|
+
// tag ; widthxheight ; GCT:0:0:7 ; bgcolor + aspect // GCT
|
21
|
+
// Image Separator // left x top // widthxheight // Flags
|
22
|
+
// LZW code size
|
23
|
+
srand(time(NULL));
|
24
|
+
int color_len = (int) sizeof(colors) / sizeof(colors[0]);
|
25
|
+
int color_idx = rand() % color_len;
|
26
|
+
if (style == 0) {
|
27
|
+
color_idx = 0;
|
28
|
+
}
|
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
|
+
*p++=250; // Data length 5*50=250
|
36
|
+
for(x=0;x<50;x++)
|
37
|
+
{
|
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); // bbb10000
|
41
|
+
p[1]=(a>>3)|64|(b<<7); // b10000xb
|
42
|
+
p[2]=b>>1; // 0000xbbb
|
43
|
+
p[3]=1|(c<<1); // 00xbbbb1
|
44
|
+
p[4]=4|(d<<3); // xbbbb100
|
45
|
+
i+=4;
|
46
|
+
p+=5;
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
// Data length // End of LZW (b10001) // Terminator // GIF End
|
51
|
+
memcpy(gif+gifsize-4,"\x01" "\x11" "\x00" ";",4);
|
52
|
+
}
|
53
|
+
|
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
|
+
#define MAX(x,y) ((x>y)?(x):(y))
|
58
|
+
|
59
|
+
static int letter(int n, int pos, unsigned char im[70*200], unsigned char swr[200], uint8_t s1, uint8_t s2) {
|
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(;*p!=-101;p++) {
|
68
|
+
if(*p<0) {
|
69
|
+
if(*p==-100) { r+=200; i=r; sk1=s1+pos; row++; continue; }
|
70
|
+
i+=-*p;
|
71
|
+
continue;
|
72
|
+
}
|
73
|
+
|
74
|
+
if(sk1>=200) sk1=sk1%200;
|
75
|
+
int skew=sw[sk1]/16;
|
76
|
+
sk1+=(swr[pos+i-r]&0x1)+1;
|
77
|
+
|
78
|
+
if(sk2>=200) sk2=sk2%200;
|
79
|
+
int skewh=sw[sk2]/70;
|
80
|
+
sk2+=(swr[row]&0x1);
|
81
|
+
|
82
|
+
unsigned char *x=i+skew*200+skewh;
|
83
|
+
mpos=MAX(mpos,pos+i-r);
|
84
|
+
|
85
|
+
if((x-im)<70*200) *x=(*p)<<4;
|
86
|
+
i++;
|
87
|
+
}
|
88
|
+
return mpos + 3;
|
89
|
+
}
|
90
|
+
|
91
|
+
#define NDOTS 10
|
92
|
+
|
93
|
+
uint32_t dr[NDOTS];
|
94
|
+
|
95
|
+
static void line(unsigned char im[70*200], unsigned char swr[200], uint8_t s1) {
|
96
|
+
int x;
|
97
|
+
int sk1=s1;
|
98
|
+
for(x=0;x<199;x++) {
|
99
|
+
if(sk1>=200) sk1=sk1%200;
|
100
|
+
int skew=sw[sk1]/20;
|
101
|
+
sk1+=swr[x]&0x3+1;
|
102
|
+
unsigned char *i= im+(200*(45+skew)+x);
|
103
|
+
i[0]=0; i[1]=0; i[200]=0; i[201]=0;
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
static void dots(unsigned char im[70*200]) {
|
108
|
+
int n;
|
109
|
+
for(n=0;n<NDOTS;n++) {
|
110
|
+
uint32_t v=dr[n];
|
111
|
+
unsigned char *i=im+v%(200*67);
|
112
|
+
|
113
|
+
i[0]=0xff;
|
114
|
+
i[1]=0xff;
|
115
|
+
i[2]=0xff;
|
116
|
+
i[200]=0xff;
|
117
|
+
i[201]=0xff;
|
118
|
+
i[202]=0xff;
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
static void blur(unsigned char im[70*200]) {
|
123
|
+
unsigned char *i=im;
|
124
|
+
int x,y;
|
125
|
+
for(y=0;y<68;y++) {
|
126
|
+
for(x=0;x<198;x++) {
|
127
|
+
unsigned int c11=*i,c12=i[1],c21=i[200],c22=i[201];
|
128
|
+
*i++=((c11+c12+c21+c22)/4);
|
129
|
+
}
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
static void filter(unsigned char im[70*200]) {
|
134
|
+
unsigned char om[70*200];
|
135
|
+
unsigned char *i=im;
|
136
|
+
unsigned char *o=om;
|
137
|
+
|
138
|
+
memset(om,0xff,sizeof(om));
|
139
|
+
|
140
|
+
int x,y;
|
141
|
+
for(y=0;y<70;y++) {
|
142
|
+
for(x=4;x<200-4;x++) {
|
143
|
+
if(i[0]>0xf0 && i[1]<0xf0) { o[0]=0; o[1]=0; }
|
144
|
+
else if(i[0]<0xf0 && i[1]>0xf0) { o[0]=0; o[1]=0; }
|
145
|
+
|
146
|
+
i++;
|
147
|
+
o++;
|
148
|
+
}
|
149
|
+
}
|
150
|
+
|
151
|
+
memmove(im,om,sizeof(om));
|
152
|
+
}
|
153
|
+
|
154
|
+
static const char *letters="abcdafahijklmnopqrstuvwxyz";
|
155
|
+
|
156
|
+
void captcha(unsigned char im[70*200], unsigned char l[8], int length, int i_line, int i_filter) {
|
157
|
+
unsigned char swr[200];
|
158
|
+
uint8_t s1,s2;
|
159
|
+
|
160
|
+
int f=open("/dev/urandom",O_RDONLY);
|
161
|
+
read(f,l,5); read(f,swr,200); read(f,dr,sizeof(dr)); read(f,&s1,1); read(f,&s2,1);
|
162
|
+
close(f);
|
163
|
+
memset(im,0xff,200*70); s1=s1&0x7f; s2=s2&0x3f;
|
164
|
+
|
165
|
+
int x;
|
166
|
+
for(x=0;x<length;x++){
|
167
|
+
l[x]%=25;
|
168
|
+
}
|
169
|
+
for(x=length;x<8;x++){
|
170
|
+
l[length]=0;
|
171
|
+
}
|
172
|
+
//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
|
+
p=letter(l[x],p,im,swr,s1,s2);
|
176
|
+
}
|
177
|
+
|
178
|
+
if (i_line == 1) {
|
179
|
+
line(im,swr,s1);
|
180
|
+
}
|
181
|
+
// dots(im);
|
182
|
+
if (i_filter == 1) {
|
183
|
+
blur(im);
|
184
|
+
filter(im);
|
185
|
+
}
|
186
|
+
|
187
|
+
for(x=0;x<length;x++){
|
188
|
+
l[x]=letters[l[x]];
|
189
|
+
}
|
190
|
+
//l[1]=letters[l[1]]; l[2]=letters[l[2]]; l[3]=letters[l[3]]; //l[4]=letters[l[4]];
|
191
|
+
}
|
192
|
+
|
193
|
+
// #ifdef CAPTCHA
|
194
|
+
//
|
195
|
+
// int main() {
|
196
|
+
// char l[6];
|
197
|
+
// unsigned char im[70*200];
|
198
|
+
// unsigned char gif[gifsize];
|
199
|
+
//
|
200
|
+
// captcha(im,l);
|
201
|
+
// makegif(im,gif);
|
202
|
+
//
|
203
|
+
// write(1,gif,gifsize);
|
204
|
+
// write(2,l,5);
|
205
|
+
//
|
206
|
+
// return 0;
|
207
|
+
// }
|
208
|
+
//
|
209
|
+
// #endif
|
210
|
+
|
211
|
+
VALUE RuCaptcha = Qnil;
|
212
|
+
|
213
|
+
void Init_rucaptcha();
|
214
|
+
|
215
|
+
VALUE create(VALUE self, VALUE style, VALUE length, VALUE line, VALUE filter);
|
216
|
+
|
217
|
+
void Init_rucaptcha() {
|
218
|
+
RuCaptcha = rb_define_module("RuCaptcha");
|
219
|
+
rb_define_singleton_method(RuCaptcha, "create", create, 4);
|
220
|
+
}
|
221
|
+
|
222
|
+
VALUE create(VALUE self, VALUE style, VALUE length, VALUE line, VALUE filter) {
|
223
|
+
char l[8];
|
224
|
+
unsigned char im[80*200];
|
225
|
+
unsigned char gif[gifsize];
|
226
|
+
int i_style = FIX2INT(style);
|
227
|
+
int i_length = FIX2INT(length);
|
228
|
+
int i_line = FIX2INT(line);
|
229
|
+
int i_filter = FIX2INT(filter);
|
230
|
+
|
231
|
+
captcha(im, l, i_length, i_line, i_filter);
|
232
|
+
makegif(im, gif, i_style);
|
233
|
+
|
234
|
+
VALUE result = rb_ary_new2(2);
|
235
|
+
rb_ary_push(result, rb_str_new2(l));
|
236
|
+
rb_ary_push(result, rb_str_new(gif, gifsize));
|
237
|
+
|
238
|
+
return result;
|
239
|
+
}
|
240
|
+
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'rails'
|
2
|
+
require 'action_controller'
|
3
|
+
require 'active_support/all'
|
4
|
+
require 'blogs_captcha/blogs_captcha'
|
5
|
+
require 'blogs_captcha/version'
|
6
|
+
require 'blogs_captcha/configuration'
|
7
|
+
require 'blogs_captcha/controller_helpers'
|
8
|
+
require 'blogs_captcha/view_helpers'
|
9
|
+
require 'blogs_captcha/cache'
|
10
|
+
require 'blogs_captcha/engine'
|
11
|
+
require 'blogs_captcha/errors/configuration'
|
12
|
+
|
13
|
+
module BlogsCaptcha
|
14
|
+
class << self
|
15
|
+
def config
|
16
|
+
return @config if defined?(@config)
|
17
|
+
@config = Configuration.new
|
18
|
+
@config.style = :colorful
|
19
|
+
@config.length = 5
|
20
|
+
@config.strikethrough = true
|
21
|
+
@config.outline = false
|
22
|
+
@config.expires_in = 2.minutes
|
23
|
+
@config.skip_cache_store_check = false
|
24
|
+
|
25
|
+
if Rails.application
|
26
|
+
@config.cache_store = Rails.application.config.cache_store
|
27
|
+
else
|
28
|
+
@config.cache_store = :mem_cache_store
|
29
|
+
end
|
30
|
+
@config.cache_store
|
31
|
+
@config
|
32
|
+
end
|
33
|
+
|
34
|
+
def configure(&block)
|
35
|
+
config.instance_exec(&block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def generate()
|
39
|
+
style = config.style == :colorful ? 1 : 0
|
40
|
+
length = config.length
|
41
|
+
|
42
|
+
unless length.in?(3..7)
|
43
|
+
raise BlogsCaptcha::Errors::Configuration, 'length config error, value must in 3..7'
|
44
|
+
end
|
45
|
+
|
46
|
+
strikethrough = config.strikethrough ? 1 : 0
|
47
|
+
outline = config.outline ? 1 : 0
|
48
|
+
self.create(style, length, strikethrough, outline)
|
49
|
+
end
|
50
|
+
|
51
|
+
def check_cache_store!
|
52
|
+
cache_store = BlogsCaptcha.config.cache_store
|
53
|
+
store_name = cache_store.is_a?(Array) ? cache_store.first : cache_store
|
54
|
+
if [:memory_store, :null_store, :file_store].include?(store_name)
|
55
|
+
BlogsCaptcha.config.cache_store = [:file_store, Rails.root.join('tmp/cache/rucaptcha/session')]
|
56
|
+
|
57
|
+
puts "
|
58
|
+
|
59
|
+
RuCaptcha's cache_store requirements are stored across processes and machines,
|
60
|
+
such as :mem_cache_store, :redis_store, or other distributed storage.
|
61
|
+
But your current set is #{cache_store}, it has changed to :file_store for working.
|
62
|
+
NOTE: :file_store is still not a good way, it only works with single server case.
|
63
|
+
|
64
|
+
Please make config file `config/initializers/rucaptcha.rb` to setup `cache_store`.
|
65
|
+
More infomation please read GitHub RuCaptcha README file.
|
66
|
+
https://github.com/huacnlee/rucaptcha
|
67
|
+
|
68
|
+
"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
ActiveSupport.on_load(:action_controller) do
|
75
|
+
ActionController::Base.send :include, BlogsCaptcha::ControllerHelpers
|
76
|
+
end
|
77
|
+
|
78
|
+
ActiveSupport.on_load(:action_view) do
|
79
|
+
include BlogsCaptcha::ViewHelpers
|
80
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module BlogsCaptcha
|
2
|
+
class Configuration
|
3
|
+
# Store Captcha code where, this config more like Rails config.cache_store
|
4
|
+
# default: Rails application config.cache_store
|
5
|
+
attr_accessor :cache_store
|
6
|
+
# rucaptcha expire time, default 2 minutes
|
7
|
+
attr_accessor :expires_in
|
8
|
+
# Color style, default: :colorful, allows: [:colorful, :black_white]
|
9
|
+
attr_accessor :style
|
10
|
+
# Chars length: default 5, allows: [3..7]
|
11
|
+
attr_accessor :length
|
12
|
+
# strikethrough, default: true
|
13
|
+
attr_accessor :strikethrough
|
14
|
+
# outline style for hard mode, default: false
|
15
|
+
attr_accessor :outline
|
16
|
+
# skip_cache_store_check, default: false
|
17
|
+
attr_accessor :skip_cache_store_check
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module BlogsCaptcha
|
2
|
+
module ControllerHelpers
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
helper_method :verify_rucaptcha?
|
7
|
+
end
|
8
|
+
|
9
|
+
# session key of rucaptcha
|
10
|
+
def rucaptcha_sesion_key_key
|
11
|
+
session_id = session.respond_to?(:id) ? session.id : session[:session_id]
|
12
|
+
warning_when_session_invalid if session_id.blank?
|
13
|
+
['rucaptcha-session', session_id].join(':')
|
14
|
+
end
|
15
|
+
|
16
|
+
# Generate a new Captcha
|
17
|
+
def generate_rucaptcha
|
18
|
+
res = BlogsCaptcha.generate()
|
19
|
+
session_val = {
|
20
|
+
code: res[0],
|
21
|
+
time: Time.now.to_i
|
22
|
+
}
|
23
|
+
RuCaptcha.cache.write(rucaptcha_sesion_key_key, session_val, expires_in: RuCaptcha.config.expires_in)
|
24
|
+
res[1]
|
25
|
+
end
|
26
|
+
|
27
|
+
# Verify captcha code
|
28
|
+
#
|
29
|
+
# params:
|
30
|
+
# resource - [optional] a ActiveModel object, if given will add validation error message to object.
|
31
|
+
# :keep_session - if true, RuCaptcha will not delete the captcha code session.
|
32
|
+
# :captcha - if given, the value of it will be used to verify the captcha,
|
33
|
+
# if do not give or blank, the value of params[:_rucaptcha] will be used to verify the captcha
|
34
|
+
#
|
35
|
+
# exmaples:
|
36
|
+
#
|
37
|
+
# verify_rucaptcha?
|
38
|
+
# verify_rucaptcha?(user, keep_session: true)
|
39
|
+
# verify_rucaptcha?(nil, keep_session: true)
|
40
|
+
# verify_rucaptcha?(nil, captcha: params[:user][:captcha])
|
41
|
+
#
|
42
|
+
def verify_rucaptcha?(resource = nil, opts = {})
|
43
|
+
opts ||= {}
|
44
|
+
|
45
|
+
store_info = BlogsCaptcha.cache.read(rucaptcha_sesion_key_key)
|
46
|
+
# make sure move used key
|
47
|
+
BlogsCaptcha.cache.delete(rucaptcha_sesion_key_key) unless opts[:keep_session]
|
48
|
+
|
49
|
+
# Make sure session exist
|
50
|
+
if store_info.blank?
|
51
|
+
return add_rucaptcha_validation_error
|
52
|
+
end
|
53
|
+
|
54
|
+
# Make sure not expire
|
55
|
+
if (Time.now.to_i - store_info[:time]) > BlogsCaptcha.config.expires_in
|
56
|
+
return add_rucaptcha_validation_error
|
57
|
+
end
|
58
|
+
|
59
|
+
# Make sure parama have captcha
|
60
|
+
captcha = (opts[:captcha] || params[:_rucaptcha] || '').downcase.strip
|
61
|
+
if captcha.blank?
|
62
|
+
return add_rucaptcha_validation_error
|
63
|
+
end
|
64
|
+
|
65
|
+
if captcha != store_info[:code]
|
66
|
+
return add_rucaptcha_validation_error
|
67
|
+
end
|
68
|
+
|
69
|
+
true
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def add_rucaptcha_validation_error
|
75
|
+
if defined?(resource) && resource && resource.respond_to?(:errors)
|
76
|
+
resource.errors.add(:base, t('rucaptcha.invalid'))
|
77
|
+
end
|
78
|
+
false
|
79
|
+
end
|
80
|
+
|
81
|
+
def warning_when_session_invalid
|
82
|
+
Rails.logger.warn "
|
83
|
+
WARNING! The session.id is blank, RuCaptcha can't work properly, please keep session available.
|
84
|
+
More details about this: https://github.com/huacnlee/rucaptcha/pull/66
|
85
|
+
"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module BlogsCaptcha
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
isolate_namespace BlogsCaptcha
|
4
|
+
|
5
|
+
initializer 'rucaptcha.init' do |app|
|
6
|
+
# https://github.com/rails/rails/blob/3-2-stable/actionpack/lib/action_dispatch/routing/route_set.rb#L268
|
7
|
+
# `app.routes.prepend` start from Rails 3.2 - 5.0
|
8
|
+
app.routes.prepend do
|
9
|
+
mount BlogsCaptcha::Engine => '/rucaptcha'
|
10
|
+
end
|
11
|
+
|
12
|
+
BlogsCaptcha.check_cache_store! unless BlogsCaptcha.config.skip_cache_store_check
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module BlogsCaptcha
|
2
|
+
module ViewHelpers
|
3
|
+
def rucaptcha_input_tag(opts = {})
|
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] ||= 5
|
11
|
+
tag(:input, opts)
|
12
|
+
end
|
13
|
+
|
14
|
+
def rucaptcha_image_tag(opts = {})
|
15
|
+
opts[:class] = opts[:class] || 'rucaptcha-image'
|
16
|
+
image_tag(ru_captcha.root_path, opts)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: blogs_captcha
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jason Lee
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-03-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: railties
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake-compiler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1'
|
41
|
+
description:
|
42
|
+
email: huacnlee@gmail.com
|
43
|
+
executables: []
|
44
|
+
extensions:
|
45
|
+
- ext/blogs_captcha/extconf.rb
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- CHANGELOG.md
|
49
|
+
- README.md
|
50
|
+
- app/controllers/blogs_captcha/captcha_controller.rb
|
51
|
+
- config/locales/rucaptcha.en.yml
|
52
|
+
- config/locales/rucaptcha.pt-BR.yml
|
53
|
+
- config/locales/rucaptcha.zh-CN.yml
|
54
|
+
- config/locales/rucaptcha.zh-TW.yml
|
55
|
+
- config/routes.rb
|
56
|
+
- ext/blogs_captcha/colors.h
|
57
|
+
- ext/blogs_captcha/extconf.rb
|
58
|
+
- ext/blogs_captcha/font.h
|
59
|
+
- ext/blogs_captcha/rucaptcha.c
|
60
|
+
- lib/blogs_captcha.rb
|
61
|
+
- lib/blogs_captcha/cache.rb
|
62
|
+
- lib/blogs_captcha/configuration.rb
|
63
|
+
- lib/blogs_captcha/controller_helpers.rb
|
64
|
+
- lib/blogs_captcha/engine.rb
|
65
|
+
- lib/blogs_captcha/errors/configuration.rb
|
66
|
+
- lib/blogs_captcha/version.rb
|
67
|
+
- lib/blogs_captcha/view_helpers.rb
|
68
|
+
homepage: https://github.com/huacnlee/rucaptcha
|
69
|
+
licenses:
|
70
|
+
- MIT
|
71
|
+
metadata: {}
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: 2.0.0
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 2.7.8
|
89
|
+
signing_key:
|
90
|
+
specification_version: 4
|
91
|
+
summary: This is a Captcha gem for Rails Applications. It drawing captcha image with
|
92
|
+
C code so it no dependencies.
|
93
|
+
test_files: []
|