Wiki2Go 1.15.1 → 1.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/bin/DebugWiki2GoServer.rb +10 -0
  2. data/bin/{Wiki2Go_make_repository.rb → Wiki2Go_make_cvs_repository.rb} +1 -1
  3. data/lib/Web2Go/WebrickRequest.rb +1 -1
  4. data/lib/Web2Go/WebrickResponse.rb +3 -3
  5. data/lib/Wiki2Go/BlackList.rb +24 -11
  6. data/lib/Wiki2Go/DotGraphics.rb +45 -5
  7. data/lib/Wiki2Go/FileStorage.rb +8 -2
  8. data/lib/Wiki2Go/GreyList.rb +38 -22
  9. data/lib/Wiki2Go/Install/make_repository.rb +351 -36
  10. data/lib/Wiki2Go/Install/make_site.rb +17 -8
  11. data/lib/Wiki2Go/Install/site/ruby.css +18 -0
  12. data/lib/Wiki2Go/Install/templates/admin.htm +11 -0
  13. data/lib/Wiki2Go/Install/templates/admin_pages/commit_site.txt +21 -0
  14. data/lib/Wiki2Go/Install/templates/admin_pages/edit.txt +33 -0
  15. data/lib/Wiki2Go/Install/templates/admin_pages/editfiles.txt +33 -0
  16. data/lib/Wiki2Go/Install/templates/admin_pages/greylist.txt +19 -37
  17. data/lib/Wiki2Go/Install/templates/admin_pages/show_log.txt +21 -0
  18. data/lib/Wiki2Go/Install/templates/admin_pages/update_conflicts.txt +38 -0
  19. data/lib/Wiki2Go/Install/templates/admin_pages/update_site.txt +49 -0
  20. data/lib/Wiki2Go/Install/wiki/ruby.css +18 -0
  21. data/lib/Wiki2Go/LineFormatter.rb +504 -0
  22. data/lib/Wiki2Go/Page.rb +50 -18
  23. data/lib/Wiki2Go/PublicWikiConfig.rb +34 -11
  24. data/lib/Wiki2Go/Server.rb +13 -2
  25. data/lib/Wiki2Go/SpamFilter.rb +27 -8
  26. data/lib/Wiki2Go/SyntaxHighlighter.rb +41 -0
  27. data/lib/Wiki2Go/Web.rb +0 -3
  28. data/lib/Wiki2Go/WebrickServlet.rb +2 -0
  29. data/lib/Wiki2Go/Wiki2Go.rb +19 -8
  30. data/lib/Wiki2Go/Wiki2GoConfig.rb +125 -18
  31. data/lib/Wiki2Go/Wiki2GoServlet.rb +32 -21
  32. data/lib/Wiki2Go/WikiFormatter.rb +55 -468
  33. data/lib/Wiki2Go/cgi/secure/log_rss +21 -0
  34. data/test/All.rb +21 -0
  35. data/test/TestBlackList.rb +82 -0
  36. data/test/TestConfig.rb +205 -0
  37. data/test/TestDot.rb +109 -0
  38. data/test/TestFormatter.rb +491 -0
  39. data/test/TestInstall.rb +120 -0
  40. data/test/TestLineFormatter.rb +553 -0
  41. data/test/TestMail.rb +29 -0
  42. data/test/TestRSS.rb +183 -0
  43. data/test/TestRepositoryMaker.rb +101 -0
  44. data/test/TestServer.rb +65 -0
  45. data/test/TestSpamFilter.rb +130 -0
  46. data/test/TestStorage.rb +212 -0
  47. data/test/TestSyntaxHighlighter.rb +41 -0
  48. data/test/TestUnitTestFiles.rb +27 -0
  49. data/test/TestUrlFinder.rb +39 -0
  50. data/test/TestWeb.rb +197 -0
  51. data/test/TestWeb2Go.rb +90 -0
  52. data/test/TestWiki2Go.rb +184 -0
  53. data/test/TestWiki2GoServlet.rb +747 -0
  54. data/test/UnitTestFiles.rb +102 -0
  55. data/test/Wiki2GoConfigForTest.rb +93 -0
  56. data/test/checksite.rb +56 -0
  57. data/test/testdata/changes.txt +4 -0
  58. data/test/testdata/expected_changes.html +93 -0
  59. data/test/testdata/expected_edit.html +105 -0
  60. data/test/testdata/expected_full_rss.xml +29 -0
  61. data/test/testdata/expected_header_rss.xml +13 -0
  62. data/test/testdata/expected_out.html +97 -0
  63. data/test/testdata/expected_put.html +99 -0
  64. data/test/testdata/expected_save.html +66 -0
  65. data/test/testdata/expected_savehtml.html +66 -0
  66. data/test/testdata/expected_search.html +67 -0
  67. data/test/testdata/expected_upload.html +69 -0
  68. data/test/testdata/expected_versions.html +85 -0
  69. data/test/testdata/expected_view.html +97 -0
  70. data/test/testdata/site/html/Xpday/rss.xml +103 -0
  71. data/test/testdata/templates/Test/child.htm +2 -0
  72. data/test/testdata/templates/Test/grandchild.htm +1 -0
  73. data/test/testdata/templates/Test/master.htm +3 -0
  74. data/test/testdata/texts/Test/FrontPage.txt +7 -0
  75. data/test/testdata/texts/Test/NewPage.txt +3 -0
  76. data/test/testdata/texts/Test/Subdir/Subpage.txt +1 -0
  77. data/test/testdata/texts/Test/empty.txt +3 -0
  78. data/test/testdata/texts/Test/test.txt +3 -0
  79. data/test/testdata/texts/Xpday/FrontPage.txt +36 -0
  80. data/test/testdata/texts/Xpday/Page.txt +3 -0
  81. data/test/testdata/texts/Xpday/VersionedPage.log +14 -0
  82. data/test/testdata/texts/Xpday/VersionedPage.txt +3 -0
  83. data/test/testdata/texts/Xpday/empty.log +3482 -0
  84. data/test/testdata/texts/Xpday/empty.txt +4 -0
  85. data/test/testdata/texts/Xpday/test.log +9425 -0
  86. data/test/testdata/texts/Xpday/test.txt +5 -0
  87. data/test/testdata/texts/whitelist.txt +1 -0
  88. metadata +85 -5
  89. data/lib/Wiki2Go/Install/templates/admin_pages/update.txt +0 -13
@@ -6,7 +6,7 @@ require 'optparse'
6
6
  require "uri"
7
7
 
8
8
  require 'rubygems'
9
- WIKI2GO_VERSION = '1.15.0'
9
+ WIKI2GO_VERSION = '1.16.0'
10
10
  require_gem "Wiki2Go","~>#{WIKI2GO_VERSION}"
11
11
 
12
12
  require 'Wiki2Go/PublicWikiConfig'
@@ -115,7 +115,7 @@ module Wiki2Go
115
115
  set_owner(configuration.directory,configuration.user)
116
116
  File.umask(oldmask)
117
117
  puts "Installed."
118
- puts "Include #{configuration.directory}/config/site.conf in your Apache configuration"
118
+ puts "Include '#{configuration.directory}/config/site.conf' in your Apache configuration"
119
119
  puts " and restart Apache to activate your wiki."
120
120
  end
121
121
  end
@@ -316,14 +316,11 @@ module Wiki2Go
316
316
  template = <<-TEMPLATE_END
317
317
  #!/usr/bin/env ruby
318
318
 
319
- #
319
+ # Select which version of Wiki2Go is used.
320
320
  require 'rubygems'
321
321
  require_gem "Wiki2Go","~>#{WIKI2GO_VERSION}"
322
322
  require "Wiki2Go/#{baseconfig}"
323
323
 
324
- # Uncomment if you want to add 'dot' graphics to your page (see http://www.graphviz.org)
325
- # require 'Wiki2Go/DotGraphics'
326
-
327
324
  class CgiOptions < Wiki2Go::#{baseconfig}
328
325
 
329
326
  def initialize
@@ -353,8 +350,19 @@ class CgiOptions < Wiki2Go::#{baseconfig}
353
350
  @subsite = '#{config.subsite}'
354
351
 
355
352
  # Uncomment if you want to add 'dot' graphics to your page (see http://www.graphviz.org)
356
- # The path must point to the 'dot' exexcutable
357
- # add_processor('GRAPH',Wiki2Go::DotGraphics.new('/usr/bin/'))
353
+ # The path must point to the 'dot' executable
354
+ # enable_dot_graphics('/usr/bin/')
355
+
356
+ # Uncomment if you want to add Ruby syntax highlighting
357
+ # You also need to include the html/ruby.css stylesheet in your template
358
+ # enable_syntax_highlighting
359
+
360
+ # If you want to enable CVS commit/update support for your wiki, uncomment the following line
361
+ # and fill in the CVSROOT and the name of the module as parameters
362
+ # The CVS repository and module must exist and the webserver user must have commit access to it
363
+ # You need to have the rscm 0.3 gem installed
364
+ # use_repository('MYCVSROOT','mymodule')
365
+
358
366
  end
359
367
 
360
368
  end
@@ -393,6 +401,7 @@ TEMPLATE_END
393
401
  mkdir_p(File.join(dest,'html'),{ :mode => 0775})
394
402
  source = File.join(config.source_dir,'site','.')
395
403
  cp_r source,dest
404
+ Dir["#{dest}/**/CVS"].each { |name| rm_r name }
396
405
  end
397
406
 
398
407
  def Install.do_make_wiki(config)
