diff options
Diffstat (limited to 'ucb/source/ucp/webdav/NeonSession.cxx')
-rw-r--r-- | ucb/source/ucp/webdav/NeonSession.cxx | 936 |
1 files changed, 607 insertions, 329 deletions
diff --git a/ucb/source/ucp/webdav/NeonSession.cxx b/ucb/source/ucp/webdav/NeonSession.cxx index 25126f619540..78f351f88f77 100644 --- a/ucb/source/ucp/webdav/NeonSession.cxx +++ b/ucb/source/ucp/webdav/NeonSession.cxx @@ -1,5 +1,4 @@ /************************************************************************* - * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2008 by Sun Microsystems, Inc. @@ -34,12 +33,14 @@ #include <hash_map> #include <vector> #include <string.h> +#include "osl/diagnose.h" +#include "osl/time.h" #include <rtl/string.h> #include <ne_socket.h> #include <ne_auth.h> #include <ne_redirect.h> -#include <ne_locks.h> #include <ne_ssl.h> +#include <ne_compress.h> #include "libxml/parser.h" #include "rtl/ustrbuf.hxx" #include "comphelper/sequence.hxx" @@ -62,6 +63,7 @@ #include <com/sun/star/security/CertificateContainer.hpp> #include <com/sun/star/security/XCertificateContainer.hpp> #include <com/sun/star/task/XMasterPasswordHandling.hpp> +#include <com/sun/star/ucb/Lock.hpp> #include <com/sun/star/xml/crypto/XSEInitializer.hpp> using namespace com::sun::star; @@ -119,10 +121,6 @@ typedef std::hash_map RequestDataMap; // ------------------------------------------------------------------- -// static members! -bool NeonSession::m_bGlobalsInited = false; -osl::Mutex NeonSession::m_aGlobalMutex; -// ------------------------------------------------------------------- // Helper fuction // ------------------------------------------------------------------- static sal_uInt16 makeStatusCode( const rtl::OUString & rStatusText ) @@ -197,14 +195,14 @@ extern "C" void NeonSession_ResponseBlockReader(void * inUserData, const char * inBuf, size_t inLen ) { - // neon calls this function with (inLen == 0)... + // neon sometimes calls this function with (inLen == 0)... if ( inLen > 0 ) { NeonRequestContext * pCtx = static_cast< NeonRequestContext * >( inUserData ); rtl::Reference< NeonInputStream > xInputStream( - pCtx->xInputStream); + pCtx->xInputStream ); if ( xInputStream.is() ) xInputStream->AddToStream( inBuf, inLen ); @@ -327,10 +325,11 @@ extern "C" int NeonSession_NeonAuth( void * inUserData, bool bCanUseSystemCreds = false; #ifdef NE_FEATURE_SSPI - bCanUseSystemCreds = (attempt == 0) && // avoid endless loops - ne_has_support( NE_FEATURE_SSPI ) && // Windows-only feature. - ( ( ne_strcasecmp( inAuthProtocol, "NTLM" ) == 0 ) || - ( ne_strcasecmp( inAuthProtocol, "Negotiate" ) == 0 ) ); + bCanUseSystemCreds + = (attempt == 0) && // avoid endless loops + ne_has_support( NE_FEATURE_SSPI ) && // Windows-only feature. + ( ( ne_strcasecmp( inAuthProtocol, "NTLM" ) == 0 ) || + ( ne_strcasecmp( inAuthProtocol, "Negotiate" ) == 0 ) ); #endif // #i97003# (tkr): Ask XMasterPasswordHandling if we should store the @@ -342,7 +341,7 @@ extern "C" int NeonSession_NeonAuth( void * inUserData, uno::Reference< task::XMasterPasswordHandling >( theSession->getMSF()->createInstance( rtl::OUString::createFromAscii( - "com.sun.star.task.PasswordContainer" )), + "com.sun.star.task.PasswordContainer" ) ), uno::UNO_QUERY ); } catch ( uno::Exception const & ) @@ -406,7 +405,7 @@ namespace { } return sPart; } -} +} // namespace // ------------------------------------------------------------------- extern "C" int NeonSession_CertificationNotify( void *userdata, @@ -445,7 +444,7 @@ extern "C" int NeonSession_CertificationNotify( void *userdata, pSession->getHostName(), cert_subject ) ); if ( certificateContainer != security::CertificateContainerStatus_NOCERT ) - return + return certificateContainer == security::CertificateContainerStatus_TRUSTED ? 0 : 1; @@ -476,7 +475,7 @@ extern "C" int NeonSession_CertificationNotify( void *userdata, rtl::OString sEECertB64( eeCertB64 ); - uno::Reference< com::sun::star::security::XCertificate > xEECert( + uno::Reference< security::XCertificate > xEECert( xSecurityEnv->createCertificateFromAscii( rtl::OStringToOUString( sEECertB64, RTL_TEXTENCODING_ASCII_US ) ) ); @@ -617,36 +616,41 @@ extern "C" void NeonSession_PreSendRequest( ne_request * req, } } - const DAVRequestHeaders & rHeaders - = pSession->getRequestEnvironment().m_aRequestHeaders; + const DAVRequestHeaders & rHeaders + = pSession->getRequestEnvironment().m_aRequestHeaders; - DAVRequestHeaders::const_iterator it1( rHeaders.begin() ); - const DAVRequestHeaders::const_iterator end1( rHeaders.end() ); + DAVRequestHeaders::const_iterator it1( rHeaders.begin() ); + const DAVRequestHeaders::const_iterator end1( rHeaders.end() ); - while ( it1 != end1 ) - { - rtl::OString aHeader - = rtl::OUStringToOString( (*it1).first, - RTL_TEXTENCODING_UTF8 ); - rtl::OString aValue - = rtl::OUStringToOString( (*it1).second, - RTL_TEXTENCODING_UTF8 ); - ne_buffer_concat( headers, aHeader.getStr(), ": ", - aValue.getStr(), EOL, NULL ); - - ++it1; + while ( it1 != end1 ) + { + rtl::OString aHeader + = rtl::OUStringToOString( (*it1).first, + RTL_TEXTENCODING_UTF8 ); + rtl::OString aValue + = rtl::OUStringToOString( (*it1).second, + RTL_TEXTENCODING_UTF8 ); + ne_buffer_concat( headers, aHeader.getStr(), ": ", + aValue.getStr(), EOL, NULL ); + + ++it1; + } } } -} // namespace +// ------------------------------------------------------------------- +// static members! +bool NeonSession::m_bGlobalsInited = false; +osl::Mutex NeonSession::m_aGlobalMutex; +NeonLockStore NeonSession::m_aNeonLockStore; // ------------------------------------------------------------------- // Constructor // ------------------------------------------------------------------- NeonSession::NeonSession( - const rtl::Reference< DAVSessionFactory > & rSessionFactory, - const rtl::OUString& inUri, - const ucbhelper::InternetProxyDecider & rProxyDecider ) + const rtl::Reference< DAVSessionFactory > & rSessionFactory, + const rtl::OUString& inUri, + const ucbhelper::InternetProxyDecider & rProxyDecider ) throw ( DAVException ) : DAVSession( rSessionFactory ), m_pHttpSession( 0 ), @@ -657,8 +661,6 @@ NeonSession::NeonSession( m_aScheme = theUri.GetScheme(); m_aHostName = theUri.GetHost(); m_nPort = theUri.GetPort(); - -// Init(); } // ------------------------------------------------------------------- @@ -670,17 +672,17 @@ NeonSession::~NeonSession( ) { ne_session_destroy( m_pHttpSession ); m_pHttpSession = 0; - // Note: Uncomment the following if locking support is required - /* - if ( mNeonLockSession != NULL ) - { - ne_lock_unregister( mNeonLockSession ); - mNeonLockSession = NULL; - } - */ } + delete static_cast< RequestDataMap * >( m_pRequestData ); +} - delete static_cast<RequestDataMap*>(m_pRequestData); +// ------------------------------------------------------------------- +void NeonSession::Init( const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + m_aEnv = rEnv; + Init(); } // ------------------------------------------------------------------- @@ -693,7 +695,7 @@ void NeonSession::Init() if ( m_pHttpSession == 0 ) { - // Ensure that Neon sockets are initialize + // Ensure that Neon sockets are initialized // --> tkr #151111# crashed if copy and pasted pictures from the internet // ne_sock_init() was executed by two threads at the same time. @@ -705,9 +707,23 @@ void NeonSession::Init() throw DAVException( DAVException::DAV_SESSION_CREATE, NeonUri::makeConnectionEndPointString( m_aHostName, m_nPort ) ); + // #122205# - libxml2 needs to be initialized once if used by // multithreaded programs like OOo. xmlInitParser(); +#if 0 + // for more debug flags see ne_utils.h; NE_DEBUGGING must be defined + // while compiling neon in order to actually activate neon debug + // output. + ne_debug_init( stderr, NE_DBG_FLUSH + | NE_DBG_HTTP + // | NE_DBG_HTTPBODY + // | NE_DBG_HTTPAUTH + // | NE_DBG_XML + // | NE_DBG_XMLPARSE + // | NE_DBG_LOCKS + ); +#endif m_bGlobalsInited = true; } @@ -747,30 +763,29 @@ void NeonSession::Init() // to the session m_pHttpSession = ne_session_create( - rtl::OUStringToOString( m_aScheme, - RTL_TEXTENCODING_UTF8 ).getStr(), - /* theUri.GetUserInfo(), - @@@ for FTP via HTTP proxy, but not supported by Neon */ - rtl::OUStringToOString( m_aHostName, - RTL_TEXTENCODING_UTF8 ).getStr(), - m_nPort ); + rtl::OUStringToOString( m_aScheme, + RTL_TEXTENCODING_UTF8 ).getStr(), + /* theUri.GetUserInfo(), + @@@ for FTP via HTTP proxy, but not supported by Neon */ + rtl::OUStringToOString( m_aHostName, + RTL_TEXTENCODING_UTF8 ).getStr(), + m_nPort ); if ( m_pHttpSession == 0 ) throw DAVException( DAVException::DAV_SESSION_CREATE, NeonUri::makeConnectionEndPointString( m_aHostName, m_nPort ) ); - if (m_aScheme.equalsIgnoreAsciiCase( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "https" ) ) ) ) - { - - // Get all trusted certificates from key store - - + // Register the session with the lock store + m_aNeonLockStore.registerSession( m_pHttpSession ); + if ( m_aScheme.equalsIgnoreAsciiCase( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "https" ) ) ) ) + { // Set a failure callback for certificate check - ne_ssl_set_verify( m_pHttpSession, NeonSession_CertificationNotify, this); - } + ne_ssl_set_verify( + m_pHttpSession, NeonSession_CertificationNotify, this); + } // Add hooks (i.e. for adding additional headers to the request) @@ -815,27 +830,20 @@ void NeonSession::Init() if ( m_aProxyName.getLength() ) { ne_session_proxy( m_pHttpSession, - rtl::OUStringToOString( m_aProxyName, - RTL_TEXTENCODING_UTF8 ) - .getStr(), + rtl::OUStringToOString( + m_aProxyName, + RTL_TEXTENCODING_UTF8 ).getStr(), m_nProxyPort ); } - // Note: Uncomment the following if locking support is required - /* - mNeonLockSession = ne_lock_register( m_pHttpSession ); - - if ( mNeonLockSession == NULL ) - throw DAVException( DAVException::DAV_SESSION_CREATE, - theUri::makeConnectionEndPointString() ); - */ - // Register for redirects. ne_redirect_register( m_pHttpSession ); // authentication callbacks. - ne_add_server_auth( m_pHttpSession, NE_AUTH_ALL, NeonSession_NeonAuth, this ); - ne_add_proxy_auth ( m_pHttpSession, NE_AUTH_ALL, NeonSession_NeonAuth, this ); + ne_add_server_auth( + m_pHttpSession, NE_AUTH_ALL, NeonSession_NeonAuth, this ); + ne_add_proxy_auth( + m_pHttpSession, NE_AUTH_ALL, NeonSession_NeonAuth, this ); } } @@ -870,15 +878,13 @@ sal_Bool NeonSession::UsesProxy() // OPTIONS // ------------------------------------------------------------------- void NeonSession::OPTIONS( const rtl::OUString & inPath, - DAVCapabilities & outCapabilities, + DAVCapabilities & outCapabilities, const DAVRequestEnvironment & rEnv ) throw( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); HttpServerCapabilities servercaps; memset( &servercaps, 0, sizeof( servercaps ) ); @@ -887,7 +893,8 @@ void NeonSession::OPTIONS( const rtl::OUString & inPath, rtl::OUStringToOString( inPath, RTL_TEXTENCODING_UTF8 ), &servercaps ); - HandleError( theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); outCapabilities.class1 = !!servercaps.dav_class1; outCapabilities.class2 = !!servercaps.dav_class2; @@ -897,60 +904,58 @@ void NeonSession::OPTIONS( const rtl::OUString & inPath, // ------------------------------------------------------------------- // PROPFIND - allprop & named // ------------------------------------------------------------------- -void NeonSession::PROPFIND( const rtl::OUString & inPath, - const Depth inDepth, +void NeonSession::PROPFIND( const rtl::OUString & inPath, + const Depth inDepth, const std::vector< rtl::OUString > & inPropNames, - std::vector< DAVResource > & ioResources, + std::vector< DAVResource > & ioResources, const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); int theRetVal = NE_OK; NeonPropFindRequest theRequest( m_pHttpSession, rtl::OUStringToOString( inPath, RTL_TEXTENCODING_UTF8 ), - inDepth, - inPropNames, - ioResources, - theRetVal ); - HandleError( theRetVal ); + inDepth, + inPropNames, + ioResources, + theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- // PROPFIND - propnames // ------------------------------------------------------------------- -void NeonSession::PROPFIND( const rtl::OUString & inPath, - const Depth inDepth, - std::vector< DAVResourceInfo >& ioResInfo, +void NeonSession::PROPFIND( const rtl::OUString & inPath, + const Depth inDepth, + std::vector< DAVResourceInfo > & ioResInfo, const DAVRequestEnvironment & rEnv ) throw( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); int theRetVal = NE_OK; NeonPropFindRequest theRequest( m_pHttpSession, rtl::OUStringToOString( inPath, RTL_TEXTENCODING_UTF8 ), - inDepth, - ioResInfo, - theRetVal ); - HandleError( theRetVal ); + inDepth, + ioResInfo, + theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- // PROPPATCH // ------------------------------------------------------------------- -void NeonSession::PROPPATCH( const rtl::OUString & inPath, - const std::vector< ProppatchValue > & inValues, +void NeonSession::PROPPATCH( const rtl::OUString & inPath, + const std::vector< ProppatchValue > & inValues, const DAVRequestEnvironment & rEnv ) throw( DAVException ) { @@ -974,9 +979,10 @@ void NeonSession::PROPPATCH( const rtl::OUString & inPath, executable w ( #ifndef WIN32 ) All dead properties are of course writable. - */ + */ int theRetVal = NE_OK; + int n; // for the "for" loop // Generate the list of properties we want to set. @@ -1000,8 +1006,8 @@ void NeonSession::PROPPATCH( const rtl::OUString & inPath, if ( DAVProperties::isUCBDeadProperty( *pName ) ) { // DAV dead property added by WebDAV UCP? - if ( !UCBDeadPropertyValue::toXML( - rValue.value, aStringValue ) ) + if ( !UCBDeadPropertyValue::toXML( rValue.value, + aStringValue ) ) { // Error! pItems[ n ].value = 0; @@ -1015,7 +1021,7 @@ void NeonSession::PROPPATCH( const rtl::OUString & inPath, // complex properties... if ( rValue.name == DAVProperties::SOURCE ) { - uno::Sequence< ::com::sun::star::ucb::Link > aLinks; + uno::Sequence< ucb::Link > aLinks; if ( rValue.value >>= aLinks ) { LinkSequence::toXML( aLinks, aStringValue ); @@ -1055,9 +1061,7 @@ void NeonSession::PROPPATCH( const rtl::OUString & inPath, { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); pItems[ n ].name = 0; @@ -1076,7 +1080,7 @@ void NeonSession::PROPPATCH( const rtl::OUString & inPath, delete [] pItems; - HandleError( theRetVal ); + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- @@ -1090,9 +1094,7 @@ void NeonSession::HEAD( const ::rtl::OUString & inPath, { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); int theRetVal = NE_OK; NeonHeadRequest theRequest( m_pHttpSession, @@ -1100,7 +1102,8 @@ void NeonSession::HEAD( const ::rtl::OUString & inPath, inHeaderNames, ioResource, theRetVal ); - HandleError( theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- @@ -1108,14 +1111,12 @@ void NeonSession::HEAD( const ::rtl::OUString & inPath, // ------------------------------------------------------------------- uno::Reference< io::XInputStream > NeonSession::GET( const rtl::OUString & inPath, - const DAVRequestEnvironment & rEnv ) + const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); rtl::Reference< NeonInputStream > xInputStream( new NeonInputStream ); NeonRequestContext aCtx( xInputStream ); @@ -1125,23 +1126,23 @@ NeonSession::GET( const rtl::OUString & inPath, NeonSession_ResponseBlockReader, false, &aCtx ); - HandleError( theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); + return uno::Reference< io::XInputStream >( xInputStream.get() ); } // ------------------------------------------------------------------- // GET // ------------------------------------------------------------------- -void NeonSession::GET( const rtl::OUString & inPath, +void NeonSession::GET( const rtl::OUString & inPath, uno::Reference< io::XOutputStream > & ioOutputStream, const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); NeonRequestContext aCtx( ioOutputStream ); int theRetVal = GET( m_pHttpSession, @@ -1150,7 +1151,8 @@ void NeonSession::GET( const rtl::OUString & inPath, NeonSession_ResponseBlockWriter, false, &aCtx ); - HandleError( theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- @@ -1158,16 +1160,14 @@ void NeonSession::GET( const rtl::OUString & inPath, // ------------------------------------------------------------------- uno::Reference< io::XInputStream > NeonSession::GET( const rtl::OUString & inPath, - const std::vector< ::rtl::OUString > & inHeaderNames, - DAVResource & ioResource, - const DAVRequestEnvironment & rEnv ) + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); ioResource.uri = inPath; ioResource.properties.clear(); @@ -1180,7 +1180,9 @@ NeonSession::GET( const rtl::OUString & inPath, NeonSession_ResponseBlockReader, true, &aCtx ); - HandleError( theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); + return uno::Reference< io::XInputStream >( xInputStream.get() ); } @@ -1188,17 +1190,15 @@ NeonSession::GET( const rtl::OUString & inPath, // GET // ------------------------------------------------------------------- void NeonSession::GET( const rtl::OUString & inPath, - uno::Reference< io::XOutputStream > & ioOutputStream, - const std::vector< ::rtl::OUString > & inHeaderNames, - DAVResource & ioResource, - const DAVRequestEnvironment & rEnv ) + uno::Reference< io::XOutputStream > & ioOutputStream, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); ioResource.uri = inPath; ioResource.properties.clear(); @@ -1210,27 +1210,26 @@ void NeonSession::GET( const rtl::OUString & inPath, NeonSession_ResponseBlockWriter, true, &aCtx ); - HandleError( theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- // PUT // ------------------------------------------------------------------- -void NeonSession::PUT( const rtl::OUString & inPath, +void NeonSession::PUT( const rtl::OUString & inPath, const uno::Reference< io::XInputStream > & inInputStream, const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; - uno::Sequence< sal_Int8 > aDataToSend; if ( !getDataFromInputStream( inInputStream, aDataToSend, false ) ) throw DAVException( DAVException::DAV_INVALID_ARG ); + Init( rEnv ); + int theRetVal = PUT( m_pHttpSession, rtl::OUStringToOString( inPath, RTL_TEXTENCODING_UTF8 ), @@ -1238,7 +1237,7 @@ void NeonSession::PUT( const rtl::OUString & inPath, aDataToSend.getConstArray() ), aDataToSend.getLength() ); - HandleError( theRetVal ); + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- @@ -1246,10 +1245,10 @@ void NeonSession::PUT( const rtl::OUString & inPath, // ------------------------------------------------------------------- uno::Reference< io::XInputStream > NeonSession::POST( const rtl::OUString & inPath, - const rtl::OUString & rContentType, - const rtl::OUString & rReferer, - const uno::Reference< io::XInputStream > & inInputStream, - const DAVRequestEnvironment & rEnv ) + const rtl::OUString & rContentType, + const rtl::OUString & rReferer, + const uno::Reference< io::XInputStream > & inInputStream, + const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); @@ -1258,15 +1257,13 @@ NeonSession::POST( const rtl::OUString & inPath, if ( !getDataFromInputStream( inInputStream, aDataToSend, true ) ) throw DAVException( DAVException::DAV_INVALID_ARG ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); rtl::Reference< NeonInputStream > xInputStream( new NeonInputStream ); NeonRequestContext aCtx( xInputStream ); int theRetVal = POST( m_pHttpSession, rtl::OUStringToOString( - inPath, RTL_TEXTENCODING_UTF8 ), + inPath, RTL_TEXTENCODING_UTF8 ), reinterpret_cast< const char * >( aDataToSend.getConstArray() ), NeonSession_ResponseBlockReader, @@ -1274,7 +1271,8 @@ NeonSession::POST( const rtl::OUString & inPath, rContentType, rReferer ); - HandleError( theRetVal ); + HandleError( theRetVal, inPath, rEnv ); + return uno::Reference< io::XInputStream >( xInputStream.get() ); } @@ -1295,9 +1293,7 @@ void NeonSession::POST( const rtl::OUString & inPath, if ( !getDataFromInputStream( inInputStream, aDataToSend, true ) ) throw DAVException( DAVException::DAV_INVALID_ARG ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); NeonRequestContext aCtx( oOutputStream ); int theRetVal = POST( m_pHttpSession, @@ -1310,20 +1306,7 @@ void NeonSession::POST( const rtl::OUString & inPath, rContentType, rReferer ); - HandleError( theRetVal ); -} - -// ------------------------------------------------------------------- -// ABORT -// ------------------------------------------------------------------- -void NeonSession::ABORT() - throw ( DAVException ) -{ - // 11.11.09 (tkr): The following code lines causing crashes if closing a ongoing connection. It turned out that this existing solution doesn't work in multi-threading environments. - // So I disabled them in 3.2. . Issue #73893# should fix it in OOo 3.3. - - //if (NULL !=m_pHttpSession) - // ne_close_connection(m_pHttpSession); + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- @@ -1335,30 +1318,27 @@ void NeonSession::MKCOL( const rtl::OUString & inPath, { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); int theRetVal = ne_mkcol( m_pHttpSession, rtl::OUStringToOString( - inPath, RTL_TEXTENCODING_UTF8 ) ); - HandleError( theRetVal ); + inPath, RTL_TEXTENCODING_UTF8 ) ); + + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- // COPY // ------------------------------------------------------------------- -void NeonSession::COPY( const rtl::OUString & inSourceURL, - const rtl::OUString & inDestinationURL, +void NeonSession::COPY( const rtl::OUString & inSourceURL, + const rtl::OUString & inDestinationURL, const DAVRequestEnvironment & rEnv, - sal_Bool inOverWrite ) + sal_Bool inOverWrite ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); NeonUri theSourceUri( inSourceURL ); NeonUri theDestinationUri( inDestinationURL ); @@ -1367,12 +1347,13 @@ void NeonSession::COPY( const rtl::OUString & inSourceURL, inOverWrite ? 1 : 0, NE_DEPTH_INFINITE, rtl::OUStringToOString( - theSourceUri.GetPath(), - RTL_TEXTENCODING_UTF8 ), + theSourceUri.GetPath(), + RTL_TEXTENCODING_UTF8 ), rtl::OUStringToOString( - theDestinationUri.GetPath(), - RTL_TEXTENCODING_UTF8 ) ); - HandleError( theRetVal ); + theDestinationUri.GetPath(), + RTL_TEXTENCODING_UTF8 ) ); + + HandleError( theRetVal, inSourceURL, rEnv ); } // ------------------------------------------------------------------- @@ -1386,21 +1367,20 @@ void NeonSession::MOVE( const rtl::OUString & inSourceURL, { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); NeonUri theSourceUri( inSourceURL ); NeonUri theDestinationUri( inDestinationURL ); int theRetVal = ne_move( m_pHttpSession, inOverWrite ? 1 : 0, rtl::OUStringToOString( - theSourceUri.GetPath(), - RTL_TEXTENCODING_UTF8 ), + theSourceUri.GetPath(), + RTL_TEXTENCODING_UTF8 ), rtl::OUStringToOString( - theDestinationUri.GetPath(), - RTL_TEXTENCODING_UTF8 ) ); - HandleError( theRetVal ); + theDestinationUri.GetPath(), + RTL_TEXTENCODING_UTF8 ) ); + + HandleError( theRetVal, inSourceURL, rEnv ); } // ------------------------------------------------------------------- @@ -1412,53 +1392,282 @@ void NeonSession::DESTROY( const rtl::OUString & inPath, { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); int theRetVal = ne_delete( m_pHttpSession, rtl::OUStringToOString( - inPath, RTL_TEXTENCODING_UTF8 ) ); - HandleError( theRetVal ); + inPath, RTL_TEXTENCODING_UTF8 ) ); + + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- -// LOCK +namespace +{ + sal_Int32 lastChanceToSendRefreshRequest( TimeValue const & rStart, + int timeout ) + { + TimeValue aEnd; + osl_getSystemTime( &aEnd ); + + // Try to estimate a safe absolute time for sending the + // lock refresh request. + sal_Int32 lastChanceToSendRefreshRequest = -1; + if ( timeout != NE_TIMEOUT_INFINITE ) + { + sal_Int32 calltime = aEnd.Seconds - rStart.Seconds; + if ( calltime <= timeout ) + { + lastChanceToSendRefreshRequest + = aEnd.Seconds + timeout - calltime; + } + else + { + OSL_TRACE( "No chance to refresh lock before timeout!" ); + } + } + return lastChanceToSendRefreshRequest; + } + +} // namespace + +// ------------------------------------------------------------------- +// LOCK (set new lock) // ------------------------------------------------------------------- -// Note: Uncomment the following if locking support is required -/* -void NeonSession::LOCK( const Lock & inLock, +void NeonSession::LOCK( const ::rtl::OUString & inPath, + ucb::Lock & rLock, const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); + Init( rEnv ); - m_aEnv = rEnv; + /* Create a depth zero, exclusive write lock, with default timeout + * (allowing a server to pick a default). token, owner and uri are + * unset. */ + NeonLock * theLock = ne_lock_create(); + + // Set the lock uri + ne_uri aUri; + ne_uri_parse( rtl::OUStringToOString( makeAbsoluteURL( inPath ), + RTL_TEXTENCODING_UTF8 ).getStr(), + &aUri ); + theLock->uri = aUri; + + // Set the lock depth + switch( rLock.Depth ) + { + case ucb::LockDepth_ZERO: + theLock->depth = NE_DEPTH_ZERO; + break; + case ucb::LockDepth_ONE: + theLock->depth = NE_DEPTH_ONE; + break; + case ucb::LockDepth_INFINITY: + theLock->depth = NE_DEPTH_INFINITE; + break; + default: + throw DAVException( DAVException::DAV_INVALID_ARG ); + } + + // Set the lock scope + switch ( rLock.Scope ) + { + case ucb::LockScope_EXCLUSIVE: + theLock->scope = ne_lockscope_exclusive; + break; + case ucb::LockScope_SHARED: + theLock->scope = ne_lockscope_shared; + break; + default: + throw DAVException( DAVException::DAV_INVALID_ARG ); + } + + // Set the lock timeout + theLock->timeout = (long)rLock.Timeout; + + // Set the lock owner + rtl::OUString aValue; + rLock.Owner >>= aValue; + theLock->owner = + ne_strdup( rtl::OUStringToOString( aValue, + RTL_TEXTENCODING_UTF8 ).getStr() ); + TimeValue startCall; + osl_getSystemTime( &startCall ); + + int theRetVal = ne_lock( m_pHttpSession, theLock ); + + if ( theRetVal == NE_OK ) + { + m_aNeonLockStore.addLock( theLock, + this, + lastChanceToSendRefreshRequest( + startCall, theLock->timeout ) ); + + uno::Sequence< rtl::OUString > aTokens( 1 ); + aTokens[ 0 ] = rtl::OUString::createFromAscii( theLock->token ); + rLock.LockTokens = aTokens; + + OSL_TRACE( "NeonSession::LOCK: created lock for %s. token: %s", + rtl::OUStringToOString( makeAbsoluteURL( inPath ), + RTL_TEXTENCODING_UTF8 ).getStr(), + theLock->token ); + } + else + { + ne_lock_destroy( theLock ); + + OSL_TRACE( "NeonSession::LOCK: obtaining lock for %s failed!", + rtl::OUStringToOString( makeAbsoluteURL( inPath ), + RTL_TEXTENCODING_UTF8 ).getStr() ); + } + + HandleError( theRetVal, inPath, rEnv ); +} + +// ------------------------------------------------------------------- +// LOCK (refresh existing lock) +// ------------------------------------------------------------------- +sal_Int64 NeonSession::LOCK( const ::rtl::OUString & inPath, + sal_Int64 nTimeout, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + // Try to get the neon lock from lock store + NeonLock * theLock + = m_aNeonLockStore.findByUri( makeAbsoluteURL( inPath ) ); + if ( !theLock ) + throw DAVException( DAVException::DAV_NOT_LOCKED ); + + Init( rEnv ); + + // refresh existing lock. + theLock->timeout = static_cast< long >( nTimeout ); - Lockit( inLock, true ); + TimeValue startCall; + osl_getSystemTime( &startCall ); + + int theRetVal = ne_lock_refresh( m_pHttpSession, theLock ); + + if ( theRetVal == NE_OK ) + { + m_aNeonLockStore.updateLock( theLock, + lastChanceToSendRefreshRequest( + startCall, theLock->timeout ) ); + } + + HandleError( theRetVal, inPath, rEnv ); + + return theLock->timeout; +} + +// ------------------------------------------------------------------- +// LOCK (refresh existing lock) +// ------------------------------------------------------------------- +bool NeonSession::LOCK( NeonLock * pLock, + sal_Int32 & rlastChanceToSendRefreshRequest ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + +#if OSL_DEBUG_LEVEL > 0 + char * p = ne_uri_unparse( &(pLock->uri) ); + OSL_TRACE( "NeonSession::LOCK: Refreshing lock for %s.", p ); + ne_free( p ); +#endif + + // refresh existing lock. + + TimeValue startCall; + osl_getSystemTime( &startCall ); + + if ( ne_lock_refresh( m_pHttpSession, pLock ) == NE_OK ) + { + rlastChanceToSendRefreshRequest + = lastChanceToSendRefreshRequest( startCall, pLock->timeout ); + + OSL_TRACE( "Lock successfully refreshed." ); + return true; + } + else + { + OSL_TRACE( "Lock not refreshed!" ); + return false; + } } -*/ // ------------------------------------------------------------------- // UNLOCK // ------------------------------------------------------------------- -// Note: Uncomment the following if locking support is required -/* -void NeonSession::UNLOCK( const Lock & inLock, +void NeonSession::UNLOCK( const ::rtl::OUString & inPath, const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); + // get the neon lock from lock store + NeonLock * theLock + = m_aNeonLockStore.findByUri( makeAbsoluteURL( inPath ) ); + if ( !theLock ) + throw DAVException( DAVException::DAV_NOT_LOCKED ); - m_aEnv = rEnv; + Init( rEnv ); + + int theRetVal = ne_unlock( m_pHttpSession, theLock ); + + if ( theRetVal == NE_OK ) + { + m_aNeonLockStore.removeLock( theLock ); + ne_lock_destroy( theLock ); + } + else + { + OSL_TRACE( "NeonSession::UNLOCK: unlocking of %s failed.", + rtl::OUStringToOString( makeAbsoluteURL( inPath ), + RTL_TEXTENCODING_UTF8 ).getStr() ); + } + + HandleError( theRetVal, inPath, rEnv ); +} + +// ------------------------------------------------------------------- +// UNLOCK +// ------------------------------------------------------------------- +bool NeonSession::UNLOCK( NeonLock * pLock ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Lockit( inLock, false ); +#if OSL_DEBUG_LEVEL > 0 + char * p = ne_uri_unparse( &(pLock->uri) ); + OSL_TRACE( "NeonSession::UNLOCK: Unlocking %s.", p ); + ne_free( p ); +#endif + + if ( ne_unlock( m_pHttpSession, pLock ) == NE_OK ) + { + OSL_TRACE( "UNLOCK succeeded." ); + return true; + } + else + { + OSL_TRACE( "UNLOCK failed!" ); + return false; + } +} + +// ------------------------------------------------------------------- +void NeonSession::abort() + throw ( DAVException ) +{ + // 11.11.09 (tkr): The following code lines causing crashes if + // closing a ongoing connection. It turned out that this existing + // solution doesn't work in multi-threading environments. + // So I disabled them in 3.2. . Issue #73893# should fix it in OOo 3.3. + //if ( m_pHttpSession ) + // ne_close_connection( m_pHttpSession ); } -*/ // ------------------------------------------------------------------- const ucbhelper::InternetProxyServer & NeonSession::getProxySettings() const @@ -1479,10 +1688,98 @@ const ucbhelper::InternetProxyServer & NeonSession::getProxySettings() const } // ------------------------------------------------------------------- +namespace { + +bool containsLocktoken( const uno::Sequence< ucb::Lock > & rLocks, + const char * token ) +{ + for ( sal_Int32 n = 0; n < rLocks.getLength(); ++n ) + { + const uno::Sequence< rtl::OUString > & rTokens + = rLocks[ n ].LockTokens; + for ( sal_Int32 m = 0; m < rTokens.getLength(); ++m ) + { + if ( rTokens[ m ].equalsAscii( token ) ) + return true; + } + } + return false; +} + +} // namespace + +// ------------------------------------------------------------------- +bool NeonSession::removeExpiredLocktoken( const rtl::OUString & inURL, + const DAVRequestEnvironment & rEnv ) +{ + NeonLock * theLock = m_aNeonLockStore.findByUri( inURL ); + if ( !theLock ) + return false; + + // do a lockdiscovery to check whether this lock is still valid. + try + { + // @@@ Alternative: use ne_lock_discover() => less overhead + + std::vector< DAVResource > aResources; + std::vector< rtl::OUString > aPropNames; + aPropNames.push_back( DAVProperties::LOCKDISCOVERY ); + + PROPFIND( rEnv.m_aRequestURI, DAVZERO, aPropNames, aResources, rEnv ); + + if ( aResources.size() == 0 ) + return false; + + std::vector< DAVPropertyValue >::const_iterator it + = aResources[ 0 ].properties.begin(); + std::vector< DAVPropertyValue >::const_iterator end + = aResources[ 0 ].properties.end(); + + while ( it != end ) + { + if ( (*it).Name.equals( DAVProperties::LOCKDISCOVERY ) ) + { + uno::Sequence< ucb::Lock > aLocks; + if ( !( (*it).Value >>= aLocks ) ) + return false; + + if ( !containsLocktoken( aLocks, theLock->token ) ) + { + // expired! + break; + } + + // still valid. + return false; + } + ++it; + } + + // No lockdiscovery prop in propfind result / locktoken not found + // in propfind result -> not locked + OSL_TRACE( "NeonSession::removeExpiredLocktoken: Removing " + " expired lock token for %s. token: %s", + rtl::OUStringToOString( inURL, + RTL_TEXTENCODING_UTF8 ).getStr(), + theLock->token ); + + m_aNeonLockStore.removeLock( theLock ); + ne_lock_destroy( theLock ); + return true; + } + catch ( DAVException const & ) + { + } + return false; +} + +// ------------------------------------------------------------------- // HandleError // Common Error Handler // ------------------------------------------------------------------- -void NeonSession::HandleError( int nError ) +void NeonSession::HandleError( int nError, + const rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { m_aEnv = DAVRequestEnvironment(); @@ -1491,60 +1788,84 @@ void NeonSession::HandleError( int nError ) switch ( nError ) { case NE_OK: - // Cleanup. return; case NE_ERROR: // Generic error { rtl::OUString aText = rtl::OUString::createFromAscii( - ne_get_error( m_pHttpSession ) ); - throw DAVException( DAVException::DAV_HTTP_ERROR, - aText, - makeStatusCode( aText ) ); - } + ne_get_error( m_pHttpSession ) ); + + sal_uInt16 code = makeStatusCode( aText ); + + if ( code == SC_LOCKED ) + { + if ( m_aNeonLockStore.findByUri( + makeAbsoluteURL( inPath ) ) == 0 ) + { + // locked by 3rd party + throw DAVException( DAVException::DAV_LOCKED ); + } + else + { + // locked by ourself + throw DAVException( DAVException::DAV_LOCKED_SELF ); + } + } + + // Special handling for 400 and 412 status codes, which may indicate + // that a lock previously obtained by us has been released meanwhile + // by the server. Unfortunately, RFC is not clear at this point, + // thus server implementations behave different... + else if ( code == SC_BAD_REQUEST || code == SC_PRECONDITION_FAILED ) + { + if ( removeExpiredLocktoken( makeAbsoluteURL( inPath ), rEnv ) ) + throw DAVException( DAVException::DAV_LOCK_EXPIRED ); + } + throw DAVException( DAVException::DAV_HTTP_ERROR, aText, code ); + } case NE_LOOKUP: // Name lookup failed. throw DAVException( DAVException::DAV_HTTP_LOOKUP, NeonUri::makeConnectionEndPointString( - m_aHostName, m_nPort ) ); + m_aHostName, m_nPort ) ); case NE_AUTH: // User authentication failed on server throw DAVException( DAVException::DAV_HTTP_AUTH, NeonUri::makeConnectionEndPointString( - m_aHostName, m_nPort ) ); + m_aHostName, m_nPort ) ); case NE_PROXYAUTH: // User authentication failed on proxy throw DAVException( DAVException::DAV_HTTP_AUTHPROXY, NeonUri::makeConnectionEndPointString( - m_aProxyName, m_nProxyPort ) ); + m_aProxyName, m_nProxyPort ) ); case NE_CONNECT: // Could not connect to server throw DAVException( DAVException::DAV_HTTP_CONNECT, NeonUri::makeConnectionEndPointString( - m_aHostName, m_nPort ) ); + m_aHostName, m_nPort ) ); case NE_TIMEOUT: // Connection timed out throw DAVException( DAVException::DAV_HTTP_TIMEOUT, NeonUri::makeConnectionEndPointString( - m_aHostName, m_nPort ) ); + m_aHostName, m_nPort ) ); case NE_FAILED: // The precondition failed throw DAVException( DAVException::DAV_HTTP_FAILED, NeonUri::makeConnectionEndPointString( - m_aHostName, m_nPort ) ); + m_aHostName, m_nPort ) ); case NE_RETRY: // Retry request (ne_end_request ONLY) throw DAVException( DAVException::DAV_HTTP_RETRY, NeonUri::makeConnectionEndPointString( - m_aHostName, m_nPort ) ); + m_aHostName, m_nPort ) ); case NE_REDIRECT: { NeonUri aUri( ne_redirect_location( m_pHttpSession ) ); throw DAVException( - DAVException::DAV_HTTP_REDIRECT, aUri.GetURI() ); + DAVException::DAV_HTTP_REDIRECT, aUri.GetURI() ); } - default: + default: { OSL_TRACE( "NeonSession::HandleError : Unknown Neon error code!" ); throw DAVException( DAVException::DAV_HTTP_ERROR, @@ -1554,78 +1875,6 @@ void NeonSession::HandleError( int nError ) } } -// Note: Uncomment the following if locking support is required -/* -void NeonSession::Lockit( const Lock & inLock, bool inLockit ) - throw ( DAVException ) -{ - osl::Guard< osl::Mutex > theGuard( m_aMutex ); - - // Create the neon lock - NeonLock * theLock = new NeonLock; - int theRetVal; - - // Set the lock uri - NeonUri theUri( inLock.uri ); - theLock->uri = const_cast< char * > - ( rtl::OUStringToOString( - theUri.GetPath(), RTL_TEXTENCODING_UTF8 ).getStr() ); - - if ( inLockit ) - { - // Set the lock depth - switch( inLock.depth ) - { - case DAVZERO: - case DAVINFINITY: - theLock->depth = int ( inLock.depth ); - break; - default: - throw DAVException( DAVException::DAV_INVALID_ARG ); - break; - } - - // Set the lock scope - switch ( inLock.scope ) - { - case EXCLUSIVE: - theLock->scope = ne_lockscope_exclusive; - break; - case SHARED: - theLock->scope = ne_lockscope_shared; - break; - default: - throw DAVException( DAVException::DAV_INVALID_ARG ); - break; - } - - // Set the lock owner - const char * theOwner = rtl::OUStringToOString( inLock.owner, - RTL_TEXTENCODING_UTF8 ); - theLock->owner = const_cast< char * > ( theOwner ); - - // Set the lock timeout - // Note: Neon ignores the timeout - //theLock->timeout = inLock.timeout; - - theRetVal = ne_lock( m_pHttpSession, theLock ); - } - else - { - - // Set the lock token - rtl::OUString theToken = inLock.locktoken.getConstArray()[ 0 ]; - theLock->token = const_cast< char * > - ( rtl::OUStringToOString( - theToken, RTL_TEXTENCODING_UTF8 ).getStr() ); - - theRetVal = ne_unlock( m_pHttpSession, theLock ); - } - - HandleError( theRetVal ); -} -*/ - // ------------------------------------------------------------------- namespace { @@ -1702,22 +1951,23 @@ int NeonSession::GET( ne_session * sess, #if NEON_VERSION < 0x0250 if ( getheaders ) - ne_add_response_header_catcher( req, runResponseHeaderHandler, userdata ); + ne_add_response_header_catcher( + req, runResponseHeaderHandler, userdata ); #endif - ne_add_response_body_reader( req, ne_accept_2xx, reader, userdata ); + ne_decompress * dc + = ne_decompress_reader( req, ne_accept_2xx, reader, userdata ); ret = ne_request_dispatch( req ); #if NEON_VERSION >= 0x0250 if ( getheaders ) { - while ((cursor = ne_response_header_iterate(req, cursor, &name, &value)) - != NULL) + while ( ( cursor = ne_response_header_iterate( + req, cursor, &name, &value ) ) != NULL ) { char buffer[8192]; ne_snprintf(buffer, sizeof buffer, "%s: %s", name, value); - runResponseHeaderHandler(userdata, buffer); } } @@ -1725,6 +1975,9 @@ int NeonSession::GET( ne_session * sess, if ( ret == NE_OK && ne_get_status( req )->klass != 2 ) ret = NE_ERROR; + if ( dc != 0 ) + ne_decompress_destroy(dc); + ne_request_destroy( req ); return ret; } @@ -1812,10 +2065,11 @@ int NeonSession::POST( ne_session * sess, // ------------------------------------------------------------------- // static -bool NeonSession::getDataFromInputStream( - const uno::Reference< io::XInputStream > & xStream, - uno::Sequence< sal_Int8 > & rData, - bool bAppendTrailingZeroByte ) +bool +NeonSession::getDataFromInputStream( + const uno::Reference< io::XInputStream > & xStream, + uno::Sequence< sal_Int8 > & rData, + bool bAppendTrailingZeroByte ) { if ( xStream.is() ) { @@ -1898,32 +2152,56 @@ bool NeonSession::getDataFromInputStream( } return false; } -// ------------------------------------------------------------------- -//static - -NeonSession::Map NeonSession::certMap; // --------------------------------------------------------------------- sal_Bool -NeonSession::isDomainMatch( rtl::OUString certHostName) +NeonSession::isDomainMatch( rtl::OUString certHostName ) { rtl::OUString hostName = getHostName(); - if (hostName.equalsIgnoreAsciiCase( certHostName )) + if (hostName.equalsIgnoreAsciiCase( certHostName ) ) return sal_True; - - - if ( 0 == certHostName.indexOf( rtl::OUString::createFromAscii( "*" ) ) && hostName.getLength() >= certHostName.getLength() ) + if ( 0 == certHostName.indexOf( rtl::OUString::createFromAscii( "*" ) ) && + hostName.getLength() >= certHostName.getLength() ) { rtl::OUString cmpStr = certHostName.copy( 1 ); - if ( hostName.matchIgnoreAsciiCase( cmpStr, hostName.getLength( ) - cmpStr.getLength()) ) + if ( hostName.matchIgnoreAsciiCase( + cmpStr, hostName.getLength() - cmpStr.getLength() ) ) return sal_True; - } - return sal_False; } - +// --------------------------------------------------------------------- +rtl::OUString NeonSession::makeAbsoluteURL( rtl::OUString const & rURL ) const +{ + try + { + // Is URL relative or already absolute? + if ( rURL[ 0 ] != sal_Unicode( '/' ) ) + { + // absolute. + return rtl::OUString( rURL ); + } + else + { + ne_uri aUri; + memset( &aUri, 0, sizeof( aUri ) ); + + ne_fill_server_uri( m_pHttpSession, &aUri ); + aUri.path + = ne_strdup( rtl::OUStringToOString( + rURL, RTL_TEXTENCODING_UTF8 ).getStr() ); + NeonUri aNeonUri( &aUri ); + ne_uri_free( &aUri ); + return aNeonUri.GetURI(); + } + } + catch ( DAVException const & ) + { + } + // error. + return rtl::OUString(); +} |