| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_ucb.hxx" |
| |
| #include <hash_map> |
| #include <vector> |
| #include <string.h> |
| #include <rtl/string.h> |
| #include "comphelper/sequence.hxx" |
| #include "ucbhelper/simplecertificatevalidationrequest.hxx" |
| |
| #include "AprEnv.hxx" |
| #include <apr/apr_strings.h> |
| |
| #include "DAVAuthListener.hxx" |
| #include "SerfTypes.hxx" |
| #include "SerfSession.hxx" |
| #include "SerfUri.hxx" |
| #include "SerfRequestProcessor.hxx" |
| #include "SerfCallbacks.hxx" |
| #include "SerfInputStream.hxx" |
| #include "UCBDeadPropertyValue.hxx" |
| |
| #include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp> |
| #include <com/sun/star/security/XCertificate.hpp> |
| #include <com/sun/star/security/CertificateValidity.hpp> |
| #include <com/sun/star/security/CertificateContainerStatus.hpp> |
| #include <com/sun/star/security/CertificateContainer.hpp> |
| #include <com/sun/star/security/XCertificateContainer.hpp> |
| #include <com/sun/star/security/CertAltNameEntry.hpp> |
| #include <com/sun/star/security/XSanExtension.hpp> |
| #define OID_SUBJECT_ALTERNATIVE_NAME "2.5.29.17" |
| |
| #include <com/sun/star/ucb/Lock.hpp> |
| #include <com/sun/star/xml/crypto/XSEInitializer.hpp> |
| |
| using namespace com::sun::star; |
| using namespace http_dav_ucp; |
| |
| |
| // ------------------------------------------------------------------- |
| // static members! |
| //SerfLockStore SerfSession::m_aSerfLockStore; |
| |
| // ------------------------------------------------------------------- |
| // Constructor |
| // ------------------------------------------------------------------- |
| SerfSession::SerfSession( |
| const rtl::Reference< DAVSessionFactory > & rSessionFactory, |
| const rtl::OUString& inUri, |
| const ucbhelper::InternetProxyDecider & rProxyDecider ) |
| throw ( DAVException ) |
| : DAVSession( rSessionFactory ) |
| , m_aMutex() |
| , m_aUri( inUri ) |
| , m_aProxyName() |
| , m_nProxyPort( 0 ) |
| , m_pSerfConnection( 0 ) |
| , m_pSerfContext( 0 ) |
| , m_bIsHeadRequestInProgress( false ) |
| , m_bUseChunkedEncoding( false ) |
| , m_bNoOfTransferEncodingSwitches( 0 ) |
| , m_rProxyDecider( rProxyDecider ) |
| , m_aEnv() |
| { |
| m_pSerfContext = serf_context_create( getAprPool() ); |
| |
| m_pSerfBucket_Alloc = serf_bucket_allocator_create( getAprPool(), NULL, NULL ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // Destructor |
| // ------------------------------------------------------------------- |
| SerfSession::~SerfSession( ) |
| { |
| if ( m_pSerfConnection ) |
| { |
| serf_connection_close( m_pSerfConnection ); |
| m_pSerfConnection = 0; |
| } |
| } |
| |
| // ------------------------------------------------------------------- |
| void SerfSession::Init( const DAVRequestEnvironment & rEnv ) |
| throw ( DAVException ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| m_aEnv = rEnv; |
| Init(); |
| } |
| |
| // ------------------------------------------------------------------- |
| void SerfSession::Init() |
| throw ( DAVException ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| |
| bool bCreateNewSession = false; |
| |
| if ( m_pSerfConnection == 0 ) |
| { |
| const ucbhelper::InternetProxyServer & rProxyCfg = getProxySettings(); |
| |
| m_aProxyName = rProxyCfg.aName; |
| m_nProxyPort = rProxyCfg.nPort; |
| |
| // Not yet initialized. Create new session. |
| bCreateNewSession = true; |
| } |
| else |
| { |
| const ucbhelper::InternetProxyServer & rProxyCfg = getProxySettings(); |
| |
| if ( ( rProxyCfg.aName != m_aProxyName ) |
| || ( rProxyCfg.nPort != m_nProxyPort ) ) |
| { |
| m_aProxyName = rProxyCfg.aName; |
| m_nProxyPort = rProxyCfg.nPort; |
| |
| // new session needed, destroy old first |
| serf_connection_close( m_pSerfConnection ); |
| m_pSerfConnection = 0; |
| bCreateNewSession = true; |
| } |
| } |
| |
| if ( bCreateNewSession ) |
| { |
| // TODO - close_connection callback |
| apr_status_t status = serf_connection_create2( &m_pSerfConnection, |
| m_pSerfContext, |
| *(m_aUri.getAprUri()), |
| Serf_ConnectSetup, this, |
| 0 /* close connection callback */, 0 /* close connection baton */, |
| getAprPool() ); |
| |
| if ( m_pSerfConnection == 0 ||status != APR_SUCCESS ) |
| { |
| throw DAVException( DAVException::DAV_SESSION_CREATE, |
| SerfUri::makeConnectionEndPointString( m_aUri.GetHost(), m_aUri.GetPort() ) ); |
| } |
| |
| // Register the session with the lock store |
| // m_aSerfLockStore.registerSession( m_pSerfConnection ); |
| |
| if ( m_aProxyName.getLength() ) |
| { |
| apr_sockaddr_t *proxy_address = NULL; |
| status = apr_sockaddr_info_get( &proxy_address, |
| rtl::OUStringToOString( m_aProxyName, RTL_TEXTENCODING_UTF8 ).getStr(), |
| APR_UNSPEC, |
| static_cast<apr_port_t>(m_nProxyPort), |
| 0, getAprPool() ); |
| |
| if ( status != APR_SUCCESS ) |
| { |
| throw DAVException( DAVException::DAV_SESSION_CREATE, |
| SerfUri::makeConnectionEndPointString( m_aUri.GetHost(), m_aUri.GetPort() ) ); |
| } |
| |
| serf_config_proxy( m_pSerfContext, proxy_address ); |
| } |
| |
| |
| serf_config_credentials_callback( m_pSerfContext, Serf_Credentials ); |
| |
| m_bUseChunkedEncoding = isSSLNeeded(); |
| } |
| } |
| |
| apr_pool_t* SerfSession::getAprPool() |
| { |
| return apr_environment::AprEnv::getAprEnv()->getAprPool(); |
| } |
| |
| serf_bucket_alloc_t* SerfSession::getSerfBktAlloc() |
| { |
| return m_pSerfBucket_Alloc; |
| } |
| |
| serf_context_t* SerfSession::getSerfContext() |
| { |
| return m_pSerfContext; |
| } |
| |
| SerfConnection* SerfSession::getSerfConnection() |
| { |
| return m_pSerfConnection; |
| } |
| |
| bool SerfSession::isHeadRequestInProgress() |
| { |
| return m_bIsHeadRequestInProgress; |
| } |
| |
| bool SerfSession::isSSLNeeded() |
| { |
| return m_aUri.GetScheme().equalsIgnoreAsciiCase( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "https" ) ) ); |
| } |
| |
| char* SerfSession::getHostinfo() |
| { |
| return m_aUri.getAprUri()->hostinfo; |
| } |
| |
| |
| // ------------------------------------------------------------------- |
| // virtual |
| sal_Bool SerfSession::CanUse( const rtl::OUString & inUri ) |
| { |
| try |
| { |
| SerfUri theUri( inUri ); |
| if ( ( theUri.GetPort() == m_aUri.GetPort() ) && |
| ( theUri.GetHost() == m_aUri.GetHost() ) && |
| ( theUri.GetScheme() == m_aUri.GetScheme() ) ) |
| { |
| return sal_True; |
| } |
| } |
| catch ( DAVException const & ) |
| { |
| return sal_False; |
| } |
| return sal_False; |
| } |
| |
| // ------------------------------------------------------------------- |
| // virtual |
| sal_Bool SerfSession::UsesProxy() |
| { |
| Init(); |
| return ( m_aProxyName.getLength() > 0 ); |
| } |
| |
| apr_status_t SerfSession::setupSerfConnection( apr_socket_t * inAprSocket, |
| serf_bucket_t **outSerfInputBucket, |
| serf_bucket_t **outSerfOutputBucket, |
| apr_pool_t* /*inAprPool*/ ) |
| { |
| serf_bucket_t *tmpInputBkt; |
| tmpInputBkt = serf_context_bucket_socket_create( getSerfContext(), |
| inAprSocket, |
| getSerfBktAlloc() ); |
| |
| if ( isSSLNeeded() ) |
| { |
| tmpInputBkt = serf_bucket_ssl_decrypt_create( tmpInputBkt, |
| 0, |
| getSerfBktAlloc() ); |
| /** Set the callback that is called to authenticate the |
| certifcate (chain). |
| */ |
| serf_ssl_server_cert_chain_callback_set( |
| serf_bucket_ssl_decrypt_context_get(tmpInputBkt), |
| NULL, |
| Serf_CertificateChainValidation, |
| this); |
| serf_ssl_set_hostname( serf_bucket_ssl_decrypt_context_get( tmpInputBkt ), |
| getHostinfo() ); |
| |
| *outSerfOutputBucket = serf_bucket_ssl_encrypt_create( *outSerfOutputBucket, |
| serf_bucket_ssl_decrypt_context_get( tmpInputBkt ), |
| getSerfBktAlloc() ); |
| } |
| |
| *outSerfInputBucket = tmpInputBkt; |
| |
| return APR_SUCCESS; |
| } |
| |
| apr_status_t SerfSession::provideSerfCredentials( bool bGiveProvidedCredentialsASecondTry, |
| char ** outUsername, |
| char ** outPassword, |
| serf_request_t * /*inRequest*/, |
| int /*inCode*/, |
| const char *inAuthProtocol, |
| const char *inRealm, |
| apr_pool_t *inAprPool ) |
| { |
| DAVAuthListener * pListener = getRequestEnvironment().m_xAuthListener.get(); |
| if ( !pListener ) |
| { |
| // abort |
| return SERF_ERROR_AUTHN_FAILED; |
| } |
| |
| rtl::OUString theUserName; |
| rtl::OUString thePassWord; |
| try |
| { |
| SerfUri uri( getRequestEnvironment().m_aRequestURI ); |
| rtl::OUString aUserInfo( uri.GetUserInfo() ); |
| if ( aUserInfo.getLength() ) |
| { |
| sal_Int32 nPos = aUserInfo.indexOf( '@' ); |
| if ( nPos == -1 ) |
| { |
| theUserName = aUserInfo; |
| } |
| else |
| { |
| theUserName = aUserInfo.copy( 0, nPos ); |
| thePassWord = aUserInfo.copy( nPos + 1 ); |
| } |
| } |
| } |
| catch ( DAVException const & ) |
| { |
| // abort |
| return SERF_ERROR_AUTHN_FAILED; |
| } |
| |
| const bool bCanUseSystemCreds = ( ( strcasecmp( inAuthProtocol, "NTLM" ) == 0 ) || |
| ( strcasecmp( inAuthProtocol, "Negotiate" ) == 0 ) ); |
| |
| int theRetVal = pListener->authenticate( rtl::OUString::createFromAscii( inRealm ), |
| getHostName(), |
| theUserName, |
| thePassWord, |
| bCanUseSystemCreds, |
| bGiveProvidedCredentialsASecondTry ? sal_False : sal_True ); |
| |
| if ( theRetVal == 0 ) |
| { |
| *outUsername = apr_pstrdup( inAprPool, rtl::OUStringToOString( theUserName, RTL_TEXTENCODING_UTF8 ).getStr() ); |
| *outPassword = apr_pstrdup( inAprPool, rtl::OUStringToOString( thePassWord, RTL_TEXTENCODING_UTF8 ).getStr() ); |
| } |
| |
| return theRetVal != 0 ? SERF_ERROR_AUTHN_FAILED : APR_SUCCESS; |
| } |
| |
| namespace { |
| // ------------------------------------------------------------------- |
| // Helper function |
| ::rtl::OUString GetHostnamePart( const ::rtl::OUString& _rRawString ) |
| { |
| ::rtl::OUString sPart; |
| ::rtl::OUString sPartId = ::rtl::OUString::createFromAscii( "CN=" ); |
| sal_Int32 nContStart = _rRawString.indexOf( sPartId ); |
| if ( nContStart != -1 ) |
| { |
| nContStart = nContStart + sPartId.getLength(); |
| sal_Int32 nContEnd |
| = _rRawString.indexOf( sal_Unicode( ',' ), nContStart ); |
| sPart = _rRawString.copy( nContStart, nContEnd - nContStart ); |
| } |
| return sPart; |
| } |
| } // namespace |
| |
| |
| apr_status_t SerfSession::verifySerfCertificateChain ( |
| int, |
| const serf_ssl_certificate_t * const * pCertificateChainBase64Encoded, |
| int nCertificateChainLength) |
| { |
| // Check arguments. |
| if (pCertificateChainBase64Encoded == NULL || nCertificateChainLength<=0) |
| { |
| OSL_ASSERT(pCertificateChainBase64Encoded != NULL); |
| OSL_ASSERT(nCertificateChainLength>0); |
| return SERF_SSL_CERT_UNKNOWN_FAILURE; |
| } |
| |
| // Create some crypto objects to decode and handle the base64 |
| // encoded certificate chain. |
| uno::Reference< xml::crypto::XSEInitializer > xSEInitializer; |
| uno::Reference< security::XCertificateContainer > xCertificateContainer; |
| uno::Reference< xml::crypto::XXMLSecurityContext > xSecurityContext; |
| uno::Reference< xml::crypto::XSecurityEnvironment > xSecurityEnv; |
| try |
| { |
| // Create a certificate container. |
| xCertificateContainer = uno::Reference< security::XCertificateContainer >( |
| getMSF()->createInstance( |
| rtl::OUString::createFromAscii( |
| "com.sun.star.security.CertificateContainer" ) ), |
| uno::UNO_QUERY_THROW); |
| |
| xSEInitializer = uno::Reference< xml::crypto::XSEInitializer >( |
| getMSF()->createInstance( |
| rtl::OUString::createFromAscii( "com.sun.star.xml.crypto.SEInitializer" ) ), |
| uno::UNO_QUERY_THROW); |
| |
| xSecurityContext = xSEInitializer->createSecurityContext( rtl::OUString() ); |
| if (xSecurityContext.is()) |
| xSecurityEnv = xSecurityContext->getSecurityEnvironment(); |
| |
| if ( ! xSecurityContext.is() || ! xSecurityEnv.is()) |
| { |
| // Do we have to dispose xSEInitializer or xCertificateContainer? |
| return SERF_SSL_CERT_UNKNOWN_FAILURE; |
| } |
| } |
| catch ( uno::Exception const &) |
| { |
| return SERF_SSL_CERT_UNKNOWN_FAILURE; |
| } |
| |
| // Decode the server certificate. |
| const char* sBase64EncodedServerCertificate ( |
| serf_ssl_cert_export( |
| pCertificateChainBase64Encoded[0], |
| getAprPool())); |
| uno::Reference< security::XCertificate > xServerCertificate( |
| xSecurityEnv->createCertificateFromAscii( |
| rtl::OUString::createFromAscii(sBase64EncodedServerCertificate))); |
| if ( ! xServerCertificate.is()) |
| return SERF_SSL_CERT_UNKNOWN_FAILURE; |
| |
| // Get the subject from the server certificate. |
| ::rtl::OUString sServerCertificateSubject (xServerCertificate->getSubjectName()); |
| sal_Int32 nIndex = 0; |
| while (nIndex >= 0) |
| { |
| const ::rtl::OUString sToken (sServerCertificateSubject.getToken(0, ',', nIndex)); |
| if (sToken.compareToAscii("CN=", 3) == 0) |
| { |
| sServerCertificateSubject = sToken.copy(3); |
| break; |
| } |
| else if (sToken.compareToAscii(" CN=", 4) == 0) |
| { |
| sServerCertificateSubject = sToken.copy(4); |
| break; |
| } |
| } |
| |
| // When the certificate container already contains a (trusted) |
| // entry for the server then we do not have to authenticate any |
| // certificate. |
| const security::CertificateContainerStatus eStatus ( |
| xCertificateContainer->hasCertificate( |
| getHostName(), sServerCertificateSubject ) ); |
| if (eStatus != security::CertificateContainerStatus_NOCERT) |
| { |
| return eStatus == security::CertificateContainerStatus_TRUSTED |
| ? APR_SUCCESS |
| : SERF_SSL_CERT_UNKNOWN_FAILURE; |
| } |
| |
| // The shortcut failed, so try to verify the whole chain. This is |
| // done outside the isDomainMatch() block because the result is |
| // used by the interaction handler. |
| std::vector< uno::Reference< security::XCertificate > > aChain; |
| for (nIndex=1; nIndex<nCertificateChainLength; ++nIndex) |
| { |
| const char* sBase64EncodedCertificate ( |
| serf_ssl_cert_export( |
| pCertificateChainBase64Encoded[nIndex], |
| getAprPool())); |
| uno::Reference< security::XCertificate > xCertificate( |
| xSecurityEnv->createCertificateFromAscii( |
| rtl::OUString::createFromAscii(sBase64EncodedCertificate))); |
| if ( ! xCertificate.is()) |
| return SERF_SSL_CERT_UNKNOWN_FAILURE; |
| aChain.push_back(xCertificate); |
| } |
| const sal_Int64 nVerificationResult (xSecurityEnv->verifyCertificate( |
| xServerCertificate, |
| ::comphelper::containerToSequence(aChain))); |
| |
| // When the certificate matches the host name then we can use the |
| // result of the verification. |
| bool bHostnameMatchesCertHostnames = false; |
| { |
| uno::Sequence< uno::Reference< security::XCertificateExtension > > extensions = xServerCertificate->getExtensions(); |
| uno::Sequence< security::CertAltNameEntry > altNames; |
| for (sal_Int32 i = 0 ; i < extensions.getLength(); ++i) |
| { |
| uno::Reference< security::XCertificateExtension >element = extensions[i]; |
| |
| const rtl::OString aId ( (const sal_Char *)element->getExtensionId().getArray(), element->getExtensionId().getLength()); |
| if ( aId.equals( OID_SUBJECT_ALTERNATIVE_NAME ) ) |
| { |
| uno::Reference< security::XSanExtension > sanExtension ( element, uno::UNO_QUERY ); |
| altNames = sanExtension->getAlternativeNames(); |
| break; |
| } |
| } |
| |
| uno::Sequence< ::rtl::OUString > certHostNames(altNames.getLength() + 1); |
| certHostNames[0] = sServerCertificateSubject; |
| for( int n = 0; n < altNames.getLength(); ++n ) |
| { |
| if (altNames[n].Type == security::ExtAltNameType_DNS_NAME) |
| { |
| altNames[n].Value >>= certHostNames[n+1]; |
| } |
| } |
| |
| for ( int i = 0; i < certHostNames.getLength() && !bHostnameMatchesCertHostnames; ++i ) |
| { |
| bHostnameMatchesCertHostnames = isDomainMatch( certHostNames[i] ); |
| } |
| |
| } |
| if ( bHostnameMatchesCertHostnames ) |
| { |
| |
| if (nVerificationResult == 0) |
| { |
| // Certificate (chain) is valid. |
| xCertificateContainer->addCertificate(getHostName(), sServerCertificateSubject, sal_True); |
| return APR_SUCCESS; |
| } |
| else if ((nVerificationResult & security::CertificateValidity::CHAIN_INCOMPLETE) != 0) |
| { |
| // We do not have enough information for verification, |
| // neither automatically (as we just discovered) nor |
| // manually (so there is no point in showing any dialog.) |
| return SERF_SSL_CERT_UNKNOWN_FAILURE; |
| } |
| else if ((nVerificationResult & |
| (security::CertificateValidity::INVALID | security::CertificateValidity::REVOKED)) != 0) |
| { |
| // Certificate (chain) is invalid. |
| xCertificateContainer->addCertificate(getHostName(), sServerCertificateSubject, sal_False); |
| return SERF_SSL_CERT_UNKNOWN_FAILURE; |
| } |
| else |
| { |
| // For all other we have to ask the user. |
| } |
| } |
| |
| // We have not been able to automatically verify (or falsify) the |
| // certificate chain. To resolve this we have to ask the user. |
| const uno::Reference< ucb::XCommandEnvironment > xEnv( getRequestEnvironment().m_xEnv ); |
| if ( xEnv.is() ) |
| { |
| uno::Reference< task::XInteractionHandler > xIH( xEnv->getInteractionHandler() ); |
| if ( xIH.is() ) |
| { |
| rtl::Reference< ucbhelper::SimpleCertificateValidationRequest > |
| xRequest( new ucbhelper::SimpleCertificateValidationRequest( |
| static_cast<sal_Int32>(nVerificationResult), xServerCertificate, getHostName() ) ); |
| xIH->handle( xRequest.get() ); |
| |
| rtl::Reference< ucbhelper::InteractionContinuation > xSelection |
| = xRequest->getSelection(); |
| |
| if ( xSelection.is() ) |
| { |
| uno::Reference< task::XInteractionApprove > xApprove( xSelection.get(), uno::UNO_QUERY ); |
| if ( xApprove.is() ) |
| { |
| xCertificateContainer->addCertificate( getHostName(), sServerCertificateSubject, sal_True ); |
| return APR_SUCCESS; |
| } |
| else |
| { |
| // Don't trust cert |
| xCertificateContainer->addCertificate( getHostName(), sServerCertificateSubject, sal_False ); |
| return SERF_SSL_CERT_UNKNOWN_FAILURE; |
| } |
| } |
| } |
| else |
| { |
| // Don't trust cert |
| xCertificateContainer->addCertificate( getHostName(), sServerCertificateSubject, sal_False ); |
| return SERF_SSL_CERT_UNKNOWN_FAILURE; |
| } |
| } |
| |
| return SERF_SSL_CERT_UNKNOWN_FAILURE; |
| } |
| |
| serf_bucket_t* SerfSession::acceptSerfResponse( serf_request_t * inSerfRequest, |
| serf_bucket_t * inSerfStreamBucket, |
| apr_pool_t* /*inAprPool*/ ) |
| { |
| // get the per-request bucket allocator |
| serf_bucket_alloc_t* SerfBktAlloc = serf_request_get_alloc( inSerfRequest ); |
| |
| // create a barrier bucket so the response doesn't eat us! |
| serf_bucket_t *responseBkt = serf_bucket_barrier_create( inSerfStreamBucket, |
| SerfBktAlloc ); |
| |
| // create response bucket |
| responseBkt = serf_bucket_response_create( responseBkt, |
| SerfBktAlloc ); |
| |
| if ( isHeadRequestInProgress() ) |
| { |
| // advise the response bucket that this was from a HEAD request and that it should not expect to see a response body. |
| serf_bucket_response_set_head( responseBkt ); |
| } |
| |
| return responseBkt; |
| } |
| |
| SerfRequestProcessor* SerfSession::createReqProc( const rtl::OUString & inPath ) |
| { |
| return new SerfRequestProcessor( *this, |
| inPath, |
| m_bUseChunkedEncoding ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // PROPFIND - allprop & named |
| // ------------------------------------------------------------------- |
| void SerfSession::PROPFIND( const rtl::OUString & inPath, |
| const Depth inDepth, |
| const std::vector< rtl::OUString > & inPropNames, |
| std::vector< DAVResource > & ioResources, |
| const DAVRequestEnvironment & rEnv ) |
| throw ( DAVException ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| |
| Init( rEnv ); |
| |
| apr_status_t status = APR_SUCCESS; |
| boost::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) ); |
| aReqProc->processPropFind( inDepth, |
| inPropNames, |
| ioResources, |
| status ); |
| |
| if ( status == APR_SUCCESS && |
| aReqProc->mpDAVException == 0 && |
| ioResources.empty() ) |
| { |
| m_aEnv = DAVRequestEnvironment(); |
| throw DAVException( DAVException::DAV_HTTP_ERROR, inPath, (sal_uInt16)APR_EGENERAL ); |
| } |
| HandleError( aReqProc ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // PROPFIND - propnames |
| // ------------------------------------------------------------------- |
| void SerfSession::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( rEnv ); |
| |
| apr_status_t status = APR_SUCCESS; |
| boost::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) ); |
| aReqProc->processPropFind( inDepth, |
| ioResInfo, |
| status ); |
| |
| if ( status == APR_SUCCESS && |
| aReqProc->mpDAVException == 0 && |
| ioResInfo.empty() ) |
| { |
| m_aEnv = DAVRequestEnvironment(); |
| throw DAVException( DAVException::DAV_HTTP_ERROR, inPath, (sal_uInt16)APR_EGENERAL ); |
| } |
| HandleError( aReqProc ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // PROPPATCH |
| // ------------------------------------------------------------------- |
| void SerfSession::PROPPATCH( const rtl::OUString & inPath, |
| const std::vector< ProppatchValue > & inValues, |
| const DAVRequestEnvironment & rEnv ) |
| throw( DAVException ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| |
| Init( rEnv ); |
| |
| apr_status_t status = APR_SUCCESS; |
| boost::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) ); |
| aReqProc->processPropPatch( inValues, |
| status ); |
| |
| HandleError( aReqProc ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // HEAD |
| // ------------------------------------------------------------------- |
| void SerfSession::HEAD( const ::rtl::OUString & inPath, |
| const std::vector< ::rtl::OUString > & inHeaderNames, |
| DAVResource & ioResource, |
| const DAVRequestEnvironment & rEnv ) |
| throw( DAVException ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| |
| Init( rEnv ); |
| |
| m_bIsHeadRequestInProgress = true; |
| |
| boost::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) ); |
| ioResource.uri = inPath; |
| ioResource.properties.clear(); |
| apr_status_t status = APR_SUCCESS; |
| aReqProc->processHead( inHeaderNames, |
| ioResource, |
| status ); |
| |
| m_bIsHeadRequestInProgress = false; |
| |
| HandleError( aReqProc ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // GET |
| // ------------------------------------------------------------------- |
| uno::Reference< io::XInputStream > |
| SerfSession::GET( const rtl::OUString & inPath, |
| const DAVRequestEnvironment & rEnv ) |
| throw ( DAVException ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| |
| Init( rEnv ); |
| |
| uno::Reference< SerfInputStream > xInputStream( new SerfInputStream ); |
| apr_status_t status = APR_SUCCESS; |
| boost::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) ); |
| aReqProc->processGet( xInputStream, |
| status ); |
| |
| HandleError( aReqProc ); |
| |
| return uno::Reference< io::XInputStream >( xInputStream.get() ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // GET |
| // ------------------------------------------------------------------- |
| void SerfSession::GET( const rtl::OUString & inPath, |
| uno::Reference< io::XOutputStream > & ioOutputStream, |
| const DAVRequestEnvironment & rEnv ) |
| throw ( DAVException ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| |
| Init( rEnv ); |
| |
| apr_status_t status = APR_SUCCESS; |
| boost::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) ); |
| aReqProc->processGet( ioOutputStream, |
| status ); |
| |
| HandleError( aReqProc ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // GET |
| // ------------------------------------------------------------------- |
| uno::Reference< io::XInputStream > |
| SerfSession::GET( const rtl::OUString & inPath, |
| const std::vector< ::rtl::OUString > & inHeaderNames, |
| DAVResource & ioResource, |
| const DAVRequestEnvironment & rEnv ) |
| throw ( DAVException ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| |
| Init( rEnv ); |
| |
| boost::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) ); |
| uno::Reference< SerfInputStream > xInputStream( new SerfInputStream ); |
| ioResource.uri = inPath; |
| ioResource.properties.clear(); |
| apr_status_t status = APR_SUCCESS; |
| aReqProc->processGet( xInputStream, |
| inHeaderNames, |
| ioResource, |
| status ); |
| |
| HandleError( aReqProc ); |
| |
| return uno::Reference< io::XInputStream >( xInputStream.get() ); |
| } |
| |
| |
| // ------------------------------------------------------------------- |
| // GET |
| // ------------------------------------------------------------------- |
| void SerfSession::GET( const rtl::OUString & inPath, |
| 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( rEnv ); |
| |
| boost::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) ); |
| ioResource.uri = inPath; |
| ioResource.properties.clear(); |
| apr_status_t status = APR_SUCCESS; |
| aReqProc->processGet( ioOutputStream, |
| inHeaderNames, |
| ioResource, |
| status ); |
| |
| HandleError( aReqProc ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // PUT |
| // ------------------------------------------------------------------- |
| void SerfSession::PUT( const rtl::OUString & inPath, |
| const uno::Reference< io::XInputStream > & inInputStream, |
| const DAVRequestEnvironment & rEnv ) |
| throw ( DAVException ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| |
| Init( rEnv ); |
| |
| boost::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) ); |
| uno::Sequence< sal_Int8 > aDataToSend; |
| if ( !getDataFromInputStream( inInputStream, aDataToSend, false ) ) |
| throw DAVException( DAVException::DAV_INVALID_ARG ); |
| apr_status_t status = APR_SUCCESS; |
| aReqProc->processPut( reinterpret_cast< const char * >( aDataToSend.getConstArray() ), |
| aDataToSend.getLength(), |
| status ); |
| |
| HandleError( aReqProc ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // POST |
| // ------------------------------------------------------------------- |
| uno::Reference< io::XInputStream > |
| SerfSession::POST( const rtl::OUString & inPath, |
| 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 ); |
| |
| uno::Sequence< sal_Int8 > aDataToSend; |
| if ( !getDataFromInputStream( inInputStream, aDataToSend, true ) ) |
| { |
| throw DAVException( DAVException::DAV_INVALID_ARG ); |
| } |
| |
| Init( rEnv ); |
| |
| boost::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) ); |
| uno::Reference< SerfInputStream > xInputStream( new SerfInputStream ); |
| apr_status_t status = APR_SUCCESS; |
| aReqProc->processPost( reinterpret_cast< const char * >( aDataToSend.getConstArray() ), |
| aDataToSend.getLength(), |
| rContentType, |
| rReferer, |
| xInputStream, |
| status ); |
| |
| HandleError( aReqProc ); |
| return uno::Reference< io::XInputStream >( xInputStream.get() ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // POST |
| // ------------------------------------------------------------------- |
| void SerfSession::POST( const rtl::OUString & inPath, |
| const rtl::OUString & rContentType, |
| const rtl::OUString & rReferer, |
| const uno::Reference< io::XInputStream > & inInputStream, |
| uno::Reference< io::XOutputStream > & oOutputStream, |
| const DAVRequestEnvironment & rEnv ) |
| throw ( DAVException ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| |
| uno::Sequence< sal_Int8 > aDataToSend; |
| if ( !getDataFromInputStream( inInputStream, aDataToSend, true ) ) |
| { |
| throw DAVException( DAVException::DAV_INVALID_ARG ); |
| } |
| |
| Init( rEnv ); |
| |
| boost::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) ); |
| apr_status_t status = APR_SUCCESS; |
| aReqProc->processPost( reinterpret_cast< const char * >( aDataToSend.getConstArray() ), |
| aDataToSend.getLength(), |
| rContentType, |
| rReferer, |
| oOutputStream, |
| status ); |
| |
| HandleError( aReqProc ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // MKCOL |
| // ------------------------------------------------------------------- |
| void SerfSession::MKCOL( const rtl::OUString & inPath, |
| const DAVRequestEnvironment & rEnv ) |
| throw ( DAVException ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| |
| Init( rEnv ); |
| |
| boost::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) ); |
| apr_status_t status = APR_SUCCESS; |
| aReqProc->processMkCol( status ); |
| |
| HandleError( aReqProc ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // COPY |
| // ------------------------------------------------------------------- |
| void SerfSession::COPY( const rtl::OUString & inSourceURL, |
| const rtl::OUString & inDestinationURL, |
| const DAVRequestEnvironment & rEnv, |
| sal_Bool inOverWrite ) |
| throw ( DAVException ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| |
| Init( rEnv ); |
| |
| SerfUri theSourceUri( inSourceURL ); |
| boost::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( theSourceUri.GetPath() ) ); |
| apr_status_t status = APR_SUCCESS; |
| aReqProc->processCopy( inDestinationURL, |
| (inOverWrite ? true : false), |
| status ); |
| |
| HandleError( aReqProc ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // MOVE |
| // ------------------------------------------------------------------- |
| void SerfSession::MOVE( const rtl::OUString & inSourceURL, |
| const rtl::OUString & inDestinationURL, |
| const DAVRequestEnvironment & rEnv, |
| sal_Bool inOverWrite ) |
| throw ( DAVException ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| |
| Init( rEnv ); |
| |
| SerfUri theSourceUri( inSourceURL ); |
| boost::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( theSourceUri.GetPath() ) ); |
| apr_status_t status = APR_SUCCESS; |
| aReqProc->processMove( inDestinationURL, |
| (inOverWrite ? true : false), |
| status ); |
| |
| HandleError( aReqProc ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // DESTROY |
| // ------------------------------------------------------------------- |
| void SerfSession::DESTROY( const rtl::OUString & inPath, |
| const DAVRequestEnvironment & rEnv ) |
| throw ( DAVException ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| |
| Init( rEnv ); |
| |
| boost::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) ); |
| apr_status_t status = APR_SUCCESS; |
| aReqProc->processDelete( status ); |
| |
| HandleError( aReqProc ); |
| } |
| |
| // ------------------------------------------------------------------- |
| /* |
| 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) |
| // ------------------------------------------------------------------- |
| void SerfSession::LOCK( const ::rtl::OUString & inPath, |
| ucb::Lock & /*rLock*/, |
| const DAVRequestEnvironment & rEnv ) |
| throw ( DAVException ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| |
| Init( rEnv ); |
| |
| boost::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) ); |
| HandleError( aReqProc ); |
| /* Create a depth zero, exclusive write lock, with default timeout |
| * (allowing a server to pick a default). token, owner and uri are |
| * unset. */ |
| /* |
| SerfLock * 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_aSerfLockStore.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( "SerfSession::LOCK: created lock for %s. token: %s", |
| rtl::OUStringToOString( makeAbsoluteURL( inPath ), |
| RTL_TEXTENCODING_UTF8 ).getStr(), |
| theLock->token ); |
| } |
| else |
| { |
| ne_lock_destroy( theLock ); |
| |
| OSL_TRACE( "SerfSession::LOCK: obtaining lock for %s failed!", |
| rtl::OUStringToOString( makeAbsoluteURL( inPath ), |
| RTL_TEXTENCODING_UTF8 ).getStr() ); |
| } |
| |
| HandleError( theRetVal, inPath, rEnv ); |
| */ |
| } |
| |
| // ------------------------------------------------------------------- |
| // LOCK (refresh existing lock) |
| // ------------------------------------------------------------------- |
| sal_Int64 SerfSession::LOCK( const ::rtl::OUString & /*inPath*/, |
| sal_Int64 nTimeout, |
| const DAVRequestEnvironment & /*rEnv*/ ) |
| throw ( DAVException ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| |
| return nTimeout; |
| /* |
| // Try to get the neon lock from lock store |
| SerfLock * theLock |
| = m_aSerfLockStore.findByUri( makeAbsoluteURL( inPath ) ); |
| if ( !theLock ) |
| throw DAVException( DAVException::DAV_NOT_LOCKED ); |
| |
| Init( rEnv ); |
| |
| // refresh existing lock. |
| theLock->timeout = static_cast< long >( nTimeout ); |
| |
| TimeValue startCall; |
| osl_getSystemTime( &startCall ); |
| |
| int theRetVal = ne_lock_refresh( m_pHttpSession, theLock ); |
| |
| if ( theRetVal == NE_OK ) |
| { |
| m_aSerfLockStore.updateLock( theLock, |
| lastChanceToSendRefreshRequest( |
| startCall, theLock->timeout ) ); |
| } |
| |
| HandleError( theRetVal, inPath, rEnv ); |
| |
| return theLock->timeout; |
| */ |
| } |
| |
| // ------------------------------------------------------------------- |
| // LOCK (refresh existing lock) |
| // ------------------------------------------------------------------- |
| bool SerfSession::LOCK( SerfLock * /*pLock*/, |
| sal_Int32 & /*rlastChanceToSendRefreshRequest*/ ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| |
| return true; |
| /* |
| // 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 |
| // ------------------------------------------------------------------- |
| void SerfSession::UNLOCK( const ::rtl::OUString & /*inPath*/, |
| const DAVRequestEnvironment & /*rEnv*/ ) |
| throw ( DAVException ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| |
| /* |
| // get the neon lock from lock store |
| SerfLock * theLock |
| = m_aSerfLockStore.findByUri( makeAbsoluteURL( inPath ) ); |
| if ( !theLock ) |
| throw DAVException( DAVException::DAV_NOT_LOCKED ); |
| |
| Init( rEnv ); |
| |
| int theRetVal = ne_unlock( m_pHttpSession, theLock ); |
| |
| if ( theRetVal == NE_OK ) |
| { |
| m_aSerfLockStore.removeLock( theLock ); |
| ne_lock_destroy( theLock ); |
| } |
| else |
| { |
| OSL_TRACE( "SerfSession::UNLOCK: unlocking of %s failed.", |
| rtl::OUStringToOString( makeAbsoluteURL( inPath ), |
| RTL_TEXTENCODING_UTF8 ).getStr() ); |
| } |
| |
| HandleError( theRetVal, inPath, rEnv ); |
| */ |
| } |
| |
| // ------------------------------------------------------------------- |
| // UNLOCK |
| // ------------------------------------------------------------------- |
| bool SerfSession::UNLOCK( SerfLock * /*pLock*/ ) |
| { |
| osl::Guard< osl::Mutex > theGuard( m_aMutex ); |
| |
| return true; |
| /* |
| if ( ne_unlock( m_pHttpSession, pLock ) == NE_OK ) |
| { |
| OSL_TRACE( "UNLOCK succeeded." ); |
| return true; |
| } |
| else |
| { |
| OSL_TRACE( "UNLOCK failed!" ); |
| return false; |
| } |
| */ |
| } |
| |
| // ------------------------------------------------------------------- |
| void SerfSession::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 & SerfSession::getProxySettings() const |
| { |
| if ( m_aUri.GetScheme().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "http" ) ) || |
| m_aUri.GetScheme().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "https" ) ) ) |
| { |
| return m_rProxyDecider.getProxy( m_aUri.GetScheme(), |
| m_aUri.GetHost(), |
| m_aUri.GetPort() ); |
| } |
| else |
| { |
| // TODO: figure out, if this case can occur |
| return m_rProxyDecider.getProxy( m_aUri.GetScheme(), |
| rtl::OUString() /* not used */, |
| -1 /* not used */ ); |
| } |
| } |
| |
| /* |
| // ------------------------------------------------------------------- |
| 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 SerfSession::removeExpiredLocktoken( const rtl::OUString & /*inURL*/, |
| const DAVRequestEnvironment & /*rEnv*/ ) |
| { |
| return true; |
| /* |
| SerfLock * theLock = m_aSerfLockStore.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( "SerfSession::removeExpiredLocktoken: Removing " |
| " expired lock token for %s. token: %s", |
| rtl::OUStringToOString( inURL, |
| RTL_TEXTENCODING_UTF8 ).getStr(), |
| theLock->token ); |
| |
| m_aSerfLockStore.removeLock( theLock ); |
| ne_lock_destroy( theLock ); |
| return true; |
| } |
| catch ( DAVException const & ) |
| { |
| } |
| return false; |
| */ |
| } |
| |
| // ------------------------------------------------------------------- |
| // HandleError |
| // Common Error Handler |
| // ------------------------------------------------------------------- |
| void SerfSession::HandleError( boost::shared_ptr<SerfRequestProcessor> rReqProc ) |
| throw ( DAVException ) |
| { |
| m_aEnv = DAVRequestEnvironment(); |
| |
| if ( rReqProc->mpDAVException ) |
| { |
| DAVException* mpDAVExp( rReqProc->mpDAVException ); |
| |
| serf_connection_reset( getSerfConnection() ); |
| |
| if ( mpDAVExp->getStatus() == 413 && |
| m_bNoOfTransferEncodingSwitches < 2 ) |
| { |
| m_bUseChunkedEncoding = !m_bUseChunkedEncoding; |
| ++m_bNoOfTransferEncodingSwitches; |
| } |
| |
| throw DAVException( mpDAVExp->getError(), |
| mpDAVExp->getData(), |
| mpDAVExp->getStatus() ); |
| } |
| |
| /* |
| // Map error code to DAVException. |
| switch ( nError ) |
| { |
| case NE_OK: |
| return; |
| |
| case NE_ERROR: // Generic error |
| { |
| rtl::OUString aText = rtl::OUString::createFromAscii( |
| ne_get_error( m_pHttpSession ) ); |
| |
| sal_uInt16 code = makeStatusCode( aText ); |
| |
| if ( code == SC_LOCKED ) |
| { |
| if ( m_aSerfLockStore.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, |
| SerfUri::makeConnectionEndPointString( |
| m_aHostName, m_nPort ) ); |
| |
| case NE_AUTH: // User authentication failed on server |
| throw DAVException( DAVException::DAV_HTTP_AUTH, |
| SerfUri::makeConnectionEndPointString( |
| m_aHostName, m_nPort ) ); |
| |
| case NE_PROXYAUTH: // User authentication failed on proxy |
| throw DAVException( DAVException::DAV_HTTP_AUTHPROXY, |
| SerfUri::makeConnectionEndPointString( |
| m_aProxyName, m_nProxyPort ) ); |
| |
| case NE_CONNECT: // Could not connect to server |
| throw DAVException( DAVException::DAV_HTTP_CONNECT, |
| SerfUri::makeConnectionEndPointString( |
| m_aHostName, m_nPort ) ); |
| |
| case NE_TIMEOUT: // Connection timed out |
| throw DAVException( DAVException::DAV_HTTP_TIMEOUT, |
| SerfUri::makeConnectionEndPointString( |
| m_aHostName, m_nPort ) ); |
| |
| case NE_FAILED: // The precondition failed |
| throw DAVException( DAVException::DAV_HTTP_FAILED, |
| SerfUri::makeConnectionEndPointString( |
| m_aHostName, m_nPort ) ); |
| |
| case NE_RETRY: // Retry request (ne_end_request ONLY) |
| throw DAVException( DAVException::DAV_HTTP_RETRY, |
| SerfUri::makeConnectionEndPointString( |
| m_aHostName, m_nPort ) ); |
| |
| case NE_REDIRECT: |
| { |
| SerfUri aUri( ne_redirect_location( m_pHttpSession ) ); |
| throw DAVException( |
| DAVException::DAV_HTTP_REDIRECT, aUri.GetURI() ); |
| } |
| default: |
| { |
| OSL_TRACE( "SerfSession::HandleError : Unknown Serf error code!" ); |
| throw DAVException( DAVException::DAV_HTTP_ERROR, |
| rtl::OUString::createFromAscii( |
| ne_get_error( m_pHttpSession ) ) ); |
| } |
| } |
| */ |
| } |
| |
| // ------------------------------------------------------------------- |
| // static |
| bool |
| SerfSession::getDataFromInputStream( |
| const uno::Reference< io::XInputStream > & xStream, |
| uno::Sequence< sal_Int8 > & rData, |
| bool bAppendTrailingZeroByte ) |
| { |
| if ( xStream.is() ) |
| { |
| uno::Reference< io::XSeekable > xSeekable( xStream, uno::UNO_QUERY ); |
| if ( xSeekable.is() ) |
| { |
| try |
| { |
| sal_Int32 nSize |
| = sal::static_int_cast<sal_Int32>(xSeekable->getLength()); |
| sal_Int32 nRead |
| = xStream->readBytes( rData, nSize ); |
| |
| if ( nRead == nSize ) |
| { |
| if ( bAppendTrailingZeroByte ) |
| { |
| rData.realloc( nSize + 1 ); |
| rData[ nSize ] = sal_Int8( 0 ); |
| } |
| return true; |
| } |
| } |
| catch ( io::NotConnectedException const & ) |
| { |
| // readBytes |
| } |
| catch ( io::BufferSizeExceededException const & ) |
| { |
| // readBytes |
| } |
| catch ( io::IOException const & ) |
| { |
| // getLength, readBytes |
| } |
| } |
| else |
| { |
| try |
| { |
| uno::Sequence< sal_Int8 > aBuffer; |
| sal_Int32 nPos = 0; |
| |
| sal_Int32 nRead = xStream->readSomeBytes( aBuffer, 65536 ); |
| while ( nRead > 0 ) |
| { |
| if ( rData.getLength() < ( nPos + nRead ) ) |
| rData.realloc( nPos + nRead ); |
| |
| aBuffer.realloc( nRead ); |
| rtl_copyMemory( (void*)( rData.getArray() + nPos ), |
| (const void*)aBuffer.getConstArray(), |
| nRead ); |
| nPos += nRead; |
| |
| aBuffer.realloc( 0 ); |
| nRead = xStream->readSomeBytes( aBuffer, 65536 ); |
| } |
| |
| if ( bAppendTrailingZeroByte ) |
| { |
| rData.realloc( nPos + 1 ); |
| rData[ nPos ] = sal_Int8( 0 ); |
| } |
| return true; |
| } |
| catch ( io::NotConnectedException const & ) |
| { |
| // readBytes |
| } |
| catch ( io::BufferSizeExceededException const & ) |
| { |
| // readBytes |
| } |
| catch ( io::IOException const & ) |
| { |
| // readBytes |
| } |
| } |
| } |
| return false; |
| } |
| |
| // --------------------------------------------------------------------- |
| sal_Bool |
| SerfSession::isDomainMatch( rtl::OUString certHostName ) |
| { |
| rtl::OUString hostName = getHostName(); |
| |
| if (hostName.equalsIgnoreAsciiCase( certHostName ) ) |
| return sal_True; |
| |
| 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() ) ) |
| return sal_True; |
| } |
| return sal_False; |
| } |
| |
| /* |
| // --------------------------------------------------------------------- |
| rtl::OUString SerfSession::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() ); |
| SerfUri aSerfUri( &aUri ); |
| ne_uri_free( &aUri ); |
| return aSerfUri.GetURI(); |
| } |
| } |
| catch ( DAVException const & ) |
| { |
| } |
| // error. |
| return rtl::OUString(); |
| } |
| */ |