rims 0.2.5 → 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -780,22 +780,22 @@ module RIMS
780
780
  end
781
781
  end
782
782
 
783
- services = Riser::DRbServices.new(drb_process_num)
784
- services.add_sticky_process_service(:engine,
785
- Riser::ResourceSet.build{|builder|
786
- builder.at_create{|unique_user_id|
787
- mail_store = MailStore.build(unique_user_id, kvs_meta_open, kvs_text_open)
788
- Protocol::Decoder::Engine.new(unique_user_id, mail_store, logger,
789
- bulk_response_count: @config.bulk_response_count,
790
- read_lock_timeout_seconds: @config.read_lock_timeout_seconds,
791
- write_lock_timeout_seconds: @config.write_lock_timeout_seconds,
792
- cleanup_write_lock_timeout_seconds: @config.cleanup_write_lock_timeout_seconds)
793
- }
794
- builder.at_destroy{|engine|
795
- engine.destroy
796
- }
797
- builder.alias_unref(:destroy)
798
- })
783
+ drb_services = Riser::DRbServices.new(drb_process_num)
784
+ drb_services.add_sticky_process_service(:engine,
785
+ Riser::ResourceSet.build{|builder|
786
+ builder.at_create{|unique_user_id|
787
+ mail_store = MailStore.build(unique_user_id, kvs_meta_open, kvs_text_open)
788
+ Protocol::Decoder::Engine.new(unique_user_id, mail_store, logger,
789
+ bulk_response_count: @config.bulk_response_count,
790
+ read_lock_timeout_seconds: @config.read_lock_timeout_seconds,
791
+ write_lock_timeout_seconds: @config.write_lock_timeout_seconds,
792
+ cleanup_write_lock_timeout_seconds: @config.cleanup_write_lock_timeout_seconds)
793
+ }
794
+ builder.at_destroy{|engine|
795
+ engine.destroy
796
+ }
797
+ builder.alias_unref(:destroy)
798
+ })
799
799
 
800
800
  server.before_start{|server_socket|
801
801
  logger.info('start server.')
@@ -906,11 +906,11 @@ module RIMS
906
906
  logger.info("authorization parameter: mail_delivery_user=#{@config.mail_delivery_user}")
907
907
 
908
908
  logger.info('dRuby services: start server.')
909
- services.start_server
909
+ drb_services.start_server
910
910
  }
911
911
  server.at_fork{
912
912
  logger.info('dRuby services: detach server.')
913
- services.detach_server
913
+ drb_services.detach_server
914
914
  }
915
915
  server.at_stop{|stop_state|
916
916
  case (stop_state)
@@ -926,7 +926,7 @@ module RIMS
926
926
  }
927
927
  server.preprocess{
928
928
  logger.info('dRuby services: start client.')
929
- services.start_client
929
+ drb_services.start_client
930
930
  auth.start_plug_in(logger)
931
931
  }
932
932
  server.dispatch{|socket|
@@ -947,7 +947,7 @@ module RIMS
947
947
  stream = Riser::WriteBufferStream.new(socket, @config.send_buffer_limit_size)
948
948
  end
949
949
  stream = Riser::LoggingStream.new(stream, protocol_logger)
950
- decoder = Protocol::Decoder.new_decoder(services, auth, logger, mail_delivery_user: @config.mail_delivery_user)
950
+ decoder = Protocol::Decoder.new_decoder(drb_services, auth, logger, mail_delivery_user: @config.mail_delivery_user)
951
951
  Protocol::Decoder.repl(decoder, conn_limits, stream, stream, logger)
952
952
  ensure
953
953
  if (stream) then
@@ -980,7 +980,7 @@ module RIMS
980
980
  }
981
981
  server.after_stop{
982
982
  logger.info('dRuby services: stop server.')
983
- services.stop_server
983
+ drb_services.stop_server
984
984
  logger.info('stop server.')
985
985
  }
986
986
 
@@ -1,5 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
+ require 'digest'
3
4
  require 'fileutils'
4
5
  require 'set'
5
6
 
@@ -68,16 +69,22 @@ module RIMS
68
69
 
69
70
  module ProtocolFetchMailSample
70
71
  def make_mail_simple
71
- @simple_mail = RIMS::RFC822::Message.new(<<-'EOF')
72
+ @simple_mail_body = <<-'EOF'
73
+ Hello world.
74
+ EOF
75
+
76
+ md5_digest = Digest::MD5.digest(@simple_mail_body)
77
+ @simple_mail = RIMS::RFC822::Message.new(<<-"EOF" + @simple_mail_body)
72
78
  To: foo@nonet.org
