[FIX] Fix resolution of files with special characters for embedded file server (#705)

This commit is contained in:
zznty 2024-03-16 21:50:47 +07:00 committed by GitHub
parent 3926f3e5bf
commit 1710eb7bec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 42 additions and 5 deletions

View File

@ -7,13 +7,13 @@ import io.netty.handler.codec.http.*;
import io.netty.handler.stream.ChunkedFile;
import io.netty.util.CharsetUtil;
import pro.gravit.launchserver.socket.handlers.ContentType;
import pro.gravit.utils.helper.IOHelper;
import pro.gravit.utils.helper.VerifyHelper;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Clock;
@ -182,12 +182,18 @@ public class FileServerHandler extends SimpleChannelInboundHandler<FullHttpReque
return;
}
final String uri = request.uri();
// URLDecoder tries to decode string as application/x-www-form-urlencoded which allows + character to be used as space escape therefore breaking file names with +
final String uri = IOHelper.urlDecodeStrict(request.uri());
final String path;
if (uri == null) {
sendError(ctx, NOT_FOUND);
return;
}
try {
path = Paths.get(new URI(uri).getPath()).normalize().toString().substring(1);
} catch (URISyntaxException e) {
path = Paths.get(IOHelper.getPathFromUrlFragment(uri)).normalize().toString().substring(1);
} catch (InvalidPathException e) {
sendError(ctx, BAD_REQUEST);
return;
}

View File

@ -5,12 +5,15 @@ import javax.imageio.ImageReader;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collections;
import java.util.HexFormat;
import java.util.Set;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
@ -559,6 +562,34 @@ public final class IOHelper {
return URLEncoder.encode(s, UNICODE_CHARSET);
}
public static String urlDecodeStrict(String s) {
var builder = new StringBuilder();
char[] charArray = s.toCharArray();
for (int i = 0; i < charArray.length; i++) {
char c = charArray[i];
if (c != '%') {
builder.append(c);
continue;
}
if (i + 2 >= charArray.length) {
return null;
}
var buffer = UNICODE_CHARSET.decode(ByteBuffer.wrap(HexFormat.of().parseHex(CharBuffer.wrap(charArray, i + 1, 2))));
builder.append(buffer);
i += 2;
}
return builder.toString();
}
public static String getPathFromUrlFragment(String urlFragment) {
return urlFragment.indexOf('?') < 0 ? urlFragment : urlFragment.substring(0, urlFragment.indexOf('?'));
}
public static String verifyFileName(String fileName) {
return VerifyHelper.verify(fileName, IOHelper::isValidFileName, String.format("Invalid file name: '%s'", fileName));
}