From 103f4cbc12691bb9b3777686431bc076a56b1981 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Mon, 13 Mar 2017 09:58:21 +0000 Subject: [PATCH] some code from Parser moved to HeadersParser and to string_functions git-svn-id: svn://ttmath.org/publicrep/libscorpiohttpserver/trunk@1056 e52654a7-88a9-db11-a3e9-0013d4bc506e --- src/Makefile | 3 +- src/Makefile.dep | 6 +- src/client.cpp | 2 + src/client.h | 15 +- src/headers_parser.cpp | 301 ++++++++++++++++++++++++++++++ src/headers_parser.h | 37 ++++ src/server.cpp | 392 ++------------------------------------- src/server.h | 56 +----- src/string_functions.cpp | 94 ++++++++++ src/string_functions.h | 29 +++ 10 files changed, 500 insertions(+), 435 deletions(-) create mode 100644 src/headers_parser.cpp create mode 100644 src/headers_parser.h create mode 100644 src/string_functions.cpp create mode 100644 src/string_functions.h diff --git a/src/Makefile b/src/Makefile index 37f2d50..94f0dae 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,6 @@ CXX = g++5 -CXXFLAGS = -g3 -O0 -I/usr/local/include -std=c++11 -I../../pikotools +CXXFLAGS = -g3 -O0 -std=c++11 -pedantic -Wall -I/usr/local/include -I../../pikotools o=$(patsubst %.cpp,%.o,$(wildcard *.cpp)) name=webserver @@ -32,6 +32,7 @@ webserver: $(o) clean: rm -f $(name) + cleanall: clean @cd ../../pikotools && make clean diff --git a/src/Makefile.dep b/src/Makefile.dep index a467ae4..8d57ec7 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -1,5 +1,7 @@ # DO NOT DELETE client.o: client.h -main.o: ./server.h client.h -server.o: ./server.h client.h +headers_parser.o: headers_parser.h client.h string_functions.h +main.o: server.h client.h headers_parser.h +server.o: server.h client.h headers_parser.h string_functions.h +string_functions.o: string_functions.h diff --git a/src/client.cpp b/src/client.cpp index 1ffdd94..3ce3733 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -45,6 +45,7 @@ Client & Client::operator=(const Client & c) in_buffer_max_len = c.in_buffer_max_len; parsing_headers = c.parsing_headers; parsing_first_header = c.parsing_first_header; + http_method_str = c.http_method_str; http_method = c.http_method; http_version = c.http_version; url = c.url; @@ -81,6 +82,7 @@ void Client::PrepareToNewRequest() output_buffer_sent = 0; close_connection = false; + http_method_str.clear(); output_buffer.clear(); url.clear(); } diff --git a/src/client.h b/src/client.h index dea3714..81a8d2d 100644 --- a/src/client.h +++ b/src/client.h @@ -45,11 +45,6 @@ public: bool close_connection; - - char * in_buffer; // rename to a better name - size_t in_buffer_max_len; // at least two characters - size_t in_buffer_len; - std::string input_buffer; std::string header; @@ -71,6 +66,16 @@ public: void PrepareToNewRequest(); +private: + + char * in_buffer; // rename to a better name + size_t in_buffer_max_len; // at least two characters + size_t in_buffer_len; + std::wstring http_method_str; + + + friend class Server; + friend class HeadersParser; }; diff --git a/src/headers_parser.cpp b/src/headers_parser.cpp new file mode 100644 index 0000000..7a48628 --- /dev/null +++ b/src/headers_parser.cpp @@ -0,0 +1,301 @@ +#include +#include +#include "headers_parser.h" +#include "string_functions.h" + + + + +void HeadersParser::ParseHeaders(Client & client) +{ + header_index = 0; + + if( !ParseFirstHeader(client) ) + { + std::cout << "incorrect first header, closing connection" << std::endl; + client.close_connection = true; + return; + } + + // we are testing header_index + 3 < client.input_buffer.size() because we know + // that the \r\n\r\n sequence already exists in this string + // so there is no a problem that we leave some characters at the end of the string + while( header_index + 3 < client.input_buffer.size() && + !IsHeadersEnding(client.input_buffer.c_str() + header_index) ) + { + tmp_header.clear(); + tmp_value.clear(); + + if( ParseHeaderKey(client) ) + { + SkipWhite(client); + ParseHeaderValue(client); + TrimWhiteAtEnd(tmp_value); + + std::wcout << L"wczytalem naglowek" << std::endl; + std::wcout << tmp_header << L"|" << std::endl; + std::wcout << tmp_value << L"|" << std::endl; + + if( tmp_header.size() > 0 ) + client.in.Add(tmp_header, tmp_value); + } + else + { + // add some code to skip this line + } + } +} + + +// ptr buffer should consists of at least more 3 characters +bool HeadersParser::IsHeadersEnding(const char * ptr) +{ + return ptr[0] == '\r' && ptr[0+1] == '\n' && + ptr[0+2] == '\r' && ptr[0+3] == '\n'; +} + + +bool HeadersParser::ParseFirstHeader(Client & client) +{ + return ParseFirstHeaderMethodName(client) && + ParseFirstHeaderURL(client) && + ParseFirstHeaderHTTPVersion(client); +} + + +bool HeadersParser::ParseFirstHeaderMethodName(Client & client) +{ + wchar_t method_name[32]; + size_t method_name_index = 0; + + while( header_index < client.input_buffer.size() && + client.input_buffer[header_index] != '\r' && + !IsWhite(client.input_buffer[header_index]) ) + { + wchar_t c = (unsigned char)client.input_buffer[header_index++]; + method_name[method_name_index++] = c; + + if( method_name_index >= sizeof(method_name) / sizeof(wchar_t) ) + return false; + } + + method_name[method_name_index++] = 0; + client.http_method_str = method_name; + SkipWhite(client); + + return true; +} + + + +/* + * The generic URI syntax mandates that new URI schemes that provide for the representation + * of character data in a URI must, in effect, represent characters from the unreserved set + * without translation, and should convert all other characters to bytes according to UTF-8, + * and then percent-encode those values. This requirement was introduced in January 2005 + * with the publication of RFC 3986. URI schemes introduced before this date are not affected. + * + * + */ +bool HeadersParser::ParseFirstHeaderURL(Client & client) +{ + client.url.clear(); + url_ascii.clear(); + + while( header_index < client.input_buffer.size() && + client.input_buffer[header_index] != '\r' && + !IsWhite(client.input_buffer[header_index]) ) + { + wchar_t c = (unsigned char)client.input_buffer[header_index++]; + + if( c == '+' ) + { + c = ' '; + } + else + if( c == '%' ) + { + if( header_index + 2 < client.input_buffer.size() ) + { + wchar_t c1 = ToLower((unsigned char)client.input_buffer[header_index++]); + wchar_t c2 = ToLower((unsigned char)client.input_buffer[header_index++]); + + if( IsHexDigit(c1) && IsHexDigit(c2) ) + { + int v1 = HexDigitToValue(c1); + int v2 = HexDigitToValue(c2); + + c = static_cast((v1 << 4) + v2); + } + else + { + return false; + } + } + else + { + return false; + } + } + else + if( c < 32 || c > 127 ) + { + return false; + } + + url_ascii += static_cast(c); + } + + bool utf8_correct = PT::UTF8ToWide(url_ascii, client.url); + + SkipWhite(client); + url_ascii.clear(); + + return utf8_correct && !client.url.empty(); +} + + + + + +bool HeadersParser::ParseFirstHeaderHTTPVersion(Client & client) +{ + client.http_version = http_version_unsupported; + + if( header_index + 7 < client.input_buffer.size() && + client.input_buffer[header_index] == 'H' && + client.input_buffer[header_index + 1] == 'T' && + client.input_buffer[header_index + 2] == 'T' && + client.input_buffer[header_index + 3] == 'P' && + client.input_buffer[header_index + 4] == '/' && + IsDecDigit(client.input_buffer[header_index + 5]) && + client.input_buffer[header_index + 6] == '.' && + IsDecDigit(client.input_buffer[header_index + 7]) ) + { + int d1 = client.input_buffer[header_index + 5] - '0'; + int d2 = client.input_buffer[header_index + 7] - '0'; + + int ddd1 = client.input_buffer[header_index + 5] - '0'; + int ddd2 = client.input_buffer[header_index + 7] - '0'; + + if( d1 == 1 ) + { + client.http_version = http_version_1_0; + + } + + if( d2 == 1 ) + { + client.http_version = http_version_1_1; + } + + if( ddd1 == 1 ) + { + client.http_version = http_version_1_0; + + } + + if( ddd2 == 1 ) + { + client.http_version = http_version_1_1; + } + + if( d1 == 1 ) + { + if( d2 == 0 ) + client.http_version = http_version_1_0; + else + if( d2 == 1 ) + client.http_version = http_version_1_1; + } + + header_index += 8; + SkipWhite(client); + } + + return client.http_version != http_version_unsupported; +} + + + +// ParseHeaderKey should increment header_index at least once +bool HeadersParser::ParseHeaderKey(Client & client) +{ + while( header_index < client.input_buffer.size() && + client.input_buffer[header_index] != '\r' ) + { + if( client.input_buffer[header_index] == ':' ) + { + header_index += 1; + return true; + } + + wchar_t c = (unsigned char)client.input_buffer[header_index]; + + if( c >= 32 && c < 127 ) + { + // allow only asci characters + + tmp_header += c; + } + + header_index += 1; + } + + // there was not a colon at the end of the name + header_index += 1; + return false; +} + + +void HeadersParser::ParseHeaderValue(Client & client) +{ + while( header_index < client.input_buffer.size() ) + { + if( header_index + 1 < client.input_buffer.size() && + client.input_buffer[header_index] == '\r' && + client.input_buffer[header_index+1] == '\n' ) + { + if( header_index + 2 < client.input_buffer.size() && + (client.input_buffer[header_index+2] == ' ' || + client.input_buffer[header_index+2] == '\t') ) + { + // this line will be continued in the next line + header_index += 3; + + } + else + { + header_index += 2; + break; + } + } + else + { + wchar_t c = (unsigned char)client.input_buffer[header_index]; + + if( c >= 32 && c < 127 ) + { + // allow only ascii characters + + tmp_value += c; + } + + header_index += 1; + } + } +} + + + + +void HeadersParser::SkipWhite(Client & client) +{ + while( header_index < client.input_buffer.size() && + IsWhite(client.input_buffer[header_index]) ) + { + header_index += 1; + } +} + + diff --git a/src/headers_parser.h b/src/headers_parser.h new file mode 100644 index 0000000..0516243 --- /dev/null +++ b/src/headers_parser.h @@ -0,0 +1,37 @@ +#ifndef headerfile_libscorpiohttpserver_src_headers_parser_h +#define headerfile_libscorpiohttpserver_src_headers_parser_h + +#include "client.h" + + + + +class HeadersParser +{ +public: + + void ParseHeaders(Client & client); + bool IsHeadersEnding(const char * ptr); + +private: + + size_t header_index; + std::wstring tmp_header, tmp_value; + std::string url_ascii; + + bool ParseFirstHeader(Client & client); + bool ParseFirstHeaderMethodName(Client & client); + bool ParseFirstHeaderURL(Client & client); + bool ParseFirstHeaderHTTPVersion(Client & client); + bool ParseHeaderKey(Client & client); + void ParseHeaderValue(Client & client); + + void SkipWhite(Client & client); + + +}; + + +#endif + + diff --git a/src/server.cpp b/src/server.cpp index 7ee8809..d6dbf00 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -8,7 +8,7 @@ #include #include #include "server.h" - +#include "string_functions.h" @@ -16,7 +16,6 @@ Server::Server() { main_socket = -1; close_server = false; - header_index = 0; } Server::~Server() @@ -124,7 +123,7 @@ void Server::Wait() } else { - ReadInputFromClients(); + ReadWriteToClients(); } } } @@ -207,8 +206,7 @@ int optval; } -// change to a better name as it is used to write to a client too -void Server::ReadInputFromClients() +void Server::ReadWriteToClients() { size_t i = 0; @@ -257,6 +255,8 @@ void Server::ReadInputFromClient(Client & client) char * old_pointer = client.in_buffer + client.in_buffer_len; + // after adding to client.input_buffer we set in_buffer_len to 0 + // so here is sufficient client.in_buffer (without adding client.in_buffer_len) int read_len = read(client.socket, client.in_buffer + client.in_buffer_len, client.in_buffer_max_len - client.in_buffer_len - 1); if( read_len < 0 ) @@ -265,8 +265,6 @@ void Server::ReadInputFromClient(Client & client) std::cout << "read failed" << std::endl; client.close_connection = true; - //RemoveClientSocket(client.socket); - // do not use client reference anymore } else if( read_len == 0 ) @@ -354,9 +352,16 @@ void Server::CheckHeaders(Client & client, size_t input_buffer_index) for( ; input_buffer_index + 3 < client.input_buffer.size() ; ++input_buffer_index) { - if( IsHeadersEnding(client.input_buffer.c_str() + input_buffer_index) ) + if( headers_parser.IsHeadersEnding(client.input_buffer.c_str() + input_buffer_index) ) { - ParseHeaders(client); + headers_parser.ParseHeaders(client); + + if( !SelectMethodName(client, client.http_method_str) ) + { + std::cout << "unsupported http method" << std::endl; + client.close_connection = true; + } + client.parsing_headers = false; client.input_buffer.erase(0, input_buffer_index + 4); @@ -377,87 +382,11 @@ void Server::CheckHeaders(Client & client, size_t input_buffer_index) } -// ptr buffer should consists of at least more 3 characters -bool Server::IsHeadersEnding(const char * ptr) -{ - return ptr[0] == '\r' && ptr[0+1] == '\n' && - ptr[0+2] == '\r' && ptr[0+3] == '\n'; -} -void Server::ParseHeaders(Client & client) -{ - header_index = 0; - - if( !ParseFirstHeader(client) ) - { - std::cout << "incorrect first header, closing connection" << std::endl; - client.close_connection = true; - return; - } - - // we are testing header_index + 3 < client.input_buffer.size() because we know - // that the \r\n\r\n sequence already exists in this string - // so there is no a problem that we leave some characters at the end of the string - while( header_index + 3 < client.input_buffer.size() && - !IsHeadersEnding(client.input_buffer.c_str() + header_index) ) - { - tmp_header.clear(); - tmp_value.clear(); - - if( ParseHeaderKey(client) ) - { - SkipWhite(client); - ParseHeaderValue(client); - TrimWhiteAtEnd(tmp_value); - - std::wcout << L"wczytalem naglowek" << std::endl; - std::wcout << tmp_header << L"|" << std::endl; - std::wcout << tmp_value << L"|" << std::endl; - - if( tmp_header.size() > 0 ) - client.in.Add(tmp_header, tmp_value); - } - else - { - // add some code to skip this line - } - } -} -bool Server::ParseFirstHeader(Client & client) -{ - return ParseFirstHeaderMethodName(client) && - ParseFirstHeaderURL(client) && - ParseFirstHeaderHTTPVersion(client); -} - - -bool Server::ParseFirstHeaderMethodName(Client & client) -{ - wchar_t method_name[32]; - size_t method_name_index = 0; - - while( header_index < client.input_buffer.size() && - client.input_buffer[header_index] != '\r' && - !IsWhite(client.input_buffer[header_index]) ) - { - wchar_t c = (unsigned char)client.input_buffer[header_index++]; - method_name[method_name_index++] = c; - - if( method_name_index >= sizeof(method_name) / sizeof(wchar_t) ) - return false; - } - - method_name[method_name_index++] = 0; - SkipWhite(client); - - return SelectMethodName(client, method_name); -} - - -bool Server::SelectMethodName(Client & client, wchar_t * method_name) +bool Server::SelectMethodName(Client & client, const std::wstring & method_name) { client.http_method = http_method_unsupported; @@ -490,202 +419,9 @@ bool Server::SelectMethodName(Client & client, wchar_t * method_name) } -/* - * The generic URI syntax mandates that new URI schemes that provide for the representation - * of character data in a URI must, in effect, represent characters from the unreserved set - * without translation, and should convert all other characters to bytes according to UTF-8, - * and then percent-encode those values. This requirement was introduced in January 2005 - * with the publication of RFC 3986. URI schemes introduced before this date are not affected. - * - * - */ -bool Server::ParseFirstHeaderURL(Client & client) -{ - client.url.clear(); - url_ascii.clear(); - - while( header_index < client.input_buffer.size() && - client.input_buffer[header_index] != '\r' && - !IsWhite(client.input_buffer[header_index]) ) - { - wchar_t c = (unsigned char)client.input_buffer[header_index++]; - - if( c == '+' ) - { - c = ' '; - } - else - if( c == '%' ) - { - if( header_index + 2 < client.input_buffer.size() ) - { - wchar_t c1 = ToLower((unsigned char)client.input_buffer[header_index++]); - wchar_t c2 = ToLower((unsigned char)client.input_buffer[header_index++]); - - if( IsHexDigit(c1) && IsHexDigit(c2) ) - { - int v1 = HexDigitToValue(c1); - int v2 = HexDigitToValue(c2); - - c = static_cast((v1 << 4) + v2); - } - else - { - return false; - } - } - else - { - return false; - } - } - else - if( c < 32 || c > 127 ) - { - return false; - } - - url_ascii += static_cast(c); - } - - bool utf8_correct = PT::UTF8ToWide(url_ascii, client.url); - - SkipWhite(client); - url_ascii.clear(); - - return utf8_correct && !client.url.empty(); -} -bool Server::ParseFirstHeaderHTTPVersion(Client & client) -{ - client.http_version = http_version_unsupported; - - if( header_index + 7 < client.input_buffer.size() && - client.input_buffer[header_index] == 'H' && - client.input_buffer[header_index + 1] == 'T' && - client.input_buffer[header_index + 2] == 'T' && - client.input_buffer[header_index + 3] == 'P' && - client.input_buffer[header_index + 4] == '/' && - IsDecDigit(client.input_buffer[header_index + 5]) && - client.input_buffer[header_index + 6] == '.' && - IsDecDigit(client.input_buffer[header_index + 7]) ) - { - int d1 = client.input_buffer[header_index + 5] - '0'; - int d2 = client.input_buffer[header_index + 7] - '0'; - - int ddd1 = client.input_buffer[header_index + 5] - '0'; - int ddd2 = client.input_buffer[header_index + 7] - '0'; - - if( d1 == 1 ) - { - client.http_version = http_version_1_0; - - } - - if( d2 == 1 ) - { - client.http_version = http_version_1_1; - } - - if( ddd1 == 1 ) - { - client.http_version = http_version_1_0; - - } - - if( ddd2 == 1 ) - { - client.http_version = http_version_1_1; - } - - if( d1 == 1 ) - { - if( d2 == 0 ) - client.http_version = http_version_1_0; - else - if( d2 == 1 ) - client.http_version = http_version_1_1; - } - - header_index += 8; - SkipWhite(client); - } - - return client.http_version != http_version_unsupported; -} - - - -// ParseHeaderKey should increment header_index at least once -bool Server::ParseHeaderKey(Client & client) -{ - while( header_index < client.input_buffer.size() && - client.input_buffer[header_index] != '\r' ) - { - if( client.input_buffer[header_index] == ':' ) - { - header_index += 1; - return true; - } - - wchar_t c = (unsigned char)client.input_buffer[header_index]; - - if( c >= 32 && c < 127 ) - { - // allow only asci characters - - tmp_header += c; - } - - header_index += 1; - } - - // there was not a colon at the end of the name - header_index += 1; - return false; -} - - -void Server::ParseHeaderValue(Client & client) -{ - while( header_index < client.input_buffer.size() ) - { - if( header_index + 1 < client.input_buffer.size() && - client.input_buffer[header_index] == '\r' && - client.input_buffer[header_index+1] == '\n' ) - { - if( header_index + 2 < client.input_buffer.size() && - (client.input_buffer[header_index+2] == ' ' || - client.input_buffer[header_index+2] == '\t') ) - { - // this line will be continued in the next line - header_index += 3; - - } - else - { - header_index += 2; - break; - } - } - else - { - wchar_t c = (unsigned char)client.input_buffer[header_index]; - - if( c >= 32 && c < 127 ) - { - // allow only ascii characters - - tmp_value += c; - } - - header_index += 1; - } - } -} - //void Server::RemoveClientSocket(int client_socket) //{ @@ -696,7 +432,7 @@ void Server::ParseHeaderValue(Client & client) // close(client_socket); // client_tab.erase(client_tab.begin() + i); // -// // warning: in ReadInputFromClients we have a loop through client_tab +// // warning: in ReadWriteToClients we have a loop through client_tab // // (next item will be skipped by ++i) // break; // } @@ -704,101 +440,6 @@ void Server::ParseHeaderValue(Client & client) //} -bool Server::IsDecDigit(wchar_t c) -{ - if( c >= '0' && c <= '9' ) - return true; - - return false; -} - - -bool Server::IsHexDigit(wchar_t c) -{ - if( c >= '0' && c <= '9' ) - return true; - - if( ToLower(c) >= 'a' && ToLower(c) <= 'f' ) - return true; - - return false; -} - - -int Server::HexDigitToValue(wchar_t c) -{ - if( c >= '0' && c <= '9' ) - return static_cast(c - '0'); - - if( ToLower(c) >= 'a' && ToLower(c) <= 'f' ) - return static_cast(c - 'a') + 10; - - return 0; -} - -wchar_t Server::ToLower(wchar_t c) -{ - if( c >= 'A' && c <= 'Z' ) - c = c - 'A' + 'a'; - - return c; -} - - -bool Server::CompareNoCase(const wchar_t * str1, const wchar_t * str2) -{ - while( *str1 && *str2 && ToLower(*str1) == ToLower(*str2) ) - { - ++str1; - ++str2; - } - - if( *str1 == 0 && *str2 == 0 ) - return true; - -return false; -} - - -bool Server::CompareNoCase(const std::wstring & str1, const wchar_t * str2) -{ - return CompareNoCase(str1.c_str(), str2); -} - - - -// do not use \r or \n here -bool Server::IsWhite(wchar_t c) -{ - return (c == ' ' || c == '\t'); -} - - -void Server::TrimWhiteAtEnd(std::wstring & str) -{ - if( !str.empty() ) - { - size_t i = str.size(); - - while( i > 0 && IsWhite(str[i-1]) ) - { - i -= 1; - } - - if( i < str.size() ) - str.erase(i); - } -} - - -void Server::SkipWhite(Client & client) -{ - while( header_index < client.input_buffer.size() && - IsWhite(client.input_buffer[header_index]) ) - { - header_index += 1; - } -} void Server::CreateAnswer(Client & client) @@ -809,6 +450,7 @@ void Server::CreateAnswer(Client & client) a += L"Content-Type: text/html; charset=UTF-8\r\n"; a += L"\r\n"; a += L"hello world from my webserwer, your requested: " + client.url; + a += L"\r\n"; if( client.url == L"/quit" ) { diff --git a/src/server.h b/src/server.h index 7cbe6bb..4a16691 100644 --- a/src/server.h +++ b/src/server.h @@ -4,6 +4,7 @@ #include #include "client.h" +#include "headers_parser.h" @@ -30,74 +31,25 @@ private: std::vector client_tab; int main_socket; fd_set read_set, write_set; - std::wstring tmp_header, tmp_value; - size_t header_index; - std::string url_ascii; bool close_server; + HeadersParser headers_parser; int AddSocketsToSet(); void AddNewClient(); - // change to a better name as it is used to write to a client too - void ReadInputFromClients(); - + void ReadWriteToClients(); void ReadInputFromClient(Client & client); void WriteOutputToClient(Client & client); void CheckHeaders(Client & client, size_t input_buffer_index); - // ptr buffer should consists of at least more 3 characters - bool IsHeadersEnding(const char * ptr); - - void ParseHeaders(Client & client); - bool ParseFirstHeader(Client & client); - - - bool ParseFirstHeaderMethodName(Client & client); - - - virtual bool SelectMethodName(Client & client, wchar_t * method_name); - - - /* - * The generic URI syntax mandates that new URI schemes that provide for the representation - * of character data in a URI must, in effect, represent characters from the unreserved set - * without translation, and should convert all other characters to bytes according to UTF-8, - * and then percent-encode those values. This requirement was introduced in January 2005 - * with the publication of RFC 3986. URI schemes introduced before this date are not affected. - * - * - */ - bool ParseFirstHeaderURL(Client & client); - - bool ParseFirstHeaderHTTPVersion(Client & client); - - - - // ParseHeaderKey should increment header_index at least once - bool ParseHeaderKey(Client & client); - - - void ParseHeaderValue(Client & client); + virtual bool SelectMethodName(Client & client, const std::wstring & method_name); //void RemoveClientSocket(int client_socket); - - bool IsDecDigit(wchar_t c); - bool IsHexDigit(wchar_t c); - int HexDigitToValue(wchar_t c); - wchar_t ToLower(wchar_t c); - bool CompareNoCase(const wchar_t * str1, const wchar_t * str2); - bool CompareNoCase(const std::wstring & str1, const wchar_t * str2); - - // do not use \r or \n here - bool IsWhite(wchar_t c); - - void TrimWhiteAtEnd(std::wstring & str); - void SkipWhite(Client & client); virtual void CreateAnswer(Client & client); diff --git a/src/string_functions.cpp b/src/string_functions.cpp new file mode 100644 index 0000000..33aac26 --- /dev/null +++ b/src/string_functions.cpp @@ -0,0 +1,94 @@ +#include +#include "string_functions.h" + + + + +wchar_t ToLower(wchar_t c) +{ + if( c >= 'A' && c <= 'Z' ) + c = c - 'A' + 'a'; + + return c; +} + + +bool CompareNoCase(const wchar_t * str1, const wchar_t * str2) +{ + while( *str1 && *str2 && ToLower(*str1) == ToLower(*str2) ) + { + ++str1; + ++str2; + } + + if( *str1 == 0 && *str2 == 0 ) + return true; + +return false; +} + + +bool CompareNoCase(const std::wstring & str1, const wchar_t * str2) +{ + return CompareNoCase(str1.c_str(), str2); +} + + +bool IsDecDigit(wchar_t c) +{ + if( c >= '0' && c <= '9' ) + return true; + + return false; +} + + +bool IsHexDigit(wchar_t c) +{ + if( c >= '0' && c <= '9' ) + return true; + + if( ToLower(c) >= 'a' && ToLower(c) <= 'f' ) + return true; + + return false; +} + + +int HexDigitToValue(wchar_t c) +{ + if( c >= '0' && c <= '9' ) + return static_cast(c - '0'); + + if( ToLower(c) >= 'a' && ToLower(c) <= 'f' ) + return static_cast(c - 'a') + 10; + + return 0; +} + + + +// do not use \r or \n here +bool IsWhite(wchar_t c) +{ + return (c == ' ' || c == '\t'); +} + + + +void TrimWhiteAtEnd(std::wstring & str) +{ + if( !str.empty() ) + { + size_t i = str.size(); + + while( i > 0 && IsWhite(str[i-1]) ) + { + i -= 1; + } + + if( i < str.size() ) + str.erase(i); + } +} + diff --git a/src/string_functions.h b/src/string_functions.h new file mode 100644 index 0000000..13c8505 --- /dev/null +++ b/src/string_functions.h @@ -0,0 +1,29 @@ +#ifndef headerfile_libscorpiohttpserver_src_string_functions_h +#define headerfile_libscorpiohttpserver_src_string_functions_h + + +#include + + + +wchar_t ToLower(wchar_t c); + +bool CompareNoCase(const wchar_t * str1, const wchar_t * str2); +bool CompareNoCase(const std::wstring & str1, const wchar_t * str2); + +bool IsDecDigit(wchar_t c); +bool IsHexDigit(wchar_t c); +int HexDigitToValue(wchar_t c); + +bool IsWhite(wchar_t c); +void TrimWhiteAtEnd(std::wstring & str); + + + + + +#endif + + + +