Go to the documentation of this file.00001
00002
00003 #include "ace/Get_Opt.h"
00004 #include "ace/Auto_Ptr.h"
00005 #include "ace/OS_NS_errno.h"
00006 #include "ace/INet/HTTP_URL.h"
00007 #include "ace/INet/HTTP_ClientRequestHandler.h"
00008 #if defined (ACE_HAS_SSL) && ACE_HAS_SSL == 1
00009 # include "ace/INet/SSL_CallbackManager.h"
00010 # include "ace/INet/HTTPS_Context.h"
00011 #endif
00012 #include "ace/INet/INet_Log.h"
00013 #include <iostream>
00014 #include <fstream>
00015
00016 ACE_CString proxy_hostname;
00017 u_short proxy_port = ACE::HTTP::URL::HTTP_PROXY_PORT;
00018 ACE_CString url;
00019 ACE_CString outfile;
00020 #if defined (ACE_HAS_SSL) && ACE_HAS_SSL == 1
00021 int ssl_mode = ACE_SSL_Context::SSLv3;
00022 bool verify_peer = true;
00023 bool ignore_verify = false;
00024 ACE_CString certificate;
00025 ACE_CString private_key;
00026 ACE_CString ca_location;
00027 #endif
00028
00029 void
00030 usage (void)
00031 {
00032 std::cout << "usage: http_simple_wget [options] <url>\n";
00033 std::cout << "Executes an HTTP GET request and sends the result to STDOUT or file\n";
00034 std::cout << "\t-H <hostname> \t\tproxy host to connect to\n";
00035 std::cout << "\t-p <port> \t\tproxy port to connect to\n";
00036 std::cout << "\t-o <filename> \t\tfile to write output to\n";
00037 #if defined (ACE_HAS_SSL) && ACE_HAS_SSL == 1
00038 std::cout << "\t-v <ssl version>\t\tSSL version to use: 2, 23, 3\n";
00039 std::cout << "\t-n \t\tno peer certificate verification\n";
00040 std::cout << "\t-i \t\tignore peer certificate verification failures\n";
00041 std::cout << "\t-c <filename> \t\tcertificate file (PEM format)\n";
00042 std::cout << "\t-k <filename> \t\tprivate key file (PEM format); requires -c\n";
00043 std::cout << "\t-C <path> \t\ttrusted CA file or directory\n";
00044 #endif
00045 }
00046
00047 bool
00048 parse_args (int argc, ACE_TCHAR *argv [])
00049 {
00050 #if defined (ACE_HAS_SSL) && ACE_HAS_SSL == 1
00051 ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("H:p:o:hv:nic:k:C:"), 0, 0, ACE_Get_Opt::RETURN_IN_ORDER);
00052 #else
00053 ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("H:p:o:h"), 0, 0, ACE_Get_Opt::RETURN_IN_ORDER);
00054 #endif
00055
00056 int c;
00057 ACE_CString s;
00058 while ((c = get_opt ()) != EOF)
00059 {
00060 switch (c)
00061 {
00062 case 1:
00063 url = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ());
00064 break;
00065 case 'H':
00066 proxy_hostname = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ());
00067 break;
00068
00069 case 'p':
00070 proxy_port = (u_short)ACE_OS::atoi (ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ()));
00071 break;
00072
00073 case 'o':
00074 outfile = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ());
00075 break;
00076
00077 #if defined (ACE_HAS_SSL) && ACE_HAS_SSL == 1
00078 case 'v':
00079 {
00080 ACE_CString ver = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ());
00081 if (ver == "2")
00082 ssl_mode = ACE_SSL_Context::SSLv2;
00083 else if (ver == "23")
00084 ssl_mode = ACE_SSL_Context::SSLv23;
00085 else if (ver != "3")
00086 {
00087 std::cerr << "ERROR: Invalid SSL mode [" << ver << "] specfied!" << std::endl;
00088 return false;
00089 }
00090 }
00091 break;
00092
00093 case 'n':
00094 verify_peer = false;
00095 break;
00096
00097 case 'i':
00098 ignore_verify = true;
00099 break;
00100
00101 case 'c':
00102 certificate = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ());
00103 break;
00104
00105 case 'k':
00106 private_key = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ());
00107 break;
00108
00109 case 'C':
00110 ca_location = ACE_TEXT_ALWAYS_CHAR (get_opt.opt_arg ());
00111 break;
00112 #endif
00113 case 'h':
00114 default:
00115 usage ();
00116 return false;
00117 }
00118 }
00119
00120 return true;
00121 }
00122
00123 class My_HTTP_RequestHandler
00124 : public ACE::HTTP::ClientRequestHandler
00125 {
00126 public:
00127 My_HTTP_RequestHandler () : in_length_ (0), read_length_ (0) {}
00128 virtual ~My_HTTP_RequestHandler () {}
00129
00130 protected:
00131 virtual void handle_request_error (const ACE::HTTP::URL& url)
00132 {
00133 std::cout << "ERROR" << std::endl;
00134 std::cerr << "Failed to handle request for " << url.to_string ().c_str () << std::endl;
00135 }
00136
00137 virtual void handle_connection_error (const ACE::HTTP::URL& url)
00138 {
00139 std::cout << "ERROR" << std::endl;
00140 std::cerr << "Failed to set up connection for " << url.to_string ().c_str () << std::endl;
00141 }
00142
00143 virtual void after_read (const char_type* , int length_read)
00144 {
00145 if (this->read_length_ == 0)
00146 {
00147 this->in_length_ = this->response ().get_content_length ();
00148 }
00149 this->read_length_ += length_read;
00150 std::cout << "\r [" << this->read_length_ << '/';
00151 if (this->in_length_ != ACE::HTTP::Response::UNKNOWN_CONTENT_LENGTH)
00152 {
00153 std::cout << this->in_length_ << "] " << ((this->read_length_ * 100) / this->in_length_) << "%";
00154 }
00155 else
00156 std::cout << "???]";
00157 std::cout.flush ();
00158 }
00159
00160 virtual void on_eof ()
00161 {
00162 ACE::HTTP::ClientRequestHandler::on_eof ();
00163 std::cout << std::endl;
00164 this->read_length_ = 0;
00165 }
00166
00167 private:
00168 int in_length_;
00169 int read_length_;
00170 };
00171
00172 int
00173 ACE_TMAIN (int argc, ACE_TCHAR *argv [])
00174 {
00175 ACE_Auto_Ptr<std::ofstream> fout;
00176 std::ostream* sout = &std::cout;
00177
00178 if (!parse_args (argc, argv))
00179 {
00180 return 1;
00181 }
00182
00183 #if defined (ACE_HAS_SSL) && ACE_HAS_SSL == 1
00184 ACE::HTTPS::Context::set_default_ssl_mode (ssl_mode);
00185 ACE::HTTPS::Context::set_default_verify_mode (verify_peer);
00186 ACE::HTTPS::Context::instance ().use_default_ca ();
00187 if (!private_key.empty ())
00188 {
00189 if (certificate.empty ())
00190 {
00191 std::cerr << "ERROR: private key file [" << private_key << "] requires certificate file to be specified." << std::endl;
00192 return 1;
00193 }
00194 if (!ACE::HTTPS::Context::instance ().set_key_files (private_key.c_str (), certificate.c_str ()))
00195 {
00196 std::cerr << "ERROR: failed to set private key [" << private_key << "]." << std::endl;
00197 return 1;
00198 }
00199 }
00200 if (!ca_location.empty ())
00201 {
00202 INET_DEBUG (6, (LM_INFO, DLINFO ACE_TEXT ("loading trusted CA [%C]\n"), ca_location.c_str ()));
00203 if (!ACE::HTTPS::Context::instance ().load_trusted_ca (ca_location.c_str ()))
00204 {
00205 std::cerr << "ERROR: failed to load trusted CA from [" << ca_location << "]." << std::endl;
00206 return 1;
00207 }
00208 INET_DEBUG (6, (LM_INFO, DLINFO ACE_TEXT ("loaded [%d] trusted CA\n"), ACE::HTTPS::Context::instance ().has_trusted_ca ()));
00209 }
00210 if (ignore_verify)
00211 ACE::INet::SSL_CallbackManager::instance ()->set_certificate_callback (new ACE::INet::SSL_CertificateAcceptor);
00212 #endif
00213
00214 std::cout << "Starting..." << std::endl;
00215
00216 if (!url.empty ())
00217 {
00218 if (!outfile.empty ())
00219 {
00220 fout.reset (new std::ofstream (outfile.c_str (), std::ios_base::binary|std::ios_base::out));
00221
00222 if (!*fout)
00223 {
00224 std::cerr << "Failed to open output file : " << outfile.c_str () << std::endl;
00225 return 1;
00226 }
00227
00228 sout = fout.get ();
00229 }
00230
00231 std::cout << "Parsing url [" << url.c_str () << "]" << std::endl;
00232
00233 ACE_Auto_Ptr<ACE::INet::URL_Base> url_safe (ACE::INet::URL_Base::create_from_string (url));
00234
00235 if (url_safe.get () == 0 || url != url_safe->to_string ())
00236 {
00237 std::cerr << "Failed parsing url [" << url << "]" << std::endl;
00238 std::cerr << "\tresult = " << (url_safe.get () == 0 ? "(null)" : url_safe->to_string ().c_str ()) << std::endl;
00239 return 1;
00240 }
00241
00242 ACE::HTTP::URL& http_url = *dynamic_cast<ACE::HTTP::URL*> (url_safe.get ());
00243
00244 if (!proxy_hostname.empty ())
00245 {
00246 std::cout << "Setting proxy: " << proxy_hostname.c_str () << ':' << proxy_port << std::endl;
00247 http_url.set_proxy (proxy_hostname, proxy_port);
00248 }
00249
00250 std::cout << "Opening url...";
00251 My_HTTP_RequestHandler my_rh;
00252 ACE::INet::URLStream urlin = http_url.open (my_rh);
00253 if (urlin)
00254 {
00255 std::cout << "Received response "
00256 << (int)my_rh.response ().get_status ().get_status ()
00257 << " "
00258 << my_rh.response ().get_status ().get_reason ().c_str ()
00259 << std::endl;
00260 if (my_rh.response ().get_status ().is_ok ())
00261 {
00262 std::cout << "Length: ";
00263 if (my_rh.response ().get_content_length () != ACE::HTTP::Response::UNKNOWN_CONTENT_LENGTH)
00264 std::cout << my_rh.response ().get_content_length () << " [";
00265 else
00266 std::cout << "(unknown) [";
00267 if (my_rh.response ().get_content_type () != ACE::HTTP::Response::UNKNOWN_CONTENT_TYPE)
00268 std::cout << my_rh.response ().get_content_type ().c_str ();
00269 else
00270 std::cout << "(unknown)";
00271 std::cout << "]" << std::endl;
00272 }
00273
00274 std::cout << "Saving to: ";
00275 if (!outfile.empty ())
00276 std::cout << '\'' << outfile.c_str () << '\'' << std::endl;
00277 else
00278 std::cout << "(stdout)" << std::endl;
00279
00280 (*sout) << urlin->rdbuf ();
00281 sout->flush ();
00282 }
00283 }
00284 else
00285 {
00286 std::cerr << "ERROR: No URL specified!" << std::endl;
00287 usage ();
00288 return 1;
00289 }
00290
00291 std::cout << "Done" << std::endl;
00292
00293 return 0;
00294 }