device_api-ios 1.0.4 → 1.0.5
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 +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
|