summaryrefslogtreecommitdiffstats
path: root/wsd
diff options
context:
space:
mode:
Diffstat (limited to 'wsd')
-rw-r--r--wsd/DocumentBroker.cpp4
-rw-r--r--wsd/LOOLWSD.cpp14
-rw-r--r--wsd/LOOLWSD.hpp5
-rw-r--r--wsd/QuarantineUtil.cpp150
-rw-r--r--wsd/QuarantineUtil.hpp27
5 files changed, 198 insertions, 2 deletions
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 42d9f08c5c..ac2489cb80 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -34,6 +34,7 @@
#include "TileCache.hpp"
#include "ProxyProtocol.hpp"
#include "Util.hpp"
+#include "QuarantineUtil.hpp"
#include <common/Log.hpp>
#include <common/Message.hpp>
#include <common/Clipboard.hpp>
@@ -1136,6 +1137,9 @@ void DocumentBroker::handleSaveResponse(const std::string& sessionId, bool succe
// DocBroker will have to decide to upload or skip.
const std::string oldName = _storage->getRootFilePathToUpload();
const std::string newName = _storage->getRootFilePathUploading();
+
+ Quarantine::quarantineFile(this, _storage->getFileInfo().getFilename() + TO_UPLOAD_SUFFIX);
+
if (rename(oldName.c_str(), newName.c_str()) < 0)
{
// It's not an error if there was no file to rename, when the document isn't modified.
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 597b857714..632ad3f6ad 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -887,6 +887,8 @@ static std::string UnitTestLibrary;
unsigned int LOOLWSD::NumPreSpawnedChildren = 0;
std::unique_ptr<TraceFileWriter> LOOLWSD::TraceDumper;
+std::unordered_map<std::string, std::vector<std::string>> LOOLWSD::QuarantineMap;
+std::string LOOLWSD::QuarantinePath;
#if !MOBILEAPP
std::unique_ptr<ClipboardCache> LOOLWSD::SavedClipboards;
#endif
@@ -1125,7 +1127,9 @@ void LOOLWSD::innerInitialize(Application& self)
#ifdef ENABLE_FEATURE_RESTRICTION
{ "restricted_commands", "" },
#endif
- { "user_interface.mode", USER_INTERFACE_MODE }
+ { "user_interface.mode", USER_INTERFACE_MODE },
+ {"quarantine_files.limit_dir_size_mb", "250"},
+ {"quarantine_files.max_versions_to_maintain", "2"}
};
// Set default values, in case they are missing from the config file.
@@ -1453,6 +1457,14 @@ void LOOLWSD::innerInitialize(Application& self)
FileServerRoot = getPathFromConfig("file_server_root_path");
LOG_DBG("FileServerRoot after config: " << FileServerRoot);
+ //creating quarantine directory
+ QuarantinePath = FileServerRoot + "quarantine/";
+ Poco::File p(QuarantinePath);
+ p.createDirectories();
+ LOG_INF("Created quarantine directory " + p.path());
+
+ Quarantine::createQuarantineMap();
+
WelcomeFilesRoot = getPathFromConfig("welcome.path");
if (!getConfigValue<bool>(conf, "welcome.enable", true))
WelcomeFilesRoot = "";
diff --git a/wsd/LOOLWSD.hpp b/wsd/LOOLWSD.hpp
index 50c82e5f05..5a14e39bd8 100644
--- a/wsd/LOOLWSD.hpp
+++ b/wsd/LOOLWSD.hpp
@@ -13,6 +13,7 @@
#include <cstdio>
#include <map>
#include <set>
+#include <unordered_map>
#include <unordered_set>
#include <string>
#include <utility>
@@ -28,7 +29,7 @@
#include "FileUtil.hpp"
#include "RequestDetails.hpp"
#include "WebSocketHandler.hpp"
-
+#include "QuarantineUtil.hpp"
class ChildProcess;
class TraceFileWriter;
class DocumentBroker;
@@ -263,6 +264,8 @@ public:
static bool IsProxyPrefixEnabled;
static std::atomic<unsigned> NumConnections;
static std::unique_ptr<TraceFileWriter> TraceDumper;
+ static std::unordered_map<std::string, std::vector<std::string>> QuarantineMap;
+ static std::string QuarantinePath;
#if !MOBILEAPP
static std::unique_ptr<ClipboardCache> SavedClipboards;
#endif
diff --git a/wsd/QuarantineUtil.cpp b/wsd/QuarantineUtil.cpp
new file mode 100644
index 0000000000..6a286a5a67
--- /dev/null
+++ b/wsd/QuarantineUtil.cpp
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "QuarantineUtil.hpp"
+
+#include <Poco/Path.h>
+#include <Poco/URI.h>
+#include "ClientSession.hpp"
+#include "LOOLWSD.hpp"
+#include "DocumentBroker.hpp"
+
+#include <common/Common.hpp>
+#include <common/StringVector.hpp>
+#include <common/Log.hpp>
+
+namespace Quarantine
+{
+ void createQuarantineMap()
+ {
+ std::vector<std::string> files;
+ Poco::File(LOOLWSD::QuarantinePath).list(files);
+ LOOLWSD::QuarantineMap.clear();
+
+ std::vector<StringToken> tokens;
+ std::string decoded;
+
+ std::sort(files.begin(), files.end());
+ for (auto file : files)
+ {
+
+ Util::tokenize(file.c_str(), file.size(), '_', tokens);
+ Poco::URI::decode(file.substr(tokens[2]._index), decoded);
+ LOOLWSD::QuarantineMap[decoded].emplace_back(LOOLWSD::QuarantinePath + file);
+
+ tokens.clear();
+ decoded.clear();
+ }
+ }
+
+ void removeQuarantine()
+ {
+ FileUtil::removeFile(LOOLWSD::QuarantinePath, true);
+ }
+
+ // returns quarentine directory size in bytes
+ // files with hardlink count of more than 1 is not counted
+ // because they are originally stored in jails
+ std::size_t quarantineSize()
+ {
+ std::vector<std::string> files;
+ Poco::File(LOOLWSD::QuarantinePath).list(files);
+ std::size_t size = 0;
+ for (auto file : files)
+ {
+ FileUtil::Stat f(LOOLWSD::QuarantinePath + file);
+
+ if (f.hardLinkCount() == 1)
+ size += f.size();
+ }
+ return size;
+ }
+
+ void makeQuarantineSpace()
+ {
+ std::size_t sizeLimit = LOOLWSD::getConfigValue<std::size_t>("quarantine_files.limit_dir_size_mb", 0)*1024*1024;
+
+ if(sizeLimit == 0)
+ return;
+
+ std::vector<std::string> files;
+ Poco::File(LOOLWSD::QuarantinePath).list(files);
+
+ std::sort(files.begin(), files.end());
+
+ std::size_t currentSize = quarantineSize();
+ std::size_t index = 0;
+ while (currentSize >= sizeLimit && !files.empty())
+ {
+ FileUtil::Stat file(LOOLWSD::QuarantinePath + files[index]);
+ if(file.hardLinkCount() != 1)
+ {
+ index++;
+ continue;
+ }
+ currentSize -= file.size();
+ FileUtil::removeFile(LOOLWSD::QuarantinePath + files[index], true);
+ files.erase(files.begin());
+ }
+ }
+
+ void clearOldQuarantineVersions(std::string Wopiscr)
+ {
+ std::size_t maxVersionCount = LOOLWSD::getConfigValue<std::size_t>("quarantine_files.max_versions_to_maintain", 2);
+ std::string decoded;
+ Poco::URI::decode(Wopiscr, decoded);
+ while (LOOLWSD::QuarantineMap[decoded].size() > maxVersionCount)
+ {
+ FileUtil::removeFile(LOOLWSD::QuarantineMap[decoded][0]);
+ LOOLWSD::QuarantineMap[decoded].erase(LOOLWSD::QuarantineMap[decoded].begin());
+ }
+
+ }
+
+ bool quarantineFile(DocumentBroker* docBroker, std::string docName)
+ {
+ //return if directory size limit is 0
+ std::size_t sizeLimit = LOOLWSD::getConfigValue<std::size_t>("quarantine_files.limit_dir_size_mb", 0);
+
+ if (sizeLimit == 0)
+ return false;
+
+ std::string docKey;
+ Poco::URI::encode(docBroker->getDocKey(), "?#/", docKey);
+
+ const auto timeNow = std::chrono::system_clock::now();
+ const std::string ts = std::to_string(std::chrono::duration_cast<std::chrono::seconds>(timeNow.time_since_epoch()).count());
+
+ std::string sourcefilePath = LOOLWSD::ChildRoot + "tmp/lool-" + docBroker->getJailId() + "/user/docs/" + docBroker->getJailId() + "/" + docName;
+
+ std::string linkedFileName = ts + "_" + std::to_string(docBroker->getPid()) + "_" + docKey;
+ std::string linkedFilePath = LOOLWSD::QuarantinePath + linkedFileName;
+
+ FileUtil::Stat fileStat(linkedFilePath);
+
+ makeQuarantineSpace();
+
+ int result_link = link(sourcefilePath.c_str(),linkedFilePath.c_str());
+
+ if(result_link == 0)
+ {
+ LOOLWSD::QuarantineMap[docBroker->getDocKey()].emplace_back(linkedFilePath);
+ clearOldQuarantineVersions(docKey);
+ makeQuarantineSpace();
+
+ LOG_INF("Quarantined " + sourcefilePath + " to " + linkedFilePath);
+ return true;
+ }
+ else
+ {
+ LOG_ERR("Quarantining of file " + sourcefilePath + " filed");
+ return false;
+ }
+
+ return false;
+ }
+} \ No newline at end of file
diff --git a/wsd/QuarantineUtil.hpp b/wsd/QuarantineUtil.hpp
new file mode 100644
index 0000000000..1fb629c549
--- /dev/null
+++ b/wsd/QuarantineUtil.hpp
@@ -0,0 +1,27 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <config.h>
+#include <string>
+
+class DocumentBroker;
+namespace Quarantine
+{
+ void createQuarantineMap();
+
+ void removeQuarantine();
+
+ std::size_t quarantineSize();
+
+ void makeQuarantineSpace();
+
+ void clearOldQuarantineVersions(std::string Wopiscr);
+
+ bool quarantineFile(DocumentBroker* docBroker, std::string docName);
+}