73
79
  From: bar@nonet.org
74
80
  Subject: test
75
81
  MIME-Version: 1.0
76
82
  Content-Type: text/plain; charset=us-ascii
77
83
  Content-Transfer-Encoding: 7bit
84
+ Content-MD5: #{[ md5_digest ].pack('m').strip}
85
+ Content-Language: en-US, en
78
86
  Date: Fri, 8 Nov 2013 06:47:50 +0900 (JST)
79
87
 
80
- Hello world.
81
88
  EOF
82
89
  end
83
90
  private :make_mail_simple
@@ -97,6 +104,9 @@ Content-Type: text/plain; charset=us-ascii
97
104
  Multipart test.
98
105
  --1383.905529.351297
99
106
  Content-Type: application/octet-stream
107
+ Content-Disposition: attachment
108
+ ; filename=test.dat
109
+ ; modification-date="Wed, 12 Feb 1997 16:29:51 -0500"
100
110
 
101
111
  0123456789
102
112
  --1383.905529.351297
@@ -108,6 +118,9 @@ Subject: inner multipart
108
118
  MIME-Version: 1.0
109
119
  Date: Fri, 8 Nov 2013 19:31:03 +0900
110
120
  Content-Type: multipart/mixed; boundary="1383.905529.351298"
121
+ Content-Disposition: attachment; filename=hello.txt
122
+ Content-Language: en
123
+ Content-Location: test
111
124
 
112
125
  --1383.905529.351298
113
126
  Content-Type: text/plain; charset=us-ascii
@@ -123,7 +136,9 @@ Content-Type: multipart/mixed; boundary="1383.905529.351299"
123
136
 
124
137
  --1383.905529.351299
125
138
  Content-Type: image/gif
139
+ Content-Disposition: inline
126
140
 
141
+ GIF image...
127
142
  --1383.905529.351299
128
143
  Content-Type: message/rfc822
129
144
 
@@ -136,6 +151,7 @@ Content-Type: multipart/mixed; boundary="1383.905529.351300"
136
151
 
137
152
  --1383.905529.351300
138
153
  Content-Type: text/plain; charset=us-ascii
154
+ Content-Location: foo
139
155
 
140
156
  HALO
141
157
  --1383.905529.351300
@@ -143,10 +159,12 @@ Content-Type: multipart/alternative; boundary="1383.905529.351301"
143
159
 
144
160
  --1383.905529.351301
145
161
  Content-Type: text/plain; charset=us-ascii
162
+ Content-Location: bar
146
163
 
147
164
  alternative message.
148
165
  --1383.905529.351301
149
166
  Content-Type: text/html; charset=us-ascii
167
+ Content-Location: baz
150
168
 
151
169
  <html>
152
170
  <body><p>HTML message</p></body>
@@ -186,7 +204,7 @@ Hello world.
186
204
  private :make_mail_empty
187
205
 
188
206
  def make_mail_no_body
189
- @no_body_mail = RIMS::RFC822::Message.new('foo')
207
+ @no_body_mail = RIMS::RFC822::Message.new("Subject: foo\r\n\r\n")
190
208
  end
191
209
  private :make_mail_no_body
192
210
 
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  module RIMS
4
- VERSION = '0.2.5'
4
+ VERSION = '0.2.6'
5
5
  MAILBOX_DATA_STRUCTURE_VERSION = 'mailbox.2'
6
6
  end
7
7
 
@@ -26,6 +26,7 @@ Gem::Specification.new do |spec|
26
26
 
27
27
  spec.required_ruby_version = '>= 2.0.0'
28
28
 
29
+ spec.add_runtime_dependency "rims-rfc822", '>= 0.2.0'
29
30
  spec.add_runtime_dependency "riser", '>= 0.1.8'
30
31
  spec.add_runtime_dependency "logger-joint"
31
32
  spec.add_development_dependency "bundler"
@@ -334,6 +334,35 @@ module RIMS::Test
334
334
  assert_equal(0, status.exitstatus)
335
335
  end
336
336
 
