device_api-ios 1.0.4 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +3 -1
- data/device_api-ios.gemspec +1 -1
- data/lib/device_api/ios.rb +0 -2
- data/lib/device_api/ios/device.rb +0 -15
- metadata +2 -6
- data/lib/device_api/ios/plistutil.rb +0 -64
- data/lib/device_api/ios/signing.rb +0 -122
- data/spec/ios_plistutil_spec.rb +0 -25
- data/spec/ios_signing_spec.rb +0 -103
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 926fbbdd821c6bf1297dfb4045e81b832d46f2d8
|
4
|
+
data.tar.gz: 358f660bd73e1abef43f54d3282476743883810a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 877f9a4ac4d784b0f9d62d60024e739658aa510811ea5d52a207170a2654163431820af0bf5f264ae95a91c24896fe808f4091ffc010a733167c473f7f0e84ad
|
7
|
+
data.tar.gz: fbaead8a4318399e8730f912ca95878ba181d53e1bc6aea9f641dda85b17abb73fbc7e47d7cd6164a0fcf15a1906311013d2820e4cdc8cef6e43639fba72778e
|
data/Gemfile.lock
CHANGED
@@ -4,6 +4,7 @@ GEM
|
|
4
4
|
device_api (1.0.1)
|
5
5
|
diff-lcs (1.2.5)
|
6
6
|
ios-devices (0.2.1)
|
7
|
+
ox (2.2.3)
|
7
8
|
rspec (3.3.0)
|
8
9
|
rspec-core (~> 3.3.0)
|
9
10
|
rspec-expectations (~> 3.3.0)
|
@@ -24,7 +25,8 @@ PLATFORMS
|
|
24
25
|
DEPENDENCIES
|
25
26
|
device_api (>= 1.0.0)
|
26
27
|
ios-devices
|
28
|
+
ox
|
27
29
|
rspec
|
28
30
|
|
29
31
|
BUNDLED WITH
|
30
|
-
1.10.
|
32
|
+
1.10.6
|
data/device_api-ios.gemspec
CHANGED
data/lib/device_api/ios.rb
CHANGED
@@ -2,8 +2,6 @@ require 'yaml'
|
|
2
2
|
require 'device_api/ios/device'
|
3
3
|
require 'device_api/ios/idevice'
|
4
4
|
require 'device_api/ios/ideviceinstaller'
|
5
|
-
require 'device_api/ios/signing'
|
6
|
-
require 'device_api/ios/plistutil'
|
7
5
|
require 'device_api/ios/idevicedebug'
|
8
6
|
require 'device_api/ios/ipaddress'
|
9
7
|
require 'device_api/ios/ideviceprovision'
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'device_api/device'
|
2
2
|
require 'device_api/ios/device'
|
3
3
|
require 'device_api/ios/idevice'
|
4
|
-
require 'device_api/ios/plistutil'
|
5
4
|
require 'device_api/ios/idevicename'
|
6
5
|
require 'ios/devices'
|
7
6
|
|
@@ -62,20 +61,6 @@ module DeviceAPI
|
|
62
61
|
IDevice.trusted?(serial)
|
63
62
|
end
|
64
63
|
|
65
|
-
# Get the app bundle ID from the specified app
|
66
|
-
# @return [String] app bundle id
|
67
|
-
def package_name(app)
|
68
|
-
app_info = Plistutil.get_bundle_id_from_app(app)
|
69
|
-
app_info['CFBundleIdentifier']
|
70
|
-
end
|
71
|
-
|
72
|
-
# Get the app version from the specified app
|
73
|
-
# @return [String] app version
|
74
|
-
def app_version_number(app)
|
75
|
-
app_info = Plistutil.get_bundle_id_from_app(app)
|
76
|
-
app_info['CFBundleVersion']
|
77
|
-
end
|
78
|
-
|
79
64
|
# Get the IP Address from the device
|
80
65
|
# @return [String] IP Address of current device
|
81
66
|
def ip_address
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: device_api-ios
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- BBC
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2016-02-
|
13
|
+
date: 2016-02-19 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: device_api
|
@@ -95,13 +95,9 @@ files:
|
|
95
95
|
- lib/device_api/ios/idevicename.rb
|
96
96
|
- lib/device_api/ios/ideviceprovision.rb
|
97
97
|
- lib/device_api/ios/ipaddress.rb
|
98
|
-
- lib/device_api/ios/plistutil.rb
|
99
|
-
- lib/device_api/ios/signing.rb
|
100
98
|
- spec/ios_device_spec.rb
|
101
99
|
- spec/ios_ideviceinstaller_spec.rb
|
102
100
|
- spec/ios_ipaddress_spec.rb
|
103
|
-
- spec/ios_plistutil_spec.rb
|
104
|
-
- spec/ios_signing_spec.rb
|
105
101
|
homepage: https://github.com/bbc/device_api-ios
|
106
102
|
licenses:
|
107
103
|
- MIT
|
@@ -1,64 +0,0 @@
|
|
1
|
-
require 'device_api/execution'
|
2
|
-
require 'device_api/ios/signing'
|
3
|
-
require 'ox'
|
4
|
-
|
5
|
-
# DeviceAPI - an interface to allow for automation of devices
|
6
|
-
module DeviceAPI
|
7
|
-
# iOS component of DeviceAPI
|
8
|
-
module IOS
|
9
|
-
# Namespace for all methods encapsulating plistutil calls
|
10
|
-
class Plistutil < Execution
|
11
|
-
|
12
|
-
# Check to ensure that plistutil is available
|
13
|
-
# @return [Boolean] true if plistutil is available, false otherwise
|
14
|
-
def self.plistutil_available?
|
15
|
-
result = execute('which plistutil')
|
16
|
-
result.exit == 0
|
17
|
-
end
|
18
|
-
|
19
|
-
# Gets properties from the IPA and returns them in a hash
|
20
|
-
# @param [String] path path to the IPA/App
|
21
|
-
# @return [Hash] list of properties from the app
|
22
|
-
def self.get_bundle_id_from_app(path)
|
23
|
-
path = Signing.unpack_ipa(path) if Signing.is_ipa?(path)
|
24
|
-
get_bundle_id_from_plist("#{path}/Info.plist")
|
25
|
-
end
|
26
|
-
|
27
|
-
# Gets properties from the IPA and returns them in a hash
|
28
|
-
# @param [String] plist path to the plist
|
29
|
-
# @return [Hash] list of properties from the app
|
30
|
-
def self.get_bundle_id_from_plist(plist)
|
31
|
-
raise PlistutilCommandError.new('plistutil not found') unless plistutil_available?
|
32
|
-
result = execute("plistutil -i #{plist}")
|
33
|
-
raise PlistutilCommandError.new(result.stderr) if result.exit != 0
|
34
|
-
parse_xml(result.stdout)
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.parse_xml(xml)
|
38
|
-
info = Ox.parse(xml)
|
39
|
-
nodes = info.locate('*/dict')
|
40
|
-
values = {}
|
41
|
-
last_key = nil
|
42
|
-
nodes.first.nodes.each do |child|
|
43
|
-
if child.value == 'key'
|
44
|
-
if child.nodes.first == 'get-task-allow'
|
45
|
-
values['get-task-allow'] = nodes.first.nodes[nodes.first.nodes.index(child)+1].value
|
46
|
-
next
|
47
|
-
end
|
48
|
-
last_key = child.nodes.first
|
49
|
-
elsif child.value == 'string'
|
50
|
-
values[last_key] = child.nodes.first
|
51
|
-
end
|
52
|
-
end
|
53
|
-
values
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# plistutil error class
|
58
|
-
class PlistutilCommandError < StandardError
|
59
|
-
def initialize(msg)
|
60
|
-
super(msg)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
@@ -1,122 +0,0 @@
|
|
1
|
-
require 'device_api/execution'
|
2
|
-
require 'device_api/ios/plistutil'
|
3
|
-
|
4
|
-
# DeviceAPI - an interface to allow for automation of devices
|
5
|
-
module DeviceAPI
|
6
|
-
# iOS component of DeviceAPI
|
7
|
-
module IOS
|
8
|
-
# Namespace for all methods encapsulating idevice calls
|
9
|
-
class Signing < Execution
|
10
|
-
|
11
|
-
# Check to see if the path is an IPA
|
12
|
-
def self.is_ipa?(path)
|
13
|
-
return true if (File.extname path).downcase == '.ipa'
|
14
|
-
false
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.unpack_ipa(path)
|
18
|
-
folder = File.dirname(path)
|
19
|
-
target = (File.basename path, (File.extname path))
|
20
|
-
|
21
|
-
# Check to see if the target has already been unzipped
|
22
|
-
return Dir["#{folder}/#{target}/Payload/*.app"].first if File.exists? ("#{folder}/#{target}/Payload/")
|
23
|
-
|
24
|
-
result = execute("unzip '#{path}' -d '#{folder}/#{target}'")
|
25
|
-
raise SigningCommandError.new(result.stderr) if result.exit != 0
|
26
|
-
|
27
|
-
Dir["#{folder}/#{target}/Payload/*.app"].first
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.is_app_signed?(app_path)
|
31
|
-
app_path = unpack_ipa(app_path) if is_ipa?(app_path)
|
32
|
-
result = execute("codesign -d -vvvv '#{app_path}'")
|
33
|
-
|
34
|
-
if result.exit != 0
|
35
|
-
return false if /is not signed/.match(result.stderr)
|
36
|
-
raise SigningCommandError.new(result.stderr)
|
37
|
-
end
|
38
|
-
|
39
|
-
true
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.sign_app(options = {})
|
43
|
-
cert = options[:cert]
|
44
|
-
entitlements = options[:entitlements]
|
45
|
-
app = options[:app]
|
46
|
-
original_app = nil
|
47
|
-
|
48
|
-
if is_ipa?(app)
|
49
|
-
original_app = app
|
50
|
-
app = unpack_ipa(app)
|
51
|
-
end
|
52
|
-
|
53
|
-
# Check to see if the entitlements passed in is a file or the XML
|
54
|
-
unless File.exists?(entitlements)
|
55
|
-
file = Tempfile.new('entitlements')
|
56
|
-
file.write(entitlements)
|
57
|
-
file.close
|
58
|
-
entitlements = file.path
|
59
|
-
end
|
60
|
-
|
61
|
-
result = execute("codesign --force --sign '#{cert}' --entitlements #{entitlements} '#{app}'")
|
62
|
-
|
63
|
-
raise SigningCommandError.new(result.stderr) if result.exit != 0
|
64
|
-
|
65
|
-
zip_app(app, original_app) if original_app
|
66
|
-
end
|
67
|
-
|
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
|
71
|
-
|
72
|
-
true
|
73
|
-
end
|
74
|
-
|
75
|
-
def self.get_signing_certs
|
76
|
-
result = execute('security find-identity -p codesigning -v')
|
77
|
-
|
78
|
-
raise SigningCommandError.new(result.stderr) if result.exit != 0
|
79
|
-
|
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
|
85
|
-
end
|
86
|
-
certs
|
87
|
-
end
|
88
|
-
|
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}")
|
92
|
-
|
93
|
-
if result.exit != 0
|
94
|
-
raise SigningCommandError.new(result.stderr)
|
95
|
-
end
|
96
|
-
|
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]
|
100
|
-
|
101
|
-
return xml if raw
|
102
|
-
entitlements = Plistutil.parse_xml(xml)
|
103
|
-
return entitlements
|
104
|
-
end
|
105
|
-
|
106
|
-
def self.enable_get_tasks(app_path)
|
107
|
-
entitlements = get_entitlements(app_path, raw: true)
|
108
|
-
|
109
|
-
return entitlements if entitlements.scan(/<key>get-task-allow<\/key>\\n.*<true\/>/).count > 0
|
110
|
-
|
111
|
-
entitlements.gsub('<false/>', '<true/>') if entitlements.scan(/<key>get-task-allow<\/key>\\n.*<false\/>/)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
# Signing error class
|
116
|
-
class SigningCommandError < StandardError
|
117
|
-
def initialize(msg)
|
118
|
-
super(msg)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
data/spec/ios_plistutil_spec.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'device_api/ios/plistutil'
|
2
|
-
|
3
|
-
describe DeviceAPI::IOS::Plistutil do
|
4
|
-
describe ".get_app_bundle_id" do
|
5
|
-
it "returns the correct app bundle" do
|
6
|
-
|
7
|
-
xml = <<end
|
8
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
9
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
10
|
-
<plist version="1.0">
|
11
|
-
<dict>
|
12
|
-
<key>CFBundleIdentifier</key>
|
13
|
-
<string>com.example.apple-samplecode.UICatalog</string>
|
14
|
-
</dict>
|
15
|
-
</plist>
|
16
|
-
end
|
17
|
-
|
18
|
-
allow(Open3).to receive(:capture3) {
|
19
|
-
[xml, '', (Struct.new(:exitstatus)).new(0)]
|
20
|
-
}
|
21
|
-
bundle = DeviceAPI::IOS::Plistutil.get_bundle_id_from_plist('Info.plist')
|
22
|
-
expect(bundle['CFBundleIdentifier']).to eq('com.example.apple-samplecode.UICatalog')
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/spec/ios_signing_spec.rb
DELETED
@@ -1,103 +0,0 @@
|
|
1
|
-
$LOAD_PATH.unshift( './lib/' )
|
2
|
-
|
3
|
-
require 'device_api/execution'
|
4
|
-
require 'device_api/ios/signing'
|
5
|
-
require 'yaml'
|
6
|
-
|
7
|
-
include RSpec
|
8
|
-
|
9
|
-
describe DeviceAPI::IOS::Signing do
|
10
|
-
|
11
|
-
before(:all) do
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
describe ".is_ipa?" do
|
16
|
-
it "correctly identifies an IPA" do
|
17
|
-
expect(DeviceAPI::IOS::Signing.is_ipa?('/path/to/ipa.ipa')).to be(true)
|
18
|
-
end
|
19
|
-
|
20
|
-
it "correctly identifies a file that isn't an IPA" do
|
21
|
-
expect(DeviceAPI::IOS::Signing.is_ipa?('/path/to/app.app')).to be(false)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
describe ".get_signing_certs" do
|
26
|
-
it "returns an Array of Hashes containing iOS Signing Certificates" do
|
27
|
-
expect(DeviceAPI::IOS::Signing.get_signing_certs).to be_kind_of(Array)
|
28
|
-
end
|
29
|
-
|
30
|
-
it "returns an Array of Hashes containing correct certificates" do
|
31
|
-
out = <<-eos
|
32
|
-
1) 43ED4FA24518B1F72EE4FB3E6F7476E886A8E5D0 "iPhone Developer: Test Developer (ABC1234567)"
|
33
|
-
2) 289765876A0FB55327F8F3C2A3D4FA3F1A484CFB "iPhone Developer: Test Developer (ABC1234526)"
|
34
|
-
3) 132128763516473546816751267AFA217036217B "iPhone Developer: Test Developer (ABC1235343)"
|
35
|
-
3 valid identities found
|
36
|
-
eos
|
37
|
-
allow(Open3).to receive(:capture3) {
|
38
|
-
[out, '', (Struct.new(:exitstatus)).new(0)]
|
39
|
-
}
|
40
|
-
|
41
|
-
expect(DeviceAPI::IOS::Signing.get_signing_certs.count).to eq(3)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
describe "entitlements" do
|
46
|
-
plist = <<-eos
|
47
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
48
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
49
|
-
<plist version="1.0">
|
50
|
-
<dict>
|
51
|
-
<key>application-identifier</key>
|
52
|
-
<string>uk.co.bbc.test</string>
|
53
|
-
<key>com.apple.developer.team-identifier</key>
|
54
|
-
<string>ABC1DE2345</string>
|
55
|
-
<key>get-task-allow</key>
|
56
|
-
<false/>
|
57
|
-
<key>keychain-access-groups</key>
|
58
|
-
<array>
|
59
|
-
<string>uk.co.bbc.iplayer.test</string>
|
60
|
-
</array>
|
61
|
-
</dict>
|
62
|
-
</plist>
|
63
|
-
eos
|
64
|
-
|
65
|
-
it 'returns a list of entitlements for an app' do
|
66
|
-
allow(Open3).to receive(:capture3) {
|
67
|
-
[plist, '', (Struct.new(:exitstatus)).new(0)]
|
68
|
-
}
|
69
|
-
|
70
|
-
expected_result = {
|
71
|
-
'application-identifier' => 'uk.co.bbc.test',
|
72
|
-
'com.apple.developer.team-identifier' => 'ABC1DE2345',
|
73
|
-
'get-task-allow' => 'false'
|
74
|
-
}
|
75
|
-
expect(DeviceAPI::IOS::Signing.get_entitlements('')).to eq(expected_result)
|
76
|
-
end
|
77
|
-
|
78
|
-
it 'should replace the entitlements for an app' do
|
79
|
-
expected = <<-eos
|
80
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
81
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
82
|
-
<plist version="1.0">
|
83
|
-
<dict>
|
84
|
-
<key>application-identifier</key>
|
85
|
-
<string>uk.co.bbc.test</string>
|
86
|
-
<key>com.apple.developer.team-identifier</key>
|
87
|
-
<string>ABC1DE2345</string>
|
88
|
-
<key>get-task-allow</key>
|
89
|
-
<true/>
|
90
|
-
<key>keychain-access-groups</key>
|
91
|
-
<array>
|
92
|
-
<string>uk.co.bbc.iplayer.test</string>
|
93
|
-
</array>
|
94
|
-
</dict>
|
95
|
-
</plist>
|
96
|
-
eos
|
97
|
-
allow(Open3).to receive(:capture3) {
|
98
|
-
[plist, '', (Struct.new(:exitstatus)).new(0)]
|
99
|
-
}
|
100
|
-
expect(DeviceAPI::IOS::Signing.enable_get_tasks('test.ipa')).to eq(expected)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|