rims 0.2.6 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/CHANGELOG.md +97 -0
- data/ChangeLog +49 -0
- data/Rakefile +8 -4
- data/lib/rims.rb +31 -29
- data/lib/rims/channel.rb +35 -10
- data/lib/rims/cmd.rb +109 -3
- data/lib/rims/error.rb +15 -0
- data/lib/rims/protocol.rb +28 -7
- data/lib/rims/protocol/decoder.rb +727 -457
- data/lib/rims/protocol/parser.rb +190 -82
- data/lib/rims/service.rb +172 -39
- data/lib/rims/test.rb +31 -20
- data/lib/rims/version.rb +1 -1
- data/load_test/Rakefile +3 -1
- data/rims.gemspec +14 -13
- data/test/cmd/test_command.rb +21 -1
- data/test/test_channel.rb +2 -1
- data/test/test_error.rb +33 -1
- data/test/test_lock.rb +4 -4
- data/test/test_passwd.rb +1 -1
- data/test/test_protocol_decoder.rb +555 -41
- data/test/test_protocol_fetch.rb +14 -10
- data/test/test_protocol_request.rb +305 -280
- data/test/test_protocol_search.rb +771 -893
- data/test/test_service.rb +165 -0
- metadata +22 -7
data/lib/rims/protocol/parser.rb
CHANGED
@@ -33,21 +33,7 @@ module RIMS
|
|
33
33
|
end
|
34
34
|
|
35
35
|
class RequestReader
|
36
|
-
def
|
37
|
-
@input = input
|
38
|
-
@output = output
|
39
|
-
@logger = logger
|
40
|
-
end
|
41
|
-
|
42
|
-
def read_line
|
43
|
-
line = @input.gets or return
|
44
|
-
@logger.debug("read line: #{Protocol.io_data_log(line)}") if @logger.debug?
|
45
|
-
line.chomp!("\n")
|
46
|
-
line.chomp!("\r")
|
47
|
-
scan_line(line)
|
48
|
-
end
|
49
|
-
|
50
|
-
def scan_line(line)
|
36
|
+
def self.scan(line)
|
51
37
|
atom_list = line.scan(/BODY(?:\.\S+)?\[.*?\](?:<\d+\.\d+>)?|[\[\]()]|".*?"|[^\[\]()\s]+/i).map{|s|
|
52
38
|
case (s)
|
53
39
|
when '(', ')', '[', ']', /\A NIL \z/ix
|
@@ -77,22 +63,14 @@ module RIMS
|
|
77
63
|
end
|
78
64
|
}
|
79
65
|
if ((atom_list[-1].is_a? String) && (atom_list[-1] =~ /\A {\d+} \z/x)) then
|
80
|
-
|
81
|
-
|
82
|
-
@output.write("+ continue\r\n")
|
83
|
-
@output.flush
|
84
|
-
@logger.debug('continue literal.') if @logger.debug?
|
85
|
-
literal_string = @input.read(next_size) or raise 'unexpected client close.'
|
86
|
-
@logger.debug("read literal: #{Protocol.io_data_log(literal_string)}") if @logger.debug?
|
87
|
-
atom_list[-1] = literal_string
|
88
|
-
next_atom_list = read_line or raise 'unexpected client close.'
|
89
|
-
atom_list += next_atom_list
|
66
|
+
literal_size = $&[1..-2].to_i
|
67
|
+
atom_list[-1] = [ :literal, literal_size ]
|
90
68
|
end
|
91
69
|
|
92
70
|
atom_list
|
93
71
|
end
|
94
72
|
|
95
|
-
def parse(atom_list, last_atom=nil)
|
73
|
+
def self.parse(atom_list, last_atom=nil)
|
96
74
|
syntax_list = []
|
97
75
|
while (atom = atom_list.shift)
|
98
76
|
case (atom)
|
@@ -105,7 +83,7 @@ module RIMS
|
|
105
83
|
else
|
106
84
|
if ((atom.is_a? Array) && (atom[0] == :body)) then
|
107
85
|
body = atom[1]
|
108
|
-
body.section_list = parse(
|
86
|
+
body.section_list = parse(scan(body.section))
|
109
87
|
end
|
110
88
|
syntax_list.push(atom)
|
111
89
|
end
|
@@ -118,18 +96,90 @@ module RIMS
|
|
118
96
|
syntax_list
|
119
97
|
end
|
120
98
|
|
99
|
+
def initialize(input, output, logger, line_length_limit: 1024*8, literal_size_limit: (1024**2)*10, command_size_limit: (1024**2)*10)
|
100
|
+
@input = input
|
101
|
+
@output = output
|
102
|
+
@logger = logger
|
103
|
+
@line_length_limit = line_length_limit
|
104
|
+
@literal_size_limit = literal_size_limit
|
105
|
+
@command_size_limit = command_size_limit
|
106
|
+
@command_tag = nil
|
107
|
+
@read_size = 0
|
108
|
+
end
|
109
|
+
|
110
|
+
attr_reader :command_tag
|
111
|
+
|
112
|
+
def gets
|
113
|
+
if (line = @input.gets($/, @line_length_limit)) then # arguments compatible with OpenSSL::Buffering#gets
|
114
|
+
if (line.bytesize < @line_length_limit) then
|
115
|
+
line
|
116
|
+
elsif (line.bytesize == @line_length_limit && (line.end_with? $/)) then
|
117
|
+
line
|
118
|
+
else
|
119
|
+
raise LineTooLongError.new('line too long.', line_fragment: line)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def read_literal(size)
|
125
|
+
@logger.debug("found literal: #{size} octets.") if @logger.debug?
|
126
|
+
if (size > @literal_size_limit) then
|
127
|
+
raise LiteralSizeTooLargeError.new('literal size too large', @command_tag)
|
128
|
+
end
|
129
|
+
if (@read_size + size > @command_size_limit) then
|
130
|
+
raise CommandSizeTooLargeError.new('command size too large', @command_tag)
|
131
|
+
end
|
132
|
+
@output.write("+ continue\r\n")
|
133
|
+
@output.flush
|
134
|
+
@logger.debug('continue literal.') if @logger.debug?
|
135
|
+
literal_string = @input.read(size) or raise 'unexpected client close.'
|
136
|
+
@read_size += size
|
137
|
+
@logger.debug("read literal: #{Protocol.io_data_log(literal_string)}") if @logger.debug?
|
138
|
+
|
139
|
+
literal_string
|
140
|
+
end
|
141
|
+
private :read_literal
|
142
|
+
|
143
|
+
def read_line
|
144
|
+
line = gets or return
|
145
|
+
@logger.debug("read line: #{Protocol.io_data_log(line)}") if @logger.debug?
|
146
|
+
line.chomp!("\n")
|
147
|
+
line.chomp!("\r")
|
148
|
+
@read_size += line.bytesize
|
149
|
+
if (@read_size > @command_size_limit) then
|
150
|
+
raise CommandSizeTooLargeError.new('command size too large', @command_tag)
|
151
|
+
end
|
152
|
+
atom_list = self.class.scan(line)
|
153
|
+
|
154
|
+
if (@command_tag.nil? && ! atom_list.empty?) then
|
155
|
+
unless ((atom_list[0].is_a? String) && ! (atom_list[0].start_with? '*', '+')) then
|
156
|
+
raise SyntaxError, "invalid command tag: #{atom_list[0]}"
|
157
|
+
end
|
158
|
+
@command_tag = atom_list[0]
|
159
|
+
end
|
160
|
+
|
161
|
+
if ((atom_list[-1].is_a? Array) && (atom_list[-1][0] == :literal)) then
|
162
|
+
atom_list[-1] = read_literal(atom_list[-1][1])
|
163
|
+
next_atom_list = read_line or raise 'unexpected client close.'
|
164
|
+
atom_list += next_atom_list
|
165
|
+
end
|
166
|
+
|
167
|
+
atom_list
|
168
|
+
end
|
169
|
+
private :read_line
|
170
|
+
|
121
171
|
def read_command
|
172
|
+
@command_tag = nil
|
173
|
+
@read_size = 0
|
122
174
|
while (atom_list = read_line)
|
123
175
|
if (atom_list.empty?) then
|
176
|
+
@read_size = 0
|
124
177
|
next
|
125
178
|
end
|
126
179
|
if (atom_list.length < 2) then
|
127
|
-
raise 'need for tag and command.'
|
128
|
-
end
|
129
|
-
if (atom_list[0] =~ /\A [*+]/x) then
|
130
|
-
raise "invalid command tag: #{atom_list[0]}"
|
180
|
+
raise SyntaxError, 'need for tag and command.'
|
131
181
|
end
|
132
|
-
return parse(atom_list)
|
182
|
+
return self.class.parse(atom_list)
|
133
183
|
end
|
134
184
|
|
135
185
|
nil
|
@@ -228,13 +278,15 @@ module RIMS
|
|
228
278
|
end
|
229
279
|
|
230
280
|
class SearchParser
|
231
|
-
def initialize(mail_store, folder)
|
281
|
+
def initialize(mail_store, folder, charset_aliases: RFC822::DEFAULT_CHARSET_ALIASES, charset_convert_options: nil)
|
232
282
|
@mail_store = mail_store
|
233
283
|
@folder = folder
|
284
|
+
@charset_aliases = charset_aliases
|
285
|
+
@charset_convert_options = charset_convert_options || {}
|
234
286
|
@charset = nil
|
235
287
|
@mail_cache = Hash.new{|hash, uid|
|
236
288
|
if (msg_txt = @mail_store.msg_text(@folder.mbox_id, uid)) then
|
237
|
-
hash[uid] = RFC822::Message.new(msg_txt)
|
289
|
+
hash[uid] = RFC822::Message.new(msg_txt, charset_aliases: @charset_aliases)
|
238
290
|
end
|
239
291
|
}
|
240
292
|
end
|
@@ -247,47 +299,35 @@ module RIMS
|
|
247
299
|
attr_reader :charset
|
248
300
|
|
249
301
|
def charset=(new_charset)
|
250
|
-
|
302
|
+
charset_encoding = @charset_aliases[new_charset] || Encoding.find(new_charset)
|
303
|
+
if (charset_encoding.dummy?) then
|
304
|
+
# same error type as `Encoding.find'
|
305
|
+
raise ArgumentError, "not a searchable charset: #{new_charset}"
|
306
|
+
end
|
307
|
+
@charset = charset_encoding
|
251
308
|
end
|
252
309
|
|
253
|
-
def
|
310
|
+
def force_charset(string)
|
254
311
|
string = string.dup
|
255
312
|
string.force_encoding(@charset)
|
256
313
|
string.valid_encoding? or raise SyntaxError, "invalid #{@charset} string: #{string.inspect}"
|
257
314
|
string
|
258
315
|
end
|
259
|
-
private :
|
316
|
+
private :force_charset
|
260
317
|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
unless (text.encoding.ascii_compatible?) then
|
265
|
-
text = text.encode('utf-8')
|
266
|
-
end
|
318
|
+
def encode_charset(string)
|
319
|
+
if (string.encoding == @charset) then
|
320
|
+
string
|
267
321
|
else
|
268
|
-
|
269
|
-
text = text.encode(@charset)
|
270
|
-
end
|
322
|
+
string.encode(@charset, **@charset_convert_options)
|
271
323
|
end
|
272
|
-
|
273
|
-
text.include? search_string
|
274
324
|
end
|
275
|
-
private :
|
325
|
+
private :encode_charset
|
276
326
|
|
277
|
-
def
|
278
|
-
|
279
|
-
body_txt = mail.body.raw_source
|
280
|
-
if (charset = mail.charset) then
|
281
|
-
if (body_txt.encoding != charset) then
|
282
|
-
body_txt = body_txt.dup.force_encoding(charset)
|
283
|
-
end
|
284
|
-
end
|
285
|
-
body_txt
|
286
|
-
else
|
287
|
-
nil
|
288
|
-
end
|
327
|
+
def compile_search_regexp(search_string)
|
328
|
+
Regexp.new(Regexp.quote(search_string), true)
|
289
329
|
end
|
290
|
-
private :
|
330
|
+
private :compile_search_regexp
|
291
331
|
|
292
332
|
def end_of_cond
|
293
333
|
proc{|msg| true }
|
@@ -322,14 +362,29 @@ module RIMS
|
|
322
362
|
private :parse_msg_flag_enabled
|
323
363
|
|
324
364
|
def parse_search_header(field_name, search_string)
|
325
|
-
|
365
|
+
if (@charset) then
|
366
|
+
search_string = force_charset(search_string)
|
367
|
+
search_regexp = compile_search_regexp(search_string)
|
368
|
+
search_header = proc{|mail|
|
369
|
+
mail.mime_decoded_header_field_value_list(field_name, @charset, charset_convert_options: @charset_convert_options).any?{|field_value|
|
370
|
+
search_regexp.match? field_value
|
371
|
+
}
|
372
|
+
}
|
373
|
+
else
|
374
|
+
search_string = search_string.b
|
375
|
+
search_regexp = compile_search_regexp(search_string)
|
376
|
+
search_header = proc{|mail|
|
377
|
+
mail.header.field_value_list(field_name).any?{|field_value|
|
378
|
+
search_regexp.match? field_value
|
379
|
+
}
|
380
|
+
}
|
381
|
+
end
|
382
|
+
|
326
383
|
proc{|next_cond|
|
327
384
|
proc{|msg|
|
328
385
|
mail = get_mail(msg)
|
329
386
|
if (mail.header.key? field_name) then
|
330
|
-
mail.
|
331
|
-
string_include?(search_string, field_value)
|
332
|
-
} && next_cond.call(msg)
|
387
|
+
search_header.call(mail) && next_cond.call(msg)
|
333
388
|
else
|
334
389
|
false
|
335
390
|
end
|
@@ -372,11 +427,40 @@ module RIMS
|
|
372
427
|
private :parse_mail_bytesize
|
373
428
|
|
374
429
|
def parse_body(search_string)
|
375
|
-
|
430
|
+
if (@charset)
|
431
|
+
search_string = force_charset(search_string)
|
432
|
+
search_regexp = compile_search_regexp(search_string)
|
433
|
+
search_body = proc{|mail|
|
434
|
+
if (mail.text? || mail.messge?) then
|
435
|
+
search_regexp.match? encode_charset(mail.mime_charset_body_text)
|
436
|
+
elsif (mail.multipart?) then
|
437
|
+
mail.parts.any?{|next_mail|
|
438
|
+
search_body.call(next_mail)
|
439
|
+
}
|
440
|
+
else
|
441
|
+
false
|
442
|
+
end
|
443
|
+
}
|
444
|
+
else
|
445
|
+
search_string = search_string.b
|
446
|
+
search_regexp = compile_search_regexp(search_string)
|
447
|
+
search_body = proc{|mail|
|
448
|
+
if (mail.text? || mail.message?)then
|
449
|
+
search_regexp.match? mail.mime_binary_body_string
|
450
|
+
elsif (mail.multipart?) then
|
451
|
+
mail.parts.any?{|next_mail|
|
452
|
+
search_body.call(next_mail)
|
453
|
+
}
|
454
|
+
else
|
455
|
+
false
|
456
|
+
end
|
457
|
+
}
|
458
|
+
end
|
459
|
+
|
376
460
|
proc{|next_cond|
|
377
461
|
proc{|msg|
|
378
|
-
if (
|
379
|
-
|
462
|
+
if (mail = get_mail(msg)) then
|
463
|
+
search_body.call(mail) && next_cond.call(msg)
|
380
464
|
else
|
381
465
|
false
|
382
466
|
end
|
@@ -435,20 +519,44 @@ module RIMS
|
|
435
519
|
private :parse_or
|
436
520
|
|
437
521
|
def parse_text(search_string)
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
522
|
+
if (@charset) then
|
523
|
+
search_string = force_charset(search_string)
|
524
|
+
search_regexp = compile_search_regexp(search_string)
|
525
|
+
search_text = proc{|mail|
|
526
|
+
if (search_regexp.match? mail.mime_decoded_header_text(@charset, charset_convert_options: @charset_convert_options)) then
|
527
|
+
true
|
528
|
+
elsif (mail.text? || mail.message?) then
|
529
|
+
search_regexp.match? encode_charset(mail.mime_charset_body_text)
|
530
|
+
elsif (mail.multipart?) then
|
531
|
+
mail.parts.any?{|next_mail|
|
532
|
+
search_text.call(next_mail)
|
533
|
+
}
|
534
|
+
else
|
535
|
+
false
|
536
|
+
end
|
537
|
+
}
|
538
|
+
else
|
539
|
+
search_string = search_string.b
|
540
|
+
search_regexp = compile_search_regexp(search_string)
|
541
|
+
search_text = proc{|mail|
|
542
|
+
if (search_regexp.match? mail.header.raw_source) then
|
543
|
+
true
|
544
|
+
elsif (mail.text? || mail.message?) then
|
545
|
+
search_regexp.match? mail.mime_binary_body_string
|
546
|
+
elsif (mail.multipart?) then
|
547
|
+
mail.parts.any?{|next_mail|
|
548
|
+
search_text.call(next_mail)
|
549
|
+
}
|
550
|
+
else
|
551
|
+
false
|
552
|
+
end
|
553
|
+
}
|
554
|
+
end
|
555
|
+
|
448
556
|
proc{|next_cond|
|
449
557
|
proc{|msg|
|
450
558
|
mail = get_mail(msg)
|
451
|
-
|
559
|
+
search_text.call(mail) && next_cond.call(msg)
|
452
560
|
}
|
453
561
|
}
|
454
562
|
end
|
@@ -768,12 +876,12 @@ module RIMS
|
|
768
876
|
end
|
769
877
|
include Utils
|
770
878
|
|
771
|
-
def initialize(mail_store, folder)
|
879
|
+
def initialize(mail_store, folder, charset_aliases: RFC822::DEFAULT_CHARSET_ALIASES)
|
772
880
|
@mail_store = mail_store
|
773
881
|
@folder = folder
|
774
882
|
@mail_cache = Hash.new{|hash, uid|
|
775
883
|
if (msg_txt = @mail_store.msg_text(@folder.mbox_id, uid)) then
|
776
|
-
hash[uid] = RFC822::Message.new(msg_txt)
|
884
|
+
hash[uid] = RFC822::Message.new(msg_txt, charset_aliases: charset_aliases)
|
777
885
|
end
|
778
886
|
}
|
779
887
|
end
|
data/lib/rims/service.rb
CHANGED
@@ -118,6 +118,7 @@ module RIMS
|
|
118
118
|
# daemon:
|
119
119
|
# daemonize: true
|
120
120
|
# debug: false
|
121
|
+
# umask: 0037
|
121
122
|
# status_file: rims.pid
|
122
123
|
# server_polling_interval_seconds: 3
|
123
124
|
# server_privileged_user: nobody
|
@@ -157,10 +158,29 @@ module RIMS
|
|
157
158
|
# send_buffer_limit_size: 16384
|
158
159
|
# read_polling_interval_seconds: 1
|
159
160
|
# command_wait_timeout_seconds: 1800
|
161
|
+
# protocol:
|
162
|
+
# line_length_limit: 8192
|
163
|
+
# literal_size_limit: 10485760
|
164
|
+
# command_size_limit: 10485760
|
165
|
+
# charset:
|
166
|
+
# use_default_aliases: true
|
167
|
+
# aliases:
|
168
|
+
# - name: euc-jp
|
169
|
+
# encoding: eucJP-ms
|
170
|
+
# - name: ios-2022-jp
|
171
|
+
# encoding: CP50221
|
172
|
+
# - name: Shift_JIS
|
173
|
+
# encoding: Windows-31J
|
174
|
+
# convert_options:
|
175
|
+
# replace_invalid_byte_sequence: false
|
176
|
+
# replace_undefined_character: true
|
177
|
+
# replaced_mark: "\uFFFD"
|
160
178
|
# drb_services:
|
161
179
|
# process_num: 4
|
180
|
+
# load_limit: 134217728
|
162
181
|
# engine:
|
163
182
|
# bulk_response_count: 100
|
183
|
+
# bulk_response_size: 33554432
|
164
184
|
# read_lock_timeout_seconds: 30
|
165
185
|
# write_lock_timeout_seconds: 30
|
166
186
|
# cleanup_write_lock_timeout_seconds: 1
|
@@ -385,9 +405,8 @@ module RIMS
|
|
385
405
|
end
|
386
406
|
|
387
407
|
def daemonize?
|
388
|
-
|
389
|
-
|
390
|
-
daemon_config['daemonize']
|
408
|
+
if (@config.dig('daemon')&.key? 'daemonize') then
|
409
|
+
@config.dig('daemon', 'daemonize')
|
391
410
|
else
|
392
411
|
true
|
393
412
|
end
|
@@ -398,14 +417,17 @@ module RIMS
|
|
398
417
|
end
|
399
418
|
|
400
419
|
def daemon_debug?
|
401
|
-
|
402
|
-
|
403
|
-
daemon_config['debug']
|
420
|
+
if (@config.dig('daemon')&.key? 'debug') then
|
421
|
+
@config.dig('daemon', 'debug')
|
404
422
|
else
|
405
423
|
false
|
406
424
|
end
|
407
425
|
end
|
408
426
|
|
427
|
+
def daemon_umask
|
428
|
+
@config.dig('daemon', 'umask') || 0037
|
429
|
+
end
|
430
|
+
|
409
431
|
def status_file
|
410
432
|
file_path = @config.dig('daemon', 'status_file') || 'rims.pid'
|
411
433
|
file_path = Pathname(file_path)
|
@@ -521,22 +543,20 @@ module RIMS
|
|
521
543
|
end
|
522
544
|
|
523
545
|
def ssl_context
|
524
|
-
if (
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
end
|
530
|
-
|
531
|
-
if (use_ssl) then
|
532
|
-
ssl_context = OpenSSL::SSL::SSLContext.new
|
533
|
-
if (ssl_config_expr = openssl_config['ssl_context']) then
|
534
|
-
anon_mod = SSLContextConfigAttribute.new_module(ssl_context, base_dir)
|
535
|
-
SSLContextConfigAttribute.eval_config(anon_mod, ssl_config_expr, 'ssl_context')
|
536
|
-
end
|
546
|
+
if (@config.dig('openssl')&.key? 'use_ssl') then
|
547
|
+
use_ssl = @config.dig('openssl', 'use_ssl')
|
548
|
+
else
|
549
|
+
use_ssl = (@config.dig('openssl')&.key? 'ssl_context') || false
|
550
|
+
end
|
537
551
|
|
538
|
-
|
552
|
+
if (use_ssl) then
|
553
|
+
ssl_context = OpenSSL::SSL::SSLContext.new
|
554
|
+
if (ssl_config_expr = @config.dig('openssl', 'ssl_context')) then
|
555
|
+
anon_mod = SSLContextConfigAttribute.new_module(ssl_context, base_dir)
|
556
|
+
SSLContextConfigAttribute.eval_config(anon_mod, ssl_config_expr, 'ssl_context')
|
539
557
|
end
|
558
|
+
|
559
|
+
ssl_context
|
540
560
|
end
|
541
561
|
end
|
542
562
|
|
@@ -551,14 +571,102 @@ module RIMS
|
|
551
571
|
@config.dig('connection', 'command_wait_timeout_seconds') || 60 * 30)
|
552
572
|
end
|
553
573
|
|
574
|
+
def protocol_line_length_limit
|
575
|
+
@config.dig('protocol', 'line_length_limit') || 1024 * 8
|
576
|
+
end
|
577
|
+
|
578
|
+
def protocol_literal_size_limit
|
579
|
+
@config.dig('protocol', 'literal_size_limit') || 1024**2 * 10
|
580
|
+
end
|
581
|
+
|
582
|
+
def protocol_command_size_limit
|
583
|
+
@config.dig('protocol', 'command_size_limit') || 1024**2 * 10
|
584
|
+
end
|
585
|
+
|
586
|
+
def charset_aliases
|
587
|
+
charset_aliases = RFC822::CharsetAliases.new
|
588
|
+
|
589
|
+
if (@config.dig('charset')&.key? 'use_default_aliases') then
|
590
|
+
use_default_aliases = @config.dig('charset', 'use_default_aliases')
|
591
|
+
else
|
592
|
+
use_default_aliases = true
|
593
|
+
end
|
594
|
+
|
595
|
+
if (use_default_aliases) then
|
596
|
+
for name, encoding in RFC822::DEFAULT_CHARSET_ALIASES
|
597
|
+
charset_aliases.add_alias(name, encoding)
|
598
|
+
end
|
599
|
+
end
|
600
|
+
|
601
|
+
if (alias_list = @config.dig('charset', 'aliases')) then
|
602
|
+
for an_alias in alias_list
|
603
|
+
charset_aliases.add_alias(an_alias['name'], Encoding.find(an_alias['encoding']))
|
604
|
+
end
|
605
|
+
end
|
606
|
+
|
607
|
+
charset_aliases
|
608
|
+
end
|
609
|
+
|
610
|
+
def charset_convert_options
|
611
|
+
options = {}
|
612
|
+
|
613
|
+
if (@config.dig('charset', 'convert_options')&.key? 'replace_invalid_byte_sequence') then
|
614
|
+
replace_invalid_byte_sequence = @config.dig('charset', 'convert_options', 'replace_invalid_byte_sequence')
|
615
|
+
else
|
616
|
+
replace_invalid_byte_sequence = false
|
617
|
+
end
|
618
|
+
|
619
|
+
if (replace_invalid_byte_sequence) then
|
620
|
+
options[:invalid] = :replace
|
621
|
+
end
|
622
|
+
|
623
|
+
if (@config.dig('charset', 'convert_options')&.key? 'replace_undefined_character') then
|
624
|
+
replace_undefined_character = @config.dig('charset', 'convert_options', 'replace_undefined_character')
|
625
|
+
else
|
626
|
+
replace_undefined_character = true
|
627
|
+
end
|
628
|
+
|
629
|
+
if (replace_undefined_character) then
|
630
|
+
options[:undef] = :replace
|
631
|
+
end
|
632
|
+
|
633
|
+
if (replaced_mark = @config.dig('charset', 'convert_options', 'replaced_mark')) then
|
634
|
+
options[:replace] = replaced_mark
|
635
|
+
end
|
636
|
+
|
637
|
+
options
|
638
|
+
end
|
639
|
+
|
554
640
|
def drb_process_num
|
555
641
|
@config.dig('drb_services', 'process_num') || 0
|
556
642
|
end
|
557
643
|
|
644
|
+
def drb_server_config
|
645
|
+
config = {}
|
646
|
+
if (load_limit = @config.dig('drb_services', 'load_limit')) then
|
647
|
+
config[:load_limit] = load_limit
|
648
|
+
end
|
649
|
+
|
650
|
+
config
|
651
|
+
end
|
652
|
+
|
653
|
+
def drb_client_config
|
654
|
+
config = {}
|
655
|
+
if (load_limit = @config.dig('drb_services', 'load_limit')) then
|
656
|
+
config[:load_limit] = load_limit
|
657
|
+
end
|
658
|
+
|
659
|
+
config
|
660
|
+
end
|
661
|
+
|
558
662
|
def bulk_response_count
|
559
663
|
@config.dig('drb_services', 'engine', 'bulk_response_count') || 100
|
560
664
|
end
|
561
665
|
|
666
|
+
def bulk_response_size
|
667
|
+
@config.dig('drb_services', 'engine', 'bulk_response_size') || 1024**2 * 10
|
668
|
+
end
|
669
|
+
|
562
670
|
def read_lock_timeout_seconds
|
563
671
|
@config.dig('drb_services', 'engine', 'read_lock_timeout_seconds') ||
|
564
672
|
@config.dig('read_lock_timeout_seconds') || # for backward compatibility
|
@@ -639,8 +747,8 @@ module RIMS
|
|
639
747
|
end
|
640
748
|
|
641
749
|
def make_authentication
|
642
|
-
if (
|
643
|
-
auth_conf = @config
|
750
|
+
if (@config.dig('authentication')&.is_a? Hash) then
|
751
|
+
auth_conf = @config.dig('authentication')
|
644
752
|
else
|
645
753
|
auth_conf = {}
|
646
754
|
end
|
@@ -679,8 +787,8 @@ module RIMS
|
|
679
787
|
end
|
680
788
|
|
681
789
|
# for backward compatibility
|
682
|
-
if (
|
683
|
-
plug_in_list = @config
|
790
|
+
if (@config.dig('authentication')&.is_a? Array) then
|
791
|
+
plug_in_list = @config.dig('authentication')
|
684
792
|
for plug_in_conf in plug_in_list
|
685
793
|
plug_in_name = plug_in_conf['plug_in'] or raise KeyError, 'not found an authentication plug_in.'
|
686
794
|
plug_in_config = get_configuration(plug_in_conf)
|
@@ -717,16 +825,16 @@ module RIMS
|
|
717
825
|
using Logger::JointPlus
|
718
826
|
|
719
827
|
def setup(server, daemon: false)
|
720
|
-
file_logger_params = @config.make_file_logger_params
|
721
|
-
logger = Logger.new(*file_logger_params)
|
828
|
+
*file_logger_params, file_logger_opts = @config.make_file_logger_params
|
829
|
+
logger = Logger.new(*file_logger_params, **file_logger_opts)
|
722
830
|
|
723
|
-
stdout_logger_params = @config.make_stdout_logger_params
|
831
|
+
*stdout_logger_params, stdout_logger_opts = @config.make_stdout_logger_params
|
724
832
|
unless (daemon && @config.daemonize?) then
|
725
|
-
logger += Logger.new(*stdout_logger_params)
|
833
|
+
logger += Logger.new(*stdout_logger_params, **stdout_logger_opts)
|
726
834
|
end
|
727
835
|
|
728
|
-
protocol_logger_params = @config.make_protocol_logger_params
|
729
|
-
protocol_logger = Logger.new(*protocol_logger_params)
|
836
|
+
*protocol_logger_params, protocol_logger_opts = @config.make_protocol_logger_params
|
837
|
+
protocol_logger = Logger.new(*protocol_logger_params, **protocol_logger_opts)
|
730
838
|
|
731
839
|
logger.info('preload libraries.')
|
732
840
|
Riser.preload
|
@@ -780,16 +888,21 @@ module RIMS
|
|
780
888
|
end
|
781
889
|
end
|
782
890
|
|
783
|
-
drb_services = Riser::DRbServices.new(drb_process_num
|
891
|
+
drb_services = Riser::DRbServices.new(drb_process_num,
|
892
|
+
server_config: @config.drb_server_config,
|
893
|
+
client_config: @config.drb_client_config)
|
784
894
|
drb_services.add_sticky_process_service(:engine,
|
785
895
|
Riser::ResourceSet.build{|builder|
|
786
896
|
builder.at_create{|unique_user_id|
|
787
897
|
mail_store = MailStore.build(unique_user_id, kvs_meta_open, kvs_text_open)
|
788
898
|
Protocol::Decoder::Engine.new(unique_user_id, mail_store, logger,
|
789
899
|
bulk_response_count: @config.bulk_response_count,
|
900
|
+
bulk_response_size: @config.bulk_response_size,
|
790
901
|
read_lock_timeout_seconds: @config.read_lock_timeout_seconds,
|
791
902
|
write_lock_timeout_seconds: @config.write_lock_timeout_seconds,
|
792
|
-
cleanup_write_lock_timeout_seconds: @config.cleanup_write_lock_timeout_seconds
|
903
|
+
cleanup_write_lock_timeout_seconds: @config.cleanup_write_lock_timeout_seconds,
|
904
|
+
charset_aliases: @config.charset_aliases,
|
905
|
+
charset_convert_options: @config.charset_convert_options)
|
793
906
|
}
|
794
907
|
builder.at_destroy{|engine|
|
795
908
|
engine.destroy
|
@@ -806,17 +919,17 @@ module RIMS
|
|
806
919
|
file_logger_params[1..-2].each_with_index do |value, i|
|
807
920
|
logger.info("file logging parameter: shift_args[#{i}]=#{value}")
|
808
921
|
end
|
809
|
-
for name, value in
|
922
|
+
for name, value in file_logger_opts
|
810
923
|
logger.info("file logging parameter: #{name}=#{value}")
|
811
924
|
end
|
812
|
-
for name, value in
|
925
|
+
for name, value in stdout_logger_opts
|
813
926
|
logger.info("stdout logging parameter: #{name}=#{value}")
|
814
927
|
end
|
815
928
|
logger.info("protocol logging parameter: path=#{protocol_logger_params[0]}")
|
816
929
|
protocol_logger_params[1..-2].each_with_index do |value, i|
|
817
930
|
logger.info("protocol logging parameter: shift_args[#{i}]=#{value}")
|
818
931
|
end
|
819
|
-
for name, value in
|
932
|
+
for name, value in protocol_logger_opts
|
820
933
|
logger.info("protocol logging parameter: #{name}=#{value}")
|
821
934
|
end
|
822
935
|
logger.info("listen address: #{server_socket.local_address.inspect_sockaddr}")
|
@@ -895,11 +1008,27 @@ module RIMS
|
|
895
1008
|
logger.info("connection parameter: send_buffer_limit_size=#{@config.send_buffer_limit_size}")
|
896
1009
|
logger.info("connection parameter: read_polling_interval_seconds=#{conn_limits.read_polling_interval_seconds}")
|
897
1010
|
logger.info("connection parameter: command_wait_timeout_seconds=#{conn_limits.command_wait_timeout_seconds}")
|
1011
|
+
logger.info("protocol parameter: line_length_limit=#{@config.protocol_line_length_limit}")
|
1012
|
+
logger.info("protocol parameter: literal_size_limit=#{@config.protocol_literal_size_limit}")
|
1013
|
+
logger.info("protocol parameter: command_size_limit=#{@config.protocol_command_size_limit}")
|
1014
|
+
@config.charset_aliases.each_with_index do |(name, enc), i|
|
1015
|
+
logger.info("charset aliases parameter: alias[#{i}]: #{name} -> #{enc.name}")
|
1016
|
+
end
|
1017
|
+
for name, value in @config.charset_convert_options
|
1018
|
+
logger.info("charset convert_options parameter: #{name}=#{value}")
|
1019
|
+
end
|
898
1020
|
logger.info("drb_services parameter: process_num=#{drb_process_num}")
|
1021
|
+
for name, value in @config.drb_server_config
|
1022
|
+
logger.info("drb_services server config parameter: #{name}=#{value}")
|
1023
|
+
end
|
1024
|
+
for name, value in @config.drb_client_config
|
1025
|
+
logger.info("drb_services client config parameter: #{name}=#{value}")
|
1026
|
+
end
|
899
1027
|
logger.info("drb_services engine parameter: bulk_response_count=#{@config.bulk_response_count}")
|
900
|
-
logger.info("
|
901
|
-
logger.info("
|
902
|
-
logger.info("
|
1028
|
+
logger.info("drb_services engine parameter: bulk_response_size=#{@config.bulk_response_size}")
|
1029
|
+
logger.info("drb_services engine parameter: read_lock_timeout_seconds=#{@config.read_lock_timeout_seconds}")
|
1030
|
+
logger.info("drb_services engine parameter: write_lock_timeout_seconds=#{@config.write_lock_timeout_seconds}")
|
1031
|
+
logger.info("drb_services engine parameter: cleanup_write_lock_timeout_seconds=#{@config.cleanup_write_lock_timeout_seconds}")
|
903
1032
|
kvs_meta_log.call
|
904
1033
|
kvs_text_log.call
|
905
1034
|
logger.info("authentication parameter: hostname=#{auth.hostname}")
|
@@ -947,7 +1076,11 @@ module RIMS
|
|
947
1076
|
stream = Riser::WriteBufferStream.new(socket, @config.send_buffer_limit_size)
|
948
1077
|
end
|
949
1078
|
stream = Riser::LoggingStream.new(stream, protocol_logger)
|
950
|
-
decoder = Protocol::Decoder.new_decoder(drb_services, auth, logger,
|
1079
|
+
decoder = Protocol::Decoder.new_decoder(drb_services, auth, logger,
|
1080
|
+
mail_delivery_user: @config.mail_delivery_user,
|
1081
|
+
line_length_limit: @config.protocol_line_length_limit,
|
1082
|
+
literal_size_limit: @config.protocol_literal_size_limit,
|
1083
|
+
command_size_limit: @config.protocol_command_size_limit)
|
951
1084
|
Protocol::Decoder.repl(decoder, conn_limits, stream, stream, logger)
|
952
1085
|
ensure
|
953
1086
|
if (stream) then
|