├── .github ├── dependabot.yml └── images │ ├── logo.png │ └── ui.png ├── .gitignore ├── CHANGELOG ├── LICENSE ├── README.md ├── VERSION ├── build.gradle ├── core ├── .gitignore ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── github │ └── krlvm │ └── powertunnel │ ├── BuildConstants.java │ ├── LittleProxyServer.java │ ├── PowerTunnel.java │ ├── adapters │ ├── ProxyFiltersSourceAdapter.java │ └── UpstreamChainedProxyAdapter.java │ ├── callbacks │ └── InputStreamConsumer.java │ ├── configuration │ └── ConfigurationStore.java │ ├── exceptions │ ├── ConfigurationParseException.java │ └── PreferenceParseException.java │ ├── filters │ └── ProxyFilter.java │ ├── http │ ├── LHttpHeaders.java │ ├── LProxyMessage.java │ ├── LProxyRequest.java │ └── LProxyResponse.java │ ├── i18n │ ├── I18NBundle.java │ └── UTF8Control.java │ ├── listener │ ├── CoreProxyListener.java │ ├── ProxyListenerCallback.java │ ├── ProxyListenerInfo.java │ └── ServerListenerCallback.java │ ├── managers │ ├── ProxyAuthenticationManager.java │ └── UpstreamProxyChainedProxyManager.java │ ├── mitm │ └── MITMAuthority.java │ ├── plugin │ ├── PluginInjector.java │ └── PluginLoader.java │ ├── preferences │ ├── Preference.java │ ├── PreferenceGroup.java │ ├── PreferenceParser.java │ └── PreferenceType.java │ ├── resolver │ ├── DNSResolverWrapper.java │ └── LDNSResolver.java │ └── utilities │ └── JarLoader.java ├── desktop ├── .gitignore ├── build.gradle ├── libs │ └── swingdpi-1.2.jar └── src │ └── main │ ├── java │ └── io │ │ └── github │ │ └── krlvm │ │ └── powertunnel │ │ └── desktop │ │ ├── BuildConstants.java │ │ ├── Main.java │ │ ├── application │ │ ├── ConsoleApp.java │ │ ├── DesktopApp.java │ │ └── GraphicalApp.java │ │ ├── configuration │ │ ├── AdvancedConfiguration.java │ │ └── ServerConfiguration.java │ │ ├── frames │ │ ├── AppFrame.java │ │ ├── MainFrame.java │ │ ├── OptionsFrame.java │ │ ├── PluginsFrame.java │ │ └── PreferencesFrame.java │ │ ├── managers │ │ ├── ApplicationManager.java │ │ ├── ConsoleHandler.java │ │ └── TrayManager.java │ │ ├── parser │ │ └── ArgumentParser.java │ │ ├── system │ │ ├── ConsoleReader.java │ │ ├── SystemProxy.java │ │ └── windows │ │ │ ├── WindowsProxyHandler.java │ │ │ └── Wininet.java │ │ ├── types │ │ ├── ConsoleCommand.java │ │ └── TrayMode.java │ │ ├── ui │ │ ├── ComboBoxScroll.java │ │ ├── FieldFilter.java │ │ ├── I18N.java │ │ ├── PluginInfoRenderer.java │ │ ├── ScrollablePanel.java │ │ ├── SelectPreferenceRenderer.java │ │ └── TextRightClickPopup.java │ │ ├── updater │ │ ├── UpdateInfo.java │ │ └── UpdateNotifier.java │ │ └── utilities │ │ ├── SystemUtility.java │ │ ├── UIUtility.java │ │ └── Utility.java │ └── resources │ ├── icon.png │ ├── icon_dev.png │ ├── locale │ ├── messages_en.properties │ └── messages_ru.properties │ ├── log4j2.xml │ └── plugins │ ├── DNSResolver.jar │ └── LibertyTunnel.jar ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── littleproxy ├── .gitignore ├── build.gradle └── src │ └── main │ └── java │ ├── io │ └── netty │ │ └── handler │ │ └── codec │ │ └── http │ │ └── HttpMethod.java │ ├── java │ └── nio │ │ └── charset │ │ └── StandardCharsets.java │ └── org │ └── littleshoot │ └── proxy │ ├── HttpFilters.java │ ├── HttpFiltersAdapter.java │ ├── impl │ ├── CategorizedThreadFactory.java │ ├── ClientToProxyConnection.java │ └── ProxyToServerConnection.java │ └── mitm │ ├── Authority.java │ ├── BouncyCastleSslEngineSource.java │ ├── CertificateHelper.java │ ├── CertificateSniffingMitmManager.java │ ├── FakeCertificateException.java │ ├── MergeTrustManager.java │ ├── MitmHelper.java │ ├── RootCertificateException.java │ └── SubjectAlternativeNameHolder.java ├── sample-plugin ├── .gitignore ├── build.gradle └── src │ └── main │ ├── java │ └── io │ │ └── github │ │ └── krlvm │ │ └── powertunnel │ │ └── plugins │ │ └── sample │ │ └── SamplePlugin.java │ └── resources │ ├── locale │ ├── messages_en.properties │ └── messages_ru.properties │ ├── plugin.ini │ └── preferences.json ├── sdk ├── .gitignore ├── build.gradle ├── libs │ └── android-base64.jar └── src │ └── main │ └── java │ └── io │ └── github │ └── krlvm │ └── powertunnel │ └── sdk │ ├── PowerTunnelServer.java │ ├── ServerAdapter.java │ ├── ServerListener.java │ ├── configuration │ └── Configuration.java │ ├── exceptions │ ├── ConfigurationLoadException.java │ ├── PluginLoadException.java │ └── ProxyStartException.java │ ├── http │ ├── HttpHeaders.java │ ├── HttpMethod.java │ ├── ProxyMessage.java │ ├── ProxyRequest.java │ └── ProxyResponse.java │ ├── plugin │ ├── IPowerTunnelPlugin.java │ ├── PluginInfo.java │ └── PowerTunnelPlugin.java │ ├── proxy │ ├── DNSRequest.java │ ├── DNSResolver.java │ ├── ProxyAdapter.java │ ├── ProxyAddress.java │ ├── ProxyCredentials.java │ ├── ProxyListener.java │ ├── ProxyServer.java │ ├── ProxyStatus.java │ └── UpstreamProxyServer.java │ ├── types │ ├── FullAddress.java │ ├── PowerTunnelPlatform.java │ ├── UpstreamProxyType.java │ └── VersionInfo.java │ └── utiities │ ├── Base64Compat.java │ └── TextReader.java ├── settings.gradle └── version.txt /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: gradle 9 | directory: "/" 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /.github/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krlvm/PowerTunnel/3e5df1e6ce4e12628fee4e2b940e4db9067cde3c/.github/images/logo.png -------------------------------------------------------------------------------- /.github/images/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krlvm/PowerTunnel/3e5df1e6ce4e12628fee4e2b940e4db9067cde3c/.github/images/ui.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Idea Files 2 | /.idea/ 3 | /PowerTunnel.iml 4 | 5 | # Build Files 6 | /build/ 7 | /.gradle/ 8 | 9 | key.properties 10 | keystore.jks -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krlvm/PowerTunnel/3e5df1e6ce4e12628fee4e2b940e4db9067cde3c/CHANGELOG -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 100;2.0 -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | plugins { 19 | id 'idea' 20 | } 21 | 22 | subprojects { 23 | apply plugin: 'java' 24 | 25 | group 'io.github.krlvm.powertunnel' 26 | 27 | ext { 28 | isReleaseVersion = !version.endsWith('SNAPSHOT') 29 | } 30 | 31 | java { 32 | sourceCompatibility = JavaVersion.VERSION_1_8 33 | targetCompatibility = JavaVersion.VERSION_1_8 34 | } 35 | tasks.withType(JavaCompile) { 36 | options.encoding = 'UTF-8' 37 | options.compilerArgs += ['-Xlint:deprecation'] 38 | } 39 | 40 | repositories { 41 | mavenCentral() 42 | } 43 | 44 | test { 45 | useJUnitPlatform() 46 | } 47 | } -------------------------------------------------------------------------------- /core/.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | -------------------------------------------------------------------------------- /core/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | plugins { 19 | id 'java-library' 20 | id 'application' 21 | } 22 | 23 | version '2.5.2' 24 | 25 | configurations { 26 | runtimeClasspath { 27 | exclude group: 'com.google.guava', module: 'guava' 28 | } 29 | } 30 | task fatJar(type: Jar, group: 'build', description: 'Assembles a jar archive containing the main classes and all dependencies.') { 31 | archiveClassifier = 'all' 32 | duplicatesStrategy DuplicatesStrategy.EXCLUDE 33 | 34 | from { 35 | configurations.runtimeClasspath.findAll {it.name.endsWith('jar') }.collect { zipTree(it) } 36 | } { 37 | exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA' 38 | } 39 | 40 | with jar 41 | } 42 | 43 | dependencies { 44 | api project(':sdk') 45 | api project(':littleproxy') 46 | api 'org.jetbrains:annotations:23.0.0' 47 | implementation 'com.google.code.gson:gson:2.8.9' 48 | 49 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2' 50 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2' 51 | } -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/BuildConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel; 19 | 20 | public class BuildConstants { 21 | public static final String NAME = "PowerTunnel"; 22 | public static final String REPO = "https://github.com/krlvm/PowerTunnel"; 23 | public static final String VERSION = "2.5.2"; 24 | public static final int VERSION_CODE = 110; 25 | public static final int SDK = 110; 26 | 27 | public static boolean IS_RELEASE = isReleaseVersion(VERSION); 28 | public static final boolean DEBUG = !IS_RELEASE; 29 | 30 | public static boolean isReleaseVersion(final String version) { 31 | return !( 32 | version.contains("-dev") || 33 | version.contains("-alpha") || 34 | version.contains("-beta") || 35 | version.contains("-preview") || 36 | version.contains("-rc") 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/adapters/ProxyFiltersSourceAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.adapters; 19 | 20 | import io.github.krlvm.powertunnel.filters.ProxyFilter; 21 | import io.github.krlvm.powertunnel.sdk.proxy.ProxyListener; 22 | import io.netty.channel.ChannelHandlerContext; 23 | import io.netty.handler.codec.http.HttpRequest; 24 | import org.littleshoot.proxy.HttpFilters; 25 | import org.littleshoot.proxy.HttpFiltersSourceAdapter; 26 | 27 | public class ProxyFiltersSourceAdapter extends HttpFiltersSourceAdapter { 28 | 29 | private final ProxyListener listener; 30 | private final boolean isFullRequest, isFullResponse; 31 | 32 | public ProxyFiltersSourceAdapter(ProxyListener listener, boolean isFullRequest, boolean isFullResponse) { 33 | this.listener = listener; 34 | this.isFullRequest = isFullRequest; 35 | this.isFullResponse = isFullResponse; 36 | } 37 | 38 | @Override 39 | public HttpFilters filterRequest(HttpRequest originalRequest) { 40 | return new ProxyFilter(this.listener, originalRequest); 41 | } 42 | 43 | @Override 44 | public HttpFilters filterRequest(HttpRequest originalRequest, ChannelHandlerContext ctx) { 45 | return new ProxyFilter(this.listener, originalRequest/*, ctx*/); 46 | } 47 | 48 | @Override 49 | public int getMaximumRequestBufferSizeInBytes() { 50 | return this.isFullRequest ? 10 * 1024 * 1024 : super.getMaximumResponseBufferSizeInBytes(); 51 | } 52 | 53 | @Override 54 | public int getMaximumResponseBufferSizeInBytes() { 55 | return this.isFullResponse ? 10 * 1024 * 1024 : super.getMaximumResponseBufferSizeInBytes(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/callbacks/InputStreamConsumer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.callbacks; 19 | 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | 23 | public interface InputStreamConsumer { 24 | void accept(InputStream inputStream) throws IOException; 25 | } 26 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/configuration/ConfigurationStore.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.configuration; 19 | 20 | import io.github.krlvm.powertunnel.sdk.configuration.Configuration; 21 | 22 | import java.io.*; 23 | import java.nio.charset.StandardCharsets; 24 | import java.util.Collection; 25 | import java.util.HashMap; 26 | import java.util.Map; 27 | import java.util.Set; 28 | 29 | public class ConfigurationStore implements Configuration { 30 | 31 | private static final String DELIMITER = ": "; 32 | private static final int DELIMITER_LENGTH = DELIMITER.length(); 33 | 34 | protected final Map data = new HashMap<>(); 35 | 36 | public void read(File file) throws IOException { 37 | file.createNewFile(); 38 | this.read(new FileReader(file)); 39 | } 40 | 41 | public void read(InputStream in) throws IOException { 42 | this.read(new InputStreamReader(in, StandardCharsets.UTF_8)); 43 | } 44 | 45 | public void read(Reader source) throws IOException { 46 | data.clear(); 47 | 48 | try(BufferedReader reader = new BufferedReader(source)) { 49 | String line; 50 | while((line = reader.readLine()) != null) { 51 | final int pos = line.indexOf(DELIMITER); 52 | if (pos == -1) continue; 53 | data.put( 54 | line.substring(0, pos), 55 | line.substring(pos + DELIMITER_LENGTH) 56 | ); 57 | } 58 | } 59 | } 60 | 61 | public void save(File file) throws IOException { 62 | int current = 0; 63 | try(BufferedWriter writer = new BufferedWriter(new FileWriter(file))) { 64 | for (Map.Entry entry : entries()) { 65 | writer.write(entry.getKey() + DELIMITER + entry.getValue()); 66 | if (++current != data.size()) { 67 | writer.write("\r\n"); 68 | } 69 | } 70 | writer.flush(); 71 | } 72 | } 73 | 74 | protected Set> entries() { 75 | return data.entrySet(); 76 | } 77 | 78 | @Override 79 | public String get(String key, String defaultValue) { 80 | if (!data.containsKey(key)) set(key, defaultValue); 81 | return data.get(key); 82 | } 83 | 84 | @Override 85 | public void set(String key, String value) { 86 | data.put(key, value); 87 | } 88 | 89 | @Override 90 | public int getInt(String key, int defaultValue) { 91 | if (!data.containsKey(key)) setInt(key, defaultValue); 92 | return Integer.parseInt(data.get(key)); 93 | } 94 | 95 | @Override 96 | public void setInt(String key, int value) { 97 | data.put(key, String.valueOf(value)); 98 | } 99 | 100 | @Override 101 | public long getLong(String key, long defaultValue) { 102 | if (!data.containsKey(key)) setLong(key, defaultValue); 103 | return Long.parseLong(data.get(key)); 104 | } 105 | 106 | @Override 107 | public void setLong(String key, long value) { 108 | data.put(key, String.valueOf(value)); 109 | } 110 | 111 | @Override 112 | public boolean getBoolean(String key, boolean defaultValue) { 113 | if (!data.containsKey(key)) setBoolean(key, defaultValue); 114 | return Boolean.parseBoolean(data.get(key)); 115 | } 116 | 117 | @Override 118 | public void setBoolean(String key, boolean value) { 119 | data.put(key, String.valueOf(value)); 120 | } 121 | 122 | @Override 123 | public boolean contains(String key) { 124 | return data.containsKey(key); 125 | } 126 | 127 | @Override 128 | public void remove(String key) { 129 | data.remove(key); 130 | } 131 | 132 | @Override 133 | public Map toMap() { 134 | return data; 135 | } 136 | 137 | @Override 138 | public Collection keys() { 139 | return data.keySet(); 140 | } 141 | 142 | @Override 143 | public void clear() { 144 | data.clear(); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/exceptions/ConfigurationParseException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.exceptions; 19 | 20 | public class ConfigurationParseException extends Exception { 21 | 22 | public ConfigurationParseException(String message) { 23 | super(message); 24 | } 25 | 26 | public ConfigurationParseException(Throwable cause) { 27 | super(cause); 28 | } 29 | 30 | public ConfigurationParseException(String message, Throwable cause) { 31 | super(message, cause); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/exceptions/PreferenceParseException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.exceptions; 19 | 20 | public class PreferenceParseException extends Exception { 21 | 22 | private final String source; 23 | 24 | public PreferenceParseException(String source, String message) { 25 | this(source, message, null); 26 | } 27 | 28 | public PreferenceParseException(String source, String message, Throwable cause) { 29 | super(message, cause); 30 | this.source = source; 31 | } 32 | 33 | public String getSource() { 34 | return source; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/filters/ProxyFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.filters; 19 | 20 | import io.github.krlvm.powertunnel.http.LProxyRequest; 21 | import io.github.krlvm.powertunnel.http.LProxyResponse; 22 | import io.github.krlvm.powertunnel.sdk.proxy.ProxyListener; 23 | import io.github.krlvm.powertunnel.sdk.types.FullAddress; 24 | import io.netty.channel.ChannelHandlerContext; 25 | import io.netty.handler.codec.http.HttpObject; 26 | import io.netty.handler.codec.http.HttpRequest; 27 | import io.netty.handler.codec.http.HttpResponse; 28 | import org.littleshoot.proxy.HttpFiltersAdapter; 29 | 30 | public class ProxyFilter extends HttpFiltersAdapter { 31 | 32 | private final ProxyListener listener; 33 | private FullAddress address; 34 | 35 | public ProxyFilter(ProxyListener listener, HttpRequest originalRequest) { 36 | this(listener, originalRequest, null); 37 | } 38 | 39 | public ProxyFilter(ProxyListener listener, HttpRequest originalRequest, ChannelHandlerContext ctx) { 40 | super(originalRequest, ctx); 41 | this.listener = listener; 42 | } 43 | 44 | @Override 45 | public void saveAddress(String hostAndPort, boolean isCONNECT) { 46 | this.address = FullAddress.fromString(hostAndPort, isCONNECT ? 443 : 80); 47 | } 48 | 49 | @Override 50 | public HttpResponse clientToProxyRequest(HttpObject httpObject) { 51 | if(!(httpObject instanceof HttpRequest)) return null; 52 | LProxyRequest req = new LProxyRequest(((HttpRequest) httpObject), address); 53 | listener.onClientToProxyRequest(req); 54 | return req.getLittleProxyResponse(); 55 | } 56 | 57 | @Override 58 | public HttpResponse proxyToServerRequest(HttpObject httpObject) { 59 | if(!(httpObject instanceof HttpRequest)) return null; 60 | LProxyRequest req = new LProxyRequest(((HttpRequest) httpObject), address); 61 | listener.onProxyToServerRequest(req); 62 | return req.getLittleProxyResponse(); 63 | } 64 | 65 | @Override 66 | public HttpObject serverToProxyResponse(HttpObject httpObject) { 67 | if(!(httpObject instanceof HttpResponse)) return httpObject; 68 | LProxyResponse res = new LProxyResponse(((HttpResponse) httpObject), address); 69 | listener.onServerToProxyResponse(res); 70 | return res.getLittleProxyObject(); 71 | } 72 | 73 | @Override 74 | public HttpObject proxyToClientResponse(HttpObject httpObject) { 75 | if(!(httpObject instanceof HttpResponse)) return httpObject; 76 | LProxyResponse res = new LProxyResponse(((HttpResponse) httpObject), address); 77 | listener.onProxyToClientResponse(res); 78 | return res.getLittleProxyObject(); 79 | } 80 | 81 | @Override 82 | public int chunkSize() { 83 | return listener.onGetChunkSize(address); 84 | } 85 | 86 | @Override 87 | public boolean fullChunking() { 88 | return listener.isFullChunking(address); 89 | } 90 | 91 | @Override 92 | public String mitmGetSNI(String hostname) { 93 | return (String)listener.onGetSNI(hostname); 94 | } 95 | 96 | @Override 97 | public boolean proxyToServerAllowMitm() { 98 | return listener.isMITMAllowed(address); 99 | } 100 | 101 | static { 102 | System.setProperty("sun.net.http.allowRestrictedHeaders", "true"); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/http/LHttpHeaders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.http; 19 | 20 | import io.github.krlvm.powertunnel.sdk.http.HttpHeaders; 21 | import org.jetbrains.annotations.NotNull; 22 | import org.jetbrains.annotations.Nullable; 23 | 24 | import java.util.Set; 25 | 26 | public class LHttpHeaders implements HttpHeaders { 27 | 28 | private final io.netty.handler.codec.http.HttpHeaders headers; 29 | 30 | public LHttpHeaders(io.netty.handler.codec.http.HttpHeaders headers) { 31 | this.headers = headers; 32 | } 33 | 34 | @Override 35 | public @Nullable String get(String name) { 36 | return headers.get(name); 37 | } 38 | 39 | @Override 40 | public void set(@NotNull String name, @NotNull String value) { 41 | headers.set(name, value); 42 | } 43 | 44 | @Override 45 | public @Nullable Integer getInt(String name) { 46 | return headers.getInt(name); 47 | } 48 | 49 | @Override 50 | public void setInt(@NotNull String name, int value) { 51 | headers.setInt(name, value); 52 | } 53 | 54 | @Override 55 | public @Nullable Short getShort(String name) { 56 | return headers.getShort(name); 57 | } 58 | 59 | @Override 60 | public void setShort(@NotNull String name, short value) { 61 | headers.setShort(name, value); 62 | } 63 | 64 | @Override 65 | public @NotNull Set names() { 66 | return headers.names(); 67 | } 68 | 69 | @Override 70 | public boolean contains(@NotNull String name) { 71 | return headers.contains(name); 72 | } 73 | 74 | @Override 75 | public void remove(@NotNull String name) { 76 | headers.remove(name); 77 | } 78 | 79 | @Override 80 | public boolean isEmpty() { 81 | return headers.isEmpty(); 82 | } 83 | 84 | @Override 85 | public int size() { 86 | return headers.size(); 87 | } 88 | 89 | @Override 90 | public String toString() { 91 | return headers.toString(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/http/LProxyMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.http; 19 | 20 | import io.github.krlvm.powertunnel.sdk.http.HttpHeaders; 21 | import io.github.krlvm.powertunnel.sdk.http.ProxyMessage; 22 | import io.github.krlvm.powertunnel.sdk.types.FullAddress; 23 | import org.jetbrains.annotations.NotNull; 24 | import org.jetbrains.annotations.Nullable; 25 | 26 | public abstract class LProxyMessage implements ProxyMessage { 27 | 28 | protected T httpObject; 29 | protected HttpHeaders headers; 30 | 31 | protected final FullAddress address; 32 | 33 | protected LProxyMessage(T httpObject, FullAddress address) { 34 | this.httpObject = httpObject; 35 | this.address = address; 36 | } 37 | 38 | @Override 39 | public @Nullable FullAddress address() { 40 | return address; 41 | } 42 | 43 | @Override 44 | public @NotNull HttpHeaders headers() { 45 | if(headers == null) headers = new LHttpHeaders(this.getHeaders()); 46 | return headers; 47 | } 48 | 49 | protected abstract io.netty.handler.codec.http.HttpHeaders getHeaders(); 50 | 51 | public T getLittleProxyObject() { 52 | return httpObject; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/http/LProxyRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.http; 19 | 20 | import io.github.krlvm.powertunnel.sdk.http.HttpMethod; 21 | import io.github.krlvm.powertunnel.sdk.http.ProxyRequest; 22 | import io.github.krlvm.powertunnel.sdk.http.ProxyResponse; 23 | import io.github.krlvm.powertunnel.sdk.types.FullAddress; 24 | import io.netty.buffer.ByteBuf; 25 | import io.netty.buffer.ByteBufUtil; 26 | import io.netty.buffer.Unpooled; 27 | import io.netty.handler.codec.http.*; 28 | import org.jetbrains.annotations.NotNull; 29 | import org.jetbrains.annotations.Nullable; 30 | 31 | public class LProxyRequest extends LProxyMessage implements ProxyRequest { 32 | 33 | private ProxyResponse response; 34 | 35 | public LProxyRequest(HttpRequest request, FullAddress address) { 36 | super(request, address); 37 | } 38 | 39 | @Override 40 | public @NotNull HttpMethod getMethod() { 41 | return HttpMethod.valueOf(httpObject.method().name()); 42 | } 43 | 44 | @Override 45 | public void setMethod(@NotNull HttpMethod method) { 46 | httpObject.setMethod(io.netty.handler.codec.http.HttpMethod.valueOf(method.name())); 47 | } 48 | 49 | @Override 50 | public void setMethod(@NotNull String method) { 51 | httpObject.setMethod(new io.netty.handler.codec.http.HttpMethod(method)); 52 | } 53 | 54 | @Override 55 | public boolean isEncrypted() { 56 | return httpObject.method() == io.netty.handler.codec.http.HttpMethod.CONNECT; 57 | } 58 | 59 | @Override 60 | public void setBlocked(boolean blocked) { 61 | if (blocked) { 62 | setResponse(new LProxyResponse.Builder("Access denied by proxy server", 403) 63 | .contentType("text/plain") 64 | .build() 65 | ); 66 | } else { 67 | this.response = null; 68 | } 69 | } 70 | 71 | @Override 72 | public boolean isBlocked() { 73 | return this.response != null; 74 | } 75 | 76 | @Override 77 | public @NotNull String getUri() { 78 | return httpObject.uri(); 79 | } 80 | 81 | @Override 82 | public void setUri(@NotNull String uri) { 83 | httpObject.setUri(uri); 84 | } 85 | 86 | @Override 87 | public @Nullable ProxyResponse getResponse() { 88 | return this.response; 89 | } 90 | 91 | @Override 92 | public void setResponse(@NotNull ProxyResponse response) { 93 | this.response = response; 94 | } 95 | 96 | @Override 97 | public boolean isDataPacket() { 98 | return httpObject instanceof FullHttpRequest; 99 | } 100 | 101 | @Override 102 | public byte[] content() { 103 | if(!isDataPacket()) throw new IllegalStateException("Can't get raw content of HttpRequest chunk"); 104 | 105 | final ByteBuf buf = ((FullHttpRequest) httpObject).content(); 106 | return ByteBufUtil.getBytes(buf, 0, buf.readableBytes(), false); 107 | } 108 | 109 | @Override 110 | public void setContent(byte[] content) { 111 | if(!isDataPacket()) throw new IllegalStateException("Can't set raw content of HttpRequest chunk"); 112 | 113 | final HttpRequest response = new DefaultFullHttpRequest( 114 | httpObject.protocolVersion(), 115 | httpObject.method(), 116 | httpObject.uri(), 117 | Unpooled.wrappedBuffer(content)); 118 | response.headers().set(httpObject.headers()); 119 | 120 | response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.length); 121 | 122 | httpObject = response; 123 | } 124 | 125 | @Override 126 | protected HttpHeaders getHeaders() { 127 | return httpObject.headers(); 128 | } 129 | 130 | public HttpResponse getLittleProxyResponse() { 131 | if(this.response == null) return null; 132 | return ((LProxyResponse) this.response).getLittleProxyObject(); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/http/LProxyResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.http; 19 | 20 | import io.github.krlvm.powertunnel.sdk.http.ProxyResponse; 21 | import io.github.krlvm.powertunnel.sdk.types.FullAddress; 22 | import io.netty.buffer.ByteBuf; 23 | import io.netty.buffer.ByteBufUtil; 24 | import io.netty.buffer.Unpooled; 25 | import io.netty.handler.codec.http.*; 26 | 27 | import java.nio.charset.StandardCharsets; 28 | 29 | public class LProxyResponse extends LProxyMessage implements ProxyResponse { 30 | 31 | public LProxyResponse(HttpResponse response, FullAddress address) { 32 | super(response, address); 33 | } 34 | 35 | @Override 36 | public int code() { 37 | return httpObject.status().code(); 38 | } 39 | 40 | @Override 41 | public void setCode(int code) { 42 | httpObject.setStatus(HttpResponseStatus.valueOf(code)); 43 | } 44 | 45 | @Override 46 | public boolean isDataPacket() { 47 | return httpObject instanceof FullHttpResponse; 48 | } 49 | 50 | @Override 51 | public byte[] content() { 52 | if(!isDataPacket()) throw new IllegalStateException("Can't get raw content of HttpResponse chunk"); 53 | 54 | final ByteBuf buf = ((FullHttpResponse) httpObject).content(); 55 | return ByteBufUtil.getBytes(buf, 0, buf.readableBytes(), false); 56 | } 57 | 58 | @Override 59 | public void setContent(byte[] content) { 60 | if(!isDataPacket()) throw new IllegalStateException("Can't set raw content of HttpResponse chunk"); 61 | 62 | final HttpResponse response = new DefaultFullHttpResponse( 63 | httpObject.protocolVersion(), 64 | httpObject.status(), 65 | Unpooled.wrappedBuffer(content)); 66 | response.headers().set(httpObject.headers()); 67 | 68 | response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.length); 69 | 70 | httpObject = response; 71 | } 72 | 73 | @Override 74 | protected HttpHeaders getHeaders() { 75 | return httpObject.headers(); 76 | } 77 | 78 | public static class Builder implements ProxyResponse.Builder { 79 | 80 | private final DefaultFullHttpResponse response; 81 | 82 | public Builder(String content) { 83 | this(HttpResponseStatus.OK, content); 84 | } 85 | 86 | public Builder(String content, int code) { 87 | this(HttpResponseStatus.valueOf(code), content); 88 | } 89 | 90 | public Builder(HttpResponseStatus status, String content) { 91 | final byte[] bytes = content.getBytes(StandardCharsets.UTF_8); 92 | response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, Unpooled.wrappedBuffer(bytes)); 93 | response.headers().set(HttpHeaderNames.CONTENT_LENGTH, bytes.length); 94 | response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE); 95 | } 96 | 97 | @Override 98 | public ProxyResponse.Builder code(int code) { 99 | response.setStatus(HttpResponseStatus.valueOf(code)); 100 | return this; 101 | } 102 | 103 | @Override 104 | public ProxyResponse.Builder contentType(String contentType) { 105 | response.headers().set(HttpHeaderNames.CONTENT_TYPE, contentType + "; charset=UTF-8"); 106 | return this; 107 | } 108 | 109 | @Override 110 | public ProxyResponse.Builder header(String name, String value) { 111 | response.headers().set(name, value); 112 | return this; 113 | } 114 | 115 | @Override 116 | public ProxyResponse.Builder header(String name, int value) { 117 | response.headers().setInt(name, value); 118 | return this; 119 | } 120 | 121 | @Override 122 | public ProxyResponse.Builder header(String name, short value) { 123 | response.headers().setShort(name, value); 124 | return this; 125 | } 126 | 127 | @Override 128 | public ProxyResponse build() { 129 | return new LProxyResponse(response, null); 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/i18n/I18NBundle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.i18n; 19 | 20 | import java.util.ResourceBundle; 21 | 22 | public class I18NBundle { 23 | 24 | private final ResourceBundle bundle; 25 | 26 | public I18NBundle(ResourceBundle bundle) { 27 | this.bundle = bundle; 28 | } 29 | 30 | public String get(String key) { 31 | return get(key, "Missing locale"); 32 | } 33 | 34 | public String get(String key, String defaultValue) { 35 | if(bundle == null || !bundle.containsKey(key)) return defaultValue; 36 | return bundle.getString(key); 37 | } 38 | 39 | public static String getLocalePath(String lang) { 40 | return "locale/messages_" + (lang != null ? lang : "en"); 41 | } 42 | public static String getLocaleFilePath(String lang) { 43 | return getLocalePath(lang) + ".properties"; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/i18n/UTF8Control.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.i18n; 19 | 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.io.InputStreamReader; 23 | import java.net.URL; 24 | import java.net.URLConnection; 25 | import java.nio.charset.StandardCharsets; 26 | import java.util.Locale; 27 | import java.util.PropertyResourceBundle; 28 | import java.util.ResourceBundle; 29 | 30 | // https://stackoverflow.com/a/4660195 31 | public class UTF8Control extends ResourceBundle.Control { 32 | 33 | @Override 34 | public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) 35 | throws IOException { 36 | 37 | final String bundleName = toBundleName(baseName, locale); 38 | final String resourceName = toResourceName(bundleName, "properties"); 39 | 40 | ResourceBundle bundle = null; 41 | InputStream stream = null; 42 | if (reload) { 43 | final URL url = loader.getResource(resourceName); 44 | if (url != null) { 45 | URLConnection connection = url.openConnection(); 46 | if (connection != null) { 47 | connection.setUseCaches(false); 48 | stream = connection.getInputStream(); 49 | } 50 | } 51 | } else { 52 | stream = loader.getResourceAsStream(resourceName); 53 | } 54 | if (stream != null) { 55 | try { 56 | // Only this line is changed to make it to read properties files as UTF-8. 57 | bundle = new PropertyResourceBundle(new InputStreamReader(stream, StandardCharsets.UTF_8)); 58 | } finally { 59 | stream.close(); 60 | } 61 | } 62 | return bundle; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/listener/CoreProxyListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.listener; 19 | 20 | import io.github.krlvm.powertunnel.sdk.http.ProxyRequest; 21 | import io.github.krlvm.powertunnel.sdk.http.ProxyResponse; 22 | import io.github.krlvm.powertunnel.sdk.proxy.DNSRequest; 23 | import io.github.krlvm.powertunnel.sdk.proxy.ProxyListener; 24 | import io.github.krlvm.powertunnel.sdk.types.FullAddress; 25 | import org.jetbrains.annotations.NotNull; 26 | import org.slf4j.Logger; 27 | import org.slf4j.LoggerFactory; 28 | 29 | import java.util.Map; 30 | 31 | public class CoreProxyListener implements ProxyListener { 32 | 33 | private static final Logger LOGGER = LoggerFactory.getLogger(CoreProxyListener.class); 34 | 35 | private final Map proxyListeners; 36 | 37 | public CoreProxyListener(Map proxyListeners) { 38 | this.proxyListeners = proxyListeners; 39 | } 40 | 41 | @Override 42 | public void onClientToProxyRequest(@NotNull ProxyRequest request) { 43 | callProxyListeners((ProxyListenerCallback.Void) listener -> listener.onClientToProxyRequest(request)); 44 | } 45 | 46 | @Override 47 | public void onProxyToServerRequest(@NotNull ProxyRequest request) { 48 | callProxyListeners((ProxyListenerCallback.Void) listener -> listener.onProxyToServerRequest(request)); 49 | } 50 | 51 | @Override 52 | public void onServerToProxyResponse(@NotNull ProxyResponse response) { 53 | callProxyListeners((ProxyListenerCallback.Void) listener -> listener.onServerToProxyResponse(response)); 54 | } 55 | 56 | @Override 57 | public void onProxyToClientResponse(@NotNull ProxyResponse response) { 58 | callProxyListeners((ProxyListenerCallback.Void) listener -> listener.onProxyToClientResponse(response)); 59 | } 60 | 61 | @Override 62 | public Boolean onResolutionRequest(@NotNull DNSRequest request) { 63 | final Object result = callProxyListeners(listener -> listener.onResolutionRequest(request), false); 64 | return ((Boolean) result); 65 | } 66 | 67 | @Override 68 | public Integer onGetChunkSize(final @NotNull FullAddress address) { 69 | final Object result = callProxyListeners(listener -> listener.onGetChunkSize(address)); 70 | return result != null ? ((int) result) : 0; 71 | } 72 | 73 | @Override 74 | public Boolean isFullChunking(@NotNull FullAddress address) { 75 | final Object result = callProxyListeners(listener -> listener.isFullChunking(address)); 76 | return result != null && ((boolean) result); 77 | } 78 | 79 | @Override 80 | public Boolean isMITMAllowed(@NotNull FullAddress address) { 81 | final Object result = callProxyListeners(listener -> listener.isMITMAllowed(address)); 82 | return result == null || ((boolean) result); 83 | } 84 | 85 | @Override 86 | public Object onGetSNI(@NotNull String hostname) { 87 | final Object result = callProxyListeners(listener -> listener.onGetSNI(hostname), null, Void.TYPE); 88 | return result != Void.TYPE ? result : hostname; 89 | } 90 | 91 | private Object callProxyListeners(ProxyListenerCallback callback) { 92 | return callProxyListeners(callback, null); 93 | } 94 | 95 | private Object callProxyListeners(ProxyListenerCallback callback, Object errVal) { 96 | return callProxyListeners(callback, errVal, null); 97 | } 98 | 99 | private Object callProxyListeners(ProxyListenerCallback callback, Object errVal, Object defObj) { 100 | Object result = defObj; 101 | for (Map.Entry entry : proxyListeners.entrySet()) { 102 | Object res; 103 | try { 104 | res = callback.call(entry.getValue()); 105 | } catch (Exception ex) { 106 | LOGGER.error( 107 | "An error occurred in ProxyListener of '{}' [{}, priority={}]: {}", 108 | entry.getKey().getPluginInfo().getId(), 109 | entry.getValue().getClass().getSimpleName(), entry.getKey().getPriority(), 110 | ex.getMessage(), 111 | ex 112 | ); 113 | res = errVal; 114 | } 115 | if(res != defObj) result = res; 116 | } 117 | return result; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/listener/ProxyListenerCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.listener; 19 | 20 | import io.github.krlvm.powertunnel.sdk.proxy.ProxyListener; 21 | 22 | public interface ProxyListenerCallback { 23 | Object call(ProxyListener listener); 24 | 25 | interface Void extends ProxyListenerCallback { 26 | void callVoid(ProxyListener listener); 27 | 28 | @Override 29 | default Object call(ProxyListener listener) { 30 | callVoid(listener); 31 | return null; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/listener/ProxyListenerInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.listener; 19 | 20 | import io.github.krlvm.powertunnel.sdk.plugin.PluginInfo; 21 | 22 | public class ProxyListenerInfo { 23 | 24 | private final PluginInfo pluginInfo; 25 | private final int priority; 26 | 27 | public ProxyListenerInfo(PluginInfo pluginInfo, int priority) { 28 | this.pluginInfo = pluginInfo; 29 | this.priority = priority; 30 | } 31 | 32 | public PluginInfo getPluginInfo() { 33 | return pluginInfo; 34 | } 35 | 36 | public int getPriority() { 37 | return priority; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/listener/ServerListenerCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.listener; 19 | 20 | import io.github.krlvm.powertunnel.sdk.ServerListener; 21 | 22 | public interface ServerListenerCallback { 23 | void call(ServerListener listener); 24 | } 25 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/managers/ProxyAuthenticationManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.managers; 19 | 20 | import io.github.krlvm.powertunnel.sdk.proxy.ProxyCredentials; 21 | import org.littleshoot.proxy.ProxyAuthenticator; 22 | 23 | public class ProxyAuthenticationManager implements ProxyAuthenticator { 24 | 25 | private final String username; 26 | private final String password; 27 | 28 | public ProxyAuthenticationManager(ProxyCredentials credentials) { 29 | this(credentials.getUsername(), credentials.getPassword()); 30 | } 31 | 32 | public ProxyAuthenticationManager(String username, String password) { 33 | this.username = username; 34 | this.password = password; 35 | } 36 | 37 | @Override 38 | public boolean authenticate(String userName, String password) { 39 | return userName.equals(this.username) && password.equals(this.password); 40 | } 41 | 42 | @Override 43 | public String getRealm() { 44 | return null; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/managers/UpstreamProxyChainedProxyManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.managers; 19 | 20 | import io.github.krlvm.powertunnel.adapters.UpstreamChainedProxyAdapter; 21 | import io.netty.handler.codec.http.HttpRequest; 22 | import org.jetbrains.annotations.NotNull; 23 | import org.littleshoot.proxy.ChainedProxy; 24 | import org.littleshoot.proxy.ChainedProxyManager; 25 | import org.littleshoot.proxy.impl.ClientDetails; 26 | import java.util.Queue; 27 | 28 | public class UpstreamProxyChainedProxyManager implements ChainedProxyManager { 29 | 30 | private final UpstreamChainedProxyAdapter adapter; 31 | 32 | public UpstreamProxyChainedProxyManager(@NotNull UpstreamChainedProxyAdapter adapter) { 33 | this.adapter = adapter; 34 | } 35 | 36 | @Override 37 | public void lookupChainedProxies(HttpRequest httpRequest, Queue chainedProxies, ClientDetails clientDetails) { 38 | chainedProxies.add(adapter); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/mitm/MITMAuthority.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.mitm; 19 | 20 | import org.littleshoot.proxy.mitm.Authority; 21 | 22 | import java.io.File; 23 | 24 | public class MITMAuthority { 25 | 26 | public static final String CERTIFICATE_ALIAS = "powertunnel-root-ca"; 27 | 28 | public static Authority create(File certificateDirectory, String password) { 29 | return create(certificateDirectory, password.toCharArray()); 30 | } 31 | 32 | public static Authority create(File certificateDirectory, char[] password) { 33 | if(!certificateDirectory.exists()) certificateDirectory.mkdir(); 34 | return new Authority(certificateDirectory, CERTIFICATE_ALIAS, password, 35 | "PowerTunnel Root CA", 36 | "PowerTunnel", 37 | "PowerTunnel", 38 | "PowerTunnel", 39 | "PowerTunnel" 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/plugin/PluginInjector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.plugin; 19 | 20 | import java.io.File; 21 | 22 | public interface PluginInjector { 23 | Class inject(File file, String mainClass) throws Exception; 24 | } 25 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/preferences/Preference.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.preferences; 19 | 20 | import java.io.Serializable; 21 | import java.util.List; 22 | import java.util.Map; 23 | import java.util.stream.Collectors; 24 | 25 | public class Preference implements Serializable { 26 | 27 | private final String key; 28 | private final String title; 29 | private final String description; 30 | private final String defaultValue; 31 | private final PreferenceType type; 32 | 33 | private final String dependency; 34 | private final String dependencyValue; 35 | 36 | private final Map items; 37 | 38 | public transient Object binding; 39 | 40 | public Preference( 41 | String key, 42 | String title, 43 | String description, 44 | String defaultValue, 45 | PreferenceType type, 46 | String dependency, 47 | String dependencyValue, 48 | Map items 49 | ) { 50 | this.key = key; 51 | this.title = title; 52 | this.description = description; 53 | this.defaultValue = defaultValue; 54 | this.type = type; 55 | 56 | this.dependency = dependency; 57 | this.dependencyValue = dependencyValue; 58 | 59 | this.items = items; 60 | } 61 | 62 | public String getKey() { 63 | return key; 64 | } 65 | 66 | public String getTitle() { 67 | return title; 68 | } 69 | 70 | public String getDescription() { 71 | return description; 72 | } 73 | 74 | public String getDefaultValue() { 75 | return defaultValue; 76 | } 77 | 78 | public PreferenceType getType() { 79 | return type; 80 | } 81 | 82 | public String getDependency() { 83 | return dependency; 84 | } 85 | 86 | public String getDependencyValue() { 87 | return dependencyValue; 88 | } 89 | 90 | public Map getItems() { 91 | return items; 92 | } 93 | 94 | public List getItemsAsModels() { 95 | return items.entrySet().stream() 96 | .map(entry -> new SelectPreferenceItem(entry.getKey(), entry.getValue())) 97 | .collect(Collectors.toList()); 98 | } 99 | 100 | public static class SelectPreferenceItem { 101 | 102 | private final String key; 103 | private final String name; 104 | 105 | public SelectPreferenceItem(String key, String name) { 106 | this.key = key; 107 | this.name = name; 108 | } 109 | 110 | public String getKey() { 111 | return key; 112 | } 113 | 114 | public String getName() { 115 | return name; 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/preferences/PreferenceGroup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.preferences; 19 | 20 | import java.io.Serializable; 21 | import java.util.List; 22 | 23 | public class PreferenceGroup implements Serializable { 24 | 25 | private final String title; 26 | private final String description; 27 | private final List preferences; 28 | 29 | public PreferenceGroup(String title, String description, List preferences) { 30 | this.title = title; 31 | this.description = description; 32 | this.preferences = preferences; 33 | } 34 | 35 | public String getTitle() { 36 | return title; 37 | } 38 | 39 | public String getDescription() { 40 | return description; 41 | } 42 | 43 | public List getPreferences() { 44 | return preferences; 45 | } 46 | 47 | public Preference findPreference(String key) { 48 | for (Preference preference : preferences) { 49 | if(key.equals(preference.getKey())) return preference; 50 | } 51 | return null; 52 | } 53 | 54 | 55 | public static Preference findPreference(List groups, String key) { 56 | for (PreferenceGroup group : groups) { 57 | final Preference preference = group.findPreference(key); 58 | if(preference != null) return preference; 59 | } 60 | return null; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/preferences/PreferenceType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.preferences; 19 | 20 | public enum PreferenceType { 21 | 22 | CHECKBOX("false"), 23 | SWITCH("false"), 24 | STRING(""), 25 | NUMBER("0"), 26 | SELECT(null); 27 | 28 | final String defaultValue; 29 | 30 | PreferenceType(String defaultValue) { 31 | this.defaultValue = defaultValue; 32 | } 33 | 34 | public String getDefaultValue() { 35 | return defaultValue; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/resolver/DNSResolverWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.resolver; 19 | 20 | import io.github.krlvm.powertunnel.sdk.proxy.DNSResolver; 21 | import org.jetbrains.annotations.NotNull; 22 | import org.littleshoot.proxy.HostResolver; 23 | 24 | import java.net.InetSocketAddress; 25 | import java.net.UnknownHostException; 26 | 27 | public class DNSResolverWrapper implements DNSResolver { 28 | 29 | private final HostResolver resolver; 30 | 31 | public DNSResolverWrapper(@NotNull HostResolver resolver) { 32 | this.resolver = resolver; 33 | } 34 | 35 | @Override 36 | public @NotNull InetSocketAddress resolve(@NotNull String host, int port) throws UnknownHostException { 37 | return resolver.resolve(host, port); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/resolver/LDNSResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.resolver; 19 | 20 | import io.github.krlvm.powertunnel.sdk.proxy.DNSRequest; 21 | import io.github.krlvm.powertunnel.sdk.proxy.ProxyListener; 22 | import org.littleshoot.proxy.DefaultHostResolver; 23 | import org.littleshoot.proxy.HostResolver; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | 27 | import java.net.InetSocketAddress; 28 | import java.net.UnknownHostException; 29 | 30 | public class LDNSResolver implements HostResolver { 31 | 32 | private static final Logger LOGGER = LoggerFactory.getLogger(LDNSResolver.class); 33 | 34 | private final ProxyListener listener; 35 | private final boolean allowFallbackResolver; 36 | 37 | private final HostResolver resolver = new DefaultHostResolver(); 38 | 39 | public LDNSResolver(ProxyListener listener, boolean allowFallbackResolver) { 40 | this.listener = listener; 41 | this.allowFallbackResolver = allowFallbackResolver; 42 | } 43 | 44 | @Override 45 | public InetSocketAddress resolve(String host, int port) throws UnknownHostException { 46 | final DNSRequest request = new DNSRequest(host, port); 47 | final Boolean result = listener.onResolutionRequest(request); 48 | if(result != null && !result) { 49 | LOGGER.error("Resolution of hostname '{}' failed", host); 50 | if(!this.allowFallbackResolver) throw new UnknownHostException(); 51 | } 52 | return request.getResponse() == null ? this.resolver.resolve(host, port) : request.getResponse(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /core/src/main/java/io/github/krlvm/powertunnel/utilities/JarLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.utilities; 19 | 20 | import io.github.krlvm.powertunnel.callbacks.InputStreamConsumer; 21 | 22 | import java.io.Closeable; 23 | import java.io.File; 24 | import java.io.IOException; 25 | import java.io.InputStream; 26 | import java.util.jar.JarEntry; 27 | import java.util.jar.JarFile; 28 | 29 | public class JarLoader implements Closeable { 30 | 31 | private final JarFile jar; 32 | 33 | public JarLoader(File file) throws IOException { 34 | this.jar = new JarFile(file); 35 | } 36 | 37 | public void open(String entryName, InputStreamConsumer consumer) throws IOException { 38 | open(entryName, consumer, false); 39 | } 40 | 41 | public void open(String entryName, InputStreamConsumer consumer, boolean acceptNull) throws IOException { 42 | final JarEntry entry = this.jar.getJarEntry(entryName); 43 | if (entry == null) { 44 | if(!acceptNull) return; 45 | consumer.accept(null); 46 | return; 47 | } 48 | try(InputStream in = jar.getInputStream(entry)) { 49 | consumer.accept(in); 50 | } 51 | } 52 | 53 | public void close() throws IOException { 54 | this.jar.close(); 55 | } 56 | 57 | 58 | public static void open(File file, String entry, InputStreamConsumer consumer) throws IOException { 59 | open(file, entry, consumer, false); 60 | } 61 | public static void open(File file, String entry, InputStreamConsumer consumer, boolean acceptNull) throws IOException { 62 | try(JarLoader loader = new JarLoader(file)) { 63 | loader.open(entry, consumer, acceptNull); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /desktop/.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | -------------------------------------------------------------------------------- /desktop/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | plugins { 19 | id 'application' 20 | id 'distribution' 21 | } 22 | 23 | version '2.5.2' 24 | 25 | run { 26 | workingDir = new File('build/run') 27 | workingDir.mkdirs() 28 | 29 | standardInput = System.in 30 | } 31 | 32 | application { 33 | mainClass = 'io.github.krlvm.powertunnel.desktop.Main' 34 | } 35 | 36 | jar { 37 | if (!project.version.endsWith('SNAPSHOT')) { 38 | exclude 'icon_dev.png' 39 | } 40 | } 41 | 42 | task fatJar(type: Jar, group: 'build', description: 'Assembles a jar archive containing the main classes and all dependencies.') { 43 | archiveClassifier = 'all' 44 | duplicatesStrategy DuplicatesStrategy.EXCLUDE 45 | manifest { 46 | attributes( 47 | 'Main-Class': application.mainClass 48 | ) 49 | } 50 | from { 51 | configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it) } 52 | } { 53 | exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA' 54 | } 55 | with jar 56 | } 57 | 58 | task releaseJar(group: 'build', description: 'Assembles a signed jar archive containing the main classes and all dependencies.') { 59 | dependsOn fatJar 60 | doLast { 61 | println 'Loading signing properties...' 62 | def keystoreProperties = new Properties() 63 | def keystorePropertiesFile = rootProject.file('key.properties') 64 | if(!keystorePropertiesFile.exists()) throw new GradleException('key.properties does not exist') 65 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 66 | println 'Signing fatJar...' 67 | 68 | def stdout = new ByteArrayOutputStream() 69 | exec { 70 | workingDir rootProject.rootDir 71 | commandLine 'cmd', '/c', keystoreProperties.getProperty("jarsigner"), 72 | "-keystore", keystoreProperties.getProperty('storeFile'), 73 | "-storepass", keystoreProperties.getProperty('storePassword'), 74 | "-keypass", keystoreProperties.getProperty('keyPassword'), 75 | "-tsa", keystoreProperties.getProperty('tsa'), "-verbose", 76 | "$buildDir/libs/*-all.jar", keystoreProperties.getProperty('keyAlias') 77 | standardOutput = System.out; 78 | } 79 | println stdout 80 | } 81 | } 82 | 83 | dependencies { 84 | implementation fileTree(dir: 'libs', include: ['*.jar']) 85 | 86 | implementation project(':core') 87 | implementation 'commons-cli:commons-cli:1.5.0' 88 | implementation 'net.java.dev.jna:jna:3.2.5' 89 | 90 | implementation 'org.apache.logging.log4j:log4j-api:2.17.1' 91 | implementation 'org.apache.logging.log4j:log4j-core:2.17.1' 92 | implementation 'org.apache.logging.log4j:log4j-slf4j-impl:2.17.1' 93 | 94 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2' 95 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2' 96 | } -------------------------------------------------------------------------------- /desktop/libs/swingdpi-1.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krlvm/PowerTunnel/3e5df1e6ce4e12628fee4e2b940e4db9067cde3c/desktop/libs/swingdpi-1.2.jar -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/BuildConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop; 19 | 20 | public class BuildConstants { 21 | public static final String NAME = "PowerTunnel"; 22 | public static final String DESCRIPTION = "Powerful and extensible proxy server"; 23 | public static final String REPO = "https://github.com/krlvm/PowerTunnel"; 24 | public static final String VERSION = "2.5.2"; 25 | public static final int VERSION_CODE = 111; 26 | 27 | public static boolean IS_RELEASE = io.github.krlvm.powertunnel.BuildConstants.isReleaseVersion(VERSION); 28 | public static final boolean DEBUG = !IS_RELEASE; 29 | } 30 | -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/application/ConsoleApp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.application; 19 | 20 | import io.github.krlvm.powertunnel.desktop.configuration.ServerConfiguration; 21 | 22 | public class ConsoleApp extends DesktopApp { 23 | 24 | public ConsoleApp(ServerConfiguration configuration) { 25 | super(configuration); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/configuration/AdvancedConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.configuration; 19 | 20 | import io.github.krlvm.powertunnel.configuration.ConfigurationStore; 21 | 22 | import java.util.*; 23 | import java.util.stream.Collectors; 24 | 25 | public class AdvancedConfiguration extends ConfigurationStore { 26 | 27 | private final Collection immutableKeys = new HashSet<>(); 28 | private final Map preImmutableData = new HashMap<>(); 29 | 30 | private void saveOriginalKey(String key) { 31 | String originalVal = get(key, null); 32 | if (originalVal != null) { 33 | preImmutableData.put(key, originalVal); 34 | } 35 | } 36 | 37 | public void protect(String key, String value) { 38 | this.immutableKeys.add(key); 39 | saveOriginalKey(key); 40 | set(key, value); 41 | } 42 | 43 | public void protectInt(String key, int value) { 44 | this.immutableKeys.add(key); 45 | saveOriginalKey(key); 46 | setInt(key, value); 47 | } 48 | 49 | public void protectBoolean(String key, boolean value) { 50 | this.immutableKeys.add(key); 51 | saveOriginalKey(key); 52 | setBoolean(key, value); 53 | } 54 | 55 | @Override 56 | protected Set> entries() { 57 | Set> entries = new HashSet<>(); 58 | 59 | for (Map.Entry entry : super.entries()) { 60 | if (immutableKeys.contains(entry.getKey())) { 61 | if (!preImmutableData.containsKey(entry.getKey())) continue; 62 | entry = new AbstractMap.SimpleEntry<>(entry.getKey(), preImmutableData.get(entry.getKey())); 63 | } 64 | entries.add(entry); 65 | } 66 | 67 | return entries; 68 | } 69 | 70 | public Collection getImmutableKeys() { 71 | return immutableKeys; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/configuration/ServerConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.configuration; 19 | 20 | import io.github.krlvm.powertunnel.desktop.application.DesktopApp; 21 | 22 | import java.io.IOException; 23 | 24 | public class ServerConfiguration extends AdvancedConfiguration { 25 | 26 | public void read() throws IOException { 27 | read(DesktopApp.CONFIGURATION_FILE); 28 | } 29 | 30 | public void save() throws IOException { 31 | save(DesktopApp.CONFIGURATION_FILE); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/frames/AppFrame.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.frames; 19 | 20 | import io.github.krlvm.powertunnel.desktop.BuildConstants; 21 | import io.github.krlvm.powertunnel.desktop.application.GraphicalApp; 22 | import io.github.krlvm.powertunnel.desktop.utilities.UIUtility; 23 | import ru.krlvm.swingdpi.ScalableJFrame; 24 | 25 | import javax.swing.*; 26 | import javax.swing.border.Border; 27 | import java.awt.*; 28 | 29 | /** 30 | * Base implementation of JFrame (SwingDPI/ScalableJFrame) 31 | */ 32 | public abstract class AppFrame extends ScalableJFrame { 33 | 34 | public static final int PADDING = 8; 35 | public static final Border BORDER = BorderFactory.createEmptyBorder(PADDING, PADDING, PADDING, PADDING); 36 | 37 | protected final GraphicalApp app; 38 | 39 | private boolean failedToInitialize = false; 40 | 41 | public AppFrame() { 42 | this(null, null); 43 | } 44 | 45 | public AppFrame(GraphicalApp app) { 46 | this(null, app); 47 | } 48 | 49 | public AppFrame(String title) { 50 | this(title, null); 51 | } 52 | 53 | public AppFrame(String title, GraphicalApp app) { 54 | super((title != null ? title + " - " : "") + BuildConstants.NAME); 55 | this.app = app; 56 | 57 | setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); 58 | setIconImage(GraphicalApp.ICON); 59 | } 60 | 61 | public void showFrame() { 62 | showFrame(null); 63 | } 64 | public void showFrame(JFrame parent) { 65 | if(failedToInitialize) return; 66 | setLocationRelativeTo((parent == null || UIUtility.isMinimized(parent)) ? null : parent); 67 | setVisible(true); 68 | setState(Frame.NORMAL); 69 | toFront(); 70 | requestFocus(); 71 | } 72 | 73 | protected void frameInitialized() { 74 | setLocationRelativeTo(null); 75 | } 76 | protected void onFailedToInitialize() { 77 | failedToInitialize = true; 78 | dispose(); 79 | //throw new RuntimeException(); 80 | } 81 | public boolean isFailedToInitialize() { 82 | return failedToInitialize; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/managers/ApplicationManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.managers; 19 | 20 | import io.github.krlvm.powertunnel.desktop.utilities.Utility; 21 | import io.github.krlvm.powertunnel.plugin.PluginLoader; 22 | 23 | import java.io.File; 24 | import java.io.IOException; 25 | import java.nio.file.Path; 26 | import java.nio.file.Paths; 27 | 28 | public class ApplicationManager { 29 | 30 | private static final String[] PREINSTALLED_PLUGINS = { 31 | "LibertyTunnel.jar", 32 | "DNSResolver.jar" 33 | }; 34 | 35 | public static void extractPlugins() throws IOException { 36 | final Path pluginsDir = Paths.get(PluginLoader.PLUGINS_DIR); 37 | final File pluginsDirFile = pluginsDir.toFile(); 38 | if(!pluginsDirFile.exists()) pluginsDirFile.mkdir(); 39 | for (String plugin : PREINSTALLED_PLUGINS) { 40 | Utility.extractResource(pluginsDir.resolve(plugin), "plugins/" + plugin); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/managers/ConsoleHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.managers; 19 | 20 | import io.github.krlvm.powertunnel.desktop.system.ConsoleReader; 21 | import io.github.krlvm.powertunnel.desktop.types.ConsoleCommand; 22 | 23 | import java.util.*; 24 | import java.util.function.Consumer; 25 | 26 | public class ConsoleHandler { 27 | 28 | private final Map appCommands = new TreeMap<>((String::compareTo)); 29 | private final Map commands = new TreeMap<>(String::compareTo); 30 | 31 | public ConsoleHandler() { 32 | final ConsoleReader reader = ConsoleReader.get(); 33 | final Thread thread = new Thread(() -> { 34 | String input; 35 | while ((input = reader.readLine()) != null) { 36 | lookupCommand(input.trim()); 37 | } 38 | }, "Console Handler Thread"); 39 | thread.setDaemon(true); 40 | thread.start(); 41 | } 42 | 43 | private void lookupCommand(String input) { 44 | if ("help".equalsIgnoreCase(input)) { 45 | int longestCommand = Math.max(6, getLongestCommand(appCommands.keySet()) + getLongestCommand(commands.keySet()) + 3); 46 | int longestUsage = Math.max(6, getLongestUsage(appCommands.values()) + getLongestUsage(commands.values()) + 3); 47 | 48 | System.out.println(); 49 | System.out.println("List of available commands:"); 50 | printHelp(appCommands, longestCommand, longestUsage); 51 | printHelp(commands, longestCommand, longestUsage); 52 | System.out.println(); 53 | } else { 54 | final String[] arr = input.split(" "); 55 | for (Map.Entry entry : appCommands.entrySet()) { 56 | if (arr[0].toLowerCase().equals(entry.getKey())) { 57 | entry.getValue().getHandler().accept(Arrays.copyOfRange(arr, 1, arr.length)); 58 | return; 59 | } 60 | } 61 | if (arr.length > 1) { 62 | for (Map.Entry entry : commands.entrySet()) { 63 | if ((arr[0] + " " + arr[1]).toLowerCase().equals(entry.getKey())) { 64 | entry.getValue().getHandler().accept(Arrays.copyOfRange(arr, 2, arr.length)); 65 | return; 66 | } 67 | } 68 | } 69 | System.err.println(" Unknown command. Type 'help' to view available commands."); 70 | } 71 | } 72 | 73 | public void printHelp(Map commands, int longestCommand, int longestUsage) { 74 | for (Map.Entry entry : commands.entrySet()) { 75 | final String cmd = entry.getKey() + String.join("", 76 | Collections.nCopies(Math.max(0, longestCommand - entry.getKey().length()), " ")); 77 | final String usage = entry.getValue().getUsage() + String.join("", 78 | Collections.nCopies(Math.max(0, longestUsage - entry.getValue().getUsage().length()), " ")); 79 | System.out.println(" " + cmd + usage + entry.getValue().getDescription()); 80 | } 81 | } 82 | 83 | public void registerAppCommand( 84 | String command, 85 | Consumer handler, 86 | String usage, 87 | String description) { 88 | appCommands.put(command, new ConsoleCommand("powertunnel", command, usage, description, handler)); 89 | } 90 | 91 | public void registerCommand( 92 | String pluginId, 93 | String command, 94 | Consumer handler, 95 | String usage, 96 | String description) { 97 | if (!command.isEmpty()) throw new IllegalArgumentException("Command cannot be empty"); 98 | commands.put(pluginId + " " + command, new ConsoleCommand(pluginId, command, usage, description, handler)); 99 | } 100 | 101 | public void reset() { 102 | commands.clear(); 103 | System.gc(); 104 | } 105 | 106 | private int getLongestCommand(Set commands) { 107 | return commands.stream().max(Comparator.comparingInt(String::length)).orElse("").length(); 108 | } 109 | private int getLongestUsage(Collection commands) { 110 | return commands.stream().map(ConsoleCommand::getUsage).max(Comparator.comparingInt(String::length)).orElse("").length(); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/managers/TrayManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.managers; 19 | 20 | import io.github.krlvm.powertunnel.desktop.BuildConstants; 21 | import io.github.krlvm.powertunnel.desktop.application.GraphicalApp; 22 | import io.github.krlvm.powertunnel.desktop.ui.I18N; 23 | import ru.krlvm.swingdpi.SwingDPI; 24 | 25 | import java.awt.*; 26 | import java.awt.event.ActionListener; 27 | import java.awt.font.TextAttribute; 28 | import java.util.HashMap; 29 | import java.util.Map; 30 | 31 | public class TrayManager { 32 | 33 | private final GraphicalApp app; 34 | 35 | private TrayIcon trayIcon; 36 | 37 | private Font HEADER_FONT; 38 | private Font FONT; 39 | 40 | public TrayManager(GraphicalApp app) { 41 | this.app = app; 42 | } 43 | 44 | public void load() throws AWTException { 45 | initializeFonts(); 46 | final ActionListener openAppListener = e -> app.showFrame(); 47 | 48 | PopupMenu popup = new PopupMenu(); 49 | 50 | popup.add(getItem(BuildConstants.NAME, null, true)); 51 | popup.add(getItem(I18N.get("tray.version") + " " + BuildConstants.VERSION, null, true)); 52 | popup.add(getItem("(c) krlvm, 2019-2022", null, true)); 53 | 54 | popup.addSeparator(); 55 | 56 | popup.add(getItem(I18N.get("tray.open"), openAppListener)); 57 | 58 | popup.addSeparator(); 59 | 60 | popup.add(getItem(I18N.get("main.plugins"), e -> app.showPluginsFrame())); 61 | popup.add(getItem(I18N.get("main.options"), e -> app.showOptionsFrame())); 62 | 63 | popup.addSeparator(); 64 | 65 | popup.add(getItem(I18N.get("tray.exit"), e -> app.dispose())); 66 | 67 | trayIcon = new TrayIcon(GraphicalApp.ICON, BuildConstants.NAME, popup); 68 | trayIcon.setImageAutoSize(true); 69 | trayIcon.setToolTip(BuildConstants.NAME); 70 | trayIcon.addActionListener(openAppListener); 71 | 72 | freeFonts(); 73 | 74 | SystemTray.getSystemTray().add(trayIcon); 75 | } 76 | 77 | public void unload() { 78 | SystemTray.getSystemTray().remove(trayIcon); 79 | trayIcon = null; 80 | } 81 | 82 | public void showNotification(String message) { 83 | if(!isLoaded()) return; 84 | trayIcon.displayMessage(BuildConstants.NAME, message, TrayIcon.MessageType.NONE); 85 | } 86 | 87 | public boolean isLoaded() { 88 | return trayIcon != null; 89 | } 90 | 91 | 92 | private MenuItem getItem(String title, ActionListener listener) { 93 | return getItem(title, listener, false); 94 | } 95 | 96 | private MenuItem getItem(String title, ActionListener listener, boolean header) { 97 | final MenuItem item = new MenuItem(title); 98 | if(header) { 99 | item.setFont(HEADER_FONT); 100 | item.setEnabled(false); 101 | } else { 102 | item.setFont(FONT); 103 | } 104 | if(listener != null) item.addActionListener(listener); 105 | return item; 106 | } 107 | 108 | 109 | // region Fonts 110 | 111 | private void initializeFonts() { 112 | Map attributes = new HashMap<>(); 113 | attributes.put(TextAttribute.SIZE, 12* SwingDPI.getScaleFactor()); 114 | FONT = Font.getFont(attributes); 115 | 116 | attributes.put(TextAttribute.FAMILY, Font.DIALOG); 117 | attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD); 118 | HEADER_FONT = Font.getFont(attributes); 119 | } 120 | 121 | private void freeFonts() { 122 | FONT = null; 123 | HEADER_FONT = null; 124 | } 125 | 126 | // endregion 127 | } 128 | -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/system/ConsoleReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.system; 19 | 20 | import java.io.Console; 21 | import java.util.Scanner; 22 | 23 | public interface ConsoleReader { 24 | 25 | String readLine(); 26 | 27 | class JavaConsoleWrapper implements ConsoleReader { 28 | private final Console console; 29 | JavaConsoleWrapper(Console console) { 30 | this.console = console; 31 | } 32 | @Override 33 | public String readLine() { 34 | return console.readLine("> "); 35 | } 36 | } 37 | class BufferedConsoleWrapper implements ConsoleReader { 38 | private final Scanner scanner = new Scanner(System.in); 39 | @Override 40 | public String readLine() { 41 | return scanner.nextLine(); 42 | } 43 | } 44 | 45 | static ConsoleReader get() { 46 | final Console console = System.console(); 47 | return console != null ? new JavaConsoleWrapper(console) : new BufferedConsoleWrapper(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/system/SystemProxy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.system; 19 | 20 | import io.github.krlvm.powertunnel.desktop.system.windows.WindowsProxyHandler; 21 | import io.github.krlvm.powertunnel.desktop.utilities.SystemUtility; 22 | import io.github.krlvm.powertunnel.sdk.proxy.ProxyAddress; 23 | 24 | public class SystemProxy { 25 | 26 | private static final Handler HANDLER; 27 | static { 28 | if(SystemUtility.IS_WINDOWS) { 29 | HANDLER = new WindowsProxyHandler(); 30 | } else { 31 | HANDLER = new DummyHandler(); 32 | } 33 | } 34 | 35 | public static boolean isSupported() { 36 | return HANDLER != null && !(HANDLER instanceof DummyHandler); 37 | } 38 | 39 | public static void enableProxy(ProxyAddress address) { 40 | HANDLER.enableProxy(address); 41 | } 42 | 43 | public static void disableProxy() { 44 | HANDLER.disableProxy(); 45 | } 46 | 47 | public interface Handler { 48 | void enableProxy(ProxyAddress address); 49 | void disableProxy(); 50 | } 51 | 52 | public static final class DummyHandler implements Handler { 53 | @Override 54 | public void enableProxy(ProxyAddress address) {} 55 | @Override 56 | public void disableProxy() {} 57 | } 58 | } -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/system/windows/WindowsProxyHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.system.windows; 19 | 20 | import io.github.krlvm.powertunnel.desktop.system.SystemProxy; 21 | import io.github.krlvm.powertunnel.desktop.utilities.SystemUtility; 22 | import io.github.krlvm.powertunnel.sdk.proxy.ProxyAddress; 23 | 24 | import java.io.IOException; 25 | 26 | public class WindowsProxyHandler implements SystemProxy.Handler { 27 | 28 | public static boolean USE_IE = SystemUtility.OLD_OS; 29 | 30 | @Override 31 | public void enableProxy(ProxyAddress address) { 32 | executeAndApply( 33 | "reg add \"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\" /v ProxyEnable /t REG_DWORD /d 1 /f", 34 | "reg add \"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\" /v ProxyServer /t REG_SZ /d " + address.getHost() + ":" + address.getPort() + " /f" 35 | ); 36 | } 37 | 38 | @Override 39 | public void disableProxy() { 40 | executeAndApply("reg add \"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\" /v ProxyEnable /t REG_DWORD /d 0 /f"); 41 | } 42 | 43 | public static void executeAndApply(final String... commands) { 44 | new Thread(() -> { 45 | try { 46 | for (String command : commands) { 47 | SystemUtility.executeWindowsCommand(command); 48 | } 49 | if (!USE_IE) { 50 | Wininet wininet = Wininet.INSTANCE; 51 | wininet.InternetSetOptionW(0, 52 | wininet.INTERNET_OPTION_SETTINGS_CHANGED, null, 0); 53 | wininet.InternetSetOptionW(0, 54 | wininet.INTERNET_OPTION_REFRESH, null, 0); 55 | } else { 56 | // We need to start Internet Explorer to apply the changes 57 | SystemUtility.executeWindowsCommand("start iexplore && ping -n 5 127.0.0.1 > NUL && taskkill /f /im iexplore.exe"); 58 | } 59 | System.out.println("System proxy initialization has been finished"); 60 | } catch (IOException ex) { 61 | System.err.println("Failed to setup system proxy: " + ex.getMessage()); 62 | ex.printStackTrace(); 63 | } 64 | }).start(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/system/windows/Wininet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.system.windows; 19 | 20 | import com.sun.jna.Native; 21 | import com.sun.jna.Pointer; 22 | import com.sun.jna.win32.StdCallLibrary; 23 | import com.sun.jna.win32.W32APIOptions; 24 | 25 | public interface Wininet extends StdCallLibrary { 26 | 27 | Wininet INSTANCE = (Wininet)Native.loadLibrary("Wininet", Wininet.class, 28 | W32APIOptions.DEFAULT_OPTIONS); 29 | 30 | int INTERNET_OPTION_SETTINGS_CHANGED = 39; 31 | int INTERNET_OPTION_REFRESH = 37; 32 | 33 | boolean InternetSetOptionW(int unused, int dwOption, Pointer lpBuffer, int dwBufferLength); 34 | } -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/types/ConsoleCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.types; 19 | 20 | import java.util.function.Consumer; 21 | 22 | public class ConsoleCommand { 23 | 24 | private final String pluginId; 25 | private final String name; 26 | private final String usage; 27 | private final String description; 28 | 29 | private final Consumer handler; 30 | 31 | public ConsoleCommand(String pluginId, String name, String usage, String description, Consumer handler) { 32 | this.pluginId = pluginId; 33 | this.name = name; 34 | this.usage = usage; 35 | this.description = description; 36 | this.handler = handler; 37 | } 38 | 39 | public String getPluginId() { 40 | return pluginId; 41 | } 42 | 43 | public String getName() { 44 | return name; 45 | } 46 | 47 | public String getUsage() { 48 | return usage; 49 | } 50 | 51 | public String getDescription() { 52 | return description; 53 | } 54 | 55 | public Consumer getHandler() { 56 | return handler; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/types/TrayMode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.types; 19 | 20 | public enum TrayMode { 21 | STANDARD, 22 | MINIMIZED, 23 | DISABLED 24 | } 25 | -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/ui/ComboBoxScroll.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.ui; 19 | 20 | import javax.swing.*; 21 | import java.awt.event.MouseWheelEvent; 22 | 23 | public class ComboBoxScroll { 24 | 25 | public static void register(JComboBox comboBox) { 26 | comboBox.addMouseWheelListener((MouseWheelEvent e) -> { 27 | if(!comboBox.isEnabled()) return; 28 | final int i = comboBox.getSelectedIndex() + (e.getWheelRotation() < 0 ? -1 : 1); 29 | if(i < 0 || i >= comboBox.getItemCount()) return; 30 | comboBox.setSelectedIndex(i); 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/ui/FieldFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.ui; 19 | 20 | import javax.swing.text.AttributeSet; 21 | import javax.swing.text.BadLocationException; 22 | import javax.swing.text.Document; 23 | import javax.swing.text.DocumentFilter; 24 | import java.awt.*; 25 | import java.util.regex.Pattern; 26 | 27 | public abstract class FieldFilter extends DocumentFilter { 28 | 29 | protected abstract boolean isAllowed(String s); 30 | 31 | @Override 32 | public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException { 33 | final Document doc = fb.getDocument(); 34 | final StringBuilder sb = new StringBuilder(); 35 | sb.append(doc.getText(0, doc.getLength())); 36 | sb.insert(offset, string); 37 | 38 | if (isAllowed(sb.toString())) { 39 | super.insertString(fb, offset, string, attr); 40 | return; 41 | } 42 | Toolkit.getDefaultToolkit().beep(); 43 | } 44 | 45 | @Override 46 | public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException { 47 | final Document doc = fb.getDocument(); 48 | final StringBuilder sb = new StringBuilder(); 49 | sb.append(doc.getText(0, doc.getLength())); 50 | sb.replace(offset, offset + length, text); 51 | 52 | if (isAllowed(sb.toString())) { 53 | super.replace(fb, offset, length, text, attrs); 54 | return; 55 | } 56 | Toolkit.getDefaultToolkit().beep(); 57 | } 58 | 59 | @Override 60 | public void remove(FilterBypass fb, int offset, int length) throws BadLocationException { 61 | final Document doc = fb.getDocument(); 62 | final StringBuilder sb = new StringBuilder(); 63 | sb.append(doc.getText(0, doc.getLength())); 64 | sb.delete(offset, offset + length); 65 | 66 | if (isAllowed(sb.toString())) { 67 | super.remove(fb, offset, length); 68 | return; 69 | } 70 | Toolkit.getDefaultToolkit().beep(); 71 | } 72 | 73 | 74 | public static class Number extends FieldFilter { 75 | @Override 76 | protected boolean isAllowed(String s) { 77 | try { 78 | Integer.parseInt(s); 79 | return true; 80 | } catch (NumberFormatException ex) { 81 | return false; 82 | } 83 | } 84 | } 85 | 86 | public static class IP extends FieldFilter { 87 | private static final Pattern PATTERN = Pattern.compile("(\\d+\\.?)+"); 88 | @Override 89 | protected boolean isAllowed(String s) { 90 | return s.isEmpty() || PATTERN.matcher(s).matches(); 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/ui/I18N.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.ui; 19 | 20 | import io.github.krlvm.powertunnel.i18n.I18NBundle; 21 | import io.github.krlvm.powertunnel.i18n.UTF8Control; 22 | 23 | import java.util.Locale; 24 | import java.util.MissingResourceException; 25 | import java.util.ResourceBundle; 26 | 27 | public class I18N { 28 | 29 | private static I18NBundle bundle; 30 | private static String lang = null; 31 | 32 | public static String get(String key) { 33 | return bundle.get(key); 34 | } 35 | 36 | public static String get(String key, String defaultValue) { 37 | return bundle.get(key, defaultValue); 38 | } 39 | 40 | public static void load(Locale locale) { 41 | if(bundle != null) throw new IllegalStateException("Bundle is already loaded"); 42 | try { 43 | bundle = new I18NBundle(getResourceBundle(locale)); 44 | lang = locale.getLanguage(); 45 | } catch (MissingResourceException ex) { 46 | System.err.printf("Locale '%s' is not supported%n", locale.getLanguage()); 47 | bundle = new I18NBundle(getResourceBundle(Locale.ENGLISH)); 48 | } 49 | } 50 | 51 | public static String getLang() { 52 | return lang; 53 | } 54 | 55 | 56 | private static final String NAME = "messages"; 57 | public static ResourceBundle getResourceBundle(Locale locale) { 58 | return ResourceBundle.getBundle("locale/" + NAME, locale, new UTF8Control()); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/ui/PluginInfoRenderer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.ui; 19 | 20 | import io.github.krlvm.powertunnel.desktop.utilities.UIUtility; 21 | import io.github.krlvm.powertunnel.sdk.plugin.PluginInfo; 22 | import ru.krlvm.swingdpi.SwingDPI; 23 | 24 | import javax.swing.*; 25 | import javax.swing.border.Border; 26 | import java.awt.*; 27 | 28 | // https://stackoverflow.com/a/26476427 29 | public class PluginInfoRenderer extends JPanel implements ListCellRenderer { 30 | 31 | private final JEditorPane infoLabel = new JEditorPane(); 32 | 33 | public PluginInfoRenderer() { 34 | setLayout(new BorderLayout()); 35 | 36 | add(infoLabel, BorderLayout.NORTH); 37 | 38 | final JPanel separator = new JPanel(); 39 | separator.setBackground(Color.LIGHT_GRAY); 40 | separator.setPreferredSize(new Dimension(separator.getWidth(), 1)); 41 | 42 | add(separator, BorderLayout.SOUTH); 43 | } 44 | 45 | @Override 46 | public Dimension getMinimumSize() { 47 | return SwingDPI.scale(100, 76); 48 | } 49 | 50 | @Override 51 | public Dimension getPreferredSize() { 52 | return getMinimumSize(); 53 | } 54 | 55 | @Override 56 | public Component getListCellRendererComponent( 57 | JList list, 58 | PluginInfo value, 59 | int index, 60 | boolean isSelected, 61 | boolean cellHasFocus 62 | ) { 63 | setComponentOrientation(list.getComponentOrientation()); 64 | 65 | Color backgroundColor = null; 66 | Color foregroundColor = null; 67 | 68 | JList.DropLocation dropLocation = list.getDropLocation(); 69 | if (dropLocation != null && !dropLocation.isInsert() && dropLocation.getIndex() == index) { 70 | backgroundColor = UIManager.getColor("List.dropCellBackground"); 71 | foregroundColor = UIManager.getColor("List.dropCellForeground"); 72 | 73 | isSelected = true; 74 | } 75 | 76 | if (isSelected) { 77 | setBackground(backgroundColor == null ? list.getSelectionBackground() : backgroundColor); 78 | setForeground(foregroundColor == null ? list.getSelectionForeground() : foregroundColor); 79 | 80 | setBackground(Color.LIGHT_GRAY); 81 | } else { 82 | setBackground(list.getBackground()); 83 | setForeground(list.getForeground()); 84 | } 85 | 86 | UIUtility.setEditorPaneContent(infoLabel, String.format( 87 | "%s
%sVersion %s%s", 88 | value.getName(), 89 | value.getDescription() != null ? value.getDescription() + "
" : "", 90 | value.getVersion(), 91 | value.getAuthor() != null ? "
by " + value.getAuthor() + "" : "" 92 | ), "padding: 5px;", 0, false); 93 | infoLabel.setBackground(getBackground()); 94 | infoLabel.setForeground(getForeground()); 95 | 96 | setEnabled(list.isEnabled()); 97 | 98 | return this; 99 | } 100 | } -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/ui/SelectPreferenceRenderer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.ui; 19 | 20 | import io.github.krlvm.powertunnel.preferences.Preference; 21 | 22 | import javax.swing.*; 23 | import java.awt.*; 24 | 25 | public class SelectPreferenceRenderer extends DefaultListCellRenderer { 26 | 27 | public Component getListCellRendererComponent( 28 | JList list, 29 | Object value, 30 | int index, 31 | boolean isSelected, 32 | boolean cellHasFocus) { 33 | if (value instanceof Preference.SelectPreferenceItem) { 34 | value = ((Preference.SelectPreferenceItem)value).getName(); 35 | } 36 | super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 37 | return this; 38 | } 39 | } -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/ui/TextRightClickPopup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.ui; 19 | 20 | import javax.swing.*; 21 | import javax.swing.event.PopupMenuEvent; 22 | import javax.swing.event.PopupMenuListener; 23 | import javax.swing.text.JTextComponent; 24 | import javax.swing.undo.UndoManager; 25 | import java.awt.event.ActionEvent; 26 | import java.awt.event.KeyEvent; 27 | 28 | public class TextRightClickPopup { 29 | 30 | public static void register(JTextComponent input) { 31 | final JPopupMenu popup = new JPopupMenu(); 32 | 33 | popup.addPopupMenuListener(new PopupMenuListener() { 34 | @Override 35 | public void popupMenuWillBecomeVisible(PopupMenuEvent e) { 36 | input.requestFocus(); 37 | input.requestFocusInWindow(); 38 | } 39 | @Override 40 | public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {} 41 | @Override 42 | public void popupMenuCanceled(PopupMenuEvent e) {} 43 | }); 44 | 45 | final UndoManager undoManager = new UndoManager(); 46 | input.getDocument().addUndoableEditListener(undoManager); 47 | 48 | final Action undoAction = new AbstractAction(I18N.get("menu.undo")) { 49 | @Override 50 | public void actionPerformed(ActionEvent e) { 51 | if(undoManager.canUndo()) { 52 | undoManager.undo(); 53 | } 54 | } 55 | }; 56 | final Action redoAction = new AbstractAction(I18N.get("menu.redo")) { 57 | @Override 58 | public void actionPerformed(ActionEvent e) { 59 | if(undoManager.canRedo()) { 60 | undoManager.redo(); 61 | } 62 | } 63 | }; 64 | 65 | final Action copyAction = new AbstractAction(I18N.get("menu.copy")) { 66 | @Override 67 | public void actionPerformed(ActionEvent e) { 68 | input.copy(); 69 | } 70 | }; 71 | final Action cutAction = new AbstractAction(I18N.get("menu.cut")) { 72 | @Override 73 | public void actionPerformed(ActionEvent e) { 74 | input.cut(); 75 | } 76 | }; 77 | final Action pasteAction = new AbstractAction(I18N.get("menu.paste")) { 78 | @Override 79 | public void actionPerformed(ActionEvent e) { 80 | input.paste(); 81 | } 82 | }; 83 | final Action deleteAction = new AbstractAction(I18N.get("menu.delete")) { 84 | @Override 85 | public void actionPerformed(ActionEvent e) { 86 | input.replaceSelection(""); 87 | } 88 | }; 89 | 90 | final Action selectAllAction = new AbstractAction(I18N.get("menu.selectAll")) { 91 | @Override 92 | public void actionPerformed(ActionEvent e) { 93 | input.selectAll(); 94 | } 95 | }; 96 | 97 | 98 | input.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.CTRL_MASK), undoAction); 99 | input.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.SHIFT_MASK | KeyEvent.CTRL_MASK), redoAction); 100 | 101 | input.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.CTRL_MASK), cutAction); 102 | input.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_MASK), copyAction); 103 | input.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_MASK), pasteAction); 104 | //deleteAction 105 | 106 | input.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_MASK), selectAllAction); 107 | 108 | /* ----------------------- */ 109 | popup.add(undoAction); 110 | popup.add(redoAction); 111 | 112 | popup.addSeparator(); 113 | 114 | popup.add(cutAction); 115 | popup.add(copyAction); 116 | popup.add(pasteAction); 117 | popup.add(deleteAction); 118 | 119 | popup.addSeparator(); 120 | 121 | popup.add(selectAllAction); 122 | /* ----------------------- */ 123 | 124 | input.setComponentPopupMenu(popup); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/updater/UpdateInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.updater; 19 | 20 | public class UpdateInfo { 21 | 22 | private final String version; 23 | private final int versionCode; 24 | private final String changelog; 25 | 26 | private final String releasePage; 27 | private final String downloadUrl; 28 | 29 | public UpdateInfo(String version, int versionCode, String changelog, String releasePage, String downloadUrl) { 30 | this.version = version; 31 | this.versionCode = versionCode; 32 | this.changelog = changelog; 33 | 34 | this.releasePage = releasePage; 35 | this.downloadUrl = downloadUrl; 36 | } 37 | 38 | public String getVersion() { 39 | return version; 40 | } 41 | 42 | public int getVersionCode() { 43 | return versionCode; 44 | } 45 | 46 | public String getChangelog() { 47 | return changelog; 48 | } 49 | 50 | public String getReleasePage() { 51 | return releasePage; 52 | } 53 | 54 | public String getDownloadUrl() { 55 | return downloadUrl; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/utilities/SystemUtility.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.utilities; 19 | 20 | import sun.net.dns.ResolverConfiguration; 21 | 22 | import java.awt.*; 23 | import java.io.IOException; 24 | import java.util.ArrayList; 25 | import java.util.List; 26 | 27 | public class SystemUtility { 28 | 29 | public static final String OS = System.getProperty("os.name").toLowerCase(); 30 | public static final boolean IS_WINDOWS = OS.contains("windows"); 31 | public static final boolean OLD_OS = IS_WINDOWS && ( 32 | OS.contains("2003") || 33 | OS.contains("xp") || 34 | OS.contains("2000") 35 | ); 36 | 37 | public static final boolean IS_TERMINAL = GraphicsEnvironment.isHeadless(); 38 | 39 | public static Process executeWindowsCommand(String command) throws IOException { 40 | return executeWindowsCommand("cmd", command); 41 | } 42 | 43 | public static Process executeWindowsCommand(String handler, String command) throws IOException { 44 | return Runtime.getRuntime().exec(handler + ".exe /C " + command); 45 | } 46 | 47 | public static List getDNSServers() { 48 | try { 49 | Class.forName("sun.net.dns.ResolverConfiguration"); 50 | List list = null; 51 | try { 52 | list = ResolverConfiguration.open().nameservers(); 53 | } catch (Throwable ignored) {} 54 | return list == null ? new ArrayList<>() : new ArrayList<>(list); 55 | } catch (ClassNotFoundException ex) { 56 | return new ArrayList<>(); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /desktop/src/main/java/io/github/krlvm/powertunnel/desktop/utilities/Utility.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.desktop.utilities; 19 | 20 | import io.github.krlvm.powertunnel.desktop.Main; 21 | 22 | import java.awt.*; 23 | import java.io.File; 24 | import java.io.IOException; 25 | import java.io.InputStream; 26 | import java.net.URI; 27 | import java.net.URISyntaxException; 28 | import java.nio.file.Files; 29 | import java.nio.file.Path; 30 | import java.nio.file.StandardCopyOption; 31 | 32 | public class Utility { 33 | 34 | public static void extractResource(Path destination, String src) throws IOException { 35 | try(final InputStream in = Main.class.getResourceAsStream("/" + src)) { 36 | Files.copy(in, destination, StandardCopyOption.REPLACE_EXISTING); 37 | } 38 | } 39 | 40 | public static void launchBrowser(String address) { 41 | if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { 42 | final URI url; 43 | try { 44 | url = new URI(address); 45 | } catch (URISyntaxException ex) { 46 | return; 47 | } 48 | try { 49 | Desktop.getDesktop().browse(url); 50 | } catch (IOException ex) { 51 | ex.printStackTrace(); 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /desktop/src/main/resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krlvm/PowerTunnel/3e5df1e6ce4e12628fee4e2b940e4db9067cde3c/desktop/src/main/resources/icon.png -------------------------------------------------------------------------------- /desktop/src/main/resources/icon_dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krlvm/PowerTunnel/3e5df1e6ce4e12628fee4e2b940e4db9067cde3c/desktop/src/main/resources/icon_dev.png -------------------------------------------------------------------------------- /desktop/src/main/resources/locale/messages_en.properties: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of PowerTunnel. 3 | # 4 | # PowerTunnel is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # PowerTunnel is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with PowerTunnel. If not, see . 16 | # 17 | 18 | main.status.NOT_RUNNING = Server is not running 19 | main.status.STARTING = Server is starting 20 | main.status.RUNNING = Server is running 21 | main.status.STOPPING = Server is stopping 22 | 23 | main.start = Start server 24 | main.stop = Stop server 25 | 26 | main.plugins = Plugins 27 | main.options = Options 28 | main.about = About 29 | 30 | main.reportBug = Report a bug 31 | main.help = Help 32 | 33 | main.configureAutomaticallyPrompt = Configure system proxy automatically? 34 | main.failedToStartServer=Failed to start server 35 | 36 | 37 | plugins.title = Plugins 38 | 39 | plugins.disable = Disable 40 | plugins.enable = Enable 41 | 42 | plugins.homepage = Homepage 43 | plugins.settings = Settings 44 | plugins.additionalConfiguration=Additional configuration 45 | 46 | plugins.notConfigurable = Plugin is not configurable 47 | plugins.emptyPreferences = Plugin preferences is empty 48 | 49 | plugins.failedToRead = Failed to read plugin preferences 50 | plugins.failedToOpen = Failed to open plugin preferences 51 | 52 | plugins.note = Plugins can't be configured when server is running
Verify before installing as they may be malicious 53 | plugins.visitRegistry = Visit official plugins registry 54 | 55 | 56 | preferences.subtitle = preferences 57 | preferences.failedToSave = Failed to save preferences 58 | 59 | preferences.incorrectConfiguration = Incorrect configuration detected, do you want to reset it? 60 | preferences.exitConfirmation = Do you want to save changes? 61 | preferences.resetConfirmation = Do you want to reset configuration? 62 | 63 | preferences.note = Some preferences may not be available
because they were set from the CLI 64 | 65 | 66 | options.title = Options 67 | 68 | options.recommended = recommended 69 | 70 | options.group.proxyConnection = Proxy connection 71 | 72 | options.auto_proxy_setup = Auto proxy setup 73 | options.auto_proxy_setup.desc = Automatically setting up system proxy server configuration\n\nWindows: Internet Explorer may be started for a few seconds to apply changes. 74 | 75 | options.upstream_proxy_enabled = Connect via upstream proxy server 76 | options.upstream_proxy_enabled.desc = Use a proxy server to connect to the Internet 77 | 78 | options.upstream_proxy_host = Upstream proxy host 79 | options.upstream_proxy_port = Upstream proxy port 80 | 81 | options.upstream_proxy_protocol = Upstream proxy protocol 82 | 83 | options.upstream_proxy_auth_enabled = Upstream proxy authorization 84 | options.upstream_proxy_auth_enabled.desc = Authenticate on upstream proxy server 85 | 86 | options.upstream_proxy_auth_username = Upstream proxy username 87 | options.upstream_proxy_auth_password = Upstream proxy password 88 | 89 | options.group.proxySettings = Proxy settings 90 | 91 | options.transparent_mode = Transparent mode 92 | options.transparent_mode.desc = When proxy server is in transparent mode, it declares that it does not modify requests and responses and does not set 'Via' header 93 | 94 | options.strict_dns = Strict DNS Mode 95 | options.strict_dns.desc=When DNS Mode is not set to Strict, hostname can be resolved with the default DNS Resolver\nif the custom one could not or failed resolve hostname. 96 | 97 | options.allow_requests_to_origin_server = Allow requests to origin server 98 | options.allow_requests_to_origin_server.desc = Experimental option, fixed many connectivity issues 99 | 100 | options.note = NOTE: Some features have been moved to plugins,
so you need to open their settings for configuring 101 | 102 | 103 | updater.checkForUpdates = Check for updates 104 | updater.checkingForUpdates = Checking for updates... 105 | updater.noUpdates = No updates are available 106 | updater.updateAvailable = An update is available 107 | updater.failedToCheck = Failed to check for updates 108 | updater.dialog=%s is ready to update!

