Wiki2Go 1.17.5 → 1.22.0

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.
Files changed (108) hide show
  1. data/bin/Wiki2Go_firewall_blacklist.rb +8 -0
  2. data/bin/Wiki2Go_make_cvs_repository.rb +1 -0
  3. data/bin/Wiki2Go_make_site.rb +1 -2
  4. data/bin/Wiki2Go_update_site.rb +1 -2
  5. data/lib/Web2Go/CGIRequest.rb +8 -2
  6. data/lib/Web2Go/CGIResponse.rb +17 -14
  7. data/lib/Web2Go/MockRequest.rb +12 -2
  8. data/lib/Web2Go/MockResponse.rb +10 -7
  9. data/lib/Web2Go/WebrickRequest.rb +106 -101
  10. data/lib/Web2Go/WebrickResponse.rb +4 -8
  11. data/lib/Wiki2Go/BlackList.rb +48 -25
  12. data/lib/Wiki2Go/DotGraphics.rb +1 -1
  13. data/lib/Wiki2Go/FileStorage.rb +266 -266
  14. data/lib/Wiki2Go/HTMLFormatter.rb +28 -0
  15. data/lib/Wiki2Go/Install/config/chonqed_blacklist.txt +418 -0
  16. data/lib/Wiki2Go/Install/config/passwords +1 -1
  17. data/lib/Wiki2Go/Install/config/url_blacklist.txt +3855 -0
  18. data/lib/Wiki2Go/Install/make_repository.rb +32 -26
  19. data/lib/Wiki2Go/Install/make_site.rb +197 -111
  20. data/lib/Wiki2Go/Install/site/error.html +1 -1
  21. data/lib/Wiki2Go/Install/site/robots.txt +10 -1
  22. data/lib/Wiki2Go/Install/site/style.css +129 -64
  23. data/lib/Wiki2Go/Install/templates/admin.htm +1 -1
  24. data/lib/Wiki2Go/Install/templates/admin_pages/edit.txt +2 -1
  25. data/lib/Wiki2Go/Install/templates/admin_pages/format_for_fck.txt +31 -0
  26. data/lib/Wiki2Go/Install/templates/admin_pages/passwords.txt +1 -1
  27. data/lib/Wiki2Go/Install/templates/edit.htm +62 -46
  28. data/lib/Wiki2Go/Install/templates/full_footer.htm +31 -33
  29. data/lib/Wiki2Go/Install/templates/header.htm +0 -1
  30. data/lib/Wiki2Go/Install/templates/menu.htm +29 -0
  31. data/lib/Wiki2Go/Install/templates/pagelist.htm +46 -43
  32. data/lib/Wiki2Go/Install/templates/simple_footer.htm +20 -16
  33. data/lib/Wiki2Go/Install/templates/versionlist.htm +52 -40
  34. data/lib/Wiki2Go/Install/templates/view.htm +46 -29
  35. data/lib/Wiki2Go/Install/templates/wikiedit.htm +63 -0
  36. data/lib/Wiki2Go/Install/wiki/delete.png +0 -0
  37. data/lib/Wiki2Go/Install/wiki/style.css +133 -63
  38. data/lib/Wiki2Go/LineFormatter.rb +345 -197
  39. data/lib/Wiki2Go/Page.rb +16 -3
  40. data/lib/Wiki2Go/PrivateWikiConfig.rb +5 -5
  41. data/lib/Wiki2Go/PublicWikiConfig.rb +83 -37
  42. data/lib/Wiki2Go/ReadWriteWikiConfig.rb +8 -8
  43. data/lib/Wiki2Go/Server.rb +6 -1
  44. data/lib/Wiki2Go/SpamFilter.rb +32 -41
  45. data/lib/Wiki2Go/Web.rb +10 -3
  46. data/lib/Wiki2Go/Wiki2Go.rb +301 -94
  47. data/lib/Wiki2Go/Wiki2GoConfig.rb +87 -6
  48. data/lib/Wiki2Go/Wiki2GoServlet.rb +66 -12
  49. data/lib/Wiki2Go/WikiFormatter.rb +60 -30
  50. data/lib/Wiki2Go/cgi/diff.rb +20 -0
  51. data/lib/Wiki2Go/cgi/secure/log_rss.rb +21 -0
  52. data/lib/Wiki2Go/cgi/sidebyside.rb +20 -0
  53. data/lib/Wiki2Go/cgi/wikiedit.rb +20 -0
  54. data/lib/Wiki2Go/firewall_blacklist.rb +88 -0
  55. data/test/All.rb +5 -2
  56. data/test/TestBlackList.rb +70 -14
  57. data/test/TestConfig.rb +5 -5
  58. data/test/TestDiff.rb +95 -0
  59. data/test/TestFormatter.rb +14 -16
  60. data/test/TestHTMLFormatter.rb +37 -0
  61. data/test/TestInstall.rb +70 -27
  62. data/test/TestLineFormatter.rb +71 -15
  63. data/test/TestRSS.rb +8 -7
  64. data/test/TestRepository.rb +50 -0
  65. data/test/TestServer.rb +3 -8
  66. data/test/TestSpamFilter.rb +33 -1
  67. data/test/TestStorage.rb +11 -0
  68. data/test/TestWeb.rb +2 -2
  69. data/test/TestWiki2Go.rb +766 -166
  70. data/test/TestWiki2GoServlet.rb +1122 -524
  71. data/test/UnitTestFiles.rb +7 -3
  72. data/test/Wiki2GoConfigForTest.rb +40 -6
  73. data/test/checksite.rb +17 -50
  74. data/test/test_firewall_blacklist.rb +131 -0
  75. data/test/test_page.rb +45 -0
  76. data/test/testdata/Registration.rbl.txt +7 -0
  77. data/test/testdata/config/url_blacklist.txt +38822 -0
  78. data/test/testdata/expected_changes.html +1 -2
  79. data/test/testdata/expected_edit.html +108 -59
  80. data/test/testdata/expected_full_rss.xml +2 -2
  81. data/test/testdata/expected_out.html +97 -61
  82. data/test/testdata/expected_put.html +88 -53
  83. data/test/testdata/expected_save.html +88 -52
  84. data/test/testdata/expected_savehtml.html +88 -52
  85. data/test/testdata/expected_search.html +68 -53
  86. data/test/testdata/expected_upload.html +88 -53
  87. data/test/testdata/expected_versions.html +97 -82
  88. data/test/testdata/expected_view.html +97 -61
  89. data/test/testdata/firewall/iptables.config +37 -0
  90. data/test/testdata/firewall/user_blacklist.txt +162 -0
  91. data/test/testdata/logs/wiki.log +652 -0
  92. data/test/testdata/logs/wiki.log.0 +113 -0
  93. data/test/testdata/logs/wiki.log.1 +113 -0
  94. data/test/testdata/logs/wiki.log.2 +113 -0
  95. data/test/testdata/logs/wiki.log.3 +115 -0
  96. data/test/testdata/logs/wiki.log.4 +5 -0
  97. data/test/testdata/logs/wiki.log.5 +7 -0
  98. data/test/testdata/logs/wiki.log.6 +5 -0
  99. data/test/testdata/logs/wiki.log.7 +118 -0
  100. data/test/testdata/logs/wiki.log.8 +12 -0
  101. data/test/testdata/site/html/Xpday/rss.xml +53 -103
  102. data/test/testdata/texts/Bugs/FrontPage.txt +6 -0
  103. data/test/testdata/texts/Bugs/NoHidden.spam +17850 -0
  104. data/test/testdata/texts/Bugs/PairProgrammingParties.spam +102 -0
  105. data/test/testdata/texts/Bugs/PairProgrammingParties.txt +99 -0
  106. metadata +53 -7
  107. data/test/TestMail.rb +0 -29
  108. data/test/gc.log +0 -2
