xref: /trunk/main/ucb/source/ucp/webdav/CurlRequest.cxx (revision 51ba086bf122dbb5b50fd813e5b9a81c051aa16b)
1*51ba086bSDamjan Jovanovic /**************************************************************
2*51ba086bSDamjan Jovanovic  *
3*51ba086bSDamjan Jovanovic  * Licensed to the Apache Software Foundation (ASF) under one
4*51ba086bSDamjan Jovanovic  * or more contributor license agreements.  See the NOTICE file
5*51ba086bSDamjan Jovanovic  * distributed with this work for additional information
6*51ba086bSDamjan Jovanovic  * regarding copyright ownership.  The ASF licenses this file
7*51ba086bSDamjan Jovanovic  * to you under the Apache License, Version 2.0 (the
8*51ba086bSDamjan Jovanovic  * "License"); you may not use this file except in compliance
9*51ba086bSDamjan Jovanovic  * with the License.  You may obtain a copy of the License at
10*51ba086bSDamjan Jovanovic  *
11*51ba086bSDamjan Jovanovic  *   http://www.apache.org/licenses/LICENSE-2.0
12*51ba086bSDamjan Jovanovic  *
13*51ba086bSDamjan Jovanovic  * Unless required by applicable law or agreed to in writing,
14*51ba086bSDamjan Jovanovic  * software distributed under the License is distributed on an
15*51ba086bSDamjan Jovanovic  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*51ba086bSDamjan Jovanovic  * KIND, either express or implied.  See the License for the
17*51ba086bSDamjan Jovanovic  * specific language governing permissions and limitations
18*51ba086bSDamjan Jovanovic  * under the License.
19*51ba086bSDamjan Jovanovic  *
20*51ba086bSDamjan Jovanovic  *************************************************************/
21*51ba086bSDamjan Jovanovic 
22*51ba086bSDamjan Jovanovic 
23*51ba086bSDamjan Jovanovic 
24*51ba086bSDamjan Jovanovic // MARKER(update_precomp.py): autogen include statement, do not remove
25*51ba086bSDamjan Jovanovic #include "precompiled_webdav.hxx"
26*51ba086bSDamjan Jovanovic 
27*51ba086bSDamjan Jovanovic #include "CurlRequest.hxx"
28*51ba086bSDamjan Jovanovic 
29*51ba086bSDamjan Jovanovic using namespace ::com::sun::star;
30*51ba086bSDamjan Jovanovic using namespace http_dav_ucp;
31*51ba086bSDamjan Jovanovic 
32*51ba086bSDamjan Jovanovic CurlRequest::CurlRequest( CURL *curl )
33*51ba086bSDamjan Jovanovic     : curl( curl )
34*51ba086bSDamjan Jovanovic     , curlUrl( NULL )
35*51ba086bSDamjan Jovanovic     , requestHeaders( NULL )
36*51ba086bSDamjan Jovanovic     , requestBody( NULL )
37*51ba086bSDamjan Jovanovic     , requestBodyOffset( 0 )
38*51ba086bSDamjan Jovanovic     , requestBodySize( 0 )
39*51ba086bSDamjan Jovanovic     , useChunkedEncoding( false )
40*51ba086bSDamjan Jovanovic     , provideCredentialsCallback( NULL )
41*51ba086bSDamjan Jovanovic     , provideCredentialsUserdata( NULL )
42*51ba086bSDamjan Jovanovic     , statusCode( 0 )
43*51ba086bSDamjan Jovanovic     , responseBodyInputStream( new CurlInputStream() )
44*51ba086bSDamjan Jovanovic {
45*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HEADERFUNCTION, Curl_HeaderReceived );
46*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HEADERDATA, this );
47*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, Curl_MoreBodyReceived );
48*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_WRITEDATA, this );
49*51ba086bSDamjan Jovanovic }
50*51ba086bSDamjan Jovanovic 
51*51ba086bSDamjan Jovanovic CurlRequest::~CurlRequest()
52*51ba086bSDamjan Jovanovic {
53*51ba086bSDamjan Jovanovic     if ( curlUrl != NULL )
54*51ba086bSDamjan Jovanovic         curl_url_cleanup( curlUrl );
55*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CURLU, NULL );
56*51ba086bSDamjan Jovanovic 
57*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPHEADER, NULL );
58*51ba086bSDamjan Jovanovic     if ( requestHeaders != NULL )
59*51ba086bSDamjan Jovanovic         curl_slist_free_all( requestHeaders );
60*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_READFUNCTION, NULL );
61*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_READDATA, NULL );
62*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_INFILESIZE, -1 );
63*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_SEEKFUNCTION, NULL );
64*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_SEEKDATA, NULL );
65*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HEADERFUNCTION, NULL );
66*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HEADERDATA, NULL );
67*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, NULL );
68*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, NULL );
69*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_WRITEDATA, NULL );
70*51ba086bSDamjan Jovanovic }
71*51ba086bSDamjan Jovanovic 
72*51ba086bSDamjan Jovanovic void CurlRequest::addHeader( const rtl::OString &name, const rtl::OString &value) throw (DAVException)
73*51ba086bSDamjan Jovanovic {
74*51ba086bSDamjan Jovanovic     rtl::OString line = name + ": " + value;
75*51ba086bSDamjan Jovanovic     struct curl_slist *appended = curl_slist_append( requestHeaders, line.getStr() );
76*51ba086bSDamjan Jovanovic     if ( appended != NULL )
77*51ba086bSDamjan Jovanovic     {
78*51ba086bSDamjan Jovanovic         requestHeaders = appended;
79*51ba086bSDamjan Jovanovic         curl_easy_setopt( curl, CURLOPT_HTTPHEADER, requestHeaders );
80*51ba086bSDamjan Jovanovic     }
81*51ba086bSDamjan Jovanovic     else
82*51ba086bSDamjan Jovanovic         throw DAVException( DAVException::DAV_SESSION_CREATE, rtl::OUString::createFromAscii( "Out of memory" ) );
83*51ba086bSDamjan Jovanovic }
84*51ba086bSDamjan Jovanovic 
85*51ba086bSDamjan Jovanovic void CurlRequest::setRequestBody( const char *body, size_t size )
86*51ba086bSDamjan Jovanovic {
87*51ba086bSDamjan Jovanovic     requestBody = body;
88*51ba086bSDamjan Jovanovic     requestBodyOffset = 0;
89*51ba086bSDamjan Jovanovic     requestBodySize = size;
90*51ba086bSDamjan Jovanovic 
91*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_READFUNCTION, Curl_SendMoreBody );
92*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_READDATA, this );
93*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_SEEKFUNCTION, Curl_SeekCallback );
94*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_SEEKDATA, this );
95*51ba086bSDamjan Jovanovic     if ( useChunkedEncoding )
96*51ba086bSDamjan Jovanovic         addHeader( "Transfer-Encoding", "chunked" );
97*51ba086bSDamjan Jovanovic     else
98*51ba086bSDamjan Jovanovic         curl_easy_setopt( curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)size );
99*51ba086bSDamjan Jovanovic }
100*51ba086bSDamjan Jovanovic 
101*51ba086bSDamjan Jovanovic int CurlRequest::Curl_SeekCallback( void *userdata, curl_off_t offset, int origin )
102*51ba086bSDamjan Jovanovic {
103*51ba086bSDamjan Jovanovic     CurlRequest *request = static_cast< CurlRequest* >( userdata );
104*51ba086bSDamjan Jovanovic     if ( origin == SEEK_SET )
105*51ba086bSDamjan Jovanovic         request->requestBodyOffset = (size_t) offset;
106*51ba086bSDamjan Jovanovic     else if ( origin == SEEK_CUR )
107*51ba086bSDamjan Jovanovic         request->requestBodyOffset += (size_t) offset;
108*51ba086bSDamjan Jovanovic     else if ( origin == SEEK_END )
109*51ba086bSDamjan Jovanovic         request->requestBodyOffset += (size_t) ((curl_off_t)request->requestBodySize + offset);
110*51ba086bSDamjan Jovanovic     else
111*51ba086bSDamjan Jovanovic         return CURL_SEEKFUNC_CANTSEEK;
112*51ba086bSDamjan Jovanovic     if ( request->requestBodyOffset > request->requestBodySize )
113*51ba086bSDamjan Jovanovic         request->requestBodyOffset = request->requestBodySize;
114*51ba086bSDamjan Jovanovic     return CURL_SEEKFUNC_OK;
115*51ba086bSDamjan Jovanovic }
116*51ba086bSDamjan Jovanovic 
117*51ba086bSDamjan Jovanovic size_t CurlRequest::Curl_SendMoreBody( char *buffer, size_t size, size_t nitems, void *userdata )
118*51ba086bSDamjan Jovanovic {
119*51ba086bSDamjan Jovanovic     CurlRequest *request = static_cast< CurlRequest* >( userdata );
120*51ba086bSDamjan Jovanovic     OSL_TRACE("Curl_SendMoreBody");
121*51ba086bSDamjan Jovanovic     return request->curlSendMoreBody( buffer, nitems );
122*51ba086bSDamjan Jovanovic }
123*51ba086bSDamjan Jovanovic 
124*51ba086bSDamjan Jovanovic size_t CurlRequest::curlSendMoreBody( char *buffer, size_t len )
125*51ba086bSDamjan Jovanovic {
126*51ba086bSDamjan Jovanovic     size_t bytesToSend = requestBodySize - requestBodyOffset;
127*51ba086bSDamjan Jovanovic     if ( bytesToSend > len )
128*51ba086bSDamjan Jovanovic         bytesToSend = len;
129*51ba086bSDamjan Jovanovic     memcpy( buffer, requestBody, bytesToSend );
130*51ba086bSDamjan Jovanovic     requestBodyOffset += bytesToSend;
131*51ba086bSDamjan Jovanovic     return bytesToSend;
132*51ba086bSDamjan Jovanovic }
133*51ba086bSDamjan Jovanovic 
134*51ba086bSDamjan Jovanovic void CurlRequest::setProvideCredentialsCallback( bool (*callback)(long statusCode, void *userdata) throw (DAVException), void *userdata )
135*51ba086bSDamjan Jovanovic {
136*51ba086bSDamjan Jovanovic     provideCredentialsCallback = callback;
137*51ba086bSDamjan Jovanovic     provideCredentialsUserdata = userdata;
138*51ba086bSDamjan Jovanovic }
139*51ba086bSDamjan Jovanovic 
140*51ba086bSDamjan Jovanovic void CurlRequest::setURI( CurlUri uri, rtl::OUString path ) throw (DAVException)
141*51ba086bSDamjan Jovanovic {
142*51ba086bSDamjan Jovanovic     if ( curlUrl != NULL )
143*51ba086bSDamjan Jovanovic     {
144*51ba086bSDamjan Jovanovic         curl_url_cleanup( curlUrl );
145*51ba086bSDamjan Jovanovic         curlUrl = NULL;
146*51ba086bSDamjan Jovanovic     }
147*51ba086bSDamjan Jovanovic 
148*51ba086bSDamjan Jovanovic     curlUrl = curl_url();
149*51ba086bSDamjan Jovanovic     if ( curlUrl == NULL )
150*51ba086bSDamjan Jovanovic         throw DAVException( DAVException::DAV_SESSION_CREATE, rtl::OUString::createFromAscii( "Out of memory" ) );
151*51ba086bSDamjan Jovanovic 
152*51ba086bSDamjan Jovanovic     if ( CurlUri( path ).GetHost().isEmpty() )
153*51ba086bSDamjan Jovanovic     {
154*51ba086bSDamjan Jovanovic         // "path" is really a path, not a URI
155*51ba086bSDamjan Jovanovic         curl_url_set( curlUrl, CURLUPART_URL, rtl::OUStringToOString( uri.GetURI(), RTL_TEXTENCODING_UTF8 ).getStr(), 0 );
156*51ba086bSDamjan Jovanovic         curl_url_set( curlUrl, CURLUPART_PATH, rtl::OUStringToOString( path, RTL_TEXTENCODING_UTF8 ).getStr(), 0 );
157*51ba086bSDamjan Jovanovic     }
158*51ba086bSDamjan Jovanovic     else
159*51ba086bSDamjan Jovanovic     {
160*51ba086bSDamjan Jovanovic         // The "path" is a full URI
161*51ba086bSDamjan Jovanovic         curl_url_set( curlUrl, CURLUPART_URL, rtl::OUStringToOString( path, RTL_TEXTENCODING_UTF8 ).getStr(), 0 );
162*51ba086bSDamjan Jovanovic     }
163*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CURLU, curlUrl );
164*51ba086bSDamjan Jovanovic }
165*51ba086bSDamjan Jovanovic 
166*51ba086bSDamjan Jovanovic CURLcode CurlRequest::copy( CurlUri uri, rtl::OUString path ) throw(DAVException)
167*51ba086bSDamjan Jovanovic {
168*51ba086bSDamjan Jovanovic     setURI( uri, path );
169*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPGET, 1L );
170*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "COPY" );
171*51ba086bSDamjan Jovanovic     return perform();
172*51ba086bSDamjan Jovanovic }
173*51ba086bSDamjan Jovanovic 
174*51ba086bSDamjan Jovanovic CURLcode CurlRequest::delete_( CurlUri uri, rtl::OUString path ) throw (DAVException)
175*51ba086bSDamjan Jovanovic {
176*51ba086bSDamjan Jovanovic     setURI( uri, path );
177*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPGET, 1L );
178*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "DELETE" );
179*51ba086bSDamjan Jovanovic     return perform();
180*51ba086bSDamjan Jovanovic }
181*51ba086bSDamjan Jovanovic 
182*51ba086bSDamjan Jovanovic CURLcode CurlRequest::get( CurlUri uri, rtl::OUString path ) throw(DAVException)
183*51ba086bSDamjan Jovanovic {
184*51ba086bSDamjan Jovanovic     setURI( uri, path );
185*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPGET, 1L );
186*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "GET" );
187*51ba086bSDamjan Jovanovic     return perform();
188*51ba086bSDamjan Jovanovic }
189*51ba086bSDamjan Jovanovic 
190*51ba086bSDamjan Jovanovic CURLcode CurlRequest::head( CurlUri uri, rtl::OUString path ) throw (DAVException)
191*51ba086bSDamjan Jovanovic {
192*51ba086bSDamjan Jovanovic     setURI( uri, path );
193*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_NOBODY, 1L );
194*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "HEAD" );
195*51ba086bSDamjan Jovanovic     return perform();
196*51ba086bSDamjan Jovanovic }
197*51ba086bSDamjan Jovanovic 
198*51ba086bSDamjan Jovanovic CURLcode CurlRequest::lock( CurlUri uri, rtl::OUString path ) throw (DAVException)
199*51ba086bSDamjan Jovanovic {
200*51ba086bSDamjan Jovanovic     setURI( uri, path );
201*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_UPLOAD, 1L );
202*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "LOCK" );
203*51ba086bSDamjan Jovanovic     return perform();
204*51ba086bSDamjan Jovanovic }
205*51ba086bSDamjan Jovanovic 
206*51ba086bSDamjan Jovanovic CURLcode CurlRequest::mkcol( CurlUri uri, rtl::OUString path ) throw (DAVException)
207*51ba086bSDamjan Jovanovic {
208*51ba086bSDamjan Jovanovic     setURI( uri, path );
209*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPGET, 1L );
210*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "MKCOL" );
211*51ba086bSDamjan Jovanovic     return perform();
212*51ba086bSDamjan Jovanovic }
213*51ba086bSDamjan Jovanovic 
214*51ba086bSDamjan Jovanovic CURLcode CurlRequest::move( CurlUri uri, rtl::OUString path ) throw (DAVException)
215*51ba086bSDamjan Jovanovic {
216*51ba086bSDamjan Jovanovic     setURI( uri, path );
217*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPGET, 1L );
218*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "MOVE" );
219*51ba086bSDamjan Jovanovic     return perform();
220*51ba086bSDamjan Jovanovic }
221*51ba086bSDamjan Jovanovic 
222*51ba086bSDamjan Jovanovic CURLcode CurlRequest::post( CurlUri uri, rtl::OUString path ) throw (DAVException)
223*51ba086bSDamjan Jovanovic {
224*51ba086bSDamjan Jovanovic     setURI( uri, path );
225*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_UPLOAD, 1L );
226*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "POST" );
227*51ba086bSDamjan Jovanovic     return perform();
228*51ba086bSDamjan Jovanovic }
229*51ba086bSDamjan Jovanovic 
230*51ba086bSDamjan Jovanovic CURLcode CurlRequest::propfind( CurlUri uri, rtl::OUString path ) throw (DAVException)
231*51ba086bSDamjan Jovanovic {
232*51ba086bSDamjan Jovanovic     setURI( uri, path );
233*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_UPLOAD, 1L );
234*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "PROPFIND" );
235*51ba086bSDamjan Jovanovic     return perform();
236*51ba086bSDamjan Jovanovic }
237*51ba086bSDamjan Jovanovic 
238*51ba086bSDamjan Jovanovic CURLcode CurlRequest::proppatch( CurlUri uri, rtl::OUString path ) throw (DAVException)
239*51ba086bSDamjan Jovanovic {
240*51ba086bSDamjan Jovanovic     setURI( uri, path );
241*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_UPLOAD, 1L );
242*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "PROPPATCH" );
243*51ba086bSDamjan Jovanovic     return perform();
244*51ba086bSDamjan Jovanovic }
245*51ba086bSDamjan Jovanovic 
246*51ba086bSDamjan Jovanovic CURLcode CurlRequest::put( CurlUri uri, rtl::OUString path ) throw (DAVException)
247*51ba086bSDamjan Jovanovic {
248*51ba086bSDamjan Jovanovic     setURI( uri, path );
249*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_UPLOAD, 1L );
250*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "PUT" );
251*51ba086bSDamjan Jovanovic     return perform();
252*51ba086bSDamjan Jovanovic }
253*51ba086bSDamjan Jovanovic 
254*51ba086bSDamjan Jovanovic CURLcode CurlRequest::unlock( CurlUri uri, rtl::OUString path ) throw (DAVException)
255*51ba086bSDamjan Jovanovic {
256*51ba086bSDamjan Jovanovic     setURI( uri, path );
257*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_HTTPGET, 1L );
258*51ba086bSDamjan Jovanovic     curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "UNLOCK" );
259*51ba086bSDamjan Jovanovic     return perform();
260*51ba086bSDamjan Jovanovic }
261*51ba086bSDamjan Jovanovic 
262*51ba086bSDamjan Jovanovic CURLcode CurlRequest::perform() throw (DAVException)
263*51ba086bSDamjan Jovanovic {
264*51ba086bSDamjan Jovanovic     CURLcode rc = curl_easy_perform( curl );
265*51ba086bSDamjan Jovanovic     long statusCode = 0;
266*51ba086bSDamjan Jovanovic     curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &statusCode );
267*51ba086bSDamjan Jovanovic     if ( ( statusCode == 401 || statusCode == 407 ) && provideCredentialsCallback != NULL )
268*51ba086bSDamjan Jovanovic     {
269*51ba086bSDamjan Jovanovic         bool haveCredentials = provideCredentialsCallback( statusCode, provideCredentialsUserdata );
270*51ba086bSDamjan Jovanovic         if ( haveCredentials )
271*51ba086bSDamjan Jovanovic         {
272*51ba086bSDamjan Jovanovic             // rewind body:
273*51ba086bSDamjan Jovanovic             requestBodyOffset = 0;
274*51ba086bSDamjan Jovanovic             // retry with credentials:
275*51ba086bSDamjan Jovanovic             rc = curl_easy_perform( curl );
276*51ba086bSDamjan Jovanovic             // If this was to authenticate with the proxy, we may need to authenticate
277*51ba086bSDamjan Jovanovic             // with the destination host too:
278*51ba086bSDamjan Jovanovic             if ( statusCode == 407 )
279*51ba086bSDamjan Jovanovic             {
280*51ba086bSDamjan Jovanovic                 curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &statusCode );
281*51ba086bSDamjan Jovanovic                 if ( statusCode == 401 && provideCredentialsCallback != NULL )
282*51ba086bSDamjan Jovanovic                 {
283*51ba086bSDamjan Jovanovic                     haveCredentials = provideCredentialsCallback( statusCode, provideCredentialsUserdata );
284*51ba086bSDamjan Jovanovic                     if ( haveCredentials )
285*51ba086bSDamjan Jovanovic                     {
286*51ba086bSDamjan Jovanovic                         // rewind body:
287*51ba086bSDamjan Jovanovic                         requestBodyOffset = 0;
288*51ba086bSDamjan Jovanovic                         // retry with credentials:
289*51ba086bSDamjan Jovanovic                         rc = curl_easy_perform( curl );
290*51ba086bSDamjan Jovanovic                     }
291*51ba086bSDamjan Jovanovic                 }
292*51ba086bSDamjan Jovanovic             }
293*51ba086bSDamjan Jovanovic         }
294*51ba086bSDamjan Jovanovic     }
295*51ba086bSDamjan Jovanovic     return rc;
296*51ba086bSDamjan Jovanovic }
297*51ba086bSDamjan Jovanovic 
298*51ba086bSDamjan Jovanovic size_t CurlRequest::Curl_HeaderReceived( char *buffer, size_t size, size_t nitems, void *userdata )
299*51ba086bSDamjan Jovanovic {
300*51ba086bSDamjan Jovanovic     CurlRequest *request = static_cast< CurlRequest* >( userdata );
301*51ba086bSDamjan Jovanovic     OSL_TRACE("Curl_HeaderReceived");
302*51ba086bSDamjan Jovanovic     request->curlHeaderReceived( buffer, nitems );
303*51ba086bSDamjan Jovanovic     return nitems;
304*51ba086bSDamjan Jovanovic }
305*51ba086bSDamjan Jovanovic 
306*51ba086bSDamjan Jovanovic void CurlRequest::curlHeaderReceived( const char *buffer, size_t size )
307*51ba086bSDamjan Jovanovic {
308*51ba086bSDamjan Jovanovic     rtl::OString lineCrLf( buffer, size );
309*51ba086bSDamjan Jovanovic     sal_Int32 cr = lineCrLf.indexOf( "\r" );
310*51ba086bSDamjan Jovanovic     if ( cr < 0 )
311*51ba086bSDamjan Jovanovic         return;
312*51ba086bSDamjan Jovanovic 
313*51ba086bSDamjan Jovanovic     rtl::OString line = lineCrLf.copy( 0, cr );
314*51ba086bSDamjan Jovanovic     if ( line.indexOf( "HTTP/" ) == 0 )
315*51ba086bSDamjan Jovanovic     {
316*51ba086bSDamjan Jovanovic         // Status line
317*51ba086bSDamjan Jovanovic         // Throw away any response headers from a prior response:
318*51ba086bSDamjan Jovanovic         responseHeaders.clear();
319*51ba086bSDamjan Jovanovic         sal_Int32 idxFirstSpace = line.indexOf( ' ' );
320*51ba086bSDamjan Jovanovic         if ( idxFirstSpace > 0 )
321*51ba086bSDamjan Jovanovic         {
322*51ba086bSDamjan Jovanovic             int idxSecondSpace = line.indexOf( ' ', idxFirstSpace + 1 );
323*51ba086bSDamjan Jovanovic             if ( idxSecondSpace > 0 )
324*51ba086bSDamjan Jovanovic             {
325*51ba086bSDamjan Jovanovic                 reasonPhrase = line.copy( idxSecondSpace + 1 );
326*51ba086bSDamjan Jovanovic                 statusCode = line.copy( idxFirstSpace + 1, idxSecondSpace - idxFirstSpace - 1 ).toInt32();
327*51ba086bSDamjan Jovanovic             }
328*51ba086bSDamjan Jovanovic             else
329*51ba086bSDamjan Jovanovic             {
330*51ba086bSDamjan Jovanovic                 reasonPhrase = "";
331*51ba086bSDamjan Jovanovic                 statusCode = line.copy( idxFirstSpace + 1 ).toInt32();
332*51ba086bSDamjan Jovanovic             }
333*51ba086bSDamjan Jovanovic         }
334*51ba086bSDamjan Jovanovic     }
335*51ba086bSDamjan Jovanovic     else
336*51ba086bSDamjan Jovanovic     {
337*51ba086bSDamjan Jovanovic         // Header line
338*51ba086bSDamjan Jovanovic         if ( line.getLength() == 0 )
339*51ba086bSDamjan Jovanovic         {
340*51ba086bSDamjan Jovanovic             // End of HTTP header
341*51ba086bSDamjan Jovanovic             // Discard any intermediate body from 100 Trying or 401 Authentication required:
342*51ba086bSDamjan Jovanovic             responseBodyInputStream = new CurlInputStream();
343*51ba086bSDamjan Jovanovic             return;
344*51ba086bSDamjan Jovanovic         }
345*51ba086bSDamjan Jovanovic         sal_Int32 colon = line.indexOf( ':' );
346*51ba086bSDamjan Jovanovic         if ( colon < 0 )
347*51ba086bSDamjan Jovanovic         {
348*51ba086bSDamjan Jovanovic             OSL_TRACE("Non-empty HTTP line without a ':'. Folded header deprecated by RFC 7230?");
349*51ba086bSDamjan Jovanovic             return;
350*51ba086bSDamjan Jovanovic         }
351*51ba086bSDamjan Jovanovic         Header header;
352*51ba086bSDamjan Jovanovic         header.name = line.copy( 0, colon ).toAsciiLowerCase();
353*51ba086bSDamjan Jovanovic         header.value = line.copy( colon + 1 ).trim();
354*51ba086bSDamjan Jovanovic         responseHeaders.push_back(header);
355*51ba086bSDamjan Jovanovic     }
356*51ba086bSDamjan Jovanovic }
357*51ba086bSDamjan Jovanovic 
358*51ba086bSDamjan Jovanovic const CurlRequest::Header *CurlRequest::findResponseHeader( const rtl::OString &name )
359*51ba086bSDamjan Jovanovic {
360*51ba086bSDamjan Jovanovic     std::vector< CurlRequest::Header >::const_iterator it( responseHeaders.begin() );
361*51ba086bSDamjan Jovanovic     const std::vector< CurlRequest::Header >::const_iterator end( responseHeaders.end() );
362*51ba086bSDamjan Jovanovic     for ( ; it != end; it++ )
363*51ba086bSDamjan Jovanovic     {
364*51ba086bSDamjan Jovanovic         if ( name.equalsIgnoreAsciiCase( it->name ) )
365*51ba086bSDamjan Jovanovic             return &(*it);
366*51ba086bSDamjan Jovanovic     }
367*51ba086bSDamjan Jovanovic     return NULL;
368*51ba086bSDamjan Jovanovic }
369*51ba086bSDamjan Jovanovic 
370*51ba086bSDamjan Jovanovic void CurlRequest::saveResponseBodyTo( const uno::Reference< io::XOutputStream > & xOutStream)
371*51ba086bSDamjan Jovanovic {
372*51ba086bSDamjan Jovanovic     xOutputStream = xOutStream;
373*51ba086bSDamjan Jovanovic }
374*51ba086bSDamjan Jovanovic 
375*51ba086bSDamjan Jovanovic size_t CurlRequest::Curl_MoreBodyReceived( char *buffer, size_t size, size_t nitems, void *userdata )
376*51ba086bSDamjan Jovanovic {
377*51ba086bSDamjan Jovanovic     CurlRequest *request = static_cast< CurlRequest* >( userdata );
378*51ba086bSDamjan Jovanovic     request->curlMoreBodyReceived( buffer, nitems );
379*51ba086bSDamjan Jovanovic     return nitems;
380*51ba086bSDamjan Jovanovic }
381*51ba086bSDamjan Jovanovic 
382*51ba086bSDamjan Jovanovic void CurlRequest::curlMoreBodyReceived( const char *buffer, size_t size )
383*51ba086bSDamjan Jovanovic {
384*51ba086bSDamjan Jovanovic     if ( xOutputStream.is() )
385*51ba086bSDamjan Jovanovic     {
386*51ba086bSDamjan Jovanovic         const uno::Sequence< sal_Int8 > aDataSeq( (sal_Int8 *)buffer, size );
387*51ba086bSDamjan Jovanovic         xOutputStream->writeBytes( aDataSeq );
388*51ba086bSDamjan Jovanovic     }
389*51ba086bSDamjan Jovanovic     else if ( responseBodyInputStream.is() )
390*51ba086bSDamjan Jovanovic         responseBodyInputStream->AddToStream( buffer, size );
391*51ba086bSDamjan Jovanovic }