From fdd69f4dc8c8d804074fedd0f480d5c384c748a2 Mon Sep 17 00:00:00 2001 From: Michael Stahl Date: Mon, 2 Mar 2026 19:47:00 +0100 Subject: [PATCH] sw: improve error reporting of networked AutoText Every error about an AutoText path is reported as "Inadmissible path", which might imply that the path doesn't exist. In the situation where the AutoText is on a WebDAV share that is mounted by Windows Explorer, the path will be a file:// URL, and it is possible that the user needs to authenticate before being able to access the files, but it's not known how an authentication dialog could be shown in LO (the Windows File Picker dialog is able to do this btw), so detect this situation and show a more specific error message. (As far as possible; we cannot tell if the problem is that the user is not authenticated or if it is that the user is not authorised to access). Use `PathIsNetworkPathW` to check if it is a mounted network location. In case the network location is not reachable, the error code will be different and the generic error dialog will be shown. sw: fix -Werror=undef (cherry picked from commit cee293d3ee4fef108790eed63c69eee40d37c0bf) Change-Id: I633ea331f957edb4a943426464524a5decf0fe15 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/200856 Tested-by: allotropia jenkins Reviewed-by: Thorsten Behrens (cherry picked from commit 7a2efe02293382374cd80f9d23215740e731c755) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/201398 Tested-by: Jenkins CollaboraOffice Reviewed-by: Stephan Bergmann (cherry picked from commit 19e9e767145a5147bfee59f0b476c6a7dbf3ba12) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/201468 Tested-by: Jenkins Reviewed-by: Michael Stahl --- sw/CppunitTest_sw_uwriter.mk | 4 ++ sw/Library_sw.mk | 4 ++ sw/inc/strings.hrc | 1 + sw/source/uibase/inc/glosdoc.hxx | 5 +- sw/source/uibase/misc/glosdoc.cxx | 82 ++++++++++++++++++++++++++----- 5 files changed, 84 insertions(+), 12 deletions(-) diff --git a/sw/CppunitTest_sw_uwriter.mk b/sw/CppunitTest_sw_uwriter.mk index d48edbf943b0..d15de2cc12bb 100644 --- a/sw/CppunitTest_sw_uwriter.mk +++ b/sw/CppunitTest_sw_uwriter.mk @@ -81,6 +81,10 @@ $(eval $(call gb_CppunitTest_use_externals,sw_uwriter,\ md4c \ )) +$(eval $(call gb_CppunitTest_use_system_win32_libs,sw_uwriter,\ + shlwapi \ +)) + $(eval $(call gb_CppunitTest_set_include,sw_uwriter,\ -I$(SRCDIR)/sw/source/core/inc \ -I$(SRCDIR)/sw/inc \ diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk index cd8f026352e0..42e26a455ddd 100644 --- a/sw/Library_sw.mk +++ b/sw/Library_sw.mk @@ -50,6 +50,10 @@ $(eval $(call gb_Library_add_defs,sw,\ -DSWUI_DLL_NAME=\"$(call gb_Library_get_runtime_filename,$(call gb_Library__get_name,swui))\" \ )) +$(eval $(call gb_Library_use_system_win32_libs,sw,\ + shlwapi \ +)) + $(eval $(call gb_Library_use_libraries,sw,\ avmedia \ basegfx \ diff --git a/sw/inc/strings.hrc b/sw/inc/strings.hrc index 04763d6a3097..52d58d0d0f9a 100644 --- a/sw/inc/strings.hrc +++ b/sw/inc/strings.hrc @@ -889,6 +889,7 @@ #define STR_NO_TABLE NC_("STR_NO_TABLE", "A table with no rows or no cells cannot be inserted") #define STR_TABLE_TOO_LARGE NC_("STR_TABLE_TOO_LARGE", "The table cannot be inserted because it is too large") #define STR_ERR_INSERT_GLOS NC_("STR_ERR_INSERT_GLOS", "AutoText could not be created.") +#define STR_ERR_GLOS_NET_PATH_ACCESS NC_("STR_ERR_GLOS_NET_PATH_ACCESS", "Access to network paths denied. Please check with Windows Explorer if authentication is required to access.") #define STR_CLPBRD_FORMAT_ERROR NC_("STR_CLPBRD_FORMAT_ERROR", "Requested clipboard format is not available.") #define STR_PRIVATETEXT NC_("STR_PRIVATETEXT", "%PRODUCTNAME %PRODUCTVERSION Text Document") #define STR_PRIVATEGRAPHIC NC_("STR_PRIVATEGRAPHIC", "Image (%PRODUCTNAME %PRODUCTVERSION Text Document)") diff --git a/sw/source/uibase/inc/glosdoc.hxx b/sw/source/uibase/inc/glosdoc.hxx index e2ece010b121..5fd001f9e4b1 100644 --- a/sw/source/uibase/inc/glosdoc.hxx +++ b/sw/source/uibase/inc/glosdoc.hxx @@ -33,6 +33,9 @@ typedef rtl::Reference SwDocShellRef; #endif #include +#include + +#include #include #include @@ -50,7 +53,7 @@ class SW_DLLPUBLIC SwGlossaries UnoAutoTextEntries m_aGlossaryEntries; OUString m_aPath; - std::vector m_aInvalidPaths; + std::vector>> m_aInvalidPaths; std::vector m_PathArr; std::vector m_GlosArr; bool m_bError; diff --git a/sw/source/uibase/misc/glosdoc.cxx b/sw/source/uibase/misc/glosdoc.cxx index 2ca96274ba90..57858c67baf9 100644 --- a/sw/source/uibase/misc/glosdoc.cxx +++ b/sw/source/uibase/misc/glosdoc.cxx @@ -21,15 +21,22 @@ #include #include +#include + +#include +#include #include #include #include +#include +#include #include #include #include #include +#include #include #include #include @@ -40,9 +47,15 @@ #include #include +#include #include +#ifdef _WIN32 +#include +#include +#endif + using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -358,7 +371,7 @@ void SwGlossaries::UpdateGlosPath(bool bFull) m_PathArr.clear(); std::vector aDirArr; - std::vector aInvalidPaths; + decltype(m_aInvalidPaths) aInvalidPaths; if (!m_aPath.isEmpty()) { sal_Int32 nIndex = 0; @@ -374,10 +387,30 @@ void SwGlossaries::UpdateGlosPath(bool bFull) continue; } aDirArr.push_back(sPth); - if( !FStatHelper::IsFolder( sPth ) ) - aInvalidPaths.push_back(sPth); - else - m_PathArr.push_back(sPth); + try + { + ::ucbhelper::Content content{sPth, + uno::Reference{}, + ::comphelper::getProcessComponentContext()}; + if (content.isFolder()) + { + m_PathArr.push_back(sPth); + } + else + { + aInvalidPaths.push_back({sPth, {}}); + } + } + catch (ucb::InteractiveIOException const& e) + { + TOOLS_INFO_EXCEPTION("sw.ui", "AutoText path IO Exception: "); + aInvalidPaths.emplace_back(sPth, e.Code); + } + catch (...) + { + TOOLS_INFO_EXCEPTION("sw.ui", "AutoText path Exception: "); + aInvalidPaths.push_back({sPth, {}}); + } } while (nIndex>=0); } @@ -389,11 +422,9 @@ void SwGlossaries::UpdateGlosPath(bool bFull) if (bPathChanged || (m_aInvalidPaths != aInvalidPaths)) { m_aInvalidPaths = std::move(aInvalidPaths); - // wrong path, that means AutoText directory doesn't exist + // AutoText directory not accessible or doesn't exist + ShowError(); - ErrorHandler::HandleError( ErrCodeMsg( - ERR_AUTOPATH_ERROR, lcl_makePath(m_aInvalidPaths), - DialogMask::ButtonsOk | DialogMask::MessageError ) ); m_bError = true; } else @@ -411,8 +442,37 @@ void SwGlossaries::UpdateGlosPath(bool bFull) void SwGlossaries::ShowError() { - ErrCodeMsg nPathError(ERR_AUTOPATH_ERROR, lcl_makePath(m_aInvalidPaths), DialogMask::ButtonsOk ); - ErrorHandler::HandleError( nPathError ); + std::vector netaccess; + std::vector others; + for (auto const& it : m_aInvalidPaths) + { +#ifdef _WIN32 + OUString path; + if (it.second && *it.second == ucb::IOErrorCode_ACCESS_DENIED + && osl::FileBase::getSystemPathFromFileURL(it.first, path) == osl::FileBase::E_None + && PathIsNetworkPathW(o3tl::toW(path.getStr())) == TRUE) + { + netaccess.emplace_back(it.first); + } + else +#endif + { + others.emplace_back(it.first); + } + } + if (!netaccess.empty()) + { + std::unique_ptr const xDialog{ + Application::CreateMessageDialog(nullptr, + VclMessageType::Error, VclButtonsType::Close, + SwResId(STR_ERR_GLOS_NET_PATH_ACCESS) + u"\n\n" + lcl_makePath(netaccess))}; + xDialog->run(); + } + if (!others.empty()) + { + ErrCodeMsg nPathError(ERR_AUTOPATH_ERROR, lcl_makePath(others), DialogMask::ButtonsOk); + ErrorHandler::HandleError( nPathError ); + } } OUString SwGlossaries::GetExtension()