When receiving files, delay de-duplicating filenames

When receiving two files with the same name, the first file might not be
saved to disk already when we have to decide the name for the second if
we do it too early.

BUG: 470078
This commit is contained in:
Albert Vaca Cintora 2023-05-25 02:12:29 +02:00
parent 9ce7a676bd
commit 571575df28
3 changed files with 19 additions and 8 deletions

View file

@ -15,6 +15,7 @@
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <KLocalizedString> #include <KLocalizedString>
#include <KFileUtils>
FileTransferJob::FileTransferJob(const NetworkPacket *np, const QUrl &destination) FileTransferJob::FileTransferJob(const NetworkPacket *np, const QUrl &destination)
: KJob() : KJob()
@ -26,6 +27,7 @@ FileTransferJob::FileTransferJob(const NetworkPacket *np, const QUrl &destinatio
, m_written(0) , m_written(0)
, m_size(np->payloadSize()) , m_size(np->payloadSize())
, m_np(np) , m_np(np)
, m_autoRename(false)
{ {
Q_ASSERT(m_origin); Q_ASSERT(m_origin);
// Disabled this assert: QBluetoothSocket doesn't report "->isReadable() == true" until it's connected // Disabled this assert: QBluetoothSocket doesn't report "->isReadable() == true" until it's connected
@ -48,11 +50,18 @@ void FileTransferJob::start()
void FileTransferJob::doStart() void FileTransferJob::doStart()
{ {
if (m_destination.isLocalFile() && QFile::exists(m_destination.toLocalFile())) { if (m_destination.isLocalFile() && QFile::exists(m_destination.toLocalFile())) {
if (m_autoRename) {
QFileInfo fileInfo(m_destination.toLocalFile());
QString path = fileInfo.path();
QString fileName = fileInfo.fileName();
m_destination.setPath(path + QStringLiteral("/") + KFileUtils::suggestName(QUrl(path), fileName), QUrl::DecodedMode);
} else {
setError(2); setError(2);
setErrorText(i18n("Filename already present")); setErrorText(i18n("Filename already present"));
emitResult(); emitResult();
return; return;
} }
}
if (m_origin->bytesAvailable()) if (m_origin->bytesAvailable())
startTransfer(); startTransfer();

View file

@ -45,6 +45,10 @@ public:
{ {
m_from = from; m_from = from;
} }
void setAutoRenameIfDestinatinonExists(bool autoRename)
{
m_autoRename = autoRename;
}
const NetworkPacket *networkPacket() const NetworkPacket *networkPacket()
{ {
return m_np; return m_np;
@ -71,6 +75,7 @@ private:
qint64 m_written; qint64 m_written;
qint64 m_size; qint64 m_size;
const NetworkPacket *m_np; const NetworkPacket *m_np;
bool m_autoRename;
}; };
#endif #endif

View file

@ -16,7 +16,6 @@
#include <QTemporaryFile> #include <QTemporaryFile>
#include <KApplicationTrader> #include <KApplicationTrader>
#include <KFileUtils>
#include <KIO/Job> #include <KIO/Job>
#include <KIO/MkpathJob> #include <KIO/MkpathJob>
#include <KJobTrackerInterface> #include <KJobTrackerInterface>
@ -60,9 +59,6 @@ QUrl SharePlugin::getFileDestination(const QString filename) const
const QUrl dir = destinationDir().adjusted(QUrl::StripTrailingSlash); const QUrl dir = destinationDir().adjusted(QUrl::StripTrailingSlash);
QUrl destination(dir); QUrl destination(dir);
destination.setPath(dir.path() + QStringLiteral("/") + filename, QUrl::DecodedMode); destination.setPath(dir.path() + QStringLiteral("/") + filename, QUrl::DecodedMode);
if (destination.isLocalFile() && QFile::exists(destination.toLocalFile())) {
destination.setPath(dir.path() + QStringLiteral("/") + KFileUtils::suggestName(dir, filename), QUrl::DecodedMode);
}
return destination; return destination;
} }
@ -133,6 +129,7 @@ bool SharePlugin::receivePacket(const NetworkPacket &np)
FileTransferJob *job = np.createPayloadTransferJob(destination); FileTransferJob *job = np.createPayloadTransferJob(destination);
job->setOriginName(device()->name() + QStringLiteral(": ") + filename); job->setOriginName(device()->name() + QStringLiteral(": ") + filename);
job->setAutoRenameIfDestinatinonExists(true);
connect(job, &KJob::result, this, [this, dateCreated, dateModified, open](KJob *job) -> void { connect(job, &KJob::result, this, [this, dateCreated, dateModified, open](KJob *job) -> void {
finished(job, dateCreated, dateModified, open); finished(job, dateCreated, dateModified, open);
}); });