wsd/DocumentBroker.cpp |   54 ++++++++++++++++++++++++++++++++++++++++++++++++-
 wsd/LOOLWSD.cpp        |   31 ++++++++++++++++++++++++++++
 wsd/LOOLWSD.hpp        |    4 +++
 wsd/Storage.hpp        |    8 +++++++
 4 files changed, 96 insertions(+), 1 deletion(-)

New commits:
commit 7c77a6c3a33fea7810275649465635ebd0fda2bf
Author: Tor Lillqvist <t...@collabora.com>
Date:   Tue Nov 7 15:15:36 2017 +0200

    Add handling of "prefilter" plug-ins
    
    When the name of a document to be edited ends with an extension
    matching that mentioned in a prefilter plug-in's configuration file,
    the command specified is run and it is the output file that is
    actually edited.

diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 45396631..69cd515b 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -19,6 +19,7 @@
 #include <sstream>
 
 #include <Poco/DigestStream.h>
+#include <Poco/Exception.h>
 #include <Poco/JSON/Object.h>
 #include <Poco/Path.h>
 #include <Poco/SHA1Engine.h>
@@ -559,7 +560,58 @@ bool DocumentBroker::load(const 
std::shared_ptr<ClientSession>& session, const s
     // Let's load the document now, if not loaded.
     if (!_storage->isLoaded())
     {
-        const auto localPath = 
_storage->loadStorageFileToLocal(session->getAuthorization());
+        auto localPath = 
_storage->loadStorageFileToLocal(session->getAuthorization());
+
+        // Check if we have a prefilter "plugin" for this document format
+        for (const auto& plugin : LOOLWSD::PluginConfigurations)
+        {
+            try
+            {
+                std::string 
extension(plugin->getString("prefilter.extension"));
+                std::string 
newExtension(plugin->getString("prefilter.newextension"));
+                std::string 
commandLine(plugin->getString("prefilter.commandline"));
+
+                if (localPath.length() > extension.length()+1 &&
+                    strcasecmp(localPath.substr(localPath.length() - 
extension.length() -1).data(), (std::string(".") + extension).data()) == 0)
+                {
+                    // Extension matches, try the conversion. We convert the 
file to another one in
+                    // the same (jail) directory, with just the new extension 
tacked on.
+
+                    std::string newRootPath = _storage->getRootFilePath() + 
"." + newExtension;
+
+                    // The commandline must contain the space-separated 
substring @INPUT@ that is
+                    // replaced with the input file name, and @OUTPUT@ for the 
output file name.
+
+                    std::vector<std::string>args;
+
+                    Poco::StringTokenizer tokenizer(commandLine, " ");
+                    if (tokenizer.replace("@INPUT@", 
_storage->getRootFilePath()) != 1 ||
+                        tokenizer.replace("@OUTPUT@", newRootPath) != 1)
+                        throw Poco::NotFoundException();
+
+                    for (std::size_t i = 1; i < tokenizer.count(); i++)
+                        args.push_back(tokenizer[i]);
+
+                    Poco::ProcessHandle process = 
Poco::Process::launch(tokenizer[0], args);
+                    int rc = process.wait();
+                    if (rc != 0)
+                    {
+                        LOG_ERR("Conversion from " << extension << " to " << 
newExtension <<" failed");
+                        return false;
+                    }
+                    _storage->setRootFilePath(newRootPath);
+                    localPath += "." + newExtension;
+                }
+
+                // We successfully converted the file to something LO can use; 
break out of the for
+                // loop.
+                break;
+            }
+            catch (const Poco::NotFoundException&)
+            {
+                // This plugin is not a proper prefilter one
+            }
+        }
 
         std::ifstream istr(localPath, std::ios::binary);
         Poco::SHA1Engine sha1;
diff --git a/wsd/Storage.hpp b/wsd/Storage.hpp
index 52df9d14..c4aff64f 100644
--- a/wsd/Storage.hpp
+++ b/wsd/Storage.hpp
@@ -131,6 +131,14 @@ public:
     /// Returns the root path to the jailed file.
     const std::string& getRootFilePath() const { return _jailedFilePath; };
 
+    /// Set the root path of the jailed file, only for use in cases where we 
actually have converted
+    /// it to another format, in the same directory
+    void setRootFilePath(const std::string& newPath)
+    {
+        // Could assert here that it is in the same directory?
+        _jailedFilePath = newPath;
+    };
+
     bool isLoaded() const { return _isLoaded; }
 
     /// Asks the storage object to force overwrite to storage upon next save
commit 0831a942998144b606bea9c75a1cfe1bc165eff3
Author: Tor Lillqvist <t...@collabora.com>
Date:   Tue Nov 7 15:12:18 2017 +0200

    Add a "plug-in" mechanism
    
    Look in the directory LOOLWSD_CONFIGDIR/conf.d (or pathname passed
    with --config-dir option) for extra .xml files containing a Poco
    configuration tree. These are not merged with the actual configuration
    but kept separate. This commit does not yet actually use them for
    anything.

diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 83436634..f73f81f3 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -54,6 +54,7 @@
 #include <Poco/DOM/Element.h>
 #include <Poco/DOM/NodeList.h>
 #include <Poco/DateTimeFormatter.h>
+#include <Poco/DirectoryIterator.h>
 #include <Poco/Environment.h>
 #include <Poco/Exception.h>
 #include <Poco/File.h>
@@ -78,12 +79,14 @@
 #include <Poco/TemporaryFile.h>
 #include <Poco/ThreadPool.h>
 #include <Poco/URI.h>
+#include <Poco/Util/AbstractConfiguration.h>
 #include <Poco/Util/HelpFormatter.h>
 #include <Poco/Util/MapConfiguration.h>
 #include <Poco/Util/Option.h>
 #include <Poco/Util/OptionException.h>
 #include <Poco/Util/OptionSet.h>
 #include <Poco/Util/ServerApplication.h>
+#include <Poco/Util/XMLConfiguration.h>
 
 #include "Admin.hpp"
 #include "Auth.hpp"
@@ -121,6 +124,7 @@
 
 using namespace LOOLProtocol;
 
+using Poco::DirectoryIterator;
 using Poco::Environment;
 using Poco::Exception;
 using Poco::File;
@@ -153,6 +157,7 @@ using Poco::Util::MissingOptionException;
 using Poco::Util::Option;
 using Poco::Util::OptionSet;
 using Poco::Util::ServerApplication;
+using Poco::Util::XMLConfiguration;
 using Poco::XML::AutoPtr;
 using Poco::XML::DOMParser;
 using Poco::XML::DOMWriter;
@@ -557,12 +562,14 @@ std::string LOOLWSD::ServerName;
 std::string LOOLWSD::FileServerRoot;
 std::string LOOLWSD::LOKitVersion;
 std::string LOOLWSD::ConfigFile = LOOLWSD_CONFIGDIR "/loolwsd.xml";
+std::string LOOLWSD::ConfigDir = LOOLWSD_CONFIGDIR "/conf.d";
 Util::RuntimeConstant<bool> LOOLWSD::SSLEnabled;
 Util::RuntimeConstant<bool> LOOLWSD::SSLTermination;
 std::set<std::string> LOOLWSD::EditFileExtensions;
 unsigned LOOLWSD::MaxConnections;
 unsigned LOOLWSD::MaxDocuments;
 std::string LOOLWSD::OverrideWatermark;
+std::set<const Poco::Util::AbstractConfiguration*> 
LOOLWSD::PluginConfigurations;
 
 static std::string UnitTestLibrary;
 
@@ -687,6 +694,23 @@ void LOOLWSD::initialize(Application& self)
         loadConfiguration(ConfigFile, PRIO_DEFAULT);
     }
 
+    // Load extra ("plug-in") configuration files, if present
+    File dir(ConfigDir);
+    if (dir.exists() && dir.isDirectory())
+    {
+        for (auto configFileIterator = DirectoryIterator(dir); 
configFileIterator != DirectoryIterator(); ++configFileIterator)
+        {
+            // Only accept configuration files ending in .xml
+            const std::string configFile = 
configFileIterator.path().getFileName();
+            if (configFile.length() > 4 && 
strcasecmp(configFile.substr(configFile.length() - 4).data(), ".xml") == 0)
+            {
+                const std::string fullFileName = dir.path() + "/" + configFile;
+                std::cerr << "Trying '" << fullFileName << "'" << std::endl;
+                PluginConfigurations.insert(new 
XMLConfiguration(fullFileName));
+            }
+        }
+    }
+
     // Override any settings passed on the command-line.
     AutoPtr<AppConfigMap> overrideConfig(new AppConfigMap(_overrideSettings));
     conf.addWriteable(overrideConfig, PRIO_APPLICATION); // Highest priority
@@ -999,6 +1023,11 @@ void LOOLWSD::defineOptions(OptionSet& optionSet)
                         .repeatable(false)
                         .argument("path"));
 
