sup 0.20.0 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.travis.yml +1 -1
  4. data/CONTRIBUTORS +15 -12
  5. data/History.txt +16 -0
  6. data/ReleaseNotes +7 -0
  7. data/bin/sup +10 -24
  8. data/bin/sup-sync-back-maildir +1 -1
  9. data/contrib/completion/_sup.bash +102 -0
  10. data/lib/sup.rb +7 -7
  11. data/lib/sup/colormap.rb +5 -2
  12. data/lib/sup/contact.rb +4 -2
  13. data/lib/sup/crypto.rb +34 -2
  14. data/lib/sup/draft.rb +7 -7
  15. data/lib/sup/hook.rb +1 -1
  16. data/lib/sup/index.rb +2 -2
  17. data/lib/sup/label.rb +1 -1
  18. data/lib/sup/maildir.rb +2 -2
  19. data/lib/sup/mbox.rb +2 -2
  20. data/lib/sup/message.rb +6 -0
  21. data/lib/sup/message_chunks.rb +4 -2
  22. data/lib/sup/mode.rb +31 -26
  23. data/lib/sup/modes/edit_message_mode.rb +1 -1
  24. data/lib/sup/modes/forward_mode.rb +22 -3
  25. data/lib/sup/modes/line_cursor_mode.rb +1 -1
  26. data/lib/sup/modes/text_mode.rb +6 -1
  27. data/lib/sup/modes/thread_index_mode.rb +1 -1
  28. data/lib/sup/modes/thread_view_mode.rb +47 -6
  29. data/lib/sup/person.rb +68 -61
  30. data/lib/sup/search.rb +1 -1
  31. data/lib/sup/sent.rb +1 -1
  32. data/lib/sup/util/locale_fiddler.rb +24 -0
  33. data/lib/sup/version.rb +1 -1
  34. data/sup.gemspec +4 -3
  35. data/test/integration/test_maildir.rb +1 -1
  36. data/test/integration/test_mbox.rb +1 -1
  37. data/test/test_crypto.rb +1 -1
  38. data/test/test_header_parsing.rb +1 -1
  39. data/test/test_message.rb +77 -19
  40. data/test/test_messages_dir.rb +1 -19
  41. data/test/test_yaml_regressions.rb +1 -1
  42. data/test/unit/fixtures/contacts.txt +1 -0
  43. data/test/unit/test_contact.rb +33 -0
  44. data/test/unit/test_locale_fiddler.rb +15 -0
  45. data/test/unit/test_person.rb +37 -0
  46. metadata +31 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e7b5ce3c73c1c6d194d8103bb25de84981db2529
4
- data.tar.gz: a5d0868505c66e8c7974025d5131738d2a436ab6
3
+ metadata.gz: 7303df91a168cda15ce5be2bcb280676acafb4bb
4
+ data.tar.gz: 3abfca06f5727c6efd4b179c12304773328a2d84
5
5
  SHA512:
6
- metadata.gz: 8b44f362bd82be161b1d9451d805af1a9d73d962df4c54196703dec1bbca383fb7bd5f2c0bf6479c1fc57bc27b37ec17a65fc2b24abab838e7f2797bfb64687a
7
- data.tar.gz: e3a2eaaebf74bec788b18c28be9d9a2bee2b8fa06487780f3199aa7446ec386ac5ffc731595245e40be6423dfc1708bed14fe74ada70eab06097655ccc4fd47a
6
+ metadata.gz: 521dfa870e7caf37067677814ee4750f8c175fc4ab590e14f67fddab2f19923078b30c1f709c23e2af71cf8711a110b9ed576669f4c1dac30d67035742f53399
7
+ data.tar.gz: 17f73b5cb16135dbd9b1d423a8e899e6c2bca4fd50c52d1107f353f2e7acf52715fda32d4586cf90fc5e6252a9fe6ea761e27d583e14d094bf9f85f1a8fe59c7
data/.gitignore CHANGED
@@ -16,4 +16,7 @@ Gemfile.lock
16
16
  # generated file for gnupg test
17
17
  test/gnupg_test_home/random_seed
