extensionator 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c159fab576ebc4eee9fafc8e9c67cb3c057acf9f
4
- data.tar.gz: 67917fd1539033b7bfdc84a55e80f7b58b4e71d6
3
+ metadata.gz: 3780dd6f297b930567d87ad3db41b44f43702759
4
+ data.tar.gz: 9ac68018622dff9e312be10be2cfe97522ec35e2
5
5
  SHA512:
6
- metadata.gz: 430508a2a39100f6fe3b34357d6e323bc85e8fe4d08548a967cfa6b94adc7c74c19147c0d787daf43a29ee60101258ba397a3616812297d5a5cbb8aaf13f0bf8
7
- data.tar.gz: 7dc51d6fd2646d24ea6dbc1b8eb1bfcbfb2495cf2ea592898c0e07a0636517fb7c03732fcdc8d692dd459b347af7464d32f7ce1d8b7f609d2cdb0e718dcd02c8
6
+ metadata.gz: 7806db009edfc01d8e56a9aced37d2e287b2b37293464977d49b1e748cfedef0e5da1665bd7f709cd8dffcf91cea4e6234c12b982eadabd1bcbaac8ff2368bfa
7
+ data.tar.gz: 61eb7af4225a22e2397baf1427507ece88a658c630c22d00c6cd5d53bb7ff22e28d7cbdfaba5f5e4bcd40c120661dbfe196de15eccfd69ee82500966f8c47a6c
data/README.md CHANGED
@@ -2,13 +2,12 @@
2
2
 
3
3
  Package Chrome extensions. Inspired by [crxmake][crxmake-url], but with an eye towards simplicity and supportability. Use the CLI or the Ruby API.
4
4
 
5
- [![Gem Version][gem-img]][gem-url]
6
- [![License][license-img]][license]
7
- [![Gem Downloads][gem-dl-img]][gem-url]
5
+ [![Gem Version][gem-image]][gem-url]
6
+ [![MIT License][license-image]][license]
7
+ [![Gem Downloads][gem-dl-image]][gem-url]
8
8
  [![Build Status][travis-image]][travis-url]
9
- [![Code Climate][code-climate-img]][code-climate-url]
9
+ [![Code Climate][code-climate-image]][code-climate-url]
10
10
  [![Dependencies][gemnasium-image]][gemnasium-url]
11
- ![Phasers to stun][phasers-image]
12
11
 
13
12
  ## Install
14
13
 
@@ -70,18 +69,20 @@ Extensionator.create("dir", "key.pem", "output_file.crx", exclude: /\.md$/)
70
69
 
71
70
  Copyright 2015 Zensight. Distributed under the MIT License. See the [LICENSE][] file for more details.
72
71
 
73
- [license-img]: http://img.shields.io/badge/license-MIT-blue.svg?style=flat-square
72
+ ![Phasers to stun][phasers-image]
73
+
74
+ [license-image]: http://img.shields.io/badge/license-MIT-blue.svg?style=flat-square
74
75
  [license]: LICENSE.md
75
76
 
76
- [code-climate-img]: https://img.shields.io/codeclimate/github/Zensight/extensionator.svg?style=flat-square
77
+ [code-climate-image]: https://img.shields.io/codeclimate/github/Zensight/extensionator.svg?style=flat-square
77
78
  [code-climate-url]: https://codeclimate.com/github/Zensight/extensionator
78
79
 
79
- [gem-img]: https://img.shields.io/gem/v/extensionator.svg?style=flat-square
80
- [gem-dl-img]: https://img.shields.io/gem/dt/extensionator.svg?style=flat-square
80
+ [gem-image]: https://img.shields.io/gem/v/extensionator.svg?style=flat-square
81
+ [gem-dl-image]: https://img.shields.io/gem/dt/extensionator.svg?style=flat-square
81
82
  [gem-url]: https://rubygems.org/gems/extensionator
82
83
 
83
- [travis-url]: http://travis-ci.org/zensight/extensionator
84
- [travis-image]: http://img.shields.io/travis/zensight/extensionator.svg?style=flat-square
84
+ [travis-url]: http://travis-ci.org/Zensight/extensionator
85
+ [travis-image]: http://img.shields.io/travis/Zensight/extensionator.svg?style=flat-square
85
86
 
86
87
  [gemnasium-url]: https://gemnasium.com/zensight/extensionator
87
88
  [gemnasium-image]: https://img.shields.io/gemnasium/Zensight/extensionator.svg?style=flat-square
