sup 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +12 -0
- data/CONTRIBUTORS +84 -0
- data/Gemfile +3 -0
- data/HACKING +42 -0
- data/History.txt +361 -0
- data/LICENSE +280 -0
- data/README.md +70 -0
- data/Rakefile +12 -0
- data/ReleaseNotes +231 -0
- data/bin/sup +434 -0
- data/bin/sup-add +118 -0
- data/bin/sup-config +243 -0
- data/bin/sup-dump +43 -0
- data/bin/sup-import-dump +101 -0
- data/bin/sup-psych-ify-config-files +21 -0
- data/bin/sup-recover-sources +87 -0
- data/bin/sup-sync +210 -0
- data/bin/sup-sync-back-maildir +127 -0
- data/bin/sup-tweak-labels +140 -0
- data/contrib/colorpicker.rb +100 -0
- data/contrib/completion/_sup.zsh +114 -0
- data/devel/console.sh +3 -0
- data/devel/count-loc.sh +3 -0
- data/devel/load-index.rb +9 -0
- data/devel/profile.rb +12 -0
- data/devel/start-console.rb +5 -0
- data/doc/FAQ.txt +119 -0
- data/doc/Hooks.txt +79 -0
- data/doc/Philosophy.txt +69 -0
- data/lib/sup.rb +467 -0
- data/lib/sup/account.rb +90 -0
- data/lib/sup/buffer.rb +768 -0
- data/lib/sup/colormap.rb +239 -0
- data/lib/sup/contact.rb +67 -0
- data/lib/sup/crypto.rb +461 -0
- data/lib/sup/draft.rb +119 -0
- data/lib/sup/hook.rb +159 -0
- data/lib/sup/horizontal_selector.rb +59 -0
- data/lib/sup/idle.rb +42 -0
- data/lib/sup/index.rb +882 -0
- data/lib/sup/interactive_lock.rb +89 -0
- data/lib/sup/keymap.rb +140 -0
- data/lib/sup/label.rb +87 -0
- data/lib/sup/logger.rb +77 -0
- data/lib/sup/logger/singleton.rb +10 -0
- data/lib/sup/maildir.rb +257 -0
- data/lib/sup/mbox.rb +187 -0
- data/lib/sup/message.rb +803 -0
- data/lib/sup/message_chunks.rb +328 -0
- data/lib/sup/mode.rb +140 -0
- data/lib/sup/modes/buffer_list_mode.rb +50 -0
- data/lib/sup/modes/completion_mode.rb +55 -0
- data/lib/sup/modes/compose_mode.rb +38 -0
- data/lib/sup/modes/console_mode.rb +125 -0
- data/lib/sup/modes/contact_list_mode.rb +148 -0
- data/lib/sup/modes/edit_message_async_mode.rb +110 -0
- data/lib/sup/modes/edit_message_mode.rb +728 -0
- data/lib/sup/modes/file_browser_mode.rb +109 -0
- data/lib/sup/modes/forward_mode.rb +82 -0
- data/lib/sup/modes/help_mode.rb +19 -0
- data/lib/sup/modes/inbox_mode.rb +85 -0
- data/lib/sup/modes/label_list_mode.rb +138 -0
- data/lib/sup/modes/label_search_results_mode.rb +38 -0
- data/lib/sup/modes/line_cursor_mode.rb +203 -0
- data/lib/sup/modes/log_mode.rb +57 -0
- data/lib/sup/modes/person_search_results_mode.rb +12 -0
- data/lib/sup/modes/poll_mode.rb +19 -0
- data/lib/sup/modes/reply_mode.rb +228 -0
- data/lib/sup/modes/resume_mode.rb +52 -0
- data/lib/sup/modes/scroll_mode.rb +252 -0
- data/lib/sup/modes/search_list_mode.rb +204 -0
- data/lib/sup/modes/search_results_mode.rb +59 -0
- data/lib/sup/modes/text_mode.rb +76 -0
- data/lib/sup/modes/thread_index_mode.rb +1033 -0
- data/lib/sup/modes/thread_view_mode.rb +941 -0
- data/lib/sup/person.rb +134 -0
- data/lib/sup/poll.rb +272 -0
- data/lib/sup/rfc2047.rb +56 -0
- data/lib/sup/search.rb +110 -0
- data/lib/sup/sent.rb +58 -0
- data/lib/sup/service/label_service.rb +45 -0
- data/lib/sup/source.rb +244 -0
- data/lib/sup/tagger.rb +50 -0
- data/lib/sup/textfield.rb +253 -0
- data/lib/sup/thread.rb +452 -0
- data/lib/sup/time.rb +93 -0
- data/lib/sup/undo.rb +38 -0
- data/lib/sup/update.rb +30 -0
- data/lib/sup/util.rb +747 -0
- data/lib/sup/util/ncurses.rb +274 -0
- data/lib/sup/util/path.rb +9 -0
- data/lib/sup/util/query.rb +17 -0
- data/lib/sup/util/uri.rb +15 -0
- data/lib/sup/version.rb +3 -0
- data/sup.gemspec +53 -0
- data/test/dummy_source.rb +61 -0
- data/test/gnupg_test_home/gpg.conf +1 -0
- data/test/gnupg_test_home/pubring.gpg +0 -0
- data/test/gnupg_test_home/receiver_pubring.gpg +0 -0
- data/test/gnupg_test_home/receiver_secring.gpg +0 -0
- data/test/gnupg_test_home/receiver_trustdb.gpg +0 -0
- data/test/gnupg_test_home/secring.gpg +0 -0
- data/test/gnupg_test_home/sup-test-2@foo.bar.asc +20 -0
- data/test/gnupg_test_home/trustdb.gpg +0 -0
- data/test/integration/test_label_service.rb +18 -0
- data/test/messages/bad-content-transfer-encoding-1.eml +8 -0
- data/test/messages/binary-content-transfer-encoding-2.eml +21 -0
- data/test/messages/missing-line.eml +9 -0
- data/test/test_crypto.rb +109 -0
- data/test/test_header_parsing.rb +168 -0
- data/test/test_helper.rb +7 -0
- data/test/test_message.rb +532 -0
- data/test/test_messages_dir.rb +147 -0
- data/test/test_yaml_migration.rb +85 -0
- data/test/test_yaml_regressions.rb +17 -0
- data/test/unit/service/test_label_service.rb +19 -0
- data/test/unit/test_horizontal_selector.rb +40 -0
- data/test/unit/util/test_query.rb +46 -0
- data/test/unit/util/test_string.rb +57 -0
- data/test/unit/util/test_uri.rb +19 -0
- metadata +423 -0
@@ -0,0 +1,274 @@
|
|
1
|
+
require 'ncursesw'
|
2
|
+
require 'sup/util'
|
3
|
+
|
4
|
+
if defined? Ncurses
|
5
|
+
module Ncurses
|
6
|
+
|
7
|
+
## Helper class for storing keycodes
|
8
|
+
## and multibyte characters.
|
9
|
+
class CharCode < String
|
10
|
+
## Status code allows us to detect
|
11
|
+
## printable characters and control codes.
|
12
|
+
attr_reader :status
|
13
|
+
|
14
|
+
## Reads character from user input.
|
15
|
+
def self.nonblocking_getwch
|
16
|
+
# If we get input while we're shelled, we'll ignore it for the
|
17
|
+
# moment and use Ncurses.sync to wait until the shell_out is done.
|
18
|
+
begin
|
19
|
+
s, c = Redwood::BufferManager.shelled? ? Ncurses.sync { nil } : Ncurses.get_wch
|
20
|
+
break if s != Ncurses::ERR
|
21
|
+
end until IO.select([$stdin], nil, nil, 2)
|
22
|
+
[s, c]
|
23
|
+
end
|
24
|
+
|
25
|
+
## Returns empty singleton.
|
26
|
+
def self.empty
|
27
|
+
Empty.instance
|
28
|
+
end
|
29
|
+
|
30
|
+
## Creates new instance of CharCode
|
31
|
+
## that keeps a given keycode.
|
32
|
+
def self.keycode(c)
|
33
|
+
generate c, Ncurses::KEY_CODE_YES
|
34
|
+
end
|
35
|
+
|
36
|
+
## Creates new instance of CharCode
|
37
|
+
## that keeps a printable character.
|
38
|
+
def self.character(c)
|
39
|
+
generate c, Ncurses::OK
|
40
|
+
end
|
41
|
+
|
42
|
+
## Generates new object like new
|
43
|
+
## but for empty or erroneous objects
|
44
|
+
## it returns empty singleton.
|
45
|
+
def self.generate(c = nil, status = Ncurses::OK)
|
46
|
+
if status == Ncurses::ERR || c.nil? || c === Ncurses::ERR
|
47
|
+
empty
|
48
|
+
else
|
49
|
+
new(c, status)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
## Gets character from input.
|
54
|
+
## Pretends ctrl-c's are ctrl-g's.
|
55
|
+
def self.get handle_interrupt=true
|
56
|
+
begin
|
57
|
+
status, code = nonblocking_getwch
|
58
|
+
generate code, status
|
59
|
+
rescue Interrupt => e
|
60
|
+
raise e unless handle_interrupt
|
61
|
+
keycode Ncurses::KEY_CANCEL
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
## Enables dumb mode for any new instance.
|
66
|
+
def self.dumb!
|
67
|
+
@dumb = true
|
68
|
+
end
|
69
|
+
|
70
|
+
## Asks if dumb mode was set
|
71
|
+
def self.dumb?
|
72
|
+
defined?(@dumb) && @dumb
|
73
|
+
end
|
74
|
+
|
75
|
+
def initialize(c = "", status = Ncurses::OK)
|
76
|
+
@status = status
|
77
|
+
c = "" if c.nil?
|
78
|
+
return super("") if status == Ncurses::ERR
|
79
|
+
c = enc_char(c) if c.is_a?(Fixnum)
|
80
|
+
super c.length > 1 ? c[0,1] : c
|
81
|
+
end
|
82
|
+
|
83
|
+
## Proxy method for String's replace
|
84
|
+
def replace(c)
|
85
|
+
return self if c.object_id == object_id
|
86
|
+
if c.is_a?(self.class)
|
87
|
+
@status = c.status
|
88
|
+
super(c)
|
89
|
+
else
|
90
|
+
@status = Ncurses::OK
|
91
|
+
c = "" if c.nil?
|
92
|
+
c = enc_char(c) if c.is_a?(Fixnum)
|
93
|
+
super c.length > 1 ? c[0,1] : c
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_character ; character? ? self : "<#{code}>" end ## Returns character or code as a string
|
98
|
+
def to_keycode ; keycode? ? code : Ncurses::ERR end ## Returns keycode or ERR if it's not a keycode
|
99
|
+
def to_sequence ; bytes.to_a end ## Returns unpacked sequence of bytes for a character
|
100
|
+
def code ; ord end ## Returns decimal representation of a character
|
101
|
+
def is_keycode?(c) ; keycode? && code == c end ## Tests if keycode matches
|
102
|
+
def is_character?(c); character? && self == c end ## Tests if character matches
|
103
|
+
def try_keycode ; keycode? ? code : nil end ## Returns dec. code if keycode, nil otherwise
|
104
|
+
def try_character ; character? ? self : nil end ## Returns character if character, nil otherwise
|
105
|
+
def keycode ; try_keycode end ## Alias for try_keycode
|
106
|
+
def character ; try_character end ## Alias for try_character
|
107
|
+
def character? ; dumb? || @status == Ncurses::OK end ## Returns true if character
|
108
|
+
def character! ; @status = Ncurses::OK ; self end ## Sets character flag
|
109
|
+
def keycode? ; dumb? || @status == Ncurses::KEY_CODE_YES end ## Returns true if keycode
|
110
|
+
def keycode! ; @status = Ncurses::KEY_CODE_YES ; self end ## Sets keycode flag
|
111
|
+
def keycode=(c) ; replace(c); keycode! ; self end ## Sets keycode
|
112
|
+
def present? ; not empty? end ## Proxy method
|
113
|
+
def printable? ; character? end ## Alias for character?
|
114
|
+
def dumb? ; self.class.dumb? end ## True if we cannot distinguish keycodes from characters
|
115
|
+
|
116
|
+
# Empty singleton that
|
117
|
+
# keeps GC from going crazy.
|
118
|
+
class Empty < CharCode
|
119
|
+
include Redwood::Singleton
|
120
|
+
|
121
|
+
## Wrap methods that may change us
|
122
|
+
## and generate new object instead.
|
123
|
+
[ :"[]=", :"<<", :replace, :insert, :prepend, :append, :concat, :force_encoding, :setbyte ].
|
124
|
+
select{ |m| public_method_defined?(m) }.
|
125
|
+
concat(public_instance_methods.grep(/!\z/)).
|
126
|
+
each do |m|
|
127
|
+
class_eval <<-EVAL
|
128
|
+
def #{m}(*args)
|
129
|
+
CharCode.new.#{m}(*args)
|
130
|
+
end
|
131
|
+
EVAL
|
132
|
+
end
|
133
|
+
|
134
|
+
## proxy with class-level instance variable delegation
|
135
|
+
def self.dumb?
|
136
|
+
superclass.dumb? or !!@dumb
|
137
|
+
end
|
138
|
+
|
139
|
+
def self.empty
|
140
|
+
instance
|
141
|
+
end
|
142
|
+
|
143
|
+
def initialize
|
144
|
+
super("", Ncurses::ERR)
|
145
|
+
end
|
146
|
+
|
147
|
+
def empty? ; true end ## always true
|
148
|
+
def present? ; false end ## always false
|
149
|
+
def clear ; self end ## always self
|
150
|
+
|
151
|
+
self
|
152
|
+
end.init # CharCode::Empty
|
153
|
+
|
154
|
+
private
|
155
|
+
|
156
|
+
## Tries to make external character right.
|
157
|
+
def enc_char(c)
|
158
|
+
begin
|
159
|
+
character = c.chr($encoding)
|
160
|
+
rescue RangeError, ArgumentError
|
161
|
+
begin
|
162
|
+
character = [c].pack('U')
|
163
|
+
rescue RangeError
|
164
|
+
begin
|
165
|
+
character = c.chr
|
166
|
+
rescue
|
167
|
+
begin
|
168
|
+
character = [c].pack('C')
|
169
|
+
rescue
|
170
|
+
character = ""
|
171
|
+
@status = Ncurses::ERR
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
character.fix_encoding!
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end # class CharCode
|
179
|
+
|
180
|
+
def rows
|
181
|
+
lame, lamer = [], []
|
182
|
+
stdscr.getmaxyx lame, lamer
|
183
|
+
lame.first
|
184
|
+
end
|
185
|
+
|
186
|
+
def cols
|
187
|
+
lame, lamer = [], []
|
188
|
+
stdscr.getmaxyx lame, lamer
|
189
|
+
lamer.first
|
190
|
+
end
|
191
|
+
|
192
|
+
def curx
|
193
|
+
lame, lamer = [], []
|
194
|
+
stdscr.getyx lame, lamer
|
195
|
+
lamer.first
|
196
|
+
end
|
197
|
+
|
198
|
+
## Create replacement wrapper for form_driver_w (), which is not (yet) a standard
|
199
|
+
## function in ncurses. Some systems (Mac OS X) does not have a working
|
200
|
+
## form_driver that accepts wide chars. We are just falling back to form_driver, expect problems.
|
201
|
+
def prepare_form_driver
|
202
|
+
if not defined? Form.form_driver_w
|
203
|
+
warn "Your Ncursesw does not have a form_driver_w function (wide char aware), " \
|
204
|
+
"non-ASCII chars may not work on your system."
|
205
|
+
Form.module_eval <<-FRM_DRV, __FILE__, __LINE__ + 1
|
206
|
+
def form_driver_w form, status, c
|
207
|
+
form_driver form, c
|
208
|
+
end
|
209
|
+
module_function :form_driver_w
|
210
|
+
module DriverHelpers
|
211
|
+
def form_driver c
|
212
|
+
if !c.dumb? && c.printable?
|
213
|
+
c.each_byte do |code|
|
214
|
+
Ncurses::Form.form_driver @form, code
|
215
|
+
end
|
216
|
+
else
|
217
|
+
Ncurses::Form.form_driver @form, c.code
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
FRM_DRV
|
222
|
+
end # if not defined? Form.form_driver_w
|
223
|
+
if not defined? Ncurses.get_wch
|
224
|
+
warn "Your Ncursesw does not have a get_wch function (wide char aware), " \
|
225
|
+
"non-ASCII chars may not work on your system."
|
226
|
+
Ncurses.module_eval <<-GET_WCH, __FILE__, __LINE__ + 1
|
227
|
+
def get_wch
|
228
|
+
c = getch
|
229
|
+
c == Ncurses::ERR ? [c, 0] : [Ncurses::OK, c]
|
230
|
+
end
|
231
|
+
module_function :get_wch
|
232
|
+
GET_WCH
|
233
|
+
CharCode.dumb!
|
234
|
+
end # if not defined? Ncurses.get_wch
|
235
|
+
end
|
236
|
+
|
237
|
+
def mutex; @mutex ||= Mutex.new; end
|
238
|
+
def sync &b; mutex.synchronize(&b); end
|
239
|
+
|
240
|
+
module_function :rows, :cols, :curx, :mutex, :sync, :prepare_form_driver
|
241
|
+
|
242
|
+
remove_const :KEY_ENTER
|
243
|
+
remove_const :KEY_CANCEL
|
244
|
+
|
245
|
+
KEY_ENTER = 10
|
246
|
+
KEY_CANCEL = 7 # ctrl-g
|
247
|
+
KEY_TAB = 9
|
248
|
+
|
249
|
+
module Form
|
250
|
+
## This module contains helpers that ease
|
251
|
+
## using form_driver_ methods when @form is present.
|
252
|
+
module DriverHelpers
|
253
|
+
private
|
254
|
+
|
255
|
+
## Ncurses::Form.form_driver_w wrapper for keycodes and control characters.
|
256
|
+
def form_driver_key c
|
257
|
+
form_driver CharCode.keycode(c)
|
258
|
+
end
|
259
|
+
|
260
|
+
## Ncurses::Form.form_driver_w wrapper for printable characters.
|
261
|
+
def form_driver_char c
|
262
|
+
form_driver CharCode.character(c)
|
263
|
+
#c.is_a?(Fixnum) ? c : c.ord
|
264
|
+
end
|
265
|
+
|
266
|
+
## Ncurses::Form.form_driver_w wrapper for charcodes.
|
267
|
+
def form_driver c
|
268
|
+
Ncurses::Form.form_driver_w @form, c.status, c.code
|
269
|
+
end
|
270
|
+
end # module DriverHelpers
|
271
|
+
end # module Form
|
272
|
+
|
273
|
+
end # module Ncurses
|
274
|
+
end # if defined? Ncurses
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Redwood
|
2
|
+
module Util
|
3
|
+
module Query
|
4
|
+
class QueryDescriptionError < ArgumentError; end
|
5
|
+
|
6
|
+
def self.describe(query, fallback = nil)
|
7
|
+
d = query.description.force_encoding("UTF-8")
|
8
|
+
|
9
|
+
unless d.valid_encoding?
|
10
|
+
raise QueryDescriptionError.new(d) unless fallback
|
11
|
+
d = fallback
|
12
|
+
end
|
13
|
+
return d
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/sup/util/uri.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require "uri"
|
2
|
+
|
3
|
+
require "sup/util/path"
|
4
|
+
|
5
|
+
module Redwood
|
6
|
+
module Util
|
7
|
+
module Uri
|
8
|
+
def self.build(components)
|
9
|
+
components = components.dup
|
10
|
+
components[:path] = Path.expand(components[:path])
|
11
|
+
::URI::Generic.build(components)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/sup/version.rb
ADDED
data/sup.gemspec
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
|
3
|
+
require 'sup/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "sup"
|
7
|
+
s.version = ENV["REL"] || (::Redwood::VERSION == "git" ? "999" : ::Redwood::VERSION)
|
8
|
+
s.date = Time.now.strftime "%Y-%m-%d"
|
9
|
+
s.authors = ["William Morgan", "Gaute Hope", "Hamish Downer", "Matthieu Rakotojaona"]
|
10
|
+
s.email = "supmua@googlegroups.com"
|
11
|
+
s.summary = "A console-based email client with the best features of GMail, mutt and Emacs"
|
12
|
+
s.homepage = "http://supmua.org"
|
13
|
+
s.license = 'GPL-2'
|
14
|
+
s.description = <<-DESC
|
15
|
+
Sup is a console-based email client for people with a lot of email.
|
16
|
+
|
17
|
+
* GMail-like thread-centered archiving, tagging and muting
|
18
|
+
* Handling mail from multiple mbox and Maildir sources
|
19
|
+
* Blazing fast full-text search with a rich query language
|
20
|
+
* Multiple accounts - pick the right one when sending mail
|
21
|
+
* Ruby-programmable hooks
|
22
|
+
* Automatically tracking recent contacts
|
23
|
+
DESC
|
24
|
+
s.post_install_message = <<-EOF
|
25
|
+
SUP: please note that our old mailing lists have been shut down,
|
26
|
+
re-subscribe to supmua@googlegroups.com to discuss and follow
|
27
|
+
updates on sup (send email to: supmua+subscribe@googlegroups.com).
|
28
|
+
EOF
|
29
|
+
|
30
|
+
s.files = `git ls-files -z`.split("\x0")
|
31
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
32
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
33
|
+
s.require_paths = ["lib"]
|
34
|
+
|
35
|
+
s.required_ruby_version = '>= 1.9.3'
|
36
|
+
|
37
|
+
s.add_runtime_dependency "xapian-ruby", "~> 1.2.15"
|
38
|
+
s.add_runtime_dependency "ncursesw", "~> 1.4.0"
|
39
|
+
s.add_runtime_dependency "rmail-sup", "~> 1.0.1"
|
40
|
+
s.add_runtime_dependency "highline"
|
41
|
+
s.add_runtime_dependency "trollop", ">= 1.12"
|
42
|
+
s.add_runtime_dependency "lockfile"
|
43
|
+
s.add_runtime_dependency "mime-types", "~> 1.0"
|
44
|
+
s.add_runtime_dependency "locale", "~> 2.0"
|
45
|
+
s.add_runtime_dependency "chronic", "~> 0.9.1"
|
46
|
+
s.add_runtime_dependency "unicode", "~> 0.4.4"
|
47
|
+
|
48
|
+
s.add_development_dependency "bundler", "~> 1.3"
|
49
|
+
s.add_development_dependency "rake"
|
50
|
+
s.add_development_dependency "minitest", "~> 4.7"
|
51
|
+
s.add_development_dependency "rr", "~> 1.0.5"
|
52
|
+
s.add_development_dependency "gpgme", ">= 2.0.2"
|
53
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'sup'
|
4
|
+
require 'stringio'
|
5
|
+
require 'rmail'
|
6
|
+
require 'uri'
|
7
|
+
|
8
|
+
module Redwood
|
9
|
+
|
10
|
+
class DummySource < Source
|
11
|
+
|
12
|
+
attr_accessor :messages
|
13
|
+
|
14
|
+
def initialize uri, last_date=nil, usual=true, archived=false, id=nil, labels=[]
|
15
|
+
super uri, usual, archived, id
|
16
|
+
@messages = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def start_offset
|
20
|
+
0
|
21
|
+
end
|
22
|
+
|
23
|
+
def end_offset
|
24
|
+
# should contain the number of test messages -1
|
25
|
+
return @messages ? @messages.length - 1 : 0
|
26
|
+
end
|
27
|
+
|
28
|
+
def load_header offset
|
29
|
+
Source.parse_raw_email_header StringIO.new(raw_header(offset))
|
30
|
+
end
|
31
|
+
|
32
|
+
def load_message offset
|
33
|
+
RMail::Parser.read raw_message(offset)
|
34
|
+
end
|
35
|
+
|
36
|
+
def raw_header offset
|
37
|
+
ret = ""
|
38
|
+
f = StringIO.new(@messages[offset])
|
39
|
+
until f.eof? || (l = f.gets) =~ /^$/
|
40
|
+
ret += l
|
41
|
+
end
|
42
|
+
ret
|
43
|
+
end
|
44
|
+
|
45
|
+
def raw_message offset
|
46
|
+
@messages[offset]
|
47
|
+
end
|
48
|
+
|
49
|
+
def each_raw_message_line offset
|
50
|
+
ret = ""
|
51
|
+
f = StringIO.new(@messages[offset])
|
52
|
+
until f.eof?
|
53
|
+
yield f.gets
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
# vim:noai:ts=2:sw=2:
|
61
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
default-key 789E7011
|
Binary file
|
Binary file
|
Binary file
|