push_package 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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=