18
18
  test/gnupg_test_home/trustdb.gpg
19
+ test/gnupg_test_home/.gpg-v21-migrated
20
+ test/gnupg_test_home/private-keys-v1.d
21
+
19
22
 
@@ -3,7 +3,7 @@ language: ruby
3
3
  rvm:
4
4
  - 2.1.1
5
5
  - 2.0.0
6
- - 1.9.3
6
+ - 2.2.0
7
7
 
8
8
  before_install:
9
9
  - sudo apt-get update -qq
@@ -9,23 +9,25 @@ Eric Weikl <eric.weikl at the gmx dot nets>
9
9
  Paweł Wilk <siefca at the gnu dot orgs>
10
10
  Ismo Puustinen <ismo at the iki dot fis>
11
11
  Nicolas Pouillard <nicolas.pouillard at the gmail dot coms>
12
+ Matthieu Rakotojaona <matthieu.rakotojaona at the gmail dot coms>
12
13
  Michael Stapelberg <michael at the stapelberg dot des>
13
14
  Eric Sherman <hyperbolist at the gmail dot coms>
15
+ Zeger-Jan van de Weg <mail at the zjvandeweg dot nls>
14
16
  Tero Tilus <tero at the tilus dot nets>
15
17
  Ben Walton <bwalton at the artsci.utoronto dot cas>
16
18
  Scott Bonds <scott at the ggr dot coms>
17
19
  Mike Stipicevic <stipim at the rpi dot edus>
18
20
  Martin Bähr <mbaehr at the societyserver dot orgs>
19
- Matthieu Rakotojaona <matthieu.rakotojaona at the gmail dot coms>
21
+ Timon Vonk <timonv at the gmail dot coms>
20
22
  Clint Byrum <clint at the ubuntu dot coms>
21
23
  Wael M. Nasreddine <wael.nasreddine at the gmail dot coms>
22
24
  Marcus Williams <marcus-sup at the bar-coded dot nets>
23
25
  Lionel Ott <white.magic at the gmx dot des>
24
26
  Gaudenz Steinlin <gaudenz at the soziologie dot chs>
27
+ Per Andersson <avtobiff at the gmail dot coms>
25
28
  Ingmar Vanhassel <ingmar at the exherbo dot orgs>
26
29
  Mark Alexander <marka at the pobox dot coms>
27
30
  Edward Z. Yang <ezyang at the mit dot edus>
28
- Timon Vonk <timonv at the gmail dot coms>
29
31
  julien@macbook <julien.stechele at the gmail dot coms>
30
32
  Christopher Warrington <chrisw at the rice dot edus>
31
33
  W. Trevor King <wking at the drexel dot edus>
@@ -38,49 +40,50 @@ Markus Klinik <mkl at the lambdanaut dot nets>
38
40
  Bo Borgerson <gigabo at the gmail dot coms>
39
41
  Atte Kojo <atte.kojo at the reaktor dot fis>
40
42
  Michael Hamann <michael at the content-space dot des>
41
- Jonathan Lassoff <jof at the thejof dot coms>
42
43
  William Erik Baxter <web at the superscript dot coms>
44
+ Jonathan Lassoff <jof at the thejof dot coms>
43
45
  Grant Hollingworth <grant at the antiflux dot orgs>
44
46
  Ico Doornekamp <ico at the pruts dot nls>
45
47
  Adeodato Simó <dato at the net.com.org dot ess>
46
48
  Daniel Schoepe <daniel.schoepe at the googlemail dot coms>
47
- James Taylor <james at the jamestaylor dot orgs>
48
49
  Jason Petsod <jason at the petsod dot orgs>
50
+ James Taylor <james at the jamestaylor dot orgs>
49
51
  Steve Goldman <sgoldman at the tower-research dot coms>
50
52
  Robin Burchell <viroteck at the viroteck dot nets>
51
53
  Peter Harkins <ph at the malaprop dot orgs>
52
54
  Decklin Foster <decklin at the red-bean dot coms>
55
+ rjg-vB <rthrd at the web dot des>
53
56
  Cameron Matheson <cam+sup at the cammunism dot orgs>
