Project

General

Profile

Curl Scol plugin
sCurl.cpp
1/*
2-----------------------------------------------------------------------------
3This source file is part of OpenSpace3D
4For the latest info, see http://www.openspace3d.com
5
6Copyright (c) 2012 I-maginer
7
8This program is free software; you can redistribute it and/or modify it under
9the terms of the GNU Lesser General Public License as published by the Free Software
10Foundation; either version 2 of the License, or (at your option) any later
11version.
12
13This program is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16
17You should have received a copy of the GNU Lesser General Public License along with
18this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20http://www.gnu.org/copyleft/lesser.txt
21
22-----------------------------------------------------------------------------
23*/
24
25#include "sCurl.h"
26#include <iostream>
27#include <string>
28#include <algorithm>
29
30extern int CURL_DATA_CB;
31
32bool SCurl::CheckUrl(const std::string& url_s)
33{
34 Uri checkUri = Uri::Parse(url_s);
35 return !checkUri.Host.empty();
36}
37
38SCurl::SCurl(const std::string& url)
39{
40 m_curl = 0;
41 m_url = url;
42 m_terminate = false;
43}
44
46{
47 {
48 // to force curl to terminate the request
49 boost::mutex::scoped_lock lock(m_terminateMutex);
50 m_terminate = true;
51 }
52
53 // mutex to be sure that the process is not in the service queue but already passed in the threaded function
54 m_thread_lock.lock();
55 {
56 // mutex to wait for the threaded function to terminate
57 boost::mutex::scoped_lock lock(m_mutex);
58 m_options.clear();
59 m_formFields.clear();
60 }
61
62 // free upload buffer
63 for (size_t i = 0; i < m_options.size(); i++)
64 {
65 switch (m_options[i].type)
66 {
67 case 3 :
68 {
69 if (m_options[i].option == CURLOPT_UPLOAD)
70 {
71 if (m_options[i].uploadData.buf)
72 free(m_options[i].uploadData.buf);
73 }
74 }
75 break;
76 }
77 }
78
79 m_thread_lock.unlock();
80}
81
82size_t SCurl::Write_data(char* ptr, size_t size, size_t nmemb, void* userdata)
83{
84 SCurl* curlObj = (SCurl*) userdata;
85 size_t realsize = size * nmemb;
86 SCbData* data = new SCbData(ptr, realsize, -1);
87 OBJpostEvent(CURL_DATA_CB, SCOL_PTR userdata, SCOL_PTR data);
88 return realsize;
89}
90
91int SCurl::Progress(void *userdata, double dltotal, double dlnow, double ultotal, double ulnow)
92{
93 SCurl* curlObj = (SCurl*) userdata;
94
95 boost::mutex::scoped_lock lock(curlObj->m_terminateMutex);
96 // used to terminate the request
97 if (curlObj->m_terminate)
98 return 1;
99
100 return 0;
101}
102
103void SCurl::ExecSync()
104{
105 boost::mutex::scoped_lock lock(m_mutex);
106 CURLcode res = CURLE_FAILED_INIT;
107 m_curl = curl_easy_init();
108
109 if(m_curl)
110 {
111 // set default options
112 curl_easy_setopt(m_curl, CURLOPT_NOSIGNAL, 1L);
113 curl_easy_setopt(m_curl, CURLOPT_USERAGENT, "ScolCurl-agent/1.0");
114 curl_easy_setopt(m_curl, CURLOPT_URL, m_url.c_str());
115
116 // bind callback
117 curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, (void *)this);
118 curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, SCurl::Write_data);
119
120 curl_easy_setopt(m_curl, CURLOPT_PROGRESSDATA, (void *)this);
121 curl_easy_setopt(m_curl, CURLOPT_PROGRESSFUNCTION, SCurl::Write_data);
122
123 // Form fields
124 struct curl_httppost* formPost = 0;
125 struct curl_httppost* lastFormPost = 0;
126
127 if(!m_formFields.empty())
128 {
129 for (size_t i = 0; i < m_formFields.size(); i++)
130 {
131 curl_formadd(&formPost, &lastFormPost, CURLFORM_COPYNAME, m_formFields[i].name.c_str(), m_formFields[i].file ? CURLFORM_FILE : CURLFORM_COPYCONTENTS, m_formFields[i].value.c_str(), CURLFORM_END);
132 }
133 }
134
135 if(formPost)
136 curl_easy_setopt(m_curl, CURLOPT_HTTPPOST, formPost);
137
138 // CURL options
139 std::vector<curl_slist*> clist;
140 for (size_t i = 0; i < m_options.size(); i++)
141 {
142 switch (m_options[i].type)
143 {
144 case 0 :
145 curl_easy_setopt(m_curl, m_options[i].option, m_options[i].lvalue);
146 break;
147
148 case 1 :
149 curl_easy_setopt(m_curl, m_options[i].option, m_options[i].svalue.c_str());
150 break;
151
152 case 2 :
153 {
154 struct curl_slist* vlist = 0;
155 for (size_t j = 0; j < m_options[i].values.size(); j++)
156 {
157 vlist = curl_slist_append(vlist, m_options[i].values[j].c_str());
158 }
159 clist.push_back(vlist);
160
161 curl_easy_setopt(m_curl, m_options[i].option, vlist);
162 }
163 break;
164
165 case 3 :
166 {
167 if (m_options[i].option == CURLOPT_UPLOAD)
168 {
169 curl_easy_setopt(m_curl, CURLOPT_READFUNCTION, m_options[i].payloadSource);
170 curl_easy_setopt(m_curl, CURLOPT_READDATA, &(m_options[i]));
171 curl_easy_setopt(m_curl, CURLOPT_UPLOAD, 1L);
172 }
173 }
174 break;
175 }
176 }
177
178 // call request
179 res = curl_easy_perform(m_curl);
180
181 // free param lists
182 for (size_t i = 0; i < clist.size(); i++)
183 {
184 curl_slist_free_all(clist[i]);
185 }
186 clist.clear();
187
188 // free form fields
189 if(formPost)
190 curl_formfree(formPost);
191
192 // clean CURL
193 curl_easy_cleanup(m_curl);
194 m_curl = 0;
195 }
196
197 if(res != CURLE_OK)
198 MMechostr(MSKRUNTIME, "Curl error (%i) : %s\n", res, curl_easy_strerror(res));
199
200 SCbData* data = new SCbData("", 0, res);
201 OBJpostEvent(CURL_DATA_CB, SCOL_PTR this, SCOL_PTR data);
202
203 m_thread_lock.unlock();
204}
205
206void SCurl::CallAsync()
207{
208 m_thread_lock.lock();
209 try
210 {
211 SService* service = SService::GetInstance();
212 service->addWork(boost::bind(&SCurl::ExecSync, this));
213 }
214 catch(std::exception &e)
215 {
216 MMechostr(MSKRUNTIME, "SCurl thread error : %s, call the request synchronously.\n", e.what());
217 ExecSync();
218 }
219}
220
221void SCurl::CallSync()
222{
223 m_thread_lock.lock();
224 ExecSync();
225}
226
227void SCurl::AddFormField(const std::string& name, const std::string& value, const bool& file)
228{
229 SFormField field(name, value, file);
230 m_formFields.push_back(field);
231}
232
233void SCurl::SetHeader(const std::vector<std::string>& header)
234{
235 SCurlOption option(CURLOPT_HTTPHEADER, header);
236 m_options.push_back(option);
237}
238
239void SCurl::SetOption(const CURLoption& opt, const int& value)
240{
241 switch(opt)
242 {
243 case CURLOPT_HEADER :
244 case CURLOPT_PROXYPORT :
245 case CURLOPT_PROXYTYPE :
246 case CURLOPT_HTTPPROXYTUNNEL :
247 case CURLOPT_SOCKS5_GSSAPI_NEC :
248 case CURLOPT_LOCALPORT :
249 case CURLOPT_LOCALPORTRANGE :
250 case CURLOPT_DNS_CACHE_TIMEOUT :
251 case CURLOPT_BUFFERSIZE :
252 case CURLOPT_PORT :
253 case CURLOPT_TCP_NODELAY :
254 case CURLOPT_ADDRESS_SCOPE :
255 case CURLOPT_TCP_KEEPALIVE :
256 case CURLOPT_TCP_KEEPIDLE :
257 case CURLOPT_TCP_KEEPINTVL :
258 case CURLOPT_NETRC :
259 case CURLOPT_HTTPAUTH :
260 case CURLOPT_PROXYAUTH :
261 case CURLOPT_AUTOREFERER :
262 case CURLOPT_FOLLOWLOCATION :
263 case CURLOPT_UNRESTRICTED_AUTH :
264 case CURLOPT_MAXREDIRS :
265 case CURLOPT_POSTREDIR :
266 case CURLOPT_PUT :
267 case CURLOPT_POST :
268 case CURLOPT_POSTFIELDSIZE :
269 case CURLOPT_POSTFIELDSIZE_LARGE :
270 case CURLOPT_COOKIESESSION :
271 case CURLOPT_HTTPGET :
272 case CURLOPT_HTTPPOST :
273 case CURLOPT_HTTP_VERSION :
274 case CURLOPT_IGNORE_CONTENT_LENGTH :
275 case CURLOPT_HTTP_CONTENT_DECODING :
276 case CURLOPT_HTTP_TRANSFER_DECODING :
277 case CURLOPT_TFTP_BLKSIZE :
278 case CURLOPT_DIRLISTONLY :
279 case CURLOPT_APPEND :
280 case CURLOPT_FTP_USE_EPRT :
281 case CURLOPT_FTP_USE_EPSV :
282 case CURLOPT_FTP_CREATE_MISSING_DIRS :
283 case CURLOPT_FTP_RESPONSE_TIMEOUT :
284 case CURLOPT_FTP_SKIP_PASV_IP :
285 case CURLOPT_FTPSSLAUTH :
286 case CURLOPT_FTP_SSL_CCC :
287 case CURLOPT_FTP_FILEMETHOD :
288 case CURLOPT_RTSP_REQUEST :
289 case CURLOPT_RTSP_CLIENT_CSEQ :
290 case CURLOPT_RTSP_SERVER_CSEQ :
291 case CURLOPT_TRANSFERTEXT :
292 case CURLOPT_PROXY_TRANSFER_MODE :
293 case CURLOPT_CRLF :
294 case CURLOPT_RANGE :
295 case CURLOPT_RESUME_FROM :
296 case CURLOPT_RESUME_FROM_LARGE :
297 case CURLOPT_CUSTOMREQUEST :
298 case CURLOPT_FILETIME :
299 case CURLOPT_NOBODY :
300 case CURLOPT_INFILESIZE :
301 case CURLOPT_INFILESIZE_LARGE :
302 case CURLOPT_UPLOAD :
303 case CURLOPT_MAXFILESIZE :
304 case CURLOPT_MAXFILESIZE_LARGE :
305 case CURLOPT_TIMECONDITION :
306 case CURLOPT_TIMEVALUE :
307 case CURLOPT_TIMEOUT :
308 case CURLOPT_TIMEOUT_MS :
309 case CURLOPT_LOW_SPEED_LIMIT :
310 case CURLOPT_LOW_SPEED_TIME :
311 case CURLOPT_MAX_SEND_SPEED_LARGE :
312 case CURLOPT_MAX_RECV_SPEED_LARGE :
313 case CURLOPT_MAXCONNECTS :
314 case CURLOPT_FRESH_CONNECT :
315 case CURLOPT_FORBID_REUSE :
316 case CURLOPT_CONNECTTIMEOUT :
317 case CURLOPT_CONNECTTIMEOUT_MS :
318 case CURLOPT_IPRESOLVE :
319 case CURLOPT_CONNECT_ONLY :
320 case CURLOPT_USE_SSL :
321 case CURLOPT_ACCEPTTIMEOUT_MS :
322 case CURLOPT_SSLVERSION :
323 case CURLOPT_SSL_VERIFYPEER :
324 case CURLOPT_SSL_VERIFYHOST :
325 case CURLOPT_CERTINFO :
326 case CURLOPT_SSL_SESSIONID_CACHE :
327 case CURLOPT_SSL_OPTIONS :
328 case CURLOPT_GSSAPI_DELEGATION :
329 case CURLOPT_SSH_AUTH_TYPES :
330 case CURLOPT_NEW_FILE_PERMS :
331 case CURLOPT_NEW_DIRECTORY_PERMS :
332 {
333 SCurlOption option(opt, (long)value);
334 m_options.push_back(option);
335 break;
336 }
337
338 default:
339 MMechostr(MSKRUNTIME, "CURL option not found or not implemented with this param type\n");
340 }
341}
342
343void SCurl::SetOption(const CURLoption& opt, const std::string& value)
344{
345 switch(opt)
346 {
347 case CURLOPT_URL :
348 case CURLOPT_PROXY :
349 case CURLOPT_NOPROXY :
350 case CURLOPT_SOCKS5_GSSAPI_SERVICE :
351 case CURLOPT_INTERFACE :
352 case CURLOPT_NETRC_FILE :
353 case CURLOPT_USERPWD :
354 case CURLOPT_PROXYUSERPWD :
355 case CURLOPT_USERNAME :
356 case CURLOPT_PASSWORD :
357 case CURLOPT_PROXYUSERNAME :
358 case CURLOPT_PROXYPASSWORD :
359 case CURLOPT_TLSAUTH_USERNAME :
360 case CURLOPT_TLSAUTH_PASSWORD :
361 case CURLOPT_ACCEPT_ENCODING :
362 case CURLOPT_TRANSFER_ENCODING :
363 case CURLOPT_COPYPOSTFIELDS :
364 case CURLOPT_REFERER :
365 case CURLOPT_USERAGENT :
366 case CURLOPT_COOKIE :
367 case CURLOPT_COOKIEFILE :
368 case CURLOPT_COOKIEJAR :
369 case CURLOPT_COOKIELIST :
370 case CURLOPT_MAIL_FROM :
371 case CURLOPT_MAIL_AUTH :
372 case CURLOPT_FTPPORT :
373 case CURLOPT_FTP_ALTERNATIVE_TO_USER :
374 case CURLOPT_FTP_ACCOUNT :
375 case CURLOPT_RTSP_SESSION_ID :
376 case CURLOPT_RTSP_STREAM_URI :
377 case CURLOPT_RTSP_TRANSPORT :
378 case CURLOPT_RANGE :
379 case CURLOPT_CUSTOMREQUEST :
380 case CURLOPT_SSLCERT :
381 case CURLOPT_SSLCERTTYPE :
382 case CURLOPT_SSLKEY :
383 case CURLOPT_SSLKEYTYPE :
384 case CURLOPT_KEYPASSWD :
385 case CURLOPT_SSLENGINE :
386 case CURLOPT_SSLENGINE_DEFAULT :
387 case CURLOPT_CAINFO :
388 case CURLOPT_ISSUERCERT :
389 case CURLOPT_CAPATH :
390 case CURLOPT_CRLFILE :
391 case CURLOPT_RANDOM_FILE :
392 case CURLOPT_EGDSOCKET :
393 case CURLOPT_SSL_CIPHER_LIST :
394 case CURLOPT_KRBLEVEL :
395 case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 :
396 case CURLOPT_SSH_PUBLIC_KEYFILE :
397 case CURLOPT_SSH_PRIVATE_KEYFILE :
398 case CURLOPT_SSH_KNOWNHOSTS :
399 case CURLOPT_POSTFIELDS :
400 {
401 SCurlOption option(opt, value);
402 m_options.push_back(option);
403 break;
404 }
405
406 default:
407 MMechostr(MSKRUNTIME, "CURL option not found or not implemented with this param type\n");
408 }
409}
410
411void SCurl::SetOption(const CURLoption& opt, const std::vector<std::string>& value)
412{
413 switch(opt)
414 {
415 case CURLOPT_HTTPHEADER :
416 case CURLOPT_MAIL_RCPT :
417 case CURLOPT_QUOTE :
418 case CURLOPT_POSTQUOTE :
419 case CURLOPT_PREQUOTE :
420 case CURLOPT_RESOLVE :
421 case CURLOPT_DNS_SERVERS :
422 case CURLOPT_TELNETOPTIONS :
423 {
424 SCurlOption option(opt, value);
425 m_options.push_back(option);
426 break;
427 }
428
429 default:
430 MMechostr(MSKRUNTIME, "CURL option not found or not implemented with this param type\n");
431 }
432}
433
434void SCurl::SetOption(const CURLoption& opt, const char* mvalue, const unsigned int size)
435{
436 switch(opt)
437 {
438 case CURLOPT_UPLOAD :
439 {
440 SCurlOption option(opt, mvalue, size);
441 m_options.push_back(option);
442 break;
443 }
444
445 default:
446 MMechostr(MSKRUNTIME, "CURL option not found or not implemented with this param type\n");
447 }
448}
Definition sCurl.h:269
~SCurl()
Definition sCurl.cpp:45
SCurl(const std::string &url)
Definition sCurl.cpp:38
Definition sCurl.h:44