pymobiledevice3 4.27.0__py3-none-any.whl → 5.1.2__py3-none-any.whl
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.
- misc/plist_sniffer.py +15 -15
- misc/remotexpc_sniffer.py +29 -28
- pymobiledevice3/__main__.py +123 -98
- pymobiledevice3/_version.py +2 -2
- pymobiledevice3/bonjour.py +351 -117
- pymobiledevice3/ca.py +32 -24
- pymobiledevice3/cli/activation.py +7 -7
- pymobiledevice3/cli/afc.py +19 -19
- pymobiledevice3/cli/amfi.py +4 -4
- pymobiledevice3/cli/apps.py +51 -39
- pymobiledevice3/cli/backup.py +58 -32
- pymobiledevice3/cli/bonjour.py +27 -20
- pymobiledevice3/cli/cli_common.py +112 -81
- pymobiledevice3/cli/companion_proxy.py +4 -4
- pymobiledevice3/cli/completions.py +10 -10
- pymobiledevice3/cli/crash.py +37 -31
- pymobiledevice3/cli/developer.py +601 -519
- pymobiledevice3/cli/diagnostics.py +38 -33
- pymobiledevice3/cli/lockdown.py +82 -72
- pymobiledevice3/cli/mounter.py +84 -67
- pymobiledevice3/cli/notification.py +10 -10
- pymobiledevice3/cli/pcap.py +19 -14
- pymobiledevice3/cli/power_assertion.py +12 -10
- pymobiledevice3/cli/processes.py +10 -10
- pymobiledevice3/cli/profile.py +88 -77
- pymobiledevice3/cli/provision.py +17 -17
- pymobiledevice3/cli/remote.py +188 -111
- pymobiledevice3/cli/restore.py +43 -40
- pymobiledevice3/cli/springboard.py +30 -28
- pymobiledevice3/cli/syslog.py +85 -58
- pymobiledevice3/cli/usbmux.py +21 -20
- pymobiledevice3/cli/version.py +3 -2
- pymobiledevice3/cli/webinspector.py +156 -78
- pymobiledevice3/common.py +1 -1
- pymobiledevice3/exceptions.py +154 -60
- pymobiledevice3/irecv.py +49 -53
- pymobiledevice3/irecv_devices.py +1489 -492
- pymobiledevice3/lockdown.py +400 -251
- pymobiledevice3/lockdown_service_provider.py +5 -7
- pymobiledevice3/osu/os_utils.py +18 -9
- pymobiledevice3/osu/posix_util.py +28 -15
- pymobiledevice3/osu/win_util.py +14 -8
- pymobiledevice3/pair_records.py +19 -19
- pymobiledevice3/remote/common.py +4 -4
- pymobiledevice3/remote/core_device/app_service.py +94 -67
- pymobiledevice3/remote/core_device/core_device_service.py +17 -14
- pymobiledevice3/remote/core_device/device_info.py +5 -5
- pymobiledevice3/remote/core_device/diagnostics_service.py +10 -8
- pymobiledevice3/remote/core_device/file_service.py +47 -33
- pymobiledevice3/remote/remote_service_discovery.py +53 -35
- pymobiledevice3/remote/remotexpc.py +64 -42
- pymobiledevice3/remote/tunnel_service.py +383 -297
- pymobiledevice3/remote/utils.py +14 -13
- pymobiledevice3/remote/xpc_message.py +145 -125
- pymobiledevice3/resources/dsc_uuid_map.py +19 -19
- pymobiledevice3/resources/firmware_notifications.py +16 -16
- pymobiledevice3/restore/asr.py +27 -27
- pymobiledevice3/restore/base_restore.py +90 -47
- pymobiledevice3/restore/consts.py +87 -66
- pymobiledevice3/restore/device.py +11 -11
- pymobiledevice3/restore/fdr.py +46 -46
- pymobiledevice3/restore/ftab.py +19 -19
- pymobiledevice3/restore/img4.py +130 -133
- pymobiledevice3/restore/mbn.py +587 -0
- pymobiledevice3/restore/recovery.py +125 -135
- pymobiledevice3/restore/restore.py +535 -523
- pymobiledevice3/restore/restore_options.py +122 -115
- pymobiledevice3/restore/restored_client.py +25 -22
- pymobiledevice3/restore/tss.py +378 -270
- pymobiledevice3/service_connection.py +50 -46
- pymobiledevice3/services/accessibilityaudit.py +137 -127
- pymobiledevice3/services/afc.py +363 -293
- pymobiledevice3/services/amfi.py +21 -18
- pymobiledevice3/services/companion.py +23 -19
- pymobiledevice3/services/crash_reports.py +61 -47
- pymobiledevice3/services/debugserver_applist.py +3 -3
- pymobiledevice3/services/device_arbitration.py +8 -8
- pymobiledevice3/services/device_link.py +56 -48
- pymobiledevice3/services/diagnostics.py +971 -968
- pymobiledevice3/services/dtfetchsymbols.py +8 -8
- pymobiledevice3/services/dvt/dvt_secure_socket_proxy.py +4 -4
- pymobiledevice3/services/dvt/dvt_testmanaged_proxy.py +4 -4
- pymobiledevice3/services/dvt/instruments/activity_trace_tap.py +85 -74
- pymobiledevice3/services/dvt/instruments/application_listing.py +2 -3
- pymobiledevice3/services/dvt/instruments/condition_inducer.py +7 -6
- pymobiledevice3/services/dvt/instruments/core_profile_session_tap.py +466 -384
- pymobiledevice3/services/dvt/instruments/device_info.py +11 -11
- pymobiledevice3/services/dvt/instruments/energy_monitor.py +1 -1
- pymobiledevice3/services/dvt/instruments/graphics.py +1 -1
- pymobiledevice3/services/dvt/instruments/location_simulation.py +1 -1
- pymobiledevice3/services/dvt/instruments/location_simulation_base.py +10 -10
- pymobiledevice3/services/dvt/instruments/network_monitor.py +17 -17
- pymobiledevice3/services/dvt/instruments/notifications.py +1 -1
- pymobiledevice3/services/dvt/instruments/process_control.py +25 -10
- pymobiledevice3/services/dvt/instruments/screenshot.py +2 -2
- pymobiledevice3/services/dvt/instruments/sysmontap.py +15 -15
- pymobiledevice3/services/dvt/testmanaged/xcuitest.py +42 -52
- pymobiledevice3/services/file_relay.py +10 -10
- pymobiledevice3/services/heartbeat.py +8 -7
- pymobiledevice3/services/house_arrest.py +12 -15
- pymobiledevice3/services/installation_proxy.py +119 -100
- pymobiledevice3/services/lockdown_service.py +12 -5
- pymobiledevice3/services/misagent.py +22 -19
- pymobiledevice3/services/mobile_activation.py +84 -72
- pymobiledevice3/services/mobile_config.py +331 -301
- pymobiledevice3/services/mobile_image_mounter.py +137 -116
- pymobiledevice3/services/mobilebackup2.py +188 -150
- pymobiledevice3/services/notification_proxy.py +11 -11
- pymobiledevice3/services/os_trace.py +128 -74
- pymobiledevice3/services/pcapd.py +306 -306
- pymobiledevice3/services/power_assertion.py +10 -9
- pymobiledevice3/services/preboard.py +4 -4
- pymobiledevice3/services/remote_fetch_symbols.py +16 -14
- pymobiledevice3/services/remote_server.py +176 -146
- pymobiledevice3/services/restore_service.py +16 -16
- pymobiledevice3/services/screenshot.py +13 -10
- pymobiledevice3/services/simulate_location.py +7 -7
- pymobiledevice3/services/springboard.py +15 -15
- pymobiledevice3/services/syslog.py +5 -5
- pymobiledevice3/services/web_protocol/alert.py +3 -3
- pymobiledevice3/services/web_protocol/automation_session.py +183 -179
- pymobiledevice3/services/web_protocol/cdp_screencast.py +44 -36
- pymobiledevice3/services/web_protocol/cdp_server.py +19 -19
- pymobiledevice3/services/web_protocol/cdp_target.py +411 -373
- pymobiledevice3/services/web_protocol/driver.py +47 -45
- pymobiledevice3/services/web_protocol/element.py +74 -63
- pymobiledevice3/services/web_protocol/inspector_session.py +106 -102
- pymobiledevice3/services/web_protocol/selenium_api.py +3 -3
- pymobiledevice3/services/web_protocol/session_protocol.py +15 -10
- pymobiledevice3/services/web_protocol/switch_to.py +11 -12
- pymobiledevice3/services/webinspector.py +142 -116
- pymobiledevice3/tcp_forwarder.py +64 -50
- pymobiledevice3/tunneld/api.py +20 -15
- pymobiledevice3/tunneld/server.py +315 -193
- pymobiledevice3/usbmux.py +197 -148
- pymobiledevice3/utils.py +14 -11
- {pymobiledevice3-4.27.0.dist-info → pymobiledevice3-5.1.2.dist-info}/METADATA +2 -6
- pymobiledevice3-5.1.2.dist-info/RECORD +173 -0
- pymobiledevice3-4.27.0.dist-info/RECORD +0 -172
- {pymobiledevice3-4.27.0.dist-info → pymobiledevice3-5.1.2.dist-info}/WHEEL +0 -0
- {pymobiledevice3-4.27.0.dist-info → pymobiledevice3-5.1.2.dist-info}/entry_points.txt +0 -0
- {pymobiledevice3-4.27.0.dist-info → pymobiledevice3-5.1.2.dist-info}/licenses/LICENSE +0 -0
- {pymobiledevice3-4.27.0.dist-info → pymobiledevice3-5.1.2.dist-info}/top_level.txt +0 -0
|
@@ -9,8 +9,6 @@ from enum import IntEnum
|
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
from tarfile import TarFile
|
|
11
11
|
|
|
12
|
-
from construct import Adapter, Byte, Bytes, Computed, Enum, Int16ul, Int32ul, Optional, RepeatUntil, Struct, this
|
|
13
|
-
|
|
14
12
|
from pymobiledevice3.exceptions import PyMobileDevice3Exception
|
|
15
13
|
from pymobiledevice3.lockdown import LockdownClient
|
|
16
14
|
from pymobiledevice3.lockdown_service_provider import LockdownServiceProvider
|
|
@@ -18,8 +16,8 @@ from pymobiledevice3.services.lockdown_service import LockdownService
|
|
|
18
16
|
from pymobiledevice3.utils import try_decode
|
|
19
17
|
|
|
20
18
|
CHUNK_SIZE = 4096
|
|
21
|
-
TIME_FORMAT =
|
|
22
|
-
SYSLOG_LINE_SPLITTER =
|
|
19
|
+
TIME_FORMAT = "%H:%M:%S"
|
|
20
|
+
SYSLOG_LINE_SPLITTER = "\n\x00"
|
|
23
21
|
|
|
24
22
|
|
|
25
23
|
class SyslogLogLevel(IntEnum):
|
|
@@ -50,47 +48,96 @@ class SyslogEntry:
|
|
|
50
48
|
label: typing.Optional[SyslogLabel] = None
|
|
51
49
|
|
|
52
50
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
51
|
+
def parse_syslog_entry(data: bytes) -> SyslogEntry:
|
|
52
|
+
"""
|
|
53
|
+
Parse a syslog entry from binary data.
|
|
54
|
+
|
|
55
|
+
:param data: Raw binary data
|
|
56
|
+
:return: SyslogEntry
|
|
57
|
+
"""
|
|
58
|
+
offset = 0
|
|
59
|
+
|
|
60
|
+
# Skip first 9 bytes
|
|
61
|
+
offset += 9
|
|
62
|
+
|
|
63
|
+
# Parse pid (4 bytes, little-endian unsigned int)
|
|
64
|
+
pid = struct.unpack("<I", data[offset : offset + 4])[0]
|
|
65
|
+
offset += 4
|
|
66
|
+
|
|
67
|
+
# Skip 42 bytes
|
|
68
|
+
offset += 42
|
|
69
|
+
|
|
70
|
+
# Parse timestamp
|
|
71
|
+
seconds = struct.unpack("<I", data[offset : offset + 4])[0]
|
|
72
|
+
offset += 4
|
|
73
|
+
offset += 4 # Skip 4 bytes
|
|
74
|
+
microseconds = struct.unpack("<I", data[offset : offset + 4])[0]
|
|
75
|
+
offset += 4
|
|
76
|
+
timestamp = datetime.fromtimestamp(seconds + (microseconds / 1000000))
|
|
77
|
+
|
|
78
|
+
# Skip 1 byte
|
|
79
|
+
offset += 1
|
|
80
|
+
|
|
81
|
+
# Parse level (1 byte)
|
|
82
|
+
level = data[offset]
|
|
83
|
+
offset += 1
|
|
84
|
+
|
|
85
|
+
# Skip 38 bytes
|
|
86
|
+
offset += 38
|
|
87
|
+
|
|
88
|
+
# Parse image_name_size (2 bytes, little-endian unsigned short)
|
|
89
|
+
image_name_size = struct.unpack("<H", data[offset : offset + 2])[0]
|
|
90
|
+
offset += 2
|
|
91
|
+
|
|
92
|
+
# Parse message_size (2 bytes, little-endian unsigned short)
|
|
93
|
+
message_size = struct.unpack("<H", data[offset : offset + 2])[0]
|
|
94
|
+
offset += 2
|
|
95
|
+
|
|
96
|
+
# Skip 6 bytes
|
|
97
|
+
offset += 6
|
|
98
|
+
|
|
99
|
+
# Parse subsystem_size (4 bytes, little-endian unsigned int)
|
|
100
|
+
subsystem_size = struct.unpack("<I", data[offset : offset + 4])[0]
|
|
101
|
+
offset += 4
|
|
102
|
+
|
|
103
|
+
# Parse category_size (4 bytes, little-endian unsigned int)
|
|
104
|
+
category_size = struct.unpack("<I", data[offset : offset + 4])[0]
|
|
105
|
+
offset += 4
|
|
106
|
+
|
|
107
|
+
# Skip 4 bytes
|
|
108
|
+
offset += 4
|
|
109
|
+
|
|
110
|
+
# Parse filename (null-terminated)
|
|
111
|
+
filename_end = data.find(b"\x00", offset)
|
|
112
|
+
filename = try_decode(data[offset:filename_end])
|
|
113
|
+
offset = filename_end + 1
|
|
114
|
+
|
|
115
|
+
# Parse image_name
|
|
116
|
+
image_name = try_decode(data[offset : offset + image_name_size - 1])
|
|
117
|
+
offset += image_name_size
|
|
118
|
+
|
|
119
|
+
# Parse message
|
|
120
|
+
message = try_decode(data[offset : offset + message_size - 1])
|
|
121
|
+
offset += message_size
|
|
122
|
+
|
|
123
|
+
# Parse label (optional)
|
|
124
|
+
label = None
|
|
125
|
+
if subsystem_size > 0 and category_size > 0:
|
|
126
|
+
subsystem = try_decode(data[offset : offset + subsystem_size - 1])
|
|
127
|
+
offset += subsystem_size
|
|
128
|
+
category = try_decode(data[offset : offset + category_size - 1])
|
|
129
|
+
offset += category_size
|
|
130
|
+
label = SyslogLabel(subsystem=subsystem, category=category)
|
|
131
|
+
|
|
132
|
+
return SyslogEntry(
|
|
133
|
+
pid=pid,
|
|
134
|
+
timestamp=timestamp,
|
|
135
|
+
level=SyslogLogLevel(level),
|
|
136
|
+
image_name=image_name,
|
|
137
|
+
filename=filename,
|
|
138
|
+
message=message,
|
|
139
|
+
label=label,
|
|
140
|
+
)
|
|
94
141
|
|
|
95
142
|
|
|
96
143
|
class OsTraceService(LockdownService):
|
|
@@ -101,8 +148,9 @@ class OsTraceService(LockdownService):
|
|
|
101
148
|
* Get old stored syslog archive in PAX format (can be extracted using `pax -r < filename`).
|
|
102
149
|
* Archive contain the contents are the `/var/db/diagnostics` directory
|
|
103
150
|
"""
|
|
104
|
-
|
|
105
|
-
|
|
151
|
+
|
|
152
|
+
SERVICE_NAME = "com.apple.os_trace_relay"
|
|
153
|
+
RSD_SERVICE_NAME = "com.apple.os_trace_relay.shim.remote"
|
|
106
154
|
|
|
107
155
|
def __init__(self, lockdown: LockdownServiceProvider):
|
|
108
156
|
if isinstance(lockdown, LockdownClient):
|
|
@@ -111,7 +159,7 @@ class OsTraceService(LockdownService):
|
|
|
111
159
|
super().__init__(lockdown, self.RSD_SERVICE_NAME)
|
|
112
160
|
|
|
113
161
|
def get_pid_list(self):
|
|
114
|
-
self.service.send_plist({
|
|
162
|
+
self.service.send_plist({"Request": "PidList"})
|
|
115
163
|
|
|
116
164
|
# ignore first received unknown byte
|
|
117
165
|
self.service.recvall(1)
|
|
@@ -119,33 +167,44 @@ class OsTraceService(LockdownService):
|
|
|
119
167
|
response = self.service.recv_prefixed()
|
|
120
168
|
return plistlib.loads(response)
|
|
121
169
|
|
|
122
|
-
def create_archive(
|
|
123
|
-
|
|
170
|
+
def create_archive(
|
|
171
|
+
self,
|
|
172
|
+
out: typing.IO,
|
|
173
|
+
size_limit: typing.Optional[int] = None,
|
|
174
|
+
age_limit: typing.Optional[int] = None,
|
|
175
|
+
start_time: typing.Optional[int] = None,
|
|
176
|
+
):
|
|
177
|
+
request = {"Request": "CreateArchive"}
|
|
124
178
|
|
|
125
179
|
if size_limit is not None:
|
|
126
|
-
request.update({
|
|
180
|
+
request.update({"SizeLimit": size_limit})
|
|
127
181
|
|
|
128
182
|
if age_limit is not None:
|
|
129
|
-
request.update({
|
|
183
|
+
request.update({"AgeLimit": age_limit})
|
|
130
184
|
|
|
131
185
|
if start_time is not None:
|
|
132
|
-
request.update({
|
|
186
|
+
request.update({"StartTime": start_time})
|
|
133
187
|
|
|
134
188
|
self.service.send_plist(request)
|
|
135
189
|
|
|
136
|
-
assert
|
|
190
|
+
assert self.service.recvall(1)[0] == 1
|
|
137
191
|
|
|
138
|
-
assert plistlib.loads(self.service.recv_prefixed()).get(
|
|
192
|
+
assert plistlib.loads(self.service.recv_prefixed()).get("Status") == "RequestSuccessful", "Invalid status"
|
|
139
193
|
|
|
140
194
|
while True:
|
|
141
195
|
try:
|
|
142
|
-
assert
|
|
196
|
+
assert self.service.recvall(1)[0] == 3, "invalid magic"
|
|
143
197
|
except ConnectionAbortedError:
|
|
144
198
|
break
|
|
145
|
-
out.write(self.service.recv_prefixed(endianity=
|
|
146
|
-
|
|
147
|
-
def collect(
|
|
148
|
-
|
|
199
|
+
out.write(self.service.recv_prefixed(endianity="<"))
|
|
200
|
+
|
|
201
|
+
def collect(
|
|
202
|
+
self,
|
|
203
|
+
out: str,
|
|
204
|
+
size_limit: typing.Optional[int] = None,
|
|
205
|
+
age_limit: typing.Optional[int] = None,
|
|
206
|
+
start_time: typing.Optional[int] = None,
|
|
207
|
+
) -> None:
|
|
149
208
|
"""
|
|
150
209
|
Collect the system logs into a .logarchive that can be viewed later with tools such as log or Console.
|
|
151
210
|
|
|
@@ -155,28 +214,23 @@ class OsTraceService(LockdownService):
|
|
|
155
214
|
:param start_time: start time of logarchive in unix timestamp
|
|
156
215
|
"""
|
|
157
216
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
158
|
-
file = Path(temp_dir) /
|
|
159
|
-
with open(file,
|
|
217
|
+
file = Path(temp_dir) / "foo.tar"
|
|
218
|
+
with open(file, "wb") as f:
|
|
160
219
|
self.create_archive(f, size_limit=size_limit, age_limit=age_limit, start_time=start_time)
|
|
161
220
|
TarFile(file).extractall(out)
|
|
162
221
|
|
|
163
222
|
def syslog(self, pid=-1) -> typing.Generator[SyslogEntry, None, None]:
|
|
164
|
-
self.service.send_plist({
|
|
223
|
+
self.service.send_plist({"Request": "StartActivity", "MessageFilter": 65535, "Pid": pid, "StreamFlags": 60})
|
|
165
224
|
|
|
166
|
-
length_length, = struct.unpack(
|
|
225
|
+
(length_length,) = struct.unpack("<I", self.service.recvall(4))
|
|
167
226
|
length = int(self.service.recvall(length_length)[::-1].hex(), 16)
|
|
168
227
|
response = plistlib.loads(self.service.recvall(length))
|
|
169
228
|
|
|
170
|
-
if response.get(
|
|
171
|
-
raise PyMobileDevice3Exception(f
|
|
229
|
+
if response.get("Status") != "RequestSuccessful":
|
|
230
|
+
raise PyMobileDevice3Exception(f"got invalid response: {response}")
|
|
172
231
|
|
|
173
232
|
while True:
|
|
174
|
-
assert
|
|
175
|
-
length, = struct.unpack(
|
|
233
|
+
assert self.service.recvall(1) == b"\x02"
|
|
234
|
+
(length,) = struct.unpack("<I", self.service.recvall(4))
|
|
176
235
|
line = self.service.recvall(length)
|
|
177
|
-
|
|
178
|
-
label = None
|
|
179
|
-
if entry.label is not None:
|
|
180
|
-
label = SyslogLabel(subsystem=entry.label.subsystem, category=entry.label.category)
|
|
181
|
-
yield SyslogEntry(pid=entry.pid, timestamp=entry.timestamp, level=SyslogLogLevel(int(entry.level)),
|
|
182
|
-
image_name=entry.image_name, filename=entry.filename, message=entry.message, label=label)
|
|
236
|
+
yield parse_syslog_entry(line)
|