pymobiledevice3 7.0.7__tar.gz → 7.3.0__tar.gz

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.
Files changed (245) hide show
  1. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/PKG-INFO +1 -1
  2. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/_version.py +3 -3
  3. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/accessibility/settings.py +2 -1
  4. pymobiledevice3-7.3.0/pymobiledevice3/cli/developer/debugserver.py +286 -0
  5. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/dvt/__init__.py +30 -26
  6. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/lockdown.py +3 -2
  7. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/usbmux.py +8 -2
  8. pymobiledevice3-7.3.0/pymobiledevice3/services/dvt/instruments/network_monitor.py +158 -0
  9. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/tcp_forwarder.py +1 -1
  10. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/tunneld/server.py +23 -12
  11. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/usbmux.py +40 -23
  12. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3.egg-info/PKG-INFO +1 -1
  13. pymobiledevice3-7.0.7/pymobiledevice3/cli/developer/debugserver.py +0 -244
  14. pymobiledevice3-7.0.7/pymobiledevice3/services/dvt/instruments/network_monitor.py +0 -102
  15. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.gitattributes +0 -0
  16. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/FUNDING.yml +0 -0
  17. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  18. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  19. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  20. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/pull_request_template.md +0 -0
  21. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/workflows/codeql.yml +0 -0
  22. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/workflows/generate-executable.py +0 -0
  23. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/workflows/markdown-lint.yml +0 -0
  24. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/workflows/python-app.yml +0 -0
  25. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/workflows/python-publish.yml +0 -0
  26. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.gitignore +0 -0
  27. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.pre-commit-config.yaml +0 -0
  28. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/CODE_OF_CONDUCT.md +0 -0
  29. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/CONTRIBUTING.md +0 -0
  30. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/LICENSE +0 -0
  31. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/README.md +0 -0
  32. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/example.gif +0 -0
  33. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/markdownlint-config.json +0 -0
  34. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/misc/DTServices-14.2.txt +0 -0
  35. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/misc/DTServices-14.5.txt +0 -0
  36. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/misc/RemoteXPC.md +0 -0
  37. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/misc/plist_sniffer.py +0 -0
  38. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/misc/pyinstaller.md +0 -0
  39. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/misc/remotexpc_sniffer.py +0 -0
  40. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/misc/understanding_idevice_protocol_layers.md +0 -0
  41. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/misc/usbmux_sniff.sh +0 -0
  42. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/__init__.py +0 -0
  43. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/__main__.py +0 -0
  44. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/bonjour.py +0 -0
  45. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/ca.py +0 -0
  46. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/__init__.py +0 -0
  47. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/activation.py +0 -0
  48. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/afc.py +0 -0
  49. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/amfi.py +0 -0
  50. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/apps.py +0 -0
  51. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/backup.py +0 -0
  52. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/bonjour.py +0 -0
  53. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/cli_common.py +0 -0
  54. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/companion_proxy.py +0 -0
  55. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/crash.py +0 -0
  56. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/__init__.py +0 -0
  57. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/accessibility/__init__.py +0 -0
  58. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/arbitration.py +0 -0
  59. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/condition.py +0 -0
  60. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/core_device.py +0 -0
  61. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/dvt/core_profile_session.py +0 -0
  62. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/dvt/simulate_location.py +0 -0
  63. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/dvt/sysmon/__init__.py +0 -0
  64. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/dvt/sysmon/process.py +0 -0
  65. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/fetch_symbols.py +0 -0
  66. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/simulate_location.py +0 -0
  67. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/diagnostics/__init__.py +0 -0
  68. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/diagnostics/battery.py +0 -0
  69. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/idam.py +0 -0
  70. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/mounter.py +0 -0
  71. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/notification.py +0 -0
  72. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/pcap.py +0 -0
  73. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/power_assertion.py +0 -0
  74. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/processes.py +0 -0
  75. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/profile.py +0 -0
  76. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/provision.py +0 -0
  77. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/remote.py +0 -0
  78. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/restore.py +0 -0
  79. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/springboard.py +0 -0
  80. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/syslog.py +0 -0
  81. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/version.py +0 -0
  82. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/webinspector.py +0 -0
  83. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/common.py +0 -0
  84. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/exceptions.py +0 -0
  85. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/irecv.py +0 -0
  86. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/irecv_devices.py +0 -0
  87. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/lockdown.py +0 -0
  88. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/lockdown_service_provider.py +0 -0
  89. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/osu/__init__.py +0 -0
  90. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/osu/os_utils.py +0 -0
  91. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/osu/posix_util.py +0 -0
  92. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/osu/win_util.py +0 -0
  93. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/pair_records.py +0 -0
  94. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/__init__.py +0 -0
  95. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/common.py +0 -0
  96. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/core_device/__init__.py +0 -0
  97. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/core_device/app_service.py +0 -0
  98. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/core_device/core_device_service.py +0 -0
  99. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/core_device/device_info.py +0 -0
  100. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/core_device/diagnostics_service.py +0 -0
  101. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/core_device/file_service.py +0 -0
  102. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/module_imports.py +0 -0
  103. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/remote_service.py +0 -0
  104. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/remote_service_discovery.py +0 -0
  105. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/remotexpc.py +0 -0
  106. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/tunnel_service.py +0 -0
  107. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/utils.py +0 -0
  108. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/xpc_message.py +0 -0
  109. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/__init__.py +0 -0
  110. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/dsc_uuid_map.json +0 -0
  111. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/dsc_uuid_map.py +0 -0
  112. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/firmware_notifications.py +0 -0
  113. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/notifications.txt +0 -0
  114. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/webinspector/element_attribute.js +0 -0
  115. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/webinspector/element_clear.js +0 -0
  116. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/webinspector/enter_fullscreen.js +0 -0
  117. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/webinspector/find_nodes.js +0 -0
  118. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/webinspector/focus.js +0 -0
  119. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/webinspector/get_attribute.js +0 -0
  120. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/webinspector/is_displayed.js +0 -0
  121. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/webinspector/is_editable.js +0 -0
  122. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/webinspector/is_enabled.js +0 -0
  123. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/__init__.py +0 -0
  124. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/asr.py +0 -0
  125. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/base_restore.py +0 -0
  126. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/consts.py +0 -0
  127. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/device.py +0 -0
  128. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/fdr.py +0 -0
  129. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/ftab.py +0 -0
  130. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/img4.py +0 -0
  131. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/mbn.py +0 -0
  132. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/recovery.py +0 -0
  133. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/restore.py +0 -0
  134. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/restore_options.py +0 -0
  135. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/restored_client.py +0 -0
  136. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/tss.py +0 -0
  137. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/service_connection.py +0 -0
  138. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/__init__.py +0 -0
  139. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/accessibilityaudit.py +0 -0
  140. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/afc.py +0 -0
  141. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/amfi.py +0 -0
  142. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/companion.py +0 -0
  143. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/crash_reports.py +0 -0
  144. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/debugserver_applist.py +0 -0
  145. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/device_arbitration.py +0 -0
  146. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/device_link.py +0 -0
  147. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/diagnostics.py +0 -0
  148. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dtfetchsymbols.py +0 -0
  149. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/__init__.py +0 -0
  150. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/dvt_secure_socket_proxy.py +0 -0
  151. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/dvt_testmanaged_proxy.py +0 -0
  152. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/__init__.py +0 -0
  153. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/activity_trace_tap.py +0 -0
  154. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/application_listing.py +0 -0
  155. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/condition_inducer.py +0 -0
  156. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/core_profile_session_tap.py +0 -0
  157. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/device_info.py +0 -0
  158. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/energy_monitor.py +0 -0
  159. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/graphics.py +0 -0
  160. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/location_simulation.py +0 -0
  161. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/location_simulation_base.py +0 -0
  162. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/notifications.py +0 -0
  163. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/process_control.py +0 -0
  164. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/screenshot.py +0 -0
  165. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/sysmontap.py +0 -0
  166. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/testmanaged/xcuitest.py +0 -0
  167. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/file_relay.py +0 -0
  168. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/heartbeat.py +0 -0
  169. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/house_arrest.py +0 -0
  170. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/idam.py +0 -0
  171. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/installation_proxy.py +0 -0
  172. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/lockdown_service.py +0 -0
  173. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/misagent.py +0 -0
  174. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/mobile_activation.py +0 -0
  175. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/mobile_config.py +0 -0
  176. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/mobile_image_mounter.py +0 -0
  177. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/mobilebackup2.py +0 -0
  178. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/notification_proxy.py +0 -0
  179. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/os_trace.py +0 -0
  180. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/pcapd.py +0 -0
  181. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/power_assertion.py +0 -0
  182. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/preboard.py +0 -0
  183. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/remote_fetch_symbols.py +0 -0
  184. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/remote_server.py +0 -0
  185. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/restore_service.py +0 -0
  186. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/screenshot.py +0 -0
  187. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/simulate_location.py +0 -0
  188. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/springboard.py +0 -0
  189. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/syslog.py +0 -0
  190. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/__init__.py +0 -0
  191. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/alert.py +0 -0
  192. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/automation_session.py +0 -0
  193. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/cdp_screencast.py +0 -0
  194. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/cdp_server.py +0 -0
  195. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/cdp_target.py +0 -0
  196. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/driver.py +0 -0
  197. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/element.py +0 -0
  198. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/inspector_session.py +0 -0
  199. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/selenium_api.py +0 -0
  200. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/session_protocol.py +0 -0
  201. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/switch_to.py +0 -0
  202. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/webinspector.py +0 -0
  203. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/tunneld/__init__.py +0 -0
  204. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/tunneld/api.py +0 -0
  205. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/utils.py +0 -0
  206. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3.egg-info/SOURCES.txt +0 -0
  207. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3.egg-info/dependency_links.txt +0 -0
  208. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3.egg-info/entry_points.txt +0 -0
  209. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3.egg-info/requires.txt +0 -0
  210. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3.egg-info/top_level.txt +0 -0
  211. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pyproject.toml +0 -0
  212. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pytest.ini +0 -0
  213. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/requirements.txt +0 -0
  214. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/setup.cfg +0 -0
  215. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/__init__.py +0 -0
  216. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/cli/__init__.py +0 -0
  217. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/cli/test_cli.py +0 -0
  218. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/conftest.py +0 -0
  219. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/__init__.py +0 -0
  220. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/instruments/__init__.py +0 -0
  221. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/instruments/test_core_profile_session.py +0 -0
  222. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/instruments/test_dvt_secure_socket_proxy.py +0 -0
  223. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/instruments/test_fetch_symbols.py +0 -0
  224. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/instruments/test_location.py +0 -0
  225. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/instruments/test_screenshot.py +0 -0
  226. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_accessibility.py +0 -0
  227. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_afc.py +0 -0
  228. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_apps.py +0 -0
  229. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_backup2.py +0 -0
  230. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_bonjour.py +0 -0
  231. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_crash_reports.py +0 -0
  232. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_house_arrest.py +0 -0
  233. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_list_devices.py +0 -0
  234. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_lockdown.py +0 -0
  235. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_pcapd.py +0 -0
  236. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_springboard_services_relay.py +0 -0
  237. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_start_tunnel.py +0 -0
  238. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_syslog_relay.py +0 -0
  239. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_tcp_forwarder.py +0 -0
  240. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_web_protocol/__init__.py +0 -0
  241. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_web_protocol/common.py +0 -0
  242. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_web_protocol/conftest.py +0 -0
  243. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_web_protocol/test_driver.py +0 -0
  244. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_web_protocol/test_element.py +0 -0
  245. {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_webinspector.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pymobiledevice3
3
- Version: 7.0.7
3
+ Version: 7.3.0
4
4
  Summary: Pure python3 implementation for working with iDevices (iPhone, etc...)
5
5
  Author-email: doronz88 <doron88@gmail.com>, matan <matan1008@gmail.com>
6
6
  Maintainer-email: doronz88 <doron88@gmail.com>, matan <matan1008@gmail.com>
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '7.0.7'
32
- __version_tuple__ = version_tuple = (7, 0, 7)
31
+ __version__ = version = '7.3.0'
32
+ __version_tuple__ = version_tuple = (7, 3, 0)
33
33
 
34
- __commit_id__ = commit_id = 'g2e159e580'
34
+ __commit_id__ = commit_id = 'gdbcb99cc3'
@@ -1,3 +1,4 @@
1
+ import ast
1
2
  import logging
2
3
 
3
4
  from typer_injector import InjectingTyper
@@ -30,7 +31,7 @@ def accessibility_settings_set(service_provider: ServiceProviderDep, setting: st
30
31
  in order to list all available use the "show" command
31
32
  """
32
33
  service = AccessibilityAudit(service_provider)
33
- service.set_setting(setting, eval(value))
34
+ service.set_setting(setting, ast.literal_eval(value))
34
35
  OSUTILS.wait_return()
35
36
 
36
37
 
@@ -0,0 +1,286 @@
1
+ import logging
2
+ import os
3
+ import plistlib
4
+ import signal
5
+ import struct
6
+ import subprocess
7
+ import sys
8
+ from pathlib import Path
9
+ from tempfile import TemporaryDirectory
10
+ from typing import Annotated, Optional
11
+ from zipfile import ZipFile
12
+
13
+ import typer
14
+ from packaging.version import Version
15
+ from plumbum import local
16
+ from typer_injector import InjectingTyper
17
+
18
+ from pymobiledevice3.cli.cli_common import RSDServiceProviderDep, ServiceProviderDep, print_json
19
+ from pymobiledevice3.exceptions import RSDRequiredError
20
+ from pymobiledevice3.lockdown import create_using_usbmux
21
+ from pymobiledevice3.remote.remote_service_discovery import RemoteServiceDiscoveryService
22
+ from pymobiledevice3.services.debugserver_applist import DebugServerAppList
23
+ from pymobiledevice3.services.installation_proxy import InstallationProxyService
24
+ from pymobiledevice3.tcp_forwarder import LockdownTcpForwarder
25
+
26
+ DEBUGSERVER_CONNECTION_STEPS = """
27
+ Follow the following connections steps from LLDB:
28
+
29
+ (lldb) platform select remote-ios
30
+ (lldb) target create /path/to/local/application.app
31
+ (lldb) script lldb.target.module[0].SetPlatformFileSpec(lldb.SBFileSpec('/private/var/containers/Bundle/Application/<APP-UUID>/application.app'))
32
+ (lldb) process connect connect://[{host}]:{port} <-- ACTUAL CONNECTION DETAILS!
33
+ (lldb) process launch
34
+ """
35
+
36
+
37
+ logger = logging.getLogger(__name__)
38
+
39
+
40
+ cli = InjectingTyper(
41
+ name="debugserver",
42
+ help="Start and drive debugserver sessions (RSD for iOS 17+, usbmux for older).",
43
+ no_args_is_help=True,
44
+ )
45
+
46
+
47
+ @cli.command("applist")
48
+ def debugserver_applist(service_provider: ServiceProviderDep) -> None:
49
+ """Print the debugserver applist XML for the device."""
50
+ print_json(DebugServerAppList(service_provider).get())
51
+
52
+
53
+ @cli.command("start-server")
54
+ def debugserver_start_server(
55
+ service_provider: ServiceProviderDep,
56
+ local_port: Optional[int] = None,
57
+ host: Annotated[
58
+ str,
59
+ typer.Option(help="Address to bind the local port to."),
60
+ ] = "127.0.0.1",
61
+ ) -> None:
62
+ """
63
+ Start debugserver and print the LLDB connect string.
64
+
65
+ - For iOS < 17, you must forward to a local port (--local-port).
66
+ - For iOS >= 17, if connected over RSD, the remote host:port is printed for LLDB.
67
+ Connect quickly with your own LLDB client using the printed steps.
68
+ """
69
+
70
+ if Version(service_provider.product_version) < Version("17.0"):
71
+ service_name = "com.apple.debugserver.DVTSecureSocketProxy"
72
+ else:
73
+ service_name = "com.apple.internal.dt.remote.debugproxy"
74
+
75
+ if local_port is not None:
76
+ print(DEBUGSERVER_CONNECTION_STEPS.format(host=host, port=local_port))
77
+ print("Started port forwarding. Press Ctrl-C to close this shell when done")
78
+ sys.stdout.flush()
79
+ LockdownTcpForwarder(service_provider, local_port, service_name).start(address=host)
80
+ elif Version(service_provider.product_version) >= Version("17.0"):
81
+ if not isinstance(service_provider, RemoteServiceDiscoveryService):
82
+ raise RSDRequiredError(service_provider.identifier)
83
+ debugserver_port = service_provider.get_service_port(service_name)
84
+ print(DEBUGSERVER_CONNECTION_STEPS.format(host=service_provider.service.address[0], port=debugserver_port))
85
+ else:
86
+ print("local_port is required for iOS < 17.0")
87
+
88
+
89
+ @cli.command("lldb")
90
+ def debugserver_lldb(
91
+ service_provider: RSDServiceProviderDep,
92
+ project_or_ipa_path: Annotated[
93
+ Path,
94
+ typer.Argument(exists=True, file_okay=True, dir_okay=True),
95
+ ],
96
+ configuration: Annotated[
97
+ str,
98
+ typer.Option(help="Build configuration to invoke (e.g., Debug or Release)."),
99
+ ] = "Debug",
100
+ lldb_command: Annotated[
101
+ str,
102
+ typer.Option(help="Path to the lldb executable to run."),
103
+ ] = "lldb",
104
+ launch: Annotated[
105
+ bool,
106
+ typer.Option(help="Automatically launch the app after attaching."),
107
+ ] = False,
108
+ breakpoints: Annotated[
109
+ Optional[list[str]],
110
+ typer.Option("--break", "-b", help="Add multiple startup breakpoints"),
111
+ ] = None,
112
+ user_commands: Annotated[
113
+ Optional[list[str]],
114
+ typer.Option("--command", "-c", help="Additional commands to run at startup"),
115
+ ] = None,
116
+ ) -> None:
117
+ """
118
+ Automate lldb launch for a given xcodeproj or IPA.
119
+
120
+ \b
121
+ This will:
122
+ - Build the given xcodeproj (if provided)
123
+ - Extract the given IPA (if provided)
124
+ - Install it
125
+ - Start a debugserver attached to it
126
+ - Place breakpoints if given any
127
+ - Launch the application if requested
128
+ - Execute any additional commands if requested
129
+ - Switch to lldb shell
130
+ """
131
+ if Version(service_provider.product_version) < Version("17.0"):
132
+ logger.error("lldb is only supported on iOS >= 17.0")
133
+ return
134
+
135
+ commands = []
136
+ temp_dir = None
137
+ local_app = None
138
+ install_source = None
139
+
140
+ if project_or_ipa_path.suffix == ".xcodeproj":
141
+ with local.cwd(project_or_ipa_path.parent):
142
+ logger.info(f"Building {project_or_ipa_path} for {configuration} configuration")
143
+ local["xcodebuild"]["-project", str(project_or_ipa_path), "-configuration", configuration, "build"]()
144
+ app_candidates = [app for app in Path("build").rglob("*.app") if (app / "Info.plist").exists()]
145
+ if not app_candidates:
146
+ logger.error("No built .app with Info.plist found under build/.")
147
+ return
148
+ app_candidates.sort(key=lambda p: p.stat().st_mtime, reverse=True)
149
+ local_app = app_candidates[0].absolute()
150
+ install_source = local_app
151
+ elif project_or_ipa_path.suffix == ".ipa":
152
+ temp_dir = TemporaryDirectory()
153
+ with ZipFile(project_or_ipa_path, "r") as ipa_zip:
154
+ ipa_zip.extractall(temp_dir.name)
155
+ payload_dir = Path(temp_dir.name) / "Payload"
156
+ apps = list(payload_dir.glob("*.app"))
157
+ if not apps:
158
+ logger.error("No .app bundle found in IPA Payload.")
159
+ temp_dir.cleanup()
160
+ return
161
+ if len(apps) > 1:
162
+ logger.error("Multiple .app bundles found in IPA Payload; please provide a single-app IPA.")
163
+ temp_dir.cleanup()
164
+ return
165
+ local_app = apps[0].absolute()
166
+ install_source = project_or_ipa_path
167
+ else:
168
+ logger.error("Expected an .xcodeproj directory or an .ipa file.")
169
+ return
170
+
171
+ logger.info(f"Using app: {local_app}")
172
+
173
+ info_plist_path = local_app / "Info.plist"
174
+ info_plist = plistlib.loads(info_plist_path.read_bytes())
175
+ bundle_identifier = info_plist["CFBundleIdentifier"]
176
+ logger.info(f"Bundle identifier: {bundle_identifier}")
177
+
178
+ commands.append("platform select remote-ios")
179
+ commands.append(f'target create "{local_app.absolute()}"')
180
+
181
+ with InstallationProxyService(create_using_usbmux()) as installation_proxy:
182
+ logger.info("Installing app")
183
+ installation_proxy.install_from_local(install_source)
184
+ remote_path = installation_proxy.get_apps(bundle_identifiers=[bundle_identifier])[bundle_identifier]["Path"]
185
+ logger.info(f"Remote path: {remote_path}")
186
+ commands.append(f'script lldb.target.module[0].SetPlatformFileSpec(lldb.SBFileSpec("{remote_path}"))')
187
+
188
+ debugserver_port = service_provider.get_service_port("com.apple.internal.dt.remote.debugproxy")
189
+
190
+ # Add connection and launch commands
191
+ commands.append(f"process connect connect://[{service_provider.service.address[0]}]:{debugserver_port}")
192
+
193
+ if breakpoints:
194
+ for bp in breakpoints:
195
+ commands.append(f'breakpoint set -n "{bp}"')
196
+
197
+ if launch:
198
+ commands.append("process launch")
199
+
200
+ if user_commands:
201
+ # Add user commands
202
+ commands += user_commands
203
+
204
+ logger.info("Starting lldb with automated setup and connection")
205
+
206
+ # Works only on unix-based systems, so keep these imports here
207
+ import fcntl
208
+ import pty
209
+ import select as select_module
210
+ import termios
211
+ import tty
212
+
213
+ master, slave = pty.openpty()
214
+
215
+ process = None # Initialize process variable for signal handler
216
+
217
+ # Copy terminal size from the current terminal to PTY
218
+ def resize_pty() -> None:
219
+ """Update PTY size to match current terminal size"""
220
+ size = struct.unpack(
221
+ "HHHH", fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, struct.pack("HHHH", 0, 0, 0, 0))
222
+ )
223
+ fcntl.ioctl(master, termios.TIOCSWINSZ, struct.pack("HHHH", *size))
224
+ # Send SIGWINCH to the child process to notify it of the resize
225
+ if process is not None and process.poll() is None:
226
+ process.send_signal(signal.SIGWINCH)
227
+
228
+ # Initial resize
229
+ resize_pty()
230
+
231
+ # Set up signal handler for window resize
232
+ def handle_sigwinch(signum, frame):
233
+ resize_pty()
234
+
235
+ old_sigwinch_handler = signal.signal(signal.SIGWINCH, handle_sigwinch)
236
+
237
+ # Save original terminal settings
238
+ old_tty = termios.tcgetattr(sys.stdin)
239
+
240
+ try:
241
+ # Set TERM environment variable to enable colors
242
+ env = os.environ.copy()
243
+ env["TERM"] = os.environ.get("TERM", "xterm-256color")
244
+
245
+ process = subprocess.Popen([lldb_command], stdin=slave, stdout=slave, stderr=slave, env=env)
246
+ os.close(slave)
247
+
248
+ # Put terminal in raw mode for proper interaction
249
+ tty.setraw(sys.stdin.fileno())
250
+ # Send all commands through stdin
251
+ for command in commands:
252
+ os.write(master, (command + "\n").encode())
253
+
254
+ # Now redirect stdin from the terminal to lldb so user can interact
255
+ while True:
256
+ rlist, _, _ = select_module.select([sys.stdin, master], [], [])
257
+
258
+ if sys.stdin in rlist:
259
+ # User typed something
260
+ data = os.read(sys.stdin.fileno(), 1024)
261
+ if not data:
262
+ break
263
+ os.write(master, data)
264
+
265
+ if master in rlist:
266
+ # lldb has output
267
+ try:
268
+ data = os.read(master, 1024)
269
+ if not data:
270
+ break
271
+ os.write(sys.stdout.fileno(), data)
272
+ except OSError:
273
+ break
274
+ except (KeyboardInterrupt, OSError):
275
+ pass
276
+ finally:
277
+ # Restore terminal settings
278
+ termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty)
279
+ # Restore original SIGWINCH handler
280
+ signal.signal(signal.SIGWINCH, old_sigwinch_handler)
281
+ os.close(master)
282
+ if process is not None:
283
+ process.terminate()
284
+ process.wait()
285
+ if temp_dir is not None:
286
+ temp_dir.cleanup()
@@ -166,46 +166,49 @@ def process_id_for_bundle_id(service_provider: ServiceProviderDep, app_bundle_id
166
166
 
167
167
 
168
168
  def get_matching_processes(
169
- service_provider: ServiceProviderDep,
169
+ device_info: DeviceInfo,
170
170
  name: Optional[str] = None,
171
171
  bundle_identifier: Optional[str] = None,
172
172
  ) -> list[MatchedProcessByPid]:
173
173
  result: list[MatchedProcessByPid] = []
174
- with DvtSecureSocketProxyService(lockdown=service_provider) as dvt:
175
- device_info = DeviceInfo(dvt)
176
- for process in device_info.proclist():
177
- current_name = process["name"]
178
- current_bundle_identifier = process.get("bundleIdentifier", "")
179
- pid = process["pid"]
180
- if (bundle_identifier is not None and bundle_identifier in current_bundle_identifier) or (
181
- name is not None and name in current_name
182
- ):
183
- result.append(MatchedProcessByPid(name=current_name, pid=pid))
174
+ for process in device_info.proclist():
175
+ current_name = process["name"]
176
+ current_bundle_identifier = process.get("bundleIdentifier", "")
177
+ pid = process["pid"]
178
+ if (bundle_identifier is not None and bundle_identifier in current_bundle_identifier) or (
179
+ name is not None and name in current_name
180
+ ):
181
+ result.append(MatchedProcessByPid(name=current_name, pid=pid))
184
182
  return result
185
183
 
186
184
 
187
185
  @cli.command("pkill")
188
186
  def pkill(
189
187
  service_provider: ServiceProviderDep,
190
- expression: str,
188
+ expressions: Annotated[
189
+ list[str],
190
+ typer.Argument(help="One or more process-name (or bundle id) expressions to match."),
191
+ ],
191
192
  bundle: Annotated[
192
193
  bool,
193
- typer.Option(help="Treat given expression as a bundle-identifier instead of a process name"),
194
+ typer.Option(help="Treat given expressions as bundle-identifiers instead of process names"),
194
195
  ] = False,
195
196
  ) -> None:
196
- """Kill all processes containing `expression` in their name."""
197
- matching_name = expression if not bundle else None
198
- matching_bundle_identifier = expression if bundle else None
199
- matching_processes = get_matching_processes(
200
- service_provider, name=matching_name, bundle_identifier=matching_bundle_identifier
201
- )
202
-
197
+ """Kill all processes containing each expression in their name."""
203
198
  with DvtSecureSocketProxyService(lockdown=service_provider) as dvt:
199
+ device_info = DeviceInfo(dvt)
204
200
  process_control = ProcessControl(dvt)
205
201
 
206
- for process in matching_processes:
207
- logger.info(f"killing {process.name}({process.pid})")
208
- process_control.kill(process.pid)
202
+ for expression in expressions:
203
+ matching_name = expression if not bundle else None
204
+ matching_bundle_identifier = expression if bundle else None
205
+ matching_processes = get_matching_processes(
206
+ device_info, name=matching_name, bundle_identifier=matching_bundle_identifier
207
+ )
208
+
209
+ for process in matching_processes:
210
+ logger.info(f"Killing {process.name}({process.pid})")
211
+ process_control.kill(process.pid)
209
212
 
210
213
 
211
214
  @cli.command("launch")
@@ -301,9 +304,10 @@ def netstat(service_provider: ServiceProviderDep) -> None:
301
304
  with DvtSecureSocketProxyService(lockdown=service_provider) as dvt, NetworkMonitor(dvt) as monitor:
302
305
  for event in monitor:
303
306
  if isinstance(event, ConnectionDetectionEvent):
304
- local_host, local_port = event.local_address.split(":")
305
- remote_host, remote_port = event.local_address.split(":")
306
- logger.info(f"Connection detected: {local_host}:{local_port} -> {remote_host}:{remote_port}")
307
+ logger.info(
308
+ f"Connection detected: {event.local_address.data.address}:{event.local_address.port} -> "
309
+ f"{event.remote_address.data.address}:{event.remote_address.port}"
310
+ )
307
311
 
308
312
 
309
313
  @cli.command("screenshot")
@@ -1,3 +1,4 @@
1
+ import ast
1
2
  import asyncio
2
3
  import logging
3
4
  import plistlib
@@ -61,8 +62,8 @@ def lockdown_set(
61
62
  domain: Optional[str] = None,
62
63
  key: Optional[str] = None,
63
64
  ) -> None:
64
- """set a lockdown value using python's eval()"""
65
- print_json(service_provider.set_value(value=eval(value), domain=domain, key=key))
65
+ """set a lockdown value using python's ast.literal_eval()"""
66
+ print_json(service_provider.set_value(value=ast.literal_eval(value), domain=domain, key=key))
66
67
 
67
68
 
68
69
  @cli.command("remove")
@@ -43,6 +43,10 @@ def usbmux_forward(
43
43
  Optional[str],
44
44
  typer.Option(help="Device serial/UDID to forward traffic to."),
45
45
  ] = None,
46
+ host: Annotated[
47
+ str,
48
+ typer.Option(help="Address to bind the local port to."),
49
+ ] = "127.0.0.1",
46
50
  daemonize: Annotated[
47
51
  bool,
48
52
  typer.Option("--daemonize", "-d", help="Run the forwarder in the background."),
@@ -58,10 +62,12 @@ def usbmux_forward(
58
62
  raise NotImplementedError("daemonizing is only supported on unix platforms") from e
59
63
 
60
64
  with tempfile.NamedTemporaryFile("wt") as pid_file:
61
- daemon = Daemonize(app=f"forwarder {src_port}->{dst_port}", pid=pid_file.name, action=forwarder.start)
65
+ daemon = Daemonize(
66
+ app=f"forwarder {src_port}->{dst_port}", pid=pid_file.name, action=lambda: forwarder.start(address=host)
67
+ )
62
68
  daemon.start()
63
69
  else:
64
- forwarder.start()
70
+ forwarder.start(address=host)
65
71
 
66
72
 
67
73
  @cli.command("list")
@@ -0,0 +1,158 @@
1
+ import ipaddress
2
+ import logging
3
+ from collections.abc import Iterator
4
+ from dataclasses import dataclass
5
+ from typing import Union
6
+
7
+ from construct import Adapter, Bytes, Int8ul, Int16ub, Int32ul, Switch, this
8
+ from construct_typed import DataclassMixin, TStruct, csfield
9
+
10
+ from pymobiledevice3.services.dvt.dvt_secure_socket_proxy import DvtSecureSocketProxyService
11
+
12
+
13
+ class IpAddressAdapter(Adapter):
14
+ """Decode raw address bytes into ipaddress objects."""
15
+
16
+ def _decode(self, obj, context, path):
17
+ return ipaddress.ip_address(obj)
18
+
19
+
20
+ @dataclass
21
+ class AddressV6(DataclassMixin):
22
+ """IPv6 payload for a socket address."""
23
+
24
+ flow_info: int = csfield(Int32ul)
25
+ address: ipaddress.IPv6Address = csfield(IpAddressAdapter(Bytes(16)))
26
+ scope_id: int = csfield(Int32ul)
27
+
28
+
29
+ @dataclass
30
+ class AddressV4(DataclassMixin):
31
+ """IPv4 payload for a socket address."""
32
+
33
+ address: ipaddress.IPv4Address = csfield(IpAddressAdapter(Bytes(4)))
34
+ _zero: bytes = csfield(Bytes(8))
35
+
36
+
37
+ @dataclass
38
+ class SocketAddress(DataclassMixin):
39
+ """Parsed socket address with family-specific payload."""
40
+
41
+ length: int = csfield(Int8ul)
42
+ family: int = csfield(Int8ul)
43
+ port: int = csfield(Int16ub)
44
+ data: Union[AddressV4, AddressV6] = csfield(
45
+ Switch(
46
+ this.length,
47
+ {
48
+ 0x1C: TStruct(AddressV6),
49
+ 0x10: TStruct(AddressV4),
50
+ },
51
+ )
52
+ )
53
+
54
+
55
+ address_t = TStruct(SocketAddress)
56
+
57
+ MESSAGE_TYPE_INTERFACE_DETECTION = 0
58
+ MESSAGE_TYPE_CONNECTION_DETECTION = 1
59
+ MESSAGE_TYPE_CONNECTION_UPDATE = 2
60
+
61
+
62
+ @dataclass
63
+ class InterfaceDetectionEvent:
64
+ """Interface detection event emitted by Instruments."""
65
+
66
+ interface_index: int
67
+ name: str
68
+
69
+
70
+ @dataclass
71
+ class ConnectionDetectionEvent:
72
+ """Connection detection event emitted by Instruments."""
73
+
74
+ local_address: SocketAddress
75
+ remote_address: SocketAddress
76
+ interface_index: int
77
+ pid: int
78
+ recv_buffer_size: int
79
+ recv_buffer_used: int
80
+ serial_number: int
81
+ kind: int
82
+
83
+
84
+ @dataclass
85
+ class ConnectionUpdateEvent:
86
+ """Connection update event emitted by Instruments."""
87
+
88
+ rx_packets: int
89
+ rx_bytes: int
90
+ tx_packets: int
91
+ tx_bytes: int
92
+ rx_dups: int
93
+ rx000: int
94
+ tx_retx: int
95
+ min_rtt: int
96
+ avg_rtt: int
97
+ connection_serial: int
98
+ time: int
99
+
100
+
101
+ NetworkMonitorEvent = Union[InterfaceDetectionEvent, ConnectionDetectionEvent, ConnectionUpdateEvent]
102
+
103
+
104
+ class NetworkMonitor:
105
+ """Iterate over network monitoring events from the Instruments service."""
106
+
107
+ IDENTIFIER = "com.apple.instruments.server.services.networking"
108
+
109
+ def __init__(self, dvt: DvtSecureSocketProxyService):
110
+ self.logger = logging.getLogger(__name__)
111
+ self._channel = dvt.make_channel(self.IDENTIFIER)
112
+
113
+ def __enter__(self) -> "NetworkMonitor":
114
+ self._channel.startMonitoring(expects_reply=False)
115
+ return self
116
+
117
+ def __exit__(self, exc_type, exc_val, exc_tb) -> None:
118
+ self._channel.stopMonitoring()
119
+
120
+ def __iter__(self) -> Iterator[NetworkMonitorEvent]:
121
+ """Yield network events as they arrive from the service."""
122
+
123
+ while True:
124
+ message = self._channel.receive_plist()
125
+
126
+ event = None
127
+
128
+ if message is None:
129
+ continue
130
+
131
+ if message[0] == MESSAGE_TYPE_INTERFACE_DETECTION:
132
+ event = InterfaceDetectionEvent(*message[1])
133
+ elif message[0] == MESSAGE_TYPE_CONNECTION_DETECTION:
134
+ (
135
+ local_address,
136
+ remote_address,
137
+ interface_index,
138
+ pid,
139
+ recv_buffer_size,
140
+ recv_buffer_used,
141
+ serial_number,
142
+ kind,
143
+ ) = message[1]
144
+ event = ConnectionDetectionEvent(
145
+ local_address=address_t.parse(local_address),
146
+ remote_address=address_t.parse(remote_address),
147
+ interface_index=interface_index,
148
+ pid=pid,
149
+ recv_buffer_size=recv_buffer_size,
150
+ recv_buffer_used=recv_buffer_used,
151
+ serial_number=serial_number,
152
+ kind=kind,
153
+ )
154
+ elif message[0] == MESSAGE_TYPE_CONNECTION_UPDATE:
155
+ event = ConnectionUpdateEvent(*message[1])
156
+ else:
157
+ self.logger.warning(f"unsupported event type: {message[0]}")
158
+ yield event
@@ -38,7 +38,7 @@ class TcpForwarderBase:
38
38
  # socket to its remote socket and vice versa
39
39
  self.connections = {}
40
40
 
41
- def start(self, address="0.0.0.0"):
41
+ def start(self, address="127.0.0.1"):
42
42
  """forward each connection from given local machine port to remote device port"""
43
43
  # create local tcp server socket
44
44
  self.server_socket = socket.socket()
@@ -191,10 +191,16 @@ class TunneldCore:
191
191
 
192
192
  @asyncio_print_traceback
193
193
  async def monitor_usbmux_task(self) -> None:
194
- try:
195
- while True:
196
- try:
197
- for mux_device in usbmux.list_devices():
194
+ while True:
195
+ mux = None
196
+ try:
197
+ mux = usbmux.create_mux()
198
+ mux.listen()
199
+
200
+ while True:
201
+ await asyncio.to_thread(mux.receive_device_state_update)
202
+
203
+ for mux_device in mux.devices:
198
204
  task_identifier = f"usbmux-{mux_device.serial}-{mux_device.connection_type}"
199
205
  if self.tunnel_exists_for_udid(mux_device.serial):
200
206
  # Skip if already established a tunnel for this udid
@@ -227,14 +233,19 @@ class TunneldCore:
227
233
  name=f"start-tunnel-task-{task_identifier}",
228
234
  ),
229
235
  )
230
- except ConnectionFailedToUsbmuxdError:
231
- # This is exception is expected to occur repeatedly on linux running usbmuxd
232
- # as long as there isn't any physical iDevice connected
233
- logger.debug("failed to connect to usbmux. waiting for it to restart")
234
- finally:
235
- await asyncio.sleep(USBMUX_INTERVAL)
236
- except asyncio.CancelledError:
237
- pass
236
+ except (BlockingIOError, StreamError, OSError) as e:
237
+ # Connection lost - will reconnect on next iteration
238
+ logger.debug(f"usbmux connection error: {e}, reconnecting...")
239
+ except ConnectionFailedToUsbmuxdError:
240
+ # This is exception is expected to occur repeatedly on linux running usbmuxd
241
+ # as long as there isn't any physical iDevice connected
242
+ logger.debug("failed to connect to usbmux. waiting for it to restart")
243
+ await asyncio.sleep(USBMUX_INTERVAL)
244
+ except asyncio.CancelledError:
245
+ break
246
+ finally:
247
+ if mux is not None:
248
+ mux.close()
238
249
 
239
250
  @asyncio_print_traceback
240
251
  async def monitor_mobdev2_task(self) -> None: