xref: /trunk/main/ucb/source/ucp/webdav/CurlRequest.cxx (revision cf6516809c57e1bb0a940545cca99cdad54d4ce2)
151ba086bSDamjan Jovanovic /**************************************************************
251ba086bSDamjan Jovanovic  *
351ba086bSDamjan Jovanovic  * Licensed to the Apache Software Foundation (ASF) under one
451ba086bSDamjan Jovanovic  * or more contributor license agreements.  See the NOTICE file
551ba086bSDamjan Jovanovic  * distributed with this work for additional information
651ba086bSDamjan Jovanovic  * regarding copyright ownership.  The ASF licenses this file
751ba086bSDamjan Jovanovic  * to you under the Apache License, Version 2.0 (the
851ba086bSDamjan Jovanovic  * "License"); you may not use this file except in compliance
951ba086bSDamjan Jovanovic  * with the License.  You may obtain a copy of the License at
1051ba086bSDamjan Jovanovic  *
1151ba086bSDamjan Jovanovic  *   http://www.apache.org/licenses/LICENSE-2.0
1251ba086bSDamjan Jovanovic  *
1351ba086bSDamjan Jovanovic  * Unless required by applicable law or agreed to in writing,
1451ba086bSDamjan Jovanovic  * software distributed under the License is distributed on an
1551ba086bSDamjan Jovanovic  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1651ba086bSDamjan Jovanovic  * KIND, either express or implied.  See the License for the
1751ba086bSDamjan Jovanovic  * specific language governing permissions and limitations
1851ba086bSDamjan Jovanovic  * under the License.
1951ba086bSDamjan Jovanovic  *
2051ba086bSDamjan Jovanovic  *************************************************************/
2151ba086bSDamjan Jovanovic 
2251ba086bSDamjan Jovanovic 
2351ba086bSDamjan Jovanovic 
2451ba086bSDamjan Jovanovic // MARKER(update_precomp.py): autogen include statement, do not remove
2551ba086bSDamjan Jovanovic #include "precompiled_webdav.hxx"
2651ba086bSDamjan Jovanovic 
2751ba086bSDamjan Jovanovic #include "CurlRequest.hxx"
2851ba086bSDamjan Jovanovic 
29*19cdc44eSDamjan Jovanovic #include <string.h>
30*19cdc44eSDamjan Jovanovic 
3151ba086bSDamjan Jovanovic using namespace ::com::sun::star;
3251ba086bSDamjan Jovanovic using namespace http_dav_ucp;
3351ba086bSDamjan Jovanovic 
CurlRequest(CURL * curl)3451ba086bSDamjan Jovanovic CurlRequest::CurlRequest( CURL *curl )
3551ba086bSDamjan Jovanovic     : curl( curl )
3651ba086bSDamjan Jovanovic     , curlUrl( NULL )
3751ba086bSDamjan Jovanovic     , requestHeaders( NULL )
3851ba086bSDamjan Jovanovic     , requestBody( NULL )
3951ba086bSDamjan Jovanovic     , requestBodyOffset( 0 )
4051ba086bSDamjan Jovanovic     , requestBodySize( 0 )
4151ba086bSDamjan Jovanovic     , useChunkedEncoding( false )
4251ba086bSDamjan Jovanovic     , provideCredentialsCallback( NULL )
4351ba086bSDamjan Jovanovic     , provideCredentialsUserdata( NULL )
4451ba086bSDamjan Jovanovic     , statusCode( 0 )
4551ba086bSDamjan Jovanovic     , responseBodyInputStream( new CurlInputStream() )
4651ba086bSDamjan Jovanovic {
4751ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HEADERFUNCTION, Curl_HeaderReceived );
4851ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HEADERDATA, this );
4951ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, Curl_MoreBodyReceived );
5051ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_WRITEDATA, this );
5151ba086bSDamjan Jovanovic }
5251ba086bSDamjan Jovanovic 
~CurlRequest()5351ba086bSDamjan Jovanovic CurlRequest::~CurlRequest()
5451ba086bSDamjan Jovanovic {
5551ba086bSDamjan Jovanovic     if ( curlUrl != NULL )
5651ba086bSDamjan Jovanovic         curl_url_cleanup( curlUrl );
5751ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CURLU, NULL );
5851ba086bSDamjan Jovanovic 
5951ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPHEADER, NULL );
6051ba086bSDamjan Jovanovic     if ( requestHeaders != NULL )
6151ba086bSDamjan Jovanovic         curl_slist_free_all( requestHeaders );
6251ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_READFUNCTION, NULL );
6351ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_READDATA, NULL );
6451ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_INFILESIZE, -1 );
6551ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_SEEKFUNCTION, NULL );
6651ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_SEEKDATA, NULL );
6751ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HEADERFUNCTION, NULL );
6851ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HEADERDATA, NULL );
6951ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, NULL );
7051ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, NULL );
7151ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_WRITEDATA, NULL );
7251ba086bSDamjan Jovanovic }
7351ba086bSDamjan Jovanovic 
addHeader(const rtl::OString & name,const rtl::OString & value)7451ba086bSDamjan Jovanovic void CurlRequest::addHeader( const rtl::OString &name, const rtl::OString &value) throw (DAVException)
7551ba086bSDamjan Jovanovic {
7651ba086bSDamjan Jovanovic     rtl::OString line = name + ": " + value;
7751ba086bSDamjan Jovanovic     struct curl_slist *appended = curl_slist_append( requestHeaders, line.getStr() );
7851ba086bSDamjan Jovanovic     if ( appended != NULL )
7951ba086bSDamjan Jovanovic     {
8051ba086bSDamjan Jovanovic         requestHeaders = appended;
8151ba086bSDamjan Jovanovic         curl_easy_setopt( curl, CURLOPT_HTTPHEADER, requestHeaders );
8251ba086bSDamjan Jovanovic     }
8351ba086bSDamjan Jovanovic     else
8451ba086bSDamjan Jovanovic         throw DAVException( DAVException::DAV_SESSION_CREATE, rtl::OUString::createFromAscii( "Out of memory" ) );
8551ba086bSDamjan Jovanovic }
8651ba086bSDamjan Jovanovic 
setRequestBody(const char * body,size_t size)8751ba086bSDamjan Jovanovic void CurlRequest::setRequestBody( const char *body, size_t size )
8851ba086bSDamjan Jovanovic {
8951ba086bSDamjan Jovanovic     requestBody = body;
9051ba086bSDamjan Jovanovic     requestBodyOffset = 0;
9151ba086bSDamjan Jovanovic     requestBodySize = size;
9251ba086bSDamjan Jovanovic 
9351ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_READFUNCTION, Curl_SendMoreBody );
9451ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_READDATA, this );
9551ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_SEEKFUNCTION, Curl_SeekCallback );
9651ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_SEEKDATA, this );
9751ba086bSDamjan Jovanovic     if ( useChunkedEncoding )
9851ba086bSDamjan Jovanovic         addHeader( "Transfer-Encoding", "chunked" );
9951ba086bSDamjan Jovanovic     else
10051ba086bSDamjan Jovanovic         curl_easy_setopt( curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)size );
10151ba086bSDamjan Jovanovic }
10251ba086bSDamjan Jovanovic 
Curl_SeekCallback(void * userdata,curl_off_t offset,int origin)10351ba086bSDamjan Jovanovic int CurlRequest::Curl_SeekCallback( void *userdata, curl_off_t offset, int origin )
10451ba086bSDamjan Jovanovic {
10551ba086bSDamjan Jovanovic     CurlRequest *request = static_cast< CurlRequest* >( userdata );
10651ba086bSDamjan Jovanovic     if ( origin == SEEK_SET )
10751ba086bSDamjan Jovanovic         request->requestBodyOffset = (size_t) offset;
10851ba086bSDamjan Jovanovic     else if ( origin == SEEK_CUR )
10951ba086bSDamjan Jovanovic         request->requestBodyOffset += (size_t) offset;
11051ba086bSDamjan Jovanovic     else if ( origin == SEEK_END )
11151ba086bSDamjan Jovanovic         request->requestBodyOffset += (size_t) ((curl_off_t)request->requestBodySize + offset);
11251ba086bSDamjan Jovanovic     else
11351ba086bSDamjan Jovanovic         return CURL_SEEKFUNC_CANTSEEK;
11451ba086bSDamjan Jovanovic     if ( request->requestBodyOffset > request->requestBodySize )
11551ba086bSDamjan Jovanovic         request->requestBodyOffset = request->requestBodySize;
11651ba086bSDamjan Jovanovic     return CURL_SEEKFUNC_OK;
11751ba086bSDamjan Jovanovic }
11851ba086bSDamjan Jovanovic 
Curl_SendMoreBody(char * buffer,size_t size,size_t nitems,void * userdata)11951ba086bSDamjan Jovanovic size_t CurlRequest::Curl_SendMoreBody( char *buffer, size_t size, size_t nitems, void *userdata )
12051ba086bSDamjan Jovanovic {
12151ba086bSDamjan Jovanovic     CurlRequest *request = static_cast< CurlRequest* >( userdata );
12251ba086bSDamjan Jovanovic     OSL_TRACE("Curl_SendMoreBody");
12351ba086bSDamjan Jovanovic     return request->curlSendMoreBody( buffer, nitems );
12451ba086bSDamjan Jovanovic }
12551ba086bSDamjan Jovanovic 
curlSendMoreBody(char * buffer,size_t len)12651ba086bSDamjan Jovanovic size_t CurlRequest::curlSendMoreBody( char *buffer, size_t len )
12751ba086bSDamjan Jovanovic {
12851ba086bSDamjan Jovanovic     size_t bytesToSend = requestBodySize - requestBodyOffset;
12951ba086bSDamjan Jovanovic     if ( bytesToSend > len )
13051ba086bSDamjan Jovanovic         bytesToSend = len;
13151ba086bSDamjan Jovanovic     memcpy( buffer, requestBody, bytesToSend );
13251ba086bSDamjan Jovanovic     requestBodyOffset += bytesToSend;
13351ba086bSDamjan Jovanovic     return bytesToSend;
13451ba086bSDamjan Jovanovic }
13551ba086bSDamjan Jovanovic 
setProvideCredentialsCallback(bool (* callback)(long statusCode,void * userdata)throw (DAVException),void * userdata)13651ba086bSDamjan Jovanovic void CurlRequest::setProvideCredentialsCallback( bool (*callback)(long statusCode, void *userdata) throw (DAVException), void *userdata )
13751ba086bSDamjan Jovanovic {
13851ba086bSDamjan Jovanovic     provideCredentialsCallback = callback;
13951ba086bSDamjan Jovanovic     provideCredentialsUserdata = userdata;
14051ba086bSDamjan Jovanovic }
14151ba086bSDamjan Jovanovic 
setURI(CurlUri uri,rtl::OUString path)14251ba086bSDamjan Jovanovic void CurlRequest::setURI( CurlUri uri, rtl::OUString path ) throw (DAVException)
14351ba086bSDamjan Jovanovic {
14451ba086bSDamjan Jovanovic     if ( curlUrl != NULL )
14551ba086bSDamjan Jovanovic     {
14651ba086bSDamjan Jovanovic         curl_url_cleanup( curlUrl );
14751ba086bSDamjan Jovanovic         curlUrl = NULL;
14851ba086bSDamjan Jovanovic     }
14951ba086bSDamjan Jovanovic 
15051ba086bSDamjan Jovanovic     curlUrl = curl_url();
15151ba086bSDamjan Jovanovic     if ( curlUrl == NULL )
15251ba086bSDamjan Jovanovic         throw DAVException( DAVException::DAV_SESSION_CREATE, rtl::OUString::createFromAscii( "Out of memory" ) );
15351ba086bSDamjan Jovanovic 
15451ba086bSDamjan Jovanovic     if ( CurlUri( path ).GetHost().isEmpty() )
15551ba086bSDamjan Jovanovic     {
15651ba086bSDamjan Jovanovic         // "path" is really a path, not a URI
15751ba086bSDamjan Jovanovic         curl_url_set( curlUrl, CURLUPART_URL, rtl::OUStringToOString( uri.GetURI(), RTL_TEXTENCODING_UTF8 ).getStr(), 0 );
15851ba086bSDamjan Jovanovic         curl_url_set( curlUrl, CURLUPART_PATH, rtl::OUStringToOString( path, RTL_TEXTENCODING_UTF8 ).getStr(), 0 );
15951ba086bSDamjan Jovanovic     }
16051ba086bSDamjan Jovanovic     else
16151ba086bSDamjan Jovanovic     {
16251ba086bSDamjan Jovanovic         // The "path" is a full URI
16351ba086bSDamjan Jovanovic         curl_url_set( curlUrl, CURLUPART_URL, rtl::OUStringToOString( path, RTL_TEXTENCODING_UTF8 ).getStr(), 0 );
16451ba086bSDamjan Jovanovic     }
16551ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CURLU, curlUrl );
16651ba086bSDamjan Jovanovic }
16751ba086bSDamjan Jovanovic 
copy(CurlUri uri,rtl::OUString path)16851ba086bSDamjan Jovanovic CURLcode CurlRequest::copy( CurlUri uri, rtl::OUString path ) throw(DAVException)
16951ba086bSDamjan Jovanovic {
17051ba086bSDamjan Jovanovic     setURI( uri, path );
17151ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPGET, 1L );
17251ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "COPY" );
17351ba086bSDamjan Jovanovic     return perform();
17451ba086bSDamjan Jovanovic }
17551ba086bSDamjan Jovanovic 
delete_(CurlUri uri,rtl::OUString path)17651ba086bSDamjan Jovanovic CURLcode CurlRequest::delete_( CurlUri uri, rtl::OUString path ) throw (DAVException)
17751ba086bSDamjan Jovanovic {
17851ba086bSDamjan Jovanovic     setURI( uri, path );
17951ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPGET, 1L );
18051ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "DELETE" );
18151ba086bSDamjan Jovanovic     return perform();
18251ba086bSDamjan Jovanovic }
18351ba086bSDamjan Jovanovic 
get(CurlUri uri,rtl::OUString path)18451ba086bSDamjan Jovanovic CURLcode CurlRequest::get( CurlUri uri, rtl::OUString path ) throw(DAVException)
18551ba086bSDamjan Jovanovic {
18651ba086bSDamjan Jovanovic     setURI( uri, path );
18751ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPGET, 1L );
18851ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "GET" );
18951ba086bSDamjan Jovanovic     return perform();
19051ba086bSDamjan Jovanovic }
19151ba086bSDamjan Jovanovic 
head(CurlUri uri,rtl::OUString path)19251ba086bSDamjan Jovanovic CURLcode CurlRequest::head( CurlUri uri, rtl::OUString path ) throw (DAVException)
19351ba086bSDamjan Jovanovic {
19451ba086bSDamjan Jovanovic     setURI( uri, path );
19551ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_NOBODY, 1L );
19651ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "HEAD" );
19751ba086bSDamjan Jovanovic     return perform();
19851ba086bSDamjan Jovanovic }
19951ba086bSDamjan Jovanovic 
lock(CurlUri uri,rtl::OUString path)20051ba086bSDamjan Jovanovic CURLcode CurlRequest::lock( CurlUri uri, rtl::OUString path ) throw (DAVException)
20151ba086bSDamjan Jovanovic {
20251ba086bSDamjan Jovanovic     setURI( uri, path );
20351ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_UPLOAD, 1L );
20451ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "LOCK" );
20551ba086bSDamjan Jovanovic     return perform();
20651ba086bSDamjan Jovanovic }
20751ba086bSDamjan Jovanovic 
mkcol(CurlUri uri,rtl::OUString path)20851ba086bSDamjan Jovanovic CURLcode CurlRequest::mkcol( CurlUri uri, rtl::OUString path ) throw (DAVException)
20951ba086bSDamjan Jovanovic {
21051ba086bSDamjan Jovanovic     setURI( uri, path );
21151ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPGET, 1L );
21251ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "MKCOL" );
21351ba086bSDamjan Jovanovic     return perform();
21451ba086bSDamjan Jovanovic }
21551ba086bSDamjan Jovanovic 
move(CurlUri uri,rtl::OUString path)21651ba086bSDamjan Jovanovic CURLcode CurlRequest::move( CurlUri uri, rtl::OUString path ) throw (DAVException)
21751ba086bSDamjan Jovanovic {
21851ba086bSDamjan Jovanovic     setURI( uri, path );
21951ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPGET, 1L );
22051ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "MOVE" );
22151ba086bSDamjan Jovanovic     return perform();
22251ba086bSDamjan Jovanovic }
22351ba086bSDamjan Jovanovic 
post(CurlUri uri,rtl::OUString path)22451ba086bSDamjan Jovanovic CURLcode CurlRequest::post( CurlUri uri, rtl::OUString path ) throw (DAVException)
22551ba086bSDamjan Jovanovic {
22651ba086bSDamjan Jovanovic     setURI( uri, path );
22751ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_UPLOAD, 1L );
22851ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "POST" );
22951ba086bSDamjan Jovanovic     return perform();
23051ba086bSDamjan Jovanovic }
23151ba086bSDamjan Jovanovic 
propfind(CurlUri uri,rtl::OUString path)23251ba086bSDamjan Jovanovic CURLcode CurlRequest::propfind( CurlUri uri, rtl::OUString path ) throw (DAVException)
23351ba086bSDamjan Jovanovic {
23451ba086bSDamjan Jovanovic     setURI( uri, path );
23551ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_UPLOAD, 1L );
23651ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "PROPFIND" );
23751ba086bSDamjan Jovanovic     return perform();
23851ba086bSDamjan Jovanovic }
23951ba086bSDamjan Jovanovic 
proppatch(CurlUri uri,rtl::OUString path)24051ba086bSDamjan Jovanovic CURLcode CurlRequest::proppatch( CurlUri uri, rtl::OUString path ) throw (DAVException)
24151ba086bSDamjan Jovanovic {
24251ba086bSDamjan Jovanovic     setURI( uri, path );
24351ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_UPLOAD, 1L );
24451ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "PROPPATCH" );
24551ba086bSDamjan Jovanovic     return perform();
24651ba086bSDamjan Jovanovic }
24751ba086bSDamjan Jovanovic 
put(CurlUri uri,rtl::OUString path)24851ba086bSDamjan Jovanovic CURLcode CurlRequest::put( CurlUri uri, rtl::OUString path ) throw (DAVException)
24951ba086bSDamjan Jovanovic {
25051ba086bSDamjan Jovanovic     setURI( uri, path );
25151ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_UPLOAD, 1L );
25251ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "PUT" );
25351ba086bSDamjan Jovanovic     return perform();
25451ba086bSDamjan Jovanovic }
25551ba086bSDamjan Jovanovic 
unlock(CurlUri uri,rtl::OUString path)25651ba086bSDamjan Jovanovic CURLcode CurlRequest::unlock( CurlUri uri, rtl::OUString path ) throw (DAVException)
25751ba086bSDamjan Jovanovic {
25851ba086bSDamjan Jovanovic     setURI( uri, path );
25951ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPGET, 1L );
26051ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "UNLOCK" );
26151ba086bSDamjan Jovanovic     return perform();
26251ba086bSDamjan Jovanovic }
26351ba086bSDamjan Jovanovic 
perform()26451ba086bSDamjan Jovanovic CURLcode CurlRequest::perform() throw (DAVException)
26551ba086bSDamjan Jovanovic {
26651ba086bSDamjan Jovanovic     CURLcode rc = curl_easy_perform( curl );
26751ba086bSDamjan Jovanovic     long statusCode = 0;
26851ba086bSDamjan Jovanovic     curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &statusCode );
26951ba086bSDamjan Jovanovic     if ( ( statusCode == 401 || statusCode == 407 ) && provideCredentialsCallback != NULL )
27051ba086bSDamjan Jovanovic     {
27151ba086bSDamjan Jovanovic         bool haveCredentials = provideCredentialsCallback( statusCode, provideCredentialsUserdata );
27251ba086bSDamjan Jovanovic         if ( haveCredentials )
27351ba086bSDamjan Jovanovic         {
27451ba086bSDamjan Jovanovic             // rewind body:
27551ba086bSDamjan Jovanovic             requestBodyOffset = 0;
27651ba086bSDamjan Jovanovic             // retry with credentials:
27751ba086bSDamjan Jovanovic             rc = curl_easy_perform( curl );
27851ba086bSDamjan Jovanovic             // If this was to authenticate with the proxy, we may need to authenticate
27951ba086bSDamjan Jovanovic             // with the destination host too:
28051ba086bSDamjan Jovanovic             if ( statusCode == 407 )
28151ba086bSDamjan Jovanovic             {
28251ba086bSDamjan Jovanovic                 curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &statusCode );
28351ba086bSDamjan Jovanovic                 if ( statusCode == 401 && provideCredentialsCallback != NULL )
28451ba086bSDamjan Jovanovic                 {
28551ba086bSDamjan Jovanovic                     haveCredentials = provideCredentialsCallback( statusCode, provideCredentialsUserdata );
28651ba086bSDamjan Jovanovic                     if ( haveCredentials )
28751ba086bSDamjan Jovanovic                     {
28851ba086bSDamjan Jovanovic                         // rewind body:
28951ba086bSDamjan Jovanovic                         requestBodyOffset = 0;
29051ba086bSDamjan Jovanovic                         // retry with credentials:
29151ba086bSDamjan Jovanovic                         rc = curl_easy_perform( curl );
29251ba086bSDamjan Jovanovic                     }
29351ba086bSDamjan Jovanovic                 }
29451ba086bSDamjan Jovanovic             }
29551ba086bSDamjan Jovanovic         }
29651ba086bSDamjan Jovanovic     }
29751ba086bSDamjan Jovanovic     return rc;
29851ba086bSDamjan Jovanovic }
29951ba086bSDamjan Jovanovic 
Curl_HeaderReceived(char * buffer,size_t size,size_t nitems,void * userdata)30051ba086bSDamjan Jovanovic size_t CurlRequest::Curl_HeaderReceived( char *buffer, size_t size, size_t nitems, void *userdata )
30151ba086bSDamjan Jovanovic {
30251ba086bSDamjan Jovanovic     CurlRequest *request = static_cast< CurlRequest* >( userdata );
30351ba086bSDamjan Jovanovic     OSL_TRACE("Curl_HeaderReceived");
30451ba086bSDamjan Jovanovic     request->curlHeaderReceived( buffer, nitems );
30551ba086bSDamjan Jovanovic     return nitems;
30651ba086bSDamjan Jovanovic }
30751ba086bSDamjan Jovanovic 
curlHeaderReceived(const char * buffer,size_t size)30851ba086bSDamjan Jovanovic void CurlRequest::curlHeaderReceived( const char *buffer, size_t size )
30951ba086bSDamjan Jovanovic {
31051ba086bSDamjan Jovanovic     rtl::OString lineCrLf( buffer, size );
31151ba086bSDamjan Jovanovic     sal_Int32 cr = lineCrLf.indexOf( "\r" );
31251ba086bSDamjan Jovanovic     if ( cr < 0 )
31351ba086bSDamjan Jovanovic         return;
31451ba086bSDamjan Jovanovic 
31551ba086bSDamjan Jovanovic     rtl::OString line = lineCrLf.copy( 0, cr );
31651ba086bSDamjan Jovanovic     if ( line.indexOf( "HTTP/" ) == 0 )
31751ba086bSDamjan Jovanovic     {
31851ba086bSDamjan Jovanovic         // Status line
31951ba086bSDamjan Jovanovic         // Throw away any response headers from a prior response:
32051ba086bSDamjan Jovanovic         responseHeaders.clear();
32151ba086bSDamjan Jovanovic         sal_Int32 idxFirstSpace = line.indexOf( ' ' );
32251ba086bSDamjan Jovanovic         if ( idxFirstSpace > 0 )
32351ba086bSDamjan Jovanovic         {
32451ba086bSDamjan Jovanovic             int idxSecondSpace = line.indexOf( ' ', idxFirstSpace + 1 );
32551ba086bSDamjan Jovanovic             if ( idxSecondSpace > 0 )
32651ba086bSDamjan Jovanovic             {
32751ba086bSDamjan Jovanovic                 reasonPhrase = line.copy( idxSecondSpace + 1 );
32851ba086bSDamjan Jovanovic                 statusCode = line.copy( idxFirstSpace + 1, idxSecondSpace - idxFirstSpace - 1 ).toInt32();
32951ba086bSDamjan Jovanovic             }
33051ba086bSDamjan Jovanovic             else
33151ba086bSDamjan Jovanovic             {
33251ba086bSDamjan Jovanovic                 reasonPhrase = "";
33351ba086bSDamjan Jovanovic                 statusCode = line.copy( idxFirstSpace + 1 ).toInt32();
33451ba086bSDamjan Jovanovic             }
33551ba086bSDamjan Jovanovic         }
33651ba086bSDamjan Jovanovic     }
33751ba086bSDamjan Jovanovic     else
33851ba086bSDamjan Jovanovic     {
33951ba086bSDamjan Jovanovic         // Header line
34051ba086bSDamjan Jovanovic         if ( line.getLength() == 0 )
34151ba086bSDamjan Jovanovic         {
34251ba086bSDamjan Jovanovic             // End of HTTP header
34351ba086bSDamjan Jovanovic             // Discard any intermediate body from 100 Trying or 401 Authentication required:
34451ba086bSDamjan Jovanovic             responseBodyInputStream = new CurlInputStream();
34551ba086bSDamjan Jovanovic             return;
34651ba086bSDamjan Jovanovic         }
34751ba086bSDamjan Jovanovic         sal_Int32 colon = line.indexOf( ':' );
34851ba086bSDamjan Jovanovic         if ( colon < 0 )
34951ba086bSDamjan Jovanovic         {
35051ba086bSDamjan Jovanovic             OSL_TRACE("Non-empty HTTP line without a ':'. Folded header deprecated by RFC 7230?");
35151ba086bSDamjan Jovanovic             return;
35251ba086bSDamjan Jovanovic         }
35351ba086bSDamjan Jovanovic         Header header;
35451ba086bSDamjan Jovanovic         header.name = line.copy( 0, colon ).toAsciiLowerCase();
35551ba086bSDamjan Jovanovic         header.value = line.copy( colon + 1 ).trim();
35651ba086bSDamjan Jovanovic         responseHeaders.push_back(header);
35751ba086bSDamjan Jovanovic     }
35851ba086bSDamjan Jovanovic }
35951ba086bSDamjan Jovanovic 
findResponseHeader(const rtl::OString & name)36051ba086bSDamjan Jovanovic const CurlRequest::Header *CurlRequest::findResponseHeader( const rtl::OString &name )
36151ba086bSDamjan Jovanovic {
36251ba086bSDamjan Jovanovic     std::vector< CurlRequest::Header >::const_iterator it( responseHeaders.begin() );
36351ba086bSDamjan Jovanovic     const std::vector< CurlRequest::Header >::const_iterator end( responseHeaders.end() );
36451ba086bSDamjan Jovanovic     for ( ; it != end; it++ )
36551ba086bSDamjan Jovanovic     {
36651ba086bSDamjan Jovanovic         if ( name.equalsIgnoreAsciiCase( it->name ) )
36751ba086bSDamjan Jovanovic             return &(*it);
36851ba086bSDamjan Jovanovic     }
36951ba086bSDamjan Jovanovic     return NULL;
37051ba086bSDamjan Jovanovic }
37151ba086bSDamjan Jovanovic 
saveResponseBodyTo(const uno::Reference<io::XOutputStream> & xOutStream)37251ba086bSDamjan Jovanovic void CurlRequest::saveResponseBodyTo( const uno::Reference< io::XOutputStream > & xOutStream)
37351ba086bSDamjan Jovanovic {
37451ba086bSDamjan Jovanovic     xOutputStream = xOutStream;
37551ba086bSDamjan Jovanovic }
37651ba086bSDamjan Jovanovic 
Curl_MoreBodyReceived(char * buffer,size_t size,size_t nitems,void * userdata)37751ba086bSDamjan Jovanovic size_t CurlRequest::Curl_MoreBodyReceived( char *buffer, size_t size, size_t nitems, void *userdata )
37851ba086bSDamjan Jovanovic {
37951ba086bSDamjan Jovanovic     CurlRequest *request = static_cast< CurlRequest* >( userdata );
38051ba086bSDamjan Jovanovic     request->curlMoreBodyReceived( buffer, nitems );
38151ba086bSDamjan Jovanovic     return nitems;
38251ba086bSDamjan Jovanovic }
38351ba086bSDamjan Jovanovic 
curlMoreBodyReceived(const char * buffer,size_t size)38451ba086bSDamjan Jovanovic void CurlRequest::curlMoreBodyReceived( const char *buffer, size_t size )
38551ba086bSDamjan Jovanovic {
38651ba086bSDamjan Jovanovic     if ( xOutputStream.is() )
38751ba086bSDamjan Jovanovic     {
38851ba086bSDamjan Jovanovic         const uno::Sequence< sal_Int8 > aDataSeq( (sal_Int8 *)buffer, size );
38951ba086bSDamjan Jovanovic         xOutputStream->writeBytes( aDataSeq );
39051ba086bSDamjan Jovanovic     }
39151ba086bSDamjan Jovanovic     else if ( responseBodyInputStream.is() )
39251ba086bSDamjan Jovanovic         responseBodyInputStream->AddToStream( buffer, size );
39351ba086bSDamjan Jovanovic }
394