Client app template and ui

This commit is contained in:
pokamest 2020-11-23 16:20:25 +03:00
parent 3006c67472
commit f68415f08e
53 changed files with 4280 additions and 0 deletions

102
client/amnizia-client.pro Normal file
View file

@ -0,0 +1,102 @@
QT += widgets core gui network xml
TARGET = amnezia-client
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
win32 {
#win32-g++ {
# QMAKE_CXXFLAGS += -Werror
#}
#win32-msvc*{
# QMAKE_CXXFLAGS += /WX
#}
FORMS += ui/mainwindow.ui
RESOURCES += \
res.qrc
OTHER_FILES += platform_win/vpnclient.rc
RC_FILE = platform_win/vpnclient.rc
HEADERS += publib/winhelp.h
SOURCES += publib/winhelp.cpp
CONFIG -= embed_manifest_exe
DEFINES += _CRT_SECURE_NO_WARNINGS VPNCLIENT_TAPSIGNED
#QMAKE_LFLAGS += /MANIFESTUAC:\"level=\'requireAdministrator\' uiAccess=\'false\'\"
VERSION = 1.1.1.1
QMAKE_TARGET_COMPANY = "AmneziaVPN"
QMAKE_TARGET_PRODUCT = "AmneziaVPN"
CONFIG -= embed_manifest_exe
LIBS += -luser32 \
-lrasapi32 \
-lshlwapi \
-liphlpapi \
-lws2_32 \
-liphlpapi \
-lgdi32
MT_PATH = \"C:/Program Files (x86)/Microsoft SDKs/Windows/v7.1A/bin/x64/mt.exe\"
WIN_PWD = $$replace(PWD, /, \\)
OUT_PWD_WIN = $$replace(OUT_PWD, /, \\)
!win32-g++: QMAKE_POST_LINK = "$$MT_PATH -manifest $$quote($$WIN_PWD\\platform_win\\$$basename(TARGET).exe.manifest) -outputresource:$$quote($$OUT_PWD_WIN\\$(DESTDIR_TARGET);1)"
else: QMAKE_POST_LINK = "$$MT_PATH -manifest $$PWD/platform_win/$$basename(TARGET).exe.manifest -outputresource:$$OUT_PWD/$(DESTDIR_TARGET)"
}
macx {
OBJECTIVE_HEADERS +=
OBJECTIVE_SOURCES += publib/macos_functions.mm
HEADERS += \
SOURCES += \
QMAKE_OBJECTIVE_CFLAGS += -F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks
FORMS += ui/mainwindow_mac.ui
LIBS += -framework CoreServices -framework Foundation -framework AppKit
RESOURCES += \
res_mac.qrc
ICON = images/main.icns
}
SOURCES += main.cpp\
publib/debug.cpp \
publib/runguard.cpp \
publib/winhelp.cpp \
ui/Controls/SlidingStackedWidget.cpp \
ui/mainwindow.cpp \
ui/customshadoweffect.cpp
HEADERS += ui/mainwindow.h \
publib/debug.h \
publib/runguard.h \
publib/winhelp.h \
ui/customshadoweffect.h \
ui/Controls/SlidingStackedWidget.h
FORMS += ui/mainwindow.ui
TRANSLATIONS = translations/amneziavpn.en.ts \
translations/amneziavpn.ru.ts
win32: LIBS += -L$$PWD/../../../../../../../OpenSSL-Win32/lib/ -llibcrypto

BIN
client/fonts/Lato-Black.ttf Normal file

Binary file not shown.

Binary file not shown.

BIN
client/fonts/Lato-Bold.ttf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
client/fonts/Lato-Light.ttf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
client/fonts/Lato-Thin.ttf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
client/images/Line.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

BIN
client/images/close.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

BIN
client/images/download.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

BIN
client/images/min.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

BIN
client/images/settings.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 871 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
client/images/underline.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 B

BIN
client/images/upload.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

109
client/main.cpp Normal file
View file

