diff --git a/Base64.cpp b/Base64.cpp new file mode 100644 index 0000000..762c9fe --- /dev/null +++ b/Base64.cpp @@ -0,0 +1,103 @@ +#include "Base64.h" +#include + +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; + } + +} diff --git a/Base64.h b/Base64.h new file mode 100644 index 0000000..18e3a0e --- /dev/null +++ b/Base64.h @@ -0,0 +1,19 @@ +#ifndef __Base64_h__ +#define __Base64_h__ + +#include + +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 diff --git a/Directory.h b/Directory.h index 86e9dd1..56f203b 100644 --- a/Directory.h +++ b/Directory.h @@ -1,33 +1,33 @@ #ifndef __Directory_h__ -#define __Directory_h__ +# define __Directory_h__ -#include "includes" -#include "DirectoryEntry.h" +# include "includes" +# include "DirectoryEntry.h" namespace coreutils { - - class Directory { - - public: - Directory(std::string path) { - dir = opendir(path.c_str()); - if(dir) { - struct dirent *entry = readdir(dir); - while(entry) { - directory.emplace(std::string(entry->d_name), entry); - entry = readdir(dir); - } + + class Directory { + + public: + Directory(std::string path) { + dir = opendir(path.c_str()); + if(dir) { + struct dirent *entry = readdir(dir); + while(entry) { + directory.emplace(std::string(entry->d_name), entry); + entry = readdir(dir); + } } if(directory.size() > 0) cursor = directory.begin(); - } - - ~Directory() {} - + } + + ~Directory() {} + bool eod() { return cursor == directory.end(); } - + DirectoryEntry get() { if(cursor == directory.end()) return NULL; @@ -37,17 +37,14 @@ namespace coreutils { void next() { ++cursor; } - - private: - DIR *dir; - std::map directory; - std::map::iterator cursor; - - - - - }; - + + private: + DIR *dir; + std::map directory; + std::map::iterator cursor; + + }; + } -#endif +#endif \ No newline at end of file diff --git a/DirectoryEntry.h b/DirectoryEntry.h index e54201e..1b6bd68 100644 --- a/DirectoryEntry.h +++ b/DirectoryEntry.h @@ -1,28 +1,28 @@ #ifndef __DirectoryEntry_h__ -#define __DirectoryEntry_h__ +# define __DirectoryEntry_h__ -#include "includes" +# include "includes" namespace coreutils { - - class DirectoryEntry { - - public: - DirectoryEntry(struct dirent *entry) { - memcpy(&this->entry, entry, sizeof(struct dirent)); - } - - ~DirectoryEntry() {} - - std::string getName() { - return std::string(entry.d_name); - } - - private: - struct dirent entry; - - }; - + + class DirectoryEntry { + + public: + DirectoryEntry(struct dirent *entry) { + memcpy(&this->entry, entry, sizeof(struct dirent)); + } + + ~DirectoryEntry() {} + + std::string getName() { + return std::string(entry.d_name); + } + + private: + struct dirent entry; + + }; + } #endif diff --git a/File.cpp b/File.cpp index cffcf5c..e79f3b1 100644 --- a/File.cpp +++ b/File.cpp @@ -39,5 +39,9 @@ namespace coreutils { void File::write(std::string data) { ::write(fd, data.c_str(), data.length()); } - + + std::string File::asString() { + return std::string(buffer, size); + } + } diff --git a/File.h b/File.h index 1c25fc9..393f3d7 100644 --- a/File.h +++ b/File.h @@ -19,6 +19,7 @@ namespace coreutils { void setBufferSize(size_t size); void read(); void write(std::string data); + std::string asString(); char *buffer; size_t size; diff --git a/IMFHeader.cpp b/IMFHeader.cpp index 237c578..b39e6ac 100644 --- a/IMFHeader.cpp +++ b/IMFHeader.cpp @@ -9,8 +9,10 @@ namespace coreutils { IMFHeader::IMFHeader(PString &in) { key = in.getTokenInclude("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"); - if(!in.ifNext(":")) - throw coreutils::Exception("Invalid character in expected header token."); + if(!in.ifNext(":")) { + printf("%02X\n", in.str()[0]); + throw coreutils::Exception("Invalid character in expected header token."); + } in.skipWhitespace(); value = in.getTokenExclude("\r\n"); if(!in.ifNext("\r\n")) diff --git a/IMFMessage.cpp b/IMFMessage.cpp index ff1facd..34b605f 100644 --- a/IMFMessage.cpp +++ b/IMFMessage.cpp @@ -2,61 +2,64 @@ #include "IMFHeader.h" #include "IMFMultipart.h" #include "IMFPlainText.h" +#include "Log.h" namespace coreutils { - + IMFMessage::IMFMessage() {} - + IMFMessage::IMFMessage(PString &in) { parse(in); } void IMFMessage::parse(PString &in) { + coreutils::Log(coreutils::LOG_DEBUG_4) << "[" << in.str() << "]"; if(in.size() == 0) return; - while(!in.ifNext("\r\n")) - headers.emplace_back(in); - + while(!in.ifNext("\r\n") && !in.eod()) { + headers.emplace_back(in); + } + std::string type = getHeader("Content-Type"); - if(type.size() == 0) - type = "text/plain"; - + if(type.size() == 0) + type = "text/plain"; + if(type == "multipart/form-data") - body = new IMFMultipart(in, getHeaderKeyPairValue("Content-Type", "boundary")); - else if(type == "text/plain") - body = new IMFPlainText(in); + body = new IMFMultipart(in, getHeaderKeyPairValue("Content-Type", "boundary")); + else if(type == "text/plain") + body = new IMFPlainText(in); else - body = new IMFBody(); + body = new IMFBody(); } - + void IMFMessage::output(std::stringstream &out) { for(IMFHeader header: headers) { out << header.getKey() << ": " << header.getValue() << "\r\n"; } out << "\r\n"; } - + void IMFMessage::addHeader(std::string key, std::string value) { headers.emplace_back(key, value); - + } - + std::string IMFMessage::getHeader(std::string key, bool valueOnly) { for(IMFHeader header: headers) { if(header.getKey() == key) { - std::string value = header.getValue(); - if(valueOnly) { - std::vector split = PString(value).split(";"); - value = split[0].str(); - } - return value; + std::string value = header.getValue(); + if(valueOnly) { + std::vector split = PString(value).split(";"); + value = split[0].str(); + } + return value; } } return std::string(""); } - + std::string IMFMessage::getHeaderKeyPairValue(std::string headerKey, std::string key) { std::string value; coreutils::PString psource(getHeader(headerKey, false)); @@ -77,22 +80,21 @@ namespace coreutils { } else continue; - - + + } else if (work.ifNext(";") || work.ifNext(" ")) { if(token == key) return std::string("true"); else continue; - + } } return std::string("false"); } - - IMFBody * IMFMessage::getBody() { - return body; - } - - + + IMFBody * IMFMessage::getBody() { + return body; + } + } diff --git a/IMFRequest.cpp b/IMFRequest.cpp index 705b957..7d03857 100644 --- a/IMFRequest.cpp +++ b/IMFRequest.cpp @@ -1,5 +1,6 @@ #include "IMFRequest.h" #include "Exception.h" +#include "Log.h" namespace coreutils { @@ -13,6 +14,9 @@ namespace coreutils { if(!in.ifNext(" ")) throw coreutils::Exception("Expecting space after URI."); protocol = in.getTokenExclude("\r\n"); + + coreutils::Log(coreutils::LOG_DEBUG_4) << "[" << in.str() << "]"; + if(!in.ifNext("\r\n")) throw coreutils::Exception("Expecting CRLF after protocol."); } diff --git a/Log.cpp b/Log.cpp index cdaf5c2..26317da 100644 --- a/Log.cpp +++ b/Log.cpp @@ -61,12 +61,12 @@ namespace coreutils { Log::~Log() { if(output) { - - mtx.lock(); std::stringstream out; out << seq << "." << this->str() << std::endl;; - + + mtx.lock(); + if(logListener) logListener->logSend(out.str()); diff --git a/PString.cpp b/PString.cpp index 3c5e8cd..1d3cf13 100644 --- a/PString.cpp +++ b/PString.cpp @@ -10,14 +10,25 @@ namespace coreutils { this->pstring = pstring; } + std::vector & PString::getList() { + return list; + } + std::string PString::str() { return pstring.substr(cursor); } std::vector PString::split(std::string delimiter, int maxSize) { - std::vector list; - size_t end, - pos = cursor; + list.clear(); + + if(pstring.size() == 0) { + list.push_back(PString("")); + return list; + } + + size_t end; + size_t pos = cursor; + while(pos < pstring.length()) { end = pstring.find(delimiter, pos); if(end == std::string::npos) @@ -50,6 +61,14 @@ namespace coreutils { 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 test = (value == pstring.substr(cursor, value.length())); if(test) diff --git a/PString.h b/PString.h index 67b8574..ed26353 100644 --- a/PString.h +++ b/PString.h @@ -5,24 +5,101 @@ 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 { public: + + /// + /// + /// + PString(); + + /// + /// + /// + PString(std::string pstring); + /// + /// + /// + + std::vector & getList(); + + /// + /// + /// + std::string str(); + + /// + /// + /// + std::vector split(std::string delimiter, int maxSize = 0); + + /// + /// + /// + std::string getTokenInclude(std::string include); + + /// + /// + /// + std::string getTokenExclude(std::string exclude); + + /// + /// + /// + + coreutils::PString operator[](int index); + + /// + /// + /// + + bool eod(); + + /// + /// + /// + bool ifNext(std::string value); + + /// + /// + /// + void skipWhitespace(); + + /// + /// + /// + int cursor = 0; + + /// + /// + /// + int size(); private: std::string pstring; - + std::vector list; + }; }