parent
ff6ce6294b
commit
18f2accc7f
@ -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);
|
||||
}
|
@ -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
|
@ -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();
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
#ifndef MIME_H
|
||||
#define MIME_H
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
void registerXdgMime(QApplication &app);
|
||||
|
||||
#endif // MIME_H
|
@ -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;
|
||||
}
|
@ -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
|
Reference in new issue