Skip to content

Commit c8259c9

Browse files
committed
Ensuring folder versions of game names are safe for the file system
1 parent 5848ae8 commit c8259c9

File tree

3 files changed

+99
-36
lines changed

3 files changed

+99
-36
lines changed

src/main/java/dev/koifysh/archipelago/Client.java

Lines changed: 44 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -218,46 +218,53 @@ protected void loadDataPackage() {
218218
synchronized (Client.class){
219219
File directoryPath = dataPackageLocation.toFile();
220220

221+
if(!directoryPath.exists())
222+
{
223+
boolean success = directoryPath.mkdirs();
224+
if(success){
225+
LOGGER.info("DataPackage directory didn't exist. Starting from a new one.");
226+
} else{
227+
LOGGER.severe("Failed to make directories for datapackage cache.");
228+
}
229+
return;
230+
}
231+
221232
//ensure the path to the cache exists
222-
if(directoryPath.exists() && directoryPath.isDirectory()){
223-
//loop through all Archipelago cache folders to find valid data package files
224-
Map<String,File> localGamesList = new HashMap<String,File>();
233+
if(!directoryPath.isDirectory()) {
234+
return;
235+
}
236+
//loop through all Archipelago cache folders to find valid data package files
237+
Map<String,File> localGamesList = new HashMap<String,File>();
225238

226-
for(File gameDir : directoryPath.listFiles()){
227-
if(gameDir.isDirectory()){
228-
localGamesList.put(gameDir.getName(), gameDir);
229-
}
239+
for(File gameDir : directoryPath.listFiles()){
240+
if(gameDir.isDirectory()){
241+
localGamesList.put(gameDir.getName(), gameDir);
230242
}
243+
}
231244

232-
if(localGamesList.isEmpty()){
233-
//cache doesn't exist. Create the filepath
234-
boolean success = directoryPath.mkdirs();
235-
if(success){
236-
LOGGER.info("DataPackage directory didn't exist. Starting from a new one.");
237-
} else{
238-
LOGGER.severe("Failed to make directories for datapackage cache.");
239-
}
240-
return;
245+
if(localGamesList.isEmpty()){
246+
LOGGER.info("Datapackage is empty");
247+
return;
248+
}
249+
250+
for(String gameName : games) {
251+
String safeName = Utils.getFileSafeName(gameName);
252+
File dir = localGamesList.get(safeName);
253+
254+
if(null == dir){
255+
continue;
241256
}
242257

243-
for(String gameName : games) {
244-
File dir = localGamesList.get(gameName);
245-
246-
if(null == dir){
247-
continue;
248-
}
249-
250-
//check all checksums
251-
for(File version : dir.listFiles()){
252-
String versionStr = versions.get(gameName);
253-
if(versionStr != null && versionStr.equals(version.getName())) {
254-
try(FileReader reader = new FileReader(version)){
255-
Game game = gson.fromJson(reader, Game.class);
256-
dataPackage.update(gameName, game);
257-
LOGGER.info("Read datapackage for Game: ".concat(gameName).concat(" Checksum: ").concat(version.getName()));
258-
} catch (IOException e){
259-
LOGGER.info("Failed to read a datapackage. Starting with a new one.");
260-
}
258+
//check all checksums
259+
for(File version : dir.listFiles()){
260+
String versionStr = versions.get(gameName);
261+
if(versionStr != null && versionStr.equals(version.getName())) {
262+
try(FileReader reader = new FileReader(version)){
263+
Game game = gson.fromJson(reader, Game.class);
264+
dataPackage.update(gameName, game);
265+
LOGGER.info("Read datapackage for Game: ".concat(gameName).concat(" Checksum: ").concat(version.getName()));
266+
} catch (IOException e){
267+
LOGGER.info("Failed to read a datapackage. Starting with a new one.");
261268
}
262269
}
263270
}
@@ -269,7 +276,8 @@ public void saveDataPackage() {
269276
synchronized (Client.class){
270277
//Loop through games to ensure we have folders for each of them in the cache
271278
for(String gameName : games){
272-
File gameFolder = dataPackageLocation.resolve(gameName).toFile();
279+
String safeName = Utils.getFileSafeName(gameName);
280+
File gameFolder = dataPackageLocation.resolve(safeName).toFile();
273281
if(!gameFolder.exists()){
274282
//game folder not found. Make it
275283
gameFolder.mkdirs();
@@ -282,7 +290,7 @@ public void saveDataPackage() {
282290
}
283291

284292
//if key is for this game
285-
File filePath = dataPackageLocation.resolve(gameName).resolve(gameVersion).toFile();
293+
File filePath = dataPackageLocation.resolve(safeName).resolve(gameVersion).toFile();
286294

287295
try (Writer writer = new FileWriter(filePath)){
288296
//if game is in list of games, save it
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package dev.koifysh.archipelago;
2+
3+
public class Utils {
4+
5+
public static String getFileSafeName(String text)
6+
{
7+
if(text == null)
8+
{
9+
return null;
10+
}
11+
StringBuilder sb = new StringBuilder();
12+
13+
for(int i = 0; i < text.length(); i++)
14+
{
15+
char c = text.charAt(i);
16+
switch(c)
17+
{
18+
case '<':
19+
case '>':
20+
case ':':
21+
case '"':
22+
case '/':
23+
case '\\':
24+
case '|':
25+
case '?':
26+
case '*':
27+
continue;
28+
default:
29+
sb.append(c);
30+
31+
}
32+
}
33+
return sb.toString();
34+
}
35+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package dev.koifysh.archipelago;
2+
3+
import org.junit.jupiter.api.Test;
4+
import static org.junit.jupiter.api.Assertions.*;
5+
6+
public class UtilsTest {
7+
8+
@Test
9+
public void textIsSafe()
10+
{
11+
assertEquals("Slay the Spire", Utils.getFileSafeName("Slay the Spire"));
12+
}
13+
14+
@Test
15+
public void textIsBad()
16+
{
17+
18+
assertEquals("Slay the Spire", Utils.getFileSafeName("Slay <>\"/?\\|:*the Spire"));
19+
}
20+
}

0 commit comments

Comments
 (0)