data/lib/Wiki2Go/Page.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require "digest/sha2"
2
+
1
3
  module Wiki2Go
2
4
 
3
5
  # Represents one page in the Wiki
@@ -6,7 +8,7 @@ module Wiki2Go
6
8
  # Name of the file
7
9
  attr_reader :filename
8
10
  # Descriptive name given by author
9
- attr_reader :name
11
+ attr_accessor :name
10
12
  # Real author (if authenticated) or IP/DNS address
11
13
  attr_accessor :author
12
14
  # Authorname given by author
@@ -35,7 +37,7 @@ module Wiki2Go
35
37
  @lines = lines
36
38
  end
37
39
  @lastmodified = time
38
- @created_on = time
40
+ @created_on = time
39
41
 
40
42
  @author = author
41
43
  @alias = aliasname || author
@@ -91,9 +93,15 @@ module Wiki2Go
91
93
 
92
94
  # Content as a String
93
95
  def content
94
- return @lines.join
96
+ return @lines.join($/)
95
97
  end
96
98
 
99
+ # Checksum based on content, author, document name and author alias
100
+ # Returns String with hex digest
101
+ def checksum(salt="")
102
+ Digest::SHA256.hexdigest("#{salt}#{content}--#{author}--#{name}--#{self.alias}")
103
+ end
104
+
97
105
  # DEPRECATED use filename instead
