mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-23 02:00:20 +07:00
Merge branch 'dev' into feature/prebuilt-binaries
This commit is contained in:
+1
-1
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
|
|||||||
|
|
||||||
set(PROJECT AmneziaVPN)
|
set(PROJECT AmneziaVPN)
|
||||||
|
|
||||||
project(${PROJECT} VERSION 3.0.7.4
|
project(${PROJECT} VERSION 3.0.7.5
|
||||||
DESCRIPTION "AmneziaVPN"
|
DESCRIPTION "AmneziaVPN"
|
||||||
HOMEPAGE_URL "https://amnezia.org/"
|
HOMEPAGE_URL "https://amnezia.org/"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,14 +4,22 @@
|
|||||||
[](https://github.com/amnezia-vpn/amnezia-client/actions/workflows/deploy.yml?query=branch:dev)
|
[](https://github.com/amnezia-vpn/amnezia-client/actions/workflows/deploy.yml?query=branch:dev)
|
||||||
[](https://gitpod.io/#https://github.com/amnezia-vpn/amnezia-client)
|
[](https://gitpod.io/#https://github.com/amnezia-vpn/amnezia-client)
|
||||||
|
|
||||||
Amnezia is a VPN client with the key feature of deploying your own VPN server on you virtual server.
|
Amnezia is an open-source VPN client, with a key feature that enables you to deploy your own VPN server on your server.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
- Very easy to use - enter your ip address, ssh login and password, and Amnezia client will automatically install VPN docker containers to your server and connect to VPN.
|
- Very easy to use - enter your ip address, ssh login and password, and Amnezia will automatically install VPN docker containers to your server and connect to VPN.
|
||||||
- OpenVPN, ShadowSocks, WireGuard, IKEv2 protocols support.
|
- OpenVPN, ShadowSocks, WireGuard, IKEv2 protocols support.
|
||||||
|
- Masking VPN with OpenVPN over Cloak plugin
|
||||||
- Split tunneling support - add any sites to client to enable VPN only for them (only for desktops)
|
- Split tunneling support - add any sites to client to enable VPN only for them (only for desktops)
|
||||||
- Windows, MacOS, Linux, Android, iOS releases.
|
- Windows, MacOS, Linux, Android, iOS releases.
|
||||||
|
|
||||||
|
## Links
|
||||||
|
[https://amnezia.org](https://amnezia.org) - project website
|
||||||
|
[https://www.reddit.com/r/AmneziaVPN](https://www.reddit.com/r/AmneziaVPN) - Reddit
|
||||||
|
[https://t.me/amnezia_vpn_en](https://t.me/amnezia_vpn_en) - Telegram support channel (English)
|
||||||
|
[https://t.me/amnezia_vpn](https://t.me/amnezia_vpn) - Telegram support channel (Russian)
|
||||||
|
[https://signal.group/...](https://signal.group/#CjQKIB2gUf8QH_IXnOJMGQWMDjYz9cNfmRQipGWLFiIgc4MwEhAKBONrSiWHvoUFbbD0xwdh) - Signal channel
|
||||||
|
|
||||||
## Tech
|
## Tech
|
||||||
|
|
||||||
AmneziaVPN uses a number of open source projects to work:
|
AmneziaVPN uses a number of open source projects to work:
|
||||||
@@ -121,12 +129,6 @@ You may face compiling issues in QT Creator after you've worked in Android Studi
|
|||||||
## License
|
## License
|
||||||
GPL v.3
|
GPL v.3
|
||||||
|
|
||||||
## Contacts
|
|
||||||
[https://t.me/amnezia_vpn_en](https://t.me/amnezia_vpn_en) - Telegram support channel (English)
|
|
||||||
[https://t.me/amnezia_vpn](https://t.me/amnezia_vpn) - Telegram support channel (Russian)
|
|
||||||
[https://signal.group/...](https://signal.group/#CjQKIB2gUf8QH_IXnOJMGQWMDjYz9cNfmRQipGWLFiIgc4MwEhAKBONrSiWHvoUFbbD0xwdh) - Signal channel
|
|
||||||
[https://amnezia.org](https://amnezia.org) - project website
|
|
||||||
|
|
||||||
## Donate
|
## Donate
|
||||||
Bitcoin: bc1qn9rhsffuxwnhcuuu4qzrwp4upkrq94xnh8r26u
|
Bitcoin: bc1qn9rhsffuxwnhcuuu4qzrwp4upkrq94xnh8r26u
|
||||||
XMR: 48spms39jt1L2L5vyw2RQW6CXD6odUd4jFu19GZcDyKKQV9U88wsJVjSbL4CfRys37jVMdoaWVPSvezCQPhHXUW5UKLqUp3
|
XMR: 48spms39jt1L2L5vyw2RQW6CXD6odUd4jFu19GZcDyKKQV9U88wsJVjSbL4CfRys37jVMdoaWVPSvezCQPhHXUW5UKLqUp3
|
||||||
|
|||||||
@@ -494,7 +494,6 @@ if(ANDROID)
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/qt/AmneziaApp.kt
|
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/qt/AmneziaApp.kt
|
||||||
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/qt/PackageManagerHelper.java
|
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/qt/PackageManagerHelper.java
|
||||||
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/qt/VPNActivity.kt
|
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/qt/VPNActivity.kt
|
||||||
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/qt/VPNApplication.java
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/qt/VPNClientBinder.kt
|
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/qt/VPNClientBinder.kt
|
||||||
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/qt/VPNPermissionHelper.kt
|
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/qt/VPNPermissionHelper.kt
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#include "amnezia_application.h"
|
#include "amnezia_application.h"
|
||||||
|
|
||||||
|
#include <QClipboard>
|
||||||
#include <QFontDatabase>
|
#include <QFontDatabase>
|
||||||
|
#include <QMimeData>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
#include <QTextDocument>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QTranslator>
|
#include <QTranslator>
|
||||||
|
|
||||||
@@ -51,7 +54,7 @@
|
|||||||
setQuitOnLastWindowClosed(false);
|
setQuitOnLastWindowClosed(false);
|
||||||
|
|
||||||
// Fix config file permissions
|
// Fix config file permissions
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX && !defined(Q_OS_ANDROID)
|
||||||
{
|
{
|
||||||
QSettings s(ORGANIZATION_NAME, APPLICATION_NAME);
|
QSettings s(ORGANIZATION_NAME, APPLICATION_NAME);
|
||||||
s.setValue("permFixed", true);
|
s.setValue("permFixed", true);
|
||||||
@@ -64,7 +67,6 @@
|
|||||||
QString configLoc2 = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).first() + "/"
|
QString configLoc2 = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).first() + "/"
|
||||||
+ ORGANIZATION_NAME + "/" + APPLICATION_NAME + "/" + APPLICATION_NAME + ".conf";
|
+ ORGANIZATION_NAME + "/" + APPLICATION_NAME + "/" + APPLICATION_NAME + ".conf";
|
||||||
QFile::setPermissions(configLoc2, QFileDevice::ReadOwner | QFileDevice::WriteOwner);
|
QFile::setPermissions(configLoc2, QFileDevice::ReadOwner | QFileDevice::WriteOwner);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_settings = std::shared_ptr<Settings>(new Settings);
|
m_settings = std::shared_ptr<Settings>(new Settings);
|
||||||
@@ -135,6 +137,19 @@ void AmneziaApplication::init()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Android TextField clipboard workaround
|
||||||
|
// https://bugreports.qt.io/browse/QTBUG-113461
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
QObject::connect(qApp, &QApplication::applicationStateChanged, [](Qt::ApplicationState state) {
|
||||||
|
if (state == Qt::ApplicationActive) {
|
||||||
|
if (qApp->clipboard()->mimeData()->formats().contains("text/html")) {
|
||||||
|
QTextDocument doc;
|
||||||
|
doc.setHtml(qApp->clipboard()->mimeData()->html());
|
||||||
|
qApp->clipboard()->setText(doc.toPlainText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmneziaApplication::registerTypes()
|
void AmneziaApplication::registerTypes()
|
||||||
|
|||||||
@@ -137,9 +137,9 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
resConfig "en"
|
resConfig "en"
|
||||||
minSdkVersion = 24
|
minSdkVersion = 24
|
||||||
targetSdkVersion = 31
|
targetSdkVersion = 34
|
||||||
versionCode 10 // Change to a higher number
|
versionCode 22 // Change to a higher number
|
||||||
versionName "2.0.10" // Change to a higher number
|
versionName "3.0.7" // Change to a higher number
|
||||||
|
|
||||||
javaCompileOptions.annotationProcessorOptions.arguments = [
|
javaCompileOptions.annotationProcessorOptions.arguments = [
|
||||||
"room.schemaLocation": "${qtAndroidDir}/schemas".toString()
|
"room.schemaLocation": "${qtAndroidDir}/schemas".toString()
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import org.qtproject.qt.android.bindings.QtActivity
|
|||||||
import org.qtproject.qt.android.bindings.QtApplication
|
import org.qtproject.qt.android.bindings.QtApplication
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
|
||||||
class AmneziaApp: Application() {
|
class AmneziaApp: org.qtproject.qt.android.bindings.QtApplication() {
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
@@ -19,4 +19,4 @@ class AmneziaApp: Application() {
|
|||||||
super.onConfigurationChanged(newConfig)
|
super.onConfigurationChanged(newConfig)
|
||||||
Core.updateNotificationChannels()
|
Core.updateNotificationChannels()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
package org.amnezia.vpn.qt;
|
package org.amnezia.vpn.qt;
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.content.ClipData
|
|
||||||
import android.content.ClipboardManager
|
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.ContentResolver
|
import android.content.ContentResolver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
@@ -73,10 +71,6 @@ class VPNActivity : org.qtproject.qt.android.bindings.QtActivity() {
|
|||||||
@JvmStatic fun saveFileAs(fileContent: String, suggestedName: String) {
|
@JvmStatic fun saveFileAs(fileContent: String, suggestedName: String) {
|
||||||
VPNActivity.getInstance().saveFile(fileContent, suggestedName)
|
VPNActivity.getInstance().saveFile(fileContent, suggestedName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun putTextToClipboard(text: String) {
|
|
||||||
VPNActivity.getInstance().putToClipboard(text)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@@ -109,18 +103,6 @@ class VPNActivity : org.qtproject.qt.android.bindings.QtActivity() {
|
|||||||
startActivityForResult(intent, CREATE_FILE_ACTION_CODE)
|
startActivityForResult(intent, CREATE_FILE_ACTION_CODE)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSystemService(name: String): Any? {
|
|
||||||
return if (Build.VERSION.SDK_INT >= 29 && name == "clipboard") {
|
|
||||||
// QT will always attempt to read the clipboard if content is there.
|
|
||||||
// since we have no use of the clipboard in android 10+
|
|
||||||
// we _can_ return null
|
|
||||||
// And we definitely should since android 12 displays clipboard access.
|
|
||||||
null
|
|
||||||
} else {
|
|
||||||
super.getSystemService(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
external fun handleBackButton(): Boolean
|
external fun handleBackButton(): Boolean
|
||||||
|
|
||||||
external fun onServiceMessage(actionCode: Int, body: String?)
|
external fun onServiceMessage(actionCode: Int, body: String?)
|
||||||
@@ -317,15 +299,4 @@ class VPNActivity : org.qtproject.qt.android.bindings.QtActivity() {
|
|||||||
|
|
||||||
tmpFileContentToSave = ""
|
tmpFileContentToSave = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun putToClipboard(text: String) {
|
|
||||||
this.runOnUiThread {
|
|
||||||
val clipboard = applicationContext.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager?
|
|
||||||
|
|
||||||
if (clipboard != null) {
|
|
||||||
val clip: ClipData = ClipData.newPlainText("", text)
|
|
||||||
clipboard.setPrimaryClip(clip)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
package org.amnezia.vpn.qt;
|
|
||||||
|
|
||||||
import android.content.res.Configuration;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import org.amnezia.vpn.shadowsocks.core.Core;
|
|
||||||
import org.amnezia.vpn.shadowsocks.core.VpnManager;
|
|
||||||
|
|
||||||
public class VPNApplication extends org.qtproject.qt.android.bindings.QtApplication {
|
|
||||||
private static VPNApplication instance;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
super.onCreate();
|
|
||||||
VPNApplication.instance = this;
|
|
||||||
// Core.INSTANCE.init(this, VPNActivity.class);
|
|
||||||
// VpnManager.Companion.getInstance().init(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
|
||||||
super.onConfigurationChanged(newConfig);
|
|
||||||
// Core.INSTANCE.updateNotificationChannels();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 151 KiB |
@@ -0,0 +1,2 @@
|
|||||||
|
File AmneziaVPN_Full_logo.svg licensed by CC-BY-SA 4.0
|
||||||
|
Full license text - https://creativecommons.org/licenses/by-sa/4.0/legalcode.txt
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
#include <QLoggingCategory>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
#include "amnezia_application.h"
|
#include "amnezia_application.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
@@ -20,7 +18,6 @@ int main(int argc, char *argv[])
|
|||||||
Migrations migrationsManager;
|
Migrations migrationsManager;
|
||||||
migrationsManager.doMigrations();
|
migrationsManager.doMigrations();
|
||||||
|
|
||||||
QLoggingCategory::setFilterRules(QStringLiteral("qtc.ssh=false"));
|
|
||||||
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
|
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
|||||||
@@ -267,11 +267,6 @@ void AndroidController::startQrReaderActivity()
|
|||||||
AndroidVPNActivity::instance()->startQrCodeReader();
|
AndroidVPNActivity::instance()->startQrCodeReader();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidController::copyTextToClipboard(QString text)
|
|
||||||
{
|
|
||||||
AndroidVPNActivity::instance()->copyTextToClipboard(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidController::scheduleStatusCheckSlot()
|
void AndroidController::scheduleStatusCheckSlot()
|
||||||
{
|
{
|
||||||
QTimer::singleShot(1000, [this]() {
|
QTimer::singleShot(1000, [this]() {
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ public:
|
|||||||
void setVpnConfig(const QJsonObject &newVpnConfig);
|
void setVpnConfig(const QJsonObject &newVpnConfig);
|
||||||
|
|
||||||
void startQrReaderActivity();
|
void startQrReaderActivity();
|
||||||
void copyTextToClipboard(QString text);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void connectionStateChanged(VpnProtocol::VpnConnectionState state);
|
void connectionStateChanged(VpnProtocol::VpnConnectionState state);
|
||||||
|
|||||||
@@ -65,14 +65,6 @@ void AndroidVPNActivity::saveFileAs(QString fileContent, QString suggestedFilena
|
|||||||
QJniObject::fromString(suggestedFilename).object<jstring>());
|
QJniObject::fromString(suggestedFilename).object<jstring>());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidVPNActivity::copyTextToClipboard(QString text)
|
|
||||||
{
|
|
||||||
QJniObject::callStaticMethod<void>(
|
|
||||||
CLASSNAME,
|
|
||||||
"putTextToClipboard", "(Ljava/lang/String;)V",
|
|
||||||
QJniObject::fromString(text).object<jstring>());
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
AndroidVPNActivity* AndroidVPNActivity::instance() {
|
AndroidVPNActivity* AndroidVPNActivity::instance() {
|
||||||
if (s_instance == nullptr) {
|
if (s_instance == nullptr) {
|
||||||
|
|||||||
@@ -76,7 +76,6 @@ public:
|
|||||||
static void connectService();
|
static void connectService();
|
||||||
static void startQrCodeReader();
|
static void startQrCodeReader();
|
||||||
static void saveFileAs(QString fileContent, QString suggestedFilename);
|
static void saveFileAs(QString fileContent, QString suggestedFilename);
|
||||||
static void copyTextToClipboard(QString text);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void serviceConnected();
|
void serviceConnected();
|
||||||
|
|||||||
@@ -133,13 +133,13 @@ void UiLogic::initializeUiLogic()
|
|||||||
connect(AndroidController::instance(), &AndroidController::initialized, [this](bool status, bool connected, const QDateTime& connectionDate) {
|
connect(AndroidController::instance(), &AndroidController::initialized, [this](bool status, bool connected, const QDateTime& connectionDate) {
|
||||||
if (connected) {
|
if (connected) {
|
||||||
pageLogic<VpnLogic>()->onConnectionStateChanged(VpnProtocol::Connected);
|
pageLogic<VpnLogic>()->onConnectionStateChanged(VpnProtocol::Connected);
|
||||||
m_vpnConnection->restoreConnection();
|
if (m_vpnConnection) m_vpnConnection->restoreConnection();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!AndroidController::instance()->initialize(pageLogic<StartPageLogic>())) {
|
if (!AndroidController::instance()->initialize(pageLogic<StartPageLogic>())) {
|
||||||
qCritical() << QString("Init failed") ;
|
qCritical() << QString("Init failed");
|
||||||
emit VpnProtocol::Error;
|
if (m_vpnConnection) m_vpnConnection->connectionStateChanged(VpnProtocol::Error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -476,11 +476,7 @@ void UiLogic::saveBinaryFile(const QString &desc, QString ext, const QString &da
|
|||||||
|
|
||||||
void UiLogic::copyToClipboard(const QString &text)
|
void UiLogic::copyToClipboard(const QString &text)
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_ANDROID
|
|
||||||
AndroidController::instance()->copyTextToClipboard(text);
|
|
||||||
#else
|
|
||||||
qApp->clipboard()->setText(text);
|
qApp->clipboard()->setText(text);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UiLogic::shareTempFile(const QString &suggestedName, QString ext, const QString& data) {
|
void UiLogic::shareTempFile(const QString &suggestedName, QString ext, const QString& data) {
|
||||||
|
|||||||
Reference in New Issue
Block a user