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)
{
// TODO: Qt 5.15 bool QFile::moveToTrash()
#if defined Q_OS_UNIX && !defined Q_OS_MAC
QString trashPath, trashFilePath, trashInfoPath;
QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME"));
@ -497,33 +498,26 @@ bool FileSystem::isJunction(const QString &filename)
#endif
}
QString FileSystem::pathtoUNC(const QString &str)
#ifdef Q_OS_WIN
QString FileSystem::pathtoUNC(const QString &_str)
{
int len = 0;
QString longStr;
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.
if (_str.isEmpty()) {
return _str;
}
longStr += str;
const QString str = QDir::toNativeSeparators(_str);
const QLatin1Char sep('\\');
/* replace all occurences of / with the windows native \ */
for (auto &c : longStr) {
if (c == QLatin1Char('/')) {
c = QLatin1Char('\\');
}
// we already have a unc path
if (str.startsWith(sep + sep)) {
return str;
}
return longStr;
// prepend \\?\ and to support long names
if (str.at(0) == sep) {
return QStringLiteral(R"(\\?)") + str;
}
return QStringLiteral(R"(\\?\)") + str;
}
#endif
} // namespace OCC

View file

@ -128,6 +128,19 @@ namespace FileSystem {
* Returns the file system used at the given 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
/**
@ -144,19 +157,6 @@ namespace FileSystem {
* Returns whether the file is a junction (windows only)
*/
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);
QSettings settings(runPath, QSettings::NativeFormat);
if (enable) {
settings.setValue(appName, QCoreApplication::applicationFilePath().replace(QLatin1Char('/'), QLatin1Char('\\')));
settings.setValue(appName, QDir::toNativeSeparators(QCoreApplication::applicationFilePath()));
} else {
settings.remove(appName);
}

View file

