passbook-ios 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 +17 -0
- data/Gemfile.lock +51 -0
- data/LICENSE +22 -0
- data/README.md +122 -0
- data/Rakefile +35 -0
- data/VERSION +1 -0
- data/lib/passbook.rb +11 -0
- data/lib/passbook/pkpass.rb +142 -0
- data/lib/passbook/version.rb +3 -0
- data/lib/rails/generators/passbook/config/config_generator.rb +16 -0
- data/lib/rails/generators/passbook/config/templates/initializer.rb +11 -0
- data/passbook.gemspec +22 -0
- data/spec/data/icon.png +0 -0
- data/spec/data/icon@2x.png +0 -0
- data/spec/data/logo.png +0 -0
- data/spec/data/logo@2x.png +0 -0
- data/spec/lib/passbook/pkpass_spec.rb +128 -0
- data/spec/spec_helper.rb +7 -0
- metadata +201 -0
data/.travis.yml
ADDED
data/Gemfile
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
source 'https://rubygems.org'
|
|
2
|
+
|
|
3
|
+
# Specify your gem's dependencies in passbook.gemspec
|
|
4
|
+
gem 'rubyzip'
|
|
5
|
+
|
|
6
|
+
platforms :jruby do
|
|
7
|
+
gem 'jruby-openssl', '0.7.7'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
group :test, :development do
|
|
11
|
+
gem 'activesupport'
|
|
12
|
+
gem 'jeweler'
|
|
13
|
+
gem 'simplecov'
|
|
14
|
+
gem 'rspec'
|
|
15
|
+
gem 'rake'
|
|
16
|
+
gem 'yard'
|
|
17
|
+
end
|
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
GEM
|
|
2
|
+
remote: https://rubygems.org/
|
|
3
|
+
specs:
|
|
4
|
+
activesupport (3.2.8)
|
|
5
|
+
i18n (~> 0.6)
|
|
6
|
+
multi_json (~> 1.0)
|
|
7
|
+
bouncy-castle-java (1.5.0146.1)
|
|
8
|
+
diff-lcs (1.1.3)
|
|
9
|
+
git (1.2.5)
|
|
10
|
+
i18n (0.6.1)
|
|
11
|
+
jeweler (1.8.4)
|
|
12
|
+
bundler (~> 1.0)
|
|
13
|
+
git (>= 1.2.5)
|
|
14
|
+
rake
|
|
15
|
+
rdoc
|
|
16
|
+
jruby-openssl (0.7.7)
|
|
17
|
+
bouncy-castle-java (>= 1.5.0146.1)
|
|
18
|
+
json (1.7.5)
|
|
19
|
+
json (1.7.5-java)
|
|
20
|
+
multi_json (1.3.6)
|
|
21
|
+
rake (0.9.2.2)
|
|
22
|
+
rdoc (3.12)
|
|
23
|
+
json (~> 1.4)
|
|
24
|
+
rspec (2.11.0)
|
|
25
|
+
rspec-core (~> 2.11.0)
|
|
26
|
+
rspec-expectations (~> 2.11.0)
|
|
27
|
+
rspec-mocks (~> 2.11.0)
|
|
28
|
+
rspec-core (2.11.1)
|
|
29
|
+
rspec-expectations (2.11.3)
|
|
30
|
+
diff-lcs (~> 1.1.3)
|
|
31
|
+
rspec-mocks (2.11.3)
|
|
32
|
+
rubyzip (0.9.9)
|
|
33
|
+
simplecov (0.7.1)
|
|
34
|
+
multi_json (~> 1.0)
|
|
35
|
+
simplecov-html (~> 0.7.1)
|
|
36
|
+
simplecov-html (0.7.1)
|
|
37
|
+
yard (0.8.3)
|
|
38
|
+
|
|
39
|
+
PLATFORMS
|
|
40
|
+
java
|
|
41
|
+
ruby
|
|
42
|
+
|
|
43
|
+
DEPENDENCIES
|
|
44
|
+
activesupport
|
|
45
|
+
jeweler
|
|
46
|
+
jruby-openssl (= 0.7.7)
|
|
47
|
+
rake
|
|
48
|
+
rspec
|
|
49
|
+
rubyzip
|
|
50
|
+
simplecov
|
|
51
|
+
yard
|
data/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2012 Thomas Lauro
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
[](https://travis-ci.org/lgleasain/passbook)
|
|
2
|
+
|
|
3
|
+
# Passbook
|
|
4
|
+
|
|
5
|
+
Passbook gem let's you create pkpass for passbook iOS 6
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
TODO : push the gem to rubygems.org
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
Create initializer
|
|
14
|
+
```
|
|
15
|
+
rails g passbook:config
|
|
16
|
+
or with params
|
|
17
|
+
rails g passbook:config [Absolute path to the wwdc cert file] [Absolute path to your cert.p12 file] [Password for your certificate]
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Configure your config/initializers/passbook.rb
|
|
21
|
+
```
|
|
22
|
+
Passbook.configure do |passbook|
|
|
23
|
+
passbook.wwdc_cert = Rails.root.join('wwdc_cert.pem')
|
|
24
|
+
passbook.p12_cert = Rails.root.join('cert.p12')
|
|
25
|
+
passbook.p12_password = 'cert password'
|
|
26
|
+
end
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
If you are running this on a different machine from what you used to create your WWDC keys
|
|
30
|
+
```
|
|
31
|
+
Passbook.configure do |passbook|
|
|
32
|
+
passbook.wwdc_cert = Rails.root.join('wwdc_cert.pem')
|
|
33
|
+
passbook.p12_key = Rails.root.join('key.pem')
|
|
34
|
+
passbook.p12_certificate = Rails.root.join('certificate.pem')
|
|
35
|
+
passbook.p12_password = 'cert password'
|
|
36
|
+
end
|
|
37
|
+
```
|
|
38
|
+
If you are using Sinatra you can place this in the file you are executing or in a file that you do a require on. You would also not reference Rails.root when specifying your file path.
|
|
39
|
+
|
|
40
|
+
## Usage
|
|
41
|
+
|
|
42
|
+
Please refer to apple iOS dev center for how to build cert and json. [This article is also helpful.](http://www.raywenderlich.com/20734/beginning-passbook-part-1#more-20734)
|
|
43
|
+
```
|
|
44
|
+
pass = Passbook::PKPass.new 'your json data'
|
|
45
|
+
|
|
46
|
+
# Add file from disk
|
|
47
|
+
pass.addFile 'file_path'
|
|
48
|
+
|
|
49
|
+
# Add file from memory
|
|
50
|
+
file[:name] = 'file name'
|
|
51
|
+
file[:content] = 'whatever you want'
|
|
52
|
+
pass.addFile file
|
|
53
|
+
|
|
54
|
+
# Add multiple files
|
|
55
|
+
pass.addFiles [file_path_1, file_path_2, file_path_3]
|
|
56
|
+
|
|
57
|
+
# Add multiple files from memory
|
|
58
|
+
pass.addFiles [{name: 'file1', content: 'content1'}, {name: 'file2', content: 'content2'}, {name: 'file3', content: 'content3'}]
|
|
59
|
+
|
|
60
|
+
# Output a Tempfile
|
|
61
|
+
|
|
62
|
+
pkpass = pass.file
|
|
63
|
+
send_file pkpass.path, type: 'application/vnd.apple.pkpass', disposition: 'attachment', filename: "pass.pkpass"
|
|
64
|
+
|
|
65
|
+
# Or a stream
|
|
66
|
+
|
|
67
|
+
pkpass = pass.stream
|
|
68
|
+
send_data pkpass.string, type: 'application/vnd.apple.pkpass', disposition: 'attachment', filename: "pass.pkpass"
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
If you are using Sinatra you will need to include the 'active_support' gem and will need to require 'active_support/json/encoding'. Here is an example using the streaming mechanism.
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
require 'sinatra'
|
|
75
|
+
require 'passbook'
|
|
76
|
+
require 'active_support/json/encoding'
|
|
77
|
+
|
|
78
|
+
Passbook.configure do |passbook|
|
|
79
|
+
passbook.p12_password = '12345'
|
|
80
|
+
passbook.p12_key = 'passkey.pem'
|
|
81
|
+
passbook.p12_certificate = 'passcertificate.pem'
|
|
82
|
+
passbook.wwdc_cert = 'WWDR.pem'
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
get '/passbook' do
|
|
86
|
+
pass = # valid passbook json. refer to the wwdc documentation.
|
|
87
|
+
passbook = Passbook::PKPass.new pass
|
|
88
|
+
passbook.addFiles ['logo.png', 'logo@2x.png', 'icon.png', 'icon@2x.png']
|
|
89
|
+
response['Content-Type'] = 'application/vnd.apple.pkpass'
|
|
90
|
+
attachment 'mypass.pkpass'
|
|
91
|
+
passbook.stream.string
|
|
92
|
+
end
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
We will try to make this cleaner in the next release.
|
|
96
|
+
|
|
97
|
+
## Tests
|
|
98
|
+
|
|
99
|
+
To launch tests :
|
|
100
|
+
```
|
|
101
|
+
bundle exec rspec spec/lib/passbook/pkpass_spec.rb
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Contributing
|
|
105
|
+
|
|
106
|
+
1. Fork it
|
|
107
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
108
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
|
109
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
110
|
+
5. Create new Pull Request
|
|
111
|
+
|
|
112
|
+
## Changelog
|
|
113
|
+
|
|
114
|
+
### 0.0.4
|
|
115
|
+
Allow passbook gem to return a ZipOutputStream (needed when garbage collector delete tempfile before beeing able to use it) [Thx to applidget]
|
|
116
|
+
|
|
117
|
+
License
|
|
118
|
+
-------
|
|
119
|
+
|
|
120
|
+
passbook-ios is released under the MIT license:
|
|
121
|
+
|
|
122
|
+
* http://www.opensource.org/licenses/MIT
|
data/Rakefile
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env rake
|
|
2
|
+
require 'rubygems'
|
|
3
|
+
require 'bundler'
|
|
4
|
+
begin
|
|
5
|
+
Bundler.setup(:default, :development)
|
|
6
|
+
rescue Bundler::BundlerError => e
|
|
7
|
+
$stderr.puts e.message
|
|
8
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
|
9
|
+
exit e.status_code
|
|
10
|
+
end
|
|
11
|
+
require 'rake'
|
|
12
|
+
require 'jeweler'
|
|
13
|
+
Jeweler::Tasks.new do |gem|
|
|
14
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
|
15
|
+
gem.name = "passbook-ios"
|
|
16
|
+
gem.homepage = "http://github.com/frozon/passbook"
|
|
17
|
+
gem.license = "MIT"
|
|
18
|
+
gem.summary = %Q{A IOS Passbook generator.}
|
|
19
|
+
gem.description = %Q{This gem allows you to create IOS Passbooks. Unlike some, this works with Rails but does not require it.}
|
|
20
|
+
gem.email = ['thomas@lauro.fr', 'lgleason@polyglotprogramminginc.com']
|
|
21
|
+
gem.authors = ['Thomas Lauro', 'Lance Gleason']
|
|
22
|
+
# dependencies defined in Gemfile
|
|
23
|
+
end
|
|
24
|
+
Jeweler::RubygemsDotOrgTasks.new
|
|
25
|
+
|
|
26
|
+
require 'rspec/core'
|
|
27
|
+
require 'rspec/core/rake_task'
|
|
28
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
|
29
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
task :default => :spec
|
|
33
|
+
|
|
34
|
+
require 'yard'
|
|
35
|
+
YARD::Rake::YardocTask.new
|
data/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.1.0
|
data/lib/passbook.rb
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require "passbook/version"
|
|
2
|
+
require "passbook/pkpass"
|
|
3
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
|
4
|
+
|
|
5
|
+
module Passbook
|
|
6
|
+
mattr_accessor :p12_cert, :p12_password, :wwdc_cert, :p12_certificate, :p12_key
|
|
7
|
+
|
|
8
|
+
def self.configure
|
|
9
|
+
yield self
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
require 'digest/sha1'
|
|
2
|
+
require 'openssl'
|
|
3
|
+
require 'zip/zip'
|
|
4
|
+
require 'base64'
|
|
5
|
+
|
|
6
|
+
module Passbook
|
|
7
|
+
class PKPass
|
|
8
|
+
attr_accessor :pass, :manifest_files
|
|
9
|
+
|
|
10
|
+
def initialize pass
|
|
11
|
+
@pass = pass
|
|
12
|
+
@manifest_files = []
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def addFile file
|
|
16
|
+
@manifest_files << file
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def addFiles files
|
|
20
|
+
@manifest_files += files
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# for backwards compatibility
|
|
24
|
+
def json= json
|
|
25
|
+
@pass = json
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def build
|
|
29
|
+
manifest = createManifest
|
|
30
|
+
|
|
31
|
+
# Check pass for necessary files and fields
|
|
32
|
+
checkPass manifest
|
|
33
|
+
|
|
34
|
+
# Create pass signature
|
|
35
|
+
signature = createSignature manifest
|
|
36
|
+
|
|
37
|
+
return [manifest, signature]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Backward compatibility
|
|
41
|
+
def create
|
|
42
|
+
self.file.path
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Return a Tempfile containing our ZipStream
|
|
46
|
+
def file(options = {})
|
|
47
|
+
options[:file_name] ||= 'pass.pkpass'
|
|
48
|
+
|
|
49
|
+
temp_file = Tempfile.new(options[:file_name])
|
|
50
|
+
temp_file.write self.stream.string
|
|
51
|
+
temp_file.close
|
|
52
|
+
|
|
53
|
+
temp_file
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Return a ZipOutputStream
|
|
57
|
+
def stream
|
|
58
|
+
manifest, signature = build
|
|
59
|
+
|
|
60
|
+
outputZip manifest, signature
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def get_p12_cert_and_key
|
|
64
|
+
key_hash = {}
|
|
65
|
+
if Passbook.p12_key
|
|
66
|
+
key_hash[:key] = OpenSSL::PKey::RSA.new File.read(Passbook.p12_key), Passbook.p12_password
|
|
67
|
+
key_hash[:cert] = OpenSSL::X509::Certificate.new File.read(Passbook.p12_certificate)
|
|
68
|
+
else
|
|
69
|
+
p12 = OpenSSL::PKCS12.new File.read(Passbook.p12_cert), Passbook.p12_password
|
|
70
|
+
key_hash[:key], key_hash[:cert] = p12.key, p12.certificate
|
|
71
|
+
end
|
|
72
|
+
key_hash
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def createSignature manifest
|
|
76
|
+
p12 = get_p12_cert_and_key
|
|
77
|
+
wwdc = OpenSSL::X509::Certificate.new File.read(Passbook.wwdc_cert)
|
|
78
|
+
pk7 = OpenSSL::PKCS7.sign p12[:cert], p12[:key], manifest.to_s, [wwdc], OpenSSL::PKCS7::BINARY | OpenSSL::PKCS7::DETACHED
|
|
79
|
+
data = OpenSSL::PKCS7.write_smime pk7
|
|
80
|
+
|
|
81
|
+
str_debut = "filename=\"smime.p7s\"\n\n"
|
|
82
|
+
data = data[data.index(str_debut)+str_debut.length..data.length-1]
|
|
83
|
+
str_end = "\n\n------"
|
|
84
|
+
data = data[0..data.index(str_end)-1]
|
|
85
|
+
|
|
86
|
+
return Base64.decode64(data)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
private
|
|
90
|
+
|
|
91
|
+
def checkPass manifest
|
|
92
|
+
# Check for default images
|
|
93
|
+
raise 'Icon missing' unless manifest.include?('icon.png')
|
|
94
|
+
raise 'Icon@2x missing' unless manifest.include?('icon@2x.png')
|
|
95
|
+
|
|
96
|
+
# Check for developer field in JSON
|
|
97
|
+
raise 'Pass Type Identifier missing' unless @pass.include?('passTypeIdentifier')
|
|
98
|
+
raise 'Team Identifier missing' unless @pass.include?('teamIdentifier')
|
|
99
|
+
raise 'Serial Number missing' unless @pass.include?('serialNumber')
|
|
100
|
+
raise 'Organization Name Identifier missing' unless @pass.include?('organizationName')
|
|
101
|
+
raise 'Format Version' unless @pass.include?('formatVersion')
|
|
102
|
+
raise 'Description' unless @pass.include?('description')
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def createManifest
|
|
106
|
+
sha1s = {}
|
|
107
|
+
sha1s['pass.json'] = Digest::SHA1.hexdigest @pass
|
|
108
|
+
|
|
109
|
+
@manifest_files.each do |file|
|
|
110
|
+
if file.class == Hash
|
|
111
|
+
sha1s[file[:name]] = Digest::SHA1.hexdigest file[:content]
|
|
112
|
+
else
|
|
113
|
+
sha1s[File.basename(file)] = Digest::SHA1.file(file).hexdigest
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
return sha1s.to_json
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def outputZip manifest, signature
|
|
121
|
+
|
|
122
|
+
Zip::ZipOutputStream.write_buffer do |zip|
|
|
123
|
+
zip.put_next_entry 'pass.json'
|
|
124
|
+
zip.write @pass
|
|
125
|
+
zip.put_next_entry 'manifest.json'
|
|
126
|
+
zip.write manifest
|
|
127
|
+
zip.put_next_entry 'signature'
|
|
128
|
+
zip.write signature
|
|
129
|
+
|
|
130
|
+
@manifest_files.each do |file|
|
|
131
|
+
if file.class == Hash
|
|
132
|
+
zip.put_next_entry file[:name]
|
|
133
|
+
zip.print file[:content]
|
|
134
|
+
else
|
|
135
|
+
zip.put_next_entry File.basename(file)
|
|
136
|
+
zip.print IO.read(file)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Passbook
|
|
2
|
+
module Generators
|
|
3
|
+
class ConfigGenerator < Rails::Generators::Base
|
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
|
5
|
+
|
|
6
|
+
argument :wwdc_cert_path, type: :string, default: '', optional: true, banner: "Absolute path to your wwdc cert file"
|
|
7
|
+
argument :p12_cert_path, type: :string, default: '', optional: true, banner: "Absolute path to your cert.p12 file"
|
|
8
|
+
argument :p12_password, type: :string, default: '', optional: true, banner: "Password for your certificate"
|
|
9
|
+
|
|
10
|
+
desc 'Create passbook initializer'
|
|
11
|
+
def create_initializer_file
|
|
12
|
+
template 'initializer.rb', File.join('config', 'initializers', 'passbook.rb')
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Passbook.configure do |passbook|
|
|
2
|
+
|
|
3
|
+
# Path to your wwdc cert file
|
|
4
|
+
passbook.wwdc_cert = '<%= wwdc_cert_path %>'
|
|
5
|
+
|
|
6
|
+
# Path to your cert.p12 file
|
|
7
|
+
passbook.p12_cert = '<%= p12_cert_path %>'
|
|
8
|
+
|
|
9
|
+
# Password for your certificate
|
|
10
|
+
passbook.p12_password = '<%= p12_password %>'
|
|
11
|
+
end
|
data/passbook.gemspec
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
require File.expand_path('../lib/passbook/version', __FILE__)
|
|
3
|
+
|
|
4
|
+
Gem::Specification.new do |gem|
|
|
5
|
+
gem.authors = ["Thomas Lauro"]
|
|
6
|
+
gem.email = ["thomas@lauro.fr"]
|
|
7
|
+
gem.description = %q{Passbook gem let's you create pkpass for passbook iOS 6}
|
|
8
|
+
gem.summary = %q{Passbook gem let's you create pkpass for passbook iOS 6}
|
|
9
|
+
gem.homepage = "https://github.com/frozon/passbook"
|
|
10
|
+
|
|
11
|
+
# gem.files = `git ls-files`.split($\)
|
|
12
|
+
gem.files = Dir.glob('{app,config,lib}/**/*') + %w(Gemfile LICENSE README.md Rakefile)
|
|
13
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
|
14
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
|
15
|
+
gem.name = "passbook"
|
|
16
|
+
gem.require_paths = ["lib"]
|
|
17
|
+
gem.version = Passbook::VERSION
|
|
18
|
+
|
|
19
|
+
gem.add_dependency 'rubyzip'
|
|
20
|
+
gem.add_development_dependency 'rake'
|
|
21
|
+
gem.add_development_dependency 'rspec'
|
|
22
|
+
end
|
data/spec/data/icon.png
ADDED
|
Binary file
|
|
Binary file
|
data/spec/data/logo.png
ADDED
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Passbook do
|
|
4
|
+
|
|
5
|
+
let (:content) {{
|
|
6
|
+
:formatVersion => 1,
|
|
7
|
+
:passTypeIdentifier => "pass.passbook.test",
|
|
8
|
+
:serialNumber => "001",
|
|
9
|
+
:teamIdentifier => ENV['APPLE_TEAM_ID'],
|
|
10
|
+
:relevantDate => "2012-10-02",
|
|
11
|
+
:locations => [ #TODO
|
|
12
|
+
{
|
|
13
|
+
:longitude => 2.35403,
|
|
14
|
+
:latitude => 48.893855
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
:organizationName => "WorldCo",
|
|
18
|
+
:description => "description",
|
|
19
|
+
:foregroundColor => "rgb(227,210,18)",
|
|
20
|
+
:backgroundColor => "rgb(60, 65, 76)",
|
|
21
|
+
:logoText => "Event",
|
|
22
|
+
:eventTicket => {
|
|
23
|
+
:primaryFields => [
|
|
24
|
+
{
|
|
25
|
+
:key => "date",
|
|
26
|
+
:label => "DATE",
|
|
27
|
+
:value => "date"
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
:backFields => [
|
|
31
|
+
{
|
|
32
|
+
:key => "description",
|
|
33
|
+
:label => "DESCRIPTION",
|
|
34
|
+
:value => "description"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
:key => "aboutUs",
|
|
38
|
+
:label => "MORE",
|
|
39
|
+
:value => "about us"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
}}
|
|
44
|
+
|
|
45
|
+
let (:pass) {Passbook::PKPass.new content.to_json}
|
|
46
|
+
|
|
47
|
+
context 'signatures' do
|
|
48
|
+
before do
|
|
49
|
+
Passbook.should_receive(:p12_password).and_return 'password'
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context 'p12_cert_and_key' do
|
|
53
|
+
context 'pem p12 certs' do
|
|
54
|
+
before do
|
|
55
|
+
Passbook.should_receive(:p12_key).twice.and_return 'my_p12_key'
|
|
56
|
+
Passbook.should_receive(:p12_certificate).and_return 'my_p12_certificate'
|
|
57
|
+
File.should_receive(:read).with('my_p12_key').and_return 'my_p12_key_file'
|
|
58
|
+
File.should_receive(:read).with('my_p12_certificate').and_return 'my_p12_certificate_file'
|
|
59
|
+
OpenSSL::PKey::RSA.should_receive(:new).with('my_p12_key_file', 'password').and_return 'my_rsa_key'
|
|
60
|
+
OpenSSL::X509::Certificate.should_receive(:new).with('my_p12_certificate_file').and_return 'my_ssl_p12_cert'
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
subject {pass.get_p12_cert_and_key}
|
|
64
|
+
its([:key]) {should eq 'my_rsa_key'}
|
|
65
|
+
its([:cert]) {should eq 'my_ssl_p12_cert'}
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
context 'p12 files' do
|
|
69
|
+
let (:p12) { double('OpenSSL::PKCS12') }
|
|
70
|
+
let (:final_hash) {{:key => 'my_final_p12_key', :cert => 'my_final_p12_cert'}}
|
|
71
|
+
before do
|
|
72
|
+
p12.should_receive(:key).and_return final_hash[:key]
|
|
73
|
+
p12.should_receive(:certificate).and_return final_hash[:cert]
|
|
74
|
+
Passbook.should_receive(:p12_key).and_return nil
|
|
75
|
+
Passbook.should_receive(:p12_cert).and_return 'my_p12_cert'
|
|
76
|
+
File.should_receive(:read).with('my_p12_cert').and_return 'my_p12_cert_file'
|
|
77
|
+
OpenSSL::PKCS12.should_receive(:new).with('my_p12_cert_file', 'password').and_return p12
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
subject {pass.get_p12_cert_and_key}
|
|
81
|
+
its([:key]) {should eq final_hash[:key]}
|
|
82
|
+
its([:cert]) {should eq final_hash[:cert]}
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
context 'outputs' do
|
|
88
|
+
let (:base_path) {'spec/data'}
|
|
89
|
+
let (:entries) {["pass.json", "manifest.json", "signature", "icon.png", "icon@2x.png", "logo.png", "logo@2x.png"]}
|
|
90
|
+
|
|
91
|
+
before :each do
|
|
92
|
+
pass.addFiles ["#{base_path}/icon.png","#{base_path}/icon@2x.png","#{base_path}/logo.png","#{base_path}/logo@2x.png"]
|
|
93
|
+
pass.should_receive(:createSignature).and_return('Signed by the Honey Badger')
|
|
94
|
+
@file_entries = []
|
|
95
|
+
Zip::ZipInputStream::open(zip_path) {|io|
|
|
96
|
+
while (entry = io.get_next_entry)
|
|
97
|
+
@file_entries << entry.name
|
|
98
|
+
end
|
|
99
|
+
}
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context 'zip file' do
|
|
103
|
+
let(:zip_path) {pass.file.path}
|
|
104
|
+
|
|
105
|
+
subject {entries}
|
|
106
|
+
it {should eq @file_entries}
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
context 'StringIO' do
|
|
110
|
+
let (:temp_file) {Tempfile.new("pass.pkpass")}
|
|
111
|
+
let (:zip_path) {
|
|
112
|
+
zip_out = pass.stream
|
|
113
|
+
zip_out.class.should eq(Class::StringIO)
|
|
114
|
+
#creating file, re-reading zip to see if correctly formed
|
|
115
|
+
temp_file.write zip_out.string
|
|
116
|
+
temp_file.close
|
|
117
|
+
temp_file.path
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
subject {entries}
|
|
121
|
+
it {should eq @file_entries}
|
|
122
|
+
|
|
123
|
+
after do
|
|
124
|
+
temp_file.delete
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: passbook-ios
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Thomas Lauro
|
|
9
|
+
- Lance Gleason
|
|
10
|
+
autorequire:
|
|
11
|
+
bindir: bin
|
|
12
|
+
cert_chain: []
|
|
13
|
+
date: 2012-11-17 00:00:00.000000000 Z
|
|
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: '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: '0'
|
|
31
|
+
- !ruby/object:Gem::Dependency
|
|
32
|
+
name: jruby-openssl
|
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
|
34
|
+
none: false
|
|
35
|
+
requirements:
|
|
36
|
+
- - '='
|
|
37
|
+
- !ruby/object:Gem::Version
|
|
38
|
+
version: 0.7.7
|
|
39
|
+
type: :runtime
|
|
40
|
+
prerelease: false
|
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
42
|
+
none: false
|
|
43
|
+
requirements:
|
|
44
|
+
- - '='
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: 0.7.7
|
|
47
|
+
- !ruby/object:Gem::Dependency
|
|
48
|
+
name: activesupport
|
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
|
50
|
+
none: false
|
|
51
|
+
requirements:
|
|
52
|
+
- - ! '>='
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
type: :development
|
|
56
|
+
prerelease: false
|
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
58
|
+
none: false
|
|
59
|
+
requirements:
|
|
60
|
+
- - ! '>='
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: '0'
|
|
63
|
+
- !ruby/object:Gem::Dependency
|
|
64
|
+
name: jeweler
|
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
|
66
|
+
none: false
|
|
67
|
+
requirements:
|
|
68
|
+
- - ! '>='
|
|
69
|
+
- !ruby/object:Gem::Version
|
|
70
|
+
version: '0'
|
|
71
|
+
type: :development
|
|
72
|
+
prerelease: false
|
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
74
|
+
none: false
|
|
75
|
+
requirements:
|
|
76
|
+
- - ! '>='
|
|
77
|
+
- !ruby/object:Gem::Version
|
|
78
|
+
version: '0'
|
|
79
|
+
- !ruby/object:Gem::Dependency
|
|
80
|
+
name: simplecov
|
|
81
|
+
requirement: !ruby/object:Gem::Requirement
|
|
82
|
+
none: false
|
|
83
|
+
requirements:
|
|
84
|
+
- - ! '>='
|
|
85
|
+
- !ruby/object:Gem::Version
|
|
86
|
+
version: '0'
|
|
87
|
+
type: :development
|
|
88
|
+
prerelease: false
|
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
90
|
+
none: false
|
|
91
|
+
requirements:
|
|
92
|
+
- - ! '>='
|
|
93
|
+
- !ruby/object:Gem::Version
|
|
94
|
+
version: '0'
|
|
95
|
+
- !ruby/object:Gem::Dependency
|
|
96
|
+
name: rspec
|
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
|
98
|
+
none: false
|
|
99
|
+
requirements:
|
|
100
|
+
- - ! '>='
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0'
|
|
103
|
+
type: :development
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
none: false
|
|
107
|
+
requirements:
|
|
108
|
+
- - ! '>='
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '0'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: rake
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
none: false
|
|
115
|
+
requirements:
|
|
116
|
+
- - ! '>='
|
|
117
|
+
- !ruby/object:Gem::Version
|
|
118
|
+
version: '0'
|
|
119
|
+
type: :development
|
|
120
|
+
prerelease: false
|
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
122
|
+
none: false
|
|
123
|
+
requirements:
|
|
124
|
+
- - ! '>='
|
|
125
|
+
- !ruby/object:Gem::Version
|
|
126
|
+
version: '0'
|
|
127
|
+
- !ruby/object:Gem::Dependency
|
|
128
|
+
name: yard
|
|
129
|
+
requirement: !ruby/object:Gem::Requirement
|
|
130
|
+
none: false
|
|
131
|
+
requirements:
|
|
132
|
+
- - ! '>='
|
|
133
|
+
- !ruby/object:Gem::Version
|
|
134
|
+
version: '0'
|
|
135
|
+
type: :development
|
|
136
|
+
prerelease: false
|
|
137
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
138
|
+
none: false
|
|
139
|
+
requirements:
|
|
140
|
+
- - ! '>='
|
|
141
|
+
- !ruby/object:Gem::Version
|
|
142
|
+
version: '0'
|
|
143
|
+
description: This gem allows you to create IOS Passbooks. Unlike some, this works
|
|
144
|
+
with Rails but does not require it.
|
|
145
|
+
email:
|
|
146
|
+
- thomas@lauro.fr
|
|
147
|
+
- lgleason@polyglotprogramminginc.com
|
|
148
|
+
executables: []
|
|
149
|
+
extensions: []
|
|
150
|
+
extra_rdoc_files:
|
|
151
|
+
- LICENSE
|
|
152
|
+
- README.md
|
|
153
|
+
files:
|
|
154
|
+
- .travis.yml
|
|
155
|
+
- Gemfile
|
|
156
|
+
- Gemfile.lock
|
|
157
|
+
- LICENSE
|
|
158
|
+
- README.md
|
|
159
|
+
- Rakefile
|
|
160
|
+
- VERSION
|
|
161
|
+
- lib/passbook.rb
|
|
162
|
+
- lib/passbook/pkpass.rb
|
|
163
|
+
- lib/passbook/version.rb
|
|
164
|
+
- lib/rails/generators/passbook/config/config_generator.rb
|
|
165
|
+
- lib/rails/generators/passbook/config/templates/initializer.rb
|
|
166
|
+
- passbook.gemspec
|
|
167
|
+
- spec/data/icon.png
|
|
168
|
+
- spec/data/icon@2x.png
|
|
169
|
+
- spec/data/logo.png
|
|
170
|
+
- spec/data/logo@2x.png
|
|
171
|
+
- spec/lib/passbook/pkpass_spec.rb
|
|
172
|
+
- spec/spec_helper.rb
|
|
173
|
+
homepage: http://github.com/frozon/passbook
|
|
174
|
+
licenses:
|
|
175
|
+
- MIT
|
|
176
|
+
post_install_message:
|
|
177
|
+
rdoc_options: []
|
|
178
|
+
require_paths:
|
|
179
|
+
- lib
|
|
180
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
181
|
+
none: false
|
|
182
|
+
requirements:
|
|
183
|
+
- - ! '>='
|
|
184
|
+
- !ruby/object:Gem::Version
|
|
185
|
+
version: '0'
|
|
186
|
+
segments:
|
|
187
|
+
- 0
|
|
188
|
+
hash: -841197523115092722
|
|
189
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
190
|
+
none: false
|
|
191
|
+
requirements:
|
|
192
|
+
- - ! '>='
|
|
193
|
+
- !ruby/object:Gem::Version
|
|
194
|
+
version: '0'
|
|
195
|
+
requirements: []
|
|
196
|
+
rubyforge_project:
|
|
197
|
+
rubygems_version: 1.8.24
|
|
198
|
+
signing_key:
|
|
199
|
+
specification_version: 3
|
|
200
|
+
summary: A IOS Passbook generator.
|
|
201
|
+
test_files: []
|