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