Soks 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. data/README.txt +22 -20
  2. data/bin/soks-create-wiki.rb +11 -2
  3. data/contrib/{redcloth-3.0.1.rb → redcloth-3.0.3.rb} +161 -66
  4. data/lib/authenticators.rb +2 -2
  5. data/lib/helpers/mail2wiki-helper.rb +101 -0
  6. data/lib/helpers/rss2wiki-helper.rb +48 -0
  7. data/lib/soks-model.rb +7 -5
  8. data/lib/soks-servlet.rb +8 -19
  9. data/lib/soks-view.rb +70 -162
  10. data/lib/soks.rb +20 -2
  11. data/templates/default/attachment/favicon.ico +0 -0
  12. data/templates/default/attachment/logo_thumb.bmp +0 -0
  13. data/templates/default/attachment/robots.txt +5 -0
  14. data/templates/default/attachment/stylesheet.css +1 -0
  15. data/templates/default/content/Attached%20ruby%20logo.textile +1 -0
  16. data/templates/default/content/Attached%20test%20thing.textile +1 -0
  17. data/templates/default/content/Automatic%20Summaries.textile +1 -1
  18. data/templates/default/content/Bug%3A%20%5BFATAL%5D%20When%20renaming%20upload%20%2F%20picture%2.textile +1 -0
  19. data/templates/default/content/Bug%3A%20Duplicate%20links%2Dto%20a%20page%20sometimes%20appear.textile +1 -1
  20. data/templates/default/content/Bug%3A%20External%20links%20incorrectly%20include%20trailing%20pu.textile +1 -1
  21. data/templates/default/content/Bug%3A%20No%20robots%2Etxt%20or%20favicon%2Eico.textile +1 -1
  22. data/templates/default/content/Bug%3A%20Page%20titles%20cannot%20have%20html%20tags%20in%20them.textile +1 -1
  23. data/templates/default/content/Bug%3A%20Punctuation%20in%20page%20titles%20still%20problematic.textile +7 -0
  24. data/templates/default/content/Bug%3A%20Search%20includes%20leading%20and%20trailing%20spaces.textile +1 -0
  25. data/templates/default/content/Bug%3A%20Search%20inluced%20leading%20and%20trailing%20spaces.textile +1 -0
  26. data/templates/default/content/Bug%3A%20no%20superclass%20method%20%60%5Fdeprecated%5Fbase64.textile +1 -0
  27. data/templates/default/content/Bug%3A%20notextile%20does%20not%20prevent%20page%20inserts.textile +1 -0
  28. data/templates/default/content/Fixed%20Bug%3A%20%5BFATAL%5D%20When%20renaming%20upload%20%2F%20p.textile +34 -0
  29. data/templates/default/content/Fixed%20Bug%3A%20Duplicate%20links%2Dto%20a%20page%20sometimes%20.textile +3 -0
  30. data/templates/default/content/Fixed%20Bug%3A%20External%20links%20incorrectly%20include%20trail.textile +3 -0
  31. data/templates/default/content/Fixed%20Bug%3A%20No%20robots%2Etxt%20or%20favicon%2Eico.textile +4 -0
  32. data/templates/default/content/Fixed%20Bug%3A%20Search%20includes%20leading%20and%20trailing%20s.textile +3 -0
  33. data/templates/default/content/Fixed%20Bug%3A%20no%20superclass%20method%20%60%5Fdeprecated%5Fba.textile +3 -0
  34. data/templates/default/content/Home%20Page.textile +2 -2
  35. data/templates/default/content/How%20to%20administrate%20this%20wiki.textile +1 -1
  36. data/templates/default/content/How%20to%20report%20a%20bug.textile +8 -0
  37. data/templates/default/content/Instructions%20and%20Howtos.textile +1 -0
  38. data/templates/default/content/Known%20bugs.textile +4 -5
  39. data/templates/default/content/List%20of%20changes.textile +32 -0
  40. data/templates/default/content/Picture%20of%20a%20logo%20for%20the%20ruby%20language.textile +1 -0
  41. data/templates/default/content/Picture%20of%20powered%20by%20ruby%20logo.textile +1 -0
  42. data/templates/default/content/Planned%20Features.textile +19 -0
  43. data/templates/default/content/README.textile +22 -20
  44. data/templates/default/content/Recent%20Changes%20to%20This%20Site.textile +123 -8
  45. data/templates/default/content/SOKS%20features.textile +5 -1
  46. data/templates/default/content/Site%20Index.textile +11 -6
  47. data/templates/default/start.rb +17 -6
  48. data/templates/default/version.txt +1 -1
  49. data/templates/default/views/Page_edit.rhtml +7 -6
  50. data/templates/default/views/Page_meta.rhtml +5 -5
  51. data/templates/default/views/Page_revisions.rhtml +4 -3
  52. data/templates/default/views/Page_search_results.rhtml +3 -3
  53. data/templates/default/views/Page_view.rhtml +2 -2
  54. data/templates/default/views/UploadPage_edit.rhtml +6 -6
  55. data/templates/default/views/frame.rhtml +15 -14
  56. data/templates/instiki/content/Attached%20ruby%20logo.textile +1 -0
  57. data/templates/instiki/content/Attached%20test%20thing.textile +1 -0
  58. data/templates/instiki/content/Automatic%20Summaries.textile +1 -1
  59. data/templates/instiki/content/Bug%3A%20%5BFATAL%5D%20When%20renaming%20upload%20%2F%20picture%2.textile +1 -0
  60. data/templates/instiki/content/Bug%3A%20Duplicate%20links%2Dto%20a%20page%20sometimes%20appear.textile +1 -1
  61. data/templates/instiki/content/Bug%3A%20External%20links%20incorrectly%20include%20trailing%20pu.textile +1 -1
  62. data/templates/instiki/content/Bug%3A%20No%20robots%2Etxt%20or%20favicon%2Eico.textile +1 -1
  63. data/templates/instiki/content/Bug%3A%20Page%20titles%20cannot%20have%20html%20tags%20in%20them.textile +1 -1
  64. data/templates/instiki/content/Bug%3A%20Punctuation%20in%20page%20titles%20still%20problematic.textile +7 -0
  65. data/templates/instiki/content/Bug%3A%20Search%20includes%20leading%20and%20trailing%20spaces.textile +1 -0
  66. data/templates/instiki/content/Bug%3A%20Search%20inluced%20leading%20and%20trailing%20spaces.textile +1 -0
  67. data/templates/instiki/content/Bug%3A%20no%20superclass%20method%20%60%5Fdeprecated%5Fbase64.textile +1 -0
  68. data/templates/instiki/content/Bug%3A%20notextile%20does%20not%20prevent%20page%20inserts.textile +1 -0
  69. data/templates/instiki/content/Fixed%20Bug%3A%20%5BFATAL%5D%20When%20renaming%20upload%20%2F%20p.textile +34 -0
  70. data/templates/instiki/content/Fixed%20Bug%3A%20Duplicate%20links%2Dto%20a%20page%20sometimes%20.textile +3 -0
  71. data/templates/instiki/content/Fixed%20Bug%3A%20External%20links%20incorrectly%20include%20trail.textile +3 -0
  72. data/templates/instiki/content/Fixed%20Bug%3A%20No%20robots%2Etxt%20or%20favicon%2Eico.textile +4 -0
  73. data/templates/instiki/content/Fixed%20Bug%3A%20Search%20includes%20leading%20and%20trailing%20s.textile +3 -0
  74. data/templates/instiki/content/Fixed%20Bug%3A%20no%20superclass%20method%20%60%5Fdeprecated%5Fba.textile +3 -0
  75. data/templates/instiki/content/Home%20Page.textile +2 -2
  76. data/templates/instiki/content/How%20to%20administrate%20this%20wiki.textile +1 -1
  77. data/templates/instiki/content/How%20to%20report%20a%20bug.textile +8 -0
  78. data/templates/instiki/content/Instructions%20and%20Howtos.textile +1 -0
  79. data/templates/instiki/content/Known%20bugs.textile +4 -5
  80. data/templates/instiki/content/List%20of%20changes.textile +32 -0
  81. data/templates/instiki/content/Picture%20of%20a%20logo%20for%20the%20ruby%20language.textile +1 -0
  82. data/templates/instiki/content/Picture%20of%20powered%20by%20ruby%20logo.textile +1 -0
  83. data/templates/instiki/content/Planned%20Features.textile +19 -0
  84. data/templates/instiki/content/README.textile +22 -20
  85. data/templates/instiki/content/Recent%20Changes%20to%20This%20Site.textile +123 -8
  86. data/templates/instiki/content/SOKS%20features.textile +5 -1
  87. data/templates/instiki/content/Site%20Index.textile +11 -6
  88. data/templates/instiki/version.txt +1 -1
  89. data/templates/rails/content/Attached%20ruby%20logo.textile +1 -0
  90. data/templates/rails/content/Attached%20test%20thing.textile +1 -0
  91. data/templates/rails/content/Automatic%20Summaries.textile +1 -1
  92. data/templates/rails/content/Bug%3A%20%5BFATAL%5D%20When%20renaming%20upload%20%2F%20picture%2.textile +1 -0
  93. data/templates/rails/content/Bug%3A%20Duplicate%20links%2Dto%20a%20page%20sometimes%20appear.textile +1 -1
  94. data/templates/rails/content/Bug%3A%20External%20links%20incorrectly%20include%20trailing%20pu.textile +1 -1
  95. data/templates/rails/content/Bug%3A%20No%20robots%2Etxt%20or%20favicon%2Eico.textile +1 -1
  96. data/templates/rails/content/Bug%3A%20Page%20titles%20cannot%20have%20html%20tags%20in%20them.textile +1 -1
  97. data/templates/rails/content/Bug%3A%20Punctuation%20in%20page%20titles%20still%20problematic.textile +7 -0
  98. data/templates/rails/content/Bug%3A%20Search%20includes%20leading%20and%20trailing%20spaces.textile +1 -0
  99. data/templates/rails/content/Bug%3A%20Search%20inluced%20leading%20and%20trailing%20spaces.textile +1 -0
  100. data/templates/rails/content/Bug%3A%20no%20superclass%20method%20%60%5Fdeprecated%5Fbase64.textile +1 -0
  101. data/templates/rails/content/Bug%3A%20notextile%20does%20not%20prevent%20page%20inserts.textile +1 -0
  102. data/templates/rails/content/Fixed%20Bug%3A%20%5BFATAL%5D%20When%20renaming%20upload%20%2F%20p.textile +34 -0
  103. data/templates/rails/content/Fixed%20Bug%3A%20Duplicate%20links%2Dto%20a%20page%20sometimes%20.textile +3 -0
  104. data/templates/rails/content/Fixed%20Bug%3A%20External%20links%20incorrectly%20include%20trail.textile +3 -0
  105. data/templates/rails/content/Fixed%20Bug%3A%20No%20robots%2Etxt%20or%20favicon%2Eico.textile +4 -0
  106. data/templates/rails/content/Fixed%20Bug%3A%20Search%20includes%20leading%20and%20trailing%20s.textile +3 -0
  107. data/templates/rails/content/Fixed%20Bug%3A%20no%20superclass%20method%20%60%5Fdeprecated%5Fba.textile +3 -0
  108. data/templates/rails/content/Home%20Page.textile +2 -2
  109. data/templates/rails/content/How%20to%20administrate%20this%20wiki.textile +1 -1
  110. data/templates/rails/content/How%20to%20report%20a%20bug.textile +8 -0
  111. data/templates/rails/content/Instructions%20and%20Howtos.textile +1 -0
  112. data/templates/rails/content/Known%20bugs.textile +4 -5
  113. data/templates/rails/content/List%20of%20changes.textile +32 -0
  114. data/templates/rails/content/Picture%20of%20a%20logo%20for%20the%20ruby%20language.textile +1 -0
  115. data/templates/rails/content/Picture%20of%20powered%20by%20ruby%20logo.textile +1 -0
  116. data/templates/rails/content/Planned%20Features.textile +19 -0
  117. data/templates/rails/content/README.textile +22 -20
  118. data/templates/rails/content/Recent%20Changes%20to%20This%20Site.textile +123 -8
  119. data/templates/rails/content/SOKS%20features.textile +5 -1
  120. data/templates/rails/content/Site%20Index.textile +11 -6
  121. data/templates/rails/version.txt +1 -1
  122. metadata +64 -5
  123. data/contrib/redcloth-2.0.11.rb +0 -896
  124. /data/lib/{soks-helpers.rb → helpers/default-helpers.rb} +0 -0
