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
SerfRequestProcessor(SerfSession & rSerfSession,const rtl::OUString & inPath,const bool bUseChunkedEncoding)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
~SerfRequestProcessor()64 SerfRequestProcessor::~SerfRequestProcessor()
65 {
66 delete mpProcImpl;
67 delete mpDAVException;
68 }
69
prepareProcessor()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
processPropFind(const Depth inDepth,const std::vector<::rtl::OUString> & inPropNames,std::vector<DAVResource> & ioResources,apr_status_t & outSerfStatus)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
processPropFind(const Depth inDepth,std::vector<DAVResourceInfo> & ioResInfo,apr_status_t & outSerfStatus)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
processPropPatch(const std::vector<ProppatchValue> & inProperties,const com::sun::star::ucb::Lock inLock,apr_status_t & outSerfStatus)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
processGet(const com::sun::star::uno::Reference<SerfInputStream> & xioInStrm,apr_status_t & outSerfStatus)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
processGet(const com::sun::star::uno::Reference<SerfInputStream> & xioInStrm,const std::vector<::rtl::OUString> & inHeaderNames,DAVResource & ioResource,apr_status_t & outSerfStatus)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
processGet(const com::sun::star::uno::Reference<com::sun::star::io::XOutputStream> & xioOutStrm,apr_status_t & outSerfStatus)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
processGet(const com::sun::star::uno::Reference<com::sun::star::io::XOutputStream> & xioOutStrm,const std::vector<::rtl::OUString> & inHeaderNames,DAVResource & ioResource,apr_status_t & outSerfStatus)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
processHead(const std::vector<::rtl::OUString> & inHeaderNames,DAVResource & ioResource,apr_status_t & outSerfStatus)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
processPut(const char * inData,apr_size_t inDataLen,const com::sun::star::ucb::Lock inLock,apr_status_t & outSerfStatus)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
processPost(const char * inData,apr_size_t inDataLen,const rtl::OUString & inContentType,const rtl::OUString & inReferer,const com::sun::star::ucb::Lock inLock,const com::sun::star::uno::Reference<SerfInputStream> & xioInStrm,apr_status_t & outSerfStatus)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
processPost(const char * inData,apr_size_t inDataLen,const rtl::OUString & inContentType,const rtl::OUString & inReferer,const com::sun::star::ucb::Lock inLock,const com::sun::star::uno::Reference<com::sun::star::io::XOutputStream> & xioOutStrm,apr_status_t & outSerfStatus)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
processDelete(const com::sun::star::ucb::Lock inLock,apr_status_t & outSerfStatus)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
processMkCol(const com::sun::star::ucb::Lock inLock,apr_status_t & outSerfStatus)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
processCopy(const rtl::OUString & inDestinationPath,const bool inOverwrite,const com::sun::star::ucb::Lock inLock,apr_status_t & outSerfStatus)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
processMove(const rtl::OUString & inDestinationPath,const bool inOverwrite,const com::sun::star::ucb::Lock inLock,apr_status_t & outSerfStatus)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
processLock(const rtl::OUString & inDestinationPath,const com::sun::star::ucb::Lock & inLock,DAVPropertyValue & outLock,apr_status_t & outSerfStatus)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
processLockRefresh(const rtl::OUString & inDestinationPath,const com::sun::star::ucb::Lock & inLock,DAVPropertyValue & outLock,apr_status_t & outSerfStatus)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
processUnlock(const rtl::OUString & inDestinationPath,const com::sun::star::ucb::Lock & inLock,apr_status_t & outSerfStatus)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
runProcessor()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
postprocessProcessor(const apr_status_t inStatus)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
provideSerfCredentials(char ** outUsername,char ** outPassword,serf_request_t * inRequest,int inCode,const char * inAuthProtocol,const char * inRealm,apr_pool_t * inAprPool)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
setupSerfRequest(serf_request_t * inSerfRequest,serf_bucket_t ** outSerfRequestBucket,serf_response_acceptor_t * outSerfResponseAcceptor,void ** outSerfResponseAcceptorBaton,serf_response_handler_t * outSerfResponseHandler,void ** outSerfResponseHandlerBaton,apr_pool_t *)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
acceptSerfResponse(serf_request_t * inSerfRequest,serf_bucket_t * inSerfStreamBucket,apr_pool_t * inAprPool)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
handleSerfResponse(serf_request_t * inSerfRequest,serf_bucket_t * inSerfResponseBucket,apr_pool_t * inAprPool)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