Wiki2Go 1.17.5 → 1.22.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "CgiOptions.rb"
4
+
5
+ require "cgi"
6
+
7
+ require 'Web2Go/CGIRequest'
8
+ require 'Web2Go/CGIResponse'
9
+ require 'Wiki2Go/Wiki2GoServlet'
10
+
11
+ config = CgiOptions.new
12
+
13
+ cgi = CGI.new("html4Tr")
14
+
15
+ request = Web2Go::CGIRequest.new(cgi)
16
+ response = Web2Go::CGIResponse.new(cgi)
17
+
18
+ servlet = Wiki2Go::Servlet.new(config)
19
+ servlet.execute(request,response)
20
+
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "CgiOptions.rb"
4
+
5
+ require "cgi"
6
+
7
+ require 'Web2Go/CGIRequest'
8
+ require 'Web2Go/CGIResponse'
9
+ require 'Wiki2Go/Wiki2GoServlet'
10
+
11
+ config = CgiOptions.new
12
+
13
+ cgi = CGI.new("html4Tr")
14
+
15
+ request = Web2Go::CGIRequest.new(cgi)
16
+ response = Web2Go::CGIResponse.new(cgi)
17
+
18
+ servlet = Wiki2Go::Servlet.new(config)
19
+ servlet.execute(request,response)
20
+
21
+
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "CgiOptions.rb"
4
+
5
+ require "cgi"
6
+
7
+ require 'Web2Go/CGIRequest'
8
+ require 'Web2Go/CGIResponse'
9
+ require 'Wiki2Go/Wiki2GoServlet'
10
+
11
+ config = CgiOptions.new
12
+
13
+ cgi = CGI.new("html4Tr")
14
+
15
+ request = Web2Go::CGIRequest.new(cgi)
16
+ response = Web2Go::CGIResponse.new(cgi)
17
+
18
+ servlet = Wiki2Go::Servlet.new(config)
19
+ servlet.execute(request,response)
20
+
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "CgiOptions.rb"
4
+
5
+ require "cgi"
6
+
7
+ require 'Web2Go/CGIRequest'
8
+ require 'Web2Go/CGIResponse'
9
+ require 'Wiki2Go/Wiki2GoServlet'
10
+
11
+ config = CgiOptions.new
12
+
13
+ cgi = CGI.new("html4Tr")
14
+
15
+ request = Web2Go::CGIRequest.new(cgi)
16
+ response = Web2Go::CGIResponse.new(cgi)
17
+
18
+ servlet = Wiki2Go::Servlet.new(config)
19
+ servlet.execute(request,response)
20
+
@@ -0,0 +1,88 @@
1
+ #
2
+ # To change this template, choose Tools | Templates
3
+ # and open the template in the editor.
4
+
5
+ require 'optparse'
6
+
7
+ require 'Wiki2Go/BlackList.rb'
8
+ require 'Wiki2Go/FileStorage.rb'
9
+
10
+ module Wiki2Go
11
+ class BlacklistConfiguration
12
+ attr_accessor :head
13
+ attr_accessor :tail
14
+ attr_accessor :out
15
+ attr_accessor :directory
16
+
17
+ def initialize
18
+ @directory = File.expand_path(".")
19
+ @out = File.expand_path("./iptables.txt")
20
+ end
21
+ end
22
+
23
+ class FirewallBlacklist
24
+ def initialize(path)
25
+ @storage = Wiki2Go::FileStorage.new(path,path)
26
+ end
27
+
28
+ def FirewallBlacklist.generate(args)
29
+ opts = OptionParser.new
30
+
31
+ configuration = BlacklistConfiguration.new
32
+
33
+ opts.on("-h",'--head file',String) { |val| configuration.head = File.expand_path(val) }
34
+ opts.on("-t",'--tail file',String) { |val| configuration.tail = File.expand_path(val) }
35
+ opts.on("-o",'--out file',String) { |val| configuration.out = File.expand_path(val) }
36
+ opts.on("-d",'--directory dir',"default = .",String) { |val| configuration.directory = File.expand_path(val) }
37
+ opts.on_tail("-h", "--help", "Show this message") do
38
+ puts opts
39
+ exit
40
+ end
41
+ opts.parse(args)
42
+
43
+ list = FirewallBlacklist.new(configuration.directory)
44
+ list.write_file(configuration.head, configuration.tail, configuration.out)
45
+ end
46
+
47
+ # Reads the blacklist for the given wiki
48
+ # Returns an iptables ruleset for blocking all ip addresses in the blacklist
49
+ def generate_blocks
50
+ blacklist = @storage.load_blacklist('user')
51
+ FirewallBlacklist.block_all(blacklist)
52
+ end
53
+ # Given a string ip address
54
+ # Return a string suitable for logging and blocking that address with iptables
55
+ def FirewallBlacklist.block(ip_address)
56
+ ip_address = clean(ip_address)
57
+ "-A INPUT -p tcp --dport 80 --source #{ip_address} -j LOG --log-prefix \"spammer! \" --log-level 7\n-A INPUT -p tcp --dport 80 --source #{ip_address} -j REJECT\n"
58
+ end
59
+
60
+ def FirewallBlacklist.block_all(blacklist)
61
+ out = ""
62
+ blacklist.each do |ip_address|
63
+ out << FirewallBlacklist.block(ip_address)
64
+ end
65
+ out
66
+ end
67
+
68
+ def write_file(head,tail,out)
69
+ header = []
70
+ trailer = []
71
+ File.open(head,'r') {|f| header = f.read }
72
+ File.open(tail,'r') {|f| trailer = f.read }
73
+
74
+ File.open(out,"w") do |f|
75
+ f.write header
76
+ f.write self.generate_blocks
77
+ f.write trailer
78
+ end
79
+
80
+
81
+ end
82
+ private
83
+
84
+ def FirewallBlacklist.clean(ip_address)
85
+ ip_address.gsub(/\\\./,'.')
86
+ end
87
+ end
88
+ end
data/test/All.rb CHANGED
@@ -6,16 +6,19 @@ require 'test/unit/ui/console/testrunner'
6
6
 
7
7
  require 'TestWeb'
8
8
  require 'TestConfig'
9
+ require 'test_page'
9
10
  require 'TestLineFormatter'
10
11
  require 'TestFormatter'
11
12
  require 'TestStorage'
12
13
  require 'TestRSS'
13
14
  require 'TestWiki2Go'
14
- require 'TestBlacklist'
15
+ require 'TestBlackList'
15
16
  require 'TestUrlFinder'
16
17
  require 'TestSpamFilter'
17
18
  require 'TestWeb2Go'
18
19
  require 'TestDot'
19
20
  require 'TestWiki2GoServlet'
20
21
  require 'TestSyntaxHighlighter'
21
-
22
+ require 'TestHTMLFormatter'
23
+ require 'test_firewall_blacklist.rb'
24
+ #require 'TestInstall'
@@ -12,7 +12,7 @@ require 'UnitTestFiles'
12
12
 
13
13
  class TestBlackList < Test::Unit::TestCase
14
14
 
15
- include UnitTestFiles
15
+ include UnitTestFiles
16
16
 
17
17
  def setup
18
18
  @storage = Wiki2Go::FileStorage.new(scratchdata,scratchdata('html'))
@@ -29,13 +29,26 @@ include UnitTestFiles
29
29
  assert(!blacklist.contains('155.66.00.1'))
30
30
  end
31
31
 
32
+ def test_collection
33
+ blacklist = Wiki2Go::BlackList.new("user_blacklist.txt",[])
34
+ blacklist.add('1.2.3.4')
35
+ blacklist.add('5.6.7.8')
36
+ blacklist.add('0.0.0.0')
37
+
38
+ assert_equal ['0\.0\.0\.0','1\.2\.3\.4','5\.6\.7\.8'],blacklist.all
39
+
40
+ out = ""
41
+ blacklist.each {|pattern| out << pattern; out << ','}
42
+ assert_equal '0\.0\.0\.0,1\.2\.3\.4,5\.6\.7\.8,',out
43
+ end
44
+
32
45
  def test_find_patterns_in_text
33
46
  text = ["Some ok text", 'a bad url http://buy.viagra.com must be found' , 'some more innocent text']
34
47
  bad_urls = Wiki2Go::BlackList.new("url_blacklist.txt",['viagra\.'])
35
48
 
36
49
  assert(bad_urls.found_in(text))
37
50
  end
38
-
51
+
39
52
  def test_dont_find_patterns_in_ok_text
40
53
  text = "Some ok text\ndon''t care if viagra is mentioned\nsome more innocent text"
41
54
  bad_urls = Wiki2Go::BlackList.new("url_blacklist.txt",['viagra\.'])
@@ -59,24 +72,67 @@ include UnitTestFiles
59
72
  def test_greylist
60
73
  list = Wiki2Go::GreyList.new('.',[])