337
+ data('default' => [ false, %w[] ],
338
+ '-r' => [ false, %w[ -r prime ] ],
339
+ '--required-feature' => [ false, %w[ --required-feature=prime ] ],
340
+ '--format=yaml' => [ false, %w[ --format=yaml ] ],
341
+ '--format=json' => [ false, %w[ --format=json ] ],
342
+
343
+ # deplicated options
344
+ 'deplicated:--load-library' => [ true, %w[ --load-library=prime ] ])
345
+ def test_environment(data)
346
+ deplicated, options = data
347
+
348
+ stdout, stderr, status = Open3.capture3('rims', 'environment', *options)
349
+ pp [ stdout, stderr, status ] if $DEBUG
350
+
351
+ assert_equal(0, status.exitstatus)
352
+ if (deplicated) then
353
+ assert_match(/^warning:/, stderr)
354
+ else
355
+ assert_equal('', stderr)
356
+ end
357
+
358
+ assert_match(/RIMS Environment/, stdout)
359
+ assert_match(/RUBY VERSION.*#{Regexp.quote(RUBY_DESCRIPTION)}/, stdout)
360
+ assert_match(/RIMS VERSION.*#{Regexp.quote(RIMS::VERSION)}/, stdout)
361
+ assert_match(/AUTHENTICATION PLUG-IN.*plain/m, stdout)
362
+ assert_match(/AUTHENTICATION PLUG-IN.*hash/m, stdout)
363
+ assert_match(/KEY-VALUE STORE PLUG-IN.*gdbm/m, stdout)
364
+ end
365
+
337
366
  tls_dir = Pathname(__FILE__).parent.parent / "tls"
338
367
  TLS_CA_CERT = tls_dir / 'ca.cert'
339
368
  TLS_SERVER_CERT = tls_dir / 'server_localhost.cert'
@@ -1277,49 +1306,112 @@ Hello world.
1277
1306
  envelope = lambda{|mail|
1278
1307
  Net::IMAP::Envelope.new(mail.header['Date'],
1279
1308
  mail.header['Subject'],
1280
- mail.from ? mail.from.map{|addr| Net::IMAP::Address.new(*addr) } : nil,
1281
- mail.reply_to ? mail.reply_to.map{|addr| Net::IMAP::Address.new(*addr) } : nil,
1282
- mail.sender ? mail.sender.map{|addr| Net::IMAP::Address.new(*addr) } : nil,
1283
- mail.to ? mail.to.map{|addr| Net::IMAP::Address.new(*addr) } : nil,
1284
- mail.cc ? mail.cc.map{|addr| Net::IMAP::Address.new(*addr) } : nil,
1285
- mail.bcc ? mail.bcc.map{|addr| Net::IMAP::Address.new(*addr) } : nil,
1309
+ mail.from ? mail.from.map{|addr| Net::IMAP::Address.new(*addr.to_a) } : nil,
1310
+ mail.reply_to ? mail.reply_to.map{|addr| Net::IMAP::Address.new(*addr.to_a) } : nil,
1311
+ mail.sender ? mail.sender.map{|addr| Net::IMAP::Address.new(*addr.to_a) } : nil,
1312
+ mail.to ? mail.to.map{|addr| Net::IMAP::Address.new(*addr.to_a) } : nil,
1313
+ mail.cc ? mail.cc.map{|addr| Net::IMAP::Address.new(*addr.to_a) } : nil,
1314
+ mail.bcc ? mail.bcc.map{|addr| Net::IMAP::Address.new(*addr.to_a) } : nil,
1286
1315
  mail.header['In-Reply-To'],
1287
1316
  mail.header['Message-Id'])
1288
1317
  }
1289
- body_type = lambda{|mail|
1290
- case (mail.media_main_type_upcase)
1291
- when 'TEXT'
1318
+ body_type = lambda{|mail, extension=false|
1319
+ body_params = lambda{|params|
1320
+ if (params && ! params.empty?) then
1321
+ Hash[params.map{|n, v| [ n.upcase, v ] }]
1322
+ end
1323
+ }
1324
+ body_disposition = lambda{|mail|
1325
+ if (mail.content_disposition) then
1326
+ Net::IMAP::ContentDisposition.new(mail.content_disposition_upcase,
1327
+ body_params[mail.content_disposition_parameter_list])
1328
+ end
1329
+ }
1330
+ body_language = lambda{|mail|
1331
+ if (mail.content_language) then
1332
+ if (mail.content_language.length > 1) then
1333
+ mail.content_language_upcase
1334
+ else
1335
+ mail.content_language_upcase[0]
1336
+ end
1337
+ end
1338
+ }
1339
+ if (mail.text?) then
1292
1340
  Net::IMAP::BodyTypeText.new(mail.media_main_type_upcase,
1293
1341
  mail.media_sub_type_upcase,
1294
- Hash[mail.content_type_parameters.map{|n, v| [ n.upcase, v ] }],
1342
+ body_params[mail.content_type_parameter_list],
1295
1343
  mail.header['Content-Id'],
1296
1344
  mail.header['Content-Description'],
1297
1345
  mail.header.fetch_upcase('Content-Transfer-Encoding'),
1298
1346
  mail.raw_source.bytesize,
1299
- mail.raw_source.each_line.count)
1300
- when 'MESSAGE'
1347
+ mail.raw_source.each_line.count,
1348
+ *(
1349
+ if (extension) then
1350
+ [ mail.header['Content-MD5'],
1351
+ body_disposition[mail],
1352
+ body_language[mail],
1353
+ [ mail.header['Content-Location'] ]
1354
+ ]
1355
+ else
1356
+ []
1357
+ end
1358
+ ))
1359
+ elsif (mail.message?) then
1301
1360
  Net::IMAP::BodyTypeMessage.new(mail.media_main_type_upcase,
1302
1361
  mail.media_sub_type_upcase,
1303
- Hash[mail.content_type_parameters.map{|n, v| [ n.upcase, v ] }],
1362
+ body_params[mail.content_type_parameter_list],
1304
1363
  mail.header['Content-Id'],
1305
1364
  mail.header['Content-Description'],
1306
1365
  mail.header.fetch_upcase('Content-Transfer-Encoding'),
1307
1366
  mail.raw_source.bytesize,
1308
1367
  envelope[mail.message],
1309
- body_type[mail.message],
1310
- mail.raw_source.each_line.count)
1311
- when 'MULTIPART'
1368
+ body_type[mail.message, extension],
1369
+ mail.raw_source.each_line.count,
1370
+ *(
1371
+ if (extension) then
1372
+ [ mail.header['Content-MD5'],
1373
+ body_disposition[mail],
1374
+ body_language[mail],
1375
+ [ mail.header['Content-Location'] ]
1376
+ ]
1377
+ else
1378
+ []
1379
+ end
1380
+ ))
1381
+ elsif (mail.multipart?) then
1312
1382
  Net::IMAP::BodyTypeMultipart.new(mail.media_main_type_upcase,
1313
1383
  mail.media_sub_type_upcase,
1314
- mail.parts.map{|m| body_type[m] })
1384
+ mail.parts.map{|m| body_type[m, extension] },
1385
+ *(
1386
+ if (extension) then
1387
+ [ body_params[mail.content_type_parameter_list],
1388
+ body_disposition[mail],
1389
+ body_language[mail],
1390
+ [ mail.header['Content-Location'] ]
1391
+ ]
1392
+ else
1393
+ []
1394
+ end
1395
+ ))
1315
1396
  else
1316
1397
  Net::IMAP::BodyTypeBasic.new(mail.media_main_type_upcase,
1317
1398
  mail.media_sub_type_upcase,
1318
- Hash[mail.content_type_parameters.map{|n, v| [ n.upcase, v ] }],
1399
+ body_params[mail.content_type_parameter_list],
1319
1400
  mail.header['Content-Id'],
1320
1401
  mail.header['Content-Description'],
1321
1402
  mail.header.fetch_upcase('Content-Transfer-Encoding'),
1322
- mail.raw_source.bytesize)
1403
+ mail.raw_source.bytesize,
1404
+ *(
1405
+ if (extension) then
1406
+ [ mail.header['Content-MD5'],
1407
+ body_disposition[mail],
1408
+ body_language[mail],
1409
+ [ mail.header['Content-Location'] ]
1410
+ ]
1411
+ else
1412
+ []
1413
+ end
1414
+ ))
1323
1415
  end
