mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-28 19:58:56 +03:00
Merge pull request #2781 from nextcloud/cherry_pick_2020_w53
Cherry pick 2020 w53
This commit is contained in:
commit
fbd9f5126c
22 changed files with 199 additions and 212 deletions
|
@ -372,6 +372,7 @@ bool FileSystem::remove(const QString &fileName, QString *errorString)
|
||||||
|
|
||||||
bool FileSystem::moveToTrash(const QString &fileName, QString *errorString)
|
bool FileSystem::moveToTrash(const QString &fileName, QString *errorString)
|
||||||
{
|
{
|
||||||
|
// TODO: Qt 5.15 bool QFile::moveToTrash()
|
||||||
#if defined Q_OS_UNIX && !defined Q_OS_MAC
|
#if defined Q_OS_UNIX && !defined Q_OS_MAC
|
||||||
QString trashPath, trashFilePath, trashInfoPath;
|
QString trashPath, trashFilePath, trashInfoPath;
|
||||||
QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME"));
|
QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME"));
|
||||||
|
@ -497,33 +498,26 @@ bool FileSystem::isJunction(const QString &filename)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FileSystem::pathtoUNC(const QString &str)
|
#ifdef Q_OS_WIN
|
||||||
|
QString FileSystem::pathtoUNC(const QString &_str)
|
||||||
{
|
{
|
||||||
int len = 0;
|
if (_str.isEmpty()) {
|
||||||
QString longStr;
|
return _str;
|
||||||
|
|
||||||
len = str.length();
|
|
||||||
longStr.reserve(len + 4);
|
|
||||||
|
|
||||||
// prepend \\?\ and convert '/' => '\' to support long names
|
|
||||||
if (str[0] == QLatin1Char('/') || str[0] == QLatin1Char('\\')) {
|
|
||||||
// Don't prepend if already UNC
|
|
||||||
if (!(len > 1 && (str[1] == QLatin1Char('/') || str[1] == QLatin1Char('\\')))) {
|
|
||||||
longStr.append(QStringLiteral("\\\\?"));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
longStr.append(QStringLiteral("\\\\?\\")); // prepend string by this four magic chars.
|
|
||||||
}
|
}
|
||||||
longStr += str;
|
const QString str = QDir::toNativeSeparators(_str);
|
||||||
|
const QLatin1Char sep('\\');
|
||||||
|
|
||||||
/* replace all occurences of / with the windows native \ */
|
// we already have a unc path
|
||||||
|
if (str.startsWith(sep + sep)) {
|
||||||
for (auto &c : longStr) {
|
return str;
|
||||||
if (c == QLatin1Char('/')) {
|
|
||||||
c = QLatin1Char('\\');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return longStr;
|
// prepend \\?\ and to support long names
|
||||||
|
|
||||||
|
if (str.at(0) == sep) {
|
||||||
|
return QStringLiteral(R"(\\?)") + str;
|
||||||
|
}
|
||||||
|
return QStringLiteral(R"(\\?\)") + str;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace OCC
|
} // namespace OCC
|
||||||
|
|
|
@ -128,6 +128,19 @@ namespace FileSystem {
|
||||||
* Returns the file system used at the given path.
|
* Returns the file system used at the given path.
|
||||||
*/
|
*/
|
||||||
QString fileSystemForPath(const QString &path);
|
QString fileSystemForPath(const QString &path);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function takes a path and converts it to a UNC representation of the
|
||||||
|
* string. That means that it prepends a \\?\ (unless already UNC) and converts
|
||||||
|
* all slashes to backslashes.
|
||||||
|
*
|
||||||
|
* Note the following:
|
||||||
|
* - The string must be absolute.
|
||||||
|
* - it needs to contain a drive character to be a valid UNC
|
||||||
|
* - A conversion is only done if the path len is larger than 245. Otherwise
|
||||||
|
* the windows API functions work with the normal "unixoid" representation too.
|
||||||
|
*/
|
||||||
|
QString OCSYNC_EXPORT pathtoUNC(const QString &str);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -144,19 +157,6 @@ namespace FileSystem {
|
||||||
* Returns whether the file is a junction (windows only)
|
* Returns whether the file is a junction (windows only)
|
||||||
*/
|
*/
|
||||||
bool OCSYNC_EXPORT isJunction(const QString &filename);
|
bool OCSYNC_EXPORT isJunction(const QString &filename);
|
||||||
|
|
||||||
/*
|
|
||||||
* This function takes a path and converts it to a UNC representation of the
|
|
||||||
* string. That means that it prepends a \\?\ (unless already UNC) and converts
|
|
||||||
* all slashes to backslashes.
|
|
||||||
*
|
|
||||||
* Note the following:
|
|
||||||
* - The string must be absolute.
|
|
||||||
* - it needs to contain a drive character to be a valid UNC
|
|
||||||
* - A conversion is only done if the path len is larger than 245. Otherwise
|
|
||||||
* the windows API functions work with the normal "unixoid" representation too.
|
|
||||||
*/
|
|
||||||
QString OCSYNC_EXPORT pathtoUNC(const QString &str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -94,7 +94,7 @@ void setLaunchOnStartup_private(const QString &appName, const QString &guiName,
|
||||||
QString runPath = QLatin1String(runPathC);
|
QString runPath = QLatin1String(runPathC);
|
||||||
QSettings settings(runPath, QSettings::NativeFormat);
|
QSettings settings(runPath, QSettings::NativeFormat);
|
||||||
if (enable) {
|
if (enable) {
|
||||||
settings.setValue(appName, QCoreApplication::applicationFilePath().replace(QLatin1Char('/'), QLatin1Char('\\')));
|
settings.setValue(appName, QDir::toNativeSeparators(QCoreApplication::applicationFilePath()));
|
||||||
} else {
|
} else {
|
||||||
settings.remove(appName);
|
settings.remove(appName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,24 +158,24 @@ public:
|
||||||
* If the remote metadata changes, the local placeholder's metadata should possibly
|
* If the remote metadata changes, the local placeholder's metadata should possibly
|
||||||
* change as well.
|
* change as well.
|
||||||
*/
|
*/
|
||||||
virtual Result<void, QString> updateMetadata(const QString &filePath, time_t modtime, qint64 size, const QByteArray &fileId) = 0;
|
virtual Q_REQUIRED_RESULT Result<void, QString> updateMetadata(const QString &filePath, time_t modtime, qint64 size, const QByteArray &fileId) = 0;
|
||||||
|
|
||||||
/// Create a new dehydrated placeholder. Called from PropagateDownload.
|
/// Create a new dehydrated placeholder. Called from PropagateDownload.
|
||||||
virtual Result<void, QString> createPlaceholder(const SyncFileItem &item) = 0;
|
virtual Q_REQUIRED_RESULT Result<void, QString> createPlaceholder(const SyncFileItem &item) = 0;
|
||||||
|
|
||||||
/** Convert a hydrated placeholder to a dehydrated one. Called from PropagateDownlaod.
|
/** Convert a hydrated placeholder to a dehydrated one. Called from PropagateDownlaod.
|
||||||
*
|
*
|
||||||
* This is different from delete+create because preserving some file metadata
|
* This is different from delete+create because preserving some file metadata
|
||||||
* (like pin states) may be essential for some vfs plugins.
|
* (like pin states) may be essential for some vfs plugins.
|
||||||
*/
|
*/
|
||||||
virtual Result<void, QString> dehydratePlaceholder(const SyncFileItem &item) = 0;
|
virtual Q_REQUIRED_RESULT Result<void, QString> dehydratePlaceholder(const SyncFileItem &item) = 0;
|
||||||
|
|
||||||
/** Discovery hook: even unchanged files may need UPDATE_METADATA.
|
/** Discovery hook: even unchanged files may need UPDATE_METADATA.
|
||||||
*
|
*
|
||||||
* For instance cfapi vfs wants local hydrated non-placeholder files to
|
* For instance cfapi vfs wants local hydrated non-placeholder files to
|
||||||
* become hydrated placeholder files.
|
* become hydrated placeholder files.
|
||||||
*/
|
*/
|
||||||
virtual bool needsMetadataUpdate(const SyncFileItem &item) = 0;
|
virtual Q_REQUIRED_RESULT bool needsMetadataUpdate(const SyncFileItem &item) = 0;
|
||||||
|
|
||||||
/** Convert a new file to a hydrated placeholder.
|
/** Convert a new file to a hydrated placeholder.
|
||||||
*
|
*
|
||||||
|
@ -190,13 +190,13 @@ public:
|
||||||
* new placeholder shall supersede, for rename-replace actions with new downloads,
|
* new placeholder shall supersede, for rename-replace actions with new downloads,
|
||||||
* for example.
|
* for example.
|
||||||
*/
|
*/
|
||||||
virtual void convertToPlaceholder(
|
virtual Q_REQUIRED_RESULT Result<void, QString> convertToPlaceholder(
|
||||||
const QString &filename,
|
const QString &filename,
|
||||||
const SyncFileItem &item,
|
const SyncFileItem &item,
|
||||||
const QString &replacesFile = QString()) = 0;
|
const QString &replacesFile = QString()) = 0;
|
||||||
|
|
||||||
/// Determine whether the file at the given absolute path is a dehydrated placeholder.
|
/// Determine whether the file at the given absolute path is a dehydrated placeholder.
|
||||||
virtual bool isDehydratedPlaceholder(const QString &filePath) = 0;
|
virtual Q_REQUIRED_RESULT bool isDehydratedPlaceholder(const QString &filePath) = 0;
|
||||||
|
|
||||||
/** Similar to isDehydratedPlaceholder() but used from sync discovery.
|
/** Similar to isDehydratedPlaceholder() but used from sync discovery.
|
||||||
*
|
*
|
||||||
|
@ -205,7 +205,7 @@ public:
|
||||||
*
|
*
|
||||||
* Returning true means that type was fully determined.
|
* Returning true means that type was fully determined.
|
||||||
*/
|
*/
|
||||||
virtual bool statTypeVirtualFile(csync_file_stat_t *stat, void *stat_data) = 0;
|
virtual Q_REQUIRED_RESULT bool statTypeVirtualFile(csync_file_stat_t *stat, void *stat_data) = 0;
|
||||||
|
|
||||||
/** Sets the pin state for the item at a path.
|
/** Sets the pin state for the item at a path.
|
||||||
*
|
*
|
||||||
|
@ -216,7 +216,7 @@ public:
|
||||||
*
|
*
|
||||||
* folderPath is relative to the sync folder. Can be "" for root folder.
|
* folderPath is relative to the sync folder. Can be "" for root folder.
|
||||||
*/
|
*/
|
||||||
virtual bool setPinState(const QString &folderPath, PinState state) = 0;
|
virtual Q_REQUIRED_RESULT bool setPinState(const QString &folderPath, PinState state) = 0;
|
||||||
|
|
||||||
/** Returns the pin state of an item at a path.
|
/** Returns the pin state of an item at a path.
|
||||||
*
|
*
|
||||||
|
@ -227,7 +227,7 @@ public:
|
||||||
*
|
*
|
||||||
* Returns none on retrieval error.
|
* Returns none on retrieval error.
|
||||||
*/
|
*/
|
||||||
virtual Optional<PinState> pinState(const QString &folderPath) = 0;
|
virtual Q_REQUIRED_RESULT Optional<PinState> pinState(const QString &folderPath) = 0;
|
||||||
|
|
||||||
/** Returns availability status of an item at a path.
|
/** Returns availability status of an item at a path.
|
||||||
*
|
*
|
||||||
|
@ -236,7 +236,7 @@ public:
|
||||||
*
|
*
|
||||||
* folderPath is relative to the sync folder. Can be "" for root folder.
|
* folderPath is relative to the sync folder. Can be "" for root folder.
|
||||||
*/
|
*/
|
||||||
virtual AvailabilityResult availability(const QString &folderPath) = 0;
|
virtual Q_REQUIRED_RESULT AvailabilityResult availability(const QString &folderPath) = 0;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/** Update in-sync state based on SyncFileStatusTracker signal.
|
/** Update in-sync state based on SyncFileStatusTracker signal.
|
||||||
|
@ -296,7 +296,7 @@ public:
|
||||||
Result<void, QString> updateMetadata(const QString &, time_t, qint64, const QByteArray &) override { return {}; }
|
Result<void, QString> updateMetadata(const QString &, time_t, qint64, const QByteArray &) override { return {}; }
|
||||||
Result<void, QString> createPlaceholder(const SyncFileItem &) override { return {}; }
|
Result<void, QString> createPlaceholder(const SyncFileItem &) override { return {}; }
|
||||||
Result<void, QString> dehydratePlaceholder(const SyncFileItem &) override { return {}; }
|
Result<void, QString> dehydratePlaceholder(const SyncFileItem &) override { return {}; }
|
||||||
void convertToPlaceholder(const QString &, const SyncFileItem &, const QString &) override {}
|
Result<void, QString> convertToPlaceholder(const QString &, const SyncFileItem &, const QString &) override { return {}; }
|
||||||
|
|
||||||
bool needsMetadataUpdate(const SyncFileItem &) override { return false; }
|
bool needsMetadataUpdate(const SyncFileItem &) override { return false; }
|
||||||
bool isDehydratedPlaceholder(const QString &) override { return false; }
|
bool isDehydratedPlaceholder(const QString &) override { return false; }
|
||||||
|
|
|
@ -1260,6 +1260,7 @@ void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction dir, std::functio
|
||||||
}
|
}
|
||||||
setSyncPaused(oldPaused);
|
setSyncPaused(oldPaused);
|
||||||
});
|
});
|
||||||
|
connect(this, &Folder::destroyed, msgBox, &QMessageBox::deleteLater);
|
||||||
msgBox->open();
|
msgBox->open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -161,7 +161,10 @@ GeneralSettings::GeneralSettings(QWidget *parent)
|
||||||
_ui->autostartCheckBox->setDisabled(true);
|
_ui->autostartCheckBox->setDisabled(true);
|
||||||
_ui->autostartCheckBox->setToolTip(tr("You cannot disable autostart because system-wide autostart is enabled."));
|
_ui->autostartCheckBox->setToolTip(tr("You cannot disable autostart because system-wide autostart is enabled."));
|
||||||
} else {
|
} else {
|
||||||
_ui->autostartCheckBox->setChecked(Utility::hasLaunchOnStartup(Theme::instance()->appName()));
|
const bool hasAutoStart = Utility::hasLaunchOnStartup(Theme::instance()->appName());
|
||||||
|
// make sure the binary location is correctly set
|
||||||
|
slotToggleLaunchOnStartup(hasAutoStart);
|
||||||
|
_ui->autostartCheckBox->setChecked(hasAutoStart);
|
||||||
connect(_ui->autostartCheckBox, &QAbstractButton::toggled, this, &GeneralSettings::slotToggleLaunchOnStartup);
|
connect(_ui->autostartCheckBox, &QAbstractButton::toggled, this, &GeneralSettings::slotToggleLaunchOnStartup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,9 +90,8 @@ QNetworkReply *AccessManager::createRequest(QNetworkAccessManager::Operation op,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HttpLogger::logRequest(newRequest, op, outgoingData);
|
|
||||||
const auto reply = QNetworkAccessManager::createRequest(op, newRequest, outgoingData);
|
const auto reply = QNetworkAccessManager::createRequest(op, newRequest, outgoingData);
|
||||||
HttpLogger::logReplyOnFinished(reply);
|
HttpLogger::logRequest(reply, op, outgoingData);
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,22 +42,17 @@ bool FileSystem::fileEquals(const QString &fn1, const QString &fn2)
|
||||||
}
|
}
|
||||||
|
|
||||||
const int BufferSize = 16 * 1024;
|
const int BufferSize = 16 * 1024;
|
||||||
char buffer1[BufferSize];
|
QByteArray buffer1(BufferSize, 0);
|
||||||
char buffer2[BufferSize];
|
QByteArray buffer2(BufferSize, 0);
|
||||||
do {
|
// the files have the same size, compare all of it
|
||||||
int r = f1.read(buffer1, BufferSize);
|
while(!f1.atEnd()){
|
||||||
if (f2.read(buffer2, BufferSize) != r) {
|
f1.read(buffer1.data(), BufferSize);
|
||||||
// this should normally not happen: the files are supposed to have the same size.
|
f2.read(buffer2.data(), BufferSize);
|
||||||
|
if (buffer1 != buffer2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (r <= 0) {
|
};
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
if (memcmp(buffer1, buffer2, r) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} while (true);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t FileSystem::getModTime(const QString &filename)
|
time_t FileSystem::getModTime(const QString &filename)
|
||||||
|
@ -130,7 +125,7 @@ qint64 FileSystem::getSize(const QString &filename)
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
if (isLnkFile(filename)) {
|
if (isLnkFile(filename)) {
|
||||||
// Use csync to get the file size. Qt seems unable to get at it.
|
// Qt handles .lnk as symlink... https://doc.qt.io/qt-5/qfileinfo.html#details
|
||||||
return getSizeWithCsync(filename);
|
return getSizeWithCsync(filename);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -53,7 +53,8 @@ void logHttp(const QByteArray &verb, const QString &url, const QByteArray &id, c
|
||||||
for (const auto &it : header) {
|
for (const auto &it : header) {
|
||||||
stream << it.first << ": ";
|
stream << it.first << ": ";
|
||||||
if (it.first == "Authorization") {
|
if (it.first == "Authorization") {
|
||||||
stream << "[redacted]";
|
stream << (it.second.startsWith("Bearer ") ? "Bearer" : "Basic");
|
||||||
|
stream << " [redacted]";
|
||||||
} else {
|
} else {
|
||||||
stream << it.second;
|
stream << it.second;
|
||||||
}
|
}
|
||||||
|
@ -85,24 +86,9 @@ void logHttp(const QByteArray &verb, const QString &url, const QByteArray &id, c
|
||||||
|
|
||||||
namespace OCC {
|
namespace OCC {
|
||||||
|
|
||||||
|
void HttpLogger::logRequest(QNetworkReply *reply, QNetworkAccessManager::Operation operation, QIODevice *device)
|
||||||
void HttpLogger::logReplyOnFinished(const QNetworkReply *reply)
|
|
||||||
{
|
|
||||||
if (!lcNetworkHttp().isInfoEnabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QObject::connect(reply, &QNetworkReply::finished, reply, [reply] {
|
|
||||||
logHttp(requestVerb(*reply),
|
|
||||||
reply->url().toString(),
|
|
||||||
reply->request().rawHeader(XRequestId()),
|
|
||||||
reply->header(QNetworkRequest::ContentTypeHeader).toString(),
|
|
||||||
reply->rawHeaderPairs(),
|
|
||||||
const_cast<QNetworkReply *>(reply));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void HttpLogger::logRequest(const QNetworkRequest &request, QNetworkAccessManager::Operation operation, QIODevice *device)
|
|
||||||
{
|
{
|
||||||
|
const auto request = reply->request();
|
||||||
if (!lcNetworkHttp().isInfoEnabled()) {
|
if (!lcNetworkHttp().isInfoEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -118,6 +104,15 @@ void HttpLogger::logRequest(const QNetworkRequest &request, QNetworkAccessManage
|
||||||
request.header(QNetworkRequest::ContentTypeHeader).toString(),
|
request.header(QNetworkRequest::ContentTypeHeader).toString(),
|
||||||
header,
|
header,
|
||||||
device);
|
device);
|
||||||
|
|
||||||
|
QObject::connect(reply, &QNetworkReply::finished, reply, [reply] {
|
||||||
|
logHttp(requestVerb(*reply),
|
||||||
|
reply->url().toString(),
|
||||||
|
reply->request().rawHeader(XRequestId()),
|
||||||
|
reply->header(QNetworkRequest::ContentTypeHeader).toString(),
|
||||||
|
reply->rawHeaderPairs(),
|
||||||
|
reply);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray HttpLogger::requestVerb(QNetworkAccessManager::Operation operation, const QNetworkRequest &request)
|
QByteArray HttpLogger::requestVerb(QNetworkAccessManager::Operation operation, const QNetworkRequest &request)
|
||||||
|
|
|
@ -20,8 +20,7 @@
|
||||||
|
|
||||||
namespace OCC {
|
namespace OCC {
|
||||||
namespace HttpLogger {
|
namespace HttpLogger {
|
||||||
void OWNCLOUDSYNC_EXPORT logReplyOnFinished(const QNetworkReply *reply);
|
void OWNCLOUDSYNC_EXPORT logRequest(QNetworkReply *reply, QNetworkAccessManager::Operation operation, QIODevice *device);
|
||||||
void OWNCLOUDSYNC_EXPORT logRequest(const QNetworkRequest &request, QNetworkAccessManager::Operation operation, QIODevice *device);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper to construct the HTTP verb used in the request
|
* Helper to construct the HTTP verb used in the request
|
||||||
|
|
|
@ -737,7 +737,9 @@ QString OwncloudPropagator::adjustRenamedPath(const QString &original) const
|
||||||
bool OwncloudPropagator::updateMetadata(const SyncFileItem &item, const QString &localFolderPath, SyncJournalDb &journal, Vfs &vfs)
|
bool OwncloudPropagator::updateMetadata(const SyncFileItem &item, const QString &localFolderPath, SyncJournalDb &journal, Vfs &vfs)
|
||||||
{
|
{
|
||||||
QString fsPath = localFolderPath + item.destination();
|
QString fsPath = localFolderPath + item.destination();
|
||||||
vfs.convertToPlaceholder(fsPath, item);
|
if (!vfs.convertToPlaceholder(fsPath, item)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
auto record = item.toSyncJournalFileRecordWithInode(fsPath);
|
auto record = item.toSyncJournalFileRecordWithInode(fsPath);
|
||||||
return journal.setFileRecord(record);
|
return journal.setFileRecord(record);
|
||||||
}
|
}
|
||||||
|
|
|
@ -964,7 +964,11 @@ void PropagateDownloadFile::downloadFinished()
|
||||||
preserveGroupOwnership(_tmpFile.fileName(), existingFile);
|
preserveGroupOwnership(_tmpFile.fileName(), existingFile);
|
||||||
|
|
||||||
// Make the file a hydrated placeholder if possible
|
// Make the file a hydrated placeholder if possible
|
||||||
propagator()->syncOptions()._vfs->convertToPlaceholder(_tmpFile.fileName(), *_item, fn);
|
const auto result = propagator()->syncOptions()._vfs->convertToPlaceholder(_tmpFile.fileName(), *_item, fn);
|
||||||
|
if (!result) {
|
||||||
|
done(SyncFileItem::NormalError, result.error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the remote permissions
|
// Apply the remote permissions
|
||||||
|
|
|
@ -346,7 +346,12 @@ void OCC::SyncEngine::slotItemDiscovered(const OCC::SyncFileItemPtr &item)
|
||||||
|
|
||||||
// Ensure it's a placeholder file on disk
|
// Ensure it's a placeholder file on disk
|
||||||
if (item->_type == ItemTypeFile) {
|
if (item->_type == ItemTypeFile) {
|
||||||
_syncOptions._vfs->convertToPlaceholder(filePath, *item);
|
const auto result = _syncOptions._vfs->convertToPlaceholder(filePath, *item);
|
||||||
|
if (!result) {
|
||||||
|
item->_instruction = CSYNC_INSTRUCTION_ERROR;
|
||||||
|
item->_errorString = tr("Could not update file : %1").arg(result.error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update on-disk virtual file metadata
|
// Update on-disk virtual file metadata
|
||||||
|
@ -732,10 +737,11 @@ void SyncEngine::slotDiscoveryFinished()
|
||||||
}
|
}
|
||||||
|
|
||||||
QPointer<QObject> guard = new QObject();
|
QPointer<QObject> guard = new QObject();
|
||||||
auto callback = [this, finish, guard](bool cancel) -> void {
|
QPointer<QObject> self = this;
|
||||||
|
auto callback = [this, self, finish, guard](bool cancel) -> void {
|
||||||
// use a guard to ensure its only called once...
|
// use a guard to ensure its only called once...
|
||||||
if (!guard)
|
// qpointer to self to ensure we still exist
|
||||||
{
|
if (!guard || !self) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
guard->deleteLater();
|
guard->deleteLater();
|
||||||
|
|
|
@ -149,16 +149,16 @@ Result<void, QString> VfsCfApi::dehydratePlaceholder(const SyncFileItem &item)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void VfsCfApi::convertToPlaceholder(const QString &filename, const SyncFileItem &item, const QString &replacesFile)
|
Result<void, QString> VfsCfApi::convertToPlaceholder(const QString &filename, const SyncFileItem &item, const QString &replacesFile)
|
||||||
{
|
{
|
||||||
const auto localPath = QDir::toNativeSeparators(filename);
|
const auto localPath = QDir::toNativeSeparators(filename);
|
||||||
const auto replacesPath = QDir::toNativeSeparators(replacesFile);
|
const auto replacesPath = QDir::toNativeSeparators(replacesFile);
|
||||||
|
|
||||||
const auto handle = cfapi::handleForPath(localPath);
|
const auto handle = cfapi::handleForPath(localPath);
|
||||||
if (cfapi::findPlaceholderInfo(handle)) {
|
if (cfapi::findPlaceholderInfo(handle)) {
|
||||||
cfapi::updatePlaceholderInfo(handle, item._modtime, item._size, item._fileId, replacesPath);
|
return cfapi::updatePlaceholderInfo(handle, item._modtime, item._size, item._fileId, replacesPath);
|
||||||
} else {
|
} else {
|
||||||
cfapi::convertToPlaceholder(handle, item._modtime, item._size, item._fileId, replacesPath);
|
return cfapi::convertToPlaceholder(handle, item._modtime, item._size, item._fileId, replacesPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ public:
|
||||||
|
|
||||||
Result<void, QString> createPlaceholder(const SyncFileItem &item) override;
|
Result<void, QString> createPlaceholder(const SyncFileItem &item) override;
|
||||||
Result<void, QString> dehydratePlaceholder(const SyncFileItem &item) override;
|
Result<void, QString> dehydratePlaceholder(const SyncFileItem &item) override;
|
||||||
void convertToPlaceholder(const QString &filename, const SyncFileItem &item, const QString &replacesFile) override;
|
Result<void, QString> convertToPlaceholder(const QString &filename, const SyncFileItem &item, const QString &replacesFile) override;
|
||||||
|
|
||||||
bool needsMetadataUpdate(const SyncFileItem &) override;
|
bool needsMetadataUpdate(const SyncFileItem &) override;
|
||||||
bool isDehydratedPlaceholder(const QString &filePath) override;
|
bool isDehydratedPlaceholder(const QString &filePath) override;
|
||||||
|
|
|
@ -122,9 +122,10 @@ Result<void, QString> VfsSuffix::dehydratePlaceholder(const SyncFileItem &item)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void VfsSuffix::convertToPlaceholder(const QString &, const SyncFileItem &, const QString &)
|
Result<void, QString> VfsSuffix::convertToPlaceholder(const QString &, const SyncFileItem &, const QString &)
|
||||||
{
|
{
|
||||||
// Nothing necessary
|
// Nothing necessary
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VfsSuffix::isDehydratedPlaceholder(const QString &filePath)
|
bool VfsSuffix::isDehydratedPlaceholder(const QString &filePath)
|
||||||
|
|
|
@ -41,7 +41,7 @@ public:
|
||||||
|
|
||||||
Result<void, QString> createPlaceholder(const SyncFileItem &item) override;
|
Result<void, QString> createPlaceholder(const SyncFileItem &item) override;
|
||||||
Result<void, QString> dehydratePlaceholder(const SyncFileItem &item) override;
|
Result<void, QString> dehydratePlaceholder(const SyncFileItem &item) override;
|
||||||
void convertToPlaceholder(const QString &filename, const SyncFileItem &item, const QString &) override;
|
Result<void, QString> convertToPlaceholder(const QString &filename, const SyncFileItem &item, const QString &) override;
|
||||||
|
|
||||||
bool needsMetadataUpdate(const SyncFileItem &) override { return false; }
|
bool needsMetadataUpdate(const SyncFileItem &) override { return false; }
|
||||||
bool isDehydratedPlaceholder(const QString &filePath) override;
|
bool isDehydratedPlaceholder(const QString &filePath) override;
|
||||||
|
|
|
@ -74,6 +74,7 @@ if( UNIX AND NOT APPLE )
|
||||||
endif(UNIX AND NOT APPLE)
|
endif(UNIX AND NOT APPLE)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
nextcloud_add_test(LongWinPath "")
|
||||||
nextcloud_add_test(SyncCfApi "")
|
nextcloud_add_test(SyncCfApi "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,3 @@ add_cmocka_test(check_std_c_jhash std_tests/check_std_c_jhash.c ${TEST_TARGET_LI
|
||||||
# vio
|
# vio
|
||||||
add_cmocka_test(check_vio_ext vio_tests/check_vio_ext.cpp ${TEST_TARGET_LIBRARIES})
|
add_cmocka_test(check_vio_ext vio_tests/check_vio_ext.cpp ${TEST_TARGET_LIBRARIES})
|
||||||
|
|
||||||
# encoding
|
|
||||||
add_cmocka_test(check_encoding_functions encoding_tests/check_encoding.cpp ${TEST_TARGET_LIBRARIES})
|
|
||||||
|
|
||||||
|
|
|
@ -1,96 +0,0 @@
|
||||||
/*
|
|
||||||
* libcsync -- a library to sync a directory with another
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 by Klaas Freitag <freitag@owncloud.com>
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
#include <cstdio>
|
|
||||||
#include "common/filesystembase.h"
|
|
||||||
#include "torture.h"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <string.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "torture.h"
|
|
||||||
|
|
||||||
static void check_long_win_path(void **state)
|
|
||||||
{
|
|
||||||
(void) state; /* unused */
|
|
||||||
|
|
||||||
{
|
|
||||||
const auto path = QStringLiteral("C://DATA/FILES/MUSIC/MY_MUSIC.mp3"); // check a short path
|
|
||||||
const auto exp_path = QStringLiteral(R"(\\?\C:\\DATA\FILES\MUSIC\MY_MUSIC.mp3)");
|
|
||||||
QString new_short = OCC::FileSystem::pathtoUNC(path);
|
|
||||||
assert_string_equal(new_short.constData(), exp_path.constData());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const auto path = QStringLiteral(R"(\\foo\bar/MY_MUSIC.mp3)");
|
|
||||||
const auto exp_path = QStringLiteral(R"(\\foo\bar\MY_MUSIC.mp3)");
|
|
||||||
QString new_short = OCC::FileSystem::pathtoUNC(path);
|
|
||||||
assert_string_equal(new_short.constData(), exp_path.constData());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const auto path = QStringLiteral(R"(//foo\bar/MY_MUSIC.mp3)");
|
|
||||||
const auto exp_path = QStringLiteral(R"(\\foo\bar\MY_MUSIC.mp3)");
|
|
||||||
QString new_short = OCC::FileSystem::pathtoUNC(path);
|
|
||||||
assert_string_equal(new_short.constData(), exp_path.constData());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const auto path = QStringLiteral(R"(\foo\bar)");
|
|
||||||
const auto exp_path = QStringLiteral(R"(\\?\foo\bar)");
|
|
||||||
QString new_short = OCC::FileSystem::pathtoUNC(path);
|
|
||||||
assert_string_equal(new_short.constData(), exp_path.constData());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const auto path = QStringLiteral("/foo/bar");
|
|
||||||
const auto exp_path = QStringLiteral(R"(\\?\foo\bar)");
|
|
||||||
QString new_short = OCC::FileSystem::pathtoUNC(path);
|
|
||||||
assert_string_equal(new_short.constData(), exp_path.constData());
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto longPath = QStringLiteral("D://alonglonglonglong/blonglonglonglong/clonglonglonglong/dlonglonglonglong/"
|
|
||||||
"elonglonglonglong/flonglonglonglong/glonglonglonglong/hlonglonglonglong/ilonglonglonglong/"
|
|
||||||
"jlonglonglonglong/klonglonglonglong/llonglonglonglong/mlonglonglonglong/nlonglonglonglong/"
|
|
||||||
"olonglonglonglong/file.txt");
|
|
||||||
const auto longPathConv = QStringLiteral(R"(\\?\D:\\alonglonglonglong\blonglonglonglong\clonglonglonglong\dlonglonglonglong\)"
|
|
||||||
R"(elonglonglonglong\flonglonglonglong\glonglonglonglong\hlonglonglonglong\ilonglonglonglong\)"
|
|
||||||
R"(jlonglonglonglong\klonglonglonglong\llonglonglonglong\mlonglonglonglong\nlonglonglonglong\)"
|
|
||||||
R"(olonglonglonglong\file.txt)");
|
|
||||||
|
|
||||||
QString new_long = OCC::FileSystem::pathtoUNC(longPath);
|
|
||||||
// printf( "XXXXXXXXXXXX %s %d\n", new_long, mem_reserved);
|
|
||||||
|
|
||||||
assert_string_equal(new_long.constData(), longPathConv.constData());
|
|
||||||
|
|
||||||
// printf( "YYYYYYYYYYYY %ld\n", strlen(new_long));
|
|
||||||
assert_int_equal(new_long.length(), 286);
|
|
||||||
}
|
|
||||||
|
|
||||||
int torture_run_tests(void)
|
|
||||||
{
|
|
||||||
const struct CMUnitTest tests[] = {
|
|
||||||
cmocka_unit_test(check_long_win_path),
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
return cmocka_run_group_tests(tests, nullptr, nullptr);
|
|
||||||
}
|
|
||||||
|
|
87
test/testlongwinpath.cpp
Normal file
87
test/testlongwinpath.cpp
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* libcsync -- a library to sync a directory with another
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 by Klaas Freitag <freitag@owncloud.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include "common/filesystembase.h"
|
||||||
|
|
||||||
|
#include <QTest>
|
||||||
|
|
||||||
|
|
||||||
|
class TestLongWindowsPath : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void check_long_win_path()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const auto path = QStringLiteral("C://DATA/FILES/MUSIC/MY_MUSIC.mp3"); // check a short path
|
||||||
|
const auto exp_path = QStringLiteral("\\\\?\\C:\\\\DATA\\FILES\\MUSIC\\MY_MUSIC.mp3");
|
||||||
|
QString new_short = OCC::FileSystem::pathtoUNC(path);
|
||||||
|
QCOMPARE(new_short, exp_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto path = QStringLiteral("\\\\foo\\bar/MY_MUSIC.mp3");
|
||||||
|
const auto exp_path = QStringLiteral("\\\\foo\\bar\\MY_MUSIC.mp3");
|
||||||
|
QString new_short = OCC::FileSystem::pathtoUNC(path);
|
||||||
|
QCOMPARE(new_short, exp_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto path = QStringLiteral("//foo\\bar/MY_MUSIC.mp3");
|
||||||
|
const auto exp_path = QStringLiteral("\\\\foo\\bar\\MY_MUSIC.mp3");
|
||||||
|
QString new_short = OCC::FileSystem::pathtoUNC(path);
|
||||||
|
QCOMPARE(new_short, exp_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto path = QStringLiteral("\\foo\\bar");
|
||||||
|
const auto exp_path = QStringLiteral("\\\\?\\foo\\bar");
|
||||||
|
QString new_short = OCC::FileSystem::pathtoUNC(path);
|
||||||
|
QCOMPARE(new_short, exp_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto path = QStringLiteral("/foo/bar");
|
||||||
|
const auto exp_path = QStringLiteral("\\\\?\\foo\\bar");
|
||||||
|
QString new_short = OCC::FileSystem::pathtoUNC(path);
|
||||||
|
QCOMPARE(new_short, exp_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto longPath = QStringLiteral("D://alonglonglonglong/blonglonglonglong/clonglonglonglong/dlonglonglonglong/"
|
||||||
|
"elonglonglonglong/flonglonglonglong/glonglonglonglong/hlonglonglonglong/ilonglonglonglong/"
|
||||||
|
"jlonglonglonglong/klonglonglonglong/llonglonglonglong/mlonglonglonglong/nlonglonglonglong/"
|
||||||
|
"olonglonglonglong/file.txt");
|
||||||
|
const auto longPathConv = QStringLiteral("\\\\?\\D:\\\\alonglonglonglong\\blonglonglonglong\\clonglonglonglong\\dlonglonglonglong\\"
|
||||||
|
"elonglonglonglong\\flonglonglonglong\\glonglonglonglong\\hlonglonglonglong\\ilonglonglonglong\\"
|
||||||
|
"jlonglonglonglong\\klonglonglonglong\\llonglonglonglong\\mlonglonglonglong\\nlonglonglonglong\\"
|
||||||
|
"olonglonglonglong\\file.txt");
|
||||||
|
|
||||||
|
QString new_long = OCC::FileSystem::pathtoUNC(longPath);
|
||||||
|
// printf( "XXXXXXXXXXXX %s %d\n", new_long, mem_reserved);
|
||||||
|
|
||||||
|
QCOMPARE(new_long, longPathConv);
|
||||||
|
|
||||||
|
// printf( "YYYYYYYYYYYY %ld\n", strlen(new_long));
|
||||||
|
QCOMPARE(new_long.length(), 286);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_GUILESS_MAIN(TestLongWindowsPath)
|
||||||
|
#include "testlongwinpath.moc"
|
|
@ -8,6 +8,7 @@
|
||||||
#include <QTemporaryDir>
|
#include <QTemporaryDir>
|
||||||
|
|
||||||
#include "common/utility.h"
|
#include "common/utility.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
using namespace OCC::Utility;
|
using namespace OCC::Utility;
|
||||||
|
|
||||||
|
@ -114,22 +115,20 @@ private slots:
|
||||||
|
|
||||||
void testVersionOfInstalledBinary()
|
void testVersionOfInstalledBinary()
|
||||||
{
|
{
|
||||||
if( isLinux() ) {
|
if (isLinux()) {
|
||||||
if ( qgetenv("DISPLAY").isEmpty() ) {
|
// pass the cmd client from our build dir
|
||||||
// Current requires an X-Server
|
// this is a bit inaccurate as it does not test the "real thing"
|
||||||
return;
|
// but cmd and gui have the same --version handler by now
|
||||||
}
|
// and cmd works without X in CI
|
||||||
// pass the binary name owncloud to the next call. This brakes branding,
|
QString ver = versionOfInstalledBinary(QStringLiteral(OWNCLOUD_BIN_PATH "/" APPLICATION_EXECUTABLE "cmd"));
|
||||||
// but branding is not supposed to work with this.
|
qDebug() << "Version of installed Nextcloud: " << ver;
|
||||||
QString ver = versionOfInstalledBinary(OWNCLOUD_BIN_PATH+QLatin1String("/nextcloud"));
|
QVERIFY(!ver.isEmpty());
|
||||||
qDebug() << "Version of installed Nextcloud: " << ver;
|
|
||||||
QVERIFY( !ver.isEmpty());
|
|
||||||
|
|
||||||
QRegExp rx( R"(Nextcloud version \d+\.\d+\.\d+.*)" );
|
QRegExp rx(APPLICATION_SHORTNAME R"( version \d+\.\d+\.\d+.*)");
|
||||||
QVERIFY( rx.exactMatch(ver));
|
QVERIFY(rx.exactMatch(ver));
|
||||||
} else {
|
} else {
|
||||||
QVERIFY( versionOfInstalledBinary().isEmpty());
|
QVERIFY(versionOfInstalledBinary().isEmpty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void testTimeAgo()
|
void testTimeAgo()
|
||||||
|
|
Loading…
Reference in a new issue