@ -0,0 +1,109 @@
#include <QApplication>
#include <QFontDatabase>
#include <QCommandLineParser>
#include <QMessageBox>
#include <QFile>
#include <QTranslator>
#include <QLibraryInfo>
#include "publib/runguard.h"
#include "publib/debug.h"
#include "ui/mainwindow.h"
#ifdef Q_OS_WIN
#include <Windows.h>
#endif
#define ApplicationName "AmneziaVPN"
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(res);
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
RunGuard::instance(ApplicationName).activate();
QApplication app(argc, argv);
if (! RunGuard::instance().tryToRun()) {
qDebug() << "Tried to run second instance. Exiting...";
QMessageBox::information(NULL, QObject::tr("Notify"), QObject::tr("AmneziaVPN is already running."));
return 0;
}
QFontDatabase::addApplicationFont(":/fonts/Lato-Black.ttf");
QFontDatabase::addApplicationFont(":/fonts/Lato-BlackItalic.ttf");
QFontDatabase::addApplicationFont(":/fonts/Lato-Bold.ttf");
QFontDatabase::addApplicationFont(":/fonts/Lato-BoldItalic.ttf");
QFontDatabase::addApplicationFont(":/fonts/Lato-Italic.ttf");
QFontDatabase::addApplicationFont(":/fonts/Lato-Light.ttf");
QFontDatabase::addApplicationFont(":/fonts/Lato-LightItalic.ttf");
QFontDatabase::addApplicationFont(":/fonts/Lato-Regular.ttf");
QFontDatabase::addApplicationFont(":/fonts/Lato-Thin.ttf");
QFontDatabase::addApplicationFont(":/fonts/Lato-ThinItalic.ttf");
{
QTranslator *translator = new QTranslator;
QLocale ru(QLocale("ru_RU"));
QLocale::setDefault(ru);
if (translator->load(QLocale(), "amnezia-client", ".", QLatin1String(":/translations"))) {
bool ok = qApp->installTranslator(translator);
qDebug().noquote() << "Main: Installing translator for locale" << ru.name() << ok;
}
else {
qDebug().noquote() << "Main: Failed to install translator for locale" << ru.name();
}
}
app.setOrganizationName("AmneziaVPN");
app.setOrganizationDomain("AmneziaVPN.ORG");
app.setApplicationName(ApplicationName);
app.setApplicationDisplayName(ApplicationName);
app.setApplicationVersion("1.0.0.0");
//app.setQuitOnLastWindowClosed(false);
QCommandLineParser parser;
parser.setApplicationDescription("AmneziaVPN");
parser.addHelpOption();
parser.addVersionOption();
QCommandLineOption debugToConsoleOption("d", QCoreApplication::translate("main", "Output to console instead log file"));
parser.addOption(debugToConsoleOption);
#ifdef Q_OS_MAC
QCommandLineOption forceUseBrightIconsOption("b", QCoreApplication::translate("main", "Force use bright icons"));
parser.addOption(forceUseBrightIconsOption);
#endif
// Process the actual command line arguments given by the user
parser.process(app);
bool debugToConsole = parser.isSet(debugToConsoleOption);
bool forceUseBrightIcons = false;
#ifdef Q_OS_MAC
forceUseBrightIcons = parser.isSet(forceUseBrightIconsOption);
#endif
qDebug() << "Set output to console: " << debugToConsole;
if (!debugToConsole) {
if (!Debug::init()) {
qCritical() << "Initialization of debug subsystem failed";
}
}
QFont f("Lato Regular", 10);
f.setStyleStrategy(QFont::PreferAntialias);
app.setFont(f);
MainWindow mainWindow(forceUseBrightIcons);
mainWindow.show();
return app.exec();
}

View file

@ -0,0 +1,48 @@
#include <windows.h>
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
IDI_ICON1 ICON "../images/main.ico"
#define VER_FILEVERSION 1,1,1,1
#define VER_FILEVERSION_STR "1.1.1.1\0"
#define VER_PRODUCTVERSION 1,1,1,1
#define VER_PRODUCTVERSION_STR "1.1.1.1\0"
#define VER_COMPANYNAME_STR "AmneziaVPN"
#define VER_FILEDESCRIPTION_STR "AmneziaVPN"
#define VER_INTERNALNAME_STR "AmneziaVPN"
#define VER_LEGALCOPYRIGHT_STR "AmneziaVPN."
#define VER_LEGALTRADEMARKS1_STR "All Rights Reserved"
#define VER_LEGALTRADEMARKS2_STR VER_LEGALTRADEMARKS1_STR
#define VER_ORIGINALFILENAME_STR "amneziavpn.exe"
#define VER_PRODUCTNAME_STR "AmneziaVPN"
#define VER_COMPANYDOMAIN_STR "http://amnezia.org/"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION
PRODUCTVERSION VER_PRODUCTVERSION
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", VER_COMPANYNAME_STR
VALUE "FileDescription", VER_FILEDESCRIPTION_STR
VALUE "FileVersion", VER_FILEVERSION_STR
VALUE "InternalName", VER_INTERNALNAME_STR
VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR
VALUE "LegalTrademarks1", VER_LEGALTRADEMARKS1_STR
VALUE "LegalTrademarks2", VER_LEGALTRADEMARKS2_STR
VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR
VALUE "ProductName", VER_PRODUCTNAME_STR
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END

130
client/publib/debug.cpp Normal file
View file

