sup 0.22.1 → 1.1
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 +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
|