54
- Carl Worth <cworth at the cworth dot orgs>
55
57
  Alex Vandiver <alex at the chmrr dot nets>
58
+ Carl Worth <cworth at the cworth dot orgs>
56
59
  Jeff Balogh <its.jeff.balogh at the gmail dot coms>
57
60
  Andrew Pimlott <andrew at the pimlott dot nets>
58
61
  Matías Aguirre <matiasaguirre at the gmail dot coms>
59
62
  PaulSmecker <paul.smecker at the gmail dot coms>
60
- Per Andersson <avtobiff at the gmail dot coms>
61
63
  Ruthard Baudach <rthrd at the web dot des>
62
64
  Kornilios Kourtis <kkourt at the cslab.ece.ntua dot grs>
63
65
  Lars Fischer <fischer at the wiwi.uni-siegen dot des>
64
66
  madhat2r <MaDhAt2r at the dukefoo dot coms>
65
- Giorgio Lando <patroclo7 at the gmail dot coms>
66
67
  Kevin Riggle <kevinr at the free-dissociation dot coms>
68
+ Giorgio Lando <patroclo7 at the gmail dot coms>
67
69
  Benoît PIERRE <benoit.pierre at the gmail dot coms>
68
70
  Alvaro Herrera <alvherre at the alvh.no-ip dot orgs>
69
71
  Steven Lawrance <stl at the koffein dot nets>
70
72
  Jonah <Jonah at the GoodCoffee dot cas>
71
73
  ian <itaylor at the uark dot edus>
72
- Adam Lloyd <adam at the alloy-d dot nets>
73
74
  Todd Eisenberger <teisenbe at the andrew.cmu dot edus>
74
- 0xACE <0xACE at the users.noreply.github dot coms>
75
75
  MichaelRevell <mikearevell at the gmail dot coms>
76
+ Adam Lloyd <adam at the alloy-d dot nets>
77
+ 0xACE <0xACE at the users.noreply.github dot coms>
76
78
  Gregor Hoffleit <gregor at the sam.mediasupervision dot des>
77
- Steven Schmeiser <steven at the schmeiser dot orgs>
79
+ Sharif Olorin <sio at the tesser dot orgs>
78
80
  Steven Walter <swalter at the monarch.(none)>
79
- Jon M. Dugan <jdugan at the es dot nets>
80
- Horacio Sanson <horacio at the skillupjapan.co dot jps>
81
+ Steven Schmeiser <steven at the schmeiser dot orgs>
81
82
  Stefan Lundström <lundst at the snabb.(none)>
82
83
  William A. Kennington III <william at the wkennington dot coms>
83
84
  akojo <atte.kojo at the gmail dot coms>
85
+ Horacio Sanson <horacio at the skillupjapan.co dot jps>
86
+ Jon M. Dugan <jdugan at the es dot nets>
84
87
  Matthias Vallentin <vallentin at the icir dot orgs>
85
88
  Johannes Larsen <johs.a.larsen at the gmail dot coms>
86
89
  Kirill Smelkov <kirr at the landau.phys.spbu dot rus>
@@ -1,3 +1,19 @@
1
+ == 0.21.0 / 2015-02-12
2
+
3
+ * Key binding to fetch GPG key from keyserver (Matthieu Rakotojaona)
4
+ * Replace occurences of File.exists? with File.exist? (Zeger-Jan van de
5
+ Weg)
6
+ * You can now unsubscribe from mailinglists using an url, if you have a
7
+ goto-hook setup (Timon Vonk).
8
+ * Forward attribution can be customized using the forward-attribution
9
+ hook (Ruthard Baudach)
10
+ * Do a few more checks for buffer not nil in the hope to fix a few
11
+ random crashes
12
+ * Add bash completion (Per Andersson)
13
+ * Replace dl/import with Fiddle (Timon Vonk)
14
+ * Drop support for ruby 1.9.3
15
+ * Add tests for contact manager and persons (Zeger-Jan van de Weg)
16
+
1
17
  == 0.20.0 / 2014-10-06
2
18
 
3
19
  * add man-pages (generated from wiki) (Per Andersson)!
@@ -1,3 +1,10 @@
1
+ Release 0.21.0:
2
+
3
+ Several small features as well as polishing (including fetching a GPG key with
4
+ a shortcut and unsubscribing from mailinglist using an url). Several old
5
+ deprecated parts of sup have been modernized. Support for Ruby 1.9.3 has been
6
+ dropped. Have a look in History.txt for the details.
7
+
1
8
  Release 0.20.0:
2
9
 
3
10
  We've got man pages (Mr. Andersson)! We've got OpenBSD support (Scott Bonds)!
data/bin/sup CHANGED
@@ -7,6 +7,7 @@ require 'rubygems'
7
7
  require 'ncursesw'
8
8
 
9
9
  require 'sup/util/ncurses'
10
+ require 'sup/util/locale_fiddler'
10
11
 
11
12
  no_gpgme = false
12
13
  begin
@@ -102,32 +103,17 @@ global_keymap = Keymap.new do |k|
102
103
  end
103
104
  end
104
105
 
105
- ## the following magic enables wide characters when used with a ruby
106
- ## ncurses.so that's been compiled against libncursesw. (note the w.) why
107
- ## this works, i have no idea. much like pretty much every aspect of
108
- ## dealing with curses. cargo cult programming at its best.
109
106
  require 'rbconfig'
110
- unless RbConfig::CONFIG['arch'] =~ /openbsd/
111
- require 'dl/import'
112
- module LibC
113
- extend DL.const_defined?(:Importer) ? DL::Importer : DL::Importable
114
- setlocale_lib = case RbConfig::CONFIG['arch']
115
- when /darwin/; "libc.dylib"
116
- when /cygwin/; "cygwin1.dll"
117
- when /freebsd/; "libc.so.7"
118
- else; "libc.so.6"
119
- end
120
107
 
121
- debug "dynamically loading setlocale() from #{setlocale_lib}"
122
- begin
123
- dlload setlocale_lib
124
- extern "void setlocale(int, const char *)"
125
- debug "setting locale..."
126
- LibC.setlocale(6, "") # LC_ALL == 6
127
- rescue RuntimeError => e
128
- warn "cannot dlload setlocale(); ncurses wide character support probably broken."
129
- warn "dlload error was #{e.class}: #{e.message}"
130
- end
108
+ unless RbConfig::CONFIG['arch'] =~ /openbsd/
109
+ debug "dynamically loading setlocale()"
110
+ begin
111
+ class LibC; extend LocaleFiddler; end
112
+ debug "setting locale..."
113
+ LibC.setlocale(6, "")
114
+ rescue RuntimeError => e
115
+ warn "cannot dlload setlocale(); ncurses wide character support probably broken."
116
+ warn "dlload error was #{e.class}: #{e.message}"
131
117
  end
132
118
  end
133
119
 
@@ -60,7 +60,7 @@ $config[:sync_back_to_maildir] = true
60
60
 
61
61
  begin
62
62
  sync_performed = []
63
- sync_performed = File.readlines(Redwood::SYNC_OK_FN).collect { |e| e.strip }.find_all { |e| not e.empty? } if File.exists? Redwood::SYNC_OK_FN
63
+ sync_performed = File.readlines(Redwood::SYNC_OK_FN).collect { |e| e.strip }.find_all { |e| not e.empty? } if File.exist? Redwood::SYNC_OK_FN
64
64
  sources = []
65
65
 
66
66
  ## Try to find out sources given in parameters