@ -0,0 +1,130 @@
#include "debug.h"
#include <QDir>
#include <QStandardPaths>
#include <QDebug>
#include <QCoreApplication>
#include <QDateTime>
#define LOGS_DIR "logs"
#define CLIENT_LOG_SUFFIX "amneziavpn.log"
#define MAX_LOG_FILES 5
#define FORMAT_STRING "yyyy-MM-dd--hh-mm-ss"
QFile Debug::m_clientLog;
QTextStream Debug::m_clientLogTextStream;
QString Debug::m_clientLogName;
void debugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
// Skip Qt warnings
if (msg.contains("known incorrect sRGB profile")) return;
if (msg.contains("libpng warning")) return;
if (msg.contains("Unknown property ffont")) return;
Debug::m_clientLogTextStream << qFormatLogMessage(type, context, msg) << endl << flush;
}
bool Debug::init()
{
QString path = qApp->applicationDirPath();
QDir appDir(path);
// init function is called before exec application, so data location folder may not exist
if (!appDir.exists())
{
qWarning() << "Debug: init: log directory doesn't exist or mkpath command error:" << path;
return false;
}
if (!appDir.exists(LOGS_DIR) && !appDir.mkdir(LOGS_DIR))
{
qWarning() << "Debug: init: log directory doesn't exist or mkdir command error:" << path << LOGS_DIR;
return false;
}
if (!appDir.cd(LOGS_DIR))
{
qWarning() << "Debug: init: cd command error:" << path << LOGS_DIR;
return false;
}
//delete older log files
auto clientLogsCount = 0;
QFileInfoList logDirList = appDir.entryInfoList(
QDir::Files | QDir::NoDotAndDotDot,
QDir::Time);
for (auto fileInfo : logDirList)
{
if ((fileInfo.completeSuffix() == CLIENT_LOG_SUFFIX &&
++clientLogsCount > MAX_LOG_FILES))
{
appDir.remove(fileInfo.filePath());
}
}
//prepare log file names
auto currentDateTime = QDateTime::currentDateTime().toString(FORMAT_STRING);
m_clientLogName = QString("%1.%2").arg(currentDateTime).arg(CLIENT_LOG_SUFFIX);
return init(appDir);
}
bool Debug::init(QDir& appDir)
{
Q_UNUSED(appDir)
qSetMessagePattern("[%{time}|%{type}] %{message}");
#ifndef QT_DEBUG
m_clientLog.setFileName(appDir.filePath(m_clientLogName));
if (!m_clientLog.open(QIODevice::WriteOnly | QIODevice::Append)) {
qWarning() << "Debug::init - failed to open m_clientLog file:" << m_clientLogName;
return false;
}
m_clientLog.setTextModeEnabled(true);
m_clientLogTextStream.setDevice(&m_clientLog);
qInstallMessageHandler(debugMessageHandler);
#else
#ifdef DEBUG_OUTPUT_TWO_DIRECTIONAL
m_clientLog.setFileName(appDir.filePath(m_clientLogName));
if (!m_clientLog.open(QIODevice::WriteOnly | QIODevice::Append))
return false;
m_clientLog.setTextModeEnabled(true);
m_clientLogTextStream.setDevice(&m_clientLog);
defaultMessageHandler = qInstallMessageHandler(debugMessageHandler);
#endif
#endif
#ifndef Q_OS_WIN
if (!fixOvpnLogPermissions())
qWarning() << "Debug: permissions for ovpn.log were not fixed";
#endif
return true;
}
QString Debug::getPathToClientLog()
{
QString path = qApp->applicationDirPath();
QDir appDir(path);
if (!appDir.exists(LOGS_DIR) || !appDir.cd(LOGS_DIR))
{
qWarning() << "Debug: log directory doesn't exist or cd command error:" << path;
return "";
}
return appDir.filePath(m_clientLogName);
}
QString Debug::getPathToLogsDir()
{
QString path = qApp->applicationDirPath();
QDir appDir(path);
if (!appDir.exists(LOGS_DIR) || !appDir.cd(LOGS_DIR))
{
qWarning() << "Debug: log directory doesn't exist or cd command error" << path;
return "";
}
return appDir.absolutePath();
}

27
client/publib/debug.h Normal file
View file

@ -0,0 +1,27 @@
#ifndef DEBUG_H
#define DEBUG_H
#include <QFile>
#include <QTextStream>
#include <QString>
#include <QDir>
class Debug
{
public:
static bool init();
static QString getPathToClientLog();
static QString getPathToLogsDir();
private:
static bool init(QDir& appDir);
private:
static QFile m_clientLog;
static QTextStream m_clientLogTextStream;
static QString m_clientLogName;
friend void debugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg);
};
#endif // DEBUG_H

View file

@ -0,0 +1,88 @@
#include "runguard.h"
#include <QCryptographicHash>
namespace
{
QString generateKeyHash( const QString& key, const QString& salt )
{
QByteArray data;
data.append( key.toUtf8() );
data.append( salt.toUtf8() );
data = QCryptographicHash::hash( data, QCryptographicHash::Sha1 ).toHex();
return data;
}
}
RunGuard::RunGuard(const QString& key)
: key( key )
, memLockKey( generateKeyHash( key, "_memLockKey" ) )
, sharedmemKey( generateKeyHash( key, "_sharedmemKey" ) )
, sharedMem( sharedmemKey )
, memLock( memLockKey, 1 )
{
qDebug() << "RunGuard::RunGuard key" << key;
}
RunGuard &RunGuard::instance(const QString& key)
{
static RunGuard s(key);
return s;
}
void RunGuard::activate()
{
memLock.acquire();
{
QSharedMemory fix(sharedmemKey); // Fix for *nix: http://habrahabr.ru/post/173281/
fix.attach();
}
memLock.release();
}
RunGuard::~RunGuard()
{
release();
}
bool RunGuard::isAnotherRunning() const
{
if ( sharedMem.isAttached() )
return false;
memLock.acquire();
const bool isRunning = sharedMem.attach();
if ( isRunning )
sharedMem.detach();
memLock.release();
return isRunning;
}
bool RunGuard::tryToRun()
{
if ( isAnotherRunning() ) // Extra check
return false;
memLock.acquire();
const bool result = sharedMem.create( sizeof( quint64 ) );
memLock.release();
if ( !result )
{
release();
return false;
}
return true;
}
void RunGuard::release()
{
memLock.acquire();
if ( sharedMem.isAttached() )
sharedMem.detach();
memLock.release();
}

