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("\\", "-")
|
.replace("\\", "-")
|
||||||
.replace("/", "-"))
|
.replace("/", "-"))
|
||||||
|
.normalize()
|
||||||
.toFile();
|
.toFile();
|
||||||
|
|
||||||
if (!fl.exists()) {
|
if (!fl.exists()) {
|
||||||
|
|
|
@ -34,11 +34,20 @@ class AutoFileSyncEntry extends AutoSyncID {
|
||||||
final String relFile = DataHandler.readString(buf);
|
final String relFile = DataHandler.readString(buf);
|
||||||
SyncFolderDescriptor desc = DataExchange.getSyncFolderDescriptor(syncID);
|
SyncFolderDescriptor desc = DataExchange.getSyncFolderDescriptor(syncID);
|
||||||
if (desc!=null) {
|
if (desc!=null) {
|
||||||
return new AutoFileSyncEntry.ForDirectFileRequest(syncID, new File(relFile), desc.localFolder.resolve(relFile)
|
//ensures that the file is not above the base-folder
|
||||||
.toFile());
|
if (desc.acceptChildElements(desc.mapAbsolute(relFile))) {
|
||||||
|
return new AutoFileSyncEntry.ForDirectFileRequest(syncID, new File(relFile), desc.localFolder.resolve(relFile)
|
||||||
|
.normalize()
|
||||||
|
.toFile());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return uniqueID + " - " + relFile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public final DataExchange.NeedTransferPredicate needTransfer;
|
public final DataExchange.NeedTransferPredicate needTransfer;
|
||||||
public final File fileName;
|
public final File fileName;
|
||||||
|
@ -149,8 +158,11 @@ class AutoFileSyncEntry extends AutoSyncID {
|
||||||
if (desc != null) {
|
if (desc != null) {
|
||||||
SubFile subFile = desc.getLocalSubFile(freq.relFile.toString());
|
SubFile subFile = desc.getLocalSubFile(freq.relFile.toString());
|
||||||
if (subFile != null) {
|
if (subFile != null) {
|
||||||
final File absPath = desc.localFolder.resolve(subFile.relPath)
|
final File absPath = desc
|
||||||
.toFile();
|
.localFolder
|
||||||
|
.resolve(subFile.relPath)
|
||||||
|
.normalize()
|
||||||
|
.toFile();
|
||||||
return new AutoFileSyncEntry.ForDirectFileRequest(freq.uniqueID, new File(subFile.relPath), absPath);
|
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.SyncFileHash;
|
||||||
import ru.bclib.api.dataexchange.handler.AutoSyncID.ForDirectFileRequest;
|
import ru.bclib.api.dataexchange.handler.AutoSyncID.ForDirectFileRequest;
|
||||||
import ru.bclib.config.Configs;
|
import ru.bclib.config.Configs;
|
||||||
|
import ru.bclib.util.PathUtil;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.file.Path;
|
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()
|
public final static SyncFolderDescriptor SYNC_FOLDER = new SyncFolderDescriptor("BCLIB-SYNC", FabricLoader.getInstance()
|
||||||
.getGameDir()
|
.getGameDir()
|
||||||
.resolve("bclib-sync")
|
.resolve("bclib-sync")
|
||||||
|
.normalize()
|
||||||
.toAbsolutePath(), true);
|
.toAbsolutePath(), true);
|
||||||
final List<SyncFolderDescriptor> syncFolderDescriptions = Arrays.asList(SYNC_FOLDER);
|
final List<SyncFolderDescriptor> syncFolderDescriptions = Arrays.asList(SYNC_FOLDER);
|
||||||
|
|
||||||
|
@ -130,6 +132,11 @@ abstract public class DataExchange {
|
||||||
fileCache = new ArrayList<>(8);
|
fileCache = new ArrayList<>(8);
|
||||||
fileWalker(localFolder.toFile(), p -> fileCache.add(new SubFile(localFolder.relativize(p)
|
fileWalker(localFolder.toFile(), p -> fileCache.add(new SubFile(localFolder.relativize(p)
|
||||||
.toString(), FileHash.create(p.toFile()))));
|
.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();
|
loadCache();
|
||||||
return fileCache.stream();
|
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
|
@FunctionalInterface
|
||||||
|
|
|
@ -107,7 +107,7 @@ public class HelloClient extends DataHandler {
|
||||||
if (Configs.MAIN_CONFIG.getBoolean(Configs.MAIN_SYNC_CATEGORY, "offersSyncFolders", true)) {
|
if (Configs.MAIN_CONFIG.getBoolean(Configs.MAIN_SYNC_CATEGORY, "offersSyncFolders", true)) {
|
||||||
buf.writeInt(((DataExchange) DataExchange.getInstance()).syncFolderDescriptions.size());
|
buf.writeInt(((DataExchange) DataExchange.getInstance()).syncFolderDescriptions.size());
|
||||||
((DataExchange) DataExchange.getInstance()).syncFolderDescriptions.forEach(desc -> {
|
((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);
|
desc.serialize(buf);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -175,30 +175,44 @@ public class HelloClient extends DataHandler {
|
||||||
BCLib.LOGGER.info(" - " + desc.folderID + " (" + desc.localFolder + ", allowRemove=" + desc.removeAdditionalFiles + ")");
|
BCLib.LOGGER.info(" - " + desc.folderID + " (" + desc.localFolder + ", allowRemove=" + desc.removeAdditionalFiles + ")");
|
||||||
localDescriptor.invalidateCache();
|
localDescriptor.invalidateCache();
|
||||||
|
|
||||||
|
desc.relativeFilesStream()
|
||||||
|
.filter(desc::discardChildElements)
|
||||||
|
.forEach(subFile -> {
|
||||||
|
BCLib.LOGGER.warning(" * " + subFile.relPath + " (REJECTED)");
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
if (desc.removeAdditionalFiles) {
|
if (desc.removeAdditionalFiles) {
|
||||||
List<AutoSyncID.ForDirectFileRequest> additionalFiles = localDescriptor.relativeFilesStream()
|
List<AutoSyncID.ForDirectFileRequest> additionalFiles = localDescriptor.relativeFilesStream()
|
||||||
.filter(subFile -> !desc.hasRelativeFile(subFile))
|
.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());
|
.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);
|
filesToRemove.addAll(additionalFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
desc.relativeFilesStream().forEach(subFile -> {
|
desc.relativeFilesStream()
|
||||||
SubFile localSubFile = localDescriptor.getLocalSubFile(subFile.relPath);
|
.filter(desc::acceptChildElements)
|
||||||
if (localSubFile != null){
|
.forEach(subFile -> {
|
||||||
//the file exists locally, check if the hashes match
|
SubFile localSubFile = localDescriptor.getLocalSubFile(subFile.relPath);
|
||||||
if (!localSubFile.hash.equals(subFile.hash)){
|
if (localSubFile != null) {
|
||||||
BCLib.LOGGER.info(" * Changed " + subFile.relPath);
|
//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)));
|
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
|
//free some memory
|
||||||
localDescriptor.invalidateCache();
|
localDescriptor.invalidateCache();
|
||||||
|
@ -318,6 +332,7 @@ public class HelloClient extends DataHandler {
|
||||||
|
|
||||||
filesToRemove.forEach(aid -> {
|
filesToRemove.forEach(aid -> {
|
||||||
BCLib.LOGGER.info(" - " + aid.relFile + " (removing)");
|
BCLib.LOGGER.info(" - " + aid.relFile + " (removing)");
|
||||||
|
|
||||||
aid.relFile.delete();
|
aid.relFile.delete();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,14 @@ public class SendFiles extends DataHandler {
|
||||||
System.out.println("Got Content:" + content.length);
|
System.out.println("Got Content:" + content.length);
|
||||||
return true;
|
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);
|
writeString(buf, token);
|
||||||
buf.writeInt(existingFiles.size());
|
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…
Add table
Add a link
Reference in a new issue