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 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' unless defined? Flatulent::VERSION
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
- 'color' => '#00f',
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 = zeroh(decrypt(string))
82
- actual = zeroh(captcha)
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
- def zeroh string
93
- string.gsub(%r/[0Oo]/, '0') # ignore diffs between 0/o/O
94
- end
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.downcase
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
- def figlets options = {}
171
+ end #--}}}
172
+
173
+ def figlets options = {} #--{{{
169
174
  new(options).figlets
170
- end
171
- def element options = {}
175
+ end #--}}}
176
+
177
+ def element options = {} #--{{{
172
178
  new(options).element
173
- end
174
- def form_tags options = {}
179
+ end #--}}}
180
+
181
+ def form_tags options = {} #--{{{
175
182
  new(options).form_tags
176
- end
177
- def form options = {}
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
- def require_prototype
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
- def javascript options = {}
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
- def ajax options = {}
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.04 ]
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', 256 ]
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
- def generate_random_string
267
- chars = ('A' .. 'Z').to_a + ('1' .. '9').to_a ### zero is too much like o/O
268
- Array.new(@size).map{ chars[rand(chars.size - 1)]}.join
269
- end
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
- def figlet!
272
- spaced = @string.split(%r//).join #.join(' ')
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
- def element!
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 = @figlet.split %r//
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 ? "&nbsp;" : " "
296
480
  "&nbsp;"
297
481
  when %r/([^\s])/o
298
482
  CGI.escapeHTML $1
299
483
  end
300
- Array.new(rand(42)){ content = "<span>#{ content }</span>"}
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
- noisy = %W` | / - _ ( ) \ `
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
- next if rows[y][x] =~ %r"br"
310
- char = noisy[ rand(noisy.size) ]
311
- rows[y][x] = char
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
- =begin
523
+ def rchar *list #--{{{
524
+ list = list.flatten
525
+ n = list.size - 1
526
+ lambda{list[ rand(n) ]}
527
+ end #--}}}
319
528
 
320
- def element!
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` | / \ &lt; &gt; 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 ? "&nbsp;" : " "
346
- "&nbsp;"
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
- puts Flatulent.figlet('foobar')
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