diff --git a/client/debug.cpp b/client/debug.cpp index c9315ae7..caccbd37 100644 --- a/client/debug.cpp +++ b/client/debug.cpp @@ -6,13 +6,15 @@ #include +#include + #include "debug.h" #include "defines.h" #include "utils.h" QFile Debug::m_file; QTextStream Debug::m_textStream; -QString Debug::m_logFileName; +QString Debug::m_logFileName = QString("%1.log").arg(APPLICATION_NAME); void debugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) { @@ -40,11 +42,8 @@ bool Debug::init() return false; } - m_logFileName = QString("%1.log").arg(APPLICATION_NAME); - - m_file.setFileName(appDir.filePath(m_logFileName)); - if (!m_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + if (!m_file.open(QIODevice::Append)) { qWarning() << "Cannot open log file:" << m_logFileName; return false; } @@ -88,3 +87,52 @@ QString Debug::appLogFileNamePath() { return m_file.fileName(); } + +void Debug::clearLogs() +{ + bool isLogActive = m_file.isOpen(); + m_file.close(); + + + QString path = userLogsDir(); + QDir appDir(path); + QFile file; + file.setFileName(appDir.filePath(m_logFileName)); + + file.open(QIODevice::WriteOnly | QIODevice::Truncate); + file.resize(0); + file.close(); + + if (isLogActive) { + init(); + } +} + +void Debug::clearServiceLogs() +{ + IpcClient *m_IpcClient = new IpcClient; + + if (!m_IpcClient->isSocketConnected()) { + if (!IpcClient::init(m_IpcClient)) { + qWarning() << "Error occured when init IPC client"; + return; + } + } + + if (m_IpcClient->Interface()) { + m_IpcClient->Interface()->setLogsEnabled(false); + m_IpcClient->Interface()->cleanUp(); + } + else { + qWarning() << "Error occured cleaning up service logs"; + } +} + +void Debug::cleanUp() +{ + clearLogs(); + QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); + dir.removeRecursively(); + + clearServiceLogs(); +} diff --git a/client/debug.h b/client/debug.h index e0744842..50bf82ca 100644 --- a/client/debug.h +++ b/client/debug.h @@ -14,6 +14,9 @@ public: static bool openLogsFolder(); static bool openServiceLogsFolder(); static QString appLogFileNamePath(); + static void clearLogs(); + static void clearServiceLogs(); + static void cleanUp(); private: static QString userLogsDir(); diff --git a/client/main.cpp b/client/main.cpp index db54321a..f98b1ff5 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -86,15 +86,15 @@ int main(int argc, char *argv[]) QApplication app(argc, argv); #endif -#if defined(Q_OS_ANDROID) - NativeHelpers::registerApplicationInstance(&app); -#endif - #ifdef Q_OS_WIN AllowSetForegroundWindow(0); #endif +#if defined(Q_OS_ANDROID) + NativeHelpers::registerApplicationInstance(&app); +#endif + loadTranslator(); QFontDatabase::addApplicationFont(":/fonts/Lato-Black.ttf"); @@ -120,10 +120,26 @@ int main(int argc, char *argv[]) QCommandLineOption c_autostart {{"a", "autostart"}, "System autostart"}; parser.addOption(c_autostart); + QCommandLineOption c_cleanup {{"c", "cleanup"}, "Cleanup logs"}; + parser.addOption(c_cleanup); + parser.process(app); - if (!Debug::init()) { - qWarning() << "Initialization of debug subsystem failed"; + if (parser.isSet(c_cleanup)) { + Debug::cleanUp(); + QTimer::singleShot(100,[&app]{ + app.quit(); + }); + app.exec(); + return 0; + } + + Settings settings; + + if (settings.isSaveLogs()) { + if (!Debug::init()) { + qWarning() << "Initialization of debug subsystem failed"; + } } app.setQuitOnLastWindowClosed(false); @@ -203,18 +219,16 @@ int main(int argc, char *argv[]) uiLogic->showOnStartup(); #endif - - // TODO - fix -//#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) -// if (app.isPrimary()) { -// QObject::connect(&app, &SingleApplication::instanceStarted, &mainWindow, [&](){ -// qDebug() << "Secondary instance started, showing this window instead"; -// mainWindow.show(); -// mainWindow.showNormal(); -// mainWindow.raise(); -// }); -// } -//#endif + // TODO - fix +#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) + if (app.isPrimary()) { + QObject::connect(&app, &SingleApplication::instanceStarted, uiLogic, [&](){ + qDebug() << "Secondary instance started, showing this window instead"; + emit uiLogic->show(); + emit uiLogic->raise(); + }); + } +#endif return app.exec(); } diff --git a/client/protocols/openvpnprotocol.cpp b/client/protocols/openvpnprotocol.cpp index 75e56674..6adabfb3 100644 --- a/client/protocols/openvpnprotocol.cpp +++ b/client/protocols/openvpnprotocol.cpp @@ -159,8 +159,8 @@ ErrorCode OpenVpnProtocol::start() return lastError(); } - QString vpnLogFileNamePath = Utils::systemLogPath() + "/openvpn.log"; - Utils::createEmptyFile(vpnLogFileNamePath); +// QString vpnLogFileNamePath = Utils::systemLogPath() + "/openvpn.log"; +// Utils::createEmptyFile(vpnLogFileNamePath); if (!m_managementServer.start(m_managementHost, m_managementPort)) { setLastError(ErrorCode::OpenVpnManagementServerError); @@ -186,8 +186,7 @@ ErrorCode OpenVpnProtocol::start() m_openVpnProcess->setProgram(openVpnExecPath()); QStringList arguments({"--config" , configPath(), "--management", m_managementHost, QString::number(m_managementPort), - "--management-client", - "--log", vpnLogFileNamePath + "--management-client"/*, "--log", vpnLogFileNamePath */ }); m_openVpnProcess->setArguments(arguments); diff --git a/client/settings.h b/client/settings.h index 409f4ecd..de0207b6 100644 --- a/client/settings.h +++ b/client/settings.h @@ -67,6 +67,9 @@ public: bool isStartMinimized() const { return m_settings.value("Conf/startMinimized", false).toBool(); } void setStartMinimized(bool enabled) { m_settings.setValue("Conf/startMinimized", enabled); } + bool isSaveLogs() const { return m_settings.value("Conf/saveLogs", false).toBool(); } + void setSaveLogs(bool enabled) { m_settings.setValue("Conf/saveLogs", enabled); } + enum RouteMode { VpnAllSites, VpnOnlyForwardSites, diff --git a/client/ui/pages_logic/AppSettingsLogic.cpp b/client/ui/pages_logic/AppSettingsLogic.cpp index 2b89dd2c..4278141b 100644 --- a/client/ui/pages_logic/AppSettingsLogic.cpp +++ b/client/ui/pages_logic/AppSettingsLogic.cpp @@ -11,7 +11,8 @@ AppSettingsLogic::AppSettingsLogic(UiLogic *logic, QObject *parent): PageLogicBase(logic, parent), m_checkBoxAutostartChecked{false}, m_checkBoxAutoConnectChecked{false}, - m_checkBoxStartMinimizedChecked{false} + m_checkBoxStartMinimizedChecked{false}, + m_checkBoxSaveLogsChecked{false} { } @@ -21,6 +22,7 @@ void AppSettingsLogic::onUpdatePage() set_checkBoxAutostartChecked(Autostart::isAutostart()); set_checkBoxAutoConnectChecked(m_settings.isAutoConnect()); set_checkBoxStartMinimizedChecked(m_settings.isStartMinimized()); + set_checkBoxSaveLogsChecked(m_settings.isSaveLogs()); QString ver = QString("%1: %2 (%3)") .arg(tr("Software version")) @@ -47,7 +49,23 @@ void AppSettingsLogic::onCheckBoxStartMinimizedToggled(bool checked) m_settings.setStartMinimized(checked); } +void AppSettingsLogic::onCheckBoxSaveLogsCheckedToggled(bool checked) +{ + m_settings.setSaveLogs(checked); +} + void AppSettingsLogic::onPushButtonOpenLogsClicked() { Debug::openLogsFolder(); } + +void AppSettingsLogic::onPushButtonExportLogsClicked() +{ + +} + +void AppSettingsLogic::onPushButtonClearLogsClicked() +{ + Debug::clearLogs(); + Debug::clearServiceLogs(); +} diff --git a/client/ui/pages_logic/AppSettingsLogic.h b/client/ui/pages_logic/AppSettingsLogic.h index e71f6e98..b597b129 100644 --- a/client/ui/pages_logic/AppSettingsLogic.h +++ b/client/ui/pages_logic/AppSettingsLogic.h @@ -11,6 +11,7 @@ class AppSettingsLogic : public PageLogicBase AUTO_PROPERTY(bool, checkBoxAutostartChecked) AUTO_PROPERTY(bool, checkBoxAutoConnectChecked) AUTO_PROPERTY(bool, checkBoxStartMinimizedChecked) + AUTO_PROPERTY(bool, checkBoxSaveLogsChecked) AUTO_PROPERTY(QString, labelVersionText) public: @@ -19,7 +20,10 @@ public: Q_INVOKABLE void onCheckBoxAutostartToggled(bool checked); Q_INVOKABLE void onCheckBoxAutoconnectToggled(bool checked); Q_INVOKABLE void onCheckBoxStartMinimizedToggled(bool checked); + Q_INVOKABLE void onCheckBoxSaveLogsCheckedToggled(bool checked); Q_INVOKABLE void onPushButtonOpenLogsClicked(); + Q_INVOKABLE void onPushButtonExportLogsClicked(); + Q_INVOKABLE void onPushButtonClearLogsClicked(); public: explicit AppSettingsLogic(UiLogic *uiLogic, QObject *parent = nullptr); diff --git a/client/ui/pages_logic/protocols/OtherProtocolsLogic.cpp b/client/ui/pages_logic/protocols/OtherProtocolsLogic.cpp index a94391d5..8cf3949f 100644 --- a/client/ui/pages_logic/protocols/OtherProtocolsLogic.cpp +++ b/client/ui/pages_logic/protocols/OtherProtocolsLogic.cpp @@ -18,7 +18,9 @@ using namespace amnezia; using namespace PageEnumNS; OtherProtocolsLogic::OtherProtocolsLogic(UiLogic *logic, QObject *parent): - PageProtocolLogicBase(logic, parent) + PageProtocolLogicBase(logic, parent), + m_checkBoxSftpRestoreChecked{false} + { } diff --git a/client/ui/qml/Pages/PageAppSetting.qml b/client/ui/qml/Pages/PageAppSetting.qml index 497471b4..3d99af40 100644 --- a/client/ui/qml/Pages/PageAppSetting.qml +++ b/client/ui/qml/Pages/PageAppSetting.qml @@ -81,9 +81,19 @@ PageBase { Qt.openUrlExternally("https://github.com/amnezia-vpn/desktop-client/releases/latest") } } - BlueButtonType { + + CheckBoxType { Layout.fillWidth: true Layout.topMargin: 15 + text: qsTr("Keep logs") + checked: AppSettingsLogic.checkBoxSaveLogsChecked + onCheckedChanged: { + AppSettingsLogic.checkBoxSaveLogsChecked = checked + AppSettingsLogic.onCheckBoxSaveLogsCheckedToggled(checked) + } + } + BlueButtonType { + Layout.fillWidth: true Layout.preferredHeight: 41 text: qsTr("Open logs folder") onClicked: { @@ -97,10 +107,30 @@ PageBase { Layout.preferredHeight: 41 text: qsTr("Export logs") onClicked: { - AppSettingsLogic.onPushButtonOpenLogsClicked() + AppSettingsLogic.onPushButtonExportLogsClicked() } } + BlueButtonType { + Layout.fillWidth: true + Layout.topMargin: 15 + Layout.preferredHeight: 41 + + property string start_text: qsTr("Clear logs") + property string end_text: qsTr("Cleared") + text: start_text + + Timer { + id: timer + interval: 1000; running: false; repeat: false + onTriggered: parent.text = parent.start_text + } + onClicked: { + text = end_text + timer.running = true + AppSettingsLogic.onPushButtonClearLogsClicked() + } + } } } diff --git a/ipc/ipc_interface.rep b/ipc/ipc_interface.rep index 9cb99110..2c9f4746 100644 --- a/ipc/ipc_interface.rep +++ b/ipc/ipc_interface.rep @@ -15,5 +15,8 @@ class IpcInterface SLOT( bool checkAndInstallDriver() ); SLOT( QStringList getTapList() ); + + SLOT( void cleanUp() ); + SLOT( void setLogsEnabled(bool enabled) ); }; diff --git a/ipc/ipcserver.cpp b/ipc/ipcserver.cpp index c32e043a..d71d7c7d 100644 --- a/ipc/ipcserver.cpp +++ b/ipc/ipcserver.cpp @@ -5,6 +5,8 @@ #include #include "router.h" +#include "log.h" + #ifdef Q_OS_WIN #include "tapcontroller_win.h" #endif @@ -33,7 +35,7 @@ int IpcServer::createPrivilegedProcess() // Make sure any connections are handed to QtRO QObject::connect(pd.localServer.data(), &QLocalServer::newConnection, this, [pd]() { - qDebug() << "LocalServer new connection"; + qDebug() << "IpcServer new connection"; if (pd.serverNode) { pd.serverNode->addHostSideConnection(pd.localServer->nextPendingConnection()); pd.serverNode->enableRemoting(pd.ipcProcess.data()); @@ -105,3 +107,20 @@ QStringList IpcServer::getTapList() return QStringList(); #endif } + +void IpcServer::cleanUp() +{ + qDebug() << "IpcServer::cleanUp"; + Log::deinit(); + Log::cleanUp(); +} + +void IpcServer::setLogsEnabled(bool enabled) +{ + if (enabled) { + Log::init(); + } + else { + Log::deinit(); + } +} diff --git a/ipc/ipcserver.h b/ipc/ipcserver.h index f0182281..a5b52ed1 100644 --- a/ipc/ipcserver.h +++ b/ipc/ipcserver.h @@ -23,6 +23,8 @@ public: virtual void resetIpStack() override; virtual bool checkAndInstallDriver() override; virtual QStringList getTapList() override; + virtual void cleanUp() override; + virtual void setLogsEnabled(bool enabled) override; private: int m_localpid = 0; diff --git a/service/server/log.cpp b/service/server/log.cpp index 9d0d3a72..978a6aff 100644 --- a/service/server/log.cpp +++ b/service/server/log.cpp @@ -9,7 +9,7 @@ QFile Log::m_file; QTextStream Log::m_textStream; -QString Log::m_logFileName; +QString Log::m_logFileName = QString("%1.log").arg(SERVICE_NAME); void debugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) { @@ -22,20 +22,20 @@ void debugMessageHandler(QtMsgType type, const QMessageLogContext& context, cons std::cout << qFormatLogMessage(type, context, msg).toStdString() << std::endl << std::flush; } -bool Log::initialize() +bool Log::init() { + if (m_file.isOpen()) return true; + QString path = Utils::systemLogPath(); QDir appDir(path); if (!appDir.mkpath(path)) { return false; } - m_logFileName = QString("%1.log").arg(SERVICE_NAME); - qSetMessagePattern("%{time yyyy-MM-dd hh:mm:ss} %{type} %{message}"); m_file.setFileName(appDir.filePath(m_logFileName)); - if (!m_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + if (!m_file.open(QIODevice::Append)) { qWarning() << "Cannot open log file:" << m_logFileName; return false; } @@ -46,8 +46,59 @@ bool Log::initialize() return true; } +void Log::deinit() +{ + m_file.close(); + m_textStream.setDevice(nullptr); + qInstallMessageHandler(nullptr); +} + QString Log::serviceLogFileNamePath() { return m_file.fileName(); } +void Log::clearLogs() +{ + bool isLogActive = m_file.isOpen(); + m_file.close(); + + + QString path = Utils::systemLogPath(); + QDir appDir(path); + QFile file; + file.setFileName(appDir.filePath(m_logFileName)); + + file.open(QIODevice::WriteOnly | QIODevice::Truncate); + file.resize(0); + file.close(); + + if (isLogActive) { + init(); + } +} + +void Log::cleanUp() +{ + clearLogs(); + deinit(); + + QString path = Utils::systemLogPath(); + QDir appDir(path); + + { + QFile file; + file.setFileName(appDir.filePath(m_logFileName)); + file.remove(); + } + { + QFile file; + file.setFileName(appDir.filePath("openvpn.log")); + file.remove(); + } + +#ifdef Q_OS_WINDOWS + QDir dir(Utils::systemLogPath()); + dir.removeRecursively(); +#endif +} diff --git a/service/server/log.h b/service/server/log.h index 1c385f7a..e87dda1d 100644 --- a/service/server/log.h +++ b/service/server/log.h @@ -9,9 +9,14 @@ class Log { public: - static bool initialize(); + static bool init(); + static void deinit(); + static QString serviceLogFileNamePath(); + static void clearLogs(); + static void cleanUp(); + private: friend void debugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg); diff --git a/service/server/main.cpp b/service/server/main.cpp index d0d7d82a..9f15195c 100644 --- a/service/server/main.cpp +++ b/service/server/main.cpp @@ -20,7 +20,7 @@ int main(int argc, char **argv) { Utils::initializePath(Utils::systemLogPath()); - Log::initialize(); + Log::init(); if (argc == 2) { qInfo() << "Started as console application";