diff options
author | Kitsune Ral <Kitsune-Ral@users.sf.net> | 2019-12-13 14:47:26 +0300 |
---|---|---|
committer | Kitsune Ral <Kitsune-Ral@users.sf.net> | 2019-12-13 14:47:26 +0300 |
commit | 04960510df6058b4f25d3c41001a519e9fc5ba4a (patch) | |
tree | 3966a2b5928a29aa1f8615aa8d5a73d227992e8e /lib | |
parent | 646186d802cfe7213146e4a68f8f926e21931b17 (diff) | |
download | libquotient-04960510df6058b4f25d3c41001a519e9fc5ba4a.tar.gz libquotient-04960510df6058b4f25d3c41001a519e9fc5ba4a.zip |
Room: make downloaded file name building more robust
Specifically, handle colons and long file names gracefully. Closes #366.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/room.cpp | 40 |
1 files changed, 24 insertions, 16 deletions
diff --git a/lib/room.cpp b/lib/room.cpp index 0a192203..b6925be5 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -1005,6 +1005,11 @@ QList<User*> Room::directChatUsers() const return connection()->directChatUsers(this); } +QString safeFileName(QString rawName) +{ + return rawName.replace(QRegularExpression("[/\\<>|\"*?:]"), "_"); +} + const RoomMessageEvent* Room::Private::getEventWithFile(const QString& eventId) const { @@ -1020,20 +1025,20 @@ Room::Private::getEventWithFile(const QString& eventId) const QString Room::Private::fileNameToDownload(const RoomMessageEvent* event) const { - Q_ASSERT(event->hasFileContent()); + Q_ASSERT(event && event->hasFileContent()); const auto* fileInfo = event->content()->fileInfo(); QString fileName; if (!fileInfo->originalName.isEmpty()) - fileName = QFileInfo(fileInfo->originalName).fileName(); - else if (!event->plainBody().isEmpty()) { - // Having no better options, assume that the body has - // the original file URL or at least the file name. - if (QUrl u { event->plainBody() }; u.isValid()) - fileName = QFileInfo(u.path()).fileName(); + fileName = QFileInfo(safeFileName(fileInfo->originalName)).fileName(); + else if (QUrl u { event->plainBody() }; u.isValid()) { + qDebug(MAIN) << event->id() + << "has no file name supplied but the event body " + "looks like a URL - using the file name from it"; + fileName = u.fileName(); } - // Check the file name for sanity - if (fileName.isEmpty() || !QTemporaryFile(fileName).open()) - return "file." % fileInfo->mimeType.preferredSuffix(); + if (fileName.isEmpty()) + return safeFileName(fileInfo->mediaId()).replace('.', '-') % '.' + % fileInfo->mimeType.preferredSuffix(); if (QSysInfo::productType() == "windows") { if (const auto& suffixes = fileInfo->mimeType.suffixes(); @@ -1888,12 +1893,15 @@ void Room::downloadFile(const QString& eventId, const QUrl& localFilename) } const auto fileUrl = fileInfo->url; auto filePath = localFilename.toLocalFile(); - if (filePath.isEmpty()) { - // Build our own file path, starting with temp directory and eventId. - filePath = eventId; - filePath = QDir::tempPath() % '/' - % filePath.replace(QRegularExpression("[/\\<>|\"*?:]"), "_") - % '#' % d->fileNameToDownload(event); + if (filePath.isEmpty()) { // Setup default file path + filePath = + fileInfo->url.path().mid(1) % '_' % d->fileNameToDownload(event); + + if (filePath.size() > 200) // If too long, elide in the middle + filePath.replace(128, filePath.size() - 192, "---"); + + filePath = QDir::tempPath() % '/' % filePath; + qDebug(MAIN) << "File path:" << filePath; } auto job = connection()->downloadFile(fileUrl, filePath); if (isJobRunning(job)) { |