du-passifier 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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
+