1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <vector>
21 #include <string.h>
22 #include <sal/log.hxx>
23 #include <comphelper/processfactory.hxx>
24 #include <comphelper/sequence.hxx>
25 #include <ucbhelper/simplecertificatevalidationrequest.hxx>
26 
27 #include "AprEnv.hxx"
28 #include <apr_strings.h>
29 
30 #include "DAVAuthListener.hxx"
31 #include "SerfSession.hxx"
32 #include "SerfUri.hxx"
33 #include "SerfRequestProcessor.hxx"
34 #include "SerfCallbacks.hxx"
35 #include "SerfInputStream.hxx"
36 
37 #include <com/sun/star/xml/crypto/SEInitializer.hpp>
38 #include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
39 #include <com/sun/star/security/XCertificate.hpp>
40 #include <com/sun/star/security/CertificateValidity.hpp>
41 #include <com/sun/star/security/CertificateContainerStatus.hpp>
42 #include <com/sun/star/security/CertificateContainer.hpp>
43 #include <com/sun/star/security/XCertificateContainer.hpp>
44 #include <com/sun/star/security/CertAltNameEntry.hpp>
45 #include <com/sun/star/security/XSanExtension.hpp>
46 #include <com/sun/star/io/NotConnectedException.hpp>
47 #include <com/sun/star/io/BufferSizeExceededException.hpp>
48 #include <com/sun/star/io/IOException.hpp>
49 #define OID_SUBJECT_ALTERNATIVE_NAME "2.5.29.17"
50 
51 #include <com/sun/star/ucb/Lock.hpp>
52 #include <com/sun/star/xml/crypto/XSEInitializer.hpp>
53 
54 using namespace com::sun::star;
55 using namespace http_dav_ucp;
56 
57 // Constructor
58 
SerfSession(const rtl::Reference<DAVSessionFactory> & rSessionFactory,const OUString & inUri,const ucbhelper::InternetProxyDecider & rProxyDecider)59 SerfSession::SerfSession(
60         const rtl::Reference< DAVSessionFactory > & rSessionFactory,
61         const OUString& inUri,
62         const ucbhelper::InternetProxyDecider & rProxyDecider )
63     : DAVSession( rSessionFactory )
64     , m_aMutex()
65     , m_aUri( inUri )
66     , m_aProxyName()
67     , m_nProxyPort( 0 )
68     , m_pSerfConnection( nullptr )
69     , m_pSerfContext( nullptr )
70     , m_bIsHeadRequestInProgress( false )
71     , m_bUseChunkedEncoding( false )
72     , m_bNoOfTransferEncodingSwitches( 0 )
73     , m_rProxyDecider( rProxyDecider )
74     , m_aEnv()
75 {
76     m_pSerfContext = serf_context_create( getAprPool() );
77 
78     m_pSerfBucket_Alloc = serf_bucket_allocator_create( getAprPool(), nullptr, nullptr );
79 }
80 
81 
82 // Destructor
83 
~SerfSession()84 SerfSession::~SerfSession( )
85 {
86     if ( m_pSerfConnection )
87     {
88         serf_connection_close( m_pSerfConnection );
89         m_pSerfConnection = nullptr;
90     }
91 }
92 
93 
Init(const DAVRequestEnvironment & rEnv)94 void SerfSession::Init( const DAVRequestEnvironment & rEnv )
95 {
96     osl::Guard< osl::Mutex > theGuard( m_aMutex );
97     m_aEnv = rEnv;
98     Init();
99 }
100 
101 
Init()102 void SerfSession::Init()
103 {
104     osl::Guard< osl::Mutex > theGuard( m_aMutex );
105 
106     bool bCreateNewSession = false;
107 
108     if ( m_pSerfConnection == nullptr )
109     {
110         const ucbhelper::InternetProxyServer & rProxyCfg = getProxySettings();
111 
112         m_aProxyName = rProxyCfg.aName;
113         m_nProxyPort = rProxyCfg.nPort;
114 
115         // Not yet initialized. Create new session.
116         bCreateNewSession = true;
117     }
118     else
119     {
120         const ucbhelper::InternetProxyServer & rProxyCfg = getProxySettings();
121 
122         if ( ( rProxyCfg.aName != m_aProxyName )
123              || ( rProxyCfg.nPort != m_nProxyPort ) )
124         {
125             m_aProxyName = rProxyCfg.aName;
126             m_nProxyPort = rProxyCfg.nPort;
127 
128             // new session needed, destroy old first
129             serf_connection_close( m_pSerfConnection );
130             m_pSerfConnection = nullptr;
131             bCreateNewSession = true;
132         }
133     }
134 
135     if ( bCreateNewSession )
136     {
137         // TODO - close_connection callback
138         apr_status_t status = serf_connection_create2( &m_pSerfConnection,
139                                                        m_pSerfContext,
140                                                        m_aUri.getAprUri(),
141                                                        Serf_ConnectSetup, this,
142                                                        nullptr /* close connection callback */, nullptr /* close connection baton */,
143                                                        getAprPool() );
144 
145         if ( m_pSerfConnection == nullptr ||status != APR_SUCCESS )
146         {
147             throw DAVException( DAVException::DAV_SESSION_CREATE,
148                                 SerfUri::makeConnectionEndPointString( m_aUri.GetHost(), m_aUri.GetPort() ) );
149         }
150 
151         // Register the session with the lock store
152 //        m_aSerfLockStore.registerSession( m_pSerfConnection );
153 
154         if ( m_aProxyName.getLength() )
155         {
156             apr_sockaddr_t *proxy_address = nullptr;
157             status = apr_sockaddr_info_get( &proxy_address,
158                                             OUStringToOString( m_aProxyName, RTL_TEXTENCODING_UTF8 ).getStr(),
159                                             APR_UNSPEC,
160                                             static_cast<apr_port_t>(m_nProxyPort),
161                                             0, getAprPool() );
162 
163             if ( status != APR_SUCCESS )
164             {
165                 throw DAVException( DAVException::DAV_SESSION_CREATE,
166                                     SerfUri::makeConnectionEndPointString( m_aUri.GetHost(), m_aUri.GetPort() ) );
167             }
168 
169             serf_config_proxy( m_pSerfContext, proxy_address );
170         }
171 
172 
173         serf_config_credentials_callback( m_pSerfContext, Serf_Credentials );
174 
175         m_bUseChunkedEncoding = isSSLNeeded();
176     }
177 }
178 
getAprPool()179 apr_pool_t* SerfSession::getAprPool()
180 {
181     return apr_environment::AprEnv::getAprEnv()->getAprPool();
182 }
183 
getSerfBktAlloc()184 serf_bucket_alloc_t* SerfSession::getSerfBktAlloc()
185 {
186     return m_pSerfBucket_Alloc;
187 }
188 
getSerfContext()189 serf_context_t* SerfSession::getSerfContext()
190 {
191     return m_pSerfContext;
192 }
193 
getSerfConnection()194 serf_connection_t* SerfSession::getSerfConnection()
195 {
196     return m_pSerfConnection;
197 }
198 
isHeadRequestInProgress()199 bool SerfSession::isHeadRequestInProgress()
200 {
201     return m_bIsHeadRequestInProgress;
202 }
203 
isSSLNeeded()204 bool SerfSession::isSSLNeeded()
205 {
206     return m_aUri.GetScheme().equalsIgnoreAsciiCase( "https" );
207 }
208 
getHostinfo()209 char* SerfSession::getHostinfo()
210 {
211     return m_aUri.getAprUri().hostinfo;
212 }
213 
214 
215 // virtual
CanUse(const OUString & inUri)216 bool SerfSession::CanUse( const OUString & inUri )
217 {
218     try
219     {
220         SerfUri theUri( inUri );
221         if ( ( theUri.GetPort() == m_aUri.GetPort() ) &&
222              ( theUri.GetHost() == m_aUri.GetHost() ) &&
223              ( theUri.GetScheme() == m_aUri.GetScheme() ) )
224         {
225             return true;
226         }
227     }
228     catch ( DAVException const & )
229     {
230         return false;
231     }
232     return false;
233 }
234 
235 
236 // virtual
UsesProxy()237 bool SerfSession::UsesProxy()
238 {
239     Init();
240     return ( m_aProxyName.getLength() > 0 );
241 }
242 
setupSerfConnection(apr_socket_t * inAprSocket,serf_bucket_t ** outSerfInputBucket,serf_bucket_t ** outSerfOutputBucket,apr_pool_t *)243 apr_status_t SerfSession::setupSerfConnection( apr_socket_t * inAprSocket,
244                                                serf_bucket_t **outSerfInputBucket,
245                                                serf_bucket_t **outSerfOutputBucket,
246                                                apr_pool_t* /*inAprPool*/ )
247 {
248     serf_bucket_t *tmpInputBkt;
249     tmpInputBkt = serf_context_bucket_socket_create( getSerfContext(),
250                                                      inAprSocket,
251                                                      getSerfBktAlloc() );
252 
253     if ( isSSLNeeded() )
254     {
255         tmpInputBkt = serf_bucket_ssl_decrypt_create( tmpInputBkt,
256                                                       nullptr,
257                                                       getSerfBktAlloc() );
258         /** Set the callback that is called to authenticate the
259             certificate (chain).
260         */
261         serf_ssl_server_cert_chain_callback_set(
262             serf_bucket_ssl_decrypt_context_get(tmpInputBkt),
263             nullptr,
264             Serf_CertificateChainValidation,
265             this);
266         serf_ssl_set_hostname( serf_bucket_ssl_decrypt_context_get( tmpInputBkt ),
267                                getHostinfo() );
268 
269         *outSerfOutputBucket = serf_bucket_ssl_encrypt_create( *outSerfOutputBucket,
270                                                                serf_bucket_ssl_decrypt_context_get( tmpInputBkt ),
271                                                                getSerfBktAlloc() );
272     }
273 
274     *outSerfInputBucket = tmpInputBkt;
275 
276     return APR_SUCCESS;
277 }
278 
provideSerfCredentials(bool bGiveProvidedCredentialsASecondTry,char ** outUsername,char ** outPassword,serf_request_t *,int,const char * inAuthProtocol,const char * inRealm,apr_pool_t * inAprPool)279 apr_status_t SerfSession::provideSerfCredentials( bool bGiveProvidedCredentialsASecondTry,
280                                                   char ** outUsername,
281                                                   char ** outPassword,
282                                                   serf_request_t * /*inRequest*/,
283                                                   int /*inCode*/,
284                                                   const char *inAuthProtocol,
285                                                   const char *inRealm,
286                                                   apr_pool_t *inAprPool )
287 {
288     DAVAuthListener * pListener = getRequestEnvironment().m_xAuthListener.get();
289     if ( !pListener )
290     {
291         // abort
292         return SERF_ERROR_AUTHN_FAILED;
293     }
294 
295     OUString theUserName;
296     OUString thePassWord;
297     try
298     {
299         SerfUri uri( getRequestEnvironment().m_aRequestURI );
300         OUString aUserInfo( uri.GetUserInfo() );
301         if ( aUserInfo.getLength() )
302         {
303             sal_Int32 nPos = aUserInfo.indexOf( '@' );
304             if ( nPos == -1 )
305             {
306                 theUserName = aUserInfo;
307             }
308             else
309             {
310                 theUserName = aUserInfo.copy( 0, nPos );
311                 thePassWord = aUserInfo.copy( nPos + 1 );
312             }
313         }
314     }
315     catch ( DAVException const & )
316     {
317         // abort
318         return SERF_ERROR_AUTHN_FAILED;
319     }
320 
321     const bool bCanUseSystemCreds = ( ( strcasecmp( inAuthProtocol, "NTLM" ) == 0 ) ||
322                                       ( strcasecmp( inAuthProtocol, "Negotiate" ) == 0 ) );
323 
324     int theRetVal = pListener->authenticate( OUString::createFromAscii( inRealm ),
325                                              getHostName(),
326                                              theUserName,
327                                              thePassWord,
328                                              bCanUseSystemCreds,
329                                              bGiveProvidedCredentialsASecondTry );
330 
331     if ( theRetVal == 0 )
332     {
333         *outUsername = apr_pstrdup( inAprPool, OUStringToOString( theUserName, RTL_TEXTENCODING_UTF8 ).getStr() );
334         *outPassword = apr_pstrdup( inAprPool, OUStringToOString( thePassWord, RTL_TEXTENCODING_UTF8 ).getStr() );
335     }
336 
337     return theRetVal != 0 ? SERF_ERROR_AUTHN_FAILED : APR_SUCCESS;
338 }
339 
verifySerfCertificateChain(int,const serf_ssl_certificate_t * const * pCertificateChainBase64Encoded,int nCertificateChainLength)340 apr_status_t SerfSession::verifySerfCertificateChain (
341     int,
342     const serf_ssl_certificate_t * const * pCertificateChainBase64Encoded,
343     int nCertificateChainLength)
344 {
345     // Check arguments.
346     if (pCertificateChainBase64Encoded == nullptr || nCertificateChainLength<=0)
347     {
348         assert(pCertificateChainBase64Encoded != nullptr);
349         assert(nCertificateChainLength>0);
350         return SERF_SSL_CERT_UNKNOWN_FAILURE;
351     }
352 
353     // When called from SerfLockStore::~SerfLockStore(),
354     // css::xml::crypto::SEInitializer::create() will fail
355     // but we want to send unlock commands anyway,
356     // so just ignore certificates and return here.
357     if (apr_environment::AprEnv::getAprEnv()->getSerfLockStore()->finishing())
358         return APR_SUCCESS;
359 
360     // Create some crypto objects to decode and handle the base64
361     // encoded certificate chain.
362     uno::Reference< security::XCertificateContainer > xCertificateContainer;
363     uno::Reference< xml::crypto::XXMLSecurityContext > xSecurityContext;
364     uno::Reference< xml::crypto::XSecurityEnvironment > xSecurityEnv;
365     try
366     {
367         css::uno::Reference< css::uno::XComponentContext > xContext =
368             ::comphelper::getProcessComponentContext();
369         // Create a certificate container.
370         xCertificateContainer = security::CertificateContainer::create( xContext );
371 
372         css::uno::Reference< css::xml::crypto::XSEInitializer > xSEInitializer =
373             css::xml::crypto::SEInitializer::create( xContext );
374 
375         xSecurityContext = xSEInitializer->createSecurityContext( OUString() );
376         if (xSecurityContext.is())
377             xSecurityEnv = xSecurityContext->getSecurityEnvironment();
378 
379         if ( ! xSecurityContext.is() || ! xSecurityEnv.is())
380         {
381             // Do we have to dispose xSEInitializer or xCertificateContainer?
382             return SERF_SSL_CERT_UNKNOWN_FAILURE;
383         }
384     }
385     catch ( uno::Exception const &)
386     {
387         return SERF_SSL_CERT_UNKNOWN_FAILURE;
388     }
389 
390     // Decode the server certificate.
391     const char* sBase64EncodedServerCertificate (
392         serf_ssl_cert_export(
393             pCertificateChainBase64Encoded[0],
394             getAprPool()));
395     uno::Reference< security::XCertificate > xServerCertificate(
396         xSecurityEnv->createCertificateFromAscii(
397             OUString::createFromAscii(sBase64EncodedServerCertificate)));
398     if ( ! xServerCertificate.is())
399         return SERF_SSL_CERT_UNKNOWN_FAILURE;
400 
401     // Get the subject from the server certificate.
402     OUString sServerCertificateSubject (xServerCertificate->getSubjectName());
403     sal_Int32 nIndex = 0;
404     while (nIndex >= 0)
405     {
406         const OUString sToken (sServerCertificateSubject.getToken(0, ',', nIndex));
407         if (sToken.startsWith("CN="))
408         {
409             sServerCertificateSubject = sToken.copy(3);
410             break;
411         }
412         else if (sToken.startsWith(" CN="))
413         {
414             sServerCertificateSubject = sToken.copy(4);
415             break;
416         }
417     }
418 
419     // When the certificate container already contains a (trusted)
420     // entry for the server then we do not have to authenticate any
421     // certificate.
422     const security::CertificateContainerStatus eStatus (
423         xCertificateContainer->hasCertificate(
424             getHostName(), sServerCertificateSubject ) );
425     if (eStatus != security::CertificateContainerStatus_NOCERT)
426     {
427         return eStatus == security::CertificateContainerStatus_TRUSTED
428                ? APR_SUCCESS
429                : SERF_SSL_CERT_UNKNOWN_FAILURE;
430     }
431 
432     // The shortcut failed, so try to verify the whole chain.  This is
433     // done outside the isDomainMatch() block because the result is
434     // used by the interaction handler.
435     std::vector< uno::Reference< security::XCertificate > > aChain;
436     for (nIndex = 1; nIndex < nCertificateChainLength; ++nIndex)
437     {
438         const char* sBase64EncodedCertificate (
439             serf_ssl_cert_export(
440                 pCertificateChainBase64Encoded[nIndex],
441                 getAprPool()));
442         uno::Reference< security::XCertificate > xCertificate(
443             xSecurityEnv->createCertificateFromAscii(
444                 OUString::createFromAscii(sBase64EncodedCertificate)));
445         if ( ! xCertificate.is())
446             return SERF_SSL_CERT_UNKNOWN_FAILURE;
447         aChain.push_back(xCertificate);
448     }
449     const sal_Int64 nVerificationResult (xSecurityEnv->verifyCertificate(
450             xServerCertificate,
451             ::comphelper::containerToSequence(aChain)));
452 
453     // When the certificate matches the host name then we can use the
454     // result of the verification.
455     bool bHostnameMatchesCertHostnames = false;
456     {
457         uno::Sequence< uno::Reference< security::XCertificateExtension > > extensions = xServerCertificate->getExtensions();
458         uno::Sequence< security::CertAltNameEntry > altNames;
459         for (sal_Int32 i = 0 ; i < extensions.getLength(); ++i)
460         {
461             uno::Reference< security::XCertificateExtension >element = extensions[i];
462 
463             const OString aId ( reinterpret_cast<const char *>(const_cast<const signed char *>(element->getExtensionId().getArray())), element->getExtensionId().getLength());
464             if ( aId.equals( OID_SUBJECT_ALTERNATIVE_NAME ) )
465             {
466                 uno::Reference< security::XSanExtension > sanExtension ( element, uno::UNO_QUERY );
467                 altNames =  sanExtension->getAlternativeNames();
468                 break;
469             }
470         }
471 
472         uno::Sequence< OUString > certHostNames(altNames.getLength() + 1);
473         certHostNames[0] = sServerCertificateSubject;
474         for( int n = 0; n < altNames.getLength(); ++n )
475         {
476             if (altNames[n].Type ==  security::ExtAltNameType_DNS_NAME)
477             {
478                 altNames[n].Value >>= certHostNames[n+1];
479             }
480         }
481 
482         for ( int i = 0; i < certHostNames.getLength() && !bHostnameMatchesCertHostnames; ++i )
483         {
484             bHostnameMatchesCertHostnames = isDomainMatch( certHostNames[i] );
485         }
486 
487     }
488     if ( bHostnameMatchesCertHostnames )
489     {
490 
491         if (nVerificationResult == 0)
492         {
493             // Certificate (chain) is valid.
494             xCertificateContainer->addCertificate(getHostName(), sServerCertificateSubject,  true);
495             return APR_SUCCESS;
496         }
497         else if ((nVerificationResult & security::CertificateValidity::CHAIN_INCOMPLETE) != 0)
498         {
499             // We do not have enough information for verification,
500             // neither automatically (as we just discovered) nor
501             // manually (so there is no point in showing any dialog.)
502             return SERF_SSL_CERT_UNKNOWN_FAILURE;
503         }
504         else if ((nVerificationResult &
505                 (security::CertificateValidity::INVALID | security::CertificateValidity::REVOKED)) != 0)
506         {
507             // Certificate (chain) is invalid.
508             xCertificateContainer->addCertificate(getHostName(), sServerCertificateSubject,  false);
509             return SERF_SSL_CERT_UNKNOWN_FAILURE;
510         }
511         else
512         {
513             // For all other we have to ask the user.
514         }
515     }
516 
517     // We have not been able to automatically verify (or falsify) the
518     // certificate chain.  To resolve this we have to ask the user.
519     const uno::Reference< ucb::XCommandEnvironment > xEnv( getRequestEnvironment().m_xEnv );
520     if ( xEnv.is() )
521     {
522         uno::Reference< task::XInteractionHandler > xIH( xEnv->getInteractionHandler() );
523         if ( xIH.is() )
524         {
525             rtl::Reference< ucbhelper::SimpleCertificateValidationRequest >
526                 xRequest( new ucbhelper::SimpleCertificateValidationRequest(
527                         static_cast<sal_Int32>(nVerificationResult), xServerCertificate, getHostName() ) );
528             xIH->handle( xRequest.get() );
529 
530             rtl::Reference< ucbhelper::InteractionContinuation > xSelection
531                 = xRequest->getSelection();
532 
533             if ( xSelection.is() )
534             {
535                 uno::Reference< task::XInteractionApprove > xApprove( xSelection.get(), uno::UNO_QUERY );
536                 if ( xApprove.is() )
537                 {
538                     xCertificateContainer->addCertificate( getHostName(), sServerCertificateSubject,  true );
539                     return APR_SUCCESS;
540                 }
541                 else
542                 {
543                     // Don't trust cert
544                     xCertificateContainer->addCertificate( getHostName(), sServerCertificateSubject, false );
545                     return SERF_SSL_CERT_UNKNOWN_FAILURE;
546                 }
547             }
548         }
549         else
550         {
551             // Don't trust cert
552             xCertificateContainer->addCertificate( getHostName(), sServerCertificateSubject, false );
553             return SERF_SSL_CERT_UNKNOWN_FAILURE;
554         }
555     }
556 
557     return SERF_SSL_CERT_UNKNOWN_FAILURE;
558 }
559 
acceptSerfResponse(serf_request_t * inSerfRequest,serf_bucket_t * inSerfStreamBucket,apr_pool_t *)560 serf_bucket_t* SerfSession::acceptSerfResponse( serf_request_t * inSerfRequest,
561                                                 serf_bucket_t * inSerfStreamBucket,
562                                                 apr_pool_t* /*inAprPool*/ )
563 {
564     // get the per-request bucket allocator
565     serf_bucket_alloc_t* SerfBktAlloc = serf_request_get_alloc( inSerfRequest );
566 
567     // create a barrier bucket so the response doesn't eat us!
568     serf_bucket_t *responseBkt = serf_bucket_barrier_create( inSerfStreamBucket,
569                                                              SerfBktAlloc );
570 
571     // create response bucket
572     responseBkt = serf_bucket_response_create( responseBkt,
573                                                SerfBktAlloc );
574 
575     if ( isHeadRequestInProgress() )
576     {
577         // advise the response bucket that this was from a HEAD request and that it should not expect to see a response body.
578         serf_bucket_response_set_head( responseBkt );
579     }
580 
581     return responseBkt;
582 }
583 
createReqProc(const OUString & inPath)584 SerfRequestProcessor* SerfSession::createReqProc( const OUString & inPath )
585 {
586     return new SerfRequestProcessor( *this,
587                                      inPath,
588                                      m_bUseChunkedEncoding );
589 }
590 
591 
592 // PROPFIND - allprop & named
593 
PROPFIND(const OUString & inPath,const Depth inDepth,const std::vector<OUString> & inPropNames,std::vector<DAVResource> & ioResources,const DAVRequestEnvironment & rEnv)594 void SerfSession::PROPFIND( const OUString & inPath,
595                             const Depth inDepth,
596                             const std::vector< OUString > & inPropNames,
597                             std::vector< DAVResource > & ioResources,
598                             const DAVRequestEnvironment & rEnv )
599 {
600     osl::Guard< osl::Mutex > theGuard( m_aMutex );
601 
602     Init( rEnv );
603 
604     apr_status_t status = APR_SUCCESS;
605     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) );
606     aReqProc->processPropFind( inDepth,
607                                inPropNames,
608                                ioResources,
609                                status );
610 
611     if ( status == APR_SUCCESS &&
612          aReqProc->mpDAVException == nullptr &&
613          ioResources.empty() )
614     {
615         m_aEnv = DAVRequestEnvironment();
616         throw DAVException( DAVException::DAV_HTTP_ERROR, inPath, APR_EGENERAL );
617     }
618     HandleError( aReqProc );
619 }
620 
621 
622 // PROPFIND - propnames
623 
PROPFIND(const OUString & inPath,const Depth inDepth,std::vector<DAVResourceInfo> & ioResInfo,const DAVRequestEnvironment & rEnv)624 void SerfSession::PROPFIND( const OUString & inPath,
625                             const Depth inDepth,
626                             std::vector< DAVResourceInfo > & ioResInfo,
627                             const DAVRequestEnvironment & rEnv )
628 {
629     osl::Guard< osl::Mutex > theGuard( m_aMutex );
630 
631     Init( rEnv );
632 
633     apr_status_t status = APR_SUCCESS;
634     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) );
635     aReqProc->processPropFind( inDepth,
636                                ioResInfo,
637                                status );
638 
639     if ( status == APR_SUCCESS &&
640          aReqProc->mpDAVException == nullptr &&
641          ioResInfo.empty() )
642     {
643         m_aEnv = DAVRequestEnvironment();
644         throw DAVException( DAVException::DAV_HTTP_ERROR, inPath, APR_EGENERAL );
645     }
646     HandleError( aReqProc );
647 }
648 
649 
650 // PROPPATCH
651 
PROPPATCH(const OUString & inPath,const std::vector<ProppatchValue> & inValues,const DAVRequestEnvironment & rEnv)652 void SerfSession::PROPPATCH( const OUString & inPath,
653                              const std::vector< ProppatchValue > & inValues,
654                              const DAVRequestEnvironment & rEnv )
655 {
656     osl::Guard< osl::Mutex > theGuard( m_aMutex );
657 
658     Init( rEnv );
659 
660     apr_status_t status = APR_SUCCESS;
661     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) );
662     aReqProc->processPropPatch( inValues,
663                                 status );
664 
665     HandleError( aReqProc );
666 }
667 
668 
669 // HEAD
670 
HEAD(const OUString & inPath,const std::vector<OUString> & inHeaderNames,DAVResource & ioResource,const DAVRequestEnvironment & rEnv)671 void SerfSession::HEAD( const OUString & inPath,
672                         const std::vector< OUString > & inHeaderNames,
673                         DAVResource & ioResource,
674                         const DAVRequestEnvironment & rEnv )
675 {
676     osl::Guard< osl::Mutex > theGuard( m_aMutex );
677 
678     Init( rEnv );
679 
680     m_bIsHeadRequestInProgress = true;
681 
682     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) );
683     ioResource.uri = inPath;
684     ioResource.properties.clear();
685     apr_status_t status = APR_SUCCESS;
686     aReqProc->processHead( inHeaderNames,
687                            ioResource,
688                            status );
689 
690     m_bIsHeadRequestInProgress = false;
691 
692     HandleError( aReqProc );
693 }
694 
695 
696 // GET
697 
698 uno::Reference< io::XInputStream >
GET(const OUString & inPath,const DAVRequestEnvironment & rEnv)699 SerfSession::GET( const OUString & inPath,
700                   const DAVRequestEnvironment & rEnv )
701 {
702     osl::Guard< osl::Mutex > theGuard( m_aMutex );
703 
704     Init( rEnv );
705 
706     rtl::Reference< SerfInputStream > xInputStream( new SerfInputStream );
707     apr_status_t status = APR_SUCCESS;
708     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) );
709     aReqProc->processGet( xInputStream,
710                           status );
711 
712     HandleError( aReqProc );
713 
714     return uno::Reference< io::XInputStream >( xInputStream.get() );
715 }
716 
717 
718 // GET
719 
GET(const OUString & inPath,uno::Reference<io::XOutputStream> & ioOutputStream,const DAVRequestEnvironment & rEnv)720 void SerfSession::GET( const OUString & inPath,
721                        uno::Reference< io::XOutputStream > & ioOutputStream,
722                        const DAVRequestEnvironment & rEnv )
723 {
724     osl::Guard< osl::Mutex > theGuard( m_aMutex );
725 
726     Init( rEnv );
727 
728     apr_status_t status = APR_SUCCESS;
729     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) );
730     aReqProc->processGet( ioOutputStream,
731                           status );
732 
733     HandleError( aReqProc );
734 }
735 
736 
737 // GET
738 
739 uno::Reference< io::XInputStream >
GET(const OUString & inPath,const std::vector<OUString> & inHeaderNames,DAVResource & ioResource,const DAVRequestEnvironment & rEnv)740 SerfSession::GET( const OUString & inPath,
741                   const std::vector< OUString > & inHeaderNames,
742                   DAVResource & ioResource,
743                   const DAVRequestEnvironment & rEnv )
744 {
745     osl::Guard< osl::Mutex > theGuard( m_aMutex );
746 
747     Init( rEnv );
748 
749     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) );
750     rtl::Reference< SerfInputStream > xInputStream( new SerfInputStream );
751     ioResource.uri = inPath;
752     ioResource.properties.clear();
753     apr_status_t status = APR_SUCCESS;
754     aReqProc->processGet( xInputStream,
755                           inHeaderNames,
756                           ioResource,
757                           status );
758 
759     HandleError( aReqProc );
760 
761     return uno::Reference< io::XInputStream >( xInputStream.get() );
762 }
763 
764 
765 // GET
766 
GET(const OUString & inPath,uno::Reference<io::XOutputStream> & ioOutputStream,const std::vector<OUString> & inHeaderNames,DAVResource & ioResource,const DAVRequestEnvironment & rEnv)767 void SerfSession::GET( const OUString & inPath,
768                        uno::Reference< io::XOutputStream > & ioOutputStream,
769                        const std::vector< OUString > & inHeaderNames,
770                        DAVResource & ioResource,
771                        const DAVRequestEnvironment & rEnv )
772 {
773     osl::Guard< osl::Mutex > theGuard( m_aMutex );
774 
775     Init( rEnv );
776 
777     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) );
778     ioResource.uri = inPath;
779     ioResource.properties.clear();
780     apr_status_t status = APR_SUCCESS;
781     aReqProc->processGet( ioOutputStream,
782                           inHeaderNames,
783                           ioResource,
784                           status );
785 
786     HandleError( aReqProc );
787 }
788 
789 
790 // PUT
791 
PUT(const OUString & inPath,const uno::Reference<io::XInputStream> & inInputStream,const DAVRequestEnvironment & rEnv)792 void SerfSession::PUT( const OUString & inPath,
793                        const uno::Reference< io::XInputStream > & inInputStream,
794                        const DAVRequestEnvironment & rEnv )
795 {
796     osl::Guard< osl::Mutex > theGuard( m_aMutex );
797 
798     Init( rEnv );
799 
800     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) );
801     uno::Sequence< sal_Int8 > aDataToSend;
802     if ( !getDataFromInputStream( inInputStream, aDataToSend, false ) )
803         throw DAVException( DAVException::DAV_INVALID_ARG );
804     apr_status_t status = APR_SUCCESS;
805     aReqProc->processPut( reinterpret_cast< const char * >( aDataToSend.getConstArray() ),
806                           aDataToSend.getLength(),
807                           status );
808 
809     HandleError( aReqProc );
810 }
811 
812 
813 // POST
814 
815 uno::Reference< io::XInputStream >
POST(const OUString & inPath,const OUString & rContentType,const OUString & rReferer,const uno::Reference<io::XInputStream> & inInputStream,const DAVRequestEnvironment & rEnv)816 SerfSession::POST( const OUString & inPath,
817                    const OUString & rContentType,
818                    const OUString & rReferer,
819                    const uno::Reference< io::XInputStream > & inInputStream,
820                    const DAVRequestEnvironment & rEnv )
821 {
822     osl::Guard< osl::Mutex > theGuard( m_aMutex );
823 
824     uno::Sequence< sal_Int8 > aDataToSend;
825     if ( !getDataFromInputStream( inInputStream, aDataToSend, true ) )
826     {
827         throw DAVException( DAVException::DAV_INVALID_ARG );
828     }
829 
830     Init( rEnv );
831 
832     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) );
833     rtl::Reference< SerfInputStream > xInputStream( new SerfInputStream );
834     apr_status_t status = APR_SUCCESS;
835     aReqProc->processPost( reinterpret_cast< const char * >( aDataToSend.getConstArray() ),
836                            aDataToSend.getLength(),
837                            rContentType,
838                            rReferer,
839                            xInputStream,
840                            status );
841 
842     HandleError( aReqProc );
843     return uno::Reference< io::XInputStream >( xInputStream.get() );
844 }
845 
846 
847 // POST
848 
POST(const OUString & inPath,const OUString & rContentType,const OUString & rReferer,const uno::Reference<io::XInputStream> & inInputStream,uno::Reference<io::XOutputStream> & oOutputStream,const DAVRequestEnvironment & rEnv)849 void SerfSession::POST( const OUString & inPath,
850                         const OUString & rContentType,
851                         const OUString & rReferer,
852                         const uno::Reference< io::XInputStream > & inInputStream,
853                         uno::Reference< io::XOutputStream > & oOutputStream,
854                         const DAVRequestEnvironment & rEnv )
855 {
856     osl::Guard< osl::Mutex > theGuard( m_aMutex );
857 
858     uno::Sequence< sal_Int8 > aDataToSend;
859     if ( !getDataFromInputStream( inInputStream, aDataToSend, true ) )
860     {
861         throw DAVException( DAVException::DAV_INVALID_ARG );
862     }
863 
864     Init( rEnv );
865 
866     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) );
867     apr_status_t status = APR_SUCCESS;
868     aReqProc->processPost( reinterpret_cast< const char * >( aDataToSend.getConstArray() ),
869                            aDataToSend.getLength(),
870                            rContentType,
871                            rReferer,
872                            oOutputStream,
873                            status );
874 
875     HandleError( aReqProc );
876 }
877 
878 
879 // MKCOL
880 
MKCOL(const OUString & inPath,const DAVRequestEnvironment & rEnv)881 void SerfSession::MKCOL( const OUString & inPath,
882                          const DAVRequestEnvironment & rEnv )
883 {
884     osl::Guard< osl::Mutex > theGuard( m_aMutex );
885 
886     Init( rEnv );
887 
888     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) );
889     apr_status_t status = APR_SUCCESS;
890     aReqProc->processMkCol( status );
891 
892     HandleError( aReqProc );
893 }
894 
895 
896 // COPY
897 
COPY(const OUString & inSourceURL,const OUString & inDestinationURL,const DAVRequestEnvironment & rEnv,bool inOverWrite)898 void SerfSession::COPY( const OUString & inSourceURL,
899                         const OUString & inDestinationURL,
900                         const DAVRequestEnvironment & rEnv,
901                         bool inOverWrite )
902 {
903     osl::Guard< osl::Mutex > theGuard( m_aMutex );
904 
905     Init( rEnv );
906 
907     SerfUri theSourceUri( inSourceURL );
908     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( theSourceUri.GetPath() ) );
909     apr_status_t status = APR_SUCCESS;
910     aReqProc->processCopy( inDestinationURL, inOverWrite, status );
911 
912     HandleError( aReqProc );
913 }
914 
915 
916 // MOVE
917 
MOVE(const OUString & inSourceURL,const OUString & inDestinationURL,const DAVRequestEnvironment & rEnv,bool inOverWrite)918 void SerfSession::MOVE( const OUString & inSourceURL,
919                         const OUString & inDestinationURL,
920                         const DAVRequestEnvironment & rEnv,
921                         bool inOverWrite )
922 {
923     osl::Guard< osl::Mutex > theGuard( m_aMutex );
924 
925     Init( rEnv );
926 
927     SerfUri theSourceUri( inSourceURL );
928     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( theSourceUri.GetPath() ) );
929     apr_status_t status = APR_SUCCESS;
930     aReqProc->processMove( inDestinationURL, inOverWrite, status );
931 
932     HandleError( aReqProc );
933 }
934 
935 
936 // DESTROY
937 
DESTROY(const OUString & inPath,const DAVRequestEnvironment & rEnv)938 void SerfSession::DESTROY( const OUString & inPath,
939                            const DAVRequestEnvironment & rEnv )
940 {
941     osl::Guard< osl::Mutex > theGuard( m_aMutex );
942 
943     Init( rEnv );
944 
945     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) );
946     apr_status_t status = APR_SUCCESS;
947     aReqProc->processDelete( status );
948 
949     HandleError( aReqProc );
950 }
951 
952 
953 /*
954 namespace
955 {
956     sal_Int32 lastChanceToSendRefreshRequest( TimeValue const & rStart,
957                                               int timeout )
958     {
959         TimeValue aEnd;
960         osl_getSystemTime( &aEnd );
961 
962         // Try to estimate a safe absolute time for sending the
963         // lock refresh request.
964         sal_Int32 lastChanceToSendRefreshRequest = -1;
965         if ( timeout != NE_TIMEOUT_INFINITE )
966         {
967             sal_Int32 calltime = aEnd.Seconds - rStart.Seconds;
968             if ( calltime <= timeout )
969             {
970                 lastChanceToSendRefreshRequest
971                     = aEnd.Seconds + timeout - calltime;
972             }
973             else
974             {
975                 SAL_INFO("ucb.ucp.webdav",  "No chance to refresh lock before timeout!" );
976             }
977         }
978         return lastChanceToSendRefreshRequest;
979     }
980 
981 } // namespace
982 */
983 
984 // LOCK (set new lock)
985 
LOCK(const OUString & inPath,ucb::Lock & rLock,const DAVRequestEnvironment & rEnv)986 void SerfSession::LOCK( const OUString & inPath,
987                         ucb::Lock & rLock,
988                         const DAVRequestEnvironment & rEnv )
989 {
990     osl::Guard< osl::Mutex > theGuard( m_aMutex );
991 
992     Init( rEnv );
993 
994     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) );
995     aReqProc->processLock( rLock );
996 
997     HandleError( aReqProc );
998 }
999 
1000 
1001 // LOCK (refresh existing lock)
1002 
LOCK(const OUString &,sal_Int64 nTimeout,const DAVRequestEnvironment &)1003 sal_Int64 SerfSession::LOCK( const OUString & /*inPath*/,
1004                              sal_Int64 nTimeout,
1005                              const DAVRequestEnvironment & /*rEnv*/ )
1006 {
1007     osl::Guard< osl::Mutex > theGuard( m_aMutex );
1008 
1009     return nTimeout;
1010     /*
1011     // Try to get the neon lock from lock store
1012     SerfLock * theLock
1013         = m_aSerfLockStore.findByUri( makeAbsoluteURL( inPath ) );
1014     if ( !theLock )
1015          throw DAVException( DAVException::DAV_NOT_LOCKED );
1016 
1017     Init( rEnv );
1018 
1019     // refresh existing lock.
1020     theLock->timeout = static_cast< long >( nTimeout );
1021 
1022     TimeValue startCall;
1023     osl_getSystemTime( &startCall );
1024 
1025     int theRetVal = ne_lock_refresh( m_pHttpSession, theLock );
1026 
1027     if ( theRetVal == NE_OK )
1028     {
1029         m_aSerfLockStore.updateLock( theLock,
1030                                      lastChanceToSendRefreshRequest(
1031                                          startCall, theLock->timeout ) );
1032     }
1033 
1034     HandleError( theRetVal, inPath, rEnv );
1035 
1036     return theLock->timeout;
1037     */
1038 }
1039 
1040 
1041 // LOCK (refresh existing lock)
1042 
LOCK(const OUString & rLock,sal_Int32 * plastChanceToSendRefreshRequest)1043 bool SerfSession::LOCK( const OUString& rLock,
1044                         sal_Int32 *plastChanceToSendRefreshRequest )
1045 {
1046     osl::Guard< osl::Mutex > theGuard( m_aMutex );
1047 
1048     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( rLock ) );
1049     aReqProc->processLock( ucb::Lock(), plastChanceToSendRefreshRequest );
1050 
1051     try
1052     {
1053         HandleError( aReqProc );
1054         SAL_INFO("ucb.ucp.webdav",  "Refreshing LOCK of " << rLock << " succeeded." );
1055         return true;
1056     }
1057     catch(...)
1058     {
1059         SAL_INFO("ucb.ucp.webdav",  "Refreshing LOCK of " << rLock << " failed!" );
1060         return false;
1061     }
1062 }
1063 
1064 
1065 // UNLOCK
1066 
UNLOCK(const OUString & inPath,const DAVRequestEnvironment & rEnv)1067 void SerfSession::UNLOCK( const OUString & inPath,
1068                           const DAVRequestEnvironment & rEnv )
1069 {
1070     osl::Guard< osl::Mutex > theGuard( m_aMutex );
1071 
1072     Init( rEnv );
1073 
1074     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) );
1075     aReqProc->processUnlock();
1076 
1077     try
1078     {
1079         HandleError( aReqProc );
1080         SAL_INFO("ucb.ucp.webdav",  "UNLOCK of " << inPath << " succeeded." );
1081         apr_environment::AprEnv::getAprEnv()->getSerfLockStore()->removeLock( inPath );
1082     }
1083     catch(...)
1084     {
1085         SAL_INFO("ucb.ucp.webdav",  "UNLOCK of " << inPath << " failed!" );
1086     }
1087 }
1088 
1089 
1090 // UNLOCK
1091 
UNLOCK(const OUString & rLock)1092 void SerfSession::UNLOCK( const OUString& rLock )
1093 {
1094     osl::Guard< osl::Mutex > theGuard( m_aMutex );
1095 
1096     std::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( rLock ) );
1097     aReqProc->processUnlock();
1098 
1099     try
1100     {
1101         HandleError( aReqProc );
1102         SAL_INFO("ucb.ucp.webdav",  "UNLOCK of " << rLock << " succeeded." );
1103     }
1104     catch(...)
1105     {
1106         SAL_INFO("ucb.ucp.webdav",  "UNLOCK of " << rLock << " failed!" );
1107     }
1108 }
1109 
1110 
abort()1111 void SerfSession::abort()
1112 {
1113     // 11.11.09 (tkr): The following code lines causing crashes if
1114     // closing a ongoing connection. It turned out that this existing
1115     // solution doesn't work in multi-threading environments.
1116     // So I disabled them in 3.2. . Issue #73893# should fix it in OOo 3.3.
1117     //if ( m_pHttpSession )
1118     //    ne_close_connection( m_pHttpSession );
1119 }
1120 
1121 
getProxySettings() const1122 ucbhelper::InternetProxyServer SerfSession::getProxySettings() const
1123 {
1124     if ( m_aUri.GetScheme() == "http" || m_aUri.GetScheme() == "https" )
1125     {
1126         return m_rProxyDecider.getProxy( m_aUri.GetScheme(),
1127                                          m_aUri.GetHost(),
1128                                          m_aUri.GetPort() );
1129     }
1130     else
1131     {
1132         // TODO: figure out, if this case can occur
1133         return m_rProxyDecider.getProxy( m_aUri.GetScheme(),
1134                                          OUString() /* not used */,
1135                                          -1 /* not used */ );
1136     }
1137 }
1138 
1139 /*
1140 
1141 namespace {
1142 
1143 bool containsLocktoken( const uno::Sequence< ucb::Lock > & rLocks,
1144                         const char * token )
1145 {
1146     for ( sal_Int32 n = 0; n < rLocks.getLength(); ++n )
1147     {
1148         const uno::Sequence< OUString > & rTokens
1149             = rLocks[ n ].LockTokens;
1150         for ( sal_Int32 m = 0; m < rTokens.getLength(); ++m )
1151         {
1152             if ( rTokens[ m ].equalsAscii( token ) )
1153                 return true;
1154         }
1155     }
1156     return false;
1157 }
1158 
1159 } // namespace
1160 */
1161 
1162 
removeExpiredLocktoken(const OUString &,const DAVRequestEnvironment &)1163 bool SerfSession::removeExpiredLocktoken( const OUString & /*inURL*/,
1164                                           const DAVRequestEnvironment & /*rEnv*/ )
1165 {
1166     return true;
1167     /*
1168     SerfLock * theLock = m_aSerfLockStore.findByUri( inURL );
1169     if ( !theLock )
1170         return false;
1171 
1172     // do a lockdiscovery to check whether this lock is still valid.
1173     try
1174     {
1175         // @@@ Alternative: use ne_lock_discover() => less overhead
1176 
1177         std::vector< DAVResource > aResources;
1178         std::vector< OUString > aPropNames;
1179         aPropNames.push_back( DAVProperties::LOCKDISCOVERY );
1180 
1181         PROPFIND( rEnv.m_aRequestURI, DAVZERO, aPropNames, aResources, rEnv );
1182 
1183         if ( aResources.empty() )
1184             return false;
1185 
1186         std::vector< DAVPropertyValue >::const_iterator it
1187             = aResources[ 0 ].properties.begin();
1188         std::vector< DAVPropertyValue >::const_iterator end
1189             = aResources[ 0 ].properties.end();
1190 
1191         while ( it != end )
1192         {
1193             if ( (*it).Name.equals( DAVProperties::LOCKDISCOVERY ) )
1194             {
1195                 uno::Sequence< ucb::Lock > aLocks;
1196                 if ( !( (*it).Value >>= aLocks ) )
1197                     return false;
1198 
1199                 if ( !containsLocktoken( aLocks, theLock->token ) )
1200                 {
1201                     // expired!
1202                     break;
1203                 }
1204 
1205                 // still valid.
1206                 return false;
1207             }
1208             ++it;
1209         }
1210 
1211         // No lockdiscovery prop in propfind result / locktoken not found
1212         // in propfind result -> not locked
1213         SAL_INFO("ucb.ucp.webdav",  "SerfSession::removeExpiredLocktoken: Removing "
1214                    " expired lock token for " << inURL << ". token: " << theLock->token );
1215 
1216         m_aSerfLockStore.removeLock( theLock );
1217         ne_lock_destroy( theLock );
1218         return true;
1219     }
1220     catch ( DAVException const & )
1221     {
1222     }
1223     return false;
1224     */
1225 }
1226 
1227 
1228 // HandleError
1229 // Common Error Handler
1230 
HandleError(std::shared_ptr<SerfRequestProcessor> rReqProc)1231 void SerfSession::HandleError( std::shared_ptr<SerfRequestProcessor> rReqProc )
1232 {
1233     m_aEnv = DAVRequestEnvironment();
1234 
1235     if ( rReqProc->mpDAVException )
1236     {
1237         DAVException* mpDAVExp( rReqProc->mpDAVException );
1238 
1239         serf_connection_reset( getSerfConnection() );
1240 
1241         if ( mpDAVExp->getStatus() == 413 &&
1242              m_bNoOfTransferEncodingSwitches < 2 )
1243         {
1244             m_bUseChunkedEncoding = !m_bUseChunkedEncoding;
1245             ++m_bNoOfTransferEncodingSwitches;
1246         }
1247 
1248         throw DAVException( mpDAVExp->getError(),
1249                             mpDAVExp->getData(),
1250                             mpDAVExp->getStatus() );
1251     }
1252 
1253     /*
1254     // Map error code to DAVException.
1255     switch ( nError )
1256     {
1257         case NE_OK:
1258             return;
1259 
1260         case NE_ERROR:        // Generic error
1261         {
1262             OUString aText = OUString::createFromAscii(
1263                 ne_get_error( m_pHttpSession ) );
1264 
1265             sal_uInt16 code = makeStatusCode( aText );
1266 
1267             if ( code == SC_LOCKED )
1268             {
1269                 if ( m_aSerfLockStore.findByUri(
1270                          makeAbsoluteURL( inPath ) ) == 0 )
1271                 {
1272                     // locked by 3rd party
1273                     throw DAVException( DAVException::DAV_LOCKED );
1274                 }
1275                 else
1276                 {
1277                     // locked by ourself
1278                     throw DAVException( DAVException::DAV_LOCKED_SELF );
1279                 }
1280             }
1281 
1282             // Special handling for 400 and 412 status codes, which may indicate
1283             // that a lock previously obtained by us has been released meanwhile
1284             // by the server. Unfortunately, RFC is not clear at this point,
1285             // thus server implementations behave different...
1286             else if ( code == SC_BAD_REQUEST || code == SC_PRECONDITION_FAILED )
1287             {
1288                 if ( removeExpiredLocktoken( makeAbsoluteURL( inPath ), rEnv ) )
1289                     throw DAVException( DAVException::DAV_LOCK_EXPIRED );
1290             }
1291 
1292             throw DAVException( DAVException::DAV_HTTP_ERROR, aText, code );
1293         }
1294         case NE_LOOKUP:       // Name lookup failed.
1295             throw DAVException( DAVException::DAV_HTTP_LOOKUP,
1296                                 SerfUri::makeConnectionEndPointString(
1297                                     m_aHostName, m_nPort ) );
1298 
1299         case NE_AUTH:         // User authentication failed on server
1300             throw DAVException( DAVException::DAV_HTTP_AUTH,
1301                                 SerfUri::makeConnectionEndPointString(
1302                                     m_aHostName, m_nPort ) );
1303 
1304         case NE_PROXYAUTH:    // User authentication failed on proxy
1305             throw DAVException( DAVException::DAV_HTTP_AUTHPROXY,
1306                                 SerfUri::makeConnectionEndPointString(
1307                                     m_aProxyName, m_nProxyPort ) );
1308 
1309         case NE_CONNECT:      // Could not connect to server
1310             throw DAVException( DAVException::DAV_HTTP_CONNECT,
1311                                 SerfUri::makeConnectionEndPointString(
1312                                     m_aHostName, m_nPort ) );
1313 
1314         case NE_TIMEOUT:      // Connection timed out
1315             throw DAVException( DAVException::DAV_HTTP_TIMEOUT,
1316                                 SerfUri::makeConnectionEndPointString(
1317                                     m_aHostName, m_nPort ) );
1318 
1319         case NE_FAILED:       // The precondition failed
1320             throw DAVException( DAVException::DAV_HTTP_FAILED,
1321                                 SerfUri::makeConnectionEndPointString(
1322                                     m_aHostName, m_nPort ) );
1323 
1324         case NE_RETRY:        // Retry request (ne_end_request ONLY)
1325             throw DAVException( DAVException::DAV_HTTP_RETRY,
1326                                 SerfUri::makeConnectionEndPointString(
1327                                     m_aHostName, m_nPort ) );
1328 
1329         case NE_REDIRECT:
1330         {
1331             SerfUri aUri( ne_redirect_location( m_pHttpSession ) );
1332             throw DAVException(
1333                 DAVException::DAV_HTTP_REDIRECT, aUri.GetURI() );
1334         }
1335         default:
1336         {
1337             SAL_INFO("ucb.ucp.webdav",  "SerfSession::HandleError : Unknown Serf error code!" );
1338             throw DAVException( DAVException::DAV_HTTP_ERROR,
1339                                 OUString::createFromAscii(
1340                                     ne_get_error( m_pHttpSession ) ) );
1341         }
1342     }
1343     */
1344 }
1345 
1346 
1347 // static
1348 bool
getDataFromInputStream(const uno::Reference<io::XInputStream> & xStream,uno::Sequence<sal_Int8> & rData,bool bAppendTrailingZeroByte)1349 SerfSession::getDataFromInputStream(
1350     const uno::Reference< io::XInputStream > & xStream,
1351     uno::Sequence< sal_Int8 > & rData,
1352     bool bAppendTrailingZeroByte )
1353 {
1354     if ( xStream.is() )
1355     {
1356         uno::Reference< io::XSeekable > xSeekable( xStream, uno::UNO_QUERY );
1357         if ( xSeekable.is() )
1358         {
1359             try
1360             {
1361                 sal_Int32 nSize
1362                     = sal::static_int_cast<sal_Int32>(xSeekable->getLength());
1363                 sal_Int32 nRead
1364                     = xStream->readBytes( rData, nSize );
1365 
1366                 if ( nRead == nSize )
1367                 {
1368                     if ( bAppendTrailingZeroByte )
1369                     {
1370                         rData.realloc( nSize + 1 );
1371                         rData[ nSize ] = sal_Int8( 0 );
1372                     }
1373                     return true;
1374                 }
1375             }
1376             catch ( io::NotConnectedException const & )
1377             {
1378                 // readBytes
1379             }
1380             catch ( io::BufferSizeExceededException const & )
1381             {
1382                 // readBytes
1383             }
1384             catch ( io::IOException const & )
1385             {
1386                 // getLength, readBytes
1387             }
1388         }
1389         else
1390         {
1391             try
1392             {
1393                 uno::Sequence< sal_Int8 > aBuffer;
1394                 sal_Int32 nPos = 0;
1395 
1396                 sal_Int32 nRead = xStream->readSomeBytes( aBuffer, 65536 );
1397                 while ( nRead > 0 )
1398                 {
1399                     if ( rData.getLength() < ( nPos + nRead ) )
1400                         rData.realloc( nPos + nRead );
1401 
1402                     aBuffer.realloc( nRead );
1403                     memcpy( rData.getArray() + nPos, aBuffer.getConstArray(), nRead );
1404                     nPos += nRead;
1405 
1406                     aBuffer.realloc( 0 );
1407                     nRead = xStream->readSomeBytes( aBuffer, 65536 );
1408                 }
1409 
1410                 if ( bAppendTrailingZeroByte )
1411                 {
1412                     rData.realloc( nPos + 1 );
1413                     rData[ nPos ] = sal_Int8( 0 );
1414                 }
1415                 return true;
1416             }
1417             catch ( io::NotConnectedException const & )
1418             {
1419                 // readBytes
1420             }
1421             catch ( io::BufferSizeExceededException const & )
1422             {
1423                 // readBytes
1424             }
1425             catch ( io::IOException const & )
1426             {
1427                 // readBytes
1428             }
1429         }
1430     }
1431     return false;
1432 }
1433 
1434 
1435 bool
isDomainMatch(const OUString & certHostName)1436 SerfSession::isDomainMatch( const OUString & certHostName )
1437 {
1438     OUString hostName = getHostName();
1439 
1440     if (hostName.equalsIgnoreAsciiCase( certHostName ) )
1441         return true;
1442 
1443     if ( certHostName.startsWith( "*" ) &&
1444          hostName.getLength() >= certHostName.getLength()  )
1445     {
1446         OUString cmpStr = certHostName.copy( 1 );
1447 
1448         if ( hostName.matchIgnoreAsciiCase(
1449                 cmpStr, hostName.getLength() -  cmpStr.getLength() ) )
1450             return true;
1451     }
1452     return false;
1453 }
1454 
1455 /*
1456 
1457 OUString SerfSession::makeAbsoluteURL( OUString const & rURL ) const
1458 {
1459     try
1460     {
1461         // Is URL relative or already absolute?
1462         if ( rURL[ 0 ] != '/' )
1463         {
1464             // absolute.
1465             return OUString( rURL );
1466         }
1467         else
1468         {
1469             ne_uri aUri;
1470             memset( &aUri, 0, sizeof( aUri ) );
1471 
1472             ne_fill_server_uri( m_pHttpSession, &aUri );
1473             aUri.path
1474                 = ne_strdup( OUStringToOString(
1475                     rURL, RTL_TEXTENCODING_UTF8 ).getStr() );
1476             SerfUri aSerfUri( &aUri );
1477             ne_uri_free( &aUri );
1478             return aSerfUri.GetURI();
1479         }
1480     }
1481     catch ( DAVException const & )
1482     {
1483     }
1484     // error.
1485     return OUString();
1486 }
1487 */
1488 
1489 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1490