61
74
  assert !list.contains_user?('pvc')
62
-
75
+
63
76
  list.add('pvc','http://www.xp.be')
64
77
  assert list.contains_user?('pvc')
65
78
  assert list.url_found_in("this is a link to {xpbe@http://www.xp.be/FrontPage} ")
66
-
79
+
67
80
  assert !list.contains_user?('vera')
68
81
  assert !list.url_found_in("this is a link to {xpbe@www.xp.be/FrontPage} ")
69
-
82
+
70
83
  end
71
-
72
-
84
+
85
+
73
86
  def test_only_keep_hostnames
74
- bad_urls = Wiki2Go::BlackList.new("url_blacklist.txt",[])
75
- bad_urls.add("http://www.somehost.com/selling_useless_stuff")
76
- bad_urls.add("http://www.somehost.com/selling_illegal_stuff")
77
- bad_urls.add("http://www.somehost.com:80/selling_illegal_stuff")
78
-
79
- assert_equal 1,bad_urls.length
87
+ bad_urls = Wiki2Go::BlackList.new("url_blacklist.txt",[])
88
+ bad_urls.add("http://www.somehost.com/selling_useless_stuff")
89
+ bad_urls.add("http://www.somehost.com/selling_illegal_stuff")
90
+ bad_urls.add("http://www.somehost.com:80/selling_illegal_stuff")
91
+ bad_urls.add("http://wiki.somehost.com:80/selling_illegal_stuff")
92
+ bad_urls.add("http://somehost.com/selling_illegal_stuff")
93
+
94
+ assert_equal 1,bad_urls.length
95
+ assert_equal 'https?:\/\/([^\/]*\.)?somehost\.com',bad_urls.all[0]
96
+ end
97
+
98
+ def test_only_keep_3part_hostnames
99
+ bad_urls = Wiki2Go::BlackList.new("url_blacklist.txt",[])
100
+ bad_urls.add("http://www.somehost.co.uk/selling_useless_stuff")
101
+ bad_urls.add("http://www.somehost.co.uk/selling_illegal_stuff")
102
+ bad_urls.add("http://www.somehost.co.uk:80/selling_illegal_stuff")
103
+ bad_urls.add("http://wiki.somehost.co.uk:80/selling_illegal_stuff")
104
+ bad_urls.add("http://somehost.co.uk/selling_illegal_stuff")
105
+
106
+ assert_equal 1,bad_urls.length
107
+ assert_equal 'https?:\/\/([^\/]*\.)?somehost\.co\.uk',bad_urls.all[0]
80
108
  end
81
109
 
82
- end
110
+ def test_read_chongqed_format_blacklist
111
+ bad_urls = Wiki2Go::BlackList.new("url_blacklist.txt",['https?:\/\/([^\/]*\.)?discount-phentermine\.health-livening\.com','https?:\/\/([^\/]*\.)?discounted-phentermine\.health-livening\.com'],true)
112
+
113
+ assert_equal 1,bad_urls.length
114
+ assert_equal 'https?:\/\/([^\/]*\.)?health-livening\.com',bad_urls.all[0]
115
+ end
116
+
117
+ def test_read_chongqed_blacklist
118
+ dir = File.expand_path(File.join(File.dirname(__FILE__),'..','lib','Wiki2Go','Install'))
119
+ @storage = Wiki2Go::FileStorage.new(dir,dir)
120
+ chongqed = @storage.load_blacklist('chonqed')
121
+
122
+ assert_equal 6680,chongqed.length
123
+
124
+ end
125
+
126
+ def test_read_url_blacklist
127
+ dir = File.expand_path(File.join(File.dirname(__FILE__),'..','lib','Wiki2Go','Install'))
128
+ @storage = Wiki2Go::FileStorage.new(dir,dir)
129
+ urls = @storage.load_blacklist('url',true)
130
+
131
+ @storage.save_list(urls)
132
+
133
+ saved_urls = @storage.load_blacklist('url',true)
134
+
135
+ assert_equal urls.length,saved_urls.length
136
+
137
+ end
138
+ end
data/test/TestConfig.rb CHANGED
@@ -26,7 +26,7 @@ module TestConfig_local
26
26
  @blacklist['chonqed'] = Wiki2Go::BlackList.new(scratchdata('chonqed_blacklist.txt'),[])
27
27
  end
28
28
 
29
- def load_blacklist(type)
29
+ def load_blacklist(type,normalize_urls=false)
30
30
  @blacklist[type]
31
31
  end