@@ -0,0 +1,18 @@
1
+ .ruby .normal {}
2
+ .ruby .comment { color: #005; font-style: italic; }
3
+ .ruby .keyword { color: #A00; font-weight: bold; }
4
+ .ruby .method { color: #077; }
5
+ .ruby .class { color: #074; }
6
+ .ruby .module { color: #050; }
7
+ .ruby .punct { color: #447; font-weight: bold; }
8
+ .ruby .symbol { color: #099; }
9
+ .ruby .string { color: #944; background: #FFE; }
10
+ .ruby .char { color: #F07; }
11
+ .ruby .ident { color: #004; }
12
+ .ruby .constant { color: #07F; }
13
+ .ruby .regex { color: #B66; background: #FEF; }
14
+ .ruby .number { color: #F99; }
15
+ .ruby .attribute { color: #7BB; }
16
+ .ruby .global { color: #7FB; }
17
+ .ruby .expr { color: #227; }
18
+ .ruby .escape { color: #277; }
@@ -32,6 +32,7 @@
32
32
  <div class="menuheading"><%= formatter.admin_link("","Home")%></div>
33
33
  <ul>
34
34
  <li><%= formatter.admin_link("regenerate","Regenerate&nbsp;HTML")%></li>
35
+ <li><%= formatter.admin_link("editfiles","Edit&nbsp;Files")%></li>
35
36
  <li><%= formatter.admin_link("passwords","Passwords")%></li>
36
37
  </ul>
37
38
  <div class="menuheading">SPAM&nbsp;filter</div>
@@ -39,6 +40,16 @@
39
40
  <li><%= formatter.admin_link("greylist","Greylist")%></li>
40
41
  <li><%= formatter.admin_link("update_blacklist","Update&nbsp;Blacklist")%></li>
41
42
  </ul>
43
+ <div class="menuheading">Repository</div>
44
+ <ul>
45
+ <li><%= formatter.admin_link("update_site","Update&nbsp;Site")%></li>
46
+ <li><%= formatter.admin_link("commit_site","Commit&nbsp;Site")%></li>
47
+ <li><%= formatter.admin_link("update_conflicts","Update&nbsp;Conflicts")%></li>
48
+ </ul>
49
+ <div class="menuheading">Logs</div>
50
+ <ul>
51
+ <li><%= formatter.admin_link("show_log","Show&nbsp;Log")%></li>
52
+ </ul>
42
53
  </TD>
43
54
  <TD width="100%" valign="top">$BODY$</TD>
44
55
  </TR>
@@ -0,0 +1,21 @@
1
+ <%
2
+ output = ''
3
+
4
+ doit = @request.parameter('update',nil)
5
+ comment = @request.parameter('comment','no comment')
6
+
7
+ if doit then
8
+ commit_log = @config.commit_to_repository(comment)
9
+ commit_log = commit_log.collect { |line| CGI::escapeHTML(line) }
10
+ output = commit_log.join("<br>#{$/}")
11
+ end
12
+ %>
13
+
14
+ <h3>Commit Site</h3>
15
+ <form action="<%= File.join(@web.script_prefix,'admin','commit_site')%>" method="get">
16
+ Comment: <input name="comment" value="">
17
+ <button type="submit" name="update" value="update">
18
+ Commit site changes to repository
19
+ </button>
20
+ </form>
21
+ <%= output %>
@@ -0,0 +1,33 @@
1
+ <%
2
+
3
+ file = @request.parameter('file',nil)
4
+
5
+ content = 'EMPTY'
6
+ if !file.nil? then
7
+ filename = File.join(@config.root_directory,file)
8
+ if File.exists?(filename)
9
+ content = IO::read(filename)
10
+ end
11
+
12
+ doit = @request.parameter('update',nil)
13
+ if !doit.nil? then
14
+ content = @request.parameter('text',nil)
15
+ if !content.nil? then
16
+ File::open(filename,File::CREAT|File::WRONLY) do |f|
17
+ f.puts content
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ %>
24
+ <h3>Edit File</h3>
25
+ <form action="<%= File.join(@web.script_prefix,'admin','edit')%>" method="post">
26
+ <input type="hidden" name="file" value="<%= file %>">
27
+ <textarea name="text" rows="35" cols="96"><%= content %></textarea><br>
28
+ <button type="submit" name="update" value="update">
29
+ Save file
30
+ </button>&nbsp;<input type="reset" value=" Undo changes ">
31
+ </form>
32
+
33
+
@@ -0,0 +1,33 @@
1
+ <%
2
+
3
+ def edit_file(filename)
4
+ "<a href=\"#{ File.join(@web.script_prefix,'admin','edit')}?file=#{CGI::escape(filename)}\">#{filename}</a>"
5
+ end
6
+ %>
7
+
8
+ <%
9
+ all_files = []
10
+
11
+ Dir.chdir(@config.root_directory)
12
+ files = Dir.glob('**/*')
13
+
14
+ all_files = files.find_all { |name| File.file?(File.join(@config.root_directory,name)) && name !~ /CVS/ }.sort
15
+ all_files = all_files.reject do |name|
16
+ name =~ /\.png$/ || name =~ /\.jpg$/ || name =~ /\.gif$/ || name =~ /\.pdf$/ || name =~ /\.xls$/
17
+ end
18
+
19
+ odd = false
20
+ %>
21
+
22
+ <h3>Site files</h3>
23
+
24
+ <% if all_files.length > 0 then %>
25
+ <table class="topiclist">
26
+ <% all_files.each do |file|
27
+ style = (odd ? "odd" : "even")
28
+ odd = !odd
29
+ %>
30
+ <tr class="<%= style%>"><td><%= edit_file(file) %></td></tr>
31
+ <% end %>
32
+ </table>
33
+ <% end %>
@@ -1,44 +1,24 @@
1
1
  <%
2
+ require 'Wiki2Go/SpamFilter'
2
3
 
3
- greylist = File.join(@config.root_directory,'config','greylist.txt')
4
- exists = File.exists?(greylist)
4
+ spamfilter = Wiki2Go::SpamFilter.new(@config)
5
5
 
6
- selected_line = @request.parameter('selected_line','').strip
6
+ author = @request.parameter('author','').strip
7
+ url = @request.parameter('url','').strip
7
8
 
8
- lines = []
9
- if File.exists?(greylist) then
10
- pwdfile = File.open(greylist,'r') do |f|
11
- lines = f.readlines
12
- end
9
+ if !@request.parameter('accept').nil? && !author.empty? then
10
+ @config.log("Accept #{author} and url '#{url}'")
11
+ spamfilter.remove_from_greylist(author,url)
13
12
  end
14
13
 
15
- if exists && (!@request.parameter('accept').nil? || !@request.parameter('blacklist').nil?) && !selected_line.empty? then
16
- @config.log("Accept #{selected_line}")
17
- lines = lines.collect { |line|
18
- if line.strip == selected_line then
19
- @config.log("Remove line #{line}")
20
- nil
21
- else
22
- line
23
- end
24
- }
25
- lines = lines.compact
26
- pwdfile = File.open(greylist,'w') do |f|
27
- f.puts lines
28
- end
29
- end
30
-
31
- if !@request.parameter('blacklist').nil? && !selected_line.empty? then
32
- user , url = selected_line.split(' ')
33
- blacklist = @config.storage.load_blacklist('user')
34
- blacklist.add(user)
35
- @config.storage.save_list(blacklist)
36
-
37
- blacklist = @config.storage.load_blacklist('url')
38
- blacklist.add(url.gsub(/\\\./,'.'))
39
- @config.storage.save_list(blacklist)
14
+ if !@request.parameter('blacklist').nil? && !author.empty? then
15
+ @config.errorlog("Blacklist user '#{author}' and URL '#{url}'")
16
+ spamfilter.remove_from_greylist(author,url)
17
+ spamfilter.blacklist_user(author)
18
+ spamfilter.blacklist_url(url)
40
19
  end
41
20
 
21
+ supects = spamfilter.greylist_suspects
42
22
 
43
23
  %>
44
24
  <h3>Manage greylist</h3>
@@ -46,10 +26,10 @@ end
46
26
  <tr><th>Name</th><th>URL</th><th>&nbsp;</th><th>&nbsp;</th></tr>
47
27
  <%
48
28
  odd = false
49
- lines.each do |line|
29
+ supects.each do |suspect|
50
30
  style = (odd ? "odd" : "even")
51
31
  odd = !odd
52
- name,url = line.split(' ')
32
+ name,url = suspect.user,suspect.url
53
33
  clean_url = 'http' + url.gsub(/\\\./,'.')
54
34
  %>
55
35
  <tr class="<%= style%>">
@@ -58,12 +38,14 @@ end
58
38
  <td>
59
39
  <form action="<%= File.join(@web.script_prefix,'admin','greylist')%>" method="GET">
60
40
  <input type="submit" name="accept" value="Accept">
61
- <input type="hidden" name="selected_line" value="<%= line %>">
41
+ <input type="hidden" name="author" value="<%= name %>">
42
+ <input type="hidden" name="url" value="<%= clean_url %>">
62
43
  </form>
63
44
  </td>
64
45
  <td>
65
46
  <form action="<%= File.join(@web.script_prefix,'admin','greylist')%>" method="GET">
66
- <input type="hidden" name="selected_line" value="<%= line %>">
47
+ <input type="hidden" name="author" value="<%= name %>">
48
+ <input type="hidden" name="url" value="<%= clean_url %>">
67
49
  <input type="submit" name="blacklist" value="Blacklist">
68
50
  </form>
69
51
  </td>
@@ -0,0 +1,21 @@
1
+ <%
2
+ output = ''
3
+
4
+ doit = @request.parameter('show',nil)
5
+
6
+ if doit then
7
+ logfile = @config.logfile
8
+ File.open(logfile,File::RDONLY) do |f|
9
+ output = f.read
10
+ end
11
+ end
12
+ %>
13
+
14
+ <h3>View log</h3>
15
+ <form action="<%= File.join(@web.script_prefix,'admin','show_log')%>" method="get">
16
+ <button type="submit" name="show" value="show">
17
+ Show logfile
18
+ </button>
19
+ </form>
20
+ <%= CGI::escapeHTML(output).gsub(/\n/,"<br>\n") %>
21
+
@@ -0,0 +1,38 @@
1
+ <%
2
+
3
+ def edit_file(filename)
4
+ "<a href=\"#{ File.join(@web.script_prefix,'admin','edit')}?file=#{CGI::escape(filename)}\">#{filename}</a>"
5
+ end
6
+
7
+ def contains_conflict_marker(name)
8
+ content = IO::read(File.join(@config.root_directory,name))
9
+ return content =~ /<{7,7}/ && content =~ />{7,7}/ && content =~ /={7,7}/
10
+ end
11
+ %>
12
+
13
+ <%
14
+ clashed = []
15
+
16
+ Dir.chdir(@config.root_directory)
17
+ files = Dir.glob('**/*')
18
+
19
+ all_files = files.find_all { |name| File.file?(File.join(@config.root_directory,name)) && name !~ /CVS/ }
20
+
21
+
22
+ clashed = all_files.find_all {|name| contains_conflict_marker(name) }.sort
23
+ odd = false
24
+ %>
25
+
26
+ <h3>Update Conflicts</h3>
27
+
28
+ <% if clashed.length > 0 then %>
29
+ <hr>
30
+ <table class="topiclist"><caption>Clashed</caption>
31
+ <% clashed.each do |file|
32
+ style = (odd ? "odd" : "even")
33
+ odd = !odd
34
+ %>
35
+ <tr class="<%= style%>"><td><%= edit_file(file) %></td></tr>
36
+ <% end %>
37
+ </table>
38
+ <% end %>
@@ -0,0 +1,49 @@
1
+ <%
2
+ output = ''
3
+
4
+ doit = @request.parameter('update',nil)
5
+
6
+ updated = []
7
+ clashed = []
8
+ if doit then
9
+ updated,clashed = @config.update_from_repository
10
+ end
11
+
12
+ def edit_file(filename)
13
+ "<a href=\"#{ File.join(@web.script_prefix,'admin','edit')}?file=#{CGI::escape(filename)}\">#{filename}</a>"
14
+ end
15
+
16
+ odd = false
17
+
18
+ %>
19
+
20
+ <h3>Update Site</h3>
21
+ <form action="<%= File.join(@web.script_prefix,'admin','update_site')%>" method="get">
22
+ <button type="submit" name="update" value="update">
23
+ Update the site from repository
24
+ </button>
25
+ </form>
26
+
27
+ <% if updated.length > 0 then %>
28
+ <hr>
29
+ <table class="topiclist"><caption>Updated</caption>
30
+ <% updated.each do |file|
31
+ style = (odd ? "odd" : "even")
32
+ odd = !odd
33
+ %>
34
+ <tr class="<%= style %>"><td><%= edit_file(file) %></td></tr>
35
+ <% end %>
36
+ </table>
37
+ <% end %>
38
+
39
+ <% if clashed.length > 0 then %>
40
+ <hr>
41
+ <table class="topiclist"><caption>Clashed</caption>
42
+ <% clashed.each do |file|
43
+ style = (odd ? "odd" : "even")
44
+ odd = !odd
45
+ %>
46
+ <tr class="<%= style%>"><td><%= edit_file(file) %></td></tr>
47
+ <% end %>
48
+ </table>
49
+ <% end %>
@@ -0,0 +1,18 @@
1
+ .ruby .normal {}
2
+ .ruby .comment { color: #005; font-style: italic; }
3
+ .ruby .keyword { color: #A00; font-weight: bold; }
4
+ .ruby .method { color: #077; }
5
+ .ruby .class { color: #074; }
6
+ .ruby .module { color: #050; }
7
+ .ruby .punct { color: #447; font-weight: bold; }
8
+ .ruby .symbol { color: #099; }
9
+ .ruby .string { color: #944; background: #FFE; }
10
+ .ruby .char { color: #F07; }
11
+ .ruby .ident { color: #004; }
12
+ .ruby .constant { color: #07F; }
13
+ .ruby .regex { color: #B66; background: #FEF; }
14
+ .ruby .number { color: #F99; }
15
+ .ruby .attribute { color: #7BB; }
16
+ .ruby .global { color: #7FB; }
17
+ .ruby .expr { color: #227; }
18
+ .ruby .escape { color: #277; }
@@ -0,0 +1,504 @@
1
+
2
+ #!/usr/bin/ruby
3
+
4
+ require 'erb'
5
+ require 'cgi'
6
+ require 'English'
7
+
8
+ module Wiki2Go
9
+
10
+ class LineFormatter
11
+
12
+ attr_reader :config
13
+
14
+ def initialize(web,storage,config,generate_html,editable)
15
+ @web = web
16
+ @storage = storage
17
+ @config = config
18
+ @in_table = false
19
+ @bullets = Array.new
20
+ @pre_line = ""
21
+ @post_line = ""
22
+ @generate_html = generate_html
23
+ @editable = editable
24
+ @absolute_urls = false
25
+ end
26
+
27
+ public
28
+
29
+ def format_line(line)
30
+ @added_bullets = false
31
+ line = escape_wiki_markers(line)
32
+ line = format_wiki_markup(line)
33
+ line = format_table(line)
34
+ line = remove_markers(line)
35
+ if !@added_bullets then
36
+ emit_bullets
37
+ end
38
+
39
+ return formatted_output(line)
40
+ end
41
+
42
+ def formatting_done
43
+ emit_bullets
44
+ @pre_line
45
+ end
46
+
47
+
48
+ def absolute_url
49
+ return @web.base_url + view_page_url(@web.name,@web.current_page)
50
+ end
51
+
52
+ def absolute_url_of_topic(topic)
53
+ return @web.base_url + view_page_url(@web.name,topic)
54
+ end
55
+
56
+ def edit_link(subwiki,page,name)
57
+ if @editable then
58
+ return name + edit_this_link(subwiki,page,"?")
59
+ else
60
+ return name
61
+ end
62
+ end
63
+
64
+ def edit_this_link(subwiki,page,name)
65
+ if @editable then
66
+ return "<a href=\"#{join(@web.script_prefix,"edit"+@web.script_extension,subwiki,page)}\">#{name}</a>"
67
+ else
68
+ return ""
69
+ end
70
+ end
71
+
72
+ def save_this_link(subwiki,page)
73
+ if @editable then
74
+ return join(@web.script_prefix,"save"+@web.script_extension,subwiki,page)
75
+ else
76
+ return page
77
+ end
78
+ end
79
+
80
+ def verb_url(verb)
81
+ return join(@web.script_prefix,verb+@web.script_extension,@web.name,@web.current_page)
82
+ end
83
+
84
+ def removespam_url(user)
85
+ return join(@web.script_prefix,'removespam'+@web.script_extension,@web.name,'') + '?user=' + user
86
+ end
87
+
88
+ def version_url(page)
89
+ return join(@web.script_prefix,'versions'+@web.script_extension,@web.name,page)
90
+ end
91
+
92
+ def save_url
93
+ verb_url('save')
94
+ end
95
+
96
+ def search_link(desc)
97
+ return "<a href=\"#{search_url + "?text="+desc}\">#{desc}</a>"
98
+ end
99
+
100
+ def search_link2(desc,name)
101
+ return "<a href=\"#{search_url + "?text="+desc}\">#{name}</a>"
102
+ end
103
+
104
+ def search_url
105
+ return join(@web.script_prefix,'search'+@web.script_extension,@web.name)
106
+ end
107
+
108
+ def changes_url
109
+ if @generate_html then
110
+ return join(@web.name,'recent_changes.html')
111
+ else
112
+ return join(@web.script_prefix,'changes'+@web.script_extension,@web.name)
113
+ end
114
+ end
115
+
116
+ def changes_link(desc)
117
+ return "<a href=\"#{changes_url}\">#{desc}</a>"
118
+ end
119
+
120
+ def view_page_url(subwiki,page)
121
+ if @generate_html then
122
+ return join(subwiki,page + ".html")
123
+ else
124
+ return join(@web.script_prefix,"view" + @web.script_extension,subwiki,page)
125
+ end
126
+ end
127
+
128
+ def view_url(subwiki,page)
129
+ if @absolute_urls then
130
+ return File.join(@web.base_url,view_page_url(subwiki,page))
131
+ else
132
+ return view_page_url(subwiki,page)
133
+ end
134
+ end
135
+
136
+
137
+
138
+ def view_link(subwiki,page,name)
139
+ if subwiki == @web.name then
140
+ return "<a href=\"#{view_url(subwiki,page)}\">#{name}</a>"
141
+ else
142
+ return "<a href=\"#{view_url(subwiki,page)}\">#{subwiki}:#{name}</a>"
143
+ end
144
+ end
145
+
146
+ def perform_link(subwiki,page,name)
147
+ if @storage.exists?(File.join(subwiki,page)) then
148
+ url = join(@web.script_prefix,"view" + @web.script_extension,subwiki,page)
149
+ if subwiki == @web.name then
150
+ return "<a href=\"#{url}\">#{name}</a>"
151
+ else
152
+ return "<a href=\"#{url}\">#{subwiki}:#{name}</a>"
153
+ end
154
+ else
155
+ return edit_link(subwiki,page,name)
156
+ end
157
+ end
158
+
159
+ def view_version_link(subwiki,page,name,parameters=nil)
160
+ return "<a href=\"#{view_version_url(subwiki,page)+query_string(parameters)}\">#{name}</a>"
161
+ end
162
+
163
+ def view_version_url(subwiki,page)
164
+ return join(@web.script_prefix,"view" + @web.script_extension,subwiki,page)
165
+ end
166
+
167
+ def query_string(parameters)
168
+ return "" if parameters.nil?
169
+ return "?" + parameters.collect { |key,value| key + '=' + value}.sort.join('&')
170
+ end
171
+
172
+ def version_link(page,name)
173
+ return "<a href=\"#{version_url(page)}\">#{name}</a>"
174
+ end
175
+
176
+ def admin_link(page,name)
177
+ return "<a href=\"#{join(@web.script_prefix,'admin' + @web.script_extension,page)}\">#{name}</a>"
178
+ end
179
+
180
+
181
+ def redirect_url(url)
182
+ if @config.redirect_url?(@web,url) then
183
+ redirected_url = join(@web.script_prefix,"redirect",@web.name + "?url=" + CGI::escape(url) )
184
+ return redirected_url
185
+ else
186
+ return url
187
+ end
188
+ end
189
+
190
+ def redirect_link(label,url)
191
+ if @config.redirect_url?(@web,url) then
192
+ redirected_url = redirect_url(url)
193
+ return "<a href=\"#{redirected_url}\" rel=\"nofollow\" target=\"_blank\">#{label}</a>"
194
+ else
195
+ return "<a href=\"#{url}\" target=\"_blank\">#{label}</a>"
196
+ end
197
+
198
+ end
199
+
200
+
201
+ def resource_url(name)
202
+ if @absolute_urls then
203
+ File.join(@web.base_url,'html',@web.name,name)
204
+ else
205
+ File.join('html',@web.name,name)
206
+ end
207
+ end
208
+
209
+ def encode_mail_to(addr)
210
+
211
+ addr =~ /(.*)@(.*)/ ;
212
+ name = $1 ;
213
+ site = $2 ;
214
+
215
+ return "<a href=\"#{view_url(@web.name,"MailFormattingRules")}\" onmouseover=\"this.href='mai' + 'lto:' + '#{name}' + '&#64;' + '#{site}'\">#{name}</a>"
216
+ end
217
+
218
+ alias :encodeMailTo :encode_mail_to
219
+
220
+ private
221
+
222
+
223
+ def append(before,match,after)
224
+ result = ''
225
+ result += before if !before.nil?
226
+ result += match if !match.nil?
227
+ result += after if !after.nil?
228
+ result
229
+ end
230
+
231
+ def format_tag(text)
232
+ text = text.gsub(/"((http|ftp|gopher|news|https)\:[^"]*)"/) { externalUrl($1) }
233
+
234
+ return '<' + text + '>'
235
+ end
236
+
237
+
238
+ def format_wiki_markup(line)
239
+ if line =~ /^(.*)\{\!(.*)\!\}(.*)$/im then
240
+ before,match,after = $1,$2,$3
241
+ return append(format_wiki_markup(before),match,format_wiki_markup(after))
242
+ elsif line =~ /^(.*)<(\S.*)\>(.*)$/ then
243
+ before,match,after = $1,$2,$3
244
+ line = append(format_wiki_markup(before),escape_url_markers(format_tag(match)),format_wiki_markup(after))
245
+ elsif line =~ /^(.*)\{\%([^\}]*)\%\}(.*)$/ then
246
+ before,match,after = $1,$2,$3
247
+ line = append(format_wiki_markup(before),escape_url_markers(format_dynamic_link(match)),format_wiki_markup(after))
248
+ elsif line =~ /^(.*)\{([^\}]*)\}(.*)$/ then
249
+ before,match,after = $1,$2,$3
250
+ line = append(format_wiki_markup(before),escape_url_markers(format_forced_link(match)),format_wiki_markup(after))
251
+ elsif line =~ /^(.*)\%([^\%]*)\%(.*)$/ then
252
+ before,match,after = $1,$2,$3
253
+ line = append(format_wiki_markup(before),escape_url_markers(format_forced_link(match)),format_wiki_markup(after))
254
+ elsif line =~ /^(.*)((http|ftp|gopher|news|https)\:\/\/(\w|\/|\.|_|-|\?|\=|&|;|\~|#|,)+)(.*)$/ then
255
+ before,match,after = $1,$2,$5
256
+ line = append(format_wiki_markup(before),escape_url_markers(external_link(match)),format_wiki_markup(after))
257
+ elsif line =~ /^(.*)mailto\:([a-zA-Z0-9\-\_\.]+@[a-zA-Z0-9\-\_\.]+)(.*)$/ then
258
+ before,match,after = $1,$2,$3
259
+ line = append(format_wiki_markup(before),escape_url_markers(encode_mail_to(match)),format_wiki_markup(after))
260
+ else
261
+ line = format_brackets(line)
262
+ line = format_entities(line)
263
+ line = recognize_wiki_words(line)
264
+ end
265
+ line = format_bullets(line)
266
+ line = format_markup(line)
267
+ return line
268
+ end
269
+
270
+ def formatted_output(line)
271
+ output = @pre_line + line + @post_line
272
+ @pre_line = ""
273
+ @post_line = ""
274
+ return output
275
+ end
276
+
277
+
278
+ def escape_wiki_markers(line)
279
+ line = line.gsub(/%%/,"&percent;")
280
+ line = line.gsub(/\{\{/,"&openingbrace;")
281
+ line = line.gsub(/\}\}/,"&closingbrace;")
282
+ end
283
+
284
+ def escape_url_markers(line)
285
+ line = line.gsub(/%/ ,'&percent;')
286
+ line = line.gsub(/\{/,'&openingbrace;')
287
+ line = line.gsub(/\}/,'&closingbrace;')
288
+ line = line.gsub(/~/ ,'&tilde;')
289
+ line = line.gsub(/\*/,'&asterisk;')
290
+ line = line.gsub(/_/ ,'&underscore;')
291
+ return line
292
+ end
293
+
294
+ def remove_markers(line)
295
+ line = line.gsub(/&percent;/,"%")
296
+ line = line.gsub(/&openingbrace;/,"{")
297
+ line = line.gsub(/&closingbrace;/,"}")
298
+ line = line.gsub(/&tilde;/,"~")
299
+ line = line.gsub(/&asterisk;/,"*")
300
+ line = line.gsub(/&underscore;/,"_")
301
+ return line
302
+ end
303
+
304
+
305
+ def format_brackets(line)
306
+ line = line.gsub(/</,"&lt\;") ;
307
+ line = line.gsub(/>/,"&gt\;") ;
308
+ return line
309
+ end
310
+
311
+ def format_entities(line)
312
+ line = line.gsub(/\~/,"&tilde;") ;
313
+ line = line.gsub(/&(\w+)\;/,"~\\1\;") ;
314
+ line = line.gsub(/&(#\d+)\;/,"~\\1\;") ;
315
+ line = line.gsub(/&/,"&amp\;") ;
316
+ line = line.gsub(/~/,"&") ;
317
+ line = line.gsub(/\t/," ") ;
318
+ return line
319
+ end
320
+
321
+ def format_markup(line)
322
+ line = line.gsub(/\*\*([^\*]*)\*\*/,"<h2>\\1<\/h2>")
323
+ line = line.gsub(/\*([^\*]+)\*/,"<STRONG>\\1<\/STRONG>")
324
+ line = line.gsub(/\b_([^_]*)_/,"<EM>\\1<\/EM>")
325
+ line = line.gsub(/^---+/,"<hr>")
326
+ return line
327
+ end
328
+
329
+ def format_bullets(line)
330
+ line = line.gsub(/^([\s]{3,99})\*(.*)$/) { add_bullet($1,$2,'u') }
331
+ line = line.gsub(/^([\s]{3,99})(\d)+\.?(.*)$/) { add_bullet($1,$3,'o') }
332
+ return line
333
+ end
334
+
335
+ def format_table(line)
336
+ if @in_table then
337
+ replacement = "</table>"
338
+ else
339
+ replacement = '<table class="wikitable" >'
340
+ end
341
+ if line.gsub!(/^(\|-+\|)/,replacement) then
342
+ @in_table = ! @in_table
343
+ elsif line.gsub!(/^\|\((.+)\)-+\|/,'<table class="\1" >') then
344
+ @in_table = true
345
+ end
346
+ if @in_table then
347
+ line = line.gsub(/^\|/,"<tr><td>")
348
+ line = line.gsub(/\|\s*$/,"<\/td><\/tr>")
349
+ line = line.gsub(/\|/,"<\/td><td>")
350
+ end
351
+ return line
352
+
353
+ end
354
+
355
+ def recognize_wiki_words(line)
356
+ line = line.gsub(/(^|[^\w\.])([A-Z]+[a-z0-9]+[A-Z]+[a-zA-Z0-9]*)/) { $1 + internalLink($2) }
357
+
358
+ end
359
+
360
+ def external_link(url)
361
+ if url =~ /([^\/]+)\.(gif|jpg|jpeg|png)$/i then
362
+ alt = $1
363
+ return "<img src=\"#{url}\" alt=\"#{alt}\">"
364
+ else
365
+ return redirect_link(url,url)
366
+ end
367
+ end
368
+
369
+ def externalUrl(url)
370
+ return '"' + redirect_url(url) + (@config.redirect_url?(@web,url) ? '" rel="nofollow"' : '"') +' target="_blank"'
371
+ end
372
+
373
+ def format_forced_link(link)
374
+ if ! link.gsub!(/^([^%@]+)@(http[^%]+)$/) { labelLink($1,$2) } then
375
+ link.gsub!(/^(([^\%@]+)@)?(([^\%:]+):)?([^%]+)$/) { mega_link($2,$4,$5,@web.name) }
376
+ end
377
+ link
378
+ end
379
+
380
+ def format_dynamic_link(link)
381
+ return link.gsub(/^(([^\%@]+)@)?(([^\%:]+):)?([^%]+)$/) { dynamic_link($2,$4,$5,@web.name) }
382
+ end
383
+
384
+ def labelLink(label,url)
385
+ return redirect_link(label,url)
386
+ end
387
+
388
+ def internalLink(page)
389
+ return internalSubwikiNamedLink(@web.name,page,page)
390
+ end
391
+
392
+ def mega_link(name,subwiki,page,default_wiki)
393
+ name = page if name.nil? || name.empty?
394
+ subwiki = default_wiki if subwiki.nil? || subwiki.empty?
395
+ internalSubwikiNamedLink(subwiki,page,name)
396
+ end
397
+
398
+ def dynamic_link(name,subwiki,page,default_wiki)
399
+ name = page if name.nil? || name.empty?
400
+ subwiki = default_wiki if subwiki.nil? || subwiki.empty?
401
+ perform_link(subwiki,page+'.rbl',name)
402
+ end
403
+
404
+ def internalSubwikiNamedLink(subwiki,page,name)
405
+ if subwiki == "xpnl" then
406
+ return "<a href=\"http://www.xpnl.org/Wiki/#{page}\" target=\"_blank\">xpnl:#{page}</a>"
407
+ elsif subwiki == 'xpbe' then
408
+ return "<a href=\"http://wiki.xp.be/Xpbe/#{page}.html\" target=\"_blank\">xpbe:#{page}</a>"
409
+ elsif subwiki == "wiki" then
410
+ return "<a href=\"http://c2.com/cgi/wiki?#{page}\" target=\"_blank\">wiki:#{page}</a>"
411
+ elsif subwiki == "book" then
412
+ return "<a href=\"http://bookshelved.org/cgi-bin/wiki.pl?#{page}\" target=\"_blank\">book:#{page}</a>"
413
+ elsif subwiki == "wiki2go" then
414
+ return "<a href=\"http://wiki2go.nayima.be/Wiki2Go/#{page}.html\" target=\"_blank\">wiki2go:#{page}</a>"
415
+ elsif subwiki =~ /^isbn$/i then
416
+ name = "ISBN " + page if page == name
417
+ return "<a href=\"http://www.amazon.co.uk/exec/obidos/ASIN/#{page}/#{@config.amazon_affiliate}\" target=\"_blank\">#{name}</a>"
418
+ elsif page =~ /^isbn(.+)$/i then
419
+ name = "ISBN " + $1 if page == name
420
+ return "<a href=\"http://www.amazon.co.uk/exec/obidos/ASIN/#{$1}/#{@config.amazon_affiliate}\" target=\"_blank\">#{name}</a>"
421
+ elsif page =~ /\./ then
422
+ return resource_link(subwiki,page,name)
423
+ elsif @storage.exists?(File.join(subwiki,page)) then
424
+ return view_link(subwiki,page,name)
425
+ else
426
+ return edit_link(subwiki,page,name)
427
+ end
428
+ end
429
+
430
+ def resource_link(subwiki,page,name)
431
+ if page =~ /^(.+)\.(gif|jpg|jpeg|png)$/i then
432
+ filename = $1
433
+ alt_label = name
434
+ if page == name || url?(name) then
435
+ alt_label = filename
436
+ end
437
+ image_link = "<img src=\"#{resource_url(page)}\" border=0 alt=\"#{alt_label}\" >"
438
+ if url?(name) then
439
+ return redirect_link(image_link,name)
440
+ else
441
+ return image_link
442
+ end
443
+ elsif page =~ /^(.*)\.rbl$/i then
444
+ page_name = $1
445
+ if page == name then
446
+ name = page_name
447
+ end
448
+ return perform_link(subwiki,page,name)
449
+ elsif page =~ /^(.+)\.html?$/i then
450
+ return "<a href=\"#{resource_url(page)}\">#{name}</a>"
451
+ else
452
+ return "<a href=\"#{resource_url(page)}\" target=\"_blank\">#{name}</a>"
453
+ end
454
+ end
455
+
456
+ def add_bullet(prefix,text,code)
457
+ @added_bullets = true
458
+ depth = prefix.length / 3
459
+ result = ""
460
+ bullet_depth = @bullets.length
461
+ if depth > bullet_depth then
462
+ bullet_depth.upto(depth-1) do
463
+ result += "<#{code}l>"
464
+ @bullets.push(code)
465
+ end
466
+ elsif depth < bullet_depth then
467
+ bullet_depth.downto(depth+1) do
468
+ bullet = @bullets.pop
469
+ result += "</#{bullet}l>"
470
+ end
471
+ elsif @bullets.last != code then
472
+ bullet = @bullets.pop
473
+ result += "</#{bullet}l>"
474
+ result += "<#{code}l>"
475
+ @bullets.push(code)
476
+ end
477
+ return result + "<li>#{text}"
478
+ end
479
+
480
+ def emit_bullets
481
+ while ! @bullets.empty?
482
+ bullet = @bullets.pop
483
+ @pre_line += "</#{bullet}l>"
484
+ end
485
+ end
486
+
487
+ def join(*dirs)
488
+ result = ""
489
+ dirs.each do |name|
490
+ if !name.nil? and name.length > 0 then
491
+ result += '/' unless result.length == 0
492
+ result += name
493
+ end
494
+ end
495
+ return result.squeeze('/')
496
+ end
497
+
498
+ def url?(name)
499
+ name =~ /(http|ftp|gopher|news|https)\:(\w|\/|\.|_|-|\?|\=|&|;|\~|#|,)+/
500
+ end
501
+
502
+ end
503
+
504
+ end