Make sure we reject files that are not children of a sync-path
This commit is contained in:
parent
0b9d6093a0
commit
fdbde2e0a6
6 changed files with 99 additions and 19 deletions
|
@ -179,6 +179,7 @@ public class DataExchangeAPI extends DataExchange {
|
|||
.replace(":", "-")
|
||||
.replace("\\", "-")
|
||||
.replace("/", "-"))
|
||||
.normalize()
|
||||
.toFile();
|
||||
|
||||
if (!fl.exists()) {
|
||||
|
|
|
@ -34,11 +34,20 @@ class AutoFileSyncEntry extends AutoSyncID {
|
|||
final String relFile = DataHandler.readString(buf);
|
||||
SyncFolderDescriptor desc = DataExchange.getSyncFolderDescriptor(syncID);
|
||||
if (desc!=null) {
|
||||
return new AutoFileSyncEntry.ForDirectFileRequest(syncID, new File(relFile), desc.localFolder.resolve(relFile)
|
||||
.toFile());
|
||||
//ensures that the file is not above the base-folder
|
||||
if (desc.acceptChildElements(desc.mapAbsolute(relFile))) {
|
||||
return new AutoFileSyncEntry.ForDirectFileRequest(syncID, new File(relFile), desc.localFolder.resolve(relFile)
|
||||
.normalize()
|
||||
.toFile());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return uniqueID + " - " + relFile;
|
||||
}
|
||||
}
|
||||
public final DataExchange.NeedTransferPredicate needTransfer;
|
||||
public final File fileName;
|
||||
|
@ -149,8 +158,11 @@ class AutoFileSyncEntry extends AutoSyncID {
|
|||
if (desc != null) {
|
||||
SubFile subFile = desc.getLocalSubFile(freq.relFile.toString());
|
||||
if (subFile != null) {
|
||||
final File absPath = desc.localFolder.resolve(subFile.relPath)
|
||||
.toFile();
|
||||
final File absPath = desc
|
||||
.localFolder
|
||||
.resolve(subFile.relPath)
|
||||
.normalize()
|
||||
.toFile();
|
||||
return new AutoFileSyncEntry.ForDirectFileRequest(freq.uniqueID, new File(subFile.relPath), absPath);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import ru.bclib.api.dataexchange.FileHash;
|
|||
import ru.bclib.api.dataexchange.SyncFileHash;
|
||||
import ru.bclib.api.dataexchange.handler.AutoSyncID.ForDirectFileRequest;
|
||||
import ru.bclib.config.Configs;
|
||||
import ru.bclib.util.PathUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
|
@ -33,6 +34,7 @@ abstract public class DataExchange {
|
|||
public final static SyncFolderDescriptor SYNC_FOLDER = new SyncFolderDescriptor("BCLIB-SYNC", FabricLoader.getInstance()
|
||||
.getGameDir()
|
||||
.resolve("bclib-sync")
|
||||
.normalize()
|
||||
.toAbsolutePath(), true);
|
||||
final List<SyncFolderDescriptor> syncFolderDescriptions = Arrays.asList(SYNC_FOLDER);
|
||||
|
||||
|
@ -130,6 +132,11 @@ abstract public class DataExchange {
|
|||
fileCache = new ArrayList<>(8);
|
||||
fileWalker(localFolder.toFile(), p -> fileCache.add(new SubFile(localFolder.relativize(p)
|
||||
.toString(), FileHash.create(p.toFile()))));
|
||||
|
||||
//this tests if we can trick the system to load files that are not beneath the base-folder
|
||||
if (!BCLib.isClient()){
|
||||
fileCache.add(new SubFile("../breakout.json", FileHash.create(mapAbsolute("../breakout.json").toFile())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,6 +200,26 @@ abstract public class DataExchange {
|
|||
loadCache();
|
||||
return fileCache.stream();
|
||||
}
|
||||
|
||||
public Path mapAbsolute(String relPath) {
|
||||
return this.localFolder.resolve(relPath).normalize();
|
||||
}
|
||||
|
||||
public Path mapAbsolute(SubFile subFile) {
|
||||
return this.localFolder.resolve(subFile.relPath).normalize();
|
||||
}
|
||||
|
||||
public boolean acceptChildElements(Path absPath){
|
||||
return PathUtil.isChildOf(this.localFolder, absPath);
|
||||
}
|
||||
|
||||
public boolean acceptChildElements(SubFile subFile){
|
||||
return acceptChildElements(mapAbsolute(subFile));
|
||||
}
|
||||
|
||||
public boolean discardChildElements(SubFile subFile){
|
||||
return !acceptChildElements(subFile);
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
|
|
|
@ -107,7 +107,7 @@ public class HelloClient extends DataHandler {
|
|||
if (Configs.MAIN_CONFIG.getBoolean(Configs.MAIN_SYNC_CATEGORY, "offersSyncFolders", true)) {
|
||||
buf.writeInt(((DataExchange) DataExchange.getInstance()).syncFolderDescriptions.size());
|
||||
((DataExchange) DataExchange.getInstance()).syncFolderDescriptions.forEach(desc -> {
|
||||
BCLib.LOGGER.info(" - Offering Folder " + desc.localFolder + " (allowDelete="+desc.removeAdditionalFiles+")");
|
||||
BCLib.LOGGER.info(" - Offering Folder " + desc.localFolder + " (allowDelete=" + desc.removeAdditionalFiles + ")");
|
||||
desc.serialize(buf);
|
||||
});
|
||||
}
|
||||
|
@ -175,30 +175,44 @@ public class HelloClient extends DataHandler {
|
|||
BCLib.LOGGER.info(" - " + desc.folderID + " (" + desc.localFolder + ", allowRemove=" + desc.removeAdditionalFiles + ")");
|
||||
localDescriptor.invalidateCache();
|
||||
|
||||
desc.relativeFilesStream()
|
||||
.filter(desc::discardChildElements)
|
||||
.forEach(subFile -> {
|
||||
BCLib.LOGGER.warning(" * " + subFile.relPath + " (REJECTED)");
|
||||
});
|
||||
|
||||
|
||||
if (desc.removeAdditionalFiles) {
|
||||
List<AutoSyncID.ForDirectFileRequest> additionalFiles = localDescriptor.relativeFilesStream()
|
||||
.filter(subFile -> !desc.hasRelativeFile(subFile))
|
||||
.map(subFile -> new AutoSyncID.ForDirectFileRequest(desc.folderID, desc.localFolder.resolve(subFile.relPath).toFile()))
|
||||
.map(desc::mapAbsolute)
|
||||
.filter(desc::acceptChildElements)
|
||||
.map(absPath -> new AutoSyncID.ForDirectFileRequest(desc.folderID, absPath.toFile()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
additionalFiles.forEach(aid -> BCLib.LOGGER.info(" * Removing " + aid.relFile));
|
||||
additionalFiles.forEach(aid -> BCLib.LOGGER.info(" * " + desc.localFolder.relativize(aid.relFile.toPath()) + " (missing on server)"));
|
||||
filesToRemove.addAll(additionalFiles);
|
||||
}
|
||||
|
||||
desc.relativeFilesStream().forEach(subFile -> {
|
||||
SubFile localSubFile = localDescriptor.getLocalSubFile(subFile.relPath);
|
||||
if (localSubFile != null){
|
||||
//the file exists locally, check if the hashes match
|
||||
if (!localSubFile.hash.equals(subFile.hash)){
|
||||
BCLib.LOGGER.info(" * Changed " + subFile.relPath);
|
||||
desc.relativeFilesStream()
|
||||
.filter(desc::acceptChildElements)
|
||||
.forEach(subFile -> {
|
||||
SubFile localSubFile = localDescriptor.getLocalSubFile(subFile.relPath);
|
||||
if (localSubFile != null) {
|
||||
//the file exists locally, check if the hashes match
|
||||
if (!localSubFile.hash.equals(subFile.hash)) {
|
||||
BCLib.LOGGER.info(" * " + subFile.relPath + " (changed)");
|
||||
filesToRequest.add(new AutoSyncID.ForDirectFileRequest(desc.folderID, new File(subFile.relPath)));
|
||||
} else {
|
||||
BCLib.LOGGER.info(" * " + subFile.relPath);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//the file is missing locally
|
||||
BCLib.LOGGER.info(" * " + subFile.relPath + " (missing on client)");
|
||||
filesToRequest.add(new AutoSyncID.ForDirectFileRequest(desc.folderID, new File(subFile.relPath)));
|
||||
}
|
||||
} else {
|
||||
//the file is missing locally
|
||||
BCLib.LOGGER.info(" * Missing " + subFile.relPath);
|
||||
filesToRequest.add(new AutoSyncID.ForDirectFileRequest(desc.folderID, new File(subFile.relPath)));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//free some memory
|
||||
localDescriptor.invalidateCache();
|
||||
|
@ -318,6 +332,7 @@ public class HelloClient extends DataHandler {
|
|||
|
||||
filesToRemove.forEach(aid -> {
|
||||
BCLib.LOGGER.info(" - " + aid.relFile + " (removing)");
|
||||
|
||||
aid.relFile.delete();
|
||||
});
|
||||
|
||||
|
|
|
@ -51,6 +51,14 @@ public class SendFiles extends DataHandler {
|
|||
System.out.println("Got Content:" + content.length);
|
||||
return true;
|
||||
}));*/
|
||||
|
||||
//this will try to send a folder-file that was not registered or requested by the client
|
||||
existingFiles.add(new AutoFileSyncEntry.ForDirectFileRequest(DataExchange.SYNC_FOLDER.folderID, new File("test.json"), DataExchange.SYNC_FOLDER.mapAbsolute("test.json").toFile()));
|
||||
|
||||
//this will try to send a folder-file that was not registered or requested by the client and is outside the base-folder
|
||||
existingFiles.add(new AutoFileSyncEntry.ForDirectFileRequest(DataExchange.SYNC_FOLDER.folderID, new File("../breakout.json"), DataExchange.SYNC_FOLDER.mapAbsolute("../breakout.json").toFile()));
|
||||
|
||||
|
||||
writeString(buf, token);
|
||||
buf.writeInt(existingFiles.size());
|
||||
|
||||
|
|
17
src/main/java/ru/bclib/util/PathUtil.java
Normal file
17
src/main/java/ru/bclib/util/PathUtil.java
Normal file
|
@ -0,0 +1,17 @@
|
|||
package ru.bclib.util;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class PathUtil {
|
||||
public static boolean isChildOf(Path parent, Path child){
|
||||
if (child==null || parent==null) return false;
|
||||
|
||||
final int pCount = parent.getNameCount();
|
||||
final int cCount = child.getNameCount();
|
||||
|
||||
if (cCount > pCount) return isChildOf(parent, child.getParent());
|
||||
if (cCount < pCount) return false;
|
||||
|
||||
return child.equals(parent);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue