flatulent 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README +18 -1
- data/flatulent-0.0.2.gem +0 -0
- data/lib/flatulent.rb +320 -166
- data/rails/log/development.log +6279 -0
- data/rails/log/fastcgi.crash.log +78 -0
- data/rails/log/lighttpd.access.log +1430 -0
- data/rails/log/lighttpd.error.log +88 -0
- data/sample.html +47 -0
- data/samples.rb +52 -7
- metadata +3 -2
data/README
CHANGED
@@ -5,7 +5,7 @@ NAME
|
|
5
5
|
SYNOPSIS
|
6
6
|
|
7
7
|
the flatulent gem provides brain dead simple to use, but internally cunning,
|
8
|
-
ascii art captcha for ruby.
|
8
|
+
ascii art (figlet) captcha for ruby.
|
9
9
|
|
10
10
|
URI
|
11
11
|
|
@@ -17,6 +17,21 @@ HOW DO I GET FLATULENT?
|
|
17
17
|
gem install flatulent
|
18
18
|
|
19
19
|
HISTORY
|
20
|
+
0.0.3:
|
21
|
+
- following are now all equivalent when posting (thanks botp)
|
22
|
+
|
23
|
+
0==o==O==Q (zero, oh's, and queue)
|
24
|
+
l==l (one and el)
|
25
|
+
2==z==Z (two and z's)
|
26
|
+
5==s==S (5 and s's)
|
27
|
+
|
28
|
+
- random horizontal and vertical displacement of each char
|
29
|
+
|
30
|
+
- vastly improved background noise based on figlet char shapes
|
31
|
+
|
32
|
+
- inputs are case sensitive (thanks john joyce, chris carter)
|
33
|
+
|
34
|
+
- expanded rails examples
|
20
35
|
|
21
36
|
0.0.2
|
22
37
|
|
@@ -78,7 +93,9 @@ DOCS
|
|
78
93
|
|
79
94
|
ONLINE SAMPLES
|
80
95
|
|
96
|
+
http://drawohara.tumblr.com/post/4791838
|
81
97
|
http://drawohara.tumblr.com/post/4944987
|
98
|
+
http://drawohara.tumblr.com/post/4968766
|
82
99
|
|
83
100
|
ONLINE DEMO OF AJAX METHOD
|
84
101
|
|
data/flatulent-0.0.2.gem
CHANGED
Binary file
|
data/lib/flatulent.rb
CHANGED
@@ -1,10 +1,5 @@
|
|
1
|
-
# TODO - encrypt time
|
2
|
-
# TODO - noise is image chars
|
3
|
-
# TODO - newline in value??
|
4
|
-
# TODO - vertical offset in chars
|
5
|
-
|
6
1
|
class Flatulent
|
7
|
-
Flatulent::VERSION = '0.0.
|
2
|
+
Flatulent::VERSION = '0.0.3' unless defined? Flatulent::VERSION
|
8
3
|
def self.flatulent() Flatulent::VERSION end
|
9
4
|
def self.libdir() File.expand_path(__FILE__).gsub(%r/\.rb$/, '') end
|
10
5
|
|
@@ -15,6 +10,7 @@ class Flatulent
|
|
15
10
|
begin
|
16
11
|
require 'rubygems'
|
17
12
|
rescue LoadError
|
13
|
+
42
|
18
14
|
end
|
19
15
|
|
20
16
|
begin
|
@@ -31,7 +27,6 @@ class Flatulent
|
|
31
27
|
class EncryptionError < Error; end
|
32
28
|
class TimeBombError < Error; end
|
33
29
|
|
34
|
-
|
35
30
|
singleton_class =
|
36
31
|
class << self
|
37
32
|
self
|
@@ -46,29 +41,27 @@ class Flatulent
|
|
46
41
|
'font-family' => 'monospace',
|
47
42
|
'font-weight' => 'bold',
|
48
43
|
'font-size' => 'medium',
|
49
|
-
'background' => '#ffc',
|
50
|
-
'
|
44
|
+
#'background' => '#ffc',
|
45
|
+
'background' => '#ccffcc',
|
46
|
+
#'color' => '#000',
|
47
|
+
'color' => '#330066',
|
51
48
|
'margin' => '2px',
|
52
49
|
'padding' => '2px',
|
53
50
|
'display' => 'table',
|
54
51
|
] }
|
55
52
|
|
56
|
-
attribute('noise_style'){ Hash[
|
57
|
-
'color' => '#ccc',
|
58
|
-
] }
|
59
|
-
|
60
53
|
attribute('key'){ default_key }
|
61
54
|
|
62
|
-
def valid? keywords = {}
|
55
|
+
def valid? keywords = {} #--{{{
|
63
56
|
begin
|
64
57
|
validate! keywords
|
65
58
|
true
|
66
59
|
rescue EncryptionError, TimeBombError
|
67
60
|
false
|
68
61
|
end
|
69
|
-
end
|
62
|
+
end #--}}}
|
70
63
|
|
71
|
-
def validate! keywords = {}
|
64
|
+
def validate! keywords = {} #--{{{
|
72
65
|
keywords = keywords['flatulent'] if keywords.has_key?('flatulent')
|
73
66
|
keywords = keywords[:flatulent] if keywords.has_key?(:flatulent)
|
74
67
|
|
@@ -78,8 +71,8 @@ class Flatulent
|
|
78
71
|
string = opts['s'] or raise 'no string'
|
79
72
|
time = opts['t'] or raise 'no time'
|
80
73
|
|
81
|
-
expected =
|
82
|
-
actual =
|
74
|
+
expected = fuzzy(decrypt(string))
|
75
|
+
actual = fuzzy(captcha)
|
83
76
|
raise EncryptionError, "expected #{ expected } got #{ actual }" unless
|
84
77
|
expected == actual
|
85
78
|
|
@@ -87,29 +80,44 @@ class Flatulent
|
|
87
80
|
raise TimeBombError unless Time.now.utc <= timebomb
|
88
81
|
|
89
82
|
return actual
|
90
|
-
end
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
83
|
+
end #--}}}
|
84
|
+
|
85
|
+
# 0==o==O (zero and oh's)
|
86
|
+
# l==l (one and el)
|
87
|
+
# 2==z==Z (two and z's)
|
88
|
+
# 5==s==S (5 and s's)
|
89
|
+
def fuzzy string #--{{{
|
90
|
+
result = string.dup
|
91
|
+
close_enough = {
|
92
|
+
'0OoQ' => '0',
|
93
|
+
'1l' => '1',
|
94
|
+
'2zZ' => '2',
|
95
|
+
'5sS' => '5',
|
96
|
+
}
|
97
|
+
#string.gsub(%r/[0Oo]/, '0') # ignore diffs between 0/o/O
|
98
|
+
close_enough.each do |chars,char|
|
99
|
+
result.gsub! %r"[#{ chars }]", char
|
100
|
+
end
|
101
|
+
result
|
102
|
+
end #--}}}
|
95
103
|
|
96
|
-
def blowfish
|
104
|
+
def blowfish #--{{{
|
97
105
|
@blowfish ||= Hash.new{|h,k| h[k] = Crypt::Blowfish.new(key)}
|
98
|
-
end
|
106
|
+
end #--}}}
|
99
107
|
|
100
|
-
def munge string
|
101
|
-
string.strip
|
102
|
-
end
|
108
|
+
def munge string #--{{{
|
109
|
+
string.strip #.downcase
|
110
|
+
end #--}}}
|
103
111
|
|
104
|
-
def encrypt string
|
112
|
+
def encrypt string #--{{{
|
105
113
|
Base64.encode64(blowfish[key].encrypt_string(string.to_s)).chop # kill "\n"
|
106
|
-
end
|
114
|
+
end #--}}}
|
107
115
|
|
108
|
-
def decrypt string
|
116
|
+
def decrypt string #--{{{
|
109
117
|
munge(blowfish[key].decrypt_string(Base64.decode64("#{ string }\n")))
|
110
|
-
end
|
118
|
+
end #--}}}
|
111
119
|
|
112
|
-
def getopts options
|
120
|
+
def getopts options #--{{{
|
113
121
|
lambda do |key, *default|
|
114
122
|
default = default.first
|
115
123
|
break options[key] if options.has_key?(key)
|
@@ -119,22 +127,18 @@ class Flatulent
|
|
119
127
|
break options[key] if options.has_key?(key)
|
120
128
|
break default
|
121
129
|
end
|
122
|
-
end
|
130
|
+
end #--}}}
|
123
131
|
|
124
|
-
def default_key
|
125
|
-
#attribute('default_key') do
|
132
|
+
def default_key #--{{{
|
126
133
|
return @default_key if defined? @default_key
|
127
134
|
require 'socket'
|
128
135
|
hostname = Socket.gethostname
|
129
136
|
maddr = mac_address rescue nil
|
130
137
|
warn "could not determine mac addresss!" unless maddr
|
131
|
-
#puts(( Digest::MD5.hexdigest "--#{ hostname }--#{ maddr }--" ))
|
132
|
-
#Digest::MD5.hexdigest "--#{ hostname }--#{ maddr }--"
|
133
|
-
#@default_key = "--#{ hostname }--#{ maddr }--"
|
134
138
|
@default_key = "--#{ hostname }--#{ maddr }--"
|
135
|
-
end
|
139
|
+
end #--}}}
|
136
140
|
|
137
|
-
def mac_address
|
141
|
+
def mac_address #--{{{
|
138
142
|
return @mac_address if defined? @mac_address
|
139
143
|
re = %r/[^:\-](?:[0-9A-F][0-9A-F][:\-]){5}[0-9A-F][0-9A-F][^:\-]/io
|
140
144
|
cmds = '/sbin/ifconfig', '/bin/ifconfig', 'ifconfig', 'ipconfig /all'
|
@@ -160,28 +164,33 @@ class Flatulent
|
|
160
164
|
maddr.instance_eval{ @list = candidates; def list() @list end }
|
161
165
|
|
162
166
|
@mac_address = maddr
|
163
|
-
end
|
167
|
+
end #--}}}
|
164
168
|
|
165
|
-
def figlet options = {}
|
169
|
+
def figlet options = {} #--{{{
|
166
170
|
new(options).figlet
|
167
|
-
end
|
168
|
-
|
171
|
+
end #--}}}
|
172
|
+
|
173
|
+
def figlets options = {} #--{{{
|
169
174
|
new(options).figlets
|
170
|
-
end
|
171
|
-
|
175
|
+
end #--}}}
|
176
|
+
|
177
|
+
def element options = {} #--{{{
|
172
178
|
new(options).element
|
173
|
-
end
|
174
|
-
|
179
|
+
end #--}}}
|
180
|
+
|
181
|
+
def form_tags options = {} #--{{{
|
175
182
|
new(options).form_tags
|
176
|
-
end
|
177
|
-
|
183
|
+
end #--}}}
|
184
|
+
|
185
|
+
def form options = {} #--{{{
|
178
186
|
new(options).form
|
179
|
-
end
|
187
|
+
end #--}}}
|
180
188
|
|
181
|
-
def latest_prototype_lib
|
189
|
+
def latest_prototype_lib #--{{{
|
182
190
|
'http://www.prototypejs.org/assets/2007/6/20/prototype.js'
|
183
|
-
end
|
184
|
-
|
191
|
+
end #--}}}
|
192
|
+
|
193
|
+
def require_prototype #--{{{
|
185
194
|
%Q`
|
186
195
|
<script type="text/javascript">
|
187
196
|
var prototype = true;
|
@@ -204,8 +213,9 @@ class Flatulent
|
|
204
213
|
}
|
205
214
|
</script>
|
206
215
|
`
|
207
|
-
end
|
208
|
-
|
216
|
+
end #--}}}
|
217
|
+
|
218
|
+
def javascript options = {} #--{{{
|
209
219
|
id = options[:id] || options['id'] || 'flatulent'
|
210
220
|
url = options[:url] || options['url'] || '/flatulent/captcha'
|
211
221
|
%Q`
|
@@ -214,14 +224,15 @@ class Flatulent
|
|
214
224
|
new Ajax.Updater('#{ id }', '#{ url }', { method: 'get' });
|
215
225
|
</script>
|
216
226
|
`
|
217
|
-
end
|
218
|
-
|
227
|
+
end #--}}}
|
228
|
+
|
229
|
+
def ajax options = {} #--{{{
|
219
230
|
id = options[:id] || options['id'] || 'flatulent'
|
220
231
|
%Q`
|
221
232
|
<div id="#{ id }"></div>
|
222
233
|
#{ Flatulent.javascript }
|
223
234
|
`
|
224
|
-
end
|
235
|
+
end #--}}}
|
225
236
|
end
|
226
237
|
|
227
238
|
singleton_class.attributes.each{|a| attribute(a){ self.class.send a}}
|
@@ -235,12 +246,14 @@ class Flatulent
|
|
235
246
|
attribute 'ttl'
|
236
247
|
|
237
248
|
attribute 'figlet'
|
249
|
+
attribute 'vapour'
|
250
|
+
attribute 'captcha'
|
238
251
|
attribute 'figlets'
|
239
252
|
attribute 'element'
|
240
253
|
attribute 'form_tags'
|
241
254
|
attribute 'form'
|
242
255
|
|
243
|
-
def initialize arg = {}
|
256
|
+
def initialize arg = {} #--{{{
|
244
257
|
if Hash === arg
|
245
258
|
opt = getopts arg
|
246
259
|
@size = Integer opt[ 'size', 4 ]
|
@@ -252,37 +265,209 @@ class Flatulent
|
|
252
265
|
end
|
253
266
|
|
254
267
|
@font = String opt[ 'font', 'big' ]
|
255
|
-
@noise = Float opt[ 'noise', 0.
|
268
|
+
@noise = Float opt[ 'noise', 0.22 ]
|
256
269
|
@id = String opt[ 'id', 'flatulent' ]
|
257
270
|
@action = String opt[ 'action' ]
|
258
|
-
@ttl = Integer opt[ 'ttl',
|
271
|
+
@ttl = Integer opt[ 'ttl', 300 ]
|
272
|
+
@horizontal_fudge_factor = Integer opt[ 'horizontal_fudge_factor', 4 ]
|
273
|
+
@vertical_fudge_factor = Integer opt[ 'vertical_fudge_factor', 4 ]
|
274
|
+
|
275
|
+
@vapour_chars = Integer opt[ 'vapour_chars', 5 * @size ]
|
276
|
+
@vapour_level = Float opt[ 'vapour_level', 0.77 ]
|
259
277
|
|
260
278
|
figlet!
|
279
|
+
vapour!
|
280
|
+
captcha!
|
261
281
|
element!
|
262
282
|
form_tags!
|
263
283
|
form!
|
264
|
-
end
|
284
|
+
end #--}}}
|
285
|
+
|
286
|
+
def random_charset #--{{{
|
287
|
+
return @random_charset if defined? @random_charset
|
288
|
+
@random_charset = ('A' .. 'Z').to_a + ('1' .. '9').to_a
|
289
|
+
end #--}}}
|
290
|
+
|
291
|
+
def generate_random_string #--{{{
|
292
|
+
chars = []
|
293
|
+
n = random_charset.size - 1
|
294
|
+
loop {
|
295
|
+
( chars << random_charset[rand(n)] ).uniq!
|
296
|
+
break if chars.size >= @size or random_charset.size == chars.size
|
297
|
+
}
|
298
|
+
chars
|
299
|
+
end #--}}}
|
300
|
+
|
301
|
+
def random_char #--{{{
|
302
|
+
n = random_charset.size - 1
|
303
|
+
random_charset[rand(n)]
|
304
|
+
end #--}}}
|
305
|
+
|
306
|
+
def figlet! #--{{{
|
307
|
+
#spaced = @string.split(%r//).join #' ' #.join(' ')
|
308
|
+
fontfile = File.join fontdir, "#{ @font }.flf"
|
309
|
+
font = Text::Figlet::Font.new fontfile
|
310
|
+
typesetter = Text::Figlet::Typesetter.new font
|
265
311
|
|
266
|
-
|
267
|
-
chars =
|
268
|
-
|
269
|
-
|
312
|
+
@figlets = []
|
313
|
+
chars = @string.split %r//
|
314
|
+
#chars.each{|char| @figlets << typesetter[char]}
|
315
|
+
|
316
|
+
# horz fudge
|
317
|
+
chars.each do |char|
|
318
|
+
figlet = typesetter[char]
|
319
|
+
rows = figlet.split %r/\n/
|
320
|
+
height = rows.size
|
321
|
+
offset_l = " " * rand(@horizontal_fudge_factor)
|
322
|
+
offset_r = " " * rand(@horizontal_fudge_factor)
|
323
|
+
rows.size.times do |i|
|
324
|
+
rows[i] = "#{ offset_l }#{ rows[i] }#{ offset_r }"
|
325
|
+
end
|
326
|
+
@figlets.push rows
|
327
|
+
end
|
328
|
+
|
329
|
+
# vert fudge
|
330
|
+
@figlets.map! do |rows|
|
331
|
+
width = rows.first.size
|
332
|
+
offset_t = Array.new(rand(@vertical_fudge_factor)).map{ " " * width }
|
333
|
+
offset_b = Array.new(rand(@vertical_fudge_factor)).map{ " " * width }
|
334
|
+
offset_t + rows + offset_b
|
335
|
+
end
|
270
336
|
|
271
|
-
|
272
|
-
|
337
|
+
# vert normalize vert
|
338
|
+
tallest = @figlets.map{|rows| rows.size}.max
|
339
|
+
@figlets.size.times do |i|
|
340
|
+
rows = @figlets[i]
|
341
|
+
unless rows.size == tallest
|
342
|
+
width = rows.first.size
|
343
|
+
until rows.size == tallest
|
344
|
+
blank = " " * width
|
345
|
+
rows << blank
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
# generate final grid
|
351
|
+
grid = []
|
352
|
+
grid << (gridrow = '')
|
353
|
+
catch :done do
|
354
|
+
loop do
|
355
|
+
@figlets.each do |rows|
|
356
|
+
row = rows.shift || throw(:done)
|
357
|
+
gridrow << row
|
358
|
+
end
|
359
|
+
#gridrow << "\n"
|
360
|
+
grid << (gridrow = '')
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
# trim top and bottom iff emtpy
|
365
|
+
=begin
|
366
|
+
empty = lambda{|row| not rnow.detect{|cell| cell !~ %r"br|nbsp"}}
|
367
|
+
grid.delete_if{|row| row.strip.empty?}
|
368
|
+
=end
|
369
|
+
|
370
|
+
@figlet_width = grid.first.size
|
371
|
+
@figlet_height = grid.size
|
372
|
+
@figlet = grid.join("\n")
|
373
|
+
end #--}}}
|
374
|
+
|
375
|
+
def vapour! #--{{{
|
376
|
+
#spaced = @string.split(%r//).join #' ' #.join(' ')
|
273
377
|
fontfile = File.join fontdir, "#{ @font }.flf"
|
274
378
|
font = Text::Figlet::Font.new fontfile
|
275
379
|
typesetter = Text::Figlet::Typesetter.new font
|
276
|
-
@figlets = []
|
277
|
-
chars = spaced.split %r//
|
278
|
-
chars.each{|char| @figlets << typesetter[char]}
|
279
|
-
@figlet = typesetter[spaced]
|
280
|
-
end
|
281
380
|
|
282
|
-
|
381
|
+
grid = Array.new(@figlet_height).map{ Array.new(@figlet_width){ " " } }
|
382
|
+
width = grid.first.size
|
383
|
+
height = grid.size
|
384
|
+
|
385
|
+
@vapour_chars.times do
|
386
|
+
figlet = typesetter[random_char]
|
387
|
+
|
388
|
+
idxs = []
|
389
|
+
space = " "[0]
|
390
|
+
newline = "\n"[0]
|
391
|
+
i = 0
|
392
|
+
figlet.each_byte do |byte|
|
393
|
+
idxs << i unless byte == space or byte == newline
|
394
|
+
i += 1
|
395
|
+
end
|
396
|
+
#p idxs
|
397
|
+
to_vapourize = idxs.sort_by{ rand }.first((idxs.size * @vapour_level).ceil)
|
398
|
+
#p to_vapourize
|
399
|
+
to_vapourize.each{|idx| figlet[idx] = " "}
|
400
|
+
#puts figlet
|
401
|
+
|
402
|
+
figlet_grid = [] and figlet.each_line do |line|
|
403
|
+
figlet_grid << line.chomp.split(%r"")
|
404
|
+
end
|
405
|
+
|
406
|
+
xoff = rand(width - 1)
|
407
|
+
yoff = rand(height - 1)
|
408
|
+
|
409
|
+
figlet_grid.each_with_index do |row, y|
|
410
|
+
row.each_with_index do |char, x|
|
411
|
+
j = y + yoff
|
412
|
+
i = x + xoff
|
413
|
+
next if j >= height or i >= width
|
414
|
+
next if char == " "
|
415
|
+
grid[ y + yoff ][ x + xoff ] = char
|
416
|
+
end
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
@vapour = grid.map{|row| row.join}.join("\n")
|
421
|
+
end #--}}}
|
422
|
+
|
423
|
+
def captcha! #--{{{
|
424
|
+
@captcha = " " * @figlet.size
|
425
|
+
space = " "[0]
|
426
|
+
newline = "\n"[0]
|
427
|
+
noisy = %w`| / - _ ( ) \\ ! [ ]`
|
428
|
+
|
429
|
+
@figlet.size.times do |i|
|
430
|
+
fbyte = @figlet[i]
|
431
|
+
vbyte = @vapour[i]
|
432
|
+
|
433
|
+
if fbyte == newline
|
434
|
+
@captcha[i] = newline
|
435
|
+
elsif fbyte == space
|
436
|
+
#if vbyte == space
|
437
|
+
#@captcha[i] = noisy[ rand(noisy.size) ]
|
438
|
+
#else
|
439
|
+
@captcha[i] = vbyte
|
440
|
+
#end
|
441
|
+
else
|
442
|
+
@captcha[i] = fbyte
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
|
447
|
+
=begin
|
448
|
+
alpha = ('A'..'Z').to_a + ('a'..'z').to_a
|
449
|
+
transform = {
|
450
|
+
'|' => rchar(%w'. * \` + , ; : '),
|
451
|
+
'/' => rchar(%w'\\ ] [ { } ( ) @' + alpha),
|
452
|
+
'\\' => rchar(%w'/ ] [ { } ( ) @' + alpha),
|
453
|
+
'-' => rchar(%w'_ * ^ # @ ~'),
|
454
|
+
'_' => rchar(%w'- * ^ # @ ~'),
|
455
|
+
'(' => rchar(%w'\\ / ] [ { } ) @' + alpha),
|
456
|
+
')' => rchar(%w'\\ / ] [ { } ( @' + alpha),
|
457
|
+
}
|
458
|
+
|
459
|
+
(@noise * @captcha.size).ceil.times do |i|
|
460
|
+
cbyte = @captcha[i]
|
461
|
+
if cell =~ %r"nbsp;"
|
462
|
+
end
|
463
|
+
=end
|
464
|
+
@captcha
|
465
|
+
end #--}}}
|
466
|
+
|
467
|
+
def element! #--{{{
|
283
468
|
rows = []
|
284
469
|
rows << (row = [])
|
285
|
-
chars = @
|
470
|
+
chars = @captcha.split %r//
|
286
471
|
size = chars.size
|
287
472
|
last = size - 1
|
288
473
|
|
@@ -292,100 +477,64 @@ class Flatulent
|
|
292
477
|
when %r/\n/o
|
293
478
|
"<br>"
|
294
479
|
when %r/\s/o
|
295
|
-
#rand > 0.42 ? " " : " "
|
296
480
|
" "
|
297
481
|
when %r/([^\s])/o
|
298
482
|
CGI.escapeHTML $1
|
299
483
|
end
|
300
|
-
Array.new(rand(
|
484
|
+
Array.new(rand(10)){ content = "<span>#{ content }</span>"}
|
301
485
|
row << content
|
302
486
|
rows << (row = []) unless idx == last
|
303
487
|
end
|
304
488
|
|
305
|
-
|
489
|
+
|
490
|
+
=begin
|
491
|
+
noisy = %w`| / - _ ( ) \\`
|
492
|
+
alpha = ('A'..'Z').to_a + ('a'..'z').to_a
|
493
|
+
transform = {
|
494
|
+
'|' => rchar(%w'. * \` + , ; : '),
|
495
|
+
'/' => rchar(%w'\\ ] [ { } ( ) @' + alpha),
|
496
|
+
'\\' => rchar(%w'/ ] [ { } ( ) @' + alpha),
|
497
|
+
'-' => rchar(%w'_ * ^ # @ ~'),
|
498
|
+
'_' => rchar(%w'- * ^ # @ ~'),
|
499
|
+
'(' => rchar(%w'\\ / ] [ { } ) @' + alpha),
|
500
|
+
')' => rchar(%w'\\ / ] [ { } ( @' + alpha),
|
501
|
+
}
|
502
|
+
|
306
503
|
(@noise * chars.size).ceil.times do
|
307
504
|
y = rand(rows.size - 1)
|
308
505
|
x = rand(rows.first.size - 1)
|
309
|
-
|
310
|
-
|
311
|
-
|
506
|
+
cell = rows[y][x]
|
507
|
+
next if cell =~ %r"br"
|
508
|
+
char =
|
509
|
+
if cell =~ %r"nbsp;"
|
510
|
+
noisy[ rand(noisy.size) ]
|
511
|
+
else
|
512
|
+
#(transform[cell] || lambda{'.'}).call
|
513
|
+
nil
|
514
|
+
end
|
515
|
+
rows[y][x] = char if char
|
312
516
|
end
|
517
|
+
=end
|
313
518
|
|
314
519
|
content = rows.join
|
315
520
|
@element = "<pre id='#{ @id }_element' style='#{ css }'>#{ content }</pre>"
|
316
|
-
end
|
521
|
+
end #--}}}
|
317
522
|
|
318
|
-
|
523
|
+
def rchar *list #--{{{
|
524
|
+
list = list.flatten
|
525
|
+
n = list.size - 1
|
526
|
+
lambda{list[ rand(n) ]}
|
527
|
+
end #--}}}
|
319
528
|
|
320
|
-
def
|
321
|
-
cells = []
|
322
|
-
|
323
|
-
@figlets.each do |figlet|
|
324
|
-
rows = []
|
325
|
-
rows << (row = [])
|
326
|
-
|
327
|
-
offset_t = Array.new(rand(4)).map{ "\n"}
|
328
|
-
offset_b = Array.new(rand(4)).map{ "\n"}
|
329
|
-
|
330
|
-
offset_l = Array.new(rand(4)).map{ " "}
|
331
|
-
offset_r = Array.new(rand(4)).map{ " "}
|
332
|
-
|
333
|
-
chars = offset_t + figlet.split(%r//) + offset_b
|
334
|
-
size = chars.size
|
335
|
-
last = size - 1
|
336
|
-
#drawn = chars.select{|char| char !~ %r/\s/}
|
337
|
-
drawn = %w` | / \ < > v ^ - _ ( ) `
|
338
|
-
|
339
|
-
chars.each_with_index do |char, idx|
|
340
|
-
content =
|
341
|
-
case char
|
342
|
-
when %r/\n/o
|
343
|
-
"<br>"
|
344
|
-
when %r/\s/o
|
345
|
-
#rand > 0.42 ? " " : " "
|
346
|
-
" "
|
347
|
-
when %r/([^\s])/o
|
348
|
-
CGI.escapeHTML $1
|
349
|
-
end
|
350
|
-
#rand(10).times{ content = "<span>#{ content }</span>" }
|
351
|
-
row << content
|
352
|
-
rows << (row = []) unless idx == last
|
353
|
-
end
|
354
|
-
|
355
|
-
noisy = %w` | / \ - _ ( ) `
|
356
|
-
(@noise * chars.size).ceil.times do
|
357
|
-
y = rand(rows.size - 1)
|
358
|
-
x = rand(rows.first.size - 1)
|
359
|
-
next if rows[y][x] == "<br>"
|
360
|
-
char = noisy[ rand(noisy.size) ]
|
361
|
-
rows[y][x] = char
|
362
|
-
end
|
363
|
-
|
364
|
-
content = rows.join
|
365
|
-
cells << content
|
366
|
-
end
|
367
|
-
|
368
|
-
formatted = lambda{|x| "<pre class='#{ @id }_figlet' style='#{ css }'>#{ x }</pre>"}
|
369
|
-
|
370
|
-
@element =
|
371
|
-
"<table id='#{ @id }_element' border='0' cellpadding='0' cellspacing='0' bgcolor='#{ style["background"] }'><tr>" <<
|
372
|
-
cells.map{|cell| "<td>#{ formatted[cell] }</td>"}.join <<
|
373
|
-
"</tr></table>"
|
374
|
-
end
|
375
|
-
=end
|
376
|
-
|
377
|
-
def css
|
529
|
+
def css #--{{{
|
378
530
|
css_for style
|
379
|
-
end
|
380
|
-
def noise_css
|
381
|
-
css_for noise_style
|
382
|
-
end
|
531
|
+
end #--}}}
|
383
532
|
|
384
|
-
def css_for hash
|
533
|
+
def css_for hash #--{{{
|
385
534
|
hash.map{|kv| kv.join ':' }.join ';'
|
386
|
-
end
|
535
|
+
end #--}}}
|
387
536
|
|
388
|
-
def form_tags!
|
537
|
+
def form_tags! #--{{{
|
389
538
|
n = @string.scan(%r/\w/).size
|
390
539
|
string = @string
|
391
540
|
timebomb = Time.now.utc.to_i + @ttl
|
@@ -398,22 +547,22 @@ class Flatulent
|
|
398
547
|
<input type='hidden' name='#{ @id }[s]' id='#{ @id }_e' value='#{ encrypt string }' />
|
399
548
|
<input type='hidden' name='#{ @id }[t]' id='#{ @id }_v' value='#{ encrypt timebomb }' />
|
400
549
|
html
|
401
|
-
end
|
550
|
+
end #--}}}
|
402
551
|
alias_method 'to_html', 'form_tags'
|
403
552
|
|
404
|
-
def encrypt string
|
553
|
+
def encrypt string #--{{{
|
405
554
|
self.class.encrypt string.to_s
|
406
|
-
end
|
555
|
+
end #--}}}
|
407
556
|
|
408
|
-
def encrypted
|
557
|
+
def encrypted #--{{{
|
409
558
|
self.class.encrypt @string
|
410
|
-
end
|
559
|
+
end #--}}}
|
411
560
|
|
412
|
-
def munge string
|
561
|
+
def munge string #--{{{
|
413
562
|
self.class.munge string
|
414
|
-
end
|
563
|
+
end #--}}}
|
415
564
|
|
416
|
-
def form!
|
565
|
+
def form! #--{{{
|
417
566
|
action = "action='#{ @action }'"
|
418
567
|
@form = <<-html
|
419
568
|
<form method='post' #{ action }>
|
@@ -421,19 +570,19 @@ class Flatulent
|
|
421
570
|
<input type='submit' name='#{ @id }[submit]' id='#{ @id }_submit' value='Submit' />
|
422
571
|
</form>
|
423
572
|
html
|
424
|
-
end
|
573
|
+
end #--}}}
|
425
574
|
|
426
|
-
def to_html
|
575
|
+
def to_html #--{{{
|
427
576
|
element
|
428
|
-
end
|
577
|
+
end #--}}}
|
429
578
|
|
430
|
-
def to_s
|
579
|
+
def to_s #--{{{
|
431
580
|
form
|
432
|
-
end
|
581
|
+
end #--}}}
|
433
582
|
|
434
|
-
def getopts options
|
583
|
+
def getopts options #--{{{
|
435
584
|
self.class.getopts options
|
436
|
-
end
|
585
|
+
end #--}}}
|
437
586
|
end
|
438
587
|
|
439
588
|
def Flatulent(*a, &b) Flatulent.new(*a, &b) end
|
@@ -446,5 +595,10 @@ if $0 == __FILE__
|
|
446
595
|
#p e
|
447
596
|
#p Flatulent.decrypt(e)
|
448
597
|
|
449
|
-
|
598
|
+
f = Flatulent.new #('foobar')
|
599
|
+
puts f.figlet
|
600
|
+
puts('-' * 79)
|
601
|
+
puts f.vapour
|
602
|
+
puts('-' * 79)
|
603
|
+
puts f.captcha
|
450
604
|
end
|