fruity_builder 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8d8ae8d1b4b33450affa9d95e70c438bac84f250
4
- data.tar.gz: 02aa4a49e613e1f7f330043e61dee0a09788ee45
3
+ metadata.gz: 840aa45bbec96aa6b16e53b63886b335ceb50b29
4
+ data.tar.gz: 35dded1625ff0a3d9d70c16c060e4d9b60fa6650
5
5
  SHA512:
6
- metadata.gz: cab3fe1d9d54fb4b81f2b694ff0bef41c24b0ea65aa5289669c173c4fe9c79185d1eba26e68b67a75076a9401dd81e92d841b1af3e84a04d07aa18a0d1dc656d
7
- data.tar.gz: 2ca8656316a5268d2e216d3cee62a56dfe1fa8b5af58dbf14bfb7c26a197069f671274c7a17690a636db951add469f8b20232cefcc0bffca0a12355ada85d72a
6
+ metadata.gz: b8a112412efd89a4235d4525129da6671ef56d3d6106c88a3ed1940d159e78297c1e8936c6b5ae1bbe1cab290dd9c2332a0478b2375f176aa6aee3090aca3fa1
7
+ data.tar.gz: 976fe8ccf7e0ab35f1129886de885680320c7ce7092a2db57d8e9867d316009afd926a5576ba5eaae66a111fed49d857e9512890393e7b52caa945b933cdacd7
@@ -2,92 +2,94 @@ require 'fruity_builder/lib/execution'
2
2
  require 'ox'
3
3
 
4
4
  module FruityBuilder
5
- class Plistutil < Execution
5
+ module IOS
6
+ class Plistutil < Execution
6
7
 
7
- def self.get_xml(options = {})
8
- if options.key?(:file)
9
- IO.read(options[:file])
10
- elsif options.key?(:xml)
11
- options[:xml]
8
+ def self.get_xml(options = {})
9
+ if options.key?(:file)
10
+ IO.read(options[:file])
11
+ elsif options.key?(:xml)
12
+ options[:xml]
13
+ end
12
14
  end
13
- end
14
15
 
15
- def self.get_bundle_id(options = {})
16
- xml = get_xml(options)
16
+ def self.get_bundle_id(options = {})
17
+ xml = get_xml(options)
17
18
 
18
- raise PlistutilCommandError.new('No XML was passed') unless xml
19
- identifiers = xml.scan(/.*CFBundleIdentifier<\/key>\n\t<string>(.*?)<\/string>/)
20
- identifiers << xml.scan(/.*CFBundleName<\/key>\n\t<string>(.*?)<\/string>/)
21
- identifiers.flatten.uniq
22
- end
19
+ raise PlistutilCommandError.new('No XML was passed') unless xml
20
+ identifiers = xml.scan(/.*CFBundleIdentifier<\/key>\n\t<string>(.*?)<\/string>/)
21
+ identifiers << xml.scan(/.*CFBundleName<\/key>\n\t<string>(.*?)<\/string>/)
22
+ identifiers.flatten.uniq
23
+ end
23
24
 
24
- def self.replace_bundle_id(options = {})
25
- xml = get_xml(options)
25
+ def self.replace_bundle_id(options = {})
26
+ xml = get_xml(options)
26
27
 
27
- raise PlistutilCommandError.new('No XML was passed') unless xml
28
+ raise PlistutilCommandError.new('No XML was passed') unless xml
28
29
 
29
- replacements = xml.scan(/.*CFBundleIdentifier<\/key>\n\t<string>(.*?)<\/string>/)
30
- replacements << xml.scan(/.*CFBundleName<\/key>\n\t<string>(.*?)<\/string>/)
30
+ replacements = xml.scan(/.*CFBundleIdentifier<\/key>\n\t<string>(.*?)<\/string>/)
31
+ replacements << xml.scan(/.*CFBundleName<\/key>\n\t<string>(.*?)<\/string>/)
31
32
 
32
- replacements.flatten.uniq.each do |replacement|
33
- xml = xml.gsub(replacement, options[:new_id])
34
- end
33
+ replacements.flatten.uniq.each do |replacement|
34
+ xml = xml.gsub(replacement, options[:new_id])
35
+ end
35
36
 
