19646dec5SDamjan Jovanovic /**************************************************************
29646dec5SDamjan Jovanovic  *
39646dec5SDamjan Jovanovic  * Licensed to the Apache Software Foundation (ASF) under one
49646dec5SDamjan Jovanovic  * or more contributor license agreements.  See the NOTICE file
59646dec5SDamjan Jovanovic  * distributed with this work for additional information
69646dec5SDamjan Jovanovic  * regarding copyright ownership.  The ASF licenses this file
79646dec5SDamjan Jovanovic  * to you under the Apache License, Version 2.0 (the
89646dec5SDamjan Jovanovic  * "License"); you may not use this file except in compliance
99646dec5SDamjan Jovanovic  * with the License.  You may obtain a copy of the License at
109646dec5SDamjan Jovanovic  *
119646dec5SDamjan Jovanovic  *   http://www.apache.org/licenses/LICENSE-2.0
129646dec5SDamjan Jovanovic  *
139646dec5SDamjan Jovanovic  * Unless required by applicable law or agreed to in writing,
149646dec5SDamjan Jovanovic  * software distributed under the License is distributed on an
159646dec5SDamjan Jovanovic  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
169646dec5SDamjan Jovanovic  * KIND, either express or implied.  See the License for the
179646dec5SDamjan Jovanovic  * specific language governing permissions and limitations
189646dec5SDamjan Jovanovic  * under the License.
199646dec5SDamjan Jovanovic  *
209646dec5SDamjan Jovanovic  *************************************************************/
219646dec5SDamjan Jovanovic 
229646dec5SDamjan Jovanovic 
239646dec5SDamjan Jovanovic 
249646dec5SDamjan Jovanovic // MARKER(update_precomp.py): autogen include statement, do not remove
259646dec5SDamjan Jovanovic #include "precompiled_webdav.hxx"
269646dec5SDamjan Jovanovic 
279646dec5SDamjan Jovanovic #include "CurlRequest.hxx"
289646dec5SDamjan Jovanovic 
29*b28b64c2SDamjan Jovanovic #include <string.h>
30*b28b64c2SDamjan Jovanovic 
319646dec5SDamjan Jovanovic using namespace ::com::sun::star;
329646dec5SDamjan Jovanovic using namespace http_dav_ucp;
339646dec5SDamjan Jovanovic 
CurlRequest(CURL * curl)349646dec5SDamjan Jovanovic CurlRequest::CurlRequest( CURL *curl )
359646dec5SDamjan Jovanovic     : curl( curl )
369646dec5SDamjan Jovanovic     , curlUrl( NULL )
379646dec5SDamjan Jovanovic     , requestHeaders( NULL )
389646dec5SDamjan Jovanovic     , requestBody( NULL )
399646dec5SDamjan Jovanovic     , requestBodyOffset( 0 )
409646dec5SDamjan Jovanovic     , requestBodySize( 0 )
419646dec5SDamjan Jovanovic     , useChunkedEncoding( false )
429646dec5SDamjan Jovanovic     , provideCredentialsCallback( NULL )
439646dec5SDamjan Jovanovic     , provideCredentialsUserdata( NULL )
449646dec5SDamjan Jovanovic     , statusCode( 0 )
459646dec5SDamjan Jovanovic     , responseBodyInputStream( new CurlInputStream() )
469646dec5SDamjan Jovanovic {
479646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HEADERFUNCTION, Curl_HeaderReceived );
489646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HEADERDATA, this );
499646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, Curl_MoreBodyReceived );
509646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_WRITEDATA, this );
519646dec5SDamjan Jovanovic }
529646dec5SDamjan Jovanovic 
~CurlRequest()539646dec5SDamjan Jovanovic CurlRequest::~CurlRequest()
549646dec5SDamjan Jovanovic {
559646dec5SDamjan Jovanovic     if ( curlUrl != NULL )
569646dec5SDamjan Jovanovic         curl_url_cleanup( curlUrl );
579646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CURLU, NULL );
589646dec5SDamjan Jovanovic 
599646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPHEADER, NULL );
609646dec5SDamjan Jovanovic     if ( requestHeaders != NULL )
619646dec5SDamjan Jovanovic         curl_slist_free_all( requestHeaders );
629646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_READFUNCTION, NULL );
639646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_READDATA, NULL );
649646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_INFILESIZE, -1 );
659646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_SEEKFUNCTION, NULL );
669646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_SEEKDATA, NULL );
679646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HEADERFUNCTION, NULL );
689646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HEADERDATA, NULL );
699646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, NULL );
709646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, NULL );
719646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_WRITEDATA, NULL );
729646dec5SDamjan Jovanovic }
739646dec5SDamjan Jovanovic 
addHeader(const rtl::OString & name,const rtl::OString & value)749646dec5SDamjan Jovanovic void CurlRequest::addHeader( const rtl::OString &name, const rtl::OString &value) throw (DAVException)
759646dec5SDamjan Jovanovic {
769646dec5SDamjan Jovanovic     rtl::OString line = name + ": " + value;
779646dec5SDamjan Jovanovic     struct curl_slist *appended = curl_slist_append( requestHeaders, line.getStr() );
789646dec5SDamjan Jovanovic     if ( appended != NULL )
799646dec5SDamjan Jovanovic     {
809646dec5SDamjan Jovanovic         requestHeaders = appended;
819646dec5SDamjan Jovanovic         curl_easy_setopt( curl, CURLOPT_HTTPHEADER, requestHeaders );
829646dec5SDamjan Jovanovic     }
839646dec5SDamjan Jovanovic     else
849646dec5SDamjan Jovanovic         throw DAVException( DAVException::DAV_SESSION_CREATE, rtl::OUString::createFromAscii( "Out of memory" ) );
859646dec5SDamjan Jovanovic }
869646dec5SDamjan Jovanovic 
setRequestBody(const char * body,size_t size)879646dec5SDamjan Jovanovic void CurlRequest::setRequestBody( const char *body, size_t size )
889646dec5SDamjan Jovanovic {
899646dec5SDamjan Jovanovic     requestBody = body;
909646dec5SDamjan Jovanovic     requestBodyOffset = 0;
919646dec5SDamjan Jovanovic     requestBodySize = size;
929646dec5SDamjan Jovanovic 
939646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_READFUNCTION, Curl_SendMoreBody );
949646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_READDATA, this );
959646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_SEEKFUNCTION, Curl_SeekCallback );
969646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_SEEKDATA, this );
979646dec5SDamjan Jovanovic     if ( useChunkedEncoding )
989646dec5SDamjan Jovanovic         addHeader( "Transfer-Encoding", "chunked" );
999646dec5SDamjan Jovanovic     else
1009646dec5SDamjan Jovanovic         curl_easy_setopt( curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)size );
1019646dec5SDamjan Jovanovic }
1029646dec5SDamjan Jovanovic 
Curl_SeekCallback(void * userdata,curl_off_t offset,int origin)1039646dec5SDamjan Jovanovic int CurlRequest::Curl_SeekCallback( void *userdata, curl_off_t offset, int origin )
1049646dec5SDamjan Jovanovic {
1059646dec5SDamjan Jovanovic     CurlRequest *request = static_cast< CurlRequest* >( userdata );
1069646dec5SDamjan Jovanovic     if ( origin == SEEK_SET )
1079646dec5SDamjan Jovanovic         request->requestBodyOffset = (size_t) offset;
1089646dec5SDamjan Jovanovic     else if ( origin == SEEK_CUR )
1099646dec5SDamjan Jovanovic         request->requestBodyOffset += (size_t) offset;
1109646dec5SDamjan Jovanovic     else if ( origin == SEEK_END )
1119646dec5SDamjan Jovanovic         request->requestBodyOffset += (size_t) ((curl_off_t)request->requestBodySize + offset);
1129646dec5SDamjan Jovanovic     else
1139646dec5SDamjan Jovanovic         return CURL_SEEKFUNC_CANTSEEK;
1149646dec5SDamjan Jovanovic     if ( request->requestBodyOffset > request->requestBodySize )
1159646dec5SDamjan Jovanovic         request->requestBodyOffset = request->requestBodySize;
1169646dec5SDamjan Jovanovic     return CURL_SEEKFUNC_OK;
1179646dec5SDamjan Jovanovic }
1189646dec5SDamjan Jovanovic 
Curl_SendMoreBody(char * buffer,size_t size,size_t nitems,void * userdata)1199646dec5SDamjan Jovanovic size_t CurlRequest::Curl_SendMoreBody( char *buffer, size_t size, size_t nitems, void *userdata )
1209646dec5SDamjan Jovanovic {
1219646dec5SDamjan Jovanovic     CurlRequest *request = static_cast< CurlRequest* >( userdata );
1229646dec5SDamjan Jovanovic     OSL_TRACE("Curl_SendMoreBody");
1239646dec5SDamjan Jovanovic     return request->curlSendMoreBody( buffer, nitems );
1249646dec5SDamjan Jovanovic }
1259646dec5SDamjan Jovanovic 
curlSendMoreBody(char * buffer,size_t len)1269646dec5SDamjan Jovanovic size_t CurlRequest::curlSendMoreBody( char *buffer, size_t len )
1279646dec5SDamjan Jovanovic {
1289646dec5SDamjan Jovanovic     size_t bytesToSend = requestBodySize - requestBodyOffset;
1299646dec5SDamjan Jovanovic     if ( bytesToSend > len )
1309646dec5SDamjan Jovanovic         bytesToSend = len;
1319646dec5SDamjan Jovanovic     memcpy( buffer, requestBody, bytesToSend );
1329646dec5SDamjan Jovanovic     requestBodyOffset += bytesToSend;
1339646dec5SDamjan Jovanovic     return bytesToSend;
1349646dec5SDamjan Jovanovic }
1359646dec5SDamjan Jovanovic 
setProvideCredentialsCallback(bool (* callback)(long statusCode,void * userdata)throw (DAVException),void * userdata)1369646dec5SDamjan Jovanovic void CurlRequest::setProvideCredentialsCallback( bool (*callback)(long statusCode, void *userdata) throw (DAVException), void *userdata )
1379646dec5SDamjan Jovanovic {
1389646dec5SDamjan Jovanovic     provideCredentialsCallback = callback;
1399646dec5SDamjan Jovanovic     provideCredentialsUserdata = userdata;
1409646dec5SDamjan Jovanovic }
1419646dec5SDamjan Jovanovic 
setURI(CurlUri uri,rtl::OUString path)1429646dec5SDamjan Jovanovic void CurlRequest::setURI( CurlUri uri, rtl::OUString path ) throw (DAVException)
1439646dec5SDamjan Jovanovic {
1449646dec5SDamjan Jovanovic     if ( curlUrl != NULL )
1459646dec5SDamjan Jovanovic     {
1469646dec5SDamjan Jovanovic         curl_url_cleanup( curlUrl );
1479646dec5SDamjan Jovanovic         curlUrl = NULL;
1489646dec5SDamjan Jovanovic     }
1499646dec5SDamjan Jovanovic 
1509646dec5SDamjan Jovanovic     curlUrl = curl_url();
1519646dec5SDamjan Jovanovic     if ( curlUrl == NULL )
1529646dec5SDamjan Jovanovic         throw DAVException( DAVException::DAV_SESSION_CREATE, rtl::OUString::createFromAscii( "Out of memory" ) );
1539646dec5SDamjan Jovanovic 
1549646dec5SDamjan Jovanovic     if ( CurlUri( path ).GetHost().isEmpty() )
1559646dec5SDamjan Jovanovic     {
1569646dec5SDamjan Jovanovic         // "path" is really a path, not a URI
1579646dec5SDamjan Jovanovic         curl_url_set( curlUrl, CURLUPART_URL, rtl::OUStringToOString( uri.GetURI(), RTL_TEXTENCODING_UTF8 ).getStr(), 0 );
1589646dec5SDamjan Jovanovic         curl_url_set( curlUrl, CURLUPART_PATH, rtl::OUStringToOString( path, RTL_TEXTENCODING_UTF8 ).getStr(), 0 );
1599646dec5SDamjan Jovanovic     }
1609646dec5SDamjan Jovanovic     else
1619646dec5SDamjan Jovanovic     {
1629646dec5SDamjan Jovanovic         // The "path" is a full URI
1639646dec5SDamjan Jovanovic         curl_url_set( curlUrl, CURLUPART_URL, rtl::OUStringToOString( path, RTL_TEXTENCODING_UTF8 ).getStr(), 0 );
1649646dec5SDamjan Jovanovic     }
1659646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CURLU, curlUrl );
1669646dec5SDamjan Jovanovic }
1679646dec5SDamjan Jovanovic 
copy(CurlUri uri,rtl::OUString path)1689646dec5SDamjan Jovanovic CURLcode CurlRequest::copy( CurlUri uri, rtl::OUString path ) throw(DAVException)
1699646dec5SDamjan Jovanovic {
1709646dec5SDamjan Jovanovic     setURI( uri, path );
1719646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPGET, 1L );
1729646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "COPY" );
1739646dec5SDamjan Jovanovic     return perform();
1749646dec5SDamjan Jovanovic }
1759646dec5SDamjan Jovanovic 
delete_(CurlUri uri,rtl::OUString path)1769646dec5SDamjan Jovanovic CURLcode CurlRequest::delete_( CurlUri uri, rtl::OUString path ) throw (DAVException)
1779646dec5SDamjan Jovanovic {
1789646dec5SDamjan Jovanovic     setURI( uri, path );
1799646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPGET, 1L );
1809646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "DELETE" );
1819646dec5SDamjan Jovanovic     return perform();
1829646dec5SDamjan Jovanovic }
1839646dec5SDamjan Jovanovic 
get(CurlUri uri,rtl::OUString path)1849646dec5SDamjan Jovanovic CURLcode CurlRequest::get( CurlUri uri, rtl::OUString path ) throw(DAVException)
1859646dec5SDamjan Jovanovic {
1869646dec5SDamjan Jovanovic     setURI( uri, path );
1879646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPGET, 1L );
1889646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "GET" );
1899646dec5SDamjan Jovanovic     return perform();
1909646dec5SDamjan Jovanovic }
1919646dec5SDamjan Jovanovic 
head(CurlUri uri,rtl::OUString path)1929646dec5SDamjan Jovanovic CURLcode CurlRequest::head( CurlUri uri, rtl::OUString path ) throw (DAVException)
1939646dec5SDamjan Jovanovic {
1949646dec5SDamjan Jovanovic     setURI( uri, path );
1959646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_NOBODY, 1L );
1969646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "HEAD" );
1979646dec5SDamjan Jovanovic     return perform();
1989646dec5SDamjan Jovanovic }
1999646dec5SDamjan Jovanovic 
lock(CurlUri uri,rtl::OUString path)2009646dec5SDamjan Jovanovic CURLcode CurlRequest::lock( CurlUri uri, rtl::OUString path ) throw (DAVException)
2019646dec5SDamjan Jovanovic {
2029646dec5SDamjan Jovanovic     setURI( uri, path );
2039646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_UPLOAD, 1L );
2049646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "LOCK" );
2059646dec5SDamjan Jovanovic     return perform();
2069646dec5SDamjan Jovanovic }
2079646dec5SDamjan Jovanovic 
mkcol(CurlUri uri,rtl::OUString path)2089646dec5SDamjan Jovanovic CURLcode CurlRequest::mkcol( CurlUri uri, rtl::OUString path ) throw (DAVException)
2099646dec5SDamjan Jovanovic {
2109646dec5SDamjan Jovanovic     setURI( uri, path );
2119646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPGET, 1L );
2129646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "MKCOL" );
2139646dec5SDamjan Jovanovic     return perform();
2149646dec5SDamjan Jovanovic }
2159646dec5SDamjan Jovanovic 
move(CurlUri uri,rtl::OUString path)2169646dec5SDamjan Jovanovic CURLcode CurlRequest::move( CurlUri uri, rtl::OUString path ) throw (DAVException)
2179646dec5SDamjan Jovanovic {
2189646dec5SDamjan Jovanovic     setURI( uri, path );
2199646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPGET, 1L );
2209646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "MOVE" );
2219646dec5SDamjan Jovanovic     return perform();
2229646dec5SDamjan Jovanovic }
2239646dec5SDamjan Jovanovic 
post(CurlUri uri,rtl::OUString path)2249646dec5SDamjan Jovanovic CURLcode CurlRequest::post( CurlUri uri, rtl::OUString path ) throw (DAVException)
2259646dec5SDamjan Jovanovic {
2269646dec5SDamjan Jovanovic     setURI( uri, path );
2279646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_UPLOAD, 1L );
2289646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "POST" );
2299646dec5SDamjan Jovanovic     return perform();
2309646dec5SDamjan Jovanovic }
2319646dec5SDamjan Jovanovic 
propfind(CurlUri uri,rtl::OUString path)2329646dec5SDamjan Jovanovic CURLcode CurlRequest::propfind( CurlUri uri, rtl::OUString path ) throw (DAVException)
2339646dec5SDamjan Jovanovic {
2349646dec5SDamjan Jovanovic     setURI( uri, path );
2359646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_UPLOAD, 1L );
2369646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "PROPFIND" );
2379646dec5SDamjan Jovanovic     return perform();
2389646dec5SDamjan Jovanovic }
2399646dec5SDamjan Jovanovic 
proppatch(CurlUri uri,rtl::OUString path)2409646dec5SDamjan Jovanovic CURLcode CurlRequest::proppatch( CurlUri uri, rtl::OUString path ) throw (DAVException)
2419646dec5SDamjan Jovanovic {
2429646dec5SDamjan Jovanovic     setURI( uri, path );
2439646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_UPLOAD, 1L );
2449646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "PROPPATCH" );
2459646dec5SDamjan Jovanovic     return perform();
2469646dec5SDamjan Jovanovic }
2479646dec5SDamjan Jovanovic 
put(CurlUri uri,rtl::OUString path)2489646dec5SDamjan Jovanovic CURLcode CurlRequest::put( CurlUri uri, rtl::OUString path ) throw (DAVException)
2499646dec5SDamjan Jovanovic {
2509646dec5SDamjan Jovanovic     setURI( uri, path );
2519646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_UPLOAD, 1L );
2529646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "PUT" );
2539646dec5SDamjan Jovanovic     return perform();
2549646dec5SDamjan Jovanovic }
2559646dec5SDamjan Jovanovic 
unlock(CurlUri uri,rtl::OUString path)2569646dec5SDamjan Jovanovic CURLcode CurlRequest::unlock( CurlUri uri, rtl::OUString path ) throw (DAVException)
2579646dec5SDamjan Jovanovic {
2589646dec5SDamjan Jovanovic     setURI( uri, path );
2599646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPGET, 1L );
2609646dec5SDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "UNLOCK" );
2619646dec5SDamjan Jovanovic     return perform();
2629646dec5SDamjan Jovanovic }
2639646dec5SDamjan Jovanovic 
perform()2649646dec5SDamjan Jovanovic CURLcode CurlRequest::perform() throw (DAVException)
2659646dec5SDamjan Jovanovic {
2669646dec5SDamjan Jovanovic     CURLcode rc = curl_easy_perform( curl );
2679646dec5SDamjan Jovanovic     long statusCode = 0;
2689646dec5SDamjan Jovanovic     curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &statusCode );
2699646dec5SDamjan Jovanovic     if ( ( statusCode == 401 || statusCode == 407 ) && provideCredentialsCallback != NULL )
2709646dec5SDamjan Jovanovic     {
2719646dec5SDamjan Jovanovic         bool haveCredentials = provideCredentialsCallback( statusCode, provideCredentialsUserdata );
2729646dec5SDamjan Jovanovic         if ( haveCredentials )
2739646dec5SDamjan Jovanovic         {
2749646dec5SDamjan Jovanovic             // rewind body:
2759646dec5SDamjan Jovanovic             requestBodyOffset = 0;
2769646dec5SDamjan Jovanovic             // retry with credentials:
2779646dec5SDamjan Jovanovic             rc = curl_easy_perform( curl );
2789646dec5SDamjan Jovanovic             // If this was to authenticate with the proxy, we may need to authenticate
2799646dec5SDamjan Jovanovic             // with the destination host too:
2809646dec5SDamjan Jovanovic             if ( statusCode == 407 )
2819646dec5SDamjan Jovanovic             {
2829646dec5SDamjan Jovanovic                 curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &statusCode );
2839646dec5SDamjan Jovanovic                 if ( statusCode == 401 && provideCredentialsCallback != NULL )
2849646dec5SDamjan Jovanovic                 {
2859646dec5SDamjan Jovanovic                     haveCredentials = provideCredentialsCallback( statusCode, provideCredentialsUserdata );
2869646dec5SDamjan Jovanovic                     if ( haveCredentials )
2879646dec5SDamjan Jovanovic                     {
2889646dec5SDamjan Jovanovic                         // rewind body:
2899646dec5SDamjan Jovanovic                         requestBodyOffset = 0;
2909646dec5SDamjan Jovanovic                         // retry with credentials:
2919646dec5SDamjan Jovanovic                         rc = curl_easy_perform( curl );
2929646dec5SDamjan Jovanovic                     }
2939646dec5SDamjan Jovanovic                 }
2949646dec5SDamjan Jovanovic             }
2959646dec5SDamjan Jovanovic         }
2969646dec5SDamjan Jovanovic     }
2979646dec5SDamjan Jovanovic     return rc;
2989646dec5SDamjan Jovanovic }
2999646dec5SDamjan Jovanovic 
Curl_HeaderReceived(char * buffer,size_t size,size_t nitems,void * userdata)3009646dec5SDamjan Jovanovic size_t CurlRequest::Curl_HeaderReceived( char *buffer, size_t size, size_t nitems, void *userdata )
3019646dec5SDamjan Jovanovic {
3029646dec5SDamjan Jovanovic     CurlRequest *request = static_cast< CurlRequest* >( userdata );
3039646dec5SDamjan Jovanovic     OSL_TRACE("Curl_HeaderReceived");
3049646dec5SDamjan Jovanovic     request->curlHeaderReceived( buffer, nitems );
3059646dec5SDamjan Jovanovic     return nitems;
3069646dec5SDamjan Jovanovic }
3079646dec5SDamjan Jovanovic 
curlHeaderReceived(const char * buffer,size_t size)3089646dec5SDamjan Jovanovic void CurlRequest::curlHeaderReceived( const char *buffer, size_t size )
3099646dec5SDamjan Jovanovic {
3109646dec5SDamjan Jovanovic     rtl::OString lineCrLf( buffer, size );
3119646dec5SDamjan Jovanovic     sal_Int32 cr = lineCrLf.indexOf( "\r" );
3129646dec5SDamjan Jovanovic     if ( cr < 0 )
3139646dec5SDamjan Jovanovic         return;
3149646dec5SDamjan Jovanovic 
3159646dec5SDamjan Jovanovic     rtl::OString line = lineCrLf.copy( 0, cr );
3169646dec5SDamjan Jovanovic     if ( line.indexOf( "HTTP/" ) == 0 )
3179646dec5SDamjan Jovanovic     {
3189646dec5SDamjan Jovanovic         // Status line
3199646dec5SDamjan Jovanovic         // Throw away any response headers from a prior response:
3209646dec5SDamjan Jovanovic         responseHeaders.clear();
3219646dec5SDamjan Jovanovic         sal_Int32 idxFirstSpace = line.indexOf( ' ' );
3229646dec5SDamjan Jovanovic         if ( idxFirstSpace > 0 )
3239646dec5SDamjan Jovanovic         {
3249646dec5SDamjan Jovanovic             int idxSecondSpace = line.indexOf( ' ', idxFirstSpace + 1 );
3259646dec5SDamjan Jovanovic             if ( idxSecondSpace > 0 )
3269646dec5SDamjan Jovanovic             {
3279646dec5SDamjan Jovanovic                 reasonPhrase = line.copy( idxSecondSpace + 1 );
3289646dec5SDamjan Jovanovic                 statusCode = line.copy( idxFirstSpace + 1, idxSecondSpace - idxFirstSpace - 1 ).toInt32();
3299646dec5SDamjan Jovanovic             }
3309646dec5SDamjan Jovanovic             else
3319646dec5SDamjan Jovanovic             {
3329646dec5SDamjan Jovanovic                 reasonPhrase = "";
3339646dec5SDamjan Jovanovic                 statusCode = line.copy( idxFirstSpace + 1 ).toInt32();
3349646dec5SDamjan Jovanovic             }
3359646dec5SDamjan Jovanovic         }
3369646dec5SDamjan Jovanovic     }
3379646dec5SDamjan Jovanovic     else
3389646dec5SDamjan Jovanovic     {
3399646dec5SDamjan Jovanovic         // Header line
3409646dec5SDamjan Jovanovic         if ( line.getLength() == 0 )
3419646dec5SDamjan Jovanovic         {
3429646dec5SDamjan Jovanovic             // End of HTTP header
3439646dec5SDamjan Jovanovic             // Discard any intermediate body from 100 Trying or 401 Authentication required:
3449646dec5SDamjan Jovanovic             responseBodyInputStream = new CurlInputStream();
3459646dec5SDamjan Jovanovic             return;
3469646dec5SDamjan Jovanovic         }
3479646dec5SDamjan Jovanovic         sal_Int32 colon = line.indexOf( ':' );
3489646dec5SDamjan Jovanovic         if ( colon < 0 )
3499646dec5SDamjan Jovanovic         {
3509646dec5SDamjan Jovanovic             OSL_TRACE("Non-empty HTTP line without a ':'. Folded header deprecated by RFC 7230?");
3519646dec5SDamjan Jovanovic             return;
3529646dec5SDamjan Jovanovic         }
3539646dec5SDamjan Jovanovic         Header header;
3549646dec5SDamjan Jovanovic         header.name = line.copy( 0, colon ).toAsciiLowerCase();
3559646dec5SDamjan Jovanovic         header.value = line.copy( colon + 1 ).trim();
3569646dec5SDamjan Jovanovic         responseHeaders.push_back(header);
3579646dec5SDamjan Jovanovic     }
3589646dec5SDamjan Jovanovic }
3599646dec5SDamjan Jovanovic 
findResponseHeader(const rtl::OString & name)3609646dec5SDamjan Jovanovic const CurlRequest::Header *CurlRequest::findResponseHeader( const rtl::OString &name )
3619646dec5SDamjan Jovanovic {
3629646dec5SDamjan Jovanovic     std::vector< CurlRequest::Header >::const_iterator it( responseHeaders.begin() );
3639646dec5SDamjan Jovanovic     const std::vector< CurlRequest::Header >::const_iterator end( responseHeaders.end() );
3649646dec5SDamjan Jovanovic     for ( ; it != end; it++ )
3659646dec5SDamjan Jovanovic     {
3669646dec5SDamjan Jovanovic         if ( name.equalsIgnoreAsciiCase( it->name ) )
3679646dec5SDamjan Jovanovic             return &(*it);
3689646dec5SDamjan Jovanovic     }
3699646dec5SDamjan Jovanovic     return NULL;
3709646dec5SDamjan Jovanovic }
3719646dec5SDamjan Jovanovic 
saveResponseBodyTo(const uno::Reference<io::XOutputStream> & xOutStream)3729646dec5SDamjan Jovanovic void CurlRequest::saveResponseBodyTo( const uno::Reference< io::XOutputStream > & xOutStream)
3739646dec5SDamjan Jovanovic {
3749646dec5SDamjan Jovanovic     xOutputStream = xOutStream;
3759646dec5SDamjan Jovanovic }
3769646dec5SDamjan Jovanovic 
Curl_MoreBodyReceived(char * buffer,size_t size,size_t nitems,void * userdata)3779646dec5SDamjan Jovanovic size_t CurlRequest::Curl_MoreBodyReceived( char *buffer, size_t size, size_t nitems, void *userdata )
3789646dec5SDamjan Jovanovic {
3799646dec5SDamjan Jovanovic     CurlRequest *request = static_cast< CurlRequest* >( userdata );
3809646dec5SDamjan Jovanovic     request->curlMoreBodyReceived( buffer, nitems );
3819646dec5SDamjan Jovanovic     return nitems;
3829646dec5SDamjan Jovanovic }
3839646dec5SDamjan Jovanovic 
curlMoreBodyReceived(const char * buffer,size_t size)3849646dec5SDamjan Jovanovic void CurlRequest::curlMoreBodyReceived( const char *buffer, size_t size )
3859646dec5SDamjan Jovanovic {
3869646dec5SDamjan Jovanovic     if ( xOutputStream.is() )
3879646dec5SDamjan Jovanovic     {
3889646dec5SDamjan Jovanovic         const uno::Sequence< sal_Int8 > aDataSeq( (sal_Int8 *)buffer, size );
3899646dec5SDamjan Jovanovic         xOutputStream->writeBytes( aDataSeq );
3909646dec5SDamjan Jovanovic     }
3919646dec5SDamjan Jovanovic     else if ( responseBodyInputStream.is() )
3929646dec5SDamjan Jovanovic         responseBodyInputStream->AddToStream( buffer, size );
393*b28b64c2SDamjan Jovanovic }
394