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 }