mirror of
https://github.com/lammertb/libhttp.git
synced 2026-01-27 08:02:47 +03:00
Moved parse_http_message to own file
This commit is contained in:
1
Makefile
1
Makefile
@@ -80,6 +80,7 @@ LIB_SOURCES = src/libhttp.c \
|
||||
src/httplib_log_access.c \
|
||||
src/httplib_master_thread.c \
|
||||
src/httplib_mkcol.c \
|
||||
src/httplib_parse_http_message.c \
|
||||
src/httplib_parse_net.c \
|
||||
src/httplib_prepare_cgi_environment.c \
|
||||
src/httplib_process_new_connection.c \
|
||||
|
||||
92
src/httplib_parse_http_message.c
Normal file
92
src/httplib_parse_http_message.c
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lammert Bies
|
||||
* Copyright (c) 2013-2016 the Civetweb developers
|
||||
* Copyright (c) 2004-2013 Sergey Lyubka
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "libhttp-private.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* int XX_httplib_parse_http_message( char *buf, int len, struct mg_request_info *ri );
|
||||
*
|
||||
* The function XX_httplib_parse_http_message() parses an HTTP request and
|
||||
* fills in the mg_request_info structure. This function modifies the buffer by
|
||||
* NUL terminating HTTP request components, header names and header values.
|
||||
* Parameters:
|
||||
* buf (in/out) pointer to the HTTP header to parse and split
|
||||
* len (in) length of the HTTP header buffer
|
||||
* ri (out) parsed header as a mg_request_info structure
|
||||
* The parameters buf and ri must be valid pointers (not NULL) with a length
|
||||
* larger than zero. On error the function return a negative value, otherwise
|
||||
* the length of the request is returned.
|
||||
*/
|
||||
|
||||
int XX_httplib_parse_http_message( char *buf, int len, struct mg_request_info *ri ) {
|
||||
|
||||
int is_request;
|
||||
int request_length;
|
||||
char *start_line;
|
||||
|
||||
request_length = XX_httplib_get_request_len(buf, len);
|
||||
|
||||
if (request_length > 0) {
|
||||
/* Reset attributes. DO NOT TOUCH is_ssl, remote_ip, remote_addr,
|
||||
* remote_port */
|
||||
ri->remote_user = ri->request_method = ri->request_uri =
|
||||
ri->http_version = NULL;
|
||||
ri->num_headers = 0;
|
||||
|
||||
buf[request_length - 1] = '\0';
|
||||
|
||||
/* RFC says that all initial whitespaces should be ingored */
|
||||
while (*buf != '\0' && isspace(*(unsigned char *)buf)) {
|
||||
buf++;
|
||||
}
|
||||
start_line = XX_httplib_skip(&buf, "\r\n");
|
||||
ri->request_method = XX_httplib_skip(&start_line, " ");
|
||||
ri->request_uri = XX_httplib_skip(&start_line, " ");
|
||||
ri->http_version = start_line;
|
||||
|
||||
/* HTTP message could be either HTTP request:
|
||||
* "GET / HTTP/1.0 ..."
|
||||
* or a HTTP response:
|
||||
* "HTTP/1.0 200 OK ..."
|
||||
* otherwise it is invalid.
|
||||
*/
|
||||
is_request = XX_httplib_is_valid_http_method(ri->request_method);
|
||||
if ((is_request && memcmp(ri->http_version, "HTTP/", 5) != 0)
|
||||
|| (!is_request && memcmp(ri->request_method, "HTTP/", 5) != 0)) {
|
||||
/* Not a valid request or response: invalid */
|
||||
return -1;
|
||||
}
|
||||
if (is_request) ri->http_version += 5;
|
||||
if (XX_httplib_parse_http_headers(&buf, ri) < 0) {
|
||||
/* Error while parsing headers */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return request_length;
|
||||
|
||||
} /* XX_httplib_parse_http_message */
|
||||
@@ -927,6 +927,7 @@ void XX_httplib_interpret_uri( struct mg_connection *conn, char *filename, size_
|
||||
int XX_httplib_is_authorized_for_put( struct mg_connection *conn );
|
||||
int XX_httplib_is_not_modified( const struct mg_connection *conn, const struct file *filep );
|
||||
int XX_httplib_is_put_or_delete_method( const struct mg_connection *conn );
|
||||
int XX_httplib_is_valid_http_method( const char *method );
|
||||
int XX_httplib_is_valid_port( unsigned long port );
|
||||
int XX_httplib_is_websocket_protocol( const struct mg_connection *conn );
|
||||
int XX_httplib_join_thread( pthread_t threadid );
|
||||
@@ -980,6 +981,7 @@ int XX_httplib_set_throttle( const char *spec, uint32_t remote_ip, const char
|
||||
int XX_httplib_set_uid_option( struct mg_context *ctx );
|
||||
int XX_httplib_should_decode_url( const struct mg_connection *conn );
|
||||
int XX_httplib_should_keep_alive( const struct mg_connection *conn );
|
||||
char * XX_httplib_skip( char **buf, const char *delimiters );
|
||||
void XX_httplib_snprintf( const struct mg_connection *conn, int *truncated, char *buf, size_t buflen, PRINTF_FORMAT_STRING(const char *fmt), ... ) PRINTF_ARGS(5, 6);
|
||||
void XX_httplib_sockaddr_to_string(char *buf, size_t len, const union usa *usa );
|
||||
pid_t XX_httplib_spawn_process( struct mg_connection *conn, const char *prog, char *envblk, char *envp[], int fdin[2], int fdout[2], int fderr[2], const char *dir );
|
||||
|
||||
@@ -1290,10 +1290,11 @@ static char * skip_quoted(char **buf, const char *delimiters, const char *whites
|
||||
|
||||
/* Simplified version of skip_quoted without quote char
|
||||
* and whitespace == delimiters */
|
||||
static char * skip(char **buf, const char *delimiters) {
|
||||
char *XX_httplib_skip( char **buf, const char *delimiters ) {
|
||||
|
||||
return skip_quoted(buf, delimiters, delimiters, 0);
|
||||
}
|
||||
return skip_quoted( buf, delimiters, delimiters, 0 );
|
||||
|
||||
} /* XX_httplib_skip */
|
||||
|
||||
|
||||
/* Return HTTP header value, or NULL if not found. */
|
||||
@@ -5251,7 +5252,7 @@ int XX_httplib_parse_http_headers( char **buf, struct mg_request_info *ri ) {
|
||||
} /* XX_httplib_parse_http_headers */
|
||||
|
||||
|
||||
static int is_valid_http_method(const char *method) {
|
||||
int XX_httplib_is_valid_http_method( const char *method ) {
|
||||
|
||||
return !strcmp(method, "GET") /* HTTP (RFC 2616) */
|
||||
|| !strcmp(method, "POST") /* HTTP (RFC 2616) */
|
||||
@@ -5276,62 +5277,5 @@ static int is_valid_http_method(const char *method) {
|
||||
|
||||
/* PATCH method only allowed for CGI/Lua/LSP and callbacks. */
|
||||
|| !strcmp(method, "PATCH"); /* PATCH method (RFC 5789) */
|
||||
}
|
||||
|
||||
|
||||
/* Parse HTTP request, fill in mg_request_info structure.
|
||||
* This function modifies the buffer by NUL-terminating
|
||||
* HTTP request components, header names and header values.
|
||||
* Parameters:
|
||||
* buf (in/out): pointer to the HTTP header to parse and split
|
||||
* len (in): length of HTTP header buffer
|
||||
* re (out): parsed header as mg_request_info
|
||||
* buf and ri must be valid pointers (not NULL), len>0.
|
||||
* Returns <0 on error. */
|
||||
int XX_httplib_parse_http_message( char *buf, int len, struct mg_request_info *ri ) {
|
||||
|
||||
int is_request;
|
||||
int request_length;
|
||||
char *start_line;
|
||||
|
||||
request_length = XX_httplib_get_request_len(buf, len);
|
||||
|
||||
if (request_length > 0) {
|
||||
/* Reset attributes. DO NOT TOUCH is_ssl, remote_ip, remote_addr,
|
||||
* remote_port */
|
||||
ri->remote_user = ri->request_method = ri->request_uri =
|
||||
ri->http_version = NULL;
|
||||
ri->num_headers = 0;
|
||||
|
||||
buf[request_length - 1] = '\0';
|
||||
|
||||
/* RFC says that all initial whitespaces should be ingored */
|
||||
while (*buf != '\0' && isspace(*(unsigned char *)buf)) {
|
||||
buf++;
|
||||
}
|
||||
start_line = skip(&buf, "\r\n");
|
||||
ri->request_method = skip(&start_line, " ");
|
||||
ri->request_uri = skip(&start_line, " ");
|
||||
ri->http_version = start_line;
|
||||
|
||||
/* HTTP message could be either HTTP request:
|
||||
* "GET / HTTP/1.0 ..."
|
||||
* or a HTTP response:
|
||||
* "HTTP/1.0 200 OK ..."
|
||||
* otherwise it is invalid.
|
||||
*/
|
||||
is_request = is_valid_http_method(ri->request_method);
|
||||
if ((is_request && memcmp(ri->http_version, "HTTP/", 5) != 0)
|
||||
|| (!is_request && memcmp(ri->request_method, "HTTP/", 5) != 0)) {
|
||||
/* Not a valid request or response: invalid */
|
||||
return -1;
|
||||
}
|
||||
if (is_request) ri->http_version += 5;
|
||||
if (XX_httplib_parse_http_headers(&buf, ri) < 0) {
|
||||
/* Error while parsing headers */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return request_length;
|
||||
|
||||
} /* XX_httplib_parse_http_message */
|
||||
} /* XX_httplib_is_valid_http_method */
|
||||
|
||||
Reference in New Issue
Block a user