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