1
0
Fork 0

foxx file upload

This commit is contained in:
Jan Steemann 2015-01-23 11:23:58 +01:00
parent f5aa621536
commit 81db41763f
4 changed files with 191 additions and 11 deletions

View File

@ -32,6 +32,7 @@
#include "Basics/FileUtils.h"
#include "Basics/files.h"
#include "Basics/logging.h"
#include "Basics/StringUtils.h"
#include "HttpServer/HttpServer.h"
#include "Rest/HttpRequest.h"
@ -77,7 +78,7 @@ Handler::status_t RestUploadHandler::execute () {
return status_t(Handler::HANDLER_DONE);
}
char* filename = NULL;
char* filename = nullptr;
if (TRI_GetTempName("uploads", &filename, false) != TRI_ERROR_NO_ERROR) {
generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_INTERNAL, "could not generate temp file");
@ -91,8 +92,28 @@ Handler::status_t RestUploadHandler::execute () {
filename,
relative);
char const* body = _request->body();
size_t bodySize = _request->bodySize();
bool found;
char const* value = _request->value("multipart", found);
bool multiPart = false;
if (found) {
multiPart = triagens::basics::StringUtils::boolean(value);
if (multiPart) {
if (! parseMultiPart(body, bodySize)) {
TRI_Free(TRI_CORE_MEM_ZONE, relative);
TRI_Free(TRI_CORE_MEM_ZONE, filename);
generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_INTERNAL, "invalid multipart request");
return status_t(Handler::HANDLER_FAILED);
}
}
}
try {
FileUtils::spit(string(filename), _request->body(), _request->bodySize());
FileUtils::spit(string(filename), body, bodySize);
TRI_Free(TRI_CORE_MEM_ZONE, filename);
}
catch (...) {
@ -111,16 +132,157 @@ Handler::status_t RestUploadHandler::execute () {
TRI_json_t json;
TRI_InitObjectJson(TRI_CORE_MEM_ZONE, &json);
TRI_Insert3ObjectJson(TRI_CORE_MEM_ZONE, &json, "filename", TRI_CreateStringJson(TRI_CORE_MEM_ZONE, fullName, strlen(fullName)));
TRI_InitObjectJson(TRI_UNKNOWN_MEM_ZONE, &json);
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, &json, "filename", TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, fullName, strlen(fullName)));
generateResult(HttpResponse::CREATED, &json);
TRI_DestroyJson(TRI_CORE_MEM_ZONE, &json);
TRI_DestroyJson(TRI_UNKNOWN_MEM_ZONE, &json);
// success
return status_t(Handler::HANDLER_DONE);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief parses a multi-part request body and determines the boundaries of
/// its first element
////////////////////////////////////////////////////////////////////////////////
bool RestUploadHandler::parseMultiPart (char const*& body,
size_t& length) {
char const* beg = _request->body();
char const* end = beg + _request->bodySize();
while (beg < end && (*beg == '\r' || *beg == '\n' || *beg == ' ')) {
++beg;
}
// find delimiter
char const* ptr = beg;
while (ptr < end && *ptr == '-') {
++ptr;
}
while (ptr < end && *ptr != '\r' && *ptr != '\n') {
++ptr;
}
if (ptr == beg) {
// oops
return false;
}
std::string const delimiter(beg, ptr - beg);
if (ptr < end && *ptr == '\r') {
++ptr;
}
if (ptr < end && *ptr == '\n') {
++ptr;
}
std::vector<std::pair<char const*, size_t>> parts;
while (ptr < end) {
char const* p = TRI_IsContainedMemory(ptr, end - ptr, delimiter.c_str(), delimiter.size());
if (p == nullptr || p + delimiter.size() + 2 >= end || p - 2 <= ptr) {
return false;
}
char const* q = p;
if (*(q - 1) == '\n') {
--q;
}
if (*(q - 1) == '\r') {
--q;
}
parts.push_back(std::make_pair(ptr, q - ptr));
ptr = p + delimiter.size();
if (*ptr == '-' && *(ptr + 1) == '-') {
// eom
break;
}
if (*ptr == '\r') {
++ptr;
}
if (ptr < end && *ptr == '\n') {
++ptr;
}
}
for (auto& part : parts) {
auto ptr = part.first;
auto end = part.first + part.second;
char const* data = nullptr;
while (ptr < end) {
while (ptr < end && *ptr == ' ') {
++ptr;
}
if (ptr < end && (*ptr == '\r' || *ptr == '\n')) {
// end of headers
if (*ptr == '\r') {
++ptr;
}
if (ptr < end && *ptr == '\n') {
++ptr;
}
data = ptr;
break;
}
// header line
char const* eol = TRI_IsContainedMemory(ptr, end - ptr, "\r\n", 2);
if (eol == nullptr) {
eol = TRI_IsContainedMemory(ptr, end - ptr, "\n", 1);
}
if (eol == nullptr) {
return false;
}
char const* colon = TRI_IsContainedMemory(ptr, end - ptr, ":", 1);
if (colon == nullptr) {
return false;
}
char const* p = colon;
while (p > ptr && *(p - 1) == ' ') {
--p;
}
++colon;
while (colon < eol && *colon == ' ') {
++colon;
}
char const* q = eol;
while (q > ptr && *(q - 1) == ' ') {
--q;
}
ptr = eol;
if (*ptr == '\r') {
++ptr;
}
if (ptr < end && *ptr == '\n') {
++ptr;
}
}
if (data == nullptr) {
return false;
}
body = data;
length = static_cast<size_t>(end - data);
// stop after the first found element
break;
}
return true;
}
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------

