sw/Library_sw.mk | 4 + sw/inc/strings.hrc | 1 sw/source/uibase/inc/glosdoc.hxx | 5 +- sw/source/uibase/misc/glosdoc.cxx | 83 ++++++++++++++++++++++++++++++++------ 4 files changed, 80 insertions(+), 13 deletions(-)
New commits: commit 7a2efe02293382374cd80f9d23215740e731c755 Author: Michael Stahl <[email protected]> AuthorDate: Mon Mar 2 19:47:00 2026 +0100 Commit: Thorsten Behrens <[email protected]> CommitDate: Fri Mar 6 00:59:12 2026 +0100 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. Change-Id: I633ea331f957edb4a943426464524a5decf0fe15 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/200856 Tested-by: allotropia jenkins <[email protected]> Reviewed-by: Thorsten Behrens <[email protected]> diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk index 7999ece93c3d..82d5124d671c 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,\ $(call gb_Helper_optional,AVMEDIA,avmedia) \ basegfx \ diff --git a/sw/inc/strings.hrc b/sw/inc/strings.hrc index 8c771426ef00..17ba9859b387 100644 --- a/sw/inc/strings.hrc +++ b/sw/inc/strings.hrc @@ -794,6 +794,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 14b4be59eef6..fad28d055805 100644 --- a/sw/source/uibase/inc/glosdoc.hxx +++ b/sw/source/uibase/inc/glosdoc.hxx @@ -32,6 +32,9 @@ typedef tools::SvRef<SwDocShell> SwDocShellRef; #endif #include <cppuhelper/weakref.hxx> +#include <com/sun/star/ucb/IOErrorCode.hpp> + +#include <optional> #include <vector> #include <swdllapi.h> @@ -46,7 +49,7 @@ class SW_DLLPUBLIC SwGlossaries UnoAutoTextEntries m_aGlossaryEntries; OUString m_aPath; - std::vector<OUString> m_aInvalidPaths; + std::vector<std::pair<OUString, std::optional<css::ucb::IOErrorCode>>> m_aInvalidPaths; std::vector<OUString> m_PathArr; std::vector<OUString> m_GlosArr; bool m_bError; diff --git a/sw/source/uibase/misc/glosdoc.cxx b/sw/source/uibase/misc/glosdoc.cxx index 69a2df2237cc..3247d7932ab5 100644 --- a/sw/source/uibase/misc/glosdoc.cxx +++ b/sw/source/uibase/misc/glosdoc.cxx @@ -20,15 +20,21 @@ #include <algorithm> #include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/ucb/InteractiveIOException.hpp> + +#include <comphelper/processfactory.hxx> #include <comphelper/servicehelper.hxx> #include <unotools/transliterationwrapper.hxx> #include <vcl/errinf.hxx> +#include <vcl/svapp.hxx> +#include <tools/diagnose_ex.h> #include <osl/diagnose.h> #include <rtl/character.hxx> #include <svl/urihelper.hxx> #include <svl/fstathelper.hxx> +#include <ucbhelper/content.hxx> #include <unotools/pathoptions.hxx> #include <unotools/tempfile.hxx> #include <swtypes.hxx> @@ -39,10 +45,16 @@ #include <unoatxt.hxx> #include <swerror.h> +#include <strings.hrc> #include <globals.hrc> #include <memory> +#ifdef _WIN32 +#include <o3tl/char16_t2wchar_t.hxx> +#include <shlwapi.h> +#endif + using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -358,7 +370,7 @@ void SwGlossaries::UpdateGlosPath(bool bFull) m_PathArr.clear(); std::vector<OUString> aDirArr; - std::vector<OUString> aInvalidPaths; + decltype(m_aInvalidPaths) aInvalidPaths; if (!m_aPath.isEmpty()) { sal_Int32 nIndex = 0; @@ -374,10 +386,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<ucb::XCommandEnvironment>{}, + ::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 +421,9 @@ void SwGlossaries::UpdateGlosPath(bool bFull) if (bPathChanged || (m_aInvalidPaths != aInvalidPaths)) { m_aInvalidPaths = aInvalidPaths; - // wrong path, that means AutoText directory doesn't exist + // AutoText directory not accessible or doesn't exist + ShowError(); - ErrorHandler::HandleError( *new StringErrorInfo( - ERR_AUTOPATH_ERROR, lcl_makePath(m_aInvalidPaths), - DialogMask::ButtonsOk | DialogMask::MessageError ) ); m_bError = true; } else @@ -412,9 +442,38 @@ void SwGlossaries::UpdateGlosPath(bool bFull) void SwGlossaries::ShowError() { - ErrCode nPathError = *new StringErrorInfo(ERR_AUTOPATH_ERROR, - lcl_makePath(m_aInvalidPaths), DialogMask::ButtonsOk ); - ErrorHandler::HandleError( nPathError ); + std::vector<OUString> netaccess; + std::vector<OUString> others; + for (auto const& it : m_aInvalidPaths) + { + OUString path; +#if _WIN32 + 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<weld::MessageDialog> const xDialog{ + Application::CreateMessageDialog(nullptr, + VclMessageType::Error, VclButtonsType::Close, + SwResId(STR_ERR_GLOS_NET_PATH_ACCESS) + u" " + lcl_makePath(netaccess))}; + xDialog->run(); + } + if (!others.empty()) + { + ErrorHandler::HandleError( *new StringErrorInfo( + ERR_AUTOPATH_ERROR, lcl_makePath(others), + DialogMask::ButtonsOk | DialogMask::MessageError) ); + } } OUString SwGlossaries::GetExtension()
