Merge pull request #2781 from nextcloud/cherry_pick_2020_w53

Cherry pick 2020 w53
This commit is contained in:
Kevin Ottens 2020-12-30 19:00:19 +01:00 committed by GitHub
commit fbd9f5126c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 199 additions and 212 deletions

View file

@ -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 { const QString str = QDir::toNativeSeparators(_str);
longStr.append(QStringLiteral("\\\\?\\")); // prepend string by this four magic chars. const QLatin1Char sep('\\');
}
longStr += str;
/* replace all occurences of / with the windows native \ */ // we already have a unc path
if (str.startsWith(sep + sep)) {
return str;
}
// prepend \\?\ and to support long names
for (auto &c : longStr) { if (str.at(0) == sep) {
if (c == QLatin1Char('/')) { return QStringLiteral(R"(\\?)") + str;
c = QLatin1Char('\\');
} }
} return QStringLiteral(R"(\\?\)") + str;
return longStr;
} }
#endif
} // namespace OCC } // namespace OCC

View file

@ -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);
} }
/** @} */ /** @} */

View file

@ -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);
} }

View file

@ -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; }

View file

@ -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();
} }

View file

@ -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);
} }

View file

@ -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;
} }

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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);
} }

View file

@ -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

View file

@ -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();

View file

@ -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);
} }
} }

View file

@ -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;

View file

@ -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)

View file

@ -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;

View file

@ -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()

View file

@ -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})

View file

@ -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
View 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"

View file

@ -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,21 +115,19 @@ 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.
QString ver = versionOfInstalledBinary(OWNCLOUD_BIN_PATH+QLatin1String("/nextcloud"));
qDebug() << "Version of installed Nextcloud: " << ver; qDebug() << "Version of installed Nextcloud: " << ver;
QVERIFY( !ver.isEmpty()); 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());
} }
} }