21
21
import com .google .gson .Gson ;
22
22
import javafx .concurrent .Task ;
23
23
24
- import java .io .File ;
25
24
import java .io .FileNotFoundException ;
26
25
import java .io .IOException ;
27
26
import java .net .MalformedURLException ;
@@ -74,7 +73,6 @@ public class TSS extends Task<String> {
74
73
private TSS (String deviceIdentifier , String ecid , String savePath , String boardConfig , boolean includeBetas , String manualVersion , String manualIpswURL , String apnonce , String generator , boolean saveToTSSSaver , boolean saveToSHSHHost ) {
75
74
this .deviceIdentifier = deviceIdentifier ;
76
75
this .ecid = ecid ;
77
- this .savePath = savePath ;
78
76
this .boardConfig = boardConfig ;
79
77
this .includeBetas = includeBetas ;
80
78
this .manualVersion = manualVersion ;
@@ -83,6 +81,7 @@ private TSS(String deviceIdentifier, String ecid, String savePath, String boardC
83
81
this .generator = generator ;
84
82
this .saveToTSSSaver = saveToTSSSaver ;
85
83
this .saveToSHSHHost = saveToSHSHHost ;
84
+ this .savePath = parsePath (savePath );
86
85
}
87
86
88
87
/**
@@ -98,7 +97,7 @@ protected String call() throws TSSException {
98
97
ArrayList <String > args = constructArgs ();
99
98
100
99
var alreadySaved = new StringJoiner (", " );
101
- var savedFor = new StringJoiner (", " );
100
+ var newlySaved = new StringJoiner (", " );
102
101
for (Utils .IOSVersion iosVersion : iosVersions ) {
103
102
if (!Prefs .getAlwaysSaveNewBlobs () && checkAlreadySaved (iosVersion )) {
104
103
alreadySaved .add (iosVersion .versionString ());
@@ -116,14 +115,14 @@ protected String call() throws TSSException {
116
115
}
117
116
118
117
if (iosVersion .versionString () != null ) {
119
- savedFor .add (iosVersion .versionString ());
118
+ newlySaved .add (iosVersion .versionString ());
120
119
}
121
120
}
122
- StringBuilder responseBuilder = new StringBuilder ();
123
- if (manualIpswURL != null || savedFor .length () > 0 ) {
121
+ var responseBuilder = new StringBuilder ();
122
+ if (manualIpswURL != null || newlySaved .length () > 0 ) {
124
123
responseBuilder .append ("Successfully saved blobs in\n " ).append (savePath );
125
- if (savedFor .length () > 0 ) {
126
- responseBuilder .append ("\n \n For version" ).append (iosVersions .size () == 1 ? " " : "s " ).append (savedFor );
124
+ if (newlySaved .length () > 0 ) {
125
+ responseBuilder .append ("\n \n For version" ).append (iosVersions .size () == 1 ? " " : "s " ).append (newlySaved );
127
126
}
128
127
if (alreadySaved .length () > 0 ) {
129
128
responseBuilder .append ("\n \n " );
@@ -156,7 +155,7 @@ private boolean checkAlreadySaved(Utils.IOSVersion ios) {
156
155
String fileName = "%s_%s_%s_%s-%s_%s.shsh2"
157
156
.formatted (parseECID (), deviceIdentifier , getBoardConfig (), versionStringOnly , ios .buildid (), apnonce );
158
157
159
- if (Files .exists (Path .of (savePath , fileName ))) {
158
+ if (Files .exists (Path .of (parsePathWithVersion ( ios ) , fileName ))) {
160
159
System .out .println ("Already Saved: " + fileName );
161
160
return true ;
162
161
}
@@ -168,16 +167,59 @@ private long parseECID() {
168
167
: Long .parseLong (ecid .startsWith ("0x" ) ? ecid .substring (2 ) : ecid , 16 );
169
168
}
170
169
170
+ private String parsePath (String input ) {
171
+ if (!input .contains ("${" )) return input ;
172
+ String template = input ;
173
+
174
+ var variables = Map .of ("${DeviceIdentifier}" , deviceIdentifier ,
175
+ "${BoardConfig}" , getBoardConfig (),
176
+ "${APNonce}" , apnonce ,
177
+ "${Generator}" , generator ,
178
+ "${DeviceModel}" , Devices .identifierToModel (deviceIdentifier ),
179
+ "${ECID}" , ecid );
180
+ for (Map .Entry <String , String > entry : variables .entrySet ()) {
181
+ template = template .replace (entry .getKey (), entry .getValue ());
182
+ }
183
+ return template ;
184
+ }
185
+
186
+ private String parsePathWithVersion (Utils .IOSVersion ios ) {
187
+ if (!savePath .contains ("${" )) return savePath ;
188
+ var template = savePath ;
189
+
190
+ Map <String , String > variables ;
191
+ if (ios .versionString () != null ) {
192
+ variables = Map .of ("${FullVersionString}" , ios .versionString (),
193
+ "${BuildID}" , ios .buildid (),
194
+ "${MajorVersion}" , ios .versionString ().replaceFirst ("\\ ..*" , "" ));
195
+ } else {
196
+ variables = Map .of ("${FullVersionString}" , "UnknownVersion" ,
197
+ "${BuildID}" , "UnknownBuildID" ,
198
+ "${MajorVersion}" , "UnknownVersion" );
199
+ }
200
+ for (Map .Entry <String , String > entry : variables .entrySet ()) {
201
+ template = template .replace (entry .getKey (), entry .getValue ());
202
+ }
203
+
204
+ return template ;
205
+ }
171
206
172
207
private void saveFor (Utils .IOSVersion iosVersion , ArrayList <String > args ) throws TSSException {
173
208
final int urlIndex = args .size () - 1 ;
209
+ final int pathIndex = args .size () - 3 ;
174
210
Path manifest ;
175
211
try {
176
212
manifest = extractBuildManifest (iosVersion .ipswURL ());
177
213
args .set (urlIndex , manifest .toString ());
178
214
} catch (IOException e ) {
179
215
throw new TSSException ("Unable to extract BuildManifest." , true , e );
180
216
}
217
+ try {
218
+ args .set (pathIndex , parsePathWithVersion (iosVersion ));
219
+ Files .createDirectories (Path .of (args .get (pathIndex )));
220
+ } catch (IOException e ) {
221
+ throw new TSSException ("Unable to create save directory. Try with a different save path. If you are using variables, make sure they are spelled correctly." , false , e );
222
+ }
181
223
try {
182
224
System .out .println ("Running: " + args );
183
225
String tssLog = executeProgram (args );
@@ -258,9 +300,7 @@ private List<Utils.IOSVersion> getIOSVersions() throws TSSException {
258
300
private ArrayList <String > constructArgs () {
259
301
ArrayList <String > args = new ArrayList <>(17 );
260
302
String tsscheckerPath = Utils .getTsschecker ().getAbsolutePath ();
261
- //noinspection ResultOfMethodCallIgnored
262
- new File (savePath ).mkdirs ();
263
- Collections .addAll (args , tsscheckerPath , "--nocache" , "--save" , "--device" , deviceIdentifier , "--ecid" , ecid , "--save-path" , savePath );
303
+ Collections .addAll (args , tsscheckerPath , "--nocache" , "--save" , "--device" , deviceIdentifier , "--ecid" , ecid );
264
304
Collections .addAll (args , "--boardconfig" , getBoardConfig ());
265
305
if (apnonce != null ) {
266
306
Collections .addAll (args , "--apnonce" , apnonce );
@@ -270,7 +310,9 @@ private ArrayList<String> constructArgs() {
270
310
} else {
271
311
Collections .addAll (args , "--generator" , "0x1111111111111111" );
272
312
}
273
- Collections .addAll (args , "--build-manifest" , "will be replaced in loop" );
313
+
314
+ Collections .addAll (args , "--save-path" , "will be replaced in loop" ,
315
+ "--build-manifest" , "will be replaced in loop" );
274
316
275
317
return args ;
276
318
}
@@ -294,7 +336,7 @@ && containsIgnoreCase(tsscheckerLog, "checking tss status failed")) {
294
336
} else if (containsIgnoreCase (tsscheckerLog , "Could not resolve host" )) {
295
337
throw new TSSException ("Saving blobs failed. Check your internet connection." , false , tsscheckerLog );
296
338
} else if (containsIgnoreCase (tsscheckerLog , "can't save shsh at" )) {
297
- throw new TSSException ("'" + savePath + "' is not a valid path" , false );
339
+ throw new TSSException ("'" + savePath + "' is not a valid path. If you are using variables, make sure they are spelled correctly. " , false );
298
340
} else if (containsIgnoreCase (tsscheckerLog , "IS NOT being signed" )) {
299
341
if (manualVersion == null ) {
300
342
throw new TSSException ("The " + Devices .getOSNameForType (Devices .getDeviceType (deviceIdentifier )) + " version is not being signed for device " + deviceIdentifier , false );
0 commit comments