+    optionSet.addOption(Option("config-dir", "", "Override extra configuration 
directory path.")
+                        .required(false)
+                        .repeatable(false)
+                        .argument("path"));
+
 #if ENABLE_DEBUG
     optionSet.addOption(Option("unitlib", "", "Unit testing library path.")
                         .required(false)
@@ -1051,6 +1080,8 @@ void LOOLWSD::handleOption(const std::string& optionName,
     }
     else if (optionName == "config-file")
         ConfigFile = value;
+    else if (optionName == "config-dir")
+        ConfigDir = value;
 #if ENABLE_DEBUG
     else if (optionName == "unitlib")
         UnitTestLibrary = value;
diff --git a/wsd/LOOLWSD.hpp b/wsd/LOOLWSD.hpp
index c61956a1..40a32b73 100644
--- a/wsd/LOOLWSD.hpp
+++ b/wsd/LOOLWSD.hpp
@@ -12,10 +12,12 @@
 
 #include <atomic>
 #include <map>
+#include <set>
 #include <string>
 
 #include <Poco/Path.h>
 #include <Poco/Process.h>
+#include <Poco/Util/AbstractConfiguration.h>
 #include <Poco/Util/OptionSet.h>
 #include <Poco/Util/ServerApplication.h>
 
@@ -46,6 +48,7 @@ public:
     static std::string FuzzFileName;
     static std::string Cache;
     static std::string ConfigFile;
+    static std::string ConfigDir;
     static std::string SysTemplate;
     static std::string LoTemplate;
     static std::string ChildRoot;
@@ -59,6 +62,7 @@ public:
     static unsigned MaxConnections;
     static unsigned MaxDocuments;
     static std::string OverrideWatermark;
+    static std::set<const Poco::Util::AbstractConfiguration*> 
PluginConfigurations;
 
     static std::vector<int> getKitPids();
 
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to