sup 0.22.1 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/checks.yml +70 -0
- data/.gitignore +1 -3
- data/.rubocop.yml +5 -0
- data/CONTRIBUTORS +14 -5
- data/Gemfile +6 -1
- data/History.txt +76 -0
- data/Manifest.txt +149 -0
- data/README.md +32 -5
- data/Rakefile +40 -1
- data/bin/sup +7 -5
- data/bin/sup-add +16 -20
- data/bin/sup-config +30 -44
- data/bin/sup-dump +2 -2
- data/bin/sup-import-dump +4 -4
- data/bin/sup-sync +3 -3
- data/bin/sup-sync-back-maildir +2 -2
- data/bin/sup-tweak-labels +5 -5
- data/ext/mkrf_conf_xapian.rb +10 -4
- data/lib/sup/colormap.rb +1 -1
- data/lib/sup/crypto.rb +17 -8
- data/lib/sup/hook.rb +9 -9
- data/lib/sup/index.rb +20 -7
- data/lib/sup/keymap.rb +1 -1
- data/lib/sup/logger.rb +1 -1
- data/lib/sup/maildir.rb +4 -4
- data/lib/sup/mbox.rb +4 -4
- data/lib/sup/message.rb +26 -15
- data/lib/sup/message_chunks.rb +29 -20
- data/lib/sup/mode.rb +1 -0
- data/lib/sup/modes/completion_mode.rb +0 -1
- data/lib/sup/modes/contact_list_mode.rb +1 -0
- data/lib/sup/modes/file_browser_mode.rb +2 -2
- data/lib/sup/modes/label_list_mode.rb +1 -1
- data/lib/sup/modes/reply_mode.rb +3 -1
- data/lib/sup/modes/search_list_mode.rb +2 -2
- data/lib/sup/modes/thread_index_mode.rb +1 -1
- data/lib/sup/modes/thread_view_mode.rb +15 -13
- data/lib/sup/rfc2047.rb +21 -6
- data/lib/sup/source.rb +9 -3
- data/lib/sup/textfield.rb +0 -1
- data/lib/sup/thread.rb +0 -1
- data/lib/sup/util/axe.rb +17 -0
- data/lib/sup/util/ncurses.rb +3 -3
- data/lib/sup/util.rb +42 -67
- data/lib/sup/version.rb +10 -1
- data/lib/sup.rb +13 -8
- data/man/sup-add.1 +34 -55
- data/man/sup-config.1 +23 -36
- data/man/sup-dump.1 +25 -35
- data/man/sup-import-dump.1 +33 -54
- data/man/sup-psych-ify-config-files.1 +25 -34
- data/man/sup-recover-sources.1 +34 -49
- data/man/sup-sync-back-maildir.1 +39 -60
- data/man/sup-sync.1 +49 -79
- data/man/sup-tweak-labels.1 +35 -58
- data/man/sup.1 +50 -62
- data/sup.gemspec +12 -9
- data/test/dummy_source.rb +21 -15
- data/test/fixtures/embedded-message.eml +34 -0
- data/test/fixtures/mailing-list-header.eml +80 -0
- data/test/fixtures/non-ascii-header-in-nested-message.eml +36 -0
- data/test/fixtures/non-ascii-header.eml +8 -0
- data/test/fixtures/rfc2047-header-encoding.eml +15 -0
- data/test/fixtures/text-attachments-with-charset.eml +60 -0
- data/test/fixtures/utf8-header.eml +17 -0
- data/test/fixtures/zimbra-quote-with-bottom-post.eml +27 -0
- data/test/gnupg_test_home/gpg.conf +2 -1
- data/test/gnupg_test_home/private-keys-v1.d/306D2EE90FF0014B5B9FD07E265C751791674140.key +0 -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/regen_keys.sh +69 -18
- data/test/gnupg_test_home/secring.gpg +0 -0
- data/test/gnupg_test_home/sup-test-2@foo.bar.asc +20 -22
- data/test/integration/test_mbox.rb +1 -1
- data/test/integration/test_sup-add.rb +83 -0
- data/test/test_crypto.rb +46 -0
- data/test/test_header_parsing.rb +9 -1
- data/test/test_helper.rb +7 -4
- data/test/test_message.rb +188 -22
- data/test/test_messages_dir.rb +13 -15
- data/test/unit/test_horizontal_selector.rb +4 -4
- data/test/unit/test_locale_fiddler.rb +1 -1
- data/test/unit/util/test_query.rb +10 -4
- data/test/unit/util/test_string.rb +9 -3
- data/test/unit/util/test_uri.rb +2 -2
- metadata +93 -51
- data/.travis.yml +0 -13
- data/bin/sup-psych-ify-config-files +0 -21
- data/test/gnupg_test_home/key1.gen +0 -15
- data/test/gnupg_test_home/key2.gen +0 -15
- data/test/gnupg_test_home/key_ecc.gen +0 -13
- data/test/gnupg_test_home/private-keys-v1.d/719C7455A7169C6EE8819C6E91002E4F9DD00A65.key +0 -1
- data/test/gnupg_test_home/private-keys-v1.d/8A130806A754AA29D59487D76BD355040D9F26C0.key +0 -0
- data/test/gnupg_test_home/private-keys-v1.d/B7AA46B22BD8A6AD1B4F266C19A3B124A32DDD71.key +0 -0
- data/test/gnupg_test_home/private-keys-v1.d/FA64ACD7CC871371BDF57285A6CDF0E618827783.key +0 -0
- data/test/integration/test_label_service.rb +0 -18
- data/test/test_yaml_migration.rb +0 -85
data/bin/sup-config
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
4
4
|
|
5
|
-
require '
|
6
|
-
require 'trollop'
|
5
|
+
require 'optimist'
|
7
6
|
require "sup"
|
7
|
+
require 'sup/util/axe'
|
8
8
|
|
9
|
-
$opts =
|
9
|
+
$opts = Optimist::options do
|
10
10
|
version "sup-config (sup #{Redwood::VERSION})"
|
11
11
|
banner <<EOS
|
12
12
|
Interactive configuration tool for Sup. Won't destroy existing
|
@@ -19,20 +19,6 @@ No options.
|
|
19
19
|
EOS
|
20
20
|
end
|
21
21
|
|
22
|
-
def axe q, default=nil
|
23
|
-
question = if default && !default.empty?
|
24
|
-
"#{q} (enter for \"#{default}\"): "
|
25
|
-
else
|
26
|
-
"#{q}: "
|
27
|
-
end
|
28
|
-
ans = ask question
|
29
|
-
ans.empty? ? default : ans.to_s
|
30
|
-
end
|
31
|
-
|
32
|
-
def axe_yes q, default="n"
|
33
|
-
axe(q, default) =~ /^y|yes$/i
|
34
|
-
end
|
35
|
-
|
36
22
|
def build_cmd cmd
|
37
23
|
(ENV["RUBY_INVOCATION"] ? ENV["RUBY_INVOCATION"] + " " : "") + File.join(File.dirname($0), cmd)
|
38
24
|
end
|
@@ -42,8 +28,8 @@ def add_source
|
|
42
28
|
|
43
29
|
type = nil
|
44
30
|
|
45
|
-
say "Ok, adding a new source."
|
46
|
-
choose do |menu|
|
31
|
+
@cli.say "Ok, adding a new source."
|
32
|
+
@cli.choose do |menu|
|
47
33
|
menu.prompt = "What type of mail source is it? "
|
48
34
|
menu.choice("mbox file") { type = :mbox }
|
49
35
|
menu.choice("maildir directory") { type = :maildir }
|
@@ -51,7 +37,7 @@ def add_source
|
|
51
37
|
end
|
52
38
|
|
53
39
|
while true do
|
54
|
-
say "Ok, now for the details."
|
40
|
+
@cli.say "Ok, now for the details."
|
55
41
|
|
56
42
|
default_labels, components = case type
|
57
43
|
when :mbox
|
@@ -75,11 +61,11 @@ def add_source
|
|
75
61
|
uri = begin
|
76
62
|
Redwood::Util::Uri.build components
|
77
63
|
rescue URI::Error => e
|
78
|
-
say "Whoopsie! I couldn't build a URI from that: #{e.message}"
|
64
|
+
@cli.say "Whoopsie! I couldn't build a URI from that: #{e.message}"
|
79
65
|
if axe_yes("Try again?") then next else return end
|
80
66
|
end
|
81
67
|
|
82
|
-
say "I'm going to add this source: #{uri}"
|
68
|
+
@cli.say "I'm going to add this source: #{uri}"
|
83
69
|
unless axe("Does that look right?", "y") =~ /^y|yes$/i
|
84
70
|
if axe_yes("Try again?") then next else return end
|
85
71
|
end
|
@@ -108,21 +94,21 @@ def add_source
|
|
108
94
|
|
109
95
|
system cmd
|
110
96
|
if $?.success?
|
111
|
-
say "Great! Added!"
|
97
|
+
@cli.say "Great! Added!"
|
112
98
|
break
|
113
99
|
else
|
114
|
-
say "Rats, that failed. You may have to do it manually."
|
100
|
+
@cli.say "Rats, that failed. You may have to do it manually."
|
115
101
|
if axe_yes("Try again?") then next else return end
|
116
102
|
end
|
117
103
|
end
|
118
104
|
end
|
119
105
|
|
120
|
-
|
106
|
+
@cli.wrap_at = :auto
|
121
107
|
Redwood::start
|
122
108
|
index = Redwood::Index.init
|
123
109
|
Redwood::SourceManager.load_sources
|
124
110
|
|
125
|
-
say <<EOS
|
111
|
+
@cli.say <<EOS
|
126
112
|
Howdy neighbor! This here's sup-config, ready to help you jack in to
|
127
113
|
the next generation of digital cyberspace: the text-based email
|
128
114
|
program. Get ready to be the envy of everyone in your internets
|
@@ -138,11 +124,11 @@ account = $config[:accounts][:default]
|
|
138
124
|
name = axe "What's your name?", account[:name]
|
139
125
|
email = axe "What's your (primary) email address?", account[:email]
|
140
126
|
|
141
|
-
say "Ok, your from header will look like this:"
|
142
|
-
say " From: #{name} <#{email}>"
|
127
|
+
@cli.say "Ok, your from header will look like this:"
|
128
|
+
@cli.say " From: #{name} <#{email}>"
|
143
129
|
|
144
|
-
say "\nDo you have any alternate email addresses that also receive email?"
|
145
|
-
say "If so, enter them now, separated by spaces."
|
130
|
+
@cli.say "\nDo you have any alternate email addresses that also receive email?"
|
131
|
+
@cli.say "If so, enter them now, separated by spaces."
|
146
132
|
alts = axe("Alternate email addresses", account[:alternates].join(" ")).split(/\s+/)
|
147
133
|
|
148
134
|
sigfn = axe "What file contains your signature?", account[:signature]
|
@@ -159,36 +145,36 @@ $config[:time_mode] = time_mode
|
|
159
145
|
|
160
146
|
done = false
|
161
147
|
until done
|
162
|
-
say "\nNow, we'll tell Sup where to find all your email."
|
148
|
+
@cli.say "\nNow, we'll tell Sup where to find all your email."
|
163
149
|
Redwood::SourceManager.load_sources
|
164
|
-
say "Current sources:"
|
150
|
+
@cli.say "Current sources:"
|
165
151
|
if Redwood::SourceManager.sources.empty?
|
166
|
-
say " No sources!"
|
152
|
+
@cli.say " No sources!"
|
167
153
|
else
|
168
154
|
Redwood::SourceManager.sources.each { |s| puts "* #{s}" }
|
169
155
|
end
|
170
156
|
|
171
|
-
say "\n"
|
172
|
-
choose do |menu|
|
157
|
+
@cli.say "\n"
|
158
|
+
@cli.choose do |menu|
|
173
159
|
menu.prompt = "Your wish? "
|
174
160
|
menu.choice("Add a new source.") { add_source }
|
175
161
|
menu.choice("Done adding sources!") { done = true }
|
176
162
|
end
|
177
163
|
end
|
178
164
|
|
179
|
-
say "\nSup needs to know where to store your sent messages."
|
180
|
-
say "Only sources capable of storing mail will be listed.\n\n"
|
165
|
+
@cli.say "\nSup needs to know where to store your sent messages."
|
166
|
+
@cli.say "Only sources capable of storing mail will be listed.\n\n"
|
181
167
|
|
182
168
|
Redwood::SourceManager.load_sources
|
183
169
|
if Redwood::SourceManager.sources.empty?
|
184
|
-
say "\nUsing the default sup://sent, since you haven't configured other sources yet."
|
170
|
+
@cli.say "\nUsing the default sup://sent, since you haven't configured other sources yet."
|
185
171
|
$config[:sent_source] = 'sup://sent'
|
186
172
|
else
|
187
173
|
# this handles the event that source.yaml already contains the SentLoader
|
188
174
|
# source.
|
189
175
|
have_sup_sent = false
|
190
176
|
|
191
|
-
choose do |menu|
|
177
|
+
@cli.choose do |menu|
|
192
178
|
menu.prompt = "Store my sent mail in? "
|
193
179
|
|
194
180
|
menu.choice('Default (an mbox in ~/.sup, aka sup://sent)') { $config[:sent_source] = 'sup://sent'} unless have_sup_sent
|
@@ -202,9 +188,9 @@ end
|
|
202
188
|
|
203
189
|
Redwood::save_yaml_obj $config, Redwood::CONFIG_FN, false, true
|
204
190
|
|
205
|
-
say "Ok, I've saved you up a nice lil' #{Redwood::CONFIG_FN}."
|
191
|
+
@cli.say "Ok, I've saved you up a nice lil' #{Redwood::CONFIG_FN}."
|
206
192
|
|
207
|
-
say <<EOS
|
193
|
+
@cli.say <<EOS
|
208
194
|
|
209
195
|
The final step is to import all your messages into the Sup index.
|
210
196
|
Depending on how many messages are in the sources, this could take
|
@@ -218,10 +204,10 @@ if axe_yes "Run sup-sync to import all messages now?"
|
|
218
204
|
puts "Ok, trying to run \"#{cmd}\"..."
|
219
205
|
system cmd
|
220
206
|
if $?.success?
|
221
|
-
say "Great! It worked!"
|
207
|
+
@cli.say "Great! It worked!"
|
222
208
|
break
|
223
209
|
else
|
224
|
-
say "Rats, that failed. You may have to do it manually."
|
210
|
+
@cli.say "Rats, that failed. You may have to do it manually."
|
225
211
|
if axe_yes("Try again?") then next else break end
|
226
212
|
end
|
227
213
|
end
|
@@ -229,7 +215,7 @@ end
|
|
229
215
|
|
230
216
|
index.load
|
231
217
|
|
232
|
-
say <<EOS
|
218
|
+
@cli.say <<EOS
|
233
219
|
|
234
220
|
Okee doke, you've got yourself an index of #{index.size} messages. Looks
|
235
221
|
like you're ready to jack in to cyberspace there, cowboy.
|
data/bin/sup-dump
CHANGED
@@ -3,12 +3,12 @@
|
|
3
3
|
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
4
4
|
|
5
5
|
require 'xapian'
|
6
|
-
require '
|
6
|
+
require 'optimist'
|
7
7
|
require 'set'
|
8
8
|
|
9
9
|
BASE_DIR = ENV["SUP_BASE"] || File.join(ENV["HOME"], ".sup")
|
10
10
|
|
11
|
-
$opts =
|
11
|
+
$opts = Optimist::options do
|
12
12
|
version "sup-dump"
|
13
13
|
banner <<EOS
|
14
14
|
Dumps all message state from the sup index to standard out. You can
|
data/bin/sup-import-dump
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
4
4
|
|
5
5
|
require 'uri'
|
6
|
-
require '
|
6
|
+
require 'optimist'
|
7
7
|
require "sup"
|
8
8
|
|
9
9
|
PROGRESS_UPDATE_INTERVAL = 15 # seconds
|
@@ -11,7 +11,7 @@ PROGRESS_UPDATE_INTERVAL = 15 # seconds
|
|
11
11
|
class AbortExecution < SystemExit
|
12
12
|
end
|
13
13
|
|
14
|
-
opts =
|
14
|
+
opts = Optimist::options do
|
15
15
|
version "sup-import-dump (sup #{Redwood::VERSION})"
|
16
16
|
banner <<EOS
|
17
17
|
Imports message state previously exported by sup-dump into the index.
|
@@ -36,8 +36,8 @@ EOS
|
|
36
36
|
|
37
37
|
conflicts :ignore_missing, :warn_missing, :abort_missing
|
38
38
|
end
|
39
|
-
|
40
|
-
|
39
|
+
Optimist::die "No dump file given" if ARGV.empty?
|
40
|
+
Optimist::die "Extra arguments given" if ARGV.length > 1
|
41
41
|
dump_name = ARGV.shift
|
42
42
|
missing_action = [:ignore_missing, :warn_missing, :abort_missing].find { |x| opts[x] } || :abort_missing
|
43
43
|
|
data/bin/sup-sync
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
4
4
|
|
5
5
|
require 'uri'
|
6
|
-
require '
|
6
|
+
require 'optimist'
|
7
7
|
require "sup"
|
8
8
|
|
9
9
|
PROGRESS_UPDATE_INTERVAL = 15 # seconds
|
@@ -30,7 +30,7 @@ def time
|
|
30
30
|
Time.now - startt
|
31
31
|
end
|
32
32
|
|
33
|
-
opts =
|
33
|
+
opts = Optimist::options do
|
34
34
|
version "sup-sync (sup #{Redwood::VERSION})"
|
35
35
|
banner <<EOS
|
36
36
|
Synchronizes the Sup index with one or more message sources by adding
|
@@ -112,7 +112,7 @@ begin
|
|
112
112
|
Redwood::SourceManager.usual_sources
|
113
113
|
else
|
114
114
|
ARGV.map do |uri|
|
115
|
-
Redwood::SourceManager.source_for uri or
|
115
|
+
Redwood::SourceManager.source_for uri or Optimist::die "Unknown source: #{uri}. Did you add it with sup-add first?"
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
data/bin/sup-sync-back-maildir
CHANGED
@@ -3,10 +3,10 @@
|
|
3
3
|
|
4
4
|
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
5
5
|
|
6
|
-
require '
|
6
|
+
require 'optimist'
|
7
7
|
require "sup"
|
8
8
|
|
9
|
-
opts =
|
9
|
+
opts = Optimist::options do
|
10
10
|
version "sup-sync-back-maildir (sup #{Redwood::VERSION})"
|
11
11
|
banner <<EOS
|
12
12
|
Export Xapian entries to Maildir sources on disk.
|
data/bin/sup-tweak-labels
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
4
4
|
|
5
|
-
require '
|
5
|
+
require 'optimist'
|
6
6
|
require "sup"
|
7
7
|
|
8
8
|
class Float
|
@@ -25,7 +25,7 @@ def time
|
|
25
25
|
Time.now - startt
|
26
26
|
end
|
27
27
|
|
28
|
-
opts =
|
28
|
+
opts = Optimist::options do
|
29
29
|
version "sup-tweak-labels (sup #{Redwood::VERSION})"
|
30
30
|
banner <<EOS
|
31
31
|
Batch modification of message state for messages already in the index.
|
@@ -58,7 +58,7 @@ opts[:verbose] = true if opts[:very_verbose]
|
|
58
58
|
add_labels = opts[:add].to_set_of_symbols ","
|
59
59
|
remove_labels = opts[:remove].to_set_of_symbols ","
|
60
60
|
|
61
|
-
|
61
|
+
Optimist::die "nothing to do: no labels to add or remove" if add_labels.empty? && remove_labels.empty?
|
62
62
|
|
63
63
|
Redwood::start
|
64
64
|
index = Redwood::Index.init
|
@@ -71,10 +71,10 @@ begin
|
|
71
71
|
Redwood::SourceManager.sources
|
72
72
|
else
|
73
73
|
ARGV.map do |uri|
|
74
|
-
Redwood::SourceManager.source_for uri or
|
74
|
+
Redwood::SourceManager.source_for uri or Optimist::die "Unknown source: #{uri}. Did you add it with sup-add first?"
|
75
75
|
end
|
76
76
|
end.map { |s| s.id }
|
77
|
-
|
77
|
+
Optimist::die "nothing to do: no sources" if source_ids.empty?
|
78
78
|
|
79
79
|
query = "(" + source_ids.map { |id| "source_id:#{id}" }.join(" OR ") + ")"
|
80
80
|
if add_labels.empty?
|
data/ext/mkrf_conf_xapian.rb
CHANGED
@@ -10,13 +10,19 @@ end
|
|
10
10
|
|
11
11
|
puts "xapian: platform specific dependencies.."
|
12
12
|
|
13
|
-
|
13
|
+
destination = File.writable?(Gem.dir) ? Gem.dir : Gem.user_dir
|
14
|
+
inst = Gem::DependencyInstaller.new(:install_dir => destination)
|
14
15
|
begin
|
15
16
|
|
16
17
|
if !RbConfig::CONFIG['arch'].include?('openbsd')
|
17
18
|
# update version in Gemfile as well
|
18
19
|
name = "xapian-ruby"
|
19
|
-
version =
|
20
|
+
version =
|
21
|
+
if /^2\.0\./ =~ RUBY_VERSION
|
22
|
+
["~> 1.2", "< 1.3.6"]
|
23
|
+
else
|
24
|
+
"~> 1.2"
|
25
|
+
end
|
20
26
|
|
21
27
|
begin
|
22
28
|
# try to load gem
|
@@ -34,8 +40,8 @@ begin
|
|
34
40
|
STDERR.puts "xapian: openbsd: you have to install xapian-core and xapian-bindings manually, have a look at: https://github.com/sup-heliotrope/sup/wiki/Installation%3A-OpenBSD"
|
35
41
|
end
|
36
42
|
|
37
|
-
rescue
|
38
|
-
|
43
|
+
rescue StandardError => e
|
44
|
+
STDERR.puts "Unable to install #{name} gem: #{e.inspect}"
|
39
45
|
exit(1)
|
40
46
|
|
41
47
|
end
|
data/lib/sup/colormap.rb
CHANGED
data/lib/sup/crypto.rb
CHANGED
@@ -127,18 +127,27 @@ EOS
|
|
127
127
|
def sign from, to, payload
|
128
128
|
return unknown_status(@not_working_reason) unless @not_working_reason.nil?
|
129
129
|
|
130
|
+
# We grab this from the GPG::Ctx below after signing, so that we can set
|
131
|
+
# micalg in Content-Type to match the hash algorithm GPG decided to use.
|
132
|
+
hash_algo = nil
|
133
|
+
|
130
134
|
gpg_opts = {:protocol => GPGME::PROTOCOL_OpenPGP, :armor => true, :textmode => true}
|
131
135
|
gpg_opts.merge!(gen_sign_user_opts(from))
|
132
136
|
gpg_opts = HookManager.run("gpg-options",
|
133
137
|
{:operation => "sign", :options => gpg_opts}) || gpg_opts
|
134
138
|
begin
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
139
|
+
input = GPGME::Data.new(format_payload(payload))
|
140
|
+
output = GPGME::Data.new()
|
141
|
+
GPGME::Ctx.new(gpg_opts) do |ctx|
|
142
|
+
if gpg_opts[:signer]
|
143
|
+
signers = GPGME::Key.find(:secret, gpg_opts[:signer], :sign)
|
144
|
+
ctx.add_signer(*signers)
|
145
|
+
end
|
146
|
+
ctx.sign(input, output, GPGME::SIG_MODE_DETACH)
|
147
|
+
hash_algo = GPGME::hash_algo_name(ctx.sign_result.signatures[0].hash_algo)
|
141
148
|
end
|
149
|
+
output.seek(0)
|
150
|
+
sig = output.read
|
142
151
|
rescue GPGME::Error => exc
|
143
152
|
raise Error, gpgme_exc_msg(exc.message)
|
144
153
|
end
|
@@ -150,7 +159,7 @@ EOS
|
|
150
159
|
end
|
151
160
|
|
152
161
|
envelope = RMail::Message.new
|
153
|
-
envelope.header["Content-Type"] =
|
162
|
+
envelope.header["Content-Type"] = "multipart/signed; protocol=application/pgp-signature; micalg=pgp-#{hash_algo.downcase}"
|
154
163
|
|
155
164
|
envelope.add_part payload
|
156
165
|
signature = RMail::Message.make_attachment sig, "application/pgp-signature", nil, "signature.asc"
|
@@ -233,7 +242,7 @@ EOS
|
|
233
242
|
end
|
234
243
|
|
235
244
|
if valid || !unknown
|
236
|
-
summary_line = simplify_sig_line(verify_result.signatures[0].to_s, all_trusted)
|
245
|
+
summary_line = simplify_sig_line(verify_result.signatures[0].to_s.dup, all_trusted)
|
237
246
|
end
|
238
247
|
|
239
248
|
if all_output_lines.length == 0
|
data/lib/sup/hook.rb
CHANGED
@@ -109,20 +109,20 @@ class HookManager
|
|
109
109
|
@descs[name] = desc
|
110
110
|
end
|
111
111
|
|
112
|
-
def print_hooks f=$stdout
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
EOS
|
117
|
-
|
118
|
-
HookManager.descs.sort.each do |name, desc|
|
119
|
-
f.puts <<EOS
|
112
|
+
def print_hooks pattern="", f=$stdout
|
113
|
+
matching_hooks = HookManager.descs.sort.keep_if {|name, desc| pattern.empty? or name.match(pattern)}.map do |name, desc|
|
114
|
+
<<EOS
|
120
115
|
#{name}
|
121
116
|
#{"-" * name.length}
|
122
117
|
File: #{fn_for name}
|
123
118
|
#{desc}
|
124
119
|
EOS
|
125
120
|
end
|
121
|
+
|
122
|
+
showing_str = matching_hooks.size == HookManager.descs.size ? "" : " (showing #{matching_hooks.size})"
|
123
|
+
f.puts "Have #{HookManager.descs.size} registered hooks#{showing_str}:"
|
124
|
+
f.puts
|
125
|
+
matching_hooks.each { |text| f.puts text }
|
126
126
|
end
|
127
127
|
|
128
128
|
def enabled? name; !hook_for(name).nil? end
|
@@ -138,7 +138,7 @@ private
|
|
138
138
|
returning IO.read(fn_for(name)) do
|
139
139
|
debug "read '#{name}' from #{fn_for(name)}"
|
140
140
|
end
|
141
|
-
rescue SystemCallError
|
141
|
+
rescue SystemCallError
|
142
142
|
#debug "disabled hook for '#{name}': #{e.message}"
|
143
143
|
nil
|
144
144
|
end
|
data/lib/sup/index.rb
CHANGED
@@ -425,7 +425,7 @@ EOS
|
|
425
425
|
|
426
426
|
## gmail style "is" operator
|
427
427
|
subs = subs.gsub(/\b(is|has):(\S+)\b/) do
|
428
|
-
|
428
|
+
_field, label = $1, $2
|
429
429
|
case label
|
430
430
|
when "read"
|
431
431
|
"-label:unread"
|
@@ -516,19 +516,32 @@ EOS
|
|
516
516
|
qp.stemmer = Xapian::Stem.new($config[:stem_language])
|
517
517
|
qp.stemming_strategy = Xapian::QueryParser::STEM_SOME
|
518
518
|
qp.default_op = Xapian::Query::OP_AND
|
519
|
-
|
520
|
-
|
521
|
-
|
519
|
+
valuerangeprocessor = Xapian::NumberValueRangeProcessor.new(DATE_VALUENO,
|
520
|
+
'date:', true)
|
521
|
+
qp.add_valuerangeprocessor(valuerangeprocessor)
|
522
|
+
NORMAL_PREFIX.each { |k,info| info[:prefix].each {
|
523
|
+
|v| qp.add_prefix k, v }
|
524
|
+
}
|
525
|
+
BOOLEAN_PREFIX.each { |k,info| info[:prefix].each {
|
526
|
+
|v| qp.add_boolean_prefix k, v, info[:exclusive] }
|
527
|
+
}
|
522
528
|
|
523
529
|
begin
|
524
|
-
xapian_query = qp.parse_query(subs, Xapian::QueryParser::FLAG_PHRASE|
|
530
|
+
xapian_query = qp.parse_query(subs, Xapian::QueryParser::FLAG_PHRASE |
|
531
|
+
Xapian::QueryParser::FLAG_BOOLEAN |
|
532
|
+
Xapian::QueryParser::FLAG_LOVEHATE |
|
533
|
+
Xapian::QueryParser::FLAG_WILDCARD)
|
525
534
|
rescue RuntimeError => e
|
526
535
|
raise ParseError, "xapian query parser error: #{e}"
|
527
536
|
end
|
528
537
|
|
529
538
|
debug "parsed xapian query: #{Util::Query.describe(xapian_query, subs)}"
|
530
539
|
|
531
|
-
|
540
|
+
if xapian_query.nil? or xapian_query.empty?
|
541
|
+
raise ParseError, "couldn't parse \"#{s}\" as xapian query " \
|
542
|
+
"(special characters aren't indexed)"
|
543
|
+
end
|
544
|
+
|
532
545
|
query[:qobj] = xapian_query
|
533
546
|
query[:text] = s
|
534
547
|
query
|
@@ -636,7 +649,7 @@ EOS
|
|
636
649
|
end
|
637
650
|
|
638
651
|
def synchronize &b
|
639
|
-
@index_mutex.synchronize
|
652
|
+
@index_mutex.synchronize(&b)
|
640
653
|
end
|
641
654
|
|
642
655
|
def run_query xapian_query, offset, limit, checkatleast=0
|
data/lib/sup/keymap.rb
CHANGED
data/lib/sup/logger.rb
CHANGED
@@ -71,7 +71,7 @@ end
|
|
71
71
|
|
72
72
|
## include me to have top-level #debug, #info, etc. methods.
|
73
73
|
module LogsStuff
|
74
|
-
Logger::LEVELS.each { |l| define_method(l) { |s| Logger.instance.send(l, s) } }
|
74
|
+
Logger::LEVELS.each { |l| define_method(l) { |s, uplevel = 0| Logger.instance.send(l, s) } }
|
75
75
|
end
|
76
76
|
|
77
77
|
end
|
data/lib/sup/maildir.rb
CHANGED
@@ -12,13 +12,13 @@ class Maildir < Source
|
|
12
12
|
def initialize uri, usual=true, archived=false, sync_back=true, id=nil, labels=[]
|
13
13
|
super uri, usual, archived, id
|
14
14
|
@expanded_uri = Source.expand_filesystem_uri(uri)
|
15
|
-
parts =
|
15
|
+
parts = /^([a-zA-Z0-9]*:(\/\/)?)(.*)/.match @expanded_uri
|
16
16
|
if parts
|
17
17
|
prefix = parts[1]
|
18
18
|
@path = parts[3]
|
19
|
-
uri = URI(prefix +
|
19
|
+
uri = URI(prefix + Source.encode_path_for_uri(@path))
|
20
20
|
else
|
21
|
-
uri = URI(
|
21
|
+
uri = URI(Source.encode_path_for_uri @path)
|
22
22
|
@path = uri.path
|
23
23
|
end
|
24
24
|
|
@@ -30,7 +30,7 @@ class Maildir < Source
|
|
30
30
|
# sync by default if not specified
|
31
31
|
@sync_back = true if @sync_back.nil?
|
32
32
|
|
33
|
-
@dir = URI.
|
33
|
+
@dir = URI.decode_www_form_component uri.path
|
34
34
|
@labels = Set.new(labels || [])
|
35
35
|
@mutex = Mutex.new
|
36
36
|
@ctimes = { 'cur' => Time.at(0), 'new' => Time.at(0) }
|
data/lib/sup/mbox.rb
CHANGED
@@ -19,13 +19,13 @@ class MBox < Source
|
|
19
19
|
case uri_or_fp
|
20
20
|
when String
|
21
21
|
@expanded_uri = Source.expand_filesystem_uri(uri_or_fp)
|
22
|
-
parts =
|
22
|
+
parts = /^([a-zA-Z0-9]*:(\/\/)?)(.*)/.match @expanded_uri
|
23
23
|
if parts
|
24
24
|
prefix = parts[1]
|
25
25
|
@path = parts[3]
|
26
|
-
uri = URI(prefix +
|
26
|
+
uri = URI(prefix + Source.encode_path_for_uri(@path))
|
27
27
|
else
|
28
|
-
uri = URI(
|
28
|
+
uri = URI(Source.encode_path_for_uri @expanded_uri)
|
29
29
|
@path = uri.path
|
30
30
|
end
|
31
31
|
|
@@ -36,7 +36,7 @@ class MBox < Source
|
|
36
36
|
else
|
37
37
|
@f = uri_or_fp
|
38
38
|
@path = uri_or_fp.path
|
39
|
-
@expanded_uri = "mbox://#{
|
39
|
+
@expanded_uri = "mbox://#{Source.encode_path_for_uri @path}"
|
40
40
|
end
|
41
41
|
|
42
42
|
super uri_or_fp, usual, archived, id
|