hermeneutics 1.21 → 1.24
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/LICENSE +1 -1
- data/lib/hermeneutics/addrs.rb +5 -27
- data/lib/hermeneutics/cgi.rb +18 -22
- data/lib/hermeneutics/cli/imap.rb +1 -2
- data/lib/hermeneutics/cli/lmtp.rb +183 -0
- data/lib/hermeneutics/cli/pop3.rb +0 -1
- data/lib/hermeneutics/cli/protocol.rb +12 -2
- data/lib/hermeneutics/cli/smtp.rb +1 -8
- data/lib/hermeneutics/color.rb +1 -1
- data/lib/hermeneutics/contents.rb +9 -10
- data/lib/hermeneutics/escape.rb +18 -44
- data/lib/hermeneutics/mail.rb +17 -17
- data/lib/hermeneutics/message.rb +1 -5
- data/lib/hermeneutics/tags.rb +1 -1
- data/lib/hermeneutics/types.rb +6 -0
- data/lib/hermeneutics/version.rb +1 -1
- metadata +4 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: df19436c205dec9d79e7ea6329b0039f73c0df18785684b3497a5beacba86de0
|
|
4
|
+
data.tar.gz: 71249e9f95d7d3b7a5cc4c69de6dcdf8d50312db07d6b4e06e75df798e24a7f6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 53de39c130f7134771b2ae8a03047ddd58ddf8daed8bf1b62e32f3627fe0125324e89a33aec4072cd38e4c5194261322e32d6069533fed8845c352982ca714fc
|
|
7
|
+
data.tar.gz: f3b02d37c1397fa5ddc2bf76247d85b1eef0d99a74d0c3afda583e97d1938ab1a7542c3ea557eec95c0deef199ddd1dfa5e73f3618598af009b8848f7def97d9
|
data/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
= Hermeneutics -- Ruby mail and CGI handling
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2011-
|
|
3
|
+
Copyright (c) 2011-2024, Bertram Scharpf <software@bertram-scharpf.de>.
|
|
4
4
|
All rights reserved.
|
|
5
5
|
|
|
6
6
|
Redistribution and use in source and binary forms, with or without
|
data/lib/hermeneutics/addrs.rb
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
=begin rdoc
|
|
8
8
|
|
|
9
|
-
:section: Classes
|
|
9
|
+
:section: Classes defined here
|
|
10
10
|
|
|
11
11
|
Hermeneutics::Addr is a single address
|
|
12
12
|
Hermeneutics::AddrList is a list of addresses in mail header fields.
|
|
@@ -306,22 +306,6 @@ module Hermeneutics
|
|
|
306
306
|
end
|
|
307
307
|
end
|
|
308
308
|
|
|
309
|
-
def lexer_decode str, &block
|
|
310
|
-
if block_given? then
|
|
311
|
-
HeaderExt.lexer str do |k,s|
|
|
312
|
-
case k
|
|
313
|
-
when :decoded then yield Token[ :char, s, true]
|
|
314
|
-
when :plain then lexer s, &block
|
|
315
|
-
when :space then yield Token[ :space]
|
|
316
|
-
end
|
|
317
|
-
end
|
|
318
|
-
else
|
|
319
|
-
r = []
|
|
320
|
-
lexer_decode str do |t| r.push t end
|
|
321
|
-
r
|
|
322
|
-
end
|
|
323
|
-
end
|
|
324
|
-
|
|
325
309
|
private
|
|
326
310
|
|
|
327
311
|
def escaped h, c
|
|
@@ -432,7 +416,7 @@ module Hermeneutics
|
|
|
432
416
|
# # "Möller, Fritz" <fmoeller@example.com>
|
|
433
417
|
#
|
|
434
418
|
def parse_decode str, &block
|
|
435
|
-
l = Token.
|
|
419
|
+
l = Token.lexer str
|
|
436
420
|
compile l, &block
|
|
437
421
|
end
|
|
438
422
|
|
|
@@ -577,7 +561,8 @@ module Hermeneutics
|
|
|
577
561
|
|
|
578
562
|
class <<self
|
|
579
563
|
def parse cont
|
|
580
|
-
|
|
564
|
+
str = HeaderExt.decode cont
|
|
565
|
+
new.add_quoted str
|
|
581
566
|
end
|
|
582
567
|
end
|
|
583
568
|
|
|
@@ -596,7 +581,7 @@ module Hermeneutics
|
|
|
596
581
|
def push addrs
|
|
597
582
|
case addrs
|
|
598
583
|
when nil then
|
|
599
|
-
when String then
|
|
584
|
+
when String then add_quoted addrs
|
|
600
585
|
when Addr then @list.push addrs
|
|
601
586
|
else addrs.each { |a| push a }
|
|
602
587
|
end
|
|
@@ -681,13 +666,6 @@ module Hermeneutics
|
|
|
681
666
|
self
|
|
682
667
|
end
|
|
683
668
|
|
|
684
|
-
def add_encoded cont
|
|
685
|
-
Addr.parse_decode cont.to_s do |a,|
|
|
686
|
-
@list.push a
|
|
687
|
-
end
|
|
688
|
-
self
|
|
689
|
-
end
|
|
690
|
-
|
|
691
669
|
end
|
|
692
670
|
|
|
693
671
|
end
|
data/lib/hermeneutics/cgi.rb
CHANGED
|
@@ -129,7 +129,7 @@ module Hermeneutics
|
|
|
129
129
|
|
|
130
130
|
def parameters nl: false, sym: false, strip: false
|
|
131
131
|
if block_given? then
|
|
132
|
-
|
|
132
|
+
parameter_data.parse do |k,v,**kw|
|
|
133
133
|
k = k.to_sym if sym
|
|
134
134
|
if v then
|
|
135
135
|
v.strip! if strip
|
|
@@ -146,33 +146,28 @@ module Hermeneutics
|
|
|
146
146
|
end
|
|
147
147
|
end
|
|
148
148
|
|
|
149
|
-
def
|
|
149
|
+
def parameter_data
|
|
150
150
|
case request_method
|
|
151
151
|
when "GET", "HEAD" then
|
|
152
|
-
Data::UrlEnc
|
|
152
|
+
dc, d = Data::UrlEnc, query_string
|
|
153
153
|
when "POST" then
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
warn "Content length #{content_length} is wrong (#{
|
|
154
|
+
d = $stdin.binmode.read
|
|
155
|
+
d.bytesize == content_length.to_i or
|
|
156
|
+
warn "Content length #{content_length} is wrong (#{d.bytesize})."
|
|
157
157
|
ct = ContentType.parse content_type
|
|
158
|
-
|
|
159
|
-
case ct.fulltype
|
|
160
|
-
when "application/x-www-form-urlencoded"
|
|
161
|
-
|
|
162
|
-
when "
|
|
163
|
-
|
|
164
|
-
when "
|
|
165
|
-
|
|
166
|
-
when "application/json" then
|
|
167
|
-
Data::Json.new data
|
|
168
|
-
when "application/x-yaml", "application/yaml" then
|
|
169
|
-
Data::Yaml.new data
|
|
170
|
-
else
|
|
171
|
-
Data::UrlEnc.new data
|
|
158
|
+
d.force_encoding ct[ :charset]||Encoding::ASCII_8BIT
|
|
159
|
+
dc = case ct.fulltype
|
|
160
|
+
when "application/x-www-form-urlencoded" then Data::UrlEnc
|
|
161
|
+
when "multipart/form-data" then a = [ ct.hash] ; Data::Multiparted
|
|
162
|
+
when "text/plain" then Data::Plain
|
|
163
|
+
when "application/json" then Data::Json
|
|
164
|
+
when "application/x-yaml", "application/yaml" then Data::Yaml
|
|
165
|
+
else Data::UrlEnc
|
|
172
166
|
end
|
|
173
167
|
else
|
|
174
|
-
Data::Lines
|
|
168
|
+
dc, d = Data::Lines, read_interactive
|
|
175
169
|
end
|
|
170
|
+
dc.new d, *a
|
|
176
171
|
end
|
|
177
172
|
|
|
178
173
|
|
|
@@ -208,8 +203,9 @@ module Hermeneutics
|
|
|
208
203
|
class Lines < Plain
|
|
209
204
|
def initialize lines
|
|
210
205
|
@lines = lines
|
|
206
|
+
super nil
|
|
211
207
|
end
|
|
212
|
-
def data ; @lines.join "\n" ; end
|
|
208
|
+
def data ; @data ||= @lines.join "\n" ; end
|
|
213
209
|
def parse
|
|
214
210
|
@lines.each { |s|
|
|
215
211
|
k, v = s.split %r/=/
|
|
@@ -16,7 +16,6 @@ module Hermeneutics
|
|
|
16
16
|
|
|
17
17
|
PORT, PORT_SSL = 143, 993
|
|
18
18
|
|
|
19
|
-
class Error < StandardError ; end
|
|
20
19
|
class UnspecResponse < Error ; end
|
|
21
20
|
class ServerBye < Error ; end
|
|
22
21
|
class ServerError < Error ; end
|
|
@@ -37,7 +36,7 @@ module Hermeneutics
|
|
|
37
36
|
|
|
38
37
|
def initialize *args
|
|
39
38
|
super
|
|
40
|
-
@tag = "
|
|
39
|
+
@tag = "%s%04d" % [ TAG_PREFIX, 0]
|
|
41
40
|
@info = [ get_response]
|
|
42
41
|
start_watch
|
|
43
42
|
end
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
#
|
|
2
|
+
# lib/hermeneutics/cli/lmtp.rb -- LMTP client
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
require "hermeneutics/cli/protocol"
|
|
6
|
+
|
|
7
|
+
module Hermeneutics
|
|
8
|
+
|
|
9
|
+
module Cli
|
|
10
|
+
|
|
11
|
+
class LMTP < Protocol
|
|
12
|
+
|
|
13
|
+
CRLF = true
|
|
14
|
+
|
|
15
|
+
class UnspecError < Error ; end
|
|
16
|
+
class ServerNotReady < Error ; end
|
|
17
|
+
class NotOk < Error ; end
|
|
18
|
+
class NotReadyForData < Error ; end
|
|
19
|
+
class Unused < Error ; end
|
|
20
|
+
class Uncaught < Error ; end
|
|
21
|
+
|
|
22
|
+
class <<self
|
|
23
|
+
private :new
|
|
24
|
+
def open socketfile
|
|
25
|
+
UNIXSocket.open socketfile do |s|
|
|
26
|
+
i = new s, nil
|
|
27
|
+
yield i
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
attr_reader :domain, :greet
|
|
33
|
+
attr_reader :advertised
|
|
34
|
+
attr_reader :last_response
|
|
35
|
+
|
|
36
|
+
def initialize *args
|
|
37
|
+
super
|
|
38
|
+
get_response.ok? or raise ServerNotReady, @last_response.msg
|
|
39
|
+
@rcpt = 0
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def size
|
|
43
|
+
@advertised && @advertised[ :SIZE]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def lhlo host = nil
|
|
48
|
+
@advertised = {}
|
|
49
|
+
write_cmd "LHLO", host||Socket.gethostname
|
|
50
|
+
get_response_ok do |code,msg|
|
|
51
|
+
unless @domain then
|
|
52
|
+
@domain, @greet = msg.split nil, 2
|
|
53
|
+
next
|
|
54
|
+
end
|
|
55
|
+
keyword, param = msg.split nil, 2
|
|
56
|
+
keyword.upcase!
|
|
57
|
+
keyword = keyword.to_sym
|
|
58
|
+
case keyword
|
|
59
|
+
when :SIZE then param = Integer param
|
|
60
|
+
when :AUTH then param = param.split.map { |p| p.upcase! ; p.to_sym }
|
|
61
|
+
end
|
|
62
|
+
@advertised[ keyword] = param || true
|
|
63
|
+
end
|
|
64
|
+
unless @domain then
|
|
65
|
+
@domain, @greet = @last_response.msg.split nil, 2
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def mail_from from
|
|
70
|
+
cmd "MAIL", "FROM:<#{from}>"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def rcpt_to to
|
|
74
|
+
cmd "RCPT", "TO:<#{to}>"
|
|
75
|
+
@rcpt += 1
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def data reader
|
|
79
|
+
write_cmd "DATA"
|
|
80
|
+
get_response.waiting? or raise NotReadyForData, @last_response.msg
|
|
81
|
+
reader.each_line { |l|
|
|
82
|
+
l =~ /\A\./ and l = ".#{l}"
|
|
83
|
+
writeline l
|
|
84
|
+
}
|
|
85
|
+
writeline "."
|
|
86
|
+
get_response_rcpts
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def bdat data
|
|
90
|
+
data.each { |d|
|
|
91
|
+
write_cmd "BDAT", d.bytesize
|
|
92
|
+
write d
|
|
93
|
+
get_response_ok
|
|
94
|
+
}
|
|
95
|
+
write_cmd "BDAT", 0, "LAST"
|
|
96
|
+
get_response_rcpts
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def rset
|
|
100
|
+
cmd "RSET"
|
|
101
|
+
ensure
|
|
102
|
+
@rcpt = 0
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def noop str = nil
|
|
106
|
+
cmd "NOOP"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def quit
|
|
110
|
+
cmd "QUIT"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
private
|
|
115
|
+
|
|
116
|
+
def cmd name, *args, &block
|
|
117
|
+
write_cmd name, *args
|
|
118
|
+
get_response_ok &block
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def write_cmd name, *args
|
|
122
|
+
l = [ name, *args].join " "
|
|
123
|
+
writeline l
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
class Response
|
|
127
|
+
|
|
128
|
+
attr_reader :code, :msg
|
|
129
|
+
|
|
130
|
+
def initialize code, msg
|
|
131
|
+
@code, @msg = code, msg
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def kat ; code / 100 ; end
|
|
135
|
+
|
|
136
|
+
def to_s ; "%03d %s" % [ @code, @msg] ; end
|
|
137
|
+
|
|
138
|
+
def prelim? ; kat == 1 ; end
|
|
139
|
+
def ok? ; kat == 2 ; end
|
|
140
|
+
def waiting? ; kat == 3 ; end
|
|
141
|
+
def error? ; kat == 4 ; end
|
|
142
|
+
def fatal? ; kat == 5 ; end
|
|
143
|
+
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def get_response_ok &block
|
|
147
|
+
get_response &block
|
|
148
|
+
@last_response.ok? or raise NotOk, @last_response.msg
|
|
149
|
+
true
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def get_response
|
|
153
|
+
loop do
|
|
154
|
+
r = readline
|
|
155
|
+
if r =~ /\A(\d\d\d) / then
|
|
156
|
+
@last_response = Response.new $1.to_i, $'
|
|
157
|
+
break @last_response
|
|
158
|
+
elsif r =~ /\A(\d\d\d)-/ then
|
|
159
|
+
block_given? or raise Uncaught, r
|
|
160
|
+
yield $1.to_i, $'
|
|
161
|
+
else
|
|
162
|
+
raise UnspecError, r
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def get_response_rcpts
|
|
168
|
+
r = []
|
|
169
|
+
@rcpt.times {
|
|
170
|
+
r.push get_response
|
|
171
|
+
@last_response.ok? or raise NotOk, @last_response.msg
|
|
172
|
+
}
|
|
173
|
+
r
|
|
174
|
+
ensure
|
|
175
|
+
@rcpt = 0
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
end
|
|
183
|
+
|
|
@@ -22,8 +22,12 @@ module Hermeneutics
|
|
|
22
22
|
|
|
23
23
|
module Cli
|
|
24
24
|
|
|
25
|
+
|
|
25
26
|
class Protocol
|
|
26
27
|
|
|
28
|
+
class Error < StandardError ; end
|
|
29
|
+
class Timeout < Error ; end
|
|
30
|
+
|
|
27
31
|
class <<self
|
|
28
32
|
private :new
|
|
29
33
|
def open host, port, timeout: nil, ssl: false
|
|
@@ -80,7 +84,7 @@ module Hermeneutics
|
|
|
80
84
|
end
|
|
81
85
|
|
|
82
86
|
def readline
|
|
83
|
-
|
|
87
|
+
wait
|
|
84
88
|
r = @socket.readline
|
|
85
89
|
r.chomp!
|
|
86
90
|
@trace and $stderr.puts "S: #{r}"
|
|
@@ -94,7 +98,7 @@ module Hermeneutics
|
|
|
94
98
|
end
|
|
95
99
|
|
|
96
100
|
def read bytes
|
|
97
|
-
|
|
101
|
+
wait
|
|
98
102
|
r = @socket.read bytes
|
|
99
103
|
@trace and $stderr.puts "S- #{r.inspect}"
|
|
100
104
|
r
|
|
@@ -105,6 +109,12 @@ module Hermeneutics
|
|
|
105
109
|
not @socket.ready?
|
|
106
110
|
end
|
|
107
111
|
|
|
112
|
+
def wait
|
|
113
|
+
if @timeout then
|
|
114
|
+
raise Timeout unless @socket.wait @timeout
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
108
118
|
end
|
|
109
119
|
|
|
110
120
|
|
|
@@ -14,7 +14,6 @@ module Hermeneutics
|
|
|
14
14
|
|
|
15
15
|
PORT, PORT_SSL = 25, 465
|
|
16
16
|
|
|
17
|
-
class Error < StandardError ; end
|
|
18
17
|
class UnspecError < Error ; end
|
|
19
18
|
class ServerNotReady < Error ; end
|
|
20
19
|
class NotOk < Error ; end
|
|
@@ -194,7 +193,7 @@ module Hermeneutics
|
|
|
194
193
|
r = readline
|
|
195
194
|
if r =~ /\A(\d\d\d) / then
|
|
196
195
|
@last_response = Response.new $1.to_i, $'
|
|
197
|
-
break
|
|
196
|
+
break @last_response
|
|
198
197
|
elsif r =~ /\A(\d\d\d)-/ then
|
|
199
198
|
block_given? or raise Uncaught, r
|
|
200
199
|
yield $1.to_i, $'
|
|
@@ -202,12 +201,6 @@ module Hermeneutics
|
|
|
202
201
|
raise UnspecError, r
|
|
203
202
|
end
|
|
204
203
|
end
|
|
205
|
-
@last_response
|
|
206
|
-
ensure
|
|
207
|
-
unless done? then
|
|
208
|
-
r = readline
|
|
209
|
-
r and raise Unused, "Unexpected data: #{r.inspect}"
|
|
210
|
-
end
|
|
211
204
|
end
|
|
212
205
|
|
|
213
206
|
end
|
data/lib/hermeneutics/color.rb
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
=begin rdoc
|
|
6
6
|
|
|
7
|
-
:section: Classes
|
|
7
|
+
:section: Classes defined here
|
|
8
8
|
|
|
9
9
|
Hermeneutics::Contents is a content field parser.
|
|
10
10
|
|
|
@@ -44,9 +44,9 @@ module Hermeneutics
|
|
|
44
44
|
# ds[ "a"] #=> "0123456"
|
|
45
45
|
#
|
|
46
46
|
def parse line
|
|
47
|
-
rest = line
|
|
48
|
-
|
|
49
|
-
new
|
|
47
|
+
rest = HeaderExt.decode line
|
|
48
|
+
rest.strip!
|
|
49
|
+
new *(build_args rest)
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def urltext
|
|
@@ -55,7 +55,7 @@ module Hermeneutics
|
|
|
55
55
|
|
|
56
56
|
private
|
|
57
57
|
|
|
58
|
-
def
|
|
58
|
+
def build_args rest
|
|
59
59
|
hash = Hash.new { |h,k| h[ k] = [] }
|
|
60
60
|
asts = {}
|
|
61
61
|
while rest.notempty? do
|
|
@@ -66,6 +66,7 @@ module Hermeneutics
|
|
|
66
66
|
else
|
|
67
67
|
[ rest.dup, ""]
|
|
68
68
|
end
|
|
69
|
+
rest.lstrip!
|
|
69
70
|
key.downcase!
|
|
70
71
|
key = key.to_sym
|
|
71
72
|
asts[ key] = ast
|
|
@@ -91,7 +92,7 @@ module Hermeneutics
|
|
|
91
92
|
end
|
|
92
93
|
r[ k] = v
|
|
93
94
|
}
|
|
94
|
-
r
|
|
95
|
+
[ r]
|
|
95
96
|
end
|
|
96
97
|
|
|
97
98
|
end
|
|
@@ -236,11 +237,9 @@ module Hermeneutics
|
|
|
236
237
|
# c.caption #=> "text/html"
|
|
237
238
|
# c[ :boundary] #=> "0123456"
|
|
238
239
|
#
|
|
239
|
-
def
|
|
240
|
-
rest = line.strip
|
|
240
|
+
def build_args rest
|
|
241
241
|
caption, rest = rest.split Dictionary::RES, 2
|
|
242
|
-
|
|
243
|
-
new caption, hash
|
|
242
|
+
[ caption, *(super rest)]
|
|
244
243
|
end
|
|
245
244
|
|
|
246
245
|
end
|
data/lib/hermeneutics/escape.rb
CHANGED
|
@@ -9,7 +9,7 @@ require "supplement"
|
|
|
9
9
|
|
|
10
10
|
=begin rdoc
|
|
11
11
|
|
|
12
|
-
:section: Classes
|
|
12
|
+
:section: Classes defined here
|
|
13
13
|
|
|
14
14
|
Hermeneutics::Entities encodes to and decodes from HTML-Entities
|
|
15
15
|
(+&+ etc.)
|
|
@@ -235,7 +235,7 @@ module Hermeneutics
|
|
|
235
235
|
# representing the ASCII code. Eight bit characters should be masked the
|
|
236
236
|
# same way.
|
|
237
237
|
#
|
|
238
|
-
#
|
|
238
|
+
# A URL line does not store encoding information by itself. A locator may
|
|
239
239
|
# either say one of these:
|
|
240
240
|
#
|
|
241
241
|
# http://www.example.com/subdir/index.html?umlfield=%C3%BCber+alles
|
|
@@ -401,11 +401,12 @@ module Hermeneutics
|
|
|
401
401
|
#
|
|
402
402
|
def mkurl path, hash = nil, anchor = nil
|
|
403
403
|
unless Hash === hash then
|
|
404
|
-
hash, anchor = anchor,
|
|
404
|
+
hash, anchor = anchor, nil
|
|
405
405
|
end
|
|
406
|
-
r = "
|
|
407
|
-
r <<
|
|
408
|
-
r << "
|
|
406
|
+
r = ""
|
|
407
|
+
r << path.to_s
|
|
408
|
+
r << "?" << (encode_hash hash) if hash
|
|
409
|
+
r << "#" << anchor.to_s if anchor
|
|
409
410
|
r
|
|
410
411
|
end
|
|
411
412
|
|
|
@@ -726,28 +727,18 @@ module Hermeneutics
|
|
|
726
727
|
#
|
|
727
728
|
def decode str
|
|
728
729
|
r, e = [], []
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
elsif l == :plain then
|
|
737
|
-
r.push SPACE
|
|
738
|
-
end
|
|
739
|
-
when :space then
|
|
740
|
-
nil
|
|
741
|
-
when :plain then
|
|
742
|
-
if l == :decoded then
|
|
743
|
-
r.push SPACE
|
|
744
|
-
end
|
|
730
|
+
loop do
|
|
731
|
+
if str =~ /=\?([a-z0-9_-]+?)\?([QB])\?([!-~]+?)\?=/i then
|
|
732
|
+
p = $`
|
|
733
|
+
d = unmask $1, $2, $3
|
|
734
|
+
str = $'
|
|
735
|
+
else
|
|
736
|
+
p = str
|
|
745
737
|
end
|
|
746
|
-
r.push
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
r.pop
|
|
738
|
+
r.push p if p =~ /\S/
|
|
739
|
+
d or break
|
|
740
|
+
r.push d
|
|
741
|
+
e.push d.encoding
|
|
751
742
|
end
|
|
752
743
|
e.uniq!
|
|
753
744
|
begin
|
|
@@ -760,23 +751,6 @@ module Hermeneutics
|
|
|
760
751
|
end
|
|
761
752
|
end
|
|
762
753
|
|
|
763
|
-
def lexer str
|
|
764
|
-
while str do
|
|
765
|
-
str =~ /(\s+)|\B=\?(\S*?)\?([QB])\?(\S*?)\?=\B/i
|
|
766
|
-
if $1 then
|
|
767
|
-
yield :plain, $` unless $`.empty?
|
|
768
|
-
yield :space, $&
|
|
769
|
-
elsif $2 then
|
|
770
|
-
yield :plain, $` unless $`.empty?
|
|
771
|
-
d = unmask $2, $3, $4
|
|
772
|
-
yield :decoded, d
|
|
773
|
-
else
|
|
774
|
-
yield :plain, str
|
|
775
|
-
end
|
|
776
|
-
str = $'.notempty?
|
|
777
|
-
end
|
|
778
|
-
end
|
|
779
|
-
|
|
780
754
|
private
|
|
781
755
|
|
|
782
756
|
def unmask cs, tp, txt
|
data/lib/hermeneutics/mail.rb
CHANGED
|
@@ -248,7 +248,7 @@ module Hermeneutics
|
|
|
248
248
|
}
|
|
249
249
|
open_smtp conn do |smtp|
|
|
250
250
|
log :INF, "Sending to", *tos
|
|
251
|
-
smtp.mail_from headers.from.first.plain
|
|
251
|
+
headers.from.empty? or smtp.mail_from headers.from.first.plain
|
|
252
252
|
tos.each { |t| smtp.rcpt_to t }
|
|
253
253
|
smtp.data m
|
|
254
254
|
end
|
|
@@ -261,22 +261,22 @@ module Hermeneutics
|
|
|
261
261
|
def open_smtp arg, &block
|
|
262
262
|
if [ :mail_from, :rcpt_to, :data].map { |m| arg.respond_to? m }.all? then
|
|
263
263
|
yield arg
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
264
|
+
else
|
|
265
|
+
a = {}
|
|
266
|
+
case arg
|
|
267
|
+
when nil then h, p = "localhost", nil
|
|
268
|
+
when String then h, p = arg.split ":" ; p &&= Integer p
|
|
269
|
+
when Array then h, p = *arg
|
|
270
|
+
when Hash then a = arg.clone ; h, p = (a.delete :host), (a.delete :port)
|
|
271
|
+
else h, p = arg.host, arg.port ; arg.scheme == "smtps" and a[ :ssl] = true
|
|
272
|
+
end
|
|
273
|
+
require "hermeneutics/cli/smtp"
|
|
274
|
+
Cli::SMTP.open h, p, **a do |smtp|
|
|
275
|
+
smtp.helo
|
|
276
|
+
yield smtp
|
|
277
|
+
ensure
|
|
278
|
+
smtp.quit
|
|
279
|
+
end
|
|
280
280
|
end
|
|
281
281
|
end
|
|
282
282
|
|
data/lib/hermeneutics/message.rb
CHANGED
|
@@ -146,11 +146,7 @@ module Hermeneutics
|
|
|
146
146
|
|
|
147
147
|
def contents type = nil
|
|
148
148
|
if type then
|
|
149
|
-
|
|
150
|
-
if not @contents.is_a? type then
|
|
151
|
-
@contents = type.parse @data
|
|
152
|
-
end
|
|
153
|
-
else
|
|
149
|
+
unless @contents and (@contents.is_a? type) then
|
|
154
150
|
@contents = type.parse @data
|
|
155
151
|
end
|
|
156
152
|
else
|
data/lib/hermeneutics/tags.rb
CHANGED
data/lib/hermeneutics/types.rb
CHANGED
data/lib/hermeneutics/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hermeneutics
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: '1.
|
|
4
|
+
version: '1.24'
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bertram Scharpf
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: supplement
|
|
@@ -59,6 +58,7 @@ files:
|
|
|
59
58
|
- lib/hermeneutics/cli/imap/commands.rb
|
|
60
59
|
- lib/hermeneutics/cli/imap/parser.rb
|
|
61
60
|
- lib/hermeneutics/cli/imap/utf7imap.rb
|
|
61
|
+
- lib/hermeneutics/cli/lmtp.rb
|
|
62
62
|
- lib/hermeneutics/cli/openssl.rb
|
|
63
63
|
- lib/hermeneutics/cli/pop3.rb
|
|
64
64
|
- lib/hermeneutics/cli/protocol.rb
|
|
@@ -77,7 +77,6 @@ homepage: http://www.bertram-scharpf.de
|
|
|
77
77
|
licenses:
|
|
78
78
|
- BSD-2-Clause
|
|
79
79
|
metadata: {}
|
|
80
|
-
post_install_message:
|
|
81
80
|
rdoc_options:
|
|
82
81
|
- "--charset"
|
|
83
82
|
- utf-8
|
|
@@ -97,8 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
97
96
|
version: '0'
|
|
98
97
|
requirements:
|
|
99
98
|
- Ruby, at least 3.0
|
|
100
|
-
rubygems_version: 3.
|
|
101
|
-
signing_key:
|
|
99
|
+
rubygems_version: 3.7.1
|
|
102
100
|
specification_version: 4
|
|
103
101
|
summary: CGI and mail handling
|
|
104
102
|
test_files: []
|