external/libcmis/UnpackedTarball_libcmis.mk |    1 
 external/libcmis/exceptions.patch.1         |  171 ++++++++++++++++++++++++++++
 ucb/source/ucp/cmis/cmis_content.cxx        |   35 +++++
 ucb/source/ucp/cmis/cmis_repo_content.cxx   |   35 +++++
 4 files changed, 240 insertions(+), 2 deletions(-)

New commits:
commit 16c0dfed795e2c6cfb88488f776f1ef496079c99
Author:     Michael Stahl <[email protected]>
AuthorDate: Fri Jun 21 15:48:05 2024 +0200
Commit:     Michael Stahl <[email protected]>
CommitDate: Fri Jun 21 19:17:27 2024 +0200

    libcmis,ucb: get more informative error messages for CMIS UCP
    
    Currently it reports pretty much everything as
    "The specified device is invalid."
    but clearly we can do better.
    
    Try not to change the public API of libcmis too much; it has 2 string
    members in libcmis::Exception, add a bunch more type values such as
    "dnsFailed", "connectFailed", "connectTimeout", "transferFailed".
    
    Also there were 2 HttpSession functions that convert libcmis::Exception
    to CurlException - very odd, was apparently done to appease Coverity,
    but the exception specifications that caused Coverity to complain were
    removed from libcmis anyway; let's remove that, every caller of these
    functions i looked at would immediately convert it back to
    libcmis::Exception anyway.
    
    Change-Id: Iee853af8bb541e6b071b75d593b6c031f67a886d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169335
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <[email protected]>
    (cherry picked from commit f91effb36b2be1ff8937d684191fb2f19d6ac97d)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169303

diff --git a/external/libcmis/UnpackedTarball_libcmis.mk 
b/external/libcmis/UnpackedTarball_libcmis.mk
index ede32bc8fad3..af5feed5e96a 100644
--- a/external/libcmis/UnpackedTarball_libcmis.mk
+++ b/external/libcmis/UnpackedTarball_libcmis.mk
@@ -21,6 +21,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,libcmis,\
        external/libcmis/http-session-cleanup.patch.1 \
        external/libcmis/factory-no-retry-ssl.patch.1 \
        external/libcmis/sharepoint-auth.patch.1 \
+       external/libcmis/exceptions.patch.1 \
 ))
 
 # vim: set noet sw=4 ts=4:
diff --git a/external/libcmis/exceptions.patch.1 
b/external/libcmis/exceptions.patch.1
new file mode 100644
index 000000000000..29a66f229c4c
--- /dev/null
+++ b/external/libcmis/exceptions.patch.1
@@ -0,0 +1,171 @@
+--- libcmis/src/libcmis/http-session.cxx.orig  2024-06-21 12:22:36.083125022 
+0200
++++ libcmis/src/libcmis/http-session.cxx       2024-06-21 13:08:37.403016695 
+0200
+@@ -653,7 +653,8 @@
+         m_authProvided = authProvider->authenticationQuery( m_username, 
m_password );
+         if ( !m_authProvided )
+         {
+-            throw CurlException( "User cancelled authentication request" );
++            // report this as 401 so it becomes permissionDenied
++            throw CurlException("User cancelled authentication request", 
CURLE_OK, "", 401);
+         }
+     }
+ }
+@@ -762,6 +762,7 @@
+         if ( CURLE_SSL_CACERT == errCode )
+         {
+             vector< string > certificates;
++            string err(errBuff);
+ 
+             // We somehow need to rerun the request to get the certificate
+             curl_easy_setopt(m_curlHandle, CURLOPT_SSL_VERIFYHOST, 0);
+@@ -814,7 +815,7 @@
+                 }
+                 else
+                 {
+-                    throw CurlException( "Invalid SSL certificate" );
++                    throw CurlException(err, CURLE_SSL_CACERT);
+                 }
+             }
+         }
+@@ -827,7 +828,6 @@
+ 
+ 
+ void HttpSession::checkOAuth2( string url )
+-try
+ {
+     if ( m_oauth2Handler )
+     {
+@@ -836,10 +836,6 @@
+             oauth2Authenticate( );
+     }
+ }
+-catch ( const libcmis::Exception& e )
+-{
+-    throw CurlException( e.what( ) );
+-}
+ 
+ long HttpSession::getHttpStatus( )
+ {
+@@ -906,15 +902,10 @@
+ }
+ 
+ void HttpSession::oauth2Refresh( )
+-try
+ {
+     const ScopeGuard<bool> inOauth2Guard(m_inOAuth2Authentication, true);
+     m_oauth2Handler->refresh( );
+ }
+-catch ( const libcmis::Exception& e )
+-{
+-    throw CurlException( e.what() );
+-}
+ 
+ void HttpSession::initProtocols( )
+ {
+@@ -981,11 +972,43 @@
+             break;
+         default:
+             msg = what();
+-            if ( !isCancelled( ) )
+-                msg += ": " + m_url;
+-            else
+-                type = "permissionDenied";
+-            break;
++            switch (m_code)
++            {
++                case CURLE_COULDNT_RESOLVE_PROXY:
++                case CURLE_COULDNT_RESOLVE_HOST:
++                    type = "dnsFailed";
++                    break;
++                case CURLE_COULDNT_CONNECT:
++                case CURLE_SSL_CONNECT_ERROR:
++                case CURLE_SSL_CERTPROBLEM:
++                case CURLE_SSL_CIPHER:
++                case CURLE_PEER_FAILED_VERIFICATION:
++#if CURL_AT_LEAST_VERSION(7, 19, 0)
++                case CURLE_SSL_ISSUER_ERROR:
++#endif
++                case CURLE_SSL_PINNEDPUBKEYNOTMATCH:
++                case CURLE_SSL_INVALIDCERTSTATUS:
++                case CURLE_FAILED_INIT:
++#if CURL_AT_LEAST_VERSION(7, 69, 0)
++                case CURLE_QUIC_CONNECT_ERROR:
++#endif
++                    type = "connectFailed";
++                    break;
++                case CURLE_OPERATION_TIMEDOUT:
++                    type = "connectTimeout";
++                    break;
++                case CURLE_WRITE_ERROR:
++                case CURLE_READ_ERROR: // error returned from our callbacks
++                case CURLE_ABORTED_BY_CALLBACK:
++                case CURLE_SEND_ERROR:
++                case CURLE_RECV_ERROR:
++                    type = "transferFailed";
++                    break;
++                default:
++                    if ( !isCancelled( ) )
++                        msg += ": " + m_url;
++                    break;
++            }
+     }
+ 
+     return libcmis::Exception( msg, type );
+--- libcmis/src/libcmis/http-session.hxx.orig  2024-06-21 12:36:22.785868998 
+0200
++++ libcmis/src/libcmis/http-session.hxx       2024-06-21 12:36:44.272966309 
+0200
+@@ -71,10 +71,10 @@
+         {
+         }
+ 
+-        CurlException( std::string message ) :
++        CurlException(std::string message, CURLcode const code) :
+             exception( ),
+             m_message( message ),
+-            m_code( CURLE_OK ),
++            m_code(code),
+             m_url( ),
+             m_httpStatus( 0 ),
+             m_cancelled( true ),
+--- libcmis/src/libcmis/sharepoint-session.cxx.orig    2024-06-21 
12:23:07.164265783 +0200
++++ libcmis/src/libcmis/sharepoint-session.cxx 2024-06-21 12:37:45.528243723 
+0200
+@@ -289,6 +291,7 @@
+         if ( CURLE_SSL_CACERT == errCode )
+         {
+             vector< string > certificates;
++            string err(errBuff);
+ 
+             // We somehow need to rerun the request to get the certificate
+             curl_easy_setopt(m_curlHandle, CURLOPT_SSL_VERIFYHOST, 0);
+@@ -344,7 +344,7 @@
+                 }
+                 else
+                 {
+-                    throw CurlException( "Invalid SSL certificate" );
++                    throw CurlException(err, CURLE_SSL_CACERT);
+                 }
+             }
+         }
+--- libcmis/src/libcmis/session-factory.cxx.orig       2024-06-21 
15:37:55.132824666 +0200
++++ libcmis/src/libcmis/session-factory.cxx    2024-06-21 15:36:17.558408868 
+0200
+@@ -96,7 +96,7 @@
+                 }
+                 catch (const CurlException& e)
+                 {
+-                    if (strcmp(e.what(), "Invalid SSL certificate") == 0)
++                    if (e.getErrorCode() == CURLE_SSL_CACERT)
+                     {
+                         // no point in trying other protocols
+                         throw e.getCmisException();
+--- libcmis/qa/libcmis/test-atom.cxx.orig      2024-06-21 15:39:49.130310447 
+0200
++++ libcmis/qa/libcmis/test-atom.cxx   2024-06-21 15:39:51.541320721 +0200
+@@ -323,8 +323,8 @@
+         }
+         catch ( const libcmis::Exception& e )
+         {
+-            CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong exception message",
+-                    string( "Invalid SSL certificate" ), string( e.what() ) );
++            CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong exception type",
++                    string("connectFailed"), string(e.getType()) );
+         }
+     }
+ }
diff --git a/ucb/source/ucp/cmis/cmis_content.cxx 
b/ucb/source/ucp/cmis/cmis_content.cxx
index e4681e29ab04..851dc790879d 100644
--- a/ucb/source/ucp/cmis/cmis_content.cxx
+++ b/ucb/source/ucp/cmis/cmis_content.cxx
@@ -27,6 +27,9 @@
 #include <com/sun/star/ucb/InsertCommandArgument2.hpp>
 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
 #include <com/sun/star/ucb/OpenMode.hpp>
 #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
