CLOUD: Add UploadFileClientHandler

Now Client reads the first headers block, then LocalWebserver decides
which Handler to use. In case of "/upload", UploadFileHandler is used.

But now it only knows the "path" parameter. If that's valid, actual
UploadFileClientHandler is created, which reads the contents of the
request and, when finds there  an "upload_file" field, starts saving it
in the directory specified by "path".

With that we don't need temp files approach from Reader class.
This commit is contained in:
Alexander Tkachev 2016-07-09 15:49:18 +06:00
parent a424ebbc28
commit e4bb7c4e75
11 changed files with 597 additions and 163 deletions

View file

@ -135,14 +135,14 @@ void Reader::cleanup() {
}
}
bool Reader::readRequest() {
bool Reader::readWholeRequest() {
if (_state == RS_NONE) _state = RS_READING_HEADERS;
while (true) {
if (!bytesLeft()) return false;
if (_state == RS_READING_HEADERS)
if (!readHeaders())
if (!readWholeHeaders())
return false;
if (_boundary.empty()) return true; //not POST multipart
@ -150,7 +150,7 @@ bool Reader::readRequest() {
if (!bytesLeft()) return false;
if (_state == RS_READING_CONTENT)
if (!readContent())
if (!readWholeContent())
return false;
if (_availableBytes >= 2) {
@ -171,7 +171,69 @@ bool Reader::readRequest() {
return true;
}
bool Reader::readHeaders() {
bool Reader::readFirstHeaders() {
if (_state == RS_NONE) _state = RS_READING_HEADERS;
if (!bytesLeft()) return false;
if (_state == RS_READING_HEADERS)
return readWholeHeaders();
warning("Reader::readFirstHeaders(): bad state");
return false;
}
bool Reader::readFirstContent(Common::WriteStream *stream) {
if (_state != RS_READING_CONTENT) {
warning("Reader::readFirstContent(): bad state");
return false;
}
if (!bytesLeft()) return false;
return readWholeContentIntoStream(stream);
}
bool Reader::readBlockHeaders(Common::WriteStream *stream) {
if (_state != RS_READING_HEADERS) {
warning("Reader::readBlockHeaders(): bad state");
return false;
}
if (!bytesLeft()) return false;
return readWholeHeadersIntoStream(stream);
}
bool Reader::readBlockContent(Common::WriteStream *stream) {
if (_state != RS_READING_CONTENT) {
warning("Reader::readBlockContent(): bad state");
return false;
}
if (!bytesLeft()) return false;
if (!readWholeContentIntoStream(stream))
return false;
/*
if (_availableBytes >= 2) {
Common::String bts;
bts += readOne();
bts += readOne();
if (bts == "--") _isOver = true;
else if (bts != "\r\n")
warning("strange bytes: \"%s\"", bts.c_str());
} else {
warning("strange ending");
_isOver = true;
}
*/
return true;
}
bool Reader::readWholeHeaders() {
Common::String boundary = "\r\n\r\n";
if (_window == nullptr) {
makeWindow(boundary.size());
@ -188,6 +250,20 @@ bool Reader::readHeaders() {
return true;
}
bool Reader::readWholeHeadersIntoStream(Common::WriteStream *stream) {
Common::String boundary = "\r\n\r\n";
if (_window == nullptr) makeWindow(boundary.size());
while (readOneByteInStream(stream, boundary)) {
if (!bytesLeft()) return false;
}
if (stream) stream->flush();
freeWindow();
_state = RS_READING_CONTENT;
return true;
}
namespace {
void readFromThatUntilLineEnd(const char *cstr, Common::String needle, Common::String &result) {
const char *position = strstr(cstr, needle.c_str());
@ -383,7 +459,7 @@ Common::String generateTempFileName(Common::String originalFilename, Common::Ran
}
}
bool Reader::readContent() {
bool Reader::readWholeContent() {
Common::String boundary = "--" + _boundary;
if (!_firstBlock) boundary = "\r\n" + boundary;
if (_window == nullptr) {
@ -435,6 +511,23 @@ bool Reader::readContent() {
return true;
}
bool Reader::readWholeContentIntoStream(Common::WriteStream *stream) {
Common::String boundary = "--" + _boundary;
if (!_firstBlock) boundary = "\r\n" + boundary;
if (_window == nullptr) makeWindow(boundary.size());
while (readOneByteInStream(stream, boundary)) {
if (!bytesLeft()) return false;
}
_firstBlock = false;
if (stream) stream->flush();
freeWindow();
_state = RS_READING_HEADERS;
return true;
}
void Reader::handleFileContent(Common::String filename) {
debug("\nHANDLE FILE CONTENT:\nFILE >>%s<< SAVED INTO >>%s<<", _currentFileName.c_str(), filename.c_str());
_attachedFiles[_currentFileName] = filename;
@ -469,7 +562,7 @@ bool Reader::readOneByteInStream(Common::WriteStream *stream, const Common::Stri
return false;
//if not, add the first byte of the window to the string
stream->writeByte(_window[0]);
if (stream) stream->writeByte(_window[0]);
for (uint32 i = 1; i < _windowSize; ++i)
_window[i - 1] = _window[i];
--_windowUsed;
@ -494,8 +587,8 @@ bool Reader::readOneByteInString(Common::String &buffer, const Common::String &b
}
byte Reader::readOne() {
byte b = _content[0];
++_content;
byte b;
_content->read(&b, 1);
--_availableBytes;
--_bytesLeft;
return b;
@ -503,9 +596,9 @@ byte Reader::readOne() {
uint32 Reader::bytesLeft() { return _bytesLeft; }
void Reader::setContent(byte *buffer, uint32 size) {
_content = buffer;
_bytesLeft = size;
void Reader::setContent(Common::MemoryReadWriteStream *stream) {
_content = stream;
_bytesLeft = stream->size() - stream->pos();
}
bool Reader::badRequest() { return _isBadRequest; }