passifier 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.
Files changed (43) hide show
  1. data/Gemfile +15 -0
  2. data/LICENSE.md +22 -0
  3. data/README.md +125 -0
  4. data/Rakefile +48 -0
  5. data/examples/assets/background.png +0 -0
  6. data/examples/assets/background@2x.png +0 -0
  7. data/examples/assets/icon.png +0 -0
  8. data/examples/assets/icon@2x.png +0 -0
  9. data/examples/assets/logo.png +0 -0
  10. data/examples/assets/logo@2x.png +0 -0
  11. data/examples/assets/thumbnail.png +0 -0
  12. data/examples/assets/thumbnail@2x.png +0 -0
  13. data/examples/simple.rb +87 -0
  14. data/lib/passifier.rb +26 -0
  15. data/lib/passifier/archive.rb +52 -0
  16. data/lib/passifier/manifest.rb +37 -0
  17. data/lib/passifier/manifest_signature.rb +33 -0
  18. data/lib/passifier/pass.rb +82 -0
  19. data/lib/passifier/signing.rb +38 -0
  20. data/lib/passifier/spec.rb +31 -0
  21. data/lib/passifier/static_file.rb +24 -0
  22. data/lib/passifier/storage.rb +94 -0
  23. data/lib/passifier/url_source.rb +30 -0
  24. data/test/assets/background.png +0 -0
  25. data/test/assets/background@2x.png +0 -0
  26. data/test/assets/icon.png +0 -0
  27. data/test/assets/icon@2x.png +0 -0
  28. data/test/assets/logo.png +0 -0
  29. data/test/assets/logo@2x.png +0 -0
  30. data/test/assets/thumbnail.png +0 -0
  31. data/test/assets/thumbnail@2x.png +0 -0
  32. data/test/helper.rb +159 -0
  33. data/test/passifier/test_archive.rb +44 -0
  34. data/test/passifier/test_manifest.rb +27 -0
  35. data/test/passifier/test_manifest_signature.rb +13 -0
  36. data/test/passifier/test_pass.rb +45 -0
  37. data/test/passifier/test_signing.rb +47 -0
  38. data/test/passifier/test_spec.rb +20 -0
  39. data/test/passifier/test_static_file.rb +25 -0
  40. data/test/passifier/test_storage.rb +157 -0
  41. data/test/passifier/test_url_source.rb +30 -0
  42. data/test/test_passifier.rb +10 -0
  43. metadata +172 -0
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "rdoc", "~> 3.12"
10
+ gem "bundler"
11
+ gem "jeweler", "~> 1.8.4"
12
+ end
13
+
14
+ gem "rake"
15
+ gem "rubyzip"
data/LICENSE.md ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License
2
+
3
+ Copyright (c) Paperless Post, http://www.paperlesspost.com
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,125 @@
1
+ # Passifier
2
+
3
+ Generate Apple Passbook passes in Ruby
4
+
5
+ Passifier does most of the hard work and will easier allow you to automate generating pkpass files. You simply supply
6
+
7
+ * A Hash of metadata and layout (basically pass.json for those experienced)
8
+ * Image urls and paths
9
+ * The location of your key/certificate files
10
+ * Output path for the generated .pkpass file
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'passifier'
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ### Metadata and Layout
23
+
24
+ First, supply a bunch of pass information and styling. This will become the file pass.json within the pass archive. More inforomation on pass.json and creating a layout can be found at [developers.apple.com](https://developer.apple.com/library/prerelease/ios/documentation/UserExperience/Reference/PassKit_Bundle/Chapters/Introduction.html).
25
+
26
+ ```ruby
27
+
28
+ serial = "SO_SERIAL"
29
+
30
+ spec = {
31
+ "formatVersion" => 1,
32
+ "passTypeIdentifier" => "pass.example.example",
33
+ "teamIdentifier" => "ATEAMID",
34
+ "relevantDate" => "2012-07-30T14:19Z",
35
+ "organizationName" => "Example Inc.",
36
+ "serialNumber" => serial,
37
+ "description" => "this is a pass",
38
+ "labelColor" => "rgb(122, 16, 38)",
39
+ "backgroundColor" => "rgb(227, 227, 227)",
40
+ "foregroundColor" => "rgb(110,110,110)",
41
+ "generic" => {
42
+ "headerFields" => [
43
+ {
44
+ "key" => "date",
45
+ "label" => "Date",
46
+ "value" => "October 30th"
47
+ }
48
+ ],
49
+ "primaryFields" => [
50
+ {
51
+ "key" => "title",
52
+ "label" => "",
53
+ "value" => "Passifier!"
54
+ }
55
+ ],
56
+ "secondaryFields" => [
57
+ {
58
+ "key" => "host",
59
+ "label" => "Host",
60
+ "value" => "paperlesspost.com",
61
+ }
62
+ ]
63
+ }
64
+ }
65
+ ```
66
+
67
+ ### Images
68
+
69
+ Notice that you can use either paths or urls here
70
+
71
+ ```ruby
72
+
73
+ images = {
74
+ "background.png" => "assets/background.png",
75
+ "background@2x.png" => "assets/background@2x.png",
76
+ "icon.png" => "assets/icon.png",
77
+ "icon@2x.png" => "assets/icon@2x.png",
78
+ "logo.png" => "http://i.imgur.com/WLUf6.png",
79
+ "logo@2x.png" => "http://i.imgur.com/mOpQo.png",
80
+ "thumbnail.png" => "assets/thumbnail.png",
81
+ "thumbnail@2x.png" => "assets/thumbnail@2x.png"
82
+ }
83
+ ```
84
+
85
+ ### Signing
86
+
87
+ Give Passifier some info about your .pem files.
88
+
89
+ (to-do: more info on obtaining certificates and creating pem files)
90
+
91
+ ```ruby
92
+ key_pem = "../test/assets/signing/key/key.pem"
93
+ pass_phrase = "somethingsomething"
94
+ cert_pem = "../test/assets/signing/certificate/certificate.pem"
95
+ ```
96
+
97
+ ### Generate!
98
+
99
+ ```ruby
100
+ # Create the signing
101
+ signing = Passifier::Signing.new(key_pem, pass_phrase, cert_pem)
102
+
103
+ # Finally, create the pass archive
104
+ Passifier::Pass.create_archive("readme.pkpass", serial, spec, images, signing)
105
+ ```
106
+
107
+ Passifier will have created the file `readme.pkpass` for you. When opened in Passbook, that pass looks something like:
108
+
109
+ ![image](http://i.imgur.com/fooaB.jpg)
110
+
111
+ Find a similar example with some more explanation [here](http://github.com/paperlesspost/passifier/blob/master/examples/simple.rb)
112
+
113
+ ## Contributing to Passifier
114
+
115
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
116
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
117
+ * Create an issue in the issue tracker
118
+ * Fork the project.
119
+ * Start a feature/bugfix branch; include the issue number in the branch name.
120
+ * Commit and push until you are happy with your contribution.
121
+ * Make sure to add tests for it. This is important so we don't break it in a future version unintentionally.
122
+
123
+ ## Copyright
124
+
125
+ Copyright © 2012 Paperless Post. See LICENSE.md for details.
data/Rakefile ADDED
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ $LOAD_PATH.unshift 'lib'
17
+ require "passifier"
18
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
19
+ gem.version = Passifier::VERSION
20
+ gem.name = "passifier"
21
+ gem.homepage = "http://github.com/paperlesspost/passifier"
22
+ gem.license = "MIT"
23
+ gem.summary = %Q{Generate Apple Passbook passes in Ruby}
24
+ gem.description = %Q{Generate Apple Passbook passes in Ruby}
25
+ gem.email = "ari.russo@gmail.com"
26
+ gem.authors = ["Ari Russo"]
27
+ # dependencies defined in Gemfile
28
+ end
29
+ Jeweler::RubygemsDotOrgTasks.new
30
+
31
+ require 'rake/testtask'
32
+ Rake::TestTask.new(:test) do |test|
33
+ test.libs << 'lib' << 'test'
34
+ test.pattern = 'test/**/test_*.rb'
35
+ test.verbose = true
36
+ end
37
+
38
+ task :default => :test
39
+
40
+ require 'rdoc/task'
41
+ Rake::RDocTask.new do |rdoc|
42
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
43
+
44
+ rdoc.rdoc_dir = 'rdoc'
45
+ rdoc.title = "blah #{version}"
46
+ rdoc.rdoc_files.include('README*')
47
+ rdoc.rdoc_files.include('lib/**/*.rb')
48
+ end
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.join( File.dirname( __FILE__ ), '../lib')
3
+
4
+ require "passifier"
5
+
6
+ # This is an example that will generate a simple pass file
7
+
8
+ # 1. Pass metadata and layout
9
+ # This is used to generate the pass.json file for the archive.
10
+ # See () for more information about pass.json usage
11
+ #
12
+ serial = "SO_SERIAL"
13
+ spec = {
14
+ "formatVersion" => 1,
15
+ "passTypeIdentifier" => "pass.example.example",
16
+ "teamIdentifier" => "ATEAMID",
17
+ "relevantDate" => "2012-07-30T14:19Z",
18
+ "organizationName" => "Example Inc.",
19
+ "serialNumber" => serial,
20
+ "description" => "this is a pass",
21
+ "labelColor" => "rgb(122, 16, 38)",
22
+ "backgroundColor" => "rgb(227, 227, 227)",
23
+ "foregroundColor" => "rgb(110,110,110)",
24
+ "generic" => {
25
+ "headerFields" => [
26
+ {
27
+ "key" => "date",
28
+ "label" => "Date",
29
+ "value" => "October 30th"
30
+ }
31
+ ],
32
+ "primaryFields" => [
33
+ {
34
+ "key" => "title",
35
+ "label" => "",
36
+ "value" => "Passifier!"
37
+ }
38
+ ],
39
+ "secondaryFields" => [
40
+ {
41
+ "key" => "host",
42
+ "label" => "Host",
43
+ "value" => "dev.paperlesspost.com",
44
+ }
45
+ ]
46
+ }
47
+ }
48
+
49
+ #
50
+ # 2. Image assets
51
+ # notice that you can use either paths or urls here
52
+ #
53
+ images = {
54
+ "background.png" => "assets/background.png",
55
+ "background@2x.png" => "assets/background@2x.png",
56
+ "icon.png" => "assets/icon.png",
57
+ "icon@2x.png" => "assets/icon@2x.png",
58
+ "logo.png" => "http://i.imgur.com/WLUf6.png",
59
+ "logo@2x.png" => "http://i.imgur.com/mOpQo.png",
60
+ "thumbnail.png" => "assets/thumbnail.png",
61
+ "thumbnail@2x.png" => "assets/thumbnail@2x.png"
62
+ }
63
+
64
+ #
65
+ # 3. Signing settings
66
+ # Replace with your own paths/password if you plan on running this example
67
+ #
68
+ key_pem = "../test/assets/signing/key/key.pem"
69
+ pass_phrase = File.read("../test/assets/signing/pass_phrase.txt").strip.lstrip # you can just replace this with a string if you want
70
+ cert_pem = "../test/assets/signing/certificate/certificate.pem"
71
+
72
+ #
73
+ #
74
+ # Now, generate the pass!
75
+ #
76
+ #
77
+
78
+ # Create the signing
79
+ #
80
+ signing = Passifier::Signing.new(key_pem, pass_phrase, cert_pem)
81
+
82
+ # Create the pass archive
83
+ output_file = "./simple.pkpass"
84
+ Passifier::Pass.create_archive(output_file, serial, spec, images, signing)
85
+
86
+ # Finished!
87
+ puts "Finished generating the pass archive: #{output_file}"
data/lib/passifier.rb ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # libs
4
+ require "forwardable"
5
+ require "json"
6
+ require "net/http"
7
+ require "zip/zip"
8
+
9
+ # modules
10
+ require "passifier/signing"
11
+
12
+ # classes
13
+ require "passifier/archive"
14
+ require "passifier/manifest"
15
+ require "passifier/manifest_signature"
16
+ require "passifier/pass"
17
+ require "passifier/spec"
18
+ require "passifier/static_file"
19
+ require "passifier/storage"
20
+ require "passifier/url_source"
21
+
22
+ module Passifier
23
+
24
+ VERSION = "0.0.2"
25
+
26
+ end
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module Passifier
4
+
5
+ # Represents the .pkpass archive file for the pass. Despite the extension, a .pkpass file is actually
6
+ # a zip archive.
7
+ class Archive
8
+
9
+ attr_reader :assets,
10
+ :id,
11
+ :path
12
+
13
+ # @param [String] path The archive path
14
+ # @param [String] id An ID to represent the Archive
15
+ def initialize(path, id, assets)
16
+ @assets = assets
17
+ @path = path
18
+ @id = id
19
+ end
20
+
21
+ # The raw data of this archive file
22
+ # @return [String] The raw data of this archive file
23
+ def data
24
+ File.open(@path, 'rb') {|file| file.read } unless @path.nil?
25
+ end
26
+
27
+ def destroy
28
+ unless @storage.nil?
29
+ @storage.cleanup
30
+ @storage.remove_zip(@path)
31
+ end
32
+ end
33
+
34
+ # Write the zip archive to disk
35
+ # @param [Hash] options The options to store an Archive with.
36
+ # @option opts [String] :scratch_directory The directory to use for temp files while creating the archive.
37
+ # (not to be confused with the archive path)
38
+ def store(options = {})
39
+ scratch_dir = options[:scratch_directory] || "/tmp/passkit/#{@id}"
40
+ @storage = Storage.new(scratch_dir, @assets)
41
+ @storage.store
42
+ @storage.zip(@path)
43
+ @storage.cleanup
44
+ end
45
+ alias_method :save, :store
46
+
47
+ end
48
+
49
+ end
50
+
51
+
52
+
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module Passifier
4
+
5
+ class Manifest
6
+
7
+ attr_reader :hash
8
+ alias_method :to_hash, :hash
9
+
10
+ # @param [Array<Passifier::StaticFile, Passifier::UrlSource>] images_files The image files to populate the manifest with
11
+ # @param [Passifier::Signing] signing The signing to sign the images and generate the digests with
12
+ def initialize(image_files, signing)
13
+ @image_files = image_files
14
+ populate_content(signing)
15
+ end
16
+
17
+ def filename
18
+ "manifest.json"
19
+ end
20
+
21
+ def content
22
+ to_hash.to_json
23
+ end
24
+
25
+ private
26
+
27
+ # Convert the image files into signed SHA1 digests for use in the manifest file
28
+ # @return [String] The resulting contents of the manifest file (aka Passifier::Manifest#content)
29
+ def populate_content(signing)
30
+ @hash = {}
31
+ @image_files.each { |file| @hash[file.name] = signing.sha(file.content) }
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module Passifier
4
+
5
+ # Represents the signing of the manifest file aka "signature" file in the archive
6
+ class ManifestSignature
7
+
8
+ attr_reader :content, :manifest
9
+
10
+ # @param [Passifier::Manifest] manifest The Manifest to base the signature on
11
+ def initialize(manifest, signing)
12
+ @manifest = manifest
13
+ populate_content(signing)
14
+ end
15
+
16
+ def filename
17
+ "signature"
18
+ end
19
+
20
+ private
21
+
22
+ # Sign the contents of the Manifest
23
+ # @param [Passifier::Signing] signing The signing to use to generate the signature file
24
+ # @return [String] The content of the manifest signature file aka "signature" in the archive
25
+ def populate_content(signing)
26
+ @content = signing.sign(manifest.content)
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+