00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032 #include <string>
00033 #include <fstream>
00034 #include <iomanip>
00035 #include <iostream>
00036
00037 #include "dir-ops.h"
00038 #include "file-ops.h"
00039 #include "file-stat.h"
00040 #include "oct-env.h"
00041 #include "glob-match.h"
00042
00043 #include "defun-dld.h"
00044 #include "error.h"
00045 #include "oct-obj.h"
00046 #include "ov-cell.h"
00047 #include "pager.h"
00048 #include "oct-map.h"
00049 #include "oct-refcount.h"
00050 #include "unwind-prot.h"
00051
00052 #ifdef HAVE_CURL
00053
00054 #include <curl/curl.h>
00055 #include <curl/curlver.h>
00056 #include <curl/easy.h>
00057
00058 static int
00059 write_data (void *buffer, size_t size, size_t nmemb, void *streamp)
00060 {
00061 std::ostream& stream = *(static_cast<std::ostream*> (streamp));
00062 stream.write (static_cast<const char*> (buffer), size*nmemb);
00063 return (stream.fail () ? 0 : size * nmemb);
00064 }
00065
00066 static int
00067 read_data (void *buffer, size_t size, size_t nmemb, void *streamp)
00068 {
00069 std::istream& stream = *(static_cast<std::istream*> (streamp));
00070 stream.read (static_cast<char*> (buffer), size*nmemb);
00071 if (stream.eof ())
00072 return stream.gcount ();
00073 else
00074 return (stream.fail () ? 0 : size * nmemb);
00075 }
00076
00077 static size_t
00078 throw_away (void *, size_t size, size_t nmemb, void *)
00079 {
00080 return static_cast<size_t>(size * nmemb);
00081 }
00082
00083 class
00084 curl_handle
00085 {
00086 private:
00087 class
00088 curl_handle_rep
00089 {
00090 public:
00091 curl_handle_rep (void) : count (1), valid (true), ascii (false)
00092 {
00093 curl = curl_easy_init ();
00094 if (!curl)
00095 error ("can not create curl handle");
00096 }
00097
00098 ~curl_handle_rep (void)
00099 {
00100 if (curl)
00101 curl_easy_cleanup (curl);
00102 }
00103
00104 bool is_valid (void) const
00105 {
00106 return valid;
00107 }
00108
00109 bool perform (bool curlerror) const
00110 {
00111 bool retval = false;
00112 if (!error_state)
00113 {
00114 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00115
00116 errnum = curl_easy_perform (curl);
00117 if (errnum != CURLE_OK)
00118 {
00119 if (curlerror)
00120 error ("%s", curl_easy_strerror (errnum));
00121 }
00122 else
00123 retval = true;
00124
00125 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00126 }
00127 return retval;
00128 }
00129
00130 CURL* handle (void) const
00131 {
00132 return curl;
00133 }
00134
00135 bool is_ascii (void) const
00136 {
00137 return ascii;
00138 }
00139
00140 bool is_binary (void) const
00141 {
00142 return !ascii;
00143 }
00144
00145 octave_refcount<size_t> count;
00146 std::string host;
00147 bool valid;
00148 bool ascii;
00149 mutable CURLcode errnum;
00150
00151 private:
00152 CURL *curl;
00153
00154
00155
00156 curl_handle_rep (const curl_handle_rep& ov);
00157
00158 curl_handle_rep& operator = (const curl_handle_rep&);
00159 };
00160
00161 public:
00162
00163
00164
00165
00166 #define setopt(option, parameter) \
00167 { \
00168 CURLcode res = curl_easy_setopt (rep->handle (), option, parameter); \
00169 if (res != CURLE_OK) \
00170 error ("%s", curl_easy_strerror (res)); \
00171 }
00172
00173 curl_handle (void) : rep (new curl_handle_rep ())
00174 {
00175 rep->valid = false;
00176 }
00177
00178 curl_handle (const std::string& _host, const std::string& user,
00179 const std::string& passwd) :
00180 rep (new curl_handle_rep ())
00181 {
00182 rep->host = _host;
00183 init (user, passwd, std::cin, octave_stdout);
00184
00185 std::string url = "ftp://" + _host;
00186 setopt (CURLOPT_URL, url.c_str());
00187
00188
00189 if (!error_state)
00190 perform ();
00191 }
00192
00193 curl_handle (const std::string& url, const std::string& method,
00194 const Cell& param, std::ostream& os, bool& retval) :
00195 rep (new curl_handle_rep ())
00196 {
00197 retval = false;
00198
00199 init ("", "", std::cin, os);
00200
00201 setopt (CURLOPT_NOBODY, 0);
00202
00203
00204
00205 std::string query_string = form_query_string (param);
00206
00207 if (method == "get")
00208 {
00209 query_string = url + "?" + query_string;
00210 setopt (CURLOPT_URL, query_string.c_str ());
00211 }
00212 else if (method == "post")
00213 {
00214 setopt (CURLOPT_URL, url.c_str ());
00215 setopt (CURLOPT_POSTFIELDS, query_string.c_str ());
00216 }
00217 else
00218 setopt (CURLOPT_URL, url.c_str());
00219
00220 if (!error_state)
00221 retval = perform (false);
00222 }
00223
00224 curl_handle (const curl_handle& h) : rep (h.rep)
00225 {
00226 rep->count++;
00227 }
00228
00229 ~curl_handle (void)
00230 {
00231 if (--rep->count == 0)
00232 delete rep;
00233 }
00234
00235 curl_handle& operator = (const curl_handle& h)
00236 {
00237 if (this != &h)
00238 {
00239 if (--rep->count == 0)
00240 delete rep;
00241
00242 rep = h.rep;
00243 rep->count++;
00244 }
00245 return *this;
00246 }
00247
00248 bool is_valid (void) const
00249 {
00250 return rep->is_valid ();
00251 }
00252
00253 std::string lasterror (void) const
00254 {
00255 return std::string (curl_easy_strerror (rep->errnum));
00256 }
00257
00258 void set_ostream (std::ostream& os) const
00259 {
00260 setopt (CURLOPT_WRITEDATA, static_cast<void*> (&os));
00261 }
00262
00263 void set_istream (std::istream& is) const
00264 {
00265 setopt (CURLOPT_READDATA, static_cast<void*> (&is));
00266 }
00267
00268 void ascii (void) const
00269 {
00270 setopt (CURLOPT_TRANSFERTEXT, 1);
00271 rep->ascii = true;
00272 }
00273
00274 void binary (void) const
00275 {
00276 setopt (CURLOPT_TRANSFERTEXT, 0);
00277 rep->ascii = false;
00278 }
00279
00280 bool is_ascii (void) const
00281 {
00282 return rep->is_ascii ();
00283 }
00284
00285 bool is_binary (void) const
00286 {
00287 return rep->is_binary ();
00288 }
00289
00290 void cwd (const std::string& path) const
00291 {
00292 struct curl_slist *slist = 0;
00293 std::string cmd = "cwd " + path;
00294 slist = curl_slist_append (slist, cmd.c_str());
00295 setopt (CURLOPT_POSTQUOTE, slist);
00296 if (! error_state)
00297 perform ();
00298 setopt (CURLOPT_POSTQUOTE, 0);
00299 curl_slist_free_all (slist);
00300 }
00301
00302 void del (const std::string& file) const
00303 {
00304 struct curl_slist *slist = 0;
00305 std::string cmd = "dele " + file;
00306 slist = curl_slist_append (slist, cmd.c_str());
00307 setopt (CURLOPT_POSTQUOTE, slist);
00308 if (! error_state)
00309 perform ();
00310 setopt (CURLOPT_POSTQUOTE, 0);
00311 curl_slist_free_all (slist);
00312 }
00313
00314 void rmdir (const std::string& path) const
00315 {
00316 struct curl_slist *slist = 0;
00317 std::string cmd = "rmd " + path;
00318 slist = curl_slist_append (slist, cmd.c_str());
00319 setopt (CURLOPT_POSTQUOTE, slist);
00320 if (! error_state)
00321 perform ();
00322 setopt (CURLOPT_POSTQUOTE, 0);
00323 curl_slist_free_all (slist);
00324 }
00325
00326 bool mkdir (const std::string& path, bool curlerror = true) const
00327 {
00328 bool retval = false;
00329 struct curl_slist *slist = 0;
00330 std::string cmd = "mkd " + path;
00331 slist = curl_slist_append (slist, cmd.c_str());
00332 setopt (CURLOPT_POSTQUOTE, slist);
00333 if (! error_state)
00334 retval = perform (curlerror);
00335 setopt (CURLOPT_POSTQUOTE, 0);
00336 curl_slist_free_all (slist);
00337 return retval;
00338 }
00339
00340 void rename (const std::string& oldname, const std::string& newname) const
00341 {
00342 struct curl_slist *slist = 0;
00343 std::string cmd = "rnfr " + oldname;
00344 slist = curl_slist_append (slist, cmd.c_str());
00345 cmd = "rnto " + newname;
00346 slist = curl_slist_append (slist, cmd.c_str());
00347 setopt (CURLOPT_POSTQUOTE, slist);
00348 if (! error_state)
00349 perform ();
00350 setopt (CURLOPT_POSTQUOTE, 0);
00351 curl_slist_free_all (slist);
00352 }
00353
00354 void put (const std::string& file, std::istream& is) const
00355 {
00356 std::string url = "ftp://" + rep->host + "/" + file;
00357 setopt (CURLOPT_URL, url.c_str());
00358 setopt (CURLOPT_UPLOAD, 1);
00359 setopt (CURLOPT_NOBODY, 0);
00360 set_istream (is);
00361 if (! error_state)
00362 perform ();
00363 set_istream (std::cin);
00364 setopt (CURLOPT_NOBODY, 1);
00365 setopt (CURLOPT_UPLOAD, 0);
00366 url = "ftp://" + rep->host;
00367 setopt (CURLOPT_URL, url.c_str());
00368 }
00369
00370 void get (const std::string& file, std::ostream& os) const
00371 {
00372 std::string url = "ftp://" + rep->host + "/" + file;
00373 setopt (CURLOPT_URL, url.c_str());
00374 setopt (CURLOPT_NOBODY, 0);
00375 set_ostream (os);
00376 if (! error_state)
00377 perform ();
00378 set_ostream (octave_stdout);
00379 setopt (CURLOPT_NOBODY, 1);
00380 url = "ftp://" + rep->host;
00381 setopt (CURLOPT_URL, url.c_str());
00382 }
00383
00384 void dir (void) const
00385 {
00386 std::string url = "ftp://" + rep->host + "/";
00387 setopt (CURLOPT_URL, url.c_str());
00388 setopt (CURLOPT_NOBODY, 0);
00389 if (! error_state)
00390 perform ();
00391 setopt (CURLOPT_NOBODY, 1);
00392 url = "ftp://" + rep->host;
00393 setopt (CURLOPT_URL, url.c_str());
00394 }
00395
00396 string_vector list (void) const
00397 {
00398 std::ostringstream buf;
00399 std::string url = "ftp://" + rep->host + "/";
00400 setopt (CURLOPT_WRITEDATA, static_cast<void*> (&buf));
00401 setopt (CURLOPT_URL, url.c_str());
00402 setopt (CURLOPT_DIRLISTONLY, 1);
00403 setopt (CURLOPT_NOBODY, 0);
00404 if (! error_state)
00405 perform ();
00406 setopt (CURLOPT_NOBODY, 1);
00407 url = "ftp://" + rep->host;
00408 setopt (CURLOPT_WRITEDATA, static_cast<void*> (&octave_stdout));
00409 setopt (CURLOPT_DIRLISTONLY, 0);
00410 setopt (CURLOPT_URL, url.c_str());
00411
00412
00413 std::string str = buf.str ();
00414 octave_idx_type n = 0;
00415 size_t pos = 0;
00416 while (true)
00417 {
00418 pos = str.find_first_of('\n', pos);
00419 if (pos == std::string::npos)
00420 break;
00421 pos++;
00422 n++;
00423 }
00424 string_vector retval (n);
00425 pos = 0;
00426 for (octave_idx_type i = 0; i < n; i++)
00427 {
00428 size_t newpos = str.find_first_of('\n', pos);
00429 if (newpos == std::string::npos)
00430 break;
00431
00432 retval(i) = str.substr(pos, newpos - pos);
00433 pos = newpos + 1;
00434 }
00435 return retval;
00436 }
00437
00438 void get_fileinfo (const std::string& filename, double& filesize,
00439 time_t& filetime, bool& fileisdir) const
00440 {
00441 std::string path = pwd();
00442
00443 std::string url = "ftp://" + rep->host + "/" + path + "/" + filename;
00444 setopt (CURLOPT_URL, url.c_str());
00445 setopt (CURLOPT_FILETIME, 1);
00446 setopt (CURLOPT_HEADERFUNCTION, throw_away);
00447 setopt (CURLOPT_WRITEFUNCTION, throw_away);
00448
00449
00450
00451
00452
00453 if (! error_state)
00454 {
00455 if (! perform (false))
00456 {
00457 fileisdir = true;
00458 filetime = -1;
00459 filesize = 0;
00460 }
00461 else
00462 {
00463 fileisdir = false;
00464 time_t ft;
00465 curl_easy_getinfo(rep->handle (), CURLINFO_FILETIME, &ft);
00466 filetime = ft;
00467 double fs;
00468 curl_easy_getinfo(rep->handle (),
00469 CURLINFO_CONTENT_LENGTH_DOWNLOAD, &fs);
00470 filesize = fs;
00471 }
00472 }
00473
00474 setopt (CURLOPT_WRITEFUNCTION, write_data);
00475 setopt (CURLOPT_HEADERFUNCTION, 0);
00476 setopt (CURLOPT_FILETIME, 0);
00477 url = "ftp://" + rep->host;
00478 setopt (CURLOPT_URL, url.c_str());
00479
00480
00481
00482
00483
00484 cwd ("/" + path);
00485 }
00486
00487 std::string pwd (void) const
00488 {
00489 struct curl_slist *slist = 0;
00490 std::string retval;
00491 std::ostringstream buf;
00492
00493 slist = curl_slist_append (slist, "pwd");
00494 setopt (CURLOPT_POSTQUOTE, slist);
00495 setopt (CURLOPT_HEADERFUNCTION, write_data);
00496 setopt (CURLOPT_WRITEHEADER, static_cast<void *>(&buf));
00497
00498 if (! error_state)
00499 {
00500 perform ();
00501 retval = buf.str();
00502
00503
00504 size_t pos2 = retval.rfind ('"');
00505 size_t pos1 = retval.rfind ('"', pos2 - 1);
00506 retval = retval.substr(pos1 + 1, pos2 - pos1 - 1);
00507 }
00508 setopt (CURLOPT_HEADERFUNCTION, 0);
00509 setopt (CURLOPT_WRITEHEADER, 0);
00510 setopt (CURLOPT_POSTQUOTE, 0);
00511 curl_slist_free_all (slist);
00512
00513 return retval;
00514 }
00515
00516 bool perform (bool curlerror = true) const
00517 {
00518 return rep->perform (curlerror);
00519 }
00520
00521 private:
00522 curl_handle_rep *rep;
00523
00524 std::string form_query_string (const Cell& param)
00525 {
00526 std::ostringstream query;
00527
00528 for (int i = 0; i < param.numel (); i += 2)
00529 {
00530 std::string name = param(i).string_value ();
00531 std::string text = param(i+1).string_value ();
00532
00533
00534 char *enc_name = curl_easy_escape (rep->handle(), name.c_str (),
00535 name.length ());
00536 char *enc_text = curl_easy_escape (rep->handle(), text.c_str (),
00537 text.length ());
00538
00539 query << enc_name << "=" << enc_text;
00540
00541 curl_free (enc_name);
00542 curl_free (enc_text);
00543
00544 if (i < param.numel()-1)
00545 query << "&";
00546 }
00547
00548 query.flush ();
00549
00550 return query.str ();
00551 }
00552
00553 void init (const std::string& user, const std::string& passwd,
00554 std::istream& is, std::ostream& os)
00555 {
00556
00557 setopt (CURLOPT_NOBODY, 1);
00558
00559
00560 std::string userpwd = user;
00561 if (! passwd.empty ())
00562 userpwd += ":" + passwd;
00563 if (! userpwd.empty ())
00564 setopt (CURLOPT_USERPWD, userpwd.c_str ());
00565
00566
00567 setopt (CURLOPT_WRITEFUNCTION, write_data);
00568
00569
00570 setopt (CURLOPT_WRITEDATA, static_cast<void*> (&os));
00571
00572
00573 setopt (CURLOPT_READFUNCTION, read_data);
00574
00575
00576 setopt (CURLOPT_READDATA, static_cast<void*> (&is));
00577
00578
00579 setopt (CURLOPT_FOLLOWLOCATION, true);
00580
00581
00582
00583
00584 setopt (CURLOPT_FTP_USE_EPSV, false);
00585
00586 setopt (CURLOPT_NOPROGRESS, true);
00587 setopt (CURLOPT_FAILONERROR, true);
00588
00589 setopt (CURLOPT_POSTQUOTE, 0);
00590 setopt (CURLOPT_QUOTE, 0);
00591 }
00592
00593 #undef setopt
00594 };
00595
00596 class
00597 curl_handles
00598 {
00599 public:
00600
00601 typedef std::map<std::string, curl_handle>::iterator iterator;
00602 typedef std::map<std::string, curl_handle>::const_iterator const_iterator;
00603
00604 curl_handles (void) : map ()
00605 {
00606 curl_global_init(CURL_GLOBAL_DEFAULT);
00607 }
00608
00609 ~curl_handles (void)
00610 {
00611
00612
00613 map.erase (begin(), end());
00614
00615 curl_global_cleanup ();
00616 }
00617
00618 iterator begin (void) { return iterator (map.begin ()); }
00619 const_iterator begin (void) const { return const_iterator (map.begin ()); }
00620
00621 iterator end (void) { return iterator (map.end ()); }
00622 const_iterator end (void) const { return const_iterator (map.end ()); }
00623
00624 iterator seek (const std::string& k) { return map.find (k); }
00625 const_iterator seek (const std::string& k) const { return map.find (k); }
00626
00627 std::string key (const_iterator p) const { return p->first; }
00628
00629 curl_handle& contents (const std::string& k)
00630 {
00631 return map[k];
00632 }
00633
00634 curl_handle contents (const std::string& k) const
00635 {
00636 const_iterator p = seek (k);
00637 return p != end () ? p->second : curl_handle ();
00638 }
00639
00640 curl_handle& contents (iterator p)
00641 { return p->second; }
00642
00643 curl_handle contents (const_iterator p) const
00644 { return p->second; }
00645
00646 void del (const std::string& k)
00647 {
00648 iterator p = map.find (k);
00649
00650 if (p != map.end ())
00651 map.erase (p);
00652 }
00653
00654 private:
00655 std::map<std::string, curl_handle> map;
00656 };
00657
00658 static curl_handles handles;
00659
00660 static void
00661 cleanup_urlwrite (std::string filename)
00662 {
00663 octave_unlink (filename);
00664 }
00665
00666 static void
00667 reset_path (const curl_handle curl)
00668 {
00669 curl.cwd ("..");
00670 }
00671
00672 static void
00673 delete_file (std::string file)
00674 {
00675 octave_unlink (file);
00676 }
00677 #endif
00678
00679 DEFUN_DLD (urlwrite, args, nargout,
00680 "-*- texinfo -*-\n\
00681 @deftypefn {Loadable Function} {} urlwrite (@var{url}, @var{localfile})\n\
00682 @deftypefnx {Loadable Function} {@var{f} =} urlwrite (@var{url}, @var{localfile})\n\
00683 @deftypefnx {Loadable Function} {[@var{f}, @var{success}] =} urlwrite (@var{url}, @var{localfile})\n\
00684 @deftypefnx {Loadable Function} {[@var{f}, @var{success}, @var{message}] =} urlwrite (@var{url}, @var{localfile})\n\
00685 Download a remote file specified by its @var{url} and save it as\n\
00686 @var{localfile}. For example:\n\
00687 \n\
00688 @example\n\
00689 @group\n\
00690 urlwrite (\"ftp://ftp.octave.org/pub/octave/README\",\n\
00691 \"README.txt\");\n\
00692 @end group\n\
00693 @end example\n\
00694 \n\
00695 The full path of the downloaded file is returned in @var{f}. The\n\
00696 variable @var{success} is 1 if the download was successful,\n\
00697 otherwise it is 0 in which case @var{message} contains an error\n\
00698 message. If no output argument is specified and an error occurs,\n\
00699 then the error is signaled through Octave's error handling mechanism.\n\
00700 \n\
00701 This function uses libcurl. Curl supports, among others, the HTTP,\n\
00702 FTP and FILE protocols. Username and password may be specified in\n\
00703 the URL, for example:\n\
00704 \n\
00705 @example\n\
00706 @group\n\
00707 urlwrite (\"http://username:password@@example.com/file.txt\",\n\
00708 \"file.txt\");\n\
00709 @end group\n\
00710 @end example\n\
00711 \n\
00712 GET and POST requests can be specified by @var{method} and @var{param}.\n\
00713 The parameter @var{method} is either @samp{get} or @samp{post}\n\
00714 and @var{param} is a cell array of parameter and value pairs.\n\
00715 For example:\n\
00716 \n\
00717 @example\n\
00718 @group\n\
00719 urlwrite (\"http://www.google.com/search\", \"search.html\",\n\
00720 \"get\", @{\"query\", \"octave\"@});\n\
00721 @end group\n\
00722 @end example\n\
00723 @seealso{urlread}\n\
00724 @end deftypefn")
00725 {
00726 octave_value_list retval;
00727
00728 #ifdef HAVE_CURL
00729
00730 int nargin = args.length ();
00731
00732
00733 if (nargin != 2 && nargin != 4)
00734 {
00735 print_usage ();
00736 return retval;
00737 }
00738
00739 std::string url = args(0).string_value();
00740
00741 if (error_state)
00742 {
00743 error ("urlwrite: URL must be a character string");
00744 return retval;
00745 }
00746
00747
00748 std::string filename = args(1).string_value();
00749
00750 if (error_state)
00751 {
00752 error ("urlwrite: LOCALFILE must be a character string");
00753 return retval;
00754 }
00755
00756 std::string method;
00757 Cell param;
00758
00759 if (nargin == 4)
00760 {
00761 method = args(2).string_value();
00762
00763 if (error_state)
00764 {
00765 error ("urlwrite: METHOD must be \"get\" or \"post\"");
00766 return retval;
00767 }
00768
00769 if (method != "get" && method != "post")
00770 {
00771 error ("urlwrite: METHOD must be \"get\" or \"post\"");
00772 return retval;
00773 }
00774
00775 param = args(3).cell_value();
00776
00777 if (error_state)
00778 {
00779 error ("urlwrite: parameters (PARAM) for get and post requests must be given as a cell");
00780 return retval;
00781 }
00782
00783
00784 if (param.numel () % 2 == 1 )
00785 {
00786 error ("urlwrite: number of elements in PARAM must be even");
00787 return retval;
00788 }
00789 }
00790
00791
00792
00793
00794
00795 file_stat fs (filename);
00796
00797 std::ofstream ofile (filename.c_str(), std::ios::out | std::ios::binary);
00798
00799 if (! ofile.is_open ())
00800 {
00801 error ("urlwrite: unable to open file");
00802 return retval;
00803 }
00804
00805 unwind_protect_safe frame;
00806
00807 frame.add_fcn (cleanup_urlwrite, filename);
00808
00809 bool ok;
00810 curl_handle curl = curl_handle (url, method, param, ofile, ok);
00811
00812 ofile.close ();
00813
00814 if (!error_state)
00815 frame.discard ();
00816 else
00817 frame.run ();
00818
00819 if (nargout > 0)
00820 {
00821 if (ok)
00822 {
00823 retval(2) = std::string ();
00824 retval(1) = true;
00825 retval(0) = octave_env::make_absolute (filename);
00826 }
00827 else
00828 {
00829 retval(2) = curl.lasterror ();
00830 retval(1) = false;
00831 retval(0) = std::string ();
00832 }
00833 }
00834
00835 if (nargout < 2 && ! ok)
00836 error ("urlwrite: curl: %s", curl.lasterror ().c_str ());
00837
00838 #else
00839 error ("urlwrite: not available in this version of Octave");
00840 #endif
00841
00842 return retval;
00843 }
00844
00845 DEFUN_DLD (urlread, args, nargout,
00846 "-*- texinfo -*-\n\
00847 @deftypefn {Loadable Function} {@var{s} =} urlread (@var{url})\n\
00848 @deftypefnx {Loadable Function} {[@var{s}, @var{success}] =} urlread (@var{url})\n\
00849 @deftypefnx {Loadable Function} {[@var{s}, @var{success}, @var{message}] =} urlread (@var{url})\n\
00850 @deftypefnx {Loadable Function} {[@dots{}] =} urlread (@var{url}, @var{method}, @var{param})\n\
00851 Download a remote file specified by its @var{url} and return its content\n\
00852 in string @var{s}. For example:\n\
00853 \n\
00854 @example\n\
00855 s = urlread (\"ftp://ftp.octave.org/pub/octave/README\");\n\
00856 @end example\n\
00857 \n\
00858 The variable @var{success} is 1 if the download was successful,\n\
00859 otherwise it is 0 in which case @var{message} contains an error\n\
00860 message. If no output argument is specified and an error occurs,\n\
00861 then the error is signaled through Octave's error handling mechanism.\n\
00862 \n\
00863 This function uses libcurl. Curl supports, among others, the HTTP,\n\
00864 FTP and FILE protocols. Username and password may be specified in the\n\
00865 URL@. For example:\n\
00866 \n\
00867 @example\n\
00868 s = urlread (\"http://user:password@@example.com/file.txt\");\n\
00869 @end example\n\
00870 \n\
00871 GET and POST requests can be specified by @var{method} and @var{param}.\n\
00872 The parameter @var{method} is either @samp{get} or @samp{post}\n\
00873 and @var{param} is a cell array of parameter and value pairs.\n\
00874 For example:\n\
00875 \n\
00876 @example\n\
00877 @group\n\
00878 s = urlread (\"http://www.google.com/search\", \"get\",\n\
00879 @{\"query\", \"octave\"@});\n\
00880 @end group\n\
00881 @end example\n\
00882 @seealso{urlwrite}\n\
00883 @end deftypefn")
00884 {
00885
00886 octave_value_list retval;
00887
00888 #ifdef HAVE_CURL
00889
00890 int nargin = args.length ();
00891
00892
00893 if (nargin != 1 && nargin != 3)
00894 {
00895 print_usage ();
00896 return retval;
00897 }
00898
00899 std::string url = args(0).string_value();
00900
00901 if (error_state)
00902 {
00903 error ("urlread: URL must be a character string");
00904 return retval;
00905 }
00906
00907 std::string method;
00908 Cell param;
00909
00910 if (nargin == 3)
00911 {
00912 method = args(1).string_value();
00913
00914 if (error_state)
00915 {
00916 error ("urlread: METHOD must be \"get\" or \"post\"");
00917 return retval;
00918 }
00919
00920 if (method != "get" && method != "post")
00921 {
00922 error ("urlread: METHOD must be \"get\" or \"post\"");
00923 return retval;
00924 }
00925
00926 param = args(2).cell_value();
00927
00928 if (error_state)
00929 {
00930 error ("urlread: parameters (PARAM) for get and post requests must be given as a cell");
00931 return retval;
00932 }
00933
00934 if (param.numel () % 2 == 1 )
00935 {
00936 error ("urlread: number of elements in PARAM must be even");
00937 return retval;
00938 }
00939 }
00940
00941 std::ostringstream buf;
00942
00943 bool ok;
00944 curl_handle curl = curl_handle (url, method, param, buf, ok);
00945
00946 if (nargout > 0)
00947 {
00948
00949 retval(2) = ok ? "" : curl.lasterror ();
00950 retval(1) = ok;
00951 retval(0) = buf.str ();
00952 }
00953
00954 if (nargout < 2 && ! ok)
00955 error ("urlread: curl: %s", curl.lasterror().c_str());
00956
00957 #else
00958 error ("urlread: not available in this version of Octave");
00959 #endif
00960
00961 return retval;
00962 }
00963
00964 DEFUN_DLD (__ftp__, args, ,
00965 "-*- texinfo -*-\n\
00966 @deftypefn {Loadable Function} {} __ftp__ (@var{handle}, @var{host})\n\
00967 @deftypefnx {Loadable Function} {} __ftp__ (@var{handle}, @var{host}, @var{username}, @var{password})\n\
00968 Undocumented internal function\n\
00969 @end deftypefn")
00970 {
00971 #ifdef HAVE_CURL
00972 int nargin = args.length ();
00973 std::string handle;
00974 std::string host;
00975 std::string user = "anonymous";
00976 std::string passwd = "";
00977
00978 if (nargin < 2 || nargin > 4)
00979 error ("incorrect number of arguments");
00980 else
00981 {
00982 handle = args(0).string_value ();
00983 host = args(1).string_value ();
00984
00985 if (nargin > 1)
00986 user = args(2).string_value ();
00987
00988 if (nargin > 2)
00989 passwd = args(3).string_value ();
00990
00991 if (!error_state)
00992 {
00993 handles.contents (handle) = curl_handle (host, user, passwd);
00994
00995 if (error_state)
00996 handles.del (handle);
00997 }
00998 }
00999 #else
01000 error ("__ftp__: not available in this version of Octave");
01001 #endif
01002
01003 return octave_value ();
01004 }
01005
01006 DEFUN_DLD (__ftp_pwd__, args, ,
01007 "-*- texinfo -*-\n\
01008 @deftypefn {Loadable Function} {} __ftp_pwd__ (@var{handle})\n\
01009 Undocumented internal function\n\
01010 @end deftypefn")
01011 {
01012 octave_value retval;
01013 #ifdef HAVE_CURL
01014 int nargin = args.length ();
01015
01016 if (nargin != 1)
01017 error ("__ftp_pwd__: incorrect number of arguments");
01018 else
01019 {
01020 std::string handle = args(0).string_value ();
01021
01022 if (!error_state)
01023 {
01024 const curl_handle curl = handles.contents (handle);
01025
01026 if (curl.is_valid ())
01027 retval = curl.pwd ();
01028 else
01029 error ("__ftp_pwd__: invalid ftp handle");
01030 }
01031 }
01032 #else
01033 error ("__ftp_pwd__: not available in this version of Octave");
01034 #endif
01035
01036 return retval;
01037 }
01038
01039 DEFUN_DLD (__ftp_cwd__, args, ,
01040 "-*- texinfo -*-\n\
01041 @deftypefn {Loadable Function} {} __ftp_cwd__ (@var{handle}, @var{path})\n\
01042 Undocumented internal function\n\
01043 @end deftypefn")
01044 {
01045 #ifdef HAVE_CURL
01046 int nargin = args.length ();
01047
01048 if (nargin != 1 && nargin != 2)
01049 error ("__ftp_cwd__: incorrect number of arguments");
01050 else
01051 {
01052 std::string handle = args(0).string_value ();
01053 std::string path = "";
01054
01055 if (nargin > 1)
01056 path = args(1).string_value ();
01057
01058 if (!error_state)
01059 {
01060 const curl_handle curl = handles.contents (handle);
01061
01062 if (curl.is_valid ())
01063 curl.cwd (path);
01064 else
01065 error ("__ftp_cwd__: invalid ftp handle");
01066 }
01067 }
01068 #else
01069 error ("__ftp_cwd__: not available in this version of Octave");
01070 #endif
01071
01072 return octave_value ();
01073 }
01074
01075 DEFUN_DLD (__ftp_dir__, args, nargout,
01076 "-*- texinfo -*-\n\
01077 @deftypefn {Loadable Function} {} __ftp_dir__ (@var{handle})\n\
01078 Undocumented internal function\n\
01079 @end deftypefn")
01080 {
01081 octave_value retval;
01082 #ifdef HAVE_CURL
01083 int nargin = args.length ();
01084
01085 if (nargin != 1)
01086 error ("__ftp_dir__: incorrect number of arguments");
01087 else
01088 {
01089 std::string handle = args(0).string_value ();
01090
01091 if (!error_state)
01092 {
01093 const curl_handle curl = handles.contents (handle);
01094
01095 if (curl.is_valid ())
01096 {
01097 if (nargout == 0)
01098 curl.dir ();
01099 else
01100 {
01101 string_vector sv = curl.list ();
01102 octave_idx_type n = sv.length ();
01103 if (n == 0)
01104 {
01105 string_vector flds (5);
01106 flds(0) = "name";
01107 flds(1) = "date";
01108 flds(2) = "bytes";
01109 flds(3) = "isdir";
01110 flds(4) = "datenum";
01111 retval = octave_map (flds);
01112 }
01113 else
01114 {
01115 octave_map st;
01116 Cell filectime (dim_vector (n, 1));
01117 Cell filesize (dim_vector (n, 1));
01118 Cell fileisdir (dim_vector (n, 1));
01119 Cell filedatenum (dim_vector (n, 1));
01120
01121 st.assign ("name", Cell (sv));
01122
01123 for (octave_idx_type i = 0; i < n; i++)
01124 {
01125 time_t ftime;
01126 bool fisdir;
01127 double fsize;
01128
01129 curl.get_fileinfo (sv(i), fsize, ftime, fisdir);
01130
01131 fileisdir (i) = fisdir;
01132 filectime (i) = ctime (&ftime);
01133 filesize (i) = fsize;
01134 filedatenum (i) = double (ftime);
01135 }
01136 st.assign ("date", filectime);
01137 st.assign ("bytes", filesize);
01138 st.assign ("isdir", fileisdir);
01139 st.assign ("datenum", filedatenum);
01140 retval = st;
01141 }
01142 }
01143 }
01144 else
01145 error ("__ftp_dir__: invalid ftp handle");
01146 }
01147 }
01148 #else
01149 error ("__ftp_dir__: not available in this version of Octave");
01150 #endif
01151
01152 return retval;
01153 }
01154
01155 DEFUN_DLD (__ftp_ascii__, args, ,
01156 "-*- texinfo -*-\n\
01157 @deftypefn {Loadable Function} {} __ftp_ascii__ (@var{handle})\n\
01158 Undocumented internal function\n\
01159 @end deftypefn")
01160 {
01161 #ifdef HAVE_CURL
01162 int nargin = args.length ();
01163
01164 if (nargin != 1)
01165 error ("__ftp_ascii__: incorrect number of arguments");
01166 else
01167 {
01168 std::string handle = args(0).string_value ();
01169
01170 if (!error_state)
01171 {
01172 const curl_handle curl = handles.contents (handle);
01173
01174 if (curl.is_valid ())
01175 curl.ascii ();
01176 else
01177 error ("__ftp_ascii__: invalid ftp handle");
01178 }
01179 }
01180 #else
01181 error ("__ftp_ascii__: not available in this version of Octave");
01182 #endif
01183
01184 return octave_value ();
01185 }
01186
01187 DEFUN_DLD (__ftp_binary__, args, ,
01188 "-*- texinfo -*-\n\
01189 @deftypefn {Loadable Function} {} __ftp_binary__ (@var{handle})\n\
01190 Undocumented internal function\n\
01191 @end deftypefn")
01192 {
01193 #ifdef HAVE_CURL
01194 int nargin = args.length ();
01195
01196 if (nargin != 1)
01197 error ("__ftp_binary__: incorrect number of arguments");
01198 else
01199 {
01200 std::string handle = args(0).string_value ();
01201
01202 if (!error_state)
01203 {
01204 const curl_handle curl = handles.contents (handle);
01205
01206 if (curl.is_valid ())
01207 curl.binary ();
01208 else
01209 error ("__ftp_binary__: invalid ftp handle");
01210 }
01211 }
01212 #else
01213 error ("__ftp_binary__: not available in this version of Octave");
01214 #endif
01215
01216 return octave_value ();
01217 }
01218
01219 DEFUN_DLD (__ftp_close__, args, ,
01220 "-*- texinfo -*-\n\
01221 @deftypefn {Loadable Function} {} __ftp_close__ (@var{handle})\n\
01222 Undocumented internal function\n\
01223 @end deftypefn")
01224 {
01225 #ifdef HAVE_CURL
01226 int nargin = args.length ();
01227
01228 if (nargin != 1)
01229 error ("__ftp_close__: incorrect number of arguments");
01230 else
01231 {
01232 std::string handle = args(0).string_value ();
01233
01234 if (!error_state)
01235 handles.del (handle);
01236 }
01237 #else
01238 error ("__ftp_close__: not available in this version of Octave");
01239 #endif
01240
01241 return octave_value ();
01242 }
01243
01244 DEFUN_DLD (__ftp_mode__, args, ,
01245 "-*- texinfo -*-\n\
01246 @deftypefn {Loadable Function} {} __ftp_mode__ (@var{handle})\n\
01247 Undocumented internal function\n\
01248 @end deftypefn")
01249 {
01250 octave_value retval;
01251 #ifdef HAVE_CURL
01252 int nargin = args.length ();
01253
01254 if (nargin != 1)
01255 error ("__ftp_mode__: incorrect number of arguments");
01256 else
01257 {
01258 std::string handle = args(0).string_value ();
01259
01260
01261 if (!error_state)
01262 {
01263 const curl_handle curl = handles.contents (handle);
01264
01265 if (curl.is_valid ())
01266 retval = (curl.is_ascii() ? "ascii" : "binary");
01267 else
01268 error ("__ftp_binary__: invalid ftp handle");
01269 }
01270 }
01271 #else
01272 error ("__ftp_mode__: not available in this version of Octave");
01273 #endif
01274
01275 return retval;
01276 }
01277
01278 DEFUN_DLD (__ftp_delete__, args, ,
01279 "-*- texinfo -*-\n\
01280 @deftypefn {Loadable Function} {} __ftp_delete__ (@var{handle}, @var{path})\n\
01281 Undocumented internal function\n\
01282 @end deftypefn")
01283 {
01284 #ifdef HAVE_CURL
01285 int nargin = args.length ();
01286
01287 if (nargin != 2)
01288 error ("__ftp_delete__: incorrect number of arguments");
01289 else
01290 {
01291 std::string handle = args(0).string_value ();
01292 std::string file = args(1).string_value ();
01293
01294 if (!error_state)
01295 {
01296 const curl_handle curl = handles.contents (handle);
01297
01298 if (curl.is_valid ())
01299 curl.del (file);
01300 else
01301 error ("__ftp_delete__: invalid ftp handle");
01302 }
01303 }
01304 #else
01305 error ("__ftp_delete__: not available in this version of Octave");
01306 #endif
01307
01308 return octave_value ();
01309 }
01310
01311 DEFUN_DLD (__ftp_rmdir__, args, ,
01312 "-*- texinfo -*-\n\
01313 @deftypefn {Loadable Function} {} __ftp_rmdir__ (@var{handle}, @var{path})\n\
01314 Undocumented internal function\n\
01315 @end deftypefn")
01316 {
01317 #ifdef HAVE_CURL
01318 int nargin = args.length ();
01319
01320 if (nargin != 2)
01321 error ("__ftp_rmdir__: incorrect number of arguments");
01322 else
01323 {
01324 std::string handle = args(0).string_value ();
01325 std::string dir = args(1).string_value ();
01326
01327 if (!error_state)
01328 {
01329 const curl_handle curl = handles.contents (handle);
01330
01331 if (curl.is_valid ())
01332 curl.rmdir (dir);
01333 else
01334 error ("__ftp_rmdir__: invalid ftp handle");
01335 }
01336 }
01337 #else
01338 error ("__ftp_rmdir__: not available in this version of Octave");
01339 #endif
01340
01341 return octave_value ();
01342 }
01343
01344 DEFUN_DLD (__ftp_mkdir__, args, ,
01345 "-*- texinfo -*-\n\
01346 @deftypefn {Loadable Function} {} __ftp_mkdir__ (@var{handle}, @var{path})\n\
01347 Undocumented internal function\n\
01348 @end deftypefn")
01349 {
01350 #ifdef HAVE_CURL
01351 int nargin = args.length ();
01352
01353 if (nargin != 2)
01354 error ("__ftp_mkdir__: incorrect number of arguments");
01355 else
01356 {
01357 std::string handle = args(0).string_value ();
01358 std::string dir = args(1).string_value ();
01359
01360 if (!error_state)
01361 {
01362 const curl_handle curl = handles.contents (handle);
01363
01364 if (curl.is_valid ())
01365 curl.mkdir (dir);
01366 else
01367 error ("__ftp_mkdir__: invalid ftp handle");
01368 }
01369 }
01370 #else
01371 error ("__ftp_mkdir__: not available in this version of Octave");
01372 #endif
01373
01374 return octave_value ();
01375 }
01376
01377 DEFUN_DLD (__ftp_rename__, args, ,
01378 "-*- texinfo -*-\n\
01379 @deftypefn {Loadable Function} {} __ftp_rename__ (@var{handle}, @var{path})\n\
01380 Undocumented internal function\n\
01381 @end deftypefn")
01382 {
01383 #ifdef HAVE_CURL
01384 int nargin = args.length ();
01385
01386 if (nargin != 3)
01387 error ("__ftp_rename__: incorrect number of arguments");
01388 else
01389 {
01390 std::string handle = args(0).string_value ();
01391 std::string oldname = args(1).string_value ();
01392 std::string newname = args(2).string_value ();
01393
01394 if (!error_state)
01395 {
01396 const curl_handle curl = handles.contents (handle);
01397
01398 if (curl.is_valid ())
01399 curl.rename (oldname, newname);
01400 else
01401 error ("__ftp_rename__: invalid ftp handle");
01402 }
01403 }
01404 #else
01405 error ("__ftp_rename__: not available in this version of Octave");
01406 #endif
01407
01408 return octave_value ();
01409 }
01410
01411 #ifdef HAVE_CURL
01412 static string_vector
01413 mput_directory (const curl_handle& curl, const std::string& base,
01414 const std::string& dir)
01415 {
01416 string_vector retval;
01417
01418 if (! curl.mkdir (dir, false))
01419 warning ("__ftp_mput__: can not create the remote directory ""%s""",
01420 (base.length() == 0 ? dir : base +
01421 file_ops::dir_sep_str () + dir).c_str ());
01422
01423 curl.cwd (dir);
01424
01425 if (! error_state)
01426 {
01427 unwind_protect_safe frame;
01428
01429 frame.add_fcn (reset_path, curl);
01430
01431 std::string realdir = base.length() == 0 ? dir : base +
01432 file_ops::dir_sep_str () + dir;
01433
01434 dir_entry dirlist (realdir);
01435
01436 if (dirlist)
01437 {
01438 string_vector files = dirlist.read ();
01439
01440 for (octave_idx_type i = 0; i < files.length (); i++)
01441 {
01442 std::string file = files (i);
01443
01444 if (file == "." || file == "..")
01445 continue;
01446
01447 std::string realfile = realdir + file_ops::dir_sep_str () + file;
01448 file_stat fs (realfile);
01449
01450 if (! fs.exists ())
01451 {
01452 error ("__ftp__mput: file ""%s"" does not exist",
01453 realfile.c_str ());
01454 break;
01455 }
01456
01457 if (fs.is_dir ())
01458 {
01459 retval.append (mput_directory (curl, realdir, file));
01460
01461 if (error_state)
01462 break;
01463 }
01464 else
01465 {
01466
01467 std::ifstream ifile (realfile.c_str(), std::ios::in |
01468 std::ios::binary);
01469
01470 if (! ifile.is_open ())
01471 {
01472 error ("__ftp_mput__: unable to open file ""%s""",
01473 realfile.c_str ());
01474 break;
01475 }
01476
01477 curl.put (file, ifile);
01478
01479 ifile.close ();
01480
01481 if (error_state)
01482 break;
01483
01484 retval.append (realfile);
01485 }
01486 }
01487 }
01488 else
01489 error ("__ftp_mput__: can not read the directory ""%s""",
01490 realdir.c_str());
01491 }
01492
01493 return retval;
01494 }
01495 #endif
01496
01497 DEFUN_DLD (__ftp_mput__, args, nargout,
01498 "-*- texinfo -*-\n\
01499 @deftypefn {Loadable Function} {} __ftp_mput__ (@var{handle}, @var{files})\n\
01500 Undocumented internal function\n\
01501 @end deftypefn")
01502 {
01503 string_vector retval;
01504
01505 #ifdef HAVE_CURL
01506 int nargin = args.length ();
01507
01508 if (nargin != 2)
01509 error ("__ftp_mput__: incorrect number of arguments");
01510 else
01511 {
01512 std::string handle = args(0).string_value ();
01513 std::string pat = args(1).string_value ();
01514
01515 if (!error_state)
01516 {
01517 const curl_handle curl = handles.contents (handle);
01518
01519 if (curl.is_valid ())
01520 {
01521 glob_match pattern (file_ops::tilde_expand (pat));
01522 string_vector files = pattern.glob ();
01523
01524 for (octave_idx_type i = 0; i < files.length (); i++)
01525 {
01526 std::string file = files (i);
01527
01528 file_stat fs (file);
01529
01530 if (! fs.exists ())
01531 {
01532 error ("__ftp__mput: file does not exist");
01533 break;
01534 }
01535
01536 if (fs.is_dir ())
01537 {
01538 retval.append (mput_directory (curl, "", file));
01539 if (error_state)
01540 break;
01541 }
01542 else
01543 {
01544
01545 std::ifstream ifile (file.c_str(), std::ios::in |
01546 std::ios::binary);
01547
01548 if (! ifile.is_open ())
01549 {
01550 error ("__ftp_mput__: unable to open file");
01551 break;
01552 }
01553
01554 curl.put (file, ifile);
01555
01556 ifile.close ();
01557
01558 if (error_state)
01559 break;
01560
01561 retval.append (file);
01562 }
01563 }
01564 }
01565 else
01566 error ("__ftp_mput__: invalid ftp handle");
01567 }
01568 }
01569 #else
01570 error ("__ftp_mput__: not available in this version of Octave");
01571 #endif
01572
01573 return (nargout > 0 ? octave_value (retval) : octave_value ());
01574 }
01575
01576 #ifdef HAVE_CURL
01577 static void
01578 getallfiles (const curl_handle& curl, const std::string& dir,
01579 const std::string& target)
01580 {
01581 std::string sep = file_ops::dir_sep_str ();
01582 file_stat fs (dir);
01583
01584 if (!fs || !fs.is_dir ())
01585 {
01586 std::string msg;
01587 int status = octave_mkdir (dir, 0777, msg);
01588
01589 if (status < 0)
01590 error ("__ftp_mget__: can't create directory %s%s%s. %s",
01591 target.c_str(), sep.c_str(), dir.c_str(), msg.c_str());
01592 }
01593
01594 if (! error_state)
01595 {
01596 curl.cwd (dir);
01597
01598 if (! error_state)
01599 {
01600 unwind_protect_safe frame;
01601
01602 frame.add_fcn (reset_path, curl);
01603
01604 string_vector sv = curl.list ();
01605
01606 for (octave_idx_type i = 0; i < sv.length (); i++)
01607 {
01608 time_t ftime;
01609 bool fisdir;
01610 double fsize;
01611
01612 curl.get_fileinfo (sv(i), fsize, ftime, fisdir);
01613
01614 if (fisdir)
01615 getallfiles (curl, sv(i), target + dir + sep);
01616 else
01617 {
01618 std::string realfile = target + dir + sep + sv(i);
01619 std::ofstream ofile (realfile.c_str(),
01620 std::ios::out |
01621 std::ios::binary);
01622
01623 if (! ofile.is_open ())
01624 {
01625 error ("__ftp_mget__: unable to open file");
01626 break;
01627 }
01628
01629 unwind_protect_safe frame2;
01630
01631 frame2.add_fcn (delete_file, realfile);
01632
01633 curl.get (sv(i), ofile);
01634
01635 ofile.close ();
01636
01637 if (!error_state)
01638 frame2.discard ();
01639 else
01640 frame2.run ();
01641 }
01642
01643 if (error_state)
01644 break;
01645 }
01646 }
01647 }
01648 }
01649 #endif
01650
01651 DEFUN_DLD (__ftp_mget__, args, ,
01652 "-*- texinfo -*-\n\
01653 @deftypefn {Loadable Function} {} __ftp_mget__ (@var{handle}, @var{files})\n\
01654 Undocumented internal function\n\
01655 @end deftypefn")
01656 {
01657 #ifdef HAVE_CURL
01658 int nargin = args.length ();
01659
01660 if (nargin != 2 && nargin != 3)
01661 error ("__ftp_mget__: incorrect number of arguments");
01662 else
01663 {
01664 std::string handle = args(0).string_value ();
01665 std::string file = args(1).string_value ();
01666 std::string target;
01667
01668 if (nargin == 3)
01669 target = args(2).string_value () + file_ops::dir_sep_str ();
01670
01671 if (! error_state)
01672 {
01673 const curl_handle curl = handles.contents (handle);
01674
01675 if (curl.is_valid ())
01676 {
01677 string_vector sv = curl.list ();
01678 octave_idx_type n = 0;
01679 glob_match pattern (file);
01680
01681 for (octave_idx_type i = 0; i < sv.length (); i++)
01682 {
01683 if (pattern.match (sv(i)))
01684 {
01685 n++;
01686
01687 time_t ftime;
01688 bool fisdir;
01689 double fsize;
01690
01691 curl.get_fileinfo (sv(i), fsize, ftime, fisdir);
01692
01693 if (fisdir)
01694 getallfiles (curl, sv(i), target);
01695 else
01696 {
01697 std::ofstream ofile ((target + sv(i)).c_str(),
01698 std::ios::out |
01699 std::ios::binary);
01700
01701 if (! ofile.is_open ())
01702 {
01703 error ("__ftp_mget__: unable to open file");
01704 break;
01705 }
01706
01707 unwind_protect_safe frame;
01708
01709 frame.add_fcn (delete_file, target + sv(i));
01710
01711 curl.get (sv(i), ofile);
01712
01713 ofile.close ();
01714
01715 if (!error_state)
01716 frame.discard ();
01717 else
01718 frame.run ();
01719 }
01720
01721 if (error_state)
01722 break;
01723 }
01724 }
01725 if (n == 0)
01726 error ("__ftp_mget__: file not found");
01727 }
01728 }
01729 }
01730 #else
01731 error ("__ftp_mget__: not available in this version of Octave");
01732 #endif
01733
01734 return octave_value ();
01735 }