Skip to content

Commit bd0c329

Browse files
authored
Merge pull request #54 from cjmang/datapackage
Ensuring folder versions of game names are safe for the file system
2 parents c10aad6 + 9140fe2 commit bd0c329

File tree

4 files changed

+100
-37
lines changed

4 files changed

+100
-37
lines changed

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

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

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

230-
for(File gameDir : directoryPath.listFiles()){
231-
if(gameDir.isDirectory()){
232-
localGamesList.put(gameDir.getName(), gameDir);
233-
}
243+
for(File gameDir : directoryPath.listFiles()){
244+
if(gameDir.isDirectory()){
245+
localGamesList.put(gameDir.getName(), gameDir);
234246
}
247+
}
235248

236-
if(localGamesList.isEmpty()){
237-
//cache doesn't exist. Create the filepath
238-
boolean success = directoryPath.mkdirs();
239-
if(success){
240-
LOGGER.info("DataPackage directory didn't exist. Starting from a new one.");
241-
} else{
242-
LOGGER.severe("Failed to make directories for datapackage cache.");
243-
}
244-
return;
249+
if(localGamesList.isEmpty()){
250+
LOGGER.info("Datapackage is empty");
251+
return;
252+
}
253+
254+
for(String gameName : games) {
255+
String safeName = Utils.getFileSafeName(gameName);
256+
File dir = localGamesList.get(safeName);
257+
258+
if(null == dir){
259+
continue;
245260
}
246261

247-
for(String gameName : games) {
248-
File dir = localGamesList.get(gameName);
249-
250-
if(null == dir){
251-
continue;
252-
}
253-
254-
//check all checksums
255-
for(File version : dir.listFiles()){
256-
String versionStr = versions.get(gameName);
257-
if(versionStr != null && versionStr.equals(version.getName())) {
258-
try(FileReader reader = new FileReader(version)){
259-
Game game = gson.fromJson(reader, Game.class);
260-
dataPackage.update(gameName, game);
261-
LOGGER.info("Read datapackage for Game: ".concat(gameName).concat(" Checksum: ").concat(version.getName()));
262-
} catch (IOException e){
263-
LOGGER.info("Failed to read a datapackage. Starting with a new one.");
264-
}
262+
//check all checksums
263+
for(File version : dir.listFiles()){
264+
String versionStr = versions.get(gameName);
265+
if(versionStr != null && versionStr.equals(version.getName())) {
266+
try(FileReader reader = new FileReader(version)){
267+
Game game = gson.fromJson(reader, Game.class);
268+
dataPackage.update(gameName, game);
269+
LOGGER.info("Read datapackage for Game: ".concat(gameName).concat(" Checksum: ").concat(version.getName()));
270+
} catch (IOException e){
271+
LOGGER.info("Failed to read a datapackage. Starting with a new one.");
265272
}
266273
}
267274
}
@@ -273,7 +280,8 @@ public void saveDataPackage() {
273280
synchronized (Client.class){
274281
//Loop through games to ensure we have folders for each of them in the cache
275282
for(String gameName : games){
276-
File gameFolder = dataPackageLocation.resolve(gameName).toFile();
283+
String safeName = Utils.getFileSafeName(gameName);
284+
File gameFolder = dataPackageLocation.resolve(safeName).toFile();
277285
if(!gameFolder.exists()){
278286
//game folder not found. Make it
279287
gameFolder.mkdirs();
@@ -286,7 +294,7 @@ public void saveDataPackage() {
286294
}
287295

288296
//if key is for this game
289-
File filePath = dataPackageLocation.resolve(gameName).resolve(gameVersion).toFile();
297+
File filePath = dataPackageLocation.resolve(safeName).resolve(gameVersion).toFile();
290298

291299
try (Writer writer = new FileWriter(filePath)){
292300
//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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package dev.koifysh.archipelago.network;
22

33
public enum ConnectionResult {
4-
Success,InvalidSlot, SlotAlreadyTaken, IncompatibleVersion, InvalidPassword
4+
Success,InvalidSlot, SlotAlreadyTaken, IncompatibleVersion, InvalidPassword,InvalidGame
55
}
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)