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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 195 apr_pool_t* SerfSession::getAprPool() 196 { 197 return apr_environment::AprEnv::getAprEnv()->getAprPool(); 198 } 199 200 serf_bucket_alloc_t* SerfSession::getSerfBktAlloc() 201 { 202 return m_pSerfBucket_Alloc; 203 } 204 205 serf_context_t* SerfSession::getSerfContext() 206 { 207 return m_pSerfContext; 208 } 209 210 SerfConnection* SerfSession::getSerfConnection() 211 { 212 return m_pSerfConnection; 213 } 214 215 bool SerfSession::isHeadRequestInProgress() 216 { 217 return m_bIsHeadRequestInProgress; 218 } 219 220 bool SerfSession::isSSLNeeded() 221 { 222 return m_aUri.GetScheme().equalsIgnoreAsciiCase( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "https" ) ) ); 223 } 224 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 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 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 303 sal_Bool SerfSession::UsesProxy() 304 { 305 Init(); 306 return ( m_aProxyName.getLength() > 0 ); 307 } 308 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 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 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 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 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 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 > 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 // ------------------------------------------------------------------- 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 > 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 > 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 { 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 1364 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 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 // ------------------------------------------------------------------- 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 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 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