aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKitsune Ral <Kitsune-Ral@users.sf.net>2019-12-13 14:47:26 +0300
committerKitsune Ral <Kitsune-Ral@users.sf.net>2019-12-13 14:47:26 +0300
commit04960510df6058b4f25d3c41001a519e9fc5ba4a (patch)
tree3966a2b5928a29aa1f8615aa8d5a73d227992e8e /lib
parent646186d802cfe7213146e4a68f8f926e21931b17 (diff)
downloadlibquotient-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.cpp40
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)) {