From: Olivier Goffart Date: Tue, 10 Jul 2018 14:56:15 +0000 (+0200) Subject: Handle Encoding Problems X-Git-Tag: archive/raspbian/3.16.7-1_deb13u1+rpi1~1^2~12^2~21^2~468^2~560 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=92ddc6090074902ab34319c8b31e6cf9f0ad87bb;p=nextcloud-desktop.git Handle Encoding Problems TestSyncEngine now passes --- diff --git a/src/csync/csync_update.cpp b/src/csync/csync_update.cpp index 4c121503b..dc383f05a 100644 --- a/src/csync/csync_update.cpp +++ b/src/csync/csync_update.cpp @@ -148,21 +148,6 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr f } } - auto localCodec = QTextCodec::codecForLocale(); - if (ctx->current == REMOTE_REPLICA && localCodec->mibEnum() != 106) { - /* If the locale codec is not UTF-8, we must check that the filename from the server can - * be encoded in the local file system. - * - * We cannot use QTextCodec::canEncode() since that can incorrectly return true, see - * https://bugreports.qt.io/browse/QTBUG-6925. - */ - QTextEncoder encoder(localCodec, QTextCodec::ConvertInvalidToNull); - if (encoder.fromUnicode(QString::fromUtf8(fs->path)).contains('\0')) { - qCInfo(lcUpdate, "cannot encode %s to local encoding %d", - fs->path.constData(), localCodec->mibEnum()); - excluded = CSYNC_FILE_EXCLUDE_CANNOT_ENCODE; - } - } if (fs->type == ItemTypeFile ) { if (fs->modtime == 0) { diff --git a/src/libsync/discovery.cpp b/src/libsync/discovery.cpp index 2dec6fdac..8cb2adfe8 100644 --- a/src/libsync/discovery.cpp +++ b/src/libsync/discovery.cpp @@ -19,10 +19,12 @@ #include #include #include +#include #include "vio/csync_vio_local.h" #include "common/checksums.h" #include "csync_exclude.h" + namespace OCC { Q_LOGGING_CATEGORY(lcDisco, "sync.discovery", QtInfoMsg) @@ -97,7 +99,20 @@ void ProcessDirectoryJob::start() } while (auto dirent = csync_vio_local_readdir(dh)) { LocalInfo i; - i.name = QString::fromUtf8(dirent->path); // FIXME! conversion errors + static QTextCodec *codec = QTextCodec::codecForName("UTF-8"); + ASSERT(codec); + QTextCodec::ConverterState state; + i.name = codec->toUnicode(dirent->path, dirent->path.size(), &state); + if (state.invalidChars > 0 || state.remainingChars > 0) { + _childIgnored = true; + auto item = SyncFileItemPtr::create(); + item->_file = _currentFolder + i.name; + item->_instruction = CSYNC_INSTRUCTION_IGNORE; + item->_status = SyncFileItem::NormalError; + item->_errorString = tr("Filename encoding is not valid"); + emit itemDiscovered(item); + continue; + } i.modtime = dirent->modtime; i.size = dirent->size; i.inode = dirent->inode; @@ -194,6 +209,20 @@ bool ProcessDirectoryJob::handleExcluded(const QString &path, bool isDirectory, excluded = CSYNC_FILE_EXCLUDE_HIDDEN; } + auto localCodec = QTextCodec::codecForLocale(); + if (localCodec->mibEnum() != 106) { + // If the locale codec is not UTF-8, we must check that the filename from the server can + // be encoded in the local file system. + // + // We cannot use QTextCodec::canEncode() since that can incorrectly return true, see + // https://bugreports.qt.io/browse/QTBUG-6925. + QTextEncoder encoder(localCodec, QTextCodec::ConvertInvalidToNull); + if (encoder.fromUnicode(path).contains('\0')) { + qCWarning(lcDisco) << "Cannot encode " << path << " to local encoding " << localCodec->name(); + excluded = CSYNC_FILE_EXCLUDE_CANNOT_ENCODE; + } + } + if (excluded == CSYNC_NOT_EXCLUDED /* FIXME && item->_type != ItemTypeSoftLink */) { return false; } else if (excluded == CSYNC_FILE_SILENTLY_EXCLUDED || excluded == CSYNC_FILE_EXCLUDE_AND_REMOVE) { diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp index 31a12dac6..0b26a3ae4 100644 --- a/src/libsync/syncengine.cpp +++ b/src/libsync/syncengine.cpp @@ -387,28 +387,7 @@ int SyncEngine::treewalkFile(csync_file_stat_t * /*file*/, csync_file_stat_t * / // Decode utf8 path and rename_path QByteArrays to QStrings QString fileUtf8; QString renameTarget; - bool utf8DecodeError = false; - { - const auto toUnicode = [](QByteArray utf8, QString *result) { - static QTextCodec *codec = QTextCodec::codecForName("UTF-8"); - ASSERT(codec); - - QTextCodec::ConverterState state; - *result = codec->toUnicode(utf8, utf8.size(), &state); - return !(state.invalidChars > 0 || state.remainingChars > 0); - }; - - if (!toUnicode(file->path, &fileUtf8)) { - qCWarning(lcEngine) << "File ignored because of invalid utf-8 sequence: " << file->path; - instruction = CSYNC_INSTRUCTION_IGNORE; - utf8DecodeError = true; - } - if (!toUnicode(file->rename_path, &renameTarget)) { - qCWarning(lcEngine) << "File ignored because of invalid utf-8 sequence in the rename_path: " << file->path << file->rename_path; - instruction = CSYNC_INSTRUCTION_IGNORE; - utf8DecodeError = true; - } - } + // key is the handle that the SyncFileItem will have in the map. QString key = fileUtf8; @@ -513,11 +492,6 @@ int SyncEngine::treewalkFile(csync_file_stat_t * /*file*/, csync_file_stat_t * / } - if (item->_instruction == CSYNC_INSTRUCTION_IGNORE && utf8DecodeError) { - item->_status = SyncFileItem::NormalError; - //item->_instruction = CSYNC_INSTRUCTION_ERROR; - item->_errorString = tr("Filename encoding is not valid"); - } bool isDirectory = file->type == ItemTypeDirectory;