Small fixes to path module

This commit is contained in:
2026-04-18 19:50:23 +02:00
parent 1819861326
commit 46b6f4867e
3 changed files with 103 additions and 72 deletions

View File

@@ -8,6 +8,7 @@ import java.net.URLDecoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import sh.rhiobet.lalafin.api.configuration.FileApiConfiguration; import sh.rhiobet.lalafin.api.configuration.FileApiConfiguration;
@@ -22,8 +23,22 @@ public class PathFactory {
} else { } else {
java.nio.file.Path rootFolderPath = Paths.get(this.fileApiConfiguration.directory()); java.nio.file.Path rootFolderPath = Paths.get(this.fileApiConfiguration.directory());
if (names.size() > 1 && names.get(names.size() - 2).getPath().endsWith(".zip")) { int zipIndex = -1;
return new ZipEntryPath(names, rootFolderPath); for (int i = 0; i < names.size(); i++) {
if (names.get(i).getPath().endsWith(".zip")) {
zipIndex = i;
break;
}
}
if (zipIndex >= 0 && zipIndex < names.size() - 1) {
FileSystemPath zipFilePath =
new FileSystemPath(names.subList(0, zipIndex + 1), rootFolderPath);
String zipEntryName = names.stream()
.skip(zipIndex + 1)
.map(PathSegment::getPath)
.collect(Collectors.joining("/"));
return new ZipEntryPath(zipFilePath, zipEntryName);
} else { } else {
return new FileSystemPath(names, rootFolderPath); return new FileSystemPath(names, rootFolderPath);
} }
@@ -38,7 +53,8 @@ public class PathFactory {
if (decoded.equals(current)) break; if (decoded.equals(current)) break;
current = decoded; current = decoded;
} }
return current.contains("/") || current.contains("\0") || current.equals("..") || current.equals("."); return current.contains("/") || current.contains("\0") || current.equals("..")
|| current.equals(".");
}); });
} }
} }

View File

@@ -6,11 +6,15 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
import org.jboss.resteasy.reactive.common.util.Encode; import org.jboss.resteasy.reactive.common.util.Encode;
public final class ZipEntryPath implements Path { public final class ZipEntryPath implements Path {
private long size = 0;
private boolean exists = false;
FileSystemPath zipFilePath; FileSystemPath zipFilePath;
List<String> segments; List<String> segments;
@@ -38,20 +42,18 @@ public final class ZipEntryPath implements Path {
@Override @Override
public long getSize() { public long getSize() {
try (ZipFile zipFile = new ZipFile(this.zipFilePath.absolutePath.toFile())) { if (this.size == 0) {
return zipFile.getEntry(this.segments.getLast()).getSize(); fetchEntryData();
} catch (IOException ignored) { }
return 0; return this.size;
}
} }
@Override @Override
public boolean exists() { public boolean exists() {
try (ZipFile zipFile = new ZipFile(this.zipFilePath.absolutePath.toFile())) { if (!this.exists) {
return zipFile.getEntry(segments.getLast()) != null; fetchEntryData();
} catch (IOException ignored) {
return false;
} }
return this.exists;
} }
@Override @Override
@@ -70,63 +72,74 @@ public final class ZipEntryPath implements Path {
return new ZipEntryInputStream(zipFile, return new ZipEntryInputStream(zipFile,
zipFile.getInputStream(zipFile.getEntry(this.segments.getLast()))); zipFile.getInputStream(zipFile.getEntry(this.segments.getLast())));
} }
}
private void fetchEntryData() {
class ZipEntryInputStream extends InputStream { try (ZipFile zipFile = new ZipFile(this.zipFilePath.absolutePath.toFile())) {
private final ZipFile zipFile; ZipEntry zipEntry = zipFile.getEntry(this.segments.getLast());
private final InputStream is; this.exists = zipEntry != null;
public ZipEntryInputStream(ZipFile zipFile, InputStream is) { if (this.exists) {
this.zipFile = zipFile; this.size = zipEntry.getSize();
this.is = is; }
} } catch (IOException ignored) { }
}
@Override
public int read() throws IOException { private class ZipEntryInputStream extends InputStream {
return this.is.read(); private final ZipFile zipFile;
} private final InputStream is;
@Override public ZipEntryInputStream(ZipFile zipFile, InputStream is) {
public int read(byte[] buf) throws IOException { this.zipFile = zipFile;
return this.is.read(buf); this.is = is;
} }
@Override @Override
public int read(byte[] buf, int off, int len) throws IOException { public int read() throws IOException {
return this.is.read(buf, off, len); return this.is.read();
} }
@Override @Override
public byte[] readAllBytes() throws IOException { public int read(byte[] buf) throws IOException {
return this.is.readAllBytes(); return this.is.read(buf);
} }
@Override @Override
public byte[] readNBytes(int len) throws IOException { public int read(byte[] buf, int off, int len) throws IOException {
return this.is.readNBytes(len); return this.is.read(buf, off, len);
} }
@Override @Override
public int readNBytes(byte[] buf, int off, int len) throws IOException { public byte[] readAllBytes() throws IOException {
return this.is.readNBytes(buf, off, len); return this.is.readAllBytes();
} }
@Override @Override
public long skip(long n) throws IOException { public byte[] readNBytes(int len) throws IOException {
return this.is.skip(n); return this.is.readNBytes(len);
} }
@Override @Override
public int available() throws IOException { public int readNBytes(byte[] buf, int off, int len) throws IOException {
return this.is.available(); return this.is.readNBytes(buf, off, len);
} }
@Override @Override
public void close() throws IOException { public long skip(long n) throws IOException {
try { return this.is.skip(n);
this.is.close(); }
} finally {
this.zipFile.close(); @Override
} public int available() throws IOException {
} return this.is.available();
}
@Override
public void close() throws IOException {
try {
this.is.close();
} finally {
this.zipFile.close();
}
}
}
} }

View File

@@ -5,6 +5,7 @@ import java.io.OutputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Optional; import java.util.Optional;
import java.util.regex.Pattern;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject; import jakarta.inject.Inject;
@@ -62,7 +63,8 @@ public class ThumbnailPathPlugin extends PathAccessor implements PathPlugin {
private Optional<java.nio.file.Path> getThumbnailPath(Path path) { private Optional<java.nio.file.Path> getThumbnailPath(Path path) {
try { try {
return Files.list(getAbsolutePath(path).getParent().resolve(".thumbnails")) return Files.list(getAbsolutePath(path).getParent().resolve(".thumbnails"))
.filter(f -> f.getFileName().toString().matches("^" + path.getFilename() + "(\\.[^.]+)*$")) .filter(f -> f.getFileName().toString()
.matches("^" + Pattern.quote(path.getFilename()) + "(\\.[^.]+)*$"))
.findFirst(); .findFirst();
} catch (IOException ignored) { } catch (IOException ignored) {
return Optional.empty(); return Optional.empty();