Skip to content

Commit

Permalink
Support URI proxies
Browse files Browse the repository at this point in the history
Fixes #361
  • Loading branch information
AlexProgrammerDE committed Mar 14, 2024
1 parent 6556137 commit 960c22e
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 65 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,20 @@ ip:port <- no authentication
ip:port:username:password <- authentication
```

#### URI

This format allows you to use multiple proxy types in one file.

<!--suppress HttpUrlsUsage -->
```text
socks5://ip:port <- no authentication
socks5://username:password@ip:port <- authentication
socks4://ip:port <- no authentication
socks4://username@ip:port <- authentication
http://ip:port <- no authentication
http://username:password@ip:port <- authentication
```

## 🧵 Demo

SoulFire has a built-in GUI for easy usage.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import com.soulfiremc.brigadier.GenericTerminalConsole;
import com.soulfiremc.builddata.BuildData;
import com.soulfiremc.client.settings.ProxyParser;
import com.soulfiremc.settings.account.AuthType;
import com.soulfiremc.settings.proxy.ProxyType;
import java.io.IOException;
Expand Down Expand Up @@ -126,12 +127,12 @@ public Integer call() {
}
}

if (proxyFile != null && proxyType != null) {
if (proxyFile != null) {
try {
cliManager
.clientSettingsManager()
.proxyRegistry()
.loadFromString(Files.readString(proxyFile), proxyType);
.loadFromString(Files.readString(proxyFile), proxyType == null ? ProxyParser.uriParser() : ProxyParser.typeParser(proxyType));
} catch (IOException e) {
log.error("Failed to load proxies!", e);
return 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.soulfiremc.client.gui.GUIManager;
import com.soulfiremc.client.gui.libs.JEnumComboBox;
import com.soulfiremc.client.gui.popups.ImportTextDialog;
import com.soulfiremc.client.settings.ProxyParser;
import com.soulfiremc.settings.proxy.ProxyType;
import com.soulfiremc.settings.proxy.SFProxy;
import com.soulfiremc.util.BuiltinSettingsConstants;
Expand Down Expand Up @@ -160,6 +161,7 @@ public void mousePressed(MouseEvent e) {
menu.add(createProxyLoadButton(guiManager, parent, ProxyType.HTTP));
menu.add(createProxyLoadButton(guiManager, parent, ProxyType.SOCKS4));
menu.add(createProxyLoadButton(guiManager, parent, ProxyType.SOCKS5));
menu.add(createURLProxyLoadButton(guiManager, parent));
menu.show(e.getComponent(), e.getX(), e.getY());
}
});
Expand Down Expand Up @@ -193,7 +195,25 @@ private static JMenuItem createProxyLoadButton(
guiManager,
parent,
text ->
guiManager.clientSettingsManager().proxyRegistry().loadFromString(text, type)));
guiManager.clientSettingsManager().proxyRegistry().loadFromString(text, ProxyParser.typeParser(type))));

return button;
}

private static JMenuItem createURLProxyLoadButton(
GUIManager guiManager, GUIFrame parent) {
var button = new JMenuItem("URI");

button.addActionListener(
e ->
new ImportTextDialog(
SFPathConstants.WORKING_DIRECTORY,
"Load URI proxies",
"URI list file",
guiManager,
parent,
text ->
guiManager.clientSettingsManager().proxyRegistry().loadFromString(text, ProxyParser.uriParser())));

return button;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,24 +39,28 @@ public class AccountRegistry {
private final RPCClient rpcClient;

public void loadFromString(String data, AuthType authType, SFProxy proxy) {
var newAccounts =
data.lines()
.map(String::strip)
.filter(line -> !line.isBlank())
.distinct()
.map(account -> fromStringSingle(account, authType, proxy))
.map(account -> new EnabledWrapper<>(true, account))
.toList();

if (newAccounts.isEmpty()) {
log.warn("No accounts found in the provided data!");
return;
}
try {
var newAccounts =
data.lines()
.map(String::strip)
.filter(line -> !line.isBlank())
.distinct()
.map(account -> fromStringSingle(account, authType, proxy))
.map(account -> new EnabledWrapper<>(true, account))
.toList();

if (newAccounts.isEmpty()) {
log.warn("No accounts found in the provided data!");
return;
}

this.accounts.addAll(newAccounts);
callLoadHooks();
this.accounts.addAll(newAccounts);
callLoadHooks();

log.info("Loaded {} accounts!", newAccounts.size());
log.info("Loaded {} accounts!", newAccounts.size());
} catch (Exception e) {
log.error("Failed to load accounts from string!", e);
}
}

private MinecraftAccount fromStringSingle(String data, AuthType authType, SFProxy proxy) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* SoulFire
* Copyright (C) 2024 AlexProgrammerDE
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.soulfiremc.client.settings;

import com.soulfiremc.settings.proxy.ProxyType;
import com.soulfiremc.settings.proxy.SFProxy;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Locale;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public abstract class ProxyParser {
abstract SFProxy parse(String proxyData);

private static <T> T getIndexOrNull(T[] array, int index) {
if (index < array.length) {
return array[index];
} else {
return null;
}
}

public static ProxyParser typeParser(ProxyType type) {
return new ProxyParser() {
@Override
public SFProxy parse(String proxyData) {
var split = proxyData.split(":");

if (split.length < 2) {
throw new IllegalArgumentException("Proxy must have at least a host and a port!");
}

var host = split[0];
var port = Integer.parseInt(split[1]);
var username = getIndexOrNull(split, 2);
var password = getIndexOrNull(split, 3);

return new SFProxy(type, host, port, username, password);
}
};
}

public static ProxyParser uriParser() {
return new ProxyParser() {
@Override
public SFProxy parse(String proxyData) {
URI uri;
try {
uri = URI.create(proxyData).parseServerAuthority();
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}

var scheme = uri.getScheme();

if (scheme == null) {
throw new IllegalArgumentException("Proxy URI must have a scheme!");
}

var proxyType = ProxyType.valueOf(scheme.toUpperCase(Locale.ROOT));
var userInfo = uri.getUserInfo();
var host = uri.getHost();
var port = uri.getPort();

if (host == null || port == -1) {
throw new IllegalArgumentException("Proxy URI must have a host and a port!");
}

String username = null;
String password = null;

if (userInfo != null) {
var split = userInfo.split(":");
username = getIndexOrNull(split, 0);
password = getIndexOrNull(split, 1);
}

return new SFProxy(proxyType, host, port, username, password);
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
*/
package com.soulfiremc.client.settings;

import com.soulfiremc.settings.proxy.ProxyType;
import com.soulfiremc.settings.proxy.SFProxy;
import com.soulfiremc.util.EnabledWrapper;
import java.util.ArrayList;
Expand All @@ -32,56 +31,34 @@ public class ProxyRegistry {
private final List<EnabledWrapper<SFProxy>> proxies = new ArrayList<>();
private final List<Runnable> loadHooks = new ArrayList<>();

private static <T> T getIndexOrNull(T[] array, int index) {
if (index < array.length) {
return array[index];
} else {
return null;
}
}

public void loadFromString(String data, ProxyType proxyType) {
var newProxies =
data.lines()
.map(String::strip)
.filter(line -> !line.isBlank())
.distinct()
.map(line -> fromStringSingle(line, proxyType))
.toList();

if (newProxies.isEmpty()) {
log.warn("No proxies found in the provided data!");
return;
}

this.proxies.addAll(newProxies);
callLoadHooks();

log.info("Loaded {} proxies!", newProxies.size());
}

private EnabledWrapper<SFProxy> fromStringSingle(String data, ProxyType proxyType) {
data = data.trim();

var split = data.split(":");

if (split.length < 2) {
throw new IllegalArgumentException("Proxy must have at least a host and a port!");
}

public void loadFromString(String data, ProxyParser proxyParser) {
try {
var host = split[0];
var port = Integer.parseInt(split[1]);
var username = getIndexOrNull(split, 2);
var password = getIndexOrNull(split, 3);

return new EnabledWrapper<>(true, new SFProxy(proxyType, host, port, username, password));
var newProxies =
data.lines()
.map(String::strip)
.filter(line -> !line.isBlank())
.distinct()
.map(line -> fromStringSingle(line, proxyParser))
.toList();

if (newProxies.isEmpty()) {
log.warn("No proxies found in the provided data!");
return;
}

this.proxies.addAll(newProxies);
callLoadHooks();

log.info("Loaded {} proxies!", newProxies.size());
} catch (Exception e) {
log.error("Failed to load proxy from string.", e);
throw new RuntimeException(e);
log.error("Failed to load proxies from string!", e);
}
}

private EnabledWrapper<SFProxy> fromStringSingle(String data, ProxyParser proxyParser) {
return new EnabledWrapper<>(true, proxyParser.parse(data));
}

public List<EnabledWrapper<SFProxy>> getProxies() {
return Collections.unmodifiableList(proxies);
}
Expand Down

0 comments on commit 960c22e

Please sign in to comment.