diff options
author | Mamadou DIOP <bossiel@yahoo.fr> | 2015-08-17 01:56:35 +0200 |
---|---|---|
committer | Mamadou DIOP <bossiel@yahoo.fr> | 2015-08-17 01:56:35 +0200 |
commit | 631fffee8a28b1bec5ed1f1d26a20e0135967f99 (patch) | |
tree | 74afe3bf3efe15aa82bcd0272b2b0f4d48c2d837 /tinyHTTP/ragel | |
parent | 7908865936604036e6f200f1b5e069f8752f3a3a (diff) | |
download | doubango-631fffee8a28b1bec5ed1f1d26a20e0135967f99.zip doubango-631fffee8a28b1bec5ed1f1d26a20e0135967f99.tar.gz |
-
Diffstat (limited to 'tinyHTTP/ragel')
18 files changed, 3197 insertions, 0 deletions
diff --git a/tinyHTTP/ragel/thttp_machine_header.rl b/tinyHTTP/ragel/thttp_machine_header.rl new file mode 100644 index 0000000..680cff9 --- /dev/null +++ b/tinyHTTP/ragel/thttp_machine_header.rl @@ -0,0 +1,87 @@ +/* +* Copyright (C) 2010-2015 Mamadou Diop. +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ +/**@file thttp_machine_headers.rl. + * @brief Ragel file. + */ + +/*== Header pasrsing machine. Supports both full-length and compact mode. */ +%%{ + machine thttp_machine_header; + + Accept = "Accept"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Accept; + Accept_Charset = "Accept-Charset"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Accept_Charset; + Accept_Encoding = "Accept-Encoding"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Accept_Encoding; + Accept_Language = "Accept-Language"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Accept_Language; + Allow = "Allow"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Allow; + Authorization = "Authorization"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Authorization; + Cache_Control = "Cache-Control"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Cache_Control; + Connection = "Connection"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Connection; + Content_Encoding = ("Content-Encoding"i | "e") SP* HCOLON SP*<: any* :>CRLF @parse_header_Content_Encoding; + Content_Language = "Content-Language"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Content_Language; + Content_Length = "Content-Length"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Content_Length; + Content_Location = "Content-Location"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Content_Location; + Content_MD5 = "Content-MD5"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Content_MD5; + Content_Range = "Content-Range"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Content_Range; + Content_Type = ("Content-Type"i | "c") SP* HCOLON SP*<: any* :>CRLF @parse_header_Content_Type; + Date = "Date"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Date; + ETag = "ETag"i SP* HCOLON SP*<: any* :>CRLF @parse_header_ETag; + Expect = "Expect"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Expect; + Expires = "Expires"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Expires; + From = "From"i SP* HCOLON SP*<: any* :>CRLF @parse_header_From; + Host = "Host"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Host; + If_Match = "If-Match"i SP* HCOLON SP*<: any* :>CRLF @parse_header_If_Match; + If_Modified_Since = "If-Modified-Since"i SP* HCOLON SP*<: any* :>CRLF @parse_header_If_Modified_Since; + If_None_Match = "If-None-Match"i SP* HCOLON SP*<: any* :>CRLF @parse_header_If_None_Match; + If_Range = "If-Range"i SP* HCOLON SP*<: any* :>CRLF @parse_header_If_Range; + If_Unmodified_Since = "If-Unmodified-Since"i SP* HCOLON SP*<: any* :>CRLF @parse_header_If_Unmodified_Since; + Last_Modified = "Last-Modified"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Last_Modified; + Max_Forwards = "Max-Forwards"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Max_Forwards; + Pragma = "Pragma"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Pragma; + Proxy_Authenticate = "Proxy-Authenticate"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Proxy_Authenticate; + Proxy_Authorization = "Proxy-Authorization"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Proxy_Authorization; + Range = "Range"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Range; + Referer = "Referer"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Referer; + Transfer_Encoding = "Transfer-Encoding"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Transfer_Encoding; + TE = "TE"i SP* HCOLON SP*<: any* :>CRLF @parse_header_TE; + Trailer = "Trailer"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Trailer; + Upgrade = "Upgrade"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Upgrade; + User_Agent = "User-Agent"i SP* HCOLON SP*<: any* :>CRLF @parse_header_User_Agent; + Via = "Via"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Via; + Warning = "Warning"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Warning; + WWW_Authenticate = "WWW-Authenticate"i SP* HCOLON SP*<: any* :>CRLF @parse_header_WWW_Authenticate; + + # WebSocket + Sec_WebSocket_Accept = "Sec-WebSocket-Accept"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Sec_WebSocket_Accept; + Sec_WebSocket_Key = "Sec-WebSocket-Key"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Sec_WebSocket_Key; + Sec_WebSocket_Protocol = "Sec-WebSocket-Protocol"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Sec_WebSocket_Protocol; + Sec_WebSocket_Version = "Sec-WebSocket-Version"i SP* HCOLON SP*<: any* :>CRLF @parse_header_Sec_WebSocket_Version; + + + ###### + extension_header = (token) SP* HCOLON SP*<: any* :>CRLF @parse_header_extension_header; + + general_header = Cache_Control | Connection | Date | Pragma | Trailer | Transfer_Encoding | Upgrade | Via | Warning; + auth_header = Authorization | WWW_Authenticate | Proxy_Authorization | Proxy_Authenticate; + request_header = Accept | Accept_Charset | Accept_Encoding | Accept_Language | Expect | From | Host | If_Match | If_Modified_Since | If_None_Match | If_Range | If_Unmodified_Since | Max_Forwards | Range | Referer | TE | User_Agent; + entity_header = Allow | Content_Encoding | Content_Language | Content_Length | Content_Location | Content_MD5 | Content_Range | Content_Type | ETag | Expires | Last_Modified; + ws_header = Sec_WebSocket_Accept | Sec_WebSocket_Key | Sec_WebSocket_Protocol | Sec_WebSocket_Version; + + HEADER = (general_header | auth_header | request_header | entity_header | ws_header)@1 | extension_header@0; +}%%
\ No newline at end of file diff --git a/tinyHTTP/ragel/thttp_machine_message.rl b/tinyHTTP/ragel/thttp_machine_message.rl new file mode 100644 index 0000000..f889b24 --- /dev/null +++ b/tinyHTTP/ragel/thttp_machine_message.rl @@ -0,0 +1,44 @@ +/* +* Copyright (C) 2010-2015 Mamadou Diop. +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ +/**@file thttp_machine_message.rl + * @brief Ragel file. + */ +%%{ + machine thttp_machine_message; + + message_body = any*; + HTTP_Version = ("HTTP"i "/" DIGIT+ "." DIGIT+)>tag %parse_httpversion; + + message_header = any+ >tag :>CRLF %parse_header; + + # HTTP RESPONSE + Reason_Phrase = (( reserved | unreserved | escaped | UTF8_NONASCII | UTF8_CONT | SP | HTAB )*)>tag %parse_reason_phrase; + Status_Line = HTTP_Version :>SP Status_Code>tag %parse_status_code :>SP Reason_Phrase :>CRLF; + Response = Status_Line (message_header* :>CRLF); + + # HTTP REQUEST + URI = (any+)>tag %parse_requesturl; + Request_URI = URI; + Request_Line = Method>tag %parse_method :>SP Request_URI :>SP HTTP_Version :>CRLF; + Request = Request_Line (message_header* :>CRLF); + + # HTTP MESSAGE + HTTP_message = (Response | Request)>1 @eoh message_body?>0; +}%%
\ No newline at end of file diff --git a/tinyHTTP/ragel/thttp_machine_utils.rl b/tinyHTTP/ragel/thttp_machine_utils.rl new file mode 100644 index 0000000..6af17a1 --- /dev/null +++ b/tinyHTTP/ragel/thttp_machine_utils.rl @@ -0,0 +1,110 @@ +/* +* Copyright (C) 2010-2015 Mamadou Diop. +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ +/**@file thttp_machine_utils.rl + * @brief Ragel file. + * + */ +%%{ + machine thttp_machine_utils; + + OCTET = "0x"[0-9A-Fa-f]+; + CHAR = 0x01..0x7f; + VCHAR = 0x21..0x7e; + ALPHA = 0x41..0x5a | 0x61..0x7a; + DIGIT = 0x30..0x39; + CTL = 0x00..0x1f | 0x7f; + HTAB = "\t"; + LF = "\n"; + CR = "\r"; + SP = " "; + DQUOTE = "\""; + BIT = "0" | "1"; + HEXDIG = DIGIT | "A"i | "B"i | "C"i | "D"i | "E"i | "F"i; + CRLF = CR LF; + WSP = SP | HTAB; + LWSP = ( WSP | ( CRLF WSP ) )*; + LWS = ( WSP* CRLF )? WSP+; + SWS = LWS?; + EQUAL = SWS "=" SWS; + LHEX = DIGIT | 0x61..0x66; + HCOLON = ( SP | HTAB )* ":" SWS; + separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | DQUOTE | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HTAB; + STAR = SWS "*" SWS; + SLASH = SWS "/" SWS; + LPAREN = SWS "(" SWS; + RPAREN = SWS ")" SWS; + COMMA = SWS "," SWS; + SEMI = SWS ";" SWS; + COLON = SWS ":" SWS; + LAQUOT = SWS "<"; + LDQUOT = SWS DQUOTE; + RAQUOT = ">" SWS; + RDQUOT = DQUOTE SWS; + UTF8_CONT = 0x80..0xbf; + + ##### FIXME: UTF8_NONASCII up to 2bytes will fail on Android + UTF8_NONASCII = ( 0x80..0xff ); + #UTF8_NONASCII = ( 0xc0..0xdf UTF8_CONT ) | ( 0xe0..0xef UTF8_CONT{2} ) | ( 0xf0..0xf7 UTF8_CONT{3} ) | ( 0xf8..0xfb UTF8_CONT{4} ) | ( 0xfc..0xfd UTF8_CONT{5} ); + ctext = 0x21..0x27 | 0x2a..0x5b | 0x5d..0x7e | UTF8_NONASCII | LWS; + qvalue = ( "0" ( "." DIGIT{,3} )? ) | ( "1" ( "." "0"{,3} )? ); + alphanum = ALPHA | DIGIT; + scheme = ALPHA ( ALPHA | DIGIT | "+" | "-" | "." )*; + token = ( alphanum | "-" | "." | "!" | "%" | "*" | "_" | "+" | "`" | "'" | "~" )+; + ietf_token = token; + x_token = "x-"i token; + iana_token = token; + token_nodot = ( alphanum | "-" | "!" | "%" | "*" | "_" | "+" | "`" | "'" | "~" )+; + word = ( alphanum | "-" | "." | "!" | "%" | "*" | "_" | "+" | "`" | "'" | "~" | "(" | ")" | "<" | ">" | ":" | "\\" | DQUOTE | "/" | "[" | "]" | "?" | "{" | "}" )+; + domainlabel = alphanum | ( alphanum ( alphanum | "-" )* alphanum ); + toplabel = ALPHA | ( ALPHA ( alphanum | "-" )* alphanum ); + hostname = ( domainlabel "." )* toplabel "."?; + IPv4address = DIGIT{1,3} "." DIGIT{1,3} "." DIGIT{1,3} "." DIGIT{1,3}; + hex4 = HEXDIG{1,4}; + hexseq = hex4 ( ":" hex4 )*; + hexpart = hexseq | ( hexseq "::" hexseq? ) | ( "::" hexseq? ); + IPv6address = hexpart ( ":" IPv4address )?; + IPv6reference = "[" IPv6address "]"; + host = hostname | IPv4address | IPv6reference; + qdtext = LWS | "!" | 0x23..0x5b | 0x5d..0x7e | UTF8_NONASCII; + quoted_pair = "\\" ( 0x00..0x09 | 0x0b..0x0c | 0x0e..0x7f ); + quoted_string = SWS DQUOTE ( qdtext | quoted_pair )* DQUOTE; + gen_value = token | host | quoted_string; + generic_param = token ( EQUAL gen_value )?; + accept_param = ( "q"i EQUAL qvalue ) | generic_param; + mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"; + unreserved = alphanum | mark; + escaped = "%" HEXDIG HEXDIG; + user_unreserved = "&" | "=" | "+" | "$" | "," | ";" | "?" | "/"; + user = ( unreserved | escaped | user_unreserved )+; + param_unreserved = "[" | "]" | "/" | ":" | "&" | "+" | "$"; + pct_encoded = "%" HEXDIG HEXDIG; + paramchar = param_unreserved | unreserved | pct_encoded; + pname = paramchar+; + pvalue = paramchar+; + parameter = ";" pname ( "=" pvalue )?; + reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","; + urlc = reserved | unreserved | escaped; + + extension_code = DIGIT{3}; + Status_Code = "100" | "101" | "200" | "201" | "202" | "203" | "204" | "205" | "206" | "300" | "301" | "302" | "303" | "304" | "305" | "307" | "400" | "401" | "402" | "403" | "404" | "405" | "406" | "407" | "408" | "409" | "410" | "411" | "412" | "413" | "414" | "415" | "416" | "417" | "500" | "501" | "502" | "503" | "504" | "505" | extension_code; + + extension_method = token; + Method = "OPTIONS"i | "GET"i | "HEAD"i | "POST"i | "PUT"i | "DELETE"i | "TRACE"i | "CONNECT"i | extension_method; +}%%
\ No newline at end of file diff --git a/tinyHTTP/ragel/thttp_machine_ws.rl b/tinyHTTP/ragel/thttp_machine_ws.rl new file mode 100644 index 0000000..4326e41 --- /dev/null +++ b/tinyHTTP/ragel/thttp_machine_ws.rl @@ -0,0 +1,46 @@ +/* +* Copyright (C) 2010-2015 Mamadou Diop. +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ +*/ + +%%{ + machine thttp_machine_ws; + + extension_param = token ( "=" ( token | quoted_string ) )?; + NZDIGIT = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"; + version = DIGIT | ( NZDIGIT DIGIT ) | ( "1" DIGIT DIGIT ) | ( "2" DIGIT DIGIT ); + base64_character = ALPHA | DIGIT | "+" | "/"; + base64_data = base64_character{4}; + base64_padding = ( base64_character{2} "==" ) | ( base64_character{3} "=" ); + base64_value_non_empty = ( base64_data+ base64_padding? ) | base64_padding; + Sec_WebSocket_Key = base64_value_non_empty; + registered_token = token; + extension_token = registered_token; + extension = extension_token ( ";" extension_param )*; + extension_list = extension ( COMMA extension )*; + Sec_WebSocket_Extensions = extension_list; + Sec_WebSocket_Protocol_Client = token ( COMMA token )*; + Sec_WebSocket_Version_Client = version; + Sec_WebSocket_Accept = base64_value_non_empty; + Sec_WebSocket_Protocol_Server = token; + Sec_WebSocket_Version_Server = version ( COMMA version )*; + Sec_WebSocket_Version = version ( COMMA version )*; + Sec_WebSocket_Protocol = token ( COMMA token )*; + +}%%
\ No newline at end of file diff --git a/tinyHTTP/ragel/thttp_parser_header.rl b/tinyHTTP/ragel/thttp_parser_header.rl new file mode 100644 index 0000000..c4445ed --- /dev/null +++ b/tinyHTTP/ragel/thttp_parser_header.rl @@ -0,0 +1,522 @@ +/* +* Copyright (C) 2010-2015 Mamadou Diop. +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ + +/**@file thttp_parser_header.c + * @brief HTTP headers parser. + */ +#include "tinyhttp/parsers/thttp_parser_header.h" + +//#include "tinyhttp/headers/thttp_header_Allow.h" +//#include "tinyhttp/headers/thttp_header_Allow_Events.h" +#include "tinyhttp/headers/thttp_header_Authorization.h" +//#include "tinyhttp/headers/thttp_header_Call_ID.h" +//#include "tinyhttp/headers/thttp_header_Contact.h" +//#include "tinyhttp/headers/thttp_header_CSeq.h" +#include "tinyhttp/headers/thttp_header_Dummy.h" +#include "tinyhttp/headers/thttp_header_ETag.h" +//#include "tinyhttp/headers/thttp_header_Expires.h" +//#include "tinyhttp/headers/thttp_header_From.h" +//#include "tinyhttp/headers/thttp_header_Max_Forwards.h" +//#include "tinyhttp/headers/thttp_header_Min_Expires.h" +//#include "tinyhttp/headers/thttp_header_Path.h" +//#include "tinyhttp/headers/thttp_header_P_Access_Network_Info.h" +//#include "tinyhttp/headers/thttp_header_P_Preferred_Identity.h" +//#include "tinyhttp/headers/thttp_header_Privacy.h" +//#include "tinyhttp/headers/thttp_header_Proxy_Authenticate.h" +//#include "tinyhttp/headers/thttp_header_Proxy_Authorization.h" +//#include "tinyhttp/headers/thttp_header_Record_Route.h" +//#include "tinyhttp/headers/thttp_header_Require.h" +//#include "tinyhttp/headers/thttp_header_Route.h" +#include "tinyhttp/headers/thttp_header_Sec_WebSocket_Accept.h" +#include "tinyhttp/headers/thttp_header_Sec_WebSocket_Key.h" +#include "tinyhttp/headers/thttp_header_Sec_WebSocket_Protocol.h" +#include "tinyhttp/headers/thttp_header_Sec_WebSocket_Version.h" +//#include "tinyhttp/headers/thttp_header_Service_Route.h" +//#include "tinyhttp/headers/thttp_header_Supported.h" +#include "tinyhttp/headers/thttp_header_Transfer_Encoding.h" +//#include "tinyhttp/headers/thttp_header_User_Agent.h" +//#include "tinyhttp/headers/thttp_header_Via.h" +#include "tinyhttp/headers/thttp_header_WWW_Authenticate.h" + +#include "tsk_debug.h" + +#undef ADD_HEADERS +#undef ADD_HEADER + +#define ADD_HEADERS(headers)\ + if(headers)\ + {\ + tsk_list_item_t *item;\ + tsk_list_foreach(item, headers)\ + {\ + thttp_header_t *hdr = tsk_object_ref(item->data);\ + tsk_list_push_back_data(message->headers, ((void**) &hdr));\ + }\ + \ + TSK_OBJECT_SAFE_FREE(headers);\ + } +#define ADD_HEADER(header)\ + if(header)\ + {\ + tsk_list_push_back_data(message->headers, ((void**) &header));\ + } + +/*********************************** +* Ragel state machine. +*/ +%%{ + machine thttp_machine_parser_headers; + + + # /*== Accept: ==*/ + action parse_header_Accept + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Accept NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Accept_Charset: ==*/ + action parse_header_Accept_Charset + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Accept_Charset NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Accept_Encoding: ==*/ + action parse_header_Accept_Encoding + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Accept_Encoding NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Accept_Language: ==*/ + action parse_header_Accept_Language + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Accept_Language NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Allow: ==*/ + action parse_header_Allow + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Allow NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Authorization: ==*/ + action parse_header_Authorization + { + thttp_header_Authorization_t *header = thttp_header_Authorization_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + } + + # /*== Cache_Control: ==*/ + action parse_header_Cache_Control + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Cache_Control NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Connection: ==*/ + action parse_header_Connection + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Connection NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Content_Encoding: ==*/ + action parse_header_Content_Encoding + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Content_Encoding NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Content_Language: ==*/ + action parse_header_Content_Language + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Content_Language NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Content_Length: ==*/ + action parse_header_Content_Length + { + if(!message->Content_Length){ + message->Content_Length = thttp_header_Content_Length_parse(state->tag_start, (state->tag_end-state->tag_start)); + } + else{ + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + //TSK_DEBUG_WARN("The message already have 'Content-Length' header."); + } + } + + # /*== Content_Location: ==*/ + action parse_header_Content_Location + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Content_Location NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Content_MD5: ==*/ + action parse_header_Content_MD5 + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Content_MD5 NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Content_Range: ==*/ + action parse_header_Content_Range + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Content_Range NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Content_Type: ==*/ + action parse_header_Content_Type + { + if(!message->Content_Type){ + message->Content_Type = thttp_header_Content_Type_parse(state->tag_start, (state->tag_end-state->tag_start)); + } + else{ + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + //TSK_DEBUG_WARN("The message already have 'Content-Type' header."); + } + } + + # /*== Date: ==*/ + action parse_header_Date + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Date NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== ETag: ==*/ + action parse_header_ETag + { + thttp_header_ETag_t *header = thttp_header_ETag_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Expires NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Expect: ==*/ + action parse_header_Expect + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Expect NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Expires: ==*/ + action parse_header_Expires + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Expires NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== From: ==*/ + action parse_header_From + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_From NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Host: ==*/ + action parse_header_Host + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Host NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== If_Match: ==*/ + action parse_header_If_Match + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_If_Match NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== If_Modified_Since: ==*/ + action parse_header_If_Modified_Since + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_If_Modified_Since NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== If_None_Match: ==*/ + action parse_header_If_None_Match + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_If_None_Match NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== If_Range: ==*/ + action parse_header_If_Range + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_If_Range NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== If_Unmodified_Since: ==*/ + action parse_header_If_Unmodified_Since + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_If_Unmodified_Since NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Last_Modified: ==*/ + action parse_header_Last_Modified + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Last_Modified NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Max_Forwards: ==*/ + action parse_header_Max_Forwards + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Max_Forwards NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Pragma: ==*/ + action parse_header_Pragma + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Pragma NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Proxy_Authenticate: ==*/ + action parse_header_Proxy_Authenticate + { + thttp_header_Proxy_Authenticate_t *header = thttp_header_Proxy_Authenticate_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + } + + # /*== Proxy_Authorization: ==*/ + action parse_header_Proxy_Authorization + { + thttp_header_Proxy_Authorization_t *header = thttp_header_Proxy_Authorization_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + } + + # /*== Range: ==*/ + action parse_header_Range + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Range NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Referer: ==*/ + action parse_header_Referer + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Referer NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /* == Sec-WebSocket-Accept == */ + action parse_header_Sec_WebSocket_Accept + { + thttp_header_Sec_WebSocket_Accept_t* header = thttp_header_Sec_WebSocket_Accept_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + } + + # /* == Sec-WebSocket-Key == */ + action parse_header_Sec_WebSocket_Key + { + thttp_header_Sec_WebSocket_Key_t* header = thttp_header_Sec_WebSocket_Key_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + } + + # /* == Sec-WebSocket-Protocol == */ + action parse_header_Sec_WebSocket_Protocol + { + thttp_header_Sec_WebSocket_Protocol_t* header = thttp_header_Sec_WebSocket_Protocol_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + } + + + # /* == Sec-WebSocket-Version == */ + action parse_header_Sec_WebSocket_Version + { + thttp_header_Sec_WebSocket_Version_t* header = thttp_header_Sec_WebSocket_Version_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + } + + # /*== TE: ==*/ + action parse_header_TE + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_TE NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Trailer: ==*/ + action parse_header_Trailer + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Trailer NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Transfer_Encoding: ==*/ + action parse_header_Transfer_Encoding + { + thttp_header_Transfer_Encoding_t *header = thttp_header_Transfer_Encoding_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Trailer NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Upgrade: ==*/ + action parse_header_Upgrade + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Upgrade NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== User_Agent: ==*/ + action parse_header_User_Agent + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_User_Agent NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Via: ==*/ + action parse_header_Via + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Via NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== Warning: ==*/ + action parse_header_Warning + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_Warning NOT IMPLEMENTED. Will be added as Dummy header."); + } + + # /*== WWW-Authenticate: ==*/ + action parse_header_WWW_Authenticate + { + thttp_header_WWW_Authenticate_t *header = thttp_header_WWW_Authenticate_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + } + + # /*== extension_header: ==*/ + action parse_header_extension_header + { + thttp_header_Dummy_t *header = thttp_header_Dummy_parse(state->tag_start, (state->tag_end-state->tag_start)); + ADD_HEADER(header); + + //TSK_DEBUG_WARN("parse_header_extension_header NOT IMPLEMENTED. Will be added as Dummy header."); + } + + + # Includes + include thttp_machine_utils "./ragel/thttp_machine_utils.rl"; + include thttp_machine_header "./ragel/thttp_machine_header.rl"; + + # Entry point + main := HEADER; +}%% + +int thttp_header_parse(tsk_ragel_state_t *state, thttp_message_t *message) +{ + int cs = 0; + const char *p = state->tag_start; + const char *pe = state->tag_end; + const char *eof = pe; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + %%write data; + (void)(eof); + (void)(thttp_machine_parser_headers_first_final); + (void)(thttp_machine_parser_headers_error); + (void)(thttp_machine_parser_headers_en_main); + %%write init; + %%write exec; + TSK_RAGEL_DISABLE_WARNINGS_END() + + return ( cs >= %%{ write first_final; }%% ) ? 0 : -1; +} diff --git a/tinyHTTP/ragel/thttp_parser_header_Authorization.rl b/tinyHTTP/ragel/thttp_parser_header_Authorization.rl new file mode 100644 index 0000000..b5d6319 --- /dev/null +++ b/tinyHTTP/ragel/thttp_parser_header_Authorization.rl @@ -0,0 +1,296 @@ +/* +* Copyright (C) 2010-2015 Mamadou Diop. +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ + +/**@file thttp_header_Authorization.c + * @brief HTTP Authorization header. + */ +#include "tinyhttp/headers/thttp_header_Authorization.h" + +#include "tinyhttp/parsers/thttp_parser_url.h" + +#include "tsk_debug.h" +#include "tsk_memory.h" +#include "tsk_time.h" + +#include <string.h> + +/*********************************** +* Ragel state machine. +*/ +%%{ + machine thttp_machine_parser_header_Authorization; + + # Includes + include thttp_machine_utils "./ragel/thttp_machine_utils.rl"; + + action tag{ + tag_start = p; + } + + action is_digest{ + hdr_Authorization->scheme = tsk_strdup("Digest"); + } + + action is_basic{ + hdr_Authorization->scheme = tsk_strdup("Basic"); + } + + action is_auth{ + THTTP_HEADER(hdr_Authorization)->type = thttp_htype_Authorization; + } + + action is_proxy{ + THTTP_HEADER(hdr_Authorization)->type = thttp_htype_Proxy_Authorization; + } + + action parse_username{ + TSK_PARSER_SET_STRING(hdr_Authorization->username); + tsk_strunquote(&hdr_Authorization->username); + } + + action parse_realm{ + TSK_PARSER_SET_STRING(hdr_Authorization->realm); + tsk_strunquote(&hdr_Authorization->realm); + } + + action parse_nonce{ + TSK_PARSER_SET_STRING(hdr_Authorization->nonce); + tsk_strunquote(&hdr_Authorization->nonce); + } + + action parse_uri{ + TSK_PARSER_SET_STRING(hdr_Authorization->uri); + } + + action parse_response{ + TSK_PARSER_SET_STRING(hdr_Authorization->response); + tsk_strunquote(&hdr_Authorization->response); + } + + action parse_algorithm{ + TSK_PARSER_SET_STRING(hdr_Authorization->algorithm); + } + + action parse_cnonce{ + TSK_PARSER_SET_STRING(hdr_Authorization->cnonce); + tsk_strunquote(&hdr_Authorization->cnonce); + } + + action parse_opaque{ + TSK_PARSER_SET_STRING(hdr_Authorization->opaque); + tsk_strunquote(&hdr_Authorization->opaque); + } + + action parse_qop{ + TSK_PARSER_SET_STRING(hdr_Authorization->qop); + //tsk_strunquote(&hdr_Authorization->qop); + } + + action parse_nc{ + TSK_PARSER_SET_STRING(hdr_Authorization->nc); + } + + action parse_param{ + TSK_PARSER_ADD_PARAM(THTTP_HEADER_PARAMS(hdr_Authorization)); + } + + action eob{ + } + + #FIXME: Only Digest (MD5, AKAv1-MD5 and AKAv2-MD5) is supported + qop_value = "auth" | "auth-int" | token; + other_response = (any+); + auth_param = generic_param>tag %parse_param; + + username = "username"i EQUAL quoted_string>tag %parse_username; + realm = "realm"i EQUAL quoted_string>tag %parse_realm; + nonce = "nonce"i EQUAL quoted_string>tag %parse_nonce; + digest_uri = "uri"i EQUAL LDQUOT <: (any*)>tag %parse_uri :> RDQUOT; + #dresponse = "response"i EQUAL LDQUOT <: (LHEX{32})>tag %parse_response :> RDQUOT; + dresponse = "response"i EQUAL quoted_string>tag %parse_response; + algorithm = "algorithm"i EQUAL <:token>tag %parse_algorithm; + cnonce = "cnonce"i EQUAL quoted_string>tag %parse_cnonce; + opaque = "opaque"i EQUAL quoted_string>tag %parse_opaque; + message_qop = "qop"i EQUAL qop_value>tag %parse_qop; + nonce_count = "nc"i EQUAL (LHEX{8})>tag %parse_nc; + + dig_resp = (username | realm | nonce | digest_uri | dresponse | algorithm | cnonce | opaque | message_qop | nonce_count)@1 | auth_param@0; + digest_response = dig_resp ( COMMA <:dig_resp )*; + credentials = ( ("Digest"i%is_digest | "Basic"i%is_basic) LWS digest_response ) | other_response; + Authorization = ("Authorization"i>is_auth | "Proxy-Authorization"i>is_proxy) HCOLON credentials; + + # Entry point + main := Authorization :>CRLF @eob; + +}%% + +thttp_header_Authorization_t* thttp_header_authorization_create() +{ + return tsk_object_new(thttp_header_Authorization_def_t); +} + +int thttp_header_Authorization_tostring(const thttp_header_t* header, tsk_buffer_t* output) +{ + if(header) + { + const thttp_header_Authorization_t *Authorization = (const thttp_header_Authorization_t*)header; + if(Authorization && Authorization->scheme) + { + if(tsk_striequals(Authorization->scheme, "Basic")){ + return tsk_buffer_append_2(output, "%s %s", + Authorization->scheme, Authorization->response); + } + else{ + return tsk_buffer_append_2(output, "%s %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + Authorization->scheme, + + Authorization->username ? "username=\"" : "", + Authorization->username ? Authorization->username : "", + Authorization->username ? "\"" : "", + + Authorization->realm ? ",realm=\"" : "", + Authorization->realm ? Authorization->realm : "", + Authorization->realm ? "\"" : "", + + Authorization->nonce ? ",nonce=\"" : "", + Authorization->nonce ? Authorization->nonce : "", + Authorization->nonce ? "\"" : "", + + Authorization->uri ? ",uri=\"" : "", + Authorization->uri ? Authorization->uri : "", + Authorization->uri ? "\"" : "", + + Authorization->response ? ",response=\"" : "", + Authorization->response ? Authorization->response : "", + Authorization->response ? "\"" : "", + + Authorization->algorithm ? ",algorithm=" : "", + Authorization->algorithm ? Authorization->algorithm : "", + + Authorization->cnonce ? ",cnonce=\"" : "", + Authorization->cnonce ? Authorization->cnonce : "", + Authorization->cnonce ? "\"" : "", + + Authorization->opaque ? ",opaque=\"" : "", + Authorization->opaque ? Authorization->opaque : "", + Authorization->opaque ? "\"" : "", + + Authorization->qop ? ",qop=" : "", + Authorization->qop ? Authorization->qop : "", + + Authorization->nc ? ",nc=" : "", + Authorization->nc ? Authorization->nc : "" + ); + } + } + } + return -1; +} + +/**@ingroup thttp_header_group +*/ +thttp_header_Authorization_t *thttp_header_Authorization_parse(const char *data, tsk_size_t size) +{ + int cs = 0; + const char *p = data; + const char *pe = p + size; + const char *eof = pe; + thttp_header_Authorization_t *hdr_Authorization = thttp_header_authorization_create(); + + const char *tag_start = tsk_null; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + %%write data; + (void)(eof); + (void)(thttp_machine_parser_header_Authorization_first_final); + (void)(thttp_machine_parser_header_Authorization_error); + (void)(thttp_machine_parser_header_Authorization_en_main); + + %%write init; + %%write exec; + TSK_RAGEL_DISABLE_WARNINGS_END() + + if( cs < %%{ write first_final; }%% ){ + TSK_DEBUG_ERROR("Failed to parse Authorization header."); + TSK_OBJECT_SAFE_FREE(hdr_Authorization); + } + + return hdr_Authorization; +} + +/**@ingroup thttp_header_group +*/ +thttp_header_Proxy_Authorization_t *thttp_header_Proxy_Authorization_parse(const char *data, tsk_size_t size) +{ + return thttp_header_Authorization_parse(data, size); +} + + + +//======================================================== +// Authorization header object definition +// + +static tsk_object_t* thttp_header_Authorization_ctor(tsk_object_t *self, va_list * app) +{ + thttp_header_Authorization_t *Authorization = self; + if(Authorization){ + THTTP_HEADER(Authorization)->type = thttp_htype_Authorization; + THTTP_HEADER(Authorization)->tostring = thttp_header_Authorization_tostring; + } + else{ + TSK_DEBUG_ERROR("Failed to create new Authorization header."); + } + return self; +} + +static tsk_object_t* thttp_header_Authorization_dtor(tsk_object_t *self) +{ + thttp_header_Authorization_t *Authorization = self; + if(Authorization){ + TSK_FREE(Authorization->scheme); + TSK_FREE(Authorization->username); + TSK_FREE(Authorization->realm); + TSK_FREE(Authorization->nonce); + TSK_FREE(Authorization->uri); + TSK_FREE(Authorization->response); + TSK_FREE(Authorization->algorithm); + TSK_FREE(Authorization->cnonce); + TSK_FREE(Authorization->opaque); + TSK_FREE(Authorization->qop); + TSK_FREE(Authorization->nc); + + TSK_OBJECT_SAFE_FREE(THTTP_HEADER_PARAMS(Authorization)); + } + else{ + TSK_DEBUG_ERROR("Null Authorization header."); + } + + return self; +} + +static const tsk_object_def_t thttp_header_Authorization_def_s = +{ + sizeof(thttp_header_Authorization_t), + thttp_header_Authorization_ctor, + thttp_header_Authorization_dtor, + tsk_null +}; +const tsk_object_def_t *thttp_header_Authorization_def_t = &thttp_header_Authorization_def_s; diff --git a/tinyHTTP/ragel/thttp_parser_header_Content_Length.rl b/tinyHTTP/ragel/thttp_parser_header_Content_Length.rl new file mode 100644 index 0000000..1bb5f28 --- /dev/null +++ b/tinyHTTP/ragel/thttp_parser_header_Content_Length.rl @@ -0,0 +1,145 @@ +/* +* Copyright (C) 2010-2015 Mamadou Diop. +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ +/**@file thttp_header_Content_Length.c + * @brief HTTP Content-Length header. + * + */ +#include "tinyhttp/headers/thttp_header_Content_Length.h" + +#include "tsk_debug.h" +#include "tsk_memory.h" + +/*********************************** +* Ragel state machine. +*/ +%%{ + machine thttp_machine_parser_header_Content_Length; + + # Includes + include thttp_machine_utils "./ragel/thttp_machine_utils.rl"; + + action tag{ + tag_start = p; + } + + action parse_content_length{ + TSK_PARSER_SET_INTEGER(hdr_clength->length); + } + + action eob{ + } + + Content_Length = "Content-Length"i HCOLON (DIGIT+)>tag %parse_content_length; + + # Entry point + main := Content_Length :>CRLF @eob; + +}%% + +thttp_header_Content_Length_t* thttp_header_content_length_create(uint32_t length) +{ + return tsk_object_new(THTTP_HEADER_CONTENT_LENGTH_VA_ARGS(length)); +} + +int thttp_header_Content_Length_tostring(const thttp_header_t* header, tsk_buffer_t* output) +{ + if(header){ + const thttp_header_Content_Length_t *Content_Length = (const thttp_header_Content_Length_t*)header; + return tsk_buffer_append_2(output, "%d", Content_Length->length); + } + + return -1; +} + +/**@ingroup thttp_header_group +*/ +thttp_header_Content_Length_t *thttp_header_Content_Length_parse(const char *data, tsk_size_t size) +{ + int cs = 0; + const char *p = data; + const char *pe = p + size; + const char *eof = pe; + thttp_header_Content_Length_t *hdr_clength = thttp_header_content_length_create(0); + + const char *tag_start = tsk_null; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + %%write data; + (void)(eof); + (void)(thttp_machine_parser_header_Content_Length_first_final); + (void)(thttp_machine_parser_header_Content_Length_error); + (void)(thttp_machine_parser_header_Content_Length_en_main); + %%write init; + %%write exec; + TSK_RAGEL_DISABLE_WARNINGS_END() + + if( cs < %%{ write first_final; }%% ){ + TSK_OBJECT_SAFE_FREE(hdr_clength); + } + + return hdr_clength; +} + + + + + + + +//======================================================== +// Content_Length header object definition +// + +static tsk_object_t* thttp_header_Content_Length_ctor(tsk_object_t *self, va_list * app) +{ + thttp_header_Content_Length_t *Content_Length = self; + if(Content_Length){ + Content_Length->length = va_arg(*app, uint32_t); + + THTTP_HEADER(Content_Length)->type = thttp_htype_Content_Length; + THTTP_HEADER(Content_Length)->tostring = thttp_header_Content_Length_tostring; + } + else{ + TSK_DEBUG_ERROR("Failed to create new Content_Length header."); + } + return self; +} + +static tsk_object_t* thttp_header_Content_Length_dtor(tsk_object_t *self) +{ + thttp_header_Content_Length_t *Content_Length = self; + if(Content_Length){ + TSK_OBJECT_SAFE_FREE(THTTP_HEADER_PARAMS(Content_Length)); + } + else{ + TSK_DEBUG_ERROR("Null Content_Length header."); + } + + return self; +} + +static const tsk_object_def_t thttp_header_Content_Length_def_s = +{ + sizeof(thttp_header_Content_Length_t), + thttp_header_Content_Length_ctor, + thttp_header_Content_Length_dtor, + tsk_null +}; +const tsk_object_def_t *thttp_header_Content_Length_def_t = &thttp_header_Content_Length_def_s; diff --git a/tinyHTTP/ragel/thttp_parser_header_Content_Type.rl b/tinyHTTP/ragel/thttp_parser_header_Content_Type.rl new file mode 100644 index 0000000..090b45e --- /dev/null +++ b/tinyHTTP/ragel/thttp_parser_header_Content_Type.rl @@ -0,0 +1,175 @@ +/* +* Copyright (C) 2010-2015 Mamadou Diop. +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ + +/**@file thttp_header_Content_Type.c + * @brief HTTP Content-Type header. + */ +#include "tinyhttp/headers/thttp_header_Content_Type.h" + +#include "tsk_debug.h" +#include "tsk_memory.h" + +#include <string.h> + +/*********************************** +* Ragel state machine. +*/ +%%{ + machine thttp_machine_parser_header_Content_Type; + + # Includes + include thttp_machine_utils "./ragel/thttp_machine_utils.rl"; + + action tag{ + tag_start = p; + } + + action parse_content_type{ + TSK_PARSER_SET_STRING(hdr_ctype->type); + } + + action parse_param{ + TSK_PARSER_ADD_PARAM(THTTP_HEADER_PARAMS(hdr_ctype)); + } + + action eob{ + } + + extension_token = ietf_token | x_token; + + m_attribute = token; + m_value = token | quoted_string; + m_parameter = (m_attribute EQUAL m_value)>tag %parse_param; + + discrete_type = "text"i | "image"i | "audio"i | "video"i | "application"i | extension_token; + composite_type = "message"i | "multipart"i | extension_token; + m_type = discrete_type | composite_type; + m_subtype = extension_token | iana_token; + + media_type = (m_type SLASH m_subtype)@1 >tag %parse_content_type ((SEMI m_parameter)*)@0; + + Content_Type = ( "Content-Type"i ) HCOLON media_type; + + # Entry point + main := Content_Type :>CRLF @eob; + +}%% + +thttp_header_Content_Type_t* thttp_header_content_type_create(const char* type) +{ + return tsk_object_new(THTTP_HEADER_CONTENT_TYPE_VA_ARGS(type)); +} + +thttp_header_Content_Type_t* thttp_header_content_type_create_null() +{ + return thttp_header_content_type_create(tsk_null); +} + +int thttp_header_Content_Type_tostring(const thttp_header_t* header, tsk_buffer_t* output) +{ + if(header){ + const thttp_header_Content_Type_t *Content_Type = (const thttp_header_Content_Type_t*)header; + return tsk_buffer_append(output, Content_Type->type, tsk_strlen(Content_Type->type)); + } + + return -1; +} + +/**@ingroup thttp_header_group +*/ +thttp_header_Content_Type_t *thttp_header_Content_Type_parse(const char *data, tsk_size_t size) +{ + int cs = 0; + const char *p = data; + const char *pe = p + size; + const char *eof = pe; + thttp_header_Content_Type_t *hdr_ctype = thttp_header_content_type_create_null(); + + const char *tag_start = tsk_null; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + %%write data; + (void)(eof); + (void)(thttp_machine_parser_header_Content_Type_first_final); + (void)(thttp_machine_parser_header_Content_Type_error); + (void)(thttp_machine_parser_header_Content_Type_en_main); + %%write init; + %%write exec; + TSK_RAGEL_DISABLE_WARNINGS_END() + + if( cs < %%{ write first_final; }%% ){ + TSK_DEBUG_ERROR("Failed to parse Content-Type header."); + TSK_OBJECT_SAFE_FREE(hdr_ctype); + } + + return hdr_ctype; +} + + + + + + + +//======================================================== +// Content_Type header object definition +// + +/**@ingroup thttp_header_Content_Type_group +*/ +static tsk_object_t* thttp_header_Content_Type_ctor(tsk_object_t *self, va_list * app) +{ + thttp_header_Content_Type_t *Content_Type = self; + if(Content_Type){ + THTTP_HEADER(Content_Type)->type = thttp_htype_Content_Type; + THTTP_HEADER(Content_Type)->tostring = thttp_header_Content_Type_tostring; + + Content_Type->type = tsk_strdup( va_arg(*app, const char*) ); + } + else{ + TSK_DEBUG_ERROR("Failed to create new Content_Type header."); + } + return self; +} + +/**@ingroup thttp_header_Content_Type_group +*/ +static tsk_object_t* thttp_header_Content_Type_dtor(tsk_object_t *self) +{ + thttp_header_Content_Type_t *Content_Type = self; + if(Content_Type){ + TSK_FREE(Content_Type->type); + TSK_OBJECT_SAFE_FREE(THTTP_HEADER_PARAMS(Content_Type)); + } + else{ + TSK_DEBUG_ERROR("Null Content_Type header."); + } + + return self; +} + +static const tsk_object_def_t thttp_header_Content_Type_def_s = +{ + sizeof(thttp_header_Content_Type_t), + thttp_header_Content_Type_ctor, + thttp_header_Content_Type_dtor, + tsk_null +}; +const tsk_object_def_t *thttp_header_Content_Type_def_t = &thttp_header_Content_Type_def_s; diff --git a/tinyHTTP/ragel/thttp_parser_header_Dummy.rl b/tinyHTTP/ragel/thttp_parser_header_Dummy.rl new file mode 100644 index 0000000..9e630db --- /dev/null +++ b/tinyHTTP/ragel/thttp_parser_header_Dummy.rl @@ -0,0 +1,167 @@ +/* +* Copyright (C) 2010-2015 Mamadou Diop. +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ + +/**@file thttp_header_Dummy.c + * @brief HTTP 'Dummy' header. + * + */ +#include "tinyhttp/headers/thttp_header_Dummy.h" + +#include "tinyhttp/parsers/thttp_parser_url.h" + +#include "tsk_debug.h" +#include "tsk_memory.h" + +#include <string.h> + +/*********************************** +* Ragel state machine. +*/ +%%{ + machine thttp_machine_parser_header_Dummy; + + # Includes + include thttp_machine_utils "./ragel/thttp_machine_utils.rl"; + + action tag{ + tag_start = p; + } + + action parse_name{ + TSK_PARSER_SET_STRING(hdr_Dummy->name); + } + + action parse_value{ + TSK_PARSER_SET_STRING(hdr_Dummy->value); + } + + action eob{ + } + + Dummy = token>tag %parse_name SP* HCOLON SP*<: any*>tag %parse_value; + + # Entry point + main := Dummy :>CRLF @eob; + +}%% + +thttp_header_Dummy_t* thttp_header_dummy_create(const char* name, const char* value) +{ + return tsk_object_new(THTTP_HEADER_DUMMY_VA_ARGS(name, value)); +} + +thttp_header_Dummy_t* thttp_header_dummy_create_null() +{ + return thttp_header_dummy_create(tsk_null, tsk_null); +} + + +int thttp_header_Dummy_tostring(const thttp_header_t* header, tsk_buffer_t* output) +{ + if(header){ + const thttp_header_Dummy_t *Dummy = (const thttp_header_Dummy_t*)header; + if(Dummy->value){ + return tsk_buffer_append(output, Dummy->value, tsk_strlen(Dummy->value)); + } + return 0; + } + + return -1; +} + +/**@ingroup thttp_header_group +*/ +thttp_header_Dummy_t *thttp_header_Dummy_parse(const char *data, tsk_size_t size) +{ + int cs = 0; + const char *p = data; + const char *pe = p + size; + const char *eof = pe; + thttp_header_Dummy_t *hdr_Dummy = thttp_header_dummy_create_null(); + + const char *tag_start = tsk_null; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + %%write data; + (void)(eof); + (void)(thttp_machine_parser_header_Dummy_first_final); + (void)(thttp_machine_parser_header_Dummy_error); + (void)(thttp_machine_parser_header_Dummy_en_main); + %%write init; + %%write exec; + TSK_RAGEL_DISABLE_WARNINGS_END() + + if( cs < %%{ write first_final; }%% ){ + TSK_OBJECT_SAFE_FREE(hdr_Dummy); + } + + return hdr_Dummy; +} + + + + + + + +//======================================================== +// Dummy header object definition +// + +static tsk_object_t* thttp_header_Dummy_ctor(tsk_object_t *self, va_list * app) +{ + thttp_header_Dummy_t *Dummy = self; + if(Dummy){ + THTTP_HEADER(Dummy)->type = thttp_htype_Dummy; + THTTP_HEADER(Dummy)->tostring = thttp_header_Dummy_tostring; + + Dummy->name = tsk_strdup(va_arg(*app, const char*)); + Dummy->value = tsk_strdup(va_arg(*app, const char*)); + } + else{ + TSK_DEBUG_ERROR("Failed to create new Dummy header."); + } + return self; +} + +static tsk_object_t* thttp_header_Dummy_dtor(tsk_object_t *self) +{ + thttp_header_Dummy_t *Dummy = self; + if(Dummy){ + TSK_FREE(Dummy->name); + TSK_FREE(Dummy->value); + + TSK_OBJECT_SAFE_FREE(THTTP_HEADER_PARAMS(Dummy)); + } + else{ + TSK_DEBUG_ERROR("Null Dummy header."); + } + + return self; +} + +static const tsk_object_def_t thttp_header_Dummy_def_s = +{ + sizeof(thttp_header_Dummy_t), + thttp_header_Dummy_ctor, + thttp_header_Dummy_dtor, + tsk_null +}; +const tsk_object_def_t *thttp_header_Dummy_def_t = &thttp_header_Dummy_def_s; diff --git a/tinyHTTP/ragel/thttp_parser_header_ETag.rl b/tinyHTTP/ragel/thttp_parser_header_ETag.rl new file mode 100644 index 0000000..8c346dc --- /dev/null +++ b/tinyHTTP/ragel/thttp_parser_header_ETag.rl @@ -0,0 +1,173 @@ +/* +* Copyright (C) 2010-2015 Mamadou Diop. +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ + +/**@file thttp_header_ETag.c + * @brief HTTP 'Etag' header. + */ +#include "tinyhttp/headers/thttp_header_ETag.h" + +#include "tinyhttp/parsers/thttp_parser_url.h" + +#include "tsk_debug.h" +#include "tsk_memory.h" + +#include <string.h> + +/*********************************** +* Ragel state machine. +*/ +%%{ + machine thttp_machine_parser_header_ETag; + alphtype unsigned char; + + # Includes + include thttp_machine_utils "./ragel/thttp_machine_utils.rl"; + + action tag{ + tag_start = p; + } + + action is_weak{ + hdr_ETag->isWeak = tsk_true; + } + + action parse_entity_tag{ + TSK_PARSER_SET_STRING(hdr_ETag->value); + tsk_strunquote(&hdr_ETag->value); + } + + action eob{ + } + + weak = "W/"i %is_weak; + opaque_tag = quoted_string>tag %parse_entity_tag; + entity_tag = weak? <: opaque_tag; + ETag = "ETag"i HCOLON entity_tag; + + # Entry point + main := ETag :>CRLF @eob; + +}%% + +thttp_header_ETag_t* thttp_header_etag_create(const char* value) +{ + return tsk_object_new(THTTP_HEADER_ETAG_VA_ARGS(value)); +} + +thttp_header_ETag_t* thttp_header_etag_create_null() +{ + return thttp_header_etag_create(tsk_null); +} + + +int thttp_header_ETag_tostring(const thttp_header_t* header, tsk_buffer_t* output) +{ + if(header){ + const thttp_header_ETag_t *ETag = (const thttp_header_ETag_t*)header; + if(ETag->value){ + return tsk_buffer_append_2(output, "%s\"%s\"", + ETag->isWeak ? "W/" : "", + ETag->value); + } + return 0; + } + + return -1; +} + +/**@ingroup thttp_header_group +*/ +thttp_header_ETag_t *thttp_header_ETag_parse(const char *data, tsk_size_t size) +{ + int cs = 0; + const char *p = data; + const char *pe = p + size; + const char *eof = pe; + thttp_header_ETag_t *hdr_ETag = thttp_header_etag_create_null(); + + const char *tag_start = tsk_null; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + %%write data; + (void)(eof); + (void)(thttp_machine_parser_header_ETag_first_final); + (void)(thttp_machine_parser_header_ETag_error); + (void)(thttp_machine_parser_header_ETag_en_main); + %%write init; + %%write exec; + TSK_RAGEL_DISABLE_WARNINGS_END() + + if( cs < %%{ write first_final; }%% ){ + TSK_DEBUG_ERROR("Failed to parse ETag header."); + TSK_OBJECT_SAFE_FREE(hdr_ETag); + } + + return hdr_ETag; +} + + + + + + + +//======================================================== +// ETag header object definition +// + +static tsk_object_t* thttp_header_ETag_ctor(tsk_object_t *self, va_list * app) +{ + thttp_header_ETag_t *ETag = self; + if(ETag){ + THTTP_HEADER(ETag)->type = thttp_htype_ETag; + THTTP_HEADER(ETag)->tostring = thttp_header_ETag_tostring; + + ETag->value = tsk_strdup(va_arg(*app, const char*)); + } + else{ + TSK_DEBUG_ERROR("Failed to create new ETag header."); + } + return self; +} + +static tsk_object_t* thttp_header_ETag_dtor(tsk_object_t *self) +{ + thttp_header_ETag_t *ETag = self; + if(ETag) + { + TSK_FREE(ETag->value); + + TSK_OBJECT_SAFE_FREE(THTTP_HEADER_PARAMS(ETag)); + } + else{ + TSK_DEBUG_ERROR("Null ETag header."); + } + + return self; +} + +static const tsk_object_def_t thttp_header_ETag_def_s = +{ + sizeof(thttp_header_ETag_t), + thttp_header_ETag_ctor, + thttp_header_ETag_dtor, + tsk_null +}; +const tsk_object_def_t *thttp_header_ETag_def_t = &thttp_header_ETag_def_s; diff --git a/tinyHTTP/ragel/thttp_parser_header_Sec_WebSocket_Accept.rl b/tinyHTTP/ragel/thttp_parser_header_Sec_WebSocket_Accept.rl new file mode 100644 index 0000000..b650d8d --- /dev/null +++ b/tinyHTTP/ragel/thttp_parser_header_Sec_WebSocket_Accept.rl @@ -0,0 +1,146 @@ +/* +* Copyright (C) 2010-2015 Mamadou Diop. +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ + +/**@file thttp_header_Sec_WebSocket_Accept.c + * @brief WebSocket "Sec-WebSocket-Accept" header. + */ +#include "tinyhttp/headers/thttp_header_Sec_WebSocket_Accept.h" + +#include "tsk_debug.h" + +#include <string.h> + +%%{ + machine thttp_machine_parser_header_Sec_WebSocket_Accept; + + # Includes + include thttp_machine_utils "./ragel/thttp_machine_utils.rl"; + include thttp_machine_ws "./ragel/thttp_machine_ws.rl"; + + action tag { tag_start = p; } + action eob { } + + action parse_key{ + TSK_PARSER_SET_STRING(hdr_Sec_WebSocket_Accept->value); + } + + # Entry point + main := "Sec-WebSocket-Accept"i SP* HCOLON SP*<: Sec_WebSocket_Accept>tag %parse_key :>CRLF @eob; +}%% + +thttp_header_Sec_WebSocket_Accept_t* thttp_header_Sec_WebSocket_Accept_create(const char* value) +{ + return tsk_object_new(THTTP_HEADER_SEC_WEBSOCKET_ACCEPT_VA_ARGS(value)); +} + +thttp_header_Sec_WebSocket_Accept_t* thttp_header_Sec_WebSocket_Accept_create_null() +{ + return thttp_header_Sec_WebSocket_Accept_create(tsk_null); +} + + +int thttp_header_Sec_WebSocket_Accept_tostring(const thttp_header_t* header, tsk_buffer_t* output) +{ + if(header){ + const thttp_header_Sec_WebSocket_Accept_t *Sec_WebSocket_Accept = (const thttp_header_Sec_WebSocket_Accept_t*)header; + if(Sec_WebSocket_Accept->value){ + return tsk_buffer_append(output, Sec_WebSocket_Accept->value, tsk_strlen(Sec_WebSocket_Accept->value)); + } + return 0; + } + + return -1; +} + +thttp_header_Sec_WebSocket_Accept_t *thttp_header_Sec_WebSocket_Accept_parse(const char *data, tsk_size_t size) +{ + int cs = 0; + const char *p = data; + const char *pe = p + size; + const char *eof = pe; + thttp_header_Sec_WebSocket_Accept_t *hdr_Sec_WebSocket_Accept = thttp_header_Sec_WebSocket_Accept_create_null(); + + const char *tag_start = tsk_null; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + %%write data; + (void)(eof); + (void)(thttp_machine_parser_header_Sec_WebSocket_Accept_first_final); + (void)(thttp_machine_parser_header_Sec_WebSocket_Accept_error); + (void)(thttp_machine_parser_header_Sec_WebSocket_Accept_en_main); + %%write init; + %%write exec; + TSK_RAGEL_DISABLE_WARNINGS_END() + + if( cs < %%{ write first_final; }%% ){ + TSK_DEBUG_ERROR("Failed to parse Sec-WebSocket-Accept header."); + TSK_OBJECT_SAFE_FREE(hdr_Sec_WebSocket_Accept); + } + + return hdr_Sec_WebSocket_Accept; +} + + + + + + + +//======================================================== +// Sec_WebSocket_Accept header object definition +// + +static tsk_object_t* thttp_header_Sec_WebSocket_Accept_ctor(tsk_object_t *self, va_list * app) +{ + thttp_header_Sec_WebSocket_Accept_t *Sec_WebSocket_Accept = self; + if(Sec_WebSocket_Accept){ + THTTP_HEADER(Sec_WebSocket_Accept)->type = thttp_htype_Sec_WebSocket_Accept; + THTTP_HEADER(Sec_WebSocket_Accept)->tostring = thttp_header_Sec_WebSocket_Accept_tostring; + + Sec_WebSocket_Accept->value = tsk_strdup(va_arg(*app, const char*)); + } + else{ + TSK_DEBUG_ERROR("Failed to create new Sec-WebSocket-Accept header."); + } + return self; +} + +static tsk_object_t* thttp_header_Sec_WebSocket_Accept_dtor(tsk_object_t *self) +{ + thttp_header_Sec_WebSocket_Accept_t *Sec_WebSocket_Accept = self; + if(Sec_WebSocket_Accept){ + TSK_FREE(Sec_WebSocket_Accept->value); + TSK_OBJECT_SAFE_FREE(THTTP_HEADER_PARAMS(Sec_WebSocket_Accept)); + } + else{ + TSK_DEBUG_ERROR("Null Sec_WebSocket_Accept header."); + } + + return self; +} + +static const tsk_object_def_t thttp_header_Sec_WebSocket_Accept_def_s = +{ + sizeof(thttp_header_Sec_WebSocket_Accept_t), + thttp_header_Sec_WebSocket_Accept_ctor, + thttp_header_Sec_WebSocket_Accept_dtor, + tsk_null +}; +const tsk_object_def_t *thttp_header_Sec_WebSocket_Accept_def_t = &thttp_header_Sec_WebSocket_Accept_def_s; diff --git a/tinyHTTP/ragel/thttp_parser_header_Sec_WebSocket_Key.rl b/tinyHTTP/ragel/thttp_parser_header_Sec_WebSocket_Key.rl new file mode 100644 index 0000000..31ce4d7 --- /dev/null +++ b/tinyHTTP/ragel/thttp_parser_header_Sec_WebSocket_Key.rl @@ -0,0 +1,146 @@ +/* +* Copyright (C) 2010-2015 Mamadou Diop. +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ + +/**@file thttp_header_Sec_WebSocket_Key.c + * @brief WebSocket "Sec-WebSocket-Key" header. + */ +#include "tinyhttp/headers/thttp_header_Sec_WebSocket_Key.h" + +#include "tsk_debug.h" + +#include <string.h> + +%%{ + machine thttp_machine_parser_header_Sec_WebSocket_Key; + + # Includes + include thttp_machine_utils "./ragel/thttp_machine_utils.rl"; + include thttp_machine_ws "./ragel/thttp_machine_ws.rl"; + + action tag { tag_start = p; } + action eob { } + + action parse_key{ + TSK_PARSER_SET_STRING(hdr_Sec_WebSocket_Key->value); + } + + # Entry point + main := "Sec-WebSocket-Key"i SP* HCOLON SP*<: Sec_WebSocket_Key>tag %parse_key :>CRLF @eob; +}%% + +thttp_header_Sec_WebSocket_Key_t* thttp_header_Sec_WebSocket_Key_create(const char* value) +{ + return tsk_object_new(THTTP_HEADER_SEC_WEBSOCKET_KEY_VA_ARGS(value)); +} + +thttp_header_Sec_WebSocket_Key_t* thttp_header_Sec_WebSocket_Key_create_null() +{ + return thttp_header_Sec_WebSocket_Key_create(tsk_null); +} + + +int thttp_header_Sec_WebSocket_Key_tostring(const thttp_header_t* header, tsk_buffer_t* output) +{ + if(header){ + const thttp_header_Sec_WebSocket_Key_t *Sec_WebSocket_Key = (const thttp_header_Sec_WebSocket_Key_t*)header; + if(Sec_WebSocket_Key->value){ + return tsk_buffer_append(output, Sec_WebSocket_Key->value, tsk_strlen(Sec_WebSocket_Key->value)); + } + return 0; + } + + return -1; +} + +thttp_header_Sec_WebSocket_Key_t *thttp_header_Sec_WebSocket_Key_parse(const char *data, tsk_size_t size) +{ + int cs = 0; + const char *p = data; + const char *pe = p + size; + const char *eof = pe; + thttp_header_Sec_WebSocket_Key_t *hdr_Sec_WebSocket_Key = thttp_header_Sec_WebSocket_Key_create_null(); + + const char *tag_start = tsk_null; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + %%write data; + (void)(eof); + (void)(thttp_machine_parser_header_Sec_WebSocket_Key_first_final); + (void)(thttp_machine_parser_header_Sec_WebSocket_Key_error); + (void)(thttp_machine_parser_header_Sec_WebSocket_Key_en_main); + %%write init; + %%write exec; + TSK_RAGEL_DISABLE_WARNINGS_END() + + if( cs < %%{ write first_final; }%% ){ + TSK_DEBUG_ERROR("Failed to parse Sec-WebSocket-Key header."); + TSK_OBJECT_SAFE_FREE(hdr_Sec_WebSocket_Key); + } + + return hdr_Sec_WebSocket_Key; +} + + + + + + + +//======================================================== +// Sec_WebSocket_Key header object definition +// + +static tsk_object_t* thttp_header_Sec_WebSocket_Key_ctor(tsk_object_t *self, va_list * app) +{ + thttp_header_Sec_WebSocket_Key_t *Sec_WebSocket_Key = self; + if(Sec_WebSocket_Key){ + THTTP_HEADER(Sec_WebSocket_Key)->type = thttp_htype_Sec_WebSocket_Key; + THTTP_HEADER(Sec_WebSocket_Key)->tostring = thttp_header_Sec_WebSocket_Key_tostring; + + Sec_WebSocket_Key->value = tsk_strdup(va_arg(*app, const char*)); + } + else{ + TSK_DEBUG_ERROR("Failed to create new Sec-WebSocket-Key header."); + } + return self; +} + +static tsk_object_t* thttp_header_Sec_WebSocket_Key_dtor(tsk_object_t *self) +{ + thttp_header_Sec_WebSocket_Key_t *Sec_WebSocket_Key = self; + if(Sec_WebSocket_Key){ + TSK_FREE(Sec_WebSocket_Key->value); + TSK_OBJECT_SAFE_FREE(THTTP_HEADER_PARAMS(Sec_WebSocket_Key)); + } + else{ + TSK_DEBUG_ERROR("Null Sec_WebSocket_Key header."); + } + + return self; +} + +static const tsk_object_def_t thttp_header_Sec_WebSocket_Key_def_s = +{ + sizeof(thttp_header_Sec_WebSocket_Key_t), + thttp_header_Sec_WebSocket_Key_ctor, + thttp_header_Sec_WebSocket_Key_dtor, + tsk_null +}; +const tsk_object_def_t *thttp_header_Sec_WebSocket_Key_def_t = &thttp_header_Sec_WebSocket_Key_def_s; diff --git a/tinyHTTP/ragel/thttp_parser_header_Sec_WebSocket_Protocol.rl b/tinyHTTP/ragel/thttp_parser_header_Sec_WebSocket_Protocol.rl new file mode 100644 index 0000000..8617c57 --- /dev/null +++ b/tinyHTTP/ragel/thttp_parser_header_Sec_WebSocket_Protocol.rl @@ -0,0 +1,162 @@ +/* +* Copyright (C) 2010-2015 Mamadou Diop. +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ + +/**@file thttp_header_Sec_WebSocket_Protocol.c + * @brief WebSocket "Sec-WebSocket-Protocol" header. + * + */ +#include "tinyhttp/headers/thttp_header_Sec_WebSocket_Protocol.h" + +#include "tsk_debug.h" + +#include <string.h> + +%%{ + machine thttp_machine_parser_header_Sec_WebSocket_Protocol; + + # Includes + include thttp_machine_utils "./ragel/thttp_machine_utils.rl"; + include thttp_machine_ws "./ragel/thttp_machine_ws.rl"; + + action tag { tag_start = p; } + action eob { } + + action add_protocol{ + TSK_PARSER_ADD_STRING(hdr_Sec_WebSocket_Protocol->values); + } + + Sec_WebSocket_Protocol_Value = token>tag %add_protocol ( COMMA token>tag %add_protocol )*; + + # Entry point + main := "Sec-WebSocket-Protocol"i SP* HCOLON SP*<: Sec_WebSocket_Protocol_Value :>CRLF @eob; +}%% + +thttp_header_Sec_WebSocket_Protocol_t* thttp_header_Sec_WebSocket_Protocol_create(const char* protocol) +{ + return tsk_object_new(THTTP_HEADER_SEC_WEBSOCKET_PROTOCOL_VA_ARGS(protocol)); +} + +thttp_header_Sec_WebSocket_Protocol_t* thttp_header_Sec_WebSocket_Protocol_create_null() +{ + return thttp_header_Sec_WebSocket_Protocol_create(tsk_null); +} + + +int thttp_header_Sec_WebSocket_Protocol_tostring(const thttp_header_t* header, tsk_buffer_t* output) +{ + if(header){ + const thttp_header_Sec_WebSocket_Protocol_t *Sec_WebSocket_Protocol = (const thttp_header_Sec_WebSocket_Protocol_t*)header; + if(Sec_WebSocket_Protocol->values){ + const tsk_list_item_t* item; + const char* str; + tsk_list_foreach(item, Sec_WebSocket_Protocol->values){ + if((str = TSK_STRING_STR(item->data))){ + tsk_buffer_append(output, str, tsk_strlen(str)); + } + } + } + return 0; + } + + return -1; +} + +thttp_header_Sec_WebSocket_Protocol_t *thttp_header_Sec_WebSocket_Protocol_parse(const char *data, tsk_size_t size) +{ + int cs = 0; + const char *p = data; + const char *pe = p + size; + const char *eof = pe; + thttp_header_Sec_WebSocket_Protocol_t *hdr_Sec_WebSocket_Protocol = thttp_header_Sec_WebSocket_Protocol_create_null(); + + const char *tag_start = tsk_null; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + %%write data; + (void)(eof); + (void)(thttp_machine_parser_header_Sec_WebSocket_Protocol_first_final); + (void)(thttp_machine_parser_header_Sec_WebSocket_Protocol_error); + (void)(thttp_machine_parser_header_Sec_WebSocket_Protocol_en_main); + %%write init; + %%write exec; + TSK_RAGEL_DISABLE_WARNINGS_END() + + if( cs < %%{ write first_final; }%% ){ + TSK_DEBUG_ERROR("Failed to parse Sec-WebSocket-Protocol header."); + TSK_OBJECT_SAFE_FREE(hdr_Sec_WebSocket_Protocol); + } + + return hdr_Sec_WebSocket_Protocol; +} + + + + + + + +//======================================================== +// Sec_WebSocket_Protocol header object definition +// + +static tsk_object_t* thttp_header_Sec_WebSocket_Protocol_ctor(tsk_object_t *self, va_list * app) +{ + thttp_header_Sec_WebSocket_Protocol_t *Sec_WebSocket_Protocol = self; + if(Sec_WebSocket_Protocol){ + const char* protocol; + Sec_WebSocket_Protocol->values = tsk_list_create(); + THTTP_HEADER(Sec_WebSocket_Protocol)->type = thttp_htype_Sec_WebSocket_Protocol; + THTTP_HEADER(Sec_WebSocket_Protocol)->tostring = thttp_header_Sec_WebSocket_Protocol_tostring; + + if((protocol = va_arg(*app, const char*))){ + tsk_string_t* str_ver = tsk_string_create(protocol); + if(str_ver){ + tsk_list_push_back_data(Sec_WebSocket_Protocol->values, ((void**) &str_ver)); + } + } + } + else{ + TSK_DEBUG_ERROR("Failed to create new Sec-WebSocket-Protocol header."); + } + return self; +} + +static tsk_object_t* thttp_header_Sec_WebSocket_Protocol_dtor(tsk_object_t *self) +{ + thttp_header_Sec_WebSocket_Protocol_t *Sec_WebSocket_Protocol = self; + if(Sec_WebSocket_Protocol){ + TSK_OBJECT_SAFE_FREE(Sec_WebSocket_Protocol->values); + TSK_OBJECT_SAFE_FREE(THTTP_HEADER_PARAMS(Sec_WebSocket_Protocol)); + } + else{ + TSK_DEBUG_ERROR("Null Sec_WebSocket_Protocol header."); + } + + return self; +} + +static const tsk_object_def_t thttp_header_Sec_WebSocket_Protocol_def_s = +{ + sizeof(thttp_header_Sec_WebSocket_Protocol_t), + thttp_header_Sec_WebSocket_Protocol_ctor, + thttp_header_Sec_WebSocket_Protocol_dtor, + tsk_null +}; +const tsk_object_def_t *thttp_header_Sec_WebSocket_Protocol_def_t = &thttp_header_Sec_WebSocket_Protocol_def_s; diff --git a/tinyHTTP/ragel/thttp_parser_header_Sec_WebSocket_Version.rl b/tinyHTTP/ragel/thttp_parser_header_Sec_WebSocket_Version.rl new file mode 100644 index 0000000..32b6939 --- /dev/null +++ b/tinyHTTP/ragel/thttp_parser_header_Sec_WebSocket_Version.rl @@ -0,0 +1,161 @@ +/* +* Copyright (C) 2010-2015 Mamadou Diop. +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ + +/**@file thttp_header_Sec_WebSocket_Version.c + * @brief WebSocket "Sec-WebSocket-Key" header. + */ +#include "tinyhttp/headers/thttp_header_Sec_WebSocket_Version.h" + +#include "tsk_debug.h" + +#include <string.h> + +%%{ + machine thttp_machine_parser_header_Sec_WebSocket_Version; + + # Includes + include thttp_machine_utils "./ragel/thttp_machine_utils.rl"; + include thttp_machine_ws "./ragel/thttp_machine_ws.rl"; + + action tag { tag_start = p; } + action eob { } + + action add_version{ + TSK_PARSER_ADD_STRING(hdr_Sec_WebSocket_Version->values); + } + + Sec_WebSocket_Version_Value = version>tag %add_version ( COMMA version>tag %add_version )*; + + # Entry point + main := "Sec-WebSocket-Version"i SP* HCOLON SP*<: Sec_WebSocket_Version_Value :>CRLF @eob; +}%% + +thttp_header_Sec_WebSocket_Version_t* thttp_header_Sec_WebSocket_Version_create(const char* version) +{ + return tsk_object_new(THTTP_HEADER_SEC_WEBSOCKET_VERSION_VA_ARGS(version)); +} + +thttp_header_Sec_WebSocket_Version_t* thttp_header_Sec_WebSocket_Version_create_null() +{ + return thttp_header_Sec_WebSocket_Version_create(tsk_null); +} + + +int thttp_header_Sec_WebSocket_Version_tostring(const thttp_header_t* header, tsk_buffer_t* output) +{ + if(header){ + const thttp_header_Sec_WebSocket_Version_t *Sec_WebSocket_Version = (const thttp_header_Sec_WebSocket_Version_t*)header; + if(Sec_WebSocket_Version->values){ + const tsk_list_item_t* item; + const char* str; + tsk_list_foreach(item, Sec_WebSocket_Version->values){ + if((str = TSK_STRING_STR(item->data))){ + tsk_buffer_append(output, str, tsk_strlen(str)); + } + } + } + return 0; + } + + return -1; +} + +thttp_header_Sec_WebSocket_Version_t *thttp_header_Sec_WebSocket_Version_parse(const char *data, tsk_size_t size) +{ + int cs = 0; + const char *p = data; + const char *pe = p + size; + const char *eof = pe; + thttp_header_Sec_WebSocket_Version_t *hdr_Sec_WebSocket_Version = thttp_header_Sec_WebSocket_Version_create_null(); + + const char *tag_start = tsk_null; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + %%write data; + (void)(eof); + (void)(thttp_machine_parser_header_Sec_WebSocket_Version_first_final); + (void)(thttp_machine_parser_header_Sec_WebSocket_Version_error); + (void)(thttp_machine_parser_header_Sec_WebSocket_Version_en_main); + %%write init; + %%write exec; + TSK_RAGEL_DISABLE_WARNINGS_END() + + if( cs < %%{ write first_final; }%% ){ + TSK_DEBUG_ERROR("Failed to parse Sec-WebSocket-Version header."); + TSK_OBJECT_SAFE_FREE(hdr_Sec_WebSocket_Version); + } + + return hdr_Sec_WebSocket_Version; +} + + + + + + + +//======================================================== +// Sec_WebSocket_Version header object definition +// + +static tsk_object_t* thttp_header_Sec_WebSocket_Version_ctor(tsk_object_t *self, va_list * app) +{ + thttp_header_Sec_WebSocket_Version_t *Sec_WebSocket_Version = self; + if(Sec_WebSocket_Version){ + const char* version; + Sec_WebSocket_Version->values = tsk_list_create(); + THTTP_HEADER(Sec_WebSocket_Version)->type = thttp_htype_Sec_WebSocket_Version; + THTTP_HEADER(Sec_WebSocket_Version)->tostring = thttp_header_Sec_WebSocket_Version_tostring; + + if((version = va_arg(*app, const char*))){ + tsk_string_t* str_ver = tsk_string_create(version); + if(str_ver){ + tsk_list_push_back_data(Sec_WebSocket_Version->values, ((void**) &str_ver)); + } + } + } + else{ + TSK_DEBUG_ERROR("Failed to create new Sec-WebSocket-Version header."); + } + return self; +} + +static tsk_object_t* thttp_header_Sec_WebSocket_Version_dtor(tsk_object_t *self) +{ + thttp_header_Sec_WebSocket_Version_t *Sec_WebSocket_Version = self; + if(Sec_WebSocket_Version){ + TSK_OBJECT_SAFE_FREE(Sec_WebSocket_Version->values); + TSK_OBJECT_SAFE_FREE(THTTP_HEADER_PARAMS(Sec_WebSocket_Version)); + } + else{ + TSK_DEBUG_ERROR("Null Sec_WebSocket_Version header."); + } + + return self; +} + +static const tsk_object_def_t thttp_header_Sec_WebSocket_Version_def_s = +{ + sizeof(thttp_header_Sec_WebSocket_Version_t), + thttp_header_Sec_WebSocket_Version_ctor, + thttp_header_Sec_WebSocket_Version_dtor, + tsk_null +}; +const tsk_object_def_t *thttp_header_Sec_WebSocket_Version_def_t = &thttp_header_Sec_WebSocket_Version_def_s; diff --git a/tinyHTTP/ragel/thttp_parser_header_Transfer_Encoding.rl b/tinyHTTP/ragel/thttp_parser_header_Transfer_Encoding.rl new file mode 100644 index 0000000..7126281 --- /dev/null +++ b/tinyHTTP/ragel/thttp_parser_header_Transfer_Encoding.rl @@ -0,0 +1,162 @@ +/* +* Copyright (C) 2010-2015 Mamadou Diop. +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ + +/**@file thttp_header_Transfer_Encoding.c + * @brief HTTP Transfer-Encoding header. + */ +#include "tinyhttp/headers/thttp_header_Transfer_Encoding.h" + +#include "tsk_debug.h" +#include "tsk_memory.h" + +#include <string.h> + +/*********************************** +* Ragel state machine. +*/ +%%{ + machine thttp_machine_parser_header_Transfer_Encoding; + + # Includes + include thttp_machine_utils "./ragel/thttp_machine_utils.rl"; + + action tag{ + tag_start = p; + } + + action parse_encoding{ + TSK_PARSER_SET_STRING(hdr_tencoding->encoding); + } + + action parse_param{ + TSK_PARSER_ADD_PARAM(THTTP_HEADER_PARAMS(hdr_tencoding)); + } + + action eob{ + } + + Transfer_Encoding = ( "Transfer-Encoding"i ) HCOLON token>tag %parse_encoding :>( ";" (pname("=" pvalue )?)>tag %parse_param )*; + + # Entry point + main := Transfer_Encoding :>CRLF @eob; + +}%% + +thttp_header_Transfer_Encoding_t* thttp_header_transfer_encoding_create(const char* encoding) +{ + return tsk_object_new(THTTP_HEADER_TRANSFER_ENCODING_VA_ARGS(encoding)); +} + +thttp_header_Transfer_Encoding_t* thttp_header_transfer_encoding_create_null() +{ + return thttp_header_transfer_encoding_create(tsk_null); +} + + +int thttp_header_Transfer_Encoding_tostring(const thttp_header_t* header, tsk_buffer_t* output) +{ + if(header){ + const thttp_header_Transfer_Encoding_t *Transfer_Encoding = (const thttp_header_Transfer_Encoding_t*)header; + if(Transfer_Encoding->encoding){ + return tsk_buffer_append(output, Transfer_Encoding->encoding, tsk_strlen(Transfer_Encoding->encoding)); + } + return 0; + } + + return -1; +} + +/**@ingroup thttp_header_group +*/ +thttp_header_Transfer_Encoding_t *thttp_header_Transfer_Encoding_parse(const char *data, tsk_size_t size) +{ + int cs = 0; + const char *p = data; + const char *pe = p + size; + const char *eof = pe; + thttp_header_Transfer_Encoding_t *hdr_tencoding = thttp_header_transfer_encoding_create_null(); + + const char *tag_start = tsk_null; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + %%write data; + (void)(eof); + (void)(thttp_machine_parser_header_Transfer_Encoding_first_final); + (void)(thttp_machine_parser_header_Transfer_Encoding_error); + (void)(thttp_machine_parser_header_Transfer_Encoding_en_main); + %%write init; + %%write exec; + TSK_RAGEL_DISABLE_WARNINGS_END() + + if( cs < %%{ write first_final; }%% ){ + TSK_DEBUG_ERROR("Failed to parse Tansfer-Encoding header."); + TSK_OBJECT_SAFE_FREE(hdr_tencoding); + } + + return hdr_tencoding; +} + + + + + + + +//======================================================== +// Transfer_Encoding header object definition +// + +static tsk_object_t* thttp_header_Transfer_Encoding_ctor(tsk_object_t *self, va_list * app) +{ + thttp_header_Transfer_Encoding_t *Transfer_Encoding = self; + if(Transfer_Encoding){ + THTTP_HEADER(Transfer_Encoding)->type = thttp_htype_Transfer_Encoding; + THTTP_HEADER(Transfer_Encoding)->tostring = thttp_header_Transfer_Encoding_tostring; + + Transfer_Encoding->encoding = tsk_strdup( va_arg(*app, const char*) ); + } + else{ + TSK_DEBUG_ERROR("Failed to create new Transfer_Encoding header."); + } + return self; +} + +static tsk_object_t* thttp_header_Transfer_Encoding_dtor(tsk_object_t* self) +{ + thttp_header_Transfer_Encoding_t *Transfer_Encoding = self; + if(Transfer_Encoding){ + TSK_FREE(Transfer_Encoding->encoding); + TSK_OBJECT_SAFE_FREE(THTTP_HEADER_PARAMS(Transfer_Encoding)); + } + else{ + TSK_DEBUG_ERROR("Null Transfer_Encoding header."); + } + + return self; +} + +static const tsk_object_def_t thttp_header_Transfer_Encoding_def_s = +{ + sizeof(thttp_header_Transfer_Encoding_t), + thttp_header_Transfer_Encoding_ctor, + thttp_header_Transfer_Encoding_dtor, + tsk_null +}; +const tsk_object_def_t *thttp_header_Transfer_Encoding_def_t = &thttp_header_Transfer_Encoding_def_s; diff --git a/tinyHTTP/ragel/thttp_parser_header_WWW_Authenticate.rl b/tinyHTTP/ragel/thttp_parser_header_WWW_Authenticate.rl new file mode 100644 index 0000000..e72ab4b --- /dev/null +++ b/tinyHTTP/ragel/thttp_parser_header_WWW_Authenticate.rl @@ -0,0 +1,259 @@ +/* +* Copyright (C) 2010-2015 Mamadou Diop. +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ + +/**@file thttp_header_WWW_Authenticate.c + * @brief HTTP WWW-Authenticate header. + */ +#include "tinyhttp/headers/thttp_header_WWW_Authenticate.h" + +#include "tinyhttp/parsers/thttp_parser_url.h" + +#include "tsk_debug.h" +#include "tsk_memory.h" +#include "tsk_time.h" + +#include <string.h> + +// Check if we have ",CRLF" ==> See WWW-Authenticate header +// As :>CRLF is preceded by any+ ==> p will be at least (start + 1) +// p point to CR +#define prev_not_comma(p) !(p && p[-1] == ',') + +/*********************************** +* Ragel state machine. +*/ +%%{ + machine thttp_machine_parser_header_WWW_Authenticate; + + # Includes + include thttp_machine_utils "./ragel/thttp_machine_utils.rl"; + + action tag{ + tag_start = p; + } + + action is_digest{ + hdr_WWW_Authenticate->scheme = tsk_strdup("Digest"); + } + + action is_basic{ + hdr_WWW_Authenticate->scheme = tsk_strdup("Basic"); + } + + action is_auth{ + THTTP_HEADER(hdr_WWW_Authenticate)->type = thttp_htype_WWW_Authenticate; + } + + action is_proxy{ + THTTP_HEADER(hdr_WWW_Authenticate)->type = thttp_htype_Proxy_Authenticate; + } + + action parse_realm{ + TSK_PARSER_SET_STRING(hdr_WWW_Authenticate->realm); + tsk_strunquote(&hdr_WWW_Authenticate->realm); + } + + action parse_domain{ + TSK_PARSER_SET_STRING(hdr_WWW_Authenticate->domain); + //tsk_strunquote(&hdr_WWW_Authenticate->domain); + } + + action parse_nonce{ + TSK_PARSER_SET_STRING(hdr_WWW_Authenticate->nonce); + tsk_strunquote(&hdr_WWW_Authenticate->nonce); + } + + action parse_opaque{ + TSK_PARSER_SET_STRING(hdr_WWW_Authenticate->opaque); + tsk_strunquote(&hdr_WWW_Authenticate->opaque); + } + + action parse_stale{ + hdr_WWW_Authenticate->stale = tsk_strniequals(tag_start, "true", 4); + } + + action parse_algorithm{ + TSK_PARSER_SET_STRING(hdr_WWW_Authenticate->algorithm); + } + + action parse_qop{ + TSK_PARSER_SET_STRING(hdr_WWW_Authenticate->qop); + //tsk_strunquote(&hdr_WWW_Authenticate->qop); + } + + action parse_param{ + TSK_PARSER_ADD_PARAM(THTTP_HEADER_PARAMS(hdr_WWW_Authenticate)); + } + + action prev_not_comma{ + prev_not_comma(p) + } + + action eob{ + } + + #FIXME: Only Digest (MD5, AKAv1-MD5 and AKAv2-MD5) is supported + other_challenge = (any+); + auth_param = generic_param>tag %parse_param; + + realm = "realm"i EQUAL quoted_string>tag %parse_realm; + domain = "domain"i EQUAL LDQUOT <: (any*)>tag %parse_domain :> RDQUOT; + nonce = "nonce"i EQUAL quoted_string>tag %parse_nonce; + opaque = "opaque"i EQUAL quoted_string>tag %parse_opaque; + stale = "stale"i EQUAL ( "true"i | "false"i )>tag %parse_stale; + algorithm = "algorithm"i EQUAL <:token>tag %parse_algorithm; + qop_options = "qop"i EQUAL LDQUOT <: (any*)>tag %parse_qop :> RDQUOT; + + digest_cln = (realm | domain | nonce | opaque | stale | algorithm | qop_options)@1 | auth_param@0; + challenge = ( ("Digest"i%is_digest | "Basic"i%is_basic) LWS digest_cln ( (COMMA | CRLF) <:digest_cln )* ) | other_challenge; + WWW_Authenticate = ("WWW-Authenticate"i>is_auth | "Proxy-Authenticate"i>is_proxy) HCOLON challenge; + + # Entry point + main := WWW_Authenticate CRLF @eob; + +}%% + +thttp_header_WWW_Authenticate_t* thttp_header_www_authenticate_create() +{ + return tsk_object_new(thttp_header_WWW_Authenticate_def_t); +} + +int thttp_header_WWW_Authenticate_tostring(const thttp_header_t* header, tsk_buffer_t* output) +{ + if(header){ + const thttp_header_WWW_Authenticate_t *WWW_Authenticate = (const thttp_header_WWW_Authenticate_t*)header; + if(WWW_Authenticate && WWW_Authenticate->scheme){ + return tsk_buffer_append_2(output, "%s realm=\"%s\"%s%s%s%s%s%s%s%s%s%s%s%s,stale=%s%s%s", + WWW_Authenticate->scheme, + WWW_Authenticate->realm ? WWW_Authenticate->realm : "", + + WWW_Authenticate->domain ? ",domain=\"" : "", + WWW_Authenticate->domain ? WWW_Authenticate->domain : "", + WWW_Authenticate->domain ? "\"" : "", + + + WWW_Authenticate->qop ? ",qop=\"" : "", + WWW_Authenticate->qop ? WWW_Authenticate->qop : "", + WWW_Authenticate->qop ? "\"" : "", + + + WWW_Authenticate->nonce ? ",nonce=\"" : "", + WWW_Authenticate->nonce ? WWW_Authenticate->nonce : "", + WWW_Authenticate->nonce ? "\"" : "", + + WWW_Authenticate->opaque ? ",opaque=\"" : "", + WWW_Authenticate->opaque ? WWW_Authenticate->opaque : "", + WWW_Authenticate->opaque ? "\"" : "", + + WWW_Authenticate->stale ? "TRUE" : "FALSE", + + WWW_Authenticate->algorithm ? ",algorithm=" : "", + WWW_Authenticate->algorithm ? WWW_Authenticate->algorithm : "" + ); + } + } + return -1; +} + +/**@ingroup thttp_header_group +*/ +thttp_header_WWW_Authenticate_t *thttp_header_WWW_Authenticate_parse(const char *data, tsk_size_t size) +{ + int cs = 0; + const char *p = data; + const char *pe = p + size; + const char *eof = pe; + thttp_header_WWW_Authenticate_t *hdr_WWW_Authenticate = thttp_header_www_authenticate_create(); + + const char *tag_start = tsk_null; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + %%write data; + (void)(eof); + (void)(thttp_machine_parser_header_WWW_Authenticate_first_final); + (void)(thttp_machine_parser_header_WWW_Authenticate_error); + (void)(thttp_machine_parser_header_WWW_Authenticate_en_main); + %%write init; + %%write exec; + TSK_RAGEL_DISABLE_WARNINGS_END() + + if( cs < %%{ write first_final; }%% ){ + TSK_DEBUG_ERROR("Failed to parse WWW-Authenticate header."); + TSK_OBJECT_SAFE_FREE(hdr_WWW_Authenticate); + } + + return hdr_WWW_Authenticate; +} + +thttp_header_Proxy_Authenticate_t *thttp_header_Proxy_Authenticate_parse(const char *data, tsk_size_t size) +{ + return thttp_header_WWW_Authenticate_parse(data, size); +} + + + + + +//======================================================== +// WWW_Authenticate header object definition +// + +static tsk_object_t* thttp_header_WWW_Authenticate_ctor(tsk_object_t *self, va_list * app) +{ + thttp_header_WWW_Authenticate_t *WWW_Authenticate = self; + if(WWW_Authenticate){ + THTTP_HEADER(WWW_Authenticate)->type = thttp_htype_WWW_Authenticate; + THTTP_HEADER(WWW_Authenticate)->tostring = thttp_header_WWW_Authenticate_tostring; + } + else{ + TSK_DEBUG_ERROR("Failed to create new WWW_Authenticate header."); + } + return self; +} + +static tsk_object_t* thttp_header_WWW_Authenticate_dtor(tsk_object_t *self) +{ + thttp_header_WWW_Authenticate_t *WWW_Authenticate = self; + if(WWW_Authenticate){ + TSK_FREE(WWW_Authenticate->scheme); + TSK_FREE(WWW_Authenticate->realm); + TSK_FREE(WWW_Authenticate->domain); + TSK_FREE(WWW_Authenticate->nonce); + TSK_FREE(WWW_Authenticate->opaque); + TSK_FREE(WWW_Authenticate->algorithm); + TSK_FREE(WWW_Authenticate->qop); + + TSK_OBJECT_SAFE_FREE(THTTP_HEADER_PARAMS(WWW_Authenticate)); + } + else{ + TSK_DEBUG_ERROR("Null WWW_Authenticate header."); + } + + return self; +} + +static const tsk_object_def_t thttp_header_WWW_Authenticate_def_s = +{ + sizeof(thttp_header_WWW_Authenticate_t), + thttp_header_WWW_Authenticate_ctor, + thttp_header_WWW_Authenticate_dtor, + tsk_null +}; +const tsk_object_def_t *thttp_header_WWW_Authenticate_def_t = &thttp_header_WWW_Authenticate_def_s; diff --git a/tinyHTTP/ragel/thttp_parser_message.rl b/tinyHTTP/ragel/thttp_parser_message.rl new file mode 100644 index 0000000..547b654 --- /dev/null +++ b/tinyHTTP/ragel/thttp_parser_message.rl @@ -0,0 +1,257 @@ +/* +* Copyright (C) 2010-2015 Mamadou Diop. +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ +/**@file thttp_parser_message.c + * @brief HTTP parser. + * + */ +#include "tinyhttp/parsers/thttp_parser_message.h" +#include "tinyhttp/parsers/thttp_parser_header.h" + +#include "tinyhttp/parsers/thttp_parser_url.h" + +#include "tsk_debug.h" +#include "tsk_memory.h" + +static void thttp_message_parser_execute(tsk_ragel_state_t *state, thttp_message_t *message, tsk_bool_t extract_content); +static void thttp_message_parser_init(tsk_ragel_state_t *state); +static void thttp_message_parser_eoh(tsk_ragel_state_t *state, thttp_message_t *message, tsk_bool_t extract_content); + +/*********************************** +* Ragel state machine. +*/ +%%{ + machine thttp_machine_parser_message; + + #/* Tag the buffer (start point). */ + action tag{ + state->tag_start = p; + } + + #/* HTTP method */ + action parse_method{ + int len; + state->tag_end = p; + len = (int)(state->tag_end - state->tag_start); + + if(message->type == thttp_unknown){ + message->type = thttp_request; + if(!message->line.request.method){ + message->line.request.method = tsk_calloc(1, len+1); + memcpy(message->line.request.method, state->tag_start, len); + } + } + else{ + state->cs = thttp_machine_parser_message_error; + } + } + + #/* Request URI parsing */ + action parse_requesturl{ + int len; + state->tag_end = p; + len = (int)(state->tag_end - state->tag_start); + + if(!message->line.request.url){ + message->line.request.url = thttp_url_parse(state->tag_start, (tsk_size_t)len); + } + } + + #/* Sip Version */ + action parse_httpversion{ + int len; + state->tag_end = p; + len = (int)(state->tag_end - state->tag_start); + + if(!message->http_version){ + message->http_version = tsk_calloc(1, len+1); + memcpy(message->http_version, state->tag_start, len); + } + } + + #/* Status Code */ + action parse_status_code{ + int len; + state->tag_end = p; + len = (int)(state->tag_end - state->tag_start); + + if(message->type == thttp_unknown){ + message->type = thttp_response; + message->line.response.status_code = atoi(state->tag_start); + } + else{ + state->cs = thttp_machine_parser_message_error; + } + } + + #/* Reason Phrase */ + action parse_reason_phrase{ + int len; + state->tag_end = p; + len = (int)(state->tag_end - state->tag_start); + + if(!message->line.response.reason_phrase){ + message->line.response.reason_phrase = tsk_calloc(1, len+1); + memcpy(message->line.response.reason_phrase, state->tag_start, len); + } + } + + #/* Parse http header */ + action parse_header{ + int len; + state->tag_end = p; + len = (int)(state->tag_end - state->tag_start); + + if(thttp_header_parse(state, message)){ + TSK_DEBUG_ERROR("Failed to parse header - %s", state->tag_start); + } + else{ + //TSK_DEBUG_INFO("THTTP_MESSAGE_PARSER::PARSE_HEADER len=%d state=%d", len, state->cs); + } + } + + #/* Parse http content/body. */ + #action parse_body + #{ + # int len; + # state->tag_end = p; + # len = (int)(state->tag_end - state->tag_start); + # TSK_DEBUG_ERROR("==THTTP_MESSAGE_PARSER::PARSE_BODY=="); + #} + + #/* End-Of-Headers */ + action eoh{ + state->cs = cs; + state->p = p; + state->pe = pe; + state->eof = eof; + + thttp_message_parser_eoh(state, message, extract_content); + + cs = state->cs; + p = state->p; + pe = state->pe; + eof = state->eof; + } + + # Includes + include thttp_machine_utils "./ragel/thttp_machine_utils.rl"; + include thttp_machine_message "./ragel/thttp_machine_message.rl"; + + # Entry point + main := HTTP_message; +}%% + + +TSK_RAGEL_DISABLE_WARNINGS_BEGIN() +/* Regel data */ +%%write data; +TSK_RAGEL_DISABLE_WARNINGS_END() + +/** Parses raw HTTP buffer. + * + * @param state Ragel state containing the buffer references. + * @param result @ref thttp_message_t object representing the raw buffer. + * @param extract_content Indicates wheteher to parse the message content or not. If set to true, then + * only headers will be parsed. + * + * @retval Zero if succeed and non-zero error code otherwise. +**/ +int thttp_message_parse(tsk_ragel_state_t *state, thttp_message_t **result, tsk_bool_t extract_content) +{ + if(!state || state->pe <= state->p){ + return -1; + } + + if(!*result){ + *result = thttp_message_create(); + } + + /* Ragel init */ + thttp_message_parser_init(state); + + /* + * State mechine execution. + */ + thttp_message_parser_execute(state, *result, extract_content); + + /* Check result */ + + if( state->cs < %%{ write first_final; }%% ){ + TSK_DEBUG_ERROR("Failed to parse HTTP message."); + TSK_OBJECT_SAFE_FREE(*result); + return -2; + } + return 0; +} + + +static void thttp_message_parser_init(tsk_ragel_state_t *state) +{ + int cs = 0; + + /* Regel machine initialization. */ + %% write init; + + state->cs = cs; +} + +static void thttp_message_parser_execute(tsk_ragel_state_t *state, thttp_message_t *message, tsk_bool_t extract_content) +{ + int cs = state->cs; + const char *p = state->p; + const char *pe = state->pe; + const char *eof = state->eof; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + %% write exec; + TSK_RAGEL_DISABLE_WARNINGS_END() + + state->cs = cs; + state->p = p; + state->pe = pe; + state->eof = eof; +} + +static void thttp_message_parser_eoh(tsk_ragel_state_t *state, thttp_message_t *message, tsk_bool_t extract_content) +{ + int cs = state->cs; + const char *p = state->p; + const char *pe = state->pe; + const char *eof = state->eof; + + if(extract_content && message){ + uint32_t clen = THTTP_MESSAGE_CONTENT_LENGTH(message); + if(clen){ + if((p + clen)<pe && !message->Content){ + message->Content = tsk_buffer_create((p+1), clen); + p = (p + clen); + } + else{ + p = (pe - 1); + } + } + } + //%%write eof; + + state->cs = cs; + state->p = p; + state->pe = pe; + state->eof = eof; +} diff --git a/tinyHTTP/ragel/thttp_parser_url.rl b/tinyHTTP/ragel/thttp_parser_url.rl new file mode 100644 index 0000000..ffd3054 --- /dev/null +++ b/tinyHTTP/ragel/thttp_parser_url.rl @@ -0,0 +1,139 @@ +/* +* Copyright (C) 2010-2015 Mamadou Diop. +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ +/**@file thttp_parser_url.c + * @brief HTTP/HTTPS URL parser. + */ +#include "tinyhttp/parsers/thttp_parser_url.h" + +#include "tsk_string.h" +#include "tsk_memory.h" +#include "tsk_debug.h" + +/*********************************** +* Ragel state machine. +*/ +%%{ + machine thttp_machine_parser_url; + + # Includes + include thttp_machine_utils "./ragel/thttp_machine_utils.rl"; + + action tag{ + tag_start = p; + } + + #/* Sets URL type */ + action is_http { url->scheme = tsk_strdup("http"), url->type = thttp_url_http; } + action is_https { url->scheme = tsk_strdup("https"), url->type = thttp_url_https; } + + #/* Sets HOST type */ + action is_ipv4 { url->host_type = url->host_type = thttp_host_ipv4; } + action is_ipv6 { url->host_type = url->host_type = thttp_host_ipv6; } + action is_hostname { url->host_type = url->host_type = thttp_host_hostname; } + + action parse_host{ + TSK_PARSER_SET_STRING(url->host); + } + + action parse_port{ + have_port = 1; + TSK_PARSER_SET_INT(url->port); + } + + action parse_hpath{ + TSK_PARSER_SET_STRING(url->hpath); + } + + action parse_search{ + TSK_PARSER_SET_STRING(url->search); + } + + action eob{ + } + + #// RFC 1738: "http://" hostport [ "/" hpath [ "?" search ]] + #// FIXME: hpath is no optional (see above) but in my def. I use it as opt (any*). + + search = any* >tag %parse_search; + hpath = any* >tag %parse_hpath; + port = DIGIT+ >tag %parse_port; + myhost = ((IPv6reference >is_ipv6) | (IPv4address >is_ipv4) | (hostname >is_hostname)) >tag %parse_host; + hostport = myhost ( ":" port )?; + main := ( (("http:"i>tag %is_http | "https:"i>tag %is_https) "//")? hostport? :>("/" hpath :>("?" search)?)? ) @eob; + #main := ( hostport? :>("/" hpath :>("?" search)?)? ) @eob; + +}%% + +/**@ingroup thttp_url_group +* Parses a HTTP/HTTPS url. +* @param urlstring A pointer to a valid url string. If the port is missing, then it's default value will be 443 if +* the scheme is 'https' and 80 otherwise.<br> +* @param length The length of the url string. +* @retval A well-defined object representing the url string. +* +* @code +* thttp_url_t* url = thttp_url_parse("http://www.google.com", tsk_strlen("http://www.google.com")); +* @endcode +* +* @sa @ref thttp_url_tostring<br>@ref thttp_url_serialize +**/ +thttp_url_t *thttp_url_parse(const char *urlstring, tsk_size_t length) +{ + tsk_bool_t have_port = tsk_false; + int cs = 0; + const char *p = urlstring; + const char *pe = p + length; + const char *eof = pe; + + const char *ts = 0, *te = 0; + int act =0; + + thttp_url_t *url = thttp_url_create(thttp_url_unknown); + + const char *tag_start = 0; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + %%write data; + (void)(ts); + (void)(te); + (void)(act); + (void)(eof); + (void)(thttp_machine_parser_url_first_final); + (void)(thttp_machine_parser_url_error); + (void)(thttp_machine_parser_url_en_main); + %%write init; + %%write exec; + TSK_RAGEL_DISABLE_WARNINGS_END() + + if( cs < %%{ write first_final; }%% ){ + TSK_DEBUG_ERROR("Failed to parse HTTP/HTTPS URL: '%.*s'", length, urlstring); + TSK_OBJECT_SAFE_FREE(url); + } + else if(!have_port){ + if(url->type == thttp_url_https){ + url->port = 443; + } + else{ + url->port = 80; + } + } + + return url; +} |