sup 1.0 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/checks.yml +70 -0
- data/.rubocop.yml +5 -0
- data/CONTRIBUTORS +3 -2
- data/Gemfile +5 -1
- data/History.txt +20 -0
- data/Manifest.txt +149 -0
- data/README.md +9 -3
- data/Rakefile +40 -1
- data/bin/sup-add +4 -8
- data/ext/mkrf_conf_xapian.rb +10 -4
- data/lib/sup/colormap.rb +1 -1
- data/lib/sup/hook.rb +1 -1
- data/lib/sup/index.rb +2 -2
- data/lib/sup/keymap.rb +1 -1
- data/lib/sup/maildir.rb +4 -4
- data/lib/sup/mbox.rb +4 -4
- data/lib/sup/message.rb +6 -5
- data/lib/sup/message_chunks.rb +27 -19
- data/lib/sup/modes/completion_mode.rb +0 -1
- data/lib/sup/modes/file_browser_mode.rb +2 -2
- data/lib/sup/modes/label_list_mode.rb +1 -1
- data/lib/sup/modes/search_list_mode.rb +2 -2
- data/lib/sup/modes/thread_view_mode.rb +1 -2
- data/lib/sup/rfc2047.rb +21 -6
- data/lib/sup/source.rb +8 -2
- data/lib/sup/textfield.rb +0 -1
- data/lib/sup/thread.rb +0 -1
- data/lib/sup/util.rb +28 -48
- data/lib/sup/version.rb +1 -1
- data/lib/sup.rb +12 -8
- data/man/sup-add.1 +15 -15
- data/man/sup-config.1 +11 -11
- data/man/sup-dump.1 +9 -9
- data/man/sup-import-dump.1 +15 -15
- data/man/sup-psych-ify-config-files.1 +9 -9
- data/man/sup-recover-sources.1 +12 -12
- data/man/sup-sync-back-maildir.1 +14 -14
- data/man/sup-sync.1 +20 -20
- data/man/sup-tweak-labels.1 +16 -16
- data/man/sup.1 +21 -21
- data/sup.gemspec +6 -4
- data/test/dummy_source.rb +21 -15
- data/test/fixtures/embedded-message.eml +34 -0
- data/test/fixtures/non-ascii-header-in-nested-message.eml +36 -0
- data/test/fixtures/non-ascii-header.eml +8 -0
- data/test/fixtures/rfc2047-header-encoding.eml +15 -0
- data/test/fixtures/text-attachments-with-charset.eml +15 -1
- data/test/fixtures/utf8-header.eml +17 -0
- data/test/integration/test_mbox.rb +1 -1
- data/test/integration/test_sup-add.rb +83 -0
- data/test/test_crypto.rb +44 -0
- data/test/test_header_parsing.rb +9 -1
- data/test/test_helper.rb +7 -4
- data/test/test_message.rb +124 -32
- data/test/test_messages_dir.rb +13 -15
- data/test/unit/test_horizontal_selector.rb +4 -4
- data/test/unit/test_locale_fiddler.rb +1 -1
- data/test/unit/util/test_query.rb +1 -1
- data/test/unit/util/test_string.rb +3 -3
- data/test/unit/util/test_uri.rb +2 -2
- metadata +46 -18
- data/.travis.yml +0 -18
- data/bin/sup-psych-ify-config-files +0 -21
- data/test/integration/test_label_service.rb +0 -18
- data/test/test_yaml_migration.rb +0 -85
@@ -0,0 +1,83 @@
|
|
1
|
+
class TestSupAdd < Minitest::Test
|
2
|
+
|
3
|
+
def setup
|
4
|
+
@path = Dir.mktmpdir
|
5
|
+
end
|
6
|
+
|
7
|
+
def teardown
|
8
|
+
FileUtils.rm_r @path
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_can_add_maildir_source
|
12
|
+
_out, _err = capture_subprocess_io do
|
13
|
+
assert system({"SUP_BASE" => @path}, "bin/sup-add", "maildir:///some/path")
|
14
|
+
end
|
15
|
+
|
16
|
+
generated_sources_yaml = File.read "#{@path}/sources.yaml"
|
17
|
+
assert_equal <<EOS, generated_sources_yaml
|
18
|
+
---
|
19
|
+
- !<tag:supmua.org,2006-10-01/Redwood/Maildir>
|
20
|
+
uri: maildir:///some/path
|
21
|
+
usual: true
|
22
|
+
archived: false
|
23
|
+
sync_back: true
|
24
|
+
id: 1
|
25
|
+
labels: []
|
26
|
+
EOS
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_fixes_old_tag_uri_syntax
|
30
|
+
File.write "#{@path}/sources.yaml", <<EOS
|
31
|
+
---
|
32
|
+
- !supmua.org,2006-10-01/Redwood/Maildir
|
33
|
+
uri: maildir:/some/path
|
34
|
+
usual: true
|
35
|
+
archived: false
|
36
|
+
sync_back: true
|
37
|
+
id: 1
|
38
|
+
labels: []
|
39
|
+
EOS
|
40
|
+
_out, _err = capture_subprocess_io do
|
41
|
+
assert system({"SUP_BASE" => @path}, "bin/sup-add", "maildir:///other/path")
|
42
|
+
end
|
43
|
+
|
44
|
+
generated_sources_yaml = File.read "#{@path}/sources.yaml"
|
45
|
+
assert_equal <<EOS, generated_sources_yaml
|
46
|
+
---
|
47
|
+
- !<tag:supmua.org,2006-10-01/Redwood/Maildir>
|
48
|
+
uri: maildir:/some/path
|
49
|
+
usual: true
|
50
|
+
archived: false
|
51
|
+
sync_back: true
|
52
|
+
id: 1
|
53
|
+
labels: []
|
54
|
+
- !<tag:supmua.org,2006-10-01/Redwood/Maildir>
|
55
|
+
uri: maildir:///other/path
|
56
|
+
usual: true
|
57
|
+
archived: false
|
58
|
+
sync_back: true
|
59
|
+
id: 2
|
60
|
+
labels: []
|
61
|
+
EOS
|
62
|
+
end
|
63
|
+
|
64
|
+
## https://github.com/sup-heliotrope/sup/issues/545
|
65
|
+
def test_source_with_invalid_uri_chars_in_path
|
66
|
+
_out, _err = capture_subprocess_io do
|
67
|
+
assert system({"SUP_BASE" => @path}, "bin/sup-add", "maildir:~/.mail/gmail/[Gmail]/.All Mail/")
|
68
|
+
end
|
69
|
+
|
70
|
+
generated_sources_yaml = File.read "#{@path}/sources.yaml"
|
71
|
+
assert_equal <<EOS, generated_sources_yaml
|
72
|
+
---
|
73
|
+
- !<tag:supmua.org,2006-10-01/Redwood/Maildir>
|
74
|
+
uri: maildir:~/.mail/gmail/[Gmail]/.All Mail/
|
75
|
+
usual: true
|
76
|
+
archived: false
|
77
|
+
sync_back: true
|
78
|
+
id: 1
|
79
|
+
labels: []
|
80
|
+
EOS
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
data/test/test_crypto.rb
CHANGED
@@ -69,6 +69,24 @@ class TestCryptoManager < Minitest::Test
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
+
def test_sign_nested_parts
|
73
|
+
if CryptoManager.have_crypto? then
|
74
|
+
body = RMail::Message.new
|
75
|
+
body.header["Content-Disposition"] = "inline"
|
76
|
+
body.body = "ABCDEFG"
|
77
|
+
payload = RMail::Message.new
|
78
|
+
payload.header["MIME-Version"] = "1.0"
|
79
|
+
payload.add_part body
|
80
|
+
payload.add_part RMail::Message.make_attachment "attachment", "text/plain", nil, "attachment.txt"
|
81
|
+
signed = CryptoManager.sign @from_email, @to_email, payload
|
82
|
+
## The result is a multipart/signed containing a multipart/mixed.
|
83
|
+
## There should be a MIME-Version header on the top-level
|
84
|
+
## multipart/signed message, but *not* on the enclosed
|
85
|
+
## multipart/mixed part.
|
86
|
+
assert_equal 1, signed.to_s.scan(/MIME-Version:/).size
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
72
90
|
def test_encrypt
|
73
91
|
if CryptoManager.have_crypto? then
|
74
92
|
encrypted = CryptoManager.encrypt @from_email, [@to_email], "ABCDEFG"
|
@@ -116,6 +134,32 @@ class TestCryptoManager < Minitest::Test
|
|
116
134
|
CryptoManager.verify signed.body[0], signed.body[1], true
|
117
135
|
end
|
118
136
|
end
|
137
|
+
|
138
|
+
def test_verify_nested_parts
|
139
|
+
if CryptoManager.have_crypto?
|
140
|
+
## Generate a multipart/signed containing a multipart/mixed.
|
141
|
+
## We will test verifying the generated signature below.
|
142
|
+
## Importantly, the inner multipart/mixed does *not* have a
|
143
|
+
## MIME-Version header because it is not a top-level message.
|
144
|
+
payload = RMail::Parser.read <<EOS
|
145
|
+
Content-Type: multipart/mixed; boundary="=-1652088224-7794-561531-1825-1-="
|
146
|
+
|
147
|
+
|
148
|
+
--=-1652088224-7794-561531-1825-1-=
|
149
|
+
Content-Disposition: inline
|
150
|
+
|
151
|
+
ABCDEFG
|
152
|
+
--=-1652088224-7794-561531-1825-1-=
|
153
|
+
Content-Disposition: attachment; filename="attachment.txt"
|
154
|
+
Content-Type: text/plain; name="attachment.txt"
|
155
|
+
|
156
|
+
attachment
|
157
|
+
--=-1652088224-7794-561531-1825-1-=--
|
158
|
+
EOS
|
159
|
+
signed = CryptoManager.sign @from_email_ecc, @to_email, payload
|
160
|
+
CryptoManager.verify payload, signed.body[1], true
|
161
|
+
end
|
162
|
+
end
|
119
163
|
end
|
120
164
|
|
121
165
|
end
|
data/test/test_header_parsing.rb
CHANGED
@@ -11,9 +11,15 @@ class TestMBoxParsing < Minitest::Test
|
|
11
11
|
def setup
|
12
12
|
@path = Dir.mktmpdir
|
13
13
|
@mbox = File.join(@path, 'test_mbox')
|
14
|
+
@log = StringIO.new
|
15
|
+
Redwood::Logger.add_sink @log
|
16
|
+
Redwood::Logger.remove_sink $stderr
|
14
17
|
end
|
15
18
|
|
16
19
|
def teardown
|
20
|
+
Redwood::Logger.clear!
|
21
|
+
Redwood::Logger.remove_sink @log
|
22
|
+
Redwood::Logger.add_sink $stderr
|
17
23
|
FileUtils.rm_r @path
|
18
24
|
end
|
19
25
|
|
@@ -69,7 +75,7 @@ EOS
|
|
69
75
|
|
70
76
|
def test_blank_lines
|
71
77
|
h = Source.parse_raw_email_header StringIO.new("")
|
72
|
-
|
78
|
+
assert_nil h["message-id"]
|
73
79
|
end
|
74
80
|
|
75
81
|
def test_empty_headers
|
@@ -133,6 +139,8 @@ EOS
|
|
133
139
|
assert_equal 61, offset
|
134
140
|
offset = l.next_offset 61
|
135
141
|
assert_nil offset
|
142
|
+
assert_match(/WARNING: found invalid date in potential mbox split line, not splitting/,
|
143
|
+
@log.string)
|
136
144
|
end
|
137
145
|
|
138
146
|
def test_more_from_line_splitting
|
data/test/test_helper.rb
CHANGED
@@ -2,9 +2,12 @@ require "rubygems" rescue nil
|
|
2
2
|
require 'minitest/autorun'
|
3
3
|
require "rr"
|
4
4
|
|
5
|
-
def
|
5
|
+
def fixture_path(filename)
|
6
|
+
File.expand_path("../fixtures/#{filename}", __FILE__)
|
7
|
+
end
|
8
|
+
|
9
|
+
def fixture_contents(filename)
|
6
10
|
file = ''
|
7
|
-
|
8
|
-
File.open(path) { |io| file = io.read }
|
11
|
+
File.open(fixture_path(filename)) { |io| file = io.read }
|
9
12
|
file
|
10
|
-
end
|
13
|
+
end
|
data/test/test_message.rb
CHANGED
@@ -21,10 +21,8 @@ class TestMessage < Minitest::Test
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def test_simple_message
|
24
|
-
message = fixture('simple-message.eml')
|
25
|
-
|
26
24
|
source = DummySource.new("sup-test://test_simple_message")
|
27
|
-
source.messages = [ message ]
|
25
|
+
source.messages = [ fixture_path('simple-message.eml') ]
|
28
26
|
source_info = 0
|
29
27
|
|
30
28
|
sup_message = Message.build_from_source(source, source_info)
|
@@ -99,10 +97,8 @@ class TestMessage < Minitest::Test
|
|
99
97
|
end
|
100
98
|
|
101
99
|
def test_multipart_message
|
102
|
-
message = fixture('multi-part.eml')
|
103
|
-
|
104
100
|
source = DummySource.new("sup-test://test_multipart_message")
|
105
|
-
source.messages = [
|
101
|
+
source.messages = [ fixture_path('multi-part.eml') ]
|
106
102
|
source_info = 0
|
107
103
|
|
108
104
|
sup_message = Message.build_from_source(source, source_info)
|
@@ -126,10 +122,8 @@ class TestMessage < Minitest::Test
|
|
126
122
|
end
|
127
123
|
|
128
124
|
def test_broken_message_1
|
129
|
-
message = fixture('missing-from-to.eml')
|
130
|
-
|
131
125
|
source = DummySource.new("sup-test://test_broken_message_1")
|
132
|
-
source.messages = [
|
126
|
+
source.messages = [ fixture_path('missing-from-to.eml') ]
|
133
127
|
source_info = 0
|
134
128
|
|
135
129
|
sup_message = Message.build_from_source(source, source_info)
|
@@ -150,10 +144,8 @@ class TestMessage < Minitest::Test
|
|
150
144
|
end
|
151
145
|
|
152
146
|
def test_broken_message_2
|
153
|
-
message = fixture('no-body.eml')
|
154
|
-
|
155
147
|
source = DummySource.new("sup-test://test_broken_message_1")
|
156
|
-
source.messages = [
|
148
|
+
source.messages = [ fixture_path('no-body.eml') ]
|
157
149
|
source_info = 0
|
158
150
|
|
159
151
|
sup_message = Message.build_from_source(source, source_info)
|
@@ -167,10 +159,8 @@ class TestMessage < Minitest::Test
|
|
167
159
|
end
|
168
160
|
|
169
161
|
def test_multipart_message_2
|
170
|
-
message = fixture('multi-part-2.eml')
|
171
|
-
|
172
162
|
source = DummySource.new("sup-test://test_multipart_message_2")
|
173
|
-
source.messages = [
|
163
|
+
source.messages = [ fixture_path('multi-part-2.eml') ]
|
174
164
|
source_info = 0
|
175
165
|
|
176
166
|
sup_message = Message.build_from_source(source, source_info)
|
@@ -178,21 +168,20 @@ class TestMessage < Minitest::Test
|
|
178
168
|
|
179
169
|
chunks = sup_message.load_from_source! # read the message body chunks
|
180
170
|
|
181
|
-
|
171
|
+
assert_equal(1, chunks.length)
|
172
|
+
assert(chunks[0].is_a? Redwood::Chunk::Attachment)
|
182
173
|
end
|
183
174
|
|
184
175
|
def test_text_attachment_decoding
|
185
|
-
message = fixture('text-attachments-with-charset.eml')
|
186
|
-
|
187
176
|
source = DummySource.new("sup-test://test_text_attachment_decoding")
|
188
|
-
source.messages = [
|
177
|
+
source.messages = [ fixture_path('text-attachments-with-charset.eml') ]
|
189
178
|
source_info = 0
|
190
179
|
|
191
180
|
sup_message = Message.build_from_source(source, source_info)
|
192
181
|
sup_message.load_from_source!
|
193
182
|
|
194
183
|
chunks = sup_message.load_from_source!
|
195
|
-
assert_equal(
|
184
|
+
assert_equal(7, chunks.length)
|
196
185
|
assert(chunks[0].is_a? Redwood::Chunk::Text)
|
197
186
|
## The first attachment declares charset=us-ascii
|
198
187
|
assert(chunks[1].is_a? Redwood::Chunk::Attachment)
|
@@ -207,13 +196,18 @@ class TestMessage < Minitest::Test
|
|
207
196
|
## which will be replaced with U+FFFD REPLACEMENT CHARACTER
|
208
197
|
assert(chunks[4].is_a? Redwood::Chunk::Attachment)
|
209
198
|
assert_equal(["Embedded\ufffdgarbage"], chunks[4].lines)
|
199
|
+
## The fifth attachment has an invalid charset, which should still
|
200
|
+
## be handled gracefully
|
201
|
+
assert(chunks[5].is_a? Redwood::Chunk::Attachment)
|
202
|
+
assert_equal(["Example invalid charset"], chunks[5].lines)
|
203
|
+
## The sixth attachment is UTF-7 encoded
|
204
|
+
assert(chunks[6].is_a? Redwood::Chunk::Attachment)
|
205
|
+
assert_equal(["This is ✨UTF-7✨"], chunks[6].lines)
|
210
206
|
end
|
211
207
|
|
212
208
|
def test_mailing_list_header
|
213
|
-
message = fixture('mailing-list-header.eml')
|
214
|
-
|
215
209
|
source = DummySource.new("sup-test://test_mailing_list_header")
|
216
|
-
source.messages = [
|
210
|
+
source.messages = [ fixture_path('mailing-list-header.eml') ]
|
217
211
|
source_info = 0
|
218
212
|
|
219
213
|
sup_message = Message.build_from_source(source, source_info)
|
@@ -227,10 +221,8 @@ class TestMessage < Minitest::Test
|
|
227
221
|
end
|
228
222
|
|
229
223
|
def test_blank_header_lines
|
230
|
-
message = fixture('blank-header-fields.eml')
|
231
|
-
|
232
224
|
source = DummySource.new("sup-test://test_blank_header_lines")
|
233
|
-
source.messages = [
|
225
|
+
source.messages = [ fixture_path('blank-header-fields.eml') ]
|
234
226
|
source_info = 0
|
235
227
|
|
236
228
|
sup_message = Message.build_from_source(source, source_info)
|
@@ -248,11 +240,113 @@ class TestMessage < Minitest::Test
|
|
248
240
|
|
249
241
|
end
|
250
242
|
|
251
|
-
def
|
252
|
-
|
243
|
+
def test_rfc2047_header_encoding
|
244
|
+
source = DummySource.new("sup-test://test_rfc2047_header_encoding")
|
245
|
+
source.messages = [ fixture_path("rfc2047-header-encoding.eml") ]
|
246
|
+
source_info = 0
|
247
|
+
|
248
|
+
sup_message = Message.build_from_source(source, source_info)
|
249
|
+
sup_message.load_from_source!
|
250
|
+
|
251
|
+
assert_equal("Hans Martin Djupvik, Ingrid Bø, Ирина Сидорова, " +
|
252
|
+
"Jesper Berg, Frida Engø " +
|
253
|
+
"bad: =?UTF16?q?badcharsetname?==?US-ASCII?b?/w?=" +
|
254
|
+
"=?UTF-7?Q?=41=6D=65=72=69=63=61=E2=80=99=73?=",
|
255
|
+
sup_message.subj)
|
256
|
+
end
|
257
|
+
|
258
|
+
def test_nonascii_header
|
259
|
+
## Spammers sometimes send invalid high bytes in the headers.
|
260
|
+
## They will be replaced with U+FFFD REPLACEMENT CHARACTER.
|
261
|
+
source = DummySource.new("sup-test://test_nonascii_header")
|
262
|
+
source.messages = [ fixture_path("non-ascii-header.eml") ]
|
263
|
+
source_info = 0
|
264
|
+
|
265
|
+
sup_message = Message.build_from_source(source, source_info)
|
266
|
+
sup_message.load_from_source!
|
267
|
+
|
268
|
+
assert_equal("SPAM \ufffd", sup_message.from.name)
|
269
|
+
assert_equal("spammer@example.com", sup_message.from.email)
|
270
|
+
assert_equal("spam \ufffd spam", sup_message.subj)
|
271
|
+
end
|
272
|
+
|
273
|
+
def test_utf8_header
|
274
|
+
## UTF-8 is allowed in header values according to RFC6532.
|
275
|
+
source = DummySource.new("sup-test://test_utf8_header")
|
276
|
+
source.messages = [ fixture_path("utf8-header.eml") ]
|
277
|
+
source_info = 0
|
278
|
+
|
279
|
+
sup_message = Message.build_from_source(source, source_info)
|
280
|
+
sup_message.load_from_source!
|
281
|
+
|
282
|
+
assert_equal(Encoding::UTF_8, sup_message.subj.encoding)
|
283
|
+
assert_equal("LibraryThing: State of the Thing — January", sup_message.subj)
|
284
|
+
end
|
285
|
+
|
286
|
+
def test_nonascii_header_in_nested_message
|
287
|
+
source = DummySource.new("sup-test://test_nonascii_header_in_nested_message")
|
288
|
+
source.messages = [ fixture_path("non-ascii-header-in-nested-message.eml") ]
|
289
|
+
source_info = 0
|
290
|
+
|
291
|
+
sup_message = Message.build_from_source(source, source_info)
|
292
|
+
chunks = sup_message.load_from_source!
|
293
|
+
|
294
|
+
assert_equal(3, chunks.length)
|
253
295
|
|
296
|
+
assert(chunks[0].is_a? Redwood::Chunk::Text)
|
297
|
+
|
298
|
+
assert(chunks[1].is_a? Redwood::Chunk::EnclosedMessage)
|
299
|
+
assert_equal(4, chunks[1].lines.length)
|
300
|
+
assert_equal("From: SPAM \ufffd <spammer@example.com>", chunks[1].lines[0])
|
301
|
+
assert_equal("To: enclosed <enclosed@example.invalid>", chunks[1].lines[1])
|
302
|
+
assert_equal("Subject: spam \ufffd spam", chunks[1].lines[3])
|
303
|
+
|
304
|
+
assert(chunks[2].is_a? Redwood::Chunk::Text)
|
305
|
+
assert_equal(1, chunks[2].lines.length)
|
306
|
+
assert_equal("This is a spam.", chunks[2].lines[0])
|
307
|
+
end
|
308
|
+
|
309
|
+
def test_embedded_message
|
310
|
+
source = DummySource.new("sup-test://test_embedded_message")
|
311
|
+
source.messages = [ fixture_path("embedded-message.eml") ]
|
312
|
+
source_info = 0
|
313
|
+
|
314
|
+
sup_message = Message.build_from_source(source, source_info)
|
315
|
+
|
316
|
+
chunks = sup_message.load_from_source!
|
317
|
+
assert_equal(3, chunks.length)
|
318
|
+
|
319
|
+
assert_equal("sender@example.com", sup_message.from.email)
|
320
|
+
assert_equal("Sender", sup_message.from.name)
|
321
|
+
assert_equal(1, sup_message.to.length)
|
322
|
+
assert_equal("recipient@example.invalid", sup_message.to[0].email)
|
323
|
+
assert_equal("recipient", sup_message.to[0].name)
|
324
|
+
assert_equal("Email with embedded message", sup_message.subj)
|
325
|
+
|
326
|
+
assert(chunks[0].is_a? Redwood::Chunk::Text)
|
327
|
+
assert_equal("Example outer message.", chunks[0].lines[0])
|
328
|
+
assert_equal("Example second line.", chunks[0].lines[1])
|
329
|
+
|
330
|
+
assert(chunks[1].is_a? Redwood::Chunk::EnclosedMessage)
|
331
|
+
assert_equal(4, chunks[1].lines.length)
|
332
|
+
assert_equal("From: Embed sender <embed@example.com>", chunks[1].lines[0])
|
333
|
+
assert_equal("To: rcpt2 <rcpt2@example.invalid>", chunks[1].lines[1])
|
334
|
+
assert_equal("Date: ", chunks[1].lines[2][0..5])
|
335
|
+
assert_equal(
|
336
|
+
Time.rfc2822("Wed, 15 Jul 2020 12:34:56 +0000"),
|
337
|
+
Time.rfc2822(chunks[1].lines[2][6..-1])
|
338
|
+
)
|
339
|
+
assert_equal("Subject: Embedded subject line", chunks[1].lines[3])
|
340
|
+
|
341
|
+
assert(chunks[2].is_a? Redwood::Chunk::Text)
|
342
|
+
assert_equal(2, chunks[2].lines.length)
|
343
|
+
assert_equal("Example embedded message.", chunks[2].lines[0])
|
344
|
+
assert_equal("Second line.", chunks[2].lines[1])
|
345
|
+
end
|
346
|
+
|
347
|
+
def test_malicious_attachment_names
|
254
348
|
source = DummySource.new("sup-test://test_blank_header_lines")
|
255
|
-
source.messages = [
|
349
|
+
source.messages = [ fixture_path('malicious-attachment-names.eml') ]
|
256
350
|
source_info = 0
|
257
351
|
|
258
352
|
sup_message = Message.build_from_source(source, source_info)
|
@@ -276,10 +370,8 @@ class TestMessage < Minitest::Test
|
|
276
370
|
# tries to do the right thing and reply after the quote.
|
277
371
|
# In this case we want to just look at the > markers when determining where
|
278
372
|
# the quoted chunk ends.
|
279
|
-
message = fixture('zimbra-quote-with-bottom-post.eml')
|
280
|
-
|
281
373
|
source = DummySource.new("sup-test://test_zimbra_quote_with_bottom_post")
|
282
|
-
source.messages = [
|
374
|
+
source.messages = [ fixture_path('zimbra-quote-with-bottom-post.eml') ]
|
283
375
|
source_info = 0
|
284
376
|
|
285
377
|
sup_message = Message.build_from_source(source, source_info)
|
data/test/test_messages_dir.rb
CHANGED
@@ -13,19 +13,22 @@ class TestMessagesDir < ::Minitest::Test
|
|
13
13
|
def setup
|
14
14
|
@path = Dir.mktmpdir
|
15
15
|
Redwood::HookManager.init File.join(@path, 'hooks')
|
16
|
+
@log = StringIO.new
|
17
|
+
Redwood::Logger.add_sink @log
|
18
|
+
Redwood::Logger.remove_sink $stderr
|
16
19
|
end
|
17
20
|
|
18
21
|
def teardown
|
22
|
+
Redwood::Logger.clear!
|
23
|
+
Redwood::Logger.remove_sink @log
|
24
|
+
Redwood::Logger.add_sink $stderr
|
19
25
|
Redwood::HookManager.deinstantiate!
|
20
26
|
FileUtils.rm_r @path
|
21
27
|
end
|
22
28
|
|
23
29
|
def test_binary_content_transfer_encoding
|
24
|
-
message = ''
|
25
|
-
File.open('test/fixtures/binary-content-transfer-encoding-2.eml') { |f| message = f.read }
|
26
|
-
|
27
30
|
source = DummySource.new("sup-test://test_messages")
|
28
|
-
source.messages = [
|
31
|
+
source.messages = [ fixture_path('binary-content-transfer-encoding-2.eml') ]
|
29
32
|
source_info = 0
|
30
33
|
|
31
34
|
sup_message = Message.build_from_source(source, source_info)
|
@@ -41,7 +44,6 @@ class TestMessagesDir < ::Minitest::Test
|
|
41
44
|
assert_equal("Important", subj)
|
42
45
|
|
43
46
|
chunks = sup_message.load_from_source!
|
44
|
-
indexable_chunks = sup_message.indexable_chunks
|
45
47
|
|
46
48
|
# there should be only one chunk
|
47
49
|
#assert_equal(1, chunks.length)
|
@@ -50,14 +52,13 @@ class TestMessagesDir < ::Minitest::Test
|
|
50
52
|
|
51
53
|
# lines should contain an error message
|
52
54
|
assert (lines.join.include? "An error occurred while loading this message."), "This message should not load successfully"
|
55
|
+
|
56
|
+
assert_match(/WARNING: problem reading message/, @log.string)
|
53
57
|
end
|
54
58
|
|
55
59
|
def test_bad_content_transfer_encoding
|
56
|
-
message = ''
|
57
|
-
File.open('test/fixtures/bad-content-transfer-encoding-1.eml') { |f| message = f.read }
|
58
|
-
|
59
60
|
source = DummySource.new("sup-test://test_messages")
|
60
|
-
source.messages = [
|
61
|
+
source.messages = [ fixture_path('bad-content-transfer-encoding-1.eml') ]
|
61
62
|
source_info = 0
|
62
63
|
|
63
64
|
sup_message = Message.build_from_source(source, source_info)
|
@@ -73,7 +74,6 @@ class TestMessagesDir < ::Minitest::Test
|
|
73
74
|
assert_equal("Content-Transfer-Encoding:-bug in sup", subj)
|
74
75
|
|
75
76
|
chunks = sup_message.load_from_source!
|
76
|
-
indexable_chunks = sup_message.indexable_chunks
|
77
77
|
|
78
78
|
# there should be only one chunk
|
79
79
|
#assert_equal(1, chunks.length)
|
@@ -82,14 +82,13 @@ class TestMessagesDir < ::Minitest::Test
|
|
82
82
|
|
83
83
|
# lines should contain an error message
|
84
84
|
assert (lines.join.include? "An error occurred while loading this message."), "This message should not load successfully"
|
85
|
+
|
86
|
+
assert_match(/WARNING: problem reading message/, @log.string)
|
85
87
|
end
|
86
88
|
|
87
89
|
def test_missing_line
|
88
|
-
message = ''
|
89
|
-
File.open('test/fixtures/missing-line.eml') { |f| message = f.read }
|
90
|
-
|
91
90
|
source = DummySource.new("sup-test://test_messages")
|
92
|
-
source.messages = [
|
91
|
+
source.messages = [ fixture_path('missing-line.eml') ]
|
93
92
|
source_info = 0
|
94
93
|
|
95
94
|
sup_message = Message.build_from_source(source, source_info)
|
@@ -105,7 +104,6 @@ class TestMessagesDir < ::Minitest::Test
|
|
105
104
|
assert_equal("Encoding bug", subj)
|
106
105
|
|
107
106
|
chunks = sup_message.load_from_source!
|
108
|
-
indexable_chunks = sup_message.indexable_chunks
|
109
107
|
|
110
108
|
# there should be only one chunk
|
111
109
|
#assert_equal(1, chunks.length)
|
@@ -13,18 +13,18 @@ describe Redwood::HorizontalSelector do
|
|
13
13
|
|
14
14
|
it "init w/ the first value selected" do
|
15
15
|
first_value = values.first
|
16
|
-
@selector.val
|
16
|
+
assert_equal first_value, @selector.val
|
17
17
|
end
|
18
18
|
|
19
19
|
it "stores value for selection" do
|
20
20
|
second_value = values[1]
|
21
21
|
@selector.set_to second_value
|
22
|
-
@selector.val
|
22
|
+
assert_equal second_value, @selector.val
|
23
23
|
end
|
24
24
|
|
25
25
|
describe "for unknown value" do
|
26
26
|
it "cannot select unknown value" do
|
27
|
-
@selector.
|
27
|
+
assert_equal false, @selector.can_set_to?(strange_value)
|
28
28
|
end
|
29
29
|
|
30
30
|
it "refuses selecting unknown value" do
|
@@ -34,7 +34,7 @@ describe Redwood::HorizontalSelector do
|
|
34
34
|
@selector.set_to strange_value
|
35
35
|
end
|
36
36
|
|
37
|
-
@selector.val
|
37
|
+
assert_equal old_value, @selector.val
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -30,7 +30,7 @@ describe Redwood::Util::Query do
|
|
30
30
|
else
|
31
31
|
# xapian 1.2 doesn't handle this bad input, so we do
|
32
32
|
assert_raises Redwood::Util::Query::QueryDescriptionError do
|
33
|
-
|
33
|
+
_desc = Redwood::Util::Query.describe (query)
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -18,7 +18,7 @@ describe "Sup's String extension" do
|
|
18
18
|
|
19
19
|
it "calculates display length of a string" do
|
20
20
|
data.each do |(str, length)|
|
21
|
-
str.display_length
|
21
|
+
assert_equal length, str.display_length
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -36,7 +36,7 @@ describe "Sup's String extension" do
|
|
36
36
|
|
37
37
|
it "slices string by display length" do
|
38
38
|
data.each do |(str, length, sliced)|
|
39
|
-
str.slice_by_display_length(length)
|
39
|
+
assert_equal sliced, str.slice_by_display_length(length)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
@@ -56,7 +56,7 @@ describe "Sup's String extension" do
|
|
56
56
|
|
57
57
|
it "wraps string by display length" do
|
58
58
|
data.each do |(str, length, wrapped)|
|
59
|
-
str.wrap(length)
|
59
|
+
assert_equal wrapped, str.wrap(length)
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
data/test/unit/util/test_uri.rb
CHANGED
@@ -7,13 +7,13 @@ describe Redwood::Util::Uri do
|
|
7
7
|
it "builds uri from hash" do
|
8
8
|
components = {:path => "/var/mail/foo", :scheme => "mbox"}
|
9
9
|
uri = Redwood::Util::Uri.build(components)
|
10
|
-
|
10
|
+
assert_equal "mbox:/var/mail/foo", uri.to_s
|
11
11
|
end
|
12
12
|
|
13
13
|
it "expands ~ in path" do
|
14
14
|
components = {:path => "~/foo", :scheme => "maildir"}
|
15
15
|
uri = Redwood::Util::Uri.build(components)
|
16
|
-
|
16
|
+
assert_equal "maildir:#{ENV["HOME"]}/foo", uri.to_s
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|