mirror of
https://github.com/GravitLauncher/Launcher
synced 2025-05-12 12:06:33 +03:00
[FEATURE] Автоматическое создание ZIP архивов для директорий весом менее 32MB.
This commit is contained in:
parent
493fbf8f2b
commit
e30e749351
28 changed files with 97 additions and 125 deletions
|
@ -31,12 +31,14 @@
|
|||
import java.util.Timer;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import io.netty.handler.logging.LogLevel;
|
||||
import pro.gravit.launcher.Launcher;
|
||||
import pro.gravit.launcher.LauncherConfig;
|
||||
import pro.gravit.launcher.NeedGarbageCollection;
|
||||
import pro.gravit.launcher.hasher.HashedDir;
|
||||
import pro.gravit.launcher.hasher.HashedEntry;
|
||||
import pro.gravit.launcher.hwid.HWIDProvider;
|
||||
import pro.gravit.launcher.managers.ConfigManager;
|
||||
import pro.gravit.launcher.managers.GarbageManager;
|
||||
|
@ -65,7 +67,6 @@
|
|||
import pro.gravit.launchserver.components.Component;
|
||||
import pro.gravit.launchserver.components.RegLimiterComponent;
|
||||
import pro.gravit.launchserver.config.LaunchServerRuntimeConfig;
|
||||
import pro.gravit.launchserver.dao.UserService;
|
||||
import pro.gravit.launchserver.dao.provider.DaoProvider;
|
||||
import pro.gravit.launchserver.manangers.*;
|
||||
import pro.gravit.launchserver.manangers.hook.AuthHookManager;
|
||||
|
@ -457,6 +458,8 @@ public static void main(String... args) throws Throwable {
|
|||
|
||||
public final Timer taskPool;
|
||||
|
||||
public final Path optimizedUpdatesDir;
|
||||
|
||||
public static Class<? extends LauncherBinary> defaultLauncherEXEBinaryClass = null;
|
||||
|
||||
public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException, InvalidKeySpecException {
|
||||
|
@ -485,6 +488,7 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException
|
|||
publicKeyFile = dir.resolve("public.key");
|
||||
privateKeyFile = dir.resolve("private.key");
|
||||
updatesDir = dir.resolve("updates");
|
||||
optimizedUpdatesDir = dir.resolve("optimized_updates");
|
||||
profilesDir = dir.resolve("profiles");
|
||||
|
||||
//Registration handlers and providers
|
||||
|
@ -634,6 +638,9 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException
|
|||
// Sync updates dir
|
||||
if (!IOHelper.isDir(updatesDir))
|
||||
Files.createDirectory(updatesDir);
|
||||
if (!IOHelper.isDir(optimizedUpdatesDir))
|
||||
Files.createDirectory(optimizedUpdatesDir);
|
||||
updatesDirMap = null;
|
||||
syncUpdatesDir(null);
|
||||
|
||||
// Sync profiles dir
|
||||
|
@ -872,6 +879,7 @@ public void syncProfilesDir() throws IOException {
|
|||
|
||||
public void syncUpdatesDir(Collection<String> dirs) throws IOException {
|
||||
LogHelper.info("Syncing updates dir");
|
||||
boolean start = updatesDirMap == null;
|
||||
Map<String, SignedObjectHolder<HashedDir>> newUpdatesDirMap = new HashMap<>(16);
|
||||
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(updatesDir)) {
|
||||
for (final Path updateDir : dirStream) {
|
||||
|
@ -894,17 +902,43 @@ public void syncUpdatesDir(Collection<String> dirs) throws IOException {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Sync and sign update dir
|
||||
LogHelper.info("Syncing '%s' update dir", name);
|
||||
HashedDir updateHDir = new HashedDir(updateDir, null, true, true);
|
||||
if (!start) processUpdate(updateDir, updateHDir, name);
|
||||
newUpdatesDirMap.put(name, new SignedObjectHolder<>(updateHDir, privateKey));
|
||||
}
|
||||
}
|
||||
updatesDirMap = Collections.unmodifiableMap(newUpdatesDirMap);
|
||||
}
|
||||
|
||||
public void restart() {
|
||||
private void processUpdate(Path updateDir, HashedDir updateHDir, String name) throws IOException {
|
||||
updateHDir.walk(IOHelper.CROSS_SEPARATOR, (path, filename, entry) -> {
|
||||
if (entry.getType().equals(HashedEntry.Type.DIR)) {
|
||||
if (entry.size() < IOHelper.MB32) {
|
||||
Path p = updateDir.resolve(path);
|
||||
Path out = optimizedUpdatesDir.resolve(name).resolve(path);
|
||||
try (ZipOutputStream compressed = new ZipOutputStream(IOHelper.newOutput(out))) {
|
||||
IOHelper.walk(p, new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
compressed.putNextEntry(IOHelper.newZipEntry(
|
||||
p.relativize(file).toString()
|
||||
.replace(IOHelper.PLATFORM_SEPARATOR, IOHelper.CROSS_SEPARATOR)));
|
||||
IOHelper.transfer(file, compressed);
|
||||
return super.visitFile(file, attrs);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
return HashedDir.WalkAction.SKIP_DIR;
|
||||
}
|
||||
}
|
||||
return HashedDir.WalkAction.CONTINUE;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void restart() {
|
||||
ProcessBuilder builder = new ProcessBuilder();
|
||||
if (config.startScript != null) builder.command(Collections.singletonList(config.startScript));
|
||||
else throw new IllegalArgumentException("Please create start script and link it as startScript in config.");
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package pro.gravit.launchserver.command.basic;
|
||||
|
||||
import org.bouncycastle.cert.X509CertificateHolder;
|
||||
import pro.gravit.launcher.events.PingEvent;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.command.Command;
|
||||
import pro.gravit.launchserver.socket.handlers.NettyServerSocketHandler;
|
||||
|
@ -9,7 +8,6 @@
|
|||
|
||||
import java.nio.file.Paths;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
|
||||
public class TestCommand extends Command {
|
||||
public TestCommand(LaunchServer server) {
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
|
||||
public class UserService {
|
||||
|
||||
private final UserDAO usersDao;
|
||||
|
|
|
@ -1,22 +1,16 @@
|
|||
package pro.gravit.launchserver.manangers;
|
||||
|
||||
|
||||
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
|
||||
import org.bouncycastle.asn1.x500.X500Name;
|
||||
import org.bouncycastle.asn1.x500.X500NameBuilder;
|
||||
import org.bouncycastle.asn1.x500.style.BCStyle;
|
||||
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
|
||||
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
|
||||
import org.bouncycastle.cert.CertIOException;
|
||||
import org.bouncycastle.cert.X509CertificateHolder;
|
||||
import org.bouncycastle.cert.X509v3CertificateBuilder;
|
||||
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
|
||||
import org.bouncycastle.crypto.params.ECKeyParameters;
|
||||
import org.bouncycastle.crypto.util.PrivateKeyFactory;
|
||||
import org.bouncycastle.crypto.util.PrivateKeyInfoFactory;
|
||||
import org.bouncycastle.jce.ECNamedCurveTable;
|
||||
import org.bouncycastle.jce.spec.ECParameterSpec;
|
||||
import org.bouncycastle.openssl.PEMWriter;
|
||||
import org.bouncycastle.operator.ContentSigner;
|
||||
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
|
||||
import org.bouncycastle.operator.OperatorCreationException;
|
||||
|
@ -27,12 +21,10 @@
|
|||
import pro.gravit.utils.helper.IOHelper;
|
||||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.file.Path;
|
||||
import java.security.*;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.spec.ECGenParameterSpec;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
|
|
|
@ -2,14 +2,11 @@
|
|||
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import pro.gravit.launcher.hasher.HashedEntry;
|
||||
import pro.gravit.launcher.hasher.HashedEntryAdapter;
|
||||
import pro.gravit.launcher.hwid.HWID;
|
||||
import pro.gravit.launcher.hwid.HWIDProvider;
|
||||
import pro.gravit.launcher.managers.GsonManager;
|
||||
import pro.gravit.launcher.request.JsonResultSerializeAdapter;
|
||||
import pro.gravit.launcher.request.WebSocketEvent;
|
||||
import pro.gravit.launcher.request.websockets.ClientWebSocketService;
|
||||
import pro.gravit.launchserver.auth.handler.AuthHandler;
|
||||
import pro.gravit.launchserver.auth.hwid.HWIDHandler;
|
||||
import pro.gravit.launchserver.auth.permissions.PermissionsHandler;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package pro.gravit.launchserver.socket;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Arrays;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
|
@ -63,7 +64,7 @@ public void initChannel(SocketChannel ch) {
|
|||
pipeline.addLast(new WebSocketServerCompressionHandler());
|
||||
pipeline.addLast(new WebSocketServerProtocolHandler(WEBSOCKET_PATH, null, true));
|
||||
if (server.config.netty.fileServerEnabled)
|
||||
pipeline.addLast(new FileServerHandler(server.updatesDir, true));
|
||||
pipeline.addLast(new FileServerHandler(Arrays.asList(server.updatesDir, server.optimizedUpdatesDir)));
|
||||
pipeline.addLast(new WebSocketFrameHandler(context, server, service));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -58,7 +58,8 @@ public WebSocketService(ChannelGroup channels, LaunchServer server) {
|
|||
private static final HashMap<String, Class> responses = new HashMap<>();
|
||||
private final Gson gson;
|
||||
|
||||
public void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client, String ip) {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client, String ip) {
|
||||
String request = frame.text();
|
||||
WebSocketServerResponse response = gson.fromJson(request, WebSocketServerResponse.class);
|
||||
if (server.config.netty.proxy.enabled) {
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
import pro.gravit.launchserver.socket.LauncherNettyServer;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
|
||||
@SuppressWarnings({"unused", "rawtypes"})
|
||||
@SuppressWarnings("unused")
|
||||
public final class NettyServerSocketHandler implements Runnable, AutoCloseable {
|
||||
private SSLServerSocketFactory ssf;
|
||||
private SSLServerSocketFactory ssf;
|
||||
|
||||
public volatile boolean logConnections = Boolean.getBoolean("launcher.logConnections");
|
||||
|
||||
|
|
|
@ -2,22 +2,17 @@
|
|||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.channel.group.DefaultChannelGroup;
|
||||
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
|
||||
import io.netty.util.concurrent.GlobalEventExecutor;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.launchserver.socket.NettyConnectContext;
|
||||
import pro.gravit.launchserver.socket.WebSocketService;
|
||||
import pro.gravit.utils.helper.CommonHelper;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
import static io.netty.handler.codec.http.HttpMethod.GET;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.FORBIDDEN;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.FOUND;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.METHOD_NOT_ALLOWED;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND;
|
||||
|
@ -22,13 +21,13 @@
|
|||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.TimeZone;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.activation.MimetypesFileTypeMap;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
|
@ -48,6 +47,8 @@
|
|||
import io.netty.handler.codec.http.LastHttpContent;
|
||||
import io.netty.handler.stream.ChunkedFile;
|
||||
import io.netty.util.CharsetUtil;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
|
||||
public class FileServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
|
||||
|
||||
|
@ -56,12 +57,10 @@ public class FileServerHandler extends SimpleChannelInboundHandler<FullHttpReque
|
|||
public static final String READ = "r";
|
||||
public static final int HTTP_CACHE_SECONDS = 60;
|
||||
private static final boolean OLD_ALGO = Boolean.parseBoolean(System.getProperty("launcher.fileserver.oldalgo", "true"));
|
||||
private final Path base;
|
||||
private final boolean fullOut;
|
||||
private final List<Path> base;
|
||||
|
||||
public FileServerHandler(Path base, boolean fullOut) {
|
||||
public FileServerHandler(List<Path> base) {
|
||||
this.base = base;
|
||||
this.fullOut = fullOut;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -83,13 +82,13 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr
|
|||
return;
|
||||
}
|
||||
|
||||
File file = base.resolve(path).toFile();
|
||||
if (file.isHidden() || !file.exists()) {
|
||||
Optional<File> fileO = base.stream().map(t -> t.resolve(path)).filter(t -> IOHelper.isFile(t) && !IOHelper.isHidden(t)).map(t -> t.toFile()).findFirst();
|
||||
if (!fileO.isPresent()) {
|
||||
sendError(ctx, NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
if (file.isDirectory()) {
|
||||
File file = fileO.get();
|
||||
/*if (file.isDirectory()) {
|
||||
if (fullOut) {
|
||||
if (uri.endsWith("/")) {
|
||||
sendListing(ctx, file, uri);
|
||||
|
@ -98,12 +97,12 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr
|
|||
}
|
||||
} else sendError(ctx, NOT_FOUND); // can not handle dirs
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (!file.isFile()) {
|
||||
/*if (!file.isFile()) {
|
||||
sendError(ctx, FORBIDDEN);
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
// Cache Validation
|
||||
String ifModifiedSince = request.headers().get(HttpHeaderNames.IF_MODIFIED_SINCE);
|
||||
|
@ -166,14 +165,12 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr
|
|||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
cause.printStackTrace();
|
||||
LogHelper.error(cause);
|
||||
if (ctx.channel().isActive()) {
|
||||
sendError(ctx, INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Pattern INSECURE_URI = Pattern.compile(".*[<>&\"].*");
|
||||
|
||||
private static String sanitizeUri(String uri) {
|
||||
// Decode the path.
|
||||
try {
|
||||
|
@ -192,60 +189,6 @@ private static String sanitizeUri(String uri) {
|
|||
return Paths.get(uri).normalize().toString().substring(1);
|
||||
}
|
||||
|
||||
private static final Pattern ALLOWED_FILE_NAME = Pattern.compile("[^-\\._]?[^<>&\\\"]*");
|
||||
|
||||
private static void sendListing(ChannelHandlerContext ctx, File dir, String dirPath) {
|
||||
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK);
|
||||
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTF-8");
|
||||
|
||||
StringBuilder buf = new StringBuilder()
|
||||
.append("<!DOCTYPE html>\r\n")
|
||||
.append("<html><head><meta charset='utf-8' /><title>")
|
||||
.append("Listing of: ")
|
||||
.append(dirPath)
|
||||
.append("</title></head><body>\r\n")
|
||||
|
||||
.append("<h3>Listing of: ")
|
||||
.append(dirPath)
|
||||
.append("</h3>\r\n")
|
||||
|
||||
.append("<ul>")
|
||||
.append("<li><a href=\"../\">..</a></li>\r\n");
|
||||
|
||||
for (File f : dir.listFiles()) {
|
||||
if (f.isHidden() || !f.canRead()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String name = f.getName();
|
||||
if (!ALLOWED_FILE_NAME.matcher(name).matches()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buf.append("<li><a href=\"")
|
||||
.append(name)
|
||||
.append("\">")
|
||||
.append(name)
|
||||
.append("</a></li>\r\n");
|
||||
}
|
||||
|
||||
buf.append("</ul></body></html>\r\n");
|
||||
ByteBuf buffer = Unpooled.copiedBuffer(buf, CharsetUtil.UTF_8);
|
||||
response.content().writeBytes(buffer);
|
||||
buffer.release();
|
||||
|
||||
// Close the connection as soon as the error message is sent.
|
||||
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
|
||||
}
|
||||
|
||||
private static void sendRedirect(ChannelHandlerContext ctx, String newUri) {
|
||||
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, FOUND);
|
||||
response.headers().set(HttpHeaderNames.LOCATION, newUri);
|
||||
|
||||
// Close the connection as soon as the error message is sent.
|
||||
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
|
||||
}
|
||||
|
||||
private static void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {
|
||||
FullHttpResponse response = new DefaultFullHttpResponse(
|
||||
HTTP_1_1, status, Unpooled.copiedBuffer("Failure: " + status + "\r\n", CharsetUtil.UTF_8));
|
||||
|
|
|
@ -36,10 +36,17 @@ public interface DownloadTotalCallback {
|
|||
public static class DownloadTask {
|
||||
public String apply;
|
||||
public long size;
|
||||
public boolean isZip;
|
||||
|
||||
public DownloadTask(String apply, long size) {
|
||||
this.apply = apply;
|
||||
this.size = size;
|
||||
isZip = false;
|
||||
}
|
||||
public DownloadTask(String apply, long size, boolean isZip) {
|
||||
this.apply = apply;
|
||||
this.size = size;
|
||||
this.isZip = isZip;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +66,7 @@ public void download(String base, List<DownloadTask> applies, Path dstDirFile, D
|
|||
get.reset();
|
||||
get.setURI(u);
|
||||
}
|
||||
httpclient.execute(get, new FileDownloadResponseHandler(targetPath, apply, callback, totalCallback, false));
|
||||
httpclient.execute(get, new FileDownloadResponseHandler(targetPath, apply, callback, totalCallback));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -118,12 +125,12 @@ public FileDownloadResponseHandler(Path target) {
|
|||
totalCallback = null;
|
||||
}
|
||||
|
||||
public FileDownloadResponseHandler(Path target, DownloadTask task, DownloadCallback callback, DownloadTotalCallback totalCallback, boolean zip) {
|
||||
public FileDownloadResponseHandler(Path target, DownloadTask task, DownloadCallback callback, DownloadTotalCallback totalCallback) {
|
||||
this.target = target;
|
||||
this.task = task;
|
||||
this.callback = callback;
|
||||
this.totalCallback = totalCallback;
|
||||
this.zip = zip;
|
||||
this.zip = task != null ? task.isZip : false;
|
||||
}
|
||||
|
||||
public FileDownloadResponseHandler(Path target, DownloadCallback callback, DownloadTotalCallback totalCallback, boolean zip) {
|
||||
|
@ -137,16 +144,6 @@ public FileDownloadResponseHandler(Path target, DownloadCallback callback, Downl
|
|||
@Override
|
||||
public Path handleResponse(HttpResponse response) throws IOException {
|
||||
InputStream source = response.getEntity().getContent();
|
||||
int returnCode = response.getStatusLine().getStatusCode();
|
||||
if(returnCode != 200)
|
||||
{
|
||||
throw new IllegalStateException(String.format("Request download file %s return code %d", target.toString(), returnCode));
|
||||
}
|
||||
long contentLength = response.getEntity().getContentLength();
|
||||
if (task != null && contentLength != task.size)
|
||||
{
|
||||
LogHelper.warning("Missing content length: expected %d | found %d", task.size, contentLength);
|
||||
}
|
||||
if (zip) {
|
||||
try (ZipInputStream input = IOHelper.newZipInput(source)) {
|
||||
ZipEntry entry = input.getNextEntry();
|
||||
|
@ -171,13 +168,14 @@ public Path handleResponse(HttpResponse response) throws IOException {
|
|||
}
|
||||
if (callback != null && task != null) {
|
||||
callback.stateChanged(task.apply, 0, task.size);
|
||||
transfer(source, this.target, task.apply, task.size, callback, totalCallback);
|
||||
transfer(source, target, task.apply, task.size < 0 ? source.available() : task.size, callback, totalCallback);
|
||||
} else
|
||||
IOHelper.transfer(source, this.target);
|
||||
IOHelper.transfer(source, IOHelper.newOutput(target));
|
||||
return this.target;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void transfer(InputStream input, Path file, String filename, long size, DownloadCallback callback, DownloadTotalCallback totalCallback) throws IOException {
|
||||
try (OutputStream fileOutput = IOHelper.newOutput(file)) {
|
||||
long downloaded = 0L;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
//Набор стандартных событий
|
||||
public class ControlEvent {
|
||||
@SuppressWarnings("unused")
|
||||
private static final UUID uuid = UUID.fromString("f1051a64-0cd0-4ed8-8430-d856a196e91f");
|
||||
|
||||
public enum ControlCommand {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package pro.gravit.launcher.events.request;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
import pro.gravit.launcher.LauncherNetworkAPI;
|
||||
import pro.gravit.launcher.events.RequestEvent;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package pro.gravit.launcher.events.request;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import pro.gravit.launcher.LauncherNetworkAPI;
|
||||
import pro.gravit.launcher.events.RequestEvent;
|
||||
import pro.gravit.launcher.profiles.PlayerProfile;
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
|
||||
|
||||
public class CheckServerRequestEvent extends RequestEvent {
|
||||
private static final UUID _uuid = UUID.fromString("8801d07c-51ba-4059-b61d-fe1f1510b28a");
|
||||
@SuppressWarnings("unused")
|
||||
private static final UUID _uuid = UUID.fromString("8801d07c-51ba-4059-b61d-fe1f1510b28a");
|
||||
@LauncherNetworkAPI
|
||||
public UUID uuid;
|
||||
@LauncherNetworkAPI
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
|
||||
public class JoinServerRequestEvent extends RequestEvent {
|
||||
@SuppressWarnings("unused")
|
||||
private static final UUID uuid = UUID.fromString("2a12e7b5-3f4a-4891-a2f9-ea141c8e1995");
|
||||
|
||||
public JoinServerRequestEvent(boolean allow) {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
|
||||
public class LauncherRequestEvent extends RequestEvent {
|
||||
@SuppressWarnings("unused")
|
||||
private static final UUID uuid = UUID.fromString("d54cc12a-4f59-4f23-9b10-f527fdd2e38f");
|
||||
@LauncherNetworkAPI
|
||||
public String url;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
|
||||
public class ProfileByUUIDRequestEvent extends RequestEvent {
|
||||
@SuppressWarnings("unused")
|
||||
private static final UUID uuid = UUID.fromString("b9014cf3-4b95-4d38-8c5f-867f190a18a0");
|
||||
@LauncherNetworkAPI
|
||||
public String error;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
|
||||
public class ProfileByUsernameRequestEvent extends RequestEvent {
|
||||
@SuppressWarnings("unused")
|
||||
private static final UUID uuid = UUID.fromString("06204302-ff6b-4779-b97d-541e3bc39aa1");
|
||||
@LauncherNetworkAPI
|
||||
public String error;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
|
||||
public class ProfilesRequestEvent extends RequestEvent {
|
||||
@SuppressWarnings("unused")
|
||||
private static final UUID uuid = UUID.fromString("2f26fbdf-598a-46dd-92fc-1699c0e173b1");
|
||||
@LauncherNetworkAPI
|
||||
public List<ClientProfile> profiles;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
|
||||
public class SetProfileRequestEvent extends RequestEvent {
|
||||
@SuppressWarnings("unused")
|
||||
private static final UUID uuid = UUID.fromString("08c0de9e-4364-4152-9066-8354a3a48541");
|
||||
@LauncherNetworkAPI
|
||||
public ClientProfile newProfile;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
|
||||
public class UpdateListRequestEvent extends RequestEvent {
|
||||
@SuppressWarnings("unused")
|
||||
private static final UUID uuid = UUID.fromString("5fa836ae-6b61-401c-96ac-d8396f07ec6b");
|
||||
@LauncherNetworkAPI
|
||||
public final HashSet<String> dirs;
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
import pro.gravit.launcher.LauncherAPI;
|
||||
import pro.gravit.launcher.LauncherNetworkAPI;
|
||||
import pro.gravit.launcher.events.request.AuthRequestEvent;
|
||||
import pro.gravit.launcher.hwid.OshiHWID;
|
||||
import pro.gravit.launcher.request.Request;
|
||||
import pro.gravit.launcher.request.websockets.WebSocketRequest;
|
||||
import pro.gravit.utils.helper.VerifyHelper;
|
||||
|
|
|
@ -210,6 +210,10 @@ public UpdateRequestEvent requestDo(StandartClientWebSocketService service) thro
|
|||
} catch (IOException ex) {
|
||||
LogHelper.error(ex);
|
||||
}
|
||||
if (entry.size() < IOHelper.MB32) {
|
||||
adds.add(new ListDownloader.DownloadTask(path, -1, true));
|
||||
return HashedDir.WalkAction.SKIP_DIR;
|
||||
}
|
||||
}
|
||||
return HashedDir.WalkAction.CONTINUE;
|
||||
});
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
|
|
|
@ -7,13 +7,10 @@
|
|||
|
||||
import javax.net.ssl.SSLException;
|
||||
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import pro.gravit.launcher.events.request.ErrorRequestEvent;
|
||||
import pro.gravit.launcher.request.Request;
|
||||
import pro.gravit.launcher.request.RequestException;
|
||||
import pro.gravit.launcher.request.WebSocketEvent;
|
||||
import pro.gravit.utils.helper.CommonHelper;
|
||||
import pro.gravit.utils.helper.JVMHelper;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
|
||||
|
|
|
@ -350,7 +350,7 @@ public void walk(CharSequence separator, WalkCallback callback) throws IOExcepti
|
|||
}
|
||||
|
||||
public enum WalkAction {
|
||||
STOP, CONTINUE
|
||||
STOP, SKIP_DIR, CONTINUE
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
|
@ -375,7 +375,9 @@ private WalkAction walk(String append, CharSequence separator, WalkCallback call
|
|||
else newAppend = append + separator + entry.getKey();
|
||||
WalkAction a = callback.walked(newAppend, entry.getKey(), e);
|
||||
if (a == WalkAction.STOP) return a;
|
||||
a = ((HashedDir) e).walk(newAppend, separator, callback, false);
|
||||
if (a == WalkAction.CONTINUE)
|
||||
a = ((HashedDir) e).walk(newAppend, separator, callback, false);
|
||||
else a = WalkAction.CONTINUE; // skip
|
||||
if (a == WalkAction.STOP) return a;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -297,6 +297,15 @@ public static boolean isFile(Path path) {
|
|||
return Files.isRegularFile(path, LINK_OPTIONS);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static boolean isHidden(Path path) {
|
||||
try {
|
||||
return Files.isHidden(path);
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static boolean isValidFileName(String fileName) {
|
||||
return !fileName.equals(".") && !fileName.equals("..") &&
|
||||
|
|
Loading…
Reference in a new issue