CLOUD: Add Reader sketch

That should be part of the Client, I guess. Reader is not ready to
continue reading from place it stopped, but it already works as it
should for the case when whole content is available.
This commit is contained in:
Alexander Tkachev 2016-07-07 16:57:14 +06:00
parent 4d88f51de9
commit 79b39bf0d0
3 changed files with 294 additions and 0 deletions

View file

@ -0,0 +1,220 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/networking/sdl_net/reader.h"
#include <common/debug.h>
namespace Networking {
Reader::Reader() {
_contentLength = 0;
_availableBytes = 0;
_window = nullptr;
_windowUsed = 0;
_windowSize = 0;
_content =
"POST /upload HTTP/1.1\r\n" \
"Host: 127.0.0.1:12345\r\n" \
"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0\r\n" \
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" \
"Accept-Language: ru,en-US;q=0.7,en;q=0.3\r\n" \
"Accept-Encoding: gzip, deflate\r\n" \
"Referer: http://127.0.0.1:12345/files\r\n" \
"Connection: keep-alive\r\n" \
"Content-Type: multipart/form-data; boundary=---------------------------93411339527546\r\n" \
"Content-Length: 319\r\n" \
"\r\n" \
"-----------------------------93411339527546\r\n" \
"Content-Disposition: form-data; name=\"path\"\r\n" \
"\r\n" \
"/root\r\n" \
"-----------------------------93411339527546\r\n" \
"Content-Disposition: form-data; name=\"upload_file\"; filename=\"irc.txt\"\r\n" \
"Content-Type: text/plain\r\n" \
"\r\n" \
"shells.fnordserver.eu/1400\r\n" \
"-----------------------------93411339527546--";
}
Reader::~Reader() {}
void Reader::readResponse() {
while (true) {
readHeaders(); //til "\r\n\r\n"
readContent(); //til "--" + _boundary
if (_availableBytes >= 2) {
Common::String bts;
bts += readOne();
bts += readOne();
if (bts == "--") break;
if (bts == "\r\n") continue;
warning("strange bytes: \"%s\"", bts);
} else {
warning("strange ending");
break;
}
}
if (_availableBytes > 0) debug("STRANGE END: %llu bytes left", _availableBytes);
else debug("END");
}
void Reader::readHeaders() {
Common::String boundary = "\r\n\r\n";
makeWindow(boundary.size());
Common::String headers = "";
while (readOneByteInString(headers, boundary));
handleHeaders(headers);
}
namespace {
void readFromThatUntilLineEnd(const char *cstr, Common::String needle, Common::String &result) {
const char *position = strstr(cstr, needle.c_str());
if (position) {
char c;
for (const char *i = position + needle.size(); c = *i, c != 0; ++i) {
if (c == '\n' || c == '\r') break;
result += c;
}
}
}
}
void Reader::handleHeaders(Common::String headers) {
debug("\nHANDLE HEADERS:\n>>%s<<", headers.c_str());
if (_boundary.empty()) {
//TODO: parse method, path, query, fragment
//find boundary
_boundary = "";
readFromThatUntilLineEnd(headers.c_str(), "boundary=", _boundary);
//find content length
Common::String contentLength = "";
readFromThatUntilLineEnd(headers.c_str(), "Content-Length: ", contentLength);
_contentLength = contentLength.asUint64();
_availableBytes = _contentLength;
debug("BOUNDARY: %s", _boundary.c_str());
debug("LENGTH: %llu", _contentLength);
} else {
//find field name
_currentFieldName = "";
readFromThatUntilLineEnd(headers.c_str(), "name=\"", _currentFieldName);
for (uint32 i = 0; i < _currentFieldName.size(); ++i)
if (_currentFieldName[i] == '\"') {
_currentFieldName.erase(i);
break;
}
debug("FIELD NAME: >>%s<<", _currentFieldName.c_str());
//find out field type
//_fieldIsFile = true;
}
}
void Reader::readContent() {
Common::String boundary = "--" + _boundary;
makeWindow(boundary.size());
/*
if (_fieldIsFile) {
//create temporary file
tempFileName = generateTempFileName();
stream = openFileStream(tempFileName);
//read till "--" + _boundary
while (readOneByteInStream(stream));
handleFileContent(tempFileName);
} else {
*/
Common::String buffer = "";
while (readOneByteInString(buffer, boundary)) ;
handleValueContent(buffer);
//}
}
void Reader::handleFileContent(Common::String filename) {
_attachedFiles[_currentFieldName] = filename;
}
void Reader::handleValueContent(Common::String value) {
debug("\nHANDLE CONTENT:\n>>%s<<", value.c_str());
_fields[_currentFieldName] = value;
}
void Reader::makeWindow(uint32 size) {
delete[] _window;
_window = nullptr;
_window = new byte[size];
_windowUsed = 0;
_windowSize = size;
}
/*
bool Reader::readOneByteInStream(stream) {
b = read(1);
_window[_windowUsed++] = b;
if (_windowUsed < _windowSize) return true;
//when window is filled, check whether that's the boundary
if (_window == "--" + _boundary)
return false;
//if not, write the first byte of the window to the stream
stream.write(_window[0]);
for (uint32 i = 1; i < _windowSize; ++i)
_window[i - 1] = _window[i];
--_windowUsed;
return true;
}
*/
bool Reader::readOneByteInString(Common::String &buffer, const Common::String &boundary) {
byte b = readOne();
_window[_windowUsed++] = b;
if (_windowUsed < _windowSize) return true;
//when window is filled, check whether that's the boundary
if (Common::String((char *)_window, _windowSize) == boundary)
return false;
//if not, add the first byte of the window to the string
buffer += _window[0];
for (uint32 i = 1; i < _windowSize; ++i)
_window[i - 1] = _window[i];
--_windowUsed;
return true;
}
byte Reader::readOne() {
byte b = _content[0];
_content.deleteChar(0);
--_availableBytes;
return b;
}
} // End of namespace Networking