@@ -427,7 +430,37 @@ namespace cmis
                     }
                     catch( const libcmis::Exception & e )
                     {
-                        if ( e.getType() != "permissionDenied" )
+                        if (e.getType() == "dnsFailed")
+                        {
+                            uno::Any ex;
+                            ex <<= ucb::InteractiveNetworkResolveNameException(
+                                    OStringToOUString(e.what(), 
RTL_TEXTENCODING_UTF8),
+                                    getXWeak(),
+                                    task::InteractionClassification_ERROR,
+                                    m_aURL.getBindingUrl());
+                            ucbhelper::cancelCommandExecution(ex, xEnv);
+                        }
+                        else if (e.getType() == "connectFailed" || e.getType() 
== "connectTimeout")
+                        {
+                            uno::Any ex;
+                            ex <<= ucb::InteractiveNetworkConnectException(
+                                    OStringToOUString(e.what(), 
RTL_TEXTENCODING_UTF8),
+                                    getXWeak(),
+                                    task::InteractionClassification_ERROR,
+                                    m_aURL.getBindingUrl());
+                            ucbhelper::cancelCommandExecution(ex, xEnv);
+                        }
+                        else if (e.getType() == "transferFailed")
+                        {
+                            uno::Any ex;
+                            ex <<= ucb::InteractiveNetworkReadException(
+                                    OStringToOUString(e.what(), 
RTL_TEXTENCODING_UTF8),
+                                    getXWeak(),
+                                    task::InteractionClassification_ERROR,
+                                    m_aURL.getBindingUrl());
+                            ucbhelper::cancelCommandExecution(ex, xEnv);
+                        }
+                        else if (e.getType() != "permissionDenied")
                         {
                             SAL_INFO("ucb.ucp.cmis", "Unexpected libcmis 
exception: " << e.what());
                             throw;
diff --git a/ucb/source/ucp/cmis/cmis_repo_content.cxx 
b/ucb/source/ucp/cmis/cmis_repo_content.cxx
index d5bd88e75776..af6b487f7a17 100644
--- a/ucb/source/ucp/cmis/cmis_repo_content.cxx
+++ b/ucb/source/ucp/cmis/cmis_repo_content.cxx
@@ -15,6 +15,9 @@
 #include <com/sun/star/beans/PropertyValue.hpp>
 #include <com/sun/star/beans/XPropertySetInfo.hpp>
 #include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
 #include <com/sun/star/ucb/XCommandInfo.hpp>
 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
 #ifndef SYSTEM_CURL
@@ -201,7 +204,37 @@ namespace cmis
                 {
                     SAL_INFO( "ucb.ucp.cmis", "Error getting repositories: " 
<< e.what() );
 
-                    if ( e.getType() != "permissionDenied" )
+                    if (e.getType() == "dnsFailed")
+                    {
+                        uno::Any ex;
+                        ex <<= ucb::InteractiveNetworkResolveNameException(
+                                OStringToOUString(e.what(), 
RTL_TEXTENCODING_UTF8),
+                                getXWeak(),
+                                task::InteractionClassification_ERROR,
+                                m_aURL.getBindingUrl());
+                        ucbhelper::cancelCommandExecution(ex, xEnv);
+                    }
+                    else if (e.getType() == "connectFailed" || e.getType() == 
"connectTimeout")
+                    {
+                        uno::Any ex;
+                        ex <<= ucb::InteractiveNetworkConnectException(
+                                OStringToOUString(e.what(), 
RTL_TEXTENCODING_UTF8),
+                                getXWeak(),
+                                task::InteractionClassification_ERROR,
+                                m_aURL.getBindingUrl());
+                        ucbhelper::cancelCommandExecution(ex, xEnv);
+                    }
+                    else if (e.getType() == "transferFailed")
+                    {
+                        uno::Any ex;
+                        ex <<= ucb::InteractiveNetworkReadException(
+                                OStringToOUString(e.what(), 
RTL_TEXTENCODING_UTF8),
+                                getXWeak(),
+                                task::InteractionClassification_ERROR,
+                                m_aURL.getBindingUrl());
+                        ucbhelper::cancelCommandExecution(ex, xEnv);
+                    }
+                    else if (e.getType() != "permissionDenied")
                     {
                         ucbhelper::cancelCommandExecution(
                                         ucb::IOErrorCode_INVALID_DEVICE,

Reply via email to