1324
1416
  }
1325
1417
 
@@ -1406,9 +1498,9 @@ Hello world.
1406
1498
  imap_fetch.call(msg_set[1..-1], 'BODY'))
1407
1499
 
1408
1500
  assert_equal(fetch_data[
1409
- [ 1, { 'BODYSTRUCTURE' => body_type[@simple_mail] } ],
1410
- [ 2, { 'BODYSTRUCTURE' => body_type[@mpart_mail] } ],
1411
- [ 3, { 'BODYSTRUCTURE' => body_type[@mime_subject_mail] } ]
1501
+ [ 1, { 'BODYSTRUCTURE' => body_type[@simple_mail, true] } ],
1502
+ [ 2, { 'BODYSTRUCTURE' => body_type[@mpart_mail, true] } ],
1503
+ [ 3, { 'BODYSTRUCTURE' => body_type[@mime_subject_mail, true] } ]
1412
1504
  ],
1413
1505
  imap_fetch.call(msg_set[1..-1], 'BODYSTRUCTURE'))
1414
1506
 
@@ -135,8 +135,10 @@ module RIMS::Test
135
135
  output = StringIO.new('', 'w')
136
136
  input_gets = input.method(:gets)
137
137
  output_write = lambda{|res|
138
- for line in res
139
- output << line
138
+ for data in res
139
+ if (data != :flush) then
140
+ output << data
141
+ end
140
142
  end
141
143
  }
