Mercurial > hg > octave-jordi
comparison libinterp/corefcn/urlwrite.cc @ 17555:0946b0e06544
move url_transfer classes to liboctave
* liboctave/util/url-transfer.h, liboctave/util/url-transfer.cc:
New files, extracted from libinterp/dldfcn/urlwrite.cc.
* libinterp/corefcn/urlwrite.cc: Move here from
libinterp/dldfcn/urlwrite.cc.
* libinterp/corefcn/module.mk, libinterp/dldfcn/module-files,
liboctave/link-deps.mk liboctave/util/module.mk: Update for new and
renamed files.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 03 Oct 2013 15:52:49 -0400 |
parents | libinterp/dldfcn/urlwrite.cc@f0d21e7d4653 |
children | 9e8a9f043944 |
comparison
equal
deleted
inserted
replaced
17554:f0d21e7d4653 | 17555:0946b0e06544 |
---|---|
1 // urlwrite and urlread, a curl front-end for octave | |
2 /* | |
3 | |
4 Copyright (C) 2006-2012 Alexander Barth | |
5 Copyright (C) 2009 David Bateman | |
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 | |
11 Free Software Foundation; either version 3 of the License, or (at your | |
12 option) any later version. | |
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 | |
20 along with Octave; see the file COPYING. If not, see | |
21 <http://www.gnu.org/licenses/>. | |
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> | |
35 #include <iostream> | |
36 | |
37 #include "dir-ops.h" | |
38 #include "file-ops.h" | |
39 #include "file-stat.h" | |
40 #include "oct-env.h" | |
41 #include "oct-handle.h" | |
42 #include "glob-match.h" | |
43 #include "singleton-cleanup.h" | |
44 #include "url-transfer.h" | |
45 | |
46 #include "defun.h" | |
47 #include "error.h" | |
48 #include "oct-obj.h" | |
49 #include "ov-cell.h" | |
50 #include "pager.h" | |
51 #include "oct-map.h" | |
52 #include "oct-refcount.h" | |
53 #include "unwind-prot.h" | |
54 | |
55 static void | |
56 delete_file (const std::string& file) | |
57 { | |
58 octave_unlink (file); | |
59 } | |
60 | |
61 typedef octave_handle curl_handle; | |
62 | |
63 class OCTINTERP_API ch_manager | |
64 { | |
65 protected: | |
66 | |
67 ch_manager (void) | |
68 : handle_map (), handle_free_list (), | |
69 next_handle (-1.0 - (rand () + 1.0) / (RAND_MAX + 2.0)) { } | |
70 | |
71 public: | |
72 | |
73 static void create_instance (void); | |
74 | |
75 static bool instance_ok (void) | |
76 { | |
77 bool retval = true; | |
78 | |
79 if (! instance) | |
80 create_instance (); | |
81 | |
82 if (! instance) | |
83 { | |
84 ::error ("unable to create ch_manager!"); | |
85 | |
86 retval = false; | |
87 } | |
88 | |
89 return retval; | |
90 } | |
91 | |
92 static void cleanup_instance (void) { delete instance; instance = 0; } | |
93 | |
94 static curl_handle get_handle (void) | |
95 { | |
96 return instance_ok () | |
97 ? instance->do_get_handle () : curl_handle (); | |
98 } | |
99 | |
100 static void free (const curl_handle& h) | |
101 { | |
102 if (instance_ok ()) | |
103 instance->do_free (h); | |
104 } | |
105 | |
106 static curl_handle lookup (double val) | |
107 { | |
108 return instance_ok () ? instance->do_lookup (val) : curl_handle (); | |
109 } | |
110 | |
111 static curl_handle lookup (const octave_value& val) | |
112 { | |
113 return val.is_real_scalar () | |
114 ? lookup (val.double_value ()) : curl_handle (); | |
115 } | |
116 | |
117 static url_transfer get_object (double val) | |
118 { | |
119 return get_object (lookup (val)); | |
120 } | |
121 | |
122 static url_transfer get_object (const octave_value& val) | |
123 { | |
124 return get_object (lookup (val)); | |
125 } | |
126 | |
127 static url_transfer get_object (const curl_handle& h) | |
128 { | |
129 return instance_ok () ? instance->do_get_object (h) : url_transfer (); | |
130 } | |
131 | |
132 static curl_handle make_curl_handle (const std::string& host, | |
133 const std::string& user, | |
134 const std::string& passwd) | |
135 { | |
136 return instance_ok () | |
137 ? instance->do_make_curl_handle (host, user, passwd) : curl_handle (); | |
138 } | |
139 | |
140 static Matrix handle_list (void) | |
141 { | |
142 return instance_ok () ? instance->do_handle_list () : Matrix (); | |
143 } | |
144 | |
145 private: | |
146 | |
147 static ch_manager *instance; | |
148 | |
149 typedef std::map<curl_handle, url_transfer>::iterator iterator; | |
150 typedef std::map<curl_handle, url_transfer>::const_iterator const_iterator; | |
151 | |
152 typedef std::set<curl_handle>::iterator free_list_iterator; | |
153 typedef std::set<curl_handle>::const_iterator const_free_list_iterator; | |
154 | |
155 // A map of handles to curl objects. | |
156 std::map<curl_handle, url_transfer> handle_map; | |
157 | |
158 // The available curl handles. | |
159 std::set<curl_handle> handle_free_list; | |
160 | |
161 // The next handle available if handle_free_list is empty. | |
162 double next_handle; | |
163 | |
164 curl_handle do_get_handle (void); | |
165 | |
166 void do_free (const curl_handle& h); | |
167 | |
168 curl_handle do_lookup (double val) | |
169 { | |
170 iterator p = (xisnan (val) ? handle_map.end () : handle_map.find (val)); | |
171 | |
172 return (p != handle_map.end ()) ? p->first : curl_handle (); | |
173 } | |
174 | |
175 url_transfer do_get_object (const curl_handle& h) | |
176 { | |
177 iterator p = (h.ok () ? handle_map.find (h) : handle_map.end ()); | |
178 | |
179 return (p != handle_map.end ()) ? p->second : url_transfer (); | |
180 } | |
181 | |
182 curl_handle do_make_curl_handle (const std::string& host, | |
183 const std::string& user, | |
184 const std::string& passwd) | |
185 { | |
186 curl_handle h = get_handle (); | |
187 | |
188 url_transfer obj (host, user, passwd, octave_stdout); | |
189 | |
190 if (! error_state) | |
191 handle_map[h] = obj; | |
192 else | |
193 h = curl_handle (); | |
194 | |
195 return h; | |
196 } | |
197 | |
198 Matrix do_handle_list (void) | |
199 { | |
200 Matrix retval (1, handle_map.size ()); | |
201 | |
202 octave_idx_type i = 0; | |
203 for (const_iterator p = handle_map.begin (); p != handle_map.end (); p++) | |
204 { | |
205 curl_handle h = p->first; | |
206 | |
207 retval(i++) = h.value (); | |
208 } | |
209 | |
210 return retval; | |
211 } | |
212 }; | |
213 | |
214 void | |
215 ch_manager::create_instance (void) | |
216 { | |
217 instance = new ch_manager (); | |
218 | |
219 if (instance) | |
220 singleton_cleanup_list::add (cleanup_instance); | |
221 } | |
222 | |
223 static double | |
224 make_handle_fraction (void) | |
225 { | |
226 static double maxrand = RAND_MAX + 2.0; | |
227 | |
228 return (rand () + 1.0) / maxrand; | |
229 } | |
230 | |
231 curl_handle | |
232 ch_manager::do_get_handle (void) | |
233 { | |
234 curl_handle retval; | |
235 | |
236 // Curl handles are negative integers plus some random fractional | |
237 // part. To avoid running out of integers, we recycle the integer | |
238 // part but tack on a new random part each time. | |
239 | |
240 free_list_iterator p = handle_free_list.begin (); | |
241 | |
242 if (p != handle_free_list.end ()) | |
243 { | |
244 retval = *p; | |
245 handle_free_list.erase (p); | |
246 } | |
247 else | |
248 { | |
249 retval = curl_handle (next_handle); | |
250 | |
251 next_handle = std::ceil (next_handle) - 1.0 - make_handle_fraction (); | |
252 } | |
253 | |
254 return retval; | |
255 } | |
256 | |
257 void | |
258 ch_manager::do_free (const curl_handle& h) | |
259 { | |
260 if (h.ok ()) | |
261 { | |
262 iterator p = handle_map.find (h); | |
263 | |
264 if (p != handle_map.end ()) | |
265 { | |
266 // Curl handles are negative integers plus some random | |
267 // fractional part. To avoid running out of integers, we | |
268 // recycle the integer part but tack on a new random part | |
269 // each time. | |
270 | |
271 handle_map.erase (p); | |
272 | |
273 if (h.value () < 0) | |
274 handle_free_list.insert (std::ceil (h.value ()) - make_handle_fraction ()); | |
275 } | |
276 else | |
277 error ("ch_manager::free: invalid object %g", h.value ()); | |
278 } | |
279 } | |
280 | |
281 ch_manager *ch_manager::instance = 0; | |
282 | |
283 DEFUN (urlwrite, args, nargout, | |
284 "-*- texinfo -*-\n\ | |
285 @deftypefn {Loadable Function} {} urlwrite (@var{url}, @var{localfile})\n\ | |
286 @deftypefnx {Loadable Function} {@var{f} =} urlwrite (@var{url}, @var{localfile})\n\ | |
287 @deftypefnx {Loadable Function} {[@var{f}, @var{success}] =} urlwrite (@var{url}, @var{localfile})\n\ | |
288 @deftypefnx {Loadable Function} {[@var{f}, @var{success}, @var{message}] =} urlwrite (@var{url}, @var{localfile})\n\ | |
289 Download a remote file specified by its @var{url} and save it as\n\ | |
290 @var{localfile}. For example:\n\ | |
291 \n\ | |
292 @example\n\ | |
293 @group\n\ | |
294 urlwrite (\"ftp://ftp.octave.org/pub/octave/README\",\n\ | |
295 \"README.txt\");\n\ | |
296 @end group\n\ | |
297 @end example\n\ | |
298 \n\ | |
299 The full path of the downloaded file is returned in @var{f}. The\n\ | |
300 variable @var{success} is 1 if the download was successful,\n\ | |
301 otherwise it is 0 in which case @var{message} contains an error\n\ | |
302 message. If no output argument is specified and an error occurs,\n\ | |
303 then the error is signaled through Octave's error handling mechanism.\n\ | |
304 \n\ | |
305 This function uses libcurl. Curl supports, among others, the HTTP,\n\ | |
306 FTP and FILE protocols. Username and password may be specified in\n\ | |
307 the URL, for example:\n\ | |
308 \n\ | |
309 @example\n\ | |
310 @group\n\ | |
311 urlwrite (\"http://username:password@@example.com/file.txt\",\n\ | |
312 \"file.txt\");\n\ | |
313 @end group\n\ | |
314 @end example\n\ | |
315 \n\ | |
316 GET and POST requests can be specified by @var{method} and @var{param}.\n\ | |
317 The parameter @var{method} is either @samp{get} or @samp{post}\n\ | |
318 and @var{param} is a cell array of parameter and value pairs.\n\ | |
319 For example:\n\ | |
320 \n\ | |
321 @example\n\ | |
322 @group\n\ | |
323 urlwrite (\"http://www.google.com/search\", \"search.html\",\n\ | |
324 \"get\", @{\"query\", \"octave\"@});\n\ | |
325 @end group\n\ | |
326 @end example\n\ | |
327 @seealso{urlread}\n\ | |
328 @end deftypefn") | |
329 { | |
330 octave_value_list retval; | |
331 | |
332 int nargin = args.length (); | |
333 | |
334 // verify arguments | |
335 if (nargin != 2 && nargin != 4) | |
336 { | |
337 print_usage (); | |
338 return retval; | |
339 } | |
340 | |
341 std::string url = args(0).string_value (); | |
342 | |
343 if (error_state) | |
344 { | |
345 error ("urlwrite: URL must be a character string"); | |
346 return retval; | |
347 } | |
348 | |
349 // name to store the file if download is succesful | |
350 std::string filename = args(1).string_value (); | |
351 | |
352 if (error_state) | |
353 { | |
354 error ("urlwrite: LOCALFILE must be a character string"); | |
355 return retval; | |
356 } | |
357 | |
358 std::string method; | |
359 Array<std::string> param; | |
360 | |
361 if (nargin == 4) | |
362 { | |
363 method = args(2).string_value (); | |
364 | |
365 if (error_state) | |
366 { | |
367 error ("urlwrite: METHOD must be \"get\" or \"post\""); | |
368 return retval; | |
369 } | |
370 | |
371 if (method != "get" && method != "post") | |
372 { | |
373 error ("urlwrite: METHOD must be \"get\" or \"post\""); | |
374 return retval; | |
375 } | |
376 | |
377 param = args(3).cellstr_value (); | |
378 | |
379 if (error_state) | |
380 { | |
381 error ("urlwrite: parameters (PARAM) for get and post requests must be given as a cell array of character strings"); | |
382 return retval; | |
383 } | |
384 | |
385 | |
386 if (param.numel () % 2 == 1 ) | |
387 { | |
388 error ("urlwrite: number of elements in PARAM must be even"); | |
389 return retval; | |
390 } | |
391 } | |
392 | |
393 // The file should only be deleted if it doesn't initially exist, we | |
394 // create it, and the download fails. We use unwind_protect to do | |
395 // it so that the deletion happens no matter how we exit the function. | |
396 | |
397 file_stat fs (filename); | |
398 | |
399 std::ofstream ofile (filename.c_str (), std::ios::out | std::ios::binary); | |
400 | |
401 if (! ofile.is_open ()) | |
402 { | |
403 error ("urlwrite: unable to open file"); | |
404 return retval; | |
405 } | |
406 | |
407 unwind_protect_safe frame; | |
408 | |
409 frame.add_fcn (delete_file, filename); | |
410 | |
411 url_transfer curl = url_transfer (url, method, param, ofile); | |
412 | |
413 ofile.close (); | |
414 | |
415 if (curl.good ()) | |
416 frame.discard (); | |
417 | |
418 if (nargout > 0) | |
419 { | |
420 if (curl.good ()) | |
421 { | |
422 retval(2) = std::string (); | |
423 retval(1) = true; | |
424 retval(0) = octave_env::make_absolute (filename); | |
425 } | |
426 else | |
427 { | |
428 retval(2) = curl.lasterror (); | |
429 retval(1) = false; | |
430 retval(0) = std::string (); | |
431 } | |
432 } | |
433 | |
434 if (nargout < 2 && ! curl.good ()) | |
435 error ("urlwrite: %s", curl.lasterror ().c_str ()); | |
436 | |
437 return retval; | |
438 } | |
439 | |
440 DEFUN (urlread, args, nargout, | |
441 "-*- texinfo -*-\n\ | |
442 @deftypefn {Loadable Function} {@var{s} =} urlread (@var{url})\n\ | |
443 @deftypefnx {Loadable Function} {[@var{s}, @var{success}] =} urlread (@var{url})\n\ | |
444 @deftypefnx {Loadable Function} {[@var{s}, @var{success}, @var{message}] =} urlread (@var{url})\n\ | |
445 @deftypefnx {Loadable Function} {[@dots{}] =} urlread (@var{url}, @var{method}, @var{param})\n\ | |
446 Download a remote file specified by its @var{url} and return its content\n\ | |
447 in string @var{s}. For example:\n\ | |
448 \n\ | |
449 @example\n\ | |
450 s = urlread (\"ftp://ftp.octave.org/pub/octave/README\");\n\ | |
451 @end example\n\ | |
452 \n\ | |
453 The variable @var{success} is 1 if the download was successful,\n\ | |
454 otherwise it is 0 in which case @var{message} contains an error\n\ | |
455 message. If no output argument is specified and an error occurs,\n\ | |
456 then the error is signaled through Octave's error handling mechanism.\n\ | |
457 \n\ | |
458 This function uses libcurl. Curl supports, among others, the HTTP,\n\ | |
459 FTP and FILE protocols. Username and password may be specified in the\n\ | |
460 URL@. For example:\n\ | |
461 \n\ | |
462 @example\n\ | |
463 s = urlread (\"http://user:password@@example.com/file.txt\");\n\ | |
464 @end example\n\ | |
465 \n\ | |
466 GET and POST requests can be specified by @var{method} and @var{param}.\n\ | |
467 The parameter @var{method} is either @samp{get} or @samp{post}\n\ | |
468 and @var{param} is a cell array of parameter and value pairs.\n\ | |
469 For example:\n\ | |
470 \n\ | |
471 @example\n\ | |
472 @group\n\ | |
473 s = urlread (\"http://www.google.com/search\", \"get\",\n\ | |
474 @{\"query\", \"octave\"@});\n\ | |
475 @end group\n\ | |
476 @end example\n\ | |
477 @seealso{urlwrite}\n\ | |
478 @end deftypefn") | |
479 { | |
480 // Octave's return value | |
481 octave_value_list retval; | |
482 | |
483 int nargin = args.length (); | |
484 | |
485 // verify arguments | |
486 if (nargin != 1 && nargin != 3) | |
487 { | |
488 print_usage (); | |
489 return retval; | |
490 } | |
491 | |
492 std::string url = args(0).string_value (); | |
493 | |
494 if (error_state) | |
495 { | |
496 error ("urlread: URL must be a character string"); | |
497 return retval; | |
498 } | |
499 | |
500 std::string method; | |
501 Array<std::string> param; | |
502 | |
503 if (nargin == 3) | |
504 { | |
505 method = args(1).string_value (); | |
506 | |
507 if (error_state) | |
508 { | |
509 error ("urlread: METHOD must be \"get\" or \"post\""); | |
510 return retval; | |
511 } | |
512 | |
513 if (method != "get" && method != "post") | |
514 { | |
515 error ("urlread: METHOD must be \"get\" or \"post\""); | |
516 return retval; | |
517 } | |
518 | |
519 param = args(2).cellstr_value (); | |
520 | |
521 if (error_state) | |
522 { | |
523 error ("urlread: parameters (PARAM) for get and post requests must be given as a cell array of character strings"); | |
524 return retval; | |
525 } | |
526 | |
527 if (param.numel () % 2 == 1 ) | |
528 { | |
529 error ("urlread: number of elements in PARAM must be even"); | |
530 return retval; | |
531 } | |
532 } | |
533 | |
534 std::ostringstream buf; | |
535 | |
536 url_transfer curl = url_transfer (url, method, param, buf); | |
537 | |
538 if (curl.good ()) | |
539 { | |
540 if (nargout > 0) | |
541 { | |
542 // Return empty string if no error occured. | |
543 retval(2) = curl.good () ? "" : curl.lasterror (); | |
544 retval(1) = curl.good (); | |
545 retval(0) = buf.str (); | |
546 } | |
547 } | |
548 | |
549 if (nargout < 2 && ! curl.good ()) | |
550 error ("urlread: %s", curl.lasterror().c_str()); | |
551 | |
552 return retval; | |
553 } | |
554 | |
555 DEFUN (__ftp__, args, , | |
556 "-*- texinfo -*-\n\ | |
557 @deftypefn {Loadable Function} {@var{handle} =} __ftp__ (@var{host})\n\ | |
558 @deftypefnx {Loadable Function} {@var{handle} =} __ftp__ (@var{host}, @var{username}, @var{password})\n\ | |
559 Undocumented internal function\n\ | |
560 @end deftypefn") | |
561 { | |
562 octave_value retval; | |
563 | |
564 int nargin = args.length (); | |
565 std::string host; | |
566 std::string user = "anonymous"; | |
567 std::string passwd = ""; | |
568 | |
569 if (nargin < 1 || nargin > 3) | |
570 { | |
571 print_usage (); | |
572 return retval; | |
573 } | |
574 else | |
575 { | |
576 host = args(0).string_value (); | |
577 | |
578 if (nargin > 1) | |
579 user = args(1).string_value (); | |
580 | |
581 if (nargin > 2) | |
582 passwd = args(2).string_value (); | |
583 | |
584 if (! error_state) | |
585 { | |
586 curl_handle ch | |
587 = ch_manager::make_curl_handle (host, user, passwd, octave_stdout); | |
588 | |
589 if (! error_state) | |
590 retval = ch.value (); | |
591 } | |
592 } | |
593 | |
594 return retval; | |
595 } | |
596 | |
597 DEFUN (__ftp_pwd__, args, , | |
598 "-*- texinfo -*-\n\ | |
599 @deftypefn {Loadable Function} {} __ftp_pwd__ (@var{handle})\n\ | |
600 Undocumented internal function\n\ | |
601 @end deftypefn") | |
602 { | |
603 octave_value retval; | |
604 | |
605 int nargin = args.length (); | |
606 | |
607 if (nargin != 1) | |
608 error ("__ftp_pwd__: incorrect number of arguments"); | |
609 else | |
610 { | |
611 url_transfer curl = ch_manager::get_object (args(0)); | |
612 | |
613 if (error_state) | |
614 return retval; | |
615 | |
616 if (curl.is_valid ()) | |
617 retval = curl.pwd (); | |
618 else | |
619 error ("__ftp_pwd__: invalid ftp handle"); | |
620 } | |
621 | |
622 return retval; | |
623 } | |
624 | |
625 DEFUN (__ftp_cwd__, args, , | |
626 "-*- texinfo -*-\n\ | |
627 @deftypefn {Loadable Function} {} __ftp_cwd__ (@var{handle}, @var{path})\n\ | |
628 Undocumented internal function\n\ | |
629 @end deftypefn") | |
630 { | |
631 octave_value retval; | |
632 | |
633 int nargin = args.length (); | |
634 | |
635 if (nargin != 1 && nargin != 2) | |
636 error ("__ftp_cwd__: incorrect number of arguments"); | |
637 else | |
638 { | |
639 url_transfer curl = ch_manager::get_object (args(0)); | |
640 | |
641 if (error_state) | |
642 return retval; | |
643 | |
644 if (curl.is_valid ()) | |
645 { | |
646 std::string path = ""; | |
647 | |
648 if (nargin > 1) | |
649 path = args(1).string_value (); | |
650 | |
651 if (! error_state) | |
652 curl.cwd (path); | |
653 else | |
654 error ("__ftp_cwd__: expecting path as second argument"); | |
655 } | |
656 else | |
657 error ("__ftp_cwd__: invalid ftp handle"); | |
658 } | |
659 | |
660 return retval; | |
661 } | |
662 | |
663 DEFUN (__ftp_dir__, args, nargout, | |
664 "-*- texinfo -*-\n\ | |
665 @deftypefn {Loadable Function} {} __ftp_dir__ (@var{handle})\n\ | |
666 Undocumented internal function\n\ | |
667 @end deftypefn") | |
668 { | |
669 octave_value retval; | |
670 | |
671 int nargin = args.length (); | |
672 | |
673 if (nargin != 1) | |
674 error ("__ftp_dir__: incorrect number of arguments"); | |
675 else | |
676 { | |
677 url_transfer curl = ch_manager::get_object (args(0)); | |
678 | |
679 if (error_state) | |
680 return retval; | |
681 | |
682 if (curl.is_valid ()) | |
683 { | |
684 if (nargout == 0) | |
685 curl.dir (); | |
686 else | |
687 { | |
688 string_vector sv = curl.list (); | |
689 octave_idx_type n = sv.length (); | |
690 | |
691 if (n == 0) | |
692 { | |
693 string_vector flds (5); | |
694 | |
695 flds(0) = "name"; | |
696 flds(1) = "date"; | |
697 flds(2) = "bytes"; | |
698 flds(3) = "isdir"; | |
699 flds(4) = "datenum"; | |
700 | |
701 retval = octave_map (flds); | |
702 } | |
703 else | |
704 { | |
705 octave_map st; | |
706 | |
707 Cell filectime (dim_vector (n, 1)); | |
708 Cell filesize (dim_vector (n, 1)); | |
709 Cell fileisdir (dim_vector (n, 1)); | |
710 Cell filedatenum (dim_vector (n, 1)); | |
711 | |
712 st.assign ("name", Cell (sv)); | |
713 | |
714 for (octave_idx_type i = 0; i < n; i++) | |
715 { | |
716 time_t ftime; | |
717 bool fisdir; | |
718 double fsize; | |
719 | |
720 curl.get_fileinfo (sv(i), fsize, ftime, fisdir); | |
721 | |
722 fileisdir (i) = fisdir; | |
723 filectime (i) = ctime (&ftime); | |
724 filesize (i) = fsize; | |
725 filedatenum (i) = double (ftime); | |
726 } | |
727 | |
728 st.assign ("date", filectime); | |
729 st.assign ("bytes", filesize); | |
730 st.assign ("isdir", fileisdir); | |
731 st.assign ("datenum", filedatenum); | |
732 | |
733 retval = st; | |
734 } | |
735 } | |
736 } | |
737 else | |
738 error ("__ftp_dir__: invalid ftp handle"); | |
739 } | |
740 | |
741 return retval; | |
742 } | |
743 | |
744 DEFUN (__ftp_ascii__, args, , | |
745 "-*- texinfo -*-\n\ | |
746 @deftypefn {Loadable Function} {} __ftp_ascii__ (@var{handle})\n\ | |
747 Undocumented internal function\n\ | |
748 @end deftypefn") | |
749 { | |
750 octave_value retval; | |
751 | |
752 int nargin = args.length (); | |
753 | |
754 if (nargin != 1) | |
755 error ("__ftp_ascii__: incorrect number of arguments"); | |
756 else | |
757 { | |
758 url_transfer curl = ch_manager::get_object (args(0)); | |
759 | |
760 if (error_state) | |
761 return retval; | |
762 | |
763 if (curl.is_valid ()) | |
764 curl.ascii (); | |
765 else | |
766 error ("__ftp_ascii__: invalid ftp handle"); | |
767 } | |
768 | |
769 return retval; | |
770 } | |
771 | |
772 DEFUN (__ftp_binary__, args, , | |
773 "-*- texinfo -*-\n\ | |
774 @deftypefn {Loadable Function} {} __ftp_binary__ (@var{handle})\n\ | |
775 Undocumented internal function\n\ | |
776 @end deftypefn") | |
777 { | |
778 octave_value retval; | |
779 | |
780 int nargin = args.length (); | |
781 | |
782 if (nargin != 1) | |
783 error ("__ftp_binary__: incorrect number of arguments"); | |
784 else | |
785 { | |
786 url_transfer curl = ch_manager::get_object (args(0)); | |
787 | |
788 if (error_state) | |
789 return retval; | |
790 | |
791 if (curl.is_valid ()) | |
792 curl.binary (); | |
793 else | |
794 error ("__ftp_binary__: invalid ftp handle"); | |
795 } | |
796 | |
797 return retval; | |
798 } | |
799 | |
800 DEFUN (__ftp_close__, args, , | |
801 "-*- texinfo -*-\n\ | |
802 @deftypefn {Loadable Function} {} __ftp_close__ (@var{handle})\n\ | |
803 Undocumented internal function\n\ | |
804 @end deftypefn") | |
805 { | |
806 octave_value retval; | |
807 | |
808 int nargin = args.length (); | |
809 | |
810 if (nargin != 1) | |
811 error ("__ftp_close__: incorrect number of arguments"); | |
812 else | |
813 { | |
814 curl_handle h = ch_manager::lookup (args(0)); | |
815 | |
816 if (error_state) | |
817 return retval; | |
818 | |
819 if (h.ok ()) | |
820 ch_manager::free (h); | |
821 else | |
822 error ("__ftp_close__: invalid ftp handle"); | |
823 } | |
824 | |
825 return retval; | |
826 } | |
827 | |
828 DEFUN (__ftp_mode__, args, , | |
829 "-*- texinfo -*-\n\ | |
830 @deftypefn {Loadable Function} {} __ftp_mode__ (@var{handle})\n\ | |
831 Undocumented internal function\n\ | |
832 @end deftypefn") | |
833 { | |
834 octave_value retval; | |
835 | |
836 int nargin = args.length (); | |
837 | |
838 if (nargin != 1) | |
839 error ("__ftp_mode__: incorrect number of arguments"); | |
840 else | |
841 { | |
842 url_transfer curl = ch_manager::get_object (args(0)); | |
843 | |
844 if (error_state) | |
845 return retval; | |
846 | |
847 if (curl.is_valid ()) | |
848 retval = (curl.is_ascii () ? "ascii" : "binary"); | |
849 else | |
850 error ("__ftp_binary__: invalid ftp handle"); | |
851 } | |
852 | |
853 return retval; | |
854 } | |
855 | |
856 DEFUN (__ftp_delete__, args, , | |
857 "-*- texinfo -*-\n\ | |
858 @deftypefn {Loadable Function} {} __ftp_delete__ (@var{handle}, @var{path})\n\ | |
859 Undocumented internal function\n\ | |
860 @end deftypefn") | |
861 { | |
862 octave_value retval; | |
863 | |
864 int nargin = args.length (); | |
865 | |
866 if (nargin != 2) | |
867 error ("__ftp_delete__: incorrect number of arguments"); | |
868 else | |
869 { | |
870 url_transfer curl = ch_manager::get_object (args(0)); | |
871 | |
872 if (error_state) | |
873 return retval; | |
874 | |
875 if (curl.is_valid ()) | |
876 { | |
877 std::string file = args(1).string_value (); | |
878 | |
879 if (! error_state) | |
880 curl.del (file); | |
881 else | |
882 error ("__ftp_delete__: expecting file name as second argument"); | |
883 } | |
884 else | |
885 error ("__ftp_delete__: invalid ftp handle"); | |
886 } | |
887 | |
888 return retval; | |
889 } | |
890 | |
891 DEFUN (__ftp_rmdir__, args, , | |
892 "-*- texinfo -*-\n\ | |
893 @deftypefn {Loadable Function} {} __ftp_rmdir__ (@var{handle}, @var{path})\n\ | |
894 Undocumented internal function\n\ | |
895 @end deftypefn") | |
896 { | |
897 octave_value retval; | |
898 | |
899 int nargin = args.length (); | |
900 | |
901 if (nargin != 2) | |
902 error ("__ftp_rmdir__: incorrect number of arguments"); | |
903 else | |
904 { | |
905 url_transfer curl = ch_manager::get_object (args(0)); | |
906 | |
907 if (error_state) | |
908 return retval; | |
909 | |
910 if (curl.is_valid ()) | |
911 { | |
912 std::string dir = args(1).string_value (); | |
913 | |
914 if (! error_state) | |
915 curl.rmdir (dir); | |
916 else | |
917 error ("__ftp_rmdir__: expecting directory name as second argument"); | |
918 } | |
919 else | |
920 error ("__ftp_rmdir__: invalid ftp handle"); | |
921 } | |
922 | |
923 return retval; | |
924 } | |
925 | |
926 DEFUN (__ftp_mkdir__, args, , | |
927 "-*- texinfo -*-\n\ | |
928 @deftypefn {Loadable Function} {} __ftp_mkdir__ (@var{handle}, @var{path})\n\ | |
929 Undocumented internal function\n\ | |
930 @end deftypefn") | |
931 { | |
932 octave_value retval; | |
933 | |
934 int nargin = args.length (); | |
935 | |
936 if (nargin != 2) | |
937 error ("__ftp_mkdir__: incorrect number of arguments"); | |
938 else | |
939 { | |
940 url_transfer curl = ch_manager::get_object (args(0)); | |
941 | |
942 if (error_state) | |
943 return retval; | |
944 | |
945 if (curl.is_valid ()) | |
946 { | |
947 std::string dir = args(1).string_value (); | |
948 | |
949 if (! error_state) | |
950 curl.mkdir (dir); | |
951 else | |
952 error ("__ftp_mkdir__: expecting directory name as second argument"); | |
953 } | |
954 else | |
955 error ("__ftp_mkdir__: invalid ftp handle"); | |
956 } | |
957 | |
958 return retval; | |
959 } | |
960 | |
961 DEFUN (__ftp_rename__, args, , | |
962 "-*- texinfo -*-\n\ | |
963 @deftypefn {Loadable Function} {} __ftp_rename__ (@var{handle}, @var{path})\n\ | |
964 Undocumented internal function\n\ | |
965 @end deftypefn") | |
966 { | |
967 octave_value retval; | |
968 | |
969 int nargin = args.length (); | |
970 | |
971 if (nargin != 3) | |
972 error ("__ftp_rename__: incorrect number of arguments"); | |
973 else | |
974 { | |
975 url_transfer curl = ch_manager::get_object (args(0)); | |
976 | |
977 if (error_state) | |
978 return retval; | |
979 | |
980 if (curl.is_valid ()) | |
981 { | |
982 std::string oldname = args(1).string_value (); | |
983 std::string newname = args(2).string_value (); | |
984 | |
985 if (! error_state) | |
986 curl.rename (oldname, newname); | |
987 else | |
988 error ("__ftp_rename__: expecting file names for second and third arguments"); | |
989 } | |
990 else | |
991 error ("__ftp_rename__: invalid ftp handle"); | |
992 } | |
993 | |
994 return retval; | |
995 } | |
996 | |
997 DEFUN (__ftp_mput__, args, nargout, | |
998 "-*- texinfo -*-\n\ | |
999 @deftypefn {Loadable Function} {} __ftp_mput__ (@var{handle}, @var{files})\n\ | |
1000 Undocumented internal function\n\ | |
1001 @end deftypefn") | |
1002 { | |
1003 octave_value retval; | |
1004 | |
1005 int nargin = args.length (); | |
1006 | |
1007 if (nargin != 2) | |
1008 error ("__ftp_mput__: incorrect number of arguments"); | |
1009 else | |
1010 { | |
1011 url_transfer curl = ch_manager::get_object (args(0)); | |
1012 | |
1013 if (error_state) | |
1014 return retval; | |
1015 | |
1016 if (curl.is_valid ()) | |
1017 { | |
1018 std::string pat = args(1).string_value (); | |
1019 | |
1020 if (! error_state) | |
1021 { | |
1022 string_vector file_list; | |
1023 | |
1024 glob_match pattern (file_ops::tilde_expand (pat)); | |
1025 string_vector files = pattern.glob (); | |
1026 | |
1027 for (octave_idx_type i = 0; i < files.length (); i++) | |
1028 { | |
1029 std::string file = files (i); | |
1030 | |
1031 file_stat fs (file); | |
1032 | |
1033 if (! fs.exists ()) | |
1034 { | |
1035 error ("__ftp__mput: file does not exist"); | |
1036 break; | |
1037 } | |
1038 | |
1039 if (fs.is_dir ()) | |
1040 { | |
1041 file_list.append (curl.mput_directory ("", file)); | |
1042 | |
1043 if (! curl.good ()) | |
1044 { | |
1045 error ("__ftp_mput__: %s", curl.lasterror().c_str()); | |
1046 break; | |
1047 } | |
1048 } | |
1049 else | |
1050 { | |
1051 // FIXME Does ascii mode need to be flagged here? | |
1052 std::ifstream ifile (file.c_str (), std::ios::in | | |
1053 std::ios::binary); | |
1054 | |
1055 if (! ifile.is_open ()) | |
1056 { | |
1057 error ("__ftp_mput__: unable to open file"); | |
1058 break; | |
1059 } | |
1060 | |
1061 curl.put (file, ifile); | |
1062 | |
1063 ifile.close (); | |
1064 | |
1065 if (! curl.good ()) | |
1066 { | |
1067 error ("__ftp_mput__: %s", curl.lasterror().c_str()); | |
1068 break; | |
1069 } | |
1070 | |
1071 file_list.append (file); | |
1072 } | |
1073 } | |
1074 | |
1075 if (nargout > 0) | |
1076 retval = file_list; | |
1077 } | |
1078 else | |
1079 error ("__ftp_mput__: expecting file name patter as second argument"); | |
1080 } | |
1081 else | |
1082 error ("__ftp_mput__: invalid ftp handle"); | |
1083 } | |
1084 | |
1085 return retval; | |
1086 } | |
1087 | |
1088 DEFUN (__ftp_mget__, args, , | |
1089 "-*- texinfo -*-\n\ | |
1090 @deftypefn {Loadable Function} {} __ftp_mget__ (@var{handle}, @var{files})\n\ | |
1091 Undocumented internal function\n\ | |
1092 @end deftypefn") | |
1093 { | |
1094 octave_value retval; | |
1095 | |
1096 int nargin = args.length (); | |
1097 | |
1098 if (nargin != 2 && nargin != 3) | |
1099 error ("__ftp_mget__: incorrect number of arguments"); | |
1100 else | |
1101 { | |
1102 url_transfer curl = ch_manager::get_object (args(0)); | |
1103 | |
1104 if (error_state) | |
1105 return retval; | |
1106 | |
1107 if (curl.is_valid ()) | |
1108 { | |
1109 std::string file = args(1).string_value (); | |
1110 std::string target; | |
1111 | |
1112 if (nargin == 3) | |
1113 target = args(2).string_value () + file_ops::dir_sep_str (); | |
1114 | |
1115 if (! error_state) | |
1116 { | |
1117 string_vector sv = curl.list (); | |
1118 octave_idx_type n = 0; | |
1119 glob_match pattern (file); | |
1120 | |
1121 | |
1122 for (octave_idx_type i = 0; i < sv.length (); i++) | |
1123 { | |
1124 if (pattern.match (sv(i))) | |
1125 { | |
1126 n++; | |
1127 | |
1128 time_t ftime; | |
1129 bool fisdir; | |
1130 double fsize; | |
1131 | |
1132 curl.get_fileinfo (sv(i), fsize, ftime, fisdir); | |
1133 | |
1134 if (fisdir) | |
1135 curl.mget_directory (sv(i), target); | |
1136 else | |
1137 { | |
1138 std::ofstream ofile ((target + sv(i)).c_str (), | |
1139 std::ios::out | | |
1140 std::ios::binary); | |
1141 | |
1142 if (! ofile.is_open ()) | |
1143 { | |
1144 error ("__ftp_mget__: unable to open file"); | |
1145 break; | |
1146 } | |
1147 | |
1148 unwind_protect_safe frame; | |
1149 | |
1150 frame.add_fcn (delete_file, target + sv(i)); | |
1151 | |
1152 curl.get (sv(i), ofile); | |
1153 | |
1154 ofile.close (); | |
1155 | |
1156 if (curl.good ()) | |
1157 frame.discard (); | |
1158 } | |
1159 | |
1160 if (! curl.good ()) | |
1161 { | |
1162 error ("__ftp_mget__: %s", curl.lasterror().c_str()); | |
1163 break; | |
1164 } | |
1165 } | |
1166 } | |
1167 if (n == 0) | |
1168 error ("__ftp_mget__: file not found"); | |
1169 } | |
1170 else | |
1171 error ("__ftp_mget__: expecting file name and target as second and third arguments"); | |
1172 } | |
1173 else | |
1174 error ("__ftp_mget__: invalid ftp handle"); | |
1175 } | |
1176 | |
1177 return retval; | |
1178 } |