aboutsummaryrefslogtreecommitdiff
path: root/src/qt
diff options
context:
space:
mode:
Diffstat (limited to 'src/qt')
-rw-r--r--src/qt/ipc.cpp106
-rw-r--r--src/qt/ipc.h35
-rw-r--r--src/qt/mime.cpp42
-rw-r--r--src/qt/mime.h8
-rw-r--r--src/qt/utils.cpp20
-rw-r--r--src/qt/utils.h11
6 files changed, 222 insertions, 0 deletions
diff --git a/src/qt/ipc.cpp b/src/qt/ipc.cpp
new file mode 100644
index 00000000..c7d1aa86
--- /dev/null
+++ b/src/qt/ipc.cpp
@@ -0,0 +1,106 @@
+#include <QCoreApplication>
+#include <QLocalSocket>
+#include <QLocalServer>
+#include <QtNetwork>
+#include <QDebug>
+
+#include "ipc.h"
+#include "utils.h"
+
+// Start listening for incoming IPC commands on UDS (Unix) or named pipe (Windows)
+void IPC::bind(){
+ QString path = QString(this->m_socketFile.absoluteFilePath());
+ qDebug() << path;
+
+ this->m_server = new QLocalServer(this);
+ this->m_server->setSocketOptions(QLocalServer::UserAccessOption);
+
+ bool restarted = false;
+ if(!this->m_server->listen(path)){
+ // On Unix if the server crashes without closing listen will fail with AddressInUseError.
+ // To create a new server the file should be removed. On Windows two local servers can listen
+ // to the same pipe at the same time, but any connections will go to one of the server.
+#ifdef Q_OS_UNIX
+ qDebug() << QString("Unable to start IPC server in \"%1\": \"%2\". Retrying.").arg(path).arg(this->m_server->errorString());
+ if(this->m_socketFile.exists()){
+ QFile file(path);
+ file.remove();
+
+ if(this->m_server->listen(path)){
+ restarted = true;
+ }
+ }
+#endif
+ if(!restarted)
+ qDebug() << QString("Unable to start IPC server in \"%1\": \"%2\".").arg(path).arg(this->m_server->errorString());
+ }
+
+ connect(this->m_server, &QLocalServer::newConnection, this, &IPC::handleConnection);
+}
+
+// Process incoming IPC command. First check if monero-wallet-gui is
+// already running. If it is, send it to that instance instead, if not,
+// queue the command for later use inside our QML engine. Returns true
+// when queued, false if sent to another instance, at which point we can
+// kill the current process.
+bool IPC::saveCommand(QString cmdString){
+ qDebug() << QString("saveCommand called: %1").arg(cmdString);
+
+ QLocalSocket ls;
+ QByteArray buffer;
+ buffer = buffer.append(cmdString);
+ QString socketFilePath = this->socketFile().filePath();
+
+ ls.connectToServer(socketFilePath, QIODevice::WriteOnly);
+ if(ls.waitForConnected(1000)){
+ ls.write(buffer);
+ if (!ls.waitForBytesWritten(1000)){
+ qDebug() << QString("Could not send command \"%1\" over IPC %2: \"%3\"").arg(cmdString, socketFilePath, ls.errorString());
+ return false;
+ }
+
+ qDebug() << QString("Sent command \"%1\" over IPC \"%2\"").arg(cmdString, socketFilePath);
+ return false;
+ }
+
+ if(ls.isOpen())
+ ls.disconnectFromServer();
+
+ // Queue for later
+ this->SetQueuedCmd(cmdString);
+ return true;
+}
+
+bool IPC::saveCommand(const QUrl &url){;
+ this->saveCommand(url.toString());
+}
+
+void IPC::handleConnection(){
+ QLocalSocket *clientConnection = this->m_server->nextPendingConnection();
+ connect(clientConnection, &QLocalSocket::disconnected,
+ clientConnection, &QLocalSocket::deleteLater);
+
+ clientConnection->waitForReadyRead(2);
+ QByteArray cmdArray = clientConnection->readAll();
+ QString cmdString = QTextCodec::codecForMib(106)->toUnicode(cmdArray); // UTF-8
+ qDebug() << cmdString;
+
+ this->parseCommand(cmdString);
+
+ clientConnection->close();
+ delete clientConnection;
+}
+
+void IPC::parseCommand(const QUrl &url){
+ this->parseCommand(url.toString());
+}
+
+void IPC::parseCommand(QString cmdString){
+ if(cmdString.contains(reURI)){
+ this->emitUriHandler(cmdString);
+ }
+}
+
+void IPC::emitUriHandler(QString uriString){
+ emit uriHandler(uriString);
+}
diff --git a/src/qt/ipc.h b/src/qt/ipc.h
new file mode 100644
index 00000000..5c3cc73a
--- /dev/null
+++ b/src/qt/ipc.h
@@ -0,0 +1,35 @@
+#ifndef IPC_H
+#define IPC_H
+
+#include <QtCore>
+#include <QLocalServer>
+#include <qt/utils.h>
+
+class IPC : public QObject
+{
+Q_OBJECT
+public:
+ IPC(QObject *parent = 0) : QObject(parent) {}
+ QFileInfo socketFile() const { return m_socketFile; }
+ Q_INVOKABLE QString queuedCmd() { return m_queuedCmd; }
+ void SetQueuedCmd(const QString cmdString) { m_queuedCmd = cmdString; }
+
+public slots:
+ void bind();
+ void handleConnection();
+ bool saveCommand(QString cmdString);
+ bool saveCommand(const QUrl &url);
+ void parseCommand(QString cmdString);
+ void parseCommand(const QUrl &url);
+ void emitUriHandler(QString uriString);
+
+signals:
+ void uriHandler(QString uriString);
+
+private:
+ QLocalServer *m_server;
+ QString m_queuedCmd;
+ QFileInfo m_socketFile = QFileInfo(QString(QDir::tempPath() + "/xmr-gui_%2.sock").arg(getAccountName()));
+};
+
+#endif // IPC_H
diff --git a/src/qt/mime.cpp b/src/qt/mime.cpp
new file mode 100644
index 00000000..76fbb19c
--- /dev/null
+++ b/src/qt/mime.cpp
@@ -0,0 +1,42 @@
+#include <QtCore>
+#include <QApplication>
+#include <QFile>
+#include <QTextStream>
+
+#include "mime.h"
+#include "utils.h"
+
+void registerXdgMime(QApplication &app){
+ // MacOS handled via Info.plist
+ // Windows handled in the installer by rbrunner7
+
+ QString xdg = QString(
+ "[Desktop Entry]\n"
+ "Name=Monero GUI\n"
+ "GenericName=Monero-GUI\n"
+ "X-GNOME-FullName=Monero-GUI\n"
+ "Comment=Monero GUI\n"
+ "Keywords=Monero;\n"
+ "Exec=%1 %u\n"
+ "Terminal=false\n"
+ "Type=Application\n"
+ "Icon=monero\n"
+ "Categories=Network;GNOME;Qt;\n"
+ "MimeType=x-scheme-handler/monero;x-scheme-handler/moneroseed\n"
+ "StartupNotify=true\n"
+ "X-GNOME-Bugzilla-Bugzilla=GNOME\n"
+ "X-GNOME-UsesNotifications=true\n"
+ ).arg(app.applicationFilePath());
+
+ QString appPath = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation);
+ QString filePath = QString("%1/monero-gui.desktop").arg(appPath);
+
+ qDebug() << QString("Writing %1").arg(filePath);
+ QFile file(filePath);
+ if(file.open(QIODevice::WriteOnly)){
+ QTextStream out(&file); out << xdg << endl;
+ file.close();
+ }
+ else
+ file.close();
+}
diff --git a/src/qt/mime.h b/src/qt/mime.h
new file mode 100644
index 00000000..a6c79587
--- /dev/null
+++ b/src/qt/mime.h
@@ -0,0 +1,8 @@
+#ifndef MIME_H
+#define MIME_H
+
+#include <QApplication>
+
+void registerXdgMime(QApplication &app);
+
+#endif // MIME_H
diff --git a/src/qt/utils.cpp b/src/qt/utils.cpp
new file mode 100644
index 00000000..cb0ad4f9
--- /dev/null
+++ b/src/qt/utils.cpp
@@ -0,0 +1,20 @@
+#include <QtCore>
+
+#include "utils.h"
+
+bool fileExists(QString path) {
+ QFileInfo check_file(path);
+ if (check_file.exists() && check_file.isFile())
+ return true;
+ else
+ return false;
+}
+
+QString getAccountName(){
+ QString accountName = qgetenv("USER"); // mac/linux
+ if (accountName.isEmpty())
+ accountName = qgetenv("USERNAME"); // Windows
+ if (accountName.isEmpty())
+ accountName = "My monero Account";
+ return accountName;
+}
diff --git a/src/qt/utils.h b/src/qt/utils.h
new file mode 100644
index 00000000..6a014ffc
--- /dev/null
+++ b/src/qt/utils.h
@@ -0,0 +1,11 @@
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <QtCore>
+#include <QRegExp>
+
+bool fileExists(QString path);
+QString getAccountName();
+const static QRegExp reURI = QRegExp("^\\w+:\\/\\/([\\w+\\-?\\-_\\-=\\-&]+)");
+
+#endif // UTILS_H