flatulent 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|