37
client/publib/runguard.h Normal file
View file

@ -0,0 +1,37 @@
#ifndef RUNGUARD_H
#define RUNGUARD_H
#include <QObject>
#include <QSharedMemory>
#include <QSystemSemaphore>
#include <QDebug>
/**
* @brief The RunGuard class - The application single instance (via shared memory)
*/
class RunGuard
{
public:
static RunGuard &instance(const QString& key = QString());
~RunGuard();
void activate();
bool isAnotherRunning() const;
bool tryToRun();
void release();
private:
RunGuard(const QString& key);
Q_DISABLE_COPY( RunGuard )
const QString key;
const QString memLockKey;
const QString sharedmemKey;
mutable QSharedMemory sharedMem;
mutable QSystemSemaphore memLock;
};
#endif // RUNGUARD_H

261
client/publib/winhelp.cpp Normal file
View file

@ -0,0 +1,261 @@
#include "winhelp.h"
#include <stdio.h>
#include <Windows.h>
#include <Shlwapi.h>
#include <TlHelp32.h>
#include <Ras.h>
#include <iphlpapi.h>
#define REG_AUTORUN_PATH "Software\\Microsoft\\Windows\\CurrentVersion\\Run"
int winhelpGetRegistry(const char *name, const char *reg, char *value)
{
unsigned long nType = REG_SZ, nData = MAX_PATH;
if(ERROR_SUCCESS != SHGetValueA(HKEY_CURRENT_USER, reg,
name, &nType, value, &nData))
return -1;
return 1;
}
int winhelpSetRegistry(const char *name, const char *reg, const char *value)
{
if(ERROR_SUCCESS != SHSetValueA(HKEY_CURRENT_USER, reg,
name, REG_SZ, value, (DWORD)strlen(value)))
return -1;
return 1;
}
int winhelpLaunchStartupRegister(const char *name, int enable, const char *p)
{
char path[MAX_PATH] = {0};
if(p && strlen(p) == 0)
p = NULL;
if(p) {
if(enable)
strcpy(path, "\"");
else
strcpy(path, ";\"");
GetModuleFileNameA(NULL, path + strlen(path), MAX_PATH);
strcat(path, "\" ");
strcat(path, p);
} else {
if(enable)
strcpy(path, "");
else
strcpy(path, ";");
GetModuleFileNameA(NULL, path + strlen(path), MAX_PATH);
}
if(winhelpSetRegistry(name, REG_AUTORUN_PATH, path) < 0)
return -1;
return 1;
}
/* use the task scheduler, we do not need to care about UAC when start up */
int winhelpLaunchStartupTaskScheduler(const char *name, int enable, const char *p)
{
char cmd[MAX_PATH * 10] = {0};
char path[MAX_PATH] = {0};
UINT i = 0;
GetModuleFileNameA(NULL, path, MAX_PATH);
if (QString(path).contains("build-vpn-")) {
qDebug() << "winhelpLaunchStartupTaskScheduler : skipping auto launch for build dir";
return 0;
}
if(enable) {
if(p == NULL)
p = "";
sprintf(cmd, "schtasks /create /sc onlogon /tr \"\\\"%s\\\" %s\" "
"/tn \"%s\" /f /rl highest", path, p, name);
} else {
sprintf(cmd, "schtasks /delete /tn \"%s\" /f", name);
}
qDebug().noquote() << "winhelpLaunchStartupTaskScheduler cmd:" << cmd;
i = WinExec(cmd, SW_HIDE);
return 1;
}
int winhelpLaunchStartup(const char *name, int enable, const char *p)
{
OSVERSIONINFOA info = {0};
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
if(GetVersionExA(&info) < 0)
return -2;
if(info.dwMajorVersion >= 6)
return winhelpLaunchStartupTaskScheduler(name, enable, p);
else
return winhelpLaunchStartupRegister(name, enable, p);
}
int str2int(const char *s)
{
int r = 0;
while(*s && *(s + 1) && *(s + 2) && *(s + 3)) {
r += ((const int *)s)[0];
s += 4;
}
return r;
}
int winhelpOneProcess()
{
char path[MAX_PATH] = {0};
int i = 0, size = 0, cur = 0;
GetModuleFileNameA(NULL, path, MAX_PATH);
size = strlen(path);
for(i = size; i >= 0 && path[i] != '\\' ; i--);
cur = i + 1;
while(path[i] != '.' && path[i])i++;
path[i] = '\0';
sprintf(path, "ONE_%s", path + cur);
CreateEventA(NULL, FALSE, FALSE, path);
if(GetLastError())
return 0;
return 1;
}
int winhelpSystemBits()
{
typedef BOOL (WINAPI *LPFN_ISWOW64)(HANDLE, PBOOL);
int b64 = FALSE;
LPFN_ISWOW64 fnIsWow64 = (LPFN_ISWOW64)GetProcAddress(
GetModuleHandleA("kernel32"), "IsWow64Process");
if(NULL != fnIsWow64) {
if(!fnIsWow64(GetCurrentProcess(),&b64)) {
return -1;
}
}
return b64 ? 64 : 86;
}
bool winhelpIsSystem_x64()
{
typedef BOOL (WINAPI *LPFN_ISWOW64)(HANDLE, PBOOL);
int b64 = FALSE;
LPFN_ISWOW64 fnIsWow64 = (LPFN_ISWOW64)GetProcAddress(
GetModuleHandleA("kernel32"), "IsWow64Process");
if(NULL != fnIsWow64) {
if(!fnIsWow64(GetCurrentProcess(),&b64)) {
return false;
}
}
return b64 ? true : false;
}
typedef struct _PROCESS_QUERY
{
HANDLE h;
PROCESSENTRY32 d;
}PROCESS_QUERY;
int winhelpProcessQuery(void **p)
{
PROCESS_QUERY *q = (PROCESS_QUERY *)malloc(sizeof(PROCESS_QUERY));
if(q == NULL)
return -2;
q->h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(q->h == INVALID_HANDLE_VALUE) {
free(q);
return -1;
}
if(FALSE == Process32First(q->h, &q->d)) {
CloseHandle(q->h);
free(q);
return -3;
}
*p = (void *)q;
return 1;
}
int winhelpProcessNext(void *h, char *name)
{
PROCESS_QUERY *q = (PROCESS_QUERY *)h;
int pid = 0;
if(q == NULL)
return 0;
if(q->h == NULL) {
free(q);
return 0;
}
if(name)
wsprintfA(name, "%ls", q->d.szExeFile);
pid = (int)q->d.th32ProcessID;
if(FALSE == Process32Next(q->h, &q->d)) {
CloseHandle(q->h);
q->h = NULL;
}
return pid;
}
int winhelpRecvEvent(const char *event)
{
HANDLE hEvent = CreateEventA(NULL, FALSE, FALSE, event);
if(hEvent == NULL)
return 0;
WaitForSingleObject(hEvent, INFINITE);
CloseHandle(hEvent);
return 1;
}
int winhelpSendEvent(const char *event)
{
HANDLE hEvent = OpenEventA(EVENT_ALL_ACCESS, FALSE, event);
if(hEvent == NULL)
return 0;
SetEvent(hEvent);
CloseHandle(hEvent);
return 1;
}
int winhelpSystemVersion()
{
OSVERSIONINFOA ver = {0};
int version = 0;
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
GetVersionExA(&ver);
version = ver.dwMajorVersion * 0x100 + ver.dwMinorVersion;
return version;
}
int winhelperSetMTUSize(const char *subname, int size)
{
char cmd[MAX_PATH] = {0};
sprintf(cmd, "netsh interface ipv4 set subinterface \"%s\" mtu=%d store=persistent",
subname, size);
return (int)WinExec(cmd, SW_HIDE);
}
int winhelpRecvSendBytes(const char *dev, int *recv, int *send)
{
MIB_IFTABLE *it = NULL;
DWORD size = sizeof(MIB_IFTABLE), ret = 0, i = 0;
DWORD tr = 0, ts = 0;
if(it = (MIB_IFTABLE *)malloc(sizeof (MIB_IFTABLE)), it == NULL)
return -1;
if(GetIfTable(it, &size, FALSE) == ERROR_INSUFFICIENT_BUFFER) {
free(it);
if(it = (MIB_IFTABLE *)malloc(size), it == NULL)
return -2;
}
if(ret = GetIfTable(it, &size, FALSE), ret != NO_ERROR) {
free(it);
return -3;
}
for(i = 0; i < it->dwNumEntries; i++) {
MIB_IFROW *ir = &it->table[i];
if(strstr((const char *)ir->bDescr, dev) == 0)
continue;
tr += (int)ir->dwInOctets;
ts += (int)ir->dwOutOctets;
}
*recv = tr;
*send = ts;
free(it);
return 1;
}

