From b2c01ffe21fbf1fc06ef91274fa3ebf5752bac34 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 5 Jan 2015 13:54:31 +0100 Subject: [PATCH] SyncEngine: Show an error when a file name is not encoded with valid UTF-8 ... instead of uploading the file with replacement character, and asserting on the next sync. Issue #2649 If the file or folder on the file system has a name with invalid UTF-8, We would convert the name to utf-8, and the conversion would result in replacement character placeholder. And we would upload that file on the server with that name, and save it with this name on the database. Fix this issue by showing an error to the user for invalid files. --- src/mirall/syncengine.cpp | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/mirall/syncengine.cpp b/src/mirall/syncengine.cpp index c03ed124f0..0f9f398b18 100644 --- a/src/mirall/syncengine.cpp +++ b/src/mirall/syncengine.cpp @@ -45,6 +45,7 @@ #include #include #include +#include namespace Mirall { @@ -314,7 +315,16 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote ) { if( ! file ) return -1; - QString fileUtf8 = QString::fromUtf8( file->path ); + QTextCodec::ConverterState utf8State; + QTextCodec *codec = QTextCodec::codecForName("UTF-8"); + Q_ASSERT(codec); + QString fileUtf8 = codec->toUnicode(file->path, qstrlen(file->path), &utf8State); + + auto instruction = file->instruction; + if (utf8State.invalidChars > 0) { + qDebug() << "File ignored because of invalid utf-8 sequence: " << file->path; + instruction = CSYNC_INSTRUCTION_IGNORE; + } // Gets a default-contructed SyncFileItem or the one from the first walk (=local walk) SyncFileItem item = _syncItemMap.value(fileUtf8); @@ -322,12 +332,12 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote ) item._originalFile = item._file; if (item._instruction == CSYNC_INSTRUCTION_NONE - || (item._instruction == CSYNC_INSTRUCTION_IGNORE && file->instruction != CSYNC_INSTRUCTION_NONE)) { - item._instruction = file->instruction; + || (item._instruction == CSYNC_INSTRUCTION_IGNORE && instruction != CSYNC_INSTRUCTION_NONE)) { + item._instruction = instruction; item._modtime = file->modtime; } else { - if (file->instruction != CSYNC_INSTRUCTION_NONE) { - qDebug() << "ERROR: Instruction" << item._instruction << "vs" << file->instruction << "for" << fileUtf8; + if (instruction != CSYNC_INSTRUCTION_NONE) { + qDebug() << "ERROR: Instruction" << item._instruction << "vs" << instruction << "for" << fileUtf8; Q_ASSERT(!"Instructions are both unequal NONE"); return -1; } @@ -381,6 +391,12 @@ int SyncEngine::treewalkFile( TREE_WALK_FILE *file, bool remote ) /* No error string */ } + if (item._instruction == CSYNC_INSTRUCTION_IGNORE && utf8State.invalidChars > 0) { + item._status = SyncFileItem::NormalError; + //item._instruction = CSYNC_INSTRUCTION_ERROR; + item._errorString = tr("Filename encoding is not valid"); + } + item._isDirectory = file->type == CSYNC_FTW_TYPE_DIR; // The etag is already set in the previous sync phases somewhere. Maybe we should remove it there