apple_manifest_rails 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 697d45b8821e48c937d6c4e0b605c55fce1c5a1a
4
+ data.tar.gz: 19f2f6e2939b48e17576dd25593c01b1bc666e04
5
+ SHA512:
6
+ metadata.gz: 069a1471eac1d5f5fad7c17dc44b63f47eaeb9f2575a4ca67cb1af0cad11a42daec32dce6ee6c4dff332d6ba50866d31208145b4b4ccac6c54b041eba4a53027
7
+ data.tar.gz: 2363631a4ccca248568fafcd7ff189c0c73cf53fa581eb904c78b6f7a2518d88d4632bf72628eace78fa2ea0478e69f259e5cbe55f8fb49dbece0cc63316955e
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2013 Keyvan Fatehi
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # AppleManifestRails
2
+
3
+ Mountable Rails engine for capturing iOS UDID, check if IPA is installable, and installing if so.
4
+
5
+ Created for a Rails 3.2 app, might work in Rails 4, but I haven't tried. Let me know if it works!
6
+
7
+ ## Install
8
+
9
+ 1. Add to your rails gemfile
10
+
11
+ ```ruby
12
+ gem 'apple_manifest_rails'
13
+ ```
14
+
15
+ 2. Bundle
16
+
17
+ 3. Mount the engine in `config/routes.rb`
18
+
19
+ ```ruby
20
+ Example::Application.routes.draw do
21
+ mount AppleManifestRails::Engine => '/'
22
+ end
23
+ ```
24
+
25
+ 4. Start your server and navigate your iOS Safari browser to `/enroll`
26
+
27
+ ## Configure
28
+
29
+ The engine assumes the following directory structure in your rails project
30
+ ```
31
+ rails_application/
32
+ app/
33
+ config/
34
+ ...
35
+ mobile_build/
36
+ builds/
37
+ app.ipa
38
+ manifest.plist
39
+ Profile.mobileconfig
40
+ ```
41
+
42
+ The plist and mobileconfig files are part of the UDID capture and install processes, they are templates that will be modified before being sent to the client. See the `templates` directory for what these files need to look like. Customize them to your liking.
43
+
44
+ The app.ipa file is the actual compiled binary archive from Xcode. The engine will look at the embedded.mobileprovision to check if the client is installable.
45
+
46
+ ## Contributing
47
+
48
+ Yeah! Fork it, make it better! I know there are others out there that dislike relying on Testflight and Hockeyapp too -- that functionality can just be a mountable engine!
49
+
50
+ ## License
51
+
52
+ MIT or WTFPL
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'AppleManifestRails'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
data/WTFPL-LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2
+ Version 2, December 2004
3
+
4
+ Copyright (C) 2013 Keyvan Fatehi <keyvanfatehi@gmail.com>
5
+
6
+ Everyone is permitted to copy and distribute verbatim or modified
7
+ copies of this license document, and changing it is allowed as long
8
+ as the name is changed.
9
+
10
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12
+
13
+ 0. You just DO WHAT THE FUCK YOU WANT TO.
@@ -0,0 +1,15 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // the compiled file.
9
+ //
10
+ // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11
+ // GO AFTER THE REQUIRES BELOW.
12
+ //
13
+ //= require jquery
14
+ //= require jquery_ujs
15
+ //= require_tree .
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,4 @@
1
+ module AppleManifestRails
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,58 @@
1
+ require_dependency "apple_manifest_rails/application_controller"
2
+
3
+ module AppleManifestRails
4
+ class ManifestController < ApplicationController
5
+ # Enroll (Capture UDID)
6
+ def enroll
7
+ @ios_device = request.user_agent =~ /(Mobile\/.+Safari)/
8
+ end
9
+
10
+ def mobileconfig
11
+ enroll = AppleManifest::Enroll::MobileConfig.new(request)
12
+ enroll.write_mobileconfig
13
+ send_file enroll.outfile_path, type: enroll.mime_type
14
+ end
15
+
16
+ def extract_udid
17
+ parser = AppleManifest::Enroll::ResponseParser.new(request)
18
+ udid = parser.get 'UDID'
19
+ version = parser.get 'VERSION'
20
+ product = parser.get 'PRODUCT'
21
+ # TODO log this stuff
22
+ redirect_to "#{request.url}/check_install?udid=#{udid}", status: 301
23
+ end
24
+
25
+ # Check install
26
+ def check_install
27
+ @udid = params[:udid]
28
+ @checker = AppleManifest::Install::Checker.new(@udid, 'app.ipa')
29
+ set_itms_url if @checker.installable?
30
+ end
31
+
32
+ # Install (Send IPA)
33
+ def install
34
+ set_itms_url
35
+ render layout:false
36
+ end
37
+
38
+ def manifest
39
+ install = AppleManifest::Install::IPA.new(request)
40
+ install.write_manifest
41
+ send_file install.manifest_path
42
+ end
43
+
44
+ def send_ipa
45
+ send_file ipa_path
46
+ end
47
+
48
+ private
49
+ def ipa_path
50
+ filename = 'app.ipa'
51
+ Rails.root.join('mobile_build', 'builds', filename).to_s
52
+ end
53
+
54
+ def set_itms_url
55
+ @itms_url = AppleManifest::Install::IPA.new(request).itms_uri
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,4 @@
1
+ module AppleManifestRails
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module AppleManifestRails
2
+ module ManifestHelper
3
+ end
4
+ end
@@ -0,0 +1,5 @@
1
+ - if @checker.installable?
2
+ = javascript_tag "window.location.href = '#{@itms_url}'"
3
+ - else
4
+ Your device is not provisioned and so cannot install.
5
+ Your UDID: #{@udid}
@@ -0,0 +1,15 @@
1
+ - if @ios_device
2
+ #device
3
+ #header
4
+ %h1#title Enroll Device
5
+ #content
6
+ %ol.instructions
7
+ %li Tap Start to begin process
8
+ %li Press "Install" to allow access to device UDID
9
+ %li If the app can be installed on your device, it will be installed
10
+ %br
11
+ .container{style:'padding:20px;font-size:24pt;text-align:center;font-family:helvetica'}
12
+ %a.btn{href:"/enroll/mobileconfig"} Start
13
+
14
+ - else
15
+ %p{style:'color:black;text-align:center'} Please return to this page with your iOS device
@@ -0,0 +1,3 @@
1
+ .container{style:'padding:100px;font-size:24pt;text-align:center;font-family:helvetica'}
2
+ %a.btn.pull-right{href:@itms_url}
3
+ iOS Install
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>AppleManifestRails</title>
5
+ <%= stylesheet_link_tag "apple_manifest_rails/application", :media => "all" %>
6
+ <%= javascript_include_tag "apple_manifest_rails/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,9 @@
1
+ AppleManifestRails::Engine.routes.draw do
2
+ get "/enroll" => "manifest#enroll"
3
+ get "/enroll/mobileconfig" => "manifest#mobileconfig"
4
+ post "/enroll/mobileconfig/extract_udid" => "manifest#extract_udid"
5
+ get "/enroll/mobileconfig/extract_udid/check_install" => "manifest#check_install"
6
+ get "/install" => "manifest#install"
7
+ get "/apple_manifest/manifest.plist" => "manifest#manifest"
8
+ get "/install/(:appname).ipa" => "manifest#send_ipa"
9
+ end
@@ -0,0 +1,32 @@
1
+ module AppleManifest
2
+ module Enroll
3
+ class MobileConfig
4
+ attr_accessor :next_url
5
+
6
+ def initialize request
7
+ self.next_url = "#{request.url}/extract_udid"
8
+ end
9
+
10
+ def outfile_path
11
+ Rails.root.join('tmp', 'Profile.mobileconfig').to_s
12
+ end
13
+
14
+ def mime_type
15
+ "application/x-apple-aspen-config; charset=utf-8"
16
+ end
17
+
18
+ def write_mobileconfig
19
+ File.open(self.outfile_path, "w") do |out|
20
+ File.open(template_path, "r") do |tmpl|
21
+ out.write tmpl.read.gsub('[NextURL]', self.next_url)
22
+ end
23
+ end
24
+ end
25
+
26
+ private
27
+ def template_path
28
+ Rails.root.join('mobile_build', 'Profile.mobileconfig').to_s
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,21 @@
1
+ module AppleManifest
2
+ module Enroll
3
+ class ResponseParser
4
+ attr_accessor :body
5
+
6
+ def initialize request
7
+ self.body = deobfuscate(request.body.read)
8
+ end
9
+
10
+ def get key
11
+ self.body.match(/<key>#{key}<key><string>([a-zA-Z0-9]+)<string>/)[1]
12
+ end
13
+
14
+ private
15
+ def deobfuscate(input)
16
+ regex = /[A-Za-z0-9]|\>|\<|\?|\!|\"/
17
+ input.chars.select{|i| i.match(regex) }.join
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,35 @@
1
+ require 'fileutils'
2
+ require 'zip/zipfilesystem'
3
+
4
+ module AppleManifest
5
+ module Install
6
+ class Checker
7
+ attr_accessor :mobileprovision
8
+
9
+ def initialize udid, appname
10
+ ipa_path = Rails.root.join('mobile_build', 'builds', appname).to_s
11
+ extract_mobileprovision_from ipa_path
12
+ @installable = self.mobileprovision.include? udid
13
+ end
14
+
15
+ def extract_mobileprovision_from ipa_path
16
+ tempfile = File.join('tmp', 'embedded.mobileprovision')
17
+ FileUtils.rm tempfile if File.exists? tempfile
18
+ Zip::ZipFile.open(ipa_path) do |zipfile|
19
+ zipfile.each do |file|
20
+ if file.to_s.include? 'embedded.mobileprovision'
21
+ file.extract tempfile
22
+ break
23
+ end
24
+ end
25
+ end
26
+ File.open(tempfile) {|f| self.mobileprovision = f.read }
27
+ FileUtils.rm tempfile
28
+ end
29
+
30
+ def installable?
31
+ @installable
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,40 @@
1
+ module AppleManifest
2
+ module Install
3
+ class IPA
4
+
5
+ def template
6
+ Rails.root.join('mobile_build', 'manifest.plist').to_s
7
+ end
8
+
9
+ def tmp
10
+ Rails.root.join('tmp', 'manifest.plist').to_s
11
+ end
12
+
13
+ attr_accessor :base_url
14
+
15
+ def initialize(request)
16
+ self.base_url = "#{request.scheme}://#{request.host_with_port}"
17
+ end
18
+
19
+ def itms_uri
20
+ "itms-services://?action=download-manifest&url=#{self.base_url}/apple_manifest/manifest.plist"
21
+ end
22
+
23
+ def url
24
+ "#{self.base_url}/install/app.ipa"
25
+ end
26
+
27
+ def write_manifest
28
+ File.open(tmp, "w") do |f|
29
+ File.open(template, "r") do |tmpl|
30
+ f.write tmpl.read.gsub("[IPAURL]", self.url)
31
+ end
32
+ end
33
+ end
34
+
35
+ def manifest_path
36
+ Rails.root.join("tmp","manifest.plist").to_s
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,5 @@
1
+ module AppleManifestRails
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace AppleManifestRails
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module AppleManifestRails
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,9 @@
1
+ require "apple_manifest_rails/engine"
2
+
3
+ require "apple_manifest/enroll/mobile_config"
4
+ require "apple_manifest/enroll/response_parser"
5
+ require "apple_manifest/install/checker"
6
+ require "apple_manifest/install/ipa"
7
+
8
+ module AppleManifestRails
9
+ end
@@ -0,0 +1,8 @@
1
+ # desc "Print enrolled device information"
2
+ # task :apple_manifest_rails do
3
+ # # Task goes here
4
+ # end
5
+
6
+ # desc "Print installs"
7
+
8
+ # desc "Update IPA"
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: apple_manifest_rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Keyvan Fatehi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-05-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 3.2.11
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 3.2.11
27
+ - !ruby/object:Gem::Dependency
28
+ name: haml-rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 0.3.5
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 0.3.5
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubyzip
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 0.9.9
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.9.9
55
+ description: Mountable Rails engine for iOS UDID capture and app (IPA) distribution.
56
+ Uses the IPA's embedded.mobileprovision to determine if IPA can be installed.
57
+ email:
58
+ - keyvanfatehi@gmail.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - app/assets/javascripts/apple_manifest_rails/application.js
64
+ - app/assets/javascripts/apple_manifest_rails/manifest.js
65
+ - app/assets/stylesheets/apple_manifest_rails/application.css
66
+ - app/assets/stylesheets/apple_manifest_rails/manifest.css
67
+ - app/controllers/apple_manifest_rails/application_controller.rb
68
+ - app/controllers/apple_manifest_rails/manifest_controller.rb
69
+ - app/helpers/apple_manifest_rails/application_helper.rb
70
+ - app/helpers/apple_manifest_rails/manifest_helper.rb
71
+ - app/views/apple_manifest_rails/manifest/check_install.html.haml
72
+ - app/views/apple_manifest_rails/manifest/enroll.html.haml
73
+ - app/views/apple_manifest_rails/manifest/install.html.haml
74
+ - app/views/layouts/apple_manifest_rails/application.html.erb
75
+ - config/routes.rb
76
+ - lib/apple_manifest/enroll/mobile_config.rb
77
+ - lib/apple_manifest/enroll/response_parser.rb
78
+ - lib/apple_manifest/install/checker.rb
79
+ - lib/apple_manifest/install/ipa.rb
80
+ - lib/apple_manifest_rails/engine.rb
81
+ - lib/apple_manifest_rails/version.rb
82
+ - lib/apple_manifest_rails.rb
83
+ - lib/tasks/apple_manifest_rails_tasks.rake
84
+ - MIT-LICENSE
85
+ - WTFPL-LICENSE
86
+ - Rakefile
87
+ - README.md
88
+ homepage: https://github.com/keyvanfatehi/apple_manifest_rails
89
+ licenses:
90
+ - MIT
91
+ - WTFPL
92
+ metadata: {}
93
+ post_install_message: Thanks for installing AppleManifestRails! See https://github.com/keyvanfatehi/apple_manifest_rails
94
+ to see how to use this engine in your rails app to distribute your iOS applications.
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - '>='
101
+ - !ruby/object:Gem::Version
102
+ version: 1.9.2
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.0.3
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: Rails engine for iOS app distribution
114
+ test_files: []