26
client/publib/winhelp.h Normal file
View file

@ -0,0 +1,26 @@
#ifndef WINHELP_H
#define WINHELP_H
#include <QDebug>
#ifdef __cplusplus
extern "C" {
#endif
extern int winhelpLaunchStartup(const char *, int, const char *);
extern int winhelpOneProcess();
extern int winhelpSystemBits();
extern bool winhelpIsSystem_x64();
extern int winhelpProcessQuery(void **);
extern int winhelpProcessNext(void *, char *);
extern int winhelpRecvEvent(const char *);
extern int winhelpSendEvent(const char *);
extern int winhelpSystemVersion();
extern int winhelperSetMTUSize(const char *, int);
extern int winhelpRecvSendBytes(const char *, int *, int *);
#ifdef __cplusplus
}
#endif
#endif /* WINHELP_H */

39
client/res.qrc Normal file
View file

@ -0,0 +1,39 @@
<RCC>
<qresource prefix="/">
<file>images/close.png</file>
<file>images/listitembg.png</file>
<file>images/settings.png</file>
<file>images/underline.png</file>
<file>images/min.png</file>
<file>images/favorites_disabled.png</file>
<file>images/favorites_enabled.png</file>
<file>images/favorites_hover.png</file>
<file>images/controls/check_off.png</file>
<file>images/controls/check_on.png</file>
<file>images/controls/radio_off.png</file>
<file>images/controls/radio_on.png</file>
<file>images/connected_line.png</file>
<file>images/download.png</file>
<file>images/upload.png</file>
<file>images/controls/checkbox_hover.png</file>
<file>images/controls/checkbox_unchecked.png</file>
<file>images/tray/active.png</file>
<file>images/tray/default.png</file>
<file>images/tray/error.png</file>
<file>images/arrow_left.png</file>
<file>images/connect_button_connected.png</file>
<file>images/connect_button_disconnected.png</file>
<file>fonts/Lato-Black.ttf</file>
<file>fonts/Lato-BlackItalic.ttf</file>
<file>fonts/Lato-Bold.ttf</file>
<file>fonts/Lato-BoldItalic.ttf</file>
<file>fonts/Lato-Italic.ttf</file>
<file>fonts/Lato-Light.ttf</file>
<file>fonts/Lato-LightItalic.ttf</file>
<file>fonts/Lato-Regular.ttf</file>
<file>fonts/Lato-Thin.ttf</file>
<file>fonts/Lato-ThinItalic.ttf</file>
<file>images/Line.png</file>
<file>images/AmneziaVPN.png</file>
</qresource>
</RCC>