36
- IO.write(options[:file], xml) if options.key?(:file)
37
- xml
38
- end
37
+ IO.write(options[:file], xml) if options.key?(:file)
38
+ xml
39
+ end
39
40
 
40
- # Check to ensure that plistutil is available
41
- # @return [Boolean] true if plistutil is available, false otherwise
42
- def self.plistutil_available?
43
- result = execute('which plistutil')
44
- result.exit == 0
45
- end
41
+ # Check to ensure that plistutil is available
42
+ # @return [Boolean] true if plistutil is available, false otherwise
43
+ def self.plistutil_available?
44
+ result = execute('which plistutil')
45
+ result.exit == 0
46
+ end
46
47
 
47
- # Gets properties from the IPA and returns them in a hash
48
- # @param [String] path path to the IPA/App
49
- # @return [Hash] list of properties from the app
50
- def self.get_bundle_id_from_app(path)
51
- path = Signing.unpack_ipa(path) if Signing.is_ipa?(path)
52
- get_bundle_id_from_plist("#{path}/Info.plist")
53
- end
48
+ # Gets properties from the IPA and returns them in a hash
49
+ # @param [String] path path to the IPA/App
50
+ # @return [Hash] list of properties from the app
51
+ def self.get_bundle_id_from_app(path)
52
+ path = Signing.unpack_ipa(path) if Signing.is_ipa?(path)
53
+ get_bundle_id_from_plist("#{path}/Info.plist")
54
+ end
54
55
 
55
- # Gets properties from the IPA and returns them in a hash
56
- # @param [String] plist path to the plist
57
- # @return [Hash] list of properties from the app
58
- def self.get_bundle_id_from_plist(plist)
59
- raise PlistutilCommandError.new('plistutil not found') unless plistutil_available?
60
- result = execute("plistutil -i #{plist}")
61
- raise PlistutilCommandError.new(result.stderr) if result.exit != 0
62
- parse_xml(result.stdout)
63
- end
56
+ # Gets properties from the IPA and returns them in a hash
57
+ # @param [String] plist path to the plist
58
+ # @return [Hash] list of properties from the app
59
+ def self.get_bundle_id_from_plist(plist)
60
+ raise PlistutilCommandError.new('plistutil not found') unless plistutil_available?
61
+ result = execute("plistutil -i #{plist}")
62
+ raise PlistutilCommandError.new(result.stderr) if result.exit != 0
63
+ parse_xml(result.stdout)
64
+ end
64
65
 
65
- def self.parse_xml(xml)
66
- info = Ox.parse(xml)
67
- nodes = info.locate('*/dict')
68
- values = {}
69
- last_key = nil
70
- nodes.each do |node|
71
- node.nodes.each do |child|
72
- if child.value == 'key'
73
- if child.nodes.first == 'get-task-allow'
74
- values['get-task-allow'] = nodes.first.nodes[nodes.first.nodes.index(child)+1].value
75
- next
66
+ def self.parse_xml(xml)
67
+ info = Ox.parse(xml)
68
+ nodes = info.locate('*/dict')
69
+ values = {}
70
+ last_key = nil
71
+ nodes.each do |node|
72
+ node.nodes.each do |child|
73
+ if child.value == 'key'
74
+ if child.nodes.first == 'get-task-allow'
75
+ values['get-task-allow'] = nodes.first.nodes[nodes.first.nodes.index(child)+1].value
76
+ next
77
+ end
78
+ last_key = child.nodes.first
79
+ elsif child.value == 'string'
80
+ values[last_key] = child.nodes.first
76
81
  end
77
- last_key = child.nodes.first
78
- elsif child.value == 'string'
79
- values[last_key] = child.nodes.first
80
82
  end
81
83
  end
84
+ values
82
85
  end
83
- values
84
86
  end
85
- end
86
87
 
87
- # plistutil error class
88
- class PlistutilCommandError < StandardError
89
- def initialize(msg)
90
- super(msg)
88
+ # plistutil error class
89
+ class PlistutilCommandError < StandardError
90
+ def initialize(msg)
91
+ super(msg)
92
+ end
91
93
  end
92
94
  end
93
95
  end
@@ -2,117 +2,121 @@ require 'fruity_builder/lib/execution'
2
2
  require 'fruity_builder/plistutil'
3
3
 
4
4
  module FruityBuilder
