Fixed "Slic3r crashes when sending STLs with special characters to the printer"
https://github.com/prusa3d/Slic3r/issues/597 The "Send to OctoPrint" function will now send the file name encoded in UTF-8, so the file name will not get mangled. The C++ Slic3r::encode_path() function was returning a string to Perl, which was marked as UTF-8. This has been fixed, now encode_path() returns a plain Perl string. Added path_to_filename, path_to_stem, path_to_extension, path_to_parent_path Perl wrappers to boost::filesystem::path splitting functionality to be able to split UTF-8 encoded files on Windows correctly.
This commit is contained in:
parent
1bf67b4b62
commit
f5160b7a72
@ -1460,15 +1460,19 @@ sub send_gcode {
|
||||
my $ua = LWP::UserAgent->new;
|
||||
$ua->timeout(180);
|
||||
|
||||
my $enc_path = Slic3r::encode_path($self->{send_gcode_file});
|
||||
my $res = $ua->post(
|
||||
"http://" . $self->{config}->octoprint_host . "/api/files/local",
|
||||
Content_Type => 'form-data',
|
||||
'X-Api-Key' => $self->{config}->octoprint_apikey,
|
||||
Content => [
|
||||
# OctoPrint doesn't like Windows paths so we use basename()
|
||||
# Also, since we need to read from filesystem we process it through encode_path()
|
||||
file => [ $enc_path, basename($enc_path) ],
|
||||
file => [
|
||||
# On Windows, the path has to be encoded in local code page for perl to be able to open it.
|
||||
Slic3r::encode_path($self->{send_gcode_file}),
|
||||
# Remove the UTF-8 flag from the perl string, so the LWP::UserAgent can insert
|
||||
# the UTF-8 encoded string into the request as a byte stream.
|
||||
Encode::encode_utf8(Slic3r::path_to_filename($self->{send_gcode_file}))
|
||||
],
|
||||
print => $self->{send_gcode_file_print} ? 1 : 0,
|
||||
],
|
||||
);
|
||||
|
||||
|
@ -25,16 +25,39 @@ void set_data_dir(const std::string &path);
|
||||
// Return a full path to the GUI resource files.
|
||||
const std::string& data_dir();
|
||||
|
||||
extern std::string encode_path(const char *src);
|
||||
// A special type for strings encoded in the local Windows 8-bit code page.
|
||||
// This type is only needed for Perl bindings to relay to Perl that the string is raw, not UTF-8 encoded.
|
||||
typedef std::string local_encoded_string;
|
||||
|
||||
// Convert an UTF-8 encoded string into local coding.
|
||||
// On Windows, the UTF-8 string is converted to a local 8-bit code page.
|
||||
// On OSX and Linux, this function does no conversion and returns a copy of the source string.
|
||||
extern local_encoded_string encode_path(const char *src);
|
||||
extern std::string decode_path(const char *src);
|
||||
extern std::string normalize_utf8_nfc(const char *src);
|
||||
|
||||
// File path / name / extension splitting utilities, working with UTF-8,
|
||||
// to be published to Perl.
|
||||
namespace PerlUtils {
|
||||
// Get a file name including the extension.
|
||||
extern std::string path_to_filename(const char *src);
|
||||
// Get a file name without the extension.
|
||||
extern std::string path_to_stem(const char *src);
|
||||
// Get just the extension.
|
||||
extern std::string path_to_extension(const char *src);
|
||||
// Get a directory without the trailing slash.
|
||||
extern std::string path_to_parent_path(const char *src);
|
||||
};
|
||||
|
||||
// Timestamp formatted for header_slic3r_generated().
|
||||
extern std::string timestamp_str();
|
||||
// Standard "generated by Slic3r version xxx timestamp xxx" header string,
|
||||
// to be placed at the top of Slic3r generated files.
|
||||
inline std::string header_slic3r_generated() { return std::string("generated by " SLIC3R_FORK_NAME " " SLIC3R_VERSION " " ) + timestamp_str(); }
|
||||
|
||||
// Encode a file into a multi-part HTTP response with a given boundary.
|
||||
std::string octoprint_encode_file_send_request_content(const char *path, bool select, bool print, const char *boundary);
|
||||
|
||||
// Compute the next highest power of 2 of 32-bit v
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html
|
||||
template<typename T>
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/date_time/local_time/local_time.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/nowide/integration/filesystem.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
|
||||
@ -235,6 +237,17 @@ std::string normalize_utf8_nfc(const char *src)
|
||||
return boost::locale::normalize(src, boost::locale::norm_nfc, locale_utf8);
|
||||
}
|
||||
|
||||
namespace PerlUtils {
|
||||
// Get a file name including the extension.
|
||||
std::string path_to_filename(const char *src) { return boost::filesystem::path(src).filename().string(); }
|
||||
// Get a file name without the extension.
|
||||
std::string path_to_stem(const char *src) { return boost::filesystem::path(src).stem().string(); }
|
||||
// Get just the extension.
|
||||
std::string path_to_extension(const char *src) { return boost::filesystem::path(src).extension().string(); }
|
||||
// Get a directory without the trailing slash.
|
||||
std::string path_to_parent_path(const char *src) { return boost::filesystem::path(src).parent_path().string(); }
|
||||
};
|
||||
|
||||
std::string timestamp_str()
|
||||
{
|
||||
const auto now = boost::posix_time::second_clock::local_time();
|
||||
@ -247,4 +260,31 @@ std::string timestamp_str()
|
||||
return buf;
|
||||
}
|
||||
|
||||
std::string octoprint_encode_file_send_request_content(const char *cpath, bool select, bool print, const char *boundary)
|
||||
{
|
||||
// Read the complete G-code string into a string buffer.
|
||||
// It will throw if the file cannot be open or read.
|
||||
std::stringstream str_stream;
|
||||
{
|
||||
boost::nowide::ifstream ifs(cpath);
|
||||
str_stream << ifs.rdbuf();
|
||||
}
|
||||
|
||||
boost::filesystem::path path(cpath);
|
||||
std::string request = boundary + '\n';
|
||||
request += "Content-Disposition: form-data; name=\"";
|
||||
request += path.stem().string() + "\"; filename=\"" + path.filename().string() + "\"\n";
|
||||
request += "Content-Type: application/octet-stream\n\n";
|
||||
request += str_stream.str();
|
||||
request += boundary + '\n';
|
||||
request += "Content-Disposition: form-data; name=\"select\"\n\n";
|
||||
request += select ? "true\n" : "false\n";
|
||||
request += boundary + '\n';
|
||||
request += "Content-Disposition: form-data; name=\"print\"\n\n";
|
||||
request += print ? "true\n" : "false\n";
|
||||
request += boundary + '\n';
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
@ -91,7 +91,7 @@ data_dir()
|
||||
RETVAL = const_cast<char*>(Slic3r::data_dir().c_str());
|
||||
OUTPUT: RETVAL
|
||||
|
||||
std::string
|
||||
local_encoded_string
|
||||
encode_path(src)
|
||||
const char *src;
|
||||
CODE:
|
||||
@ -112,6 +112,34 @@ normalize_utf8_nfc(src)
|
||||
RETVAL = Slic3r::normalize_utf8_nfc(src);
|
||||
OUTPUT: RETVAL
|
||||
|
||||
std::string
|
||||
path_to_filename(src)
|
||||
const char *src;
|
||||
CODE:
|
||||
RETVAL = Slic3r::PerlUtils::path_to_filename(src);
|
||||
OUTPUT: RETVAL
|
||||
|
||||
std::string
|
||||
path_to_stem(src)
|
||||
const char *src;
|
||||
CODE:
|
||||
RETVAL = Slic3r::PerlUtils::path_to_stem(src);
|
||||
OUTPUT: RETVAL
|
||||
|
||||
std::string
|
||||
path_to_extension(src)
|
||||
const char *src;
|
||||
CODE:
|
||||
RETVAL = Slic3r::PerlUtils::path_to_extension(src);
|
||||
OUTPUT: RETVAL
|
||||
|
||||
std::string
|
||||
path_to_parent_path(src)
|
||||
const char *src;
|
||||
CODE:
|
||||
RETVAL = Slic3r::PerlUtils::path_to_parent_path(src);
|
||||
OUTPUT: RETVAL
|
||||
|
||||
void
|
||||
xspp_test_croak_hangs_on_strawberry()
|
||||
CODE:
|
||||
|
@ -1,6 +1,7 @@
|
||||
coordf_t T_NV
|
||||
|
||||
std::string T_STD_STRING
|
||||
local_encoded_string T_STD_STRING_LOCAL_ENCODING
|
||||
t_config_option_key T_STD_STRING
|
||||
t_model_material_id T_STD_STRING
|
||||
|
||||
@ -279,6 +280,14 @@ T_STD_STRING
|
||||
$var = std::string(c, len);
|
||||
}
|
||||
|
||||
INPUT
|
||||
T_STD_STRING_LOCAL_ENCODING
|
||||
{
|
||||
size_t len;
|
||||
const char * c = SvPV($arg, len);
|
||||
$var = std::string(c, len);
|
||||
}
|
||||
|
||||
T_STD_VECTOR_STD_STRING
|
||||
if (SvROK($arg) && SvTYPE(SvRV($arg))==SVt_PVAV) {
|
||||
AV* av = (AV*)SvRV($arg);
|
||||
@ -438,6 +447,9 @@ OUTPUT
|
||||
T_STD_STRING
|
||||
$arg = newSVpvn_utf8( $var.c_str(), $var.length(), true );
|
||||
|
||||
T_STD_STRING_LOCAL_ENCODING
|
||||
$arg = newSVpvn( $var.c_str(), $var.length() );
|
||||
|
||||
T_STD_VECTOR_STD_STRING
|
||||
AV* av = newAV();
|
||||
$arg = newRV_noinc((SV*)av);
|
||||
|
Loading…
Reference in New Issue
Block a user