@@ -0,0 +1,102 @@
1
+ # Sup Bash completion
2
+ #
3
+ # * Complete options for all Sup commands.
4
+ # * Disable completion for next option when current option takes an argument.
5
+ # * Complete sources, directories, and files, where applicable.
6
+
7
+ _sup_cmds() {
8
+ local cur prev opts sources
9
+ COMPREPLY=()
10
+ cur="${COMP_WORDS[COMP_CWORD]}"
11
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
12
+ sources="$(sed -n '/uri:/ {s/.*uri:\s*//p}' $HOME/.sup/sources.yaml)"
13
+
14
+ case "${1##/*}" in
15
+ sup-add)
16
+ opts="--archive -a --unusual -u --sync-back --no-sync-back -s
17
+ --labels -l --force-new -f --force-account -o --version -v
18
+ --help -h mbox: maildir:"
19
+
20
+ case $prev in
21
+ --labels|-l|--force-account|-o)
22
+ COMPREPLY=()
23
+ return 0
24
+ ;;
25
+ esac
26
+ ;;
27
+ sup-config|sup-dump)
28
+ opts="--version -v --help -h"
29
+ ;;
30
+ sup-import-dump)
31
+ opts="--verbose -v --ignore-missing -i --warn-missing -w
32
+ --abort-missing -a --atomic -t --dry-run -n --version --help
33
+ -h"
34
+ ;;
35
+ sup)
36
+ opts="--list-hooks -l --no-threads -n --no-initial-poll -o --search
37
+ -s --compose -c --subject -j --version -v --help -h"
38
+
39
+ case $prev in
40
+ --search|-s|--compose|-c|--subject|-j)
41
+ COMPREPLY=()
42
+ return 0
43
+ ;;
44
+ esac
45
+ ;;
46
+ sup-recover-sources)
47
+ opts="--unusual --archive --scan-num --help -h $sources"
48
+
49
+ case $prev in
50
+ --scan-num)
51
+ COMPREPLY=()
52
+ return 0
53
+ ;;
54
+ esac
55
+ ;;
56
+ sup-sync)
57
+ opts="--asis --restore --discard --archive -x --read -r
58
+ --extra-labels --verbose -v --optimize -o --all-sources
59
+ --dry-run -n --version --help -h ${sources}"
60
+
61
+
62
+ case $prev in
63
+ --restore|--extra-labels)
64
+ COMPREPLY=()
65
+ return 0
66
+ ;;
67
+ esac
68
+ ;;
69
+ sup-sync-back-maildir)
70
+ maildir_sources="$(echo $sources | tr ' ' '\n' | grep maildir)"
71
+ opts="--no-confirm -n --no-merge -m --list-sources -l
72
+ --unusual-sources-too -u --version -v --help -h
73
+ $maildir_sources"
74
+ ;;
75
+ sup-tweak-labels)
76
+ opts="--add -a --remove -r --query -q --verbose -v --very-verbose
77
+ -e --all-sources --dry-run -n --no-sync-back -o --version
78
+ --help -h $sources"
79
+
80
+ case $prev in
81
+ --add|-a|--remove|-r|--query|-q)
82
+ COMPREPLY=()
83
+ return 0
84
+ ;;
85
+ esac
86
+ ;;
87
+ esac
88
+
89
+ COMPREPLY=( $(compgen -W "$opts" -- ${cur}) )
90
+ return 0
91
+ }
92
+
93
+ complete -F _sup_cmds sup \
94
+ sup-add \
95
+ sup-config \
96
+ sup-dump \
97
+ sup-recover-sources \
98
+ sup-sync \
99
+ sup-sync-back-maildir \
100
+ sup-tweak-labels
101
+
102
+ complete -F _sup_cmds -o filenames -o plusdirs sup-import-dump
data/lib/sup.rb CHANGED
@@ -105,7 +105,7 @@ module Redwood
105
105
  o
106
106
  end
107
107
 
108
- mode = if File.exists? fn
108
+ mode = if File.exist? fn
109
109
  File.stat(fn).mode
110
110
  else
111
111
  0600
@@ -113,7 +113,7 @@ module Redwood
113
113
 
114
114
  if backup
115
115
  backup_fn = fn + '.bak'
116
- if File.exists?(fn) && File.size(fn) > 0
116
+ if File.exist?(fn) && File.size(fn) > 0
117
117
  File.open(backup_fn, "w", mode) do |f|
118
118
  File.open(fn, "r") { |old_f| FileUtils.copy_stream old_f, f }
119
119
  f.fsync
@@ -139,7 +139,7 @@ module Redwood
139
139
  end
140
140
 
141
141
  def load_yaml_obj fn, compress=false
142
- o = if File.exists? fn
142
+ o = if File.exist? fn
143
143
  if compress