@@ -2,8 +2,10 @@
2
2
 
3
3
  begin
4
4
  require_relative "../lib/extensionator"
5
+ require_relative "../lib/extensionator/cli"
5
6
  rescue LoadError
6
7
  require "extensionator"
8
+ require "../lib/extensionator/cli"
7
9
  end
8
10
 
9
11
  Extensionator::CLI.start
@@ -1,7 +1,24 @@
1
- Dir["#{__dir__}/extensionator/*.rb"].each{|f| require f}
1
+ require_relative "extensionator/error"
2
+ require_relative "extensionator/manifest"
3
+ require_relative "extensionator/crx"
4
+ require_relative "extensionator/creator"
2
5
 
3
6
  module Extensionator
4
- def self.create(dir, key_file, dest_filename, opts = {exclude: /\.crx$/})
5
- Impl.create(dir, key_file, dest_filename, opts)
7
+
8
+ def self.validate(dir, opts={})
9
+ Creator.new(dir, opts).validate
10
+ end
11
+
12
+ def self.crx(dir, identity_file, dest_filename, opts = {})
13
+ Creator.new(dir, opts.merge(identity: identity_file)).crx(dest_filename)
14
+ end
15
+
16
+ def self.zip(dir, dest_filename, opts= {})
17
+ Creator.new(dir, opts).zip(dest_filename)
18
+ end
19
+
20
+ ##deprecated, reverse compat
21
+ def self.create(dir, identity_file, dest_filename, opts = {})
22
+ crx(dir, identity_file, dest_filename, opts)
6
23
  end
7
24
  end
@@ -1,13 +1,18 @@
1
1
  require "slop"
2
+ require_relative "../extensionator"
2
3
 
3
4
  module Extensionator
4
5
  module CLI
5
6
  def self.start
6
7
  opts = Slop.parse do |o|
7
- o.string "-d", "--directory", "Directory containing the extension. (Default: .)", default: "."
8
- o.string "-i", "--identity", "Location of the pem file to sign with. (Required)"
9
- o.string "-o", "--output", "Location of the output file. (Default: 'extension.crx')", default: "extension.crx"
10
- o.string "-e", "--exclude", "Regular expression for filenames to exclude. (Default: \.crx$)", default: nil
8
+ o.string "-d", "--directory", "Directory containing the extension. (Default: .)"
9
+ o.string "-i", "--identity", "Location of the pem file to sign with."
10
+ o.string "-o", "--output", "Location of the output file. (Default: 'extension.[zip|crx]')"
11
+ o.string "-e", "--exclude", "Regular expression for filenames to exclude. (Default: \.crx$)"
12
+ o.string "-f", "--format", "Type of file to produce, either zip or crx. Defaults to crx"
13
+ o.string "--inject-version", "Inject a version number into the manifest file."
14
+ o.bool "--inject-key", "Inject a key parameter into the manifest file."
15
+ #o.string "--skip-validation", "Don't try to validate this extension."
11
16
  o.on "-v", "--version", "Extensionator version info." do
12
17
  puts Extensionator::VERSION
13
18
  exit
@@ -18,12 +23,19 @@ module Extensionator
18
23
  end
19
24
  end
20
25
 
21
- abort("No identity file specified; use --identity or -i switch.") unless opts[:identity]
26
+ creator = Creator.new(opts[:directory], opts)
27
+ if opts[:format] == "zip"
28
+ creator.zip(opts[:output] || "output.zip")
29
+ else
30
+ creator.crx(opts[:output] || "output.crx")
31
+ end
32
+
33
+ end
22
34
 
23
- Extensionator.create(opts[:directory],
24
- opts[:identity],
25
- opts[:output],
26
- exclude: opts[:exclude] ? Regexp.new(opts[:exclude]) : nil)
35
+ def self.fixup_options(in_opts)
36
+ opts = in_opts.clone
37
+ opts[:output] = output.to_sym if opts[:output]
38
+ opts[:exclude] = Regexp.new(opts[:exclude]) if opts[:exclude]
27
39
  end
28
40
  end
29
41
  end