data/README.txt CHANGED
@@ -4,9 +4,9 @@ h1. SOKS: Another Ruby Wiki
4
4
  * The project has been kindly hosted at http://rubyforge.org/projects/soks/
5
5
 
6
6
  Quickstart:
7
- 1. gem install Soks
8
- 2. soks-create-wiki.rb
9
- 3. http://localhost:8000
7
+ # gem install Soks
8
+ # soks-create-wiki.rb
9
+ # http://localhost:8000
10
10
 
11
11
  h2. REQUIRES
12
12
 
@@ -21,13 +21,13 @@ h2. AUTHOR
21
21
  h2. INSTALL
22
22
 
23
23
  Preferably:
24
- 1. Install rubygems from http://rubyforge.org/projects/rubygems/
25
- 2. gem install Soks (you may need to be root first)
24
+ # Install rubygems from http://rubyforge.org/projects/rubygems/
25
+ # gem install Soks (you may need to be root first)
26
26
 
27
27
  Alternatively
28
- 1. Download the tar or zip file from http://rubyforge.org/projects/soks/
29
- 2. Unzip or untar it
30
- 3. Change into the soks directory
28
+ # Download the tar or zip file from http://rubyforge.org/projects/soks/
29
+ # Unzip or untar it
30
+ # Change into the soks directory
31
31
 
