public
Description: command-line tool to sign update manifests of Mozilla extensions (update.rdf)
Homepage: http://hyperstruct.net/projects/spock
Clone URL: git://github.com/bard/spock.git
bard (author)
Sat Aug 16 15:18:38 -0700 2008
spock / spock
100755 95 lines (70 sloc) 2.795 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/usr/bin/env ruby
#-*- ruby -*-
 
######################################################################
# Retrieve command-line parameters
 
require 'optparse'
require 'ostruct'
require 'digest'
require 'digest/sha2'
 
options = OpenStruct.new
options.ext_id = nil
options.version = nil
options.update_link = nil
 
OptionParser.new do |opts|
  opts.banner = "Usage: #{File.basename($0)} [options] FILE"
 
  opts.on('-i', '--extension-id ID',
    'ID of the extension resource, including version if any', 'Examples:',
    'urn:mozilla:extension:foo@bar.org:0.1',
    'urn:mozilla:extension:{eecba28f-b68b-4b3a-b501-6ce12e6b8696}') { |options.ext_id| }
  opts.on('-v', '--version VERSION',
    'Set <version/> value in resulting update.rdf') { |options.version| }
  opts.on('-u', '--update-link URL',
    'Set <updateLink/> value in resulting update.rdf') { |options.update_link| }
  opts.on('-f', '--file PACKAGE_FILENAME',
    'Determine <updateHash/> value using PACKAGE_FILENAME') { |options.package_filename| }
  opts.on('-d', '--nss-directory DIR',
    'Directory containing key key3.db',
    'Example: ~/.mozilla/mccoy/rt7xxbxw.default/') { |options.nss_dir| }
 
  opts.separator ''
 
  opts.on_tail('-h', '--help', 'This help text') do
    puts opts
    exit
  end
end.parse!
options.filename = ARGV.shift
 
 
 
options.filename or abort "#{File.basename($0)}: please provide path to update.rdf."
options.ext_id or abort "#{File.basename($0)}: please provide an extension ID."
options.nss_dir or abort "#{File.basename($0)}: please provide path to directory containing key3.db."
 
 
######################################################################
# NORMALIZE update.rdf
 
require File.dirname(__FILE__) + '/normalize_update_rdf'
 
ds = parse_nt(rdf2nt(options.filename))
 
def filehash(filename)
  if Digest::SHA256.method_defined?(:file)
    Digest::SHA256.file(filename)
  else
    Digest::SHA256.hexdigest(File.read(filename))
  end
end
 
updater = proc do |subj, pred, obj|
  if pred == NS_EM + 'version'
    options.version
  elsif pred == NS_EM + 'updateLink'
    options.update_link
  elsif pred == NS_EM + 'updateHash' and options.package_filename
    "sha256:#{filehash(options.package_filename)}"
  end
end
 
signable_data = serialize_resource(ds, options.ext_id, &updater)
signer_cmdline = "#{File.dirname(__FILE__)}/nss_sign_data #{options.nss_dir}"
 
signature = IO.popen(signer_cmdline, 'w+') do |f|
  f.write signable_data
  f.close_write
  f.gets.chomp
end
 
ds[options.ext_id] << [options.ext_id, NS_EM + 'signature', signature]
 
signed_data = serialize_resource(ds, options.ext_id, &updater)
 
puts '<?xml version="1.0"?>'
puts '<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">'
puts signed_data
puts '</RDF:RDF>'