Compare commits
13 Commits
v0.1
...
0d2e518000
Author | SHA1 | Date | |
---|---|---|---|
0d2e518000 | |||
b108cb7151 | |||
c82cf03814 | |||
8a82da95bd | |||
a408173064 | |||
dd479fa668 | |||
e76988ee77 | |||
f29f997289 | |||
afa9d33f3d | |||
fc92b963d4 | |||
9acbd5dccf | |||
87ebc137d5 | |||
67189f34c6 |
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
.user
|
||||||
|
.o
|
||||||
|
*.user
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
moc_*.cpp
|
||||||
|
moc_*.h
|
||||||
|
Makefile
|
||||||
|
cli/looqs
|
||||||
|
gui/looqs-gui
|
||||||
|
qrc_*
|
@ -1,5 +1,10 @@
|
|||||||
# looqs: Release notes
|
# looqs: Release notes
|
||||||
|
|
||||||
|
## 2022-06-07 - v0.2
|
||||||
|
CHANGES:
|
||||||
|
- Sandboxing: Add environment variable `LOOQS_DISABLE_SANDBOXING` to disable sandboxing. This is intended for troubleshooting
|
||||||
|
- Sandboxing: Fix issue where activation failed on kernels without landlock
|
||||||
|
|
||||||
## 2022-06-06 - v0.1
|
## 2022-06-06 - v0.1
|
||||||
The first release comes with basic functionality. It's a start that can be considered useful to some degree.
|
The first release comes with basic functionality. It's a start that can be considered useful to some degree.
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@ The architecture ensures that the parsing of documents and the preview generatio
|
|||||||
|
|
||||||
Qt code is considered trusted in this model. While one may critize this, it was the only practical solution. looqs uses its serialization mechanism and other classes to communicate between the non-sandboxed GUI process and the sandboxed processes.
|
Qt code is considered trusted in this model. While one may critize this, it was the only practical solution. looqs uses its serialization mechanism and other classes to communicate between the non-sandboxed GUI process and the sandboxed processes.
|
||||||
|
|
||||||
|
Set the enviornment variable `LOOQS_DISABLE_SANDBOX=1` to disable sandboxing. It's intended for troublehshooting.
|
||||||
|
|
||||||
## Database
|
## Database
|
||||||
The heart is sqlite, with the FTS5 extensions behind the full-text search. I definitly did not
|
The heart is sqlite, with the FTS5 extensions behind the full-text search. I definitly did not
|
||||||
want to run some heavy Java based solutions. I explored other options like Postgresql, I've discard them due to some limitations back then.
|
want to run some heavy Java based solutions. I explored other options like Postgresql, I've discard them due to some limitations back then.
|
||||||
|
@ -30,7 +30,7 @@ There is no need to write the long form of filters. There are also booleans avai
|
|||||||
|
|
||||||
|
|
||||||
## Current status
|
## Current status
|
||||||
Last version: 2022-06-06, v0.1
|
Last version: 2022-06-07, v0.2
|
||||||
|
|
||||||
Please see [Changelog](CHANGELOG.md) for a human readable list of changes.
|
Please see [Changelog](CHANGELOG.md) for a human readable list of changes.
|
||||||
|
|
||||||
|
54
gui/main.cpp
54
gui/main.cpp
@ -23,25 +23,51 @@ void enableIpcSandbox()
|
|||||||
qCritical() << "Failed to init policy for sandbox";
|
qCritical() << "Failed to init policy for sandbox";
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
policy->namespace_options = EXILE_UNSHARE_NETWORK | EXILE_UNSHARE_USER;
|
policy->namespace_options = EXILE_UNSHARE_USER | EXILE_UNSHARE_MOUNT | EXILE_UNSHARE_NETWORK;
|
||||||
policy->no_new_privs = 1;
|
policy->no_new_privs = 1;
|
||||||
policy->drop_caps = 1;
|
policy->drop_caps = 1;
|
||||||
policy->vow_promises =
|
policy->vow_promises = exile_vows_from_str("thread cpath rpath unix stdio proc error");
|
||||||
exile_vows_from_str("thread cpath wpath rpath unix stdio prot_exec proc shm fsnotify ioctl error");
|
policy->mount_path_policies_to_chroot = 1;
|
||||||
|
|
||||||
QString ipcSocketPath = Common::ipcSocketPath();
|
QString ipcSocketPath = Common::ipcSocketPath();
|
||||||
QFileInfo info{ipcSocketPath};
|
QFileInfo info{ipcSocketPath};
|
||||||
QString ipcSocketPathDir = info.absolutePath();
|
QString ipcSocketPathDir = info.absolutePath();
|
||||||
std::string stdIpcSocketPath = ipcSocketPathDir.toStdString();
|
std::string stdIpcSocketPath = ipcSocketPathDir.toStdString();
|
||||||
|
|
||||||
exile_append_path_policies(policy, EXILE_FS_ALLOW_ALL_READ, "/");
|
/* we only need the 'server' side of the 'unix' vow (for unix sockets)'. The process
|
||||||
exile_append_path_policies(policy, EXILE_FS_ALLOW_ALL_READ | EXILE_FS_ALLOW_ALL_WRITE, stdIpcSocketPath.c_str());
|
* has no business to connect anywhere.
|
||||||
|
*
|
||||||
|
* Maybe this case should be handled by exile at some point, but for now deal with it here */
|
||||||
|
exile_append_syscall_policy(policy, EXILE_SYS(connect), EXILE_SYSCALL_DENY_RET_ERROR, NULL, 0);
|
||||||
|
|
||||||
|
/* ALLOW_EXEC is needed for fallback, not in landlock mode. It does not allow executing anything though here
|
||||||
|
* due to the vows */
|
||||||
|
exile_append_path_policies(policy, EXILE_FS_ALLOW_ALL_READ | EXILE_FS_ALLOW_EXEC, "/");
|
||||||
|
exile_append_path_policies(policy, EXILE_FS_ALLOW_ALL_READ | EXILE_FS_ALLOW_ALL_WRITE | EXILE_FS_ALLOW_EXEC,
|
||||||
|
stdIpcSocketPath.c_str());
|
||||||
int ret = exile_enable_policy(policy);
|
int ret = exile_enable_policy(policy);
|
||||||
if(ret != 0)
|
if(ret != 0)
|
||||||
{
|
{
|
||||||
qDebug() << "Failed to establish sandbox";
|
qDebug() << "Failed to establish sandbox" << Qt::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Arguments are irrelevant for sandbox test, just want to silence analyzer/compiler warnings */
|
||||||
|
ret = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if(ret != -1 || errno != EACCES)
|
||||||
|
{
|
||||||
|
qCritical() << "Sandbox sanity check failed" << Qt::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct sockaddr *addr = {};
|
||||||
|
ret = connect(3, addr, sizeof(*addr));
|
||||||
|
if(ret != -1 || errno != EACCES)
|
||||||
|
{
|
||||||
|
qCritical() << "Sandbox sanity check failed" << Qt::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
exile_free_policy(policy);
|
exile_free_policy(policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,14 +80,21 @@ int main(int argc, char *argv[])
|
|||||||
if(arg == "ipc")
|
if(arg == "ipc")
|
||||||
{
|
{
|
||||||
Common::setupAppInfo();
|
Common::setupAppInfo();
|
||||||
enableIpcSandbox();
|
if(Common::noSandboxModeRequested())
|
||||||
QApplication a(argc, argv);
|
{
|
||||||
|
qInfo() << "Launching with no sandbox!" << Qt::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enableIpcSandbox();
|
||||||
|
}
|
||||||
|
QCoreApplication a(argc, argv);
|
||||||
|
|
||||||
IpcServer *ipcserver = new IpcServer();
|
IpcServer *ipcserver = new IpcServer();
|
||||||
qDebug() << "Launching IPC Server";
|
qDebug() << "Launching IPC Server";
|
||||||
if(!ipcserver->startSpawner(socketPath))
|
if(!ipcserver->startSpawner(socketPath))
|
||||||
{
|
{
|
||||||
qCritical() << "Error failed to spawn";
|
qCritical() << "Error failed to spawn" << Qt::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
qDebug() << "Launched IPC Server";
|
qDebug() << "Launched IPC Server";
|
||||||
@ -109,7 +142,6 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
Common::setupAppInfo();
|
Common::setupAppInfo();
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
parser.addOption({{"s", "no-sandbox"}, "Disable sandboxing"});
|
|
||||||
QStringList appArgs;
|
QStringList appArgs;
|
||||||
for(int i = 0; i < argc; i++)
|
for(int i = 0; i < argc; i++)
|
||||||
{
|
{
|
||||||
@ -117,6 +149,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
parser.parse(appArgs);
|
parser.parse(appArgs);
|
||||||
|
|
||||||
|
QApplication a(argc, argv);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Common::ensureConfigured();
|
Common::ensureConfigured();
|
||||||
@ -127,7 +160,6 @@ int main(int argc, char *argv[])
|
|||||||
QMessageBox::critical(nullptr, "Error", e.message);
|
QMessageBox::critical(nullptr, "Error", e.message);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
QApplication a(argc, argv);
|
|
||||||
a.setWindowIcon(QIcon(":/looqs.svg"));
|
a.setWindowIcon(QIcon(":/looqs.svg"));
|
||||||
QObject::connect(&a, &QApplication::aboutToQuit, &process, &QProcess::kill);
|
QObject::connect(&a, &QApplication::aboutToQuit, &process, &QProcess::kill);
|
||||||
|
|
||||||
|
@ -192,12 +192,6 @@ void MainWindow::connectSignals()
|
|||||||
|
|
||||||
QMessageBox::about(this, "About looqs", html);
|
QMessageBox::about(this, "About looqs", html);
|
||||||
});
|
});
|
||||||
connect(ui->menuOpenConfigInTextEditorAction, &QAction::triggered, this,
|
|
||||||
[this](bool checked)
|
|
||||||
{
|
|
||||||
QSettings setting;
|
|
||||||
QDesktopServices::openUrl(setting.fileName());
|
|
||||||
});
|
|
||||||
connect(ui->menuAboutQtAction, &QAction::triggered, this,
|
connect(ui->menuAboutQtAction, &QAction::triggered, this,
|
||||||
[this](bool checked) { QMessageBox::aboutQt(this, "About Qt"); });
|
[this](bool checked) { QMessageBox::aboutQt(this, "About Qt"); });
|
||||||
connect(ui->menuSyncIndexAction, &QAction::triggered, this, &MainWindow::startIndexSync);
|
connect(ui->menuSyncIndexAction, &QAction::triggered, this, &MainWindow::startIndexSync);
|
||||||
@ -215,6 +209,7 @@ void MainWindow::connectSignals()
|
|||||||
});
|
});
|
||||||
connect(this, &MainWindow::beginIndexSync, indexSyncer, &IndexSyncer::sync);
|
connect(this, &MainWindow::beginIndexSync, indexSyncer, &IndexSyncer::sync);
|
||||||
connect(&this->progressDialog, &QProgressDialog::canceled, indexSyncer, &IndexSyncer::cancel);
|
connect(&this->progressDialog, &QProgressDialog::canceled, indexSyncer, &IndexSyncer::cancel);
|
||||||
|
connect(ui->btnSaveSettings, &QPushButton::clicked, this, &MainWindow::saveSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::startIndexSync()
|
void MainWindow::startIndexSync()
|
||||||
@ -236,6 +231,7 @@ void MainWindow::startIndexSync()
|
|||||||
|
|
||||||
emit beginIndexSync();
|
emit beginIndexSync();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::spinPreviewPageValueChanged(int val)
|
void MainWindow::spinPreviewPageValueChanged(int val)
|
||||||
{
|
{
|
||||||
makePreviews(val);
|
makePreviews(val);
|
||||||
@ -351,6 +347,45 @@ void MainWindow::tabChanged()
|
|||||||
makePreviews(ui->spinPreviewPage->value());
|
makePreviews(ui->spinPreviewPage->value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Settings tab active */
|
||||||
|
if(ui->tabWidget->currentIndex() == 3)
|
||||||
|
{
|
||||||
|
initSettingsTabs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::initSettingsTabs()
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
|
||||||
|
QString pdfViewerCmd = settings.value(SETTINGS_KEY_PDFVIEWER).toString();
|
||||||
|
QString excludedPaths = Common::excludedPaths().join(';');
|
||||||
|
QString mountPaths = Common::mountPaths().join(';');
|
||||||
|
int numPagesPerPreview = settings.value(SETTINGS_KEY_PREVIEWSPERPAGE, 20).toInt();
|
||||||
|
|
||||||
|
ui->txtSettingPdfPreviewerCmd->setText(pdfViewerCmd);
|
||||||
|
ui->txtSettingIgnoredPaths->setText(excludedPaths);
|
||||||
|
ui->txtSettingMountPaths->setText(mountPaths);
|
||||||
|
ui->spinSettingNumerPerPages->setValue(numPagesPerPreview);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::saveSettings()
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
|
||||||
|
QString pdfViewerCmd = ui->txtSettingPdfPreviewerCmd->text();
|
||||||
|
QStringList excludedPaths = ui->txtSettingIgnoredPaths->text().split(';');
|
||||||
|
QStringList mountPaths = ui->txtSettingMountPaths->text().split(';');
|
||||||
|
|
||||||
|
settings.setValue(SETTINGS_KEY_PDFVIEWER, pdfViewerCmd);
|
||||||
|
settings.setValue(SETTINGS_KEY_EXCLUDEDPATHS, excludedPaths);
|
||||||
|
settings.setValue(SETTINGS_KEY_MOUNTPATHS, mountPaths);
|
||||||
|
settings.setValue(SETTINGS_KEY_PREVIEWSPERPAGE, ui->spinSettingNumerPerPages->value());
|
||||||
|
|
||||||
|
settings.sync();
|
||||||
|
|
||||||
|
QProcess::startDetached(qApp->arguments()[0], qApp->arguments().mid(1));
|
||||||
|
qApp->quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::previewReceived(QSharedPointer<PreviewResult> preview, unsigned int previewGeneration)
|
void MainWindow::previewReceived(QSharedPointer<PreviewResult> preview, unsigned int previewGeneration)
|
||||||
@ -389,7 +424,7 @@ void MainWindow::lineEditReturnPressed()
|
|||||||
ui->lblSearchResults->setText("Invalid paranthesis");
|
ui->lblSearchResults->setText("Invalid paranthesis");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(indexerTabActive())
|
if(ui->tabWidget->currentIndex() > 1)
|
||||||
{
|
{
|
||||||
ui->tabWidget->setCurrentIndex(0);
|
ui->tabWidget->setCurrentIndex(0);
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,7 @@ class MainWindow : public QMainWindow
|
|||||||
void openDocument(QString path, int num);
|
void openDocument(QString path, int num);
|
||||||
void openFile(QString path);
|
void openFile(QString path);
|
||||||
unsigned int currentPreviewGeneration = 1;
|
unsigned int currentPreviewGeneration = 1;
|
||||||
|
void initSettingsTabs();
|
||||||
private slots:
|
private slots:
|
||||||
void lineEditReturnPressed();
|
void lineEditReturnPressed();
|
||||||
void treeSearchItemActivated(QTreeWidgetItem *item, int i);
|
void treeSearchItemActivated(QTreeWidgetItem *item, int i);
|
||||||
@ -73,6 +74,7 @@ class MainWindow : public QMainWindow
|
|||||||
void finishIndexing();
|
void finishIndexing();
|
||||||
void addPathToIndex();
|
void addPathToIndex();
|
||||||
void startIndexSync();
|
void startIndexSync();
|
||||||
|
void saveSettings();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void startIpcPreviews(RenderConfig config, const QVector<RenderTarget> &targets);
|
void startIpcPreviews(RenderConfig config, const QVector<RenderTarget> &targets);
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1221</width>
|
<width>1280</width>
|
||||||
<height>709</height>
|
<height>736</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -27,7 +27,7 @@
|
|||||||
<enum>QTabWidget::South</enum>
|
<enum>QTabWidget::South</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="resultsTab">
|
<widget class="QWidget" name="resultsTab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
@ -81,8 +81,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1185</width>
|
<width>1244</width>
|
||||||
<height>419</height>
|
<height>446</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout"/>
|
<layout class="QHBoxLayout" name="horizontalLayout"/>
|
||||||
@ -344,6 +344,126 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QWidget" name="settingsTab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Settings</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupPdfSettings">
|
||||||
|
<property name="title">
|
||||||
|
<string>PDF Viewer</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Command to open PDF pages in (%f = file path; %p = page number)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="txtSettingPdfPreviewerCmd"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupMountPaths">
|
||||||
|
<property name="title">
|
||||||
|
<string>Mount paths</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lblMountPaths">
|
||||||
|
<property name="text">
|
||||||
|
<string>Path prefixes of files that should not be removed during sync, even if they cannot be accessed (e . g. files indexed on external disks) . Separated by ;</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="txtSettingMountPaths"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Ignored paths</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Path prefixes that should always be ignored during indexing (will be applied before the ignore patterns). Separated by ;</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="txtSettingIgnoredPaths"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="Misc">
|
||||||
|
<property name="title">
|
||||||
|
<string>Misc</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Max number of previews per 'page' in 'Previews' tab: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="spinSettingNumerPerPages"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnSaveSettings">
|
||||||
|
<property name="text">
|
||||||
|
<string>Save settings and restart</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -368,7 +488,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1221</width>
|
<width>1280</width>
|
||||||
<height>35</height>
|
<height>35</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -376,7 +496,6 @@
|
|||||||
<property name="title">
|
<property name="title">
|
||||||
<string>looqs</string>
|
<string>looqs</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="menuOpenConfigInTextEditorAction"/>
|
|
||||||
<addaction name="menuSyncIndexAction"/>
|
<addaction name="menuSyncIndexAction"/>
|
||||||
<addaction name="menuAboutAction"/>
|
<addaction name="menuAboutAction"/>
|
||||||
<addaction name="menuAboutQtAction"/>
|
<addaction name="menuAboutQtAction"/>
|
||||||
@ -389,11 +508,6 @@
|
|||||||
<string>About</string>
|
<string>About</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="menuOpenConfigInTextEditorAction">
|
|
||||||
<property name="text">
|
|
||||||
<string>Open config in text editor</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="menuAboutQtAction">
|
<action name="menuAboutQtAction">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>About Qt</string>
|
<string>About Qt</string>
|
||||||
|
@ -14,13 +14,6 @@
|
|||||||
#include "databasefactory.h"
|
#include "databasefactory.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
||||||
#define SETTINGS_KEY_DBPATH "dbpath"
|
|
||||||
#define SETTINGS_KEY_FIRSTRUN "firstrun"
|
|
||||||
#define SETTINGS_KEY_IPCSOCKETPATH "ipcsocketpath"
|
|
||||||
#define SETTINGS_KEY_PDFVIEWER "pdfviewer"
|
|
||||||
#define SETTINGS_KEY_EXCLUDEDPATHS "excludedpaths"
|
|
||||||
#define SETTINGS_KEY_MOUNTPATHS "mountpaths"
|
|
||||||
|
|
||||||
inline void initResources()
|
inline void initResources()
|
||||||
{
|
{
|
||||||
Q_INIT_RESOURCE(migrations);
|
Q_INIT_RESOURCE(migrations);
|
||||||
@ -91,10 +84,10 @@ void Common::setPdfViewer()
|
|||||||
void Common::ensureConfigured()
|
void Common::ensureConfigured()
|
||||||
{
|
{
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
QVariant firstRun = settings.value(SETTINGS_KEY_FIRSTRUN);
|
QString dbpath = databasePath();
|
||||||
if(!firstRun.isValid())
|
if(dbpath == "")
|
||||||
{
|
{
|
||||||
QString dbpath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
|
dbpath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
|
||||||
QDir dir;
|
QDir dir;
|
||||||
if(!dir.exists(dbpath))
|
if(!dir.exists(dbpath))
|
||||||
{
|
{
|
||||||
@ -104,38 +97,34 @@ void Common::ensureConfigured()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dbpath += "/looqs.sqlite";
|
dbpath += "/looqs.sqlite";
|
||||||
|
}
|
||||||
|
if(!QFile::exists(dbpath))
|
||||||
|
{
|
||||||
if(!initSqliteDatabase(dbpath))
|
if(!initSqliteDatabase(dbpath))
|
||||||
{
|
{
|
||||||
throw LooqsGeneralException("Failed to initialize sqlite database");
|
throw LooqsGeneralException("Failed to initialize sqlite database");
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.setValue(SETTINGS_KEY_FIRSTRUN, false);
|
|
||||||
settings.setValue(SETTINGS_KEY_DBPATH, dbpath);
|
settings.setValue(SETTINGS_KEY_DBPATH, dbpath);
|
||||||
setPdfViewer();
|
|
||||||
}
|
}
|
||||||
else
|
DatabaseFactory factory{dbpath};
|
||||||
|
auto db = factory.forCurrentThread();
|
||||||
|
DBMigrator migrator{db};
|
||||||
|
if(migrator.migrationNeeded())
|
||||||
{
|
{
|
||||||
|
QFile out;
|
||||||
QString dbpath = databasePath();
|
out.open(stderr, QIODevice::WriteOnly);
|
||||||
if(!QFile::exists(dbpath))
|
Logger migrationLogger{&out};
|
||||||
{
|
migrationLogger << "Database is being upgraded, please be patient..." << Qt::endl;
|
||||||
throw LooqsGeneralException("Database " + dbpath + " was not found");
|
QObject::connect(&migrator, &DBMigrator::migrationDone,
|
||||||
}
|
[&migrationLogger](uint32_t migration)
|
||||||
DatabaseFactory factory{dbpath};
|
{ migrationLogger << "Progress: Successfully migrated to: " << migration << Qt::endl; });
|
||||||
auto db = factory.forCurrentThread();
|
migrator.performMigrations();
|
||||||
DBMigrator migrator{db};
|
migrationLogger << "Database upgraded successfully" << Qt::endl;
|
||||||
if(migrator.migrationNeeded())
|
}
|
||||||
{
|
QVariant pdfViewer = settings.value(SETTINGS_KEY_PDFVIEWER);
|
||||||
QFile out;
|
if(!pdfViewer.isValid())
|
||||||
out.open(stderr, QIODevice::WriteOnly);
|
{
|
||||||
Logger migrationLogger{&out};
|
setPdfViewer();
|
||||||
migrationLogger << "Database is being upgraded, please be patient..." << Qt::endl;
|
|
||||||
QObject::connect(&migrator, &DBMigrator::migrationDone,
|
|
||||||
[&migrationLogger](uint32_t migration)
|
|
||||||
{ migrationLogger << "Progress: Successfully migrated to: " << migration << Qt::endl; });
|
|
||||||
migrator.performMigrations();
|
|
||||||
migrationLogger << "Database upgraded successfully" << Qt::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,6 +146,16 @@ QString Common::databasePath()
|
|||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Common::noSandboxModeRequested()
|
||||||
|
{
|
||||||
|
QString env = getenv("LOOQS_DISABLE_SANDBOX");
|
||||||
|
if(env == "1")
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
QString Common::ipcSocketPath()
|
QString Common::ipcSocketPath()
|
||||||
{
|
{
|
||||||
return "/tmp/.looqs/looqs-ipc-socket";
|
return "/tmp/.looqs/looqs-ipc-socket";
|
||||||
@ -166,19 +165,18 @@ QString Common::ipcSocketPath()
|
|||||||
// return settings.value(SETTINGS_KEY_IPCSOCKETPATH, "/tmp/.looqs/looqs-ipc-socket").toString();
|
// return settings.value(SETTINGS_KEY_IPCSOCKETPATH, "/tmp/.looqs/looqs-ipc-socket").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
static QStringList excludedPaths = {"/proc", "/sys", "/dev", "/tmp", "/var/run", "/run"};
|
|
||||||
|
|
||||||
QStringList Common::excludedPaths()
|
QStringList Common::excludedPaths()
|
||||||
{
|
{
|
||||||
static int ran = false;
|
static int ran = false;
|
||||||
|
static QStringList excludedPaths;
|
||||||
if(!ran)
|
if(!ran)
|
||||||
{
|
{
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
QStringList userExcludedPaths = settings.value(SETTINGS_KEY_EXCLUDEDPATHS).toStringList();
|
QStringList defaults{"/proc", "/sys", "/dev", "/tmp", "/var/run", "/run"};
|
||||||
|
excludedPaths = settings.value(SETTINGS_KEY_EXCLUDEDPATHS, defaults).toStringList();
|
||||||
ran = true;
|
ran = true;
|
||||||
::excludedPaths.append(userExcludedPaths);
|
|
||||||
}
|
}
|
||||||
return ::excludedPaths;
|
return excludedPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList Common::mountPaths()
|
QStringList Common::mountPaths()
|
||||||
|
@ -2,6 +2,14 @@
|
|||||||
#define COMMON_H
|
#define COMMON_H
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
#define SETTINGS_KEY_DBPATH "dbpath"
|
||||||
|
#define SETTINGS_KEY_IPCSOCKETPATH "ipcsocketpath"
|
||||||
|
#define SETTINGS_KEY_PDFVIEWER "pdfviewer"
|
||||||
|
#define SETTINGS_KEY_EXCLUDEDPATHS "excludedpaths"
|
||||||
|
#define SETTINGS_KEY_MOUNTPATHS "mountpaths"
|
||||||
|
#define SETTINGS_KEY_PREVIEWSPERPAGE "previewsPerPage"
|
||||||
|
|
||||||
namespace Common
|
namespace Common
|
||||||
{
|
{
|
||||||
void setupAppInfo();
|
void setupAppInfo();
|
||||||
@ -15,6 +23,7 @@ QStringList excludedPaths();
|
|||||||
QStringList mountPaths();
|
QStringList mountPaths();
|
||||||
bool isTextFile(QFileInfo fileInfo);
|
bool isTextFile(QFileInfo fileInfo);
|
||||||
bool isMountPath(QString path);
|
bool isMountPath(QString path);
|
||||||
|
bool noSandboxModeRequested();
|
||||||
QString versionText();
|
QString versionText();
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
#endif
|
#endif
|
||||||
|
@ -19,7 +19,21 @@ void Indexer::beginIndexing()
|
|||||||
QVector<QString> dirs;
|
QVector<QString> dirs;
|
||||||
|
|
||||||
WildcardMatcher wildcardMatcher;
|
WildcardMatcher wildcardMatcher;
|
||||||
wildcardMatcher.setPatterns(this->ignorePattern);
|
|
||||||
|
QStringList ignoreList = this->ignorePattern;
|
||||||
|
|
||||||
|
for(QString &excludedPath : Common::excludedPaths())
|
||||||
|
{
|
||||||
|
QString pattern = excludedPath;
|
||||||
|
if(!pattern.endsWith("/"))
|
||||||
|
{
|
||||||
|
pattern += "/";
|
||||||
|
}
|
||||||
|
pattern += "*";
|
||||||
|
ignoreList.append(excludedPath);
|
||||||
|
}
|
||||||
|
ignoreList.append(this->ignorePattern);
|
||||||
|
wildcardMatcher.setPatterns(ignoreList);
|
||||||
for(QString &path : this->pathsToScan)
|
for(QString &path : this->pathsToScan)
|
||||||
{
|
{
|
||||||
if(wildcardMatcher.match(path))
|
if(wildcardMatcher.match(path))
|
||||||
@ -40,7 +54,7 @@ void Indexer::beginIndexing()
|
|||||||
if(!dirs.empty())
|
if(!dirs.empty())
|
||||||
{
|
{
|
||||||
this->dirScanner->setPaths(dirs);
|
this->dirScanner->setPaths(dirs);
|
||||||
this->dirScanner->setIgnorePatterns(this->ignorePattern);
|
this->dirScanner->setIgnorePatterns(ignoreList);
|
||||||
|
|
||||||
this->dirScanner->scan();
|
this->dirScanner->scan();
|
||||||
}
|
}
|
||||||
|
@ -27,10 +27,15 @@ static QMap<QString, Processor *> processors{
|
|||||||
|
|
||||||
void SandboxedProcessor::enableSandbox(QString readablePath)
|
void SandboxedProcessor::enableSandbox(QString readablePath)
|
||||||
{
|
{
|
||||||
|
if(Common::noSandboxModeRequested())
|
||||||
|
{
|
||||||
|
qInfo() << "Sandbox is disabled!" << Qt::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
struct exile_policy *policy = exile_init_policy();
|
struct exile_policy *policy = exile_init_policy();
|
||||||
if(policy == NULL)
|
if(policy == NULL)
|
||||||
{
|
{
|
||||||
qCritical() << "Could not init exile";
|
qCritical() << "Could not init exile" << Qt::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
policy->namespace_options = EXILE_UNSHARE_NETWORK | EXILE_UNSHARE_USER;
|
policy->namespace_options = EXILE_UNSHARE_NETWORK | EXILE_UNSHARE_USER;
|
||||||
@ -38,6 +43,8 @@ void SandboxedProcessor::enableSandbox(QString readablePath)
|
|||||||
std::string readablePathLocation;
|
std::string readablePathLocation;
|
||||||
if(!readablePath.isEmpty())
|
if(!readablePath.isEmpty())
|
||||||
{
|
{
|
||||||
|
policy->namespace_options |= EXILE_UNSHARE_MOUNT;
|
||||||
|
policy->mount_path_policies_to_chroot = 1;
|
||||||
readablePathLocation = readablePath.toStdString();
|
readablePathLocation = readablePath.toStdString();
|
||||||
if(exile_append_path_policies(policy, EXILE_FS_ALLOW_ALL_READ, readablePathLocation.c_str()) != 0)
|
if(exile_append_path_policies(policy, EXILE_FS_ALLOW_ALL_READ, readablePathLocation.c_str()) != 0)
|
||||||
{
|
{
|
||||||
|
Submodule submodules/exile.h updated: 42d44b0cc1...8f38dc4480
Reference in New Issue
Block a user