View file

@ -0,0 +1,193 @@
#include "SlidingStackedWidget.h"
SlidingStackedWidget::SlidingStackedWidget(QWidget *parent)
: QStackedWidget(parent)
{
if (parent != 0) {
m_mainwindow = parent;
}
else {
m_mainwindow = this;
qDebug().noquote() << "ATTENTION: untested mainwindow case !";
}
// parent should not be 0; not tested for any other case yet !!
#ifdef Q_OS_SYMBIAN
#ifndef __S60_50__
qDebug().noquote() << "WARNING: ONLY TESTED AND 5TH EDITION";
#endif // __S60_50__
#endif // Q_OS_SYMBIAN
// Now, initialize some private variables with default values
m_vertical = false;
// setVerticalMode(true);
m_speed = 500;
m_animationtype = QEasingCurve::OutBack; // check out the QEasingCurve documentation for different styles
m_now = 0;
m_next = 0;
m_wrap = false;
m_pnow = QPoint(0,0);
m_active = false;
}
SlidingStackedWidget::~SlidingStackedWidget() {
}
void SlidingStackedWidget::setVerticalMode(bool vertical) {
m_vertical = vertical;
}
void SlidingStackedWidget::setSpeed(int speed) {
m_speed = speed;
}
void SlidingStackedWidget::setAnimation(enum QEasingCurve::Type animationtype) {
m_animationtype = animationtype;
}
void SlidingStackedWidget::setWrap(bool wrap) {
m_wrap = wrap;
}
void SlidingStackedWidget::slideInNext() {
int now = currentIndex();
if (m_wrap || (now < count() - 1))
// count is inherit from QStackedWidget
slideInIdx(now + 1);
}
void SlidingStackedWidget::slideInPrev() {
int now = currentIndex();
if (m_wrap || (now > 0))
slideInIdx(now - 1);
}
void SlidingStackedWidget::slideInIdx(int idx, enum t_direction direction) {
// int idx, t_direction direction=AUTOMATIC
if (idx > count() - 1) {
direction = m_vertical ? TOP2BOTTOM : RIGHT2LEFT;
idx = (idx) % count();
}
else if (idx < 0) {
direction = m_vertical ? BOTTOM2TOP: LEFT2RIGHT;
idx = (idx + count()) % count();
}
slideInWgtImpl(widget(idx), direction);
// widget() is a function inherited from QStackedWidget
}
void SlidingStackedWidget::slideInWidget(QWidget *widget, SlidingStackedWidget::t_direction direction)
{
Q_UNUSED(direction);
#ifdef Q_OS_WIN
int idx = indexOf(widget);
slideInIdx(idx, direction);
#endif
#ifdef Q_OS_MAC
setCurrentWidget(widget);
#endif
}
void SlidingStackedWidget::slideInWgtImpl(QWidget * newwidget, enum t_direction direction) {
if (m_active) {
return;
}
else m_active = true;
enum t_direction directionhint;
int now = currentIndex(); // currentIndex() is a function inherited from QStackedWidget
int next = indexOf(newwidget);
if (now == next) {
m_active = false;
return;
}
else if (now < next) {
directionhint = m_vertical ? TOP2BOTTOM : RIGHT2LEFT;
}
else {
directionhint = m_vertical ? BOTTOM2TOP : LEFT2RIGHT;
}
if (direction == AUTOMATIC) {
direction = directionhint;
}
// NOW....
// calculate the shifts
int offsetx = frameRect().width(); // inherited from mother
int offsety = frameRect().height(); // inherited from mother
// the following is important, to ensure that the new widget
// has correct geometry information when sliding in first time
widget(next)->setGeometry(0, 0, offsetx, offsety);
if (direction == BOTTOM2TOP) {
offsetx = 0;
offsety = -offsety;
}
else if (direction == TOP2BOTTOM) {
offsetx = 0;
// offsety = offsety;
}
else if (direction == RIGHT2LEFT) {
offsetx = -offsetx;
offsety = 0;
}
else if (direction == LEFT2RIGHT) {
// offsetx = offsetx;
offsety = 0;
}
// re-position the next widget outside/aside of the display area
QPoint pnext = widget(next)->pos();
QPoint pnow = widget(now)->pos();
m_pnow = pnow;
widget(next)->move(pnext.x() - offsetx, pnext.y() - offsety);
// make it visible/show
widget(next)->show();
widget(next)->raise();
// animate both, the now and next widget to the side, using animation framework
QPropertyAnimation *animnow = new QPropertyAnimation(widget(now), "pos");
animnow->setDuration(m_speed);
animnow->setEasingCurve(m_animationtype);
animnow->setStartValue(QPoint(pnow.x(), pnow.y()));
animnow->setEndValue(QPoint(offsetx + pnow.x(), offsety + pnow.y()));
QPropertyAnimation *animnext = new QPropertyAnimation(widget(next), "pos");
animnext->setDuration(m_speed);
animnext->setEasingCurve(m_animationtype);
animnext->setStartValue(QPoint(-offsetx + pnext.x(), offsety + pnext.y()));
animnext->setEndValue(QPoint(pnext.x(), pnext.y()));
QParallelAnimationGroup *animgroup = new QParallelAnimationGroup;
animgroup->addAnimation(animnow);
animgroup->addAnimation(animnext);
QObject::connect(animgroup, SIGNAL(finished()),this,SLOT(animationDoneSlot()));
m_next = next;
m_now = now;
m_active = true;
animgroup->start();
// note; the rest is done via a connect from the animation ready;
// animation->finished() provides a signal when animation is done;
// so we connect this to some post processing slot,
// that we implement here below in animationDoneSlot.
}
void SlidingStackedWidget::animationDoneSlot(void) {
// when ready, call the QStackedWidget slot setCurrentIndex(int)
setCurrentIndex(m_next); // this function is inherited from QStackedWidget
// then hide the outshifted widget now, and (may be done already implicitely by QStackedWidget)
widget(m_now)->hide();
// then set the position of the outshifted widget now back to its original
widget(m_now)->move(m_pnow);
// so that the application could also still call the QStackedWidget original functions/slots for changings
// widget(m_now)->update();
// setCurrentIndex(m_next); // this function is inherit from QStackedWidget
m_active = false;
emit animationFinished();
}

