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