diff --git a/AddressBook.cpp b/AddressBook.cpp index c6a06490..b508e01e 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -33,18 +33,13 @@ const IdentHash * AddressBook::FindAddress (const std::string& address) void AddressBook::LoadHostsFromI2P () { std::string content; - - std::stringstream url_ss; - // TODO: hosts link in config - // TODO: url download via HTTPProxy - url_ss << "http://127.0.0.1:" << i2p::util::config::GetArg("-httpport", 7070) << "/udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna/hosts.txt"; while (true) { - content = i2p::util::http::httpRequest(url_ss.str()); - - // TODO: check http errors - if (! boost::starts_with(content, "") && content.size() > 0) - break; + // TODO: hosts link in config + int http_code = i2p::util::http::httpRequestViaI2pProxy("http://udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p/hosts.txt", content); + if (http_code ==200) + if (!boost::starts_with(content, "") && !content.empty()) // TODO: test and remove + break; std::this_thread::sleep_for(std::chrono::seconds(5)); } diff --git a/HTTPServer.cpp b/HTTPServer.cpp index f7f15cc1..961acbb1 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -118,12 +118,26 @@ namespace util } // namespace misc_strings - std::vector HTTPConnection::reply::to_buffers() + std::vector HTTPConnection::reply::to_buffers(int status) { std::vector buffers; if (headers.size () > 0) - { - buffers.push_back (boost::asio::buffer ("HTTP/1.0 200 OK\r\n")); // always OK + { + switch (status) + { + case 105: buffers.push_back(boost::asio::buffer("HTTP/1.0 105 Name Not Resolved\r\n")); break; + case 200: buffers.push_back(boost::asio::buffer("HTTP/1.0 200 OK\r\n")); break; + case 400: buffers.push_back(boost::asio::buffer("HTTP/1.0 400 Bad Request\r\n")); break; + case 404: buffers.push_back(boost::asio::buffer("HTTP/1.0 404 Not Found\r\n")); break; + case 408: buffers.push_back(boost::asio::buffer("HTTP/1.0 408 Request Timeout\r\n")); break; + case 500: buffers.push_back(boost::asio::buffer("HTTP/1.0 500 Internal Server Error\r\n")); break; + case 502: buffers.push_back(boost::asio::buffer("HTTP/1.0 502 Bad Gateway\r\n")); break; + case 503: buffers.push_back(boost::asio::buffer("HTTP/1.0 503 Not Implemented\r\n")); break; + case 504: buffers.push_back(boost::asio::buffer("HTTP/1.0 504 Gateway Timeout\r\n")); break; + default: + buffers.push_back(boost::asio::buffer("HTTP/1.0 200 OK\r\n")); + } + for (std::size_t i = 0; i < headers.size(); ++i) { header& h = headers[i]; @@ -311,28 +325,41 @@ namespace util { i2p::data::IdentHash destination; std::string fullAddress; - if (address.find (".i2p") != std::string::npos) - { - auto addr = i2p::data::netdb.FindAddress(address); - if (!addr) + if (address.find(".b32.i2p") != std::string::npos) + { + if (i2p::data::Base32ToByteStream(address.c_str(), address.length() - strlen(".b32.i2p"), (uint8_t *)destination, 32) != 32) { - LogPrint ("Unknown address ", address); - SendReply ("" + itoopieImage + "
Unknown address " + address + ""); + LogPrint ("Invalid Base32 address ", address); + SendReply ("" + itoopieImage + "
Invalid Base32 address", 400); return; - } - destination = *addr; + } fullAddress = address; } else - { - if (i2p::data::Base32ToByteStream (address.c_str (), address.length (), (uint8_t *)destination, 32) != 32) + { + if (address.find(".i2p") != std::string::npos) { - LogPrint ("Invalid Base32 address ", address); - SendReply ("" + itoopieImage + "
Invalid Base32 address"); - return; + auto addr = i2p::data::netdb.FindAddress(address); + if (!addr) + { + LogPrint ("Unknown address ", address); + SendReply ("" + itoopieImage + "
Unknown address " + address + "", 105); + return; + } + destination = *addr; + fullAddress = address; } - fullAddress = address + ".b32.i2p"; - } + else + { + if (i2p::data::Base32ToByteStream(address.c_str(), address.length(), (uint8_t *)destination, 32) != 32) + { + LogPrint("Invalid Base32 address ", address); + SendReply("" + itoopieImage + "
Invalid Base32 address", 400); + return; + } + fullAddress = address + ".b32.i2p"; + } + } auto leaseSet = i2p::data::netdb.FindLeaseSet (destination); if (!leaseSet || !leaseSet->HasNonExpiredLeases ()) @@ -342,7 +369,7 @@ namespace util leaseSet = i2p::data::netdb.FindLeaseSet (destination); if (!leaseSet || !leaseSet->HasNonExpiredLeases ()) // still no LeaseSet { - SendReply (leaseSet ? "" + itoopieImage + "
Leases expired" : "" + itoopieImage + "LeaseSet not found"); + SendReply (leaseSet ? "" + itoopieImage + "
Leases expired" : "" + itoopieImage + "LeaseSet not found", 504); return; } } @@ -375,13 +402,13 @@ namespace util else { if (m_Stream && m_Stream->IsOpen ()) - SendReply ("" + itoopieImage + "
Not responding"); + SendReply ("" + itoopieImage + "
Not responding", 504); else Terminate (); } } - void HTTPConnection::SendReply (const std::string& content) + void HTTPConnection::SendReply (const std::string& content, int status) { m_Reply.content = content; m_Reply.headers.resize(2); @@ -390,7 +417,7 @@ namespace util m_Reply.headers[1].name = "Content-Type"; m_Reply.headers[1].value = "text/html"; - boost::asio::async_write (*m_Socket, m_Reply.to_buffers(), + boost::asio::async_write (*m_Socket, m_Reply.to_buffers(status), boost::bind (&HTTPConnection::HandleWriteReply, this, boost::asio::placeholders::error)); } diff --git a/HTTPServer.h b/HTTPServer.h index df9ca4e7..cb594794 100644 --- a/HTTPServer.h +++ b/HTTPServer.h @@ -36,7 +36,7 @@ namespace util std::vector
headers; std::string content; - std::vector to_buffers(); + std::vector to_buffers (int status); }; public: @@ -53,7 +53,7 @@ namespace util void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleWriteReply(const boost::system::error_code& ecode); void HandleWrite (const boost::system::error_code& ecode); - void SendReply (const std::string& content); + void SendReply (const std::string& content, int status = 200); void HandleRequest (); void FillContent (std::stringstream& s); diff --git a/Win32/.gitignore b/Win32/.gitignore index d62f96f6..447f966d 100644 --- a/Win32/.gitignore +++ b/Win32/.gitignore @@ -5,4 +5,5 @@ !*.vcproj !*.vcxproj !*.vcxproj.filters -!.gitignore +!*.iss +!.gitignore \ No newline at end of file diff --git a/Win32/i2pd.vcxproj b/Win32/i2pd.vcxproj index 8a501ae0..87ee6151 100644 --- a/Win32/i2pd.vcxproj +++ b/Win32/i2pd.vcxproj @@ -106,8 +106,9 @@ ./..;$(VC_SourcePath); - .\boost;.\cryptopp;$(IncludePath) - .\stage-x86\lib;$(LibraryPath) + ./..;$(BOOST);$(CRYPTOPP);$(IncludePath) + $(BOOST)\stage\lib;$(CRYPTOPP)\cryptopp\Win32\Output\$(Configuration)\;$(LibraryPath) + ./..;$(VC_SourcePath); @@ -134,6 +135,7 @@ true true true + cryptlib.lib;%(AdditionalDependencies) diff --git a/Win32/inno_installer.iss b/Win32/inno_installer.iss new file mode 100644 index 00000000..12d69b38 --- /dev/null +++ b/Win32/inno_installer.iss @@ -0,0 +1,81 @@ + +#define I2Pd_AppName "i2pd" +#define I2Pd_ver "0.1" + +[Setup] +AppName={#I2Pd_AppName} +AppVersion={#I2Pd_ver} +DefaultDirName={pf}\I2Pd +DefaultGroupName=I2Pd +UninstallDisplayIcon={app}\I2Pd.exe +Compression=lzma2 +SolidCompression=yes +OutputDir=. +LicenseFile=.\..\LICENSE +OutputBaseFilename=setup_{#I2Pd_AppName}_v{#I2Pd_ver} + +[Files] +Source: "i2pd.exe"; DestDir: "{app}" + +[Icons] +Name: "{group}\I2Pd"; Filename: "{app}\i2pd.exe" + +[Code] + +var + DefaultTop, + DefaultLeft, + DefaultHeight, + DefaultBackTop, + DefaultNextTop, + DefaultCancelTop, + DefaultBevelTop, + DefaultOuterHeight: Integer; + +const + LicenseHeight = 400; + +procedure InitializeWizard(); +begin + DefaultTop := WizardForm.Top; + DefaultLeft := WizardForm.Left; + DefaultHeight := WizardForm.Height; + DefaultBackTop := WizardForm.BackButton.Top; + DefaultNextTop := WizardForm.NextButton.Top; + DefaultCancelTop := WizardForm.CancelButton.Top; + DefaultBevelTop := WizardForm.Bevel.Top; + DefaultOuterHeight := WizardForm.OuterNotebook.Height; + + WizardForm.InnerPage.Height := WizardForm.InnerPage.Height + (LicenseHeight - DefaultHeight); + WizardForm.InnerNotebook.Height := WizardForm.InnerNotebook.Height + (LicenseHeight - DefaultHeight); + WizardForm.LicensePage.Height := WizardForm.LicensePage.Height + (LicenseHeight - DefaultHeight); + WizardForm.LicenseMemo.Height := WizardForm.LicenseMemo.Height + (LicenseHeight - DefaultHeight); + WizardForm.LicenseNotAcceptedRadio.Top := WizardForm.LicenseNotAcceptedRadio.Top + (LicenseHeight - DefaultHeight); + WizardForm.LicenseAcceptedRadio.Top := WizardForm.LicenseAcceptedRadio.Top + (LicenseHeight - DefaultHeight); + +end; + +procedure CurPageChanged(CurPageID: Integer); +begin + if CurPageID = wpLicense then + begin + WizardForm.Top := DefaultTop - (LicenseHeight - DefaultHeight) div 2; + WizardForm.Height := LicenseHeight; + WizardForm.OuterNotebook.Height := WizardForm.OuterNotebook.Height + (LicenseHeight - DefaultHeight); + WizardForm.CancelButton.Top := DefaultCancelTop + (LicenseHeight - DefaultHeight); + WizardForm.NextButton.Top := DefaultNextTop + (LicenseHeight - DefaultHeight); + WizardForm.BackButton.Top := DefaultBackTop + (LicenseHeight - DefaultHeight); + WizardForm.Bevel.Top := DefaultBevelTop + (LicenseHeight - DefaultHeight); + end + else + begin + WizardForm.Top := DefaultTop; + WizardForm.Left := DefaultLeft; + WizardForm.Height := DefaultHeight; + WizardForm.OuterNotebook.Height := DefaultOuterHeight; + WizardForm.CancelButton.Top := DefaultCancelTop; + WizardForm.NextButton.Top := DefaultNextTop; + WizardForm.BackButton.Top := DefaultBackTop; + WizardForm.Bevel.Top := DefaultBevelTop; + end; +end; \ No newline at end of file diff --git a/util.cpp b/util.cpp index 05073c82..3fd60ca1 100644 --- a/util.cpp +++ b/util.cpp @@ -249,13 +249,72 @@ namespace http } } - std::string url::portstr_ = "80"; - unsigned int url::port_ = 80; - std::string url::user_ = ""; - std::string url::pass_ = ""; + int httpRequestViaI2pProxy(const std::string& address, std::string &content) + { + content = ""; + try + { + boost::asio::ip::tcp::iostream site; + // please don't uncomment following line because it's not compatible with boost 1.46 + // 1.46 is default boost for Ubuntu 12.04 LTS + //site.expires_from_now (boost::posix_time::seconds(30)); + { + std::stringstream ss; ss << i2p::util::config::GetArg("-httpproxyport", 4446); + site.connect("127.0.0.1", ss.str()); + } + if (site) + { + i2p::util::http::url u(address); + std::stringstream ss; + ss << "GET " << address << " HTTP/1.0" << std::endl; + ss << "Host: " << u.host_ << std::endl; + ss << "Accept: */*" << std::endl; + ss << "User - Agent: Wget / 1.11.4" << std::endl; + ss << "Connection: close" << std::endl; + ss << std::endl; + site << ss.str(); + + // read response + std::string version, statusMessage; + site >> version; // HTTP version + int status; + site >> status; // status + std::getline(site, statusMessage); + if (status == 200) // OK + { + std::string header; + while (std::getline(site, header) && header != "\r"){} + std::stringstream ss; + ss << site.rdbuf(); + content = ss.str(); + return status; + } + else + { + LogPrint("HTTP response ", status); + return status; + } + } + else + { + LogPrint("Can't connect to proxy"); + return 408; + } + } + catch (std::exception& ex) + { + LogPrint("Failed to download ", address, " : ", ex.what()); + return 408; + } + } url::url(const std::string& url_s) { + portstr_ = "80"; + port_ = 80; + user_ = ""; + pass_ = ""; + parse(url_s); } diff --git a/util.h b/util.h index 8766a516..8b335648 100644 --- a/util.h +++ b/util.h @@ -35,16 +35,18 @@ namespace util namespace http { std::string httpRequest(const std::string& address); + int httpRequestViaI2pProxy(const std::string& address, std::string &content); // return http code + struct url { url(const std::string& url_s); // omitted copy, ==, accessors, ... private: void parse(const std::string& url_s); public: std::string protocol_, host_, path_, query_; - static std::string portstr_; - static unsigned int port_; - static std::string user_; - static std::string pass_; + std::string portstr_; + unsigned int port_; + std::string user_; + std::string pass_; }; } }