5
- # Namespace for all methods encapsulating idevice calls
6
- class Signing < Execution
5
+ module IOS
6
+ # Namespace for all methods encapsulating idevice calls
7
+ class Signing < Execution
8
+
9
+ # Check to see if the path is an IPA
10
+ def self.is_ipa?(path)
11
+ return true if (File.extname path).downcase == '.ipa'
12
+ false
13
+ end
7
14
 
8
- # Check to see if the path is an IPA
9
- def self.is_ipa?(path)
10
- return true if (File.extname path).downcase == '.ipa'
11
- false
12
- end
15
+ def self.unpack_ipa(path)
16
+ folder = File.dirname(path)
17
+ target = (File.basename path, (File.extname path))
13
18
 
14
- def self.unpack_ipa(path)
15
- folder = File.dirname(path)
16
- target = (File.basename path, (File.extname path))
19
+ # Check to see if the target has already been unzipped
20
+ return Dir["#{folder}/#{target}/Payload/*.app"].first if File.exists? ("#{folder}/#{target}/Payload/")
17
21
 
18
- # Check to see if the target has already been unzipped
19
- return Dir["#{folder}/#{target}/Payload/*.app"].first if File.exists? ("#{folder}/#{target}/Payload/")
22
+ result = execute("unzip '#{path}' -d '#{folder}/#{target}'")
23
+ raise SigningCommandError.new(result.stderr) if result.exit != 0
20
24
 
21
- result = execute("unzip '#{path}' -d '#{folder}/#{target}'")
22
- raise SigningCommandError.new(result.stderr) if result.exit != 0
25
+ Dir["#{folder}/#{target}/Payload/*.app"].first
26
+ end
23
27
 
24
- Dir["#{folder}/#{target}/Payload/*.app"].first
25
- end
28
+ def self.is_app_signed?(app_path)
29
+ app_path = unpack_ipa(app_path) if is_ipa?(app_path)
30
+ result = execute("codesign -d -vvvv '#{app_path}'")
26
31
 
27
- def self.is_app_signed?(app_path)
28
- app_path = unpack_ipa(app_path) if is_ipa?(app_path)
29
- result = execute("codesign -d -vvvv '#{app_path}'")
32
+ if result.exit != 0
33
+ return false if /is not signed/.match(result.stderr)
34
+ raise SigningCommandError.new(result.stderr)
35
+ end
30
36
 
31
- if result.exit != 0
32
- return false if /is not signed/.match(result.stderr)
33
- raise SigningCommandError.new(result.stderr)
37
+ true
34
38
  end
35
39
 
36
- true
37
- end
38
-
39
- def self.sign_app(options = {})
40
- cert = options[:cert]
41
- entitlements = options[:entitlements]
42
- app = options[:app]
43
- original_app = nil
40
+ def self.sign_app(options = {})
41
+ cert = options[:cert]
42
+ entitlements = options[:entitlements]
43
+ app = options[:app]
44
+ original_app = nil
44
45
 
45
- if is_ipa?(app)
46
- original_app = app
47
- app = unpack_ipa(app)
48
- end
46
+ if is_ipa?(app)
47
+ original_app = app
48
+ app = unpack_ipa(app)
49
+ end
49
50
 
50
- # Check to see if the entitlements passed in is a file or the XML
51
- unless File.exists?(entitlements)
52
- file = Tempfile.new('entitlements')
53
- file.write(entitlements)
54
- file.close
55
- entitlements = file.path
56
- end
51
+ command = "codesign --force --sign '#{cert}'"
52
+ # Check to see if the entitlements passed in is a file or the XML
53
+ unless File.exists?(entitlements)
54
+ file = Tempfile.new('entitlements')
55
+ file.write(entitlements)
56
+ file.close
57
+ entitlements = file.path
58
+ command = command + " --entitlements #{entitlements}"
59
+ end
57
60
 
58
- result = execute("codesign --force --sign '#{cert}' --entitlements #{entitlements} '#{app}'")
61
+ result = execute(command + " '#{app}'")
59
62
 
60
- raise SigningCommandError.new(result.stderr) if result.exit != 0
63
+ raise SigningCommandError.new(result.stderr) if result.exit != 0
61
64
 
62
- zip_app(app, original_app) if original_app
63
- end
65
+ zip_app(app, original_app) if original_app
66
+ end
64
67
 
