summaryrefslogtreecommitdiffstats
path: root/tinyHTTP/ragel
diff options
context:
space:
mode:
authorMamadou DIOP <bossiel@yahoo.fr>2015-08-17 01:56:35 +0200
committerMamadou DIOP <bossiel@yahoo.fr>2015-08-17 01:56:35 +0200
commit631fffee8a28b1bec5ed1f1d26a20e0135967f99 (patch)
tree74afe3bf3efe15aa82bcd0272b2b0f4d48c2d837 /tinyHTTP/ragel
parent7908865936604036e6f200f1b5e069f8752f3a3a (diff)
downloaddoubango-631fffee8a28b1bec5ed1f1d26a20e0135967f99.zip
doubango-631fffee8a28b1bec5ed1f1d26a20e0135967f99.tar.gz
-
Diffstat (limited to 'tinyHTTP/ragel')
-rw-r--r--tinyHTTP/ragel/thttp_machine_header.rl87
-rw-r--r--tinyHTTP/ragel/thttp_machine_message.rl44
-rw-r--r--tinyHTTP/ragel/thttp_machine_utils.rl110
-rw-r--r--tinyHTTP/ragel/thttp_machine_ws.rl46
-rw-r--r--tinyHTTP/ragel/thttp_parser_header.rl522
-rw-r--r--tinyHTTP/ragel/thttp_parser_header_Authorization.rl296
-rw-r--r--tinyHTTP/ragel/thttp_parser_header_Content_Length.rl145
-rw-r--r--tinyHTTP/ragel/thttp_parser_header_Content_Type.rl175
-rw-r--r--tinyHTTP/ragel/thttp_parser_header_Dummy.rl167
-rw-r--r--tinyHTTP/ragel/thttp_parser_header_ETag.rl173
-rw-r--r--tinyHTTP/ragel/thttp_parser_header_Sec_WebSocket_Accept.rl146
-rw-r--r--tinyHTTP/ragel/thttp_parser_header_Sec_WebSocket_Key.rl146
-rw-r--r--tinyHTTP/ragel/thttp_parser_header_Sec_WebSocket_Protocol.rl162
-rw-r--r--tinyHTTP/ragel/thttp_parser_header_Sec_WebSocket_Version.rl161
-rw-r--r--tinyHTTP/ragel/thttp_parser_header_Transfer_Encoding.rl162
-rw-r--r--tinyHTTP/ragel/thttp_parser_header_WWW_Authenticate.rl259
-rw-r--r--tinyHTTP/ragel/thttp_parser_message.rl257
-rw-r--r--tinyHTTP/ragel/thttp_parser_url.rl139
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;
+}
OpenPOWER on IntegriCloud