Просмотр исходного кода

RemotePermissions: Fix empty vs null

Fixes two bugs that appeared since the introduction of the struct:
- when reading permissions from the journal, null ("") was read as
  empty-not-null
- when reading permissinos from the server, empty ("") was read as null

Addresses #4608
Christian Kamm 7 лет назад
Родитель
Сommit
be0fa72fcb

+ 23 - 12
src/common/remotepermissions.cpp

@@ -27,7 +27,7 @@ static const char letters[] = " WDNVCKRSMm";
 template <typename Char>
 void RemotePermissions::fromArray(const Char *p)
 {
-    _value = p ? notNullMask : 0;
+    _value = notNullMask;
     if (!p)
         return;
     while (*p) {
@@ -37,17 +37,7 @@ void RemotePermissions::fromArray(const Char *p)
     }
 }
 
-RemotePermissions::RemotePermissions(const char *p)
-{
-    fromArray(p);
-}
-
-RemotePermissions::RemotePermissions(const QString &s)
-{
-    fromArray(s.isEmpty() ? nullptr : s.utf16());
-}
-
-QByteArray RemotePermissions::toString() const
+QByteArray RemotePermissions::toDbValue() const
 {
     QByteArray result;
     if (isNull())
@@ -64,4 +54,25 @@ QByteArray RemotePermissions::toString() const
     return result;
 }
 
+QByteArray RemotePermissions::toString() const
+{
+    return toDbValue();
+}
+
+RemotePermissions RemotePermissions::fromDbValue(const QByteArray &value)
+{
+    if (value.isEmpty())
+        return RemotePermissions();
+    RemotePermissions perm;
+    perm.fromArray(value.constData());
+    return perm;
+}
+
+RemotePermissions RemotePermissions::fromServerString(const QString &value)
+{
+    RemotePermissions perm;
+    perm.fromArray(value.utf16());
+    return perm;
+}
+
 } // namespace OCC

+ 13 - 2
src/common/remotepermissions.h

@@ -58,11 +58,22 @@ public:
         // (by setting forceRemoteDiscovery in SyncJournalDb::checkConnect)
         PermissionsCount = IsMountedSub
     };
+
+    /// null permissions
     RemotePermissions() = default;
-    explicit RemotePermissions(const char *);
-    explicit RemotePermissions(const QString &);
 
+    /// array with one character per permission, "" is null, " " is non-null but empty
+    QByteArray toDbValue() const;
+
+    /// output for display purposes, no defined format (same as toDbValue in practice)
     QByteArray toString() const;
+
+    /// read value that was written with toDbValue()
+    static RemotePermissions fromDbValue(const QByteArray &);
+
+    /// read a permissions string received from the server, never null
+    static RemotePermissions fromServerString(const QString &);
+
     bool hasPermission(Permissions p) const
     {
         return _value & (1 << static_cast<int>(p));

+ 1 - 1
src/common/syncjournaldb.cpp

@@ -58,7 +58,7 @@ static void fillFileRecordFromGetQuery(SyncJournalFileRecord &rec, SqlQuery &que
     rec._type = static_cast<ItemType>(query.intValue(3));
     rec._etag = query.baValue(4);
     rec._fileId = query.baValue(5);
-    rec._remotePerm = RemotePermissions(query.baValue(6).constData());
+    rec._remotePerm = RemotePermissions::fromDbValue(query.baValue(6));
     rec._fileSize = query.int64Value(7);
     rec._serverHasIgnoredFiles = (query.intValue(8) > 0);
     rec._checksumHeader = query.baValue(9);

+ 2 - 2
src/libsync/discoveryphase.cpp

@@ -239,7 +239,7 @@ static void propertyMapToFileStat(const QMap<QString, QString> &map, RemoteInfo
         } else if (property == "dDC") {
             result.directDownloadCookies = value;
         } else if (property == "permissions") {
-            result.remotePerm = RemotePermissions(value);
+            result.remotePerm = RemotePermissions::fromServerString(value);
         } else if (property == "checksums") {
             result.checksumHeader = findBestChecksum(value.toUtf8());
         } else if (property == "share-types" && !value.isEmpty()) {
@@ -263,7 +263,7 @@ void DiscoverySingleDirectoryJob::directoryListingIteratedSlot(QString file, con
         // The first entry is for the folder itself, we should process it differently.
         _ignoredFirst = true;
         if (map.contains("permissions")) {
-            RemotePermissions perm(map.value("permissions"));
+            auto perm = RemotePermissions::fromServerString(map.value("permissions"));
             emit firstDirectoryPermissions(perm);
             _isExternalStorage = perm.hasPermission(RemotePermissions::IsMounted);
         }

+ 1 - 1
test/testpermissions.cpp

@@ -16,7 +16,7 @@ static void applyPermissionsFromName(FileInfo &info) {
     static QRegularExpression rx("_PERM_([^_]*)_[^/]*$");
     auto m = rx.match(info.name);
     if (m.hasMatch()) {
-        info.permissions = RemotePermissions(m.captured(1));
+        info.permissions = RemotePermissions::fromServerString(m.captured(1));
     }
 
     for (FileInfo &sub : info.children)

+ 4 - 4
test/testsyncjournaldb.cpp

@@ -57,7 +57,7 @@ private slots:
         record._type = ItemTypeDirectory;
         record._etag = "789789";
         record._fileId = "abcd";
-        record._remotePerm = RemotePermissions("RW");
+        record._remotePerm = RemotePermissions::fromDbValue("RW");
         record._fileSize = 213089055;
         record._checksumHeader = "MD5:mychecksum";
         QVERIFY(_db.setFileRecord(record));
@@ -79,7 +79,7 @@ private slots:
         record._type = ItemTypeFile;
         record._etag = "789FFF";
         record._fileId = "efg";
-        record._remotePerm = RemotePermissions("NV");
+        record._remotePerm = RemotePermissions::fromDbValue("NV");
         record._fileSize = 289055;
         _db.setFileRecordMetadata(record);
         QVERIFY(_db.getFileRecord(QByteArrayLiteral("foo"), &storedRecord));
@@ -96,7 +96,7 @@ private slots:
         {
             SyncJournalFileRecord record;
             record._path = "foo-checksum";
-            record._remotePerm = RemotePermissions("RW");
+            record._remotePerm = RemotePermissions::fromDbValue(" ");
             record._checksumHeader = "MD5:mychecksum";
             record._modtime = Utility::qDateTimeToTime_t(QDateTime::currentDateTimeUtc());
             QVERIFY(_db.setFileRecord(record));
@@ -117,7 +117,7 @@ private slots:
         {
             SyncJournalFileRecord record;
             record._path = "foo-nochecksum";
-            record._remotePerm = RemotePermissions("RWN");
+            record._remotePerm = RemotePermissions();
             record._modtime = Utility::qDateTimeToTime_t(QDateTime::currentDateTimeUtc());
 
             QVERIFY(_db.setFileRecord(record));