Mercurial > octave-nkf
annotate src/DLD-FUNCTIONS/urlwrite.cc @ 10084:81e88250bf42
urlwrite: avoid using errno as a local variable
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Mon, 11 Jan 2010 16:07:15 -0500 |
parents | 2cd940306a06 |
children | 40dfc0c99116 |
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 { | |
10084
81e88250bf42
urlwrite: avoid using errno as a local variable
John W. Eaton <jwe@octave.org>
parents:
10066
diff
changeset
|
254 CURLcode errnum; |
9880 | 255 |
10084
81e88250bf42
urlwrite: avoid using errno as a local variable
John W. Eaton <jwe@octave.org>
parents:
10066
diff
changeset
|
256 curl_easy_getinfo (rep->handle(), CURLINFO_OS_ERRNO, &errnum); |
9880 | 257 |
10084
81e88250bf42
urlwrite: avoid using errno as a local variable
John W. Eaton <jwe@octave.org>
parents:
10066
diff
changeset
|
258 return std::string (curl_easy_strerror (errnum)); |
9880 | 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 | |
9918
57b41617c9fd
avoid LIBCURL version check
John W. Eaton <jwe@octave.org>
parents:
9905
diff
changeset
|
563 std::string userpwd = user; |
57b41617c9fd
avoid LIBCURL version check
John W. Eaton <jwe@octave.org>
parents:
9905
diff
changeset
|
564 if (! passwd.empty ()) |
57b41617c9fd
avoid LIBCURL version check
John W. Eaton <jwe@octave.org>
parents:
9905
diff
changeset
|
565 userpwd += ":" + passwd; |
57b41617c9fd
avoid LIBCURL version check
John W. Eaton <jwe@octave.org>
parents:
9905
diff
changeset
|
566 setopt (CURLOPT_USERPWD, userpwd.c_str ()); |
9880 | 567 |
568 // Define our callback to get called when there's data to be written. | |
569 setopt (CURLOPT_WRITEFUNCTION, write_data); | |
6992 | 570 |
9880 | 571 // Set a pointer to our struct to pass to the callback. |
572 setopt (CURLOPT_WRITEDATA, static_cast<void*> (&os)); | |
573 | |
574 // Define our callback to get called when there's data to be read | |
575 setopt (CURLOPT_READFUNCTION, read_data); | |
576 | |
577 // Set a pointer to our struct to pass to the callback. | |
578 setopt (CURLOPT_READDATA, static_cast<void*> (&is)); | |
579 | |
580 // Follow redirects. | |
581 setopt (CURLOPT_FOLLOWLOCATION, true); | |
582 | |
583 // Don't use EPSV since connecting to sites that don't support it | |
584 // will hang for some time (3 minutes?) before moving on to try PASV | |
585 // instead. | |
586 setopt (CURLOPT_FTP_USE_EPSV, false); | |
587 | |
588 setopt (CURLOPT_NOPROGRESS, true); | |
589 setopt (CURLOPT_FAILONERROR, true); | |
6992 | 590 |
9880 | 591 setopt (CURLOPT_POSTQUOTE, 0); |
592 setopt (CURLOPT_QUOTE, 0); | |
593 } | |
594 | |
595 #undef setopt | |
596 }; | |
597 | |
598 class | |
599 curl_handles | |
600 { | |
601 public: | |
602 | |
603 typedef std::map<std::string, curl_handle>::iterator iterator; | |
604 typedef std::map<std::string, curl_handle>::const_iterator const_iterator; | |
6043 | 605 |
9880 | 606 curl_handles (void) : map () |
607 { | |
608 curl_global_init(CURL_GLOBAL_DEFAULT); | |
609 } | |
610 | |
611 ~curl_handles (void) | |
612 { | |
613 // Remove the elements of the map explicitly as they should | |
614 // be deleted before the call to curl_global_cleanup | |
615 for (iterator pa = begin (); pa != end (); pa++) | |
616 map.erase (pa); | |
6992 | 617 |
9880 | 618 curl_global_cleanup (); |
619 } | |
620 | |
621 iterator begin (void) { return iterator (map.begin ()); } | |
622 const_iterator begin (void) const { return const_iterator (map.begin ()); } | |
623 | |
624 iterator end (void) { return iterator (map.end ()); } | |
625 const_iterator end (void) const { return const_iterator (map.end ()); } | |
6992 | 626 |
9880 | 627 iterator seek (const std::string& k) { return map.find (k); } |
628 const_iterator seek (const std::string& k) const { return map.find (k); } | |
629 | |
630 std::string key (const_iterator p) const { return p->first; } | |
631 | |
632 curl_handle& contents (const std::string& k) | |
633 { | |
634 return map[k]; | |
635 } | |
636 | |
637 curl_handle contents (const std::string& k) const | |
638 { | |
639 const_iterator p = seek (k); | |
640 return p != end () ? p->second : curl_handle (); | |
641 } | |
642 | |
643 curl_handle& contents (iterator p) | |
644 { return p->second; } | |
6992 | 645 |
9880 | 646 curl_handle contents (const_iterator p) const |
647 { return p->second; } | |
648 | |
649 void del (const std::string& k) | |
650 { | |
651 iterator p = map.find (k); | |
652 | |
653 if (p != map.end ()) | |
654 map.erase (p); | |
655 } | |
6043 | 656 |
9880 | 657 private: |
658 std::map<std::string, curl_handle> map; | |
659 }; | |
660 | |
661 static curl_handles handles; | |
662 | |
663 static void | |
664 cleanup_urlwrite (std::string filename) | |
665 { | |
666 file_ops::unlink (filename); | |
6043 | 667 } |
668 | |
9880 | 669 static void |
670 reset_path (const curl_handle curl) | |
671 { | |
672 curl.cwd (".."); | |
673 } | |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
674 |
9880 | 675 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
|
676 { |
9880 | 677 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
|
678 } |
9880 | 679 #endif |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
680 |
6043 | 681 DEFUN_DLD (urlwrite, args, nargout, |
682 "-*- texinfo -*-\n\ | |
9880 | 683 @deftypefn {Loadable Function} {} urlwrite (@var{url}, @var{localfile})\n\ |
6043 | 684 @deftypefnx {Loadable Function} {@var{f} =} urlwrite (@var{url}, @var{localfile})\n\ |
685 @deftypefnx {Loadable Function} {[@var{f}, @var{success}] =} urlwrite (@var{url}, @var{localfile})\n\ | |
686 @deftypefnx {Loadable Function} {[@var{f}, @var{success}, @var{message}] =} urlwrite (@var{url}, @var{localfile})\n\ | |
9880 | 687 Download a remote file specified by its @var{url} and save it as\n\ |
6043 | 688 @var{localfile}. For example,\n\ |
689 \n\ | |
690 @example\n\ | |
9064
7c02ec148a3c
Check grammar on all .cc files
Rik <rdrider0-list@yahoo.com>
parents:
8920
diff
changeset
|
691 @group\n\ |
7031 | 692 urlwrite (\"ftp://ftp.octave.org/pub/octave/README\", \n\ |
693 \"README.txt\");\n\ | |
9064
7c02ec148a3c
Check grammar on all .cc files
Rik <rdrider0-list@yahoo.com>
parents:
8920
diff
changeset
|
694 @end group\n\ |
6043 | 695 @end example\n\ |
696 \n\ | |
697 The full path of the downloaded file is returned in @var{f}. The\n\ | |
698 variable @var{success} is 1 if the download was successful,\n\ | |
699 otherwise it is 0 in which case @var{message} contains an error\n\ | |
700 message. If no output argument is specified and if an error occurs,\n\ | |
6588 | 701 then the error is signaled through Octave's error handling mechanism.\n\ |
6043 | 702 \n\ |
703 This function uses libcurl. Curl supports, among others, the HTTP,\n\ | |
704 FTP and FILE protocols. Username and password may be specified in\n\ | |
705 the URL, for example:\n\ | |
706 \n\ | |
707 @example\n\ | |
9064
7c02ec148a3c
Check grammar on all .cc files
Rik <rdrider0-list@yahoo.com>
parents:
8920
diff
changeset
|
708 @group\n\ |
6588 | 709 urlwrite (\"http://username:password@@example.com/file.txt\",\n\ |
710 \"file.txt\");\n\ | |
9064
7c02ec148a3c
Check grammar on all .cc files
Rik <rdrider0-list@yahoo.com>
parents:
8920
diff
changeset
|
711 @end group\n\ |
6043 | 712 @end example\n\ |
713 \n\ | |
714 GET and POST requests can be specified by @var{method} and @var{param}.\n\ | |
6589 | 715 The parameter @var{method} is either @samp{get} or @samp{post}\n\ |
6588 | 716 and @var{param} is a cell array of parameter and value pairs.\n\ |
717 For example:\n\ | |
6043 | 718 \n\ |
719 @example\n\ | |
9064
7c02ec148a3c
Check grammar on all .cc files
Rik <rdrider0-list@yahoo.com>
parents:
8920
diff
changeset
|
720 @group\n\ |
6588 | 721 urlwrite (\"http://www.google.com/search\", \"search.html\",\n\ |
722 \"get\", @{\"query\", \"octave\"@});\n\ | |
9064
7c02ec148a3c
Check grammar on all .cc files
Rik <rdrider0-list@yahoo.com>
parents:
8920
diff
changeset
|
723 @end group\n\ |
6043 | 724 @end example\n\ |
725 @seealso{urlread}\n\ | |
726 @end deftypefn") | |
727 { | |
728 octave_value_list retval; | |
729 | |
9905
84a7c11ff928
Correctly compile even when libcurl is not present according to configure
Rik <rdrider0-list@yahoo.com>
parents:
9885
diff
changeset
|
730 #ifdef HAVE_CURL |
6043 | 731 |
732 int nargin = args.length (); | |
733 | |
734 // verify arguments | |
735 if (nargin != 2 && nargin != 4) | |
736 { | |
737 print_usage (); | |
738 return retval; | |
739 } | |
740 | |
741 std::string url = args(0).string_value(); | |
742 | |
743 if (error_state) | |
744 { | |
745 error ("urlwrite: url must be a character string"); | |
746 return retval; | |
747 } | |
748 | |
749 // name to store the file if download is succesful | |
750 std::string filename = args(1).string_value(); | |
751 | |
752 if (error_state) | |
753 { | |
754 error ("urlwrite: localfile must be a character string"); | |
755 return retval; | |
756 } | |
757 | |
758 std::string method; | |
759 Cell param; // empty cell array | |
760 | |
761 if (nargin == 4) | |
762 { | |
763 method = args(2).string_value(); | |
764 | |
765 if (error_state) | |
766 { | |
767 error ("urlwrite: method can only be \"get\" or \"post\""); | |
768 return retval; | |
769 } | |
770 | |
771 if (method != "get" && method != "post") | |
772 { | |
773 error ("urlwrite: method can only be \"get\" or \"post\""); | |
774 return retval; | |
775 } | |
776 | |
777 param = args(3).cell_value(); | |
778 | |
779 if (error_state) | |
780 { | |
781 error ("urlwrite: parameters for get and post requests must be given as a cell"); | |
782 return retval; | |
783 } | |
784 | |
785 | |
786 if (param.numel () % 2 == 1 ) | |
787 { | |
788 error ("urlwrite: number of elements in param must be even"); | |
789 return retval; | |
790 } | |
791 } | |
792 | |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
793 // 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
|
794 // 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
|
795 // 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
|
796 |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
797 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
|
798 |
6986 | 799 std::ofstream ofile (filename.c_str(), std::ios::out | std::ios::binary); |
6043 | 800 |
6986 | 801 if (! ofile.is_open ()) |
6043 | 802 { |
803 error ("urlwrite: unable to open file"); | |
804 return retval; | |
805 } | |
806 | |
10066
2cd940306a06
make unwind_protect frames local
Jaroslav Hajek <highegg@gmail.com>
parents:
9918
diff
changeset
|
807 unwind_protect_safe frame; |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
808 |
10066
2cd940306a06
make unwind_protect frames local
Jaroslav Hajek <highegg@gmail.com>
parents:
9918
diff
changeset
|
809 frame.add_fcn (cleanup_urlwrite, filename); |
9880 | 810 |
811 bool res; | |
812 curl_handle curl = curl_handle (url, method, param, ofile, res); | |
6043 | 813 |
6986 | 814 ofile.close (); |
6043 | 815 |
9880 | 816 if (!error_state) |
10066
2cd940306a06
make unwind_protect frames local
Jaroslav Hajek <highegg@gmail.com>
parents:
9918
diff
changeset
|
817 frame.discard (); |
9880 | 818 else |
10066
2cd940306a06
make unwind_protect frames local
Jaroslav Hajek <highegg@gmail.com>
parents:
9918
diff
changeset
|
819 frame.run (); |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
820 |
6043 | 821 if (nargout > 0) |
822 { | |
9880 | 823 if (res) |
8151
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
824 { |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
825 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
|
826 retval(1) = true; |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
827 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
|
828 } |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
829 else |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
830 { |
9880 | 831 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
|
832 retval(1) = false; |
3725f819b5b3
urlwrite.cc (Furlwrite): delete files we create if download fails
John W. Eaton <jwe@octave.org>
parents:
7481
diff
changeset
|
833 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
|
834 } |
6043 | 835 } |
836 | |
9880 | 837 if (nargout < 2 && res) |
838 error ("urlwrite: curl: %s", curl.lasterror ().c_str ()); | |
6043 | 839 |
840 #else | |
6981 | 841 error ("urlwrite: not available in this version of Octave"); |
6043 | 842 #endif |
843 | |
844 return retval; | |
845 } | |
846 | |
847 DEFUN_DLD (urlread, args, nargout, | |
848 "-*- texinfo -*-\n\ | |
6549 | 849 @deftypefn {Loadable Function} {@var{s} =} urlread (@var{url})\n\ |
6043 | 850 @deftypefnx {Loadable Function} {[@var{s}, @var{success}] =} urlread (@var{url})\n\ |
6549 | 851 @deftypefnx {Loadable Function} {[@var{s}, @var{success}, @var{message}] =} urlread (@var{url})\n\ |
6547 | 852 @deftypefnx {Loadable Function} {[@dots{}] =} urlread (@var{url}, @var{method}, @var{param})\n\ |
9880 | 853 Download a remote file specified by its @var{url} and return its content\n\ |
6043 | 854 in string @var{s}. For example,\n\ |
855 \n\ | |
856 @example\n\ | |
6588 | 857 s = urlread (\"ftp://ftp.octave.org/pub/octave/README\");\n\ |
6043 | 858 @end example\n\ |
859 \n\ | |
860 The variable @var{success} is 1 if the download was successful,\n\ | |
861 otherwise it is 0 in which case @var{message} contains an error\n\ | |
862 message. If no output argument is specified and if an error occurs,\n\ | |
6588 | 863 then the error is signaled through Octave's error handling mechanism.\n\ |
6043 | 864 \n\ |
865 This function uses libcurl. Curl supports, among others, the HTTP,\n\ | |
866 FTP and FILE protocols. Username and password may be specified in the\n\ | |
867 URL. For example,\n\ | |
868 \n\ | |
869 @example\n\ | |
7031 | 870 s = urlread (\"http://user:password@@example.com/file.txt\");\n\ |
6043 | 871 @end example\n\ |
872 \n\ | |
873 GET and POST requests can be specified by @var{method} and @var{param}.\n\ | |
6588 | 874 The parameter @var{method} is either @samp{get} or @samp{post}\n\ |
875 and @var{param} is a cell array of parameter and value pairs.\n\ | |
6650 | 876 For example,\n\ |
6043 | 877 \n\ |
878 @example\n\ | |
9064
7c02ec148a3c
Check grammar on all .cc files
Rik <rdrider0-list@yahoo.com>
parents:
8920
diff
changeset
|
879 @group\n\ |
6588 | 880 s = urlread (\"http://www.google.com/search\", \"get\",\n\ |
881 @{\"query\", \"octave\"@});\n\ | |
9064
7c02ec148a3c
Check grammar on all .cc files
Rik <rdrider0-list@yahoo.com>
parents:
8920
diff
changeset
|
882 @end group\n\ |
6043 | 883 @end example\n\ |
884 @seealso{urlwrite}\n\ | |
885 @end deftypefn") | |
886 { | |
6588 | 887 // Octave's return value |
6043 | 888 octave_value_list retval; |
889 | |
9905
84a7c11ff928
Correctly compile even when libcurl is not present according to configure
Rik <rdrider0-list@yahoo.com>
parents:
9885
diff
changeset
|
890 #ifdef HAVE_CURL |
6043 | 891 |
892 int nargin = args.length (); | |
893 | |
894 // verify arguments | |
895 if (nargin != 1 && nargin != 3) | |
896 { | |
897 print_usage (); | |
898 return retval; | |
899 } | |
900 | |
901 std::string url = args(0).string_value(); | |
902 | |
903 if (error_state) | |
904 { | |
905 error ("urlread: url must be a character string"); | |
906 return retval; | |
907 } | |
908 | |
909 std::string method; | |
910 Cell param; // empty cell array | |
911 | |
912 if (nargin == 3) | |
913 { | |
914 method = args(1).string_value(); | |
915 | |
916 if (error_state) | |
917 { | |
918 error ("urlread: method can only be \"get\" or \"post\""); | |
919 return retval; | |
920 } | |
921 | |
922 if (method != "get" && method != "post") | |
923 { | |
924 error ("urlread: method can only be \"get\" or \"post\""); | |
925 return retval; | |
926 } | |
927 | |
928 param = args(2).cell_value(); | |
929 | |
930 if (error_state) | |
931 { | |
932 error ("urlread: parameters for get and post requests must be given as a cell"); | |
933 return retval; | |
934 } | |
935 | |
936 if (param.numel () % 2 == 1 ) | |
937 { | |
938 error ("urlread: number of elements in param must be even"); | |
939 return retval; | |
940 } | |
941 } | |
942 | |
6986 | 943 std::ostringstream buf; |
6043 | 944 |
9880 | 945 bool res; |
946 curl_handle curl = curl_handle (url, method, param, buf, res); | |
6043 | 947 |
948 if (nargout > 0) | |
949 { | |
6986 | 950 retval(0) = buf.str (); |
9880 | 951 retval(1) = res; |
6986 | 952 // Return empty string if no error occured. |
9880 | 953 retval(2) = res ? "" : curl.lasterror (); |
6043 | 954 } |
955 | |
9880 | 956 if (nargout < 2 && !res) |
957 error ("urlread: curl: %s", curl.lasterror().c_str()); | |
6043 | 958 |
959 #else | |
6981 | 960 error ("urlread: not available in this version of Octave"); |
6043 | 961 #endif |
962 | |
963 return retval; | |
964 } | |
9880 | 965 |
966 DEFUN_DLD (__ftp__, args, , | |
967 "-*- texinfo -*-\n\ | |
968 @deftypefn {Loadable Function} {} __ftp__ (@var{handle}, @var{host})\n\ | |
969 @deftypefnx {Loadable Function} {} __ftp__ (@var{handle}, @var{host}, @var{username}, @var{password})\n\ | |
970 Undocumented internal function\n\ | |
971 @end deftypefn") | |
972 { | |
973 #ifdef HAVE_CURL | |
974 int nargin = args.length (); | |
975 std::string handle; | |
976 std::string host; | |
977 std::string user = "anonymous"; | |
978 std::string passwd = ""; | |
979 | |
980 if (nargin < 2 || nargin > 4) | |
981 error ("incorrect number of arguments"); | |
982 else | |
983 { | |
984 handle = args(0).string_value (); | |
985 host = args(1).string_value (); | |
986 | |
987 if (nargin > 1) | |
988 user = args(2).string_value (); | |
989 | |
990 if (nargin > 2) | |
991 passwd = args(3).string_value (); | |
992 | |
993 if (!error_state) | |
994 { | |
995 handles.contents (handle) = curl_handle (host, user, passwd); | |
996 | |
997 if (error_state) | |
998 handles.del (handle); | |
999 } | |
1000 } | |
1001 #else | |
1002 error ("__ftp__: not available in this version of Octave"); | |
1003 #endif | |
1004 | |
1005 return octave_value (); | |
1006 } | |
1007 | |
1008 DEFUN_DLD (__ftp_pwd__, args, , | |
1009 "-*- texinfo -*-\n\ | |
1010 @deftypefn {Loadable Function} {} __ftp_pwd__ (@var{handle})\n\ | |
1011 Undocumented internal function\n\ | |
1012 @end deftypefn") | |
1013 { | |
1014 octave_value retval; | |
1015 #ifdef HAVE_CURL | |
1016 int nargin = args.length (); | |
1017 | |
1018 if (nargin != 1) | |
1019 error ("incorrect number of arguments"); | |
1020 else | |
1021 { | |
1022 std::string handle = args(0).string_value (); | |
1023 | |
1024 if (!error_state) | |
1025 { | |
1026 const curl_handle curl = handles.contents (handle); | |
1027 | |
1028 if (curl.is_valid ()) | |
1029 retval = curl.pwd (); | |
1030 else | |
1031 error ("__ftp_pwd__: invalid ftp handle"); | |
1032 } | |
1033 } | |
1034 #else | |
1035 error ("__ftp_pwd__: not available in this version of Octave"); | |
1036 #endif | |
1037 | |
1038 return retval; | |
1039 } | |
1040 | |
1041 DEFUN_DLD (__ftp_cwd__, args, , | |
1042 "-*- texinfo -*-\n\ | |
1043 @deftypefn {Loadable Function} {} __ftp_cwd__ (@var{handle}, @var{path})\n\ | |
1044 Undocumented internal function\n\ | |
1045 @end deftypefn") | |
1046 { | |
1047 #ifdef HAVE_CURL | |
1048 int nargin = args.length (); | |
1049 | |
1050 if (nargin != 1 && nargin != 2) | |
1051 error ("incorrect number of arguments"); | |
1052 else | |
1053 { | |
1054 std::string handle = args(0).string_value (); | |
1055 std::string path = ""; | |
1056 | |
1057 if (nargin > 1) | |
1058 path = args(1).string_value (); | |
1059 | |
1060 if (!error_state) | |
1061 { | |
1062 const curl_handle curl = handles.contents (handle); | |
1063 | |
1064 if (curl.is_valid ()) | |
1065 curl.cwd (path); | |
1066 else | |
1067 error ("__ftp_cwd__: invalid ftp handle"); | |
1068 } | |
1069 } | |
1070 #else | |
1071 error ("__ftp_cwd__: not available in this version of Octave"); | |
1072 #endif | |
1073 | |
1074 return octave_value (); | |
1075 } | |
1076 | |
1077 DEFUN_DLD (__ftp_dir__, args, nargout, | |
1078 "-*- texinfo -*-\n\ | |
1079 @deftypefn {Loadable Function} {} __ftp_dir__ (@var{handle})\n\ | |
1080 Undocumented internal function\n\ | |
1081 @end deftypefn") | |
1082 { | |
1083 octave_value retval; | |
1084 #ifdef HAVE_CURL | |
1085 int nargin = args.length (); | |
1086 | |
1087 if (nargin != 1) | |
1088 error ("incorrect number of arguments"); | |
1089 else | |
1090 { | |
1091 std::string handle = args(0).string_value (); | |
1092 | |
1093 if (!error_state) | |
1094 { | |
1095 const curl_handle curl = handles.contents (handle); | |
1096 | |
1097 if (curl.is_valid ()) | |
1098 { | |
1099 if (nargout == 0) | |
1100 curl.dir (); | |
1101 else | |
1102 { | |
1103 string_vector sv = curl.list (); | |
1104 octave_idx_type n = sv.length (); | |
1105 if (n == 0) | |
1106 { | |
1107 string_vector flds (5); | |
1108 flds(0) = "name"; | |
1109 flds(1) = "date"; | |
1110 flds(2) = "bytes"; | |
1111 flds(3) = "isdir"; | |
1112 flds(4) = "datenum"; | |
1113 retval = Octave_map (flds); | |
1114 } | |
1115 else | |
1116 { | |
1117 Octave_map st; | |
1118 Cell filectime (dim_vector (n, 1)); | |
1119 Cell filesize (dim_vector (n, 1)); | |
1120 Cell fileisdir (dim_vector (n, 1)); | |
1121 Cell filedatenum (dim_vector (n, 1)); | |
1122 | |
1123 st.assign ("name", Cell (sv)); | |
1124 | |
1125 for (octave_idx_type i = 0; i < n; i++) | |
1126 { | |
1127 time_t ftime; | |
1128 bool fisdir; | |
1129 double fsize; | |
1130 | |
1131 curl.get_fileinfo (sv(i), fsize, ftime, fisdir); | |
1132 | |
1133 fileisdir (i) = fisdir; | |
1134 filectime (i) = ctime (&ftime); | |
1135 filesize (i) = fsize; | |
1136 filedatenum (i) = double (ftime); | |
1137 } | |
1138 st.assign ("date", filectime); | |
1139 st.assign ("bytes", filesize); | |
1140 st.assign ("isdir", fileisdir); | |
1141 st.assign ("datenum", filedatenum); | |
1142 retval = st; | |
1143 } | |
1144 } | |
1145 } | |
1146 else | |
1147 error ("__ftp_dir__: invalid ftp handle"); | |
1148 } | |
1149 } | |
1150 #else | |
1151 error ("__ftp_dir__: not available in this version of Octave"); | |
1152 #endif | |
1153 | |
1154 return retval; | |
1155 } | |
1156 | |
1157 DEFUN_DLD (__ftp_ascii__, args, , | |
1158 "-*- texinfo -*-\n\ | |
1159 @deftypefn {Loadable Function} {} __ftp_ascii__ (@var{handle})\n\ | |
1160 Undocumented internal function\n\ | |
1161 @end deftypefn") | |
1162 { | |
1163 #ifdef HAVE_CURL | |
1164 int nargin = args.length (); | |
1165 | |
1166 if (nargin != 1) | |
1167 error ("incorrect number of arguments"); | |
1168 else | |
1169 { | |
1170 std::string handle = args(0).string_value (); | |
1171 | |
1172 if (!error_state) | |
1173 { | |
1174 const curl_handle curl = handles.contents (handle); | |
1175 | |
1176 if (curl.is_valid ()) | |
1177 curl.ascii (); | |
1178 else | |
1179 error ("__ftp_ascii__: invalid ftp handle"); | |
1180 } | |
1181 } | |
1182 #else | |
1183 error ("__ftp_ascii__: not available in this version of Octave"); | |
1184 #endif | |
1185 | |
1186 return octave_value (); | |
1187 } | |
1188 | |
1189 DEFUN_DLD (__ftp_binary__, args, , | |
1190 "-*- texinfo -*-\n\ | |
1191 @deftypefn {Loadable Function} {} __ftp_binary__ (@var{handle})\n\ | |
1192 Undocumented internal function\n\ | |
1193 @end deftypefn") | |
1194 { | |
1195 #ifdef HAVE_CURL | |
1196 int nargin = args.length (); | |
1197 | |
1198 if (nargin != 1) | |
1199 error ("incorrect number of arguments"); | |
1200 else | |
1201 { | |
1202 std::string handle = args(0).string_value (); | |
1203 | |
1204 if (!error_state) | |
1205 { | |
1206 const curl_handle curl = handles.contents (handle); | |
1207 | |
1208 if (curl.is_valid ()) | |
1209 curl.binary (); | |
1210 else | |
1211 error ("__ftp_binary__: invalid ftp handle"); | |
1212 } | |
1213 } | |
1214 #else | |
1215 error ("__ftp_binary__: not available in this version of Octave"); | |
1216 #endif | |
1217 | |
1218 return octave_value (); | |
1219 } | |
1220 | |
1221 DEFUN_DLD (__ftp_close__, args, , | |
1222 "-*- texinfo -*-\n\ | |
1223 @deftypefn {Loadable Function} {} __ftp_close__ (@var{handle})\n\ | |
1224 Undocumented internal function\n\ | |
1225 @end deftypefn") | |
1226 { | |
1227 #ifdef HAVE_CURL | |
1228 int nargin = args.length (); | |
1229 | |
1230 if (nargin != 1) | |
1231 error ("incorrect number of arguments"); | |
1232 else | |
1233 { | |
1234 std::string handle = args(0).string_value (); | |
1235 | |
1236 if (!error_state) | |
1237 handles.del (handle); | |
1238 } | |
1239 #else | |
1240 error ("__ftp_close__: not available in this version of Octave"); | |
1241 #endif | |
1242 | |
1243 return octave_value (); | |
1244 } | |
1245 | |
1246 DEFUN_DLD (__ftp_mode__, args, , | |
1247 "-*- texinfo -*-\n\ | |
1248 @deftypefn {Loadable Function} {} __ftp_mode__ (@var{handle})\n\ | |
1249 Undocumented internal function\n\ | |
1250 @end deftypefn") | |
1251 { | |
1252 octave_value retval; | |
1253 #ifdef HAVE_CURL | |
1254 int nargin = args.length (); | |
1255 | |
1256 if (nargin != 1) | |
1257 error ("incorrect number of arguments"); | |
1258 else | |
1259 { | |
1260 std::string handle = args(0).string_value (); | |
1261 | |
1262 | |
1263 if (!error_state) | |
1264 { | |
1265 const curl_handle curl = handles.contents (handle); | |
1266 | |
1267 if (curl.is_valid ()) | |
1268 retval = (curl.is_ascii() ? "ascii" : "binary"); | |
1269 else | |
1270 error ("__ftp_binary__: invalid ftp handle"); | |
1271 } | |
1272 } | |
1273 #else | |
1274 error ("__ftp_mode__: not available in this version of Octave"); | |
1275 #endif | |
1276 | |
1277 return retval; | |
1278 } | |
1279 | |
1280 DEFUN_DLD (__ftp_delete__, args, , | |
1281 "-*- texinfo -*-\n\ | |
1282 @deftypefn {Loadable Function} {} __ftp_delete__ (@var{handle}, @var{path})\n\ | |
1283 Undocumented internal function\n\ | |
1284 @end deftypefn") | |
1285 { | |
1286 #ifdef HAVE_CURL | |
1287 int nargin = args.length (); | |
1288 | |
1289 if (nargin != 2) | |
1290 error ("incorrect number of arguments"); | |
1291 else | |
1292 { | |
1293 std::string handle = args(0).string_value (); | |
1294 std::string file = args(1).string_value (); | |
1295 | |
1296 if (!error_state) | |
1297 { | |
1298 const curl_handle curl = handles.contents (handle); | |
1299 | |
1300 if (curl.is_valid ()) | |
1301 curl.del (file); | |
1302 else | |
1303 error ("__ftp_delete__: invalid ftp handle"); | |
1304 } | |
1305 } | |
1306 #else | |
1307 error ("__ftp_delete__: not available in this version of Octave"); | |
1308 #endif | |
1309 | |
1310 return octave_value (); | |
1311 } | |
1312 | |
1313 DEFUN_DLD (__ftp_rmdir__, args, , | |
1314 "-*- texinfo -*-\n\ | |
1315 @deftypefn {Loadable Function} {} __ftp_rmdir__ (@var{handle}, @var{path})\n\ | |
1316 Undocumented internal function\n\ | |
1317 @end deftypefn") | |
1318 { | |
1319 #ifdef HAVE_CURL | |
1320 int nargin = args.length (); | |
1321 | |
1322 if (nargin != 2) | |
1323 error ("incorrect number of arguments"); | |
1324 else | |
1325 { | |
1326 std::string handle = args(0).string_value (); | |
1327 std::string dir = args(1).string_value (); | |
1328 | |
1329 if (!error_state) | |
1330 { | |
1331 const curl_handle curl = handles.contents (handle); | |
1332 | |
1333 if (curl.is_valid ()) | |
1334 curl.rmdir (dir); | |
1335 else | |
1336 error ("__ftp_rmdir__: invalid ftp handle"); | |
1337 } | |
1338 } | |
1339 #else | |
1340 error ("__ftp_rmdir__: not available in this version of Octave"); | |
1341 #endif | |
1342 | |
1343 return octave_value (); | |
1344 } | |
1345 | |
1346 DEFUN_DLD (__ftp_mkdir__, args, , | |
1347 "-*- texinfo -*-\n\ | |
1348 @deftypefn {Loadable Function} {} __ftp_mkdir__ (@var{handle}, @var{path})\n\ | |
1349 Undocumented internal function\n\ | |
1350 @end deftypefn") | |
1351 { | |
1352 #ifdef HAVE_CURL | |
1353 int nargin = args.length (); | |
1354 | |
1355 if (nargin != 2) | |
1356 error ("incorrect number of arguments"); | |
1357 else | |
1358 { | |
1359 std::string handle = args(0).string_value (); | |
1360 std::string dir = args(1).string_value (); | |
1361 | |
1362 if (!error_state) | |
1363 { | |
1364 const curl_handle curl = handles.contents (handle); | |
1365 | |
1366 if (curl.is_valid ()) | |
1367 curl.mkdir (dir); | |
1368 else | |
1369 error ("__ftp_mkdir__: invalid ftp handle"); | |
1370 } | |
1371 } | |
1372 #else | |
1373 error ("__ftp_mkdir__: not available in this version of Octave"); | |
1374 #endif | |
1375 | |
1376 return octave_value (); | |
1377 } | |
1378 | |
1379 DEFUN_DLD (__ftp_rename__, args, , | |
1380 "-*- texinfo -*-\n\ | |
1381 @deftypefn {Loadable Function} {} __ftp_rename__ (@var{handle}, @var{path})\n\ | |
1382 Undocumented internal function\n\ | |
1383 @end deftypefn") | |
1384 { | |
1385 #ifdef HAVE_CURL | |
1386 int nargin = args.length (); | |
1387 | |
1388 if (nargin != 3) | |
1389 error ("incorrect number of arguments"); | |
1390 else | |
1391 { | |
1392 std::string handle = args(0).string_value (); | |
1393 std::string oldname = args(1).string_value (); | |
1394 std::string newname = args(2).string_value (); | |
1395 | |
1396 if (!error_state) | |
1397 { | |
1398 const curl_handle curl = handles.contents (handle); | |
1399 | |
1400 if (curl.is_valid ()) | |
1401 curl.rename (oldname, newname); | |
1402 else | |
1403 error ("__ftp_rename__: invalid ftp handle"); | |
1404 } | |
1405 } | |
1406 #else | |
1407 error ("__ftp_rename__: not available in this version of Octave"); | |
1408 #endif | |
1409 | |
1410 return octave_value (); | |
1411 } | |
1412 | |
9905
84a7c11ff928
Correctly compile even when libcurl is not present according to configure
Rik <rdrider0-list@yahoo.com>
parents:
9885
diff
changeset
|
1413 #ifdef HAVE_CURL |
9880 | 1414 static string_vector |
1415 mput_directory (const curl_handle& curl, const std::string& base, | |
1416 const std::string& dir) | |
1417 { | |
1418 string_vector retval; | |
1419 | |
1420 if (! curl.mkdir (dir, false)) | |
1421 warning ("__ftp_mput__: can not create the remote directory ""%s""", | |
1422 (base.length() == 0 ? dir : base + | |
1423 file_ops::dir_sep_str () + dir).c_str ()); | |
1424 | |
1425 curl.cwd (dir); | |
1426 | |
1427 if (! error_state) | |
1428 { | |
10066
2cd940306a06
make unwind_protect frames local
Jaroslav Hajek <highegg@gmail.com>
parents:
9918
diff
changeset
|
1429 unwind_protect_safe frame; |
9880 | 1430 |
10066
2cd940306a06
make unwind_protect frames local
Jaroslav Hajek <highegg@gmail.com>
parents:
9918
diff
changeset
|
1431 frame.add_fcn (reset_path, curl); |
9880 | 1432 |
1433 std::string realdir = base.length() == 0 ? dir : base + | |
1434 file_ops::dir_sep_str () + dir; | |
1435 | |
1436 dir_entry dirlist (realdir); | |
1437 | |
1438 if (dirlist) | |
1439 { | |
1440 string_vector files = dirlist.read (); | |
1441 | |
1442 for (octave_idx_type i = 0; i < files.length (); i++) | |
1443 { | |
1444 std::string file = files (i); | |
1445 | |
1446 if (file == "." || file == "..") | |
1447 continue; | |
1448 | |
1449 std::string realfile = realdir + file_ops::dir_sep_str () + file; | |
1450 file_stat fs (realfile); | |
1451 | |
1452 if (! fs.exists ()) | |
1453 { | |
1454 error ("__ftp__mput: file ""%s"" does not exist", | |
1455 realfile.c_str ()); | |
1456 break; | |
1457 } | |
1458 | |
1459 if (fs.is_dir ()) | |
1460 { | |
1461 retval.append (mput_directory (curl, realdir, file)); | |
1462 | |
1463 if (error_state) | |
1464 break; | |
1465 } | |
1466 else | |
1467 { | |
1468 // FIXME Does ascii mode need to be flagged here? | |
1469 std::ifstream ifile (realfile.c_str(), std::ios::in | | |
1470 std::ios::binary); | |
1471 | |
1472 if (! ifile.is_open ()) | |
1473 { | |
1474 error ("__ftp_mput__: unable to open file ""%s""", | |
1475 realfile.c_str ()); | |
1476 break; | |
1477 } | |
1478 | |
1479 curl.put (file, ifile); | |
1480 | |
1481 ifile.close (); | |
1482 | |
1483 if (error_state) | |
1484 break; | |
1485 | |
1486 retval.append (realfile); | |
1487 } | |
1488 } | |
1489 } | |
1490 else | |
1491 error ("__ftp_mput__: can not read the directory ""%s""", | |
1492 realdir.c_str()); | |
1493 } | |
1494 | |
1495 return retval; | |
1496 } | |
9905
84a7c11ff928
Correctly compile even when libcurl is not present according to configure
Rik <rdrider0-list@yahoo.com>
parents:
9885
diff
changeset
|
1497 #endif |
9880 | 1498 |
1499 DEFUN_DLD (__ftp_mput__, args, nargout, | |
1500 "-*- texinfo -*-\n\ | |
1501 @deftypefn {Loadable Function} {} __ftp_mput__ (@var{handle}, @var{files})\n\ | |
1502 Undocumented internal function\n\ | |
1503 @end deftypefn") | |
1504 { | |
1505 string_vector retval; | |
1506 | |
1507 #ifdef HAVE_CURL | |
1508 int nargin = args.length (); | |
1509 | |
1510 if (nargin != 2) | |
1511 error ("incorrect number of arguments"); | |
1512 else | |
1513 { | |
1514 std::string handle = args(0).string_value (); | |
1515 std::string pat = args(1).string_value (); | |
1516 | |
1517 if (!error_state) | |
1518 { | |
1519 const curl_handle curl = handles.contents (handle); | |
1520 | |
1521 if (curl.is_valid ()) | |
1522 { | |
1523 glob_match pattern (file_ops::tilde_expand (pat)); | |
1524 string_vector files = pattern.glob (); | |
1525 | |
1526 for (octave_idx_type i = 0; i < files.length (); i++) | |
1527 { | |
1528 std::string file = files (i); | |
1529 | |
1530 file_stat fs (file); | |
1531 | |
1532 if (! fs.exists ()) | |
1533 { | |
1534 error ("__ftp__mput: file does not exist"); | |
1535 break; | |
1536 } | |
1537 | |
1538 if (fs.is_dir ()) | |
1539 { | |
1540 retval.append (mput_directory (curl, "", file)); | |
1541 if (error_state) | |
1542 break; | |
1543 } | |
1544 else | |
1545 { | |
1546 // FIXME Does ascii mode need to be flagged here? | |
1547 std::ifstream ifile (file.c_str(), std::ios::in | | |
1548 std::ios::binary); | |
1549 | |
1550 if (! ifile.is_open ()) | |
1551 { | |
1552 error ("__ftp_mput__: unable to open file"); | |
1553 break; | |
1554 } | |
1555 | |
1556 curl.put (file, ifile); | |
1557 | |
1558 ifile.close (); | |
1559 | |
1560 if (error_state) | |
1561 break; | |
1562 | |
1563 retval.append (file); | |
1564 } | |
1565 } | |
1566 } | |
1567 else | |
1568 error ("__ftp_mput__: invalid ftp handle"); | |
1569 } | |
1570 } | |
1571 #else | |
1572 error ("__ftp_mput__: not available in this version of Octave"); | |
1573 #endif | |
1574 | |
1575 return (nargout > 0 ? octave_value (retval) : octave_value ()); | |
1576 } | |
1577 | |
1578 #ifdef HAVE_CURL | |
1579 static void | |
1580 getallfiles (const curl_handle& curl, const std::string& dir, | |
1581 const std::string& target) | |
1582 { | |
1583 std::string sep = file_ops::dir_sep_str (); | |
1584 file_stat fs (dir); | |
1585 | |
1586 if (!fs || !fs.is_dir ()) | |
1587 { | |
1588 std::string msg; | |
1589 int status = file_ops::mkdir (dir, 0777, msg); | |
1590 | |
1591 if (status < 0) | |
1592 error ("__ftp_mget__: can't create directory %s%s%s. %s", | |
1593 target.c_str(), sep.c_str(), dir.c_str(), msg.c_str()); | |
1594 } | |
1595 | |
1596 if (! error_state) | |
1597 { | |
1598 curl.cwd (dir); | |
1599 | |
1600 if (! error_state) | |
1601 { | |
10066
2cd940306a06
make unwind_protect frames local
Jaroslav Hajek <highegg@gmail.com>
parents:
9918
diff
changeset
|
1602 unwind_protect_safe frame; |
9880 | 1603 |
10066
2cd940306a06
make unwind_protect frames local
Jaroslav Hajek <highegg@gmail.com>
parents:
9918
diff
changeset
|
1604 frame.add_fcn (reset_path, curl); |
9880 | 1605 |
10066
2cd940306a06
make unwind_protect frames local
Jaroslav Hajek <highegg@gmail.com>
parents:
9918
diff
changeset
|
1606 string_vector sv = curl.list (); |
9880 | 1607 |
1608 for (octave_idx_type i = 0; i < sv.length (); i++) | |
1609 { | |
1610 time_t ftime; | |
1611 bool fisdir; | |
1612 double fsize; | |
1613 | |
1614 curl.get_fileinfo (sv(i), fsize, ftime, fisdir); | |
1615 | |
1616 if (fisdir) | |
1617 getallfiles (curl, sv(i), target + dir + sep); | |
1618 else | |
1619 { | |
1620 std::string realfile = target + dir + sep + sv(i); | |
1621 std::ofstream ofile (realfile.c_str(), | |
1622 std::ios::out | | |
1623 std::ios::binary); | |
1624 | |
1625 if (! ofile.is_open ()) | |
1626 { | |
1627 error ("__ftp_mget__: unable to open file"); | |
1628 break; | |
1629 } | |
1630 | |
10066
2cd940306a06
make unwind_protect frames local
Jaroslav Hajek <highegg@gmail.com>
parents:
9918
diff
changeset
|
1631 unwind_protect_safe frame2; |
9880 | 1632 |
10066
2cd940306a06
make unwind_protect frames local
Jaroslav Hajek <highegg@gmail.com>
parents:
9918
diff
changeset
|
1633 frame2.add_fcn (delete_file, realfile); |
9880 | 1634 |
1635 curl.get (sv(i), ofile); | |
1636 | |
1637 ofile.close (); | |
1638 | |
1639 if (!error_state) | |
10066
2cd940306a06
make unwind_protect frames local
Jaroslav Hajek <highegg@gmail.com>
parents:
9918
diff
changeset
|
1640 frame2.discard (); |
9880 | 1641 else |
10066
2cd940306a06
make unwind_protect frames local
Jaroslav Hajek <highegg@gmail.com>
parents:
9918
diff
changeset
|
1642 frame2.run (); |
9880 | 1643 } |
1644 | |
1645 if (error_state) | |
1646 break; | |
1647 } | |
1648 } | |
1649 } | |
1650 } | |
1651 #endif | |
1652 | |
1653 DEFUN_DLD (__ftp_mget__, args, , | |
1654 "-*- texinfo -*-\n\ | |
1655 @deftypefn {Loadable Function} {} __ftp_mget__ (@var{handle}, @var{files})\n\ | |
1656 Undocumented internal function\n\ | |
1657 @end deftypefn") | |
1658 { | |
1659 #ifdef HAVE_CURL | |
1660 int nargin = args.length (); | |
1661 | |
1662 if (nargin != 2 && nargin != 3) | |
1663 error ("incorrect number of arguments"); | |
1664 else | |
1665 { | |
1666 std::string handle = args(0).string_value (); | |
1667 std::string file = args(1).string_value (); | |
1668 std::string target; | |
1669 | |
1670 if (nargin == 3) | |
1671 target = args(2).string_value () + file_ops::dir_sep_str (); | |
1672 | |
1673 if (! error_state) | |
1674 { | |
1675 const curl_handle curl = handles.contents (handle); | |
1676 | |
1677 if (curl.is_valid ()) | |
1678 { | |
1679 string_vector sv = curl.list (); | |
1680 octave_idx_type n = 0; | |
1681 glob_match pattern (file); | |
1682 | |
1683 for (octave_idx_type i = 0; i < sv.length (); i++) | |
1684 { | |
1685 if (pattern.match (sv(i))) | |
1686 { | |
1687 n++; | |
1688 | |
1689 time_t ftime; | |
1690 bool fisdir; | |
1691 double fsize; | |
1692 | |
1693 curl.get_fileinfo (sv(i), fsize, ftime, fisdir); | |
1694 | |
1695 if (fisdir) | |
1696 getallfiles (curl, sv(i), target); | |
1697 else | |
1698 { | |
1699 std::ofstream ofile ((target + sv(i)).c_str(), | |
1700 std::ios::out | | |
1701 std::ios::binary); | |
1702 | |
1703 if (! ofile.is_open ()) | |
1704 { | |
1705 error ("__ftp_mget__: unable to open file"); | |
1706 break; | |
1707 } | |
1708 | |
10066
2cd940306a06
make unwind_protect frames local
Jaroslav Hajek <highegg@gmail.com>
parents:
9918
diff
changeset
|
1709 unwind_protect_safe frame; |
9880 | 1710 |
10066
2cd940306a06
make unwind_protect frames local
Jaroslav Hajek <highegg@gmail.com>
parents:
9918
diff
changeset
|
1711 frame.add_fcn (delete_file, target + sv(i)); |
9880 | 1712 |
1713 curl.get (sv(i), ofile); | |
1714 | |
1715 ofile.close (); | |
1716 | |
1717 if (!error_state) | |
10066
2cd940306a06
make unwind_protect frames local
Jaroslav Hajek <highegg@gmail.com>
parents:
9918
diff
changeset
|
1718 frame.discard (); |
9880 | 1719 else |
10066
2cd940306a06
make unwind_protect frames local
Jaroslav Hajek <highegg@gmail.com>
parents:
9918
diff
changeset
|
1720 frame.run (); |
9880 | 1721 } |
1722 | |
1723 if (error_state) | |
1724 break; | |
1725 } | |
1726 } | |
1727 if (n == 0) | |
1728 error ("__ftp_mget__: file not found"); | |
1729 } | |
1730 } | |
1731 } | |
1732 #else | |
1733 error ("__ftp_mget__: not available in this version of Octave"); | |
1734 #endif | |
1735 | |
1736 return octave_value (); | |
1737 } |