diff options
Diffstat (limited to 'ACE/protocols/ace/INet/HTTP_Simple_exec.cpp')
-rw-r--r-- | ACE/protocols/ace/INet/HTTP_Simple_exec.cpp | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/ACE/protocols/ace/INet/HTTP_Simple_exec.cpp b/ACE/protocols/ace/INet/HTTP_Simple_exec.cpp new file mode 100644 index 00000000000..65805c2c582 --- /dev/null +++ b/ACE/protocols/ace/INet/HTTP_Simple_exec.cpp @@ -0,0 +1,294 @@ +// $Id$ + +#include "ace/Get_Opt.h" +#include "ace/Auto_Ptr.h" +#include "ace/OS_NS_errno.h" +#include "ace/INet/HTTP_URL.h" +#include "ace/INet/HTTP_ClientRequestHandler.h" +#if defined (ACE_HAS_SSL) && ACE_HAS_SSL == 1 +# include "ace/INet/SSL_CallbackManager.h" +# include "ace/INet/HTTPS_Context.h" +#endif +#include "ace/INet/INet_Log.h" +#include <iostream> +#include <fstream> + +ACE_CString proxy_hostname; +u_short proxy_port = ACE::HTTP::URL::HTTP_PROXY_PORT; +ACE_CString url; +ACE_CString outfile; +#if defined (ACE_HAS_SSL) && ACE_HAS_SSL == 1 +int ssl_mode = ACE_SSL_Context::SSLv3; +bool verify_peer = true; +bool ignore_verify = false; +ACE_CString certificate; +ACE_CString private_key; +ACE_CString ca_location; +#endif + +void +usage (void) +{ + std::cout << "usage: http_simple_wget [options] <url>\n"; + std::cout << "Executes an HTTP GET request and sends the result to STDOUT or file\n"; + std::cout << "\t-H <hostname> \t\tproxy host to connect to\n"; + std::cout << "\t-p <port> \t\tproxy port to connect to\n"; + std::cout << "\t-o <filename> \t\tfile to write output to\n"; +#if defined (ACE_HAS_SSL) && ACE_HAS_SSL == 1 + std::cout << "\t-v <ssl version>\t\tSSL version to use: 2, 23, 3\n"; + std::cout << "\t-n \t\tno peer certificate verification\n"; + std::cout << "\t-i \t\tignore peer certificate verification failures\n"; + std::cout << "\t-c <filename> \t\tcertificate file (PEM format)\n"; + std::cout << "\t-k <filename> \t\tprivate key file (PEM format); requires -c\n"; + std::cout << "\t-C <path> \t\ttrusted CA file or directory\n"; +#endif +} + +bool +parse_args (int argc, ACE_TCHAR *argv []) +{ +#if defined (ACE_HAS_SSL) && ACE_HAS_SSL == 1 + ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("H:p:o:hv:nic:k:C:"), 0, 0, ACE_Get_Opt::RETURN_IN_ORDER); +#else + ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("H:p:o:h"), 0, 0, ACE_Get_Opt::RETURN_IN_ORDER); +#endif + + int c; + ACE_CString s; + while ((c = get_opt ()) != EOF) + { + switch (c) + { + case 1: + url = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ()); + break; + case 'H': + proxy_hostname = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ()); + break; + + case 'p': + proxy_port = (u_short)ACE_OS::atoi (ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ())); + break; + + case 'o': + outfile = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ()); + break; + +#if defined (ACE_HAS_SSL) && ACE_HAS_SSL == 1 + case 'v': + { + ACE_CString ver = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ()); + if (ver == "2") + ssl_mode = ACE_SSL_Context::SSLv2; + else if (ver == "23") + ssl_mode = ACE_SSL_Context::SSLv23; + else if (ver != "3") // default mode + { + std::cerr << "ERROR: Invalid SSL mode [" << ver << "] specfied!" << std::endl; + return false; + } + } + break; + + case 'n': + verify_peer = false; + break; + + case 'i': + ignore_verify = true; + break; + + case 'c': + certificate = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ()); + break; + + case 'k': + private_key = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ()); + break; + + case 'C': + ca_location = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ()); + break; +#endif + case 'h': + default: + usage (); + return false; + } + } + + return true; +} + +class My_HTTP_RequestHandler + : public ACE::HTTP::ClientRequestHandler +{ + public: + My_HTTP_RequestHandler () : in_length_ (0), read_length_ (0) {} + virtual ~My_HTTP_RequestHandler () {} + + protected: + virtual void handle_request_error (const ACE::HTTP::URL& url) + { + std::cout << "ERROR" << std::endl; + std::cerr << "Failed to handle request for " << url.to_string ().c_str () << std::endl; + } + + virtual void handle_connection_error (const ACE::HTTP::URL& url) + { + std::cout << "ERROR" << std::endl; + std::cerr << "Failed to set up connection for " << url.to_string ().c_str () << std::endl; + } + + virtual void after_read (const char_type* /*buffer*/, int length_read) + { + if (this->read_length_ == 0) + { + this->in_length_ = this->response ().get_content_length (); + } + this->read_length_ += length_read; + std::cout << "\r [" << this->read_length_ << '/'; + if (this->in_length_ != ACE::HTTP::Response::UNKNOWN_CONTENT_LENGTH) + { + std::cout << this->in_length_ << "] " << ((this->read_length_ * 100) / this->in_length_) << "%"; + } + else + std::cout << "???]"; + std::cout.flush (); + } + + virtual void on_eof () + { + ACE::HTTP::ClientRequestHandler::on_eof (); + std::cout << std::endl; + this->read_length_ = 0; + } + + private: + int in_length_; + int read_length_; +}; + +int +ACE_TMAIN (int argc, ACE_TCHAR *argv []) +{ + ACE_Auto_Ptr<std::ofstream> fout; + std::ostream* sout = &std::cout; + + if (!parse_args (argc, argv)) + { + return 1; + } + +#if defined (ACE_HAS_SSL) && ACE_HAS_SSL == 1 + ACE::HTTPS::Context::set_default_ssl_mode (ssl_mode); + ACE::HTTPS::Context::set_default_verify_mode (verify_peer); + ACE::HTTPS::Context::instance ().use_default_ca (); + if (!private_key.empty ()) + { + if (certificate.empty ()) + { + std::cerr << "ERROR: private key file [" << private_key << "] requires certificate file to be specified." << std::endl; + return 1; + } + if (!ACE::HTTPS::Context::instance ().set_key_files (private_key.c_str (), certificate.c_str ())) + { + std::cerr << "ERROR: failed to set private key [" << private_key << "]." << std::endl; + return 1; + } + } + if (!ca_location.empty ()) + { + INET_DEBUG (6, (LM_INFO, DLINFO ACE_TEXT ("loading trusted CA [%C]\n"), ca_location.c_str ())); + if (!ACE::HTTPS::Context::instance ().load_trusted_ca (ca_location.c_str ())) + { + std::cerr << "ERROR: failed to load trusted CA from [" << ca_location << "]." << std::endl; + return 1; + } + INET_DEBUG (6, (LM_INFO, DLINFO ACE_TEXT ("loaded [%d] trusted CA\n"), ACE::HTTPS::Context::instance ().has_trusted_ca ())); + } + if (ignore_verify) + ACE::INet::SSL_CallbackManager::instance ()->set_certificate_callback (new ACE::INet::SSL_CertificateAcceptor); +#endif + + std::cout << "Starting..." << std::endl; + + if (!url.empty ()) + { + if (!outfile.empty ()) + { + fout.reset (new std::ofstream (outfile.c_str (), std::ios_base::binary|std::ios_base::out)); + + if (!*fout) + { + std::cerr << "Failed to open output file : " << outfile.c_str () << std::endl; + return 1; + } + + sout = fout.get (); + } + + std::cout << "Parsing url [" << url.c_str () << "]" << std::endl; + + ACE_Auto_Ptr<ACE::INet::URL_Base> url_safe (ACE::INet::URL_Base::create_from_string (url)); + + if (url_safe.get () == 0 || url != url_safe->to_string ()) + { + std::cerr << "Failed parsing url [" << url << "]" << std::endl; + std::cerr << "\tresult = " << (url_safe.get () == 0 ? "(null)" : url_safe->to_string ().c_str ()) << std::endl; + return 1; + } + + ACE::HTTP::URL& http_url = *dynamic_cast<ACE::HTTP::URL*> (url_safe.get ()); + + if (!proxy_hostname.empty ()) + { + std::cout << "Setting proxy: " << proxy_hostname.c_str () << ':' << proxy_port << std::endl; + http_url.set_proxy (proxy_hostname, proxy_port); + } + + std::cout << "Opening url..."; + My_HTTP_RequestHandler my_rh; + ACE::INet::URLStream urlin = http_url.open (my_rh); + if (urlin) + { + std::cout << "Received response " + << (int)my_rh.response ().get_status ().get_status () + << " " + << my_rh.response ().get_status ().get_reason ().c_str () + << std::endl; + if (my_rh.response ().get_status ().is_ok ()) + { + std::cout << "Length: "; + if (my_rh.response ().get_content_length () != ACE::HTTP::Response::UNKNOWN_CONTENT_LENGTH) + std::cout << my_rh.response ().get_content_length () << " ["; + else + std::cout << "(unknown) ["; + if (my_rh.response ().get_content_type () != ACE::HTTP::Response::UNKNOWN_CONTENT_TYPE) + std::cout << my_rh.response ().get_content_type ().c_str (); + else + std::cout << "(unknown)"; + std::cout << "]" << std::endl; + } + + std::cout << "Saving to: "; + if (!outfile.empty ()) + std::cout << '\'' << outfile.c_str () << '\'' << std::endl; + else + std::cout << "(stdout)" << std::endl; + + (*sout) << urlin->rdbuf (); + sout->flush (); + } + } + else + { + std::cerr << "ERROR: No URL specified!" << std::endl; + usage (); + return 1; + } + + std::cout << "Done" << std::endl; + + return 0; +} |