GUI: Begin IPC mechanism to open files despite sandboxing
This commit is contained in:
父節點
3e387b99f8
當前提交
890925929a
@ -4,7 +4,7 @@
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core concurrent gui
|
||||
QT += core concurrent gui network
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
CONFIG += c++17
|
||||
@ -23,6 +23,8 @@ DEFINES += QT_DEPRECATED_WARNINGS
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
SOURCES += \
|
||||
ipcclient.cpp \
|
||||
ipcserver.cpp \
|
||||
main.cpp \
|
||||
mainwindow.cpp \
|
||||
pdfworker.cpp \
|
||||
@ -30,6 +32,9 @@ SOURCES += \
|
||||
clicklabel.cpp
|
||||
|
||||
HEADERS += \
|
||||
ipc.h \
|
||||
ipcclient.h \
|
||||
ipcserver.h \
|
||||
mainwindow.h \
|
||||
pdfworker.h \
|
||||
pdfpreview.h \
|
||||
|
9
gui/ipc.h
Normal file
9
gui/ipc.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef IPC_H
|
||||
#define IPC_H
|
||||
|
||||
enum IPCCommand
|
||||
{
|
||||
DocOpen,
|
||||
FileOpen
|
||||
};
|
||||
#endif // IPC_H
|
27
gui/ipcclient.cpp
Normal file
27
gui/ipcclient.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include <QDataStream>
|
||||
#include "ipcclient.h"
|
||||
|
||||
IPCClient::IPCClient(QString socketPath)
|
||||
{
|
||||
this->socketPath = socketPath;
|
||||
}
|
||||
|
||||
bool IPCClient::sendCommand(IPCCommand command, QStringList args)
|
||||
{
|
||||
bool result = false;
|
||||
QLocalSocket socket;
|
||||
socket.connectToServer(socketPath);
|
||||
if(socket.isOpen() && socket.isWritable())
|
||||
{
|
||||
QDataStream stream(&socket);
|
||||
stream << command;
|
||||
stream << args;
|
||||
socket.flush();
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Not connected to IPC server";
|
||||
}
|
||||
return result;
|
||||
}
|
18
gui/ipcclient.h
Normal file
18
gui/ipcclient.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef IPCCLIENT_H
|
||||
#define IPCCLIENT_H
|
||||
#include <QLocalSocket>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include "ipc.h"
|
||||
|
||||
class IPCClient
|
||||
{
|
||||
private:
|
||||
QString socketPath;
|
||||
|
||||
public:
|
||||
IPCClient(QString socketPath);
|
||||
bool sendCommand(IPCCommand command, QStringList args);
|
||||
};
|
||||
|
||||
#endif // IPCCLIENT_H
|
88
gui/ipcserver.cpp
Normal file
88
gui/ipcserver.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
#include <QFile>
|
||||
#include <QDesktopServices>
|
||||
#include <QSettings>
|
||||
#include <QProcess>
|
||||
#include <QUrl>
|
||||
#include <QLocalSocket>
|
||||
#include <QDataStream>
|
||||
#include "ipcserver.h"
|
||||
|
||||
IpcServer::IpcServer()
|
||||
{
|
||||
connect(&this->spawningServer, &QLocalServer::newConnection, this, &IpcServer::spawnerNewConnection);
|
||||
}
|
||||
|
||||
bool IpcServer::startSpawner(QString socketPath)
|
||||
{
|
||||
QFile::remove(socketPath);
|
||||
return this->spawningServer.listen(socketPath);
|
||||
}
|
||||
|
||||
bool IpcServer::docOpen(QString path, int pagenum)
|
||||
{
|
||||
QSettings settings;
|
||||
QString command = settings.value("pdfviewer").toString();
|
||||
if(command != "" && command.contains("%p") && command.contains("%f"))
|
||||
{
|
||||
QStringList splitted = command.split(" ");
|
||||
if(splitted.size() > 1)
|
||||
{
|
||||
QString cmd = splitted[0];
|
||||
QStringList args = splitted.mid(1);
|
||||
args.replaceInStrings("%f", path);
|
||||
args.replaceInStrings("%p", QString::number(pagenum));
|
||||
|
||||
QProcess::startDetached(cmd, args);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IpcServer::fileOpen(QString path)
|
||||
{
|
||||
return QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
||||
}
|
||||
|
||||
void IpcServer::spawnerNewConnection()
|
||||
{
|
||||
QScopedPointer<QLocalSocket> socket{this->spawningServer.nextPendingConnection()};
|
||||
if(!socket.isNull())
|
||||
{
|
||||
if(!socket->waitForReadyRead())
|
||||
{
|
||||
return;
|
||||
}
|
||||
QDataStream stream(socket.get());
|
||||
IPCCommand command;
|
||||
QStringList args;
|
||||
stream >> command;
|
||||
stream >> args;
|
||||
if(args.size() < 1)
|
||||
{
|
||||
stream << "invalid";
|
||||
return;
|
||||
}
|
||||
if(command == DocOpen)
|
||||
{
|
||||
if(args.size() < 2)
|
||||
{
|
||||
stream << "invalid";
|
||||
return;
|
||||
}
|
||||
docOpen(args[0], args[2].toInt());
|
||||
}
|
||||
if(command == FileOpen)
|
||||
{
|
||||
if(args.size() < 1)
|
||||
{
|
||||
stream << "invalid";
|
||||
return;
|
||||
}
|
||||
fileOpen(args[0]);
|
||||
}
|
||||
}
|
||||
}
|
21
gui/ipcserver.h
Normal file
21
gui/ipcserver.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef IPCSERVER_H
|
||||
#define IPCSERVER_H
|
||||
#include <QString>
|
||||
#include <QLocalServer>
|
||||
#include "ipc.h"
|
||||
class IpcServer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
QLocalServer spawningServer;
|
||||
bool docOpen(QString path, int pagenum);
|
||||
bool fileOpen(QString path);
|
||||
private slots:
|
||||
void spawnerNewConnection();
|
||||
|
||||
public:
|
||||
IpcServer();
|
||||
bool startSpawner(QString socketPath);
|
||||
};
|
||||
|
||||
#endif // IPCSERVER_H
|
38
gui/main.cpp
38
gui/main.cpp
@ -2,19 +2,51 @@
|
||||
#include <QSettings>
|
||||
#include <QMessageBox>
|
||||
#include <QStandardPaths>
|
||||
#include <QProcess>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "searchresult.h"
|
||||
#include "pdfpreview.h"
|
||||
#include "../shared/common.h"
|
||||
#include "../submodules/qssb.h/qssb.h"
|
||||
#include "ipcserver.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QString socketPath = "/tmp/looqs-spawner";
|
||||
if(argc > 1)
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
QString arg = argv[1];
|
||||
if(arg == "ipc")
|
||||
{
|
||||
IpcServer *ipcserver = new IpcServer();
|
||||
qDebug() << "Launching ipc";
|
||||
if(!ipcserver->startSpawner(socketPath))
|
||||
{
|
||||
qDebug() << "Error failed to spawn";
|
||||
return 1;
|
||||
}
|
||||
qDebug() << "Launched";
|
||||
}
|
||||
return a.exec();
|
||||
}
|
||||
QProcess process;
|
||||
QStringList args;
|
||||
args << "ipc";
|
||||
if(!process.startDetached("/proc/self/exe", args))
|
||||
{
|
||||
QString errorMsg = "Failed to start IPC server";
|
||||
qDebug() << errorMsg;
|
||||
QMessageBox::critical(nullptr, "Error", errorMsg);
|
||||
}
|
||||
|
||||
struct qssb_policy *policy = qssb_init_policy();
|
||||
std::string appDataLocation = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation).toStdString();
|
||||
std::string cacheDataLocation = QStandardPaths::writableLocation(QStandardPaths::CacheLocation).toStdString();
|
||||
|
||||
std::string sockPath = socketPath.toStdString();
|
||||
policy->namespace_options = QSSB_UNSHARE_NETWORK | QSSB_UNSHARE_USER;
|
||||
|
||||
qssb_append_path_policy(policy, QSSB_FS_ALLOW_READ | QSSB_FS_ALLOW_REMOVE_FILE, "/");
|
||||
qssb_append_path_policy(policy, QSSB_FS_ALLOW_READ | QSSB_FS_ALLOW_REMOVE_FILE | QSSB_FS_ALLOW_WRITE,
|
||||
appDataLocation.c_str());
|
||||
@ -44,7 +76,9 @@ int main(int argc, char *argv[])
|
||||
qRegisterMetaType<QVector<SearchResult>>("QVector<SearchResult>");
|
||||
qRegisterMetaType<QVector<PdfPreview>>("QVector<PdfPreview>");
|
||||
qRegisterMetaType<PdfPreview>("PdfPreview");
|
||||
MainWindow w;
|
||||
|
||||
IPCClient client{socketPath};
|
||||
MainWindow w{0, client};
|
||||
w.showMaximized();
|
||||
|
||||
return a.exec();
|
||||
|
@ -18,10 +18,11 @@
|
||||
#include "../shared/looqsgeneralexception.h"
|
||||
#include "../shared/common.h"
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
|
||||
MainWindow::MainWindow(QWidget *parent, IPCClient &client) : QMainWindow(parent), ui(new Ui::MainWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowTitle(QCoreApplication::applicationName());
|
||||
this->ipcClient = &client;
|
||||
QSettings settings;
|
||||
|
||||
db = QSqlDatabase::addDatabase("QSQLITE");
|
||||
@ -136,29 +137,7 @@ void MainWindow::pdfPreviewReceived(PdfPreview preview)
|
||||
label->setPixmap(QPixmap::fromImage(preview.previewImage));
|
||||
label->setToolTip(preview.documentPath);
|
||||
ui->scrollAreaWidgetContents->layout()->addWidget(label);
|
||||
connect(label, &ClickLabel::leftClick,
|
||||
[docPath, previewPage]()
|
||||
{
|
||||
QSettings settings;
|
||||
QString command = settings.value("pdfviewer").toString();
|
||||
if(command != "" && command.contains("%p") && command.contains("%f"))
|
||||
{
|
||||
QStringList splitted = command.split(" ");
|
||||
if(splitted.size() > 1)
|
||||
{
|
||||
QString cmd = splitted[0];
|
||||
QStringList args = splitted.mid(1);
|
||||
args.replaceInStrings("%f", docPath);
|
||||
args.replaceInStrings("%p", QString::number(previewPage));
|
||||
|
||||
QProcess::startDetached(cmd, args);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(docPath));
|
||||
}
|
||||
});
|
||||
connect(label, &ClickLabel::leftClick, [this, docPath, previewPage]() { ipcDocOpen(docPath, previewPage); });
|
||||
connect(label, &ClickLabel::rightClick,
|
||||
[this, docPath, previewPage]()
|
||||
{
|
||||
@ -301,17 +280,27 @@ void MainWindow::createSearchResutlMenu(QMenu &menu, const QFileInfo &fileInfo)
|
||||
[&fileInfo] { QGuiApplication::clipboard()->setText(fileInfo.fileName()); });
|
||||
menu.addAction("Copy full path to clipboard",
|
||||
[&fileInfo] { QGuiApplication::clipboard()->setText(fileInfo.absoluteFilePath()); });
|
||||
menu.addAction("Open containing folder",
|
||||
[&fileInfo]
|
||||
{
|
||||
QString dir = fileInfo.absolutePath();
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(dir));
|
||||
});
|
||||
menu.addAction("Open containing folder", [this, &fileInfo] { this->ipcFileOpen(fileInfo.absolutePath()); });
|
||||
}
|
||||
|
||||
void MainWindow::ipcDocOpen(QString path, int num)
|
||||
{
|
||||
QStringList args;
|
||||
args << path;
|
||||
args << QString::number(num);
|
||||
this->ipcClient->sendCommand(DocOpen, args);
|
||||
}
|
||||
|
||||
void MainWindow::ipcFileOpen(QString path)
|
||||
{
|
||||
QStringList args;
|
||||
args << path;
|
||||
this->ipcClient->sendCommand(FileOpen, args);
|
||||
}
|
||||
|
||||
void MainWindow::treeSearchItemActivated(QTreeWidgetItem *item, int i)
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(item->text(1)));
|
||||
ipcFileOpen(item->text(1));
|
||||
}
|
||||
|
||||
void MainWindow::showSearchResultsContextMenu(const QPoint &point)
|
||||
|
@ -8,8 +8,10 @@
|
||||
#include <QKeyEvent>
|
||||
#include <QFutureWatcher>
|
||||
#include <QSqlDatabase>
|
||||
#include <QLocalSocket>
|
||||
#include "pdfworker.h"
|
||||
#include "../shared/looqsquery.h"
|
||||
#include "ipcclient.h"
|
||||
namespace Ui
|
||||
{
|
||||
class MainWindow;
|
||||
@ -20,7 +22,7 @@ class MainWindow : public QMainWindow
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
explicit MainWindow(QWidget *parent, IPCClient &client);
|
||||
~MainWindow();
|
||||
signals:
|
||||
void beginSearch(const QString &query);
|
||||
@ -28,6 +30,7 @@ class MainWindow : public QMainWindow
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
IPCClient *ipcClient;
|
||||
QFileIconProvider iconProvider;
|
||||
bool pdfDirty;
|
||||
QSqlDatabase db;
|
||||
@ -45,6 +48,9 @@ class MainWindow : public QMainWindow
|
||||
LooqsQuery currentQuery;
|
||||
int pdfPreviewsPerPage;
|
||||
void createSearchResutlMenu(QMenu &menu, const QFileInfo &fileInfo);
|
||||
void ipcDocOpen(QString path, int num);
|
||||
void ipcFileOpen(QString path);
|
||||
|
||||
private slots:
|
||||
void lineEditReturnPressed();
|
||||
void treeSearchItemActivated(QTreeWidgetItem *item, int i);
|
||||
|
@ -13,6 +13,8 @@ TEMPLATE = lib
|
||||
CONFIG += staticlib
|
||||
CONFIG += c++17
|
||||
|
||||
INCLUDEPATH += $$PWD/../sandbox/qssb.h/
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any feature of Qt which has been marked as deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 75f607bc350354ed31fd0977311917e13241e703
|
||||
Subproject commit 692c9b54b7b5fdca6a416d91d3f34d15af185c33
|
載入中…
新增問題並參考
Block a user