push_package 0.0.3 → 0.1.0

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.
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ ---
2
+ language: ruby
3
+ rvm:
4
+ - 1.9.3
5
+ - jruby-19mode
6
+ - rbx-19mode
7
+ - 2.0.0
8
+ notifications:
9
+ email:
10
+ - adam.v.duke@gmail.com
11
+ - stefan.natchev@gmail.com
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- push_package (0.0.3)
4
+ push_package (0.1.0)
5
+ rubyzip (~> 1.1.0)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
@@ -14,6 +15,7 @@ GEM
14
15
  method_source (~> 0.8)
15
16
  slop (~> 3.4)
16
17
  rake (10.0.3)
18
+ rubyzip (1.1.0)
17
19
  slop (3.4.6)
18
20
 
19
21
  PLATFORMS
data/README.md CHANGED
@@ -1,14 +1,43 @@
1
+ # Push Package
2
+
1
3
  ## Purpose
2
- Make implementing safari push notifications easier for ruby developers.
4
+
5
+ This gem provides a Ruby library and command line tool for creating a push package to be used for [Safari Push Notifications](https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NotificationProgrammingGuideForWebsites/PushNotifications/PushNotifications.html#//apple_ref/doc/uid/TP40013225-CH3-SW24).
6
+
7
+ ## Features
8
+
9
+ * Validates push package contents
10
+ * Generates manifest.json
11
+ * Signs package with required signature
12
+ * Creates pushPackage.zip
13
+
14
+ ## Installation
15
+
16
+ ```gem install push_package```
3
17
 
4
18
  ## Notes:
5
19
 
20
+ This gem depends on `zip` being in your shell's `PATH`
21
+
22
+ You must obtain a Website Push certificate from apple which requires a iOS developer license or a Mac developer license
23
+
6
24
  ```ruby
7
- def create
8
- package = PushPackage.new(website_params, iconset_path, certificate)
9
- package.save('path/to/save')
10
- send_file 'path/to/save'
11
- end
25
+ require 'push_package'
26
+
27
+ website_params = {
28
+ websiteName: "Bay Airlines",
29
+ websitePushID: "web.com.example.domain",
30
+ allowedDomains: ["http://domain.example.com"],
31
+ urlFormatString: "http://domain.example.com/%@/?flight=%@",
32
+ authenticationToken: "19f8d7a6e9fb8a7f6d9330dabe",
33
+ webServiceURL: "https://example.com/push"
34
+ }
35
+
36
+ iconset_path = 'path/to/iconset'
37
+ certificate = 'path/to/certificate.p12' # or certificate_string
38
+ package = PushPackage.new(website_params, iconset_path, certificate, 'optional cert password')
39
+ package.save('path/to/save')
40
+
12
41
  ```
13
42
 
14
43
  ```shell
data/lib/push_package.rb CHANGED
@@ -2,7 +2,9 @@ require 'push_package/version'
2
2
  require 'json'
3
3
  require 'fileutils'
4
4
  require 'tmpdir'
5
+ require 'tempfile'
5
6
  require 'openssl'
7
+ require 'zip'
6
8
 
7
9
  class PushPackage
8
10
  class InvalidIconsetError < StandardError; end
@@ -30,40 +32,66 @@ class PushPackage
30
32
  @p12 = OpenSSL::PKCS12.new(cert_data, password)
31
33
  end
32
34
 
33
- def save(output_path)
34
- Dir.mktmpdir('pushPackage') do |dir|
35
- json = File.open(dir + '/website.json', 'w+')
36
- json.write(JSON.dump(@website_params))
37
- json.close
35
+ def save(output_path = nil)
38
36
 
39
- Dir.mkdir(File.join(dir,'icon.iconset'))
40
- Dir.glob(@iconset_path + '/*.png').each do |icon|
41
- FileUtils.cp(icon, dir + '/icon.iconset/')
42
- end
37
+ @working_dir = Dir.mktmpdir('pushPackage')
43
38
 
44
- manifest_keys = REQUIRED_ICONSET_FILES.map{|f| 'icon.iconset/' + f }
45
- manifest_keys << 'website.json'
46
- manifest_values = manifest_keys.map {|file| Digest::SHA1.file(File.join(dir, file)).hexdigest }
47
- manifest_data = Hash[manifest_keys.zip(manifest_values)].to_json
48
- File.open(dir + '/manifest.json', 'w+') do |manifest|
49
- manifest.write(manifest_data)
50
- end
39
+ if output_path
40
+ output_path = File.expand_path(output_path)
41
+ else
42
+ output_path = Dir.tmpdir + '/pushPackage.zip'
43
+ end
51
44
 
52
- #use the certificate to create a pkcs7 detached signature
53
- signature = OpenSSL::PKCS7::sign(@p12.certificate, @p12.key, manifest_data, [], OpenSSL::PKCS7::BINARY | OpenSSL::PKCS7::DETACHED)
45
+ ## overwrite existing push packages
46
+ File.delete(output_path) if File.exists?(output_path)
54
47
 
55
- File.open(dir + '/signature', 'wb+') do |file|
56
- file << signature.to_der
57
- end
48
+ zip = Zip::File.open(output_path, Zip::File::CREATE)
49
+
50
+ File.open(@working_dir + '/website.json', 'w+') do |json|
51
+ json.write(JSON.dump(@website_params))
52
+ end
53
+
54
+ Dir.mkdir(File.join(@working_dir,'icon.iconset'))
55
+ Dir.glob(@iconset_path + '/*.png').each do |icon|
56
+ FileUtils.cp(icon, @working_dir + '/icon.iconset/')
57
+ end
58
58
 
59
- `pushd #{dir}; zip -r #{output_path} ./; popd`
59
+ File.open(@working_dir + '/manifest.json', 'w+') do |manifest|
60
+ manifest.write(manifest_data)
60
61
  end
61
62
 
63
+ File.open(@working_dir + '/signature', 'wb+') do |file|
64
+ file.write(signature.to_der)
65
+ end
66
+
67
+ Dir.glob(@working_dir + '/**/*').each do |file|
68
+ next if File.directory?(file)
69
+ zip.add(file.gsub("#{@working_dir}/", ''), file)
70
+ end
71
+
72
+ zip.close
73
+
74
+ #clean up the temporary directory
75
+ FileUtils.remove_entry_secure(@working_dir)
76
+
77
+ #re-open the file for reading
62
78
  File.open(output_path, 'r')
63
79
  end
64
80
 
65
81
  private
66
82
 
83
+ def signature
84
+ #use the certificate to create a pkcs7 detached signature
85
+ OpenSSL::PKCS7::sign(@p12.certificate, @p12.key, manifest_data, [], OpenSSL::PKCS7::BINARY | OpenSSL::PKCS7::DETACHED)
86
+ end
87
+
88
+ def manifest_data
89
+ manifest_keys = REQUIRED_ICONSET_FILES.map{|f| 'icon.iconset/' + f }
90
+ manifest_keys << 'website.json'
91
+ manifest_values = manifest_keys.map {|file| Digest::SHA1.file(File.join(@working_dir, file)).hexdigest }
92
+ Hash[manifest_keys.zip(manifest_values)].to_json
93
+ end
94
+
67
95
  def valid_website_params?(params)
68
96
  REQUIRED_WEBSITE_PARAMS.all? do |param|
69
97
  params.keys.include?(param)
@@ -1,3 +1,3 @@
1
1
  class PushPackage
2
- VERSION = '0.0.3'.freeze
2
+ VERSION = '0.1.0'.freeze
3
3
  end
data/push_package.gemspec CHANGED
@@ -5,7 +5,7 @@ require 'push_package/version'
5
5
 
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "push_package"
8
- gem.version = PushPackage::VERSION
8
+ gem.version = PushPackage::VERSION.dup
9
9
  gem.authors = ["Stefan Natchev", "Adam Duke"]
10
10
  gem.email = ["stefan.natchev@gmail.com", "adam.v.duke@gmail.com"]
11
11
  gem.summary = %q{A gem for creating Safari push notification push packages.}
@@ -19,6 +19,8 @@ Gem::Specification.new do |gem|
19
19
  gem.require_paths = ["lib"]
20
20
  gem.required_ruby_version = '>= 1.9'
21
21
 
22
+ gem.add_runtime_dependency 'rubyzip', '~> 1.1.0'
23
+
22
24
  gem.add_development_dependency 'minitest', '~> 4.7.0'
23
25
  gem.add_development_dependency 'rake', '~> 10.0.3'
24
26
  gem.add_development_dependency 'pry'
@@ -84,7 +84,19 @@ describe PushPackage do
84
84
  end
85
85
 
86
86
  it 'should save to the file system' do
87
- File.exist?(output_path).must_equal(true)
87
+ File.exist?(output_path).must_equal true
88
+ end
89
+
90
+ it 'should save with a relative path' do
91
+ push_package.save('pushPackage.zip')
92
+ File.exist?('./pushPackage.zip').must_equal true
93
+ File.delete('./pushPackage.zip')
94
+ end
95
+
96
+ it 'should save to a temporary path' do
97
+ file = push_package.save
98
+ File.exist?(file.path).must_equal true
99
+ File.delete(file.path)
88
100
  end
89
101
 
90
102
  it 'should return the file handle' do
metadata CHANGED
@@ -1,7 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: push_package
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Stefan Natchev
@@ -9,11 +10,28 @@ authors:
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2013-11-14 00:00:00.000000000 Z
13
+ date: 2013-12-19 00:00:00.000000000 Z
13
14
  dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rubyzip
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: 1.1.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ version: 1.1.0
14
31
  - !ruby/object:Gem::Dependency
15
32
  name: minitest
16
33
  requirement: !ruby/object:Gem::Requirement
34
+ none: false
17
35
  requirements:
18
36
  - - ~>
19
37
  - !ruby/object:Gem::Version
@@ -21,6 +39,7 @@ dependencies:
21
39
  type: :development
22
40
  prerelease: false
23
41
  version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
24
43
  requirements:
25
44
  - - ~>
26
45
  - !ruby/object:Gem::Version
@@ -28,6 +47,7 @@ dependencies:
28
47
  - !ruby/object:Gem::Dependency
29
48
  name: rake
30
49
  requirement: !ruby/object:Gem::Requirement
50
+ none: false
31
51
  requirements:
32
52
  - - ~>
33
53
  - !ruby/object:Gem::Version
@@ -35,6 +55,7 @@ dependencies:
35
55
  type: :development
36
56
  prerelease: false
37
57
  version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
38
59
  requirements:
39
60
  - - ~>
40
61
  - !ruby/object:Gem::Version
@@ -42,6 +63,7 @@ dependencies:
42
63
  - !ruby/object:Gem::Dependency
43
64
  name: pry
44
65
  requirement: !ruby/object:Gem::Requirement
66
+ none: false
45
67
  requirements:
46
68
  - - ! '>='
47
69
  - !ruby/object:Gem::Version
@@ -49,6 +71,7 @@ dependencies:
49
71
  type: :development
50
72
  prerelease: false
51
73
  version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
52
75
  requirements:
53
76
  - - ! '>='
54
77
  - !ruby/object:Gem::Version
@@ -63,6 +86,7 @@ extensions: []
63
86
  extra_rdoc_files: []
64
87
  files:
65
88
  - .gitignore
89
+ - .travis.yml
66
90
  - Gemfile
67
91
  - Gemfile.lock
68
92
  - LICENSE.txt
@@ -86,26 +110,27 @@ files:
86
110
  homepage: https://github.com/symmetricinfinity/push_package
87
111
  licenses:
88
112
  - MIT
89
- metadata: {}
90
113
  post_install_message:
91
114
  rdoc_options: []
92
115
  require_paths:
93
116
  - lib
94
117
  required_ruby_version: !ruby/object:Gem::Requirement
118
+ none: false
95
119
  requirements:
96
120
  - - ! '>='
97
121
  - !ruby/object:Gem::Version
98
122
  version: '1.9'
99
123
  required_rubygems_version: !ruby/object:Gem::Requirement
124
+ none: false
100
125
  requirements:
101
126
  - - ! '>='
102
127
  - !ruby/object:Gem::Version
103
128
  version: '0'
104
129
  requirements: []
105
130
  rubyforge_project:
106
- rubygems_version: 2.1.0
131
+ rubygems_version: 1.8.23
107
132
  signing_key:
108
- specification_version: 4
133
+ specification_version: 3
109
134
  summary: A gem for creating Safari push notification push packages.
110
135
  test_files:
111
136
  - spec/fixtures/iconset/icon_128x128.png
checksums.yaml DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ZjE5YzE1ZWIwZGY2OGQxNDM3YmE1NWIwN2U4ZGFiZTgxMDY3ZTk1Ng==
5
- data.tar.gz: !binary |-
6
- NDJlZTBmM2ZlNmY5NTAzM2NjY2MxYWZhN2MxN2FiMmI0ODNhMzQ4OQ==
7
- SHA512:
8
- metadata.gz: !binary |-
9
- ZGFhYzJmYWM3YWZkZWUwMGUwNWUxNjFiNGI5NWZhZDQ3NTljMmQ4ZDAwZWY4
10
- NWRmMDcwYmViZGI5ZTQ5OTkwZjIwNzY5ZjU0MTkzNTBiNmUyOWY1MDUwMGMw
11
- NDk4MGQ4YWNjYzQzMjA1MWRjOWMyYjkwMTJlNDNjY2Y0M2E5MzA=
12
- data.tar.gz: !binary |-
13
- ZDg3ZTUxZDRlZTFlM2VjNTFmZGY5YTgxN2JjZjk3ZWIxYjZlODAxZjNlMDY1
14
- OGMzNWRlNTIyNTI3ODcxMzExZWEyZTRjMTI2YjE0NWM1YWIwZGUwNjJiNzRl
15
- MTAxYWIxMTljMTQ5NjVlZmU1NWVkZDdiMjYzNWIyZTRiM2VmODg=