push_package 0.0.1 → 0.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.
- checksums.yaml +8 -8
- data/Gemfile.lock +9 -1
- data/README.md +13 -1
- data/lib/push_package.rb +75 -1
- data/lib/push_package/version.rb +2 -2
- data/push_package.gemspec +1 -0
- data/spec/fixtures/iconset/icon_128x128.png +0 -0
- data/spec/fixtures/iconset/icon_128x128@2x.png +0 -0
- data/spec/fixtures/iconset/icon_16x16.png +0 -0
- data/spec/fixtures/iconset/icon_16x16@2x.png +0 -0
- data/spec/fixtures/iconset/icon_32x32.png +0 -0
- data/spec/fixtures/iconset/icon_32x32@2x.png +0 -0
- data/spec/fixtures/manifest.json +1 -0
- data/spec/fixtures/self-signed.p12 +0 -0
- data/spec/fixtures/signature +0 -0
- data/spec/push_package_spec.rb +121 -0
- data/spec/spec_helper.rb +3 -0
- metadata +34 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YzMyYmUwZDI3OTNhMjQ5ZmMzYTljZDk0M2Y1YmU0NTUwM2M3MTA2OA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YmQwOGVjMjRiMTUwZTYzMGM0MGEzM2I1MzcxODczMGRkNGQ0ZGU4Zg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MWQzY2NkYzBhZjhjMGI3MzJkMjg4YTZkYzUwYTNiMmE4NzQ5MmJiZDE4NDJi
|
10
|
+
MTdkZGQyY2I0ZDUzZjdmMzc0MjJmYzI4MTk4YjBkMjY0NjU4M2RkZmUyNzJi
|
11
|
+
NzJhNTJkOGVkN2JkODkzYWMyNDQxMDgyYmEwMGE0ZjUyZmZjMTg=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZmZjYjNkYWFmOWQxMmY0ZmJmMDIyNDExZDU0MmExMDliZjEzMjM4MWQzOGZl
|
14
|
+
Y2Y1N2I1MDRiNDIzNjIwYmYwMDFmMDdlOWU3MDJhYTdiMmFmMjMxZTUyMDFk
|
15
|
+
NWRkMDk2ZGE0NTVjZjYyZGI4NWNmYjAxMjdkZWVmNzk1YTRjMTY=
|
data/Gemfile.lock
CHANGED
@@ -1,18 +1,26 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
push_package (0.0.
|
4
|
+
push_package (0.0.2)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
+
coderay (1.0.9)
|
10
|
+
method_source (0.8.2)
|
9
11
|
minitest (4.7.0)
|
12
|
+
pry (0.9.12.2)
|
13
|
+
coderay (~> 1.0.5)
|
14
|
+
method_source (~> 0.8)
|
15
|
+
slop (~> 3.4)
|
10
16
|
rake (10.0.3)
|
17
|
+
slop (3.4.6)
|
11
18
|
|
12
19
|
PLATFORMS
|
13
20
|
ruby
|
14
21
|
|
15
22
|
DEPENDENCIES
|
16
23
|
minitest (~> 4.7.0)
|
24
|
+
pry
|
17
25
|
push_package!
|
18
26
|
rake (~> 10.0.3)
|
data/README.md
CHANGED
@@ -2,7 +2,19 @@
|
|
2
2
|
Make implementing safari push notifications easier for ruby developers.
|
3
3
|
|
4
4
|
## Notes:
|
5
|
-
|
5
|
+
|
6
|
+
```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
|
12
|
+
```
|
13
|
+
|
14
|
+
```shell
|
15
|
+
$> push_package --website-json=./website.json --iconset-path=~/project/iconset --output-dir=./ --certificate=./Certificate.p12
|
16
|
+
wrote: ./pushPackage.zip
|
17
|
+
```
|
6
18
|
|
7
19
|
## Contributing
|
8
20
|
|
data/lib/push_package.rb
CHANGED
@@ -1,4 +1,78 @@
|
|
1
1
|
require 'push_package/version'
|
2
|
+
require 'json'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'tmpdir'
|
5
|
+
require 'openssl'
|
2
6
|
|
3
|
-
|
7
|
+
class PushPackage
|
8
|
+
class InvalidIconsetError < StandardError; end
|
9
|
+
class InvalidParameterError < StandardError; end
|
10
|
+
|
11
|
+
REQUIRED_WEBSITE_PARAMS = ["websiteName", "websitePushID", "allowedDomains", "urlFormatString", "authenticationToken", "webServiceURL"]
|
12
|
+
REQUIRED_ICONSET_FILES = ["icon_16x16.png", "icon_16x16@2x.png", "icon_32x32.png", "icon_32x32@2x.png", "icon_128x128.png", "icon_128x128@2x.png" ]
|
13
|
+
|
14
|
+
attr_reader :p12
|
15
|
+
|
16
|
+
def initialize(website_params, iconset_path, certificate, password = nil)
|
17
|
+
raise InvalidParameterError unless valid_website_params?(website_params)
|
18
|
+
raise InvalidIconsetError unless valid_iconset?(iconset_path)
|
19
|
+
raise ArgumentError unless certificate
|
20
|
+
|
21
|
+
@website_params = website_params
|
22
|
+
@iconset_path = iconset_path
|
23
|
+
|
24
|
+
if certificate.respond_to?(:read)
|
25
|
+
cert_data = certificate.read
|
26
|
+
certificate.rewind if certificate.respond_to?(:rewind)
|
27
|
+
else
|
28
|
+
cert_data = File.read(certificate)
|
29
|
+
end
|
30
|
+
@p12 = OpenSSL::PKCS12.new(cert_data, password)
|
31
|
+
end
|
32
|
+
|
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
|
38
|
+
|
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
|
43
|
+
|
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
|
51
|
+
|
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)
|
54
|
+
|
55
|
+
File.open(dir + '/signature', 'wb+') do |file|
|
56
|
+
file << signature.to_der
|
57
|
+
end
|
58
|
+
|
59
|
+
`pushd #{dir}; zip -r #{output_path} ./; popd`
|
60
|
+
end
|
61
|
+
|
62
|
+
File.open(output_path, 'r')
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def valid_website_params?(params)
|
68
|
+
REQUIRED_WEBSITE_PARAMS.all? do |param|
|
69
|
+
params.keys.include?(param)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def valid_iconset?(iconset_path)
|
74
|
+
REQUIRED_ICONSET_FILES.all? do |file|
|
75
|
+
File.exist?(File.join(iconset_path, file))
|
76
|
+
end
|
77
|
+
end
|
4
78
|
end
|
data/lib/push_package/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
VERSION = '0.0.
|
1
|
+
class PushPackage
|
2
|
+
VERSION = '0.0.2'.freeze
|
3
3
|
end
|
data/push_package.gemspec
CHANGED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
{"icon.iconset/icon_128x128.png":"28969578f1788252807a7d8205db269cb7699fa8","icon.iconset/icon_128x128@2x.png":"dd2bf0e3cb998467b0e5f5ae11675a454ad77601","icon.iconset/icon_16x16.png":"48e791d0c88b92fae51ffa8363821857210fca01","icon.iconset/icon_16x16@2x.png":"5a74d295cc09ca5896a4ceb7cac0d030cc85e894","icon.iconset/icon_32x32.png":"8c71bc22f4cfe12ad98aabe94da6a70fe9f15741","icon.iconset/icon_32x32@2x.png":"750e080d38efe1c227b2498f73f006007f3da24b","website.json":"3eaed6475443b895a49e3a1220e547f2be90434a"}
|
Binary file
|
Binary file
|
data/spec/push_package_spec.rb
CHANGED
@@ -1,10 +1,131 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'fileutils'
|
2
3
|
|
3
4
|
describe PushPackage do
|
4
5
|
|
6
|
+
let(:iconset_path) { fixture_path 'iconset' }
|
7
|
+
|
8
|
+
let(:website_params) do
|
9
|
+
{
|
10
|
+
'websiteName' => 'Push Package Test',
|
11
|
+
'websitePushID' => 'web.com.symmetricinfinity.push_package',
|
12
|
+
'allowedDomains' => ['http://symmetricinfinity.com/push_package/', 'http://lvh.me'],
|
13
|
+
'urlFormatString' => 'http://symmetricinfinity.com/push_package/?%@=%@',
|
14
|
+
'authenticationToken' => 'nr2o1spn515949r5q54so22o8rq95575',
|
15
|
+
'webServiceURL' => 'https://api.zeropush.com/safari'
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:expected_manifest) do
|
20
|
+
{
|
21
|
+
'icon.iconset/icon_128x128.png' => '28969578f1788252807a7d8205db269cb7699fa8',
|
22
|
+
'icon.iconset/icon_128x128@2x.png' => 'dd2bf0e3cb998467b0e5f5ae11675a454ad77601',
|
23
|
+
'icon.iconset/icon_16x16.png' => '48e791d0c88b92fae51ffa8363821857210fca01',
|
24
|
+
'icon.iconset/icon_16x16@2x.png' => '5a74d295cc09ca5896a4ceb7cac0d030cc85e894',
|
25
|
+
'icon.iconset/icon_32x32.png' => '8c71bc22f4cfe12ad98aabe94da6a70fe9f15741',
|
26
|
+
'icon.iconset/icon_32x32@2x.png' => '750e080d38efe1c227b2498f73f006007f3da24b',
|
27
|
+
'website.json' => '3eaed6475443b895a49e3a1220e547f2be90434a'
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
let(:certificate) { File.open(fixture_path('self-signed.p12')) }
|
32
|
+
|
5
33
|
describe 'the truth' do
|
6
34
|
it 'should pass' do
|
7
35
|
'test'.must_equal('test')
|
8
36
|
end
|
9
37
|
end
|
38
|
+
|
39
|
+
describe '.new' do
|
40
|
+
it 'should check website_params' do
|
41
|
+
lambda do
|
42
|
+
PushPackage.new({}, iconset_path, certificate)
|
43
|
+
end.must_raise(PushPackage::InvalidParameterError)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'must have a valid iconset' do
|
47
|
+
lambda do
|
48
|
+
PushPackage.new(website_params, '/tmp', certificate)
|
49
|
+
end.must_raise(PushPackage::InvalidIconsetError)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should support a certificate path' do
|
53
|
+
lambda do
|
54
|
+
PushPackage.new(website_params, iconset_path, nil)
|
55
|
+
end.must_raise(ArgumentError)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should support certificate path' do
|
59
|
+
lambda do
|
60
|
+
PushPackage.new(website_params, iconset_path, '/some/file.p12')
|
61
|
+
end.must_raise(Errno::ENOENT)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#save' do
|
66
|
+
let(:output_path) { '/tmp/pushPackage.zip' }
|
67
|
+
let(:tmp_path) { '/tmp/pushPackage' }
|
68
|
+
let(:extracted_package) do
|
69
|
+
`unzip #{output_path} -d #{tmp_path}`
|
70
|
+
Dir.glob(tmp_path + '/**/*').map do |d|
|
71
|
+
d.gsub(tmp_path + '/', '')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
let(:push_package) { PushPackage.new(website_params, iconset_path, certificate) }
|
76
|
+
|
77
|
+
before do
|
78
|
+
push_package.save(output_path)
|
79
|
+
end
|
80
|
+
|
81
|
+
after do
|
82
|
+
File.delete(output_path) if File.exist?(output_path)
|
83
|
+
FileUtils.rm_rf(tmp_path)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should save to the file system' do
|
87
|
+
File.exist?(output_path).must_equal(true)
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should return the file handle' do
|
91
|
+
file = push_package.save(output_path)
|
92
|
+
file.must_be_instance_of File
|
93
|
+
File.exists?(file.path).must_equal true
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should be a zip file' do
|
97
|
+
extracted_package.wont_be_empty
|
98
|
+
$?.success?.must_equal true
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should have a valid manifest.json file' do
|
102
|
+
extracted_package.must_include('manifest.json')
|
103
|
+
manifest = JSON.load(File.open(tmp_path + '/manifest.json', 'r'))
|
104
|
+
manifest.sort.must_equal(expected_manifest.sort)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should have the iconset in icon.iconset subdirectory' do
|
108
|
+
icons = extracted_package.select {|file| file.start_with?('icon.iconset/') }
|
109
|
+
icons = icons.map {|i| i.gsub('icon.iconset/', '') }
|
110
|
+
icons.sort.must_equal(PushPackage::REQUIRED_ICONSET_FILES.sort)
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should have a website.json file' do
|
114
|
+
extracted_package.must_include('website.json')
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'should have a valid signature' do
|
118
|
+
extracted_package.must_include('signature')
|
119
|
+
signature = File.read(tmp_path + '/signature')
|
120
|
+
p7 = OpenSSL::PKCS7.new(signature)
|
121
|
+
store = OpenSSL::X509::Store.new
|
122
|
+
store.add_cert(push_package.p12.certificate)
|
123
|
+
p7.verify(
|
124
|
+
[push_package.p12.certificate],
|
125
|
+
store,
|
126
|
+
File.read(tmp_path + '/manifest.json'),
|
127
|
+
OpenSSL::PKCS7::DETACHED
|
128
|
+
).must_equal true
|
129
|
+
end
|
130
|
+
end
|
10
131
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
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.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stefan Natchev
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-11-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: minitest
|
@@ -39,6 +39,20 @@ dependencies:
|
|
39
39
|
- - ~>
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: 10.0.3
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: pry
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
42
56
|
description: As of OSX 10.9 Safari can receive push notifications when it is closed.
|
43
57
|
email:
|
44
58
|
- stefan.natchev@gmail.com
|
@@ -56,6 +70,15 @@ files:
|
|
56
70
|
- lib/push_package.rb
|
57
71
|
- lib/push_package/version.rb
|
58
72
|
- push_package.gemspec
|
73
|
+
- spec/fixtures/iconset/icon_128x128.png
|
74
|
+
- spec/fixtures/iconset/icon_128x128@2x.png
|
75
|
+
- spec/fixtures/iconset/icon_16x16.png
|
76
|
+
- spec/fixtures/iconset/icon_16x16@2x.png
|
77
|
+
- spec/fixtures/iconset/icon_32x32.png
|
78
|
+
- spec/fixtures/iconset/icon_32x32@2x.png
|
79
|
+
- spec/fixtures/manifest.json
|
80
|
+
- spec/fixtures/self-signed.p12
|
81
|
+
- spec/fixtures/signature
|
59
82
|
- spec/push_package_spec.rb
|
60
83
|
- spec/spec_helper.rb
|
61
84
|
homepage: https://github.com/symmetricinfinity/push_package
|
@@ -83,5 +106,14 @@ signing_key:
|
|
83
106
|
specification_version: 4
|
84
107
|
summary: A gem for creating Safari push notification push packages.
|
85
108
|
test_files:
|
109
|
+
- spec/fixtures/iconset/icon_128x128.png
|
110
|
+
- spec/fixtures/iconset/icon_128x128@2x.png
|
111
|
+
- spec/fixtures/iconset/icon_16x16.png
|
112
|
+
- spec/fixtures/iconset/icon_16x16@2x.png
|
113
|
+
- spec/fixtures/iconset/icon_32x32.png
|
114
|
+
- spec/fixtures/iconset/icon_32x32@2x.png
|
115
|
+
- spec/fixtures/manifest.json
|
116
|
+
- spec/fixtures/self-signed.p12
|
117
|
+
- spec/fixtures/signature
|
86
118
|
- spec/push_package_spec.rb
|
87
119
|
- spec/spec_helper.rb
|