desktop/source/lib/init.cxx | 25 +++++ include/osl/file.h | 48 +++++++++ include/osl/file.hxx | 52 ++++++++++ include/sfx2/lokhelper.hxx | 3 include/svx/PaletteManager.hxx | 4 include/svx/theme/IThemeColorChanger.hxx | 10 +- include/svx/theme/ThemeColorChangerCommon.hxx | 5 + include/svx/theme/ThemeColorPaletteManager.hxx | 3 include/tools/hostfilter.hxx | 28 +++++ include/unotools/pathoptions.hxx | 1 sal/osl/unx/file.cxx | 124 +++++++++++++++++++++++++ sal/osl/unx/file_impl.hxx | 2 sal/osl/unx/file_misc.cxx | 34 ++++++ sal/osl/unx/file_stat.cxx | 6 + sal/osl/unx/file_volume.cxx | 4 sal/osl/unx/pipe.cxx | 4 sal/osl/unx/process.cxx | 5 - sal/osl/unx/profile.cxx | 4 sal/qa/osl/file/osl_File.cxx | 118 +++++++++++++++++++++++ sal/util/sal.map | 6 + sc/source/core/tool/webservicelink.cxx | 8 + sc/source/filter/html/htmlpars.cxx | 10 ++ sc/source/ui/docshell/externalrefmgr.cxx | 5 - sc/source/ui/drawfunc/fuins1.cxx | 11 ++ sc/source/ui/inc/ThemeColorChanger.hxx | 2 sc/source/ui/theme/ThemeColorChanger.cxx | 4 sc/source/ui/view/tabvwshc.cxx | 9 + sd/inc/theme/ThemeColorChanger.hxx | 2 sd/source/core/ThemeColorChanger.cxx | 4 sd/source/ui/func/fuinsert.cxx | 14 ++ sd/source/ui/inc/ViewShellBase.hxx | 2 sd/source/ui/view/ViewShellBase.cxx | 15 +++ sd/source/ui/view/drviews2.cxx | 8 - sfx2/source/view/lokhelper.cxx | 17 +++ svx/source/tbxctrls/PaletteManager.cxx | 36 +++++++ svx/source/theme/ThemeColorChangerCommon.cxx | 56 +++++++---- svx/source/theme/ThemeColorPaletteManager.cxx | 9 - sw/source/core/inc/ThemeColorChanger.hxx | 2 sw/source/core/model/ThemeColorChanger.cxx | 4 sw/source/filter/html/htmlgrin.cxx | 6 + sw/source/uibase/shells/basesh.cxx | 7 - sw/source/uibase/uiview/view.cxx | 7 - sw/source/uibase/uiview/view2.cxx | 10 ++ tools/Library_tl.mk | 1 tools/source/inet/hostfilter.cxx | 31 ++++++ ucb/source/ucp/webdav-curl/CurlSession.cxx | 7 + unotools/source/config/pathoptions.cxx | 6 + 47 files changed, 718 insertions(+), 61 deletions(-)
New commits: commit 88281b55c1d781f73a663188229c639a290c53bc Author: Szymon Kłos <szymon.k...@collabora.com> AuthorDate: Mon Jan 8 18:46:13 2024 +0100 Commit: Szymon Kłos <szymon.k...@collabora.com> CommitDate: Mon Jan 15 21:07:28 2024 +0100 Send document colors with lok callback First step for publishing any palette for LOK. Let's start with Document colors (colors used in the document) which can be extracted similar to theme colors from SfxViewShell. Modify generateJSON function so it appends palette into existing ptree/JSON. In the next step we can make it more generic so it will be able to send any palette managed by PaletteManager. Change-Id: Ibb56690af6dfd59ee232e88b28e7a3d312d0e16c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161798 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> (cherry picked from commit 0460be8848b0ce02c07183e41dd7137ac3b94164) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161941 Tested-by: Jenkins Reviewed-by: Szymon Kłos <szymon.k...@collabora.com> diff --git a/include/svx/PaletteManager.hxx b/include/svx/PaletteManager.hxx index 81f30ea7de76..90fa00de59fe 100644 --- a/include/svx/PaletteManager.hxx +++ b/include/svx/PaletteManager.hxx @@ -27,6 +27,7 @@ #include <deque> #include <vector> #include <memory> +#include <set> namespace com::sun::star::uno { class XComponentContext; } namespace svx { class ToolboxButtonColorUpdaterBase; } @@ -86,6 +87,9 @@ public: bool GetLumModOff(sal_uInt16 nThemeIndex, sal_uInt16 nEffect, sal_Int16& rLumMod, sal_Int16& rLumOff); static void DispatchColorCommand(const OUString& aCommand, const NamedColor& rColor); + + /// Appends node for Document Colors into the ptree + static void generateJSON(boost::property_tree::ptree& aTree, const std::set<Color>& rColors); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/theme/IThemeColorChanger.hxx b/include/svx/theme/IThemeColorChanger.hxx index 0b3b88d60afa..035494f12324 100644 --- a/include/svx/theme/IThemeColorChanger.hxx +++ b/include/svx/theme/IThemeColorChanger.hxx @@ -22,7 +22,7 @@ public: void apply(std::shared_ptr<model::ColorSet> const& pColorSet) { doApply(pColorSet); - svx::theme::notifyLOK(pColorSet); + svx::theme::notifyLOK(pColorSet, std::set<Color>()); } private: diff --git a/include/svx/theme/ThemeColorChangerCommon.hxx b/include/svx/theme/ThemeColorChangerCommon.hxx index 3a585236fbf8..9fa3f4376ddc 100644 --- a/include/svx/theme/ThemeColorChangerCommon.hxx +++ b/include/svx/theme/ThemeColorChangerCommon.hxx @@ -9,6 +9,7 @@ #pragma once +#include <set> #include <svx/svxdllapi.h> #include <docmodel/theme/ColorSet.hxx> #include <svx/svdobj.hxx> @@ -22,7 +23,9 @@ namespace theme SVXCORE_DLLPUBLIC void updateSdrObject(model::ColorSet const& rColorSet, SdrObject* pObject, SdrView* pView, SfxUndoManager* pUndoManager = nullptr); -SVXCORE_DLLPUBLIC void notifyLOK(std::shared_ptr<model::ColorSet> const& pColorSet); +/// Sends to the LOK updated palettes +SVXCORE_DLLPUBLIC void notifyLOK(std::shared_ptr<model::ColorSet> const& pColorSet, + const std::set<Color>& rDocumentColors); } } // end svx namespace diff --git a/include/svx/theme/ThemeColorPaletteManager.hxx b/include/svx/theme/ThemeColorPaletteManager.hxx index 7bb8526a2409..8531021bbc84 100644 --- a/include/svx/theme/ThemeColorPaletteManager.hxx +++ b/include/svx/theme/ThemeColorPaletteManager.hxx @@ -14,6 +14,7 @@ #include <memory> #include <tools/color.hxx> #include <docmodel/theme/ThemeColorType.hxx> +#include <boost/property_tree/json_parser.hpp> namespace model { @@ -60,7 +61,7 @@ class SVXCORE_DLLPUBLIC ThemeColorPaletteManager final public: ThemeColorPaletteManager(std::shared_ptr<model::ColorSet> const& pColorSet); ThemePaletteCollection generate(); - OString generateJSON(); + void generateJSON(boost::property_tree::ptree& aTree); }; } // end svx namespace diff --git a/sc/source/ui/view/tabvwshc.cxx b/sc/source/ui/view/tabvwshc.cxx index 3cde75058033..13d852f58630 100644 --- a/sc/source/ui/view/tabvwshc.cxx +++ b/sc/source/ui/view/tabvwshc.cxx @@ -479,7 +479,9 @@ void ScTabViewShell::afterCallbackRegistered() SfxObjectShell* pDocShell = GetObjectShell(); if (pDocShell) { - svx::theme::notifyLOK(pDocShell->GetThemeColors()); + std::shared_ptr<model::ColorSet> pThemeColors = pDocShell->GetThemeColors(); + std::set<Color> aDocumentColors = pDocShell->GetDocColors(); + svx::theme::notifyLOK(pThemeColors, aDocumentColors); } } diff --git a/sd/source/ui/view/ViewShellBase.cxx b/sd/source/ui/view/ViewShellBase.cxx index 6ba412acf7d9..70691ce1133e 100644 --- a/sd/source/ui/view/ViewShellBase.cxx +++ b/sd/source/ui/view/ViewShellBase.cxx @@ -1019,7 +1019,9 @@ void ViewShellBase::afterCallbackRegistered() SfxObjectShell* pDocShell = GetObjectShell(); if (pDocShell) { - svx::theme::notifyLOK(pDocShell->GetThemeColors()); + std::shared_ptr<model::ColorSet> pThemeColors = pDocShell->GetThemeColors(); + std::set<Color> aDocumentColors = pDocShell->GetDocColors(); + svx::theme::notifyLOK(pThemeColors, aDocumentColors); } } diff --git a/svx/source/tbxctrls/PaletteManager.cxx b/svx/source/tbxctrls/PaletteManager.cxx index a98149ff30bb..c9330eec408f 100644 --- a/svx/source/tbxctrls/PaletteManager.cxx +++ b/svx/source/tbxctrls/PaletteManager.cxx @@ -50,7 +50,6 @@ #include <memory> #include <array> #include <stack> -#include <set> PaletteManager::PaletteManager() : mnMaxRecentColors(Application::GetSettings().GetStyleSettings().GetColorValueSetColumnCount()), @@ -469,4 +468,39 @@ void PaletteManager::DispatchColorCommand(const OUString& aCommand, const NamedC } } +// TODO: make it generic, send any palette +void PaletteManager::generateJSON(boost::property_tree::ptree& aTree, const std::set<Color>& rColors) +{ + boost::property_tree::ptree aColorListTree; + sal_uInt32 nStartIndex = 1; + + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + sal_uInt32 nColumnCount = rStyleSettings.GetColorValueSetColumnCount(); + const OUString aNamePrefix(Concat2View(SvxResId(RID_SVXSTR_DOC_COLOR_PREFIX) + " ")); + + auto aColorIt = rColors.begin(); + while (aColorIt != rColors.end()) + { + boost::property_tree::ptree aColorRowTree; + + for (sal_uInt32 nColumn = 0; nColumn < nColumnCount; nColumn++) + { + boost::property_tree::ptree aColorTree; + OUString sName = aNamePrefix + OUString::number(nStartIndex++); + aColorTree.put("Value", aColorIt->AsRGBHexString().toUtf8()); + aColorTree.put("Name", sName); + + aColorRowTree.push_back(std::make_pair("", aColorTree)); + + aColorIt++; + if (aColorIt == rColors.end()) + break; + } + + aColorListTree.push_back(std::make_pair("", aColorRowTree)); + } + + aTree.add_child("DocumentColors", aColorListTree); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/theme/ThemeColorChangerCommon.cxx b/svx/source/theme/ThemeColorChangerCommon.cxx index 0e3548ed83cc..bca8ea1a1bb7 100644 --- a/svx/source/theme/ThemeColorChangerCommon.cxx +++ b/svx/source/theme/ThemeColorChangerCommon.cxx @@ -22,6 +22,7 @@ #include <sfx2/lokhelper.hxx> +#include <svx/PaletteManager.hxx> #include <svx/svdmodel.hxx> #include <svx/svdotext.hxx> #include <svx/svdundo.hxx> @@ -171,12 +172,23 @@ void updateSdrObject(model::ColorSet const& rColorSet, SdrObject* pObject, SdrVi updateEditEngTextSections(rColorSet, pObject, *pView); } -void notifyLOK(std::shared_ptr<model::ColorSet> const& pColorSet) +void notifyLOK(std::shared_ptr<model::ColorSet> const& pColorSet, + const std::set<Color>& rDocumentColors) { if (comphelper::LibreOfficeKit::isActive()) { svx::ThemeColorPaletteManager aManager(pColorSet); - SfxLokHelper::notifyAllViews(LOK_CALLBACK_COLOR_PALETTES, aManager.generateJSON()); + std::stringstream aStream; + boost::property_tree::ptree aTree; + + if (pColorSet) + aManager.generateJSON(aTree); + if (rDocumentColors.size()) + PaletteManager::generateJSON(aTree, rDocumentColors); + + boost::property_tree::write_json(aStream, aTree); + + SfxLokHelper::notifyAllViews(LOK_CALLBACK_COLOR_PALETTES, OString(aStream.str())); } } diff --git a/svx/source/theme/ThemeColorPaletteManager.cxx b/svx/source/theme/ThemeColorPaletteManager.cxx index 0e4f20899645..a89456576736 100644 --- a/svx/source/theme/ThemeColorPaletteManager.cxx +++ b/svx/source/theme/ThemeColorPaletteManager.cxx @@ -16,7 +16,6 @@ #include <svx/strings.hrc> #include <docmodel/theme/ColorSet.hxx> #include <docmodel/color/ComplexColorJSON.hxx> -#include <boost/property_tree/json_parser.hpp> #include <array> @@ -127,11 +126,10 @@ svx::ThemePaletteCollection ThemeColorPaletteManager::generate() return aThemePaletteCollection; } -OString ThemeColorPaletteManager::generateJSON() +void ThemeColorPaletteManager::generateJSON(boost::property_tree::ptree& aTree) { svx::ThemePaletteCollection aThemePaletteCollection = generate(); - boost::property_tree::ptree aTree; boost::property_tree::ptree aColorListTree; for (size_t nEffect = 0; nEffect < 6; ++nEffect) @@ -161,11 +159,6 @@ OString ThemeColorPaletteManager::generateJSON() } aTree.add_child("ThemeColors", aColorListTree); - - std::stringstream aStream; - boost::property_tree::write_json(aStream, aTree); - - return OString(aStream.str()); } } // end svx namespace diff --git a/sw/source/uibase/uiview/view.cxx b/sw/source/uibase/uiview/view.cxx index 0474824e69eb..8583fc004a5a 100644 --- a/sw/source/uibase/uiview/view.cxx +++ b/sw/source/uibase/uiview/view.cxx @@ -1218,7 +1218,9 @@ void SwView::afterCallbackRegistered() auto* pDocShell = GetDocShell(); if (pDocShell) { - svx::theme::notifyLOK(pDocShell->GetThemeColors()); + std::shared_ptr<model::ColorSet> pThemeColors = pDocShell->GetThemeColors(); + std::set<Color> aDocumentColors = pDocShell->GetDocColors(); + svx::theme::notifyLOK(pThemeColors, aDocumentColors); } } commit 035cd913e0361cce9d799eb3b331b6d7bcf7910e Author: Szymon Kłos <szymon.k...@collabora.com> AuthorDate: Sun Jan 7 18:31:22 2024 +0100 Commit: Szymon Kłos <szymon.k...@collabora.com> CommitDate: Mon Jan 15 21:07:27 2024 +0100 sc: announce theme colors with lok callback As it is done already for Writer. Unfortunately cannot move the code from afterCallbackRegistered to base class in sfx2 as it is not linked to svx which is needed to generate JSON. So at least share generation and sending part in ThemeColorChangerCommon. Signed-off-by: Szymon Kłos <szymon.k...@collabora.com> Change-Id: Icbf681230bd4c49698c47d852a0862620d93bcec Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161771 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161927 Tested-by: Jenkins diff --git a/include/svx/theme/IThemeColorChanger.hxx b/include/svx/theme/IThemeColorChanger.hxx index d9273238c712..0b3b88d60afa 100644 --- a/include/svx/theme/IThemeColorChanger.hxx +++ b/include/svx/theme/IThemeColorChanger.hxx @@ -11,6 +11,7 @@ #include <svx/svxdllapi.h> #include <docmodel/theme/ColorSet.hxx> +#include "ThemeColorChangerCommon.hxx" namespace svx { @@ -18,7 +19,14 @@ class SVXCORE_DLLPUBLIC IThemeColorChanger { public: virtual ~IThemeColorChanger() = default; - virtual void apply(std::shared_ptr<model::ColorSet> const& pColorSet) = 0; + void apply(std::shared_ptr<model::ColorSet> const& pColorSet) + { + doApply(pColorSet); + svx::theme::notifyLOK(pColorSet); + } + +private: + virtual void doApply(std::shared_ptr<model::ColorSet> const& pColorSet) = 0; }; } // end svx namespace diff --git a/include/svx/theme/ThemeColorChangerCommon.hxx b/include/svx/theme/ThemeColorChangerCommon.hxx index febc34ae3873..3a585236fbf8 100644 --- a/include/svx/theme/ThemeColorChangerCommon.hxx +++ b/include/svx/theme/ThemeColorChangerCommon.hxx @@ -21,6 +21,8 @@ namespace theme { SVXCORE_DLLPUBLIC void updateSdrObject(model::ColorSet const& rColorSet, SdrObject* pObject, SdrView* pView, SfxUndoManager* pUndoManager = nullptr); + +SVXCORE_DLLPUBLIC void notifyLOK(std::shared_ptr<model::ColorSet> const& pColorSet); } } // end svx namespace diff --git a/sc/source/ui/inc/ThemeColorChanger.hxx b/sc/source/ui/inc/ThemeColorChanger.hxx index 57ca91cdb83c..f85401385888 100644 --- a/sc/source/ui/inc/ThemeColorChanger.hxx +++ b/sc/source/ui/inc/ThemeColorChanger.hxx @@ -24,7 +24,7 @@ public: ThemeColorChanger(ScDocShell& rDocShell); virtual ~ThemeColorChanger() override; - void apply(std::shared_ptr<model::ColorSet> const& pColorSet) override; + void doApply(std::shared_ptr<model::ColorSet> const& pColorSet) override; }; } // end sc namespace diff --git a/sc/source/ui/theme/ThemeColorChanger.cxx b/sc/source/ui/theme/ThemeColorChanger.cxx index c9b88652dcc3..2ba881544372 100644 --- a/sc/source/ui/theme/ThemeColorChanger.cxx +++ b/sc/source/ui/theme/ThemeColorChanger.cxx @@ -19,7 +19,7 @@ #include <editeng/boxitem.hxx> #include <editeng/borderline.hxx> #include <svx/svditer.hxx> -#include <svx/theme/ThemeColorChangerCommon.hxx> +#include <svx/theme/IThemeColorChanger.hxx> #include <undodraw.hxx> #include <stlpool.hxx> @@ -311,7 +311,7 @@ void changeThemeColorInTheDocModel(ScDocShell& rDocShell, } // end anonymous ns -void ThemeColorChanger::apply(std::shared_ptr<model::ColorSet> const& pColorSet) +void ThemeColorChanger::doApply(std::shared_ptr<model::ColorSet> const& pColorSet) { // Can't change to an empty color set if (!pColorSet) diff --git a/sc/source/ui/view/tabvwshc.cxx b/sc/source/ui/view/tabvwshc.cxx index 147bf68c4968..3cde75058033 100644 --- a/sc/source/ui/view/tabvwshc.cxx +++ b/sc/source/ui/view/tabvwshc.cxx @@ -20,6 +20,7 @@ #include <scitems.hxx> #include <sfx2/childwin.hxx> #include <sfx2/dispatch.hxx> +#include <svx/theme/ThemeColorChangerCommon.hxx> #include <editeng/editview.hxx> #include <inputhdl.hxx> @@ -474,6 +475,12 @@ void ScTabViewShell::afterCallbackRegistered() pInputWindow->NotifyLOKClient(); } } + + SfxObjectShell* pDocShell = GetObjectShell(); + if (pDocShell) + { + svx::theme::notifyLOK(pDocShell->GetThemeColors()); + } } void ScTabViewShell::NotifyCursor(SfxViewShell* pOtherShell) const diff --git a/sd/inc/theme/ThemeColorChanger.hxx b/sd/inc/theme/ThemeColorChanger.hxx index ff100fd511ce..6a467bc4c47a 100644 --- a/sd/inc/theme/ThemeColorChanger.hxx +++ b/sd/inc/theme/ThemeColorChanger.hxx @@ -27,7 +27,7 @@ public: ThemeColorChanger(SdrPage* pMasterPage, sd::DrawDocShell* pDocShell); virtual ~ThemeColorChanger() override; - void apply(std::shared_ptr<model::ColorSet> const& pColorSet) override; + void doApply(std::shared_ptr<model::ColorSet> const& pColorSet) override; }; } // end sd namespace diff --git a/sd/source/core/ThemeColorChanger.cxx b/sd/source/core/ThemeColorChanger.cxx index 70d14bc37438..b941407881ed 100644 --- a/sd/source/core/ThemeColorChanger.cxx +++ b/sd/source/core/ThemeColorChanger.cxx @@ -9,7 +9,7 @@ #include <editeng/colritem.hxx> #include <theme/ThemeColorChanger.hxx> -#include <svx/theme/ThemeColorChangerCommon.hxx> +#include <svx/theme/IThemeColorChanger.hxx> #include <svx/svdmodel.hxx> #include <svx/svditer.hxx> #include <docmodel/theme/Theme.hxx> @@ -133,7 +133,7 @@ bool changeStyles(sd::DrawDocShell* pDocShell, std::shared_ptr<model::ColorSet> } // end anonymous ns -void ThemeColorChanger::apply(std::shared_ptr<model::ColorSet> const& pColorSet) +void ThemeColorChanger::doApply(std::shared_ptr<model::ColorSet> const& pColorSet) { auto* pUndoManager = mpDocShell->GetUndoManager(); sd::ViewShell* pViewShell = mpDocShell->GetViewShell(); diff --git a/sd/source/ui/inc/ViewShellBase.hxx b/sd/source/ui/inc/ViewShellBase.hxx index acdd244c70f3..e31429f6e41a 100644 --- a/sd/source/ui/inc/ViewShellBase.hxx +++ b/sd/source/ui/inc/ViewShellBase.hxx @@ -217,6 +217,8 @@ public: int getEditMode() const override; /// See SfxViewShell::setEditMode(). void setEditMode(int nMode); + /// See SfxViewShell::afterCallbackRegistered(). + void afterCallbackRegistered() override; /// See SfxViewShell::NotifyCursor(). void NotifyCursor(SfxViewShell* pViewShell) const override; /// See SfxViewShell::GetColorConfigColor(). diff --git a/sd/source/ui/view/ViewShellBase.cxx b/sd/source/ui/view/ViewShellBase.cxx index 9e8e7b1aa5d4..6ba412acf7d9 100644 --- a/sd/source/ui/view/ViewShellBase.cxx +++ b/sd/source/ui/view/ViewShellBase.cxx @@ -62,6 +62,7 @@ #include <sfx2/objface.hxx> #include <sfx2/viewfrm.hxx> #include <svl/whiter.hxx> +#include <svx/theme/ThemeColorChangerCommon.hxx> #include <vcl/commandinfoprovider.hxx> #include <vcl/settings.hxx> #include <vcl/svapp.hxx> @@ -1010,6 +1011,18 @@ void ViewShellBase::setEditMode(int nMode) } } +void ViewShellBase::afterCallbackRegistered() +{ + // common tasks + SfxViewShell::afterCallbackRegistered(); + + SfxObjectShell* pDocShell = GetObjectShell(); + if (pDocShell) + { + svx::theme::notifyLOK(pDocShell->GetThemeColors()); + } +} + void ViewShellBase::NotifyCursor(SfxViewShell* pOtherShell) const { ViewShell* pThisShell = framework::FrameworkHelper::Instance(*const_cast<ViewShellBase*>(this))->GetViewShell(FrameworkHelper::msCenterPaneURL).get(); diff --git a/sd/source/ui/view/drviews2.cxx b/sd/source/ui/view/drviews2.cxx index 90cde7c792f5..0847df373f44 100644 --- a/sd/source/ui/view/drviews2.cxx +++ b/sd/source/ui/view/drviews2.cxx @@ -188,8 +188,6 @@ #include <theme/ThemeColorChanger.hxx> #include <svx/dialog/ThemeDialog.hxx> -#include <svx/theme/ThemeColorPaletteManager.hxx> -#include <sfx2/lokhelper.hxx> #include <LibreOfficeKit/LibreOfficeKitEnums.h> #include <ViewShellBase.hxx> @@ -3562,12 +3560,6 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) { sd::ThemeColorChanger aChanger(pMasterPage, pDocShell); aChanger.apply(pColorSet); - - if (comphelper::LibreOfficeKit::isActive()) - { - svx::ThemeColorPaletteManager aManager(pColorSet); - SfxLokHelper::notifyAllViews(LOK_CALLBACK_COLOR_PALETTES, aManager.generateJSON()); - } } }); diff --git a/svx/source/theme/ThemeColorChangerCommon.cxx b/svx/source/theme/ThemeColorChangerCommon.cxx index 82f915fef930..0e3548ed83cc 100644 --- a/svx/source/theme/ThemeColorChangerCommon.cxx +++ b/svx/source/theme/ThemeColorChangerCommon.cxx @@ -7,30 +7,29 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include <svx/theme/ThemeColorChangerCommon.hxx> +#include <comphelper/lok.hxx> -#include <sal/config.h> -#include <editeng/colritem.hxx> -#include <editeng/unoprnms.hxx> -#include <docmodel/uno/UnoComplexColor.hxx> #include <docmodel/theme/ColorSet.hxx> -#include <com/sun/star/text/XTextRange.hpp> -#include <com/sun/star/container/XEnumerationAccess.hpp> -#include <com/sun/star/container/XEnumeration.hpp> -#include <com/sun/star/beans/XPropertySet.hpp> -#include <com/sun/star/util/XComplexColor.hpp> - -#include <svx/xlnclit.hxx> -#include <svx/xflclit.hxx> -#include <svx/xdef.hxx> +#include <editeng/colritem.hxx> +#include <editeng/editeng.hxx> #include <editeng/eeitem.hxx> -#include <svx/svdundo.hxx> +#include <editeng/section.hxx> + +#include <LibreOfficeKit/LibreOfficeKitEnums.h> + +#include <sal/config.h> + +#include <sfx2/lokhelper.hxx> + #include <svx/svdmodel.hxx> #include <svx/svdotext.hxx> - -#include <editeng/editeng.hxx> -#include <editeng/section.hxx> +#include <svx/svdundo.hxx> +#include <svx/theme/ThemeColorChangerCommon.hxx> +#include <svx/theme/ThemeColorPaletteManager.hxx> +#include <svx/xdef.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xflclit.hxx> using namespace css; @@ -172,6 +171,15 @@ void updateSdrObject(model::ColorSet const& rColorSet, SdrObject* pObject, SdrVi updateEditEngTextSections(rColorSet, pObject, *pView); } +void notifyLOK(std::shared_ptr<model::ColorSet> const& pColorSet) +{ + if (comphelper::LibreOfficeKit::isActive()) + { + svx::ThemeColorPaletteManager aManager(pColorSet); + SfxLokHelper::notifyAllViews(LOK_CALLBACK_COLOR_PALETTES, aManager.generateJSON()); + } +} + } // end svx::theme namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/inc/ThemeColorChanger.hxx b/sw/source/core/inc/ThemeColorChanger.hxx index 6eeb3a25f612..f919496fd595 100644 --- a/sw/source/core/inc/ThemeColorChanger.hxx +++ b/sw/source/core/inc/ThemeColorChanger.hxx @@ -25,7 +25,7 @@ public: ThemeColorChanger(SwDocShell* pDocSh); virtual ~ThemeColorChanger() override; - void apply(std::shared_ptr<model::ColorSet> const& pColorSet) override; + void doApply(std::shared_ptr<model::ColorSet> const& pColorSet) override; }; } // end sw namespace diff --git a/sw/source/core/model/ThemeColorChanger.cxx b/sw/source/core/model/ThemeColorChanger.cxx index 8cbc0b971066..c61ea96b2a5a 100644 --- a/sw/source/core/model/ThemeColorChanger.cxx +++ b/sw/source/core/model/ThemeColorChanger.cxx @@ -34,7 +34,7 @@ #include <sal/config.h> #include <svx/svdpage.hxx> #include <svx/svditer.hxx> -#include <svx/theme/ThemeColorChangerCommon.hxx> +#include <svx/theme/IThemeColorChanger.hxx> #include <docmodel/uno/UnoComplexColor.hxx> #include <docmodel/theme/Theme.hxx> #include <editeng/unoprnms.hxx> @@ -322,7 +322,7 @@ ThemeColorChanger::ThemeColorChanger(SwDocShell* pDocSh) ThemeColorChanger::~ThemeColorChanger() = default; -void ThemeColorChanger::apply(std::shared_ptr<model::ColorSet> const& pColorSet) +void ThemeColorChanger::doApply(std::shared_ptr<model::ColorSet> const& pColorSet) { SwDoc* pDocument = mpDocSh->GetDoc(); if (!pDocument) diff --git a/sw/source/uibase/shells/basesh.cxx b/sw/source/uibase/shells/basesh.cxx index 57e7c8299546..52e24b0b6077 100644 --- a/sw/source/uibase/shells/basesh.cxx +++ b/sw/source/uibase/shells/basesh.cxx @@ -91,7 +91,6 @@ #include <SwRewriter.hxx> #include <GraphicSizeCheck.hxx> #include <svx/galleryitem.hxx> -#include <svx/theme/ThemeColorPaletteManager.hxx> #include <sfx2/devtools/DevelopmentToolChildWindow.hxx> #include <com/sun/star/gallery/GalleryItemType.hpp> #include <com/sun/star/beans/PropertyValues.hpp> @@ -102,7 +101,6 @@ #include <svx/dialog/ThemeDialog.hxx> #include <comphelper/scopeguard.hxx> #include <comphelper/lok.hxx> -#include <sfx2/lokhelper.hxx> #include <LibreOfficeKit/LibreOfficeKitEnums.h> #include <osl/diagnose.h> @@ -2984,11 +2982,6 @@ void SwBaseShell::ExecDlg(SfxRequest &rReq) if (pColorSet) { pChanger->apply(pColorSet); - if (comphelper::LibreOfficeKit::isActive()) - { - svx::ThemeColorPaletteManager aManager(pColorSet); - SfxLokHelper::notifyAllViews(LOK_CALLBACK_COLOR_PALETTES, aManager.generateJSON()); - } } }); } diff --git a/sw/source/uibase/uiview/view.cxx b/sw/source/uibase/uiview/view.cxx index 2d46cd04f260..0474824e69eb 100644 --- a/sw/source/uibase/uiview/view.cxx +++ b/sw/source/uibase/uiview/view.cxx @@ -102,7 +102,7 @@ #include <PostItMgr.hxx> #include <annotsh.hxx> #include <swruler.hxx> -#include <svx/theme/ThemeColorPaletteManager.hxx> +#include <svx/theme/ThemeColorChangerCommon.hxx> #include <com/sun/star/document/XDocumentProperties.hpp> #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> @@ -1218,8 +1218,7 @@ void SwView::afterCallbackRegistered() auto* pDocShell = GetDocShell(); if (pDocShell) { - svx::ThemeColorPaletteManager aManager(pDocShell->GetThemeColors()); - libreOfficeKitViewCallback(LOK_CALLBACK_COLOR_PALETTES, aManager.generateJSON()); + svx::theme::notifyLOK(pDocShell->GetThemeColors()); } } commit deec43b36446ac3ac5c77b88bf47e4e0a4ba2057 Author: Szymon Kłos <szymon.k...@collabora.com> AuthorDate: Tue Dec 19 19:24:19 2023 +0100 Commit: Szymon Kłos <szymon.k...@collabora.com> CommitDate: Mon Jan 15 21:07:27 2024 +0100 lok: send error on access denied in image import 2 followup for commit 64624d225c71229acce4f889d4863d7c29c52658 lok: send error on access denied in image import It shows an error in LOK when we try to insert image from remote host blocked by HostFilter Previously it was showing error in paste case, now do the same also on image insertion. For now disable HandleGraphicFilterError in sd, as it crashes, is synchronous and cannot be easily fixed - dialog sits inside module not linked to sfx2, needs some rework. Change-Id: I3c15ff5621add97ef9d60d4f4c1305dae2909158 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161001 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161774 Tested-by: Jenkins Reviewed-by: Szymon Kłos <szymon.k...@collabora.com> diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx index 338dda192b8c..3751d6758571 100644 --- a/include/sfx2/lokhelper.hxx +++ b/include/sfx2/lokhelper.hxx @@ -227,7 +227,7 @@ public: static VclPtr<vcl::Window> getInPlaceDocWindow(SfxViewShell* pViewShell); /// Sends Network Access error to LOK - static void sendNetworkAccessError(); + static void sendNetworkAccessError(std::string_view rAction); static void notifyLog(const std::ostringstream& stream); diff --git a/sc/source/filter/html/htmlpars.cxx b/sc/source/filter/html/htmlpars.cxx index 10d31fc84cd4..43ff3cca2de5 100644 --- a/sc/source/filter/html/htmlpars.cxx +++ b/sc/source/filter/html/htmlpars.cxx @@ -1325,7 +1325,7 @@ void ScHTMLLayoutParser::Image( HtmlImportInfo* pInfo ) { INetURLObject aURL(pImage->aURL); if (HostFilter::isForbidden(aURL.GetHost())) - SfxLokHelper::sendNetworkAccessError(); + SfxLokHelper::sendNetworkAccessError("paste"); } sal_uInt16 nFormat; diff --git a/sc/source/ui/drawfunc/fuins1.cxx b/sc/source/ui/drawfunc/fuins1.cxx index 72886789b448..9b51a62c5b2a 100644 --- a/sc/source/ui/drawfunc/fuins1.cxx +++ b/sc/source/ui/drawfunc/fuins1.cxx @@ -22,6 +22,7 @@ #include <officecfg/Office/Common.hxx> #include <editeng/sizeitem.hxx> #include <sal/log.hxx> +#include <sfx2/lokhelper.hxx> #include <sfx2/opengrf.hxx> #include <sfx2/viewfrm.hxx> #include <svx/svdograf.hxx> @@ -48,6 +49,9 @@ #include <globstr.hrc> #include <comphelper/lok.hxx> +#include <tools/hostfilter.hxx> +#include <tools/urlobj.hxx> + #include <com/sun/star/frame/XDispatchProvider.hpp> #include <com/sun/star/media/XPlayer.hpp> #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> @@ -279,6 +283,13 @@ FuInsertGraphic::FuInsertGraphic( ScTabViewShell& rViewSh, if ( pReqArgs->GetItemState( FN_PARAM_1, true, &pItem ) == SfxItemState::SET ) bAsLink = static_cast<const SfxBoolItem*>(pItem)->GetValue(); + if (comphelper::LibreOfficeKit::isActive()) + { + INetURLObject aURL(aFileName); + if (INetProtocol::File != aURL.GetProtocol() && HostFilter::isForbidden(aURL.GetHost())) + SfxLokHelper::sendNetworkAccessError("insert"); + } + Graphic aGraphic; ErrCode nError = GraphicFilter::LoadGraphic( aFileName, aFilterName, aGraphic, &GraphicFilter::GetGraphicFilter() ); if ( nError == ERRCODE_NONE ) diff --git a/sd/source/ui/func/fuinsert.cxx b/sd/source/ui/func/fuinsert.cxx index 31b286c822e3..e8409c815b25 100644 --- a/sd/source/ui/func/fuinsert.cxx +++ b/sd/source/ui/func/fuinsert.cxx @@ -36,6 +36,7 @@ #include <svl/stritem.hxx> #include <sfx2/dispatch.hxx> +#include <sfx2/lokhelper.hxx> #include <sfx2/msgpool.hxx> #include <sfx2/msg.hxx> #include <svtools/insdlg.hxx> @@ -60,6 +61,9 @@ #include <svx/charthelper.hxx> #include <svx/svxids.hrc> +#include <tools/hostfilter.hxx> +#include <tools/urlobj.hxx> + #include <sdresid.hxx> #include <View.hxx> #include <sdmod.hxx> @@ -129,6 +133,13 @@ void FuInsertGraphic::DoExecute( SfxRequest& rReq ) if ( pArgs->GetItemState( FN_PARAM_1, true, &pItem ) == SfxItemState::SET ) bAsLink = static_cast<const SfxBoolItem*>(pItem)->GetValue(); + if (comphelper::LibreOfficeKit::isActive()) + { + INetURLObject aURL(aFileName); + if (INetProtocol::File != aURL.GetProtocol() && HostFilter::isForbidden(aURL.GetHost())) + SfxLokHelper::sendNetworkAccessError("insert"); + } + nError = GraphicFilter::LoadGraphic( aFileName, aFilterName, aGraphic, &GraphicFilter::GetGraphicFilter() ); } else @@ -188,8 +199,9 @@ void FuInsertGraphic::DoExecute( SfxRequest& rReq ) } } } - else + else if (!comphelper::LibreOfficeKit::isActive()) { + // TODO: enable in LOK, it contains synchronous error window without LOKNotifier SdGRFFilter::HandleGraphicFilterError( nError, GraphicFilter::GetGraphicFilter().GetLastError() ); } } diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx index 853b35bb7431..73473dd7640b 100644 --- a/sfx2/source/view/lokhelper.cxx +++ b/sfx2/source/view/lokhelper.cxx @@ -1075,13 +1075,13 @@ VclPtr<vcl::Window> SfxLokHelper::getInPlaceDocWindow(SfxViewShell* pViewShell) return {}; } -void SfxLokHelper::sendNetworkAccessError() +void SfxLokHelper::sendNetworkAccessError(std::string_view rAction) { tools::JsonWriter aWriter; aWriter.put("code", static_cast<sal_uInt32>( ErrCode(ErrCodeArea::Inet, sal_uInt16(ErrCodeClass::Access)))); aWriter.put("kind", "network"); - aWriter.put("cmd", "paste"); + aWriter.put("cmd", rAction); SfxViewShell* pViewShell = SfxViewShell::Current(); if (pViewShell) diff --git a/sw/source/filter/html/htmlgrin.cxx b/sw/source/filter/html/htmlgrin.cxx index 8f04dce5546e..5a61f49ccca1 100644 --- a/sw/source/filter/html/htmlgrin.cxx +++ b/sw/source/filter/html/htmlgrin.cxx @@ -513,7 +513,7 @@ IMAGE_SETEVENT: else if (m_sBaseURL.isEmpty() || !aGraphicData.isEmpty()) { if (comphelper::LibreOfficeKit::isActive() && HostFilter::isForbidden(aGraphicURL.GetHost())) - SfxLokHelper::sendNetworkAccessError(); + SfxLokHelper::sendNetworkAccessError("paste"); // sBaseURL is empty if the source is clipboard // aGraphicData is non-empty for <object data="..."> -> not a linked graphic. diff --git a/sw/source/uibase/uiview/view2.cxx b/sw/source/uibase/uiview/view2.cxx index cc6faf78a3c5..a6a6975e984c 100644 --- a/sw/source/uibase/uiview/view2.cxx +++ b/sw/source/uibase/uiview/view2.cxx @@ -50,6 +50,7 @@ #include <svx/statusitem.hxx> #include <svx/viewlayoutitem.hxx> #include <svx/zoomslideritem.hxx> +#include <sfx2/lokhelper.hxx> #include <sfx2/htmlmode.hxx> #include <vcl/svapp.hxx> #include <sfx2/app.hxx> @@ -71,6 +72,7 @@ #include <svl/ptitem.hxx> #include <sfx2/viewfrm.hxx> #include <vcl/errinf.hxx> +#include <tools/hostfilter.hxx> #include <tools/urlobj.hxx> #include <svx/svdview.hxx> #include <swtypes.hxx> @@ -309,6 +311,14 @@ ErrCode SwView::InsertGraphic( const OUString &rPath, const OUString &rFilter, { pFilter = &GraphicFilter::GetGraphicFilter(); } + + if (comphelper::LibreOfficeKit::isActive()) + { + INetURLObject aURL(rPath); + if (INetProtocol::File != aURL.GetProtocol() && HostFilter::isForbidden(aURL.GetHost())) + SfxLokHelper::sendNetworkAccessError("insert"); + } + aResult = GraphicFilter::LoadGraphic( rPath, rFilter, aGraphic, pFilter ); if( ERRCODE_NONE == aResult ) commit cecec662b42b0f47780c2a73c6cd9b61b54419bb Author: Szymon Kłos <szymon.k...@collabora.com> AuthorDate: Mon Dec 4 18:36:29 2023 +0100 Commit: Szymon Kłos <szymon.k...@collabora.com> CommitDate: Mon Jan 15 21:07:27 2024 +0100 lok: send error on access denied in image import - when we paste HTML with references to external images and host filter is configured then we have empty graphics - inform client about that so we can show an error to the user Change-Id: I7d584c256d8d004955c970056341ab42864d1dd3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160319 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> Reviewed-by: Szymon Kłos <szymon.k...@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161773 Tested-by: Jenkins diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx index dc144503b8dd..338dda192b8c 100644 --- a/include/sfx2/lokhelper.hxx +++ b/include/sfx2/lokhelper.hxx @@ -226,6 +226,9 @@ public: static VclPtr<vcl::Window> getInPlaceDocWindow(SfxViewShell* pViewShell); + /// Sends Network Access error to LOK + static void sendNetworkAccessError(); + static void notifyLog(const std::ostringstream& stream); private: diff --git a/sc/source/filter/html/htmlpars.cxx b/sc/source/filter/html/htmlpars.cxx index f5f890081592..10d31fc84cd4 100644 --- a/sc/source/filter/html/htmlpars.cxx +++ b/sc/source/filter/html/htmlpars.cxx @@ -20,6 +20,7 @@ #include <memory> #include <sal/config.h> +#include <comphelper/lok.hxx> #include <comphelper/string.hxx> #include <scitems.hxx> @@ -37,6 +38,7 @@ #include <editeng/justifyitem.hxx> #include <sal/log.hxx> #include <sfx2/objsh.hxx> +#include <sfx2/lokhelper.hxx> #include <svl/numformat.hxx> #include <svl/intitem.hxx> #include <utility> @@ -47,6 +49,7 @@ #include <vcl/outdev.hxx> #include <vcl/svapp.hxx> +#include <tools/hostfilter.hxx> #include <tools/urlobj.hxx> #include <osl/diagnose.h> #include <o3tl/string_view.hxx> @@ -1318,6 +1321,13 @@ void ScHTMLLayoutParser::Image( HtmlImportInfo* pInfo ) return ; } + if (comphelper::LibreOfficeKit::isActive()) + { + INetURLObject aURL(pImage->aURL); + if (HostFilter::isForbidden(aURL.GetHost())) + SfxLokHelper::sendNetworkAccessError(); + } + sal_uInt16 nFormat; std::optional<Graphic> oGraphic(std::in_place); GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx index 2e3674f7d287..853b35bb7431 100644 --- a/sfx2/source/view/lokhelper.cxx +++ b/sfx2/source/view/lokhelper.cxx @@ -37,6 +37,7 @@ #include <comphelper/lok.hxx> #include <sfx2/msgpool.hxx> #include <comphelper/scopeguard.hxx> +#include <tools/json_writer.hxx> #include <boost/property_tree/json_parser.hpp> @@ -1074,4 +1075,20 @@ VclPtr<vcl::Window> SfxLokHelper::getInPlaceDocWindow(SfxViewShell* pViewShell) return {}; } +void SfxLokHelper::sendNetworkAccessError() +{ + tools::JsonWriter aWriter; + aWriter.put("code", static_cast<sal_uInt32>( + ErrCode(ErrCodeArea::Inet, sal_uInt16(ErrCodeClass::Access)))); + aWriter.put("kind", "network"); + aWriter.put("cmd", "paste"); + + SfxViewShell* pViewShell = SfxViewShell::Current(); + if (pViewShell) + { + pViewShell->libreOfficeKitViewCallback( + LOK_CALLBACK_ERROR, aWriter.finishAndGetAsOString()); + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/html/htmlgrin.cxx b/sw/source/filter/html/htmlgrin.cxx index 072b8945d234..8f04dce5546e 100644 --- a/sw/source/filter/html/htmlgrin.cxx +++ b/sw/source/filter/html/htmlgrin.cxx @@ -19,6 +19,7 @@ #include <memory> #include <hintids.hxx> +#include <comphelper/lok.hxx> #include <comphelper/string.hxx> #include <comphelper/documentinfo.hxx> #include <vcl/svapp.hxx> @@ -34,6 +35,7 @@ #include <editeng/langitem.hxx> #include <sfx2/docfile.hxx> #include <sfx2/event.hxx> +#include <sfx2/lokhelper.hxx> #include <vcl/imap.hxx> #include <svtools/htmltokn.h> #include <svtools/htmlkywd.hxx> @@ -69,6 +71,7 @@ #include <vcl/graphicfilter.hxx> #include <tools/UnitConversion.hxx> +#include <tools/hostfilter.hxx> #include <tools/urlobj.hxx> #include <unotools/securityoptions.hxx> @@ -509,6 +512,9 @@ IMAGE_SETEVENT: } else if (m_sBaseURL.isEmpty() || !aGraphicData.isEmpty()) { + if (comphelper::LibreOfficeKit::isActive() && HostFilter::isForbidden(aGraphicURL.GetHost())) + SfxLokHelper::sendNetworkAccessError(); + // sBaseURL is empty if the source is clipboard // aGraphicData is non-empty for <object data="..."> -> not a linked graphic. if (ERRCODE_NONE == GraphicFilter::GetGraphicFilter().ImportGraphic(aGraphic, aGraphicURL)) commit 440dec9a7e854d7d3dced73625db52796700d8e6 Author: Szymon Kłos <szymon.k...@collabora.com> AuthorDate: Fri Dec 1 08:35:51 2023 +0100 Commit: Szymon Kłos <szymon.k...@collabora.com> CommitDate: Mon Jan 15 21:07:27 2024 +0100 lok: external data source list Make possible to filter allowed data sources. It is used for WebDAV curl, WEBSERVICE function, cell external references. Change-Id: Ifc82af31ff1123b5656a21e6a27624fb1616db39 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160196 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161772 Tested-by: Jenkins Reviewed-by: Szymon Kłos <szymon.k...@collabora.com> diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 58e0f2d64413..6d141aeca865 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -236,6 +236,8 @@ #include <com/sun/star/ui/XAcceleratorConfiguration.hpp> #include <svtools/acceleratorexecute.hxx> +#include <tools/hostfilter.hxx> + using namespace css; using namespace vcl; using namespace desktop; @@ -7763,6 +7765,12 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char } #endif + char* pAllowlist = ::getenv("LOK_HOST_ALLOWLIST"); + if (pAllowlist) + { + HostFilter::setAllowedHostsRegex(pAllowlist); + } + // What stage are we at ? if (pThis == nullptr) { diff --git a/include/tools/hostfilter.hxx b/include/tools/hostfilter.hxx new file mode 100644 index 000000000000..afbf885b0cb4 --- /dev/null +++ b/include/tools/hostfilter.hxx @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * 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/. + */ + +#ifndef INCLUDED_TOOLS_HOSTFILTER_HXX +#define INCLUDED_TOOLS_HOSTFILTER_HXX + +#include <rtl/ustring.hxx> +#include <tools/toolsdllapi.h> + +// Helper for filtering allowed hosts for remote connections + +class TOOLS_DLLPUBLIC HostFilter +{ +public: + static void setAllowedHostsRegex(const char* sAllowedRegex); + + static bool isForbidden(const OUString& rHost); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sc/source/core/tool/webservicelink.cxx b/sc/source/core/tool/webservicelink.cxx index 156048430636..c30f34300edf 100644 --- a/sc/source/core/tool/webservicelink.cxx +++ b/sc/source/core/tool/webservicelink.cxx @@ -7,7 +7,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include <comphelper/lok.hxx> #include <comphelper/processfactory.hxx> #include <sfx2/linkmgr.hxx> #include <sfx2/bindings.hxx> @@ -16,6 +15,9 @@ #include <com/sun/star/ucb/SimpleFileAccess.hpp> #include <com/sun/star/io/XInputStream.hpp> +#include <tools/hostfilter.hxx> +#include <tools/urlobj.hxx> + #include <utility> #include <webservicelink.hxx> #include <brdcst.hxx> @@ -37,7 +39,9 @@ sfx2::SvBaseLink::UpdateResult ScWebServiceLink::DataChanged(const OUString&, co aResult.clear(); bHasResult = false; - if (comphelper::LibreOfficeKit::isActive()) + INetURLObject aURLObject(aURL); + const OUString sHost = aURLObject.GetHost(); + if (HostFilter::isForbidden(sHost)) { SAL_WARN("sc.ui", "ScWebServiceLink::DataChanged: blocked access to external file: \"" << aURL << "\""); diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx index 01476aababe0..58e10dc77e88 100644 --- a/sc/source/ui/docshell/externalrefmgr.cxx +++ b/sc/source/ui/docshell/externalrefmgr.cxx @@ -50,6 +50,7 @@ #include <svl/urihelper.hxx> #include <svl/sharedstringpool.hxx> #include <sfx2/linkmgr.hxx> +#include <tools/hostfilter.hxx> #include <tools/urlobj.hxx> #include <unotools/charclass.hxx> #include <unotools/configmgr.hxx> @@ -2542,7 +2543,9 @@ SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, OUSt if (!isFileLoadable(aFile)) return nullptr; - if (comphelper::LibreOfficeKit::isActive()) + INetURLObject aURLObject(aFile); + const OUString sHost = aURLObject.GetHost(); + if (HostFilter::isForbidden(sHost)) { SAL_WARN( "sc.ui", "ScExternalRefManager::loadSrcDocument: blocked access to external file: \"" << aFile << "\""); return nullptr; diff --git a/tools/Library_tl.mk b/tools/Library_tl.mk index 8269e6ae98bf..99176a7c0902 100644 --- a/tools/Library_tl.mk +++ b/tools/Library_tl.mk @@ -67,6 +67,7 @@ $(eval $(call gb_Library_add_exception_objects,tl,\ tools/source/inet/inetmime \ tools/source/inet/inetmsg \ tools/source/inet/inetstrm \ + tools/source/inet/hostfilter \ tools/source/memtools/multisel \ tools/source/misc/cpuid \ tools/source/misc/extendapplicationenvironment \ diff --git a/tools/source/inet/hostfilter.cxx b/tools/source/inet/hostfilter.cxx new file mode 100644 index 000000000000..5bc63d42cfb7 --- /dev/null +++ b/tools/source/inet/hostfilter.cxx @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * 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 <tools/hostfilter.hxx> +#include <regex> + +static std::regex g_AllowedHostsRegex(""); +static bool g_AllowedHostsSet = false; + +void HostFilter::setAllowedHostsRegex(const char* sAllowedRegex) +{ + g_AllowedHostsSet = sAllowedRegex && sAllowedRegex[0] != ' + if (g_AllowedHostsSet) + g_AllowedHostsRegex = sAllowedRegex; +} + +bool HostFilter::isForbidden(const OUString& rHost) +{ + if (!g_AllowedHostsSet) + return false; + + return !std::regex_match(rHost.toUtf8().getStr(), g_AllowedHostsRegex); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/ucb/source/ucp/webdav-curl/CurlSession.cxx b/ucb/source/ucp/webdav-curl/CurlSession.cxx index a54e9d1addfb..11dc964fbe00 100644 --- a/ucb/source/ucp/webdav-curl/CurlSession.cxx +++ b/ucb/source/ucp/webdav-curl/CurlSession.cxx @@ -37,6 +37,7 @@ #include <rtl/strbuf.hxx> #include <rtl/ustrbuf.hxx> #include <systools/curlinit.hxx> +#include <tools/hostfilter.hxx> #include <config_version.h> #include <map> @@ -1116,6 +1117,12 @@ auto CurlProcessor::ProcessRequest( ::std::pair<::std::vector<OUString> const&, DAVResource&> const* const pRequestedHeaders) -> void { + if (HostFilter::isForbidden(rURI.GetHost())) + { + SAL_WARN("ucb.ucp.webdav.curl", "Access denied to host: " << rURI.GetHost()); + throw uno::RuntimeException("access to host denied"); + } + if (pEnv) { // add custom request headers passed by caller for (auto const& rHeader : pEnv->m_aRequestHeaders) commit e727fc495a8e1bf423105e983ce194924e8ad618 Author: Szymon Kłos <szymon.k...@collabora.com> AuthorDate: Thu Nov 30 15:36:57 2023 +0100 Commit: Szymon Kłos <szymon.k...@collabora.com> CommitDate: Mon Jan 15 21:07:27 2024 +0100 lok: import Work path from LOK_WORKDIR Change-Id: If0c9727f53c1c4dfb78d1ccbd6b3ff602268bbf7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160156 Reviewed-by: Michael Meeks <michael.me...@collabora.com> Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161059 Tested-by: Jenkins Reviewed-by: Szymon Kłos <szymon.k...@collabora.com> diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 0e17568717e6..58e0f2d64413 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -7988,6 +7988,14 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char OUString aNewTemp; osl::FileBase::getTempDirURL(aNewTemp); aOptions.SetTempPath(aNewTemp); + { + const char *pWorkPath = getenv("LOK_WORKDIR"); + if (pWorkPath) + { + OString sWorkPath(pWorkPath); + aOptions.SetWorkPath(OStringToOUString(sWorkPath, RTL_TEXTENCODING_UTF8)); + } + } desktop::Desktop::CreateTemporaryDirectory(); // The RequestHandler is specifically set to be ready when all the other diff --git a/include/unotools/pathoptions.hxx b/include/unotools/pathoptions.hxx index c7468048d5df..c19a2b34baf4 100644 --- a/include/unotools/pathoptions.hxx +++ b/include/unotools/pathoptions.hxx @@ -106,6 +106,7 @@ public: void SetAutoTextPath( const OUString& rPath ); void SetBasicPath( const OUString& rPath ); void SetTempPath( const OUString& rPath ); + void SetWorkPath( const OUString& rPath ); OUString SubstituteVariable( const OUString& rVar ) const; OUString ExpandMacros( const OUString& rPath ) const; diff --git a/unotools/source/config/pathoptions.cxx b/unotools/source/config/pathoptions.cxx index 24c1fb323dcc..4234ec903df9 100644 --- a/unotools/source/config/pathoptions.cxx +++ b/unotools/source/config/pathoptions.cxx @@ -122,6 +122,7 @@ class SvtPathOptions_Impl void SetAutoTextPath( const OUString& rPath ) { SetPath( SvtPathOptions::Paths::AutoText, rPath ); } void SetBasicPath( const OUString& rPath ) { SetPath( SvtPathOptions::Paths::Basic, rPath ); } void SetTempPath( const OUString& rPath ) { SetPath( SvtPathOptions::Paths::Temp, rPath ); } + void SetWorkPath( const OUString& rPath ) { SetPath( SvtPathOptions::Paths::Work, rPath ); } OUString SubstVar( const OUString& rVar ) const; OUString ExpandMacros( const OUString& rPath ) const; @@ -589,6 +590,11 @@ void SvtPathOptions::SetTempPath( const OUString& rPath ) pImpl->SetTempPath( rPath ); } +void SvtPathOptions::SetWorkPath( const OUString& rPath ) +{ + pImpl->SetWorkPath( rPath ); +} + OUString SvtPathOptions::SubstituteVariable( const OUString& rVar ) const { return pImpl->SubstVar( rVar ); commit 997899472d8644375285593d89ca0ab0bd56ec69 Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Sat Nov 25 21:24:49 2023 +0000 Commit: Szymon Kłos <szymon.k...@collabora.com> CommitDate: Mon Jan 15 21:07:27 2024 +0100 lok: import allowed paths from the SAL_ALLOWED_PATHS. Do this on second init, in order to be able to reset this for each child kit process. Change-Id: I6939ea3677ea2b84c8944b63a9a9120e880a6bfa Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159961 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Szymon Kłos <szymon.k...@collabora.com> diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index efed041791bf..0e17568717e6 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -7754,6 +7754,15 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char } } +#ifdef LINUX + { + const char *pAllowedPaths = getenv("SAL_ALLOWED_PATHS"); + if (pAllowedPaths) + osl_setAllowedPaths( + OUString(pAllowedPaths, strlen(pAllowedPaths), RTL_TEXTENCODING_UTF8).pData); + } +#endif + // What stage are we at ? if (pThis == nullptr) { commit 5e66863ae42bf0e5b614a8f21dc44a15df727922 Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Wed Nov 22 19:37:38 2023 +0000 Commit: Szymon Kłos <szymon.k...@collabora.com> CommitDate: Mon Jan 15 21:07:27 2024 +0100 sal: initial osl::File sand-boxing commit for Unix. Change-Id: If2c106fef9640499b82b5cf350cb5169beb219fb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159838 Reviewed-by: Szymon Kłos <szymon.k...@collabora.com> Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Michael Meeks <michael.me...@collabora.com> diff --git a/include/osl/file.h b/include/osl/file.h index 07d2beb2ae1f..98ad568550b9 100644 --- a/include/osl/file.h +++ b/include/osl/file.h @@ -960,6 +960,54 @@ SAL_DLLPUBLIC oslFileError SAL_CALL osl_readFile( SAL_DLLPUBLIC oslFileError SAL_CALL osl_isEndOfFile( oslFileHandle Handle, sal_Bool *pIsEOF ); +/** Resets the list of paths and associated permissions for osl + + @param[in] pustrFileURLs + Contains a ':' delimited list of control strings and paths. + Control segments are a short path that refers to the following + segments and contain either: + + r: read-only paths follow (the default) + w: read & write paths follow + x: executable paths follow + + Any real paths (ie. having resolved all symlinks) + accessed outside of these paths will cause an + osl_File_E_ACCESS error in the relevant method calls. + + This method is Unix specific. + + @see osl_isForbiddenPath + + @since LibreOffice 7.7 +*/ +SAL_DLLPUBLIC void SAL_CALL osl_setAllowedPaths( + rtl_uString *pustrFileURLs + ); + +/** + Determine if the passed in path is not contained inside + the allowed paths, or if no allowed paths are set it + will not forbid any access. + + @param[in] pustrFileURL + A URL (or path) that we want to check if it is forbidden + to access. + + @param[in] nFlags + Flags to determine what type of access is requested, + osl_File_OpenFlag_Read | Write, or 0x80 for 'execute'. + + This method is Unix specific. + + @see osl_setAllowedPaths + + @since LibreOffice 7.7 + */ +SAL_DLLPUBLIC sal_Bool SAL_CALL osl_isForbiddenPath( + rtl_uString *pustrFileURL, int nFlags + ); + /** Write a number of bytes to a file. Writes a number of bytes to a file. diff --git a/include/osl/file.hxx b/include/osl/file.hxx index fcbabe96d674..6330247ba818 100644 --- a/include/osl/file.hxx +++ b/include/osl/file.hxx @@ -313,6 +313,58 @@ public: return static_cast< RC >( osl_createTempFile(pustr_dir_url, pHandle, ppustr_tmp_file_url) ); } + + + /** Resets the list of paths and associated permissions for osl + + @param[in] rPaths + Contains a ':' delimited list of control strings and paths. + Control segments are a short path that refers to the following + segments and contain either: + + r: read-only paths follow (the default) + w: read & write paths follow + x: executable paths follow + + Any real paths (ie. having resolved all symlinks) + accessed outside of these paths will cause an + osl_File_E_ACCESS error in the relevant method calls. + + This method is Unix specific. + + @see osl_isForbiddenPath + + @since LibreOffice 7.7 + */ + + static void setAllowedPaths(const OUString &rPaths) + { + osl_setAllowedPaths(rPaths.pData); + } + + /** + Determine if the passed in path is not contained inside + the allowed paths, or if no allowed paths are set it + will not forbid any access. + + @param[in] pustrFileURL + A URL (or path) that we want to check if it is forbidden + to access. + + @param[in] nFlags + Flags to determine what type of access is requested, + osl_File_OpenFlag_Read | Write, or 0x80 for 'execute'. + + This method is Unix specific. + + @see osl_setAllowedPaths + + @since LibreOffice 7.7 + */ + static bool isForbidden(const OUString &rPath, int nFlags) + { + return osl_isForbiddenPath(rPath.pData, nFlags); + } }; diff --git a/sal/osl/unx/file.cxx b/sal/osl/unx/file.cxx index eeee7c803fd8..848a586ad2ce 100644 --- a/sal/osl/unx/file.cxx +++ b/sal/osl/unx/file.cxx @@ -784,6 +784,125 @@ static bool osl_file_queryLocking(sal_uInt32 uFlags) return false; } +static bool abortOnForbidden = false; +static std::vector<OString> allowedPathsRead; +static std::vector<OString> allowedPathsReadWrite; +static std::vector<OString> allowedPathsExecute; + +SAL_DLLPUBLIC void osl_setAllowedPaths( + rtl_uString *pustrFilePaths + ) +{ + allowedPathsRead.clear(); + allowedPathsReadWrite.clear(); + allowedPathsExecute.clear(); + + if (!pustrFilePaths) + return; + + char eType = 'r'; + sal_Int32 nIndex = 0; + OUString aPaths(pustrFilePaths); + do + { + OString aPath = rtl::OUStringToOString( + aPaths.getToken(0, ':', nIndex), + RTL_TEXTENCODING_UTF8); + + if (aPath.getLength() == 0) + continue; + + if (aPath.getLength() == 1) + { + eType = aPath[0]; + continue; + } + + char resolvedPath[PATH_MAX]; + if (realpath(aPath.getStr(), resolvedPath)) + { + OString aPushPath = OString(resolvedPath, strlen(resolvedPath)); + if (eType == 'r') + allowedPathsRead.push_back(aPushPath); + else if (eType == 'w') + { + allowedPathsRead.push_back(aPushPath); + allowedPathsReadWrite.push_back(aPushPath); + } + else if (eType == 'x') + allowedPathsExecute.push_back(aPushPath); + } + } + while (nIndex != -1); + + abortOnForbidden = !!getenv("SAL_ABORT_ON_FORBIDDEN"); +} + +bool isForbidden(const OString &filePath, int nFlags) +{ + // avoid realpath cost unless configured + if (allowedPathsRead.size() == 0) + return false; + + char resolvedPath[PATH_MAX]; + if (!realpath(filePath.getStr(), resolvedPath)) + { + // write calls path a non-existent path that realpath will + // fail to resolve. Thankfully our I/O APIs don't allow + // symlink creation to race here. + sal_Int32 n = filePath.lastIndexOf('/'); + OString folderPath; + if (n < 1) + folderPath = "."; + else + folderPath = filePath.copy(0, n); + if (!realpath(folderPath.getStr(), resolvedPath) || + strlen(resolvedPath) + filePath.getLength() - n + 1 >= PATH_MAX) + return true; // too bad + else + strcat(resolvedPath, filePath.getStr() + n); + } + + const std::vector<OString> *pCheckPaths = &allowedPathsRead; + if (nFlags & osl_File_OpenFlag_Write || + nFlags & osl_File_OpenFlag_Create) + pCheckPaths = &allowedPathsReadWrite; + else if (nFlags & 0x80) + pCheckPaths = &allowedPathsExecute; + + bool allowed = false; + for (const auto &it : *pCheckPaths) { + if (!strncmp(resolvedPath, it.getStr(), it.getLength())) + { + allowed = true; + break; + } + } + + if (!allowed) + SAL_WARN("sal.osl", "access outside sandbox to " << + ((nFlags & osl_File_OpenFlag_Write || + nFlags & osl_File_OpenFlag_Create) ? "w" : + (nFlags & 0x80) ? "x" : "r") << ":" << + filePath << " which is really " << resolvedPath << + (allowed ? " allowed " : " forbidden") << + " check list: " << pCheckPaths->size()); + + if (abortOnForbidden && !allowed) + abort(); // a bit abrupt - but don't try to escape. + + return !allowed; +} + +SAL_DLLPUBLIC sal_Bool SAL_CALL osl_isForbiddenPath( + rtl_uString *pustrFileURL, int nFlags + ) +{ + return isForbidden( + rtl::OUStringToOString(OUString(pustrFileURL), + RTL_TEXTENCODING_UTF8), nFlags); +} + #ifdef HAVE_O_EXLOCK #define OPEN_WRITE_FLAGS ( O_RDWR | O_EXLOCK | O_NONBLOCK ) #define OPEN_CREATE_FLAGS ( O_CREAT | O_RDWR | O_EXLOCK | O_NONBLOCK ) @@ -988,6 +1107,10 @@ oslFileError openFilePath(const OString& filePath, oslFileHandle* pHandle, if (flags & O_EXCL && !(flags & O_CREAT)) flags &= ~O_EXCL; + // Sandboxing hook + if (isForbidden( filePath, uFlags )) + return osl_File_E_ACCES; + /* open the file */ int fd = open_c( filePath, flags, mode ); if (fd == -1) @@ -1602,4 +1725,5 @@ oslFileError SAL_CALL osl_setFileSize(oslFileHandle Handle, sal_uInt64 uSize) return pImpl->setSize(uSize); } + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/osl/unx/file_impl.hxx b/sal/osl/unx/file_impl.hxx index 4a9a90d4160f..64504296955d 100644 --- a/sal/osl/unx/file_impl.hxx +++ b/sal/osl/unx/file_impl.hxx @@ -40,6 +40,8 @@ struct DirectoryItem_Impl oslFileType getFileType() const; }; +bool isForbidden(const OString &filePath, int nFlags); + oslFileError openFile( rtl_uString * pustrFileURL, oslFileHandle * pHandle, sal_uInt32 uFlags, mode_t mode); diff --git a/sal/osl/unx/file_misc.cxx b/sal/osl/unx/file_misc.cxx index 752c85393b86..69ca29cdbaa4 100644 --- a/sal/osl/unx/file_misc.cxx +++ b/sal/osl/unx/file_misc.cxx @@ -143,6 +143,9 @@ oslFileError SAL_CALL osl_openDirectory(rtl_uString* ustrDirectoryURL, oslDirect osl_systemPathRemoveSeparator(path.pData); + if (isForbidden(path.getStr(), osl_File_OpenFlag_Read)) + return osl_File_E_ACCES; + #ifdef MACOSX { auto const n = std::max(int(path.getLength() + 1), int(PATH_MAX)); @@ -343,6 +346,9 @@ oslFileError SAL_CALL osl_getDirectoryItem(rtl_uString* ustrFileURL, oslDirector osl_systemPathRemoveSeparator(strSystemPath.pData); + if (isForbidden(strSystemPath, osl_File_OpenFlag_Read)) + return osl_File_E_ACCES; + if (osl::access(strSystemPath, F_OK) == -1) { osl_error = oslTranslateFileError(errno); @@ -426,6 +432,9 @@ oslFileError SAL_CALL osl_removeDirectory( rtl_uString* ustrDirectoryURL ) oslFileError osl_psz_createDirectory(char const * pszPath, sal_uInt32 flags) { + if (isForbidden(pszPath, osl_File_OpenFlag_Create)) + return osl_File_E_ACCES; + int nRet=0; int mode = (((flags & osl_File_OpenFlag_Read) == 0 @@ -455,6 +464,9 @@ oslFileError osl_psz_createDirectory(char const * pszPath, sal_uInt32 flags) static oslFileError osl_psz_removeDirectory( const char* pszPath ) { + if (isForbidden(pszPath, osl_File_OpenFlag_Write)) + return osl_File_E_ACCES; + int nRet = rmdir(pszPath); if ( nRet < 0 ) @@ -550,6 +562,9 @@ oslFileError SAL_CALL osl_createDirectoryPath( osl::systemPathRemoveSeparator(sys_path); + if (isForbidden(sys_path.getStr(), osl_File_OpenFlag_Create)) + return osl_File_E_ACCES; + // const_cast because sys_path is a local copy which we want to modify inplace instead of // copy it into another buffer on the heap again return create_dir_recursively_(sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData); @@ -584,6 +599,10 @@ oslFileError SAL_CALL osl_moveFile( rtl_uString* ustrFileURL, rtl_uString* ustrD if( eRet != osl_File_E_None ) return eRet; + if (isForbidden(srcPath, osl_File_OpenFlag_Read) || + isForbidden(destPath, osl_File_OpenFlag_Create)) + return osl_File_E_ACCES; + #ifdef MACOSX if ( macxp_resolveAlias( srcPath, PATH_MAX ) != 0 || macxp_resolveAlias( destPath, PATH_MAX ) != 0 ) return oslTranslateFileError( errno ); @@ -597,6 +616,10 @@ oslFileError SAL_CALL osl_replaceFile(rtl_uString* ustrFileURL, rtl_uString* ust int nGid = -1; char destPath[PATH_MAX]; oslFileError eRet = FileURLToPath(destPath, PATH_MAX, ustrDestURL); + + if (isForbidden(destPath, osl_File_OpenFlag_Create)) + return osl_File_E_ACCES; + if (eRet == osl_File_E_None) { struct stat aFileStat; @@ -673,6 +696,9 @@ oslFileError SAL_CALL osl_removeFile(rtl_uString* ustrFileURL) return oslTranslateFileError(errno); #endif/* MACOSX */ + if (isForbidden(path, osl_File_OpenFlag_Write)) + return osl_File_E_ACCES; + return osl_unlinkFile(path); } @@ -728,6 +754,10 @@ static oslFileError osl_unlinkFile(const char* pszPath) static oslFileError osl_psz_moveFile(const char* pszPath, const char* pszDestPath) { + if (isForbidden(pszPath, osl_File_OpenFlag_Read) || + isForbidden(pszDestPath, osl_File_OpenFlag_Create)) + return osl_File_E_ACCES; + int nRet = rename(pszPath,pszDestPath); if (nRet < 0) @@ -755,6 +785,10 @@ static oslFileError osl_psz_copyFile( const char* pszPath, const char* pszDestPa size_t nSourceSize=0; bool DestFileExists=true; + if (isForbidden(pszPath, osl_File_OpenFlag_Read) || + isForbidden(pszDestPath, osl_File_OpenFlag_Create)) + return osl_File_E_ACCES; + /* mfe: does the source file really exists? */ nRet = lstat_c(pszPath,&aFileStat); diff --git a/sal/osl/unx/file_stat.cxx b/sal/osl/unx/file_stat.cxx index 5c165132e9f3..3d0754883a11 100644 --- a/sal/osl/unx/file_stat.cxx +++ b/sal/osl/unx/file_stat.cxx @@ -274,6 +274,9 @@ static oslFileError osl_psz_setFileAttributes( const char* pszFilePath, sal_uInt OSL_ENSURE(!(osl_File_Attribute_Hidden & uAttributes), "osl_File_Attribute_Hidden doesn't work under Unix"); + if (isForbidden(pszFilePath, osl_File_OpenFlag_Write)) + return osl_File_E_ACCES; + if (uAttributes & osl_File_Attribute_OwnRead) nNewMode |= S_IRUSR; @@ -339,6 +342,9 @@ static oslFileError osl_psz_setFileTime ( struct tm* pTM=0; #endif + if (isForbidden(pszFilePath, osl_File_OpenFlag_Write)) + return osl_File_E_ACCES; + nRet = lstat_c(pszFilePath,&aFileStat); if ( nRet < 0 ) diff --git a/sal/osl/unx/file_volume.cxx b/sal/osl/unx/file_volume.cxx index e20b8a27d00e..0a6183292735 100644 --- a/sal/osl/unx/file_volume.cxx +++ b/sal/osl/unx/file_volume.cxx @@ -26,6 +26,7 @@ #include "file_error_transl.hxx" #include "file_url.hxx" +#include "file_impl.hxx" #include "system.hxx" #include <errno.h> @@ -193,6 +194,9 @@ static oslFileError osl_psz_getVolumeInformation ( if (!pInfo) return osl_File_E_INVAL; + if (isForbidden(pszDirectory, osl_File_OpenFlag_Read)) + return osl_File_E_ACCES; + pInfo->uValidFields = 0; pInfo->uAttributes = 0; pInfo->uTotalSpace = 0; diff --git a/sal/osl/unx/pipe.cxx b/sal/osl/unx/pipe.cxx index 4dfd75ddf662..62897552ed41 100644 --- a/sal/osl/unx/pipe.cxx +++ b/sal/osl/unx/pipe.cxx @@ -29,6 +29,7 @@ #include "sockimpl.hxx" #include "secimpl.hxx" +#include "file_impl.hxx" #include "unixerrnostring.hxx" #include <cassert> @@ -209,6 +210,9 @@ static oslPipe osl_psz_createPipe(const char *pszPipeName, oslPipeOptions Option SAL_INFO("sal.osl.pipe", "new pipe on fd " << pPipe->m_Socket << " '" << name << "'"); + if (isForbidden(name.getStr(), osl_File_OpenFlag_Create)) + return nullptr; + addr.sun_family = AF_UNIX; // coverity[fixed_size_dest : FALSE] - safe, see check above strcpy(addr.sun_path, name.getStr()); diff --git a/sal/osl/unx/process.cxx b/sal/osl/unx/process.cxx index cebdc6f35fdb..1d1548129f6d 100644 --- a/sal/osl/unx/process.cxx +++ b/sal/osl/unx/process.cxx @@ -19,7 +19,7 @@ #include <sal/config.h> #include <rtl/ustring.hxx> - +#include "file_impl.hxx" #include <cassert> #include <fcntl.h> #include <limits.h> @@ -598,6 +598,9 @@ oslProcessError osl_psz_executeProcess(char *pszImageName, return osl_Process_E_NotFound; } + if (isForbidden(pszImageName, 0x80 /* execute */)) + return osl_Process_E_NoPermission; + Data.m_pszArgs[0] = strdup(pszImageName); Data.m_pszArgs[1] = nullptr; diff --git a/sal/osl/unx/profile.cxx b/sal/osl/unx/profile.cxx index 1e7512a24db4..1ef1965b7c14 100644 --- a/sal/osl/unx/profile.cxx +++ b/sal/osl/unx/profile.cxx @@ -20,6 +20,7 @@ #include "system.hxx" #include "readwrite_helper.hxx" #include "file_url.hxx" +#include "file_impl.hxx" #include "unixerrnostring.hxx" #include <osl/diagnose.h> @@ -937,6 +938,9 @@ static osl_TFile* openFileImpl(const char* pszFilename, oslProfileOption Profile osl_TFile* pFile = static_cast<osl_TFile*>(calloc(1, sizeof(osl_TFile))); bool bWriteable = false; + if ( isForbidden( pszFilename, osl_File_OpenFlag_Write ) ) + return nullptr; + if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) ) { bWriteable = true; diff --git a/sal/qa/osl/file/osl_File.cxx b/sal/qa/osl/file/osl_File.cxx index 6b0c50dfafd8..0de87eeb14a9 100644 --- a/sal/qa/osl/file/osl_File.cxx +++ b/sal/qa/osl/file/osl_File.cxx @@ -1313,6 +1313,124 @@ namespace osl_FileBase CPPUNIT_REGISTRY_ADD_TO_DEFAULT("osl_osl::FileBase"); } +#if (defined UNX) + +namespace osl_Forbidden +{ + + class Forbidden : public CppUnit::TestFixture + { + OUString maScratchBad; + OUString maScratchGood; + public: + void setUp() override + { + // create a directory to play in + createTestDirectory(aTmpName3); + OUString aBadURL = aTmpName3 + "/bad"; + OUString aGoodURL = aTmpName3 + "/good"; + createTestDirectory(aBadURL); + createTestDirectory(aGoodURL); + File::getSystemPathFromFileURL(aBadURL, maScratchBad); + File::getSystemPathFromFileURL(aGoodURL, maScratchGood); + } + + void tearDown() override + { + osl_setAllowedPaths(nullptr); + OUString aBadURL = aTmpName3 + "/bad"; + OUString aGoodURL = aTmpName3 + "/good"; + deleteTestDirectory(aBadURL); + deleteTestDirectory(aGoodURL); + deleteTestDirectory(aTmpName3); + } + + void forbidden() + { + File::setAllowedPaths(maScratchGood); + CPPUNIT_ASSERT_EQUAL_MESSAGE("read bad should be forbidden", + true, File::isForbidden(maScratchBad, osl_File_OpenFlag_Read)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("read from good should be allowed", + false, File::isForbidden(maScratchGood, osl_File_OpenFlag_Read)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("write to good should be forbidden", + true, File::isForbidden(maScratchGood, osl_File_OpenFlag_Write)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("create in good should be forbidden", + true, File::isForbidden(maScratchGood, osl_File_OpenFlag_Create)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("exec from good should be forbidden", + true, File::isForbidden(maScratchGood, 0x80)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("write to non-existent should be forbidden", + true, File::isForbidden(maScratchBad + "/notthere", osl_File_OpenFlag_Write)); + + File::setAllowedPaths("w:" + maScratchGood + ":x:" + maScratchBad); + CPPUNIT_ASSERT_EQUAL_MESSAGE("read bad should be forbidden", + true, File::isForbidden(maScratchBad, osl_File_OpenFlag_Read)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("read from good should be allowed", // w implies 'r' + false, File::isForbidden(maScratchGood, osl_File_OpenFlag_Read)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("write to good should be allowed", + false, File::isForbidden(maScratchGood, osl_File_OpenFlag_Write)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("exec from good should be forbidden", + true, File::isForbidden(maScratchGood, 0x80)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("exec from bad should be allowed", + false, File::isForbidden(maScratchBad, 0x80)); + } + + void open() + { + File::setAllowedPaths(maScratchGood); + File testFile(maScratchBad + "/open"); + auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write); + CPPUNIT_ASSERT_EQUAL_MESSAGE("disabled path allowed", osl::FileBase::E_ACCES, nError1); + deleteTestFile(testFile.getURL()); + } + + void copy() + { + File::setAllowedPaths("w:" + maScratchGood); + File testGood(maScratchGood + "/good"); + File testGoodTo(maScratchGood + "/good_to"); + File testBad(maScratchBad + "/bad"); + + auto nError1 = testGood.open(osl_File_OpenFlag_Create); + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1); + + auto nErrorCopy = File::copy(maScratchGood + "/good", maScratchGood + "/good_to"); + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nErrorCopy); + + auto nErrorCopyBad = File::copy(maScratchGood + "/good_to", maScratchBad + "/bad"); + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_ACCES, nErrorCopyBad); + + deleteTestFile(maScratchGood + "/good_to"); + deleteTestFile(maScratchGood + "/good"); + } + + void nextTests() + { + // more entry points to test +#if 0 + auto nError1 = File::move(aTmpName4, aCanURL1); + auto nError2 = File::remove(aTmpName4); + auto nError3 = File::setAttributes(aTmpName6, osl_File_Attribute_ReadOnly); + bool bOk = osl_getSystemTime(pTV_current); + CPPUNIT_ASSERT(bOk); + auto nError4 = File::setTime(aTmpName6, *pTV_current, *pTV_current, *pTV_current); + CPPUNIT_ASSERT_EQUAL_MESSAGE(errorToStr(nError2).getStr(), osl::FileBase::E_None, nError2); +#endif + } + + CPPUNIT_TEST_SUITE(Forbidden); + CPPUNIT_TEST(forbidden); +// CPPUNIT_TEST(open); +// CPPUNIT_TEST(copy); +// CPPUNIT_TEST(nextTests); + CPPUNIT_TEST_SUITE_END(); + }; + + CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Forbidden::Forbidden, "osl_Forbidden"); + + CPPUNIT_REGISTRY_ADD_TO_DEFAULT("osl_Forbidden"); +} +#endif + namespace osl_FileStatus { // testing the method diff --git a/sal/util/sal.map b/sal/util/sal.map index c5c3e4d55641..586a41ee997d 100644 --- a/sal/util/sal.map +++ b/sal/util/sal.map @@ -761,6 +761,12 @@ PRIVATE_1.8 { # LibreOffice 7.3 rtl_uString_newReplaceStrAtUtf16L; } PRIVATE_1.7; +PRIVATE_1.9 { # LibreOffice 7.7 + global: + osl_setAllowedPaths; + osl_isForbiddenPath; +} PRIVATE_1.8; + PRIVATE_textenc.1 { # LibreOffice 3.6 global: _ZN3sal6detail7textenc20convertCharToUnicode*;