sup 1.0 → 1.1
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.
- 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
|