xref: /AOO41X/main/ucb/source/ucp/webdav/SerfRequestProcessor.cxx (revision c1c10f689322f7a0aeea444d576726e9e9c4db8f)
18590a0fdSAndre Fischer /**************************************************************
28590a0fdSAndre Fischer  *
38590a0fdSAndre Fischer  * Licensed to the Apache Software Foundation (ASF) under one
48590a0fdSAndre Fischer  * or more contributor license agreements.  See the NOTICE file
58590a0fdSAndre Fischer  * distributed with this work for additional information
68590a0fdSAndre Fischer  * regarding copyright ownership.  The ASF licenses this file
78590a0fdSAndre Fischer  * to you under the Apache License, Version 2.0 (the
88590a0fdSAndre Fischer  * "License"); you may not use this file except in compliance
98590a0fdSAndre Fischer  * with the License.  You may obtain a copy of the License at
108590a0fdSAndre Fischer  *
118590a0fdSAndre Fischer  *   http://www.apache.org/licenses/LICENSE-2.0
128590a0fdSAndre Fischer  *
138590a0fdSAndre Fischer  * Unless required by applicable law or agreed to in writing,
148590a0fdSAndre Fischer  * software distributed under the License is distributed on an
158590a0fdSAndre Fischer  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
168590a0fdSAndre Fischer  * KIND, either express or implied.  See the License for the
178590a0fdSAndre Fischer  * specific language governing permissions and limitations
188590a0fdSAndre Fischer  * under the License.
198590a0fdSAndre Fischer  *
208590a0fdSAndre Fischer  *************************************************************/
218590a0fdSAndre Fischer 
228590a0fdSAndre Fischer // MARKER(update_precomp.py): autogen include statement, do not remove
238590a0fdSAndre Fischer #include "precompiled_ucb.hxx"
248590a0fdSAndre Fischer 
25*c1c10f68SAriel Constenla-Haile #include "SerfRequestProcessor.hxx"
26*c1c10f68SAriel Constenla-Haile #include "SerfRequestProcessorImpl.hxx"
27*c1c10f68SAriel Constenla-Haile #include "SerfRequestProcessorImplFac.hxx"
28*c1c10f68SAriel Constenla-Haile #include "SerfCallbacks.hxx"
29*c1c10f68SAriel Constenla-Haile #include "SerfSession.hxx"
308590a0fdSAndre Fischer 
318590a0fdSAndre Fischer #include <apr_strings.h>
328590a0fdSAndre Fischer 
338590a0fdSAndre Fischer namespace http_dav_ucp
348590a0fdSAndre Fischer {
358590a0fdSAndre Fischer 
368590a0fdSAndre Fischer SerfRequestProcessor::SerfRequestProcessor( SerfSession& rSerfSession,
3749989859SOliver-Rainer Wittmann                                             const rtl::OUString & inPath,
3849989859SOliver-Rainer Wittmann                                             const bool bUseChunkedEncoding )
398590a0fdSAndre Fischer     : mrSerfSession( rSerfSession )
408590a0fdSAndre Fischer     , mPathStr( 0 )
4149989859SOliver-Rainer Wittmann     , mbUseChunkedEncoding( bUseChunkedEncoding )
428590a0fdSAndre Fischer     , mDestPathStr( 0 )
4349989859SOliver-Rainer Wittmann     , mContentType( 0 )
4449989859SOliver-Rainer Wittmann     , mReferer( 0 )
458590a0fdSAndre Fischer     , mpProcImpl( 0 )
468590a0fdSAndre Fischer     , mbProcessingDone( false )
478590a0fdSAndre Fischer     , mpDAVException()
488590a0fdSAndre Fischer     , mnHTTPStatusCode( SC_NONE )
498590a0fdSAndre Fischer     , mHTTPStatusCodeText()
508590a0fdSAndre Fischer     , mRedirectLocation()
51fb7f54d2SOliver-Rainer Wittmann     , mnSuccessfulCredentialAttempts( 0 )
52fb7f54d2SOliver-Rainer Wittmann     , mbInputOfCredentialsAborted( false )
538590a0fdSAndre Fischer     , mbSetupSerfRequestCalled( false )
548590a0fdSAndre Fischer     , mbAcceptSerfResponseCalled( false )
558590a0fdSAndre Fischer     , mbHandleSerfResponseCalled( false )
568590a0fdSAndre Fischer {
578590a0fdSAndre Fischer     mPathStr = apr_pstrdup( mrSerfSession.getAprPool(),
588590a0fdSAndre Fischer                             rtl::OUStringToOString( inPath, RTL_TEXTENCODING_UTF8 ) );
598590a0fdSAndre Fischer }
608590a0fdSAndre Fischer 
618590a0fdSAndre Fischer SerfRequestProcessor::~SerfRequestProcessor()
628590a0fdSAndre Fischer {
638590a0fdSAndre Fischer     delete mpProcImpl;
648590a0fdSAndre Fischer     delete mpDAVException;
658590a0fdSAndre Fischer }
668590a0fdSAndre Fischer 
678590a0fdSAndre Fischer void SerfRequestProcessor::prepareProcessor()
688590a0fdSAndre Fischer {
698590a0fdSAndre Fischer     delete mpDAVException;
708590a0fdSAndre Fischer     mpDAVException = 0;
718590a0fdSAndre Fischer     mnHTTPStatusCode = SC_NONE;
728590a0fdSAndre Fischer     mHTTPStatusCodeText = rtl::OUString();
738590a0fdSAndre Fischer     mRedirectLocation = rtl::OUString();
748590a0fdSAndre Fischer 
75fb7f54d2SOliver-Rainer Wittmann     mnSuccessfulCredentialAttempts = 0;
76fb7f54d2SOliver-Rainer Wittmann     mbInputOfCredentialsAborted = false;
778590a0fdSAndre Fischer     mbSetupSerfRequestCalled = false;
788590a0fdSAndre Fischer     mbAcceptSerfResponseCalled = false;
798590a0fdSAndre Fischer     mbHandleSerfResponseCalled = false;
808590a0fdSAndre Fischer }
818590a0fdSAndre Fischer 
828590a0fdSAndre Fischer // PROPFIND - allprop & named
838590a0fdSAndre Fischer bool SerfRequestProcessor::processPropFind( const Depth inDepth,
848590a0fdSAndre Fischer                                             const std::vector< ::rtl::OUString > & inPropNames,
858590a0fdSAndre Fischer                                             std::vector< DAVResource > & ioResources,
868590a0fdSAndre Fischer                                             apr_status_t& outSerfStatus )
878590a0fdSAndre Fischer {
888590a0fdSAndre Fischer     mpProcImpl = createPropFindReqProcImpl( mPathStr,
89e9ff7e89SOliver-Rainer Wittmann                                             mrSerfSession.getRequestEnvironment().m_aRequestHeaders,
908590a0fdSAndre Fischer                                             inDepth,
918590a0fdSAndre Fischer                                             inPropNames,
928590a0fdSAndre Fischer                                             ioResources );
938590a0fdSAndre Fischer     outSerfStatus = runProcessor();
948590a0fdSAndre Fischer 
958590a0fdSAndre Fischer     return outSerfStatus == APR_SUCCESS;
968590a0fdSAndre Fischer }
978590a0fdSAndre Fischer 
988590a0fdSAndre Fischer // PROPFIND - property names
998590a0fdSAndre Fischer bool SerfRequestProcessor::processPropFind( const Depth inDepth,
1008590a0fdSAndre Fischer                                             std::vector< DAVResourceInfo > & ioResInfo,
1018590a0fdSAndre Fischer                                             apr_status_t& outSerfStatus )
1028590a0fdSAndre Fischer {
1038590a0fdSAndre Fischer     mpProcImpl = createPropFindReqProcImpl( mPathStr,
104e9ff7e89SOliver-Rainer Wittmann                                             mrSerfSession.getRequestEnvironment().m_aRequestHeaders,
1058590a0fdSAndre Fischer                                             inDepth,
1068590a0fdSAndre Fischer                                             ioResInfo );
1078590a0fdSAndre Fischer     outSerfStatus = runProcessor();
1088590a0fdSAndre Fischer 
1098590a0fdSAndre Fischer     return outSerfStatus == APR_SUCCESS;
1108590a0fdSAndre Fischer }
1118590a0fdSAndre Fischer 
1128590a0fdSAndre Fischer // PROPPATCH
1138590a0fdSAndre Fischer bool SerfRequestProcessor::processPropPatch( const std::vector< ProppatchValue > & inProperties,
1148590a0fdSAndre Fischer                                              apr_status_t& outSerfStatus )
1158590a0fdSAndre Fischer {
1168590a0fdSAndre Fischer     mpProcImpl = createPropPatchReqProcImpl( mPathStr,
117e9ff7e89SOliver-Rainer Wittmann                                              mrSerfSession.getRequestEnvironment().m_aRequestHeaders,
1188590a0fdSAndre Fischer                                              inProperties );
1198590a0fdSAndre Fischer     outSerfStatus = runProcessor();
1208590a0fdSAndre Fischer 
1218590a0fdSAndre Fischer     return outSerfStatus == APR_SUCCESS;
1228590a0fdSAndre Fischer }
1238590a0fdSAndre Fischer 
1248590a0fdSAndre Fischer // GET
1258590a0fdSAndre Fischer bool SerfRequestProcessor::processGet( const com::sun::star::uno::Reference< SerfInputStream >& xioInStrm,
1268590a0fdSAndre Fischer                                        apr_status_t& outSerfStatus )
1278590a0fdSAndre Fischer {
1288590a0fdSAndre Fischer     mpProcImpl = createGetReqProcImpl( mPathStr,
129e9ff7e89SOliver-Rainer Wittmann                                        mrSerfSession.getRequestEnvironment().m_aRequestHeaders,
1308590a0fdSAndre Fischer                                        xioInStrm );
1318590a0fdSAndre Fischer     outSerfStatus = runProcessor();
1328590a0fdSAndre Fischer 
1338590a0fdSAndre Fischer     return outSerfStatus == APR_SUCCESS;
1348590a0fdSAndre Fischer }
1358590a0fdSAndre Fischer 
1368590a0fdSAndre Fischer // GET inclusive header fields
1378590a0fdSAndre Fischer bool SerfRequestProcessor::processGet( const com::sun::star::uno::Reference< SerfInputStream >& xioInStrm,
1388590a0fdSAndre Fischer                                        const std::vector< ::rtl::OUString > & inHeaderNames,
1398590a0fdSAndre Fischer                                        DAVResource & ioResource,
1408590a0fdSAndre Fischer                                        apr_status_t& outSerfStatus )
1418590a0fdSAndre Fischer {
1428590a0fdSAndre Fischer     mpProcImpl = createGetReqProcImpl( mPathStr,
143e9ff7e89SOliver-Rainer Wittmann                                        mrSerfSession.getRequestEnvironment().m_aRequestHeaders,
1448590a0fdSAndre Fischer                                        xioInStrm,
1458590a0fdSAndre Fischer                                        inHeaderNames,
1468590a0fdSAndre Fischer                                        ioResource );
1478590a0fdSAndre Fischer     outSerfStatus = runProcessor();
1488590a0fdSAndre Fischer 
1498590a0fdSAndre Fischer     return outSerfStatus == APR_SUCCESS;
1508590a0fdSAndre Fischer }
1518590a0fdSAndre Fischer 
1528590a0fdSAndre Fischer // GET
1538590a0fdSAndre Fischer bool SerfRequestProcessor::processGet( const com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& xioOutStrm,
1548590a0fdSAndre Fischer                                        apr_status_t& outSerfStatus )
1558590a0fdSAndre Fischer {
1568590a0fdSAndre Fischer     mpProcImpl = createGetReqProcImpl( mPathStr,
157e9ff7e89SOliver-Rainer Wittmann                                        mrSerfSession.getRequestEnvironment().m_aRequestHeaders,
1588590a0fdSAndre Fischer                                        xioOutStrm );
1598590a0fdSAndre Fischer     outSerfStatus = runProcessor();
1608590a0fdSAndre Fischer 
1618590a0fdSAndre Fischer     return outSerfStatus == APR_SUCCESS;
1628590a0fdSAndre Fischer }
1638590a0fdSAndre Fischer 
1648590a0fdSAndre Fischer // GET inclusive header fields
1658590a0fdSAndre Fischer bool SerfRequestProcessor::processGet( const com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& xioOutStrm,
1668590a0fdSAndre Fischer                                        const std::vector< ::rtl::OUString > & inHeaderNames,
1678590a0fdSAndre Fischer                                        DAVResource & ioResource,
1688590a0fdSAndre Fischer                                        apr_status_t& outSerfStatus )
1698590a0fdSAndre Fischer {
1708590a0fdSAndre Fischer     mpProcImpl = createGetReqProcImpl( mPathStr,
171e9ff7e89SOliver-Rainer Wittmann                                        mrSerfSession.getRequestEnvironment().m_aRequestHeaders,
1728590a0fdSAndre Fischer                                        xioOutStrm,
1738590a0fdSAndre Fischer                                        inHeaderNames,
1748590a0fdSAndre Fischer                                        ioResource );
1758590a0fdSAndre Fischer     outSerfStatus = runProcessor();
1768590a0fdSAndre Fischer 
1778590a0fdSAndre Fischer     return outSerfStatus == APR_SUCCESS;
1788590a0fdSAndre Fischer }
1798590a0fdSAndre Fischer 
1808590a0fdSAndre Fischer // HEAD
1818590a0fdSAndre Fischer bool SerfRequestProcessor::processHead( const std::vector< ::rtl::OUString > & inHeaderNames,
1828590a0fdSAndre Fischer                                         DAVResource & ioResource,
1838590a0fdSAndre Fischer                                         apr_status_t& outSerfStatus )
1848590a0fdSAndre Fischer {
1858590a0fdSAndre Fischer     mpProcImpl = createHeadReqProcImpl( mPathStr,
186e9ff7e89SOliver-Rainer Wittmann                                         mrSerfSession.getRequestEnvironment().m_aRequestHeaders,
1878590a0fdSAndre Fischer                                         inHeaderNames,
1888590a0fdSAndre Fischer                                         ioResource );
1898590a0fdSAndre Fischer     outSerfStatus = runProcessor();
1908590a0fdSAndre Fischer 
1918590a0fdSAndre Fischer     return outSerfStatus == APR_SUCCESS;
1928590a0fdSAndre Fischer }
1938590a0fdSAndre Fischer 
1948590a0fdSAndre Fischer // PUT
1958590a0fdSAndre Fischer bool SerfRequestProcessor::processPut( const char* inData,
1968590a0fdSAndre Fischer                                        apr_size_t inDataLen,
1978590a0fdSAndre Fischer                                        apr_status_t& outSerfStatus )
1988590a0fdSAndre Fischer {
1998590a0fdSAndre Fischer     mpProcImpl = createPutReqProcImpl( mPathStr,
200e9ff7e89SOliver-Rainer Wittmann                                        mrSerfSession.getRequestEnvironment().m_aRequestHeaders,
2018590a0fdSAndre Fischer                                        inData,
2028590a0fdSAndre Fischer                                        inDataLen );
2038590a0fdSAndre Fischer     outSerfStatus = runProcessor();
2048590a0fdSAndre Fischer 
2058590a0fdSAndre Fischer     return outSerfStatus == APR_SUCCESS;
2068590a0fdSAndre Fischer }
2078590a0fdSAndre Fischer 
2088590a0fdSAndre Fischer // POST
2098590a0fdSAndre Fischer bool SerfRequestProcessor::processPost( const char* inData,
2108590a0fdSAndre Fischer                                         apr_size_t inDataLen,
2118590a0fdSAndre Fischer                                         const rtl::OUString & inContentType,
2128590a0fdSAndre Fischer                                         const rtl::OUString & inReferer,
2138590a0fdSAndre Fischer                                         const com::sun::star::uno::Reference< SerfInputStream >& xioInStrm,
2148590a0fdSAndre Fischer                                         apr_status_t& outSerfStatus )
2158590a0fdSAndre Fischer {
2168590a0fdSAndre Fischer     mContentType = apr_pstrdup( mrSerfSession.getAprPool(),
2178590a0fdSAndre Fischer                                 rtl::OUStringToOString( inContentType, RTL_TEXTENCODING_UTF8 ) );
2188590a0fdSAndre Fischer     mReferer = apr_pstrdup( mrSerfSession.getAprPool(),
2198590a0fdSAndre Fischer                                 rtl::OUStringToOString( inReferer, RTL_TEXTENCODING_UTF8 ) );
2208590a0fdSAndre Fischer     mpProcImpl = createPostReqProcImpl( mPathStr,
221e9ff7e89SOliver-Rainer Wittmann                                         mrSerfSession.getRequestEnvironment().m_aRequestHeaders,
2228590a0fdSAndre Fischer                                         inData,
2238590a0fdSAndre Fischer                                         inDataLen,
2248590a0fdSAndre Fischer                                         mContentType,
2258590a0fdSAndre Fischer                                         mReferer,
2268590a0fdSAndre Fischer                                         xioInStrm );
2278590a0fdSAndre Fischer     outSerfStatus = runProcessor();
2288590a0fdSAndre Fischer 
2298590a0fdSAndre Fischer     return outSerfStatus == APR_SUCCESS;
2308590a0fdSAndre Fischer }
2318590a0fdSAndre Fischer 
2328590a0fdSAndre Fischer // POST
2338590a0fdSAndre Fischer bool SerfRequestProcessor::processPost( const char* inData,
2348590a0fdSAndre Fischer                                         apr_size_t inDataLen,
2358590a0fdSAndre Fischer                                         const rtl::OUString & inContentType,
2368590a0fdSAndre Fischer                                         const rtl::OUString & inReferer,
2378590a0fdSAndre Fischer                                         const com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& xioOutStrm,
2388590a0fdSAndre Fischer                                         apr_status_t& outSerfStatus )
2398590a0fdSAndre Fischer {
2408590a0fdSAndre Fischer     mContentType = apr_pstrdup( mrSerfSession.getAprPool(),
2418590a0fdSAndre Fischer                                 rtl::OUStringToOString( inContentType, RTL_TEXTENCODING_UTF8 ) );
2428590a0fdSAndre Fischer     mReferer = apr_pstrdup( mrSerfSession.getAprPool(),
2438590a0fdSAndre Fischer                             rtl::OUStringToOString( inReferer, RTL_TEXTENCODING_UTF8 ) );
2448590a0fdSAndre Fischer     mpProcImpl = createPostReqProcImpl( mPathStr,
245e9ff7e89SOliver-Rainer Wittmann                                         mrSerfSession.getRequestEnvironment().m_aRequestHeaders,
2468590a0fdSAndre Fischer                                         inData,
2478590a0fdSAndre Fischer                                         inDataLen,
2488590a0fdSAndre Fischer                                         mContentType,
2498590a0fdSAndre Fischer                                         mReferer,
2508590a0fdSAndre Fischer                                         xioOutStrm );
2518590a0fdSAndre Fischer     outSerfStatus = runProcessor();
2528590a0fdSAndre Fischer 
2538590a0fdSAndre Fischer     return outSerfStatus == APR_SUCCESS;
2548590a0fdSAndre Fischer }
2558590a0fdSAndre Fischer 
2568590a0fdSAndre Fischer // DELETE
2578590a0fdSAndre Fischer bool SerfRequestProcessor::processDelete( apr_status_t& outSerfStatus )
2588590a0fdSAndre Fischer {
259e9ff7e89SOliver-Rainer Wittmann     mpProcImpl = createDeleteReqProcImpl( mPathStr,
260e9ff7e89SOliver-Rainer Wittmann                                           mrSerfSession.getRequestEnvironment().m_aRequestHeaders );
2618590a0fdSAndre Fischer     outSerfStatus = runProcessor();
2628590a0fdSAndre Fischer 
2638590a0fdSAndre Fischer     return outSerfStatus == APR_SUCCESS;
2648590a0fdSAndre Fischer }
2658590a0fdSAndre Fischer 
2668590a0fdSAndre Fischer // MKCOL
2678590a0fdSAndre Fischer bool SerfRequestProcessor::processMkCol( apr_status_t& outSerfStatus )
2688590a0fdSAndre Fischer {
269e9ff7e89SOliver-Rainer Wittmann     mpProcImpl = createMkColReqProcImpl( mPathStr,
270e9ff7e89SOliver-Rainer Wittmann                                          mrSerfSession.getRequestEnvironment().m_aRequestHeaders );
2718590a0fdSAndre Fischer     outSerfStatus = runProcessor();
2728590a0fdSAndre Fischer 
2738590a0fdSAndre Fischer     return outSerfStatus == APR_SUCCESS;
2748590a0fdSAndre Fischer }
2758590a0fdSAndre Fischer 
2768590a0fdSAndre Fischer // COPY
2778590a0fdSAndre Fischer bool SerfRequestProcessor::processCopy( const rtl::OUString & inDestinationPath,
2788590a0fdSAndre Fischer                                         const bool inOverwrite,
2798590a0fdSAndre Fischer                                         apr_status_t& outSerfStatus )
2808590a0fdSAndre Fischer {
2818590a0fdSAndre Fischer     mDestPathStr = apr_pstrdup( mrSerfSession.getAprPool(),
2828590a0fdSAndre Fischer                                 rtl::OUStringToOString( inDestinationPath, RTL_TEXTENCODING_UTF8 ) );
2838590a0fdSAndre Fischer     mpProcImpl = createCopyReqProcImpl( mPathStr,
284e9ff7e89SOliver-Rainer Wittmann                                         mrSerfSession.getRequestEnvironment().m_aRequestHeaders,
2858590a0fdSAndre Fischer                                         mDestPathStr,
2868590a0fdSAndre Fischer                                         inOverwrite );
2878590a0fdSAndre Fischer     outSerfStatus = runProcessor();
2888590a0fdSAndre Fischer 
2898590a0fdSAndre Fischer     return outSerfStatus == APR_SUCCESS;
2908590a0fdSAndre Fischer }
2918590a0fdSAndre Fischer 
2928590a0fdSAndre Fischer // MOVE
2938590a0fdSAndre Fischer bool SerfRequestProcessor::processMove( const rtl::OUString & inDestinationPath,
2948590a0fdSAndre Fischer                                         const bool inOverwrite,
2958590a0fdSAndre Fischer                                         apr_status_t& outSerfStatus )
2968590a0fdSAndre Fischer {
2978590a0fdSAndre Fischer     mDestPathStr = apr_pstrdup( mrSerfSession.getAprPool(),
2988590a0fdSAndre Fischer                                 rtl::OUStringToOString( inDestinationPath, RTL_TEXTENCODING_UTF8 ) );
2998590a0fdSAndre Fischer     mpProcImpl = createMoveReqProcImpl( mPathStr,
300e9ff7e89SOliver-Rainer Wittmann                                         mrSerfSession.getRequestEnvironment().m_aRequestHeaders,
3018590a0fdSAndre Fischer                                         mDestPathStr,
3028590a0fdSAndre Fischer                                         inOverwrite );
3038590a0fdSAndre Fischer     outSerfStatus = runProcessor();
3048590a0fdSAndre Fischer 
3058590a0fdSAndre Fischer     return outSerfStatus == APR_SUCCESS;
3068590a0fdSAndre Fischer }
3078590a0fdSAndre Fischer 
3088590a0fdSAndre Fischer apr_status_t SerfRequestProcessor::runProcessor()
3098590a0fdSAndre Fischer {
3108590a0fdSAndre Fischer     prepareProcessor();
3118590a0fdSAndre Fischer 
31249989859SOliver-Rainer Wittmann     // activate chunked encoding, if requested
31349989859SOliver-Rainer Wittmann     if ( mbUseChunkedEncoding )
31449989859SOliver-Rainer Wittmann     {
31549989859SOliver-Rainer Wittmann         mpProcImpl->activateChunkedEncoding();
31649989859SOliver-Rainer Wittmann     }
31749989859SOliver-Rainer Wittmann 
3188590a0fdSAndre Fischer     // create serf request
3198590a0fdSAndre Fischer     serf_connection_request_create( mrSerfSession.getSerfConnection(),
3208590a0fdSAndre Fischer                                     Serf_SetupRequest,
3218590a0fdSAndre Fischer                                     this );
3228590a0fdSAndre Fischer 
3238590a0fdSAndre Fischer     // perform serf request
3248590a0fdSAndre Fischer     mbProcessingDone = false;
3258590a0fdSAndre Fischer     apr_status_t status = APR_SUCCESS;
3268590a0fdSAndre Fischer     serf_context_t* pSerfContext = mrSerfSession.getSerfContext();
3278590a0fdSAndre Fischer     apr_pool_t* pAprPool = mrSerfSession.getAprPool();
3288590a0fdSAndre Fischer     while ( true )
3298590a0fdSAndre Fischer     {
3308590a0fdSAndre Fischer         status = serf_context_run( pSerfContext,
3318590a0fdSAndre Fischer                                    SERF_DURATION_FOREVER,
3328590a0fdSAndre Fischer                                    pAprPool );
3338590a0fdSAndre Fischer         if ( APR_STATUS_IS_TIMEUP( status ) )
3348590a0fdSAndre Fischer         {
3358590a0fdSAndre Fischer             continue;
3368590a0fdSAndre Fischer         }
3378590a0fdSAndre Fischer         if ( status != APR_SUCCESS )
3388590a0fdSAndre Fischer         {
3398590a0fdSAndre Fischer             break;
3408590a0fdSAndre Fischer         }
3418590a0fdSAndre Fischer         if ( mbProcessingDone )
3428590a0fdSAndre Fischer         {
3438590a0fdSAndre Fischer             break;
3448590a0fdSAndre Fischer         }
3458590a0fdSAndre Fischer     }
3468590a0fdSAndre Fischer 
3478590a0fdSAndre Fischer     postprocessProcessor( status );
3488590a0fdSAndre Fischer 
3498590a0fdSAndre Fischer     return status;
3508590a0fdSAndre Fischer }
3518590a0fdSAndre Fischer 
3528590a0fdSAndre Fischer void SerfRequestProcessor::postprocessProcessor( const apr_status_t inStatus )
3538590a0fdSAndre Fischer {
3548590a0fdSAndre Fischer     if ( inStatus == APR_SUCCESS )
3558590a0fdSAndre Fischer     {
3568590a0fdSAndre Fischer         return;
3578590a0fdSAndre Fischer     }
3588590a0fdSAndre Fischer 
3598590a0fdSAndre Fischer     switch ( inStatus )
3608590a0fdSAndre Fischer     {
3618590a0fdSAndre Fischer     case APR_EGENERAL:
362fb7f54d2SOliver-Rainer Wittmann     case SERF_ERROR_AUTHN_FAILED:
3638590a0fdSAndre Fischer         // general error; <mnHTTPStatusCode> provides more information
3648590a0fdSAndre Fischer         {
3658590a0fdSAndre Fischer             switch ( mnHTTPStatusCode )
3668590a0fdSAndre Fischer             {
3678590a0fdSAndre Fischer             case SC_NONE:
3688590a0fdSAndre Fischer                 if ( !mbSetupSerfRequestCalled )
3698590a0fdSAndre Fischer                 {
3708590a0fdSAndre Fischer                     mpDAVException = new DAVException( DAVException::DAV_HTTP_LOOKUP,
3718590a0fdSAndre Fischer                                                        SerfUri::makeConnectionEndPointString( mrSerfSession.getHostName(),
3728590a0fdSAndre Fischer                                                                                               mrSerfSession.getPort() ) );
3738590a0fdSAndre Fischer                 }
374fb7f54d2SOliver-Rainer Wittmann                 else if ( mbInputOfCredentialsAborted )
375fb7f54d2SOliver-Rainer Wittmann                 {
376fb7f54d2SOliver-Rainer Wittmann                     mpDAVException = new DAVException( DAVException::DAV_HTTP_NOAUTH,
377fb7f54d2SOliver-Rainer Wittmann                                                        SerfUri::makeConnectionEndPointString( mrSerfSession.getHostName(),
378fb7f54d2SOliver-Rainer Wittmann                                                                                               mrSerfSession.getPort() ) );
379fb7f54d2SOliver-Rainer Wittmann                 }
3808590a0fdSAndre Fischer                 else
3818590a0fdSAndre Fischer                 {
3828590a0fdSAndre Fischer                     mpDAVException = new DAVException( DAVException::DAV_HTTP_ERROR,
3838590a0fdSAndre Fischer                                                        mHTTPStatusCodeText,
3848590a0fdSAndre Fischer                                                        mnHTTPStatusCode );
3858590a0fdSAndre Fischer                 }
3868590a0fdSAndre Fischer                 break;
3878590a0fdSAndre Fischer             case SC_MOVED_PERMANENTLY:
3888590a0fdSAndre Fischer             case SC_MOVED_TEMPORARILY:
3898590a0fdSAndre Fischer             case SC_SEE_OTHER:
3908590a0fdSAndre Fischer             case SC_TEMPORARY_REDIRECT:
3918590a0fdSAndre Fischer                 mpDAVException = new DAVException( DAVException::DAV_HTTP_REDIRECT,
3928590a0fdSAndre Fischer                                                    mRedirectLocation );
3938590a0fdSAndre Fischer                 break;
3948590a0fdSAndre Fischer             default:
3958590a0fdSAndre Fischer                 mpDAVException = new DAVException( DAVException::DAV_HTTP_ERROR,
3968590a0fdSAndre Fischer                                                    mHTTPStatusCodeText,
3978590a0fdSAndre Fischer                                                    mnHTTPStatusCode );
3988590a0fdSAndre Fischer                 break;
3998590a0fdSAndre Fischer             }
4008590a0fdSAndre Fischer         }
4018590a0fdSAndre Fischer         break;
4028590a0fdSAndre Fischer 
4038590a0fdSAndre Fischer     default:
4048590a0fdSAndre Fischer         mpDAVException = new DAVException( DAVException::DAV_HTTP_ERROR );
4058590a0fdSAndre Fischer         break;
4068590a0fdSAndre Fischer     }
4078590a0fdSAndre Fischer 
4088590a0fdSAndre Fischer }
4098590a0fdSAndre Fischer 
4108590a0fdSAndre Fischer apr_status_t SerfRequestProcessor::provideSerfCredentials( char ** outUsername,
4118590a0fdSAndre Fischer                                                            char ** outPassword,
4128590a0fdSAndre Fischer                                                            serf_request_t * inRequest,
4138590a0fdSAndre Fischer                                                            int inCode,
4148590a0fdSAndre Fischer                                                            const char *inAuthProtocol,
4158590a0fdSAndre Fischer                                                            const char *inRealm,
4168590a0fdSAndre Fischer                                                            apr_pool_t *inAprPool )
4178590a0fdSAndre Fischer {
418fb7f54d2SOliver-Rainer Wittmann     // as each successful provided credentials are tried twice - see below - the
419fb7f54d2SOliver-Rainer Wittmann     // number of real attempts is half of the value of <mnSuccessfulCredentialAttempts>
420fb7f54d2SOliver-Rainer Wittmann     if ( (mnSuccessfulCredentialAttempts / 2) >= 5 ||
421fb7f54d2SOliver-Rainer Wittmann          mbInputOfCredentialsAborted )
422fb7f54d2SOliver-Rainer Wittmann     {
423fb7f54d2SOliver-Rainer Wittmann         mbInputOfCredentialsAborted = true;
424fb7f54d2SOliver-Rainer Wittmann         return SERF_ERROR_AUTHN_FAILED;
425fb7f54d2SOliver-Rainer Wittmann     }
426fb7f54d2SOliver-Rainer Wittmann 
427fb7f54d2SOliver-Rainer Wittmann     // because serf keeps credentials only for a connection in case of digest authentication
428fb7f54d2SOliver-Rainer Wittmann     // we give each successful provided credentials a second try in order to workaround the
429fb7f54d2SOliver-Rainer Wittmann     // situation that the connection for which the credentials have been provided has been closed
430fb7f54d2SOliver-Rainer Wittmann     // before the provided credentials could be applied for the request.
431fb7f54d2SOliver-Rainer Wittmann     apr_status_t status = mrSerfSession.provideSerfCredentials( (mnSuccessfulCredentialAttempts % 2) == 1,
432fb7f54d2SOliver-Rainer Wittmann                                                                 outUsername,
4338590a0fdSAndre Fischer                                                                 outPassword,
4348590a0fdSAndre Fischer                                                                 inRequest,
4358590a0fdSAndre Fischer                                                                 inCode,
4368590a0fdSAndre Fischer                                                                 inAuthProtocol,
4378590a0fdSAndre Fischer                                                                 inRealm,
4388590a0fdSAndre Fischer                                                                 inAprPool );
439fb7f54d2SOliver-Rainer Wittmann     if ( status != APR_SUCCESS )
440fb7f54d2SOliver-Rainer Wittmann     {
441fb7f54d2SOliver-Rainer Wittmann         mbInputOfCredentialsAborted = true;
442fb7f54d2SOliver-Rainer Wittmann     }
443fb7f54d2SOliver-Rainer Wittmann     else
444fb7f54d2SOliver-Rainer Wittmann     {
445fb7f54d2SOliver-Rainer Wittmann         ++mnSuccessfulCredentialAttempts;
446fb7f54d2SOliver-Rainer Wittmann     }
447fb7f54d2SOliver-Rainer Wittmann 
448fb7f54d2SOliver-Rainer Wittmann     return status;
4498590a0fdSAndre Fischer }
4508590a0fdSAndre Fischer 
4518590a0fdSAndre Fischer apr_status_t SerfRequestProcessor::setupSerfRequest( serf_request_t * inSerfRequest,
4528590a0fdSAndre Fischer                                    serf_bucket_t ** outSerfRequestBucket,
4538590a0fdSAndre Fischer                                    serf_response_acceptor_t * outSerfResponseAcceptor,
4548590a0fdSAndre Fischer                                    void ** outSerfResponseAcceptorBaton,
4558590a0fdSAndre Fischer                                    serf_response_handler_t * outSerfResponseHandler,
4568590a0fdSAndre Fischer                                    void ** outSerfResponseHandlerBaton,
4578590a0fdSAndre Fischer                                    apr_pool_t * /*inAprPool*/ )
4588590a0fdSAndre Fischer {
4598590a0fdSAndre Fischer     mbSetupSerfRequestCalled = true;
4608590a0fdSAndre Fischer     *outSerfRequestBucket = mpProcImpl->createSerfRequestBucket( inSerfRequest );
4618590a0fdSAndre Fischer 
4628590a0fdSAndre Fischer     // apply callbacks for accepting response and handling response
4638590a0fdSAndre Fischer     *outSerfResponseAcceptor = Serf_AcceptResponse;
4648590a0fdSAndre Fischer     *outSerfResponseAcceptorBaton = this;
4658590a0fdSAndre Fischer     *outSerfResponseHandler = Serf_HandleResponse;
4668590a0fdSAndre Fischer     *outSerfResponseHandlerBaton = this;
4678590a0fdSAndre Fischer 
4688590a0fdSAndre Fischer     return APR_SUCCESS;
4698590a0fdSAndre Fischer }
4708590a0fdSAndre Fischer 
4718590a0fdSAndre Fischer serf_bucket_t* SerfRequestProcessor::acceptSerfResponse( serf_request_t * inSerfRequest,
4728590a0fdSAndre Fischer                                                          serf_bucket_t * inSerfStreamBucket,
4738590a0fdSAndre Fischer                                                          apr_pool_t * inAprPool )
4748590a0fdSAndre Fischer {
4758590a0fdSAndre Fischer     mbAcceptSerfResponseCalled = true;
4768590a0fdSAndre Fischer     return mrSerfSession.acceptSerfResponse( inSerfRequest,
4778590a0fdSAndre Fischer                                              inSerfStreamBucket,
4788590a0fdSAndre Fischer                                              inAprPool );
4798590a0fdSAndre Fischer }
4808590a0fdSAndre Fischer 
4818590a0fdSAndre Fischer apr_status_t SerfRequestProcessor::handleSerfResponse( serf_request_t * inSerfRequest,
4828590a0fdSAndre Fischer                                                        serf_bucket_t * inSerfResponseBucket,
4838590a0fdSAndre Fischer                                                        apr_pool_t * inAprPool )
4848590a0fdSAndre Fischer {
4858590a0fdSAndre Fischer     mbHandleSerfResponseCalled = true;
4868590a0fdSAndre Fischer 
4878590a0fdSAndre Fischer     // some general response handling and error handling
4888590a0fdSAndre Fischer     {
4898590a0fdSAndre Fischer         if ( !inSerfResponseBucket )
4908590a0fdSAndre Fischer         {
4918590a0fdSAndre Fischer             /* A NULL response can come back if the request failed completely */
4928590a0fdSAndre Fischer             mbProcessingDone = true;
4938590a0fdSAndre Fischer             return APR_EGENERAL;
4948590a0fdSAndre Fischer         }
4958590a0fdSAndre Fischer 
4968590a0fdSAndre Fischer         serf_status_line sl;
4978590a0fdSAndre Fischer         apr_status_t status = serf_bucket_response_status( inSerfResponseBucket, &sl );
4988590a0fdSAndre Fischer         if ( status )
4998590a0fdSAndre Fischer         {
5008590a0fdSAndre Fischer             mbProcessingDone = false; // allow another try in order to get a response
5018590a0fdSAndre Fischer             return status;
5028590a0fdSAndre Fischer         }
5038590a0fdSAndre Fischer         // TODO - check, if response status code handling is correct
5048590a0fdSAndre Fischer         mnHTTPStatusCode = ( sl.version != 0 && sl.code >= 0 )
5058590a0fdSAndre Fischer                            ? static_cast< sal_uInt16 >( sl.code )
5068590a0fdSAndre Fischer                            : SC_NONE;
5078590a0fdSAndre Fischer         if ( sl.reason )
5088590a0fdSAndre Fischer         {
5098590a0fdSAndre Fischer             mHTTPStatusCodeText = ::rtl::OUString::createFromAscii( sl.reason );
5108590a0fdSAndre Fischer         }
5118590a0fdSAndre Fischer         if ( ( sl.version == 0 || sl.code < 0 ) ||
5128590a0fdSAndre Fischer              mnHTTPStatusCode >= 300 )
5138590a0fdSAndre Fischer         {
5148590a0fdSAndre Fischer             if ( mnHTTPStatusCode == 301 ||
5158590a0fdSAndre Fischer                  mnHTTPStatusCode == 302 ||
5168590a0fdSAndre Fischer                  mnHTTPStatusCode == 303 ||
5178590a0fdSAndre Fischer                  mnHTTPStatusCode == 307 )
5188590a0fdSAndre Fischer             {
5198590a0fdSAndre Fischer                 // new location for certain redirections
5208590a0fdSAndre Fischer                 serf_bucket_t *headers = serf_bucket_response_get_headers( inSerfResponseBucket );
5218590a0fdSAndre Fischer                 const char* location = serf_bucket_headers_get( headers, "Location" );
5228590a0fdSAndre Fischer                 if ( location )
5238590a0fdSAndre Fischer                 {
5248590a0fdSAndre Fischer                     mRedirectLocation = rtl::OUString::createFromAscii( location );
5258590a0fdSAndre Fischer                 }
5268590a0fdSAndre Fischer                 mbProcessingDone = true;
5278590a0fdSAndre Fischer                 return APR_EGENERAL;
5288590a0fdSAndre Fischer             }
5298590a0fdSAndre Fischer             else if ( mrSerfSession.isHeadRequestInProgress() &&
5308590a0fdSAndre Fischer                       ( mnHTTPStatusCode == 401 || mnHTTPStatusCode == 407 ) )
5318590a0fdSAndre Fischer             {
5328590a0fdSAndre Fischer                 // keep going as authentication is not required on HEAD request.
5338590a0fdSAndre Fischer                 // the response already contains header fields.
5348590a0fdSAndre Fischer             }
5358590a0fdSAndre Fischer             else
5368590a0fdSAndre Fischer             {
5378590a0fdSAndre Fischer                 mbProcessingDone = true;
5388590a0fdSAndre Fischer                 return APR_EGENERAL;
5398590a0fdSAndre Fischer             }
5408590a0fdSAndre Fischer         }
5418590a0fdSAndre Fischer     }
5428590a0fdSAndre Fischer 
5438590a0fdSAndre Fischer     // request specific processing of the response bucket
5448590a0fdSAndre Fischer     apr_status_t status = APR_SUCCESS;
5458590a0fdSAndre Fischer     mbProcessingDone = mpProcImpl->processSerfResponseBucket( inSerfRequest,
5468590a0fdSAndre Fischer                                                               inSerfResponseBucket,
5478590a0fdSAndre Fischer                                                               inAprPool,
5488590a0fdSAndre Fischer                                                               status );
5498590a0fdSAndre Fischer 
5508590a0fdSAndre Fischer     return status;
5518590a0fdSAndre Fischer }
5528590a0fdSAndre Fischer 
5538590a0fdSAndre Fischer } // namespace http_dav_ucp
5548590a0fdSAndre Fischer 
555