@@ -0,0 +1,110 @@
1
+ require "find"
2
+ require "openssl"
3
+ require "pathname"
4
+ require "zip"
5
+
6
+ module Extensionator
7
+ class Creator
8
+
9
+ def initialize(dir, options)
10
+ @dir = dir
11
+ @opts = {
12
+ inject_key: false,
13
+ inject_version: nil,
14
+ skip_validation: false
15
+ }.merge(options)
16
+ end
17
+
18
+ def zip(destination)
19
+ with_files("zip") do |zip_str|
20
+ File.open(destination, "wb"){|f| f.write zip_str}
21
+ end
22
+ end
23
+
24
+ def crx(destination)
25
+ with_files("crx") do |zip_str|
26
+ CRX.create(destination, zip_str, private_key)
27
+ end
28
+ end
29
+
30
+ def validate
31
+ manifest.validate(dir_files)
32
+ end
33
+
34
+ private
35
+
36
+ def with_files(default_extension)
37
+ files = process_directory
38
+ yield zip_up(files)
39
+ end
40
+
41
+ def process_directory
42
+ new_paths = dir_files
43
+
44
+ manifest.validate(new_paths) unless @opts[:skip_validation]
45
+ manifest.inject_key(private_key) if @opts[:inject_key]
46
+ manifest.inject_version(@opts[:inject_version]) if @opts[:inject_version]
47
+
48
+ new_paths << manifest.write if manifest_updated?
49
+
50
+ new_paths
51
+ end
52
+
53
+ def zip_up(paths)
54
+ Zip.continue_on_exists_proc = true
55
+ Zip::File.add_buffer do |zip|
56
+ paths.each do |path_combo|
57
+ path_in_zip, file = path_combo
58
+ if File.directory?(file)
59
+ zip.mkdir(path_in_zip, file)
60
+ else
61
+ zip.add(path_in_zip, file)
62
+ end
63
+ end
64
+ end.string
65
+ end
66
+
67
+ def dir_files
68
+ unless @dir_files
69
+ @dir_files = []
70
+ Find.find(@dir) do |path|
71
+ case
72
+ when path == @dir
73
+ next
74
+ when (@opts[:exclude] && path =~ @opts[:exclude])
75
+ Find.prune
76
+ else
77
+ @dir_files << [relative_path(@dir, path), path]
78
+ end
79
+ end
80
+ end
81
+ @dir_files
82
+ end
83
+
84
+ def manifest
85
+ @manifest ||= Manifest.new(@dir)
86
+ end
87
+
88
+ def manifest_updated?
89
+ @manifest && @manifest.updated?
90
+ end
91
+
92
+ def private_key
93
+ @private_key ||=
94
+ if @opts[:identity]
95
+ begin
96
+ OpenSSL::PKey::RSA.new(File.read(@opts[:identity]))
97
+ rescue Error => e
98
+ raise KeyError.new("Couldn't read key file #{@opts[:identity]}: #{e.message}")
99
+ end
100
+ else
101
+ raise ArgumentError.new("You need to specify an identity file for this operation.")
102
+ end
103
+ end
104
+
105
+ def relative_path(base, target)
106
+ from, to = [base, target].map(&Pathname.method(:new))
107
+ to.relative_path_from(from).to_s
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,34 @@
1
+ require "digest/sha1"
2
+
3
+ module Extensionator
4
+ module CRX
5
+
6
+ def self.create(destination, zip_str, priv_key)
7
+ sig_bytes = sign(zip_str, priv_key)
8
+ write_crx(destination, zip_str, sig_bytes, priv_key)
9
+ end
10
+
11
+ def self.sign(zip_str, priv_key)
12
+ priv_key.sign(OpenSSL::Digest::SHA1.new, zip_str)
13
+ end
14
+
15
+ def self.write_crx(destination, zip_str, sig_bytes, priv_key)
16
+ pub_key_bytes = priv_key.public_key.to_der
17
+
18
+ #See https://developer.chrome.com/extensions/crx for the format description
19
+ File.open(destination, "wb") do |file|
20
+ file << "Cr24"
21
+ file << format_size(2)
22
+ file << format_size(pub_key_bytes.size)
23
+ file << format_size(sig_bytes.size)
24
+ file << pub_key_bytes
25
+ file << sig_bytes
26
+ file << zip_str
27
+ end
28
+ end
29
+
30
+ def self.format_size(num)
31
+ [num].pack("V")
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,9 @@
1
+ module Extensionator
2
+ class Error < StandardError
3
+
4
+ ArgumentError = Class.new(self)
5
+ KeyError = Class.new(self)
6
+ ValidationError = Class.new(self)
7
+ end
8
+ end
9
+
@@ -0,0 +1,47 @@
1
+ require "json"
2
+ require "base64"
3
+
4
+ module Extensionator
5
+ class Manifest
6
+
7
+ def initialize(dir)
8
+ manifest_file = "#{dir}/manifest.json"
9
+
10
+ raise "Can't find manifest file" unless File.exists? manifest_file
11
+
12
+ begin
13
+ @manifest = JSON.parse(File.read(manifest_file))
14
+ rescue Errno::ENOTENT => e
15
+ raise ValidationError.new("Can't read manifest file: #{e.message}")
16
+ rescue JSON::ParserError => e
17
+ raise ValidationError.new("Can't parse manifest file: #{e.message}")
18
+ end
19
+ end
20
+
21
+ def validate(paths)
22
+ #todo: actual validations!
23
+ true
24
+ end
25
+
26
+ def inject_key(priv_key)
27
+ #Chrome appears to support some shorter encoding of the pub key, but I'm not sure what it is
28
+ @manifest["key"] = Base64.encode64(priv_key.public_key.to_der).gsub("\n", "")
29
+ @updated = true
30
+ end
31
+
32
+ def inject_version(version)
33
+ @manifest["version"] = version
34
+ @updated = true
35
+ end
36
+
37
+ def updated?
38
+ @updated || false
39
+ end
40
+
41
+ def write
42
+ file = Tempfile.new("crx-manifest.json")
43
+ File.open(file, "w"){|f| f.write(JSON.dump(@manifest))}
44
+ ["manifest.json", file.path]
45
+ end
46
+ end
47
+ end
@@ -1,3 +1,3 @@
1
1
  module Extensionator
2
- VERSION = "1.0.1"
2
+ VERSION = "1.1.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: extensionator
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Isaac Cambron
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-23 00:00:00.000000000 Z
11
+ date: 2015-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -65,7 +65,10 @@ files:
65
65
  - extensionator.gemspec
66
66
  - lib/extensionator.rb
67
67
  - lib/extensionator/cli.rb
68
- - lib/extensionator/impl.rb
68
+ - lib/extensionator/creator.rb
69
+ - lib/extensionator/crx.rb
70
+ - lib/extensionator/error.rb
71
+ - lib/extensionator/manifest.rb
69
72
  - lib/extensionator/version.rb
70
73
  homepage: http://github.com/zensight/extensionator/
71
74
  licenses:
@@ -1,65 +0,0 @@
1
- require "digest/sha1"
2
- require "find"
3
- require "openssl"
4
- require "pathname"
5
- require "zip"
6
-
7
- module Extensionator
8
- module Impl
9
- def self.create(dir, key_file, dest_filename, opts)
10
- priv_key = read_key(key_file)
11
- zip_str = zip(dir, opts)
12
- sig_bytes = sign(zip_str, priv_key)
13
- write(zip_str, sig_bytes, priv_key, dest_filename)
14
- end
15
-
16
- def self.read_key(key_file)
17
- OpenSSL::PKey::RSA.new(File.read(key_file))
18
- end
19
-
20
- def self.zip(dir, opts = {})
21
- Zip::File.add_buffer do |zip|
22
- Find.find(dir) do |path|
23
- case
24
- when path == dir
25
- next
26
- when (opts[:exclude] && path =~ opts[:exclude])
27
- Find.prune
28
- when File.directory?(path)
29
- zip.mkdir(relative_path(dir, path))
30
- else
31
- zip.add(relative_path(dir, path), path)
32
- end
33
- end
34
- end.string
35
- end
36
-
37
- def self.sign(zip_str, priv_key)
38
- priv_key.sign(OpenSSL::Digest::SHA1.new, zip_str)
39
- end
40
-
41
- def self.write(zip_str, sig_bytes, priv_key, dest_filename)
42
- pub_key_bytes = priv_key.public_key.to_der
43
-
44
- #See https://developer.chrome.com/extensions/crx for the format description
45
- File.open(dest_filename, "wb") do |file|
46
- file << "Cr24"
47
- file << format_size(2)
48
- file << format_size(pub_key_bytes.size)
49
- file << format_size(sig_bytes.size)
50
- file << pub_key_bytes
51
- file << sig_bytes
52
- file << zip_str
53
- end
54
- end
55
-
56
- def self.relative_path(base, target)
57
- from, to = [base, target].map(&Pathname.method(:new))
58
- to.relative_path_from(from).to_s
59
- end
60
-
61
- def self.format_size(num)
62
- [num].pack("V")
63
- end
64
- end
65
- end