Continued work.

This commit is contained in:
Brad Arant 2020-03-03 15:46:24 -08:00
parent 4286a7b449
commit 947eef21e2
12 changed files with 323 additions and 95 deletions

103
Base64.cpp Normal file
View File

@ -0,0 +1,103 @@
#include "Base64.h"
#include <iostream>
namespace coreutils {
const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
bool Base64::isBase64(unsigned char c) {
return (isalnum(c) || (c == '+') || (c == '/'));
}
std::string Base64::encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for(i = 0; (i <4) ; i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if (i) {
for(j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = ( char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
while((i++ < 3))
ret += '=';
}
return ret;
}
std::string Base64::decode(std::string const& encoded_string) {
int in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
while (in_len-- && ( encoded_string[in_] != '=') && isBase64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i ==4) {
for (i = 0; i <4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);
char_array_3[0] = ( char_array_4[0] << 2 ) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
}
}
if (i) {
for (j = 0; j < i; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
}
return ret;
}
}

19
Base64.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef __Base64_h__
#define __Base64_h__
#include <string>
namespace coreutils {
class Base64 {
public:
bool isBase64(unsigned char c);
std::string encode(unsigned char const* bytes_to_encode, unsigned int in_len);
std::string decode(std::string const& encoded_string);
};
}
#endif

View File

@ -1,33 +1,33 @@
#ifndef __Directory_h__ #ifndef __Directory_h__
#define __Directory_h__ # define __Directory_h__
#include "includes" # include "includes"
#include "DirectoryEntry.h" # include "DirectoryEntry.h"
namespace coreutils { namespace coreutils {
class Directory { class Directory {
public: public:
Directory(std::string path) { Directory(std::string path) {
dir = opendir(path.c_str()); dir = opendir(path.c_str());
if(dir) { if(dir) {
struct dirent *entry = readdir(dir); struct dirent *entry = readdir(dir);
while(entry) { while(entry) {
directory.emplace(std::string(entry->d_name), entry); directory.emplace(std::string(entry->d_name), entry);
entry = readdir(dir); entry = readdir(dir);
} }
} }
if(directory.size() > 0) if(directory.size() > 0)
cursor = directory.begin(); cursor = directory.begin();
} }
~Directory() {} ~Directory() {}
bool eod() { bool eod() {
return cursor == directory.end(); return cursor == directory.end();
} }
DirectoryEntry get() { DirectoryEntry get() {
if(cursor == directory.end()) if(cursor == directory.end())
return NULL; return NULL;
@ -37,17 +37,14 @@ namespace coreutils {
void next() { void next() {
++cursor; ++cursor;
} }
private: private:
DIR *dir; DIR *dir;
std::map<std::string, DirectoryEntry> directory; std::map<std::string, DirectoryEntry> directory;
std::map<std::string, DirectoryEntry>::iterator cursor; std::map<std::string, DirectoryEntry>::iterator cursor;
};
};
} }
#endif #endif

View File

@ -1,28 +1,28 @@
#ifndef __DirectoryEntry_h__ #ifndef __DirectoryEntry_h__
#define __DirectoryEntry_h__ # define __DirectoryEntry_h__
#include "includes" # include "includes"
namespace coreutils { namespace coreutils {
class DirectoryEntry { class DirectoryEntry {
public: public:
DirectoryEntry(struct dirent *entry) { DirectoryEntry(struct dirent *entry) {
memcpy(&this->entry, entry, sizeof(struct dirent)); memcpy(&this->entry, entry, sizeof(struct dirent));
} }
~DirectoryEntry() {} ~DirectoryEntry() {}
std::string getName() { std::string getName() {
return std::string(entry.d_name); return std::string(entry.d_name);
} }
private: private:
struct dirent entry; struct dirent entry;
}; };
} }
#endif #endif

View File

@ -39,5 +39,9 @@ namespace coreutils {
void File::write(std::string data) { void File::write(std::string data) {
::write(fd, data.c_str(), data.length()); ::write(fd, data.c_str(), data.length());
} }
std::string File::asString() {
return std::string(buffer, size);
}
} }

1
File.h
View File

@ -19,6 +19,7 @@ namespace coreutils {
void setBufferSize(size_t size); void setBufferSize(size_t size);
void read(); void read();
void write(std::string data); void write(std::string data);
std::string asString();
char *buffer; char *buffer;
size_t size; size_t size;

View File

@ -9,8 +9,10 @@ namespace coreutils {
IMFHeader::IMFHeader(PString &in) { IMFHeader::IMFHeader(PString &in) {
key = in.getTokenInclude("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"); key = in.getTokenInclude("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-");
if(!in.ifNext(":")) if(!in.ifNext(":")) {
throw coreutils::Exception("Invalid character in expected header token."); printf("%02X\n", in.str()[0]);
throw coreutils::Exception("Invalid character in expected header token.");
}
in.skipWhitespace(); in.skipWhitespace();
value = in.getTokenExclude("\r\n"); value = in.getTokenExclude("\r\n");
if(!in.ifNext("\r\n")) if(!in.ifNext("\r\n"))

View File

@ -2,61 +2,64 @@
#include "IMFHeader.h" #include "IMFHeader.h"
#include "IMFMultipart.h" #include "IMFMultipart.h"
#include "IMFPlainText.h" #include "IMFPlainText.h"
#include "Log.h"
namespace coreutils { namespace coreutils {
IMFMessage::IMFMessage() {} IMFMessage::IMFMessage() {}
IMFMessage::IMFMessage(PString &in) { IMFMessage::IMFMessage(PString &in) {
parse(in); parse(in);
} }
void IMFMessage::parse(PString &in) { void IMFMessage::parse(PString &in) {
coreutils::Log(coreutils::LOG_DEBUG_4) << "[" << in.str() << "]";
if(in.size() == 0) if(in.size() == 0)
return; return;
while(!in.ifNext("\r\n")) while(!in.ifNext("\r\n") && !in.eod()) {
headers.emplace_back(in); headers.emplace_back(in);
}
std::string type = getHeader("Content-Type"); std::string type = getHeader("Content-Type");
if(type.size() == 0) if(type.size() == 0)
type = "text/plain"; type = "text/plain";
if(type == "multipart/form-data") if(type == "multipart/form-data")
body = new IMFMultipart(in, getHeaderKeyPairValue("Content-Type", "boundary")); body = new IMFMultipart(in, getHeaderKeyPairValue("Content-Type", "boundary"));
else if(type == "text/plain") else if(type == "text/plain")
body = new IMFPlainText(in); body = new IMFPlainText(in);
else else
body = new IMFBody(); body = new IMFBody();
} }
void IMFMessage::output(std::stringstream &out) { void IMFMessage::output(std::stringstream &out) {
for(IMFHeader header: headers) { for(IMFHeader header: headers) {
out << header.getKey() << ": " << header.getValue() << "\r\n"; out << header.getKey() << ": " << header.getValue() << "\r\n";
} }
out << "\r\n"; out << "\r\n";
} }
void IMFMessage::addHeader(std::string key, std::string value) { void IMFMessage::addHeader(std::string key, std::string value) {
headers.emplace_back(key, value); headers.emplace_back(key, value);
} }
std::string IMFMessage::getHeader(std::string key, bool valueOnly) { std::string IMFMessage::getHeader(std::string key, bool valueOnly) {
for(IMFHeader header: headers) { for(IMFHeader header: headers) {
if(header.getKey() == key) { if(header.getKey() == key) {
std::string value = header.getValue(); std::string value = header.getValue();
if(valueOnly) { if(valueOnly) {
std::vector<PString> split = PString(value).split(";"); std::vector<PString> split = PString(value).split(";");
value = split[0].str(); value = split[0].str();
} }
return value; return value;
} }
} }
return std::string(""); return std::string("");
} }
std::string IMFMessage::getHeaderKeyPairValue(std::string headerKey, std::string key) { std::string IMFMessage::getHeaderKeyPairValue(std::string headerKey, std::string key) {
std::string value; std::string value;
coreutils::PString psource(getHeader(headerKey, false)); coreutils::PString psource(getHeader(headerKey, false));
@ -77,22 +80,21 @@ namespace coreutils {
} }
else else
continue; continue;
} else if (work.ifNext(";") || work.ifNext(" ")) { } else if (work.ifNext(";") || work.ifNext(" ")) {
if(token == key) if(token == key)
return std::string("true"); return std::string("true");
else else
continue; continue;
} }
} }
return std::string("false"); return std::string("false");
} }
IMFBody * IMFMessage::getBody() { IMFBody * IMFMessage::getBody() {
return body; return body;
} }
} }

View File

@ -1,5 +1,6 @@
#include "IMFRequest.h" #include "IMFRequest.h"
#include "Exception.h" #include "Exception.h"
#include "Log.h"
namespace coreutils { namespace coreutils {
@ -13,6 +14,9 @@ namespace coreutils {
if(!in.ifNext(" ")) if(!in.ifNext(" "))
throw coreutils::Exception("Expecting space after URI."); throw coreutils::Exception("Expecting space after URI.");
protocol = in.getTokenExclude("\r\n"); protocol = in.getTokenExclude("\r\n");
coreutils::Log(coreutils::LOG_DEBUG_4) << "[" << in.str() << "]";
if(!in.ifNext("\r\n")) if(!in.ifNext("\r\n"))
throw coreutils::Exception("Expecting CRLF after protocol."); throw coreutils::Exception("Expecting CRLF after protocol.");
} }

View File

@ -61,12 +61,12 @@ namespace coreutils {
Log::~Log() { Log::~Log() {
if(output) { if(output) {
mtx.lock();
std::stringstream out; std::stringstream out;
out << seq << "." << this->str() << std::endl;; out << seq << "." << this->str() << std::endl;;
mtx.lock();
if(logListener) if(logListener)
logListener->logSend(out.str()); logListener->logSend(out.str());

View File

@ -10,14 +10,25 @@ namespace coreutils {
this->pstring = pstring; this->pstring = pstring;
} }
std::vector<PString> & PString::getList() {
return list;
}
std::string PString::str() { std::string PString::str() {
return pstring.substr(cursor); return pstring.substr(cursor);
} }
std::vector<PString> PString::split(std::string delimiter, int maxSize) { std::vector<PString> PString::split(std::string delimiter, int maxSize) {
std::vector<PString> list; list.clear();
size_t end,
pos = cursor; if(pstring.size() == 0) {
list.push_back(PString(""));
return list;
}
size_t end;
size_t pos = cursor;
while(pos < pstring.length()) { while(pos < pstring.length()) {
end = pstring.find(delimiter, pos); end = pstring.find(delimiter, pos);
if(end == std::string::npos) if(end == std::string::npos)
@ -50,6 +61,14 @@ namespace coreutils {
return pstring.substr(start, cursor - start); return pstring.substr(start, cursor - start);
} }
coreutils::PString PString::operator[](int index) {
return list[index];
}
bool PString::eod() {
return cursor >= pstring.size();
}
bool PString::ifNext(std::string value) { bool PString::ifNext(std::string value) {
bool test = (value == pstring.substr(cursor, value.length())); bool test = (value == pstring.substr(cursor, value.length()));
if(test) if(test)

View File

@ -5,24 +5,101 @@
namespace coreutils { namespace coreutils {
///
/// Use the PString object when advanced parsing algorithms are required to simplify
/// parsing. Two methods of parsing are available within the PString object. One
/// method involves using the split method to divide the string into several PString
/// objects. Split separates the string based upon a delimiter. Another method employs
/// the use of the getToken methods provided to move to through the string and assign
/// values based upon the followed path.
///
class PString { class PString {
public: public:
///
///
///
PString(); PString();
///
///
///
PString(std::string pstring); PString(std::string pstring);
///
///
///
std::vector<PString> & getList();
///
///
///
std::string str(); std::string str();
///
///
///
std::vector<PString> split(std::string delimiter, int maxSize = 0); std::vector<PString> split(std::string delimiter, int maxSize = 0);
///
///
///
std::string getTokenInclude(std::string include); std::string getTokenInclude(std::string include);
///
///
///
std::string getTokenExclude(std::string exclude); std::string getTokenExclude(std::string exclude);
///
///
///
coreutils::PString operator[](int index);
///
///
///
bool eod();
///
///
///
bool ifNext(std::string value); bool ifNext(std::string value);
///
///
///
void skipWhitespace(); void skipWhitespace();
///
///
///
int cursor = 0; int cursor = 0;
///
///
///
int size(); int size();
private: private:
std::string pstring; std::string pstring;
std::vector<PString> list;
}; };
} }