@ -158,24 +158,24 @@ public:
* If the remote metadata changes, the local placeholder's metadata should possibly
* 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.
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.
*
* This is different from delete+create because preserving some file metadata
* (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.
*
* For instance cfapi vfs wants local hydrated non-placeholder files to
* 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.
*
@ -190,13 +190,13 @@ public:
* new placeholder shall supersede, for rename-replace actions with new downloads,
* for example.
*/
virtual void convertToPlaceholder(
virtual Q_REQUIRED_RESULT Result<void, QString> convertToPlaceholder(
const QString &filename,
const SyncFileItem &item,
const QString &replacesFile = QString()) = 0;
/// 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.
*
@ -205,7 +205,7 @@ public:
*
* 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.
*
@ -216,7 +216,7 @@ public:
*
* 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.
*
@ -227,7 +227,7 @@ public:
*
* 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.
*
@ -236,7 +236,7 @@ public:
*
* 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:
/** 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> createPlaceholder(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 isDehydratedPlaceholder(const QString &) override { return false; }

View file

@ -1260,6 +1260,7 @@ void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction dir, std::functio
}
setSyncPaused(oldPaused);
});
connect(this, &Folder::destroyed, msgBox, &QMessageBox::deleteLater);
msgBox->open();
}

View file

@ -161,7 +161,10 @@ GeneralSettings::GeneralSettings(QWidget *parent)
_ui->autostartCheckBox->setDisabled(true);
_ui->autostartCheckBox->setToolTip(tr("You cannot disable autostart because system-wide autostart is enabled."));
} 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);
}

View file

@ -90,9 +90,8 @@ QNetworkReply *AccessManager::createRequest(QNetworkAccessManager::Operation op,
}
#endif
HttpLogger::logRequest(newRequest, op, outgoingData);
const auto reply = QNetworkAccessManager::createRequest(op, newRequest, outgoingData);
HttpLogger::logReplyOnFinished(reply);
HttpLogger::logRequest(reply, op, outgoingData);
return reply;
}

View file

@ -42,22 +42,17 @@ bool FileSystem::fileEquals(const QString &fn1, const QString &fn2)
}
const int BufferSize = 16 * 1024;
char buffer1[BufferSize];
char buffer2[BufferSize];
do {
int r = f1.read(buffer1, BufferSize);
if (f2.read(buffer2, BufferSize) != r) {
// this should normally not happen: the files are supposed to have the same size.
QByteArray buffer1(BufferSize, 0);
QByteArray buffer2(BufferSize, 0);
// the files have the same size, compare all of it
while(!f1.atEnd()){
f1.read(buffer1.data(), BufferSize);
f2.read(buffer2.data(), BufferSize);
if (buffer1 != buffer2) {
return false;
}
if (r <= 0) {
return true;
}
if (memcmp(buffer1, buffer2, r) != 0) {
return false;
}
} while (true);
return false;
};
return true;
}
time_t FileSystem::getModTime(const QString &filename)
@ -130,7 +125,7 @@ qint64 FileSystem::getSize(const QString &filename)
{
#ifdef Q_OS_WIN
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);
}
#endif

View file

@ -53,7 +53,8 @@ void logHttp(const QByteArray &verb, const QString &url, const QByteArray &id, c
for (const auto &it : header) {
stream << it.first << ": ";
if (it.first == "Authorization") {
stream << "[redacted]";
stream << (it.second.startsWith("Bearer ") ? "Bearer" : "Basic");
stream << " [redacted]";
} else {
stream << it.second;
}
@ -85,24 +86,9 @@ void logHttp(const QByteArray &verb, const QString &url, const QByteArray &id, c
namespace OCC {
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)
void HttpLogger::logRequest(QNetworkReply *reply, QNetworkAccessManager::Operation operation, QIODevice *device)
{
const auto request = reply->request();
if (!lcNetworkHttp().isInfoEnabled()) {
return;
}
@ -118,6 +104,15 @@ void HttpLogger::logRequest(const QNetworkRequest &request, QNetworkAccessManage
request.header(QNetworkRequest::ContentTypeHeader).toString(),
header,
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)

View file

@ -20,8 +20,7 @@
namespace OCC {
namespace HttpLogger {
void OWNCLOUDSYNC_EXPORT logReplyOnFinished(const QNetworkReply *reply);
void OWNCLOUDSYNC_EXPORT logRequest(const QNetworkRequest &request, QNetworkAccessManager::Operation operation, QIODevice *device);
void OWNCLOUDSYNC_EXPORT logRequest(QNetworkReply *reply, QNetworkAccessManager::Operation operation, QIODevice *device);
/**
* 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)
{
QString fsPath = localFolderPath + item.destination();
vfs.convertToPlaceholder(fsPath, item);
if (!vfs.convertToPlaceholder(fsPath, item)) {
return false;
}
auto record = item.toSyncJournalFileRecordWithInode(fsPath);
return journal.setFileRecord(record);
}

View file

@ -964,7 +964,11 @@ void PropagateDownloadFile::downloadFinished()
preserveGroupOwnership(_tmpFile.fileName(), existingFile);
// 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

View file

@ -346,7 +346,12 @@ void OCC::SyncEngine::slotItemDiscovered(const OCC::SyncFileItemPtr &item)
// Ensure it's a placeholder file on disk
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
@ -732,10 +737,11 @@ void SyncEngine::slotDiscoveryFinished()
}
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...
if (!guard)
{
// qpointer to self to ensure we still exist
if (!guard || !self) {
return;
}
guard->deleteLater();

View file

@ -149,16 +149,16 @@ Result<void, QString> VfsCfApi::dehydratePlaceholder(const SyncFileItem &item)
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 replacesPath = QDir::toNativeSeparators(replacesFile);
const auto handle = cfapi::handleForPath(localPath);
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 {
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> 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 isDehydratedPlaceholder(const QString &filePath) override;

View file

@ -122,9 +122,10 @@ Result<void, QString> VfsSuffix::dehydratePlaceholder(const SyncFileItem &item)
return {};
}
void VfsSuffix::convertToPlaceholder(const QString &, const SyncFileItem &, const QString &)
Result<void, QString> VfsSuffix::convertToPlaceholder(const QString &, const SyncFileItem &, const QString &)
{
// Nothing necessary
return {};
}
bool VfsSuffix::isDehydratedPlaceholder(const QString &filePath)

View file

@ -41,7 +41,7 @@ public:
Result<void, QString> createPlaceholder(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 isDehydratedPlaceholder(const QString &filePath) override;

View file

@ -74,6 +74,7 @@ if( UNIX AND NOT APPLE )
endif(UNIX AND NOT APPLE)
if (WIN32)
nextcloud_add_test(LongWinPath "")
nextcloud_add_test(SyncCfApi "")
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
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 "common/utility.h"
#include "config.h"
using namespace OCC::Utility;
@ -114,22 +115,20 @@ private slots:
void testVersionOfInstalledBinary()
{
if( isLinux() ) {
if ( qgetenv("DISPLAY").isEmpty() ) {
// Current requires an X-Server
return;
}
// pass the binary name owncloud to the next call. This brakes branding,
// but branding is not supposed to work with this.
QString ver = versionOfInstalledBinary(OWNCLOUD_BIN_PATH+QLatin1String("/nextcloud"));
qDebug() << "Version of installed Nextcloud: " << ver;
QVERIFY( !ver.isEmpty());
if (isLinux()) {
// pass the cmd client from our build dir
// this is a bit inaccurate as it does not test the "real thing"
// but cmd and gui have the same --version handler by now
// and cmd works without X in CI
QString ver = versionOfInstalledBinary(QStringLiteral(OWNCLOUD_BIN_PATH "/" APPLICATION_EXECUTABLE "cmd"));
qDebug() << "Version of installed Nextcloud: " << ver;
QVERIFY(!ver.isEmpty());
QRegExp rx( R"(Nextcloud version \d+\.\d+\.\d+.*)" );
QVERIFY( rx.exactMatch(ver));
} else {
QVERIFY( versionOfInstalledBinary().isEmpty());
}
QRegExp rx(APPLICATION_SHORTNAME R"( version \d+\.\d+\.\d+.*)");
QVERIFY(rx.exactMatch(ver));
} else {
QVERIFY(versionOfInstalledBinary().isEmpty());
}
}
void testTimeAgo()