dubai 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -0
- data/Gemfile.lock +51 -0
- data/LICENSE +19 -0
- data/README.md +28 -0
- data/Rakefile +11 -0
- data/bin/pk +21 -0
- data/dubai.gemspec +29 -0
- data/lib/dubai.rb +6 -0
- data/lib/dubai/commands.rb +5 -0
- data/lib/dubai/commands/build.rb +39 -0
- data/lib/dubai/commands/generate.rb +44 -0
- data/lib/dubai/commands/serve.rb +49 -0
- data/lib/dubai/pass.rb +96 -0
- data/lib/dubai/server.rb +12 -0
- data/lib/dubai/templates/boarding-pass.json +56 -0
- data/lib/dubai/templates/coupon.json +33 -0
- data/lib/dubai/templates/event-ticket.json +33 -0
- data/lib/dubai/templates/generic.json +33 -0
- data/lib/dubai/templates/store-card.json +33 -0
- data/spec/spec_helper.rb +11 -0
- metadata +160 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
dubai (0.0.1)
|
5
|
+
commander (~> 4.1.2)
|
6
|
+
json (~> 1.7.3)
|
7
|
+
rubyzip
|
8
|
+
sinatra
|
9
|
+
terminal-table (~> 1.4.5)
|
10
|
+
|
11
|
+
GEM
|
12
|
+
remote: http://rubygems.org/
|
13
|
+
specs:
|
14
|
+
commander (4.1.3)
|
15
|
+
highline (~> 1.6.11)
|
16
|
+
diff-lcs (1.1.3)
|
17
|
+
highline (1.6.15)
|
18
|
+
json (1.7.7)
|
19
|
+
multi_json (1.6.1)
|
20
|
+
rack (1.5.2)
|
21
|
+
rack-protection (1.3.2)
|
22
|
+
rack
|
23
|
+
rake (10.0.3)
|
24
|
+
rspec (2.12.0)
|
25
|
+
rspec-core (~> 2.12.0)
|
26
|
+
rspec-expectations (~> 2.12.0)
|
27
|
+
rspec-mocks (~> 2.12.0)
|
28
|
+
rspec-core (2.12.2)
|
29
|
+
rspec-expectations (2.12.1)
|
30
|
+
diff-lcs (~> 1.1.3)
|
31
|
+
rspec-mocks (2.12.2)
|
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
|
+
sinatra (1.3.4)
|
38
|
+
rack (~> 1.4)
|
39
|
+
rack-protection (~> 1.3)
|
40
|
+
tilt (~> 1.3, >= 1.3.3)
|
41
|
+
terminal-table (1.4.5)
|
42
|
+
tilt (1.3.3)
|
43
|
+
|
44
|
+
PLATFORMS
|
45
|
+
ruby
|
46
|
+
|
47
|
+
DEPENDENCIES
|
48
|
+
dubai!
|
49
|
+
rake
|
50
|
+
rspec
|
51
|
+
simplecov
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2013 Mattt Thompson (http://mattt.me/)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Dubai
|
2
|
+
**Generate and Preview Passbook Passes**
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
$ gem install dubai
|
7
|
+
|
8
|
+
|
9
|
+
## Comand Line Interface
|
10
|
+
|
11
|
+
Dubai also comes with the `pk` binary, which provides a convenient way to generate and preview passes
|
12
|
+
|
13
|
+
|
14
|
+
$ pk generate mypass
|
15
|
+
$ pk serve mypass
|
16
|
+
$ open http://localhost:4000
|
17
|
+
|
18
|
+
## Contact
|
19
|
+
|
20
|
+
Mattt Thompson
|
21
|
+
|
22
|
+
- http://github.com/mattt
|
23
|
+
- http://twitter.com/mattt
|
24
|
+
- m@mattt.me
|
25
|
+
|
26
|
+
## License
|
27
|
+
|
28
|
+
Dubai is available under the MIT license. See the LICENSE file for more info.
|
data/Rakefile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require "bundler"
|
2
|
+
Bundler.setup
|
3
|
+
|
4
|
+
gemspec = eval(File.read("dubai.gemspec"))
|
5
|
+
|
6
|
+
task :build => "#{gemspec.full_name}.gem"
|
7
|
+
|
8
|
+
file "#{gemspec.full_name}.gem" => gemspec.files + ["dubai.gemspec"] do
|
9
|
+
system "gem build dubai.gemspec"
|
10
|
+
system "gem install dubai-#{Dubai::VERSION}.gem"
|
11
|
+
end
|
data/bin/pk
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'commander/import'
|
4
|
+
require 'terminal-table'
|
5
|
+
|
6
|
+
$:.push File.expand_path("../../lib", __FILE__)
|
7
|
+
require 'dubai'
|
8
|
+
|
9
|
+
HighLine.track_eof = false # Fix for built-in Ruby
|
10
|
+
Signal.trap("INT") {} # Suppress backtrace when exiting command
|
11
|
+
|
12
|
+
program :version, Dubai::VERSION
|
13
|
+
program :description, 'A command-line interface for generating and previewing passbook passes'
|
14
|
+
|
15
|
+
program :help, 'Author', 'Mattt Thompson <m@mattt.me>'
|
16
|
+
program :help, 'Website', 'https://github.com/mattt'
|
17
|
+
program :help_formatter, :compact
|
18
|
+
|
19
|
+
default_command :help
|
20
|
+
|
21
|
+
require 'dubai/commands'
|
data/dubai.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "dubai"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "dubai"
|
7
|
+
s.authors = ["Mattt Thompson"]
|
8
|
+
s.email = "m@mattt.me"
|
9
|
+
s.homepage = "http://github.com/mattt/dubai"
|
10
|
+
s.version = Dubai::VERSION
|
11
|
+
s.platform = Gem::Platform::RUBY
|
12
|
+
s.summary = "Passbook pass generation and preview"
|
13
|
+
s.description = ""
|
14
|
+
|
15
|
+
s.add_dependency "json", "~> 1.7.3"
|
16
|
+
s.add_dependency "commander", "~> 4.1.2"
|
17
|
+
s.add_dependency "terminal-table", "~> 1.4.5"
|
18
|
+
s.add_dependency "sinatra"
|
19
|
+
s.add_dependency "rubyzip"
|
20
|
+
|
21
|
+
s.add_development_dependency "rspec"
|
22
|
+
s.add_development_dependency "rake"
|
23
|
+
s.add_development_dependency "simplecov"
|
24
|
+
|
25
|
+
s.files = Dir["./**/*"].reject { |file| file =~ /\.\/(bin|log|pkg|script|spec|test|vendor)/ }
|
26
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
27
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
28
|
+
s.require_paths = ["lib"]
|
29
|
+
end
|
data/lib/dubai.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
command :build do |c|
|
2
|
+
c.syntax = 'pk build [PASSNAME]'
|
3
|
+
c.summary = 'Creates a .pkpass archive'
|
4
|
+
c.description = ''
|
5
|
+
|
6
|
+
c.example 'description', 'pk archive mypass -o mypass.pkpass'
|
7
|
+
c.option '-c', '--certificate /path/to/cert.pem', 'Pass certificate'
|
8
|
+
c.option '-p', '--[no]-password', 'Prompt for certificate password'
|
9
|
+
c.option '-o', '--output /path/to/out.pkpass', '.pkpass output filepath'
|
10
|
+
|
11
|
+
c.action do |args, options|
|
12
|
+
determine_directory! unless @directory = args.first
|
13
|
+
validate_directory!
|
14
|
+
|
15
|
+
@filepath = options.output || "#{@directory}.pkpass"
|
16
|
+
validate_output_filepath!
|
17
|
+
|
18
|
+
@certificate = options.certificate
|
19
|
+
validate_certificate!
|
20
|
+
|
21
|
+
@password = ask("Enter certificate password:"){|q| q.echo = false} if options.password
|
22
|
+
|
23
|
+
Dubai::Passbook.certificate, Dubai::Passbook.password = @certificate, @password
|
24
|
+
|
25
|
+
File.open(@filepath, 'w') do |f|
|
26
|
+
f.write Dubai::Passbook::Pass.new(@directory).pkpass.string
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# alias_command :build, :archive
|
32
|
+
# alias_command :build, :b
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def validate_output_filepath!
|
37
|
+
say_error "Filepath required" and abort if @filepath.nil? or @filepath.empty?
|
38
|
+
say_error "#{@filepath} already exists" and abort if File.exist?(@filepath)
|
39
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
command :generate do |c|
|
4
|
+
c.syntax = 'pk generate PASSNAME'
|
5
|
+
c.summary = 'Generates a template pass directory'
|
6
|
+
c.description = ''
|
7
|
+
|
8
|
+
c.example 'description', 'pk generate mypass'
|
9
|
+
c.option '-T', '--type [boardingPass|coupon|eventTicket|storeCard|generic]', 'Type of pass'
|
10
|
+
|
11
|
+
c.action do |args, options|
|
12
|
+
@directory = args.first
|
13
|
+
@directory ||= ask "Enter a passbook name: "
|
14
|
+
|
15
|
+
say_error "Missing pass name" and abort if @directory.nil? or @directory.empty?
|
16
|
+
say_error "Directory #{@directory} already exists" and abort if File.directory?(@directory)
|
17
|
+
say_error "File exists at #{@directory}" and abort if File.exist?(@directory)
|
18
|
+
|
19
|
+
@type = options.type
|
20
|
+
determine_type! unless @type
|
21
|
+
validate_type!
|
22
|
+
|
23
|
+
FileUtils.mkdir_p @directory
|
24
|
+
FileUtils.cp File.join(File.dirname(__FILE__), '..', 'templates', "#{@type}.json"), File.join(@directory, 'pass.json')
|
25
|
+
['icon.png', 'icon@2x.png'].each do |file|
|
26
|
+
FileUtils.touch File.join(@directory, file)
|
27
|
+
end
|
28
|
+
|
29
|
+
say_ok "Pass generated in #{@directory}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# alias_command :generate, :new
|
34
|
+
# alias_command :generate, :g
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def determine_type!
|
39
|
+
@type ||= choose "Select a pass type", *Dubai::Passbook::Pass::TYPES
|
40
|
+
end
|
41
|
+
|
42
|
+
def validate_type!
|
43
|
+
say_error %{Invalid type: "#{@type}", expected one of: [#{Dubai::Passbook::Pass::TYPES.join(', ')}]} unless Dubai::Passbook::Pass::TYPES.include?(@type)
|
44
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
command :serve do |c|
|
2
|
+
c.syntax = 'pk serve [PASSNAME]'
|
3
|
+
c.summary = 'Creates a .pkpass archive'
|
4
|
+
c.description = ''
|
5
|
+
|
6
|
+
c.example 'description', 'pk archive mypass'
|
7
|
+
c.option '-c', '--certificate /path/to/cert.pem', 'Pass certificate'
|
8
|
+
c.option '-p', '--[no]-password', 'Prompt for certificate password'
|
9
|
+
|
10
|
+
c.action do |args, options|
|
11
|
+
determine_directory! unless @directory = args.first
|
12
|
+
validate_directory!
|
13
|
+
|
14
|
+
@certificate = options.certificate
|
15
|
+
validate_certificate!
|
16
|
+
|
17
|
+
@password = ask("Enter certificate password:"){|q| q.echo = false} if options.password
|
18
|
+
|
19
|
+
Dubai::Passbook.certificate, Dubai::Passbook.password = @certificate, @password
|
20
|
+
|
21
|
+
Dubai::Server.set :directory, @directory
|
22
|
+
Dubai::Server.run!
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# alias_command :serve, :preview
|
27
|
+
# alias_command :serve, :s
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def determine_directory!
|
32
|
+
files = Dir['*/pass.json']
|
33
|
+
@directory ||= case files.length
|
34
|
+
when 0 then nil
|
35
|
+
when 1 then File.dirname(files.first)
|
36
|
+
else
|
37
|
+
@directory = choose "Select a directory:", *files.collect{|f| File.dirname(f)}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def validate_directory!
|
42
|
+
say_error "Missing argument" and abort if @directory.nil?
|
43
|
+
say_error "Directory #{@directory} does not exist" and abort unless File.directory?(@directory)
|
44
|
+
say_error "Directory #{@directory} is not valid pass" and abort unless File.exist?(File.join(@directory, "pass.json"))
|
45
|
+
end
|
46
|
+
|
47
|
+
def validate_certificate!
|
48
|
+
say_error "Missing or invalid certificate file" and abort if @certificate.nil? or not File.exist?(@certificate)
|
49
|
+
end
|
data/lib/dubai/pass.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
require 'openssl'
|
3
|
+
require 'base64'
|
4
|
+
require 'json'
|
5
|
+
require 'zip/zip'
|
6
|
+
|
7
|
+
module Dubai
|
8
|
+
module Passbook
|
9
|
+
WWDR_CERTIFICATE = <<-EOF
|
10
|
+
-----BEGIN CERTIFICATE-----
|
11
|
+
MIIEIzCCAwugAwIBAgIBGTANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzET
|
12
|
+
MBEGA1UEChMKQXBwbGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlv
|
13
|
+
biBBdXRob3JpdHkxFjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwHhcNMDgwMjE0MTg1
|
14
|
+
NjM1WhcNMTYwMjE0MTg1NjM1WjCBljELMAkGA1UEBhMCVVMxEzARBgNVBAoMCkFw
|
15
|
+
cGxlIEluYy4xLDAqBgNVBAsMI0FwcGxlIFdvcmxkd2lkZSBEZXZlbG9wZXIgUmVs
|
16
|
+
YXRpb25zMUQwQgYDVQQDDDtBcHBsZSBXb3JsZHdpZGUgRGV2ZWxvcGVyIFJlbGF0
|
17
|
+
aW9ucyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQAD
|
18
|
+
ggEPADCCAQoCggEBAMo4VKbLVqrIJDlI6Yzu7F+4fyaRvDRTes58Y4Bhd2RepQcj
|
19
|
+
tjn+UC0VVlhwLX7EbsFKhT4v8N6EGqFXya97GP9q+hUSSRUIGayq2yoy7ZZjaFIV
|
20
|
+
PYyK7L9rGJXgA6wBfZcFZ84OhZU3au0Jtq5nzVFkn8Zc0bxXbmc1gHY2pIeBbjiP
|
21
|
+
2CsVTnsl2Fq/ToPBjdKT1RpxtWCcnTNOVfkSWAyGuBYNweV3RY1QSLorLeSUheHo
|
22
|
+
xJ3GaKWwo/xnfnC6AllLd0KRObn1zeFM78A7SIym5SFd/Wpqu6cWNWDS5q3zRinJ
|
23
|
+
6MOL6XnAamFnFbLw/eVovGJfbs+Z3e8bY/6SZasCAwEAAaOBrjCBqzAOBgNVHQ8B
|
24
|
+
Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUiCcXCam2GGCL7Ou6
|
25
|
+
9kdZxVJUo7cwHwYDVR0jBBgwFoAUK9BpR5R2Cf70a40uQKb3R01/CF4wNgYDVR0f
|
26
|
+
BC8wLTAroCmgJ4YlaHR0cDovL3d3dy5hcHBsZS5jb20vYXBwbGVjYS9yb290LmNy
|
27
|
+
bDAQBgoqhkiG92NkBgIBBAIFADANBgkqhkiG9w0BAQUFAAOCAQEA2jIAlsVUlNM7
|
28
|
+
gjdmfS5o1cPGuMsmjEiQzxMkakaOY9Tw0BMG3djEwTcV8jMTOSYtzi5VQOMLA6/6
|
29
|
+
EsLnDSG41YDPrCgvzi2zTq+GGQTG6VDdTClHECP8bLsbmGtIieFbnd5G2zWFNe8+
|
30
|
+
0OJYSzj07XVaH1xwHVY5EuXhDRHkiSUGvdW0FY5e0FmXkOlLgeLfGK9EdB4ZoDpH
|
31
|
+
zJEdOusjWv6lLZf3e7vWh0ZChetSPSayY6i0scqP9Mzis8hH4L+aWYP62phTKoL1
|
32
|
+
fGUuldkzXfXtZcwxN8VaBOhr4eeIA0p1npsoy0pAiGVDdd3LOiUjxZ5X+C7O0qmS
|
33
|
+
XnMuLyV1FQ==
|
34
|
+
-----END CERTIFICATE-----
|
35
|
+
EOF
|
36
|
+
|
37
|
+
class << self
|
38
|
+
attr_accessor :certificate, :password
|
39
|
+
end
|
40
|
+
|
41
|
+
class Pass
|
42
|
+
attr_reader :pass, :assets
|
43
|
+
|
44
|
+
TYPES = ['boarding-pass', 'coupon', 'event-ticket', 'store-card', 'generic']
|
45
|
+
|
46
|
+
def initialize(directory)
|
47
|
+
@assets = Dir[File.join(directory, '*')]
|
48
|
+
@pass = File.read(@assets.delete(@assets.detect{|file| File.basename(file) == 'pass.json'}))
|
49
|
+
end
|
50
|
+
|
51
|
+
def manifest
|
52
|
+
checksums = {}
|
53
|
+
checksums['pass.json'] = Digest::SHA1.hexdigest(@pass)
|
54
|
+
|
55
|
+
@assets.each do |file|
|
56
|
+
checksums[File.basename(file)] = Digest::SHA1.file(file).hexdigest
|
57
|
+
end
|
58
|
+
|
59
|
+
checksums.to_json
|
60
|
+
end
|
61
|
+
|
62
|
+
def pkpass
|
63
|
+
Zip::ZipOutputStream.write_buffer do |zip|
|
64
|
+
zip.put_next_entry 'pass.json' and zip.write @pass
|
65
|
+
zip.put_next_entry 'manifest.json' and zip.write manifest
|
66
|
+
zip.put_next_entry 'signature' and zip.write signature(manifest)
|
67
|
+
|
68
|
+
@assets.each do |file|
|
69
|
+
zip.put_next_entry File.basename(file) and zip.print IO.read(file)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def signature(manifest)
|
77
|
+
pk7 = OpenSSL::PKCS7.sign(p12.certificate, p12.key, manifest, [wwdr], OpenSSL::PKCS7::BINARY | OpenSSL::PKCS7::DETACHED)
|
78
|
+
data = OpenSSL::PKCS7.write_smime(pk7)
|
79
|
+
|
80
|
+
start = %{filename=\"smime.p7s"\n\n}
|
81
|
+
finish = "\n\n------"
|
82
|
+
data = data[(data.index(start) + start.length)...(data.rindex(finish) + finish.length)]
|
83
|
+
|
84
|
+
Base64.decode64(data)
|
85
|
+
end
|
86
|
+
|
87
|
+
def p12
|
88
|
+
OpenSSL::PKCS12.new(File.read(Passbook.certificate), Passbook.password)
|
89
|
+
end
|
90
|
+
|
91
|
+
def wwdr
|
92
|
+
OpenSSL::X509::Certificate.new(WWDR_CERTIFICATE)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/lib/dubai/server.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
{
|
2
|
+
"formatVersion" : 1,
|
3
|
+
"passTypeIdentifier" : "pass.com.example.boarding-pass",
|
4
|
+
"description" : "Example Boarding Pass",
|
5
|
+
"teamIdentifier": "Example",
|
6
|
+
"organizationName": "Example",
|
7
|
+
"serialNumber" : "123456",
|
8
|
+
"foregroundColor": "#866B23",
|
9
|
+
"backgroundColor": "#FFD248",
|
10
|
+
"boardingPass" : {
|
11
|
+
"primaryFields" : [
|
12
|
+
{
|
13
|
+
"key" : "origin",
|
14
|
+
"label" : "San Francisco",
|
15
|
+
"value" : "SFO"
|
16
|
+
},
|
17
|
+
{
|
18
|
+
"key" : "destination",
|
19
|
+
"label" : "London",
|
20
|
+
"value" : "LHR"
|
21
|
+
}
|
22
|
+
],
|
23
|
+
"secondaryFields" : [
|
24
|
+
{
|
25
|
+
"key" : "boarding-gate",
|
26
|
+
"label" : "Gate",
|
27
|
+
"value" : "F12"
|
28
|
+
}
|
29
|
+
],
|
30
|
+
"auxiliaryFields" : [
|
31
|
+
{
|
32
|
+
"key" : "seat",
|
33
|
+
"label" : "Seat",
|
34
|
+
"value" : "7A"
|
35
|
+
},
|
36
|
+
{
|
37
|
+
"key" : "passenger-name",
|
38
|
+
"label" : "Passenger",
|
39
|
+
"value" : "John Appleseed"
|
40
|
+
}
|
41
|
+
],
|
42
|
+
"transitType" : "PKTransitTypeAir",
|
43
|
+
"barcode" : {
|
44
|
+
"message" : "ABC123",
|
45
|
+
"format" : "PKBarcodeFormatQR",
|
46
|
+
"messageEncoding" : "iso-8859-1"
|
47
|
+
},
|
48
|
+
"backFields" : [
|
49
|
+
{
|
50
|
+
"key" : "terms",
|
51
|
+
"label" : "Terms and Conditions",
|
52
|
+
"value" : "Lorem ipsum dolar sit amet"
|
53
|
+
}
|
54
|
+
]
|
55
|
+
}
|
56
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
{
|
2
|
+
"formatVersion" : 1,
|
3
|
+
"passTypeIdentifier" : "pass.com.example.coupon",
|
4
|
+
"description" : "Example Coupon",
|
5
|
+
"teamIdentifier": "Example",
|
6
|
+
"organizationName": "Example",
|
7
|
+
"serialNumber" : "123456",
|
8
|
+
"foregroundColor": "#FFFFFF",
|
9
|
+
"backgroundColor": "#C799FF",
|
10
|
+
"generic" : {
|
11
|
+
"primaryFields" : [
|
12
|
+
|
13
|
+
],
|
14
|
+
"secondaryFields" : [
|
15
|
+
|
16
|
+
],
|
17
|
+
"auxiliaryFields" : [
|
18
|
+
|
19
|
+
],
|
20
|
+
"barcode" : {
|
21
|
+
"message" : "ABCD 123 EFGH 456 IJKL 789 MNOP",
|
22
|
+
"format" : "PKBarcodeFormatPDF417",
|
23
|
+
"messageEncoding" : "iso-8859-1"
|
24
|
+
},
|
25
|
+
"backFields" : [
|
26
|
+
{
|
27
|
+
"key" : "terms",
|
28
|
+
"label" : "Terms and Conditions",
|
29
|
+
"value" : "Lorem ipsum dolar sit amet"
|
30
|
+
}
|
31
|
+
]
|
32
|
+
}
|
33
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
{
|
2
|
+
"formatVersion" : 1,
|
3
|
+
"passTypeIdentifier" : "pass.com.example.event-ticket",
|
4
|
+
"description" : "Example Event Ticket",
|
5
|
+
"teamIdentifier": "Example",
|
6
|
+
"organizationName": "Example",
|
7
|
+
"serialNumber" : "123456",
|
8
|
+
"foregroundColor": "#FFFFFF",
|
9
|
+
"backgroundColor": "#FF5453",
|
10
|
+
"generic" : {
|
11
|
+
"primaryFields" : [
|
12
|
+
|
13
|
+
],
|
14
|
+
"secondaryFields" : [
|
15
|
+
|
16
|
+
],
|
17
|
+
"auxiliaryFields" : [
|
18
|
+
|
19
|
+
],
|
20
|
+
"barcode" : {
|
21
|
+
"message" : "ABCD 123 EFGH 456 IJKL 789 MNOP",
|
22
|
+
"format" : "PKBarcodeFormatPDF417",
|
23
|
+
"messageEncoding" : "iso-8859-1"
|
24
|
+
},
|
25
|
+
"backFields" : [
|
26
|
+
{
|
27
|
+
"key" : "terms",
|
28
|
+
"label" : "Terms and Conditions",
|
29
|
+
"value" : "Lorem ipsum dolar sit amet"
|
30
|
+
}
|
31
|
+
]
|
32
|
+
}
|
33
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
{
|
2
|
+
"formatVersion" : 1,
|
3
|
+
"passTypeIdentifier" : "pass.com.example.generic",
|
4
|
+
"description" : "Example Generic Pass",
|
5
|
+
"teamIdentifier": "Example",
|
6
|
+
"organizationName": "Example",
|
7
|
+
"serialNumber" : "123456",
|
8
|
+
"foregroundColor": "#FFFFFF",
|
9
|
+
"backgroundColor": "#444444",
|
10
|
+
"generic" : {
|
11
|
+
"primaryFields" : [
|
12
|
+
|
13
|
+
],
|
14
|
+
"secondaryFields" : [
|
15
|
+
|
16
|
+
],
|
17
|
+
"auxiliaryFields" : [
|
18
|
+
|
19
|
+
],
|
20
|
+
"barcode" : {
|
21
|
+
"message" : "ABCD 123 EFGH 456 IJKL 789 MNOP",
|
22
|
+
"format" : "PKBarcodeFormatPDF417",
|
23
|
+
"messageEncoding" : "iso-8859-1"
|
24
|
+
},
|
25
|
+
"backFields" : [
|
26
|
+
{
|
27
|
+
"key" : "terms",
|
28
|
+
"label" : "Terms and Conditions",
|
29
|
+
"value" : "Lorem ipsum dolar sit amet"
|
30
|
+
}
|
31
|
+
]
|
32
|
+
}
|
33
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
{
|
2
|
+
"formatVersion" : 1,
|
3
|
+
"passTypeIdentifier" : "pass.com.example.store-card",
|
4
|
+
"description" : "Example Store Card",
|
5
|
+
"teamIdentifier": "Example",
|
6
|
+
"organizationName": "Example",
|
7
|
+
"serialNumber" : "123456",
|
8
|
+
"foregroundColor": "#FFFFFF",
|
9
|
+
"backgroundColor": "#AFC1E3",
|
10
|
+
"generic" : {
|
11
|
+
"primaryFields" : [
|
12
|
+
|
13
|
+
],
|
14
|
+
"secondaryFields" : [
|
15
|
+
|
16
|
+
],
|
17
|
+
"auxiliaryFields" : [
|
18
|
+
|
19
|
+
],
|
20
|
+
"barcode" : {
|
21
|
+
"message" : "ABCD 123 EFGH 456 IJKL 789 MNOP",
|
22
|
+
"format" : "PKBarcodeFormatPDF417",
|
23
|
+
"messageEncoding" : "iso-8859-1"
|
24
|
+
},
|
25
|
+
"backFields" : [
|
26
|
+
{
|
27
|
+
"key" : "terms",
|
28
|
+
"label" : "Terms and Conditions",
|
29
|
+
"value" : "Lorem ipsum dolar sit amet"
|
30
|
+
}
|
31
|
+
]
|
32
|
+
}
|
33
|
+
}
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dubai
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mattt Thompson
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-20 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: json
|
16
|
+
requirement: &70231892501860 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.7.3
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70231892501860
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: commander
|
27
|
+
requirement: &70231892497740 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 4.1.2
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70231892497740
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: terminal-table
|
38
|
+
requirement: &70231892496260 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.4.5
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70231892496260
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: sinatra
|
49
|
+
requirement: &70231884046780 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70231884046780
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rubyzip
|
60
|
+
requirement: &70231884045400 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70231884045400
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: &70231884044780 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70231884044780
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: rake
|
82
|
+
requirement: &70231884043820 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70231884043820
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: simplecov
|
93
|
+
requirement: &70231884042620 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
type: :development
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *70231884042620
|
102
|
+
description: ''
|
103
|
+
email: m@mattt.me
|
104
|
+
executables:
|
105
|
+
- pk
|
106
|
+
extensions: []
|
107
|
+
extra_rdoc_files: []
|
108
|
+
files:
|
109
|
+
- ./dubai.gemspec
|
110
|
+
- ./Gemfile
|
111
|
+
- ./Gemfile.lock
|
112
|
+
- ./lib/dubai/commands/build.rb
|
113
|
+
- ./lib/dubai/commands/generate.rb
|
114
|
+
- ./lib/dubai/commands/serve.rb
|
115
|
+
- ./lib/dubai/commands.rb
|
116
|
+
- ./lib/dubai/pass.rb
|
117
|
+
- ./lib/dubai/server.rb
|
118
|
+
- ./lib/dubai/templates/boarding-pass.json
|
119
|
+
- ./lib/dubai/templates/coupon.json
|
120
|
+
- ./lib/dubai/templates/event-ticket.json
|
121
|
+
- ./lib/dubai/templates/generic.json
|
122
|
+
- ./lib/dubai/templates/store-card.json
|
123
|
+
- ./lib/dubai.rb
|
124
|
+
- ./LICENSE
|
125
|
+
- ./Rakefile
|
126
|
+
- ./README.md
|
127
|
+
- spec/spec_helper.rb
|
128
|
+
- bin/pk
|
129
|
+
homepage: http://github.com/mattt/dubai
|
130
|
+
licenses: []
|
131
|
+
post_install_message:
|
132
|
+
rdoc_options: []
|
133
|
+
require_paths:
|
134
|
+
- lib
|
135
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
+
none: false
|
137
|
+
requirements:
|
138
|
+
- - ! '>='
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
segments:
|
142
|
+
- 0
|
143
|
+
hash: -3634839724726580605
|
144
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ! '>='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
segments:
|
151
|
+
- 0
|
152
|
+
hash: -3634839724726580605
|
153
|
+
requirements: []
|
154
|
+
rubyforge_project:
|
155
|
+
rubygems_version: 1.8.15
|
156
|
+
signing_key:
|
157
|
+
specification_version: 3
|
158
|
+
summary: Passbook pass generation and preview
|
159
|
+
test_files:
|
160
|
+
- spec/spec_helper.rb
|