23
23
import com .sun .jna .Platform ;
24
24
import com .sun .jna .Pointer ;
25
25
import com .sun .jna .ptr .IntByReference ;
26
+ import com .sun .jna .ptr .LongByReference ;
26
27
import com .sun .jna .ptr .PointerByReference ;
27
28
import javafx .concurrent .Task ;
28
29
import javafx .scene .control .ButtonType ;
36
37
public class LibimobiledeviceUtil {
37
38
38
39
public static long getECID () throws LibimobiledeviceException {
39
- return Long . parseLong ( getKeyFromConnectedDevice ("UniqueChipID" , PlistType . INTEGER ));
40
+ return getPlistLong ( getLockdownValuePlist ("UniqueChipID" ));
40
41
}
41
42
42
43
public static String getDeviceModelIdentifier () throws LibimobiledeviceException {
43
- return getKeyFromConnectedDevice ( "ProductType" , PlistType . STRING );
44
+ return getPlistString ( getLockdownValuePlist ( "ProductType" ) );
44
45
}
45
46
46
47
public static String getBoardConfig () throws LibimobiledeviceException {
47
- return getKeyFromConnectedDevice ( "HardwareModel" , PlistType . STRING );
48
+ return getPlistString ( getLockdownValuePlist ( "HardwareModel" ) );
48
49
}
49
50
50
51
public static String getApNonceNormalMode () throws LibimobiledeviceException {
51
- return LibimobiledeviceUtil . plistDataToString (LibimobiledeviceUtil .getMobileGestaltKey ("ApNonce" ), ByteOrder .BIG_ENDIAN );
52
+ return plistDataToHexString (LibimobiledeviceUtil .getLockdownValuePlist ("ApNonce" ), ByteOrder .BIG_ENDIAN );
52
53
}
53
54
54
55
public static String getGenerator () throws LibimobiledeviceException {
55
- return "0x" + LibimobiledeviceUtil . plistDataToString ( LibimobiledeviceUtil . getMobileGestaltKey ("BootNonce" ), ByteOrder .LITTLE_ENDIAN );
56
+ return "0x" + plistDataToHexString ( getLockdownValuePlist ("BootNonce" ), ByteOrder .LITTLE_ENDIAN );
56
57
}
57
58
58
59
public static void exitRecovery (Pointer irecvClient ) throws LibimobiledeviceException {
@@ -135,17 +136,17 @@ protected Void call() throws LibimobiledeviceException {
135
136
}
136
137
throwIfNeeded (errorCode , ErrorCodeType .lockdownd_error );
137
138
138
- PointerByReference service = new PointerByReference ();
139
+ PointerByReference plist = new PointerByReference ();
139
140
// don't reset timeout
140
141
errorCode = -17 ;
141
142
while (errorCode == -17 && System .currentTimeMillis () < endTime ) {
142
143
if (!sleep (1000 )) {
143
144
return null ;
144
145
}
145
- errorCode = lockdownd_start_service (lockdown .getValue (), "com.apple.mobile.diagnostics_relay" , service );
146
+ errorCode = lockdownd_get_value (lockdown .getValue (), Pointer . NULL , "BootNonce" , plist );
146
147
}
147
148
if (errorCode == 0 ) {
148
- lockdownd_service_descriptor_free ( service .getValue ());
149
+ Libplist . free ( plist .getValue ());
149
150
}
150
151
lockdownd_client_free (lockdown .getValue ());
151
152
idevice_free (device .getValue ());
@@ -201,45 +202,10 @@ private static String getApnonce(Pointer irecv_client) {
201
202
return Utils .bytesToHex (apnonceBytes , ByteOrder .BIG_ENDIAN );
202
203
}
203
204
204
- private static String getKeyFromConnectedDevice (String key , PlistType plistType ) throws LibimobiledeviceException {
205
- if (plistType == null ) {
206
- plistType = PlistType .STRING ;
207
- }
208
- if (key == null ) {
209
- key = "" ;
210
- }
211
-
212
- Pointer client = lockdowndClientFromConnectedDevice ();
213
- PointerByReference plist_value = new PointerByReference ();
214
- int lockdowndGetValueErrorCode = lockdownd_get_value (client , Pointer .NULL , key , plist_value );
215
- if (lockdowndGetValueErrorCode == -8 ) {
216
- // try again, and if it doesn't work, show an error to the user + throw an exception
217
- // it always works the second time
218
- lockdownd_client_free (client );
219
- client = lockdowndClientFromConnectedDevice ();
220
- throwIfNeeded (lockdownd_get_value (client , Pointer .NULL , key , plist_value ), ErrorCodeType .lockdownd_error );
221
- } else {
222
- throwIfNeeded (lockdowndGetValueErrorCode , ErrorCodeType .lockdownd_error );
223
- }
224
- lockdownd_client_free (client );
225
- if (plistType .equals (PlistType .INTEGER )) {
226
- PointerByReference xml_doc = new PointerByReference ();
227
- Libplist .toXml (plist_value .getValue (), xml_doc , new PointerByReference ());
228
- Libplist .free (plist_value .getValue ());
229
- String toReturn = xml_doc .getValue ().getString (0 , "UTF-8" );
230
- return toReturn .substring (toReturn .indexOf ("<integer>" ) + "<integer>" .length (), toReturn .indexOf ("</integer>" ));
231
- } else {
232
- PointerByReference toReturn = new PointerByReference ();
233
- Libplist .getStringVal (plist_value .getValue (), toReturn );
234
- Libplist .free (plist_value .getValue ());
235
- return toReturn .getValue ().getString (0 , "UTF-8" );
236
- }
237
- }
238
-
239
205
/**
240
206
* Returns a plist with the root element being the requested item.
241
207
* <p>
242
- * It will look something like this:
208
+ * It will look something like this (might have different type) :
243
209
* <pre>
244
210
* {@code
245
211
* <?xml version="1.0" encoding="UTF-8"?>
@@ -252,34 +218,25 @@ private static String getKeyFromConnectedDevice(String key, PlistType plistType)
252
218
* }
253
219
* </pre>
254
220
*/
255
- private static Pointer getMobileGestaltKey (String key ) throws LibimobiledeviceException {
256
- PointerByReference device = new PointerByReference ();
257
- throwIfNeeded (idevice_new (device , Pointer .NULL ), ErrorCodeType .idevice_error );
258
- PointerByReference client = new PointerByReference ();
259
- throwIfNeeded (lockdownd_client_new_with_handshake (device .getValue (), client , "blobsaver" ), ErrorCodeType .lockdownd_error );
260
- PointerByReference service = new PointerByReference ();
261
- throwIfNeeded (lockdownd_start_service (client .getValue (), "com.apple.mobile.diagnostics_relay" , service ), ErrorCodeType .lockdownd_error );
262
- lockdownd_client_free (client .getValue ());
263
-
264
- PointerByReference diagnosticsRelayClient = new PointerByReference ();
265
- throwIfNeeded (diagnostics_relay_client_new (device .getValue (), service .getValue (), diagnosticsRelayClient ), ErrorCodeType .diagnostics_relay_error );
266
-
267
- Pointer keys = Libplist .newArray ();
268
- Libplist .arrayAppendItem (keys , Libplist .newString (key ));
269
- PointerByReference plistResult = new PointerByReference ();
270
- throwIfNeeded (diagnostics_relay_query_mobilegestalt (diagnosticsRelayClient .getValue (), keys , plistResult ), ErrorCodeType .diagnostics_relay_error );
271
- Pointer plistApnonce = Libplist .dictGetItem (Libplist .dictGetItem (plistResult .getValue (), "MobileGestalt" ), key );
272
-
273
- diagnostics_relay_goodbye (diagnosticsRelayClient .getValue ());
274
- diagnostics_relay_client_free (diagnosticsRelayClient .getValue ());
275
- lockdownd_service_descriptor_free (service .getValue ());
276
- idevice_free (device .getValue ());
277
- Libplist .free (keys );
221
+ private static Pointer getLockdownValuePlist (String key ) throws LibimobiledeviceException {
222
+ Pointer client = lockdowndClientFromConnectedDevice ();
223
+ PointerByReference plist = new PointerByReference ();
224
+ int lockdowndGetValueErrorCode = lockdownd_get_value (client , Pointer .NULL , key , plist );
225
+ if (lockdowndGetValueErrorCode == -8 ) {
226
+ // try again, and if it doesn't work, show an error to the user + throw an exception
227
+ // it always works the second time
228
+ lockdownd_client_free (client );
229
+ client = lockdowndClientFromConnectedDevice ();
230
+ throwIfNeeded (lockdownd_get_value (client , Pointer .NULL , key , plist ), ErrorCodeType .lockdownd_error );
231
+ } else {
232
+ throwIfNeeded (lockdowndGetValueErrorCode , ErrorCodeType .lockdownd_error );
233
+ }
234
+ lockdownd_client_free (client );
278
235
279
- return plistApnonce ;
236
+ return plist . getValue () ;
280
237
}
281
238
282
- private static String plistDataToString (Pointer plist , ByteOrder byteOrder ) {
239
+ private static String plistDataToHexString (Pointer plist , ByteOrder byteOrder ) {
283
240
IntByReference apnonceLength = new IntByReference ();
284
241
byte [] apnonceBytes = Libplist .getDataPtr (plist , apnonceLength ).getByteArray (0 , apnonceLength .getValue ());
285
242
String toReturn = Utils .bytesToHex (apnonceBytes , byteOrder );
@@ -288,6 +245,27 @@ private static String plistDataToString(Pointer plist, ByteOrder byteOrder) {
288
245
return toReturn ;
289
246
}
290
247
248
+ private static long getPlistLong (Pointer plist ) {
249
+ LongByReference reference = new LongByReference ();
250
+ Libplist .getUintVal (plist , reference );
251
+ Libplist .free (plist );
252
+ return reference .getValue ();
253
+ }
254
+
255
+ private static String getPlistString (Pointer plist ) {
256
+ PointerByReference reference = new PointerByReference ();
257
+ Libplist .getStringVal (plist , reference );
258
+ Libplist .free (plist );
259
+ return reference .getValue ().getString (0 , "UTF-8" );
260
+ }
261
+
262
+ // Useful for debugging
263
+ private static String plistToXml (Pointer plist ) {
264
+ PointerByReference xml_doc = new PointerByReference ();
265
+ Libplist .toXml (plist , xml_doc , new PointerByReference ());
266
+ return xml_doc .getValue ().getString (0 , "UTF-8" );
267
+ }
268
+
291
269
private static Pointer lockdowndClientFromConnectedDevice () throws LibimobiledeviceException {
292
270
PointerByReference device = new PointerByReference ();
293
271
throwIfNeeded (idevice_new (device , Pointer .NULL ), ErrorCodeType .idevice_error );
@@ -306,12 +284,8 @@ static void enterRecovery() throws LibimobiledeviceException {
306
284
lockdownd_client_free (client );
307
285
}
308
286
309
- private enum PlistType {
310
- STRING , INTEGER
311
- }
312
-
313
287
private enum ErrorCodeType {
314
- idevice_error , lockdownd_error , irecv_error , diagnostics_relay_error
288
+ idevice_error , lockdownd_error , irecv_error
315
289
}
316
290
317
291
private static void throwIfNeeded (int errorCode , ErrorCodeType errorType ) throws LibimobiledeviceException {
@@ -350,9 +324,6 @@ private static void throwIfNeeded(int errorCode, ErrorCodeType errorType) throws
350
324
message = "irecovery error: code=" + errorCode +
351
325
"\n \n If your device is still in recovery mode, use the \" Exit Recovery Mode\" option from the help menu." ;
352
326
reportableError = true ;
353
- } else if (errorType .equals (ErrorCodeType .diagnostics_relay_error )) {
354
- message = "Diagnostics Relay error: code=" + errorCode ;
355
- reportableError = true ;
356
327
}
357
328
throw new LibimobiledeviceException (message , errorType , errorCode , reportableError );
358
329
}
0 commit comments