98
106
  def title
99
107
  @filename
@@ -104,6 +112,11 @@ module Wiki2Go
104
112
  @filename = name
105
113
  end
106
114
 
115
+ # Does this page contain dynamic (Rublet) content?
116
+ def is_dynamic?
117
+ Page.is_dynamic?(@filename)
118
+ end
119
+
107
120
  # Does filename indicate that page should be executed (Rublet)?
108
121
  def Page.is_dynamic?(pagename)
109
122
  pagename =~ /\.rbl$/
@@ -38,10 +38,10 @@ module Wiki2Go
38
38
  end
39
39
  end
40
40
 
41
- class PrivateWikiConfig < Wiki2Go::PrivateWikiConfig
42
- def initialize(directory)
43
- super(directory)
44
- end
45
- end
41
+ #class PrivateWikiConfig < Wiki2Go::PrivateWikiConfig
42
+ #def initialize(directory)
43
+ #super(directory)
44
+ #end
45
+ #end
46
46
 
47
47
 
@@ -8,86 +8,132 @@ require 'Wiki2Go/SpamFilter'
8
8
  module Wiki2Go
9
9
  # Base class for public wiki
10
10
  class PublicWikiConfig < Wiki2Go::Config
11
-
11
+
12
12
  # Initialize with root directory of wiki
13
- # By default, generates HTML
13
+ # By default, generates HTML and filters SPAM
14
14
  def initialize(directory)
15
15
  super(directory)
16
16
  @generate_html = true
17
+ @delete_spam = true
17
18
  @spamfilter = Wiki2Go::SpamFilter.new(self)
18
-
19
19
  end
20
-
20
+
21
+ # Accept a call from the user if they are not blacklisted
22
+ def accept_user?(web)
23
+ return true if web.secure?
24
+
25
+ author = web.user
26
+ pagename = web.name.length > 0 ? "#{web.name}/#{web.current_page}" : web.current_page
27
+ if @spamfilter.edit_by_banned_user?(author) then
28
+ log("User #{author} is blacklisted while editing '#{pagename}'.")
29
+ return false
30
+ end
31
+ return true
32
+ end
33
+
34
+ # Add the spammer IP address to the blacklist
35
+ def blacklist_user(spammer)
36
+ @spamfilter.blacklist_user(spammer)
37
+ end
38
+
21
39
  # Accept a page save if
22
40
  # * The edit is by an authenticated user
23
41
  # * OR the user is not on the blacklist and none of the URLs on the page are on the blacklist and no more than 5 urls added
42
+ # * AND no hidden style in tags
43
+ # * AND page not erased
24
44
  def accept_page?(web,content)
25
-
26
- return true if web.secure
27
-
28
- author = web.user
29
-
45
+
46
+ return true if web.secure?
47
+
48
+ author = web.user
49
+ pagename = web.name.length > 0 ? "#{web.name}/#{web.current_page}" : web.current_page
50
+
51
+ if @spamfilter.hidden_text_in(content) then
52
+ blacklist_user(author)
53
+
54
+ log(content)
55
+ errorlog("User used hidden style in tags of '#{pagename}': Blacklisted user #{author}")
56
+
57
+ tarpit
58
+ return false
59
+ elsif @spamfilter.cleared_page?(content) then
60
+ @spamfilter.greylist_urls(author,[])
61
+ log(content)
62
+ errorlog("User erased page '#{pagename}': Greylisted user #{author}")
63
+
64
+ tarpit
65
+ return false
66
+ elsif @spamfilter.empty_urls_in(content) then
67
+ blacklist_user(author)
68
+
69
+ log(content)
70
+ errorlog("User used empty URL hrefs in '#{pagename}': Blacklisted user #{author}")
71
+
72
+ tarpit
73
+ return false
74
+ end
75
+
30
76
  current_page = storage.load_page(web.name,web.current_page)
31
77
  urls = @spamfilter.added_urls(current_page.content,content)
32
-
33
- if urls.length > @maximum_urls then
34
- @spamfilter.blacklist_user(author)
78
+
79
+ if @spamfilter.edit_by_banned_user?(author) then
35
80
  @spamfilter.blacklist_urls(urls)
36
-
37
- errorlog("User added too many URLS: #{urls.length}. Blacklisted user #{author} and #{urls.join(', ')}")
38
-
39
- tarpit
81
+
82
+ log("User #{author} is blacklisted while editing '#{pagename}'. Blacklisting #{urls.join(', ')}")
83
+
84
+ # tarpit
40
85
  return false
41
- elsif @spamfilter.edit_by_banned_user?(author) then
86
+ elsif urls.length > @maximum_urls then
87
+ blacklist_user(author)
42
88
  @spamfilter.blacklist_urls(urls)
43
-
44
- errorlog("User #{author} is blacklisted. Blacklisting #{urls.join(', ')}")
45
-
89
+
90
+ errorlog("User added too many URLS to '#{pagename}': #{urls.length}. Blacklisted user #{author} and #{urls.join(', ')}")
91
+
46
92
  tarpit
47
93
  return false
48
94
  elsif urls.length >0 && @spamfilter.edit_contains_banned_url?(urls) then
49
-
50
- @spamfilter.blacklist_user(author)
95
+
96
+ blacklist_user(author)
51
97
  @spamfilter.blacklist_urls(urls)
52
-
53
- errorlog("Edit by user #{author} contains blacklisted url. Blacklisting #{urls.join(', ')}")
54
-
98
+
99
+ errorlog("Edit by user #{author} of page '#{pagename}' contains blacklisted url. Blacklisting #{urls.join(', ')}")
100
+
55
101
  tarpit
56
102
  return false
57
103
  else
58
104
  if urls.length > 0 then
59
105
  @spamfilter.greylist_urls(author,urls)
60
- errorlog("Greylisted user #{author} because of the following urls: #{urls}")
106
+ errorlog("Greylisted user #{author} while editing '#{pagename}' because of the following urls: #{urls.join(', ')}")
61
107
  end
62
108
  return true
63
109
  end
64
110
  end
65
-
111
+
66
112
  # What to do when we encounter a spammer? Delay him for 60 seconds
67
113
  def tarpit
68
114
  sleep(60)
69
115
  end
70
-
116
+
71
117
  # A public wiki is always editable
72
118
  def editable?(web)
73
119
  true
74
120
  end
75
-
121
+
76
122
  # Redirect if the url is on the greylist, unless the user is authenticated
77
123
  def redirect_url?(web,url)
78
- return false if web.secure
79
-
124
+ return false if web.secure?
125
+
80
126
  redirect = @spamfilter.greylisted_url?(url)
81
127
  log("Redirect #{url}") if redirect
82
128
  return redirect
83
129
  end
84
-
130
+
85
131
  end
86
132
  end
87
133
 
88
- class PublicWikiConfig < Wiki2Go::PublicWikiConfig
134
+ #class PublicWikiConfig < Wiki2Go::PublicWikiConfig
89
135
 
90
- def initialize(directory)
91
- super(directory)
92
- end
93
- end
136
+ #def initialize(directory)
137
+ #super(directory)
138
+ #end
139
+ #end
@@ -4,8 +4,8 @@ require "Wiki2Go/FileStorage.rb"
4
4
  require "Wiki2Go/Wiki2GoConfig.rb"
5
5
 
6
6
  module Wiki2Go
7
- # Base class for read/write wikis (authenticated users can write, everybody can read)
8
- class ReadWriteWikiConfig < Wiki2Go::Config
7
+ # Base class for read/write wikis (authenticated users can write, everybody can read)
8
+ class ReadWriteWikiConfig < Wiki2Go::Config
9
9
 
10
10
  def initialize(directory)
11
11
  super(directory)
@@ -14,7 +14,7 @@ module Wiki2Go
14
14
 
15
15
  # Wiki is editable if user is authenticated
