From 2d22005915513f12db829331adf7871302514d1a Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Mon, 17 Nov 2025 13:16:23 +0200 Subject: [PATCH] Handle document extension signle place and handle asics IB-8624 Signed-off-by: Raul Metsma --- client/CryptoDoc.cpp | 6 +-- client/DigiDoc.cpp | 3 +- client/MainWindow.cpp | 48 +++----------------- client/MainWindow.h | 1 - client/dialogs/FileDialog.cpp | 82 ++++++++++++++++++++--------------- client/dialogs/FileDialog.h | 6 +-- client/translations/en.ts | 8 ++-- client/translations/et.ts | 8 ++-- client/translations/ru.ts | 8 ++-- 9 files changed, 71 insertions(+), 99 deletions(-) diff --git a/client/CryptoDoc.cpp b/client/CryptoDoc.cpp index 3e59d9ab4..585ffd4c0 100644 --- a/client/CryptoDoc.cpp +++ b/client/CryptoDoc.cpp @@ -122,7 +122,8 @@ bool CDocumentModel::addFile(const QString &file, const QString &mime) } auto data = std::make_unique(file); - data->open(QFile::ReadOnly); + if(!data->open(QFile::ReadOnly)) + return false; d->cdoc->files.push_back({ QFileInfo(file).fileName(), QStringLiteral("D%1").arg(d->cdoc->files.size()), @@ -209,12 +210,11 @@ QString CDocumentModel::save(int row, const QString &path) const if(d->isEncrypted) return {}; - int zone = FileDialog::fileZone(d->fileName); QString fileName = copy(row, path); QFileInfo f(fileName); if(!f.exists()) return {}; - FileDialog::setFileZone(fileName, zone); + FileDialog::setFileZone(fileName, d->fileName); return fileName; } diff --git a/client/DigiDoc.cpp b/client/DigiDoc.cpp index 1aa9d3ff0..9f30a5aa1 100644 --- a/client/DigiDoc.cpp +++ b/client/DigiDoc.cpp @@ -390,9 +390,8 @@ QString SDocumentModel::save(int row, const QString &path) const return {}; QFile::remove( path ); - int zone = FileDialog::fileZone(doc->fileName()); doc->b->dataFiles().at(size_t(row))->saveAs(path.toStdString()); - FileDialog::setFileZone(path, zone); + FileDialog::setFileZone(path, doc->fileName()); return path; } diff --git a/client/MainWindow.cpp b/client/MainWindow.cpp index 4deef88f8..e50436675 100644 --- a/client/MainWindow.cpp +++ b/client/MainWindow.cpp @@ -420,14 +420,14 @@ void MainWindow::convertToCDoc() void MainWindow::moveCryptoContainer() { - QString to = selectFile(tr("Move file"), cryptoDoc->fileName(), true); + QString to = FileDialog::getSaveFileName(this, tr("Move file"), cryptoDoc->fileName()); if(!to.isNull() && cryptoDoc->move(to)) emit ui->cryptoContainerPage->moved(to); } void MainWindow::moveSignatureContainer() { - QString to = selectFile(tr("Move file"), digiDoc->fileName(), true); + QString to = FileDialog::getSaveFileName(this, tr("Move file"), digiDoc->fileName()); if(!to.isNull() && digiDoc->move(to)) emit ui->signContainerPage->moved(to); } @@ -463,7 +463,7 @@ void MainWindow::onCryptoAction(int action, const QString &/*id*/, const QString { if(!cryptoDoc) break; - QString target = selectFile(tr("Save file"), cryptoDoc->fileName(), true); + QString target = FileDialog::getSaveFileName(this, tr("Save file"), cryptoDoc->fileName()); if(target.isEmpty()) break; if( !FileDialog::fileIsWritable(target)) @@ -471,7 +471,7 @@ void MainWindow::onCryptoAction(int action, const QString &/*id*/, const QString auto *dlg = new WarningDialog(tr("Cannot alter container %1. Save different location?").arg(target), this); dlg->addButton(WarningDialog::YES, QMessageBox::Yes); if(dlg->exec() == QMessageBox::Yes) { - QString file = selectFile(tr("Save file"), target, true); + QString file = FileDialog::getSaveFileName(this, tr("Save file"), target); if(!file.isEmpty()) cryptoDoc->saveCopy(file); } @@ -579,7 +579,7 @@ void MainWindow::openFiles(const QStringList &files, bool addFile, bool forceCre void MainWindow::openContainer(bool signature) { - QString filter = QFileDialog::tr("All Files (*)") + QStringLiteral(";;") + tr("Documents (%1)"); + QString filter = QFileDialog::tr("All Files (*)") + QStringLiteral(";;") + FileDialog::tr("Documents (%1)"); if(signature) filter = filter.arg(QStringLiteral("*.bdoc *.ddoc *.asice *.sce *.asics *.scs *.edoc *.adoc%1") .arg(Application::confValue(Application::SiVaUrl).toString().isEmpty() ? QLatin1String() : QLatin1String(" *.pdf"))); @@ -631,7 +631,7 @@ bool MainWindow::save(bool saveAs) QString target = digiDoc->fileName(); if(saveAs) - target = selectFile(tr("Save file"), target, true); + target = FileDialog::getSaveFileName(this, tr("Save file"), target); if(target.isEmpty()) return false; @@ -640,47 +640,13 @@ bool MainWindow::save(bool saveAs) auto *dlg = new WarningDialog(tr("Cannot alter container %1. Save different location?").arg(target), this); dlg->addButton(WarningDialog::YES, QMessageBox::Yes); if(dlg->exec() == QMessageBox::Yes) { - if(QString file = selectFile(tr("Save file"), target, true); !file.isEmpty()) + if(QString file = FileDialog::getSaveFileName(this, tr("Save file"), target); !file.isEmpty()) return saveAs ? digiDoc->saveAs(file) : digiDoc->save(file); } } return saveAs ? digiDoc->saveAs(target) : digiDoc->save(target); } -QString MainWindow::selectFile( const QString &title, const QString &filename, bool fixedExt ) -{ - static const QString adoc = tr("Documents (%1)").arg(QLatin1String("*.adoc")); - static const QString bdoc = tr("Documents (%1)").arg(QLatin1String("*.bdoc")); - static const QString cdoc = tr("Documents (%1)").arg(QLatin1String("*.cdoc")); - static const QString cdoc2 = tr("Documents (%1)").arg(QLatin1String("*.cdoc2")); - static const QString edoc = tr("Documents (%1)").arg(QLatin1String("*.edoc")); - static const QString asic = tr("Documents (%1)").arg(QLatin1String("*.asice *.sce")); - const QString ext = QFileInfo( filename ).suffix().toLower(); - QStringList exts; - QString active; - if( fixedExt ) - { - if(ext == QLatin1String("bdoc")) exts.append(bdoc); - if(ext == QLatin1String("cdoc")) exts.append(cdoc); - if(ext == QLatin1String("cdoc2")) exts.append(cdoc2); - if(ext == QLatin1String("asice") || ext == QLatin1String("sce")) exts.append(asic); - if(ext == QLatin1String("edoc")) exts.append(edoc); - if(ext == QLatin1String("adoc")) exts.append(adoc); - } - else - { - exts = QStringList{ bdoc, asic, edoc, adoc }; - if(ext == QLatin1String("bdoc")) active = bdoc; - if(ext == QLatin1String("cdoc")) active = cdoc; - if(ext == QLatin1String("cdoc2")) active = cdoc2; - if(ext == QLatin1String("asice") || ext == QLatin1String("sce")) active = asic; - if(ext == QLatin1String("edoc")) active = edoc; - if(ext == QLatin1String("adoc")) active = adoc; - } - - return FileDialog::getSaveFileName( this, title, filename, exts.join(QLatin1String(";;")), &active ); -} - void MainWindow::selectPage(Pages page) { auto *btn = page < CryptoIntro ? ui->signature : (page == MyEid ? ui->myEid : ui->crypto); diff --git a/client/MainWindow.h b/client/MainWindow.h index a2ee3110c..323ea7af2 100644 --- a/client/MainWindow.h +++ b/client/MainWindow.h @@ -79,7 +79,6 @@ class MainWindow final : public QWidget void removeSignature(int index); void removeSignatureFile(int index); bool save(bool saveAs = false); - QString selectFile( const QString &title, const QString &filename, bool fixedExt ); template void sign(F &&sign); bool validateFiles(const QString &container, const QStringList &files); diff --git a/client/dialogs/FileDialog.cpp b/client/dialogs/FileDialog.cpp index bab6851e3..201bea029 100644 --- a/client/dialogs/FileDialog.cpp +++ b/client/dialogs/FileDialog.cpp @@ -19,7 +19,6 @@ #include "FileDialog.h" -#include "Application.h" #include "Settings.h" #include "dialogs/WarningDialog.h" @@ -47,6 +46,8 @@ class CPtr inline operator T*() const { return d; } inline T** operator&() { return &d; } }; +#elif defined(Q_OS_MAC) +#include #endif #include @@ -61,7 +62,7 @@ QString FileDialog::createNewFileName(const QString &file, bool signature, QWidg const QFileInfo f(normalized(file)); QString dir = defaultDir.isEmpty() ? f.absolutePath() : defaultDir; QString fileName = QDir::toNativeSeparators(dir + QDir::separator() + f.completeBaseName() + extension); -#ifndef Q_OS_OSX +#ifndef Q_OS_MACOS // macOS App Sandbox restricts the rights of the application to write to the filesystem outside of // app sandbox; user must explicitly give permission to write data to the specific folders. if(!QFile::exists(fileName)) @@ -107,23 +108,6 @@ bool FileDialog::fileIsWritable( const QString &filename ) return result; } -int FileDialog::fileZone(const QString &path) -{ -#ifdef Q_OS_WIN - CPtr spzi; - CPtr spf; - DWORD dwZone = 0; - if(SUCCEEDED(CoCreateInstance(CLSID_PersistentZoneIdentifier, nullptr, CLSCTX_INPROC, IID_PPV_ARGS(&spzi))) && - SUCCEEDED(spzi->QueryInterface(&spf)) && - SUCCEEDED(spf->Load(LPCWSTR(QDir::toNativeSeparators(path).utf16()), STGM_READ)) && - SUCCEEDED(spzi->GetId(&dwZone))) - return int(dwZone); -#else - Q_UNUSED(path) -#endif - return -1; -} - bool FileDialog::isSignedPDF(const QString &path) { if(!path.endsWith(QLatin1String("pdf"), Qt::CaseInsensitive)) @@ -136,25 +120,33 @@ bool FileDialog::isSignedPDF(const QString &path) return std::any_of(list.begin(), list.end(), [&blob](const char *token) { return blob.indexOf(token) > 0; }); } -void FileDialog::setFileZone(const QString &path, int zone) +void FileDialog::setFileZone(const QString &target, const QString &source) { - if(zone < 0) - return; #ifdef Q_OS_WIN CPtr spzi; CPtr spf; - if(SUCCEEDED(CoCreateInstance(CLSID_PersistentZoneIdentifier, nullptr, CLSCTX_INPROC, IID_PPV_ARGS(&spzi))) && - SUCCEEDED(spzi->SetId(zone)) && - SUCCEEDED(spzi->QueryInterface(&spf))) - spf->Save(LPCWSTR(QDir::toNativeSeparators(path).utf16()), TRUE); + if(SUCCEEDED(CoCreateInstance(CLSID_PersistentZoneIdentifier, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&spzi))) && + SUCCEEDED(spzi->QueryInterface(&spf)) && + SUCCEEDED(spf->Load(LPCWSTR(QDir::toNativeSeparators(source).utf16()), STGM_READ))) + spf->Save(LPCWSTR(QDir::toNativeSeparators(target).utf16()), TRUE); +#elif defined(Q_OS_MACOS) + QByteArray p = QFile::encodeName(source); + ssize_t n = getxattr(p.constData(), "com.apple.quarantine", nullptr, 0, 0, 0); + if(n <= 0) + return; + QByteArray value(int(n), Qt::Uninitialized); + n = getxattr(p.constData(), "com.apple.quarantine", value.data(), value.size(), 0, 0); + if(n > 0) + setxattr(QFile::encodeName(target).constData(), "com.apple.quarantine", value.constData(), size_t(n), 0, 0); #else - Q_UNUSED(path) + Q_UNUSED(target) + Q_UNUSED(source) #endif } void FileDialog::setReadOnly(const QString &path, bool readonly) { -#if defined(Q_OS_WIN) +#ifdef Q_OS_WIN ::SetFileAttributesW(LPCWSTR(path.utf16()), readonly ? FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL); #else QFile::setPermissions(path, QFile::Permissions(QFile::Permission::ReadOwner) @@ -164,7 +156,7 @@ void FileDialog::setReadOnly(const QString &path, bool readonly) QString FileDialog::getDir( const QString &dir ) { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS Q_UNUSED(dir) QString path = QSettings().value(QStringLiteral("NSNavLastRootDirectory")).toString(); path.replace('~', QDir::homePath()); @@ -266,14 +258,32 @@ QString FileDialog::getExistingDirectory( QWidget *parent, const QString &captio return result( res ); } -QString FileDialog::getSaveFileName( QWidget *parent, const QString &caption, - const QString &dir, const QString &filter, QString *selectedFilter, Options options ) +QString FileDialog::getSaveFileName(QWidget *parent, const QString &caption, const QString &filename, QString filter) { + if(filename.endsWith(QLatin1String(".adoc"), Qt::CaseInsensitive)) + filter = tr("Documents (%1)").arg(QLatin1String("*.adoc")); + else if(filename.endsWith(QLatin1String(".asice"), Qt::CaseInsensitive) || + filename.endsWith(QLatin1String(".sce"), Qt::CaseInsensitive)) + filter = tr("Documents (%1)").arg(QLatin1String("*.asice *.sce")); + else if(filename.endsWith(QLatin1String(".asics"), Qt::CaseInsensitive) || + filename.endsWith(QLatin1String(".scs"), Qt::CaseInsensitive)) + filter = tr("Documents (%1)").arg(QLatin1String("*.asics *.scs")); + else if(filename.endsWith(QLatin1String(".bdoc"), Qt::CaseInsensitive)) + filter = tr("Documents (%1)").arg(QLatin1String("*.bdoc")); + else if(filename.endsWith(QLatin1String(".cdoc"), Qt::CaseInsensitive)) + filter = tr("Documents (%1)").arg(QLatin1String("*.cdoc")); + else if(filename.endsWith(QLatin1String(".cdoc2"), Qt::CaseInsensitive)) + filter = tr("Documents (%1)").arg(QLatin1String("*.cdoc2")); + else if(filename.endsWith(QLatin1String(".ddoc"), Qt::CaseInsensitive)) + filter = tr("Documents (%1)").arg(QLatin1String("*.ddoc")); + else if(filename.endsWith(QLatin1String(".edoc"), Qt::CaseInsensitive)) + filter = tr("Documents (%1)").arg(QLatin1String("*.edoc")); + else if(filename.endsWith(QLatin1String(".pdf"), Qt::CaseInsensitive)) + filter = tr("Documents (%1)").arg(QLatin1String("*.pdf")); QString file; while( true ) { - file = QFileDialog::getSaveFileName(parent, - caption, normalized(dir), filter, selectedFilter, options); + file = QFileDialog::getSaveFileName(parent, caption, normalized(filename), filter); if( !file.isEmpty() && !fileIsWritable( file ) ) { WarningDialog::show(parent, tr( "You don't have sufficient privileges to write this file into folder %1" ).arg( file )); @@ -301,7 +311,7 @@ QString FileDialog::normalized(const QString &data) QString FileDialog::result( const QString &str ) { -#ifndef Q_OS_OSX +#ifndef Q_OS_MACOS if(!str.isEmpty()) Settings::LAST_PATH = QFileInfo(str).absolutePath(); #else @@ -322,7 +332,7 @@ QString FileDialog::tempPath(const QString &file) { QDir tmp = QDir::temp(); if(!tmp.exists(file)) - return tmp.path() + "/" + file; + return tmp.path() + '/' + file; QFileInfo info(file); int i = 0; while(tmp.exists(QStringLiteral("%1_%2.%3").arg(info.baseName()).arg(i).arg(info.suffix()))) @@ -334,7 +344,7 @@ QString FileDialog::safeName(const QString &file) { QFileInfo info(file); QString filename = info.fileName(); -#if defined(Q_OS_WIN) +#ifdef Q_OS_WIN static const QStringList disabled { "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9" }; diff --git a/client/dialogs/FileDialog.h b/client/dialogs/FileDialog.h index c08dfb793..0de2d4d83 100644 --- a/client/dialogs/FileDialog.h +++ b/client/dialogs/FileDialog.h @@ -36,9 +36,8 @@ class FileDialog : public QFileDialog static QString createNewFileName(const QString &file, bool signature, QWidget *parent); static FileType detect(const QString &filename); static bool fileIsWritable( const QString &filename ); - static int fileZone(const QString &path); static bool isSignedPDF(const QString &path); - static void setFileZone(const QString &path, int zone); + static void setFileZone(const QString &target, const QString &source); static void setReadOnly(const QString &path, bool readonly = true); static QString normalized(const QString &file); static QString safeName(const QString &file); @@ -53,8 +52,7 @@ class FileDialog : public QFileDialog static QString getExistingDirectory(QWidget *parent = nullptr, const QString &caption = {}, const QString &dir = {}, Options options = {}); static QString getSaveFileName(QWidget *parent = nullptr, const QString &caption = {}, - const QString &dir = {}, const QString &filter = {}, - QString *selectedFilter = nullptr, Options options = {}); + const QString &filename = {}, QString filter = {}); private: static QString result( const QString &str ); diff --git a/client/translations/en.ts b/client/translations/en.ts index 7a49523c8..aee071194 100644 --- a/client/translations/en.ts +++ b/client/translations/en.ts @@ -840,6 +840,10 @@ Create %1 Create %1 + + Documents (%1) + Documents (%1) + FileItem @@ -1345,10 +1349,6 @@ ID-Card Cannot alter container %1. Save different location? Cannot alter container %1. Save to different location? - - Documents (%1) - Documents (%1) - Save file Save file diff --git a/client/translations/et.ts b/client/translations/et.ts index 597314778..e44c02d4a 100644 --- a/client/translations/et.ts +++ b/client/translations/et.ts @@ -840,6 +840,10 @@ Create %1 Loo %1 + + Documents (%1) + Dokumendid (%1) + FileItem @@ -1345,10 +1349,6 @@ ID-kaardiga Cannot alter container %1. Save different location? Ümbriku %1 salvestamine ebaõnnestus. Salvestada teise asukohta? - - Documents (%1) - Dokumendid (%1) - Save file Salvesta fail diff --git a/client/translations/ru.ts b/client/translations/ru.ts index 280c7ef25..f1db98303 100644 --- a/client/translations/ru.ts +++ b/client/translations/ru.ts @@ -840,6 +840,10 @@ Create %1 Создайте %1 + + Documents (%1) + Документы (%1) + FileItem @@ -1345,10 +1349,6 @@ ID-картой Cannot alter container %1. Save different location? Сохранение контейнера %1 не удалось. Сохранить в другой каталог? - - Documents (%1) - Документы (%1) - Save file Сохранить файл