Mercurial > hg > octave-jordi
annotate src/DLD-FUNCTIONS/urlwrite.cc @ 8151:3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 26 Sep 2008 13:16:42 -0400 |
parents | 78f3811155f7 |
children | eb63fbe60fab |
rev | line source |
---|---|
6043 | 1 // urlwrite and urlread, a curl front-end for octave |
2 /* | |
3 | |
7017 | 4 Copyright (C) 2006, 2007 Alexander Barth |
6043 | 5 |
6 This file is part of Octave. | |
7 | |
8 Octave is free software; you can redistribute it and/or modify it | |
9 under the terms of the GNU General Public License as published by the | |
7016 | 10 Free Software Foundation; either version 3 of the License, or (at your |
11 option) any later version. | |
6043 | 12 |
13 Octave is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
7016 | 19 along with Octave; see the file COPYING. If not, see |
20 <http://www.gnu.org/licenses/>. | |
6043 | 21 |
22 */ | |
23 | |
24 // Author: Alexander Barth <abarth@marine.usf.edu> | |
25 // Adapted-By: jwe | |
26 | |
27 #ifdef HAVE_CONFIG_H | |
28 #include <config.h> | |
29 #endif | |
30 | |
31 #include <string> | |
32 #include <fstream> | |
33 #include <iomanip> | |
34 | |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
35 #include "file-ops.h" |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
36 #include "file-stat.h" |
6043 | 37 #include "oct-env.h" |
38 | |
39 #include "defun-dld.h" | |
40 #include "error.h" | |
41 #include "oct-obj.h" | |
42 #include "ov-cell.h" | |
43 #include "pager.h" | |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
44 #include "unwind-prot.h" |
6043 | 45 |
46 #if defined (HAVE_CURL) | |
47 | |
48 #include <curl/curl.h> | |
49 #include <curl/types.h> | |
50 #include <curl/easy.h> | |
51 | |
52 // Write callback function for curl. | |
53 | |
6986 | 54 static int |
6043 | 55 write_data (void *buffer, size_t size, size_t nmemb, void *streamp) |
56 { | |
57 // *stream is actually an ostream object. | |
58 std::ostream& stream = *(static_cast<std::ostream*> (streamp)); | |
59 stream.write (static_cast<const char*> (buffer), size*nmemb); | |
60 return (stream.fail () ? 0 : size * nmemb); | |
61 } | |
62 | |
63 // Form the query string based on param. | |
64 | |
6986 | 65 static std::string |
6043 | 66 form_query_string (CURL *curl, const Cell& param) |
67 { | |
68 std::ostringstream query; | |
69 | |
70 for (int i = 0; i < param.numel (); i += 2) | |
71 { | |
72 std::string name = param(i).string_value (); | |
73 std::string text = param(i+1).string_value (); | |
74 | |
75 // Encode strings. | |
76 char *enc_name = curl_easy_escape (curl, name.c_str (), name.length ()); | |
77 char *enc_text = curl_easy_escape (curl, text.c_str (), text.length ()); | |
78 | |
79 query << enc_name << "=" << enc_text; | |
80 | |
81 curl_free (enc_name); | |
82 curl_free (enc_text); | |
83 | |
84 if (i < param.numel()-1) | |
85 query << "&"; | |
86 } | |
87 | |
88 query.flush (); | |
89 | |
90 return query.str (); | |
91 } | |
92 | |
93 // curl front-end | |
94 | |
6992 | 95 static void |
96 urlget_cleanup (CURL *curl) | |
97 { | |
98 curl_easy_cleanup (curl); | |
99 curl_global_cleanup (); | |
100 } | |
101 | |
6986 | 102 static CURLcode |
6043 | 103 urlget (const std::string& url, const std::string& method, |
104 const Cell& param, std::ostream& stream) | |
105 { | |
106 CURL *curl; | |
107 | |
108 curl_global_init(CURL_GLOBAL_DEFAULT); | |
109 | |
110 curl = curl_easy_init(); | |
111 | |
112 if (! curl) | |
113 return CURLE_FAILED_INIT; | |
114 | |
115 // handle paramters of GET or POST request | |
116 | |
117 std::string query_string = form_query_string (curl,param); | |
118 //octave_stdout << "query_string " << query_string << std::endl; | |
119 | |
120 if (method == "get") | |
121 { | |
122 query_string = url + "?" + query_string; | |
123 curl_easy_setopt (curl, CURLOPT_URL, query_string.c_str ()); | |
124 } | |
125 else if (method == "post") | |
126 { | |
127 curl_easy_setopt (curl, CURLOPT_URL, url.c_str ()); | |
128 curl_easy_setopt (curl, CURLOPT_POSTFIELDS, query_string.c_str ()); | |
129 } | |
130 else | |
7013 | 131 curl_easy_setopt (curl, CURLOPT_URL, url.c_str()); |
6043 | 132 |
133 // Define our callback to get called when there's data to be written. | |
134 curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, write_data); | |
135 | |
136 // Set a pointer to our struct to pass to the callback. | |
137 curl_easy_setopt (curl, CURLOPT_WRITEDATA, static_cast<void*> (&stream)); | |
138 | |
6390 | 139 // Follow redirects. |
7013 | 140 curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, true); |
141 | |
142 // Don't use EPSV since connecting to sites that don't support it | |
143 // will hang for some time (3 minutes?) before moving on to try PASV | |
144 // instead. | |
145 curl_easy_setopt (curl, CURLOPT_FTP_USE_EPSV, false); | |
6390 | 146 |
6992 | 147 curl_easy_setopt (curl, CURLOPT_NOPROGRESS, true); |
6043 | 148 curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, url.c_str ()); |
149 curl_easy_setopt (curl, CURLOPT_FAILONERROR, true); | |
150 | |
7013 | 151 // Switch on full protocol/debug output. |
152 // curl_easy_setopt (curl, CURLOPT_VERBOSE, true); | |
6043 | 153 |
6992 | 154 CURLcode res = CURLE_OK; |
155 | |
156 // To understand the following, see the definitions of these macros | |
157 // in libcruft/misc/quit.h. The idea is that we call sigsetjmp here | |
158 // then the signal handler calls siglongjmp to get back here | |
159 // immediately. Then we perform some cleanup and throw an interrupt | |
160 // exception which will get us back to the top level, cleaning up | |
161 // any local C++ objects on the stack as we go. | |
162 | |
163 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_1; | |
164 | |
165 // We were interrupted (this code is inside a block that is only | |
166 // called when siglongjmp is called from a signal handler). | |
6043 | 167 |
6992 | 168 // Is there a better error code to use? Maybe it doesn't matter |
169 // because we are about to throw an execption. | |
170 | |
171 res = CURLE_ABORTED_BY_CALLBACK; | |
172 urlget_cleanup (curl); | |
7481
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7031
diff
changeset
|
173 octave_rethrow_exception (); |
6992 | 174 |
175 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_2; | |
6043 | 176 |
6992 | 177 res = curl_easy_perform (curl); |
178 | |
179 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
180 | |
181 // If we are not interuppted, we will end up here, so we still need | |
182 // to clean up. | |
183 | |
184 urlget_cleanup (curl); | |
6043 | 185 |
186 return res; | |
187 } | |
188 | |
189 #endif | |
190 | |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
191 static bool urlwrite_delete_file; |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
192 |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
193 static std::string urlwrite_filename; |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
194 |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
195 static void |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
196 urlwrite_cleanup_file (void *) |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
197 { |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
198 if (urlwrite_delete_file) |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
199 file_ops::unlink (urlwrite_filename); |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
200 } |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
201 |
6043 | 202 DEFUN_DLD (urlwrite, args, nargout, |
203 "-*- texinfo -*-\n\ | |
204 @deftypefn {Loadable Function} {} urlwrite (@var{URL}, @var{localfile})\n\ | |
205 @deftypefnx {Loadable Function} {@var{f} =} urlwrite (@var{url}, @var{localfile})\n\ | |
206 @deftypefnx {Loadable Function} {[@var{f}, @var{success}] =} urlwrite (@var{url}, @var{localfile})\n\ | |
207 @deftypefnx {Loadable Function} {[@var{f}, @var{success}, @var{message}] =} urlwrite (@var{url}, @var{localfile})\n\ | |
208 Download a remote file specified by its @var{URL} and save it as\n\ | |
209 @var{localfile}. For example,\n\ | |
210 \n\ | |
211 @example\n\ | |
7031 | 212 urlwrite (\"ftp://ftp.octave.org/pub/octave/README\", \n\ |
213 \"README.txt\");\n\ | |
6043 | 214 @end example\n\ |
215 \n\ | |
216 The full path of the downloaded file is returned in @var{f}. The\n\ | |
217 variable @var{success} is 1 if the download was successful,\n\ | |
218 otherwise it is 0 in which case @var{message} contains an error\n\ | |
219 message. If no output argument is specified and if an error occurs,\n\ | |
6588 | 220 then the error is signaled through Octave's error handling mechanism.\n\ |
6043 | 221 \n\ |
222 This function uses libcurl. Curl supports, among others, the HTTP,\n\ | |
223 FTP and FILE protocols. Username and password may be specified in\n\ | |
224 the URL, for example:\n\ | |
225 \n\ | |
226 @example\n\ | |
6588 | 227 urlwrite (\"http://username:password@@example.com/file.txt\",\n\ |
228 \"file.txt\");\n\ | |
6043 | 229 @end example\n\ |
230 \n\ | |
231 GET and POST requests can be specified by @var{method} and @var{param}.\n\ | |
6589 | 232 The parameter @var{method} is either @samp{get} or @samp{post}\n\ |
6588 | 233 and @var{param} is a cell array of parameter and value pairs.\n\ |
234 For example:\n\ | |
6043 | 235 \n\ |
236 @example\n\ | |
6588 | 237 urlwrite (\"http://www.google.com/search\", \"search.html\",\n\ |
238 \"get\", @{\"query\", \"octave\"@});\n\ | |
6043 | 239 @end example\n\ |
240 @seealso{urlread}\n\ | |
241 @end deftypefn") | |
242 { | |
243 octave_value_list retval; | |
244 | |
245 #if defined (HAVE_CURL) | |
246 | |
247 int nargin = args.length (); | |
248 | |
249 // verify arguments | |
250 if (nargin != 2 && nargin != 4) | |
251 { | |
252 print_usage (); | |
253 return retval; | |
254 } | |
255 | |
256 std::string url = args(0).string_value(); | |
257 | |
258 if (error_state) | |
259 { | |
260 error ("urlwrite: url must be a character string"); | |
261 return retval; | |
262 } | |
263 | |
264 // name to store the file if download is succesful | |
265 std::string filename = args(1).string_value(); | |
266 | |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
267 urlwrite_filename = filename; |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
268 |
6043 | 269 if (error_state) |
270 { | |
271 error ("urlwrite: localfile must be a character string"); | |
272 return retval; | |
273 } | |
274 | |
275 std::string method; | |
276 Cell param; // empty cell array | |
277 | |
278 if (nargin == 4) | |
279 { | |
280 method = args(2).string_value(); | |
281 | |
282 if (error_state) | |
283 { | |
284 error ("urlwrite: method can only be \"get\" or \"post\""); | |
285 return retval; | |
286 } | |
287 | |
288 if (method != "get" && method != "post") | |
289 { | |
290 error ("urlwrite: method can only be \"get\" or \"post\""); | |
291 return retval; | |
292 } | |
293 | |
294 param = args(3).cell_value(); | |
295 | |
296 if (error_state) | |
297 { | |
298 error ("urlwrite: parameters for get and post requests must be given as a cell"); | |
299 return retval; | |
300 } | |
301 | |
302 | |
303 if (param.numel () % 2 == 1 ) | |
304 { | |
305 error ("urlwrite: number of elements in param must be even"); | |
306 return retval; | |
307 } | |
308 } | |
309 | |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
310 // The file should only be deleted if it doesn't initially exist, we |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
311 // create it, and the download fails. We use unwind_protect to do |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
312 // it so that the deletion happens no matter how we exit the function. |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
313 |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
314 file_stat fs (filename); |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
315 |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
316 urlwrite_delete_file = ! fs.exists (); |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
317 |
6986 | 318 std::ofstream ofile (filename.c_str(), std::ios::out | std::ios::binary); |
6043 | 319 |
6986 | 320 if (! ofile.is_open ()) |
6043 | 321 { |
322 error ("urlwrite: unable to open file"); | |
323 return retval; | |
324 } | |
325 | |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
326 unwind_protect::add (urlwrite_cleanup_file); |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
327 |
6986 | 328 CURLcode res = urlget (url, method, param, ofile); |
6043 | 329 |
6986 | 330 ofile.close (); |
6043 | 331 |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
332 urlwrite_delete_file = (res != CURLE_OK); |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
333 |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
334 unwind_protect::run (); |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
335 |
6043 | 336 if (nargout > 0) |
337 { | |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
338 if (res == CURLE_OK) |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
339 { |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
340 retval(2) = std::string (); |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
341 retval(1) = true; |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
342 retval(0) = octave_env::make_absolute (filename, octave_env::getcwd ()); |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
343 } |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
344 else |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
345 { |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
346 retval(2) = std::string (curl_easy_strerror (res)); |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
347 retval(1) = false; |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
348 retval(0) = std::string (); |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
349 } |
6043 | 350 } |
351 | |
6484 | 352 if (nargout < 2 && res != CURLE_OK) |
6043 | 353 error ("urlwrite: curl: %s", curl_easy_strerror (res)); |
354 | |
355 #else | |
6981 | 356 error ("urlwrite: not available in this version of Octave"); |
6043 | 357 #endif |
358 | |
359 return retval; | |
360 } | |
361 | |
362 DEFUN_DLD (urlread, args, nargout, | |
363 "-*- texinfo -*-\n\ | |
6549 | 364 @deftypefn {Loadable Function} {@var{s} =} urlread (@var{url})\n\ |
6043 | 365 @deftypefnx {Loadable Function} {[@var{s}, @var{success}] =} urlread (@var{url})\n\ |
6549 | 366 @deftypefnx {Loadable Function} {[@var{s}, @var{success}, @var{message}] =} urlread (@var{url})\n\ |
6547 | 367 @deftypefnx {Loadable Function} {[@dots{}] =} urlread (@var{url}, @var{method}, @var{param})\n\ |
6043 | 368 Download a remote file specified by its @var{URL} and return its content\n\ |
369 in string @var{s}. For example,\n\ | |
370 \n\ | |
371 @example\n\ | |
6588 | 372 s = urlread (\"ftp://ftp.octave.org/pub/octave/README\");\n\ |
6043 | 373 @end example\n\ |
374 \n\ | |
375 The variable @var{success} is 1 if the download was successful,\n\ | |
376 otherwise it is 0 in which case @var{message} contains an error\n\ | |
377 message. If no output argument is specified and if an error occurs,\n\ | |
6588 | 378 then the error is signaled through Octave's error handling mechanism.\n\ |
6043 | 379 \n\ |
380 This function uses libcurl. Curl supports, among others, the HTTP,\n\ | |
381 FTP and FILE protocols. Username and password may be specified in the\n\ | |
382 URL. For example,\n\ | |
383 \n\ | |
384 @example\n\ | |
7031 | 385 s = urlread (\"http://user:password@@example.com/file.txt\");\n\ |
6043 | 386 @end example\n\ |
387 \n\ | |
388 GET and POST requests can be specified by @var{method} and @var{param}.\n\ | |
6588 | 389 The parameter @var{method} is either @samp{get} or @samp{post}\n\ |
390 and @var{param} is a cell array of parameter and value pairs.\n\ | |
6650 | 391 For example,\n\ |
6043 | 392 \n\ |
393 @example\n\ | |
6588 | 394 s = urlread (\"http://www.google.com/search\", \"get\",\n\ |
395 @{\"query\", \"octave\"@});\n\ | |
6043 | 396 @end example\n\ |
397 @seealso{urlwrite}\n\ | |
398 @end deftypefn") | |
399 { | |
6588 | 400 // Octave's return value |
6043 | 401 octave_value_list retval; |
402 | |
403 #if defined (HAVE_CURL) | |
404 | |
405 int nargin = args.length (); | |
406 | |
407 // verify arguments | |
408 if (nargin != 1 && nargin != 3) | |
409 { | |
410 print_usage (); | |
411 return retval; | |
412 } | |
413 | |
414 std::string url = args(0).string_value(); | |
415 | |
416 if (error_state) | |
417 { | |
418 error ("urlread: url must be a character string"); | |
419 return retval; | |
420 } | |
421 | |
422 std::string method; | |
423 Cell param; // empty cell array | |
424 | |
425 if (nargin == 3) | |
426 { | |
427 method = args(1).string_value(); | |
428 | |
429 if (error_state) | |
430 { | |
431 error ("urlread: method can only be \"get\" or \"post\""); | |
432 return retval; | |
433 } | |
434 | |
435 if (method != "get" && method != "post") | |
436 { | |
437 error ("urlread: method can only be \"get\" or \"post\""); | |
438 return retval; | |
439 } | |
440 | |
441 param = args(2).cell_value(); | |
442 | |
443 if (error_state) | |
444 { | |
445 error ("urlread: parameters for get and post requests must be given as a cell"); | |
446 return retval; | |
447 } | |
448 | |
449 if (param.numel () % 2 == 1 ) | |
450 { | |
451 error ("urlread: number of elements in param must be even"); | |
452 return retval; | |
453 } | |
454 } | |
455 | |
6986 | 456 std::ostringstream buf; |
6043 | 457 |
6986 | 458 CURLcode res = urlget (url, method, param, buf); |
6043 | 459 |
460 if (nargout > 0) | |
461 { | |
6986 | 462 retval(0) = buf.str (); |
6043 | 463 retval(1) = res == CURLE_OK; |
6986 | 464 // Return empty string if no error occured. |
6043 | 465 retval(2) = std::string (res == CURLE_OK ? "" : curl_easy_strerror (res)); |
466 } | |
467 | |
6484 | 468 if (nargout < 2 && res != CURLE_OK) |
6043 | 469 error ("urlread: curl: %s", curl_easy_strerror (res)); |
470 | |
471 #else | |
6981 | 472 error ("urlread: not available in this version of Octave"); |
6043 | 473 #endif |
474 | |
475 return retval; | |
476 } |