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 +11 -0
- data/Gemfile.lock +3 -1
- data/README.md +35 -6
- data/lib/push_package.rb +50 -22
- data/lib/push_package/version.rb +1 -1
- data/push_package.gemspec +3 -1
- data/spec/push_package_spec.rb +13 -1
- metadata +30 -5
- checksums.yaml +0 -15
data/.travis.yml
ADDED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
push_package (0.0
|
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
|
-
|
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
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
53
|
-
|
45
|
+
## overwrite existing push packages
|
46
|
+
File.delete(output_path) if File.exists?(output_path)
|
54
47
|
|
55
|
-
|
56
|
-
|
57
|
-
|
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
|
-
|
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)
|
data/lib/push_package/version.rb
CHANGED
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'
|
data/spec/push_package_spec.rb
CHANGED
@@ -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
|
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
|
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-
|
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:
|
131
|
+
rubygems_version: 1.8.23
|
107
132
|
signing_key:
|
108
|
-
specification_version:
|
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=
|