crxmake 1.0.2

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.
Files changed (6) hide show
  1. data/README.rdoc +76 -0
  2. data/Rakefile +95 -0
  3. data/bin/crxmake +68 -0
  4. data/lib/crxmake.rb +166 -0
  5. data/test/crxmake_test.rb +35 -0
  6. metadata +73 -0
data/README.rdoc ADDED
@@ -0,0 +1,76 @@
1
+ = crxmake
2
+
3
+ * http://github.com/Constellation/crxmake
4
+
5
+ == DESCRIPTION:
6
+
7
+ make chromium extensions
8
+
9
+ == SYNOPSIS:
10
+ ruby code
11
+ require 'crxmake'
12
+ CrxMake.make(
13
+ :ex_dir => "./src",
14
+ :pkey => "./test.pem",
15
+ :crx_output => "./package/test.crx",
16
+ :verbose => true,
17
+ :ignorefile => /\.swp/,
18
+ :ignoredir => /\.(?:svn|git|cvs)/
19
+ )
20
+
21
+ command line
22
+ $ crxmake --pack-extension=<extension dir> --extension-output=<extension output path> --pack-extension-key=<pem path>
23
+
24
+ required opt
25
+ --pack-extension=<extension dir>
26
+ extension source directory
27
+
28
+ optional opt
29
+ --extension-output=<extension output path>
30
+ crx output path (default: ./<extension dirname>.crx)
31
+ --pack-extension-key=<pem path>
32
+ pem key path
33
+ --key-output=<key path>
34
+ pem key output path if you generate key (default: ./<extension
35
+ dirname>.pem)
36
+ --ignore-file=<pattern>
37
+ pattern to ignore files
38
+ pattern is compiled by Regexp.new(<pattern>)
39
+ --ignore-dir=<pattern>
40
+ pattern to ignore directories
41
+ pattern is compiled by Regexp.new(<pattern>)
42
+
43
+ == REQUIREMENTS:
44
+
45
+ * openssl
46
+ * zipruby
47
+
48
+ == INSTALL:
49
+
50
+ gem source -a http://gemcutter.org
51
+ sudo gem install crxmake
52
+
53
+ == LICENSE:
54
+
55
+ (The MIT License)
56
+
57
+ Copyright (c) 2009 Constellation
58
+
59
+ Permission is hereby granted, free of charge, to any person obtaining
60
+ a copy of this software and associated documentation files (the
61
+ 'Software'), to deal in the Software without restriction, including
62
+ without limitation the rights to use, copy, modify, merge, publish,
63
+ distribute, sublicense, and/or sell copies of the Software, and to
64
+ permit persons to whom the Software is furnished to do so, subject to
65
+ the following conditions:
66
+
67
+ The above copyright notice and this permission notice shall be
68
+ included in all copies or substantial portions of the Software.
69
+
70
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
71
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
72
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
73
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
74
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
75
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
76
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,95 @@
1
+ # vim: fileencoding=utf-8
2
+ require 'rubygems'
3
+ require 'rake'
4
+ require 'rake/clean'
5
+ require 'rake/testtask'
6
+ require 'rake/packagetask'
7
+ require 'rake/gempackagetask'
8
+ require 'rake/rdoctask'
9
+ require 'rake/contrib/rubyforgepublisher'
10
+ require 'rake/contrib/sshpublisher'
11
+ require 'fileutils'
12
+ require 'lib/crxmake'
13
+ include FileUtils
14
+
15
+ $version = CrxMake::VERSION
16
+ $readme = 'README.rdoc'
17
+ $rdoc_opts = %W(--main #{$readme} --charset utf-8 --line-numbers --inline-source)
18
+ $name = 'crxmake'
19
+ $summary = 'make chromium extension'
20
+ $author = 'Constellation'
21
+ $email = 'utatane.tea@gmail.com'
22
+ $page = 'http://github.com/Constellation/crxmake/tree/master'
23
+ $exec = %W(crxmake)
24
+ $rubyforge_project = 'crxmake'
25
+
26
+
27
+ task :default => [:test]
28
+ task :package => [:clean]
29
+
30
+ Rake::TestTask.new("test") do |t|
31
+ t.libs << "test"
32
+ t.pattern = "test/**/*_test.rb"
33
+ t.verbose = true
34
+ end
35
+
36
+ spec = Gem::Specification.new do |s|
37
+ s.name = $name
38
+ s.version = $version
39
+ s.platform = Gem::Platform::RUBY
40
+ s.has_rdoc = true
41
+ s.extra_rdoc_files = [$readme]
42
+ s.rdoc_options += $rdoc_opts
43
+ s.summary = $summary
44
+ s.description = $summary
45
+ s.author = $author
46
+ s.email = $email
47
+ s.homepage = $page
48
+ s.executables = $exec
49
+ s.rubyforge_project = $rubyforge_project
50
+ s.bindir = 'bin'
51
+ s.require_path = 'lib'
52
+ s.test_files = Dir["test/*_test.rb"]
53
+ {
54
+ "zipruby" => ">=0.3.2",
55
+ # "openssl" => ">=1.0.0"
56
+ }.each do |dep, ver|
57
+ s.add_dependency(dep, ver)
58
+ end
59
+ s.files = %w(README.rdoc Rakefile) + Dir["{bin,test,lib}/**/*"]
60
+ end
61
+
62
+ Rake::GemPackageTask.new(spec) do |p|
63
+ p.need_tar = true
64
+ p.gem_spec = spec
65
+ end
66
+
67
+ Rake::RDocTask.new do |rdoc|
68
+ rdoc.rdoc_dir = 'doc'
69
+ rdoc.options += $rdoc_opts
70
+ # rdoc.template = 'resh'
71
+ rdoc.rdoc_files.include("README.rdoc", "lib/**/*.rb", "ext/**/*.c")
72
+ end
73
+
74
+ desc "gem spec"
75
+ task :gemspec do
76
+ File.open("#{$name}.gemspec", "wb") do |f|
77
+ f << spec.to_ruby
78
+ end
79
+ end
80
+
81
+ desc "gem build"
82
+ task :build => [:gemspec] do
83
+ sh "gem build #{$name}.gemspec"
84
+ end
85
+
86
+ desc "gem install"
87
+ task :install => [:build] do
88
+ sh "sudo gem install #{$name}-#{$version}.gem --local"
89
+ end
90
+
91
+ desc "gem uninstall"
92
+ task :uninstall do
93
+ sh "sudo gem uninstall #{$name}"
94
+ end
95
+ # vim: syntax=ruby
data/bin/crxmake ADDED
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/ruby
2
+ # vim: fileencoding=utf-8
3
+ require 'rubygems'
4
+ require 'optparse'
5
+ require 'crxmake'
6
+
7
+ data = {}
8
+ usage = <<-EOS
9
+ option not valid
10
+
11
+ [usage]
12
+ required opt
13
+ --pack-extension=<extension dir>
14
+ extension source directory
15
+
16
+ optional opt
17
+ --extension-output=<extension output path>
18
+ crx output path (default: ./<extension dirname>.crx)
19
+ --pack-extension-key=<pem path>
20
+ pem key path
21
+ --key-output=<key path>
22
+ pem key output path if you generate key (default: ./<extension
23
+ dirname>.pem)
24
+ --ignore-file=<pattern>
25
+ pattern to ignore files
26
+ pattern is compiled by Regexp.new(<pattern>)
27
+ --ignore-dir=<pattern>
28
+ pattern to ignore directories
29
+ pattern is compiled by Regexp.new(<pattern>)
30
+ EOS
31
+
32
+ OptionParser.new('Packaging Chromium Extension') do |opt|
33
+ opt.version = '2'
34
+ opt.on('--pack-extension DIR') do |val|
35
+ data[:ex_dir] = val
36
+ end
37
+ opt.on('--pack-extension-key KEY') do |key|
38
+ data[:pkey] = key
39
+ end
40
+ opt.on('--key-output OKEY') do |okey|
41
+ data[:pkey_output] = okey
42
+ end
43
+ opt.on('--extension-output CRX') do |crx|
44
+ data[:crx_output] = crx
45
+ end
46
+ opt.on('--ignore-file FILE') do |file|
47
+ data[:ignorefile] = Regexp.new file
48
+ end
49
+ opt.on('--ignore-dir DIR') do |dir|
50
+ data[:ignoredir] = Regexp.new dir
51
+ end
52
+ opt.on('-v', '--verbose') do
53
+ data[:verbose] = true
54
+ end
55
+ begin
56
+ opt.parse!(ARGV)
57
+ rescue
58
+ puts usage
59
+ end
60
+ end
61
+
62
+ begin
63
+ CrxMake.make(data)
64
+ rescue => e
65
+ puts e.message
66
+ puts usage
67
+ end
68
+
data/lib/crxmake.rb ADDED
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/ruby
2
+ # vim: fileencoding=utf-8
3
+ require 'rubygems'
4
+ require 'zipruby'
5
+ require 'openssl'
6
+ require 'digest/sha1'
7
+ require 'fileutils'
8
+ require 'find'
9
+ require 'pathname'
10
+
11
+ class CrxMake < Object
12
+ VERSION = '1.0.2'
13
+ @@magic = [?C, ?r, ?2, ?4].pack('C*')
14
+ # this is chromium extension version
15
+ @@version = [2].pack('L')
16
+
17
+ # CERT_PUBLIC_KEY_INFO struct
18
+ @@key_algo = %w(30 81 9F 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01 05 00 03 81 8D 00).map{|s| s.hex}.pack('C*')
19
+ @@key_size = 1024
20
+ def initialize opt
21
+ check_valid_option(opt)
22
+ if @pkey
23
+ read_key
24
+ else
25
+ generate_key
26
+ end
27
+ create_zip
28
+ sign_zip
29
+ write_crx
30
+ ensure
31
+ final
32
+ end
33
+
34
+ private
35
+ def check_valid_option o
36
+ @exdir, @pkey, @pkey_o, @crx, @verbose, @ignorefile, @ignoredir = o[:ex_dir], o[:pkey], o[:pkey_output], o[:crx_output], o[:verbose], o[:ignorefile], o[:ignoredir]
37
+ @exdir = File.expand_path(@exdir) if @exdir
38
+ raise "extension dir not exist" if !@exdir || !File.exist?(@exdir) || !File.directory?(@exdir)
39
+ @pkey = File.expand_path(@pkey) if @pkey
40
+ raise "private key not exist" if @pkey && (!File.exist?(@pkey) || !File.file?(@pkey))
41
+ if @pkey_o
42
+ @pkey_o = File.expand_path(@pkey_o)
43
+ raise "private key output path is directory" if File.directory?(@pkey_o)
44
+ else
45
+ count = 0
46
+ loop do
47
+ if count.zero?
48
+ @pkey_o = File.expand_path("./#{File.basename(@exdir)}.pem")
49
+ else
50
+ @pkey_o = File.expand_path("./#{File.basename(@exdir)}-#{count+=1}.pem")
51
+ end
52
+ break unless File.directory?(@pkey_o)
53
+ end
54
+ end
55
+ if @crx
56
+ @crx = File.expand_path(@crx)
57
+ raise "crx path is directory" if File.directory?(@crx)
58
+ else
59
+ count = 0
60
+ loop do
61
+ if count.zero?
62
+ @crx = File.expand_path("./#{File.basename(@exdir)}.crx")
63
+ else
64
+ @crx = File.expand_path("./#{File.basename(@exdir)}-#{count+=1}.crx")
65
+ end
66
+ break unless File.directory?(@crx)
67
+ end
68
+ end
69
+ @crx_dir = File.dirname(@crx)
70
+ puts <<-EOS if @verbose
71
+ crx output dir: \"#{@crx}\"
72
+ ext dir: \"#{@exdir}\"
73
+ EOS
74
+ @zip = File.join(@crx_dir, 'extension.zip')
75
+ end
76
+
77
+ def read_key
78
+ puts "read pemkey: \"#{@pkey}\"" if @verbose
79
+ File.open(@pkey, 'rb') do |io|
80
+ @key = OpenSSL::PKey::RSA.new(io)
81
+ end
82
+ end
83
+
84
+ def generate_key
85
+ puts "generate pemkey to \"#{@pkey_o}\"" if @verbose
86
+ @key = OpenSSL::PKey::RSA.generate(@@key_size)
87
+ # save key
88
+ File.open(@pkey_o, 'wb') do |file|
89
+ file << @key.export()
90
+ end
91
+ end
92
+
93
+ def create_zip
94
+ puts "create zip" if @verbose
95
+ Zip::Archive.open(@zip, Zip::CREATE | Zip::TRUNC) do |zip|
96
+ Find.find(@exdir) do |path|
97
+ unless path == @exdir
98
+ if File.directory?(path)
99
+ if @ignoredir && File.basename(path) =~ @ignoredir
100
+ puts "ignore dir: \"#{path}\"" if @verbose
101
+ Find.prune
102
+ else
103
+ puts "include dir: \"#{path}\"" if @verbose
104
+ zip.add_dir(get_relative(@exdir, path))
105
+ end
106
+ else
107
+ if @ignorefile && File.basename(path) =~ @ignorefile
108
+ puts "ignore file: \"#{path}\"" if @verbose
109
+ else
110
+ puts "include file: \"#{path}\"" if @verbose
111
+ zip.add_file(get_relative(@exdir, path), path)
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+ puts <<-EOS if @verbose
118
+ create zip...done
119
+ zip file at \"#{@zip}\"
120
+ EOS
121
+ end
122
+
123
+ def get_relative base, target
124
+ Pathname.new(target.to_s).relative_path_from(Pathname.new(base.to_s)).to_s
125
+ end
126
+
127
+ def sign_zip
128
+ puts "sign zip" if @verbose
129
+ plain = nil
130
+ File.open(@zip, 'rb') do |file|
131
+ plain = file.read
132
+ end
133
+ @sig = @key.sign(OpenSSL::Digest::SHA1.new, plain)
134
+ end
135
+
136
+ def write_crx
137
+ print "write crx..." if @verbose
138
+ key = @@key_algo+@key.public_key.to_der
139
+ File.open(@crx, 'wb') do |file|
140
+ file << @@magic
141
+ file << @@version
142
+ file << to_sizet(key.size)
143
+ file << to_sizet(@sig.size)
144
+ file << key
145
+ file << @sig
146
+ File.open(@zip, 'rb') do |zip|
147
+ file << zip.read
148
+ end
149
+ end
150
+ puts "done at \"#{@crx}\"" if @verbose
151
+ end
152
+
153
+ def to_sizet num
154
+ return [num].pack('L')
155
+ end
156
+
157
+ def final
158
+ FileUtils.rm_rf(@zip) if @zip && File.exist?(@zip)
159
+ end
160
+
161
+ class << self
162
+ alias make new
163
+ end
164
+ end
165
+
166
+
@@ -0,0 +1,35 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../lib/crxmake'
3
+ require 'fileutils'
4
+ require 'pp'
5
+ require 'open-uri'
6
+
7
+ class CrxMakeTest < Test::Unit::TestCase
8
+ def setup
9
+ @dir = File.expand_path('tmp')
10
+ FileUtils.mkdir @dir
11
+ # chromefullfeed compile
12
+ open("http://chromefullfeed.googlecode.com/files/package.tar") do |file|
13
+ File.open(File.join(@dir, 'package.tar'), 'wb') do |f|
14
+ f << file.read
15
+ end
16
+ end
17
+ system("tar -xf #{File.join(@dir, "package.tar")} -C #{@dir}")
18
+ end
19
+ def teardown
20
+ FileUtils.rm_rf @dir
21
+ end
22
+ def test_create_crx
23
+ CrxMake.make(
24
+ :ex_dir => File.join(@dir, 'src'),
25
+ :pkey_output => File.join(@dir, 'test.pem'),
26
+ :crx_output => File.join(@dir, 'test.crx'),
27
+ :verbose => true,
28
+ :ignorefile => /\.swp$/,
29
+ :ignoredir => /^\.(?:svn|git|cvs)$/
30
+ )
31
+ assert(File.exist?(File.join(@dir, 'test.crx')))
32
+ assert(File.exist?(File.join(@dir, 'test.pem')))
33
+ end
34
+ end
35
+
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: crxmake
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Constellation
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-09 00:00:00 +09:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: zipruby
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.3.2
24
+ version:
25
+ description: make chromium extension
26
+ email: utatane.tea@gmail.com
27
+ executables:
28
+ - crxmake
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.rdoc
33
+ files:
34
+ - README.rdoc
35
+ - Rakefile
36
+ - bin/crxmake
37
+ - test/crxmake_test.rb
38
+ - lib/crxmake.rb
39
+ has_rdoc: true
40
+ homepage: http://github.com/Constellation/crxmake/tree/master
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options:
45
+ - --main
46
+ - README.rdoc
47
+ - --charset
48
+ - utf-8
49
+ - --line-numbers
50
+ - --inline-source
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ requirements: []
66
+
67
+ rubyforge_project: crxmake
68
+ rubygems_version: 1.3.5
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: make chromium extension
72
+ test_files:
73
+ - test/crxmake_test.rb