diff options
Diffstat (limited to 'butl/curl.cxx')
-rw-r--r-- | butl/curl.cxx | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/butl/curl.cxx b/butl/curl.cxx new file mode 100644 index 0000000..4951b52 --- /dev/null +++ b/butl/curl.cxx @@ -0,0 +1,166 @@ +// file : butl/curl.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include <butl/curl> + +#include <utility> // move(), forward() +#include <exception> // invalid_argument + +#include <butl/utility> // casecmp() + +using namespace std; + +namespace butl +{ + int curl:: + map_in (nullfd_t, method_proto mp, io_data& d) + { + switch (mp) + { + case ftp_put: + throw invalid_argument ("no input specified for PUT method"); + case http_post: + throw invalid_argument ("no input specified for POST method"); + case ftp_get: + case http_get: + { + d.pipe.in.reset (fdnull ()); // /dev/null + return d.pipe.in.get (); + } + } + + return -1; + } + + int curl:: + map_in (const path& f, method_proto mp, io_data& d) + { + switch (mp) + { + case ftp_put: + case http_post: + { + if (mp == ftp_put) + { + d.options.push_back ("--upload-file"); + d.options.push_back (f.string ().c_str ()); + } + else + { + d.storage = '@' + f.string (); + + d.options.push_back ("--data-binary"); + d.options.push_back (d.storage.c_str ()); + } + + if (f.string () == "-") + { + d.pipe = fdopen_pipe (fdopen_mode::binary); + out.open (move (d.pipe.out)); + } + else + d.pipe.in.reset (fdnull ()); // /dev/null + + return d.pipe.in.get (); + } + case ftp_get: + case http_get: + { + throw invalid_argument ("file input specified for GET method"); + } + } + + return -1; + } + + int curl:: + map_out (nullfd_t, method_proto mp, io_data& d) + { + switch (mp) + { + case ftp_get: + case http_get: + throw invalid_argument ("no output specified for GET method"); + case ftp_put: + case http_post: // May or may not produce output. + { + d.pipe.out.reset (fdnull ()); + return d.pipe.out.get (); // /dev/null + } + } + + return -1; + } + + int curl:: + map_out (const path& f, method_proto mp, io_data& d) + { + switch (mp) + { + case ftp_get: + case http_get: + case http_post: + { + if (f.string () == "-") + { + // Note: no need for any options, curl writes to stdout by default. + // + d.pipe = fdopen_pipe (fdopen_mode::binary); + in.open (move (d.pipe.in)); + } + else + { + d.options.push_back ("-o"); + d.options.push_back (f.string ().c_str ()); + d.pipe.out.reset (fdnull ()); // /dev/null + } + + return d.pipe.out.get (); + } + case ftp_put: + { + throw invalid_argument ("file output specified for PUT method"); + } + } + + return -1; + } + + curl::method_proto curl:: + translate (method_type m, const string& u, method_proto_options& o) + { + size_t n (u.find ("://")); + + if (n == string::npos) + throw invalid_argument ("no protocol in URL"); + + if (casecmp (u, "ftp", n) == 0 || + casecmp (u, "tftp", n) == 0) + { + switch (m) + { + case method_type::get: return method_proto::ftp_get; + case method_type::put: return method_proto::ftp_put; + case method_type::post: + throw invalid_argument ("POST method with FTP protocol"); + } + } + else if (casecmp (u, "http", n) == 0 || + casecmp (u, "https", n) == 0) + { + o.push_back ("--fail"); // Fail on HTTP errors (e.g., 404). + o.push_back ("--location"); // Follow redirects. + + switch (m) + { + case method_type::get: return method_proto::http_get; + case method_type::post: return method_proto::http_post; + case method_type::put: + throw invalid_argument ("PUT method with HTTP protocol"); + } + } + + throw invalid_argument ("unsupported protocol"); + } +} |