Version: %s

Release page: %s
Download: %s 109 | 110 | 111 | yes = Yes 112 | no = No 113 | ok = OK 114 | 115 | reset = Reset 116 | cancel = Cancel 117 | save = Save 118 | 119 | 120 | tray.version = Version 121 | 122 | tray.open = Open 123 | tray.exit = Exit 124 | 125 | tray.stillRunning = is still running in tray mode 126 | 127 | 128 | menu.undo = Undo 129 | menu.redo = Redo 130 | 131 | menu.cut = Cut 132 | menu.copy = Copy 133 | menu.paste = Paste 134 | menu.delete = Delete 135 | 136 | menu.selectAll = Select All 137 | options.proxy_auth_enabled=Require proxy authorization 138 | options.proxy_auth_enabled.desc=Proxy server will require Basic HTTP Proxy Authorization 139 | options.proxy_auth_username=Username 140 | options.proxy_auth_password=Password 141 | preferences.restartProxyPrompt=Changes won't take effect until you restart the proxy, restart it now? -------------------------------------------------------------------------------- /desktop/src/main/resources/locale/messages_ru.properties: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of PowerTunnel. 3 | # 4 | # PowerTunnel is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # PowerTunnel is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with PowerTunnel. If not, see . 16 | # 17 | main.status.NOT_RUNNING=Сервер не запущен 18 | main.status.STARTING=Сервер запускается 19 | main.status.RUNNING=Сервер запущен 20 | main.status.STOPPING=Сервер останавливается 21 | main.start=Запустить 22 | main.stop=Остановить 23 | main.plugins=Плагины 24 | main.options=Настройки 25 | main.about=О программе 26 | main.reportBug=Сообщить об ошибке 27 | main.help=Помощь 28 | main.configureAutomaticallyPrompt=Настроить системный прокси-сервер автоматически? 29 | main.failedToStartServer=Ошибка при запуске сервера 30 | plugins.title=Плагины 31 | plugins.disable=Отключить 32 | plugins.enable=Включить 33 | plugins.homepage=Вебсайт 34 | plugins.settings=Настроить 35 | plugins.additionalConfiguration=Дополнительная конфигурация 36 | plugins.notConfigurable=Плагин не имеет настроек 37 | plugins.emptyPreferences=Список настроек плагина пуст 38 | plugins.failedToRead=Ошибка при чтении настроек плагина 39 | plugins.failedToOpen=Ошибка при открытии настроек плагина 40 | plugins.note=Настройки недоступны когда сервер включен
Сторонние плагины могут быть вредоносны 41 | plugins.visitRegistry=Официальный реестр плагинов 42 | preferences.subtitle=- параметры 43 | preferences.failedToSave=Ошибка при сохранении параметров 44 | preferences.incorrectConfiguration=Обнаружена некорректная конфигурация, вы хотите сбросить ее? 45 | preferences.exitConfirmation=Вы хотите сохранить изменения? 46 | preferences.resetConfirmation=Вы действительно хотите сбросить настройки? 47 | preferences.note=Некоторые параметры могут быть недоступны,
так как установлены из CLI 48 | options.title=Настройки 49 | options.recommended=рекомендуется 50 | options.group.proxyConnection=Соединение с прокси 51 | options.auto_proxy_setup=Автоматическая настройка прокси 52 | options.auto_proxy_setup.desc=Автоматически настраивает системный прокси-сервер\n\nWindows: Internet Explorer может быть запущен на несколько секунд для применения изменений 53 | options.upstream_proxy_enabled=Подключаться через внешний прокси-сервер 54 | options.upstream_proxy_enabled.desc=Использовать внешний прокси-сервер для доступа в Интернет 55 | options.upstream_proxy_host=Адрес внешнего прокси-сервера 56 | options.upstream_proxy_port=Порт внешнего прокси-сервера 57 | options.upstream_proxy_protocol = Протокол внешнего прокси-сервера 58 | options.upstream_proxy_auth_enabled=Авторизация на внешнем прокси-сервере 59 | options.upstream_proxy_auth_enabled.desc=Авторизовываться на внешнем прокси-сервере 60 | options.upstream_proxy_auth_username=Имя пользователя внешнего прокси-сервера 61 | options.upstream_proxy_auth_password=Пароль внешнего прокси-сервера 62 | options.group.proxySettings=Настройки прокси 63 | options.transparent_mode=Прозрачный режим 64 | options.transparent_mode.desc=Когда прокси-сервер работает в прозрачном режиме, он декларирует, что не вмешивается в трафик и не добавляет заголовок 'Via' 65 | options.strict_dns=Строгий режим DNS 66 | options.strict_dns.desc=Когда строгий режим отключен, доменное имя может быть разрешено с помощью стандартного DNS-резолвера,\nесли установленный резолвер не смог разрешить доменное имя или в процессе разрешения\nпроизошла ошибка. 67 | options.allow_requests_to_origin_server=Разрешить запросы к исходному серверу 68 | options.allow_requests_to_origin_server.desc=Экспериментальная опция, исправляет множество проблем при соединении 69 | options.note=ПРИМЕЧАНИЕ: Некоторые функции были выделены в плагины,
поэтому необходимо открыть их параметры для настройки 70 | updater.checkForUpdates=Проверить обновления 71 | updater.checkingForUpdates=Проверка обновлений... 72 | updater.noUpdates=Нет доступных обновлений 73 | updater.updateAvailable=Доступно обновление 74 | updater.failedToCheck=При проверке обновлений произошла ошибка 75 | updater.dialog=Доступно обновление %s