32
32
 
@@ -35,7 +35,7 @@ module TestConfig_local
35
35
  end
36
36
  end
37
37
 
38
- class MockPublicConfig < PublicWikiConfig
38
+ class MockPublicConfig < Wiki2Go::PublicWikiConfig
39
39
 
40
40
  attr_accessor :tarpitted
41
41
 
@@ -114,7 +114,7 @@ class TestConfig < Test::Unit::TestCase
114
114
  web = Wiki2Go::Web.from_request(Web2Go::MockRequest.new('http://localhost/view/Wiki2Go/FrontPage',{ 'REMOTE_USER' => 'evilguy'} ),@config)
115
115
  @config.storage.blacklist('user','evilguy')
116
116
  assert !@config.accept_page?(web,spam_page)
117
- assert @config.tarpitted
117
+ assert !@config.tarpitted
118
118
  end
119
119
 
120
120
  def check_logged_method(config, log_method, log_string, should_match)
@@ -124,9 +124,9 @@ class TestConfig < Test::Unit::TestCase
124
124
  lines = f.readlines
125
125
  last_line = lines.pop.strip
126
126
  if should_match then
127
- assert_match Regexp.new(Regexp.quote(unique_log_string)),last_line
127
+ assert_match Regexp.new(Regexp.escape(unique_log_string)),last_line
128
128
  else
129
- assert_no_match Regexp.new(Regexp.quote(unique_log_string)),last_line
129
+ assert_no_match Regexp.new(Regexp.escape(unique_log_string)),last_line
130
130
  end
131
131
  end
132
132
  end
data/test/TestDiff.rb ADDED
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: ISO-8859-1 -*-
3
+
4
+
5
+ require 'diff/lcs'
6
+ require 'test/unit'
7
+
8
+ class TestXXX < Test::Unit::TestCase
9
+
10
+ UNKNOWN = 0
11
+ KEEPING = 1
12
+ EDITING = 2
13
+
14
+ def setup
15
+ @mode = UNKNOWN
16
+ @buffer = ''
17
+ @keeping = ''
18
+ @discarding = ''
19
+ @adding = ''
20
+ end
21
+
22
+ def teardown
23
+ end
24
+
25
+ def xtest_xxx
26
+
27
+ seq1 = %w(a b c e h j l m n p)
28
+ seq2 = %w(b c d e f j k l m r s t)
29
+
30
+ lcs = Diff::LCS.LCS(seq1, seq2)
31
+ puts lcs.inspect
32
+ puts "==="
33
+ diffs = Diff::LCS.diff(seq1, seq2,nil) # { |input| puts input.inspect }
34
+ puts "---"
35
+ puts diffs.inspect
36
+ puts "==="
37
+ sdiff = Diff::LCS.sdiff(seq1, seq2,nil) # { |input| puts input.inspect }
38
+ puts "---"
39
+ puts sdiff.inspect
40
+ puts "==="
41
+ end
42
+
43
+ def test_lcs
44
+ lcs = Diff::LCS.LCS("I added this!","I edited this")
45
+ puts lcs.inspect
46
+
47
+ diff = Diff::LCS.diff("I added this!","I edited this")
48
+ puts diff.inspect
49
+ end
50
+
51
+ def test_string
52
+
53
+ diffs = Diff::LCS.sdiff("I added this!","I edited this",nil) do |change|
54
+ case change.action
55
+ when '='
56
+ keep change.new_element
57
+ when '-'
58
+ discard change.old_element
59
+ when '+'
60
+ add change.new_element
61
+ when '!'
62
+ discard change.old_element
63
+ add change.new_element
64
+ end
65
+ done
66
+ end
67
+ puts @buffer
68
+ end
69
+
70
+ def keep(element)
71
+ done if @mode != KEEPING
72
+ @mode = KEEPING
73
+ @keeping += element
74
+ end
75
+
76
+ def add(element)
77
+ done if @mode = EDITING
78
+ @mode = EDITING
79
+ @adding += element
80
+ end
81
+ def discard(element)
82
+ done if @mode = EDITING
83
+ @mode = EDITING
84
+ @discarding += element
85
+ end
86
+
87
+ def done
88
+ @buffer += @keeping
89
+ @buffer += "<del>#{@discarding}</del>" if @discarding.length > 0
90
+ @buffer += "<add>#{@adding}</add>" if @adding.length > 0
91
+ @keeping = ''
92
+ @discarding = ''
93
+ @adding = ''
94
+ end
95
+ end