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