Mercurial > octave-nkf
comparison libinterp/dldfcn/urlwrite.cc @ 17550:77127a3badaa
move curl_object actions to rep class
* urlwrite.cc (class curl_object): Move curl actions to curl_object_rep
class. Forward all non-refcount actions to rep class.
(mput_directory): Move to curl_object_rep class. Create wrapper in
curl_object_class.
(getallfiles): Move to curl_object_rep_class, renaming to
mget_directory. Create wrapper in curl_object class.
(setopt): Delete macro.
(SETOPT, SETOPTR): New macros. Return on error.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 03 Oct 2013 09:51:56 -0400 |
parents | a646665cd574 |
children | 8fca0bbdd4c1 |
comparison
equal
deleted
inserted
replaced
17549:a646665cd574 | 17550:77127a3badaa |
---|---|
48 #include "ov-cell.h" | 48 #include "ov-cell.h" |
49 #include "pager.h" | 49 #include "pager.h" |
50 #include "oct-map.h" | 50 #include "oct-map.h" |
51 #include "oct-refcount.h" | 51 #include "oct-refcount.h" |
52 #include "unwind-prot.h" | 52 #include "unwind-prot.h" |
53 #include "gripes.h" | 53 |
54 static void | |
55 delete_file (const std::string& file) | |
56 { | |
57 octave_unlink (file); | |
58 } | |
54 | 59 |
55 #ifdef HAVE_CURL | 60 #ifdef HAVE_CURL |
56 | 61 |
57 #include <curl/curl.h> | 62 #include <curl/curl.h> |
58 #include <curl/curlver.h> | 63 #include <curl/curlver.h> |
84 } | 89 } |
85 | 90 |
86 class curl_object | 91 class curl_object |
87 { | 92 { |
88 private: | 93 private: |
94 | |
95 // I'd love to rewrite this as a private method of the curl_object | |
96 // class, but you can't pass the va_list from the wrapper SETOPT to | |
97 // the curl_easy_setopt function. | |
98 #define SETOPT(option, parameter) \ | |
99 do \ | |
100 { \ | |
101 CURLcode res = curl_easy_setopt (curl, option, parameter); \ | |
102 if (res != CURLE_OK) \ | |
103 { \ | |
104 error ("%s", curl_easy_strerror (res)); \ | |
105 return; \ | |
106 } \ | |
107 } \ | |
108 while (0) | |
109 | |
110 // Sames as above, but return retval. | |
111 #define SETOPTR(option, parameter) \ | |
112 do \ | |
113 { \ | |
114 CURLcode res = curl_easy_setopt (curl, option, parameter); \ | |
115 if (res != CURLE_OK) \ | |
116 { \ | |
117 error ("%s", curl_easy_strerror (res)); \ | |
118 return retval; \ | |
119 } \ | |
120 } \ | |
121 while (0) | |
122 | |
89 class curl_object_rep | 123 class curl_object_rep |
90 { | 124 { |
125 private: | |
126 | |
127 static void reset_path (const curl_object_rep *curl_rep) | |
128 { | |
129 curl_rep->cwd (".."); | |
130 } | |
131 | |
91 public: | 132 public: |
92 curl_object_rep (void) : count (1), valid (true), ascii (false) | 133 |
93 { | 134 curl_object_rep (void) |
94 curl = curl_easy_init (); | 135 : count (1), curl (curl_easy_init ()), host (), userpwd (), |
95 if (!curl) | 136 valid (false), ascii_mode (false), errnum () |
137 { | |
138 if (! curl) | |
139 error ("can not create curl object"); | |
140 } | |
141 | |
142 curl_object_rep (const std::string& host_arg, const std::string& user_arg, | |
143 const std::string& passwd) | |
144 : count (1), curl (curl_easy_init ()), host (host_arg), | |
145 userpwd (), valid (true), ascii_mode (false), errnum () | |
146 { | |
147 if (!curl) | |
148 { | |
149 valid = false; | |
96 error ("can not create curl object"); | 150 error ("can not create curl object"); |
97 } | 151 return; |
98 | 152 } |
99 ~curl_object_rep (void) | 153 |
100 { | 154 init (user_arg, passwd, std::cin, octave_stdout); |
101 if (curl) | 155 |
102 curl_easy_cleanup (curl); | 156 std::string url ("ftp://" + host_arg); |
103 } | 157 SETOPT (CURLOPT_URL, url.c_str ()); |
104 | 158 |
105 bool is_valid (void) const | 159 // Setup the link, with no transfer. |
106 { | 160 perform (); |
107 return valid; | 161 } |
108 } | 162 |
109 | 163 curl_object_rep (const std::string& url, const std::string& method, |
110 bool perform (bool curlerror) const | 164 const Cell& param, std::ostream& os, bool& retval) |
111 { | 165 : count (1), curl (curl_easy_init ()), host (), userpwd (), |
112 bool retval = false; | 166 valid (true), ascii_mode (false), errnum () |
113 if (!error_state) | |
114 { | |
115 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
116 | |
117 errnum = curl_easy_perform (curl); | |
118 if (errnum != CURLE_OK) | |
119 { | |
120 if (curlerror) | |
121 error ("%s", curl_easy_strerror (errnum)); | |
122 } | |
123 else | |
124 retval = true; | |
125 | |
126 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | |
127 } | |
128 return retval; | |
129 } | |
130 | |
131 CURL *object (void) const | |
132 { | |
133 return curl; | |
134 } | |
135 | |
136 bool is_ascii (void) const | |
137 { | |
138 return ascii; | |
139 } | |
140 | |
141 bool is_binary (void) const | |
142 { | |
143 return !ascii; | |
144 } | |
145 | |
146 octave_refcount<size_t> count; | |
147 std::string host; | |
148 std::string url; | |
149 std::string userpwd; | |
150 bool valid; | |
151 bool ascii; | |
152 mutable CURLcode errnum; | |
153 | |
154 private: | |
155 CURL *curl; | |
156 | |
157 // No copying! | |
158 | |
159 curl_object_rep (const curl_object_rep& ov); | |
160 | |
161 curl_object_rep& operator = (const curl_object_rep&); | |
162 }; | |
163 | |
164 public: | |
165 | |
166 // I'd love to rewrite this as a private method of the curl_object | |
167 // class, but you can't pass the va_list from the wrapper setopt to | |
168 // the curl_easy_setopt function. | |
169 #define setopt(option, parameter) \ | |
170 { \ | |
171 CURLcode res = curl_easy_setopt (rep->object (), option, parameter); \ | |
172 if (res != CURLE_OK) \ | |
173 error ("%s", curl_easy_strerror (res)); \ | |
174 } | |
175 | |
176 curl_object (void) : rep (new curl_object_rep ()) | |
177 { | |
178 rep->valid = false; | |
179 } | |
180 | |
181 curl_object (const std::string& _host, const std::string& user, | |
182 const std::string& passwd) : | |
183 rep (new curl_object_rep ()) | |
184 { | |
185 rep->host = _host; | |
186 init (user, passwd, std::cin, octave_stdout); | |
187 | |
188 rep->url = "ftp://" + _host; | |
189 setopt (CURLOPT_URL, rep->url.c_str ()); | |
190 | |
191 // Setup the link, with no transfer | |
192 if (!error_state) | |
193 perform (); | |
194 } | |
195 | |
196 curl_object (const std::string& url, const std::string& method, | |
197 const Cell& param, std::ostream& os, bool& retval) : | |
198 rep (new curl_object_rep ()) | |
199 { | 167 { |
200 retval = false; | 168 retval = false; |
201 | 169 |
170 if (!curl) | |
171 { | |
172 valid = false; | |
173 error ("can not create curl object"); | |
174 return; | |
175 } | |
176 | |
202 init ("", "", std::cin, os); | 177 init ("", "", std::cin, os); |
203 | 178 |
204 setopt (CURLOPT_NOBODY, 0); | 179 SETOPT (CURLOPT_NOBODY, 0); |
205 | 180 |
206 // Restore the default HTTP request method to GET after setting | 181 // Restore the default HTTP request method to GET after setting |
207 // NOBODY to true and back to false. This is needed for backward | 182 // NOBODY to true and back to false. This is needed for backward |
208 // compatibility with versions of libcurl < 7.18.2. | 183 // compatibility with versions of libcurl < 7.18.2. |
209 setopt (CURLOPT_HTTPGET, 1); | 184 SETOPT (CURLOPT_HTTPGET, 1); |
210 | 185 |
211 // Don't need to store the parameters here as we can't change | 186 // Don't need to store the parameters here as we can't change |
212 // the URL after the object is created | 187 // the URL after the object is created |
213 std::string query_string = form_query_string (param); | 188 std::string query_string = form_query_string (param); |
214 | 189 |
215 if (method == "get") | 190 if (method == "get") |
216 { | 191 { |
217 query_string = url + "?" + query_string; | 192 query_string = url + "?" + query_string; |
218 setopt (CURLOPT_URL, query_string.c_str ()); | 193 SETOPT (CURLOPT_URL, query_string.c_str ()); |
219 } | 194 } |
220 else if (method == "post") | 195 else if (method == "post") |
221 { | 196 { |
222 setopt (CURLOPT_URL, url.c_str ()); | 197 SETOPT (CURLOPT_URL, url.c_str ()); |
223 setopt (CURLOPT_POSTFIELDS, query_string.c_str ()); | 198 SETOPT (CURLOPT_POSTFIELDS, query_string.c_str ()); |
224 } | 199 } |
225 else | 200 else |
226 setopt (CURLOPT_URL, url.c_str ()); | 201 SETOPT (CURLOPT_URL, url.c_str ()); |
227 | 202 |
228 if (!error_state) | 203 retval = perform (false); |
229 retval = perform (false); | 204 } |
230 } | 205 |
231 | 206 ~curl_object_rep (void) |
232 curl_object (const curl_object& h) : rep (h.rep) | 207 { |
233 { | 208 if (curl) |
234 rep->count++; | 209 curl_easy_cleanup (curl); |
235 } | 210 } |
236 | 211 |
237 ~curl_object (void) | 212 bool is_valid (void) const { return valid; } |
238 { | 213 |
239 if (--rep->count == 0) | 214 bool perform (bool curlerror = true) const |
240 delete rep; | 215 { |
241 } | 216 bool retval = false; |
242 | 217 |
243 curl_object& operator = (const curl_object& h) | 218 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
244 { | 219 |
245 if (this != &h) | 220 errnum = curl_easy_perform (curl); |
246 { | 221 if (errnum != CURLE_OK) |
247 if (--rep->count == 0) | 222 { |
248 delete rep; | 223 if (curlerror) |
249 | 224 error ("%s", curl_easy_strerror (errnum)); |
250 rep = h.rep; | 225 } |
251 rep->count++; | 226 else |
252 } | 227 retval = true; |
253 return *this; | 228 |
254 } | 229 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
255 | 230 |
256 bool is_valid (void) const | 231 return retval; |
257 { | 232 } |
258 return rep->is_valid (); | 233 |
259 } | 234 std::string lasterror (void) const |
260 | 235 { |
261 std::string lasterror (void) const | 236 return std::string (curl_easy_strerror (errnum)); |
262 { | 237 } |
263 return std::string (curl_easy_strerror (rep->errnum)); | 238 |
264 } | 239 void set_ostream (std::ostream& os) const |
265 | 240 { |
266 void set_ostream (std::ostream& os) const | 241 SETOPT (CURLOPT_WRITEDATA, static_cast<void*> (&os)); |
267 { | 242 } |
268 setopt (CURLOPT_WRITEDATA, static_cast<void*> (&os)); | 243 |
269 } | 244 void set_istream (std::istream& is) const |
270 | 245 { |
271 void set_istream (std::istream& is) const | 246 SETOPT (CURLOPT_READDATA, static_cast<void*> (&is)); |
272 { | 247 } |
273 setopt (CURLOPT_READDATA, static_cast<void*> (&is)); | 248 |
274 } | 249 void ascii (void) |
275 | 250 { |
276 void ascii (void) const | 251 SETOPT (CURLOPT_TRANSFERTEXT, 1); |
277 { | 252 ascii_mode = true; |
278 setopt (CURLOPT_TRANSFERTEXT, 1); | 253 } |
279 rep->ascii = true; | 254 |
280 } | 255 void binary (void) |
281 | 256 { |
282 void binary (void) const | 257 SETOPT (CURLOPT_TRANSFERTEXT, 0); |
283 { | 258 ascii_mode = false; |
284 setopt (CURLOPT_TRANSFERTEXT, 0); | 259 } |
285 rep->ascii = false; | 260 |
286 } | 261 bool is_ascii (void) const { return ascii_mode; } |
287 | 262 |
288 bool is_ascii (void) const | 263 bool is_binary (void) const { return !ascii_mode; } |
289 { | 264 |
290 return rep->is_ascii (); | 265 void cwd (const std::string& path) const |
291 } | |
292 | |
293 bool is_binary (void) const | |
294 { | |
295 return rep->is_binary (); | |
296 } | |
297 | |
298 void cwd (const std::string& path) const | |
299 { | 266 { |
300 struct curl_slist *slist = 0; | 267 struct curl_slist *slist = 0; |
301 std::string cmd = "cwd " + path; | 268 std::string cmd = "cwd " + path; |
302 slist = curl_slist_append (slist, cmd.c_str ()); | 269 slist = curl_slist_append (slist, cmd.c_str ()); |
303 setopt (CURLOPT_POSTQUOTE, slist); | 270 SETOPT (CURLOPT_POSTQUOTE, slist); |
304 if (! error_state) | 271 perform (); |
305 perform (); | 272 SETOPT (CURLOPT_POSTQUOTE, 0); |
306 setopt (CURLOPT_POSTQUOTE, 0); | |
307 curl_slist_free_all (slist); | 273 curl_slist_free_all (slist); |
308 } | 274 } |
309 | 275 |
310 void del (const std::string& file) const | 276 void del (const std::string& file) const |
311 { | 277 { |
312 struct curl_slist *slist = 0; | 278 struct curl_slist *slist = 0; |
313 std::string cmd = "dele " + file; | 279 std::string cmd = "dele " + file; |
314 slist = curl_slist_append (slist, cmd.c_str ()); | 280 slist = curl_slist_append (slist, cmd.c_str ()); |
315 setopt (CURLOPT_POSTQUOTE, slist); | 281 SETOPT (CURLOPT_POSTQUOTE, slist); |
316 if (! error_state) | 282 perform (); |
317 perform (); | 283 SETOPT (CURLOPT_POSTQUOTE, 0); |
318 setopt (CURLOPT_POSTQUOTE, 0); | |
319 curl_slist_free_all (slist); | 284 curl_slist_free_all (slist); |
320 } | 285 } |
321 | 286 |
322 void rmdir (const std::string& path) const | 287 void rmdir (const std::string& path) const |
323 { | 288 { |
324 struct curl_slist *slist = 0; | 289 struct curl_slist *slist = 0; |
325 std::string cmd = "rmd " + path; | 290 std::string cmd = "rmd " + path; |
326 slist = curl_slist_append (slist, cmd.c_str ()); | 291 slist = curl_slist_append (slist, cmd.c_str ()); |
327 setopt (CURLOPT_POSTQUOTE, slist); | 292 SETOPT (CURLOPT_POSTQUOTE, slist); |
328 if (! error_state) | 293 perform (); |
329 perform (); | 294 SETOPT (CURLOPT_POSTQUOTE, 0); |
330 setopt (CURLOPT_POSTQUOTE, 0); | |
331 curl_slist_free_all (slist); | 295 curl_slist_free_all (slist); |
332 } | 296 } |
333 | 297 |
334 bool mkdir (const std::string& path, bool curlerror = true) const | 298 bool mkdir (const std::string& path, bool curlerror = true) const |
335 { | 299 { |
336 bool retval = false; | 300 bool retval = false; |
337 struct curl_slist *slist = 0; | 301 struct curl_slist *slist = 0; |
338 std::string cmd = "mkd " + path; | 302 std::string cmd = "mkd " + path; |
339 slist = curl_slist_append (slist, cmd.c_str ()); | 303 slist = curl_slist_append (slist, cmd.c_str ()); |
340 setopt (CURLOPT_POSTQUOTE, slist); | 304 SETOPTR (CURLOPT_POSTQUOTE, slist); |
341 if (! error_state) | 305 retval = perform (curlerror); |
342 retval = perform (curlerror); | 306 SETOPTR (CURLOPT_POSTQUOTE, 0); |
343 setopt (CURLOPT_POSTQUOTE, 0); | |
344 curl_slist_free_all (slist); | 307 curl_slist_free_all (slist); |
345 return retval; | 308 return retval; |
346 } | 309 } |
347 | 310 |
348 void rename (const std::string& oldname, const std::string& newname) const | 311 void rename (const std::string& oldname, const std::string& newname) const |
349 { | 312 { |
350 struct curl_slist *slist = 0; | 313 struct curl_slist *slist = 0; |
351 std::string cmd = "rnfr " + oldname; | 314 std::string cmd = "rnfr " + oldname; |
352 slist = curl_slist_append (slist, cmd.c_str ()); | 315 slist = curl_slist_append (slist, cmd.c_str ()); |
353 cmd = "rnto " + newname; | 316 cmd = "rnto " + newname; |
354 slist = curl_slist_append (slist, cmd.c_str ()); | 317 slist = curl_slist_append (slist, cmd.c_str ()); |
355 setopt (CURLOPT_POSTQUOTE, slist); | 318 SETOPT (CURLOPT_POSTQUOTE, slist); |
319 perform (); | |
320 SETOPT (CURLOPT_POSTQUOTE, 0); | |
321 curl_slist_free_all (slist); | |
322 } | |
323 | |
324 void put (const std::string& file, std::istream& is) const | |
325 { | |
326 std::string url = "ftp://" + host + "/" + file; | |
327 SETOPT (CURLOPT_URL, url.c_str ()); | |
328 SETOPT (CURLOPT_UPLOAD, 1); | |
329 SETOPT (CURLOPT_NOBODY, 0); | |
330 set_istream (is); | |
331 perform (); | |
332 set_istream (std::cin); | |
333 SETOPT (CURLOPT_NOBODY, 1); | |
334 SETOPT (CURLOPT_UPLOAD, 0); | |
335 url = "ftp://" + host; | |
336 SETOPT (CURLOPT_URL, url.c_str ()); | |
337 } | |
338 | |
339 void get (const std::string& file, std::ostream& os) const | |
340 { | |
341 std::string url = "ftp://" + host + "/" + file; | |
342 SETOPT (CURLOPT_URL, url.c_str ()); | |
343 SETOPT (CURLOPT_NOBODY, 0); | |
344 set_ostream (os); | |
345 perform (); | |
346 set_ostream (octave_stdout); | |
347 SETOPT (CURLOPT_NOBODY, 1); | |
348 url = "ftp://" + host; | |
349 SETOPT (CURLOPT_URL, url.c_str ()); | |
350 } | |
351 | |
352 void mget_directory (const std::string& directory, | |
353 const std::string& target) const | |
354 { | |
355 std::string sep = file_ops::dir_sep_str (); | |
356 file_stat fs (directory); | |
357 | |
358 if (!fs || !fs.is_dir ()) | |
359 { | |
360 std::string msg; | |
361 int status = octave_mkdir (directory, 0777, msg); | |
362 | |
363 if (status < 0) | |
364 { | |
365 error ("__ftp_mget__: can't create directory %s%s%s. %s", | |
366 target.c_str (), sep.c_str (), directory.c_str (), | |
367 msg.c_str ()); | |
368 | |
369 return; | |
370 } | |
371 } | |
372 | |
373 cwd (directory); | |
374 | |
356 if (! error_state) | 375 if (! error_state) |
357 perform (); | 376 { |
358 setopt (CURLOPT_POSTQUOTE, 0); | 377 unwind_protect_safe frame; |
359 curl_slist_free_all (slist); | 378 |
360 } | 379 frame.add_fcn (reset_path, this); |
361 | 380 |
362 void put (const std::string& file, std::istream& is) const | 381 string_vector sv = list (); |
363 { | 382 |
364 rep->url = "ftp://" + rep->host + "/" + file; | 383 for (octave_idx_type i = 0; i < sv.length (); i++) |
365 setopt (CURLOPT_URL, rep->url.c_str ()); | 384 { |
366 setopt (CURLOPT_UPLOAD, 1); | 385 time_t ftime; |
367 setopt (CURLOPT_NOBODY, 0); | 386 bool fisdir; |
368 set_istream (is); | 387 double fsize; |
388 | |
389 get_fileinfo (sv(i), fsize, ftime, fisdir); | |
390 | |
391 if (fisdir) | |
392 mget_directory (sv(i), target + directory + sep); | |
393 else | |
394 { | |
395 std::string realfile = target + directory + sep + sv(i); | |
396 | |
397 std::ofstream ofile (realfile.c_str (), | |
398 std::ios::out | std::ios::binary); | |
399 | |
400 if (! ofile.is_open ()) | |
401 { | |
402 error ("__ftp_mget__: unable to open file"); | |
403 break; | |
404 } | |
405 | |
406 unwind_protect_safe frame2; | |
407 | |
408 frame2.add_fcn (delete_file, realfile); | |
409 | |
410 get (sv(i), ofile); | |
411 | |
412 ofile.close (); | |
413 | |
414 if (!error_state) | |
415 frame2.discard (); | |
416 else | |
417 frame2.run (); | |
418 } | |
419 | |
420 if (error_state) | |
421 break; | |
422 } | |
423 } | |
424 } | |
425 | |
426 string_vector mput_directory (const std::string& base, | |
427 const std::string& directory) const | |
428 { | |
429 string_vector retval; | |
430 | |
431 std::string realdir | |
432 = (base.length () == 0 | |
433 ? directory : base + file_ops::dir_sep_str () + directory); | |
434 | |
435 if (! mkdir (directory, false)) | |
436 warning ("__ftp_mput__: can not create the remote directory ""%s""", | |
437 realdir.c_str ()); | |
438 | |
439 cwd (directory); | |
440 | |
369 if (! error_state) | 441 if (! error_state) |
370 perform (); | 442 { |
371 set_istream (std::cin); | 443 unwind_protect_safe frame; |
372 setopt (CURLOPT_NOBODY, 1); | 444 |
373 setopt (CURLOPT_UPLOAD, 0); | 445 frame.add_fcn (reset_path, this); |
374 rep->url = "ftp://" + rep->host; | 446 |
375 setopt (CURLOPT_URL, rep->url.c_str ()); | 447 dir_entry dirlist (realdir); |
376 } | 448 |
377 | 449 if (dirlist) |
378 void get (const std::string& file, std::ostream& os) const | 450 { |
379 { | 451 string_vector files = dirlist.read (); |
380 rep->url = "ftp://" + rep->host + "/" + file; | 452 |
381 setopt (CURLOPT_URL, rep->url.c_str ()); | 453 for (octave_idx_type i = 0; i < files.length (); i++) |
382 setopt (CURLOPT_NOBODY, 0); | 454 { |
383 set_ostream (os); | 455 std::string file = files (i); |
384 if (! error_state) | 456 |
385 perform (); | 457 if (file == "." || file == "..") |
386 set_ostream (octave_stdout); | 458 continue; |
387 setopt (CURLOPT_NOBODY, 1); | 459 |
388 rep->url = "ftp://" + rep->host; | 460 std::string realfile = realdir + file_ops::dir_sep_str () + file; |
389 setopt (CURLOPT_URL, rep->url.c_str ()); | 461 file_stat fs (realfile); |
390 } | 462 |
391 | 463 if (! fs.exists ()) |
392 void dir (void) const | 464 { |
393 { | 465 error ("__ftp__mput: file ""%s"" does not exist", |
394 rep->url = "ftp://" + rep->host + "/"; | 466 realfile.c_str ()); |
395 setopt (CURLOPT_URL, rep->url.c_str ()); | 467 break; |
396 setopt (CURLOPT_NOBODY, 0); | 468 } |
397 if (! error_state) | 469 |
398 perform (); | 470 if (fs.is_dir ()) |
399 setopt (CURLOPT_NOBODY, 1); | 471 { |
400 rep->url = "ftp://" + rep->host; | 472 retval.append (mput_directory (realdir, file)); |
401 setopt (CURLOPT_URL, rep->url.c_str ()); | 473 |
402 } | 474 if (error_state) |
403 | 475 break; |
404 string_vector list (void) const | 476 } |
405 { | 477 else |
478 { | |
479 // FIXME Does ascii mode need to be flagged here? | |
480 std::ifstream ifile (realfile.c_str (), std::ios::in | | |
481 std::ios::binary); | |
482 | |
483 if (! ifile.is_open ()) | |
484 { | |
485 error ("__ftp_mput__: unable to open file ""%s""", | |
486 realfile.c_str ()); | |
487 break; | |
488 } | |
489 | |
490 put (file, ifile); | |
491 | |
492 ifile.close (); | |
493 | |
494 if (error_state) | |
495 break; | |
496 | |
497 retval.append (realfile); | |
498 } | |
499 } | |
500 } | |
501 else | |
502 error ("__ftp_mput__: can not read the directory ""%s""", | |
503 realdir.c_str ()); | |
504 } | |
505 | |
506 return retval; | |
507 } | |
508 | |
509 void dir (void) const | |
510 { | |
511 std::string url = "ftp://" + host + "/"; | |
512 SETOPT (CURLOPT_URL, url.c_str ()); | |
513 SETOPT (CURLOPT_NOBODY, 0); | |
514 perform (); | |
515 SETOPT (CURLOPT_NOBODY, 1); | |
516 url = "ftp://" + host; | |
517 SETOPT (CURLOPT_URL, url.c_str ()); | |
518 } | |
519 | |
520 string_vector list (void) const | |
521 { | |
522 string_vector retval; | |
406 std::ostringstream buf; | 523 std::ostringstream buf; |
407 rep->url = "ftp://" + rep->host + "/"; | 524 std::string url = "ftp://" + host + "/"; |
408 setopt (CURLOPT_WRITEDATA, static_cast<void*> (&buf)); | 525 SETOPTR (CURLOPT_WRITEDATA, static_cast<void*> (&buf)); |
409 setopt (CURLOPT_URL, rep->url.c_str ()); | 526 SETOPTR (CURLOPT_URL, url.c_str ()); |
410 setopt (CURLOPT_DIRLISTONLY, 1); | 527 SETOPTR (CURLOPT_DIRLISTONLY, 1); |
411 setopt (CURLOPT_NOBODY, 0); | 528 SETOPTR (CURLOPT_NOBODY, 0); |
412 if (! error_state) | 529 perform (); |
413 perform (); | 530 SETOPTR (CURLOPT_NOBODY, 1); |
414 setopt (CURLOPT_NOBODY, 1); | 531 url = "ftp://" + host; |
415 rep->url = "ftp://" + rep->host; | 532 SETOPTR (CURLOPT_WRITEDATA, static_cast<void*> (&octave_stdout)); |
416 setopt (CURLOPT_WRITEDATA, static_cast<void*> (&octave_stdout)); | 533 SETOPTR (CURLOPT_DIRLISTONLY, 0); |
417 setopt (CURLOPT_DIRLISTONLY, 0); | 534 SETOPTR (CURLOPT_URL, url.c_str ()); |
418 setopt (CURLOPT_URL, rep->url.c_str ()); | |
419 | 535 |
420 // Count number of directory entries | 536 // Count number of directory entries |
421 std::string str = buf.str (); | 537 std::string str = buf.str (); |
422 octave_idx_type n = 0; | 538 octave_idx_type n = 0; |
423 size_t pos = 0; | 539 size_t pos = 0; |
427 if (pos == std::string::npos) | 543 if (pos == std::string::npos) |
428 break; | 544 break; |
429 pos++; | 545 pos++; |
430 n++; | 546 n++; |
431 } | 547 } |
432 string_vector retval (n); | 548 retval.resize (n); |
433 pos = 0; | 549 pos = 0; |
434 for (octave_idx_type i = 0; i < n; i++) | 550 for (octave_idx_type i = 0; i < n; i++) |
435 { | 551 { |
436 size_t newpos = str.find_first_of ('\n', pos); | 552 size_t newpos = str.find_first_of ('\n', pos); |
437 if (newpos == std::string::npos) | 553 if (newpos == std::string::npos) |
441 pos = newpos + 1; | 557 pos = newpos + 1; |
442 } | 558 } |
443 return retval; | 559 return retval; |
444 } | 560 } |
445 | 561 |
446 void get_fileinfo (const std::string& filename, double& filesize, | 562 void get_fileinfo (const std::string& filename, double& filesize, |
447 time_t& filetime, bool& fileisdir) const | 563 time_t& filetime, bool& fileisdir) const |
448 { | 564 { |
449 std::string path = pwd (); | 565 std::string path = pwd (); |
450 | 566 |
451 rep->url = "ftp://" + rep->host + "/" + path + "/" + filename; | 567 std::string url = "ftp://" + host + "/" + path + "/" + filename; |
452 setopt (CURLOPT_URL, rep->url.c_str ()); | 568 SETOPT (CURLOPT_URL, url.c_str ()); |
453 setopt (CURLOPT_FILETIME, 1); | 569 SETOPT (CURLOPT_FILETIME, 1); |
454 setopt (CURLOPT_HEADERFUNCTION, throw_away); | 570 SETOPT (CURLOPT_HEADERFUNCTION, throw_away); |
455 setopt (CURLOPT_WRITEFUNCTION, throw_away); | 571 SETOPT (CURLOPT_WRITEFUNCTION, throw_away); |
456 | 572 |
457 // FIXME | 573 // FIXME |
458 // The MDTM command fails for a directory on the servers I tested | 574 // The MDTM command fails for a directory on the servers I tested |
459 // so this is a means of testing for directories. It also means | 575 // so this is a means of testing for directories. It also means |
460 // I can't get the date of directories! | 576 // I can't get the date of directories! |
461 if (! error_state) | 577 |
462 { | 578 if (! perform (false)) |
463 if (! perform (false)) | 579 { |
464 { | 580 fileisdir = true; |
465 fileisdir = true; | 581 filetime = -1; |
466 filetime = -1; | 582 filesize = 0; |
467 filesize = 0; | 583 } |
468 } | 584 else |
469 else | 585 { |
470 { | 586 fileisdir = false; |
471 fileisdir = false; | 587 time_t ft; |
472 time_t ft; | 588 curl_easy_getinfo (curl, CURLINFO_FILETIME, &ft); |
473 curl_easy_getinfo (rep->object (), CURLINFO_FILETIME, &ft); | 589 filetime = ft; |
474 filetime = ft; | 590 double fs; |
475 double fs; | 591 curl_easy_getinfo (curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &fs); |
476 curl_easy_getinfo (rep->object (), | 592 filesize = fs; |
477 CURLINFO_CONTENT_LENGTH_DOWNLOAD, &fs); | 593 } |
478 filesize = fs; | 594 |
479 } | 595 SETOPT (CURLOPT_WRITEFUNCTION, write_data); |
480 } | 596 SETOPT (CURLOPT_HEADERFUNCTION, 0); |
481 | 597 SETOPT (CURLOPT_FILETIME, 0); |
482 setopt (CURLOPT_WRITEFUNCTION, write_data); | 598 url = "ftp://" + host; |
483 setopt (CURLOPT_HEADERFUNCTION, 0); | 599 SETOPT (CURLOPT_URL, url.c_str ()); |
484 setopt (CURLOPT_FILETIME, 0); | |
485 rep->url = "ftp://" + rep->host; | |
486 setopt (CURLOPT_URL, rep->url.c_str ()); | |
487 | 600 |
488 // The MDTM command seems to reset the path to the root with the | 601 // The MDTM command seems to reset the path to the root with the |
489 // servers I tested with, so cd again into the correct path. Make | 602 // servers I tested with, so cd again into the correct path. Make |
490 // the path absolute so that this will work even with servers that | 603 // the path absolute so that this will work even with servers that |
491 // don't end up in the root after an MDTM command. | 604 // don't end up in the root after an MDTM command. |
492 cwd ("/" + path); | 605 cwd ("/" + path); |
493 } | 606 } |
494 | 607 |
495 std::string pwd (void) const | 608 std::string pwd (void) const |
496 { | 609 { |
497 struct curl_slist *slist = 0; | 610 struct curl_slist *slist = 0; |
498 std::string retval; | 611 std::string retval; |
499 std::ostringstream buf; | 612 std::ostringstream buf; |
500 | 613 |
501 slist = curl_slist_append (slist, "pwd"); | 614 slist = curl_slist_append (slist, "pwd"); |
502 setopt (CURLOPT_POSTQUOTE, slist); | 615 SETOPTR (CURLOPT_POSTQUOTE, slist); |
503 setopt (CURLOPT_HEADERFUNCTION, write_data); | 616 SETOPTR (CURLOPT_HEADERFUNCTION, write_data); |
504 setopt (CURLOPT_WRITEHEADER, static_cast<void *>(&buf)); | 617 SETOPTR (CURLOPT_WRITEHEADER, static_cast<void *>(&buf)); |
505 | 618 |
506 if (! error_state) | 619 perform (); |
507 { | 620 retval = buf.str (); |
508 perform (); | 621 |
509 retval = buf.str (); | 622 // Can I assume that the path is alway in "" on the last line |
510 | 623 size_t pos2 = retval.rfind ('"'); |
511 // Can I assume that the path is alway in "" on the last line | 624 size_t pos1 = retval.rfind ('"', pos2 - 1); |
512 size_t pos2 = retval.rfind ('"'); | 625 retval = retval.substr (pos1 + 1, pos2 - pos1 - 1); |
513 size_t pos1 = retval.rfind ('"', pos2 - 1); | 626 |
514 retval = retval.substr (pos1 + 1, pos2 - pos1 - 1); | 627 SETOPTR (CURLOPT_HEADERFUNCTION, 0); |
515 } | 628 SETOPTR (CURLOPT_WRITEHEADER, 0); |
516 setopt (CURLOPT_HEADERFUNCTION, 0); | 629 SETOPTR (CURLOPT_POSTQUOTE, 0); |
517 setopt (CURLOPT_WRITEHEADER, 0); | |
518 setopt (CURLOPT_POSTQUOTE, 0); | |
519 curl_slist_free_all (slist); | 630 curl_slist_free_all (slist); |
520 | 631 |
521 return retval; | 632 return retval; |
522 } | 633 } |
523 | 634 |
524 bool perform (bool curlerror = true) const | 635 octave_refcount<size_t> count; |
525 { | 636 |
526 return rep->perform (curlerror); | 637 private: |
527 } | 638 |
528 | 639 CURL *curl; |
529 private: | 640 std::string host; |
530 curl_object_rep *rep; | 641 std::string userpwd; |
531 | 642 bool valid; |
532 std::string form_query_string (const Cell& param) | 643 bool ascii_mode; |
533 { | 644 mutable CURLcode errnum; |
534 std::ostringstream query; | 645 |
535 | 646 // No copying! |
536 for (int i = 0; i < param.numel (); i += 2) | 647 |
537 { | 648 curl_object_rep (const curl_object_rep& ov); |
538 std::string name = param(i).string_value (); | 649 |
539 std::string text = param(i+1).string_value (); | 650 curl_object_rep& operator = (const curl_object_rep&); |
540 | 651 |
541 // Encode strings. | 652 void init (const std::string& user, const std::string& passwd, |
542 char *enc_name = curl_easy_escape (rep->object (), name.c_str (), | 653 std::istream& is, std::ostream& os) |
543 name.length ()); | |
544 char *enc_text = curl_easy_escape (rep->object (), text.c_str (), | |
545 text.length ()); | |
546 | |
547 query << enc_name << "=" << enc_text; | |
548 | |
549 curl_free (enc_name); | |
550 curl_free (enc_text); | |
551 | |
552 if (i < param.numel ()-1) | |
553 query << "&"; | |
554 } | |
555 | |
556 query.flush (); | |
557 | |
558 return query.str (); | |
559 } | |
560 | |
561 void init (const std::string& user, const std::string& passwd, | |
562 std::istream& is, std::ostream& os) | |
563 { | 654 { |
564 // No data transfer by default | 655 // No data transfer by default |
565 setopt (CURLOPT_NOBODY, 1); | 656 SETOPT (CURLOPT_NOBODY, 1); |
566 | 657 |
567 // Set the username and password | 658 // Set the username and password |
568 rep->userpwd = user; | 659 userpwd = user; |
569 if (! passwd.empty ()) | 660 if (! passwd.empty ()) |
570 rep->userpwd += ":" + passwd; | 661 userpwd += ":" + passwd; |
571 if (! rep->userpwd.empty ()) | 662 if (! userpwd.empty ()) |
572 setopt (CURLOPT_USERPWD, rep->userpwd.c_str ()); | 663 SETOPT (CURLOPT_USERPWD, userpwd.c_str ()); |
573 | 664 |
574 // Define our callback to get called when there's data to be written. | 665 // Define our callback to get called when there's data to be written. |
575 setopt (CURLOPT_WRITEFUNCTION, write_data); | 666 SETOPT (CURLOPT_WRITEFUNCTION, write_data); |
576 | 667 |
577 // Set a pointer to our struct to pass to the callback. | 668 // Set a pointer to our struct to pass to the callback. |
578 setopt (CURLOPT_WRITEDATA, static_cast<void*> (&os)); | 669 SETOPT (CURLOPT_WRITEDATA, static_cast<void*> (&os)); |
579 | 670 |
580 // Define our callback to get called when there's data to be read | 671 // Define our callback to get called when there's data to be read |
581 setopt (CURLOPT_READFUNCTION, read_data); | 672 SETOPT (CURLOPT_READFUNCTION, read_data); |
582 | 673 |
583 // Set a pointer to our struct to pass to the callback. | 674 // Set a pointer to our struct to pass to the callback. |
584 setopt (CURLOPT_READDATA, static_cast<void*> (&is)); | 675 SETOPT (CURLOPT_READDATA, static_cast<void*> (&is)); |
585 | 676 |
586 // Follow redirects. | 677 // Follow redirects. |
587 setopt (CURLOPT_FOLLOWLOCATION, true); | 678 SETOPT (CURLOPT_FOLLOWLOCATION, true); |
588 | 679 |
589 // Don't use EPSV since connecting to sites that don't support it | 680 // Don't use EPSV since connecting to sites that don't support it |
590 // will hang for some time (3 minutes?) before moving on to try PASV | 681 // will hang for some time (3 minutes?) before moving on to try PASV |
591 // instead. | 682 // instead. |
592 setopt (CURLOPT_FTP_USE_EPSV, false); | 683 SETOPT (CURLOPT_FTP_USE_EPSV, false); |
593 | 684 |
594 setopt (CURLOPT_NOPROGRESS, true); | 685 SETOPT (CURLOPT_NOPROGRESS, true); |
595 setopt (CURLOPT_FAILONERROR, true); | 686 SETOPT (CURLOPT_FAILONERROR, true); |
596 | 687 |
597 setopt (CURLOPT_POSTQUOTE, 0); | 688 SETOPT (CURLOPT_POSTQUOTE, 0); |
598 setopt (CURLOPT_QUOTE, 0); | 689 SETOPT (CURLOPT_QUOTE, 0); |
599 } | 690 } |
600 | 691 |
601 #undef setopt | 692 std::string form_query_string (const Cell& param) |
693 { | |
694 std::ostringstream query; | |
695 | |
696 for (int i = 0; i < param.numel (); i += 2) | |
697 { | |
698 std::string name = param(i).string_value (); | |
699 std::string text = param(i+1).string_value (); | |
700 | |
701 // Encode strings. | |
702 char *enc_name = curl_easy_escape (curl, name.c_str (), | |
703 name.length ()); | |
704 char *enc_text = curl_easy_escape (curl, text.c_str (), | |
705 text.length ()); | |
706 | |
707 query << enc_name << "=" << enc_text; | |
708 | |
709 curl_free (enc_name); | |
710 curl_free (enc_text); | |
711 | |
712 if (i < param.numel ()-1) | |
713 query << "&"; | |
714 } | |
715 | |
716 query.flush (); | |
717 | |
718 return query.str (); | |
719 } | |
720 #undef SETOPT | |
721 #undef SETOPTR | |
722 }; | |
723 | |
724 public: | |
725 | |
726 curl_object (void) : rep (new curl_object_rep ()) { } | |
727 | |
728 curl_object (const std::string& host, const std::string& user, | |
729 const std::string& passwd) | |
730 : rep (new curl_object_rep (host, user, passwd)) { } | |
731 | |
732 curl_object (const std::string& url, const std::string& method, | |
733 const Cell& param, std::ostream& os, bool& retval) | |
734 : rep (new curl_object_rep (url, method, param, os, retval)) { } | |
735 | |
736 curl_object (const curl_object& h) : rep (h.rep) | |
737 { | |
738 rep->count++; | |
739 } | |
740 | |
741 ~curl_object (void) | |
742 { | |
743 if (--rep->count == 0) | |
744 delete rep; | |
745 } | |
746 | |
747 curl_object& operator = (const curl_object& h) | |
748 { | |
749 if (this != &h) | |
750 { | |
751 if (--rep->count == 0) | |
752 delete rep; | |
753 | |
754 rep = h.rep; | |
755 rep->count++; | |
756 } | |
757 | |
758 return *this; | |
759 } | |
760 | |
761 bool is_valid (void) const { return rep->is_valid (); } | |
762 | |
763 std::string lasterror (void) const { return rep->lasterror (); } | |
764 | |
765 void set_ostream (std::ostream& os) const { rep->set_ostream (os); } | |
766 | |
767 void set_istream (std::istream& is) const { rep->set_istream (is); } | |
768 | |
769 void ascii (void) const { rep->ascii (); } | |
770 | |
771 void binary (void) const { rep->binary (); } | |
772 | |
773 bool is_ascii (void) const { return rep->is_ascii (); } | |
774 | |
775 bool is_binary (void) const { return rep->is_binary (); } | |
776 | |
777 void cwd (const std::string& path) const { rep->cwd (path); } | |
778 | |
779 void del (const std::string& file) const { rep->del (file); } | |
780 | |
781 void rmdir (const std::string& path) const { rep->rmdir (path); } | |
782 | |
783 bool mkdir (const std::string& path, bool curlerror = true) const | |
784 { | |
785 return rep->mkdir (path, curlerror); | |
786 } | |
787 | |
788 void rename (const std::string& oldname, const std::string& newname) const | |
789 { | |
790 rep->rename (oldname, newname); | |
791 } | |
792 | |
793 void put (const std::string& file, std::istream& is) const | |
794 { | |
795 rep->put (file, is); | |
796 } | |
797 | |
798 void get (const std::string& file, std::ostream& os) const | |
799 { | |
800 rep->get (file, os); | |
801 } | |
802 | |
803 void mget_directory (const std::string& directory, | |
804 const std::string& target) const | |
805 { | |
806 return rep->mget_directory (directory, target); | |
807 } | |
808 | |
809 string_vector mput_directory (const std::string& base, | |
810 const std::string& directory) const | |
811 { | |
812 return mput_directory (base, directory); | |
813 } | |
814 | |
815 void dir (void) const { rep->dir (); } | |
816 | |
817 string_vector list (void) const { return rep->list (); } | |
818 | |
819 void get_fileinfo (const std::string& filename, double& filesize, | |
820 time_t& filetime, bool& fileisdir) const | |
821 { | |
822 rep->get_fileinfo (filename, filesize, filetime, fileisdir); | |
823 } | |
824 | |
825 std::string pwd (void) const { return rep->pwd (); } | |
826 | |
827 private: | |
828 | |
829 curl_object_rep *rep; | |
602 }; | 830 }; |
603 | 831 |
604 typedef octave_handle curl_handle; | 832 typedef octave_handle curl_handle; |
605 | 833 |
606 class OCTINTERP_API ch_manager | 834 class OCTINTERP_API ch_manager |
824 error ("ch_manager::free: invalid object %g", h.value ()); | 1052 error ("ch_manager::free: invalid object %g", h.value ()); |
825 } | 1053 } |
826 } | 1054 } |
827 | 1055 |
828 ch_manager *ch_manager::instance = 0; | 1056 ch_manager *ch_manager::instance = 0; |
829 | |
830 static void | |
831 reset_path (const curl_object& curl) | |
832 { | |
833 curl.cwd (".."); | |
834 } | |
835 | |
836 static void | |
837 delete_file (std::string file) | |
838 { | |
839 octave_unlink (file); | |
840 } | |
841 | 1057 |
842 #endif | 1058 #endif |
843 | 1059 |
844 DEFUN_DLD (urlwrite, args, nargout, | 1060 DEFUN_DLD (urlwrite, args, nargout, |
845 "-*- texinfo -*-\n\ | 1061 "-*- texinfo -*-\n\ |
1561 #endif | 1777 #endif |
1562 | 1778 |
1563 return octave_value (); | 1779 return octave_value (); |
1564 } | 1780 } |
1565 | 1781 |
1566 #ifdef HAVE_CURL | |
1567 static string_vector | |
1568 mput_directory (const curl_object& curl, const std::string& base, | |
1569 const std::string& dir) | |
1570 { | |
1571 string_vector retval; | |
1572 | |
1573 if (! curl.mkdir (dir, false)) | |
1574 warning ("__ftp_mput__: can not create the remote directory ""%s""", | |
1575 (base.length () == 0 ? dir : base + | |
1576 file_ops::dir_sep_str () + dir).c_str ()); | |
1577 | |
1578 curl.cwd (dir); | |
1579 | |
1580 if (! error_state) | |
1581 { | |
1582 unwind_protect_safe frame; | |
1583 | |
1584 frame.add_fcn (reset_path, curl); | |
1585 | |
1586 std::string realdir = base.length () == 0 ? dir : base + | |
1587 file_ops::dir_sep_str () + dir; | |
1588 | |
1589 dir_entry dirlist (realdir); | |
1590 | |
1591 if (dirlist) | |
1592 { | |
1593 string_vector files = dirlist.read (); | |
1594 | |
1595 for (octave_idx_type i = 0; i < files.length (); i++) | |
1596 { | |
1597 std::string file = files (i); | |
1598 | |
1599 if (file == "." || file == "..") | |
1600 continue; | |
1601 | |
1602 std::string realfile = realdir + file_ops::dir_sep_str () + file; | |
1603 file_stat fs (realfile); | |
1604 | |
1605 if (! fs.exists ()) | |
1606 { | |
1607 error ("__ftp__mput: file ""%s"" does not exist", | |
1608 realfile.c_str ()); | |
1609 break; | |
1610 } | |
1611 | |
1612 if (fs.is_dir ()) | |
1613 { | |
1614 retval.append (mput_directory (curl, realdir, file)); | |
1615 | |
1616 if (error_state) | |
1617 break; | |
1618 } | |
1619 else | |
1620 { | |
1621 // FIXME Does ascii mode need to be flagged here? | |
1622 std::ifstream ifile (realfile.c_str (), std::ios::in | | |
1623 std::ios::binary); | |
1624 | |
1625 if (! ifile.is_open ()) | |
1626 { | |
1627 error ("__ftp_mput__: unable to open file ""%s""", | |
1628 realfile.c_str ()); | |
1629 break; | |
1630 } | |
1631 | |
1632 curl.put (file, ifile); | |
1633 | |
1634 ifile.close (); | |
1635 | |
1636 if (error_state) | |
1637 break; | |
1638 | |
1639 retval.append (realfile); | |
1640 } | |
1641 } | |
1642 } | |
1643 else | |
1644 error ("__ftp_mput__: can not read the directory ""%s""", | |
1645 realdir.c_str ()); | |
1646 } | |
1647 | |
1648 return retval; | |
1649 } | |
1650 #endif | |
1651 | |
1652 DEFUN_DLD (__ftp_mput__, args, nargout, | 1782 DEFUN_DLD (__ftp_mput__, args, nargout, |
1653 "-*- texinfo -*-\n\ | 1783 "-*- texinfo -*-\n\ |
1654 @deftypefn {Loadable Function} {} __ftp_mput__ (@var{handle}, @var{files})\n\ | 1784 @deftypefn {Loadable Function} {} __ftp_mput__ (@var{handle}, @var{files})\n\ |
1655 Undocumented internal function\n\ | 1785 Undocumented internal function\n\ |
1656 @end deftypefn") | 1786 @end deftypefn") |
1687 break; | 1817 break; |
1688 } | 1818 } |
1689 | 1819 |
1690 if (fs.is_dir ()) | 1820 if (fs.is_dir ()) |
1691 { | 1821 { |
1692 retval.append (mput_directory (curl, "", file)); | 1822 retval.append (curl.mput_directory ("", file)); |
1693 if (error_state) | 1823 if (error_state) |
1694 break; | 1824 break; |
1695 } | 1825 } |
1696 else | 1826 else |
1697 { | 1827 { |
1727 #endif | 1857 #endif |
1728 | 1858 |
1729 return (nargout > 0 ? octave_value (retval) : octave_value ()); | 1859 return (nargout > 0 ? octave_value (retval) : octave_value ()); |
1730 } | 1860 } |
1731 | 1861 |
1732 #ifdef HAVE_CURL | |
1733 static void | |
1734 getallfiles (const curl_object& curl, const std::string& dir, | |
1735 const std::string& target) | |
1736 { | |
1737 std::string sep = file_ops::dir_sep_str (); | |
1738 file_stat fs (dir); | |
1739 | |
1740 if (!fs || !fs.is_dir ()) | |
1741 { | |
1742 std::string msg; | |
1743 int status = octave_mkdir (dir, 0777, msg); | |
1744 | |
1745 if (status < 0) | |
1746 error ("__ftp_mget__: can't create directory %s%s%s. %s", | |
1747 target.c_str (), sep.c_str (), dir.c_str (), msg.c_str ()); | |
1748 } | |
1749 | |
1750 if (! error_state) | |
1751 { | |
1752 curl.cwd (dir); | |
1753 | |
1754 if (! error_state) | |
1755 { | |
1756 unwind_protect_safe frame; | |
1757 | |
1758 frame.add_fcn (reset_path, curl); | |
1759 | |
1760 string_vector sv = curl.list (); | |
1761 | |
1762 for (octave_idx_type i = 0; i < sv.length (); i++) | |
1763 { | |
1764 time_t ftime; | |
1765 bool fisdir; | |
1766 double fsize; | |
1767 | |
1768 curl.get_fileinfo (sv(i), fsize, ftime, fisdir); | |
1769 | |
1770 if (fisdir) | |
1771 getallfiles (curl, sv(i), target + dir + sep); | |
1772 else | |
1773 { | |
1774 std::string realfile = target + dir + sep + sv(i); | |
1775 std::ofstream ofile (realfile.c_str (), | |
1776 std::ios::out | | |
1777 std::ios::binary); | |
1778 | |
1779 if (! ofile.is_open ()) | |
1780 { | |
1781 error ("__ftp_mget__: unable to open file"); | |
1782 break; | |
1783 } | |
1784 | |
1785 unwind_protect_safe frame2; | |
1786 | |
1787 frame2.add_fcn (delete_file, realfile); | |
1788 | |
1789 curl.get (sv(i), ofile); | |
1790 | |
1791 ofile.close (); | |
1792 | |
1793 if (!error_state) | |
1794 frame2.discard (); | |
1795 else | |
1796 frame2.run (); | |
1797 } | |
1798 | |
1799 if (error_state) | |
1800 break; | |
1801 } | |
1802 } | |
1803 } | |
1804 } | |
1805 #endif | |
1806 | |
1807 DEFUN_DLD (__ftp_mget__, args, , | 1862 DEFUN_DLD (__ftp_mget__, args, , |
1808 "-*- texinfo -*-\n\ | 1863 "-*- texinfo -*-\n\ |
1809 @deftypefn {Loadable Function} {} __ftp_mget__ (@var{handle}, @var{files})\n\ | 1864 @deftypefn {Loadable Function} {} __ftp_mget__ (@var{handle}, @var{files})\n\ |
1810 Undocumented internal function\n\ | 1865 Undocumented internal function\n\ |
1811 @end deftypefn") | 1866 @end deftypefn") |
1844 double fsize; | 1899 double fsize; |
1845 | 1900 |
1846 curl.get_fileinfo (sv(i), fsize, ftime, fisdir); | 1901 curl.get_fileinfo (sv(i), fsize, ftime, fisdir); |
1847 | 1902 |
1848 if (fisdir) | 1903 if (fisdir) |
1849 getallfiles (curl, sv(i), target); | 1904 curl.mget_directory (sv(i), target); |
1850 else | 1905 else |
1851 { | 1906 { |
1852 std::ofstream ofile ((target + sv(i)).c_str (), | 1907 std::ofstream ofile ((target + sv(i)).c_str (), |
1853 std::ios::out | | 1908 std::ios::out | |
1854 std::ios::binary); | 1909 std::ios::binary); |