144
144
  Zlib::GzipReader.open(fn) { |f| YAML::load f }
145
145
  else
@@ -180,7 +180,7 @@ module Redwood
180
180
  return if bypass_sync_check
181
181
 
182
182
  if $config[:sync_back_to_maildir]
183
- if not File.exists? Redwood::SYNC_OK_FN
183
+ if not File.exist? Redwood::SYNC_OK_FN
184
184
  Redwood.warn_syncback <<EOS
185
185
  It appears that the "sync_back_to_maildir" option has been changed
186
186
  from false to true since the last execution of sup.
@@ -191,14 +191,14 @@ Should I complain about this again? (Y/n)
191
191
  EOS
192
192
  File.open(Redwood::SYNC_OK_FN, 'w') {|f| f.write(Redwood::MAILDIR_SYNC_CHECK_SKIPPED) } if STDIN.gets.chomp.downcase == 'n'
193
193
  end
194
- elsif not $config[:sync_back_to_maildir] and File.exists? Redwood::SYNC_OK_FN
194
+ elsif not $config[:sync_back_to_maildir] and File.exist? Redwood::SYNC_OK_FN
195
195
  File.delete(Redwood::SYNC_OK_FN)
196
196
  end
197
197
  end
198
198
 
199
199
  def check_syncback_settings
200
200
  # don't check if syncback was never performed
201
- return unless File.exists? Redwood::SYNC_OK_FN
201
+ return unless File.exist? Redwood::SYNC_OK_FN
202
202
  active_sync_sources = File.readlines(Redwood::SYNC_OK_FN).collect { |e| e.strip }.find_all { |e| not e.empty? }
203
203
  return if active_sync_sources.length == 1 and active_sync_sources[0] == Redwood::MAILDIR_SYNC_CHECK_SKIPPED
204
204
  sources = SourceManager.sources
@@ -338,7 +338,7 @@ EOM
338
338
  :continuous_scroll => false,
339
339
  :always_edit_async => false,
340
340
  }
341
- if File.exists? filename
341
+ if File.exist? filename
342
342
  config = Redwood::load_yaml_obj filename
343
343
  abort "#{filename} is not a valid configuration file (it's a #{config.class}, not a hash)" unless config.is_a?(Hash)
344
344
  default_config.merge config
@@ -17,6 +17,9 @@ module Ncurses
17
17
 
18
18
  ## xterm 24-shade grayscale
19
19
  24.times { |x| color! "g#{x}", (16+6*6*6) + x }
20
+ elsif Ncurses::NUM_COLORS == -1
21
+ ## Terminal emulator doesn't appear to support colors
22
+ fail "sup must be run in a terminal with color support, please check your TERM variable."
20
23
  end
21
24
  end
22
25
 
@@ -186,13 +189,13 @@ class Colormap
186
189
  ## Try to use the user defined colors, in case of an error fall back
187
190
  ## to the default ones.
188
191
  def populate_colormap
189
- user_colors = if File.exists? Redwood::COLOR_FN
192
+ user_colors = if File.exist? Redwood::COLOR_FN
190
193
  debug "loading user colors from #{Redwood::COLOR_FN}"
191
194
  Redwood::load_yaml_obj Redwood::COLOR_FN
192
195
  end
193
196
 
194
197
  ## Set attachment sybmol to sane default for existing colorschemes
195
- if user_colors and user_colors.has_key? :to_me
198
+ if user_colors and user_colors.has_key? :to_me
196
199
  user_colors[:with_attachment] = user_colors[:to_me] unless user_colors.has_key? :with_attachment
197
200
  end
198
201
 
@@ -16,7 +16,7 @@ class ContactManager
16
16
  @a2p = {} # alias to person
17
17
  @e2p = {} # email to person
18
18
 
19
- if File.exists? fn
19
+ if File.exist? fn
20
20
  IO.foreach(fn) do |l|
21
21
  l =~ /^([^:]*): (.*)$/ or raise "can't parse #{fn} line #{l.inspect}"
22
22
  aalias, addr = $1, $2
@@ -29,11 +29,13 @@ class ContactManager
29
29
  def contacts_with_aliases; @a2p.values.uniq end
