Octoprint: Fix unicode support

This commit is contained in:
Vojtech Kral 2018-06-12 12:32:03 +02:00 committed by bubnikv
parent 1ba81655e2
commit 9ee10a8779
4 changed files with 77 additions and 38 deletions

View file

@ -3,13 +3,16 @@
#include <cstdlib>
#include <functional>
#include <thread>
#include <tuple>
#include <deque>
#include <boost/filesystem/fstream.hpp>
#include <boost/format.hpp>
#include <curl/curl.h>
#include "../../libslic3r/libslic3r.h"
namespace fs = boost::filesystem;
namespace Slic3r {
@ -34,7 +37,11 @@ struct Http::priv
::curl_httppost *form;
::curl_httppost *form_end;
::curl_slist *headerlist;
// Used for reading the body
std::string buffer;
// Used for storing file streams added as multipart form parts
// Using a deque here because unlike vector it doesn't ivalidate pointers on insertion
std::deque<std::ifstream> form_files;
size_t limit;
bool cancel;
@ -50,8 +57,9 @@ struct Http::priv
static size_t writecb(void *data, size_t size, size_t nmemb, void *userp);
static int xfercb(void *userp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);
static int xfercb_legacy(void *userp, double dltotal, double dlnow, double ultotal, double ulnow);
static size_t form_file_read_cb(char *buffer, size_t size, size_t nitems, void *userp);
void form_add_file(const char *name, const char *path, const char* filename);
void form_add_file(const char *name, const fs::path &path, const char* filename);
std::string curl_error(CURLcode curlcode);
std::string body_size_error();
@ -138,21 +146,42 @@ int Http::priv::xfercb_legacy(void *userp, double dltotal, double dlnow, double
return xfercb(userp, dltotal, dlnow, ultotal, ulnow);
}
void Http::priv::form_add_file(const char *name, const char *path, const char* filename)
size_t Http::priv::form_file_read_cb(char *buffer, size_t size, size_t nitems, void *userp)
{
auto stream = reinterpret_cast<fs::ifstream*>(userp);
try {
stream->read(buffer, size * nitems);
} catch (...) {
return CURL_READFUNC_ABORT;
}
return stream->gcount();
}
void Http::priv::form_add_file(const char *name, const fs::path &path, const char* filename)
{
// We can't use CURLFORM_FILECONTENT, because curl doesn't support Unicode filenames on Windows
// and so we use CURLFORM_STREAM with boost ifstream to read the file.
if (filename == nullptr) {
filename = path.string().c_str();
}
fs::ifstream stream(path, std::ios::in | std::ios::binary);
stream.seekg(0, std::ios::end);
size_t size = stream.tellg();
stream.seekg(0);
form_files.push_back(std::move(stream));
auto stream_ptr = &form_files.back();
if (filename != nullptr) {
::curl_formadd(&form, &form_end,
CURLFORM_COPYNAME, name,
CURLFORM_FILE, path,
CURLFORM_FILENAME, filename,
CURLFORM_CONTENTTYPE, "application/octet-stream",
CURLFORM_END
);
} else {
::curl_formadd(&form, &form_end,
CURLFORM_COPYNAME, name,
CURLFORM_FILE, path,
CURLFORM_CONTENTTYPE, "application/octet-stream",
CURLFORM_STREAM, static_cast<void*>(stream_ptr),
CURLFORM_CONTENTSLENGTH, static_cast<long>(size),
CURLFORM_END
);
}
@ -177,6 +206,7 @@ void Http::priv::http_perform()
::curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb);
::curl_easy_setopt(curl, CURLOPT_WRITEDATA, static_cast<void*>(this));
::curl_easy_setopt(curl, CURLOPT_READFUNCTION, form_file_read_cb);
::curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
#if LIBCURL_VERSION_MAJOR >= 7 && LIBCURL_VERSION_MINOR >= 32
@ -206,14 +236,20 @@ void Http::priv::http_perform()
if (res != CURLE_OK) {
if (res == CURLE_ABORTED_BY_CALLBACK) {
Progress dummyprogress(0, 0, 0, 0);
bool cancel = true;
if (progressfn) { progressfn(dummyprogress, cancel); }
if (cancel) {
// The abort comes from the request being cancelled programatically
Progress dummyprogress(0, 0, 0, 0);
bool cancel = true;
if (progressfn) { progressfn(dummyprogress, cancel); }
} else {
// The abort comes from the CURLOPT_READFUNCTION callback, which means reading file failed
if (errorfn) { errorfn(std::move(buffer), "Error reading file for file upload", http_status); }
}
}
else if (res == CURLE_WRITE_ERROR) {
if (errorfn) { errorfn(std::move(buffer), std::move(body_size_error()), http_status); }
if (errorfn) { errorfn(std::move(buffer), body_size_error(), http_status); }
} else {
if (errorfn) { errorfn(std::move(buffer), std::move(curl_error(res)), http_status); }
if (errorfn) { errorfn(std::move(buffer), curl_error(res), http_status); }
};
} else {
if (completefn) {
@ -288,13 +324,13 @@ Http& Http::form_add(const std::string &name, const std::string &contents)
return *this;
}
Http& Http::form_add_file(const std::string &name, const std::string &path)
Http& Http::form_add_file(const std::string &name, const fs::path &path)
{
if (p) { p->form_add_file(name.c_str(), path.c_str(), nullptr); }
return *this;
}
Http& Http::form_add_file(const std::string &name, const std::string &path, const std::string &filename)
Http& Http::form_add_file(const std::string &name, const fs::path &path, const std::string &filename)
{
if (p) { p->form_add_file(name.c_str(), path.c_str(), filename.c_str()); }
return *this;