[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.stream.ChunkedFile; import io.netty.handler.stream.ChunkedFile;
import io.netty.util.CharsetUtil; import io.netty.util.CharsetUtil;
import pro.gravit.launchserver.socket.handlers.ContentType; import pro.gravit.launchserver.socket.handlers.ContentType;
import pro.gravit.utils.helper.IOHelper;
import pro.gravit.utils.helper.VerifyHelper; import pro.gravit.utils.helper.VerifyHelper;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.net.URI; import java.nio.file.InvalidPathException;
import java.net.URISyntaxException;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.time.Clock; import java.time.Clock;
@ -182,12 +182,18 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr
return; 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; final String path;
if (uri == null) {
sendError(ctx, NOT_FOUND);
return;
}
try { try {
path = Paths.get(new URI(uri).getPath()).normalize().toString().substring(1); path = Paths.get(IOHelper.getPathFromUrlFragment(uri)).normalize().toString().substring(1);
} catch (URISyntaxException e) { } catch (InvalidPathException e) {
sendError(ctx, BAD_REQUEST); sendError(ctx, BAD_REQUEST);
return; return;
} }

View file

@ -5,12 +5,15 @@
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem; import java.nio.file.FileSystem;
import java.nio.file.*; import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collections; import java.util.Collections;
import java.util.HexFormat;
import java.util.Set; import java.util.Set;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.jar.Manifest; import java.util.jar.Manifest;
@ -559,6 +562,34 @@ public static String urlEncode(String s) {
return URLEncoder.encode(s, UNICODE_CHARSET); 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) { public static String verifyFileName(String fileName) {
return VerifyHelper.verify(fileName, IOHelper::isValidFileName, String.format("Invalid file name: '%s'", fileName)); return VerifyHelper.verify(fileName, IOHelper::isValidFileName, String.format("Invalid file name: '%s'", fileName));
} }