Replaced the code to substitute host address part in URL

with libcurl library calls. This solution should be more robust
than a homebrew URL parser solution.
This commit is contained in:
Vojtech Bubnik 2021-12-03 08:02:16 +01:00
parent f88d678a4a
commit f4dfbb69e2
3 changed files with 51 additions and 15 deletions

View File

@ -2219,6 +2219,7 @@ Plater::priv::~priv()
{ {
if (config != nullptr) if (config != nullptr)
delete config; delete config;
// Saves the database of visited (already shown) hints into hints.ini.
notification_manager->deactivate_loaded_hints(); notification_manager->deactivate_loaded_hints();
} }

View File

@ -5,13 +5,15 @@
#include <exception> #include <exception>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <boost/nowide/convert.hpp>
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp> #include <boost/property_tree/json_parser.hpp>
#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/predicate.hpp>
#include <curl/curl.h>
#include <wx/progdlg.h> #include <wx/progdlg.h>
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/I18N.hpp" #include "slic3r/GUI/I18N.hpp"
#include "slic3r/GUI/GUI.hpp" #include "slic3r/GUI/GUI.hpp"
#include "Http.hpp" #include "Http.hpp"
@ -25,8 +27,13 @@ namespace pt = boost::property_tree;
namespace Slic3r { namespace Slic3r {
namespace { namespace {
std::string substitute_host(const std::string& orig_addr, const std::string sub_addr) std::string substitute_host(const std::string& orig_addr, std::string sub_addr)
{ {
// put ipv6 into [] brackets
if (sub_addr.find(':') != std::string::npos && sub_addr.at(0) != '[')
sub_addr = "[" + sub_addr + "]";
#if 0
//URI = scheme ":"["//"[userinfo "@"] host [":" port]] path["?" query]["#" fragment] //URI = scheme ":"["//"[userinfo "@"] host [":" port]] path["?" query]["#" fragment]
std::string final_addr = orig_addr; std::string final_addr = orig_addr;
// http // http
@ -52,6 +59,35 @@ std::string substitute_host(const std::string& orig_addr, const std::string sub_
} }
final_addr.replace(host_start, host_end - host_start, sub_addr); final_addr.replace(host_start, host_end - host_start, sub_addr);
return final_addr; return final_addr;
#else
// Using the new CURL API for handling URL. https://everything.curl.dev/libcurl/url
// If anything fails, return the input unchanged.
std::string out = orig_addr;
CURLU *hurl = curl_url();
if (hurl) {
// Parse the input URL.
CURLUcode rc = curl_url_set(hurl, CURLUPART_URL, orig_addr.c_str(), 0);
if (rc == CURLUE_OK) {
// Replace the address.
rc = curl_url_set(hurl, CURLUPART_HOST, sub_addr.c_str(), 0);
if (rc == CURLUE_OK) {
// Extract a string fromt the CURL URL handle.
char *url;
rc = curl_url_get(hurl, CURLUPART_URL, &url, 0);
if (rc == CURLUE_OK) {
out = url;
curl_free(url);
} else
BOOST_LOG_TRIVIAL(error) << "OctoPrint substitute_host: failed to extract the URL after substitution";
} else
BOOST_LOG_TRIVIAL(error) << "OctoPrint substitute_host: failed to substitute host " << sub_addr << " in URL " << orig_addr;
} else
BOOST_LOG_TRIVIAL(error) << "OctoPrint substitute_host: failed to parse URL " << orig_addr;
curl_url_cleanup(hurl);
} else
BOOST_LOG_TRIVIAL(error) << "OctoPrint substitute_host: failed to allocate curl_url";
return out;
#endif
} }
} //namespace } //namespace
@ -110,7 +146,7 @@ bool OctoPrint::test(wxString &msg) const
#ifdef WIN32 #ifdef WIN32
.ssl_revoke_best_effort(m_ssl_revoke_best_effort) .ssl_revoke_best_effort(m_ssl_revoke_best_effort)
.on_ip_resolve([&](std::string address) { .on_ip_resolve([&](std::string address) {
msg = boost::nowide::widen(address); msg = GUI::from_u8(address);
}) })
#endif #endif
.perform_sync(); .perform_sync();
@ -138,9 +174,11 @@ bool OctoPrint::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, Erro
const auto upload_filename = upload_data.upload_path.filename(); const auto upload_filename = upload_data.upload_path.filename();
const auto upload_parent_path = upload_data.upload_path.parent_path(); const auto upload_parent_path = upload_data.upload_path.parent_path();
wxString test_msg; // If test fails, test_msg_or_host_ip contains the error message.
if (! test(test_msg)) { // Otherwise on Windows it contains the resolved IP address of the host.
error_fn(std::move(test_msg)); wxString test_msg_or_host_ip;
if (! test(test_msg_or_host_ip)) {
error_fn(std::move(test_msg_or_host_ip));
return false; return false;
} }
@ -149,23 +187,18 @@ bool OctoPrint::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, Erro
bool allow_ip_resolve = GUI::get_app_config()->get("allow_ip_resolve") == "1"; bool allow_ip_resolve = GUI::get_app_config()->get("allow_ip_resolve") == "1";
if (m_host.find("https://") == 0 || test_msg.empty() || !allow_ip_resolve) { if (m_host.find("https://") == 0 || test_msg_or_host_ip.empty() || !allow_ip_resolve) {
// If https is entered we assume signed ceritificate is being used // If https is entered we assume signed ceritificate is being used
// IP resolving will not happen - it could resolve into address not being specified in cert // IP resolving will not happen - it could resolve into address not being specified in cert
url = make_url("api/files/local"); url = make_url("api/files/local");
} else { } else {
// Curl uses easy_getinfo to get ip address of last successful transaction. // Curl uses easy_getinfo to get ip address of last successful transaction.
// If it got the address use it instead of the stored in "host" variable. // If it got the address use it instead of the stored in "host" variable.
// This new address returns in "test_msg" variable. // This new address returns in "test_msg_or_host_ip" variable.
// Solves troubles of uploades failing with name address. // Solves troubles of uploades failing with name address.
std::string resolved_addr = boost::nowide::narrow(test_msg);
// put ipv6 into [] brackets
if (resolved_addr.find(':') != std::string::npos && resolved_addr.at(0) != '[')
resolved_addr = "[" + resolved_addr + "]";
// in original address (m_host) replace host for resolved ip // in original address (m_host) replace host for resolved ip
std::string final_addr = substitute_host(m_host, resolved_addr); url = substitute_host(make_url("api/files/local", m_host), GUI::into_u8(test_msg_or_host_ip));
BOOST_LOG_TRIVIAL(debug) << "Upload address after ip resolve: " << final_addr; BOOST_LOG_TRIVIAL(info) << "Upload address after ip resolve: " << url;
url = make_url("api/files/local", final_addr);
} }
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%") BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%")

View File

@ -13,6 +13,8 @@ namespace Utils {
using boost::asio::ip::tcp; using boost::asio::ip::tcp;
// Generic command / response TCP telnet like console class.
// Used by the MKS host to send G-code commands to test connection ("M105") and to start printing ("M23 filename", "M24").
class TCPConsole class TCPConsole
{ {
public: public: