Added networking support for SL1 Digest authorization.

Renamed login/password/authorization_type to printhost_user/printhost_password/printhost_authorization_type.
Added initialization of physical printer preset with default values.
This commit is contained in:
Vojtech Bubnik 2020-09-08 15:30:59 +02:00
parent 0a4debc98c
commit ce06fc6cb7
11 changed files with 98 additions and 41 deletions

View file

@ -1365,9 +1365,10 @@ const std::vector<std::string>& PhysicalPrinter::printer_options()
"print_host", "print_host",
"printhost_apikey", "printhost_apikey",
"printhost_cafile", "printhost_cafile",
"authorization_type", "printhost_authorization_type",
"login", // HTTP digest authentization (RFC 2617)
"password" "printhost_user",
"printhost_password"
}; };
} }
return s_opts; return s_opts;
@ -1412,11 +1413,11 @@ const std::set<std::string>& PhysicalPrinter::get_preset_names() const
bool PhysicalPrinter::has_empty_config() const bool PhysicalPrinter::has_empty_config() const
{ {
return config.opt_string("print_host" ).empty() && return config.opt_string("print_host" ).empty() &&
config.opt_string("printhost_apikey").empty() && config.opt_string("printhost_apikey" ).empty() &&
config.opt_string("printhost_cafile").empty() && config.opt_string("printhost_cafile" ).empty() &&
config.opt_string("login" ).empty() && config.opt_string("printhost_user" ).empty() &&
config.opt_string("password" ).empty(); config.opt_string("printhost_password").empty();
} }
void PhysicalPrinter::update_preset_names_in_config() void PhysicalPrinter::update_preset_names_in_config()
@ -1441,7 +1442,7 @@ void PhysicalPrinter::save(const std::string& file_name_from, const std::string&
void PhysicalPrinter::update_from_preset(const Preset& preset) void PhysicalPrinter::update_from_preset(const Preset& preset)
{ {
config.apply_only(preset.config, printer_options(), false); config.apply_only(preset.config, printer_options(), true);
// add preset names to the options list // add preset names to the options list
auto ret = preset_names.emplace(preset.name); auto ret = preset_names.emplace(preset.name);
update_preset_names_in_config(); update_preset_names_in_config();
@ -1476,8 +1477,8 @@ bool PhysicalPrinter::delete_preset(const std::string& preset_name)
return preset_names.erase(preset_name) > 0; return preset_names.erase(preset_name) > 0;
} }
PhysicalPrinter::PhysicalPrinter(const std::string& name, const Preset& preset) : PhysicalPrinter::PhysicalPrinter(const std::string& name, const DynamicPrintConfig &default_config, const Preset& preset) :
name(name) name(name), config(default_config)
{ {
update_from_preset(preset); update_from_preset(preset);
} }
@ -1514,6 +1515,13 @@ std::string PhysicalPrinter::get_preset_name(std::string name)
PhysicalPrinterCollection::PhysicalPrinterCollection( const std::vector<std::string>& keys) PhysicalPrinterCollection::PhysicalPrinterCollection( const std::vector<std::string>& keys)
{ {
// Default config for a physical printer containing all key/value pairs of PhysicalPrinter::printer_options().
for (const std::string &key : keys) {
const ConfigOptionDef *opt = print_config_def.get(key);
assert(opt);
assert(opt->default_value);
m_default_config.set_key_value(key, opt->default_value->clone());
}
} }
// Load all printers found in dir_path. // Load all printers found in dir_path.
@ -1539,7 +1547,7 @@ void PhysicalPrinterCollection::load_printers(const std::string& dir_path, const
continue; continue;
} }
try { try {
PhysicalPrinter printer(name); PhysicalPrinter printer(name, this->default_config());
printer.file = dir_entry.path().string(); printer.file = dir_entry.path().string();
// Load the preset file, apply preset values on top of defaults. // Load the preset file, apply preset values on top of defaults.
try { try {
@ -1590,7 +1598,7 @@ void PhysicalPrinterCollection::load_printers_from_presets(PrinterPresetCollecti
new_printer_name = (boost::format("Printer %1%") % ++cnt).str(); new_printer_name = (boost::format("Printer %1%") % ++cnt).str();
// create new printer from this preset // create new printer from this preset
PhysicalPrinter printer(new_printer_name, preset); PhysicalPrinter printer(new_printer_name, this->default_config(), preset);
printer.loaded = true; printer.loaded = true;
save_printer(printer); save_printer(printer);
} }

View file

@ -460,8 +460,7 @@ private:
// If a preset does not exist, an iterator is returned indicating where to insert a preset with the same name. // If a preset does not exist, an iterator is returned indicating where to insert a preset with the same name.
std::deque<Preset>::iterator find_preset_internal(const std::string &name) std::deque<Preset>::iterator find_preset_internal(const std::string &name)
{ {
Preset key(m_type, name); auto it = Slic3r::lower_bound_by_predicate(m_presets.begin() + m_num_default_presets, m_presets.end(), [&name](const auto& l) { return l.name < name; });
auto it = std::lower_bound(m_presets.begin() + m_num_default_presets, m_presets.end(), key);
if (it == m_presets.end() || it->name != name) { if (it == m_presets.end() || it->name != name) {
// Preset has not been not found in the sorted list of non-default presets. Try the defaults. // Preset has not been not found in the sorted list of non-default presets. Try the defaults.
for (size_t i = 0; i < m_num_default_presets; ++ i) for (size_t i = 0; i < m_num_default_presets; ++ i)
@ -539,9 +538,8 @@ namespace PresetUtils {
class PhysicalPrinter class PhysicalPrinter
{ {
public: public:
PhysicalPrinter() {} PhysicalPrinter(const std::string& name, const DynamicPrintConfig &default_config) : name(name), config(default_config) {}
PhysicalPrinter(const std::string& name) : name(name){} PhysicalPrinter(const std::string& name, const DynamicPrintConfig &default_config, const Preset& preset);
PhysicalPrinter(const std::string& name, const Preset& preset);
void set_name(const std::string &name); void set_name(const std::string &name);
// Name of the Physical Printer, usually derived form the file name. // Name of the Physical Printer, usually derived form the file name.
@ -698,6 +696,8 @@ public:
// Generate a file path from a profile name. Add the ".ini" suffix if it is missing. // Generate a file path from a profile name. Add the ".ini" suffix if it is missing.
std::string path_from_name(const std::string& new_name) const; std::string path_from_name(const std::string& new_name) const;
const DynamicPrintConfig& default_config() const { return m_default_config; }
private: private:
PhysicalPrinterCollection& operator=(const PhysicalPrinterCollection& other); PhysicalPrinterCollection& operator=(const PhysicalPrinterCollection& other);
@ -707,9 +707,7 @@ private:
// If a preset does not exist, an iterator is returned indicating where to insert a preset with the same name. // If a preset does not exist, an iterator is returned indicating where to insert a preset with the same name.
std::deque<PhysicalPrinter>::iterator find_printer_internal(const std::string& name) std::deque<PhysicalPrinter>::iterator find_printer_internal(const std::string& name)
{ {
PhysicalPrinter printer(name); return Slic3r::lower_bound_by_predicate(m_printers.begin(), m_printers.end(), [&name](const auto& l) { return l.name < name; });
auto it = std::lower_bound(m_printers.begin(), m_printers.end(), printer);
return it;
} }
std::deque<PhysicalPrinter>::const_iterator find_printer_internal(const std::string& name) const std::deque<PhysicalPrinter>::const_iterator find_printer_internal(const std::string& name) const
{ {
@ -723,6 +721,9 @@ private:
// so that the addresses of the presets don't change during resizing of the container. // so that the addresses of the presets don't change during resizing of the container.
std::deque<PhysicalPrinter> m_printers; std::deque<PhysicalPrinter> m_printers;
// Default config for a physical printer containing all key/value pairs of PhysicalPrinter::printer_options().
DynamicPrintConfig m_default_config;
// Selected printer. // Selected printer.
size_t m_idx_selected = size_t(-1); size_t m_idx_selected = size_t(-1);
// The name of the preset which is currently select for this printer // The name of the preset which is currently select for this printer

View file

@ -133,13 +133,13 @@ void PrintConfigDef::init_common_params()
// Options used by physical printers // Options used by physical printers
def = this->add("login", coString); def = this->add("printhost_user", coString);
def->label = L("Login"); def->label = L("User");
// def->tooltip = L(""); // def->tooltip = L("");
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionString("")); def->set_default_value(new ConfigOptionString(""));
def = this->add("password", coString); def = this->add("printhost_password", coString);
def->label = L("Password"); def->label = L("Password");
// def->tooltip = L(""); // def->tooltip = L("");
def->mode = comAdvanced; def->mode = comAdvanced;
@ -151,7 +151,7 @@ void PrintConfigDef::init_common_params()
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionString("")); def->set_default_value(new ConfigOptionString(""));
def = this->add("authorization_type", coEnum); def = this->add("printhost_authorization_type", coEnum);
def->label = L("Authorization Type"); def->label = L("Authorization Type");
// def->tooltip = L(""); // def->tooltip = L("");
def->enum_keys_map = &ConfigOptionEnum<AuthorizationType>::get_enum_values(); def->enum_keys_map = &ConfigOptionEnum<AuthorizationType>::get_enum_values();

View file

@ -1080,7 +1080,7 @@ boost::any& Choice::get_value()
m_value = static_cast<SLADisplayOrientation>(ret_enum); m_value = static_cast<SLADisplayOrientation>(ret_enum);
else if (m_opt_id.compare("support_pillar_connection_mode") == 0) else if (m_opt_id.compare("support_pillar_connection_mode") == 0)
m_value = static_cast<SLAPillarConnectionMode>(ret_enum); m_value = static_cast<SLAPillarConnectionMode>(ret_enum);
else if (m_opt_id == "authorization_type") else if (m_opt_id == "printhost_authorization_type")
m_value = static_cast<AuthorizationType>(ret_enum); m_value = static_cast<AuthorizationType>(ret_enum);
} }
else if (m_opt.gui_type == "f_enum_open") { else if (m_opt.gui_type == "f_enum_open") {

View file

@ -194,7 +194,7 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
config.set_key_value(opt_key, new ConfigOptionEnum<SLADisplayOrientation>(boost::any_cast<SLADisplayOrientation>(value))); config.set_key_value(opt_key, new ConfigOptionEnum<SLADisplayOrientation>(boost::any_cast<SLADisplayOrientation>(value)));
else if(opt_key.compare("support_pillar_connection_mode") == 0) else if(opt_key.compare("support_pillar_connection_mode") == 0)
config.set_key_value(opt_key, new ConfigOptionEnum<SLAPillarConnectionMode>(boost::any_cast<SLAPillarConnectionMode>(value))); config.set_key_value(opt_key, new ConfigOptionEnum<SLAPillarConnectionMode>(boost::any_cast<SLAPillarConnectionMode>(value)));
else if(opt_key == "authorization_type") else if(opt_key == "printhost_authorization_type")
config.set_key_value(opt_key, new ConfigOptionEnum<AuthorizationType>(boost::any_cast<AuthorizationType>(value))); config.set_key_value(opt_key, new ConfigOptionEnum<AuthorizationType>(boost::any_cast<AuthorizationType>(value)));
} }
break; break;

View file

@ -755,7 +755,7 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
else if (opt_key == "support_pillar_connection_mode") { else if (opt_key == "support_pillar_connection_mode") {
ret = static_cast<int>(config.option<ConfigOptionEnum<SLAPillarConnectionMode>>(opt_key)->value); ret = static_cast<int>(config.option<ConfigOptionEnum<SLAPillarConnectionMode>>(opt_key)->value);
} }
else if (opt_key == "authorization_type") { else if (opt_key == "printhost_authorization_type") {
ret = static_cast<int>(config.option<ConfigOptionEnum<AuthorizationType>>(opt_key)->value); ret = static_cast<int>(config.option<ConfigOptionEnum<AuthorizationType>>(opt_key)->value);
} }
} }

View file

@ -155,8 +155,9 @@ void PresetForPrinter::msw_rescale()
// PhysicalPrinterDialog // PhysicalPrinterDialog
//------------------------------------------ //------------------------------------------
PhysicalPrinterDialog::PhysicalPrinterDialog(wxString printer_name) PhysicalPrinterDialog::PhysicalPrinterDialog(wxString printer_name) :
: DPIDialog(NULL, wxID_ANY, _L("Physical Printer"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), -1), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) DPIDialog(NULL, wxID_ANY, _L("Physical Printer"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), -1), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
m_printer("", wxGetApp().preset_bundle->physical_printers.default_config())
{ {
SetFont(wxGetApp().normal_font()); SetFont(wxGetApp().normal_font());
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
@ -186,7 +187,8 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxString printer_name)
PhysicalPrinter* printer = printers.find_printer(into_u8(printer_name)); PhysicalPrinter* printer = printers.find_printer(into_u8(printer_name));
if (!printer) { if (!printer) {
const Preset& preset = wxGetApp().preset_bundle->printers.get_edited_preset(); const Preset& preset = wxGetApp().preset_bundle->printers.get_edited_preset();
printer = new PhysicalPrinter(into_u8(printer_name), preset); //FIXME Vojtech: WTF??? Memory leak?
printer = new PhysicalPrinter(into_u8(printer_name), m_printer.config, preset);
// if printer_name is empty it means that new printer is created, so enable all items in the preset list // if printer_name is empty it means that new printer is created, so enable all items in the preset list
m_presets.emplace_back(new PresetForPrinter(this, preset.name)); m_presets.emplace_back(new PresetForPrinter(this, preset.name));
} }
@ -249,7 +251,7 @@ PhysicalPrinterDialog::~PhysicalPrinterDialog()
void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgroup) void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgroup)
{ {
m_optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value) { m_optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
if (opt_key == "authorization_type") if (opt_key == "printhost_authorization_type")
this->update(); this->update();
}; };
@ -308,7 +310,7 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
host_line.append_widget(print_host_test); host_line.append_widget(print_host_test);
m_optgroup->append_line(host_line); m_optgroup->append_line(host_line);
m_optgroup->append_single_option_line("authorization_type"); m_optgroup->append_single_option_line("printhost_authorization_type");
option = m_optgroup->get_option("printhost_apikey"); option = m_optgroup->get_option("printhost_apikey");
option.opt.width = Field::def_width_wider(); option.opt.width = Field::def_width_wider();
@ -368,7 +370,7 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
m_optgroup->append_line(line); m_optgroup->append_line(line);
} }
for (const std::string& opt_key : std::vector<std::string>{ "login", "password" }) { for (const std::string& opt_key : std::vector<std::string>{ "printhost_user", "printhost_password" }) {
option = m_optgroup->get_option(opt_key); option = m_optgroup->get_option(opt_key);
option.opt.width = Field::def_width_wider(); option.opt.width = Field::def_width_wider();
m_optgroup->append_single_option_line(option); m_optgroup->append_single_option_line(option);
@ -385,20 +387,20 @@ void PhysicalPrinterDialog::update()
// Only offer the host type selection for FFF, for SLA it's always the SL1 printer (at the moment) // Only offer the host type selection for FFF, for SLA it's always the SL1 printer (at the moment)
if (tech == ptFFF) { if (tech == ptFFF) {
m_optgroup->show_field("host_type"); m_optgroup->show_field("host_type");
m_optgroup->hide_field("authorization_type"); m_optgroup->hide_field("printhost_authorization_type");
for (const std::string& opt_key : std::vector<std::string>{ "login", "password" }) for (const std::string& opt_key : std::vector<std::string>{ "printhost_user", "printhost_password" })
m_optgroup->hide_field(opt_key); m_optgroup->hide_field(opt_key);
} }
else { else {
m_optgroup->set_value("host_type", int(PrintHostType::htOctoPrint), false); m_optgroup->set_value("host_type", int(PrintHostType::htOctoPrint), false);
m_optgroup->hide_field("host_type"); m_optgroup->hide_field("host_type");
m_optgroup->show_field("authorization_type"); m_optgroup->show_field("printhost_authorization_type");
AuthorizationType auth_type = m_config->option<ConfigOptionEnum<AuthorizationType>>("authorization_type")->value; AuthorizationType auth_type = m_config->option<ConfigOptionEnum<AuthorizationType>>("printhost_authorization_type")->value;
m_optgroup->show_field("printhost_apikey", auth_type == AuthorizationType::atKeyPassword); m_optgroup->show_field("printhost_apikey", auth_type == AuthorizationType::atKeyPassword);
for (const std::string& opt_key : std::vector<std::string>{ "login", "password" }) for (const std::string& opt_key : std::vector<std::string>{ "printhost_user", "printhost_password" })
m_optgroup->show_field(opt_key, auth_type == AuthorizationType::atUserPassword); m_optgroup->show_field(opt_key, auth_type == AuthorizationType::atUserPassword);
} }

View file

@ -415,6 +415,16 @@ Http& Http::remove_header(std::string name)
return *this; return *this;
} }
// Authorization by HTTP digest, based on RFC2617.
Http& Http::auth_digest(const std::string &user, const std::string &password)
{
curl_easy_setopt(p->curl, CURLOPT_USERNAME, user.c_str());
curl_easy_setopt(p->curl, CURLOPT_PASSWORD, password.c_str());
curl_easy_setopt(p->curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
return *this;
}
Http& Http::ca_file(const std::string &name) Http& Http::ca_file(const std::string &name)
{ {
if (p && priv::ca_file_supported(p->curl)) { if (p && priv::ca_file_supported(p->curl)) {

View file

@ -64,6 +64,8 @@ public:
Http& header(std::string name, const std::string &value); Http& header(std::string name, const std::string &value);
// Removes a header field. // Removes a header field.
Http& remove_header(std::string name); Http& remove_header(std::string name);
// Authorization by HTTP digest, based on RFC2617.
Http& auth_digest(const std::string &user, const std::string &password);
// Sets a CA certificate file for usage with HTTPS. This is only supported on some backends, // Sets a CA certificate file for usage with HTTPS. This is only supported on some backends,
// specifically, this is supported with OpenSSL and NOT supported with Windows and OS X native certificate store. // specifically, this is supported with OpenSSL and NOT supported with Windows and OS X native certificate store.
// See also ca_file_supported(). // See also ca_file_supported().

View file

@ -170,6 +170,13 @@ std::string OctoPrint::make_url(const std::string &path) const
} }
} }
SL1Host::SL1Host(DynamicPrintConfig *config) :
OctoPrint(config),
authorization_type(dynamic_cast<const ConfigOptionEnum<AuthorizationType>*>(config->option("printhost_authorization_type"))->value),
username(config->opt_string("printhost_user")),
password(config->opt_string("printhost_password"))
{
}
// SL1Host // SL1Host
const char* SL1Host::get_name() const { return "SL1Host"; } const char* SL1Host::get_name() const { return "SL1Host"; }
@ -191,4 +198,20 @@ bool SL1Host::validate_version_text(const boost::optional<std::string> &version_
return version_text ? boost::starts_with(*version_text, "Prusa SLA") : false; return version_text ? boost::starts_with(*version_text, "Prusa SLA") : false;
} }
void SL1Host::set_auth(Http &http) const
{
switch (authorization_type) {
case atKeyPassword:
http.header("X-Api-Key", get_apikey());
break;
case atUserPassword:
http.auth_digest(username, password);
break;
}
if (! get_cafile().empty()) {
http.ca_file(get_cafile());
}
}
} }

View file

@ -29,6 +29,8 @@ public:
bool can_test() const override { return true; } bool can_test() const override { return true; }
bool can_start_print() const override { return true; } bool can_start_print() const override { return true; }
std::string get_host() const override { return host; } std::string get_host() const override { return host; }
const std::string& get_apikey() const { return apikey; }
const std::string& get_cafile() const { return cafile; }
protected: protected:
virtual bool validate_version_text(const boost::optional<std::string> &version_text) const; virtual bool validate_version_text(const boost::optional<std::string> &version_text) const;
@ -38,14 +40,14 @@ private:
std::string apikey; std::string apikey;
std::string cafile; std::string cafile;
void set_auth(Http &http) const; virtual void set_auth(Http &http) const;
std::string make_url(const std::string &path) const; std::string make_url(const std::string &path) const;
}; };
class SL1Host: public OctoPrint class SL1Host: public OctoPrint
{ {
public: public:
SL1Host(DynamicPrintConfig *config) : OctoPrint(config) {} SL1Host(DynamicPrintConfig *config);
~SL1Host() override = default; ~SL1Host() override = default;
const char* get_name() const override; const char* get_name() const override;
@ -56,6 +58,15 @@ public:
protected: protected:
bool validate_version_text(const boost::optional<std::string> &version_text) const override; bool validate_version_text(const boost::optional<std::string> &version_text) const override;
private:
void set_auth(Http &http) const override;
// Host authorization type.
AuthorizationType authorization_type;
// username and password for HTTP Digest Authentization (RFC RFC2617)
std::string username;
std::string password;
}; };
} }