PageRenderTime 62ms CodeModel.GetById 12ms RepoModel.GetById 2ms app.codeStats 1ms

/mordor/examples/wget.cpp

http://github.com/mozy/mordor
C++ | 155 lines | 144 code | 10 blank | 1 comment | 24 complexity | 4319df9a33a9c00e5cb2415991e90075 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. // Copyright (c) 2009 - Mozy, Inc.
  2. #include "mordor/predef.h"
  3. #include <iostream>
  4. #include <boost/bind.hpp>
  5. #include <boost/shared_ptr.hpp>
  6. #include <boost/program_options.hpp>
  7. #include "mordor/config.h"
  8. #include "mordor/exception.h"
  9. #include "mordor/http/auth.h"
  10. #include "mordor/http/broker.h"
  11. #include "mordor/http/client.h"
  12. #include "mordor/http/multipart.h"
  13. #include "mordor/http/proxy.h"
  14. #include "mordor/iomanager.h"
  15. #include "mordor/main.h"
  16. #include "mordor/sleep.h"
  17. #include "mordor/socket.h"
  18. #include "mordor/streams/socket.h"
  19. #include "mordor/streams/ssl.h"
  20. #include "mordor/streams/std.h"
  21. #include "mordor/streams/transfer.h"
  22. using namespace Mordor;
  23. namespace po = boost::program_options;
  24. static bool getCredentials(HTTP::ClientRequest::ptr priorRequest,
  25. std::string &scheme, std::string &username, std::string &password,
  26. const std::string &user, const std::string &pass,
  27. size_t attempts, bool forProxy)
  28. {
  29. if (!priorRequest)
  30. return false;
  31. if (attempts > 1)
  32. return false;
  33. username = user;
  34. password = pass;
  35. const HTTP::ChallengeList &challengeList = forProxy ?
  36. priorRequest->response().response.proxyAuthenticate :
  37. priorRequest->response().response.wwwAuthenticate;
  38. #ifdef WINDOWS
  39. if (HTTP::isAcceptable(challengeList, "Negotiate")) {
  40. scheme = "Negotiate";
  41. return true;
  42. }
  43. if (HTTP::isAcceptable(challengeList, "NTLM")) {
  44. scheme = "NTLM";
  45. return true;
  46. }
  47. #endif
  48. if (HTTP::isAcceptable(challengeList, "Digest")) {
  49. scheme = "Digest";
  50. return true;
  51. }
  52. if (HTTP::isAcceptable(challengeList, "Basic")) {
  53. scheme = "Basic";
  54. return true;
  55. }
  56. return false;
  57. }
  58. MORDOR_MAIN(int argc, char *argv[])
  59. {
  60. Config::loadFromEnvironment();
  61. StdoutStream stdoutStream;
  62. IOManager ioManager;
  63. po::options_description desc("Allowed options");
  64. desc.add_options()
  65. ("help", "print this help message")
  66. ("username", po::value<std::string>(), "username")
  67. ("password", po::value<std::string>(), "password")
  68. ("proxyusername", po::value<std::string>(), "proxyusername")
  69. ("proxypassword", po::value<std::string>(), "proxypassword")
  70. ("uri", po::value<std::string>(), "uri to download");
  71. po::positional_options_description positions;
  72. positions.add("uri", -1);
  73. po::variables_map vm;
  74. try {
  75. po::store(po::command_line_parser(argc, argv).options(desc).positional(positions).run(), vm);
  76. } catch (...) {
  77. std::cout << desc << "\n";
  78. return 1;
  79. }
  80. if (vm.count("help") || !vm.count("uri")) {
  81. std::cout << desc << "\n";
  82. return 1;
  83. }
  84. try {
  85. URI uri = vm["uri"].as<std::string>();
  86. MORDOR_ASSERT(uri.authority.hostDefined());
  87. MORDOR_ASSERT(!uri.schemeDefined() || uri.scheme() == "http" || uri.scheme() == "https");
  88. HTTP::RequestBrokerOptions options;
  89. options.ioManager = &ioManager;
  90. std::string username, password, proxyusername, proxypassword;
  91. if (vm.count("username")) username = vm["username"].as<std::string>();
  92. if (vm.count("password")) password = vm["password"].as<std::string>();
  93. if (vm.count("proxyusername")) proxyusername = vm["proxyusername"].as<std::string>();
  94. if (vm.count("proxypassword")) proxypassword = vm["proxypassword"].as<std::string>();
  95. if (vm.count("proxyusername"))
  96. options.getProxyCredentialsDg = boost::bind(&getCredentials, _2, _3, _5, _6,
  97. proxyusername, proxypassword, _7, true);
  98. #ifdef OSX
  99. else
  100. options.getProxyCredentialsDg = &HTTP::getCredentialsFromKeychain;
  101. #endif
  102. HTTP::RequestBroker::ptr proxyBroker =
  103. HTTP::createRequestBroker(options).first;
  104. if (vm.count("username"))
  105. options.getCredentialsDg = boost::bind(&getCredentials, _2, _3, _5, _6,
  106. username, password, _7, false);
  107. #ifdef OSX
  108. else
  109. options.getCredentialsDg = &HTTP::getCredentialsFromKeychain;
  110. #endif
  111. options.proxyRequestBroker = proxyBroker;
  112. #ifdef WINDOWS
  113. HTTP::ProxyCache proxyCache;
  114. options.proxyForURIDg = boost::bind(
  115. &HTTP::ProxyCache::proxyFromUserSettings, &proxyCache, _1);
  116. #elif defined (OSX)
  117. HTTP::ProxyCache proxyCache(proxyBroker);
  118. options.proxyForURIDg = boost::bind(
  119. &HTTP::ProxyCache::proxyFromSystemConfiguration, &proxyCache, _1);
  120. #else
  121. options.proxyForURIDg = &HTTP::proxyFromConfig;
  122. #endif
  123. HTTP::RequestBroker::ptr requestBroker =
  124. HTTP::createRequestBroker(options).first;
  125. HTTP::Request requestHeaders;
  126. requestHeaders.requestLine.uri = uri;
  127. requestHeaders.request.host = uri.authority.host();
  128. HTTP::ClientRequest::ptr request = requestBroker->request(requestHeaders);
  129. if (request->hasResponseBody()) {
  130. if (request->response().entity.contentType.type != "multipart") {
  131. transferStream(request->responseStream(), stdoutStream);
  132. } else {
  133. Multipart::ptr responseMultipart = request->responseMultipart();
  134. for (BodyPart::ptr bodyPart = responseMultipart->nextPart(); bodyPart;
  135. bodyPart = responseMultipart->nextPart()) {
  136. transferStream(bodyPart->stream(), stdoutStream);
  137. }
  138. }
  139. }
  140. return request->response().status.status == HTTP::OK ? 0 : request->response().status.status;
  141. } catch (...) {
  142. std::cerr << boost::current_exception_diagnostic_information() << std::endl;
  143. return 2;
  144. }
  145. }