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()

Reply via email to