View file

@ -0,0 +1,76 @@
#ifndef SLIDINGSTACKEDWIDGET_H
#define SLIDINGSTACKEDWIDGET_H
#include <QStackedWidget>
#include <QWidget>
#include <QDebug>
#include <QEasingCurve>
#include <QPropertyAnimation>
#include <QParallelAnimationGroup>
/* Description
SlidingStackedWidget is a class that is derived from QtStackedWidget
and allows smooth side shifting of widgets, in addition
to the original hard switching from one to another as offered by
QStackedWidget itself.
*/
class SlidingStackedWidget : public QStackedWidget {
Q_OBJECT
public:
// This enumeration is used to define the animation direction
enum t_direction {
LEFT2RIGHT,
RIGHT2LEFT,
TOP2BOTTOM,
BOTTOM2TOP,
AUTOMATIC
};
// The Constructor and Destructor
SlidingStackedWidget(QWidget *parent);
~SlidingStackedWidget(void);
public slots:
// Some basic settings API
void setSpeed(int speed); // animation duration in milliseconds
void setAnimation(enum QEasingCurve::Type animationtype); // check out the QEasingCurve documentation for different styles
void setVerticalMode(bool vertical=true);
void setWrap(bool wrap); // wrapping is related to slideInNext/Prev;it defines the behaviour when reaching last/first page
// The Animation / Page Change API
void slideInNext();
void slideInPrev();
void slideInIdx(int idx, enum t_direction direction = AUTOMATIC);
void slideInWidget(QWidget *widget, enum t_direction direction = AUTOMATIC);
signals:
// this is used for internal purposes in the class engine
void animationFinished(void);
protected slots:
// this is used for internal purposes in the class engine
void animationDoneSlot(void);
protected:
// this is used for internal purposes in the class engine
void slideInWgtImpl(QWidget *widget, enum t_direction direction = AUTOMATIC);
QWidget *m_mainwindow;
int m_speed;
enum QEasingCurve::Type m_animationtype;
bool m_vertical;
int m_now;
int m_next;
bool m_wrap;
QPoint m_pnow;
bool m_active;
QList<QWidget*> blockedPageList;
};
#endif // SLIDINGSTACKEDWIDGET_H

View file