Версия: %s

Сведения о версии: %s
Скачать: %s 76 | yes=Да 77 | no=Нет 78 | ok=ОК 79 | reset=Сбросить 80 | cancel=Отмена 81 | save=Сохранить 82 | tray.version=Версия 83 | tray.open=Открыть 84 | tray.exit=Выйти 85 | tray.stillRunning=продолжает работать в трее 86 | menu.undo=Отменить 87 | menu.redo=Вернуть 88 | menu.cut=Вырезать 89 | menu.copy=Копировать 90 | menu.paste=Вставить 91 | menu.delete=Удалить 92 | menu.selectAll=Выделить все 93 | options.proxy_auth_enabled=Запрашивать авторизацию на прокси-сервере 94 | options.proxy_auth_enabled.desc=Прокси-сервер будет запрашивать базовую HTTP авторизацию 95 | options.proxy_auth_username=Имя пользователя 96 | options.proxy_auth_password=Пароль 97 | preferences.restartProxyPrompt=Изменения не вступят в силу до перезапуска прокси-сервера, перезапустить его сейчас? -------------------------------------------------------------------------------- /desktop/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /desktop/src/main/resources/plugins/DNSResolver.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krlvm/PowerTunnel/3e5df1e6ce4e12628fee4e2b940e4db9067cde3c/desktop/src/main/resources/plugins/DNSResolver.jar -------------------------------------------------------------------------------- /desktop/src/main/resources/plugins/LibertyTunnel.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krlvm/PowerTunnel/3e5df1e6ce4e12628fee4e2b940e4db9067cde3c/desktop/src/main/resources/plugins/LibertyTunnel.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krlvm/PowerTunnel/3e5df1e6ce4e12628fee4e2b940e4db9067cde3c/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of PowerTunnel. 3 | # 4 | # PowerTunnel is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # PowerTunnel is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with PowerTunnel. If not, see . 16 | # 17 | 18 | distributionBase=GRADLE_USER_HOME 19 | distributionPath=wrapper/dists 20 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip 21 | zipStoreBase=GRADLE_USER_HOME 22 | zipStorePath=wrapper/dists 23 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /littleproxy/.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | -------------------------------------------------------------------------------- /littleproxy/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | plugins { 19 | id 'java-library' 20 | } 21 | 22 | group 'io.github.krlvm.powertunnel.proxy' 23 | version '2.0' 24 | 25 | dependencies { 26 | api 'xyz.rogfam:littleproxy:2.0.5' 27 | api 'org.bouncycastle:bcpkix-jdk15on:1.69' 28 | 29 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2' 30 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2' 31 | } -------------------------------------------------------------------------------- /littleproxy/src/main/java/java/nio/charset/StandardCharsets.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | /* 19 | * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 20 | * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 21 | * 22 | * 23 | * 24 | * 25 | * 26 | * 27 | * 28 | * 29 | * 30 | * 31 | * 32 | * 33 | * 34 | * 35 | * 36 | * 37 | * 38 | * 39 | * 40 | * 41 | */ 42 | package java.nio.charset; 43 | 44 | import java.nio.charset.Charset; 45 | 46 | /** 47 | * Constant definitions for the standard {@link Charset Charsets}. These 48 | * charsets are guaranteed to be available on every implementation of the Java 49 | * platform. 50 | * 51 | * @see Standard Charsets 52 | * @since 1.7 53 | */ 54 | public final class StandardCharsets { 55 | 56 | private StandardCharsets() { 57 | throw new AssertionError("No java.nio.charset.StandardCharsets instances for you!"); 58 | } 59 | /** 60 | * Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the 61 | * Unicode character set 62 | */ 63 | public static final Charset US_ASCII = Charset.forName("US-ASCII"); 64 | /** 65 | * ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1 66 | */ 67 | public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); 68 | /** 69 | * Eight-bit UCS Transformation Format 70 | */ 71 | public static final Charset UTF_8 = Charset.forName("UTF-8"); 72 | /** 73 | * Sixteen-bit UCS Transformation Format, big-endian byte order 74 | */ 75 | public static final Charset UTF_16BE = Charset.forName("UTF-16BE"); 76 | /** 77 | * Sixteen-bit UCS Transformation Format, little-endian byte order 78 | */ 79 | public static final Charset UTF_16LE = Charset.forName("UTF-16LE"); 80 | /** 81 | * Sixteen-bit UCS Transformation Format, byte order identified by an 82 | * optional byte-order mark 83 | */ 84 | public static final Charset UTF_16 = Charset.forName("UTF-16"); 85 | } 86 | -------------------------------------------------------------------------------- /littleproxy/src/main/java/org/littleshoot/proxy/mitm/MitmHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package org.littleshoot.proxy.mitm; 19 | 20 | import java.io.Closeable; 21 | import java.io.IOException; 22 | 23 | public class MitmHelper { 24 | 25 | // From Apache Commons-IO 26 | public static void closeQuietly(Closeable is) { 27 | if(is == null) return; 28 | try { 29 | is.close(); 30 | } catch (IOException ignore) {} 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /sample-plugin/.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | -------------------------------------------------------------------------------- /sample-plugin/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | plugins { 19 | id 'java' 20 | } 21 | 22 | group 'io.github.krlvm.powertunnel.plugins' 23 | version '2.0' 24 | 25 | jar { 26 | destinationDirectory.set(file("$rootDir/desktop/build/run/plugins")) 27 | } 28 | 29 | dependencies { 30 | implementation project(':sdk') 31 | 32 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0' 33 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0' 34 | } -------------------------------------------------------------------------------- /sample-plugin/src/main/java/io/github/krlvm/powertunnel/plugins/sample/SamplePlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.plugins.sample; 19 | 20 | import io.github.krlvm.powertunnel.sdk.http.ProxyRequest; 21 | import io.github.krlvm.powertunnel.sdk.http.ProxyResponse; 22 | import io.github.krlvm.powertunnel.sdk.plugin.PowerTunnelPlugin; 23 | import io.github.krlvm.powertunnel.sdk.proxy.ProxyAdapter; 24 | import io.github.krlvm.powertunnel.sdk.proxy.ProxyServer; 25 | import org.jetbrains.annotations.NotNull; 26 | 27 | import java.nio.charset.StandardCharsets; 28 | 29 | public class SamplePlugin extends PowerTunnelPlugin { 30 | 31 | @Override 32 | public void onProxyInitialization(ProxyServer proxy) { 33 | proxy.setMITMEnabled(true); 34 | proxy.setFullResponse(true); 35 | proxy.setFullRequest(true); 36 | 37 | this.registerProxyListener(new ProxyAdapter() { 38 | @Override 39 | public void onClientToProxyRequest(@NotNull ProxyRequest request) { 40 | if (request.isEncrypted()) return; 41 | if (!request.getHost().equals("github.com")) return; 42 | 43 | final ProxyResponse response = getServer() 44 | .getProxyServer() 45 | .getResponseBuilder("PowerTunnel Test Plugin") 46 | .header("X-PT-Test", "OK") 47 | .build(); 48 | request.setResponse(response); 49 | } 50 | 51 | @Override 52 | public void onProxyToClientResponse(@NotNull ProxyResponse response) { 53 | if (!proxy.isMITMEnabled()) return; 54 | if (!response.isDataPacket()) return; 55 | 56 | if (!"text/html; charset=utf-8".equals(response.headers().get("Content-Type"))) return; 57 | 58 | final byte[] raw = response.content(); 59 | final String str = new String(raw, StandardCharsets.UTF_8); 60 | 61 | response.setContent(("Injected response part" + str).getBytes(StandardCharsets.UTF_8)); 62 | } 63 | }); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /sample-plugin/src/main/resources/locale/messages_en.properties: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of PowerTunnel. 3 | # 4 | # PowerTunnel is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # PowerTunnel is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with PowerTunnel. If not, see . 16 | # 17 | test-switch=Test Preference (switch) 18 | test-check=Test Preference (check) 19 | test-check.desc=Checkbox Test Preference Description -------------------------------------------------------------------------------- /sample-plugin/src/main/resources/locale/messages_ru.properties: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of PowerTunnel. 3 | # 4 | # PowerTunnel is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # PowerTunnel is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with PowerTunnel. If not, see . 16 | # 17 | 18 | test-switch=Тестовая настройка (переключатель) 19 | test-check=Тестовая настройка (флажок) 20 | test-check.desc=Описание тестовой настройки - флажка -------------------------------------------------------------------------------- /sample-plugin/src/main/resources/plugin.ini: -------------------------------------------------------------------------------- 1 | id: sample-plugin 2 | version: 1.0 3 | versionCode: 1 4 | name: Sample Plugin 5 | description: Sample Plugin for PowerTunnel 6 | author: krlvm 7 | homepage: https://github.com/krlvm/PowerTunnel 8 | mainClass: io.github.krlvm.powertunnel.plugins.sample.SamplePlugin 9 | targetSdkVersion: 90 -------------------------------------------------------------------------------- /sample-plugin/src/main/resources/preferences.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "key": "test-check", 4 | "defaultValue": true, 5 | "type": "checkbox" 6 | }, 7 | { 8 | "key": "test-switch", 9 | "description": "Switch Test Preference Description", 10 | "defaultValue": false, 11 | "type": "switch" 12 | }, 13 | { 14 | "key": "test-str", 15 | "title": "Test Preference (str)", 16 | "description": "String Test Preference Description", 17 | "defaultValue": "default value of test-str", 18 | "type": "string" 19 | }, 20 | { 21 | "key": "test-number", 22 | "title": "Test Preference (number)", 23 | "description": "Number Test Preference Description", 24 | "defaultValue": 5, 25 | "type": "number" 26 | }, 27 | { 28 | "key": "test-select", 29 | "title": "Test Preference (select)", 30 | "description": "Select Test Preference Description", 31 | "defaultValue": "opt1", 32 | "type": "select", 33 | "items": [ 34 | { 35 | "key": "opt1", 36 | "name": "Option 1 Name" 37 | }, 38 | { 39 | "key": "opt2", 40 | "name": "Option 2 Name" 41 | }, 42 | { 43 | "key": "opt3", 44 | "name": "Option 3 Name" 45 | } 46 | ] 47 | }, 48 | 49 | { 50 | "group": "dependent-preferences", 51 | "title": "Dependent preferences", 52 | "description": "Dependent preferences group description", 53 | "preferences": [ 54 | { 55 | "key": "test-number-d", 56 | "title": "Test Preference (number) dependent on 'test-check'", 57 | "description": "Number Test-C Preference Description", 58 | "type": "number", 59 | "dependency": "test-check" 60 | }, 61 | { 62 | "key": "test-number-d", 63 | "title": "Test Preference (number) dependent on 'test-str' (val='value')", 64 | "description": "Number Test-S Preference Description", 65 | "type": "number", 66 | "dependency": "test-str", 67 | "dependencyValue": "value" 68 | }, 69 | { 70 | "key": "test-number-n", 71 | "title": "Test Preference (number) dependent on 'test-number' (val='5')", 72 | "description": "Number Test-N Preference Description", 73 | "type": "number", 74 | "dependency": "test-number", 75 | "dependencyValue": 5 76 | }, 77 | { 78 | "key": "test-number-n", 79 | "title": "Test Preference (number) dependent on 'test-select' (val='opt2')", 80 | "description": "Number Test-SEL Preference Description", 81 | "type": "number", 82 | "dependency": "test-select", 83 | "dependencyValue": "opt2" 84 | } 85 | ] 86 | } 87 | ] -------------------------------------------------------------------------------- /sdk/.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | -------------------------------------------------------------------------------- /sdk/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | plugins { 19 | id 'java-library' 20 | } 21 | 22 | version '2.0' 23 | 24 | dependencies { 25 | // Include single class from Android SDK (Base64) as a runtime dependency 26 | // to avoid using reflection and speed up performance by using direct calls 27 | implementation fileTree(dir: 'libs', include: ['*.jar']) 28 | 29 | api 'org.jetbrains:annotations:23.0.0' 30 | api 'org.slf4j:slf4j-api:1.7.35' 31 | 32 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2' 33 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2' 34 | } 35 | 36 | task fatJar(type: Jar, group: 'build', description: 'Assembles a jar archive containing the main classes and all dependencies.') { 37 | archiveClassifier = 'all' 38 | duplicatesStrategy DuplicatesStrategy.EXCLUDE 39 | 40 | from { 41 | configurations.runtimeClasspath.findAll {it.name.endsWith('jar') }.collect { zipTree(it) } 42 | } { 43 | exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA' 44 | } 45 | 46 | with jar 47 | } -------------------------------------------------------------------------------- /sdk/libs/android-base64.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krlvm/PowerTunnel/3e5df1e6ce4e12628fee4e2b940e4db9067cde3c/sdk/libs/android-base64.jar -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/PowerTunnelServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk; 19 | 20 | import io.github.krlvm.powertunnel.sdk.configuration.Configuration; 21 | import io.github.krlvm.powertunnel.sdk.exceptions.ProxyStartException; 22 | import io.github.krlvm.powertunnel.sdk.plugin.PluginInfo; 23 | import io.github.krlvm.powertunnel.sdk.plugin.PowerTunnelPlugin; 24 | import io.github.krlvm.powertunnel.sdk.proxy.ProxyListener; 25 | import io.github.krlvm.powertunnel.sdk.proxy.ProxyServer; 26 | import io.github.krlvm.powertunnel.sdk.proxy.ProxyStatus; 27 | import io.github.krlvm.powertunnel.sdk.types.PowerTunnelPlatform; 28 | import io.github.krlvm.powertunnel.sdk.types.VersionInfo; 29 | import org.jetbrains.annotations.NotNull; 30 | 31 | import java.io.File; 32 | import java.io.IOException; 33 | 34 | public interface PowerTunnelServer { 35 | 36 | /** 37 | * Starts proxy server 38 | * @throws ProxyStartException if proxy server failed to start 39 | */ 40 | void start() throws ProxyStartException; 41 | 42 | /** 43 | * Stops proxy server 44 | */ 45 | void stop(); 46 | 47 | /** 48 | * Check whether proxy server is running 49 | * 50 | * @return whether proxy server is currently running 51 | */ 52 | boolean isRunning(); 53 | 54 | /** 55 | * Returns proxy server status 56 | * 57 | * @return proxy server status 58 | */ 59 | @NotNull ProxyStatus getStatus(); 60 | 61 | /** 62 | * Registers proxy server listener 63 | * 64 | * @param pluginInfo registrant plugin 65 | * @param listener proxy server listener 66 | * @return ID of registered listener 67 | */ 68 | void registerProxyListener(@NotNull PluginInfo pluginInfo, @NotNull ProxyListener listener); 69 | 70 | /** 71 | * Registers proxy server listener 72 | * 73 | * @param pluginInfo registrant plugin 74 | * @param listener proxy server listeners 75 | * @param priority proxy server listener priority 76 | */ 77 | void registerProxyListener(@NotNull PluginInfo pluginInfo, @NotNull ProxyListener listener, int priority); 78 | 79 | /** 80 | * Unregisters proxy server listener 81 | * @param listener registered proxy server listener 82 | */ 83 | void unregisterProxyListener(@NotNull ProxyListener listener); 84 | 85 | /** 86 | * Registers server listener 87 | * 88 | * @param pluginInfo registrant plugin 89 | * @param listener proxy listener 90 | */ 91 | void registerServerListener(@NotNull PluginInfo pluginInfo, @NotNull ServerListener listener); 92 | 93 | /** 94 | * Unregisters server listener 95 | * @param listener registered server listener 96 | */ 97 | void unregisterServerListener(@NotNull ServerListener listener); 98 | 99 | /** 100 | * Reads plugin configuration 101 | * 102 | * @param pluginInfo plugin info 103 | * @return configuration store 104 | */ 105 | @NotNull Configuration readConfiguration(@NotNull PluginInfo pluginInfo); 106 | 107 | /** 108 | * Saves plugin configuration 109 | * 110 | * @param pluginInfo plugin info 111 | * @param configuration configuration store 112 | */ 113 | void saveConfiguration(@NotNull PluginInfo pluginInfo, @NotNull Configuration configuration); 114 | 115 | /** 116 | * Reads file in configurations directory as plain text 117 | * 118 | * @param filename file name 119 | * @return plain text 120 | * @throws IOException on file read error 121 | */ 122 | @NotNull String readTextFile(@NotNull String filename) throws IOException; 123 | 124 | /** 125 | * Saves file in configurations directory as plain text 126 | * 127 | * @param filename file name 128 | * @param text plain text to write 129 | * @throws IOException on file read error 130 | */ 131 | @NotNull void saveTextFile(@NotNull String filename, @NotNull String text) throws IOException; 132 | 133 | /** 134 | * Returns proxy server 135 | * If proxy server was not created, returns null 136 | * 137 | * @return proxy server 138 | */ 139 | ProxyServer getProxyServer(); 140 | 141 | /** 142 | * Returns PowerTunnel platform 143 | * @return PowerTunnel platform 144 | */ 145 | PowerTunnelPlatform getPlatform(); 146 | 147 | /** 148 | * Returns PowerTunnel Core version info 149 | * @return Core version info 150 | */ 151 | VersionInfo getVersion(); 152 | } 153 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/ServerAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk; 19 | 20 | import io.github.krlvm.powertunnel.sdk.proxy.ProxyStatus; 21 | import org.jetbrains.annotations.NotNull; 22 | 23 | public abstract class ServerAdapter implements ServerListener { 24 | 25 | @Override 26 | public void beforeProxyStatusChanged(@NotNull ProxyStatus status) {} 27 | 28 | @Override 29 | public void onProxyStatusChanged(@NotNull ProxyStatus status) {} 30 | } 31 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/ServerListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk; 19 | 20 | import io.github.krlvm.powertunnel.sdk.proxy.ProxyServer; 21 | import io.github.krlvm.powertunnel.sdk.proxy.ProxyStatus; 22 | import org.jetbrains.annotations.NotNull; 23 | 24 | public interface ServerListener { 25 | 26 | /** 27 | * Called before server status changing, 28 | * e.g. after user stopped the server 29 | * 30 | * @param status new server status 31 | */ 32 | void beforeProxyStatusChanged(@NotNull ProxyStatus status); 33 | 34 | /** 35 | * Called after server status has changed, 36 | * e.g. server stopped 37 | * 38 | * @param status new server status 39 | */ 40 | void onProxyStatusChanged(@NotNull ProxyStatus status); 41 | } 42 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/configuration/Configuration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.configuration; 19 | 20 | import java.util.Collection; 21 | import java.util.Map; 22 | 23 | public interface Configuration { 24 | 25 | String get(String key, String defaultValue); 26 | void set(String key, String value); 27 | 28 | int getInt(String key, int defaultValue); 29 | void setInt(String key, int value); 30 | 31 | long getLong(String key, long defaultValue); 32 | void setLong(String key, long value); 33 | 34 | boolean getBoolean(String key, boolean defaultValue); 35 | void setBoolean(String key, boolean value); 36 | 37 | boolean contains(String key); 38 | void remove(String key); 39 | 40 | Map toMap(); 41 | Collection keys(); 42 | void clear(); 43 | 44 | String EXTENSION = ".ini"; 45 | } 46 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/exceptions/ConfigurationLoadException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.exceptions; 19 | 20 | public class ConfigurationLoadException extends Exception { 21 | 22 | public ConfigurationLoadException(Throwable cause) { 23 | super(cause); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/exceptions/PluginLoadException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.exceptions; 19 | 20 | public class PluginLoadException extends ProxyStartException { 21 | 22 | private final String jarFile; 23 | 24 | public PluginLoadException(String jarFile, String message, Throwable cause) { 25 | super(message, cause); 26 | this.jarFile = jarFile; 27 | } 28 | 29 | public PluginLoadException(String jarFile, String message) { 30 | super(message + " [" + jarFile + "]"); 31 | this.jarFile = jarFile; 32 | } 33 | 34 | public String getJarFile() { 35 | return jarFile; 36 | } 37 | 38 | @Override 39 | public String getMessage() { 40 | return super.getMessage() + " (" + jarFile + ")"; 41 | } 42 | 43 | @Override 44 | public String getLocalizedMessage() { 45 | return super.getLocalizedMessage() + " (" + jarFile + ")"; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/exceptions/ProxyStartException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.exceptions; 19 | 20 | public class ProxyStartException extends Exception { 21 | 22 | public ProxyStartException(String message) { 23 | super(message); 24 | } 25 | 26 | public ProxyStartException(Throwable cause) { 27 | super(cause); 28 | } 29 | 30 | public ProxyStartException(String message, Throwable cause) { 31 | super(message, cause); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/http/HttpHeaders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.http; 19 | 20 | import org.jetbrains.annotations.NotNull; 21 | import org.jetbrains.annotations.Nullable; 22 | 23 | import java.util.Set; 24 | 25 | public interface HttpHeaders { 26 | 27 | @Nullable String get(String name); 28 | void set(@NotNull String name, @NotNull String value); 29 | 30 | @Nullable Integer getInt(String name); 31 | void setInt(@NotNull String name, int value); 32 | 33 | @Nullable Short getShort(String name); 34 | void setShort(@NotNull String name, short value); 35 | 36 | @NotNull Set names(); 37 | boolean contains(@NotNull String name); 38 | void remove(@NotNull String name); 39 | 40 | boolean isEmpty(); 41 | int size(); 42 | } 43 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/http/HttpMethod.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.http; 19 | 20 | public enum HttpMethod { 21 | OPTIONS, 22 | GET, 23 | HEAD, 24 | POST, 25 | PUT, 26 | PATCH, 27 | DELETE, 28 | TRACE, 29 | CONNECT, 30 | } -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/http/ProxyMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.http; 19 | 20 | import io.github.krlvm.powertunnel.sdk.types.FullAddress; 21 | import org.jetbrains.annotations.NotNull; 22 | import org.jetbrains.annotations.Nullable; 23 | 24 | public interface ProxyMessage { 25 | 26 | @Nullable FullAddress address(); 27 | 28 | @NotNull HttpHeaders headers(); 29 | 30 | byte[] content(); 31 | } -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/http/ProxyRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.http; 19 | 20 | import io.github.krlvm.powertunnel.sdk.types.FullAddress; 21 | import org.jetbrains.annotations.NotNull; 22 | import org.jetbrains.annotations.Nullable; 23 | 24 | public interface ProxyRequest extends ProxyMessage { 25 | 26 | @NotNull HttpMethod getMethod(); 27 | void setMethod(@NotNull HttpMethod method); 28 | void setMethod(@NotNull String method); 29 | 30 | default boolean isEncrypted() { 31 | return getMethod() == HttpMethod.CONNECT; 32 | } 33 | 34 | default String getHost() { 35 | if (address() != null) { 36 | return address().getHost(); 37 | } else if (isEncrypted() && getUri() != null) { 38 | return FullAddress.fromString(getUri()).getHost(); 39 | } else if (headers().contains("Host")) { 40 | return headers().get("Host"); 41 | } 42 | return null; 43 | } 44 | 45 | boolean isDataPacket(); 46 | 47 | void setBlocked(boolean blocked); 48 | boolean isBlocked(); 49 | 50 | @NotNull String getUri(); 51 | void setUri(@NotNull String uri); 52 | 53 | @Nullable ProxyResponse getResponse(); 54 | void setResponse(@NotNull ProxyResponse response); 55 | 56 | @NotNull 57 | void setContent(byte[] content); 58 | } -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/http/ProxyResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.http; 19 | 20 | import org.jetbrains.annotations.NotNull; 21 | 22 | public interface ProxyResponse extends ProxyMessage { 23 | 24 | int code(); 25 | void setCode(int code); 26 | 27 | boolean isDataPacket(); 28 | 29 | void setContent(byte[] content); 30 | 31 | interface Builder { 32 | Builder code(int code); 33 | Builder contentType(String contentType); 34 | Builder header(String name, String value); 35 | Builder header(String name, int value); 36 | Builder header(String name, short value); 37 | ProxyResponse build(); 38 | } 39 | } -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/plugin/IPowerTunnelPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.plugin; 19 | 20 | import io.github.krlvm.powertunnel.sdk.ServerListener; 21 | import org.jetbrains.annotations.NotNull; 22 | 23 | public interface IPowerTunnelPlugin { 24 | 25 | int addListener(@NotNull ServerListener listener); 26 | } 27 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/plugin/PluginInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.plugin; 19 | 20 | import java.io.Serializable; 21 | 22 | public class PluginInfo implements Serializable { 23 | 24 | private final String id; 25 | private final String version; 26 | private final int versionCode; 27 | 28 | private final String name; 29 | private final String description; 30 | private final String author; 31 | private final String homepage; 32 | 33 | private final String[] configurationFiles; 34 | 35 | private final String mainClass; 36 | private final int targetSdkVersion; 37 | 38 | private final String source; 39 | 40 | /** 41 | * @param name plugin name 42 | * @param description plugin description 43 | * @param version plugin version 44 | * @param author plugin author 45 | * @param homepage plugin homepage 46 | * @param configurationFiles plugin additional configuration files 47 | * @param mainClass plugin main class 48 | * @param targetSdkVersion plugin target SDK version 49 | * @param source source jar 50 | */ 51 | public PluginInfo( 52 | String id, 53 | String version, 54 | int versionCode, 55 | String name, 56 | String description, 57 | String author, 58 | String homepage, 59 | String[] configurationFiles, 60 | String mainClass, 61 | int targetSdkVersion, 62 | String source 63 | ) { 64 | this.id = id; 65 | this.version = version; 66 | this.versionCode = versionCode; 67 | this.name = name; 68 | this.description = description; 69 | this.author = author; 70 | this.homepage = homepage; 71 | 72 | this.configurationFiles = configurationFiles; 73 | 74 | this.mainClass = mainClass; 75 | this.targetSdkVersion = targetSdkVersion; 76 | 77 | this.source = source; 78 | } 79 | 80 | public String getId() { 81 | return id; 82 | } 83 | 84 | public String getVersion() { 85 | return version; 86 | } 87 | 88 | public int getVersionCode() { 89 | return versionCode; 90 | } 91 | 92 | public String getName() { 93 | return name; 94 | } 95 | 96 | public String getDescription() { 97 | return description; 98 | } 99 | 100 | public String getAuthor() { 101 | return author; 102 | } 103 | 104 | public String getHomepage() { 105 | return homepage; 106 | } 107 | 108 | public String[] getConfigurationFiles() { 109 | return configurationFiles; 110 | } 111 | 112 | public String getMainClass() { 113 | return mainClass; 114 | } 115 | 116 | public int getTargetSdkVersion() { 117 | return targetSdkVersion; 118 | } 119 | 120 | public String getSource() { 121 | return source; 122 | } 123 | } -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/plugin/PowerTunnelPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.plugin; 19 | 20 | import io.github.krlvm.powertunnel.sdk.PowerTunnelServer; 21 | import io.github.krlvm.powertunnel.sdk.ServerListener; 22 | import io.github.krlvm.powertunnel.sdk.configuration.Configuration; 23 | import io.github.krlvm.powertunnel.sdk.proxy.ProxyListener; 24 | import io.github.krlvm.powertunnel.sdk.proxy.ProxyServer; 25 | import org.jetbrains.annotations.NotNull; 26 | 27 | import java.io.File; 28 | import java.io.IOException; 29 | 30 | public abstract class PowerTunnelPlugin { 31 | 32 | private PowerTunnelServer server; 33 | private PluginInfo info; 34 | 35 | private Configuration configuration; 36 | 37 | /** 38 | * Attaches PowerTunnel server instance to current server instance 39 | * Should be called only once after plugin initialization 40 | * 41 | * @param server PowerTunnel server instance 42 | */ 43 | public final void attachServer(@NotNull PowerTunnelServer server) { 44 | if(this.server != null) throw new IllegalStateException("A server is already attached"); 45 | this.server = server; 46 | } 47 | 48 | /** 49 | * Attaches plugin info to current plugin instance 50 | * @param info plugin info 51 | */ 52 | public void attachInfo(@NotNull PluginInfo info) { 53 | if(this.info != null) throw new IllegalStateException("PluginInfo is already attached"); 54 | this.info = info; 55 | } 56 | 57 | /** 58 | * Returns attached PowerTunnel server instance 59 | * @return attached PowerTunnel server instance 60 | */ 61 | public PowerTunnelServer getServer() { 62 | return this.server; 63 | } 64 | 65 | /** 66 | * Returns information about the plugin 67 | * @return plugin information 68 | */ 69 | public PluginInfo getInfo() { 70 | return info; 71 | } 72 | 73 | /** 74 | * Throws an exception if PowerTunnel server is not initialized 75 | */ 76 | protected void validateServer() { 77 | if(getServer() == null) throw new IllegalStateException("Server is not initialized yet"); 78 | } 79 | 80 | public void registerProxyListener(@NotNull ProxyListener listener) { 81 | validateServer(); 82 | getServer().registerProxyListener(getInfo(), listener); 83 | } 84 | public void registerProxyListener(@NotNull ProxyListener listener, int priority) { 85 | validateServer(); 86 | getServer().registerProxyListener(getInfo(), listener, priority); 87 | } 88 | 89 | public void registerServerListener(@NotNull ServerListener listener) { 90 | validateServer(); 91 | getServer().registerServerListener(getInfo(), listener); 92 | } 93 | 94 | public Configuration readConfiguration() { 95 | validateServer(); 96 | if(configuration == null) configuration = getServer().readConfiguration(getInfo()); 97 | return configuration; 98 | } 99 | 100 | public void saveConfiguration() throws IOException { 101 | if(configuration == null) return; 102 | getServer().saveConfiguration(getInfo(), configuration); 103 | } 104 | 105 | public String readTextFile(@NotNull String filename) throws IOException { 106 | validateServer(); 107 | return getServer().readTextFile(filename); 108 | } 109 | 110 | public void saveTextFile(@NotNull String filename, @NotNull String content) throws IOException { 111 | validateServer(); 112 | getServer().saveTextFile(filename, content); 113 | } 114 | 115 | 116 | /** 117 | * Called after proxy server creation 118 | * and before proxy server start 119 | * 120 | * @param proxy PowerTunnel Proxy Server 121 | */ 122 | public void onProxyInitialization(@NotNull ProxyServer proxy) {} 123 | 124 | @Override 125 | public String toString() { 126 | return "PowerTunnelPlugin{" + 127 | "info=" + info + 128 | '}'; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/proxy/DNSRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.proxy; 19 | 20 | import org.jetbrains.annotations.Nullable; 21 | 22 | import java.net.InetSocketAddress; 23 | 24 | public class DNSRequest { 25 | 26 | private final String host; 27 | private final int port; 28 | 29 | private InetSocketAddress response; 30 | 31 | public DNSRequest(String host, int port) { 32 | this.host = host; 33 | this.port = port; 34 | } 35 | 36 | public String getHost() { 37 | return host; 38 | } 39 | 40 | public int getPort() { 41 | return port; 42 | } 43 | 44 | 45 | /** 46 | * Returns response 47 | * If there's no DNS Resolvers registered, returns null 48 | * 49 | * @return response 50 | */ 51 | public @Nullable InetSocketAddress getResponse() { 52 | return response; 53 | } 54 | 55 | /** 56 | * Sets response 57 | * If response is set to null, the request will be resolved 58 | * using default DNS Resolver 59 | * 60 | * @param response 61 | */ 62 | public void setResponse(@Nullable InetSocketAddress response) { 63 | this.response = response; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/proxy/DNSResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.proxy; 19 | 20 | import org.jetbrains.annotations.NotNull; 21 | 22 | import java.net.InetSocketAddress; 23 | import java.net.UnknownHostException; 24 | 25 | public interface DNSResolver { 26 | @NotNull InetSocketAddress resolve(@NotNull String host, int port) throws UnknownHostException; 27 | } 28 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/proxy/ProxyAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.proxy; 19 | 20 | import io.github.krlvm.powertunnel.sdk.http.ProxyRequest; 21 | import io.github.krlvm.powertunnel.sdk.http.ProxyResponse; 22 | import io.github.krlvm.powertunnel.sdk.types.FullAddress; 23 | import org.jetbrains.annotations.NotNull; 24 | 25 | public abstract class ProxyAdapter implements ProxyListener { 26 | 27 | @Override 28 | public void onClientToProxyRequest(@NotNull ProxyRequest request) {} 29 | 30 | @Override 31 | public void onProxyToServerRequest(@NotNull ProxyRequest request) {} 32 | 33 | @Override 34 | public void onServerToProxyResponse(@NotNull ProxyResponse response) {} 35 | 36 | @Override 37 | public void onProxyToClientResponse(@NotNull ProxyResponse response) {} 38 | 39 | @Override 40 | public Boolean onResolutionRequest(@NotNull DNSRequest request) { 41 | return null; 42 | } 43 | 44 | @Override 45 | public Integer onGetChunkSize(@NotNull FullAddress address) { 46 | return null; 47 | } 48 | 49 | @Override 50 | public Boolean isFullChunking(@NotNull FullAddress address) { 51 | return null; 52 | } 53 | 54 | @Override 55 | public Boolean isMITMAllowed(@NotNull FullAddress address) { 56 | return null; 57 | } 58 | 59 | @Override 60 | public Object onGetSNI(@NotNull String hostname) { 61 | return Void.TYPE; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/proxy/ProxyAddress.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.proxy; 19 | 20 | import io.github.krlvm.powertunnel.sdk.types.FullAddress; 21 | import org.jetbrains.annotations.NotNull; 22 | 23 | public class ProxyAddress extends FullAddress { 24 | 25 | public ProxyAddress(@NotNull String host, int port) { 26 | super(host, port); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/proxy/ProxyCredentials.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.proxy; 19 | 20 | import io.github.krlvm.powertunnel.sdk.utiities.Base64Compat; 21 | import org.jetbrains.annotations.NotNull; 22 | 23 | import java.nio.charset.StandardCharsets; 24 | 25 | public class ProxyCredentials { 26 | 27 | private final String username; 28 | private final String password; 29 | 30 | public ProxyCredentials(@NotNull String username, @NotNull String password) { 31 | this.username = username; 32 | this.password = password; 33 | } 34 | 35 | public String getUsername() { 36 | return username; 37 | } 38 | 39 | public String getPassword() { 40 | return password; 41 | } 42 | 43 | public String toAuthorizationCode() { 44 | final String credential = this.username + ":" + this.password; 45 | final byte[] data = credential.getBytes(StandardCharsets.UTF_8); 46 | return Base64Compat.encodeToString(data).trim(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/proxy/ProxyListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.proxy; 19 | 20 | import io.github.krlvm.powertunnel.sdk.http.ProxyRequest; 21 | import io.github.krlvm.powertunnel.sdk.http.ProxyResponse; 22 | import io.github.krlvm.powertunnel.sdk.types.FullAddress; 23 | import org.jetbrains.annotations.NotNull; 24 | 25 | public interface ProxyListener { 26 | 27 | void onClientToProxyRequest(@NotNull ProxyRequest request); 28 | void onProxyToServerRequest(@NotNull ProxyRequest request); 29 | 30 | void onServerToProxyResponse(@NotNull ProxyResponse response); 31 | void onProxyToClientResponse(@NotNull ProxyResponse response); 32 | 33 | Boolean onResolutionRequest(@NotNull DNSRequest request); 34 | 35 | Integer onGetChunkSize(@NotNull FullAddress address); 36 | Boolean isFullChunking(@NotNull FullAddress address); 37 | 38 | Boolean isMITMAllowed(@NotNull FullAddress address); 39 | Object onGetSNI(@NotNull String hostname); 40 | 41 | int PRIORITY_HIGH = -5; 42 | int PRIORITY_NORMAL = 0; 43 | int PRIORITY_LOW = 5; 44 | } 45 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/proxy/ProxyStatus.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.proxy; 19 | 20 | public enum ProxyStatus { 21 | NOT_RUNNING, 22 | STARTING, 23 | RUNNING, 24 | STOPPING 25 | } -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/proxy/UpstreamProxyServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.proxy; 19 | 20 | import io.github.krlvm.powertunnel.sdk.types.UpstreamProxyType; 21 | import org.jetbrains.annotations.NotNull; 22 | import org.jetbrains.annotations.Nullable; 23 | 24 | import java.net.InetSocketAddress; 25 | import java.net.UnknownHostException; 26 | 27 | public class UpstreamProxyServer { 28 | 29 | private ProxyAddress address; 30 | private ProxyCredentials credentials; 31 | private UpstreamProxyType type; 32 | 33 | private InetSocketAddress inetSocketAddress; 34 | 35 | public UpstreamProxyServer(@NotNull ProxyAddress address) { 36 | this(address, null); 37 | } 38 | 39 | public UpstreamProxyServer(@NotNull ProxyAddress address, @Nullable ProxyCredentials credentials) { 40 | this(address, credentials, null); 41 | } 42 | 43 | public UpstreamProxyServer(@NotNull ProxyAddress address, @Nullable ProxyCredentials credentials, @Nullable UpstreamProxyType type) { 44 | this.address = address; 45 | this.credentials = credentials; 46 | this.type = type != null ? type : UpstreamProxyType.HTTP; 47 | } 48 | 49 | public @NotNull ProxyAddress getAddress() { 50 | return address; 51 | } 52 | 53 | public void setAddress(@NotNull ProxyAddress address) { 54 | this.address = address; 55 | } 56 | 57 | public void setAddress(@NotNull InetSocketAddress inetSocketAddress) { 58 | this.inetSocketAddress = inetSocketAddress; 59 | } 60 | 61 | public @Nullable ProxyCredentials getCredentials() { 62 | return credentials; 63 | } 64 | 65 | public void setCredentials(@Nullable ProxyCredentials credentials) { 66 | this.credentials = credentials; 67 | } 68 | 69 | @NotNull 70 | public UpstreamProxyType getType() { 71 | return type; 72 | } 73 | 74 | public void setType(@NotNull UpstreamProxyType type) { 75 | this.type = type; 76 | } 77 | 78 | public InetSocketAddress resolve() throws UnknownHostException { 79 | return this.isResolved() ? this.inetSocketAddress : this.address.resolve(); 80 | } 81 | 82 | public boolean isResolved() { 83 | return this.inetSocketAddress != null; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/types/FullAddress.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.types; 19 | 20 | import org.jetbrains.annotations.NotNull; 21 | import org.jetbrains.annotations.Nullable; 22 | 23 | import java.net.InetAddress; 24 | import java.net.InetSocketAddress; 25 | import java.net.UnknownHostException; 26 | 27 | public class FullAddress implements Cloneable { 28 | 29 | private final String host; 30 | private final int port; 31 | 32 | public FullAddress(@NotNull String host, int port) { 33 | this.host = host; 34 | this.port = port; 35 | } 36 | 37 | public String getHost() { 38 | return host; 39 | } 40 | 41 | public int getPort() { 42 | return port; 43 | } 44 | 45 | public InetSocketAddress resolve() throws UnknownHostException { 46 | return new InetSocketAddress(InetAddress.getByName(this.host), this.port); 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return host + ":" + port; 52 | } 53 | 54 | @Nullable 55 | public static FullAddress fromString(String input, int defaultPort) { 56 | if(!input.contains(":")) return new FullAddress(input, defaultPort); 57 | 58 | final String[] arr = input.split(":"); 59 | try { 60 | return new FullAddress(arr[0], Integer.parseInt(arr[1])); 61 | } catch (NumberFormatException ex) { 62 | return null; 63 | } 64 | } 65 | 66 | @Nullable 67 | public static FullAddress fromString(String input) { 68 | return fromString(input, -1); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/types/PowerTunnelPlatform.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.types; 19 | 20 | public enum PowerTunnelPlatform { 21 | DESKTOP, ANDROID 22 | } 23 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/types/UpstreamProxyType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.types; 19 | 20 | public enum UpstreamProxyType { 21 | HTTP, 22 | SOCKS4, 23 | SOCKS5 24 | } 25 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/types/VersionInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.types; 19 | 20 | public class VersionInfo { 21 | 22 | private final String versionName; 23 | private final int versionCode; 24 | 25 | public VersionInfo(String versionName, int versionCode) { 26 | this.versionName = versionName; 27 | this.versionCode = versionCode; 28 | } 29 | 30 | public String getVersionName() { 31 | return versionName; 32 | } 33 | 34 | public int getVersionCode() { 35 | return versionCode; 36 | } 37 | } -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/utiities/Base64Compat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.utiities; 19 | 20 | import java.util.Base64; 21 | 22 | public final class Base64Compat { 23 | 24 | public static String encodeToString(byte[] data) { 25 | return provider.encodeToString(data); 26 | } 27 | public static String encodeURLToString(byte[] data) { 28 | return provider.encodeURLToString(data); 29 | } 30 | 31 | private static Base64Provider provider; 32 | private interface Base64Provider { 33 | String encodeToString(byte[] data); 34 | String encodeURLToString(byte[] data); 35 | } 36 | private static final class Java8Base64Provider implements Base64Provider { 37 | @Override 38 | public String encodeToString(byte[] data) { 39 | return Base64.getEncoder().encodeToString(data); 40 | } 41 | @Override 42 | public String encodeURLToString(byte[] data) { 43 | return Base64.getUrlEncoder().withoutPadding().encodeToString(data); 44 | } 45 | } 46 | private static final class AndroidBase64Provider implements Base64Provider { 47 | @Override 48 | public String encodeToString(byte[] data) { 49 | return android.util.Base64.encodeToString(data, 0); 50 | } 51 | @Override 52 | public String encodeURLToString(byte[] data) { 53 | return android.util.Base64.encodeToString(data, 54 | android.util.Base64.URL_SAFE | 55 | android.util.Base64.NO_PADDING | 56 | android.util.Base64.NO_WRAP 57 | ); 58 | } 59 | } 60 | private static final class DummyBase64Provider implements Base64Provider { 61 | @Override 62 | public String encodeToString(byte[] data) { 63 | throw new RuntimeException("Not supported on your platform"); 64 | } 65 | @Override 66 | public String encodeURLToString(byte[] data) { 67 | throw new RuntimeException("Not supported on your platform"); 68 | } 69 | } 70 | static { 71 | try { 72 | Class.forName("java.util.Base64"); 73 | provider = new Java8Base64Provider(); 74 | } catch (ClassNotFoundException ex) { 75 | try { 76 | Class.forName("android.util.Base64"); 77 | provider = new AndroidBase64Provider(); 78 | } catch (ReflectiveOperationException aex) { 79 | System.err.println("Base64 is not supported on your platform\nSome functionality can be unavailable"); 80 | provider = new DummyBase64Provider(); 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /sdk/src/main/java/io/github/krlvm/powertunnel/sdk/utiities/TextReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | package io.github.krlvm.powertunnel.sdk.utiities; 19 | 20 | import java.io.*; 21 | 22 | public class TextReader { 23 | 24 | public static String read(File file) throws IOException { 25 | return read(new FileReader(file)); 26 | } 27 | 28 | public static String read(InputStream in) throws IOException { 29 | return read(new InputStreamReader(in)); 30 | } 31 | 32 | public static String read(Reader r) throws IOException { 33 | final StringBuilder builder = new StringBuilder(); 34 | try(BufferedReader reader = new BufferedReader(r)) { 35 | String line; 36 | while ((line = reader.readLine()) != null) { 37 | builder.append(line).append('\n'); 38 | } 39 | } 40 | if(builder.length() > 2) { 41 | return builder.substring(0, builder.lastIndexOf("\n")); 42 | } else { 43 | return builder.toString(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerTunnel. 3 | * 4 | * PowerTunnel is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * PowerTunnel is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with PowerTunnel. If not, see . 16 | */ 17 | 18 | rootProject.name = 'PowerTunnel' 19 | 20 | include 'sdk' 21 | include 'littleproxy', 'core' 22 | include 'desktop' 23 | include 'sample-plugin' 24 | -------------------------------------------------------------------------------- /version.txt: -------------------------------------------------------------------------------- 1 | 31;1.14 --------------------------------------------------------------------------------