16
16
  def editable?(web)
17
- web.secure
17
+ web.secure?
18
18
  end
19
19
 
20
20
  # Never redirect URLs, we trust our authenticated writers
@@ -25,10 +25,10 @@ module Wiki2Go
25
25
  end
26
26
  end
27
27
 
28
- class ReadWriteWikiConfig < Wiki2Go::ReadWriteWikiConfig
28
+ #class ReadWriteWikiConfig < Wiki2Go::ReadWriteWikiConfig
29
29
 
30
- def initialize(directory)
31
- super(directory)
32
- end
33
- end
30
+ #def initialize(directory)
31
+ #super(directory)
32
+ #end
33
+ #end
34
34
 
@@ -24,6 +24,7 @@ module Wiki2Go
24
24
  @generate_html = false
25
25
  @multi_wiki = true
26
26
  @debug = true
27
+ @editor = 'wikiedit'
27
28
  add_processor('GRAPH',Wiki2Go::DotGraphics.new('c:/Program Files/ATT/Graphviz/bin/'))
28
29
  enable_syntax_highlighting
29
30
  end
@@ -50,7 +51,7 @@ module Wiki2Go
50
51
  cvsroot = ''
51
52
  blogstyle = false
52
53
 
53
- opts.on("-d",'--dir <directory>','(default is current directory)',String) { |val| dir = val }
54
+ opts.on("-d",'--dir <directory>','(default is current directory)',String) { |val| dir = File.expand_path(val) }
54
55
  opts.on("-p",'--port <nb>',"(default is port 8081)",String) { |val| port = val }
55
56
  opts.on("-w",'--wiki <wikiname>',"(default is 'Wiki2Go')",String) { |val| wiki = val }
56
57
  opts.on("-s","--single","Single or multi-wiki (default)") { |val| single = true }
@@ -64,6 +65,8 @@ module Wiki2Go
64
65
  end
65
66
  opts.parse(args)
66
67
 
68
+ # TODO : read CgiOptions.rb (if present) and reuse what's available
69
+
67
70
  @config = LocalConfig.new(dir)
68
71
  @config.port = port
69
72
  @config.default_web = wiki
@@ -84,6 +87,8 @@ module Wiki2Go
84
87
  web_thread = Thread.new(@config) do |config|
85
88
  s = WEBrick::HTTPServer.new( :Port => config.port)
86
89
 
90
+ s.mount("/scripts/", WikiServlet,config)
91
+ s.mount("/scripts/secure/", WikiServlet,config)
87
92
  s.mount("/", WikiServlet,config)
88
93
 
89
94
  trap("INT"){ s.shutdown }
@@ -11,16 +11,14 @@ module Wiki2Go
11
11
  end
12
12
 
13
13
  def edit_by_banned_user?(author)
14
- @config.log("Checking if '#{author}' is banned")
15
- banned = banned_users.contains(author)
16
- @config.log("Checking if '#{author}' is banned. Done.")
14
+ banned = @config.banned_users.contains(author)
15
+ @config.log("Checking if '#{author}' is banned=> #{banned}")
17
16
  banned
18
17
  end
19
18
 
20
19
  def edit_contains_banned_url?(content)
21
- @config.log("Checking if '#{content}' is banned")
22
- banned = banned_urls.found_in(content) || chonqed_urls.found_in(content)
23
- @config.log("Checking if '#{content}' is banned. Done")
20
+ banned = @config.banned_urls.found_in(content) || @config.chonqed_urls.found_in(content)
21
+ @config.log("Checking if '#{content}' is banned => #{banned}")
24
22
  banned
25
23
  end
26
24
 
@@ -28,6 +26,12 @@ module Wiki2Go
28
26
  return added_urls(original_content,modified_content).size > max_new_urls
29
27
  end
30
28
 
29
+ # Some idiot spams the xp.be wiki with loads of <a href=" "> tags
30
+ def empty_urls_in(content)
31
+ refs = content.scan(/href="(\s+)"/)
32
+ refs.length > 0
33
+ end
34
+
31
35
  def added_urls(original_content, modified_content)
32
36
  url_finder = Wiki2Go::UrlFinder.new
33
37
 
@@ -38,27 +42,21 @@ module Wiki2Go
38
42
  end
39
43
 
40
44
  def blacklist_user(author)
