diff options
author | LogicParrot <LogicParrot@users.noreply.github.com> | 2016-02-05 22:45:45 +0100 |
---|---|---|
committer | LogicParrot <LogicParrot@users.noreply.github.com> | 2016-02-05 22:50:18 +0100 |
commit | ca6ef58b1ee8521e4b940ee4883dee714960e413 (patch) | |
tree | 8532add455224b07c07a759e3d906f50c0695888 /src/HTTPServer | |
parent | Merge pull request #2972 from marvinkopf/PlayerAutoComplete (diff) | |
download | cuberite-ca6ef58b1ee8521e4b940ee4883dee714960e413.tar cuberite-ca6ef58b1ee8521e4b940ee4883dee714960e413.tar.gz cuberite-ca6ef58b1ee8521e4b940ee4883dee714960e413.tar.bz2 cuberite-ca6ef58b1ee8521e4b940ee4883dee714960e413.tar.lz cuberite-ca6ef58b1ee8521e4b940ee4883dee714960e413.tar.xz cuberite-ca6ef58b1ee8521e4b940ee4883dee714960e413.tar.zst cuberite-ca6ef58b1ee8521e4b940ee4883dee714960e413.zip |
Diffstat (limited to '')
-rw-r--r-- | src/HTTPServer/EnvelopeParser.cpp | 14 | ||||
-rw-r--r-- | src/HTTPServer/EnvelopeParser.h | 26 | ||||
-rw-r--r-- | src/HTTPServer/HTTPConnection.cpp | 10 | ||||
-rw-r--r-- | src/HTTPServer/HTTPConnection.h | 36 | ||||
-rw-r--r-- | src/HTTPServer/HTTPFormParser.cpp | 6 | ||||
-rw-r--r-- | src/HTTPServer/HTTPFormParser.h | 42 | ||||
-rw-r--r-- | src/HTTPServer/HTTPMessage.cpp | 10 | ||||
-rw-r--r-- | src/HTTPServer/HTTPMessage.h | 66 | ||||
-rw-r--r-- | src/HTTPServer/HTTPServer.cpp | 32 | ||||
-rw-r--r-- | src/HTTPServer/HTTPServer.h | 30 | ||||
-rw-r--r-- | src/HTTPServer/MultipartParser.cpp | 28 | ||||
-rw-r--r-- | src/HTTPServer/MultipartParser.h | 32 | ||||
-rw-r--r-- | src/HTTPServer/NameValueParser.cpp | 30 | ||||
-rw-r--r-- | src/HTTPServer/NameValueParser.h | 24 | ||||
-rw-r--r-- | src/HTTPServer/SslHTTPConnection.cpp | 8 | ||||
-rw-r--r-- | src/HTTPServer/SslHTTPConnection.h | 10 |
16 files changed, 202 insertions, 202 deletions
diff --git a/src/HTTPServer/EnvelopeParser.cpp b/src/HTTPServer/EnvelopeParser.cpp index fd4f3836d..407e9dcfc 100644 --- a/src/HTTPServer/EnvelopeParser.cpp +++ b/src/HTTPServer/EnvelopeParser.cpp @@ -26,20 +26,20 @@ size_t cEnvelopeParser::Parse(const char * a_Data, size_t a_Size) { return 0; } - + // Start searching 1 char from the end of the already received data, if available: size_t SearchStart = m_IncomingData.size(); SearchStart = (SearchStart > 1) ? SearchStart - 1 : 0; - + m_IncomingData.append(a_Data, a_Size); - + size_t idxCRLF = m_IncomingData.find("\r\n", SearchStart); if (idxCRLF == AString::npos) { // Not a complete line yet, all input consumed: return a_Size; } - + // Parse as many lines as found: size_t Last = 0; do @@ -61,7 +61,7 @@ size_t cEnvelopeParser::Parse(const char * a_Data, size_t a_Size) idxCRLF = m_IncomingData.find("\r\n", idxCRLF + 2); } while (idxCRLF != AString::npos); m_IncomingData.erase(0, Last); - + // Parsed all lines and still expecting more return a_Size; } @@ -110,7 +110,7 @@ bool cEnvelopeParser::ParseLine(const char * a_Data, size_t a_Size) m_LastValue.append(a_Data, a_Size); return true; } - + // This is a line with a new key: NotifyLast(); for (size_t i = 0; i < a_Size; i++) @@ -122,7 +122,7 @@ bool cEnvelopeParser::ParseLine(const char * a_Data, size_t a_Size) return true; } } // for i - a_Data[] - + // No colon was found, key-less header?? return false; } diff --git a/src/HTTPServer/EnvelopeParser.h b/src/HTTPServer/EnvelopeParser.h index fe226d1f8..2fa930539 100644 --- a/src/HTTPServer/EnvelopeParser.h +++ b/src/HTTPServer/EnvelopeParser.h @@ -21,49 +21,49 @@ public: public: // Force a virtual destructor in descendants: virtual ~cCallbacks() {} - + /** Called when a full header line is parsed */ virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) = 0; } ; - - + + cEnvelopeParser(cCallbacks & a_Callbacks); - + /** Parses the incoming data. Returns the number of bytes consumed from the input. The bytes not consumed are not part of the envelope header. Returns AString::npos on error */ size_t Parse(const char * a_Data, size_t a_Size); - + /** Makes the parser forget everything parsed so far, so that it can be reused for parsing another datastream */ void Reset(void); - + /** Returns true if more input is expected for the envelope header */ bool IsInHeaders(void) const { return m_IsInHeaders; } - + /** Sets the IsInHeaders flag; used by cMultipartParser to simplify the parser initial conditions */ void SetIsInHeaders(bool a_IsInHeaders) { m_IsInHeaders = a_IsInHeaders; } - + public: /** Callbacks to call for the various events */ cCallbacks & m_Callbacks; - + /** Set to true while the parser is still parsing the envelope headers. Once set to true, the parser will not consume any more data. */ bool m_IsInHeaders; - + /** Buffer for the incoming data until it is parsed */ AString m_IncomingData; - + /** Holds the last parsed key; used for line-wrapped values */ AString m_LastKey; - + /** Holds the last parsed value; used for line-wrapped values */ AString m_LastValue; /** Notifies the callback of the key / value stored in m_LastKey / m_LastValue, then erases them */ void NotifyLast(void); - + /** Parses one line of header data. Returns true if successful */ bool ParseLine(const char * a_Data, size_t a_Size); } ; diff --git a/src/HTTPServer/HTTPConnection.cpp b/src/HTTPServer/HTTPConnection.cpp index c6a45e6ed..0db154139 100644 --- a/src/HTTPServer/HTTPConnection.cpp +++ b/src/HTTPServer/HTTPConnection.cpp @@ -104,7 +104,7 @@ void cHTTPConnection::AwaitNextRequest(void) // Nothing has been received yet, or a special response was given (SendStatusAndReason() or SendNeedAuth()) break; } - + case wcsRecvIdle: { // The client is waiting for a response, send an "Internal server error": @@ -112,7 +112,7 @@ void cHTTPConnection::AwaitNextRequest(void) m_State = wcsRecvHeaders; break; } - + case wcsSendingResp: { // The response headers have been sent, we need to terminate the response body: @@ -120,7 +120,7 @@ void cHTTPConnection::AwaitNextRequest(void) m_State = wcsRecvHeaders; break; } - + default: { ASSERT(!"Unhandled state recovery"); @@ -184,7 +184,7 @@ void cHTTPConnection::OnReceivedData(const char * a_Data, size_t a_Size) // The request headers are not yet complete return; } - + // The request has finished parsing its headers successfully, notify of it: m_State = wcsRecvBody; m_HTTPServer.NewRequest(*this, *m_CurrentRequest); @@ -194,7 +194,7 @@ void cHTTPConnection::OnReceivedData(const char * a_Data, size_t a_Size) // The body length was not specified in the request, assume zero m_CurrentRequestBodyRemaining = 0; } - + // Process the rest of the incoming data into the request body: if (a_Size > BytesConsumed) { diff --git a/src/HTTPServer/HTTPConnection.h b/src/HTTPServer/HTTPConnection.h index e1ebeb9ee..414075411 100644 --- a/src/HTTPServer/HTTPConnection.h +++ b/src/HTTPServer/HTTPConnection.h @@ -28,7 +28,7 @@ class cHTTPConnection : public cTCPLink::cCallbacks { public: - + enum eState { wcsRecvHeaders, ///< Receiving request headers (m_CurrentRequest is created if nullptr) @@ -37,48 +37,48 @@ public: wcsSendingResp, ///< Sending response body (m_CurrentRequest == nullptr) wcsInvalid, ///< The request was malformed, the connection is closing } ; - + cHTTPConnection(cHTTPServer & a_HTTPServer); virtual ~cHTTPConnection(); - + /** Sends HTTP status code together with a_Reason (used for HTTP errors). Sends the a_Reason as the body as well, so that browsers display it. */ void SendStatusAndReason(int a_StatusCode, const AString & a_Reason); - + /** Sends the "401 unauthorized" reply together with instructions on authorizing, using the specified realm */ void SendNeedAuth(const AString & a_Realm); - + /** Sends the headers contained in a_Response */ void Send(const cHTTPResponse & a_Response); - + /** Sends the data as the response (may be called multiple times) */ void Send(const void * a_Data, size_t a_Size); /** Sends the data as the response (may be called multiple times) */ void Send(const AString & a_Data) { Send(a_Data.data(), a_Data.size()); } - + /** Indicates that the current response is finished, gets ready for receiving another request (HTTP 1.1 keepalive) */ void FinishResponse(void); - + /** Resets the internal connection state for a new request. Depending on the state, this will send an "InternalServerError" status or a "ResponseEnd" */ void AwaitNextRequest(void); - + /** Terminates the connection; finishes any request being currently processed */ void Terminate(void); - + protected: typedef std::map<AString, AString> cNameValueMap; - + /** The parent webserver that is to be notified of events on this connection */ cHTTPServer & m_HTTPServer; - + /** All the incoming data until the entire request header is parsed */ AString m_IncomingHeaderData; - + /** Status in which the request currently is */ eState m_State; - + /** The request being currently received Valid only between having parsed the headers and finishing receiving the body. */ cHTTPRequest * m_CurrentRequest; @@ -89,18 +89,18 @@ protected: /** The network link attached to this connection. */ cTCPLinkPtr m_Link; - - + + // cTCPLink::cCallbacks overrides: /** The link instance has been created, remember it. */ virtual void OnLinkCreated(cTCPLinkPtr a_Link) override; /** Data is received from the client. */ virtual void OnReceivedData(const char * a_Data, size_t a_Size) override; - + /** The socket has been closed for any reason. */ virtual void OnRemoteClosed(void) override; - + /** An error has occurred on the socket. */ virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override; diff --git a/src/HTTPServer/HTTPFormParser.cpp b/src/HTTPServer/HTTPFormParser.cpp index 77f98e43b..497f84033 100644 --- a/src/HTTPServer/HTTPFormParser.cpp +++ b/src/HTTPServer/HTTPFormParser.cpp @@ -22,7 +22,7 @@ cHTTPFormParser::cHTTPFormParser(cHTTPRequest & a_Request, cCallbacks & a_Callba if (a_Request.GetMethod() == "GET") { m_Kind = fpkURL; - + // Directly parse the URL in the request: const AString & URL = a_Request.GetURL(); size_t idxQM = URL.find('?'); @@ -74,7 +74,7 @@ void cHTTPFormParser::Parse(const char * a_Data, size_t a_Size) { return; } - + switch (m_Kind) { case fpkURL: @@ -223,7 +223,7 @@ void cHTTPFormParser::OnPartHeader(const AString & a_Key, const AString & a_Valu m_IsValid = false; return; } - + // Parse the field name and optional filename from this header: cNameValueParser Parser(a_Value.data() + ParamsStart, a_Value.size() - ParamsStart); Parser.Finish(); diff --git a/src/HTTPServer/HTTPFormParser.h b/src/HTTPServer/HTTPFormParser.h index e72d4ef10..f6cbe047f 100644 --- a/src/HTTPServer/HTTPFormParser.h +++ b/src/HTTPServer/HTTPFormParser.h @@ -38,36 +38,36 @@ public: public: // Force a virtual destructor in descendants: virtual ~cCallbacks() {} - + /** Called when a new file part is encountered in the form data */ virtual void OnFileStart(cHTTPFormParser & a_Parser, const AString & a_FileName) = 0; - + /** Called when more file data has come for the current file in the form data */ virtual void OnFileData(cHTTPFormParser & a_Parser, const char * a_Data, size_t a_Size) = 0; - + /** Called when the current file part has ended in the form data */ virtual void OnFileEnd(cHTTPFormParser & a_Parser) = 0; } ; - - + + /** Creates a parser that is tied to a request and notifies of various events using a callback mechanism */ cHTTPFormParser(cHTTPRequest & a_Request, cCallbacks & a_Callbacks); - + /** Creates a parser with the specified content type that reads data from a string */ cHTTPFormParser(eKind a_Kind, const char * a_Data, size_t a_Size, cCallbacks & a_Callbacks); - + /** Adds more data into the parser, as the request body is received */ void Parse(const char * a_Data, size_t a_Size); - + /** Notifies that there's no more data incoming and the parser should finish its parsing. Returns true if parsing successful. */ bool Finish(void); - + /** Returns true if the headers suggest the request has form data parseable by this class */ static bool HasFormData(const cHTTPRequest & a_Request); - + protected: - + /** The callbacks to call for incoming file data */ cCallbacks & m_Callbacks; @@ -76,32 +76,32 @@ protected: /** Buffer for the incoming data until it's parsed */ AString m_IncomingData; - + /** True if the information received so far is a valid form; set to false on first problem. Further parsing is skipped when false. */ bool m_IsValid; - + /** The parser for the multipart data, if used */ std::unique_ptr<cMultipartParser> m_MultipartParser; - + /** Name of the currently parsed part in multipart data */ AString m_CurrentPartName; - + /** True if the currently parsed part in multipart data is a file */ bool m_IsCurrentPartFile; - + /** Filename of the current parsed part in multipart data (for file uploads) */ AString m_CurrentPartFileName; - + /** Set to true after m_Callbacks.OnFileStart() has been called, reset to false on PartEnd */ bool m_FileHasBeenAnnounced; - - + + /** Sets up the object for parsing a fpkMultipart request */ void BeginMultipart(const cHTTPRequest & a_Request); - + /** Parses m_IncomingData as form-urlencoded data (fpkURL or fpkFormUrlEncoded kinds) */ void ParseFormUrlEncoded(void); - + // cMultipartParser::cCallbacks overrides: virtual void OnPartStart (void) override; virtual void OnPartHeader(const AString & a_Key, const AString & a_Value) override; diff --git a/src/HTTPServer/HTTPMessage.cpp b/src/HTTPServer/HTTPMessage.cpp index 400625690..360145a9a 100644 --- a/src/HTTPServer/HTTPMessage.cpp +++ b/src/HTTPServer/HTTPMessage.cpp @@ -47,7 +47,7 @@ void cHTTPMessage::AddHeader(const AString & a_Key, const AString & a_Value) itr->second.append(", "); itr->second.append(a_Value); } - + // Special processing for well-known headers: if (Key == "content-type") { @@ -89,7 +89,7 @@ size_t cHTTPRequest::ParseHeaders(const char * a_Data, size_t a_Size) { return AString::npos; } - + if (m_Method.empty()) { // The first line hasn't been processed yet @@ -108,7 +108,7 @@ size_t cHTTPRequest::ParseHeaders(const char * a_Data, size_t a_Size) } return res2 + res; } - + if (m_EnvelopeParser.IsInHeaders()) { size_t res = m_EnvelopeParser.Parse(a_Data, a_Size); @@ -166,7 +166,7 @@ size_t cHTTPRequest::ParseRequestLine(const char * a_Data, size_t a_Size) m_IsValid = false; return AString::npos; } - + int NumSpaces = 0; size_t MethodEnd = 0; size_t URLEnd = 0; @@ -218,7 +218,7 @@ size_t cHTTPRequest::ParseRequestLine(const char * a_Data, size_t a_Size) } } // switch (m_IncomingHeaderData[i]) } // for i - m_IncomingHeaderData[] - + // CRLF hasn't been encountered yet, consider all data consumed return a_Size; } diff --git a/src/HTTPServer/HTTPMessage.h b/src/HTTPServer/HTTPMessage.h index ff657a272..72ecb67d1 100644 --- a/src/HTTPServer/HTTPMessage.h +++ b/src/HTTPServer/HTTPMessage.h @@ -29,26 +29,26 @@ public: mkRequest, mkResponse, } ; - + cHTTPMessage(eKind a_Kind); // Force a virtual destructor in all descendants virtual ~cHTTPMessage() {} - + /** Adds a header into the internal map of headers. Recognizes special headers: Content-Type and Content-Length */ void AddHeader(const AString & a_Key, const AString & a_Value); - + void SetContentType (const AString & a_ContentType) { m_ContentType = a_ContentType; } void SetContentLength(size_t a_ContentLength) { m_ContentLength = a_ContentLength; } - + const AString & GetContentType (void) const { return m_ContentType; } size_t GetContentLength(void) const { return m_ContentLength; } protected: typedef std::map<AString, AString> cNameValueMap; - + eKind m_Kind; - + cNameValueMap m_Headers; /** Type of the content; parsed by AddHeader(), set directly by SetContentLength() */ @@ -69,86 +69,86 @@ class cHTTPRequest : protected cEnvelopeParser::cCallbacks { typedef cHTTPMessage super; - + public: cHTTPRequest(void); - + /** Parses the request line and then headers from the received data. Returns the number of bytes consumed or AString::npos number for error */ size_t ParseHeaders(const char * a_Data, size_t a_Size); - + /** Returns true if the request did contain a Content-Length header */ bool HasReceivedContentLength(void) const { return (m_ContentLength != AString::npos); } - + /** Returns the method used in the request */ const AString & GetMethod(void) const { return m_Method; } - + /** Returns the URL used in the request */ const AString & GetURL(void) const { return m_URL; } - + /** Returns the URL used in the request, without any parameters */ AString GetBareURL(void) const; - + /** Sets the UserData pointer that is stored within this request. The request doesn't touch this data (doesn't delete it)! */ void SetUserData(void * a_UserData) { m_UserData = a_UserData; } - + /** Retrieves the UserData pointer that has been stored within this request. */ void * GetUserData(void) const { return m_UserData; } - + /** Returns true if more data is expected for the request headers */ bool IsInHeaders(void) const { return m_EnvelopeParser.IsInHeaders(); } - + /** Returns true if the request did present auth data that was understood by the parser */ bool HasAuth(void) const { return m_HasAuth; } - + /** Returns the username that the request presented. Only valid if HasAuth() is true */ const AString & GetAuthUsername(void) const { return m_AuthUsername; } - + /** Returns the password that the request presented. Only valid if HasAuth() is true */ const AString & GetAuthPassword(void) const { return m_AuthPassword; } - + bool DoesAllowKeepAlive(void) const { return m_AllowKeepAlive; } - + protected: /** Parser for the envelope data */ cEnvelopeParser m_EnvelopeParser; - + /** True if the data received so far is parsed successfully. When false, all further parsing is skipped */ bool m_IsValid; - + /** Bufferred incoming data, while parsing for the request line */ AString m_IncomingHeaderData; - + /** Method of the request (GET / PUT / POST / ...) */ AString m_Method; - + /** Full URL of the request */ AString m_URL; - + /** Data that the HTTPServer callbacks are allowed to store. */ void * m_UserData; - + /** Set to true if the request contains auth data that was understood by the parser */ bool m_HasAuth; - + /** The username used for auth */ AString m_AuthUsername; - + /** The password used for auth */ AString m_AuthPassword; - + /** Set to true if the request indicated that it supports keepalives. If false, the server will close the connection once the request is finished */ bool m_AllowKeepAlive; - - + + /** Parses the incoming data for the first line (RequestLine) Returns the number of bytes consumed, or AString::npos for an error */ size_t ParseRequestLine(const char * a_Data, size_t a_Size); - + // cEnvelopeParser::cCallbacks overrides: virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) override; } ; @@ -164,7 +164,7 @@ class cHTTPResponse : public: cHTTPResponse(void); - + /** Appends the response to the specified datastream - response line and headers. The body will be sent later directly through cConnection::Send() */ diff --git a/src/HTTPServer/HTTPServer.cpp b/src/HTTPServer/HTTPServer.cpp index bbff5d57a..814a87fe4 100644 --- a/src/HTTPServer/HTTPServer.cpp +++ b/src/HTTPServer/HTTPServer.cpp @@ -31,26 +31,26 @@ class cDebugCallbacks : virtual void OnRequestBegun(cHTTPConnection & a_Connection, cHTTPRequest & a_Request) override { UNUSED(a_Connection); - + if (cHTTPFormParser::HasFormData(a_Request)) { a_Request.SetUserData(new cHTTPFormParser(a_Request, *this)); } } - - + + virtual void OnRequestBody(cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, size_t a_Size) override { UNUSED(a_Connection); - + cHTTPFormParser * FormParser = reinterpret_cast<cHTTPFormParser *>(a_Request.GetUserData()); if (FormParser != nullptr) { FormParser->Parse(a_Data, a_Size); } } - - + + virtual void OnRequestFinished(cHTTPConnection & a_Connection, cHTTPRequest & a_Request) override { cHTTPFormParser * FormParser = reinterpret_cast<cHTTPFormParser *>(a_Request.GetUserData()); @@ -69,7 +69,7 @@ class cDebugCallbacks : a_Connection.Send("</table></body></html>"); return; } - + // Parsing failed: cHTTPResponse Resp; Resp.SetContentType("text/plain"); @@ -77,7 +77,7 @@ class cDebugCallbacks : a_Connection.Send("Form parsing failed"); return; } - + // Test the auth failure and success: if (a_Request.GetURL() == "/auth") { @@ -87,31 +87,31 @@ class cDebugCallbacks : return; } } - + cHTTPResponse Resp; Resp.SetContentType("text/plain"); a_Connection.Send(Resp); a_Connection.Send("Hello, world"); } - - + + virtual void OnFileStart(cHTTPFormParser & a_Parser, const AString & a_FileName) override { // TODO } - - + + virtual void OnFileData(cHTTPFormParser & a_Parser, const char * a_Data, size_t a_Size) override { // TODO } - + virtual void OnFileEnd(cHTTPFormParser & a_Parser) override { // TODO } - + }; static cDebugCallbacks g_DebugCallbacks; @@ -239,7 +239,7 @@ bool cHTTPServer::Start(cCallbacks & a_Callbacks, const AStringVector & a_Ports) m_ServerHandles.push_back(Handle); } } // for port - a_Ports[] - + // Report success if at least one port opened successfully: return !m_ServerHandles.empty(); } diff --git a/src/HTTPServer/HTTPServer.h b/src/HTTPServer/HTTPServer.h index d626fb475..2a094b413 100644 --- a/src/HTTPServer/HTTPServer.h +++ b/src/HTTPServer/HTTPServer.h @@ -39,48 +39,48 @@ public: { public: virtual ~cCallbacks() {} - + /** Called when a new request arrives over a connection and all its headers have been parsed. The request body needn't have arrived yet. */ virtual void OnRequestBegun(cHTTPConnection & a_Connection, cHTTPRequest & a_Request) = 0; - + /** Called when another part of request body has arrived. May be called multiple times for a single request. */ virtual void OnRequestBody(cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, size_t a_Size) = 0; - + /** Called when the request body has been fully received in previous calls to OnRequestBody() */ virtual void OnRequestFinished(cHTTPConnection & a_Connection, cHTTPRequest & a_Request) = 0; } ; - + cHTTPServer(void); virtual ~cHTTPServer(); - + /** Initializes the server - reads the cert files etc. */ bool Initialize(void); - + /** Starts the server and assigns the callbacks to use for incoming requests */ bool Start(cCallbacks & a_Callbacks, const AStringVector & a_Ports); - + /** Stops the server, drops all current connections */ void Stop(void); - + protected: friend class cHTTPConnection; friend class cSslHTTPConnection; friend class cHTTPServerListenCallbacks; - + /** The cNetwork API handle for the listening socket. */ cServerHandlePtrs m_ServerHandles; - + /** The callbacks to call for various events */ cCallbacks * m_Callbacks; - + /** The server certificate to use for the SSL connections */ cX509CertPtr m_Cert; - + /** The private key for m_Cert. */ cCryptoKeyPtr m_CertPrivKey; - + /** Called by cHTTPServerListenCallbacks when there's a new incoming connection. Returns the connection instance to be used as the cTCPLink callbacks. */ @@ -88,11 +88,11 @@ protected: /** Called by cHTTPConnection when it finishes parsing the request header */ void NewRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request); - + /** Called by cHTTPConenction when it receives more data for the request body. May be called multiple times for a single request. */ void RequestBody(cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, size_t a_Size); - + /** Called by cHTTPConnection when it detects that the request has finished (all of its body has been received) */ void RequestFinished(cHTTPConnection & a_Connection, cHTTPRequest & a_Request); } ; diff --git a/src/HTTPServer/MultipartParser.cpp b/src/HTTPServer/MultipartParser.cpp index 09732c5f7..09f4fd02a 100644 --- a/src/HTTPServer/MultipartParser.cpp +++ b/src/HTTPServer/MultipartParser.cpp @@ -56,25 +56,25 @@ ThisIsIgnoredEpilogue"; // DEBUG: Check if the onscreen output corresponds with the data above printf("Multipart parsing test finished\n"); } - + virtual void OnPartStart(void) override { printf("Starting a new part\n"); } - - + + virtual void OnPartHeader(const AString & a_Key, const AString & a_Value) override { printf(" Hdr: \"%s\"=\"%s\"\n", a_Key.c_str(), a_Value.c_str()); } - - + + virtual void OnPartData(const char * a_Data, int a_Size) override { printf(" Data: %d bytes, \"%.*s\"\n", a_Size, a_Size, a_Data); } - - + + virtual void OnPartEnd(void) override { printf("Part end\n"); @@ -110,7 +110,7 @@ cMultipartParser::cMultipartParser(const AString & a_ContentType, cCallbacks & a m_IsValid = false; return; } - + // Find the multipart boundary: ContentType.erase(0, idxSC + 1); cNameValueParser CTParser(ContentType.c_str(), ContentType.size()); @@ -126,13 +126,13 @@ cMultipartParser::cMultipartParser(const AString & a_ContentType, cCallbacks & a { return; } - + // Set the envelope parser for parsing the body, so that our Parse() function parses the ignored prefix data as a body m_EnvelopeParser.SetIsInHeaders(false); // Append an initial CRLF to the incoming data, so that a body starting with the boundary line will get caught m_IncomingData.assign("\r\n"); - + /* m_Boundary = AString("\r\n--") + m_Boundary m_BoundaryEnd = m_Boundary + "--\r\n"; @@ -151,7 +151,7 @@ void cMultipartParser::Parse(const char * a_Data, size_t a_Size) { return; } - + // Append to buffer, then parse it: m_IncomingData.append(a_Data, a_Size); for (;;) @@ -213,7 +213,7 @@ void cMultipartParser::Parse(const char * a_Data, size_t a_Size) m_IncomingData.erase(0, LineEnd); continue; } - + if (strncmp(m_IncomingData.c_str() + idxBoundary, m_Boundary.c_str(), m_Boundary.size()) == 0) { // Boundary or BoundaryEnd found: @@ -228,12 +228,12 @@ void cMultipartParser::Parse(const char * a_Data, size_t a_Size) } m_Callbacks.OnPartStart(); m_IncomingData.erase(0, LineEnd + 2); - + // Keep parsing for the headers that may have come with this data: m_EnvelopeParser.Reset(); continue; } - + // It's a line, but not a boundary. It can be fully sent to the data receiver, since a boundary cannot cross lines m_Callbacks.OnPartData(m_IncomingData.c_str(), LineEnd); m_IncomingData.erase(0, LineEnd); diff --git a/src/HTTPServer/MultipartParser.h b/src/HTTPServer/MultipartParser.h index ad76ad650..4f20b2bed 100644 --- a/src/HTTPServer/MultipartParser.h +++ b/src/HTTPServer/MultipartParser.h @@ -24,52 +24,52 @@ public: public: // Force a virtual destructor in descendants: virtual ~cCallbacks() {} - + /** Called when a new part starts */ virtual void OnPartStart(void) = 0; - + /** Called when a complete header line is received for a part */ virtual void OnPartHeader(const AString & a_Key, const AString & a_Value) = 0; - + /** Called when body for a part is received */ virtual void OnPartData(const char * a_Data, size_t a_Size) = 0; - + /** Called when the current part ends */ virtual void OnPartEnd(void) = 0; } ; - + /** Creates the parser, expects to find the boundary in a_ContentType */ cMultipartParser(const AString & a_ContentType, cCallbacks & a_Callbacks); - + /** Parses more incoming data */ void Parse(const char * a_Data, size_t a_Size); - + protected: /** The callbacks to call for various parsing events */ cCallbacks & m_Callbacks; - + /** True if the data parsed so far is valid; if false, further parsing is skipped */ bool m_IsValid; - + /** Parser for each part's envelope */ cEnvelopeParser m_EnvelopeParser; - + /** Buffer for the incoming data until it is parsed */ AString m_IncomingData; - + /** The boundary, excluding both the initial "--" and the terminating CRLF */ AString m_Boundary; - + /** Set to true if some data for the current part has already been signalized to m_Callbacks. Used for proper CRLF inserting. */ bool m_HasHadData; - - + + /** Parse one line of incoming data. The CRLF has already been stripped from a_Data / a_Size */ void ParseLine(const char * a_Data, size_t a_Size); - + /** Parse one line of incoming data in the headers section of a part. The CRLF has already been stripped from a_Data / a_Size */ void ParseHeaderLine(const char * a_Data, size_t a_Size); - + // cEnvelopeParser overrides: virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) override; } ; diff --git a/src/HTTPServer/NameValueParser.cpp b/src/HTTPServer/NameValueParser.cpp index b345fef88..f759c4d21 100644 --- a/src/HTTPServer/NameValueParser.cpp +++ b/src/HTTPServer/NameValueParser.cpp @@ -29,18 +29,18 @@ public: Parser2.Parse(Data + i, 1); } Parser2.Finish(); - + // Parse as a single chunk of data: cNameValueParser Parser(Data, sizeof(Data) - 1); - + // Use the debugger to inspect the Parser variable - + // Check that the two parsers have the same content: for (cNameValueParser::const_iterator itr = Parser.begin(), end = Parser.end(); itr != end; ++itr) { ASSERT(Parser2[itr->first] == itr->second); } // for itr - Parser[] - + // Try parsing in 2-char chunks: cNameValueParser Parser3; for (int i = 0; i < sizeof(Data) - 2; i += 2) @@ -52,13 +52,13 @@ public: Parser3.Parse(Data + sizeof(Data) - 2, 1); } Parser3.Finish(); - + // Check that the third parser has the same content: for (cNameValueParser::const_iterator itr = Parser.begin(), end = Parser.end(); itr != end; ++itr) { ASSERT(Parser3[itr->first] == itr->second); } // for itr - Parser[] - + printf("cNameValueParserTest done"); } } g_Test; @@ -96,7 +96,7 @@ cNameValueParser::cNameValueParser(const char * a_Data, size_t a_Size, bool a_Al void cNameValueParser::Parse(const char * a_Data, size_t a_Size) { ASSERT(m_State != psFinished); // Calling Parse() after Finish() is wrong! - + size_t Last = 0; for (size_t i = 0; i < a_Size;) { @@ -107,7 +107,7 @@ void cNameValueParser::Parse(const char * a_Data, size_t a_Size) { return; } - + case psKeySpace: { // Skip whitespace until a non-whitespace is found, then start the key: @@ -122,7 +122,7 @@ void cNameValueParser::Parse(const char * a_Data, size_t a_Size) } break; } - + case psKey: { // Read the key until whitespace or an equal sign: @@ -174,7 +174,7 @@ void cNameValueParser::Parse(const char * a_Data, size_t a_Size) } break; } - + case psEqualSpace: { // The space before the expected equal sign; the current key is already assigned @@ -211,7 +211,7 @@ void cNameValueParser::Parse(const char * a_Data, size_t a_Size) } // while (i < a_Size) break; } // case psEqualSpace - + case psEqual: { // just parsed the equal-sign @@ -256,7 +256,7 @@ void cNameValueParser::Parse(const char * a_Data, size_t a_Size) } // while (i < a_Size) break; } // case psEqual - + case psValueInDQuotes: { while (i < a_Size) @@ -280,7 +280,7 @@ void cNameValueParser::Parse(const char * a_Data, size_t a_Size) } break; } // case psValueInDQuotes - + case psValueInSQuotes: { while (i < a_Size) @@ -304,7 +304,7 @@ void cNameValueParser::Parse(const char * a_Data, size_t a_Size) } break; } // case psValueInSQuotes - + case psValueRaw: { while (i < a_Size) @@ -328,7 +328,7 @@ void cNameValueParser::Parse(const char * a_Data, size_t a_Size) } break; } // case psValueRaw - + case psAfterValue: { // Between the closing DQuote or SQuote and the terminating semicolon diff --git a/src/HTTPServer/NameValueParser.h b/src/HTTPServer/NameValueParser.h index c0643b139..e205079db 100644 --- a/src/HTTPServer/NameValueParser.h +++ b/src/HTTPServer/NameValueParser.h @@ -19,22 +19,22 @@ class cNameValueParser : public: /** Creates an empty parser */ cNameValueParser(bool a_AllowsKeyOnly = true); - + /** Creates an empty parser, then parses the data given. Doesn't call Finish(), so more data can be parsed later */ cNameValueParser(const char * a_Data, size_t a_Size, bool a_AllowsKeyOnly = true); - + /** Parses the data given */ void Parse(const char * a_Data, size_t a_Size); - + /** Notifies the parser that no more data will be coming. Returns true if the parser state is valid */ bool Finish(void); - + /** Returns true if the data parsed so far was valid */ bool IsValid(void) const { return (m_State != psInvalid); } - + /** Returns true if the parser expects no more data */ bool IsFinished(void) const { return ((m_State == psInvalid) || (m_State == psFinished)); } - + protected: enum eState { @@ -49,20 +49,20 @@ protected: psInvalid, ///< The parser has encountered an invalid input; further parsing is skipped psFinished, ///< The parser has already been instructed to finish and doesn't expect any more data } ; - + /** The current state of the parser */ eState m_State; - + /** If true, the parser will accept keys without an equal sign and the value */ bool m_AllowsKeyOnly; - + /** Buffer for the current Key */ AString m_CurrentKey; - + /** Buffer for the current Value; */ AString m_CurrentValue; - - + + } ; diff --git a/src/HTTPServer/SslHTTPConnection.cpp b/src/HTTPServer/SslHTTPConnection.cpp index 1e862466c..1cbe02312 100644 --- a/src/HTTPServer/SslHTTPConnection.cpp +++ b/src/HTTPServer/SslHTTPConnection.cpp @@ -49,7 +49,7 @@ void cSslHTTPConnection::OnReceivedData(const char * a_Data, size_t a_Size) Data += BytesWritten; Size -= BytesWritten; } - + // Try to read as many bytes from SSL's decryption as possible: char Buffer[32000]; int NumRead = m_Ssl.ReadPlain(Buffer, sizeof(Buffer)); @@ -64,7 +64,7 @@ void cSslHTTPConnection::OnReceivedData(const char * a_Data, size_t a_Size) // SSL requires us to send data to peer first, do so by "sending" empty data: SendData(nullptr, 0); } - + // If both failed, bail out: if ((BytesWritten == 0) && (NumRead <= 0)) { @@ -93,7 +93,7 @@ void cSslHTTPConnection::SendData(const void * a_Data, size_t a_Size) pos += static_cast<size_t>(NumWritten); } } - + // Read as many bytes from SSL's "outgoing" buffer as possible: char Buffer[32000]; size_t NumBytes = m_Ssl.ReadOutgoing(Buffer, sizeof(Buffer)); @@ -101,7 +101,7 @@ void cSslHTTPConnection::SendData(const void * a_Data, size_t a_Size) { m_Link->Send(Buffer, NumBytes); } - + // If both failed, bail out: if ((NumWritten <= 0) && (NumBytes == 0)) { diff --git a/src/HTTPServer/SslHTTPConnection.h b/src/HTTPServer/SslHTTPConnection.h index c461a3a24..b35bd8ba0 100644 --- a/src/HTTPServer/SslHTTPConnection.h +++ b/src/HTTPServer/SslHTTPConnection.h @@ -20,23 +20,23 @@ class cSslHTTPConnection : public cHTTPConnection { typedef cHTTPConnection super; - + public: /** Creates a new connection on the specified server. Sends the specified cert as the server certificate, uses the private key for decryption. */ cSslHTTPConnection(cHTTPServer & a_HTTPServer, const cX509CertPtr & a_Cert, const cCryptoKeyPtr & a_PrivateKey); ~cSslHTTPConnection(); - + protected: cBufferedSslContext m_Ssl; - + /** The certificate to send to the client */ cX509CertPtr m_Cert; - + /** The private key used for the certificate */ cCryptoKeyPtr m_PrivateKey; - + // cHTTPConnection overrides: virtual void OnReceivedData(const char * a_Data, size_t a_Size) override; // Data is received from the client virtual void SendData(const void * a_Data, size_t a_Size) override; // Data is to be sent to client |