@ -0,0 +1,76 @@
#include "customshadoweffect.h"
#include <QPainter>
CustomShadowEffect::CustomShadowEffect(QObject *parent) :
QGraphicsEffect(parent),
_distance(4.0f),
_blurRadius(10.0f),
_color(0, 0, 0, 80)
{
}
QT_BEGIN_NAMESPACE
extern Q_WIDGETS_EXPORT void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0 );
QT_END_NAMESPACE
void CustomShadowEffect::draw(QPainter* painter)
{
// if nothing to show outside the item, just draw source
if ((blurRadius() + distance()) <= 0) {
drawSource(painter);
return;
}
PixmapPadMode mode = QGraphicsEffect::PadToEffectiveBoundingRect;
QPoint offset;
const QPixmap px = sourcePixmap(Qt::DeviceCoordinates, &offset, mode);
// return if no source
if (px.isNull())
return;
// save world transform
QTransform restoreTransform = painter->worldTransform();
painter->setWorldTransform(QTransform());
// Calculate size for the background image
QSize szi(px.size().width() + 2 * distance(), px.size().height() + 2 * distance());
QImage tmp(szi, QImage::Format_ARGB32_Premultiplied);
QPixmap scaled = px.scaled(szi);
tmp.fill(0);
QPainter tmpPainter(&tmp);
tmpPainter.setCompositionMode(QPainter::CompositionMode_Source);
tmpPainter.drawPixmap(QPointF(-distance(), -distance()), scaled);
tmpPainter.end();
// blur the alpha channel
QImage blurred(tmp.size(), QImage::Format_ARGB32_Premultiplied);
blurred.fill(0);
QPainter blurPainter(&blurred);
qt_blurImage(&blurPainter, tmp, blurRadius(), false, true);
blurPainter.end();
tmp = blurred;
// blacken the image...
tmpPainter.begin(&tmp);
tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
tmpPainter.fillRect(tmp.rect(), color());
tmpPainter.end();
// draw the blurred shadow...
painter->drawImage(offset, tmp);
// draw the actual pixmap...
painter->drawPixmap(offset, px, QRectF());
// restore world transform
painter->setWorldTransform(restoreTransform);
}
QRectF CustomShadowEffect::boundingRectFor(const QRectF& rect) const
{
qreal delta = blurRadius() + distance();
return rect.united(rect.adjusted(-delta, -delta, delta, delta));
}

View file

@ -0,0 +1,31 @@
#ifndef CUSTOMSHADOWEFFECT_H
#define CUSTOMSHADOWEFFECT_H
#include <QGraphicsDropShadowEffect>
#include <QGraphicsEffect>
class CustomShadowEffect : public QGraphicsEffect
{
Q_OBJECT
public:
explicit CustomShadowEffect(QObject *parent = 0);
void draw(QPainter* painter);
QRectF boundingRectFor(const QRectF& rect) const;
inline void setDistance(qreal distance) { _distance = distance; updateBoundingRect(); }
inline qreal distance() const { return _distance; }
inline void setBlurRadius(qreal blurRadius) { _blurRadius = blurRadius; updateBoundingRect(); }
inline qreal blurRadius() const { return _blurRadius; }
inline void setColor(const QColor& color) { _color = color; }
inline QColor color() const { return _color; }
private:
qreal _distance;
qreal _blurRadius;
QColor _color;
};
#endif // CUSTOMSHADOWEFFECT_H

36
client/ui/mainwindow.cpp Normal file
View file

@ -0,0 +1,36 @@
#include <QMetaEnum>
#include <QMovie>
#include <QMessageBox>
#include <QMouseEvent>
#include <QScroller>
#include <QScrollBar>
#include <QDesktopWidget>
#include <QDesktopServices>
#include <QGridLayout>
#include <QTime>
#include "mainwindow.h"
#ifdef Q_OS_WIN
#include "ui_mainwindow.h"
#endif
#ifdef Q_OS_MAC
#include "ui_mainwindow_mac.h"
#include "publib/macos_functions.h"
#endif
MainWindow::MainWindow(bool useForceUseBrightIcons, QWidget *parent) : QMainWindow(parent),
ui(new Ui::MainWindow),
forceUseBrightIcons(useForceUseBrightIcons)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}

43
client/ui/mainwindow.h Normal file
View file

@ -0,0 +1,43 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSystemTrayIcon>
#include <QAction>
#include <QMenu>
#include <QJsonDocument>
#include <QClipboard>
#include <QStringListModel>
#include <QDataStream>
#include <QGraphicsBlurEffect>
#include "customshadoweffect.h"
namespace Ui {
class MainWindow;
}
/**
* @brief The MainWindow class - Main application window
*/
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(bool setForceUseBrightIcons = false, QWidget *parent = nullptr);
~MainWindow();
public slots:
private slots:
private:
Ui::MainWindow *ui;
bool forceUseBrightIcons = false;
};
#endif // MAINWINDOW_H

1293
client/ui/mainwindow.ui Normal file

File diff suppressed because it is too large Load diff

1665
client/ui/mainwindow_mac.ui Normal file

File diff suppressed because it is too large Load diff