65
- def self.zip_app(payload_path, ipa_path)
66
- result = execute("cd #{File.dirname(payload_path)}; zip -r #{ipa_path} ../Payload ")
67
- raise SigningCommandError.new(result.stderr) if result.exit != 0
68
+ def self.zip_app(payload_path, ipa_path)
69
+ result = execute("cd #{File.dirname(payload_path)}; zip -r #{ipa_path} ../Payload ")
70
+ raise SigningCommandError.new(result.stderr) if result.exit != 0
68
71
 
69
- true
70
- end
72
+ true
73
+ end
71
74
 
72
- def self.get_signing_certs
73
- result = execute('security find-identity -p codesigning -v')
75
+ def self.get_signing_certs
76
+ result = execute('security find-identity -p codesigning -v')
74
77
 
75
- raise SigningCommandError.new(result.stderr) if result.exit != 0
78
+ raise SigningCommandError.new(result.stderr) if result.exit != 0
76
79
 
77
- certs = []
78
- result.stdout.split("\n").each do |line|
79
- if /\)\s*(\S*)\s*"(.*)"/.match(line)
80
- certs << { id: Regexp.last_match[1], name: Regexp.last_match[2] }
80
+ certs = []
81
+ result.stdout.split("\n").each do |line|
82
+ if /\)\s*(\S*)\s*"(.*)"/.match(line)
83
+ certs << { id: Regexp.last_match[1], name: Regexp.last_match[2] }
84
+ end
81
85
  end
86
+ certs
82
87
  end
83
- certs
84
- end
85
88
 
86
- def self.get_entitlements(app_path, raw = false)
87
- app_path = unpack_ipa(app_path) if is_ipa?(app_path)
88
- result = execute("codesign -d --entitlements - #{app_path}")
89
+ def self.get_entitlements(app_path, raw = false)
90
+ app_path = unpack_ipa(app_path) if is_ipa?(app_path)
91
+ result = execute("codesign -d --entitlements - #{app_path}")
89
92
 
90
- if result.exit != 0
91
- raise SigningCommandError.new(result.stderr)
92
- end
93
+ if result.exit != 0
94
+ raise SigningCommandError.new(result.stderr)
95
+ end
93
96
 
94
- # Clean up the result as it occasionally contains invalid UTF-8 characters
95
- xml = result.stdout.to_s.encode('UTF-8', 'UTF-8', invalid: :replace)
96
- xml = xml[xml.index('<')..xml.length]
97
+ # Clean up the result as it occasionally contains invalid UTF-8 characters
98
+ xml = result.stdout.to_s.encode('UTF-8', 'UTF-8', invalid: :replace)
99
+ xml = xml[xml.index('<')..xml.length]
97
100
 
98
- return xml if raw
99
- entitlements = Plistutil.parse_xml(xml)
100
- return entitlements
101
- end
101
+ return xml if raw
102
+ entitlements = Plistutil.parse_xml(xml)
103
+ return entitlements
104
+ end
102
105
 
103
- def self.enable_get_tasks(app_path)
104
- entitlements = get_entitlements(app_path, raw: true)
106
+ def self.enable_get_tasks(app_path)
107
+ entitlements = get_entitlements(app_path, raw: true)
105
108
 
106
- return entitlements if entitlements.scan(/<key>get-task-allow<\/key>\\n.*<true\/>/).count > 0
109
+ return entitlements if entitlements.scan(/<key>get-task-allow<\/key>\\n.*<true\/>/).count > 0
107
110
 
108
- entitlements.gsub('<false/>', '<true/>') if entitlements.scan(/<key>get-task-allow<\/key>\\n.*<false\/>/)
111
+ entitlements.gsub('<false/>', '<true/>') if entitlements.scan(/<key>get-task-allow<\/key>\\n.*<false\/>/)
112
+ end
109
113
  end
110
- end
111
114
 
112
- # Signing error class
113
- class SigningCommandError < StandardError
114
- def initialize(msg)
115
- super(msg)
115
+ # Signing error class
116
+ class SigningCommandError < StandardError
117
+ def initialize(msg)
118
+ super(msg)
119
+ end
116
120
  end
117
121
  end
118
122
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fruity_builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - BBC
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-02-19 00:00:00.000000000 Z
12
+ date: 2016-05-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ox