Commit 78c76ed1 authored by Volker Krause's avatar Volker Krause
Browse files

Unify local file URL handling

This needs special attention due to Android's content: URLs.
parent f6cb7404
......@@ -161,7 +161,7 @@ private Q_SLOTS:
QTemporaryFile tmp;
QVERIFY(tmp.open());
tmp.close();
appController.exportToFile(tmp.fileName());
appController.exportToFile(QUrl::fromLocalFile(tmp.fileName()));
QCOMPARE(infoSpy.size(), 3);
KItinerary::File f(tmp.fileName());
......
......@@ -9,6 +9,7 @@ target_sources(itinerary PRIVATE
applicationcontroller.cpp
documentmanager.cpp
favoritelocationmodel.cpp
filehelper.cpp
gpxexport.cpp
healthcertificatemanager.cpp
importexport.cpp
......
......@@ -7,6 +7,7 @@
#include "applicationcontroller.h"
#include "documentmanager.h"
#include "favoritelocationmodel.h"
#include "filehelper.h"
#include "gpxexport.h"
#include "healthcertificatemanager.h"
#include "importexport.h"
......@@ -282,7 +283,7 @@ void ApplicationController::importFromUrl(const QUrl &url)
}
qCDebug(Log) << url;
if (url.isLocalFile() || url.scheme() == QLatin1String("content")) {
if (FileHelper::isLocalFile(url)) {
importLocalFile(url);
return;
}
......@@ -317,7 +318,7 @@ void ApplicationController::importLocalFile(const QUrl &url)
return;
}
QFile f(url.isLocalFile() ? url.toLocalFile() : url.toString());
QFile f(FileHelper::toLocalFile(url));
if (!f.open(QFile::ReadOnly)) {
qCWarning(Log) << "Failed to open" << f.fileName() << f.errorString();
Q_EMIT infoMessage(i18n("Import failed: %1", f.errorString()));
......@@ -334,7 +335,7 @@ void ApplicationController::importLocalFile(const QUrl &url)
m_pkPassMgr->importPass(url);
} else if (url.fileName().endsWith(QLatin1String(".itinerary"), Qt::CaseInsensitive)) {
importBundle(url);
} else if (strncmp(head.constData(), "PK\x03\x04", 4) == 0) {
} else if (FileHelper::hasZipHeader(head)) {
if (m_pkPassMgr->importPass(url).isEmpty()) {
importBundle(url);
}
......@@ -373,7 +374,7 @@ void ApplicationController::importData(const QByteArray &data)
if (data.size() < 4) {
return;
}
if (strncmp(data.constData(), "PK\x03\x04", 4) == 0) {
if (FileHelper::hasZipHeader(data)) {
if (m_pkPassMgr->importPassFromData(data).isEmpty()) {
importBundle(data);
}
......@@ -408,14 +409,14 @@ bool ApplicationController::hasClipboardContent() const
}
void ApplicationController::exportToFile(const QString &filePath)
void ApplicationController::exportToFile(const QUrl &url)
{
qCDebug(Log) << filePath;
if (filePath.isEmpty()) {
if (url.isEmpty()) {
return;
}
File f(QUrl(filePath).isLocalFile() ? QUrl(filePath).toLocalFile() : filePath);
qCDebug(Log) << url;
File f(FileHelper::toLocalFile(url));
if (!f.open(File::Write)) {
qCWarning(Log) << f.errorString();
Q_EMIT infoMessage(i18n("Export failed: %1", f.errorString()));
......@@ -434,13 +435,13 @@ void ApplicationController::exportToFile(const QString &filePath)
Q_EMIT infoMessage(i18n("Export completed."));
}
void ApplicationController::exportTripToGpx(const QString &tripGroupId, const QString &filePath)
void ApplicationController::exportTripToGpx(const QString &tripGroupId, const QUrl &url)
{
if (filePath.isEmpty()) {
if (url.isEmpty()) {
return;
}
QFile f(QUrl(filePath).isLocalFile() ? QUrl(filePath).toLocalFile() : filePath);
QFile f(FileHelper::toLocalFile(url));
if (!f.open(QFile::WriteOnly)) {
qCWarning(Log) << f.errorString() << f.fileName();
Q_EMIT infoMessage(i18n("Export failed: %1", f.errorString()));
......@@ -461,7 +462,7 @@ void ApplicationController::exportTripToGpx(const QString &tripGroupId, const QS
void ApplicationController::importBundle(const QUrl &url)
{
KItinerary::File f(url.isLocalFile() ? url.toLocalFile() : url.toString());
KItinerary::File f(FileHelper::toLocalFile(url));
if (!f.open(File::Read)) {
qCWarning(Log) << "Failed to open bundle file:" << url << f.errorString();
Q_EMIT infoMessage(i18n("Import failed: %1", f.errorString()));
......@@ -572,11 +573,11 @@ void ApplicationController::addDocument(const QString &batchId, const QUrl &url)
docInfo.setName(KAndroidExtras::ContentResolver::fileName(url));
#else
QMimeDatabase db;
docInfo.setEncodingFormat(db.mimeTypeForFile(url.isLocalFile() ? url.toLocalFile() : url.toString()).name());
docInfo.setEncodingFormat(db.mimeTypeForFile(FileHelper::toLocalFile(url)).name());
docInfo.setName(url.fileName());
#endif
m_docMgr->addDocument(docId, docInfo, url.isLocalFile() ? url.toLocalFile() : url.toString());
m_docMgr->addDocument(docId, docInfo, FileHelper::toLocalFile(url));
const auto resIds = m_resMgr->reservationsForBatch(batchId);
for (const auto &resId : resIds) {
......
......@@ -59,14 +59,9 @@ public:
static ApplicationController* instance();
bool hasClipboardContent() const;
void importBundle(const QUrl &url);
void importBundle(const QByteArray &data);
// data export
Q_INVOKABLE void exportToFile(const QString &filePath);
Q_INVOKABLE void exportTripToGpx(const QString &tripGroupId, const QString &filePath);
Q_INVOKABLE void exportToFile(const QUrl &url);
Q_INVOKABLE void exportTripToGpx(const QString &tripGroupId, const QUrl &url);
// document attaching
Q_INVOKABLE void addDocument(const QString &batchId, const QUrl &url);
......@@ -85,7 +80,11 @@ Q_SIGNALS:
void infoMessage(const QString &msg);
private:
bool hasClipboardContent() const;
void importLocalFile(const QUrl &url);
void importBundle(const QUrl &url);
void importBundle(const QByteArray &data);
void importBundle(KItinerary::File *file);
QVector<QString> importReservationOrHealthCertificate(const QByteArray &data, const QString &fileName = {});
void importHealthCertificateRecursive(const KItinerary::ExtractorDocumentNode &node);
......
/*
SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "filehelper.h"
#include <QString>
#include <QUrl>
#include <cstring>
bool FileHelper::isLocalFile(const QUrl &url)
{
return url.isLocalFile() || url.scheme() == QLatin1String("content");
}
QString FileHelper::toLocalFile(const QUrl &url)
{
return url.isLocalFile() ? url.toLocalFile() : url.toString();
}
bool FileHelper::hasZipHeader(const QByteArray &data)
{
return data.size() >= 4 && std::strncmp(data.constData(), "PK\x03\x04", 4) == 0;
}
/*
SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef FILEHELPER_H
#define FILEHELPER_H
class QByteArray;
class QString;
class QUrl;
/** File related helper methods. */
namespace FileHelper
{
/** Returns whether @p url is a file that can be read by QFile directly without downloading.
* @note This differs from QUrl::isLocalFile in also supporting Android content: URLs.
*/
bool isLocalFile(const QUrl &url);
/** Returns a path for @p url that QFile can work with.
* @note This differs from QUrl::toLocalFile in also supporting Android content: URLs.
*/
QString toLocalFile(const QUrl &url);
/** Checks whether @p data starts with the magic header of a ZIP file. */
bool hasZipHeader(const QByteArray &data);
}
#endif // FILEHELPER_H
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment