idevice 1.1.5.0
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.
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/NOTICE +202 -0
- data/README.md +74 -0
- data/Rakefile +37 -0
- data/examples/idevimgmount +58 -0
- data/examples/idumplockdownvalues +64 -0
- data/examples/ifetchcrashreports +54 -0
- data/examples/ilistapps +38 -0
- data/examples/ilistudids +26 -0
- data/examples/ilog +35 -0
- data/examples/installipa +51 -0
- data/examples/iremoveapp +42 -0
- data/examples/irestart +26 -0
- data/examples/iscreenshotr +39 -0
- data/idevice.gemspec +33 -0
- data/lib/idevice.rb +69 -0
- data/lib/idevice/afc.rb +518 -0
- data/lib/idevice/c.rb +129 -0
- data/lib/idevice/diagnostics_relay.rb +185 -0
- data/lib/idevice/file_relay.rb +83 -0
- data/lib/idevice/heartbeat.rb +99 -0
- data/lib/idevice/house_arrest.rb +138 -0
- data/lib/idevice/idevice.rb +208 -0
- data/lib/idevice/image_mounter.rb +117 -0
- data/lib/idevice/installation_proxy.rb +193 -0
- data/lib/idevice/lockdown.rb +350 -0
- data/lib/idevice/misagent.rb +112 -0
- data/lib/idevice/mobilebackup.rb +183 -0
- data/lib/idevice/mobilebackup2.rb +174 -0
- data/lib/idevice/mobilesync.rb +306 -0
- data/lib/idevice/notification_proxy.rb +168 -0
- data/lib/idevice/plist.rb +366 -0
- data/lib/idevice/restore.rb +176 -0
- data/lib/idevice/sbservices.rb +152 -0
- data/lib/idevice/screenshotr.rb +88 -0
- data/lib/idevice/version.rb +3 -0
- data/lib/idevice/webinspector.rb +96 -0
- data/spec/afc_devicespec.rb +409 -0
- data/spec/diagnostics_relay_devicespec.rb +125 -0
- data/spec/file_relay_devicespec.rb +45 -0
- data/spec/heartbeat_devicespec.rb +39 -0
- data/spec/idevice_devicespec.rb +93 -0
- data/spec/idevice_spec.rb +29 -0
- data/spec/image_mounter_devicespec.rb +65 -0
- data/spec/installation_proxy_devicespec.rb +54 -0
- data/spec/lockdown_devicespec.rb +106 -0
- data/spec/misagent_devicespec.rb +43 -0
- data/spec/mobilebackup2_devicespec.rb +58 -0
- data/spec/mobilebackup_devicespec.rb +41 -0
- data/spec/mobilesync_devicespec.rb +62 -0
- data/spec/notification_proxy_devicespec.rb +45 -0
- data/spec/plist_spec.rb +176 -0
- data/spec/restore_devicespec.rb +72 -0
- data/spec/samples/plist.bin +0 -0
- data/spec/samples/plist.xml +10 -0
- data/spec/sbservices_devicespec.rb +64 -0
- data/spec/screenshotr_devicespec.rb +39 -0
- data/spec/spec_helper.rb +73 -0
- data/spec/webinspector_devicespec.rb +36 -0
- metadata +233 -0
@@ -0,0 +1,138 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2013 Eric Monti - Bluebox Security
|
3
|
+
#
|
4
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
5
|
+
# or more contributor license agreements. See the NOTICE file
|
6
|
+
# distributed with this work for additional information
|
7
|
+
# regarding copyright ownership. The ASF licenses this file
|
8
|
+
# to you under the Apache License, Version 2.0 (the
|
9
|
+
# "License"); you may not use this file except in compliance
|
10
|
+
# with the License. You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing,
|
15
|
+
# software distributed under the License is distributed on an
|
16
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
17
|
+
# KIND, either express or implied. See the License for the
|
18
|
+
# specific language governing permissions and limitations
|
19
|
+
# under the License.
|
20
|
+
|
21
|
+
require 'idevice/c'
|
22
|
+
require 'idevice/idevice'
|
23
|
+
require 'idevice/lockdown'
|
24
|
+
require 'idevice/plist'
|
25
|
+
|
26
|
+
module Idevice
|
27
|
+
class HouseArrestError < IdeviceLibError
|
28
|
+
end
|
29
|
+
|
30
|
+
class HouseArrestClient < C::ManagedOpaquePointer
|
31
|
+
include LibHelpers
|
32
|
+
|
33
|
+
def self.release(ptr)
|
34
|
+
C.house_arrest_client_free(ptr) unless ptr.null?
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.attach(opts={})
|
38
|
+
_attach_helper("com.apple.mobile.house_arrest", opts) do |idevice, ldsvc, p_ha|
|
39
|
+
err = C.house_arrest_client_new(idevice, ldsvc, p_ha)
|
40
|
+
raise HouseArrestError, "house_arrest error: #{err}" if err != :SUCCESS
|
41
|
+
ha = p_ha.read_pointer
|
42
|
+
raise HouseArrestError, "house_arrest_client_new returned a NULL house_arrest_client_t pointer" if ha.null?
|
43
|
+
return new(ha)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def send_request(dict)
|
48
|
+
err = C.house_arrest_send_request(self, dict.to_plist_t)
|
49
|
+
raise HouseArrestError, "house_arrest error: #{err}" if err != :SUCCESS
|
50
|
+
return true
|
51
|
+
end
|
52
|
+
|
53
|
+
def send_command(command, appid)
|
54
|
+
err = C.house_arrest_send_command(self, command, appid)
|
55
|
+
raise HouseArrestError, "house_arrest error: #{err}" if err != :SUCCESS
|
56
|
+
return true
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_result
|
60
|
+
FFI::MemoryPointer.new(:pointer) do |p_result|
|
61
|
+
err = C.house_arrest_get_result(self, p_result)
|
62
|
+
raise HouseArrestError, "house_arrest error: #{err}" if err != :SUCCESS
|
63
|
+
result = p_result.read_pointer.read_plist_t
|
64
|
+
raise HouseArrestError, "house_arrest_get_result returned a null plist_t" if result.nil?
|
65
|
+
return result
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def vend_container(appid)
|
70
|
+
send_command("VendContainer", appid)
|
71
|
+
res = get_result
|
72
|
+
if res["Error"]
|
73
|
+
raise HouseArrestError, "Error vending container to appid: #{appid} - #{res.inspect}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def vend_documents(appid)
|
78
|
+
send_command("VendDocuments", appid)
|
79
|
+
res = get_result
|
80
|
+
if res["Error"]
|
81
|
+
raise HouseArrestError, "Error vending documents to appid: #{appid} - #{res.inspect}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def afc_client
|
86
|
+
FFI::MemoryPointer.new(:pointer) do |p_afc|
|
87
|
+
err = C.afc_client_new_from_house_arrest_client(self, p_afc)
|
88
|
+
raise AFCError, "AFC Error: #{err}" if err != :SUCCESS
|
89
|
+
afc = p_afc.read_pointer
|
90
|
+
raise AFCError, "afc_client_new_from_house_arrest_client returned a NULL afc_client_t pointer" if afc.null?
|
91
|
+
cli = AFCClient.new(afc)
|
92
|
+
|
93
|
+
# save a reference to ourselves in the afc client to avoid premature garbage collection...
|
94
|
+
cli.instance_variable_set(:@house_arrest, self)
|
95
|
+
return cli
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def afc_client_for_container(appid)
|
100
|
+
vend_container(appid)
|
101
|
+
return afc_client
|
102
|
+
end
|
103
|
+
|
104
|
+
def afc_client_for_documents(appid)
|
105
|
+
vend_documents(appid)
|
106
|
+
return afc_client
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
module C
|
111
|
+
ffi_lib 'imobiledevice'
|
112
|
+
|
113
|
+
typedef enum(
|
114
|
+
:SUCCESS , 0,
|
115
|
+
:INVALID_ARG , -1,
|
116
|
+
:PLIST_ERROR , -2,
|
117
|
+
:CONN_FAILED , -3,
|
118
|
+
:INVALID_MODE , -4,
|
119
|
+
:UNKNOWN_ERROR , -256,
|
120
|
+
), :house_arrest_error_t
|
121
|
+
|
122
|
+
#house_arrest_error_t house_arrest_client_new(idevice_t device, lockdownd_service_descriptor_t service, house_arrest_client_t *client);
|
123
|
+
attach_function :house_arrest_client_new, [Idevice, LockdownServiceDescriptor, :pointer], :house_arrest_error_t
|
124
|
+
|
125
|
+
#house_arrest_error_t house_arrest_client_free(house_arrest_client_t client);
|
126
|
+
attach_function :house_arrest_client_free, [HouseArrestClient], :house_arrest_error_t
|
127
|
+
|
128
|
+
#house_arrest_error_t house_arrest_send_request(house_arrest_client_t client, plist_t dict);
|
129
|
+
attach_function :house_arrest_send_request, [HouseArrestClient, Plist_t], :house_arrest_error_t
|
130
|
+
|
131
|
+
#house_arrest_error_t house_arrest_send_command(house_arrest_client_t client, const char *command, const char *appid);
|
132
|
+
attach_function :house_arrest_send_command, [HouseArrestClient, :string, :string], :house_arrest_error_t
|
133
|
+
|
134
|
+
#house_arrest_error_t house_arrest_get_result(house_arrest_client_t client, plist_t *dict);
|
135
|
+
attach_function :house_arrest_get_result, [HouseArrestClient, :pointer], :house_arrest_error_t
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,208 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2013 Eric Monti - Bluebox Security
|
3
|
+
#
|
4
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
5
|
+
# or more contributor license agreements. See the NOTICE file
|
6
|
+
# distributed with this work for additional information
|
7
|
+
# regarding copyright ownership. The ASF licenses this file
|
8
|
+
# to you under the Apache License, Version 2.0 (the
|
9
|
+
# "License"); you may not use this file except in compliance
|
10
|
+
# with the License. You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing,
|
15
|
+
# software distributed under the License is distributed on an
|
16
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
17
|
+
# KIND, either express or implied. See the License for the
|
18
|
+
# specific language governing permissions and limitations
|
19
|
+
# under the License.
|
20
|
+
|
21
|
+
require 'ffi'
|
22
|
+
require 'idevice/c'
|
23
|
+
require 'stringio'
|
24
|
+
|
25
|
+
module Idevice
|
26
|
+
class IdeviceLibError < StandardError
|
27
|
+
end
|
28
|
+
|
29
|
+
class Idevice < C::ManagedOpaquePointer
|
30
|
+
def self.release(ptr)
|
31
|
+
C.idevice_free(ptr) unless ptr.null?
|
32
|
+
end
|
33
|
+
|
34
|
+
# Use this instead of 'new' to attach to an idevice using libimobiledevice
|
35
|
+
# and instantiate a new idevice_t handle
|
36
|
+
def self.attach(opts={})
|
37
|
+
@udid = opts[:udid]
|
38
|
+
|
39
|
+
FFI::MemoryPointer.new(:pointer) do |tmpptr|
|
40
|
+
err = C.idevice_new(tmpptr, @udid)
|
41
|
+
raise IdeviceLibError, "Idevice error: #{err}" if err != :SUCCESS
|
42
|
+
|
43
|
+
idevice_t = tmpptr.read_pointer
|
44
|
+
if idevice_t.null?
|
45
|
+
raise IdeviceLibError, "idevice_new created a null pointer"
|
46
|
+
else
|
47
|
+
return new(tmpptr.read_pointer)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def udid
|
53
|
+
return @udid if @udid
|
54
|
+
|
55
|
+
@udid = nil
|
56
|
+
FFI::MemoryPointer.new(:pointer) do |udid_ptr|
|
57
|
+
err = C.idevice_get_udid(self, udid_ptr)
|
58
|
+
raise IdeviceLibError, "Idevice error: #{err}" if err != :SUCCESS
|
59
|
+
unless udid_ptr.read_pointer.null?
|
60
|
+
@udid = udid_ptr.read_pointer.read_string
|
61
|
+
C.free(udid_ptr.read_pointer)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
return @udid
|
65
|
+
end
|
66
|
+
|
67
|
+
def handle
|
68
|
+
@handle = nil
|
69
|
+
FFI::MemoryPointer.new(:uint32) do |tmpptr|
|
70
|
+
err = C.idevice_get_handle(self, tmpptr)
|
71
|
+
raise IdeviceLibError, "Idevice error: #{err}" if err != :SUCCESS
|
72
|
+
return tmpptr.read_uint32
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def connect port
|
77
|
+
IdeviceConnection.connect(self, port)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class IdeviceConnection < C::ManagedOpaquePointer
|
82
|
+
def self.release(ptr)
|
83
|
+
C.idevice_disconnect(ptr) unless ptr.null? or ptr.disconnected?
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.connect(idevice, port)
|
87
|
+
FFI::MemoryPointer.new(:pointer) do |tmpptr|
|
88
|
+
err = C.idevice_connect(idevice, port, tmpptr)
|
89
|
+
raise IdeviceLibError, "Idevice error: #{err}" if err != :SUCCESS
|
90
|
+
idev_connection = tmpptr.read_pointer
|
91
|
+
if idev_connection.null?
|
92
|
+
raise IdeviceLibError, "idevice_connect returned a null idevice_connection_t"
|
93
|
+
else
|
94
|
+
return new(idev_connection)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def disconnect
|
100
|
+
err = C.idevice_disconnect(self)
|
101
|
+
raise IdeviceLibError, "Idevice error: #{err}" if err != :SUCCESS
|
102
|
+
@_disconnected = true
|
103
|
+
nil
|
104
|
+
end
|
105
|
+
|
106
|
+
def connected?
|
107
|
+
not disconnected?
|
108
|
+
end
|
109
|
+
|
110
|
+
def disconnected?
|
111
|
+
@_disconnected == true
|
112
|
+
end
|
113
|
+
|
114
|
+
def send_data(data)
|
115
|
+
FFI::MemoryPointer.from_bytes(data) do |data_ptr|
|
116
|
+
FFI::MemoryPointer.new(:uint32) do |sent_bytes|
|
117
|
+
begin
|
118
|
+
err = C.idevice_connection_send(self, data_ptr, data_ptr.size, sent_bytes)
|
119
|
+
raise IdeviceLibError, "Idevice error: #{err}" if err != :SUCCESS
|
120
|
+
sent = sent_bytes.read_uint32
|
121
|
+
break if sent == 0
|
122
|
+
data_ptr += sent
|
123
|
+
end while data_ptr.size > 0
|
124
|
+
end
|
125
|
+
end
|
126
|
+
return
|
127
|
+
end
|
128
|
+
|
129
|
+
DEFAULT_RECV_TIMEOUT = 0
|
130
|
+
DEFAULT_RECV_CHUNKSZ = 8192
|
131
|
+
# blocking read - optionally yields to a block with each chunk read
|
132
|
+
def receive_all(timeout=nil, chunksz=nil)
|
133
|
+
timeout ||= DEFAULT_RECV_TIMEOUT
|
134
|
+
chunksz ||= DEFAULT_RECV_CHUNKSZ
|
135
|
+
recvdata = StringIO.new unless block_given?
|
136
|
+
|
137
|
+
FFI::MemoryPointer.new(chunksz) do |data_ptr|
|
138
|
+
FFI::MemoryPointer.new(:uint32) do |recv_bytes|
|
139
|
+
while (ierr=C.idevice_connection_receive_timeout(self, data_ptr, data_ptr.size, recv_bytes, timeout)) == :SUCCESS
|
140
|
+
chunk = data_ptr.read_bytes(recv_bytes.read_uint32)
|
141
|
+
if block_given?
|
142
|
+
yield chunk
|
143
|
+
else
|
144
|
+
recvdata << chunk
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# UNKNOWN_ERROR seems to indicate end of data/connection
|
149
|
+
raise IdeviceLibError, "Idevice error: #{ierr}" if ierr != :UNKNOWN_ERROR
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
return recvdata.string unless block_given?
|
154
|
+
end
|
155
|
+
|
156
|
+
# read up to maxlen bytes
|
157
|
+
def receive_data(maxlen, timeout=nil)
|
158
|
+
timeout ||= DEFAULT_RECV_TIMEOUT
|
159
|
+
recvdata = StringIO.new
|
160
|
+
|
161
|
+
FFI::MemoryPointer.new(maxlen) do |data_ptr|
|
162
|
+
FFI::MemoryPointer.new(:uint32) do |recv_bytes|
|
163
|
+
# one-shot, read up to max-len and we're done
|
164
|
+
err = C.idevice_connection_receive_timeout(self, data_ptr, data_ptr.size, recv_bytes, timeout)
|
165
|
+
raise IdeviceLibError, "Idevice error: #{err}" if err != :SUCCESS
|
166
|
+
recvdata << data_ptr.read_bytes(recv_bytes.read_uint32)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
return recvdata.string
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
module C
|
174
|
+
ffi_lib 'imobiledevice'
|
175
|
+
|
176
|
+
typedef enum(
|
177
|
+
:SUCCESS, 0,
|
178
|
+
:INVALID_ARG, -1,
|
179
|
+
:UNKNOWN_ERROR, -2,
|
180
|
+
:NO_DEVICE, -3,
|
181
|
+
:NOT_ENOUGH_DATA, -4,
|
182
|
+
:BAD_HEADER, -5,
|
183
|
+
:SSL_ERROR, -6,
|
184
|
+
), :idevice_error_t
|
185
|
+
|
186
|
+
# discovery (synchronous)
|
187
|
+
attach_function :idevice_set_debug_level, [:int], :void
|
188
|
+
attach_function :idevice_get_device_list, [:pointer, :pointer], :idevice_error_t
|
189
|
+
attach_function :idevice_device_list_free, [:pointer], :idevice_error_t
|
190
|
+
|
191
|
+
# device structure creation and destruction
|
192
|
+
attach_function :idevice_new, [:pointer, :string], :idevice_error_t
|
193
|
+
attach_function :idevice_free, [:pointer], :idevice_error_t
|
194
|
+
|
195
|
+
# connection/disconnection
|
196
|
+
attach_function :idevice_connect, [Idevice, :uint16, :pointer], :idevice_error_t
|
197
|
+
attach_function :idevice_disconnect, [IdeviceConnection], :idevice_error_t
|
198
|
+
|
199
|
+
# communication
|
200
|
+
attach_function :idevice_connection_send, [IdeviceConnection, :pointer, :uint32, :pointer], :idevice_error_t
|
201
|
+
attach_function :idevice_connection_receive_timeout, [IdeviceConnection, :pointer, :uint32, :pointer, :uint], :idevice_error_t
|
202
|
+
attach_function :idevice_connection_receive, [IdeviceConnection, :pointer, :uint32, :pointer], :idevice_error_t
|
203
|
+
|
204
|
+
# misc
|
205
|
+
attach_function :idevice_get_handle, [Idevice, :pointer], :idevice_error_t
|
206
|
+
attach_function :idevice_get_udid, [Idevice, :pointer], :idevice_error_t
|
207
|
+
end
|
208
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2013 Eric Monti - Bluebox Security
|
3
|
+
#
|
4
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
5
|
+
# or more contributor license agreements. See the NOTICE file
|
6
|
+
# distributed with this work for additional information
|
7
|
+
# regarding copyright ownership. The ASF licenses this file
|
8
|
+
# to you under the Apache License, Version 2.0 (the
|
9
|
+
# "License"); you may not use this file except in compliance
|
10
|
+
# with the License. You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing,
|
15
|
+
# software distributed under the License is distributed on an
|
16
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
17
|
+
# KIND, either express or implied. See the License for the
|
18
|
+
# specific language governing permissions and limitations
|
19
|
+
# under the License.
|
20
|
+
|
21
|
+
require 'idevice/c'
|
22
|
+
require 'idevice/plist'
|
23
|
+
require 'idevice/idevice'
|
24
|
+
require 'idevice/lockdown'
|
25
|
+
|
26
|
+
|
27
|
+
module Idevice
|
28
|
+
class ImageMounterError < IdeviceLibError
|
29
|
+
end
|
30
|
+
|
31
|
+
# Used to mount developer/debug disk images on the device.
|
32
|
+
class ImageMounterClient < C::ManagedOpaquePointer
|
33
|
+
include LibHelpers
|
34
|
+
|
35
|
+
def self.release(ptr)
|
36
|
+
C.mobile_image_mounter_free(ptr) unless ptr.null?
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.attach(opts={})
|
40
|
+
_attach_helper("com.apple.mobile.mobile_image_mounter", opts) do |idevice, ldsvc, p_mim|
|
41
|
+
err = C.mobile_image_mounter_new(idevice, ldsvc, p_mim)
|
42
|
+
raise ImageMounterError, "ImageMounter error: #{err}" if err != :SUCCESS
|
43
|
+
|
44
|
+
mim = p_mim.read_pointer
|
45
|
+
raise ImageMounterError, "mobile_image_mounter_new returned a NULL client" if mim.null?
|
46
|
+
return new(mim)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def is_mounted?(image_type="Developer")
|
51
|
+
ret = lookup_image(image_type)
|
52
|
+
return (ret["ImagePresent"] == true)
|
53
|
+
end
|
54
|
+
|
55
|
+
def lookup_image(image_type="Developer")
|
56
|
+
FFI::MemoryPointer.new(:pointer) do |p_result|
|
57
|
+
err = C.mobile_image_mounter_lookup_image(self, image_type, p_result)
|
58
|
+
raise ImageMounterError, "ImageMounter error: #{err}" if err != :SUCCESS
|
59
|
+
|
60
|
+
result = p_result.read_pointer.read_plist_t
|
61
|
+
raise ImageMounterError, "mobile_image_mounter_lookup_image returned a NULL result" if result.nil?
|
62
|
+
|
63
|
+
return result
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def mount_image(path, signature, image_type="Developer")
|
68
|
+
signature = signature.dup.force_encoding('binary')
|
69
|
+
FFI::MemoryPointer.from_bytes(signature) do |p_signature|
|
70
|
+
FFI::MemoryPointer.new(:pointer) do |p_result|
|
71
|
+
err = C.mobile_image_mounter_mount_image(self, path, p_signature, p_signature.size, image_type, p_result)
|
72
|
+
raise ImageMounterError, "ImageMounter error: #{err}" if err != :SUCCESS
|
73
|
+
|
74
|
+
result = p_result.read_pointer.read_plist_t
|
75
|
+
raise ImageMounterError, "mobile_image_mounter_mount_image returned a NULL result" if result.nil?
|
76
|
+
|
77
|
+
return result
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def hangup
|
83
|
+
err = C.mobile_image_mounter_hangup(self)
|
84
|
+
raise ImageMounterError, "ImageMounter error: #{err}" if err != :SUCCESS
|
85
|
+
|
86
|
+
return true
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
module C
|
91
|
+
ffi_lib 'imobiledevice'
|
92
|
+
|
93
|
+
typedef enum(
|
94
|
+
:SUCCESS , 0,
|
95
|
+
:INVALID_ARG , -1,
|
96
|
+
:PLIST_ERROR , -2,
|
97
|
+
:CONN_FAILED , -3,
|
98
|
+
:UNKNOWN_ERROR, -256,
|
99
|
+
), :image_mounter_error_t
|
100
|
+
|
101
|
+
#mobile_image_mounter_error_t mobile_image_mounter_new(idevice_t device, lockdownd_service_descriptor_t service, mobile_image_mounter_client_t *client);
|
102
|
+
attach_function :mobile_image_mounter_new, [Idevice, LockdownServiceDescriptor, :pointer], :image_mounter_error_t
|
103
|
+
|
104
|
+
#mobile_image_mounter_error_t mobile_image_mounter_free(mobile_image_mounter_client_t client);
|
105
|
+
attach_function :mobile_image_mounter_free, [ImageMounterClient], :image_mounter_error_t
|
106
|
+
|
107
|
+
#mobile_image_mounter_error_t mobile_image_mounter_lookup_image(mobile_image_mounter_client_t client, const char *image_type, plist_t *result);
|
108
|
+
attach_function :mobile_image_mounter_lookup_image, [ImageMounterClient, :string, :pointer], :image_mounter_error_t
|
109
|
+
|
110
|
+
#mobile_image_mounter_error_t mobile_image_mounter_mount_image(mobile_image_mounter_client_t client, const char *image_path, const char *image_signature, uint16_t signature_length, const char *image_type, plist_t *result);
|
111
|
+
attach_function :mobile_image_mounter_mount_image, [ImageMounterClient, :string, :pointer, :uint16, :string, :pointer], :image_mounter_error_t
|
112
|
+
|
113
|
+
#mobile_image_mounter_error_t mobile_image_mounter_hangup(mobile_image_mounter_client_t client);
|
114
|
+
attach_function :mobile_image_mounter_hangup, [ImageMounterClient], :image_mounter_error_t
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|