32
32
  h2. USE
33
33
 
@@ -40,22 +40,24 @@ To change the settings (url, port, etc) edit the start.rb file in the soks-wiki
40
40
 
41
41
  h2. FEATURES
42
42
 
43
- 1. Runs on its own webrick server (no independent web server required)
44
- 2. Uses textile as its text coding (a proto-standard)
45
- 3, Uses a combination of flat and yaml files for storage (no database, and page content human readable outside of soks)
46
- 3. Allows uploads
47
- 4. Allows authentication
48
- 5. Automatically links pages within the wiki
49
- 6. Pages can be deleted and moved easily (and these can be undone)
50
- 7. Has a mechanism for external classes to manipulate the wiki to provide, for instance, automatic calendar pages, or automatic summaries or blog like pages.
43
+ # Runs on its own webrick server (no independent web server required)
44
+ # Uses textile as its text coding (a proto-standard)
45
+ # Uses a combination of flat and yaml files for storage (no database, and page content human readable outside of soks)
46
+ # Allows uploads
47
+ # Allows authentication
48
+ # Automatically links pages within the wiki
49
+ # Pages can be deleted and moved easily (and these can be undone)
50
+ # Has a mechanism for external classes to manipulate the wiki to provide, for instance, automatic calendar pages, or automatic summaries or blog like pages.
51
51
 
52
52
  h2. BUGS
53
53
 
54
54
  I suspect there are many, as befits its version number. In particular it has:
55
- * Not got any way of securing pictures or attachments added to the wiki
56
- * Uses RedCloth 2.0.11 which has some formatting bugs (and no doubt some extra ones introduced by my clumsy extentions). RedCloth 3.0.1 is included but not enabled because it tends to hit stack overflows frequently for me.
55
+ * No authentication on pictures and attachments
56
+ * Punctuation in page titles problematic. ? <> and [] cause problems. : and / are ok.
57
+ * Insert page commands are not inhibited by notextile, pre or code tags
57
58
 
58
59
  h2. RELEASES
59
60
 
60
- 2005 Jan 24 - soks-0.0.3 - Second public release (alpha)
61
- 2005 Jan 11 - soks-0.0.2 - First public release (alpha)
61
+ # 2005 Feb 12 - soks-0.0.5 - Third public release (alpha)
62
+ # 2005 Jan 24 - soks-0.0.4 - Second public release (alpha)
63
+ # 2005 Jan 11 - soks-0.0.2 - First public release (alpha)
@@ -38,11 +38,20 @@ def backup_directory( directory )
38
38
  backup_dir
39
39
  end
40
40
 
41
+ # Used to remove the content of a directory (FileUtils.rm_r seems to fail for me?)
42
+ def remove_directory( directory )
43
+ Dir.entries(directory).each do |file|
44
+ next if File.directory?( file )
45
+ File.delete( File.join( directory, file ) )
46
+ end
47
+ Dir.rmdir( directory )
48
+ end
49
+
41
50
  #Find where we are
42
51
  $SOKS_APPLICATION_DIRECTORY, this_script = File.split(File.expand_path(File.dirname(__FILE__)))
43
52
 
44
53
  #Make sure we can find our libraries
45
- soks_library = [ File.join( $SOKS_APPLICATION_DIRECTORY,'lib') , File.join( $SOKS_APPLICATION_DIRECTORY,'/contrib' ) ]
54
+ soks_library = [ File.join( $SOKS_APPLICATION_DIRECTORY,'lib') , File.join( $SOKS_APPLICATION_DIRECTORY,'lib','helpers'), File.join( $SOKS_APPLICATION_DIRECTORY,'/contrib' ) ]
46
55
  $:.push( *soks_library )
47
56
 
48
57
  require 'easyprompt'
@@ -114,7 +123,7 @@ if upgrade
114
123
  puts "Copied #{source} to #{destination}"
115
124
 
116
125
  if keep_content
117
- FileUtils.rm_rf( File.join( destination, 'content' ) )
126
+ remove_directory( File.join( destination, 'content' ) )
118
127
  FileUtils.cp_r( File.join( old_wiki, 'content'), destination )
119
128
  puts "Copied content from #{old_wiki} to #{destination}"
120
129
  if wiki_version == '0.0.2'
@@ -1,3 +1,4 @@
1
+ # NOTE THERE ARE SLIGHT TWEAKS TO THIS VERSION MADE BY TAMC
1
2
  # vim:ts=4:sw=4:
2
3
  # = RedCloth - Textile and Markdown Hybrid for Ruby
3
4
  #
@@ -166,7 +167,8 @@
166
167
 
167
168
  class RedCloth < String
168
169
 
169
- VERSION = '3.0.1'
170
+ VERSION = '3.0.3'
171
+ DEFAULT_RULES = [:textile, :markdown]
170
172
 
171
173
  #
172
174
  # Two accessor for setting security restrictions.
@@ -192,6 +194,16 @@ class RedCloth < String
192
194
  #
193
195
  attr_accessor :hard_breaks
194
196
 
197
+ #
198
+ # Accessor for toggling span caps.
199
+ #
200
+ # Textile places `span' tags around capitalized
201
+ # words by default, but this wreaks havoc on Wikis.
202
+ # If +:no_span_caps+ is set, this will be
203
+ # suppressed.
204
+ #
205
+ attr_accessor :no_span_caps
206
+
195
207
  #
196
208
  # Establishes the markup predence. Available rules include:
197
209
  #
@@ -230,7 +242,6 @@ class RedCloth < String
230
242
  #
231
243
  def initialize( string, restrictions = [] )
232
244
  restrictions.each { |r| method( "#{ r }=" ).call( true ) }
233
- @rules = [:textile, :markdown]
234
245
  super( string )
235
246
  end
236
247
 
@@ -242,7 +253,7 @@ class RedCloth < String
242
253
  # #=>"And then? She <strong>fell</strong>!"
243
254
  #
244
255
  def to_html( *rules )
245
- rules = @rules if rules.empty?
256
+ rules = DEFAULT_RULES if rules.empty?
246
257
  # make our working copy
247
258
  text = self.dup
248
259
 
@@ -268,18 +279,22 @@ class RedCloth < String
268
279
  # standard clean up
269
280
  incoming_entities text
270
281
  clean_white_space text
282
+ no_textile text
271
283
 
272
284
  # start processor
273
- pre_list = rip_offtags text
285
+ @pre_list = []
286
+ rip_offtags text
287
+ hard_break text
274
288
  refs text
275
289
  blocks text
276
290
  inline text
277
- smooth_offtags text, pre_list
291
+ smooth_offtags text
278
292
 
279
293
  retrieve text
280
294
 
281
295
  text.gsub!( /<\/?notextile>/, '' )
282
296
  text.gsub!( /x%x%/, '&#38;' )
297
+ clean_html text if filter_html
283
298
  text.strip!
284
299
  text
285
300
 
@@ -340,7 +355,7 @@ class RedCloth < String
340
355
  [ /"/, '&#8220;' ], # double opening
341
356
  [ /\b( )?\.{3}/, '\1&#8230;' ], # ellipsis
342
357
  [ /\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])/, '<acronym title="\2">\1</acronym>' ], # 3+ uppercase acronym
