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)
delete config;
// Saves the database of visited (already shown) hints into hints.ini.
notification_manager->deactivate_loaded_hints();
}

View file

@ -5,13 +5,15 @@
#include <exception>
#include <boost/format.hpp>
#include <boost/log/trivial.hpp>
#include <boost/nowide/convert.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <curl/curl.h>
#include <wx/progdlg.h>
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/I18N.hpp"
#include "slic3r/GUI/GUI.hpp"
#include "Http.hpp"
@ -25,8 +27,13 @@ namespace pt = boost::property_tree;
namespace Slic3r {
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]
std::string final_addr = orig_addr;
// 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);
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
@ -110,7 +146,7 @@ bool OctoPrint::test(wxString &msg) const
#ifdef WIN32
.ssl_revoke_best_effort(m_ssl_revoke_best_effort)
.on_ip_resolve([&](std::string address) {
msg = boost::nowide::widen(address);
msg = GUI::from_u8(address);
})
#endif
.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_parent_path = upload_data.upload_path.parent_path();
wxString test_msg;
if (! test(test_msg)) {
error_fn(std::move(test_msg));
// If test fails, test_msg_or_host_ip contains the error message.
// Otherwise on Windows it contains the resolved IP address of the host.
wxString test_msg_or_host_ip;
if (! test(test_msg_or_host_ip)) {
error_fn(std::move(test_msg_or_host_ip));
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";
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
// IP resolving will not happen - it could resolve into address not being specified in cert
url = make_url("api/files/local");
} else {
// 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.
// 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.
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
std::string final_addr = substitute_host(m_host, resolved_addr);
BOOST_LOG_TRIVIAL(debug) << "Upload address after ip resolve: " << final_addr;
url = make_url("api/files/local", final_addr);
url = substitute_host(make_url("api/files/local", m_host), GUI::into_u8(test_msg_or_host_ip));
BOOST_LOG_TRIVIAL(info) << "Upload address after ip resolve: " << url;
}
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;
// 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
{
public: