Mercurial > octave-nkf
annotate src/DLD-FUNCTIONS/urlwrite.cc @ 9905:84a7c11ff928
Correctly compile even when libcurl is not present according to configure
Missing ifdefs surrounding code dependent on libcurl prevented compilation
when the library was not present.
author | Rik <rdrider0-list@yahoo.com> |
---|---|
date | Wed, 02 Dec 2009 21:42:11 -0800 |
parents | dd3fc8ba4796 |
children | 57b41617c9fd |
rev | line source |
---|---|
6043 | 1 // urlwrite and urlread, a curl front-end for octave |
2 /* | |
3 | |
8920 | 4 Copyright (C) 2006, 2007, 2008 Alexander Barth |
9880 | 5 Copyright (C) 2009 David Bateman |
6043 | 6 |
7 This file is part of Octave. | |
8 | |
9 Octave is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
7016 | 11 Free Software Foundation; either version 3 of the License, or (at your |
12 option) any later version. | |
6043 | 13 |
14 Octave is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
7016 | 20 along with Octave; see the file COPYING. If not, see |
21 <http://www.gnu.org/licenses/>. | |
6043 | 22 |
23 */ | |
24 | |
25 // Author: Alexander Barth <abarth@marine.usf.edu> | |
26 // Adapted-By: jwe | |
27 | |
28 #ifdef HAVE_CONFIG_H | |
29 #include <config.h> | |
30 #endif | |
31 | |
32 #include <string> | |
33 #include <fstream> | |
34 #include <iomanip> | |
9880 | 35 #include <iostream> |
6043 | 36 |
9880 | 37 #include "dir-ops.h" |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
38 #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
|
39 #include "file-stat.h" |
6043 | 40 #include "oct-env.h" |
9880 | 41 #include "glob-match.h" |
6043 | 42 |
43 #include "defun-dld.h" | |
44 #include "error.h" | |
45 #include "oct-obj.h" | |
46 #include "ov-cell.h" | |
47 #include "pager.h" | |
9880 | 48 #include "oct-map.h" |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
49 #include "unwind-prot.h" |
6043 | 50 |
9905
84a7c11ff928
Correctly compile even when libcurl is not present according to configure
Rik <rdrider0-list@yahoo.com>
parents:
9885
diff
changeset
|
51 #ifdef HAVE_CURL |
6043 | 52 |
53 #include <curl/curl.h> | |
9885 | 54 #include <curl/curlver.h> |
6043 | 55 #include <curl/types.h> |
56 #include <curl/easy.h> | |
57 | |
9880 | 58 static int |
6043 | 59 write_data (void *buffer, size_t size, size_t nmemb, void *streamp) |
60 { | |
61 std::ostream& stream = *(static_cast<std::ostream*> (streamp)); | |
62 stream.write (static_cast<const char*> (buffer), size*nmemb); | |
63 return (stream.fail () ? 0 : size * nmemb); | |
64 } | |
65 | |
9880 | 66 static int |
67 read_data (void *buffer, size_t size, size_t nmemb, void *streamp) | |
6043 | 68 { |
9880 | 69 std::istream& stream = *(static_cast<std::istream*> (streamp)); |
70 stream.read (static_cast<char*> (buffer), size*nmemb); | |
71 if (stream.eof ()) | |
72 return stream.gcount (); | |
73 else | |
74 return (stream.fail () ? 0 : size * nmemb); | |
6043 | 75 } |
76 | |
9880 | 77 static size_t |
78 throw_away (void *, size_t size, size_t nmemb, void *) | |
6992 | 79 { |
9880 | 80 return static_cast<size_t>(size * nmemb); |
6992 | 81 } |
82 | |
9880 | 83 class |
84 curl_handle | |
6043 | 85 { |
9880 | 86 private: |
87 class | |
88 curl_handle_rep | |
89 { | |
90 public: | |
91 curl_handle_rep (void) : count (1), valid (true), ascii (false) | |
92 { | |
93 curl = curl_easy_init (); | |
94 if (!curl) | |
95 error ("can not create curl handle"); | |
96 } | |
97 | |
98 ~curl_handle_rep (void) | |
99 { | |
100 if (curl) | |
101 curl_easy_cleanup (curl); | |
102 } | |
103 | |
104 bool is_valid (void) const | |
105 { | |
106 return valid; | |
107 } | |
108 | |
109 bool perform (bool curlerror) const | |
110 { | |
111 bool retval = false; | |
112 if (!error_state) | |
113 { | |
114 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
6043 | 115 |
9880 | 116 CURLcode res = curl_easy_perform (curl); |
117 if (res != CURLE_OK) | |
118 { | |
119 if (curlerror) | |
120 error ("%s", curl_easy_strerror (res)); | |
121 } | |
122 else | |
123 retval = true; | |
124 | |
125 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
126 } | |
127 return retval; | |
128 } | |
6043 | 129 |
9880 | 130 CURL* handle (void) const |
131 { | |
132 return curl; | |
133 } | |
134 | |
135 bool is_ascii (void) const | |
136 { | |
137 return ascii; | |
138 } | |
139 | |
140 bool is_binary (void) const | |
141 { | |
142 return !ascii; | |
143 } | |
144 | |
145 size_t count; | |
146 std::string host; | |
147 bool valid; | |
148 bool ascii; | |
149 | |
150 private: | |
151 CURL *curl; | |
6043 | 152 |
9880 | 153 // No copying! |
154 | |
155 curl_handle_rep (const curl_handle_rep& ov); | |
156 | |
157 curl_handle_rep& operator = (const curl_handle_rep&); | |
158 }; | |
159 | |
160 public: | |
6043 | 161 |
9880 | 162 // I'd love to rewrite this as a private method of the curl_handle |
163 // class, but you can't pass the va_list from the wrapper setopt to | |
164 // the curl_easy_setopt function. | |
165 #define setopt(option, parameter) \ | |
166 { \ | |
167 CURLcode res = curl_easy_setopt (rep->handle (), option, parameter); \ | |
168 if (res != CURLE_OK) \ | |
169 error ("%s", curl_easy_strerror (res)); \ | |
170 } | |
171 | |
172 curl_handle (void) : rep (new curl_handle_rep ()) | |
173 { | |
174 rep->valid = false; | |
175 } | |
176 | |
177 curl_handle (const std::string& _host, const std::string& user, | |
178 const std::string& passwd) : | |
179 rep (new curl_handle_rep ()) | |
180 { | |
181 rep->host = _host; | |
182 init (user, passwd, std::cin, octave_stdout); | |
183 | |
184 std::string url = "ftp://" + _host; | |
185 setopt (CURLOPT_URL, url.c_str()); | |
6043 | 186 |
9880 | 187 // Setup the link, with no transfer |
188 if (!error_state) | |
189 perform (); | |
190 } | |
191 | |
192 curl_handle (const std::string& url, const std::string& method, | |
193 const Cell& param, std::ostream& os, bool& retval) : | |
194 rep (new curl_handle_rep ()) | |
195 { | |
196 retval = false; | |
197 | |
198 init ("", "", std::cin, os); | |
199 | |
200 setopt (CURLOPT_NOBODY, 0); | |
201 | |
202 // Don't need to store the parameters here as we can't change | |
203 // the URL after the handle is created | |
204 std::string query_string = form_query_string (param); | |
6043 | 205 |
9880 | 206 if (method == "get") |
207 { | |
208 query_string = url + "?" + query_string; | |
209 setopt (CURLOPT_URL, query_string.c_str ()); | |
210 } | |
211 else if (method == "post") | |
212 { | |
213 setopt (CURLOPT_URL, url.c_str ()); | |
214 setopt (CURLOPT_POSTFIELDS, query_string.c_str ()); | |
215 } | |
216 else | |
217 setopt (CURLOPT_URL, url.c_str()); | |
218 | |
219 if (!error_state) | |
220 retval = perform (false); | |
221 } | |
222 | |
223 curl_handle (const curl_handle& h) : rep (h.rep) | |
6043 | 224 { |
9880 | 225 rep->count++; |
226 } | |
227 | |
228 ~curl_handle (void) | |
229 { | |
230 if (--rep->count == 0) | |
231 delete rep; | |
232 } | |
233 | |
234 curl_handle& operator = (const curl_handle& h) | |
235 { | |
236 if (this != &h) | |
237 { | |
238 if (--rep->count == 0) | |
239 delete rep; | |
240 | |
241 rep = h.rep; | |
242 rep->count++; | |
243 } | |
244 return *this; | |
245 } | |
246 | |
247 bool is_valid (void) const | |
248 { | |
249 return rep->is_valid (); | |
6043 | 250 } |
9880 | 251 |
252 std::string lasterror (void) const | |
253 { | |
254 CURLcode errno; | |
255 | |
256 curl_easy_getinfo (rep->handle(), CURLINFO_OS_ERRNO, &errno); | |
257 | |
258 return std::string (curl_easy_strerror (errno)); | |
259 } | |
260 | |
261 void set_ostream (std::ostream& os) const | |
262 { | |
263 setopt (CURLOPT_WRITEDATA, static_cast<void*> (&os)); | |
264 } | |
265 | |
266 void set_istream (std::istream& is) const | |
6043 | 267 { |
9880 | 268 setopt (CURLOPT_READDATA, static_cast<void*> (&is)); |
269 } | |
270 | |
271 void ascii (void) const | |
272 { | |
273 setopt (CURLOPT_TRANSFERTEXT, 1); | |
274 rep->ascii = true; | |
275 } | |
276 | |
277 void binary (void) const | |
278 { | |
279 setopt (CURLOPT_TRANSFERTEXT, 0); | |
280 rep->ascii = false; | |
281 } | |
282 | |
283 bool is_ascii (void) const | |
284 { | |
285 return rep->is_ascii (); | |
286 } | |
287 | |
288 bool is_binary (void) const | |
289 { | |
290 return rep->is_binary (); | |
6043 | 291 } |
9880 | 292 |
293 void cwd (const std::string& path) const | |
294 { | |
295 struct curl_slist *slist = 0; | |
296 std::string cmd = "cwd " + path; | |
297 slist = curl_slist_append (slist, cmd.c_str()); | |
298 setopt (CURLOPT_POSTQUOTE, slist); | |
299 if (! error_state) | |
300 perform (); | |
301 setopt (CURLOPT_POSTQUOTE, 0); | |
302 curl_slist_free_all (slist); | |
303 } | |
6043 | 304 |
9880 | 305 void del (const std::string& file) const |
306 { | |
307 struct curl_slist *slist = 0; | |
308 std::string cmd = "dele " + file; | |
309 slist = curl_slist_append (slist, cmd.c_str()); | |
310 setopt (CURLOPT_POSTQUOTE, slist); | |
311 if (! error_state) | |
312 perform (); | |
313 setopt (CURLOPT_POSTQUOTE, 0); | |
314 curl_slist_free_all (slist); | |
315 } | |
316 | |
317 void rmdir (const std::string& path) const | |
318 { | |
319 struct curl_slist *slist = 0; | |
320 std::string cmd = "rmd " + path; | |
321 slist = curl_slist_append (slist, cmd.c_str()); | |
322 setopt (CURLOPT_POSTQUOTE, slist); | |
323 if (! error_state) | |
324 perform (); | |
325 setopt (CURLOPT_POSTQUOTE, 0); | |
326 curl_slist_free_all (slist); | |
327 } | |
6043 | 328 |
9880 | 329 bool mkdir (const std::string& path, bool curlerror = true) const |
330 { | |
331 bool retval = false; | |
332 struct curl_slist *slist = 0; | |
333 std::string cmd = "mkd " + path; | |
334 slist = curl_slist_append (slist, cmd.c_str()); | |
335 setopt (CURLOPT_POSTQUOTE, slist); | |
336 if (! error_state) | |
337 retval = perform (curlerror); | |
338 setopt (CURLOPT_POSTQUOTE, 0); | |
339 curl_slist_free_all (slist); | |
340 return retval; | |
341 } | |
6043 | 342 |
9880 | 343 void rename (const std::string& oldname, const std::string& newname) const |
344 { | |
345 struct curl_slist *slist = 0; | |
346 std::string cmd = "rnfr " + oldname; | |
347 slist = curl_slist_append (slist, cmd.c_str()); | |
348 cmd = "rnto " + newname; | |
349 slist = curl_slist_append (slist, cmd.c_str()); | |
350 setopt (CURLOPT_POSTQUOTE, slist); | |
351 if (! error_state) | |
352 perform (); | |
353 setopt (CURLOPT_POSTQUOTE, 0); | |
354 curl_slist_free_all (slist); | |
355 } | |
356 | |
357 void put (const std::string& file, std::istream& is) const | |
358 { | |
359 std::string url = "ftp://" + rep->host + "/" + file; | |
360 setopt (CURLOPT_URL, url.c_str()); | |
361 setopt (CURLOPT_UPLOAD, 1); | |
362 setopt (CURLOPT_NOBODY, 0); | |
363 set_istream (is); | |
364 if (! error_state) | |
365 perform (); | |
366 set_istream (std::cin); | |
367 setopt (CURLOPT_NOBODY, 1); | |
368 setopt (CURLOPT_UPLOAD, 0); | |
369 url = "ftp://" + rep->host; | |
370 setopt (CURLOPT_URL, url.c_str()); | |
371 } | |
7013 | 372 |
9880 | 373 void get (const std::string& file, std::ostream& os) const |
374 { | |
375 std::string url = "ftp://" + rep->host + "/" + file; | |
376 setopt (CURLOPT_URL, url.c_str()); | |
377 setopt (CURLOPT_NOBODY, 0); | |
378 set_ostream (os); | |
379 if (! error_state) | |
380 perform (); | |
381 set_ostream (octave_stdout); | |
382 setopt (CURLOPT_NOBODY, 1); | |
383 url = "ftp://" + rep->host; | |
384 setopt (CURLOPT_URL, url.c_str()); | |
385 } | |
386 | |
387 void dir (void) const | |
388 { | |
389 std::string url = "ftp://" + rep->host + "/"; | |
390 setopt (CURLOPT_URL, url.c_str()); | |
391 setopt (CURLOPT_NOBODY, 0); | |
392 if (! error_state) | |
393 perform (); | |
394 setopt (CURLOPT_NOBODY, 1); | |
395 url = "ftp://" + rep->host; | |
396 setopt (CURLOPT_URL, url.c_str()); | |
397 } | |
6390 | 398 |
9880 | 399 string_vector list (void) const |
400 { | |
401 std::ostringstream buf; | |
402 std::string url = "ftp://" + rep->host + "/"; | |
403 setopt (CURLOPT_WRITEDATA, static_cast<void*> (&buf)); | |
404 setopt (CURLOPT_URL, url.c_str()); | |
405 setopt (CURLOPT_DIRLISTONLY, 1); | |
406 setopt (CURLOPT_NOBODY, 0); | |
407 if (! error_state) | |
408 perform (); | |
409 setopt (CURLOPT_NOBODY, 1); | |
410 url = "ftp://" + rep->host; | |
411 setopt (CURLOPT_WRITEDATA, static_cast<void*> (&octave_stdout)); | |
412 setopt (CURLOPT_DIRLISTONLY, 0); | |
413 setopt (CURLOPT_URL, url.c_str()); | |
414 | |
415 // Count number of directory entries | |
416 std::string str = buf.str (); | |
417 octave_idx_type n = 0; | |
418 size_t pos = 0; | |
419 while (true) | |
420 { | |
421 pos = str.find_first_of('\n', pos); | |
422 if (pos == std::string::npos) | |
423 break; | |
424 pos++; | |
425 n++; | |
426 } | |
427 string_vector retval (n); | |
428 pos = 0; | |
429 for (octave_idx_type i = 0; i < n; i++) | |
430 { | |
431 size_t newpos = str.find_first_of('\n', pos); | |
432 if (newpos == std::string::npos) | |
433 break; | |
434 | |
435 retval(i) = str.substr(pos, newpos - pos); | |
436 pos = newpos + 1; | |
437 } | |
438 return retval; | |
439 } | |
440 | |
441 void get_fileinfo (const std::string& filename, double& filesize, | |
442 time_t& filetime, bool& fileisdir) const | |
443 { | |
444 std::string path = pwd(); | |
6043 | 445 |
9880 | 446 std::string url = "ftp://" + rep->host + "/" + path + "/" + filename; |
447 setopt (CURLOPT_URL, url.c_str()); | |
448 setopt (CURLOPT_FILETIME, 1); | |
449 setopt (CURLOPT_HEADERFUNCTION, throw_away); | |
450 setopt (CURLOPT_WRITEFUNCTION, throw_away); | |
6043 | 451 |
9880 | 452 // FIXME |
453 // The MDTM command fails for a directory on the servers I tested | |
454 // so this is a means of testing for directories. It also means | |
455 // I can't get the date of directories! | |
456 if (! error_state) | |
457 { | |
458 if (! perform (false)) | |
459 { | |
460 fileisdir = true; | |
461 filetime = -1; | |
462 filesize = 0; | |
463 } | |
464 else | |
465 { | |
466 fileisdir = false; | |
467 time_t ft; | |
468 curl_easy_getinfo(rep->handle (), CURLINFO_FILETIME, &ft); | |
469 filetime = ft; | |
470 double fs; | |
471 curl_easy_getinfo(rep->handle (), | |
472 CURLINFO_CONTENT_LENGTH_DOWNLOAD, &fs); | |
473 filesize = fs; | |
474 } | |
475 } | |
6992 | 476 |
9880 | 477 setopt (CURLOPT_WRITEFUNCTION, write_data); |
478 setopt (CURLOPT_HEADERFUNCTION, 0); | |
479 setopt (CURLOPT_FILETIME, 0); | |
480 url = "ftp://" + rep->host; | |
481 setopt (CURLOPT_URL, url.c_str()); | |
482 | |
483 // The MDTM command seems to reset the path to the root with the | |
484 // servers I tested with, so cd again into the correct path. Make | |
485 // the path absolute so that this will work even with servers that | |
486 // don't end up in the root after an MDTM command. | |
487 cwd ("/" + path); | |
488 } | |
489 | |
490 std::string pwd (void) const | |
491 { | |
492 struct curl_slist *slist = 0; | |
493 std::string retval; | |
494 std::ostringstream buf; | |
6992 | 495 |
9880 | 496 slist = curl_slist_append (slist, "pwd"); |
497 setopt (CURLOPT_POSTQUOTE, slist); | |
498 setopt (CURLOPT_HEADERFUNCTION, write_data); | |
499 setopt (CURLOPT_WRITEHEADER, static_cast<void *>(&buf)); | |
500 | |
501 if (! error_state) | |
502 { | |
503 perform (); | |
504 retval = buf.str(); | |
505 | |
506 // Can I assume that the path is alway in "" on the last line | |
507 size_t pos2 = retval.rfind ('"'); | |
508 size_t pos1 = retval.rfind ('"', pos2 - 1); | |
509 retval = retval.substr(pos1 + 1, pos2 - pos1 - 1); | |
510 } | |
511 setopt (CURLOPT_HEADERFUNCTION, 0); | |
512 setopt (CURLOPT_WRITEHEADER, 0); | |
513 setopt (CURLOPT_POSTQUOTE, 0); | |
514 curl_slist_free_all (slist); | |
515 | |
516 return retval; | |
517 } | |
6992 | 518 |
9880 | 519 bool perform (bool curlerror = true) const |
520 { | |
521 return rep->perform (curlerror); | |
522 } | |
523 | |
524 private: | |
525 curl_handle_rep *rep; | |
526 | |
527 std::string form_query_string (const Cell& param) | |
528 { | |
529 std::ostringstream query; | |
530 | |
531 for (int i = 0; i < param.numel (); i += 2) | |
532 { | |
533 std::string name = param(i).string_value (); | |
534 std::string text = param(i+1).string_value (); | |
535 | |
536 // Encode strings. | |
537 char *enc_name = curl_easy_escape (rep->handle(), name.c_str (), | |
538 name.length ()); | |
539 char *enc_text = curl_easy_escape (rep->handle(), text.c_str (), | |
540 text.length ()); | |
541 | |
542 query << enc_name << "=" << enc_text; | |
543 | |
544 curl_free (enc_name); | |
545 curl_free (enc_text); | |
546 | |
547 if (i < param.numel()-1) | |
548 query << "&"; | |
549 } | |
550 | |
551 query.flush (); | |
6043 | 552 |
9880 | 553 return query.str (); |
554 } | |
555 | |
556 void init (const std::string& user, const std::string& passwd, | |
557 std::istream& is, std::ostream& os) | |
558 { | |
559 // No data transfer by default | |
560 setopt (CURLOPT_NOBODY, 1); | |
561 | |
562 // Set the username and password | |
9885 | 563 #if (LIBCURL_VERSION_NUM >= 0x071300) |
564 // This is possible since cURL 7.19. | |
9880 | 565 if (user.length () != 0) |
566 setopt (CURLOPT_USERNAME, user.c_str()); | |
567 if (passwd.length () != 0) | |
568 setopt (CURLOPT_PASSWORD, passwd.c_str()); | |
9885 | 569 #else |
570 // Probably needs to be static to remain valid long enough. | |
571 static std::string userpwd; | |
572 if (user.length () != 0) | |
573 { | |
574 userpwd = user; | |
575 if (passwd.length () != 0) | |
576 userpwd += ':' + passwd; | |
577 setopt (CURLOPT_USERPWD, userpwd.c_str ()); | |
578 } | |
579 #endif | |
9880 | 580 |
581 // Define our callback to get called when there's data to be written. | |
582 setopt (CURLOPT_WRITEFUNCTION, write_data); | |
6992 | 583 |
9880 | 584 // Set a pointer to our struct to pass to the callback. |
585 setopt (CURLOPT_WRITEDATA, static_cast<void*> (&os)); | |
586 | |
587 // Define our callback to get called when there's data to be read | |
588 setopt (CURLOPT_READFUNCTION, read_data); | |
589 | |
590 // Set a pointer to our struct to pass to the callback. | |
591 setopt (CURLOPT_READDATA, static_cast<void*> (&is)); | |
592 | |
593 // Follow redirects. | |
594 setopt (CURLOPT_FOLLOWLOCATION, true); | |
595 | |
596 // Don't use EPSV since connecting to sites that don't support it | |
597 // will hang for some time (3 minutes?) before moving on to try PASV | |
598 // instead. | |
599 setopt (CURLOPT_FTP_USE_EPSV, false); | |
600 | |
601 setopt (CURLOPT_NOPROGRESS, true); | |
602 setopt (CURLOPT_FAILONERROR, true); | |
6992 | 603 |
9880 | 604 setopt (CURLOPT_POSTQUOTE, 0); |
605 setopt (CURLOPT_QUOTE, 0); | |
606 } | |
607 | |
608 #undef setopt | |
609 }; | |
610 | |
611 class | |
612 curl_handles | |
613 { | |
614 public: | |
615 | |
616 typedef std::map<std::string, curl_handle>::iterator iterator; | |
617 typedef std::map<std::string, curl_handle>::const_iterator const_iterator; | |
6043 | 618 |
9880 | 619 curl_handles (void) : map () |
620 { | |
621 curl_global_init(CURL_GLOBAL_DEFAULT); | |
622 } | |
623 | |
624 ~curl_handles (void) | |
625 { | |
626 // Remove the elements of the map explicitly as they should | |
627 // be deleted before the call to curl_global_cleanup | |
628 for (iterator pa = begin (); pa != end (); pa++) | |
629 map.erase (pa); | |
6992 | 630 |
9880 | 631 curl_global_cleanup (); |
632 } | |
633 | |
634 iterator begin (void) { return iterator (map.begin ()); } | |
635 const_iterator begin (void) const { return const_iterator (map.begin ()); } | |
636 | |
637 iterator end (void) { return iterator (map.end ()); } | |
638 const_iterator end (void) const { return const_iterator (map.end ()); } | |
6992 | 639 |
9880 | 640 iterator seek (const std::string& k) { return map.find (k); } |
641 const_iterator seek (const std::string& k) const { return map.find (k); } | |
642 | |
643 std::string key (const_iterator p) const { return p->first; } | |
644 | |
645 curl_handle& contents (const std::string& k) | |
646 { | |
647 return map[k]; | |
648 } | |
649 | |
650 curl_handle contents (const std::string& k) const | |
651 { | |
652 const_iterator p = seek (k); | |
653 return p != end () ? p->second : curl_handle (); | |
654 } | |
655 | |
656 curl_handle& contents (iterator p) | |
657 { return p->second; } | |
6992 | 658 |
9880 | 659 curl_handle contents (const_iterator p) const |
660 { return p->second; } | |
661 | |
662 void del (const std::string& k) | |
663 { | |
664 iterator p = map.find (k); | |
665 | |
666 if (p != map.end ()) | |
667 map.erase (p); | |
668 } | |
6043 | 669 |
9880 | 670 private: |
671 std::map<std::string, curl_handle> map; | |
672 }; | |
673 | |
674 static curl_handles handles; | |
675 | |
676 static void | |
677 cleanup_urlwrite (std::string filename) | |
678 { | |
679 file_ops::unlink (filename); | |
6043 | 680 } |
681 | |
9880 | 682 static void |
683 reset_path (const curl_handle curl) | |
684 { | |
685 curl.cwd (".."); | |
686 } | |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
687 |
9880 | 688 void delete_file (std::string file) |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
689 { |
9880 | 690 file_ops::unlink (file); |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
691 } |
9880 | 692 #endif |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
693 |
6043 | 694 DEFUN_DLD (urlwrite, args, nargout, |
695 "-*- texinfo -*-\n\ | |
9880 | 696 @deftypefn {Loadable Function} {} urlwrite (@var{url}, @var{localfile})\n\ |
6043 | 697 @deftypefnx {Loadable Function} {@var{f} =} urlwrite (@var{url}, @var{localfile})\n\ |
698 @deftypefnx {Loadable Function} {[@var{f}, @var{success}] =} urlwrite (@var{url}, @var{localfile})\n\ | |
699 @deftypefnx {Loadable Function} {[@var{f}, @var{success}, @var{message}] =} urlwrite (@var{url}, @var{localfile})\n\ | |
9880 | 700 Download a remote file specified by its @var{url} and save it as\n\ |
6043 | 701 @var{localfile}. For example,\n\ |
702 \n\ | |
703 @example\n\ | |
9064
7c02ec148a3c
Check grammar on all .cc files
Rik <rdrider0-list@yahoo.com>
parents:
8920
diff
changeset
|
704 @group\n\ |
7031 | 705 urlwrite (\"ftp://ftp.octave.org/pub/octave/README\", \n\ |
706 \"README.txt\");\n\ | |
9064
7c02ec148a3c
Check grammar on all .cc files
Rik <rdrider0-list@yahoo.com>
parents:
8920
diff
changeset
|
707 @end group\n\ |
6043 | 708 @end example\n\ |
709 \n\ | |
710 The full path of the downloaded file is returned in @var{f}. The\n\ | |
711 variable @var{success} is 1 if the download was successful,\n\ | |
712 otherwise it is 0 in which case @var{message} contains an error\n\ | |
713 message. If no output argument is specified and if an error occurs,\n\ | |
6588 | 714 then the error is signaled through Octave's error handling mechanism.\n\ |
6043 | 715 \n\ |
716 This function uses libcurl. Curl supports, among others, the HTTP,\n\ | |
717 FTP and FILE protocols. Username and password may be specified in\n\ | |
718 the URL, for example:\n\ | |
719 \n\ | |
720 @example\n\ | |
9064
7c02ec148a3c
Check grammar on all .cc files
Rik <rdrider0-list@yahoo.com>
parents:
8920
diff
changeset
|
721 @group\n\ |
6588 | 722 urlwrite (\"http://username:password@@example.com/file.txt\",\n\ |
723 \"file.txt\");\n\ | |
9064
7c02ec148a3c
Check grammar on all .cc files
Rik <rdrider0-list@yahoo.com>
parents:
8920
diff
changeset
|
724 @end group\n\ |
6043 | 725 @end example\n\ |
726 \n\ | |
727 GET and POST requests can be specified by @var{method} and @var{param}.\n\ | |
6589 | 728 The parameter @var{method} is either @samp{get} or @samp{post}\n\ |
6588 | 729 and @var{param} is a cell array of parameter and value pairs.\n\ |
730 For example:\n\ | |
6043 | 731 \n\ |
732 @example\n\ | |
9064
7c02ec148a3c
Check grammar on all .cc files
Rik <rdrider0-list@yahoo.com>
parents:
8920
diff
changeset
|
733 @group\n\ |
6588 | 734 urlwrite (\"http://www.google.com/search\", \"search.html\",\n\ |
735 \"get\", @{\"query\", \"octave\"@});\n\ | |
9064
7c02ec148a3c
Check grammar on all .cc files
Rik <rdrider0-list@yahoo.com>
parents:
8920
diff
changeset
|
736 @end group\n\ |
6043 | 737 @end example\n\ |
738 @seealso{urlread}\n\ | |
739 @end deftypefn") | |
740 { | |
741 octave_value_list retval; | |
742 | |
9905
84a7c11ff928
Correctly compile even when libcurl is not present according to configure
Rik <rdrider0-list@yahoo.com>
parents:
9885
diff
changeset
|
743 #ifdef HAVE_CURL |
6043 | 744 |
745 int nargin = args.length (); | |
746 | |
747 // verify arguments | |
748 if (nargin != 2 && nargin != 4) | |
749 { | |
750 print_usage (); | |
751 return retval; | |
752 } | |
753 | |
754 std::string url = args(0).string_value(); | |
755 | |
756 if (error_state) | |
757 { | |
758 error ("urlwrite: url must be a character string"); | |
759 return retval; | |
760 } | |
761 | |
762 // name to store the file if download is succesful | |
763 std::string filename = args(1).string_value(); | |
764 | |
765 if (error_state) | |
766 { | |
767 error ("urlwrite: localfile must be a character string"); | |
768 return retval; | |
769 } | |
770 | |
771 std::string method; | |
772 Cell param; // empty cell array | |
773 | |
774 if (nargin == 4) | |
775 { | |
776 method = args(2).string_value(); | |
777 | |
778 if (error_state) | |
779 { | |
780 error ("urlwrite: method can only be \"get\" or \"post\""); | |
781 return retval; | |
782 } | |
783 | |
784 if (method != "get" && method != "post") | |
785 { | |
786 error ("urlwrite: method can only be \"get\" or \"post\""); | |
787 return retval; | |
788 } | |
789 | |
790 param = args(3).cell_value(); | |
791 | |
792 if (error_state) | |
793 { | |
794 error ("urlwrite: parameters for get and post requests must be given as a cell"); | |
795 return retval; | |
796 } | |
797 | |
798 | |
799 if (param.numel () % 2 == 1 ) | |
800 { | |
801 error ("urlwrite: number of elements in param must be even"); | |
802 return retval; | |
803 } | |
804 } | |
805 | |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
806 // 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
|
807 // 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
|
808 // 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
|
809 |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
810 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
|
811 |
6986 | 812 std::ofstream ofile (filename.c_str(), std::ios::out | std::ios::binary); |
6043 | 813 |
6986 | 814 if (! ofile.is_open ()) |
6043 | 815 { |
816 error ("urlwrite: unable to open file"); | |
817 return retval; | |
818 } | |
819 | |
9880 | 820 unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
821 |
9880 | 822 unwind_protect::add_fcn (cleanup_urlwrite, filename); |
823 | |
824 bool res; | |
825 curl_handle curl = curl_handle (url, method, param, ofile, res); | |
6043 | 826 |
6986 | 827 ofile.close (); |
6043 | 828 |
9880 | 829 if (!error_state) |
830 unwind_protect::discard_frame (uwp_frame); | |
831 else | |
832 unwind_protect::run_frame (uwp_frame); | |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
833 |
6043 | 834 if (nargout > 0) |
835 { | |
9880 | 836 if (res) |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
837 { |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
838 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
|
839 retval(1) = true; |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
840 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
|
841 } |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
842 else |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
843 { |
9880 | 844 retval(2) = curl.lasterror (); |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
845 retval(1) = false; |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
846 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
|
847 } |
6043 | 848 } |
849 | |
9880 | 850 if (nargout < 2 && res) |
851 error ("urlwrite: curl: %s", curl.lasterror ().c_str ()); | |
6043 | 852 |
853 #else | |
6981 | 854 error ("urlwrite: not available in this version of Octave"); |
6043 | 855 #endif |
856 | |
857 return retval; | |
858 } | |
859 | |
860 DEFUN_DLD (urlread, args, nargout, | |
861 "-*- texinfo -*-\n\ | |
6549 | 862 @deftypefn {Loadable Function} {@var{s} =} urlread (@var{url})\n\ |
6043 | 863 @deftypefnx {Loadable Function} {[@var{s}, @var{success}] =} urlread (@var{url})\n\ |
6549 | 864 @deftypefnx {Loadable Function} {[@var{s}, @var{success}, @var{message}] =} urlread (@var{url})\n\ |
6547 | 865 @deftypefnx {Loadable Function} {[@dots{}] =} urlread (@var{url}, @var{method}, @var{param})\n\ |
9880 | 866 Download a remote file specified by its @var{url} and return its content\n\ |
6043 | 867 in string @var{s}. For example,\n\ |
868 \n\ | |
869 @example\n\ | |
6588 | 870 s = urlread (\"ftp://ftp.octave.org/pub/octave/README\");\n\ |
6043 | 871 @end example\n\ |
872 \n\ | |
873 The variable @var{success} is 1 if the download was successful,\n\ | |
874 otherwise it is 0 in which case @var{message} contains an error\n\ | |
875 message. If no output argument is specified and if an error occurs,\n\ | |
6588 | 876 then the error is signaled through Octave's error handling mechanism.\n\ |
6043 | 877 \n\ |
878 This function uses libcurl. Curl supports, among others, the HTTP,\n\ | |
879 FTP and FILE protocols. Username and password may be specified in the\n\ | |
880 URL. For example,\n\ | |
881 \n\ | |
882 @example\n\ | |
7031 | 883 s = urlread (\"http://user:password@@example.com/file.txt\");\n\ |
6043 | 884 @end example\n\ |
885 \n\ | |
886 GET and POST requests can be specified by @var{method} and @var{param}.\n\ | |
6588 | 887 The parameter @var{method} is either @samp{get} or @samp{post}\n\ |
888 and @var{param} is a cell array of parameter and value pairs.\n\ | |
6650 | 889 For example,\n\ |
6043 | 890 \n\ |
891 @example\n\ | |
9064
7c02ec148a3c
Check grammar on all .cc files
Rik <rdrider0-list@yahoo.com>
parents:
8920
diff
changeset
|
892 @group\n\ |
6588 | 893 s = urlread (\"http://www.google.com/search\", \"get\",\n\ |
894 @{\"query\", \"octave\"@});\n\ | |
9064
7c02ec148a3c
Check grammar on all .cc files
Rik <rdrider0-list@yahoo.com>
parents:
8920
diff
changeset
|
895 @end group\n\ |
6043 | 896 @end example\n\ |
897 @seealso{urlwrite}\n\ | |
898 @end deftypefn") | |
899 { | |
6588 | 900 // Octave's return value |
6043 | 901 octave_value_list retval; |
902 | |
9905
84a7c11ff928
Correctly compile even when libcurl is not present according to configure
Rik <rdrider0-list@yahoo.com>
parents:
9885
diff
changeset
|
903 #ifdef HAVE_CURL |
6043 | 904 |
905 int nargin = args.length (); | |
906 | |
907 // verify arguments | |
908 if (nargin != 1 && nargin != 3) | |
909 { | |
910 print_usage (); | |
911 return retval; | |
912 } | |
913 | |
914 std::string url = args(0).string_value(); | |
915 | |
916 if (error_state) | |
917 { | |
918 error ("urlread: url must be a character string"); | |
919 return retval; | |
920 } | |
921 | |
922 std::string method; | |
923 Cell param; // empty cell array | |
924 | |
925 if (nargin == 3) | |
926 { | |
927 method = args(1).string_value(); | |
928 | |
929 if (error_state) | |
930 { | |
931 error ("urlread: method can only be \"get\" or \"post\""); | |
932 return retval; | |
933 } | |
934 | |
935 if (method != "get" && method != "post") | |
936 { | |
937 error ("urlread: method can only be \"get\" or \"post\""); | |
938 return retval; | |
939 } | |
940 | |
941 param = args(2).cell_value(); | |
942 | |
943 if (error_state) | |
944 { | |
945 error ("urlread: parameters for get and post requests must be given as a cell"); | |
946 return retval; | |
947 } | |
948 | |
949 if (param.numel () % 2 == 1 ) | |
950 { | |
951 error ("urlread: number of elements in param must be even"); | |
952 return retval; | |
953 } | |
954 } | |
955 | |
6986 | 956 std::ostringstream buf; |
6043 | 957 |
9880 | 958 bool res; |
959 curl_handle curl = curl_handle (url, method, param, buf, res); | |
6043 | 960 |
961 if (nargout > 0) | |
962 { | |
6986 | 963 retval(0) = buf.str (); |
9880 | 964 retval(1) = res; |
6986 | 965 // Return empty string if no error occured. |
9880 | 966 retval(2) = res ? "" : curl.lasterror (); |
6043 | 967 } |
968 | |
9880 | 969 if (nargout < 2 && !res) |
970 error ("urlread: curl: %s", curl.lasterror().c_str()); | |
6043 | 971 |
972 #else | |
6981 | 973 error ("urlread: not available in this version of Octave"); |
6043 | 974 #endif |
975 | |
976 return retval; | |
977 } | |
9880 | 978 |
979 DEFUN_DLD (__ftp__, args, , | |
980 "-*- texinfo -*-\n\ | |
981 @deftypefn {Loadable Function} {} __ftp__ (@var{handle}, @var{host})\n\ | |
982 @deftypefnx {Loadable Function} {} __ftp__ (@var{handle}, @var{host}, @var{username}, @var{password})\n\ | |
983 Undocumented internal function\n\ | |
984 @end deftypefn") | |
985 { | |
986 #ifdef HAVE_CURL | |
987 int nargin = args.length (); | |
988 std::string handle; | |
989 std::string host; | |
990 std::string user = "anonymous"; | |
991 std::string passwd = ""; | |
992 | |
993 if (nargin < 2 || nargin > 4) | |
994 error ("incorrect number of arguments"); | |
995 else | |
996 { | |
997 handle = args(0).string_value (); | |
998 host = args(1).string_value (); | |
999 | |
1000 if (nargin > 1) | |
1001 user = args(2).string_value (); | |
1002 | |
1003 if (nargin > 2) | |
1004 passwd = args(3).string_value (); | |
1005 | |
1006 if (!error_state) | |
1007 { | |
1008 handles.contents (handle) = curl_handle (host, user, passwd); | |
1009 | |
1010 if (error_state) | |
1011 handles.del (handle); | |
1012 } | |
1013 } | |
1014 #else | |
1015 error ("__ftp__: not available in this version of Octave"); | |
1016 #endif | |
1017 | |
1018 return octave_value (); | |
1019 } | |
1020 | |
1021 DEFUN_DLD (__ftp_pwd__, args, , | |
1022 "-*- texinfo -*-\n\ | |
1023 @deftypefn {Loadable Function} {} __ftp_pwd__ (@var{handle})\n\ | |
1024 Undocumented internal function\n\ | |
1025 @end deftypefn") | |
1026 { | |
1027 octave_value retval; | |
1028 #ifdef HAVE_CURL | |
1029 int nargin = args.length (); | |
1030 | |
1031 if (nargin != 1) | |
1032 error ("incorrect number of arguments"); | |
1033 else | |
1034 { | |
1035 std::string handle = args(0).string_value (); | |
1036 | |
1037 if (!error_state) | |
1038 { | |
1039 const curl_handle curl = handles.contents (handle); | |
1040 | |
1041 if (curl.is_valid ()) | |
1042 retval = curl.pwd (); | |
1043 else | |
1044 error ("__ftp_pwd__: invalid ftp handle"); | |
1045 } | |
1046 } | |
1047 #else | |
1048 error ("__ftp_pwd__: not available in this version of Octave"); | |
1049 #endif | |
1050 | |
1051 return retval; | |
1052 } | |
1053 | |
1054 DEFUN_DLD (__ftp_cwd__, args, , | |
1055 "-*- texinfo -*-\n\ | |
1056 @deftypefn {Loadable Function} {} __ftp_cwd__ (@var{handle}, @var{path})\n\ | |
1057 Undocumented internal function\n\ | |
1058 @end deftypefn") | |
1059 { | |
1060 #ifdef HAVE_CURL | |
1061 int nargin = args.length (); | |
1062 | |
1063 if (nargin != 1 && nargin != 2) | |
1064 error ("incorrect number of arguments"); | |
1065 else | |
1066 { | |
1067 std::string handle = args(0).string_value (); | |
1068 std::string path = ""; | |
1069 | |
1070 if (nargin > 1) | |
1071 path = args(1).string_value (); | |
1072 | |
1073 if (!error_state) | |
1074 { | |
1075 const curl_handle curl = handles.contents (handle); | |
1076 | |
1077 if (curl.is_valid ()) | |
1078 curl.cwd (path); | |
1079 else | |
1080 error ("__ftp_cwd__: invalid ftp handle"); | |
1081 } | |
1082 } | |
1083 #else | |
1084 error ("__ftp_cwd__: not available in this version of Octave"); | |
1085 #endif | |
1086 | |
1087 return octave_value (); | |
1088 } | |
1089 | |
1090 DEFUN_DLD (__ftp_dir__, args, nargout, | |
1091 "-*- texinfo -*-\n\ | |
1092 @deftypefn {Loadable Function} {} __ftp_dir__ (@var{handle})\n\ | |
1093 Undocumented internal function\n\ | |
1094 @end deftypefn") | |
1095 { | |
1096 octave_value retval; | |
1097 #ifdef HAVE_CURL | |
1098 int nargin = args.length (); | |
1099 | |
1100 if (nargin != 1) | |
1101 error ("incorrect number of arguments"); | |
1102 else | |
1103 { | |
1104 std::string handle = args(0).string_value (); | |
1105 | |
1106 if (!error_state) | |
1107 { | |
1108 const curl_handle curl = handles.contents (handle); | |
1109 | |
1110 if (curl.is_valid ()) | |
1111 { | |
1112 if (nargout == 0) | |
1113 curl.dir (); | |
1114 else | |
1115 { | |
1116 string_vector sv = curl.list (); | |
1117 octave_idx_type n = sv.length (); | |
1118 if (n == 0) | |
1119 { | |
1120 string_vector flds (5); | |
1121 flds(0) = "name"; | |
1122 flds(1) = "date"; | |
1123 flds(2) = "bytes"; | |
1124 flds(3) = "isdir"; | |
1125 flds(4) = "datenum"; | |
1126 retval = Octave_map (flds); | |
1127 } | |
1128 else | |
1129 { | |
1130 Octave_map st; | |
1131 Cell filectime (dim_vector (n, 1)); | |
1132 Cell filesize (dim_vector (n, 1)); | |
1133 Cell fileisdir (dim_vector (n, 1)); | |
1134 Cell filedatenum (dim_vector (n, 1)); | |
1135 | |
1136 st.assign ("name", Cell (sv)); | |
1137 | |
1138 for (octave_idx_type i = 0; i < n; i++) | |
1139 { | |
1140 time_t ftime; | |
1141 bool fisdir; | |
1142 double fsize; | |
1143 | |
1144 curl.get_fileinfo (sv(i), fsize, ftime, fisdir); | |
1145 | |
1146 fileisdir (i) = fisdir; | |
1147 filectime (i) = ctime (&ftime); | |
1148 filesize (i) = fsize; | |
1149 filedatenum (i) = double (ftime); | |
1150 } | |
1151 st.assign ("date", filectime); | |
1152 st.assign ("bytes", filesize); | |
1153 st.assign ("isdir", fileisdir); | |
1154 st.assign ("datenum", filedatenum); | |
1155 retval = st; | |
1156 } | |
1157 } | |
1158 } | |
1159 else | |
1160 error ("__ftp_dir__: invalid ftp handle"); | |
1161 } | |
1162 } | |
1163 #else | |
1164 error ("__ftp_dir__: not available in this version of Octave"); | |
1165 #endif | |
1166 | |
1167 return retval; | |
1168 } | |
1169 | |
1170 DEFUN_DLD (__ftp_ascii__, args, , | |
1171 "-*- texinfo -*-\n\ | |
1172 @deftypefn {Loadable Function} {} __ftp_ascii__ (@var{handle})\n\ | |
1173 Undocumented internal function\n\ | |
1174 @end deftypefn") | |
1175 { | |
1176 #ifdef HAVE_CURL | |
1177 int nargin = args.length (); | |
1178 | |
1179 if (nargin != 1) | |
1180 error ("incorrect number of arguments"); | |
1181 else | |
1182 { | |
1183 std::string handle = args(0).string_value (); | |
1184 | |
1185 if (!error_state) | |
1186 { | |
1187 const curl_handle curl = handles.contents (handle); | |
1188 | |
1189 if (curl.is_valid ()) | |
1190 curl.ascii (); | |
1191 else | |
1192 error ("__ftp_ascii__: invalid ftp handle"); | |
1193 } | |
1194 } | |
1195 #else | |
1196 error ("__ftp_ascii__: not available in this version of Octave"); | |
1197 #endif | |
1198 | |
1199 return octave_value (); | |
1200 } | |
1201 | |
1202 DEFUN_DLD (__ftp_binary__, args, , | |
1203 "-*- texinfo -*-\n\ | |
1204 @deftypefn {Loadable Function} {} __ftp_binary__ (@var{handle})\n\ | |
1205 Undocumented internal function\n\ | |
1206 @end deftypefn") | |
1207 { | |
1208 #ifdef HAVE_CURL | |
1209 int nargin = args.length (); | |
1210 | |
1211 if (nargin != 1) | |
1212 error ("incorrect number of arguments"); | |
1213 else | |
1214 { | |
1215 std::string handle = args(0).string_value (); | |
1216 | |
1217 if (!error_state) | |
1218 { | |
1219 const curl_handle curl = handles.contents (handle); | |
1220 | |
1221 if (curl.is_valid ()) | |
1222 curl.binary (); | |
1223 else | |
1224 error ("__ftp_binary__: invalid ftp handle"); | |
1225 } | |
1226 } | |
1227 #else | |
1228 error ("__ftp_binary__: not available in this version of Octave"); | |
1229 #endif | |
1230 | |
1231 return octave_value (); | |
1232 } | |
1233 | |
1234 DEFUN_DLD (__ftp_close__, args, , | |
1235 "-*- texinfo -*-\n\ | |
1236 @deftypefn {Loadable Function} {} __ftp_close__ (@var{handle})\n\ | |
1237 Undocumented internal function\n\ | |
1238 @end deftypefn") | |
1239 { | |
1240 #ifdef HAVE_CURL | |
1241 int nargin = args.length (); | |
1242 | |
1243 if (nargin != 1) | |
1244 error ("incorrect number of arguments"); | |
1245 else | |
1246 { | |
1247 std::string handle = args(0).string_value (); | |
1248 | |
1249 if (!error_state) | |
1250 handles.del (handle); | |
1251 } | |
1252 #else | |
1253 error ("__ftp_close__: not available in this version of Octave"); | |
1254 #endif | |
1255 | |
1256 return octave_value (); | |
1257 } | |
1258 | |
1259 DEFUN_DLD (__ftp_mode__, args, , | |
1260 "-*- texinfo -*-\n\ | |
1261 @deftypefn {Loadable Function} {} __ftp_mode__ (@var{handle})\n\ | |
1262 Undocumented internal function\n\ | |
1263 @end deftypefn") | |
1264 { | |
1265 octave_value retval; | |
1266 #ifdef HAVE_CURL | |
1267 int nargin = args.length (); | |
1268 | |
1269 if (nargin != 1) | |
1270 error ("incorrect number of arguments"); | |
1271 else | |
1272 { | |
1273 std::string handle = args(0).string_value (); | |
1274 | |
1275 | |
1276 if (!error_state) | |
1277 { | |
1278 const curl_handle curl = handles.contents (handle); | |
1279 | |
1280 if (curl.is_valid ()) | |
1281 retval = (curl.is_ascii() ? "ascii" : "binary"); | |
1282 else | |
1283 error ("__ftp_binary__: invalid ftp handle"); | |
1284 } | |
1285 } | |
1286 #else | |
1287 error ("__ftp_mode__: not available in this version of Octave"); | |
1288 #endif | |
1289 | |
1290 return retval; | |
1291 } | |
1292 | |
1293 DEFUN_DLD (__ftp_delete__, args, , | |
1294 "-*- texinfo -*-\n\ | |
1295 @deftypefn {Loadable Function} {} __ftp_delete__ (@var{handle}, @var{path})\n\ | |
1296 Undocumented internal function\n\ | |
1297 @end deftypefn") | |
1298 { | |
1299 #ifdef HAVE_CURL | |
1300 int nargin = args.length (); | |
1301 | |
1302 if (nargin != 2) | |
1303 error ("incorrect number of arguments"); | |
1304 else | |
1305 { | |
1306 std::string handle = args(0).string_value (); | |
1307 std::string file = args(1).string_value (); | |
1308 | |
1309 if (!error_state) | |
1310 { | |
1311 const curl_handle curl = handles.contents (handle); | |
1312 | |
1313 if (curl.is_valid ()) | |
1314 curl.del (file); | |
1315 else | |
1316 error ("__ftp_delete__: invalid ftp handle"); | |
1317 } | |
1318 } | |
1319 #else | |
1320 error ("__ftp_delete__: not available in this version of Octave"); | |
1321 #endif | |
1322 | |
1323 return octave_value (); | |
1324 } | |
1325 | |
1326 DEFUN_DLD (__ftp_rmdir__, args, , | |
1327 "-*- texinfo -*-\n\ | |
1328 @deftypefn {Loadable Function} {} __ftp_rmdir__ (@var{handle}, @var{path})\n\ | |
1329 Undocumented internal function\n\ | |
1330 @end deftypefn") | |
1331 { | |
1332 #ifdef HAVE_CURL | |
1333 int nargin = args.length (); | |
1334 | |
1335 if (nargin != 2) | |
1336 error ("incorrect number of arguments"); | |
1337 else | |
1338 { | |
1339 std::string handle = args(0).string_value (); | |
1340 std::string dir = args(1).string_value (); | |
1341 | |
1342 if (!error_state) | |
1343 { | |
1344 const curl_handle curl = handles.contents (handle); | |
1345 | |
1346 if (curl.is_valid ()) | |
1347 curl.rmdir (dir); | |
1348 else | |
1349 error ("__ftp_rmdir__: invalid ftp handle"); | |
1350 } | |
1351 } | |
1352 #else | |
1353 error ("__ftp_rmdir__: not available in this version of Octave"); | |
1354 #endif | |
1355 | |
1356 return octave_value (); | |
1357 } | |
1358 | |
1359 DEFUN_DLD (__ftp_mkdir__, args, , | |
1360 "-*- texinfo -*-\n\ | |
1361 @deftypefn {Loadable Function} {} __ftp_mkdir__ (@var{handle}, @var{path})\n\ | |
1362 Undocumented internal function\n\ | |
1363 @end deftypefn") | |
1364 { | |
1365 #ifdef HAVE_CURL | |
1366 int nargin = args.length (); | |
1367 | |
1368 if (nargin != 2) | |
1369 error ("incorrect number of arguments"); | |
1370 else | |
1371 { | |
1372 std::string handle = args(0).string_value (); | |
1373 std::string dir = args(1).string_value (); | |
1374 | |
1375 if (!error_state) | |
1376 { | |
1377 const curl_handle curl = handles.contents (handle); | |
1378 | |
1379 if (curl.is_valid ()) | |
1380 curl.mkdir (dir); | |
1381 else | |
1382 error ("__ftp_mkdir__: invalid ftp handle"); | |
1383 } | |
1384 } | |
1385 #else | |
1386 error ("__ftp_mkdir__: not available in this version of Octave"); | |
1387 #endif | |
1388 | |
1389 return octave_value (); | |
1390 } | |
1391 | |
1392 DEFUN_DLD (__ftp_rename__, args, , | |
1393 "-*- texinfo -*-\n\ | |
1394 @deftypefn {Loadable Function} {} __ftp_rename__ (@var{handle}, @var{path})\n\ | |
1395 Undocumented internal function\n\ | |
1396 @end deftypefn") | |
1397 { | |
1398 #ifdef HAVE_CURL | |
1399 int nargin = args.length (); | |
1400 | |
1401 if (nargin != 3) | |
1402 error ("incorrect number of arguments"); | |
1403 else | |
1404 { | |
1405 std::string handle = args(0).string_value (); | |
1406 std::string oldname = args(1).string_value (); | |
1407 std::string newname = args(2).string_value (); | |
1408 | |
1409 if (!error_state) | |
1410 { | |
1411 const curl_handle curl = handles.contents (handle); | |
1412 | |
1413 if (curl.is_valid ()) | |
1414 curl.rename (oldname, newname); | |
1415 else | |
1416 error ("__ftp_rename__: invalid ftp handle"); | |
1417 } | |
1418 } | |
1419 #else | |
1420 error ("__ftp_rename__: not available in this version of Octave"); | |
1421 #endif | |
1422 | |
1423 return octave_value (); | |
1424 } | |
1425 | |
9905
84a7c11ff928
Correctly compile even when libcurl is not present according to configure
Rik <rdrider0-list@yahoo.com>
parents:
9885
diff
changeset
|
1426 #ifdef HAVE_CURL |
9880 | 1427 static string_vector |
1428 mput_directory (const curl_handle& curl, const std::string& base, | |
1429 const std::string& dir) | |
1430 { | |
1431 string_vector retval; | |
1432 | |
1433 if (! curl.mkdir (dir, false)) | |
1434 warning ("__ftp_mput__: can not create the remote directory ""%s""", | |
1435 (base.length() == 0 ? dir : base + | |
1436 file_ops::dir_sep_str () + dir).c_str ()); | |
1437 | |
1438 curl.cwd (dir); | |
1439 | |
1440 if (! error_state) | |
1441 { | |
1442 unwind_protect::frame_id_t uwp_frame = | |
1443 unwind_protect::begin_frame (); | |
1444 | |
1445 unwind_protect::add_fcn (reset_path, curl); | |
1446 | |
1447 std::string realdir = base.length() == 0 ? dir : base + | |
1448 file_ops::dir_sep_str () + dir; | |
1449 | |
1450 dir_entry dirlist (realdir); | |
1451 | |
1452 if (dirlist) | |
1453 { | |
1454 string_vector files = dirlist.read (); | |
1455 | |
1456 for (octave_idx_type i = 0; i < files.length (); i++) | |
1457 { | |
1458 std::string file = files (i); | |
1459 | |
1460 if (file == "." || file == "..") | |
1461 continue; | |
1462 | |
1463 std::string realfile = realdir + file_ops::dir_sep_str () + file; | |
1464 file_stat fs (realfile); | |
1465 | |
1466 if (! fs.exists ()) | |
1467 { | |
1468 error ("__ftp__mput: file ""%s"" does not exist", | |
1469 realfile.c_str ()); | |
1470 break; | |
1471 } | |
1472 | |
1473 if (fs.is_dir ()) | |
1474 { | |
1475 retval.append (mput_directory (curl, realdir, file)); | |
1476 | |
1477 if (error_state) | |
1478 break; | |
1479 } | |
1480 else | |
1481 { | |
1482 // FIXME Does ascii mode need to be flagged here? | |
1483 std::ifstream ifile (realfile.c_str(), std::ios::in | | |
1484 std::ios::binary); | |
1485 | |
1486 if (! ifile.is_open ()) | |
1487 { | |
1488 error ("__ftp_mput__: unable to open file ""%s""", | |
1489 realfile.c_str ()); | |
1490 break; | |
1491 } | |
1492 | |
1493 curl.put (file, ifile); | |
1494 | |
1495 ifile.close (); | |
1496 | |
1497 if (error_state) | |
1498 break; | |
1499 | |
1500 retval.append (realfile); | |
1501 } | |
1502 } | |
1503 } | |
1504 else | |
1505 error ("__ftp_mput__: can not read the directory ""%s""", | |
1506 realdir.c_str()); | |
1507 | |
1508 unwind_protect::run_frame (uwp_frame); | |
1509 } | |
1510 | |
1511 return retval; | |
1512 } | |
9905
84a7c11ff928
Correctly compile even when libcurl is not present according to configure
Rik <rdrider0-list@yahoo.com>
parents:
9885
diff
changeset
|
1513 #endif |
9880 | 1514 |
1515 DEFUN_DLD (__ftp_mput__, args, nargout, | |
1516 "-*- texinfo -*-\n\ | |
1517 @deftypefn {Loadable Function} {} __ftp_mput__ (@var{handle}, @var{files})\n\ | |
1518 Undocumented internal function\n\ | |
1519 @end deftypefn") | |
1520 { | |
1521 string_vector retval; | |
1522 | |
1523 #ifdef HAVE_CURL | |
1524 int nargin = args.length (); | |
1525 | |
1526 if (nargin != 2) | |
1527 error ("incorrect number of arguments"); | |
1528 else | |
1529 { | |
1530 std::string handle = args(0).string_value (); | |
1531 std::string pat = args(1).string_value (); | |
1532 | |
1533 if (!error_state) | |
1534 { | |
1535 const curl_handle curl = handles.contents (handle); | |
1536 | |
1537 if (curl.is_valid ()) | |
1538 { | |
1539 glob_match pattern (file_ops::tilde_expand (pat)); | |
1540 string_vector files = pattern.glob (); | |
1541 | |
1542 for (octave_idx_type i = 0; i < files.length (); i++) | |
1543 { | |
1544 std::string file = files (i); | |
1545 | |
1546 file_stat fs (file); | |
1547 | |
1548 if (! fs.exists ()) | |
1549 { | |
1550 error ("__ftp__mput: file does not exist"); | |
1551 break; | |
1552 } | |
1553 | |
1554 if (fs.is_dir ()) | |
1555 { | |
1556 retval.append (mput_directory (curl, "", file)); | |
1557 if (error_state) | |
1558 break; | |
1559 } | |
1560 else | |
1561 { | |
1562 // FIXME Does ascii mode need to be flagged here? | |
1563 std::ifstream ifile (file.c_str(), std::ios::in | | |
1564 std::ios::binary); | |
1565 | |
1566 if (! ifile.is_open ()) | |
1567 { | |
1568 error ("__ftp_mput__: unable to open file"); | |
1569 break; | |
1570 } | |
1571 | |
1572 curl.put (file, ifile); | |
1573 | |
1574 ifile.close (); | |
1575 | |
1576 if (error_state) | |
1577 break; | |
1578 | |
1579 retval.append (file); | |
1580 } | |
1581 } | |
1582 } | |
1583 else | |
1584 error ("__ftp_mput__: invalid ftp handle"); | |
1585 } | |
1586 } | |
1587 #else | |
1588 error ("__ftp_mput__: not available in this version of Octave"); | |
1589 #endif | |
1590 | |
1591 return (nargout > 0 ? octave_value (retval) : octave_value ()); | |
1592 } | |
1593 | |
1594 #ifdef HAVE_CURL | |
1595 static void | |
1596 getallfiles (const curl_handle& curl, const std::string& dir, | |
1597 const std::string& target) | |
1598 { | |
1599 std::string sep = file_ops::dir_sep_str (); | |
1600 file_stat fs (dir); | |
1601 | |
1602 if (!fs || !fs.is_dir ()) | |
1603 { | |
1604 std::string msg; | |
1605 int status = file_ops::mkdir (dir, 0777, msg); | |
1606 | |
1607 if (status < 0) | |
1608 error ("__ftp_mget__: can't create directory %s%s%s. %s", | |
1609 target.c_str(), sep.c_str(), dir.c_str(), msg.c_str()); | |
1610 } | |
1611 | |
1612 if (! error_state) | |
1613 { | |
1614 curl.cwd (dir); | |
1615 | |
1616 if (! error_state) | |
1617 { | |
1618 unwind_protect::frame_id_t uwp_frame = | |
1619 unwind_protect::begin_frame (); | |
1620 | |
1621 unwind_protect::add_fcn (reset_path, curl); | |
1622 | |
1623 string_vector sv = curl.list (); | |
1624 | |
1625 for (octave_idx_type i = 0; i < sv.length (); i++) | |
1626 { | |
1627 time_t ftime; | |
1628 bool fisdir; | |
1629 double fsize; | |
1630 | |
1631 curl.get_fileinfo (sv(i), fsize, ftime, fisdir); | |
1632 | |
1633 if (fisdir) | |
1634 getallfiles (curl, sv(i), target + dir + sep); | |
1635 else | |
1636 { | |
1637 std::string realfile = target + dir + sep + sv(i); | |
1638 std::ofstream ofile (realfile.c_str(), | |
1639 std::ios::out | | |
1640 std::ios::binary); | |
1641 | |
1642 if (! ofile.is_open ()) | |
1643 { | |
1644 error ("__ftp_mget__: unable to open file"); | |
1645 break; | |
1646 } | |
1647 | |
1648 unwind_protect::frame_id_t uwp_frame2 = | |
1649 unwind_protect::begin_frame (); | |
1650 | |
1651 unwind_protect::add_fcn (delete_file, realfile); | |
1652 | |
1653 curl.get (sv(i), ofile); | |
1654 | |
1655 ofile.close (); | |
1656 | |
1657 if (!error_state) | |
1658 unwind_protect::discard_frame (uwp_frame2); | |
1659 else | |
1660 unwind_protect::run_frame (uwp_frame2); | |
1661 } | |
1662 | |
1663 if (error_state) | |
1664 break; | |
1665 } | |
1666 | |
1667 unwind_protect::run_frame (uwp_frame); | |
1668 } | |
1669 } | |
1670 } | |
1671 #endif | |
1672 | |
1673 DEFUN_DLD (__ftp_mget__, args, , | |
1674 "-*- texinfo -*-\n\ | |
1675 @deftypefn {Loadable Function} {} __ftp_mget__ (@var{handle}, @var{files})\n\ | |
1676 Undocumented internal function\n\ | |
1677 @end deftypefn") | |
1678 { | |
1679 #ifdef HAVE_CURL | |
1680 int nargin = args.length (); | |
1681 | |
1682 if (nargin != 2 && nargin != 3) | |
1683 error ("incorrect number of arguments"); | |
1684 else | |
1685 { | |
1686 std::string handle = args(0).string_value (); | |
1687 std::string file = args(1).string_value (); | |
1688 std::string target; | |
1689 | |
1690 if (nargin == 3) | |
1691 target = args(2).string_value () + file_ops::dir_sep_str (); | |
1692 | |
1693 if (! error_state) | |
1694 { | |
1695 const curl_handle curl = handles.contents (handle); | |
1696 | |
1697 if (curl.is_valid ()) | |
1698 { | |
1699 string_vector sv = curl.list (); | |
1700 octave_idx_type n = 0; | |
1701 glob_match pattern (file); | |
1702 | |
1703 for (octave_idx_type i = 0; i < sv.length (); i++) | |
1704 { | |
1705 if (pattern.match (sv(i))) | |
1706 { | |
1707 n++; | |
1708 | |
1709 time_t ftime; | |
1710 bool fisdir; | |
1711 double fsize; | |
1712 | |
1713 curl.get_fileinfo (sv(i), fsize, ftime, fisdir); | |
1714 | |
1715 if (fisdir) | |
1716 getallfiles (curl, sv(i), target); | |
1717 else | |
1718 { | |
1719 std::ofstream ofile ((target + sv(i)).c_str(), | |
1720 std::ios::out | | |
1721 std::ios::binary); | |
1722 | |
1723 if (! ofile.is_open ()) | |
1724 { | |
1725 error ("__ftp_mget__: unable to open file"); | |
1726 break; | |
1727 } | |
1728 | |
1729 unwind_protect::frame_id_t uwp_frame = | |
1730 unwind_protect::begin_frame (); | |
1731 | |
1732 unwind_protect::add_fcn (delete_file, target + sv(i)); | |
1733 | |
1734 curl.get (sv(i), ofile); | |
1735 | |
1736 ofile.close (); | |
1737 | |
1738 if (!error_state) | |
1739 unwind_protect::discard_frame (uwp_frame); | |
1740 else | |
1741 unwind_protect::run_frame (uwp_frame); | |
1742 } | |
1743 | |
1744 if (error_state) | |
1745 break; | |
1746 } | |
1747 } | |
1748 if (n == 0) | |
1749 error ("__ftp_mget__: file not found"); | |
1750 } | |
1751 } | |
1752 } | |
1753 #else | |
1754 error ("__ftp_mget__: not available in this version of Octave"); | |
1755 #endif | |
1756 | |
1757 return octave_value (); | |
1758 } |