Updated and working.

This commit is contained in:
Brad Arant 2022-01-24 14:03:58 -08:00
parent d4148b0ab4
commit a37c4e6829
30 changed files with 422 additions and 226 deletions

17
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,17 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "gnu17",
"cppStandard": "gnu++14",
"intelliSenseMode": "linux-gcc-x64",
"configurationProvider": "ms-vscode.cmake-tools"
}
],
"version": 4
}

View File

@ -1,3 +1,5 @@
{
"cmake.configureOnOpen": false
"cmake.configureOnOpen": false,
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
"C_Cpp.errorSquiggles": "Enabled"
}

View File

@ -3,6 +3,7 @@
# include "includes"
# include "DirectoryEntry.h"
# include "Log.h"
namespace coreutils {
@ -29,7 +30,7 @@ namespace coreutils {
}
DirectoryEntry get() {
if(cursor == directory.end())
if(eod())
return NULL;
return cursor->second;
}

View File

@ -18,6 +18,18 @@ namespace coreutils {
return std::string(entry.d_name);
}
unsigned char getType() {
return entry.d_type;
}
bool isFile() {
return entry.d_type == DT_REG;
}
bool isDirectory() {
return entry.d_type == DT_DIR;
}
private:
struct dirent entry;

View File

@ -1,7 +1,8 @@
#ifndef __Exception_h__
#define __Exception_h__
#include "includes"
#include <string.h>
#include <string>
namespace coreutils {

View File

@ -23,7 +23,8 @@ namespace coreutils {
}
File::~File() {
close(fd);
setBufferSize(0);
}
void File::setBufferSize(size_t size) {

View File

@ -1,18 +0,0 @@
#ifndef __IMFBody_h__
#define __IMFBody_h__
#include "ZString.h"
namespace coreutils {
class IMFBody : public ZString {
public:
IMFBody() {}
IMFBody(ZString &body) : ZString(body) {}
};
}
#endif

View File

@ -6,18 +6,16 @@ namespace coreutils {
IMFFormData::IMFFormData() {}
IMFFormData::IMFFormData(ZString &in, ZString boundary) : IMFMultipart(in, boundary) {
IMFFormData::IMFFormData(ZString &in, ZString &boundary) : IMFMultipart(in, boundary) {}
}
IMFBody * IMFFormData::getByName(ZString name) {
ZString IMFFormData::getByName(ZString &name) {
for(ZString section: sections) {
IMFMessage message(section);
if(message.getHeaderKeyPairValue((char *)"Content-Disposition", (char *)"name").equals(name)) {
return message.getBody();
if(message.getHeaderKeyPairValue("Content-Disposition", ("name")).equals(name)) {
return message.multipart;
}
}
return new IMFBody();
return ZString();
}
}

View File

@ -9,9 +9,9 @@ namespace coreutils {
public:
IMFFormData();
IMFFormData(ZString &in, ZString boundary);
IMFFormData(ZString &in, ZString &boundary);
IMFBody * getByName(ZString name);
ZString getByName(ZString &name);
};

View File

@ -4,29 +4,19 @@
namespace coreutils {
IMFHeader::IMFHeader() : ZString() {
}
IMFHeader::IMFHeader(ZString &in) : ZString(in) {
key = in.getTokenInclude((char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-0123456789");
key = in.getTokenInclude("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_0123456789");
if(key.getLength() != 0) {
if(!in.ifNext((char *)":")) {
printf("key=%s %02X\n", key.str().c_str(), in.str()[0]);
if(!in.ifNext(":"))
throw coreutils::Exception("Invalid character in expected header token.");
}
in.skipWhitespace();
value = in.goeol();
}
else if(in.skipWhitespace() > 0) {}
else if(in.str() == "") {}
coreutils::Log(coreutils::LOG_DEBUG_2) << " " << key << "[" << value << "]";
}
IMFHeader::IMFHeader(ZString key, ZString value) : ZString() {
this->key = key;
this->value = value;
}
IMFHeader::IMFHeader(ZString key, ZString value) : ZString(), key(key), value(value) {}
ZString IMFHeader::getKey() {
return key;

View File

@ -2,13 +2,13 @@
#define __IMFHeader_h__
#include "ZString.h"
#include <sstream>
namespace coreutils {
class IMFHeader : public ZString {
public:
IMFHeader();
IMFHeader(ZString &in);
IMFHeader(ZString key, ZString value);

View File

@ -6,41 +6,48 @@
namespace coreutils {
IMFMessage::IMFMessage() : ZString() {
}
IMFMessage::IMFMessage() : ZString() {}
IMFMessage::IMFMessage(ZString &in) : ZString(in) {
while (!in.ifNext("\r\n")) {
while (!in.ifNext("\r\n"))
headers.emplace_back(in);
}
ZString type = getHeader("Content-Type");
int len = getHeader("Content-Length").asInteger();
if(len > 0) {
ZString block = in.readBlock(len);
if(type.equals("multipart/form-data"))
body = new IMFMultipart(block, getHeaderKeyPairValue("Content-Type", "boundary"));
else if(type.equals("text/plain"))
body = new IMFPlainText(block);
else
body = new IMFBody(block);
block = in.readBlock(len);
if(type.equals("multipart/form-data")) {
ZString boundary(getHeaderKeyPairValue("Content-Type", "boundary"));
multipart = IMFMultipart(block, boundary);
}
}
}
IMFMessage::~IMFMessage() {}
void IMFMessage::output(std::stringstream &out) {
for(IMFHeader header: headers) {
out << header.getKey() << ": " << header.getValue() << "\r\n";
}
out << "\r\n";
// for(IMFHeader header: headers) {
// out << header.getKey() << ": " << header.getValue() << "\r\n";
// }
out << newHeaders.str() << "\r\n";
}
void IMFMessage::addHeader(ZString key, ZString value) {
headers.emplace_back(key, value);
void IMFMessage::addHeader(const char *key, const char *value) {
newHeaders << key << ": " << value << "\r\n";
}
void IMFMessage::addHeader(const char *key, ZString value) {
headers.emplace_back(ZString(key), value);
void IMFMessage::addHeader(const char *key, std::string &value) {
newHeaders << key << ": " << value << "\r\n";
}
void IMFMessage::addHeader(ZString &key, ZString &value) {
newHeaders << key << ": " << value << "\r\n";
}
void IMFMessage::addHeader(const char *key, ZString &value) {
newHeaders << key << ": " << value << "\r\n";
}
ZString IMFMessage::getHeader(ZString key, bool valueOnly) {
@ -64,37 +71,27 @@ namespace coreutils {
ZString IMFMessage::getHeaderKeyPairValue(ZString headerKey, ZString key) {
ZString value;
ZString psource(getHeader(headerKey, false));
std::vector<ZString> sourcep = psource.split(";");
for(ZString work: sourcep) {
for(ZString work: psource.split(";")) {
work.skipWhitespace();
ZString token = work.getTokenExclude("=");
if(work.ifNext((char *)"=")) {
if(work.ifNext("=")) {
if(token.equals(key)) {
if(work.ifNext((char *)"\"")) {
value = work.getTokenExclude((char *)"\"");
return value;
}
else {
if(work.ifNext("\""))
value = work.getTokenExclude("\"");
else
value = work;
return value;
}
}
else
continue;
} else if (work.ifNext((char *)";") || work.ifNext((char *)" ")) {
} else if (work.ifNext(";") || work.ifNext(" ")) {
if(token.equals(key))
return ZString((char *)"true");
return ZString("true");
else
continue;
}
}
return ZString((char *)"false");
}
IMFBody * IMFMessage::getBody() {
return body;
return ZString();
}
}

View File

@ -1,9 +1,12 @@
#ifndef __IMFMessage_h__
#define __IMFMessage_h__
#include <sstream>
#include <string>
#include <vector>
#include "ZString.h"
#include "IMFMultipart.h"
#include "IMFHeader.h"
#include "IMFBody.h"
namespace coreutils {
@ -12,22 +15,26 @@ namespace coreutils {
public:
IMFMessage();
IMFMessage(ZString &in);
virtual ~IMFMessage();
void output(std::stringstream &out);
void addHeader(ZString key, ZString value);
void addHeader(const char *key, ZString value);
void addHeader(const char *key, std::string &value);
void addHeader(const char *key, const char *value);
void addHeader(ZString &key, ZString &value);
void addHeader(const char *key, ZString &value);
ZString getHeader(ZString key, bool valueOnly = true);
ZString getHeaderKeyPairValue(const char *headerKey, const char *key);
ZString getHeaderKeyPairValue(ZString headerKey, ZString key);
IMFBody * getBody();
IMFMultipart multipart;
ZString block;
char contentLength[8];
protected:
std::vector<IMFHeader> headers;
IMFBody *body;
std::stringstream newHeaders;
};

View File

@ -1,17 +1,22 @@
#include "IMFMultipart.h"
#include "Log.h"
namespace coreutils {
IMFMultipart::IMFMultipart() {}
IMFMultipart::IMFMultipart(ZString &in, ZString boundary) {
IMFMultipart::IMFMultipart(ZString &in, ZString &boundary) {
Log(LOG_DEBUG_1) << in;
std::stringstream temp;
temp << "\r\n--" << boundary;
sections = in.split((char *)temp.str().c_str());
temp << "--" << boundary;
sections = in.split(temp.str().c_str());
for(int ix = 0; ix < sections.size(); ++ix) {
if(sections[ix].equals((char *)"--\r\n"))
sections[ix] = ZString((char *)"");
sections[ix].ifNext((char *)"\r\n");
sections[ix].ifNext("\r\n");
sections[ix].ifCRLF();
Log(LOG_DEBUG_1) << "[" << sections[ix] << "].";
if(sections[ix].equals("--"))
sections[ix] = ZString("");
sections[ix].ifNext("\r\n");
}
}

View File

@ -2,15 +2,14 @@
#define __IMFMultipart_h__
#include "ZString.h"
#include "IMFBody.h"
namespace coreutils {
class IMFMultipart: public IMFBody {
class IMFMultipart: public ZString {
public:
IMFMultipart();
IMFMultipart(ZString &in, ZString boundary);
IMFMultipart(ZString &in, ZString &boundary);
std::string toString();
int getCount();

View File

@ -5,7 +5,6 @@ namespace coreutils {
IMFPlainText::IMFPlainText() {
}
IMFPlainText::IMFPlainText(ZString &in) : IMFBody() {
}
IMFPlainText::IMFPlainText(ZString &in) : ZString(in.str().c_str()) {}
}

View File

@ -2,11 +2,10 @@
#define __IMFPlainText_h__
#include "ZString.h"
#include "IMFBody.h"
namespace coreutils {
class IMFPlainText: public IMFBody {
class IMFPlainText: public ZString {
public:
IMFPlainText();

View File

@ -5,8 +5,8 @@
namespace coreutils {
IMFRequest::IMFRequest(ZString &in) : ZString(in) {
in.goeol();
this->split(" ", 3);
setZString(in.goeol());
split(" ");
}
ZString IMFRequest::getMethod() {

View File

@ -15,16 +15,18 @@ namespace coreutils {
std::stringstream response;
response << protocol << " " << code << " " << text << CRLF;
if(mode == LENGTH)
addHeader((char *)"Content-Length", (char *)std::to_string(content.gcount()).c_str());
if(mode == LENGTH) {
sprintf(contentLength, "%li", content.str().length());
ZString conlen(contentLength);
addHeader("Content-Length", conlen);
}
else
addHeader((char *)"Transfer-Encoding", (char *)"chunked");
addHeader("Transfer-Encoding", "chunked");
addHeader((char *)"Server", (char *)"JETServer v0.0.1");
addHeader("Server", "JETServer v0.0.1");
output(response);
response << content.str();
// core::Log(core::LOG_DEBUG_4) << response.str();
return response;
}
@ -40,12 +42,4 @@ namespace coreutils {
this->text = text;
}
void IMFResponse::setCookie(ZString key, ZString data) {
addHeader("Set-Cookie", data);
}
void IMFResponse::setCookie(ZString key, std::string data) {
addHeader("Set-Cookie", ZString(data.c_str()));
}
}

View File

@ -81,9 +81,6 @@ namespace coreutils {
void setText(ZString text);
void setCookie(ZString key, ZString data);
void setCookie(ZString key, std::string data);
private:
ZString protocol;
ZString code;

View File

@ -4,8 +4,8 @@
namespace coreutils {
std::ostream& operator<<(std::ostream& os, const ZString &zstring) {
for(int ix = 0; ix < zstring.length; ++ix) {
os << zstring.data[ix];
for(int ix = 0; ix < (zstring.length - (zstring.cursor - zstring.data)); ++ix) {
os << zstring.cursor[ix];
}
return os;
}
@ -39,6 +39,24 @@ namespace coreutils {
// Log(LOG_DEBUG_2) << "ZString Copy Constructor: ";
}
ZString::ZString(std::string data) {
this->data = (char *)data.c_str();
length = data.length();
cursor = (char *)data.c_str();
}
bool ZString::operator<(const ZString &valuex) const {
return (strncmp(cursor, valuex.cursor, (valuex.length <= length ? valuex.length: length) < 0));
}
bool ZString::operator>(const ZString &valuex) const {
return (strncmp(data, valuex.data, valuex.length <= length ? valuex.length: length) > 0);
}
bool ZString::operator==(const ZString &valuex) const {
return (strncmp(data, valuex.data, valuex.length <= length ? valuex.length: length) == 0);
}
std::vector<ZString> &ZString::getList() {
return list;
}
@ -72,8 +90,7 @@ namespace coreutils {
char *end = data + length;
char *pos = cursor;
while(pos < end) {
while((pos + delimiter.getLength()) < end) {
if(strncmp(pos, delimiter.getData(), delimiter.getLength()) == 0) {
list.push_back(ZString(cursor, pos - cursor));
cursor = pos + delimiter.getLength();
@ -83,23 +100,33 @@ namespace coreutils {
++pos;
}
}
pos += delimiter.getLength();
list.push_back(ZString(cursor, pos - cursor));
cursor = pos;
return list;
}
bool ZString::isCharacter(char ch, const char *string) {
int len = strlen(string);
for(int ix = 0; ix < len; ++ix) {
if(ch == string[ix])
return true;
}
return false;
}
ZString ZString::getTokenInclude(const char *include) {
char *start = cursor;
int len = strcspn(cursor, include);
cursor += len;
return ZString(start, len);
while((cursor <= (data + length)) && isCharacter(*cursor, include))
++cursor;
return ZString(start, cursor - start);
}
ZString ZString::getTokenExclude(const char *exclude) {
char *start = cursor;
int len = strspn(cursor, exclude);
cursor += len;
return ZString(start, len);
while((cursor <= (data + length)) && !isCharacter(*cursor, exclude))
++cursor;
return ZString(start, cursor - start);
}
ZString ZString::getTokenExclude(std::string exclude) {
@ -127,9 +154,9 @@ namespace coreutils {
}
bool ZString::equals(ZString &zstring) {
if(zstring.getLength() != getLength())
if(zstring.getLength() != length)
return false;
return strncmp(data, zstring.getData(), getLength()) == 0;
return strncmp(data, zstring.getData(), length) == 0;
}
bool ZString::equals(std::string &string) {
@ -137,12 +164,29 @@ namespace coreutils {
}
bool ZString::ifNext(const char *value) {
if(((data + length) - cursor) < strlen(value))
return false;
bool test = (strncmp(cursor, value, strlen(value)) == 0);
if(test)
cursor += strlen(value);
return test;
}
int ZString::ifEqualsCount(ZString &comparator) {
int count = 0;
while(cursor < (data + length)) {
if(*cursor == *comparator.cursor) {
++count;
++cursor;
++comparator.cursor;
}
else {
return count;
}
}
return count;
}
int ZString::skipWhitespace() {
int len = strspn(cursor, " \t");
cursor += len;
@ -150,9 +194,23 @@ namespace coreutils {
}
ZString ZString::goeol() {
bool set = false;
char *temp = cursor;
cursor += strspn(cursor, "\r\n");
return ZString(temp, cursor-- - temp);
char *tempend = data + length;
while(cursor <= (data + length)) {
if(*cursor == '\r') {
tempend = cursor++;
set = true;
}
if(*cursor == '\n') {
if(!set)
tempend = cursor;
++cursor;
break;
}
++cursor;
}
return ZString(temp, tempend - temp);
}
ZString ZString::readBlock(size_t size) {
@ -166,7 +224,7 @@ namespace coreutils {
}
size_t ZString::getLength() {
return length;
return length - (cursor - data);
}
void ZString::setZString(ZString zstring) {
@ -175,4 +233,24 @@ namespace coreutils {
cursor = data;
}
void ZString::reset() {
cursor = data;
}
char ZString::charAt(int index) {
return *(data + index);
}
bool ZString::ifCRLF() {
int len = length;
if(*(data + length - 1) == '\n')
--length;
if(*(data + length - 1) == '\r')
--length;
if(cursor > (data + length))
cursor = data + length;
return len != length;
}
}

View File

@ -1,7 +1,10 @@
#ifndef __ZString_h__
#define __ZString_h__
#include "includes"
#include <string.h>
#include <string>
#include <ostream>
#include <vector>
namespace coreutils {
@ -12,7 +15,7 @@ namespace coreutils {
/// is non-destructive to its underlying references.
///
/// ZString provides several methods to reference and parse the content. First method
/// is parse(ZString delimiter) which will return a vector of ZString which contains
/// is split(ZString delimiter) which will return a vector of ZString which contains
/// references to the parts of the string split by the provided delimiter. The delimiter
/// portion is omitted from the results.
///
@ -51,6 +54,12 @@ namespace coreutils {
ZString(const ZString &zstring);
///
/// Consructor from a string.
///
ZString(std::string string);
///
/// A friend method used to write the value of the ZString from the cursor
/// point to an ostream using the << syntax.
@ -60,6 +69,10 @@ namespace coreutils {
friend std::ostream& operator<<(std::ostream& os, const std::string& string);
friend std::ostream& operator+(std::ostream& os, const ZString& zstring);
bool operator<(const ZString &valuex) const;
bool operator>(const ZString &valuex) const;
bool operator==(const ZString &valuex) const;
///
/// Return a vector of ZString objects which contain the parts established
/// by using the split method and passing a delimiter value.
@ -158,6 +171,8 @@ namespace coreutils {
bool ifNext(const char *value);
int ifEqualsCount(ZString &comparator);
///
/// Advance the cursor through the ZString for each whitespace character
/// encountered.
@ -197,14 +212,32 @@ namespace coreutils {
void setZString(ZString zstring);
size_t length;
///
///
///
void reset();
///
///
///
char charAt(int index);
///
///
///
bool ifCRLF();
private:
char *data;
// size_t length;
size_t length;
char *cursor;
std::vector<ZString> list;
bool isCharacter(char ch, const char *string);
};
}

View File

@ -27,4 +27,7 @@ else
exit -1
fi
rm *.o
rm *~

17
testing/http_request.data Normal file
View File

@ -0,0 +1,17 @@
GET / HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"
sec-ch-ua-mobile: ?0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10; rv:33.0) Gecko/20100101 Firefox/33.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,fr-CA;q=0.8,fr;q=0.7
Cookie: _ga=GA1.1.1017526412.1628195401

BIN
testing/imfmessage_test Executable file

Binary file not shown.

View File

@ -0,0 +1,26 @@
#include <iostream>
#include "../IMFMessage.h"
int main(int argc, char **argv) {
coreutils::ZString buffer("Host: localhost:8080\r\n"
"Connection: keep-alive\r\n"
"Cache-Control: max-age=0\r\n"
"sec-ch-ua: \"Chromium\";v=\"92\", \" Not A;Brand\";v=\"99\", \"Google Chrome\";v=\"92\"\r\n"
"sec-ch-ua-mobile: ?0\r\n"
"Upgrade-Insecure-Requests: 1\r\n"
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10; rv:33.0) Gecko/20100101 Firefox/33.0\r\n"
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\n"
"Sec-Fetch-Site: none\r\n"
"Sec-Fetch-Mode: navigate\r\n"
"Sec-Fetch-User: ?1\r\n"
"Sec-Fetch-Dest: document\r\n"
"Accept-Encoding: gzip, deflate, br\r\n"
"Accept-Language: en-US,en;q=0.9,fr-CA;q=0.8,fr;q=0.7\r\n"
"Cookie: _ga=GA1.1.1017526412.1628195401\r\n"
"\r\n");
coreutils::IMFMessage message(buffer);
return 0;
}

Binary file not shown.

View File

@ -4,14 +4,52 @@
int main(int argc, char **argv) {
coreutils::ZString test("character1111:22222:33333");
test.length = 9;
std::cout << "test pre-split: [" << test << "]." << std::endl;
test.split(":");
std::cout << test << std::endl;
std::cout << "test post-split: [" << test << "]." << std::endl;
std::cout << "test sections: [" << test.getList().size() << "]." << std::endl;
std::cout << test.getLength() << std::endl;
std::cout << test[0] << std::endl;
std::cout << test[1] << std::endl;
std::cout << test[2] << std::endl;
coreutils::ZString test2("character1111:::::22222:::::33333");
test2.split(":::::");
std::cout << "test string: [" << test2 << "]" << std::endl;
std::cout << "length: [" << test2.getLength() << "]" << std::endl;
std::cout << "[" << test2[0] << "]" << std::endl;
std::cout << "[" << test2[1] << "]" << std::endl;
std::cout << "[" << test2[2] << "]" << std::endl;
std::cout << "[" << test2[3] << "]" << std::endl;
coreutils::ZString boundary("----WebKitFormBoundary5hx9ixjfxtJ8nXNm");
coreutils::ZString test3("------WebKitFormBoundary5hx9ixjfxtJ8nXNm\r\n"
"Content-Disposition: form-data; name=\"username\"\r\n"
"\r\n"
"test\r\n"
"------WebKitFormBoundary5hx9ixjfxtJ8nXNm\r\n"
"Content-Disposition: form-data; name=\"password\"\r\n"
"\r\n"
"test\r\n"
"------WebKitFormBoundary5hx9ixjfxtJ8nXNm\r\n"
"Content-Disposition: form-data; name=\"verify\"\r\n"
"\r\n"
"test\r\n"
"------WebKitFormBoundary5hx9ixjfxtJ8nXNm--\r\n");
test3.split(boundary);
std::cout << "[" << test3[0] << "]" << std::endl;
std::cout << "[" << test3[1] << "]" << std::endl;
std::cout << "[" << test3[2] << "]" << std::endl;
std::cout << "[" << test3[3] << "]" << std::endl;
}