142
144
  inout_args = [ input_gets, output_write ]
@@ -158,7 +160,9 @@ module RIMS::Test
158
160
  response_message << output.string
159
161
  end
160
162
  for response in responses
161
- response_message << response
163
+ if (response != :flush) then
164
+ response_message << response
165
+ end
162
166
  end
163
167
  response_lines = StringIO.new(response_message, 'r').each_line
164
168
  ret_val = yield(response_lines)
@@ -242,7 +246,7 @@ module RIMS::Test
242
246
  extend Forwardable
243
247
 
244
248
  def open_mail_store
245
- @services.call_service(:engine, @unique_user_id) {|engine|
249
+ @drb_services.call_service(:engine, @unique_user_id) {|engine|
246
250
  begin
247
251
  @mail_store = engine.mail_store
248
252
  @mail_store.write_synchronize{
@@ -256,7 +260,7 @@ module RIMS::Test
256
260
  private :open_mail_store
257
261
 
258
262
  def make_decoder
259
- RIMS::Protocol::Decoder.new_decoder(@services, @auth, @logger)
263
+ RIMS::Protocol::Decoder.new_decoder(@drb_services, @auth, @logger)
260
264
  end
261
265
  private :make_decoder
262
266
 
@@ -288,20 +292,22 @@ module RIMS::Test
288
292
  }
289
293
  @unique_user_id = RIMS::Authentication.unique_user_id('foo')
290
294
 
291
- @services = Riser::DRbServices.new(0)
292
- @services.add_sticky_process_service(:engine,
293
- Riser::ResourceSet.build{|builder|
294
- builder.at_create{|unique_user_id|
295
- mail_store = RIMS::MailStore.build(unique_user_id, @kvs_open, @kvs_open)
296
- RIMS::Protocol::Decoder::Engine.new(unique_user_id, mail_store, @logger)
297
- }
298
- builder.at_destroy{|engine|
299
- engine.destroy
300
- }
301
- builder.alias_unref(:destroy)
302
- })
303
- @services.start_server
304
- @services.start_client
295
+ @bulk_response_count = 10
296
+ @drb_services = Riser::DRbServices.new(0)
297
+ @drb_services.add_sticky_process_service(:engine,
298
+ Riser::ResourceSet.build{|builder|
299
+ builder.at_create{|unique_user_id|
300
+ mail_store = RIMS::MailStore.build(unique_user_id, @kvs_open, @kvs_open)
301
+ RIMS::Protocol::Decoder::Engine.new(unique_user_id, mail_store, @logger,
302
+ bulk_response_count: @bulk_response_count)
303
+ }
304
+ builder.at_destroy{|engine|
305
+ engine.destroy
306
+ }
307
+ builder.alias_unref(:destroy)
308
+ })
309
+ @drb_services.start_server
310
+ @drb_services.start_client
305
311
 
306
312
  open_mail_store{
307
313
  @inbox_id = @mail_store.mbox_id('INBOX')
@@ -328,8 +334,8 @@ module RIMS::Test
328
334
  end
329
335
 
330
336
  def teardown
331
- assert_equal(0, @services.get_service(:engine, @unique_user_id).proxy_count)
332
- @services.stop_server
337
+ assert_equal(0, @drb_services.get_service(:engine, @unique_user_id).proxy_count)
338
+ @drb_services.stop_server
333
339
  pp @kvs if $DEBUG
334
340
  end
335
341
 
@@ -2439,11 +2445,6 @@ module RIMS::Test
2439
2445
  assert.match(/^#{tag} NO /, peek_next_line: true).match(/not auth/)
2440
2446
  }
2441
2447
 
2442
- if (command_test?) then
2443
- assert_equal(false, @decoder.auth?)
2444
- assert_equal(false, @decoder.selected?)
2445
- end
2446
-
2447
2448
  assert_imap_command('LOGIN foo open_sesame') {|assert|
2448
2449
  assert.equal("#{tag} OK LOGIN completed")
2449
2450
  }
@@ -2591,15 +2592,10 @@ module RIMS::Test
2591
2592
  assert_equal(false, @decoder.selected?)
2592
2593
  end
2593
2594
 
2594
- assert_imap_command('SEARCH CHARSET utf-8 ALL') {|assert|
2595
+ assert_imap_command('SEARCH CHARSET us-ascii ALL') {|assert|
2595
2596
  assert.match(/^#{tag} NO /, peek_next_line: true).match(/not auth/)
2596
2597
  }
2597
2598
 
2598
- if (command_test?) then
2599
- assert_equal(false, @decoder.auth?)
2600
- assert_equal(false, @decoder.selected?)
2601
- end
2602
-
2603
2599
  assert_imap_command('LOGIN foo open_sesame') {|assert|
2604
2600
  assert.equal("#{tag} OK LOGIN completed")
2605
2601
  }
@@ -2609,7 +2605,7 @@ module RIMS::Test
2609
2605
  assert_equal(false, @decoder.selected?)
2610
2606
  end
2611
2607
 
2612
- assert_imap_command('SEARCH CHARSET utf-8 ALL') {|assert|
2608
+ assert_imap_command('SEARCH CHARSET us-ascii ALL') {|assert|
2613
2609
  assert.match(/^#{tag} NO /, peek_next_line: true).match(/not selected/)
2614
2610
  }
2615
2611
 
@@ -2623,17 +2619,17 @@ module RIMS::Test
2623
2619
  assert_equal(true, @decoder.selected?)
2624
2620
  end
2625
2621
 
2626
- assert_imap_command('SEARCH CHARSET utf-8 ALL') {|assert|
2622
+ assert_imap_command('SEARCH CHARSET us-ascii ALL') {|assert|
2627
2623
  assert.equal("* SEARCH 1 2 3 4 5\r\n")
2628
2624
  assert.equal("#{tag} OK SEARCH completed\r\n")
2629
2625
  }
2630
2626
 
2631
- assert_imap_command('SEARCH CHARSET utf-8 BODY foo') {|assert|
2627
+ assert_imap_command('SEARCH CHARSET us-ascii BODY foo') {|assert|
2632
2628
  assert.equal("* SEARCH 1 2 3\r\n")
2633
2629
  assert.equal("#{tag} OK SEARCH completed\r\n")
2634
2630
  }
2635
2631
 
2636
- assert_imap_command('SEARCH CHARSET utf-8 BODY bar') {|assert|
2632
+ assert_imap_command('SEARCH CHARSET us-ascii BODY bar') {|assert|
2637
2633
  assert.equal("* SEARCH\r\n")
2638
2634
  assert.equal("#{tag} OK SEARCH completed\r\n")
2639
2635
  }
@@ -2645,6 +2641,15 @@ module RIMS::Test
2645
2641
  assert.equal("#{tag} OK SEARCH completed\r\n")
2646
2642
  }
2647
2643
 
2644
+ assert_imap_command("SEARCH CHARSET euc-jp BODY {#{utf8_msg.bytesize}}\r\n#{utf8_msg}".b) {|assert|
2645
+ assert.match(/^\+ /)
2646
+ assert.match(/^#{tag} BAD /, peek_next_line: true).match(/syntax error/)
2647
+ }
2648
+
2649
+ assert_imap_command('SEARCH CHARSET x-nothing BODY foo') {|assert|
2650
+ assert.match(/^#{tag} NO \[BADCHARSET \(\S+( \S+)*\)\] unknown charset/)
2651
+ }
2652
+
2648
2653
  assert_imap_command('SEARCH CHARSET') {|assert|
2649
2654
  assert.match(/^#{tag} BAD /, peek_next_line: true).match(/syntax error/)
2650
2655
  }
@@ -2679,6 +2684,7 @@ module RIMS::Test
2679
2684
 
2680
2685
  open_mail_store{
2681
2686
  add_msg("Content-Type: text/plain\r\n" +
2687
+ "\r\n" +
2682
2688
  "foo")
2683
2689
  add_msg("Content-Type: text/plain; charset=utf-8\r\n" +
2684
2690
  "X-foo: dummy\r\n" +
@@ -2705,15 +2711,10 @@ module RIMS::Test
2705
2711
  assert_equal(false, @decoder.selected?)
2706
2712
  end
2707
2713
 
2708
- assert_imap_command('SEARCH CHARSET utf-8 ALL') {|assert|
2714
+ assert_imap_command('SEARCH CHARSET us-ascii ALL') {|assert|
2709
2715
  assert.match(/^#{tag} NO /, peek_next_line: true).match(/not auth/)
2710
2716
  }
2711
2717
 
2712
- if (command_test?) then
2713
- assert_equal(false, @decoder.auth?)
2714
- assert_equal(false, @decoder.selected?)
2715
- end
2716
-
2717
2718
  assert_imap_command('LOGIN foo open_sesame') {|assert|
2718
2719
  assert.equal("#{tag} OK LOGIN completed")
2719
2720
  }
@@ -2723,7 +2724,7 @@ module RIMS::Test
2723
2724
  assert_equal(false, @decoder.selected?)
2724
2725
  end
2725
2726
 
2726
- assert_imap_command('SEARCH CHARSET utf-8 ALL') {|assert|
2727
+ assert_imap_command('SEARCH CHARSET us-ascii ALL') {|assert|
2727
2728
  assert.match(/^#{tag} NO /, peek_next_line: true).match(/not selected/)
2728
2729
  }
2729
2730
 
@@ -2737,12 +2738,12 @@ module RIMS::Test
2737
2738
  assert_equal(true, @decoder.selected?)
2738
2739
  end
2739
2740
 
2740
- assert_imap_command('SEARCH CHARSET utf-8 ALL') {|assert|
2741
+ assert_imap_command('SEARCH CHARSET us-ascii ALL') {|assert|
2741
2742
  assert.equal("* SEARCH 1 2 3 4 5\r\n")
2742
2743
  assert.equal("#{tag} OK SEARCH completed\r\n")
2743
2744
  }
2744
2745
 
2745
- assert_imap_command('SEARCH CHARSET utf-8 TEXT foo') {|assert|
2746
+ assert_imap_command('SEARCH CHARSET us-ascii TEXT foo') {|assert|
2746
2747
  assert.equal("* SEARCH 1 2 3\r\n")
2747
2748
  assert.equal("#{tag} OK SEARCH completed\r\n")
2748
2749
  }
@@ -2752,7 +2753,7 @@ module RIMS::Test
2752
2753
  assert.equal("#{tag} OK SEARCH completed\r\n")
2753
2754
  }
2754
2755
 
2755
- assert_imap_command('SEARCH CHARSET utf-8 TEXT baz') {|assert|
2756
+ assert_imap_command('SEARCH CHARSET us-ascii TEXT baz') {|assert|
2756
2757
  assert.equal("* SEARCH\r\n")
2757
2758
  assert.equal("#{tag} OK SEARCH completed\r\n")
2758
2759
  }
@@ -2764,6 +2765,15 @@ module RIMS::Test
2764
2765
  assert.equal("#{tag} OK SEARCH completed\r\n")
2765
2766
  }
2766
2767
 
2768
+ assert_imap_command("SEARCH CHARSET euc-jp TEXT {#{utf8_msg.bytesize}}\r\n#{utf8_msg}".b) {|assert|
2769
+ assert.match(/^\+ /)
2770
+ assert.match(/^#{tag} BAD /, peek_next_line: true).match(/syntax error/)
2771
+ }
2772
+
2773
+ assert_imap_command('SEARCH CHARSET x-nothing TEXT foo') {|assert|
2774
+ assert.match(/^#{tag} NO \[BADCHARSET \(\S+( \S+)*\)\] unknown charset/)
2775
+ }
2776
+
2767
2777
  assert_imap_command('SEARCH CHARSET') {|assert|
2768
2778
  assert.match(/^#{tag} BAD /, peek_next_line: true).match(/syntax error/)
2769
2779
  }
@@ -2788,6 +2798,140 @@ module RIMS::Test
2788
2798
  test_search_charset_text
2789
2799
  end
2790
2800
 
2801
+ def test_search_charset_skip_encoding_error
2802
+ imap_decode_engine_evaluate{
2803
+ if (stream_test?) then
2804
+ assert_untagged_response{|assert|
2805
+ assert.equal("* OK RIMS v#{RIMS::VERSION} IMAP4rev1 service ready.")
2806
+ }
2807
+ end
2808
+
2809
+ open_mail_store{
2810
+ add_msg("Content-Type: text/plain\r\n" +
2811
+ "\r\n" +
2812
+ "foo")
2813
+ add_msg("Content-Type: text/plain; charset=iso-2022-jp\r\n" +
2814
+ "\r\n" +
2815
+ # utf-8
2816
+ "\u3053\u3093\u306B\u3061\u306F\r\n" +
2817
+ "\u3044\u308D\u306F\u306B\u307B\u3078\u3068\r\n" +
2818
+ "\u3042\u3044\u3046\u3048\u304A\r\n" +
2819
+ "foo\r\n")
2820
+
2821
+ assert_msg_uid(1, 2)
2822
+ }
2823
+
2824
+ if (command_test?) then
2825
+ assert_equal(false, @decoder.auth?)
2826
+ assert_equal(false, @decoder.selected?)
2827
+ end
2828
+
2829
+ assert_imap_command('LOGIN foo open_sesame') {|assert|
2830
+ assert.equal("#{tag} OK LOGIN completed")
2831
+ }
2832
+
2833
+ if (command_test?) then
2834
+ assert_equal(true, @decoder.auth?)
2835
+ assert_equal(false, @decoder.selected?)
2836
+ end
2837
+
2838
+ assert_imap_command('SELECT INBOX') {|assert|
2839
+ assert.skip_while{|line| line =~ /^\* / }
2840
+ assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
2841
+ }
2842
+
2843
+ if (command_test?) then
2844
+ assert_equal(true, @decoder.auth?)
2845
+ assert_equal(true, @decoder.selected?)
2846
+ end
2847
+
2848
+ assert_imap_command('SEARCH CHARSET us-ascii BODY foo') {|assert|
2849
+ assert.equal("* SEARCH 1\r\n")
2850
+ assert.equal("#{tag} OK SEARCH completed\r\n")
2851
+ }
2852
+
2853
+ utf8_msg = "\u306F\u306B\u307B"
2854
+ assert_imap_command("SEARCH CHARSET utf-8 TEXT {#{utf8_msg.bytesize}}\r\n#{utf8_msg}".b) {|assert|
2855
+ assert.match(/^\+ /)
2856
+ assert.equal("* SEARCH\r\n")
2857
+ assert.equal("#{tag} OK SEARCH completed\r\n")
2858
+ }
2859
+
2860
+ assert_imap_command('LOGOUT') {|assert|
2861
+ assert.match(/^\* BYE /)
2862
+ assert.equal("#{tag} OK LOGOUT completed")
2863
+ }
2864
+ }
2865
+ end
2866
+
2867
+ def test_search_charset_skip_encoding_error_stream
2868
+ use_imap_stream_decode_engine
2869
+ test_search_charset_skip_encoding_error
2870
+ end
2871
+
2872
+ def test_search_interrupt_by_bad_response
2873
+ imap_decode_engine_evaluate{
2874
+ if (stream_test?) then
2875
+ assert_untagged_response{|assert|
2876
+ assert.equal("* OK RIMS v#{RIMS::VERSION} IMAP4rev1 service ready.")
2877
+ }
2878
+ end
2879
+
2880
+ open_mail_store{
2881
+ @bulk_response_count.times do
2882
+ add_msg("Content-Type: text/plain\r\n" +
2883
+ "\r\n" +
2884
+ "foo")
2885
+ end
2886
+
2887
+ add_msg("Content-Type: text/plain; charset=x-nothing\r\n" +
2888
+ "\r\n" +
2889
+ "foo")
2890
+
2891
+ assert_msg_uid(*(1..(@bulk_response_count.succ)).to_a)
2892
+ }
2893
+
2894
+ if (command_test?) then
2895
+ assert_equal(false, @decoder.auth?)
2896
+ assert_equal(false, @decoder.selected?)
2897
+ end
2898
+
2899
+ assert_imap_command('LOGIN foo open_sesame') {|assert|
2900
+ assert.equal("#{tag} OK LOGIN completed")
2901
+ }
2902
+
2903
+ if (command_test?) then
2904
+ assert_equal(true, @decoder.auth?)
2905
+ assert_equal(false, @decoder.selected?)
2906
+ end
2907
+
2908
+ assert_imap_command('SELECT INBOX') {|assert|
2909
+ assert.skip_while{|line| line =~ /^\* / }
2910
+ assert.equal("#{tag} OK [READ-WRITE] SELECT completed")
2911
+ }
2912
+
2913
+ if (command_test?) then
2914
+ assert_equal(true, @decoder.auth?)
2915
+ assert_equal(true, @decoder.selected?)
2916
+ end
2917
+
2918
+ assert_imap_command('SEARCH TEXT foo') {|assert|
2919
+ assert.match(/\A\* SEARCH( \d+)+\r\n\z/, peek_next_line: true).no_match(/ #{@bulk_response_count.succ}/)
2920
+ assert.equal("#{tag} BAD internal server error\r\n")
2921
+ }
2922
+
2923
+ assert_imap_command('LOGOUT') {|assert|
2924
+ assert.match(/^\* BYE /)
2925
+ assert.equal("#{tag} OK LOGOUT completed")
2926
+ }
2927
+ }
2928
+ end
2929
+
2930
+ def test_search_interrupt_by_bad_response_stream
2931
+ use_imap_stream_decode_engine
2932
+ test_search_interrupt_by_bad_response
2933
+ end
2934
+
2791
2935
  def test_fetch
2792
2936
  imap_decode_engine_evaluate{
2793
2937
  if (stream_test?) then