41
- bad_users = banned_users
45
+ bad_users = @config.banned_users
42
46
  bad_users.add(author)
43
47
  @config.storage.save_list(bad_users)
44
48
  end
45
49
 
46
50
  def blacklist_url(url)
47
- banned_urls.add(url)
48
- @config.storage.save_list(banned_urls)
51
+ @config.banned_urls.add(url)
52
+ @config.storage.save_list(@config.banned_urls)
49
53
  end
50
54
 
51
55
  def blacklist_urls(urls)
52
56
  urls.each do |url|
53
- banned_urls.add(url)
57
+ @config.banned_urls.add(url)
54
58
  end
55
- @config.storage.save_list(banned_urls)
56
- end
57
-
58
- def blacklist_user_and_urls_added(author,original,new_content)
59
- blacklist_user(author)
60
- new_urls = added_urls(original,new_content)
61
- blacklist_urls(new_urls)
59
+ @config.storage.save_list(@config.banned_urls)
62
60
  end
63
61
 
64
62
  def greylist_new_urls(author,original,new_content)
@@ -68,7 +66,7 @@ module Wiki2Go
68
66
 
69
67
  def greylist_urls(author,new_urls)
70
68
  if new_urls.length > 0 then
71
- list = greylist
69
+ list = @config.greylist
72
70
  new_urls.each do |url|
73
71
  list.add(author,url)
74
72
  end
@@ -77,16 +75,16 @@ module Wiki2Go
77
75
  end
78
76
 
79
77
  def greylisted_url?(url)
80
- greylist.contains_url?(url)
78
+ @config.greylist.contains_url?(url)
81
79
  end
82
80
 
83
81
  def greylist_suspects
84
- greylist.suspects
82
+ @config.greylist.suspects
85
83
  end
86
84
 
87
85
  def remove_from_greylist(author,url)
88
- greylist.remove(author,url)
89
- @config.storage.save_list(greylist)
86
+ @config.greylist.remove(author,url)
87
+ @config.storage.save_list(@config.greylist)
90
88
  end
91
89
 
92
90
  def update_chongqed
@@ -100,28 +98,21 @@ module Wiki2Go
100
98
  end
101
99
  output
102
100
  end
103
-
104
- private
105
-
106
- def banned_users
107
- @banned_users ||= @config.storage.load_blacklist('user')
108
- @banned_users
109
- end
110
-
111
- def banned_urls
112
- @banned_urls ||= @config.storage.load_blacklist('url')
113
- @banned_urls
101
+
102
+ # Verify if a spammer tries to obfuscate his crap by using inline hidden styles
103
+ # content = HTML text to examine
104
+ def hidden_text_in(content)
105
+ content =~ /<(\S[^>]*style\s*=\s*"[^"]*display\s*:\s*none[^>]*)>/i
114
106
  end
115
-
116
- def chonqed_urls
117
- @chonqed_urls ||= @config.storage.load_blacklist('chonqed')
118
- @chonqed_urls
107
+
108
+ # Detect when a non-authenticated user tries to clear a page
109
+ def cleared_page?(content)
110
+ content !~ /\S/
119
111
  end
120
112
 
121
- def greylist
122
- @greylist ||= @config.storage.load_greylist
123
- @greylist
124
- end
113
+ private
114
+
115
+
125
116
 
126
117
  end
127
118
  end
data/lib/Wiki2Go/Web.rb CHANGED
@@ -53,9 +53,11 @@ module Wiki2Go
53
53
  @request.nil? ? 'unknown' : @request.user
54
54
  end
55
55
 
56
- def secure
57
- @request.nil? ? false : @request.authenticated
58
- end
56
+ def secure?
57
+ @request.nil? ? false : @request.authenticated?
58
+ end
59
+
60
+ alias :secure :secure?
59
61
 
60
62
  def alias=(name)
61
63
  @alias = name
@@ -91,6 +93,11 @@ module Wiki2Go
91
93
  File.join(@name,@current_page)
92
94
  end
93
95
  end
96
+
97
+ # The URL of the static error page
98
+ def error_page
99
+ File.join(base_url,'error.html')
100
+ end
94
101
 
95
102
  def Web.page_url(server,port,url,verb,config)
96
103
  before,verb,web,page = Web.parse_url(url,verb,config)