View File

@ -74,6 +74,14 @@ namespace triagens {
Handler::status_t execute ();
////////////////////////////////////////////////////////////////////////////////
/// @brief parses a multi-part request body and determines the boundaries of
/// its first element
////////////////////////////////////////////////////////////////////////////////
bool parseMultiPart (char const*&,
size_t&);
};
}
}

View File

@ -124,10 +124,11 @@
$.ajax({
type: "POST",
async: false,
url: '/_api/upload',
url: '/_api/upload?multipart=true',
contentType: "multipart/form-data",
data: self.file,
processData: false,
contentType: 'application/octet-stream',
cache: false,
complete: function(res) {
if (res.readyState === 4) {
if (res.status === 201) {
@ -737,7 +738,7 @@
width: "336px"
});
$("#upload-foxx-zip").uploadFile({
url: "/_api/upload",
url: "/_api/upload?multipart=true",
allowedTypes: "zip",
onSuccess: this.installFoxxFromZip.bind(this)
});

View File

@ -129,13 +129,11 @@ static int ExtractCurrentFile (unzFile uf,
// cannot write to outfile. this may be due to the target directory missing
if (fout == NULL && ! skipPaths && filenameWithoutPath != (char*) filenameInZip) {
char* d;
char c = *(filenameWithoutPath - 1);
*(filenameWithoutPath - 1) = '\0';
// create target directory recursively
d = TRI_Concatenate2File(outPath, filenameInZip);
char* d = TRI_Concatenate2File(outPath, filenameInZip);
TRI_CreateRecursiveDirectory(d);
TRI_Free(TRI_CORE_MEM_ZONE, d);
@ -144,6 +142,17 @@ static int ExtractCurrentFile (unzFile uf,
// try again
fout = fopen(fullPath, "wb");
}
else if (fout == nullptr) {
// try to create the target directory recursively
char* d = TRI_Concatenate2File(outPath, filenameInZip);
// strip filename so we only have the directory name
char* dir = TRI_Dirname(d);
TRI_Free(TRI_CORE_MEM_ZONE, d);
TRI_CreateRecursiveDirectory(dir);
TRI_Free(TRI_CORE_MEM_ZONE, dir);
// try again
fout = fopen(fullPath, "wb");
}
TRI_Free(TRI_CORE_MEM_ZONE, fullPath);