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 "SerfRequestProcessor.hxx" 26 #include "SerfRequestProcessorImpl.hxx" 27 #include "SerfRequestProcessorImplFac.hxx" 28 #include "SerfCallbacks.hxx" 29 #include "SerfSession.hxx" 30 31 #include <apr_strings.h> 32 33 //to examine returned http code 34 #include "DAVException.hxx" 35 36 namespace http_dav_ucp 37 { 38 39 SerfRequestProcessor::SerfRequestProcessor( SerfSession& rSerfSession, 40 const rtl::OUString & inPath, 41 const bool bUseChunkedEncoding ) 42 : mrSerfSession( rSerfSession ) 43 , mPathStr( 0 ) 44 , mbUseChunkedEncoding( bUseChunkedEncoding ) 45 , mDestPathStr( 0 ) 46 , mContentType( 0 ) 47 , mReferer( 0 ) 48 , mpProcImpl( 0 ) 49 , mbProcessingDone( false ) 50 , mpDAVException() 51 , mnHTTPStatusCode( SC_NONE ) 52 , mHTTPStatusCodeText() 53 , mRedirectLocation() 54 , mnSuccessfulCredentialAttempts( 0 ) 55 , mbInputOfCredentialsAborted( false ) 56 , mbSetupSerfRequestCalled( false ) 57 , mbAcceptSerfResponseCalled( false ) 58 , mbHandleSerfResponseCalled( false ) 59 { 60 mPathStr = apr_pstrdup( mrSerfSession.getAprPool(), 61 rtl::OUStringToOString( inPath, RTL_TEXTENCODING_UTF8 ).getStr() ); 62 } 63 64 SerfRequestProcessor::~SerfRequestProcessor() 65 { 66 delete mpProcImpl; 67 delete mpDAVException; 68 } 69 70 void SerfRequestProcessor::prepareProcessor() 71 { 72 delete mpDAVException; 73 mpDAVException = 0; 74 mnHTTPStatusCode = SC_NONE; 75 mHTTPStatusCodeText = rtl::OUString(); 76 mRedirectLocation = rtl::OUString(); 77 78 mnSuccessfulCredentialAttempts = 0; 79 mbInputOfCredentialsAborted = false; 80 mbSetupSerfRequestCalled = false; 81 mbAcceptSerfResponseCalled = false; 82 mbHandleSerfResponseCalled = false; 83 } 84 85 // PROPFIND - allprop & named 86 bool SerfRequestProcessor::processPropFind( const Depth inDepth, 87 const std::vector< ::rtl::OUString > & inPropNames, 88 std::vector< DAVResource > & ioResources, 89 apr_status_t& outSerfStatus ) 90 { 91 mpProcImpl = createPropFindReqProcImpl( mPathStr, 92 mrSerfSession.getRequestEnvironment().m_aRequestHeaders, 93 inDepth, 94 inPropNames, 95 ioResources ); 96 outSerfStatus = runProcessor(); 97 98 return outSerfStatus == APR_SUCCESS; 99 } 100 101 // PROPFIND - property names 102 bool SerfRequestProcessor::processPropFind( const Depth inDepth, 103 std::vector< DAVResourceInfo > & ioResInfo, 104 apr_status_t& outSerfStatus ) 105 { 106 mpProcImpl = createPropFindReqProcImpl( mPathStr, 107 mrSerfSession.getRequestEnvironment().m_aRequestHeaders, 108 inDepth, 109 ioResInfo ); 110 outSerfStatus = runProcessor(); 111 112 return outSerfStatus == APR_SUCCESS; 113 } 114 115 // PROPPATCH 116 bool SerfRequestProcessor::processPropPatch( const std::vector< ProppatchValue > & inProperties, 117 const com::sun::star::ucb::Lock inLock, 118 apr_status_t& outSerfStatus ) 119 { 120 char * inLockToken = static_cast<char*>(0); 121 if(inLock.LockTokens.getLength() > 0) 122 { 123 inLockToken = apr_psprintf( mrSerfSession.getAprPool(), "(<%s>)", 124 rtl::OUStringToOString(inLock.LockTokens[0], RTL_TEXTENCODING_UTF8 ).getStr() ); 125 } 126 mpProcImpl = createPropPatchReqProcImpl( mPathStr, 127 mrSerfSession.getRequestEnvironment().m_aRequestHeaders, 128 inProperties, 129 inLockToken ); 130 outSerfStatus = runProcessor(); 131 132 return outSerfStatus == APR_SUCCESS; 133 } 134 135 // GET 136 bool SerfRequestProcessor::processGet( const com::sun::star::uno::Reference< SerfInputStream >& xioInStrm, 137 apr_status_t& outSerfStatus ) 138 { 139 mpProcImpl = createGetReqProcImpl( mPathStr, 140 mrSerfSession.getRequestEnvironment().m_aRequestHeaders, 141 xioInStrm ); 142 outSerfStatus = runProcessor(); 143 144 return outSerfStatus == APR_SUCCESS; 145 } 146 147 // GET inclusive header fields 148 bool SerfRequestProcessor::processGet( const com::sun::star::uno::Reference< SerfInputStream >& xioInStrm, 149 const std::vector< ::rtl::OUString > & inHeaderNames, 150 DAVResource & ioResource, 151 apr_status_t& outSerfStatus ) 152 { 153 mpProcImpl = createGetReqProcImpl( mPathStr, 154 mrSerfSession.getRequestEnvironment().m_aRequestHeaders, 155 xioInStrm, 156 inHeaderNames, 157 ioResource ); 158 outSerfStatus = runProcessor(); 159 160 return outSerfStatus == APR_SUCCESS; 161 } 162 163 // GET 164 bool SerfRequestProcessor::processGet( const com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& xioOutStrm, 165 apr_status_t& outSerfStatus ) 166 { 167 mpProcImpl = createGetReqProcImpl( mPathStr, 168 mrSerfSession.getRequestEnvironment().m_aRequestHeaders, 169 xioOutStrm ); 170 outSerfStatus = runProcessor(); 171 172 return outSerfStatus == APR_SUCCESS; 173 } 174 175 // GET inclusive header fields 176 bool SerfRequestProcessor::processGet( const com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& xioOutStrm, 177 const std::vector< ::rtl::OUString > & inHeaderNames, 178 DAVResource & ioResource, 179 apr_status_t& outSerfStatus ) 180 { 181 mpProcImpl = createGetReqProcImpl( mPathStr, 182 mrSerfSession.getRequestEnvironment().m_aRequestHeaders, 183 xioOutStrm, 184 inHeaderNames, 185 ioResource ); 186 outSerfStatus = runProcessor(); 187 188 return outSerfStatus == APR_SUCCESS; 189 } 190 191 // HEAD 192 bool SerfRequestProcessor::processHead( const std::vector< ::rtl::OUString > & inHeaderNames, 193 DAVResource & ioResource, 194 apr_status_t& outSerfStatus ) 195 { 196 mpProcImpl = createHeadReqProcImpl( mPathStr, 197 mrSerfSession.getRequestEnvironment().m_aRequestHeaders, 198 inHeaderNames, 199 ioResource ); 200 outSerfStatus = runProcessor(); 201 202 return outSerfStatus == APR_SUCCESS; 203 } 204 205 // PUT 206 bool SerfRequestProcessor::processPut( const char* inData, 207 apr_size_t inDataLen, 208 const com::sun::star::ucb::Lock inLock, 209 apr_status_t& outSerfStatus ) 210 { 211 char * inLockToken = static_cast<char*>(0); 212 if(inLock.LockTokens.getLength() > 0) 213 { 214 inLockToken = apr_psprintf( mrSerfSession.getAprPool(), "(<%s>)", 215 rtl::OUStringToOString(inLock.LockTokens[0], RTL_TEXTENCODING_UTF8 ).getStr() ); 216 } 217 mpProcImpl = createPutReqProcImpl( mPathStr, 218 mrSerfSession.getRequestEnvironment().m_aRequestHeaders, 219 inData, 220 inLockToken, 221 inDataLen ); 222 outSerfStatus = runProcessor(); 223 224 return outSerfStatus == APR_SUCCESS; 225 } 226 227 // POST 228 bool SerfRequestProcessor::processPost( const char* inData, 229 apr_size_t inDataLen, 230 const rtl::OUString & inContentType, 231 const rtl::OUString & inReferer, 232 const com::sun::star::ucb::Lock inLock, 233 const com::sun::star::uno::Reference< SerfInputStream >& xioInStrm, 234 apr_status_t& outSerfStatus ) 235 { 236 mContentType = apr_pstrdup( mrSerfSession.getAprPool(), 237 rtl::OUStringToOString( inContentType, RTL_TEXTENCODING_UTF8 ).getStr() ); 238 mReferer = apr_pstrdup( mrSerfSession.getAprPool(), 239 rtl::OUStringToOString( inReferer, RTL_TEXTENCODING_UTF8 ).getStr() ); 240 char * inLockToken = static_cast<char*>(0); 241 if(inLock.LockTokens.getLength() > 0) 242 { 243 inLockToken = apr_psprintf( mrSerfSession.getAprPool(), "(<%s>)", 244 rtl::OUStringToOString(inLock.LockTokens[0], RTL_TEXTENCODING_UTF8 ).getStr() ); 245 } 246 mpProcImpl = createPostReqProcImpl( mPathStr, 247 mrSerfSession.getRequestEnvironment().m_aRequestHeaders, 248 inData, 249 inDataLen, 250 inLockToken, 251 mContentType, 252 mReferer, 253 xioInStrm ); 254 outSerfStatus = runProcessor(); 255 256 return outSerfStatus == APR_SUCCESS; 257 } 258 259 // POST 260 bool SerfRequestProcessor::processPost( const char* inData, 261 apr_size_t inDataLen, 262 const rtl::OUString & inContentType, 263 const rtl::OUString & inReferer, 264 const com::sun::star::ucb::Lock inLock, 265 const com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& xioOutStrm, 266 apr_status_t& outSerfStatus ) 267 { 268 mContentType = apr_pstrdup( mrSerfSession.getAprPool(), 269 rtl::OUStringToOString( inContentType, RTL_TEXTENCODING_UTF8 ).getStr() ); 270 mReferer = apr_pstrdup( mrSerfSession.getAprPool(), 271 rtl::OUStringToOString( inReferer, RTL_TEXTENCODING_UTF8 ).getStr() ); 272 char * inLockToken = static_cast<char*>(0); 273 if(inLock.LockTokens.getLength() > 0) 274 { 275 inLockToken = apr_psprintf( mrSerfSession.getAprPool(), "(<%s>)", 276 rtl::OUStringToOString(inLock.LockTokens[0], RTL_TEXTENCODING_UTF8 ).getStr() ); 277 } 278 mpProcImpl = createPostReqProcImpl( mPathStr, 279 mrSerfSession.getRequestEnvironment().m_aRequestHeaders, 280 inData, 281 inDataLen, 282 inLockToken, 283 mContentType, 284 mReferer, 285 xioOutStrm ); 286 outSerfStatus = runProcessor(); 287 288 return outSerfStatus == APR_SUCCESS; 289 } 290 291 // DELETE 292 bool SerfRequestProcessor::processDelete( const com::sun::star::ucb::Lock inLock, 293 apr_status_t& outSerfStatus ) 294 { 295 char * inLockToken = static_cast<char*>(0); 296 if(inLock.LockTokens.getLength() > 0) 297 { 298 inLockToken = apr_psprintf( mrSerfSession.getAprPool(), "(<%s>)", 299 rtl::OUStringToOString(inLock.LockTokens[0], RTL_TEXTENCODING_UTF8 ).getStr() ); 300 } 301 mpProcImpl = createDeleteReqProcImpl( mPathStr, 302 mrSerfSession.getRequestEnvironment().m_aRequestHeaders, 303 inLockToken ); 304 outSerfStatus = runProcessor(); 305 306 return outSerfStatus == APR_SUCCESS; 307 } 308 309 // MKCOL 310 bool SerfRequestProcessor::processMkCol( const com::sun::star::ucb::Lock inLock, 311 apr_status_t& outSerfStatus ) 312 { 313 char * inLockToken = static_cast<char*>(0); 314 if(inLock.LockTokens.getLength() > 0) 315 { 316 inLockToken = apr_psprintf( mrSerfSession.getAprPool(), "(<%s>)", 317 rtl::OUStringToOString(inLock.LockTokens[0], RTL_TEXTENCODING_UTF8 ).getStr() ); 318 } 319 mpProcImpl = createMkColReqProcImpl( mPathStr, 320 mrSerfSession.getRequestEnvironment().m_aRequestHeaders, 321 inLockToken ); 322 outSerfStatus = runProcessor(); 323 324 return outSerfStatus == APR_SUCCESS; 325 } 326 327 // COPY 328 bool SerfRequestProcessor::processCopy( const rtl::OUString & inDestinationPath, 329 const bool inOverwrite, 330 const com::sun::star::ucb::Lock inLock, 331 apr_status_t& outSerfStatus ) 332 { 333 mDestPathStr = apr_pstrdup( mrSerfSession.getAprPool(), 334 rtl::OUStringToOString( inDestinationPath, RTL_TEXTENCODING_UTF8 ).getStr() ); 335 char * inLockToken = static_cast<char*>(0); 336 if(inLock.LockTokens.getLength() > 0) 337 { 338 inLockToken = apr_psprintf( mrSerfSession.getAprPool(), "(<%s>)", 339 rtl::OUStringToOString(inLock.LockTokens[0], RTL_TEXTENCODING_UTF8 ).getStr() ); 340 } 341 mpProcImpl = createCopyReqProcImpl( mPathStr, 342 mrSerfSession.getRequestEnvironment().m_aRequestHeaders, 343 mDestPathStr, 344 inOverwrite, 345 inLockToken ); 346 outSerfStatus = runProcessor(); 347 348 return outSerfStatus == APR_SUCCESS; 349 } 350 351 // MOVE 352 bool SerfRequestProcessor::processMove( const rtl::OUString & inDestinationPath, 353 const bool inOverwrite, 354 const com::sun::star::ucb::Lock inLock, 355 apr_status_t& outSerfStatus ) 356 { 357 mDestPathStr = apr_pstrdup( mrSerfSession.getAprPool(), 358 rtl::OUStringToOString( inDestinationPath, RTL_TEXTENCODING_UTF8 ).getStr() ); 359 char * inLockToken = static_cast<char*>(0); 360 if(inLock.LockTokens.getLength() > 0) 361 { 362 inLockToken = apr_psprintf( mrSerfSession.getAprPool(), "(<%s>)", 363 rtl::OUStringToOString(inLock.LockTokens[0], RTL_TEXTENCODING_UTF8 ).getStr() ); 364 } 365 mpProcImpl = createMoveReqProcImpl( mPathStr, 366 mrSerfSession.getRequestEnvironment().m_aRequestHeaders, 367 mDestPathStr, 368 inOverwrite, 369 inLockToken ); 370 outSerfStatus = runProcessor(); 371 372 return outSerfStatus == APR_SUCCESS; 373 } 374 375 //LOCK creating a new lock 376 bool SerfRequestProcessor::processLock( const rtl::OUString & inDestinationPath, 377 const com::sun::star::ucb::Lock& inLock, 378 DAVPropertyValue & outLock, 379 apr_status_t& outSerfStatus ) 380 { 381 mDestPathStr = apr_pstrdup( mrSerfSession.getAprPool(), 382 rtl::OUStringToOString( inDestinationPath, RTL_TEXTENCODING_UTF8 ).getStr() ); 383 char * Timeout; 384 if(inLock.Timeout == -1) 385 Timeout = apr_psprintf( mrSerfSession.getAprPool(), "Infinite" ); 386 else 387 Timeout = apr_psprintf( mrSerfSession.getAprPool(), "Second-%ld", inLock.Timeout ); 388 389 mpProcImpl = createLockReqProcImpl( mPathStr, 390 mrSerfSession.getRequestEnvironment().m_aRequestHeaders, 391 inLock, 392 Timeout, 393 outLock); 394 outSerfStatus = runProcessor(); 395 396 return outSerfStatus == APR_SUCCESS; 397 } 398 399 //LOCK refresh an existing lock 400 bool SerfRequestProcessor::processLockRefresh( const rtl::OUString & inDestinationPath, 401 const com::sun::star::ucb::Lock& inLock, 402 DAVPropertyValue & outLock, 403 apr_status_t& outSerfStatus ) 404 { 405 mDestPathStr = apr_pstrdup( mrSerfSession.getAprPool(), 406 rtl::OUStringToOString( inDestinationPath, RTL_TEXTENCODING_UTF8 ).getStr() ); 407 char * Timeout; 408 if(inLock.Timeout == -1) 409 Timeout = apr_psprintf( mrSerfSession.getAprPool(), "Infinite" ); 410 else 411 Timeout = apr_psprintf( mrSerfSession.getAprPool(), "Second-%ld", inLock.Timeout ); 412 413 char * inLockToken = apr_psprintf( mrSerfSession.getAprPool(), "(<%s>)", 414 rtl::OUStringToOString(inLock.LockTokens[0], RTL_TEXTENCODING_UTF8 ).getStr() ); 415 416 mpProcImpl = createLockRefreshProcImpl( mPathStr, 417 mrSerfSession.getRequestEnvironment().m_aRequestHeaders, 418 inLock, 419 inLockToken, 420 Timeout, 421 outLock); 422 outSerfStatus = runProcessor(); 423 424 return outSerfStatus == APR_SUCCESS; 425 } 426 427 //ULOCK unlock an existing lock 428 bool SerfRequestProcessor::processUnlock( const rtl::OUString & inDestinationPath, 429 const com::sun::star::ucb::Lock& inLock, 430 apr_status_t& outSerfStatus ) 431 { 432 mDestPathStr = apr_pstrdup( mrSerfSession.getAprPool(), 433 rtl::OUStringToOString( inDestinationPath, RTL_TEXTENCODING_UTF8 ).getStr() ); 434 435 char * aToken = apr_psprintf( mrSerfSession.getAprPool(), "<%s>", 436 rtl::OUStringToOString(inLock.LockTokens[0], RTL_TEXTENCODING_UTF8 ).getStr() ); 437 438 mpProcImpl = createUnlockProcImpl( mPathStr, 439 mrSerfSession.getRequestEnvironment().m_aRequestHeaders, 440 inLock, 441 aToken ); 442 443 outSerfStatus = runProcessor(); 444 445 return outSerfStatus == APR_SUCCESS; 446 } 447 448 apr_status_t SerfRequestProcessor::runProcessor() 449 { 450 prepareProcessor(); 451 452 // activate chunked encoding, if requested 453 if ( mbUseChunkedEncoding ) 454 { 455 mpProcImpl->activateChunkedEncoding(); 456 } 457 458 // create serf request 459 OSL_ASSERT(mrSerfSession.getSerfConnection() != NULL); 460 serf_connection_request_create( mrSerfSession.getSerfConnection(), 461 Serf_SetupRequest, 462 this ); 463 464 // perform serf request 465 mbProcessingDone = false; 466 apr_status_t status = APR_SUCCESS; 467 serf_context_t* pSerfContext = mrSerfSession.getSerfContext(); 468 apr_pool_t* pAprPool = mrSerfSession.getAprPool(); 469 while ( true ) 470 { 471 status = serf_context_run( pSerfContext, 472 SERF_DURATION_FOREVER, 473 pAprPool ); 474 if ( APR_STATUS_IS_TIMEUP( status ) ) 475 { 476 continue; 477 } 478 if ( status != APR_SUCCESS ) 479 { 480 #if OSL_DEBUG_LEVEL > 0 481 char buff[512]; 482 OSL_TRACE("SerfRequestProcessor::runProcessor, status != APR_SUCCESS: %d (%s)",status, apr_strerror(status, buff, 512)); 483 #endif 484 break; 485 } 486 if ( mbProcessingDone ) 487 { 488 break; 489 } 490 } 491 492 postprocessProcessor( status ); 493 494 return status; 495 } 496 497 void SerfRequestProcessor::postprocessProcessor( const apr_status_t inStatus ) 498 { 499 if ( inStatus == APR_SUCCESS ) 500 { 501 return; 502 } 503 504 OSL_TRACE("SerfRequestProcessor::postprocessProcessor:%d",__LINE__); 505 switch ( inStatus ) 506 { 507 case APR_EGENERAL: 508 case SERF_ERROR_AUTHN_FAILED: 509 // general error; <mnHTTPStatusCode> provides more information 510 { 511 switch ( mnHTTPStatusCode ) 512 { 513 case SC_NONE: 514 if ( !mbSetupSerfRequestCalled ) 515 { 516 mpDAVException = new DAVException( DAVException::DAV_HTTP_LOOKUP, 517 SerfUri::makeConnectionEndPointString( mrSerfSession.getHostName(), 518 mrSerfSession.getPort() ) ); 519 } 520 else if ( mbInputOfCredentialsAborted ) 521 { 522 mpDAVException = new DAVException( DAVException::DAV_HTTP_NOAUTH, 523 SerfUri::makeConnectionEndPointString( mrSerfSession.getHostName(), 524 mrSerfSession.getPort() ) ); 525 } 526 else 527 { 528 mpDAVException = new DAVException( DAVException::DAV_HTTP_ERROR, 529 mHTTPStatusCodeText, 530 mnHTTPStatusCode ); 531 } 532 break; 533 case SC_MOVED_PERMANENTLY: 534 case SC_MOVED_TEMPORARILY: 535 case SC_SEE_OTHER: 536 case SC_TEMPORARY_REDIRECT: 537 mpDAVException = new DAVException( DAVException::DAV_HTTP_REDIRECT, 538 mRedirectLocation ); 539 break; 540 case SC_LOCKED: 541 mpDAVException = new DAVException( DAVException::DAV_LOCKED, 542 mHTTPStatusCodeText, 543 mnHTTPStatusCode ); 544 break; 545 default: 546 mpDAVException = new DAVException( DAVException::DAV_HTTP_ERROR, 547 mHTTPStatusCodeText, 548 mnHTTPStatusCode ); 549 break; 550 } 551 } 552 break; 553 554 default: 555 mpDAVException = new DAVException( DAVException::DAV_HTTP_ERROR ); 556 break; 557 } 558 } 559 560 apr_status_t SerfRequestProcessor::provideSerfCredentials( char ** outUsername, 561 char ** outPassword, 562 serf_request_t * inRequest, 563 int inCode, 564 const char *inAuthProtocol, 565 const char *inRealm, 566 apr_pool_t *inAprPool ) 567 { 568 // as each successful provided credentials are tried twice - see below - the 569 // number of real attempts is half of the value of <mnSuccessfulCredentialAttempts> 570 if ( (mnSuccessfulCredentialAttempts / 2) >= 5 || 571 mbInputOfCredentialsAborted ) 572 { 573 mbInputOfCredentialsAborted = true; 574 return SERF_ERROR_AUTHN_FAILED; 575 } 576 577 // because serf keeps credentials only for a connection in case of digest authentication 578 // we give each successful provided credentials a second try in order to workaround the 579 // situation that the connection for which the credentials have been provided has been closed 580 // before the provided credentials could be applied for the request. 581 apr_status_t status = mrSerfSession.provideSerfCredentials( (mnSuccessfulCredentialAttempts % 2) == 1, 582 outUsername, 583 outPassword, 584 inRequest, 585 inCode, 586 inAuthProtocol, 587 inRealm, 588 inAprPool ); 589 if ( status != APR_SUCCESS ) 590 { 591 mbInputOfCredentialsAborted = true; 592 } 593 else 594 { 595 ++mnSuccessfulCredentialAttempts; 596 } 597 598 return status; 599 } 600 601 apr_status_t SerfRequestProcessor::setupSerfRequest( serf_request_t * inSerfRequest, 602 serf_bucket_t ** outSerfRequestBucket, 603 serf_response_acceptor_t * outSerfResponseAcceptor, 604 void ** outSerfResponseAcceptorBaton, 605 serf_response_handler_t * outSerfResponseHandler, 606 void ** outSerfResponseHandlerBaton, 607 apr_pool_t * /*inAprPool*/ ) 608 { 609 mbSetupSerfRequestCalled = true; 610 *outSerfRequestBucket = mpProcImpl->createSerfRequestBucket( inSerfRequest ); 611 612 // apply callbacks for accepting response and handling response 613 *outSerfResponseAcceptor = Serf_AcceptResponse; 614 *outSerfResponseAcceptorBaton = this; 615 *outSerfResponseHandler = Serf_HandleResponse; 616 *outSerfResponseHandlerBaton = this; 617 618 return APR_SUCCESS; 619 } 620 621 serf_bucket_t* SerfRequestProcessor::acceptSerfResponse( serf_request_t * inSerfRequest, 622 serf_bucket_t * inSerfStreamBucket, 623 apr_pool_t * inAprPool ) 624 { 625 mbAcceptSerfResponseCalled = true; 626 return mrSerfSession.acceptSerfResponse( inSerfRequest, 627 inSerfStreamBucket, 628 inAprPool ); 629 } 630 631 apr_status_t SerfRequestProcessor::handleSerfResponse( serf_request_t * inSerfRequest, 632 serf_bucket_t * inSerfResponseBucket, 633 apr_pool_t * inAprPool ) 634 { 635 mbHandleSerfResponseCalled = true; 636 637 // some general response handling and error handling 638 { 639 if ( !inSerfResponseBucket ) 640 { 641 /* A NULL response can come back if the request failed completely */ 642 mbProcessingDone = true; 643 return APR_EGENERAL; 644 } 645 646 serf_status_line sl; 647 apr_status_t status = serf_bucket_response_status( inSerfResponseBucket, &sl ); 648 if ( status ) 649 { 650 mbProcessingDone = false; // allow another try in order to get a response 651 return status; 652 } 653 serf_bucket_t *headers = serf_bucket_response_get_headers( inSerfResponseBucket ); 654 655 // check header according: 656 // http://tools.ietf.org/html/rfc7231#section-7.4.2 657 // need to do this so we can adjust the protocol accordingly 658 // serf_bucket_headers_get is case independent 659 const char* server = serf_bucket_headers_get( headers, "server" ); 660 if( server ) 661 { 662 //update the server type on session 663 mrSerfSession.setServerHeaderField( ::rtl::OUString::createFromAscii( server ) ); 664 } 665 //the following extension is MS IIS specific, 666 //see https://msdn.microsoft.com/en-us/library/cc250064.aspx 667 //site last checked on 2015-03-02 668 //TODO i126305 need to be added when serf is updated to a version supporting Windows authentication 669 //const char* msDavExtErr = serf_bucket_headers_get( headers, "X-MSDAVEXT_ERROR" ); 670 671 // TODO - check, if response status code handling is correct 672 mnHTTPStatusCode = ( sl.version != 0 && sl.code >= 0 ) 673 ? static_cast< sal_uInt16 >( sl.code ) 674 : SC_NONE; 675 if ( sl.reason ) 676 { 677 mHTTPStatusCodeText = ::rtl::OUString::createFromAscii( sl.reason ); 678 } 679 if ( ( sl.version == 0 || sl.code < 0 ) || 680 mnHTTPStatusCode >= 300 ) 681 { 682 if ( mnHTTPStatusCode == 301 || 683 mnHTTPStatusCode == 302 || 684 mnHTTPStatusCode == 303 || 685 mnHTTPStatusCode == 307 ) 686 { 687 // new location for certain redirections 688 const char* location = serf_bucket_headers_get( headers, "Location" ); 689 if ( location ) 690 { 691 mRedirectLocation = rtl::OUString::createFromAscii( location ); 692 } 693 mbProcessingDone = true; 694 return APR_EGENERAL; 695 } 696 else if ( mrSerfSession.isHeadRequestInProgress() && 697 ( mnHTTPStatusCode == 401 || mnHTTPStatusCode == 407 ) ) 698 { 699 // keep going as authentication is not required on HEAD request. 700 // the response already contains header fields. 701 } 702 else 703 { 704 mbProcessingDone = true; 705 return APR_EGENERAL; 706 } 707 } 708 } 709 710 // request specific processing of the response bucket 711 apr_status_t status = APR_SUCCESS; 712 mbProcessingDone = mpProcImpl->processSerfResponseBucket( inSerfRequest, 713 inSerfResponseBucket, 714 inAprPool, 715 status ); 716 717 return status; 718 } 719 720 } // namespace http_dav_ucp 721 722