30
30
 
31
31
  def update_alias person, aalias=nil
32
+ ## Deleting old data if it exists
32
33
  old_aalias = @p2a[person]
33
- if(old_aalias != nil and old_aalias != "") # remove old alias
34
+ if old_aalias
34
35
  @a2p.delete old_aalias
35
36
  @e2p.delete person.email
36
37
  end
38
+ ## Update with new data
37
39
  @p2a[person] = aalias
38
40
  unless aalias.nil? || aalias.empty?
39
41
  @a2p[aalias] = person
@@ -16,6 +16,9 @@ class CryptoManager
16
16
  [:encrypt, "Encrypt only"]
17
17
  )
18
18
 
19
+ KEY_PATTERN = /(-----BEGIN PGP PUBLIC KEY BLOCK.*-----END PGP PUBLIC KEY BLOCK)/m
20
+ KEYSERVER_URL = "http://pool.sks-keyservers.net:11371/pks/lookup"
21
+
19
22
  HookManager.register "gpg-options", <<EOS
20
23
  Runs before gpg is called, allowing you to modify the options (most
21
24
  likely you would want to add something to certain commands, like
@@ -212,9 +215,10 @@ EOS
212
215
  unknown = false
213
216
  all_output_lines = []
214
217
  all_trusted = true
218
+ unknown_fingerprint = nil
215
219
 
216
220
  verify_result.signatures.each do |signature|
217
- output_lines, trusted = sig_output_lines signature
221
+ output_lines, trusted, unknown_fingerprint = sig_output_lines signature
218
222
  all_output_lines << output_lines
219
223
  all_output_lines.flatten!
220
224
  all_trusted &&= trusted
@@ -242,6 +246,8 @@ EOS
242
246
  end
243
247
  elsif !unknown
244
248
  Chunk::CryptoNotice.new(:invalid, summary_line, all_output_lines)
249
+ elsif unknown_fingerprint
250
+ Chunk::CryptoNotice.new(:unknown_key, "Unable to determine validity of cryptographic signature", all_output_lines, unknown_fingerprint)
245
251
  else
246
252
  unknown_status all_output_lines
247
253
  end
@@ -351,6 +357,31 @@ EOS
351
357
  [notice, sig, msg]
352
358
  end
353
359
 
360
+ def retrieve fingerprint
361
+ require 'net/http'
362
+ uri = URI($config[:keyserver_url] || KEYSERVER_URL)
363
+ unless uri.scheme == "http" and not uri.host.nil?
364
+ return "Invalid url: #{uri}"
365
+ end
366
+
367
+ fingerprint = "0x" + fingerprint unless fingerprint[0..1] == "0x"
368
+ params = {op: "get", search: fingerprint}
369
+ uri.query = URI.encode_www_form(params)
370
+
371
+ begin
372
+ res = Net::HTTP.get_response(uri)
373
+ rescue SocketError # Host doesn't exist or we couldn't connect
374
+ end
375
+ return "Couldn't get key from keyserver at this address: #{uri}" unless res.is_a?(Net::HTTPSuccess)
376
+
377
+ match = KEY_PATTERN.match(res.body)
378
+ return "No key found" unless match && match.length > 0
379
+
380
+ GPGME::Key.import(match[0])
381
+
382
+ return nil
383
+ end
384
+
354
385
  private
355
386
 
356
387
  def unknown_status lines=[]
@@ -394,6 +425,7 @@ private
394
425
  rescue EOFError
395
426
  from_key = nil
396
427
  first_sig = "No public key available for #{signature.fingerprint}"
428
+ unknown_fpr = signature.fingerprint
397
429
  end
398
430
 
399
431
  time_line = "Signature made " + signature.timestamp.strftime("%a %d %b %Y %H:%M:%S %Z") +
@@ -422,7 +454,7 @@ private
422
454
  output_lines << HookManager.run("sig-output",
423
455
  {:signature => signature, :from_key => from_key})
424
456
  end
425
- return output_lines, trusted
457
+ return output_lines, trusted, unknown_fpr
426
458
  end
427
459
 
428
460
  def key_type key, fpr