du-passifier 0.0.4

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 +133 -0
  4. data/Rakefile +57 -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 +86 -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 +169 -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,133 @@
1
+ # Passifier
2
+
3
+ Generate Apple Passbook passes in Ruby
4
+
5
+ Passifier does most of the hard work and will more easily allow you to automate generating pkpass files. You simply supply
6
+
7
+ * A Hash of metadata and layout (the contents of pass.json for those experienced)
8
+ * Image URLs and paths
9
+ * The location of your key and certificate .pem files
10
+ * Output path where you'd like 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 information 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_number = "SO_SERIAL"
29
+
30
+ spec = {
31
+ "formatVersion": 1,
32
+ "passTypeIdentifier": "pass.example.example",
33
+ "teamIdentifier": "METS",
34
+ "relevantDate": "2012-07-30T14:19Z",
35
+ "organizationName": "Example Inc.",
36
+ "serialNumber": serial_number,
37
+ "description": "The example pass from README.md",
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
+ Specify a Hash of images. Notice that you can use either paths or urls here.
70
+
71
+ ```ruby
72
+
73
+ assets = {
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 = "path/to/a/key.pem"
93
+ pass_phrase = "somethingsomething"
94
+ cert_pem = "path/to/a/certificate.pem"
95
+
96
+ # Create a Signing object
97
+ signing = Passifier::Signing.new(key_pem, pass_phrase, cert_pem)
98
+ ```
99
+
100
+ ### Generate!
101
+
102
+ Now it's time to create your pass.
103
+
104
+ ```ruby
105
+ Passifier::Pass.generate("readme.pkpass", serial_number, spec, assets, signing)
106
+ ```
107
+
108
+ Passifier will have created the file `readme.pkpass` for you. When opened in Passbook, that pass looks something like:
109
+
110
+ ![image](http://i.imgur.com/fooaB.jpg)
111
+
112
+ ## Further Reading
113
+
114
+ * Find a similar example with some more explanation [here](http://github.com/paperlesspost/passifier/blob/master/examples/simple.rb)
115
+ * Read a blog post about Passifier [here]()
116
+
117
+ ## Documentation
118
+
119
+ * [rubydoc](http://rubydoc.info/github/paperlesspost/passifier)
120
+
121
+ ## Contributing to Passifier
122
+
123
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
124
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
125
+ * Create an issue in the issue tracker
126
+ * Fork the project.
127
+ * Start a feature/bugfix branch; include the issue number in the branch name.
128
+ * Commit and push until you are happy with your contribution.
129
+ * Make sure to add tests for it. This is important so we don't break it in a future version unintentionally.
130
+
131
+ ## Copyright
132
+
133
+ Copyright © 2012 Paperless Post. See LICENSE.md for details.
data/Rakefile ADDED
@@ -0,0 +1,57 @@
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
+
15
+
16
+ require 'jeweler'
17
+ begin
18
+ Jeweler::Tasks.new do |gem|
19
+ $LOAD_PATH.unshift 'lib'
20
+ require "passifier"
21
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
22
+ gem.version = Passifier::VERSION
23
+ gem.name = "passifier"
24
+ gem.homepage = "http://github.com/paperlesspost/passifier"
25
+ gem.license = "MIT"
26
+ gem.summary = %Q{Generate Apple Passbook passes in Ruby}
27
+ gem.description = %Q{Generate Apple Passbook passes in Ruby}
28
+ gem.email = "ari.russo@gmail.com"
29
+ gem.authors = ["Ari Russo"]
30
+ # dependencies defined in Gemfile
31
+ end
32
+
33
+ Jeweler::RubygemsDotOrgTasks.new
34
+ Jeweler::GemcutterTasks.new
35
+ rescue LoadError
36
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
37
+ end
38
+
39
+
40
+ require 'rake/testtask'
41
+ Rake::TestTask.new(:test) do |test|
42
+ test.libs << 'lib' << 'test'
43
+ test.pattern = 'test/**/test_*.rb'
44
+ test.verbose = true
45
+ end
46
+
47
+ task :default => :test
48
+
49
+ require 'rdoc/task'
50
+ Rake::RDocTask.new do |rdoc|
51
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
52
+
53
+ rdoc.rdoc_dir = 'rdoc'
54
+ rdoc.title = "blah #{version}"
55
+ rdoc.rdoc_files.include('README*')
56
+ rdoc.rdoc_files.include('lib/**/*.rb')
57
+ end
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,86 @@
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
+ # Create a signing object
73
+ signing = Passifier::Signing.new(key_pem, pass_phrase, cert_pem)
74
+
75
+ #
76
+ #
77
+ # Now, generate the pass!
78
+ #
79
+ #
80
+
81
+ # Create the pass archive
82
+ output_file = "./simple.pkpass"
83
+ Passifier::Pass.generate(output_file, serial, spec, images, signing)
84
+
85
+ # Finished!
86
+ 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.4"
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>] asset_files The asset 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(asset_files, signing)
13
+ @asset_files = asset_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
+ @asset_files.each { |file| @hash[file.name] = signing.sha(file.content) }
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+