[Libreoffice-commits] online.git: loolwsd/Storage.cpp

Pranav Kant pranavk at collabora.co.uk
Fri Nov 11 14:39:29 UTC 2016


 loolwsd/Storage.cpp |  106 +++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 80 insertions(+), 26 deletions(-)

New commits:
commit bde2b14679df126972e2d01065d78ada11c156ce
Author: Pranav Kant <pranavk at collabora.co.uk>
Date:   Fri Nov 11 20:02:29 2016 +0530

    loolwsd: Use Levenshtein distance to tolerate mis-spells
    
    ... case sensitiveness and wrong types.
    
    Change-Id: I3ce59c551722138f7e5cb0f00ebcdcb8682e7d0b

diff --git a/loolwsd/Storage.cpp b/loolwsd/Storage.cpp
index c58b1bf..37098b9 100644
--- a/loolwsd/Storage.cpp
+++ b/loolwsd/Storage.cpp
@@ -10,6 +10,7 @@
 #include "Storage.hpp"
 #include "config.h"
 
+#include <algorithm>
 #include <cassert>
 #include <fstream>
 #include <string>
@@ -17,6 +18,7 @@
 #include <Poco/JSON/Object.h>
 #include <Poco/JSON/Parser.h>
 #include <Poco/Net/DNS.h>
+#include <Poco/Exception.h>
 #include <Poco/Net/HTTPClientSession.h>
 #include <Poco/Net/HTTPRequest.h>
 #include <Poco/Net/HTTPResponse.h>
@@ -278,12 +280,74 @@ Poco::Net::HTTPClientSession* getHTTPClientSession(const Poco::URI& uri)
                        : new Poco::Net::HTTPClientSession(uri.getHost(), uri.getPort());
 }
 
-Poco::Dynamic::Var getOrWarn(const Poco::JSON::Object::Ptr &object, const char *key)
+int getLevenshteinDist(const std::string& string1, const std::string& string2) {
+    int matrix[string1.size() + 1][string2.size() + 1];
+
+    for (size_t i = 0; i < string1.size() + 1; i++)
+    {
+        for (size_t j = 0; j < string2.size() + 1; j++)
+        {
+            if (i == 0)
+            {
+                matrix[i][j] = j;
+            }
+            else if (j == 0)
+            {
+                matrix[i][j] = i;
+            }
+            else if (string1[i - 1] == string2[j - 1])
+            {
+                matrix[i][j] = matrix[i - 1][j - 1];
+            }
+            else
+            {
+                matrix[i][j] = 1 + std::min(std::min(matrix[i][j - 1], matrix[i - 1][j]),
+                                            matrix[i - 1][j - 1]);
+            }
+        }
+    }
+
+    return matrix[string1.size()][string2.size()];
+}
+
+template <typename T>
+void getWOPIValue(const Poco::JSON::Object::Ptr &object, const std::string& key, T& value)
 {
-    const auto value = object->get(key);
-    if (value.isEmpty())
-        Log::error("Missing JSON property: '" + std::string(key) + "'");
-    return value;
+    std::vector<std::string> propertyNames;
+    object->getNames(propertyNames);
+
+    // Check each property name against given key
+    // and accept with a mis-spell tolerance of 2
+    // TODO: propertyNames can be pruned after getting its value
+    for (const auto& userInput: propertyNames)
+    {
+        std::string string1(key), string2(userInput);
+        std::transform(key.begin(), key.end(), string1.begin(), tolower);
+        std::transform(userInput.begin(), userInput.end(), string2.begin(), tolower);
+        int levDist = getLevenshteinDist(string1, string2);
+
+        if (levDist > 2) /* Mis-spelling tolerance */
+            continue;
+        else if (levDist > 0 || key != userInput)
+        {
+            LOG_WRN("Incorrect JSON property [" << userInput << "]. Automatically corrected to " << key);
+        }
+
+        try
+        {
+            const Poco::Dynamic::Var valueVar = object->get(userInput);
+            value = valueVar.convert<T>();
+        }
+        catch (const Poco::Exception& exc)
+        {
+            LOG_ERR("getWOPIValue: " << exc.displayText() <<
+                    (exc.nested() ? " (" + exc.nested()->displayText() + ")" : ""));
+        }
+
+        return;
+    }
+
+    LOG_WRN("Missing JSON property [" << key << "]");
 }
 
 } // anonymous namespace
@@ -336,27 +400,17 @@ WopiStorage::WOPIFileInfo WopiStorage::getWOPIFileInfo(const Poco::URI& uriPubli
         Poco::JSON::Parser parser;
         const auto result = parser.parse(stringJSON);
         const auto& object = result.extract<Poco::JSON::Object::Ptr>();
-        filename = getOrWarn(object, "BaseFileName").toString();
-        const auto sizeVar = getOrWarn(object, "Size");
-        size = std::stoul(sizeVar.toString(), nullptr, 0);
-        const auto ownerIdVar = getOrWarn(object, "OwnerId");
-        ownerId = (ownerIdVar.isString() ? ownerIdVar.toString() : "");
-        const auto userIdVar = getOrWarn(object, "UserId");
-        userId = (userIdVar.isString() ? userIdVar.toString() : "");
-        const auto userNameVar = getOrWarn(object,"UserFriendlyName");
-        userName = (userNameVar.isString() ? userNameVar.toString() : "anonymous");
-        const auto canWriteVar = getOrWarn(object, "UserCanWrite");
-        canWrite = canWriteVar.isBoolean() ? canWriteVar.convert<bool>() : false;
-        const auto postMessageOriginVar = getOrWarn(object, "PostMessageOrigin");
-        postMessageOrigin = postMessageOriginVar.isString() ? postMessageOriginVar.toString() : "";
-        const auto hidePrintOptionVar = getOrWarn(object, "HidePrintOption");
-        hidePrintOption = hidePrintOptionVar.isBoolean() ? hidePrintOptionVar.convert<bool>() : false;
-        const auto hideSaveOptionVar = getOrWarn(object, "HideSaveOption");
-        hideSaveOption = hideSaveOptionVar.isBoolean() ? hideSaveOptionVar.convert<bool>() : false;
-        const auto hideExportOptionVar = getOrWarn(object, "HideExportOption");
-        hideExportOption = hideExportOptionVar.isBoolean() ? hideExportOptionVar.convert<bool>() : false;
-        const auto enableOwnerTerminationVar = getOrWarn(object, "EnableOwnerTermination");
-        enableOwnerTermination = enableOwnerTerminationVar.isBoolean() ? enableOwnerTerminationVar.convert<bool>() : false;
+        getWOPIValue(object, "BaseFileName", filename);
+        getWOPIValue(object, "Size", size);
+        getWOPIValue(object, "OwnerId", ownerId);
+        getWOPIValue(object, "UserId", userId);
+        getWOPIValue(object, "UserFriendlyName", userName);
+        getWOPIValue(object, "UserCanWrite", canWrite);
+        getWOPIValue(object, "PostMessageOrigin", postMessageOrigin);
+        getWOPIValue(object, "HidePrintOption", hidePrintOption);
+        getWOPIValue(object, "HideSaveOption", hideSaveOption);
+        getWOPIValue(object, "HideExportOption", hideExportOption);
+        getWOPIValue(object, "EnableOwnerTermination", enableOwnerTermination);
     }
     else
         Log::error("WOPI::CheckFileInfo is missing JSON payload");


More information about the Libreoffice-commits mailing list