343
- [ /(^|[^"][>\s])([A-Z][A-Z0-9 ]{2,})([^<a-z0-9]|$)/, '\1<span class="caps">\2</span>\3' ], # 3+ uppercase caps
358
+ [ /(^|[^"][>\s])([A-Z][A-Z0-9 ]{2,})([^<a-z0-9]|$)/, '\1<span class="caps">\2</span>\3', :no_span_caps ], # 3+ uppercase caps
344
359
  [ /(\.\s)?\s?--\s?/, '\1&#8212;' ], # em dash
345
360
  [ /\s->\s/, ' &rarr; ' ], # right arrow
346
361
  [ /\s-\s/, ' &#8211; ' ], # en dash
@@ -366,20 +381,36 @@ class RedCloth < String
366
381
  QTAGS = [
367
382
  ['**', 'b'],
368
383
  ['*', 'strong'],
369
- ['??', 'cite'],
370
- ['-', 'del'],
384
+ ['??', 'cite', :limit],
385
+ ['-', 'del', :limit],
371
386
  ['__', 'i'],
372
- ['_', 'em'],
373
- ['%', 'span'],
374
- ['+', 'ins'],
387
+ ['_', 'em', :limit],
388
+ ['%', 'span', :limit],
389
+ ['+', 'ins', :limit],
375
390
  ['^', 'sup'],
376
391
  ['~', 'sub']
377
392
  ]
378
- QTAGS_RE = /(#{ QTAGS.collect { |rc, ht| Regexp::quote( rc ) }.join( '|' ) })
379
- (#{C})
380
- (?::(\S+?))?
381
- ([^\s\1]+?(?:[^\n]|\n(?!\n))*?)
382
- \1/xm
393
+ QTAGS.collect! do |rc, ht, rtype|
394
+ rcq = Regexp::quote rc
395
+ re =
396
+ case rtype
397
+ when :limit
398
+ /(\W)
399
+ (#{rcq})
400
+ (#{C})
401
+ (?::(\S+?))?
402
+ (.+?)
403
+ #{rcq}
404
+ (?=\W)/x
405
+ else
406
+ /(#{rcq})
407
+ (#{C})
408
+ (?::(\S+?))?
409
+ (.+?)
410
+ #{rcq}/xm
411
+ end
412
+ [rc, ht, re, rtype]
413
+ end
383
414
 
384
415
  #
385
416
  # Flexible HTML escaping
@@ -394,7 +425,8 @@ class RedCloth < String
394
425
 
395
426
  # Search and replace for Textile glyphs (quotes, dashes, other symbols)
396
427
  def pgl( text )
397
- GLYPHS.each do |re, resub|
428
+ GLYPHS.each do |re, resub, tog|
429
+ next if tog and method( tog ).call
398
430
  text.gsub! re, resub
399
431
  end
400
432
  end
@@ -412,7 +444,7 @@ class RedCloth < String
412
444
  style << "vertical-align:#{ v_align( $& ) };" if text =~ A_VLGN
413
445
  end
414
446
 
415
- style << "#{ $1 };" if not @filter_styles and
447
+ style << "#{ $1 };" if not filter_styles and
416
448
  text.sub!( /\{([^}]*)\}/, '' )
417
449
 
418
450
  lang = $1 if
@@ -526,20 +558,18 @@ class RedCloth < String
526
558
  end
527
559
  end
528
560
 
529
- CODE_RE = /
530
- (^|[\s>#{PUNCT}{(\[]) # 1 open bracket?
531
- @ # opening
532
- (?:\|(\w+?)\|)? # 2 language
533
- (\S(?:[^\n]|\n(?!\n))*?) # 3 code
534
- @ # closing
535
- (?=[\s\]}\)<#{PUNCT}]|$) # 4 closing bracket?
536
- /x
561
+ CODE_RE = /(\W)
562
+ @
563
+ (?:\|(\w+?)\|)?
564
+ (.+?)
565
+ @
566
+ (?=\W)/x
537
567
 
538
568
  def inline_textile_code( text )
539
569
  text.gsub!( CODE_RE ) do |m|
540
570
  before,lang,code,after = $~[1..4]
541
571
  lang = " lang=\"#{ lang }\"" if lang
542
- "#{ before }<code#{ lang }>#{ code }</code>#{ after }"
572
+ rip_offtags( "#{ before }<code#{ lang }>#{ code }</code>#{ after }" )
543
573
  end
544
574
  end
545
575
 
@@ -548,14 +578,14 @@ class RedCloth < String
548
578
  end
549
579
 
550
580
  def hard_break( text )
551
- text.gsub!( /(.)\n(?! *[#*\s|])/, "\\1<br />" ) if @hard_breaks
581
+ text.gsub!( /(.)\n(?! *[#*\s|]|$)/, "\\1<br />" ) if hard_breaks
552
582
  end
553
583
 
554
- BLOCKS_GROUP_RE = /((?:\n*([#*> ])(?:[^\n]|\n+\2|\n(?!\n|\Z))+))|((?:[^\n]+|\n+ +|\n(?![#*\n]|\Z))+)/m
584
+ BLOCKS_GROUP_RE = /\n{2,}(?! )/m
555
585
 
556
586
  def blocks( text, deep_code = false )
557
- text.gsub!( BLOCKS_GROUP_RE ) do |blk|
558
- plain = $3 ? true : false
587
+ text.replace( text.split( BLOCKS_GROUP_RE ).collect do |blk|
588
+ plain = blk !~ /\A[#*> ]/
559
589
 
560
590
  # skip blocks that are complex HTML
561
591
  if blk =~ /^<\/?(\w+).*>/ and not SIMPLE_HTML_TAGS.include? $1
@@ -578,11 +608,11 @@ class RedCloth < String
578
608
  end
579
609
  end
580
610
 
581
- block_applied = nil
611
+ block_applied = 0
582
612
  @rules.each do |rule_name|
583
- break if block_applied = ( rule_name.to_s.match /^block_/ and method( rule_name ).call( blk ) )
613
+ block_applied += 1 if ( rule_name.to_s.match /^block_/ and method( rule_name ).call( blk ) )
584
614
  end
585
- unless block_applied
615
+ if block_applied.zero?
586
616
  if deep_code
587
617
  blk = "\t<pre><code>#{ blk }</code></pre>"
588
618
  else
@@ -594,7 +624,7 @@ class RedCloth < String
594
624
  end
595
625
  end
596
626
 
597
- end
627
+ end.join( "\n\n" ) )
598
628
  end
599
629
 
600
630
  def textile_bq( tag, atts, cite, content )
@@ -694,16 +724,23 @@ class RedCloth < String
694
724
  end
695
725
 
696
726
  def inline_textile_span( text )
697
- text.gsub!( QTAGS_RE ) do |m|
698
-
699
- qtag,atts,cite,content = $~[1..4]
700
- ht = QTAGS.assoc( qtag ).last
701
- atts = pba( atts )
702
- atts << " cite=\"#{ cite }\"" if cite
703
- atts = shelve( atts ) if atts
727
+ QTAGS.each do |qtag_rc, ht, qtag_re, rtype|
728
+ text.gsub!( qtag_re ) do |m|
729
+
730
+ case rtype
731
+ when :limit
732
+ sta,qtag,atts,cite,content = $~[1..5]
733
+ else
734
+ qtag,atts,cite,content = $~[1..4]
735
+ sta = ''
736
+ end
737
+ atts = pba( atts )
738
+ atts << " cite=\"#{ cite }\"" if cite
739
+ atts = shelve( atts ) if atts
704
740
 
705
- "<#{ ht }#{ atts }>#{ content }</#{ ht }>"
741
+ "#{ sta }<#{ ht }#{ atts }>#{ content }</#{ ht }>"
706
742
 
743
+ end
707
744
  end
708
745
  end
709
746
 
@@ -865,14 +902,14 @@ class RedCloth < String
865
902
  end
866
903
  end
867
904
 
868
- def shelve( val )
869
- @shelf << val
870
- " <#{ @shelf.length }>"
905
+ def shelve( val )
906
+ @shelf << val
907
+ "<#{ @shelf.length }>"
871
908
  end
872
909
 
873
910
  def retrieve( text )
874
911
  @shelf.each_with_index do |r, i|
875
- text.gsub!( " <#{ i + 1 }>", r )
912
+ text.gsub!( "<#{ i + 1 }>", r )
876
913
  end
877
914
  end
878
915
 
@@ -885,9 +922,9 @@ class RedCloth < String
885
922
  end
886
923
 
887
924
  def no_textile( text )
888
- text.gsub!( /(^|\s)==(.*?)==(\s|$)?/,
925
+ text.gsub!( /(^|\s)==([^=]+.*?)==(\s|$)?/,
889
926
  '\1<notextile>\2</notextile>\3' )
890
- text.gsub!( /^ *==(.*?)==/m,
927
+ text.gsub!( /^ *==([^=]+.*?)==/m,
891
928
  '\1<notextile>\2</notextile>\3' )
892
929
  end
893
930
 
@@ -907,11 +944,13 @@ class RedCloth < String
907
944
 
908
945
  def flush_left( text )
909
946
  indt = 0
910
- while text !~ /^ {#{indt}}\S/
911
- indt += 1
912
- end
913
- if indt.nonzero?
914
- text.gsub!( /^ {#{indt}}/, '' )
947
+ if text =~ /^ /
948
+ while text !~ /^ {#{indt}}\S/
949
+ indt += 1
950
+ end unless text.empty?
951
+ if indt.nonzero?
952
+ text.gsub!( /^ {#{indt}}/, '' )
953
+ end
915
954
  end
916
955
  end
917
956
 
@@ -936,9 +975,7 @@ class RedCloth < String
936
975
  text.gsub!( ALLTAG_MATCH ) do |line|
937
976
  ## matches are off if we're between <code>, <pre> etc.
938
977
  if $1
939
- if @filter_html
940
- htmlesc( line, :NoQuotes )
941
- elsif line =~ OFFTAG_OPEN
978
+ if line =~ OFFTAG_OPEN
942
979
  codepre += 1
943
980
  elsif line =~ OFFTAG_CLOSE
944
981
  codepre -= 1
@@ -957,7 +994,6 @@ class RedCloth < String
957
994
  end
958
995
 
959
996
  def rip_offtags( text )
960
- pre_list = []
961
997
  if text =~ /<.*>/
962
998
  ## strip and encode <pre> content
963
999
  codepre, used_offtags = 0, {}
@@ -968,17 +1004,17 @@ class RedCloth < String
968
1004
  used_offtags[offtag] = true
969
1005
  if codepre - used_offtags.length > 0
970
1006
  htmlesc( line, :NoQuotes ) unless used_offtags['notextile']
971
- pre_list.last << line
1007
+ @pre_list.last << line
972
1008
  line = ""
973
1009
  else
974
1010
  htmlesc( aftertag, :NoQuotes ) if aftertag and not used_offtags['notextile']
975
- line = "<redpre##{ pre_list.length }>"
976
- pre_list << "#{ $3 }#{ aftertag }"
1011
+ line = "<redpre##{ @pre_list.length }>"
1012
+ @pre_list << "#{ $3 }#{ aftertag }"
977
1013
  end
978
1014
  elsif $1 and codepre > 0
979
1015
  if codepre - used_offtags.length > 0
980
1016
  htmlesc( line, :NoQuotes ) unless used_offtags['notextile']
981
- pre_list.last << line
1017
+ @pre_list.last << line
982
1018
  line = ""
983
1019
  end
984
1020
  codepre -= 1 unless codepre.zero?
@@ -987,13 +1023,13 @@ class RedCloth < String
987
1023
  line
988
1024
  end
989
1025
  end
990
- pre_list
1026
+ text
991
1027
  end
992
1028
 
993
- def smooth_offtags( text, pre_list )
994
- unless pre_list.empty?
1029
+ def smooth_offtags( text )
1030
+ unless @pre_list.empty?
995
1031
  ## replace <pre> content
996
- text.gsub!( /<redpre#(\d+)>/ ) { pre_list[$1.to_i] }
1032
+ text.gsub!( /<redpre#(\d+)>/ ) { @pre_list[$1.to_i] }
997
1033
  end
998
1034
  end
999
1035
 
@@ -1015,5 +1051,64 @@ class RedCloth < String
1015
1051
  ' <a target="_blank" href="http://hobix.com/textile/#' + helpvar + '" onclick="window.open(this.href, \'popupwindow\', \'width=' + windowW + ',height=' + windowH + ',scrollbars,resizable\'); return false;">' + name + '</a><br />'
1016
1052
  end
1017
1053
 
1054
+ # HTML cleansing stuff
1055
+ BASIC_TAGS = {
1056
+ 'a' => ['href', 'title'],
1057
+ 'img' => ['src', 'alt', 'title'],
1058
+ 'br' => [],
1059
+ 'i' => nil,
1060
+ 'u' => nil,
1061
+ 'b' => nil,
1062
+ 'pre' => nil,
1063
+ 'kbd' => nil,
1064
+ 'code' => ['lang'],
1065
+ 'cite' => nil,
1066
+ 'strong' => nil,
1067
+ 'em' => nil,
1068
+ 'ins' => nil,
1069
+ 'sup' => nil,
1070
+ 'sub' => nil,
1071
+ 'del' => nil,
1072
+ 'table' => nil,
1073
+ 'tr' => nil,
1074
+ 'td' => ['colspan', 'rowspan'],
1075
+ 'th' => nil,
1076
+ 'ol' => nil,
1077
+ 'ul' => nil,
1078
+ 'li' => nil,
1079
+ 'p' => nil,
1080
+ 'h1' => nil,
1081
+ 'h2' => nil,
1082
+ 'h3' => nil,
1083
+ 'h4' => nil,
1084
+ 'h5' => nil,
1085
+ 'h6' => nil,
1086
+ 'blockquote' => ['cite']
1087
+ }
1088
+
1089
+ def clean_html( text, tags = BASIC_TAGS )
1090
+ text.gsub!( /<!\[CDATA\[/, '' )
1091
+ text.gsub!( /<(\/?)(\w+)(.*?)(\/?)>/ ) do
1092
+ raw = $~
1093
+ tag = raw[2].downcase
1094
+ if tags.has_key? tag
1095
+ pcs = [tag]
1096
+ tags[tag].each do |prop|
1097
+ ['"', "'", ''].each do |q|
1098
+ q2 = ( q != '' ? q : '\s' )
1099
+ if raw[3] =~ /#{prop}\s*=\s*#{q}([^#{q2}]+)#{q}/i
1100
+ attrv = $1
1101
+ next if prop == 'src' and attrv !~ /^http/
1102
+ pcs << "#{prop}=\"#{attrv.gsub('"', '\\"')}\""
1103
+ break
1104
+ end
1105
+ end
1106
+ end if tags[tag]
1107
+ "<#{raw[1]}#{pcs.join " "}#{raw[4]}>"
1108
+ else
1109
+ " "
1110
+ end
1111
+ end
1112
+ end
1018
1113
  end
1019
1114
 
@@ -37,7 +37,7 @@ module WEBrick
37
37
  unless basic_credentials = check_scheme(req)
38
38
  challenge(req, res)
39
39
  end
40
- userid, password = decode64(basic_credentials).split(":", 2)
40
+ userid, password = Base64.decode64(basic_credentials).split(":", 2)
41
41
  if userid.empty?
42
42
  error("user id was not given.")
43
43
  challenge(req, res)
@@ -70,7 +70,7 @@ module WEBrick
70
70
  unless basic_credentials = check_scheme(req)
71
71
  challenge(req, res)
72
72
  end
73
- userid, password = decode64(basic_credentials).split(":", 2)
73
+ userid, password = Base64.decode64(basic_credentials).split(":", 2)
74
74
  password ||= ""
75
75
  if userid.empty?
76
76
  error("user id was not given.")
@@ -0,0 +1,101 @@
1
+ require 'net/imap'
2
+
3
+ class Message
4
+
5
+ attr_reader :message_id, :subject, :sender_name, :sender_email, :date, :text
6
+
7
+ def initialize( imap, message_id )
8
+ @imap, @message_id = imap, message_id
9
+ envelope = @imap.fetch( @message_id, 'ENVELOPE' ).first.attr['ENVELOPE']
10
+ @subject = envelope['subject']
11
+ @sender_name = envelope['from'].first['name']
12
+ @sender_email = envelope['from'].first['mailbox'] + '@' + envelope['from'].first['host']
13
+ @text = plain_text_content_from_message( message_id )
14
+ end
15
+
16
+ def plain_text_content_from_message( id )
17
+ text = @imap.fetch( id, 'BODY[1]' ).first.attr['BODY[1]']
18
+ text.gsub!(/\r\n/,"\n")
19
+ text.gsub!(/\r/,"\n")
20
+ text.gsub!(/=\n/,'')
21
+ text.gsub!(/((?:=[0-9a-fA-F]{2})+)/n) { [$1.delete('=')].pack('H*') }
22
+ text
23
+ end
24
+
25
+ end
26
+
27
+ class Mail2WikiHelper
28
+
29
+ DEFAULT_SETTINGS = {
30
+ :server => 'imap.hermes.cam.ac.uk',
31
+ :username => 'tamc2',
32
+ :password => '',
33
+ :mailbox => 'mcr notices',
34
+ :check_frequency => 600, # Seconds
35
+ :subject_regexp => /.*/,
36
+ }
37
+
38
+ def initialize( wiki, settings = {} )
39
+ @settings = DEFAULT_SETTINGS.merge( settings )
40
+ @wiki = wiki
41
+ check_mailbox
42
+ Thread.new do
43
+ loop do
44
+ sleep @settings[:check_frequency ]
45
+ check_mailbox
46
+ end
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def check_mailbox
53
+ login
54
+ select_mailbox
55
+ p "Checking for emails in #{@settings[:server]}"
56
+ new_messages_for_wiki do |message_id|
57
+ this_message = Message.new( @imap, message_id )
58
+ if this_message.subject =~ @settings[:subject_regexp]
59
+ add_message_to_wiki( this_message )
60
+ mark_as_added( message_id )
61
+ end
62
+ end
63
+ logout
64
+ end
65
+
66
+ def add_message_to_wiki( message )
67
+ current_page = @wiki.page( message.subject )
68
+ if current_page.empty?
69
+ text = "h1. #{message.subject}"
70
+ else
71
+ text = current_page.textile
72
+ end
73
+ text << "\n\n----\n\n"
74
+ text << "#{message.date} from #{message.sender_name} #{message.sender_email}\n"
75
+ text << message.text.gsub(/[\*-]{2,}/,'').gsub(/\n\s+/,"\n").gsub(/\n/,"\n\n")
76
+ @wiki.revise(message.subject, text, message.sender_name )
77
+ end
78
+
79
+ def login
80
+ @imap = Net::IMAP.new(@settings[:server])
81
+ @imap.login( @settings[:username], @settings[:password] )
82
+ end
83
+
84
+ def logout
85
+ @imap.logout
86
+ @imap.disconnect
87
+ end
88
+
89
+ def select_mailbox
90
+ @imap.select @settings[:mailbox]
91
+ end
92
+
93
+ def new_messages_for_wiki
94
+ @imap.search('UNKEYWORD PutInWiki').each { |id| yield id }
95
+ end
96
+
97
+ def mark_as_added( id )
98
+ # @imap.store( id, '+FLAGS', ['PutInWiki'] )
99
+ end
100
+
101
+ end
@@ -0,0 +1,48 @@
1
+ require 'rss/1.0'
2
+ require 'rss/2.0'
3
+ require 'open-uri'
4
+
5
+ class RSS2WikiHelper
6
+
7
+ DEFAULT_SETTINGS = {
8
+ :url => 'http://localhost:8000/rss/recent%20changes%20to%20this%20site',
9
+ :pagename => nil, # If nil, uses channel title,
10
+ :check_frequency => 1200,
11
+ :author => 'AutomaticRSS2Wiki',
12
+ }
13
+
14
+ def initialize( wiki, settings = {} )
15
+ @settings = DEFAULT_SETTINGS.merge( settings )
16
+ @wiki = wiki
17
+ Thread.new do
18
+ loop do
19
+ update_rss
20
+ update_wiki
21
+ sleep @settings[ :check_frequency ]
22
+ end
23
+ end
24
+ end
25
+
26
+ def update_wiki
27
+ @wiki.revise( @settings[:pagename] || @rss.channel.title, render, @rss.items.first.respond_to?('author') ? @rss.items.first.author : "AutomaticRSS" )
28
+ end
29
+
30
+ def render
31
+ content = "h1. #{@rss.channel.title}\n\n"
32
+ @rss.items.each do |item|
33
+ content << "# [[ #{escape(item.title)} => #{item.link} ]]\n"
34
+ end
35
+ content
36
+ end
37
+
38
+ def update_rss
39
+ $stderr.puts "Updating feed"
40
+ open(@settings[:url]) do |http|
41
+ @rss = RSS::Parser.parse( http.read , false)
42
+ end
43
+ end
44
+
45
+ def escape( string )
46
+ string.tr('[]=>','')
47
+ end
48
+ end