diff --git a/examples/http_server/Makefile b/examples/http_server/Makefile
new file mode 100644
index 0000000..42fdd33
--- /dev/null
+++ b/examples/http_server/Makefile
@@ -0,0 +1,13 @@
+PROGRAM=http_server
+
+#ESPBAUD=921600
+
+EXTRA_CFLAGS=-DLWIP_HTTPD_CGI=1 -DLWIP_HTTPD_SSI=1 -I./fsdata
+
+EXTRA_COMPONENTS=extras/httpd
+
+include ../../common.mk
+
+html:
+	@echo "Generating fsdata.."
+	cd fsdata && ./makefsdata
diff --git a/examples/http_server/fsdata/fs/404.html b/examples/http_server/fsdata/fs/404.html
new file mode 100644
index 0000000..8155203
--- /dev/null
+++ b/examples/http_server/fsdata/fs/404.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no">
+
+		<link rel="stylesheet" type="text/css" href="css/siimple.min.css">
+		<link rel="stylesheet" type="text/css" href="css/style.css">
+		<link rel="shortcut icon" href="img/favicon.png">
+
+		<title>HTTP Server</title>
+	</head>
+	<body>
+		<ul class="navbar">
+			<li><a href="/">Home</a></li>
+			<li><a href="about">About</a></li>
+		</ul>
+
+		<div class="grid main">
+			<h1>404 - Page not found</h1>
+			<div class="alert alert-error">Sorry, the page you are requesting was not found on this server.</div>
+		</div>
+	</body>
+</html>
+
diff --git a/examples/http_server/fsdata/fs/about.html b/examples/http_server/fsdata/fs/about.html
new file mode 100644
index 0000000..1692485
--- /dev/null
+++ b/examples/http_server/fsdata/fs/about.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no">
+
+		<link rel="stylesheet" type="text/css" href="css/siimple.min.css">
+		<link rel="stylesheet" type="text/css" href="css/style.css">
+		<link rel="shortcut icon" href="img/favicon.png">
+
+		<title>HTTP Server</title>
+	</head>
+	<body>
+		<ul class="navbar">
+			<li><a href="/">Home</a></li>
+			<li><a class="active" href="about">About</a></li>
+		</ul>
+
+		<div class="grid main">
+			<h1>About</h1>
+			<p>This server is built on httpd from LwIP.</p>
+			<p>For more info see <a href="http://www.nongnu.org/lwip/2_0_0/group__httpd.html">HTTP Server documentation</a>.</p>
+		</div>
+	</body>
+</html>
+
diff --git a/examples/http_server/fsdata/fs/css/siimple.min.css b/examples/http_server/fsdata/fs/css/siimple.min.css
new file mode 100644
index 0000000..a52f026
--- /dev/null
+++ b/examples/http_server/fsdata/fs/css/siimple.min.css
@@ -0,0 +1,8 @@
+/**
+ * siimple - Minimal CSS framework for flat and clean designs.
+ * @version v1.3.7
+ * @link https://siimple.juanes.xyz/
+ * @license MIT
+ */
+
+@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,300);ol,ol li,p,ul,ul li{line-height:28px}.alert,pre{width:calc(100% - 30px)}.alert,.btn{border-radius:5px}.heart:after{content:"\2764";color:#f45660}body,h1,h2,h3,h4,h5,h6{color:#526475}body{margin:0;padding:0;font-family:'Open Sans';font-size:16px;font-weight:300;background-color:#fff}.alert a,a{text-decoration:none;font-weight:400}blockquote{border-left:4px solid #6a7e95;padding:5px 5px 5px 20px}a{color:#09a0f6;transition:all .3s}a:hover{text-decoration:underline;cursor:pointer}p{margin-bottom:20px;margin-top:0;display:block}ol,ul{margin-bottom:16px;margin-top:0}.alert,h1,h2,h3,h4,h5,h6{font-weight:300;margin-top:0;margin-bottom:20px;display:block}small{color:#6a7e95;font-size:14px}h1{font-size:36px;line-height:50px}h2{font-size:32px;line-height:46px}h3{font-size:28px;line-height:42px}h4{font-size:24px;line-height:38px}h5{font-size:20px;line-height:34px}.alert,.btn,h6{font-size:16px}h6{line-height:30px}.alert{text-align:left;border-width:1px;border-style:solid;background-color:#E1F5FE;color:#03A9F4;border-color:#03A9F4;padding:16px 14px;padding:16px 14px;padding:16px 14px}.btn,.btn-outline{font-family:'Open Sans';font-weight:300;display:inline-block;transition:all .3s;-webkit-touch-callout:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;text-align:center;cursor:pointer;margin:5px 5px 20px}.alert-error{color:#D32F2F;background-color:#FFEBEE;border-color:#F44336}.alert-warning{background-color:#FFF8E1;color:#FF8F00;border-color:#FFC107}.alert-done{background-color:#E8F5E9;color:#388E3C;border-color:#4CAF50}.btn{text-decoration:none!important;line-height:28px;color:#fff;background-color:#09a0f6;border:0;padding:5px 25px}.btn:hover{text-decoration:none;opacity:.8}.btn-small{font-size:14px!important;line-height:20px!important;padding:4px 15px!important}.btn-big{font-size:22px!important;line-height:34px!important;padding:8px 30px!important}.btn-outline,pre{line-height:28px}.btn-outline{font-size:16px;text-decoration:none!important;border-radius:5px;color:#09a0f6;background-color:transparent;border:1px solid #09a0f6;padding:5px 25px}.btn-outline:hover{text-decoration:none;color:#fff;background-color:#09a0f6}code,pre{font-family:'Open Sans';font-size:16px;font-weight:300;border-radius:5px;background-color:#f1f5fa}code{color:#09a0f6;padding-left:6px;padding-right:6px}pre{display:block;padding:14px;margin-bottom:20px;color:#526475;overflow-x:auto}.form-input[disabled],.form-input[type=text],.form-input[type=password],.form-input[type=number],.form-input[type=email],.form-input[type=date]{color:#526475;padding:10px;outline:0;box-sizing:border-box;margin:0 5px 20px;font-family:'Open Sans';font-size:16px;font-weight:300;display:inline-block;transition:all .3s;height:40px}.form-input[type=text],.form-input[type=password],.form-input[type=number],.form-input[type=email]{width:100%;border:1px solid #d1e1e8;border-radius:5px;line-height:40px}.form-input[type=text]:focus,.form-input[type=password]:focus,.form-input[type=number]:focus,.form-input[type=email]:focus{border:1px solid #09a0f6}.form-input[type=date]{border:1px solid #d1e1e8;border-radius:5px;width:auto!important}.form-input[type=date]:focus{border:1px solid #09a0f6}.form-input[disabled]{width:100%;border:1px solid #d1e1e8;border-radius:5px;cursor:not-allowed;background-color:#d1e1e8}.form-input[disabled]:focus{border:1px solid #09a0f6}.form-input[type=submit],.form-input[type=button]{font-family:'Open Sans';font-size:16px;font-weight:300;-webkit-touch-callout:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;text-align:center;text-decoration:none!important;line-height:28px;display:inline-block;cursor:pointer;border-radius:5px;transition:all .3s;color:#fff;background-color:#09a0f6;border:0;margin:5px 5px 20px;padding:5px 25px}.form-select,.form-textarea{font-family:'Open Sans';font-size:16px;display:inline-block;width:100%;transition:all .3s;outline:0;box-sizing:border-box;margin:0 5px 20px;font-weight:300;color:#526475}.form-input[type=submit]:hover,.form-input[type=button]:hover{text-decoration:none;opacity:.8}.form-select{padding:6px 10px 10px;border:1px solid #d1e1e8;border-radius:5px;height:40px;background-color:#fff}.form-select:focus{border:1px solid #09a0f6}.form-textarea{padding:10px;border:1px solid #d1e1e8;border-radius:5px;resize:vertical}.form-textarea:focus{border:1px solid #09a0f6}.form-auto{width:auto!important}.grid{display:block;width:960px;margin-left:auto;margin-right:auto;min-height:40px}@media (max-width:960px){.grid{width:94%}}.grid-fluid,.row{width:100%}.row{display:inline-block;margin-left:0;margin-right:0}.row:after{content:" ";clear:both;display:table;line-height:0}.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-7,.col-8,.col-9{display:inline-block;vertical-align:top;float:left;padding:1%}.col-1{width:6.33%}.col-2{width:14.66%}.col-3{width:22.99%}.col-4{width:31.33%}.col-5{width:39.66%}.col-6{width:47.99%;display:inline-block;vertical-align:top;float:left;padding:1%}.col-7{width:56.33%}.col-8{width:64.66%}.col-9{width:72.99%}.col-10{width:81.33%}.col-11{width:89.66%}.col-12{width:97.99%}@media (max-width:400px){.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9{width:98%}}.table{display:table;width:100%;border-width:0;border-collapse:collapse;font-weight:300;color:#526475;margin-top:0;margin-bottom:20px}.table thead tr td{font-weight:400;border-bottom:2px solid #d1e1e8;background-color:#f6f8fa}.table tr td{border-bottom:1px solid #d1e1e8;padding-top:10px;padding-bottom:10px;padding-left:10px}
\ No newline at end of file
diff --git a/examples/http_server/fsdata/fs/css/style.css b/examples/http_server/fsdata/fs/css/style.css
new file mode 100644
index 0000000..b5b27d6
--- /dev/null
+++ b/examples/http_server/fsdata/fs/css/style.css
@@ -0,0 +1,73 @@
+ul.navbar {
+	list-style-type: none;
+	margin-bottom: 32px;
+	padding: 0;
+	overflow: hidden;
+	background-color: #333;
+}
+ul.navbar li {
+	float: left;
+}
+ul.navbar li a {
+	display: block;
+	color: white;
+	text-align: center;
+	padding: 14px 16px;
+	text-decoration: none;
+}
+ul.navbar li a:hover:not(.active) {
+	background-color: #111;
+}
+ul.navbar li a.active {
+	background-color: #09a0f6;
+}
+@media screen and (max-width: 600px){
+	ul.navbar li.right, 
+	ul.navbar li {float: none;}
+}
+.onoffswitch {
+	position: relative; width: 90px;
+	-webkit-user-select:none; -moz-user-select:none; -ms-user-select: none;
+}
+.onoffswitch-checkbox {
+	display: none;
+}
+.onoffswitch-label {
+	display: block; overflow: hidden; cursor: pointer;
+	border: 2px solid #03A9F4; border-radius: 20px;
+}
+.onoffswitch-inner {
+	display: block; width: 200%; margin-left: -100%;
+	transition: margin 0.3s ease-in 0s;
+}
+.onoffswitch-inner:before, .onoffswitch-inner:after {
+	display: block; float: left; width: 50%; height: 30px; padding: 0; line-height: 30px;
+	font-size: 14px; color: white; font-family: Trebuchet, Arial, sans-serif; font-weight: bold;
+	box-sizing: border-box;
+}
+.onoffswitch-inner:before {
+	content: "ON";
+	text-align: left;
+	padding-left: 14px;
+	background-color: #E1F5FE; color: #03A9F4;
+}
+.onoffswitch-inner:after {
+	content: "OFF";
+	padding-right: 14px;
+	background-color: #FFFFFF; color: #999999;
+	text-align: right;
+}
+.onoffswitch-switch {
+	display: block; width: 18px; margin: 6px;
+	background: #FFFFFF;
+	position: absolute; top: 0; bottom: 0;
+	right: 56px;
+	border: 2px solid #03A9F4; border-radius: 20px;
+	transition: all 0.3s ease-in 0s; 
+}
+.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-inner {
+	margin-left: 0;
+}
+.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-switch {
+	right: 0px; 
+}
\ No newline at end of file
diff --git a/examples/http_server/fsdata/fs/img/favicon.png b/examples/http_server/fsdata/fs/img/favicon.png
new file mode 100644
index 0000000..126f24b
Binary files /dev/null and b/examples/http_server/fsdata/fs/img/favicon.png differ
diff --git a/examples/http_server/fsdata/fs/index.ssi b/examples/http_server/fsdata/fs/index.ssi
new file mode 100644
index 0000000..eb9db29
--- /dev/null
+++ b/examples/http_server/fsdata/fs/index.ssi
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no">
+
+		<link rel="stylesheet" type="text/css" href="css/siimple.min.css">
+		<link rel="stylesheet" type="text/css" href="css/style.css">
+		<link rel="shortcut icon" href="img/favicon.png">
+
+		<title>HTTP Server</title>
+	</head>
+	<body>
+		<ul class="navbar">
+			<li><a class="active" href="/">Home</a></li>
+			<li><a href="about">About</a></li>
+		</ul>
+
+		<div class="grid main">
+			<h1>ESP8266 HTTP Server</h1>
+
+			<div class="alert alert-done">HTTP Server is up and running.</div>
+
+			<p>This is an example HTTP server with CGI and SSI support. The switch below will allow you to test CGI handler and turn
+			the blue LED on or off.</p>
+
+			<div class="cover" align="center">
+				<div class="onoffswitch">
+					<input type="checkbox" name="onoffswitch" class="onoffswitch-checkbox" id="led-switch" onclick="gpio();">
+					<label class="onoffswitch-label" for="led-switch">
+						<span class="onoffswitch-inner"></span>
+						<span class="onoffswitch-switch"></span>
+					</label>
+				</div>
+			</div>
+
+			<h1>Server Status</h1>
+			<table class="table table-striped">
+				<tr>
+					<td><b>Uptime:</b></td>
+					<td><!--#uptime--> seconds</td>
+				</tr>
+				<tr>
+					<td><b>Free heap:</b></td>
+					<td><!--#heap--> bytes</td>
+				</tr>
+				<tr>
+					<td><b>LED state:</b></td>
+					<td id="ledState"><!--#led--></td>
+				</tr>
+			</table>
+
+			<h1>How it works</h1>
+			<p> Each time the server detects a tag of the form <code>&lt;!--#name--&gt;</code> in a .shtml, .ssi or .shtm file
+				where <code>name</code> appears as one of the tags supplied to <code>http_set_ssi_handler</code> in the <code>pcConfigSSITags</code> array,
+				an insert string is appended after the tag string in file and sent back to the client.</p>
+			<p>A CGI handler function is called each time the server is asked for a file
+				whose name was previously registered as a CGI function using a call to <code>http_set_cgi_handler</code>.
+				This function allows you to access the parameters provided along with the URI.</p>
+		</div>
+
+		<script>
+			window.onload = function () {
+				var ls = document.getElementById('ledState').innerHTML;
+				ls = ls.split(/-->/).pop().trim();
+				document.getElementById('led-switch').checked = (ls == 'On');
+			};
+			function gpio() {
+				if (document.getElementById('led-switch').checked)
+					window.location.href = 'gpio?off=2';
+				else
+					window.location.href = 'gpio?on=2';
+			};
+		</script>
+	</body>
+</html>
diff --git a/examples/http_server/fsdata/fsdata.c b/examples/http_server/fsdata/fsdata.c
new file mode 100644
index 0000000..90d8c06
--- /dev/null
+++ b/examples/http_server/fsdata/fsdata.c
@@ -0,0 +1,1361 @@
+#include "httpd/fsdata.h"
+
+static const unsigned char data_index_ssi[] = {
+	/* /index.ssi */
+	0x2F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x73, 0x73, 0x69, 0,
+	0x48, 0x54, 0x54, 0x50, 0x2F, 0x31, 0x2E, 0x30, 0x20, 0x32, 
+	0x30, 0x30, 0x20, 0x4F, 0x4B, 0x0D, 0x0A, 0x6C, 0x77, 0x49, 
+	0x50, 0x2F, 0x31, 0x2E, 0x34, 0x2E, 0x31, 0x20, 0x28, 0x68, 
+	0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x73, 0x61, 0x76, 0x61, 
+	0x6E, 0x6E, 0x61, 0x68, 0x2E, 0x6E, 0x6F, 0x6E, 0x67, 0x6E, 
+	0x75, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x70, 0x72, 0x6F, 0x6A, 
+	0x65, 0x63, 0x74, 0x73, 0x2F, 0x6C, 0x77, 0x69, 0x70, 0x29, 
+	0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x2D, 
+	0x74, 0x79, 0x70, 0x65, 0x3A, 0x20, 0x74, 0x65, 0x78, 0x74, 
+	0x2F, 0x68, 0x74, 0x6D, 0x6C, 0x0D, 0x0A, 0x0D, 0x0A, 0x3C, 
+	0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 
+	0x74, 0x6D, 0x6C, 0x3E, 0x0A, 0x3C, 0x68, 0x74, 0x6D, 0x6C, 
+	0x3E, 0x0A, 0x09, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x0A, 
+	0x09, 0x09, 0x3C, 0x6D, 0x65, 0x74, 0x61, 0x20, 0x63, 0x68, 
+	0x61, 0x72, 0x73, 0x65, 0x74, 0x3D, 0x22, 0x75, 0x74, 0x66, 
+	0x2D, 0x38, 0x22, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x65, 
+	0x74, 0x61, 0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3D, 0x22, 0x76, 
+	0x69, 0x65, 0x77, 0x70, 0x6F, 0x72, 0x74, 0x22, 0x20, 0x63, 
+	0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x3D, 0x22, 0x77, 0x69, 
+	0x64, 0x74, 0x68, 0x3D, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 
+	0x2D, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2C, 0x20, 0x75, 0x73, 
+	0x65, 0x72, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x61, 0x62, 0x6C, 
+	0x65, 0x3D, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x0A, 0x09, 0x09, 
+	0x3C, 0x6C, 0x69, 0x6E, 0x6B, 0x20, 0x72, 0x65, 0x6C, 0x3D, 
+	0x22, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x73, 0x68, 0x65, 0x65, 
+	0x74, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x74, 
+	0x65, 0x78, 0x74, 0x2F, 0x63, 0x73, 0x73, 0x22, 0x20, 0x68, 
+	0x72, 0x65, 0x66, 0x3D, 0x22, 0x63, 0x73, 0x73, 0x2F, 0x73, 
+	0x69, 0x69, 0x6D, 0x70, 0x6C, 0x65, 0x2E, 0x6D, 0x69, 0x6E, 
+	0x2E, 0x63, 0x73, 0x73, 0x22, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 
+	0x6C, 0x69, 0x6E, 0x6B, 0x20, 0x72, 0x65, 0x6C, 0x3D, 0x22, 
+	0x73, 0x74, 0x79, 0x6C, 0x65, 0x73, 0x68, 0x65, 0x65, 0x74, 
+	0x22, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x74, 0x65, 
+	0x78, 0x74, 0x2F, 0x63, 0x73, 0x73, 0x22, 0x20, 0x68, 0x72, 
+	0x65, 0x66, 0x3D, 0x22, 0x63, 0x73, 0x73, 0x2F, 0x73, 0x74, 
+	0x79, 0x6C, 0x65, 0x2E, 0x63, 0x73, 0x73, 0x22, 0x3E, 0x0A, 
+	0x09, 0x09, 0x3C, 0x6C, 0x69, 0x6E, 0x6B, 0x20, 0x72, 0x65, 
+	0x6C, 0x3D, 0x22, 0x73, 0x68, 0x6F, 0x72, 0x74, 0x63, 0x75, 
+	0x74, 0x20, 0x69, 0x63, 0x6F, 0x6E, 0x22, 0x20, 0x68, 0x72, 
+	0x65, 0x66, 0x3D, 0x22, 0x69, 0x6D, 0x67, 0x2F, 0x66, 0x61, 
+	0x76, 0x69, 0x63, 0x6F, 0x6E, 0x2E, 0x70, 0x6E, 0x67, 0x22, 
+	0x3E, 0x0A, 0x0A, 0x09, 0x09, 0x3C, 0x74, 0x69, 0x74, 0x6C, 
+	0x65, 0x3E, 0x48, 0x54, 0x54, 0x50, 0x20, 0x53, 0x65, 0x72, 
+	0x76, 0x65, 0x72, 0x3C, 0x2F, 0x74, 0x69, 0x74, 0x6C, 0x65, 
+	0x3E, 0x0A, 0x09, 0x3C, 0x2F, 0x68, 0x65, 0x61, 0x64, 0x3E, 
+	0x0A, 0x09, 0x3C, 0x62, 0x6F, 0x64, 0x79, 0x3E, 0x0A, 0x09, 
+	0x09, 0x3C, 0x75, 0x6C, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 
+	0x3D, 0x22, 0x6E, 0x61, 0x76, 0x62, 0x61, 0x72, 0x22, 0x3E, 
+	0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6C, 0x69, 0x3E, 0x3C, 0x61, 
+	0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x61, 0x63, 
+	0x74, 0x69, 0x76, 0x65, 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 
+	0x3D, 0x22, 0x2F, 0x22, 0x3E, 0x48, 0x6F, 0x6D, 0x65, 0x3C, 
+	0x2F, 0x61, 0x3E, 0x3C, 0x2F, 0x6C, 0x69, 0x3E, 0x0A, 0x09, 
+	0x09, 0x09, 0x3C, 0x6C, 0x69, 0x3E, 0x3C, 0x61, 0x20, 0x68, 
+	0x72, 0x65, 0x66, 0x3D, 0x22, 0x61, 0x62, 0x6F, 0x75, 0x74, 
+	0x22, 0x3E, 0x41, 0x62, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x61, 
+	0x3E, 0x3C, 0x2F, 0x6C, 0x69, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 
+	0x2F, 0x75, 0x6C, 0x3E, 0x0A, 0x0A, 0x09, 0x09, 0x3C, 0x64, 
+	0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 
+	0x67, 0x72, 0x69, 0x64, 0x20, 0x6D, 0x61, 0x69, 0x6E, 0x22, 
+	0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x68, 0x31, 0x3E, 0x45, 
+	0x53, 0x50, 0x38, 0x32, 0x36, 0x36, 0x20, 0x48, 0x54, 0x54, 
+	0x50, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3C, 0x2F, 
+	0x68, 0x31, 0x3E, 0x0A, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 
+	0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 
+	0x61, 0x6C, 0x65, 0x72, 0x74, 0x20, 0x61, 0x6C, 0x65, 0x72, 
+	0x74, 0x2D, 0x64, 0x6F, 0x6E, 0x65, 0x22, 0x3E, 0x48, 0x54, 
+	0x54, 0x50, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 
+	0x69, 0x73, 0x20, 0x75, 0x70, 0x20, 0x61, 0x6E, 0x64, 0x20, 
+	0x72, 0x75, 0x6E, 0x6E, 0x69, 0x6E, 0x67, 0x2E, 0x3C, 0x2F, 
+	0x64, 0x69, 0x76, 0x3E, 0x0A, 0x0A, 0x09, 0x09, 0x09, 0x3C, 
+	0x70, 0x3E, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 
+	0x61, 0x6E, 0x20, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 
+	0x20, 0x48, 0x54, 0x54, 0x50, 0x20, 0x73, 0x65, 0x72, 0x76, 
+	0x65, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x43, 0x47, 
+	0x49, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x53, 0x53, 0x49, 0x20, 
+	0x73, 0x75, 0x70, 0x70, 0x6F, 0x72, 0x74, 0x2E, 0x20, 0x54, 
+	0x68, 0x65, 0x20, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 
+	0x62, 0x65, 0x6C, 0x6F, 0x77, 0x20, 0x77, 0x69, 0x6C, 0x6C, 
+	0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x20, 0x79, 0x6F, 0x75, 
+	0x20, 0x74, 0x6F, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x43, 
+	0x47, 0x49, 0x20, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 
+	0x20, 0x61, 0x6E, 0x64, 0x20, 0x74, 0x75, 0x72, 0x6E, 0x0A, 
+	0x09, 0x09, 0x09, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6C, 0x75, 
+	0x65, 0x20, 0x4C, 0x45, 0x44, 0x20, 0x6F, 0x6E, 0x20, 0x6F, 
+	0x72, 0x20, 0x6F, 0x66, 0x66, 0x2E, 0x3C, 0x2F, 0x70, 0x3E, 
+	0x0A, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x76, 0x20, 
+	0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x63, 0x6F, 0x76, 
+	0x65, 0x72, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3D, 
+	0x22, 0x63, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x22, 0x3E, 0x0A, 
+	0x09, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x76, 0x20, 0x63, 
+	0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x6F, 0x6E, 0x6F, 0x66, 
+	0x66, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x22, 0x3E, 0x0A, 
+	0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x69, 0x6E, 0x70, 0x75, 
+	0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x63, 0x68, 
+	0x65, 0x63, 0x6B, 0x62, 0x6F, 0x78, 0x22, 0x20, 0x6E, 0x61, 
+	0x6D, 0x65, 0x3D, 0x22, 0x6F, 0x6E, 0x6F, 0x66, 0x66, 0x73, 
+	0x77, 0x69, 0x74, 0x63, 0x68, 0x22, 0x20, 0x63, 0x6C, 0x61, 
+	0x73, 0x73, 0x3D, 0x22, 0x6F, 0x6E, 0x6F, 0x66, 0x66, 0x73, 
+	0x77, 0x69, 0x74, 0x63, 0x68, 0x2D, 0x63, 0x68, 0x65, 0x63, 
+	0x6B, 0x62, 0x6F, 0x78, 0x22, 0x20, 0x69, 0x64, 0x3D, 0x22, 
+	0x6C, 0x65, 0x64, 0x2D, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 
+	0x22, 0x20, 0x6F, 0x6E, 0x63, 0x6C, 0x69, 0x63, 0x6B, 0x3D, 
+	0x22, 0x67, 0x70, 0x69, 0x6F, 0x28, 0x29, 0x3B, 0x22, 0x3E, 
+	0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x6C, 0x61, 0x62, 
+	0x65, 0x6C, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 
+	0x6F, 0x6E, 0x6F, 0x66, 0x66, 0x73, 0x77, 0x69, 0x74, 0x63, 
+	0x68, 0x2D, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x22, 0x20, 0x66, 
+	0x6F, 0x72, 0x3D, 0x22, 0x6C, 0x65, 0x64, 0x2D, 0x73, 0x77, 
+	0x69, 0x74, 0x63, 0x68, 0x22, 0x3E, 0x0A, 0x09, 0x09, 0x09, 
+	0x09, 0x09, 0x09, 0x3C, 0x73, 0x70, 0x61, 0x6E, 0x20, 0x63, 
+	0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x6F, 0x6E, 0x6F, 0x66, 
+	0x66, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2D, 0x69, 0x6E, 
+	0x6E, 0x65, 0x72, 0x22, 0x3E, 0x3C, 0x2F, 0x73, 0x70, 0x61, 
+	0x6E, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 
+	0x73, 0x70, 0x61, 0x6E, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 
+	0x3D, 0x22, 0x6F, 0x6E, 0x6F, 0x66, 0x66, 0x73, 0x77, 0x69, 
+	0x74, 0x63, 0x68, 0x2D, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 
+	0x22, 0x3E, 0x3C, 0x2F, 0x73, 0x70, 0x61, 0x6E, 0x3E, 0x0A, 
+	0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x6C, 0x61, 0x62, 
+	0x65, 0x6C, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 
+	0x64, 0x69, 0x76, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 
+	0x64, 0x69, 0x76, 0x3E, 0x0A, 0x0A, 0x09, 0x09, 0x09, 0x3C, 
+	0x68, 0x31, 0x3E, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 
+	0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, 0x68, 0x31, 
+	0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x74, 0x61, 0x62, 0x6C, 
+	0x65, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x74, 
+	0x61, 0x62, 0x6C, 0x65, 0x20, 0x74, 0x61, 0x62, 0x6C, 0x65, 
+	0x2D, 0x73, 0x74, 0x72, 0x69, 0x70, 0x65, 0x64, 0x22, 0x3E, 
+	0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x74, 0x72, 0x3E, 0x0A, 
+	0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x74, 0x64, 0x3E, 0x3C, 
+	0x62, 0x3E, 0x55, 0x70, 0x74, 0x69, 0x6D, 0x65, 0x3A, 0x3C, 
+	0x2F, 0x62, 0x3E, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x0A, 0x09, 
+	0x09, 0x09, 0x09, 0x09, 0x3C, 0x74, 0x64, 0x3E, 0x3C, 0x21, 
+	0x2D, 0x2D, 0x23, 0x75, 0x70, 0x74, 0x69, 0x6D, 0x65, 0x2D, 
+	0x2D, 0x3E, 0x20, 0x73, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x73, 
+	0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09, 
+	0x3C, 0x2F, 0x74, 0x72, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09, 
+	0x3C, 0x74, 0x72, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 
+	0x3C, 0x74, 0x64, 0x3E, 0x3C, 0x62, 0x3E, 0x46, 0x72, 0x65, 
+	0x65, 0x20, 0x68, 0x65, 0x61, 0x70, 0x3A, 0x3C, 0x2F, 0x62, 
+	0x3E, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x0A, 0x09, 0x09, 0x09, 
+	0x09, 0x09, 0x3C, 0x74, 0x64, 0x3E, 0x3C, 0x21, 0x2D, 0x2D, 
+	0x23, 0x68, 0x65, 0x61, 0x70, 0x2D, 0x2D, 0x3E, 0x20, 0x62, 
+	0x79, 0x74, 0x65, 0x73, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x0A, 
+	0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x74, 0x72, 0x3E, 0x0A, 
+	0x09, 0x09, 0x09, 0x09, 0x3C, 0x74, 0x72, 0x3E, 0x0A, 0x09, 
+	0x09, 0x09, 0x09, 0x09, 0x3C, 0x74, 0x64, 0x3E, 0x3C, 0x62, 
+	0x3E, 0x4C, 0x45, 0x44, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 
+	0x3A, 0x3C, 0x2F, 0x62, 0x3E, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 
+	0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x74, 0x64, 0x20, 
+	0x69, 0x64, 0x3D, 0x22, 0x6C, 0x65, 0x64, 0x53, 0x74, 0x61, 
+	0x74, 0x65, 0x22, 0x3E, 0x3C, 0x21, 0x2D, 0x2D, 0x23, 0x6C, 
+	0x65, 0x64, 0x2D, 0x2D, 0x3E, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 
+	0x0A, 0x09, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x74, 0x72, 0x3E, 
+	0x0A, 0x09, 0x09, 0x09, 0x3C, 0x2F, 0x74, 0x61, 0x62, 0x6C, 
+	0x65, 0x3E, 0x0A, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x68, 0x31, 
+	0x3E, 0x48, 0x6F, 0x77, 0x20, 0x69, 0x74, 0x20, 0x77, 0x6F, 
+	0x72, 0x6B, 0x73, 0x3C, 0x2F, 0x68, 0x31, 0x3E, 0x0A, 0x09, 
+	0x09, 0x09, 0x3C, 0x70, 0x3E, 0x20, 0x45, 0x61, 0x63, 0x68, 
+	0x20, 0x74, 0x69, 0x6D, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 
+	0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x64, 0x65, 0x74, 
+	0x65, 0x63, 0x74, 0x73, 0x20, 0x61, 0x20, 0x74, 0x61, 0x67, 
+	0x20, 0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6F, 
+	0x72, 0x6D, 0x20, 0x3C, 0x63, 0x6F, 0x64, 0x65, 0x3E, 0x26, 
+	0x6C, 0x74, 0x3B, 0x21, 0x2D, 0x2D, 0x23, 0x6E, 0x61, 0x6D, 
+	0x65, 0x2D, 0x2D, 0x26, 0x67, 0x74, 0x3B, 0x3C, 0x2F, 0x63, 
+	0x6F, 0x64, 0x65, 0x3E, 0x20, 0x69, 0x6E, 0x20, 0x61, 0x20, 
+	0x2E, 0x73, 0x68, 0x74, 0x6D, 0x6C, 0x2C, 0x20, 0x2E, 0x73, 
+	0x73, 0x69, 0x20, 0x6F, 0x72, 0x20, 0x2E, 0x73, 0x68, 0x74, 
+	0x6D, 0x20, 0x66, 0x69, 0x6C, 0x65, 0x0A, 0x09, 0x09, 0x09, 
+	0x09, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x3C, 0x63, 0x6F, 
+	0x64, 0x65, 0x3E, 0x6E, 0x61, 0x6D, 0x65, 0x3C, 0x2F, 0x63, 
+	0x6F, 0x64, 0x65, 0x3E, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 
+	0x72, 0x73, 0x20, 0x61, 0x73, 0x20, 0x6F, 0x6E, 0x65, 0x20, 
+	0x6F, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x61, 0x67, 
+	0x73, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6C, 0x69, 0x65, 0x64, 
+	0x20, 0x74, 0x6F, 0x20, 0x3C, 0x63, 0x6F, 0x64, 0x65, 0x3E, 
+	0x68, 0x74, 0x74, 0x70, 0x5F, 0x73, 0x65, 0x74, 0x5F, 0x73, 
+	0x73, 0x69, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 
+	0x3C, 0x2F, 0x63, 0x6F, 0x64, 0x65, 0x3E, 0x20, 0x69, 0x6E, 
+	0x20, 0x74, 0x68, 0x65, 0x20, 0x3C, 0x63, 0x6F, 0x64, 0x65, 
+	0x3E, 0x70, 0x63, 0x43, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x53, 
+	0x53, 0x49, 0x54, 0x61, 0x67, 0x73, 0x3C, 0x2F, 0x63, 0x6F, 
+	0x64, 0x65, 0x3E, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2C, 
+	0x0A, 0x09, 0x09, 0x09, 0x09, 0x61, 0x6E, 0x20, 0x69, 0x6E, 
+	0x73, 0x65, 0x72, 0x74, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 
+	0x67, 0x20, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x65, 0x6E, 
+	0x64, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 
+	0x74, 0x68, 0x65, 0x20, 0x74, 0x61, 0x67, 0x20, 0x73, 0x74, 
+	0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x6E, 0x20, 0x66, 0x69, 
+	0x6C, 0x65, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x73, 0x65, 0x6E, 
+	0x74, 0x20, 0x62, 0x61, 0x63, 0x6B, 0x20, 0x74, 0x6F, 0x20, 
+	0x74, 0x68, 0x65, 0x20, 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 
+	0x2E, 0x3C, 0x2F, 0x70, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 
+	0x70, 0x3E, 0x41, 0x20, 0x43, 0x47, 0x49, 0x20, 0x68, 0x61, 
+	0x6E, 0x64, 0x6C, 0x65, 0x72, 0x20, 0x66, 0x75, 0x6E, 0x63, 
+	0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, 0x73, 0x20, 0x63, 0x61, 
+	0x6C, 0x6C, 0x65, 0x64, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 
+	0x74, 0x69, 0x6D, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 
+	0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x61, 
+	0x73, 0x6B, 0x65, 0x64, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x61, 
+	0x20, 0x66, 0x69, 0x6C, 0x65, 0x0A, 0x09, 0x09, 0x09, 0x09, 
+	0x77, 0x68, 0x6F, 0x73, 0x65, 0x20, 0x6E, 0x61, 0x6D, 0x65, 
+	0x20, 0x77, 0x61, 0x73, 0x20, 0x70, 0x72, 0x65, 0x76, 0x69, 
+	0x6F, 0x75, 0x73, 0x6C, 0x79, 0x20, 0x72, 0x65, 0x67, 0x69, 
+	0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 
+	0x61, 0x20, 0x43, 0x47, 0x49, 0x20, 0x66, 0x75, 0x6E, 0x63, 
+	0x74, 0x69, 0x6F, 0x6E, 0x20, 0x75, 0x73, 0x69, 0x6E, 0x67, 
+	0x20, 0x61, 0x20, 0x63, 0x61, 0x6C, 0x6C, 0x20, 0x74, 0x6F, 
+	0x20, 0x3C, 0x63, 0x6F, 0x64, 0x65, 0x3E, 0x68, 0x74, 0x74, 
+	0x70, 0x5F, 0x73, 0x65, 0x74, 0x5F, 0x63, 0x67, 0x69, 0x5F, 
+	0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x3C, 0x2F, 0x63, 
+	0x6F, 0x64, 0x65, 0x3E, 0x2E, 0x0A, 0x09, 0x09, 0x09, 0x09, 
+	0x54, 0x68, 0x69, 0x73, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 
+	0x69, 0x6F, 0x6E, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x73, 
+	0x20, 0x79, 0x6F, 0x75, 0x20, 0x74, 0x6F, 0x20, 0x61, 0x63, 
+	0x63, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 
+	0x61, 0x72, 0x61, 0x6D, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 
+	0x70, 0x72, 0x6F, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x61, 
+	0x6C, 0x6F, 0x6E, 0x67, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 
+	0x74, 0x68, 0x65, 0x20, 0x55, 0x52, 0x49, 0x2E, 0x3C, 0x2F, 
+	0x70, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x64, 0x69, 0x76, 
+	0x3E, 0x0A, 0x0A, 0x09, 0x09, 0x3C, 0x73, 0x63, 0x72, 0x69, 
+	0x70, 0x74, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x77, 0x69, 0x6E, 
+	0x64, 0x6F, 0x77, 0x2E, 0x6F, 0x6E, 0x6C, 0x6F, 0x61, 0x64, 
+	0x20, 0x3D, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 
+	0x6E, 0x20, 0x28, 0x29, 0x20, 0x7B, 0x0A, 0x09, 0x09, 0x09, 
+	0x09, 0x76, 0x61, 0x72, 0x20, 0x6C, 0x73, 0x20, 0x3D, 0x20, 
+	0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, 
+	0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 
+	0x79, 0x49, 0x64, 0x28, 0x27, 0x6C, 0x65, 0x64, 0x53, 0x74, 
+	0x61, 0x74, 0x65, 0x27, 0x29, 0x2E, 0x69, 0x6E, 0x6E, 0x65, 
+	0x72, 0x48, 0x54, 0x4D, 0x4C, 0x3B, 0x0A, 0x09, 0x09, 0x09, 
+	0x09, 0x6C, 0x73, 0x20, 0x3D, 0x20, 0x6C, 0x73, 0x2E, 0x73, 
+	0x70, 0x6C, 0x69, 0x74, 0x28, 0x2F, 0x2D, 0x2D, 0x3E, 0x2F, 
+	0x29, 0x2E, 0x70, 0x6F, 0x70, 0x28, 0x29, 0x2E, 0x74, 0x72, 
+	0x69, 0x6D, 0x28, 0x29, 0x3B, 0x0A, 0x09, 0x09, 0x09, 0x09, 
+	0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, 
+	0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 
+	0x79, 0x49, 0x64, 0x28, 0x27, 0x6C, 0x65, 0x64, 0x2D, 0x73, 
+	0x77, 0x69, 0x74, 0x63, 0x68, 0x27, 0x29, 0x2E, 0x63, 0x68, 
+	0x65, 0x63, 0x6B, 0x65, 0x64, 0x20, 0x3D, 0x20, 0x28, 0x6C, 
+	0x73, 0x20, 0x3D, 0x3D, 0x20, 0x27, 0x4F, 0x6E, 0x27, 0x29, 
+	0x3B, 0x0A, 0x09, 0x09, 0x09, 0x7D, 0x3B, 0x0A, 0x09, 0x09, 
+	0x09, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 
+	0x67, 0x70, 0x69, 0x6F, 0x28, 0x29, 0x20, 0x7B, 0x0A, 0x09, 
+	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x64, 0x6F, 0x63, 
+	0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, 
+	0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, 0x64, 
+	0x28, 0x27, 0x6C, 0x65, 0x64, 0x2D, 0x73, 0x77, 0x69, 0x74, 
+	0x63, 0x68, 0x27, 0x29, 0x2E, 0x63, 0x68, 0x65, 0x63, 0x6B, 
+	0x65, 0x64, 0x29, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x77, 
+	0x69, 0x6E, 0x64, 0x6F, 0x77, 0x2E, 0x6C, 0x6F, 0x63, 0x61, 
+	0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x68, 0x72, 0x65, 0x66, 0x20, 
+	0x3D, 0x20, 0x27, 0x67, 0x70, 0x69, 0x6F, 0x3F, 0x6F, 0x66, 
+	0x66, 0x3D, 0x32, 0x27, 0x3B, 0x0A, 0x09, 0x09, 0x09, 0x09, 
+	0x65, 0x6C, 0x73, 0x65, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 
+	0x77, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x2E, 0x6C, 0x6F, 0x63, 
+	0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x68, 0x72, 0x65, 0x66, 
+	0x20, 0x3D, 0x20, 0x27, 0x67, 0x70, 0x69, 0x6F, 0x3F, 0x6F, 
+	0x6E, 0x3D, 0x32, 0x27, 0x3B, 0x0A, 0x09, 0x09, 0x09, 0x7D, 
+	0x3B, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x73, 0x63, 0x72, 0x69, 
+	0x70, 0x74, 0x3E, 0x0A, 0x09, 0x3C, 0x2F, 0x62, 0x6F, 0x64, 
+	0x79, 0x3E, 0x0A, 0x3C, 0x2F, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 
+	0x0A, };
+
+static const unsigned char data_404_html[] = {
+	/* /404.html */
+	0x2F, 0x34, 0x30, 0x34, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0,
+	0x48, 0x54, 0x54, 0x50, 0x2F, 0x31, 0x2E, 0x30, 0x20, 0x34, 
+	0x30, 0x34, 0x20, 0x46, 0x69, 0x6C, 0x65, 0x20, 0x6E, 0x6F, 
+	0x74, 0x20, 0x66, 0x6F, 0x75, 0x6E, 0x64, 0x0D, 0x0A, 0x6C, 
+	0x77, 0x49, 0x50, 0x2F, 0x31, 0x2E, 0x34, 0x2E, 0x31, 0x20, 
+	0x28, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x73, 0x61, 
+	0x76, 0x61, 0x6E, 0x6E, 0x61, 0x68, 0x2E, 0x6E, 0x6F, 0x6E, 
+	0x67, 0x6E, 0x75, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x70, 0x72, 
+	0x6F, 0x6A, 0x65, 0x63, 0x74, 0x73, 0x2F, 0x6C, 0x77, 0x69, 
+	0x70, 0x29, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 
+	0x74, 0x2D, 0x74, 0x79, 0x70, 0x65, 0x3A, 0x20, 0x74, 0x65, 
+	0x78, 0x74, 0x2F, 0x68, 0x74, 0x6D, 0x6C, 0x0D, 0x0A, 0x0D, 
+	0x0A, 0x3C, 0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 
+	0x20, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0A, 0x3C, 0x68, 0x74, 
+	0x6D, 0x6C, 0x3E, 0x0A, 0x09, 0x3C, 0x68, 0x65, 0x61, 0x64, 
+	0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x65, 0x74, 0x61, 0x20, 
+	0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3D, 0x22, 0x75, 
+	0x74, 0x66, 0x2D, 0x38, 0x22, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 
+	0x6D, 0x65, 0x74, 0x61, 0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3D, 
+	0x22, 0x76, 0x69, 0x65, 0x77, 0x70, 0x6F, 0x72, 0x74, 0x22, 
+	0x20, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x3D, 0x22, 
+	0x77, 0x69, 0x64, 0x74, 0x68, 0x3D, 0x64, 0x65, 0x76, 0x69, 
+	0x63, 0x65, 0x2D, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2C, 0x20, 
+	0x75, 0x73, 0x65, 0x72, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x61, 
+	0x62, 0x6C, 0x65, 0x3D, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x0A, 
+	0x09, 0x09, 0x3C, 0x6C, 0x69, 0x6E, 0x6B, 0x20, 0x72, 0x65, 
+	0x6C, 0x3D, 0x22, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x73, 0x68, 
+	0x65, 0x65, 0x74, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 
+	0x22, 0x74, 0x65, 0x78, 0x74, 0x2F, 0x63, 0x73, 0x73, 0x22, 
+	0x20, 0x68, 0x72, 0x65, 0x66, 0x3D, 0x22, 0x63, 0x73, 0x73, 
+	0x2F, 0x73, 0x69, 0x69, 0x6D, 0x70, 0x6C, 0x65, 0x2E, 0x6D, 
+	0x69, 0x6E, 0x2E, 0x63, 0x73, 0x73, 0x22, 0x3E, 0x0A, 0x09, 
+	0x09, 0x3C, 0x6C, 0x69, 0x6E, 0x6B, 0x20, 0x72, 0x65, 0x6C, 
+	0x3D, 0x22, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x73, 0x68, 0x65, 
+	0x65, 0x74, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 
+	0x74, 0x65, 0x78, 0x74, 0x2F, 0x63, 0x73, 0x73, 0x22, 0x20, 
+	0x68, 0x72, 0x65, 0x66, 0x3D, 0x22, 0x63, 0x73, 0x73, 0x2F, 
+	0x73, 0x74, 0x79, 0x6C, 0x65, 0x2E, 0x63, 0x73, 0x73, 0x22, 
+	0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x6C, 0x69, 0x6E, 0x6B, 0x20, 
+	0x72, 0x65, 0x6C, 0x3D, 0x22, 0x73, 0x68, 0x6F, 0x72, 0x74, 
+	0x63, 0x75, 0x74, 0x20, 0x69, 0x63, 0x6F, 0x6E, 0x22, 0x20, 
+	0x68, 0x72, 0x65, 0x66, 0x3D, 0x22, 0x69, 0x6D, 0x67, 0x2F, 
+	0x66, 0x61, 0x76, 0x69, 0x63, 0x6F, 0x6E, 0x2E, 0x70, 0x6E, 
+	0x67, 0x22, 0x3E, 0x0A, 0x0A, 0x09, 0x09, 0x3C, 0x74, 0x69, 
+	0x74, 0x6C, 0x65, 0x3E, 0x48, 0x54, 0x54, 0x50, 0x20, 0x53, 
+	0x65, 0x72, 0x76, 0x65, 0x72, 0x3C, 0x2F, 0x74, 0x69, 0x74, 
+	0x6C, 0x65, 0x3E, 0x0A, 0x09, 0x3C, 0x2F, 0x68, 0x65, 0x61, 
+	0x64, 0x3E, 0x0A, 0x09, 0x3C, 0x62, 0x6F, 0x64, 0x79, 0x3E, 
+	0x0A, 0x09, 0x09, 0x3C, 0x75, 0x6C, 0x20, 0x63, 0x6C, 0x61, 
+	0x73, 0x73, 0x3D, 0x22, 0x6E, 0x61, 0x76, 0x62, 0x61, 0x72, 
+	0x22, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6C, 0x69, 0x3E, 
+	0x3C, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3D, 0x22, 0x2F, 
+	0x22, 0x3E, 0x48, 0x6F, 0x6D, 0x65, 0x3C, 0x2F, 0x61, 0x3E, 
+	0x3C, 0x2F, 0x6C, 0x69, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 
+	0x6C, 0x69, 0x3E, 0x3C, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 
+	0x3D, 0x22, 0x61, 0x62, 0x6F, 0x75, 0x74, 0x22, 0x3E, 0x41, 
+	0x62, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x61, 0x3E, 0x3C, 0x2F, 
+	0x6C, 0x69, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x75, 0x6C, 
+	0x3E, 0x0A, 0x0A, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x76, 0x20, 
+	0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x67, 0x72, 0x69, 
+	0x64, 0x20, 0x6D, 0x61, 0x69, 0x6E, 0x22, 0x3E, 0x0A, 0x09, 
+	0x09, 0x09, 0x3C, 0x68, 0x31, 0x3E, 0x34, 0x30, 0x34, 0x20, 
+	0x2D, 0x20, 0x50, 0x61, 0x67, 0x65, 0x20, 0x6E, 0x6F, 0x74, 
+	0x20, 0x66, 0x6F, 0x75, 0x6E, 0x64, 0x3C, 0x2F, 0x68, 0x31, 
+	0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x64, 0x69, 0x76, 0x20, 
+	0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x61, 0x6C, 0x65, 
+	0x72, 0x74, 0x20, 0x61, 0x6C, 0x65, 0x72, 0x74, 0x2D, 0x65, 
+	0x72, 0x72, 0x6F, 0x72, 0x22, 0x3E, 0x53, 0x6F, 0x72, 0x72, 
+	0x79, 0x2C, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x67, 
+	0x65, 0x20, 0x79, 0x6F, 0x75, 0x20, 0x61, 0x72, 0x65, 0x20, 
+	0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6E, 0x67, 
+	0x20, 0x77, 0x61, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x66, 
+	0x6F, 0x75, 0x6E, 0x64, 0x20, 0x6F, 0x6E, 0x20, 0x74, 0x68, 
+	0x69, 0x73, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2E, 
+	0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 
+	0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0A, 0x09, 0x3C, 0x2F, 0x62, 
+	0x6F, 0x64, 0x79, 0x3E, 0x0A, 0x3C, 0x2F, 0x68, 0x74, 0x6D, 
+	0x6C, 0x3E, 0x0A, 0x0A, };
+
+static const unsigned char data_about_html[] = {
+	/* /about.html */
+	0x2F, 0x61, 0x62, 0x6F, 0x75, 0x74, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0,
+	0x48, 0x54, 0x54, 0x50, 0x2F, 0x31, 0x2E, 0x30, 0x20, 0x32, 
+	0x30, 0x30, 0x20, 0x4F, 0x4B, 0x0D, 0x0A, 0x6C, 0x77, 0x49, 
+	0x50, 0x2F, 0x31, 0x2E, 0x34, 0x2E, 0x31, 0x20, 0x28, 0x68, 
+	0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x73, 0x61, 0x76, 0x61, 
+	0x6E, 0x6E, 0x61, 0x68, 0x2E, 0x6E, 0x6F, 0x6E, 0x67, 0x6E, 
+	0x75, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x70, 0x72, 0x6F, 0x6A, 
+	0x65, 0x63, 0x74, 0x73, 0x2F, 0x6C, 0x77, 0x69, 0x70, 0x29, 
+	0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x2D, 
+	0x74, 0x79, 0x70, 0x65, 0x3A, 0x20, 0x74, 0x65, 0x78, 0x74, 
+	0x2F, 0x68, 0x74, 0x6D, 0x6C, 0x0D, 0x0A, 0x0D, 0x0A, 0x3C, 
+	0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 
+	0x74, 0x6D, 0x6C, 0x3E, 0x0A, 0x3C, 0x68, 0x74, 0x6D, 0x6C, 
+	0x3E, 0x0A, 0x09, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x0A, 
+	0x09, 0x09, 0x3C, 0x6D, 0x65, 0x74, 0x61, 0x20, 0x63, 0x68, 
+	0x61, 0x72, 0x73, 0x65, 0x74, 0x3D, 0x22, 0x75, 0x74, 0x66, 
+	0x2D, 0x38, 0x22, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 0x6D, 0x65, 
+	0x74, 0x61, 0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3D, 0x22, 0x76, 
+	0x69, 0x65, 0x77, 0x70, 0x6F, 0x72, 0x74, 0x22, 0x20, 0x63, 
+	0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x3D, 0x22, 0x77, 0x69, 
+	0x64, 0x74, 0x68, 0x3D, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 
+	0x2D, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2C, 0x20, 0x75, 0x73, 
+	0x65, 0x72, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x61, 0x62, 0x6C, 
+	0x65, 0x3D, 0x6E, 0x6F, 0x22, 0x3E, 0x0A, 0x0A, 0x09, 0x09, 
+	0x3C, 0x6C, 0x69, 0x6E, 0x6B, 0x20, 0x72, 0x65, 0x6C, 0x3D, 
+	0x22, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x73, 0x68, 0x65, 0x65, 
+	0x74, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x74, 
+	0x65, 0x78, 0x74, 0x2F, 0x63, 0x73, 0x73, 0x22, 0x20, 0x68, 
+	0x72, 0x65, 0x66, 0x3D, 0x22, 0x63, 0x73, 0x73, 0x2F, 0x73, 
+	0x69, 0x69, 0x6D, 0x70, 0x6C, 0x65, 0x2E, 0x6D, 0x69, 0x6E, 
+	0x2E, 0x63, 0x73, 0x73, 0x22, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 
+	0x6C, 0x69, 0x6E, 0x6B, 0x20, 0x72, 0x65, 0x6C, 0x3D, 0x22, 
+	0x73, 0x74, 0x79, 0x6C, 0x65, 0x73, 0x68, 0x65, 0x65, 0x74, 
+	0x22, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x74, 0x65, 
+	0x78, 0x74, 0x2F, 0x63, 0x73, 0x73, 0x22, 0x20, 0x68, 0x72, 
+	0x65, 0x66, 0x3D, 0x22, 0x63, 0x73, 0x73, 0x2F, 0x73, 0x74, 
+	0x79, 0x6C, 0x65, 0x2E, 0x63, 0x73, 0x73, 0x22, 0x3E, 0x0A, 
+	0x09, 0x09, 0x3C, 0x6C, 0x69, 0x6E, 0x6B, 0x20, 0x72, 0x65, 
+	0x6C, 0x3D, 0x22, 0x73, 0x68, 0x6F, 0x72, 0x74, 0x63, 0x75, 
+	0x74, 0x20, 0x69, 0x63, 0x6F, 0x6E, 0x22, 0x20, 0x68, 0x72, 
+	0x65, 0x66, 0x3D, 0x22, 0x69, 0x6D, 0x67, 0x2F, 0x66, 0x61, 
+	0x76, 0x69, 0x63, 0x6F, 0x6E, 0x2E, 0x70, 0x6E, 0x67, 0x22, 
+	0x3E, 0x0A, 0x0A, 0x09, 0x09, 0x3C, 0x74, 0x69, 0x74, 0x6C, 
+	0x65, 0x3E, 0x48, 0x54, 0x54, 0x50, 0x20, 0x53, 0x65, 0x72, 
+	0x76, 0x65, 0x72, 0x3C, 0x2F, 0x74, 0x69, 0x74, 0x6C, 0x65, 
+	0x3E, 0x0A, 0x09, 0x3C, 0x2F, 0x68, 0x65, 0x61, 0x64, 0x3E, 
+	0x0A, 0x09, 0x3C, 0x62, 0x6F, 0x64, 0x79, 0x3E, 0x0A, 0x09, 
+	0x09, 0x3C, 0x75, 0x6C, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 
+	0x3D, 0x22, 0x6E, 0x61, 0x76, 0x62, 0x61, 0x72, 0x22, 0x3E, 
+	0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6C, 0x69, 0x3E, 0x3C, 0x61, 
+	0x20, 0x68, 0x72, 0x65, 0x66, 0x3D, 0x22, 0x2F, 0x22, 0x3E, 
+	0x48, 0x6F, 0x6D, 0x65, 0x3C, 0x2F, 0x61, 0x3E, 0x3C, 0x2F, 
+	0x6C, 0x69, 0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x6C, 0x69, 
+	0x3E, 0x3C, 0x61, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 
+	0x22, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x22, 0x20, 0x68, 
+	0x72, 0x65, 0x66, 0x3D, 0x22, 0x61, 0x62, 0x6F, 0x75, 0x74, 
+	0x22, 0x3E, 0x41, 0x62, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x61, 
+	0x3E, 0x3C, 0x2F, 0x6C, 0x69, 0x3E, 0x0A, 0x09, 0x09, 0x3C, 
+	0x2F, 0x75, 0x6C, 0x3E, 0x0A, 0x0A, 0x09, 0x09, 0x3C, 0x64, 
+	0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 
+	0x67, 0x72, 0x69, 0x64, 0x20, 0x6D, 0x61, 0x69, 0x6E, 0x22, 
+	0x3E, 0x0A, 0x09, 0x09, 0x09, 0x3C, 0x68, 0x31, 0x3E, 0x41, 
+	0x62, 0x6F, 0x75, 0x74, 0x3C, 0x2F, 0x68, 0x31, 0x3E, 0x0A, 
+	0x09, 0x09, 0x09, 0x3C, 0x70, 0x3E, 0x54, 0x68, 0x69, 0x73, 
+	0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x69, 0x73, 
+	0x20, 0x62, 0x75, 0x69, 0x6C, 0x74, 0x20, 0x6F, 0x6E, 0x20, 
+	0x68, 0x74, 0x74, 0x70, 0x64, 0x20, 0x66, 0x72, 0x6F, 0x6D, 
+	0x20, 0x4C, 0x77, 0x49, 0x50, 0x2E, 0x3C, 0x2F, 0x70, 0x3E, 
+	0x0A, 0x09, 0x09, 0x09, 0x3C, 0x70, 0x3E, 0x46, 0x6F, 0x72, 
+	0x20, 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x69, 0x6E, 0x66, 0x6F, 
+	0x20, 0x73, 0x65, 0x65, 0x20, 0x3C, 0x61, 0x20, 0x68, 0x72, 
+	0x65, 0x66, 0x3D, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 
+	0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6E, 0x6F, 0x6E, 0x67, 0x6E, 
+	0x75, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x6C, 0x77, 0x69, 0x70, 
+	0x2F, 0x32, 0x5F, 0x30, 0x5F, 0x30, 0x2F, 0x67, 0x72, 0x6F, 
+	0x75, 0x70, 0x5F, 0x5F, 0x68, 0x74, 0x74, 0x70, 0x64, 0x2E, 
+	0x68, 0x74, 0x6D, 0x6C, 0x22, 0x3E, 0x48, 0x54, 0x54, 0x50, 
+	0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x64, 0x6F, 
+	0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x61, 0x74, 0x69, 0x6F, 
+	0x6E, 0x3C, 0x2F, 0x61, 0x3E, 0x2E, 0x3C, 0x2F, 0x70, 0x3E, 
+	0x0A, 0x09, 0x09, 0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0A, 
+	0x09, 0x3C, 0x2F, 0x62, 0x6F, 0x64, 0x79, 0x3E, 0x0A, 0x3C, 
+	0x2F, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0A, 0x0A, };
+
+static const unsigned char data_img_favicon_png[] = {
+	/* /img/favicon.png */
+	0x2F, 0x69, 0x6D, 0x67, 0x2F, 0x66, 0x61, 0x76, 0x69, 0x63, 0x6F, 0x6E, 0x2E, 0x70, 0x6E, 0x67, 0,
+	0x48, 0x54, 0x54, 0x50, 0x2F, 0x31, 0x2E, 0x30, 0x20, 0x32, 
+	0x30, 0x30, 0x20, 0x4F, 0x4B, 0x0D, 0x0A, 0x6C, 0x77, 0x49, 
+	0x50, 0x2F, 0x31, 0x2E, 0x34, 0x2E, 0x31, 0x20, 0x28, 0x68, 
+	0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x73, 0x61, 0x76, 0x61, 
+	0x6E, 0x6E, 0x61, 0x68, 0x2E, 0x6E, 0x6F, 0x6E, 0x67, 0x6E, 
+	0x75, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x70, 0x72, 0x6F, 0x6A, 
+	0x65, 0x63, 0x74, 0x73, 0x2F, 0x6C, 0x77, 0x69, 0x70, 0x29, 
+	0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x2D, 
+	0x74, 0x79, 0x70, 0x65, 0x3A, 0x20, 0x69, 0x6D, 0x61, 0x67, 
+	0x65, 0x2F, 0x70, 0x6E, 0x67, 0x0D, 0x0A, 0x0D, 0x0A, 0x89, 
+	0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 
+	0x0D, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 
+	0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1F, 0xF3, 
+	0xFF, 0x61, 0x00, 0x00, 0x02, 0xBF, 0x49, 0x44, 0x41, 0x54, 
+	0x38, 0xCB, 0xA5, 0x92, 0x4F, 0x6C, 0x14, 0x75, 0x14, 0xC7, 
+	0x3F, 0x3B, 0x3B, 0x33, 0xFB, 0xBF, 0xBB, 0x74, 0x59, 0xD8, 
+	0xA5, 0xC5, 0x76, 0x4B, 0x65, 0x6B, 0x49, 0x10, 0x41, 0x41, 
+	0x20, 0x84, 0xD2, 0x80, 0x6D, 0x6C, 0x62, 0x80, 0xC4, 0x78, 
+	0xF1, 0x64, 0xD2, 0x93, 0x89, 0x77, 0xF1, 0xE4, 0xD9, 0x83, 
+	0x37, 0x63, 0x3C, 0xE0, 0xC5, 0x43, 0x2F, 0x46, 0x23, 0x90, 
+	0x70, 0x30, 0x01, 0xA5, 0x6A, 0x29, 0x2D, 0x65, 0xA1, 0x14, 
+	0xD3, 0xAD, 0x08, 0xBB, 0x9A, 0xD9, 0xA6, 0xBB, 0x65, 0xF6, 
+	0x5F, 0x67, 0x77, 0xE7, 0x37, 0xF3, 0xF3, 0x62, 0xD7, 0xA6, 
+	0xE2, 0xC9, 0x77, 0x79, 0x2F, 0x2F, 0xEF, 0xFB, 0xC9, 0x37, 
+	0x2F, 0x5F, 0xF8, 0x9F, 0xE5, 0xD9, 0xBE, 0x78, 0x77, 0xF2, 
+	0x83, 0x54, 0xA2, 0x7F, 0xF8, 0x13, 0xAF, 0x2F, 0xFC, 0xB6, 
+	0xAB, 0x06, 0xF4, 0xEE, 0xB0, 0x9F, 0xDB, 0xF3, 0xD9, 0x92, 
+	0x91, 0x5F, 0xF9, 0x72, 0xEE, 0xDA, 0xE5, 0x4B, 0x80, 0xF8, 
+	0x4F, 0xC0, 0x89, 0x8B, 0xEF, 0xBF, 0x63, 0x05, 0x52, 0x53, 
+	0x17, 0x26, 0xC6, 0x19, 0x39, 0xD4, 0x47, 0xD0, 0xA7, 0x52, 
+	0xB1, 0xDA, 0x2C, 0x3D, 0x2D, 0xF3, 0xFD, 0x4F, 0x77, 0x29, 
+	0xAE, 0x64, 0x6D, 0xBF, 0x65, 0xBC, 0xF2, 0xC3, 0x95, 0xAF, 
+	0x1E, 0x6E, 0x6A, 0x94, 0x8E, 0x7A, 0xE7, 0xD1, 0xB1, 0xAA, 
+	0x9E, 0x9A, 0x7A, 0x61, 0xE8, 0x30, 0xAA, 0x3F, 0x84, 0x5F, 
+	0x53, 0xD8, 0xB7, 0x3B, 0x44, 0x40, 0xF3, 0x52, 0x6D, 0x41, 
+	0xAA, 0xA7, 0x8F, 0x57, 0x8F, 0x9F, 0xD6, 0x0E, 0x1D, 0x3B, 
+	0xB5, 0x08, 0xEC, 0xD9, 0x94, 0x79, 0x37, 0x07, 0x2D, 0x73, 
+	0x26, 0x77, 0x76, 0x74, 0xD4, 0xB3, 0x27, 0xB9, 0x8B, 0xC1, 
+	0x54, 0x17, 0x89, 0xA8, 0x1F, 0xAB, 0xED, 0x10, 0xF6, 0xAB, 
+	0xEC, 0x8D, 0x07, 0xD1, 0x75, 0x8D, 0x74, 0x32, 0x8A, 0xA2, 
+	0xFA, 0x88, 0xEC, 0xDA, 0x7B, 0xEE, 0xD1, 0xDC, 0x8F, 0x9F, 
+	0x77, 0x1C, 0x4C, 0xBC, 0xF7, 0xE1, 0xE4, 0x81, 0xE1, 0x03, 
+	0x9E, 0xA6, 0x03, 0x45, 0xB3, 0xC9, 0xFE, 0x54, 0x84, 0xB6, 
+	0x70, 0x51, 0x14, 0x0F, 0xEB, 0xF5, 0x36, 0x56, 0x5B, 0xD0, 
+	0xDB, 0x1D, 0xC4, 0xA7, 0xAB, 0x44, 0x23, 0x61, 0x32, 0x99, 
+	0xCC, 0x41, 0xD8, 0x99, 0xE9, 0x00, 0xA2, 0xB1, 0xEE, 0xB1, 
+	0x42, 0xA9, 0x8E, 0xEB, 0xBA, 0x9C, 0x3F, 0xDA, 0x83, 0x69, 
+	0xD9, 0xE4, 0x8C, 0x1A, 0xCB, 0x46, 0x8D, 0xAA, 0x65, 0x53, 
+	0x6B, 0x0A, 0x5A, 0xB6, 0x4D, 0x2C, 0xA4, 0x23, 0x5C, 0x49, 
+	0x38, 0x12, 0x63, 0x68, 0x64, 0x74, 0xBC, 0x03, 0x10, 0xAE, 
+	0x4C, 0xB9, 0xAE, 0x64, 0xF4, 0xE5, 0x5E, 0xBA, 0x02, 0x2A, 
+	0xAE, 0x10, 0x44, 0x83, 0x1A, 0xB3, 0x2B, 0xEB, 0xAC, 0x18, 
+	0x35, 0xCC, 0x5A, 0x93, 0xC7, 0x46, 0x85, 0xB6, 0xED, 0x20, 
+	0xA5, 0x8B, 0x70, 0x1C, 0xF6, 0xA7, 0xFB, 0x77, 0x77, 0x00, 
+	0xD9, 0xA5, 0x5C, 0xA9, 0x65, 0x35, 0x28, 0x99, 0x75, 0x2A, 
+	0xB5, 0x06, 0x21, 0x5D, 0xC1, 0x15, 0x36, 0xC7, 0x06, 0xBA, 
+	0xF0, 0x79, 0x5D, 0x14, 0x1C, 0xE2, 0x61, 0x15, 0x29, 0x1D, 
+	0x14, 0x24, 0x9A, 0xD7, 0xC3, 0xAD, 0x3B, 0xD9, 0xF5, 0xCE, 
+	0x13, 0xCB, 0x76, 0x24, 0xB9, 0x6F, 0xA0, 0x6F, 0xBC, 0x58, 
+	0xB5, 0x69, 0xD8, 0x92, 0x54, 0x3C, 0x4C, 0xAB, 0x2D, 0x10, 
+	0xC2, 0xE1, 0x59, 0x75, 0x03, 0x9F, 0xEA, 0x21, 0xF7, 0x47, 
+	0x09, 0x5C, 0x87, 0x46, 0xA3, 0x4E, 0x76, 0x71, 0x89, 0xD9, 
+	0x6F, 0xAF, 0x5E, 0x82, 0x8A, 0xA1, 0x02, 0xD0, 0x58, 0xFB, 
+	0xAC, 0x55, 0x2B, 0x7F, 0x3A, 0x3D, 0x6B, 0xA2, 0xA9, 0x5E, 
+	0xCE, 0x1E, 0xEE, 0x47, 0x91, 0x12, 0xC7, 0x71, 0x09, 0xEA, 
+	0x1E, 0x96, 0xF3, 0xAB, 0xDC, 0x5B, 0xFE, 0x93, 0x2B, 0x86, 
+	0x01, 0x96, 0x89, 0x59, 0xFC, 0xBD, 0x00, 0xF9, 0xF9, 0x7F, 
+	0x72, 0x50, 0x5E, 0x6A, 0x0F, 0xF7, 0x27, 0x26, 0x69, 0x94, 
+	0xA8, 0x9B, 0x25, 0x56, 0xD7, 0xCA, 0x94, 0xD6, 0x4D, 0x76, 
+	0x84, 0x34, 0x16, 0x73, 0x79, 0xA6, 0xAE, 0xCF, 0x50, 0x28, 
+	0x14, 0x58, 0x98, 0xBF, 0xC7, 0x6F, 0xB9, 0x5F, 0xF1, 0x79, 
+	0xDD, 0x37, 0xFF, 0x95, 0x83, 0xDC, 0xC2, 0xF4, 0xDD, 0x93, 
+	0x23, 0xE7, 0x64, 0x2C, 0xA4, 0x9F, 0x39, 0xF2, 0x52, 0x1A, 
+	0x21, 0x04, 0x5F, 0x7C, 0x7D, 0x93, 0xEF, 0x6E, 0xCC, 0xB1, 
+	0x56, 0x28, 0xF0, 0xC6, 0xEB, 0x83, 0x2C, 0x3E, 0xB8, 0x4F, 
+	0x44, 0x97, 0xE3, 0xF9, 0x99, 0x6F, 0x7E, 0x79, 0x5E, 0x94, 
+	0x35, 0x20, 0x46, 0xA0, 0xE7, 0xAD, 0x17, 0x5F, 0x3B, 0xF5, 
+	0x91, 0xF0, 0x06, 0xD3, 0x89, 0xF8, 0x0E, 0x1E, 0x3D, 0x2E, 
+	0x30, 0xD8, 0x9B, 0x60, 0x61, 0x7A, 0x3A, 0xCB, 0xC6, 0x93, 
+	0x8F, 0x69, 0x56, 0x1E, 0x00, 0x06, 0xB0, 0x01, 0xC8, 0xED, 
+	0x80, 0xF8, 0xDF, 0x31, 0x8D, 0x00, 0xE1, 0x58, 0x32, 0x9D, 
+	0x1C, 0x1A, 0xE8, 0x95, 0x33, 0x3F, 0xDF, 0x2A, 0x02, 0x36, 
+	0xD0, 0x00, 0x56, 0x81, 0xE2, 0xF3, 0x00, 0xDB, 0x5D, 0x79, 
+	0xB6, 0xCC, 0x72, 0x4B, 0x97, 0x5B, 0x8F, 0xFF, 0x02, 0x78, 
+	0x99, 0x27, 0xDD, 0x60, 0x50, 0xF9, 0x07, 0x00, 0x00, 0x00, 
+	0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82, };
+
+static const unsigned char data_css_siimple_min_css[] = {
+	/* /css/siimple.min.css */
+	0x2F, 0x63, 0x73, 0x73, 0x2F, 0x73, 0x69, 0x69, 0x6D, 0x70, 0x6C, 0x65, 0x2E, 0x6D, 0x69, 0x6E, 0x2E, 0x63, 0x73, 0x73, 0,
+	0x48, 0x54, 0x54, 0x50, 0x2F, 0x31, 0x2E, 0x30, 0x20, 0x32, 
+	0x30, 0x30, 0x20, 0x4F, 0x4B, 0x0D, 0x0A, 0x6C, 0x77, 0x49, 
+	0x50, 0x2F, 0x31, 0x2E, 0x34, 0x2E, 0x31, 0x20, 0x28, 0x68, 
+	0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x73, 0x61, 0x76, 0x61, 
+	0x6E, 0x6E, 0x61, 0x68, 0x2E, 0x6E, 0x6F, 0x6E, 0x67, 0x6E, 
+	0x75, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x70, 0x72, 0x6F, 0x6A, 
+	0x65, 0x63, 0x74, 0x73, 0x2F, 0x6C, 0x77, 0x69, 0x70, 0x29, 
+	0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x2D, 
+	0x74, 0x79, 0x70, 0x65, 0x3A, 0x20, 0x74, 0x65, 0x78, 0x74, 
+	0x2F, 0x63, 0x73, 0x73, 0x0D, 0x0A, 0x0D, 0x0A, 0x0D, 0x0A, 
+	0x2F, 0x2A, 0x2A, 0x0A, 0x20, 0x2A, 0x20, 0x73, 0x69, 0x69, 
+	0x6D, 0x70, 0x6C, 0x65, 0x20, 0x2D, 0x20, 0x4D, 0x69, 0x6E, 
+	0x69, 0x6D, 0x61, 0x6C, 0x20, 0x43, 0x53, 0x53, 0x20, 0x66, 
+	0x72, 0x61, 0x6D, 0x65, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x66, 
+	0x6F, 0x72, 0x20, 0x66, 0x6C, 0x61, 0x74, 0x20, 0x61, 0x6E, 
+	0x64, 0x20, 0x63, 0x6C, 0x65, 0x61, 0x6E, 0x20, 0x64, 0x65, 
+	0x73, 0x69, 0x67, 0x6E, 0x73, 0x2E, 0x0A, 0x20, 0x2A, 0x20, 
+	0x40, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x76, 
+	0x31, 0x2E, 0x33, 0x2E, 0x37, 0x0A, 0x20, 0x2A, 0x20, 0x40, 
+	0x6C, 0x69, 0x6E, 0x6B, 0x20, 0x68, 0x74, 0x74, 0x70, 0x73, 
+	0x3A, 0x2F, 0x2F, 0x73, 0x69, 0x69, 0x6D, 0x70, 0x6C, 0x65, 
+	0x2E, 0x6A, 0x75, 0x61, 0x6E, 0x65, 0x73, 0x2E, 0x78, 0x79, 
+	0x7A, 0x2F, 0x0A, 0x20, 0x2A, 0x20, 0x40, 0x6C, 0x69, 0x63, 
+	0x65, 0x6E, 0x73, 0x65, 0x20, 0x4D, 0x49, 0x54, 0x0A, 0x20, 
+	0x2A, 0x2F, 0x0A, 0x0A, 0x40, 0x69, 0x6D, 0x70, 0x6F, 0x72, 
+	0x74, 0x20, 0x75, 0x72, 0x6C, 0x28, 0x68, 0x74, 0x74, 0x70, 
+	0x73, 0x3A, 0x2F, 0x2F, 0x66, 0x6F, 0x6E, 0x74, 0x73, 0x2E, 
+	0x67, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x61, 0x70, 0x69, 0x73, 
+	0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x63, 0x73, 0x73, 0x3F, 0x66, 
+	0x61, 0x6D, 0x69, 0x6C, 0x79, 0x3D, 0x4F, 0x70, 0x65, 0x6E, 
+	0x2B, 0x53, 0x61, 0x6E, 0x73, 0x3A, 0x34, 0x30, 0x30, 0x2C, 
+	0x33, 0x30, 0x30, 0x29, 0x3B, 0x6F, 0x6C, 0x2C, 0x6F, 0x6C, 
+	0x20, 0x6C, 0x69, 0x2C, 0x70, 0x2C, 0x75, 0x6C, 0x2C, 0x75, 
+	0x6C, 0x20, 0x6C, 0x69, 0x7B, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 
+	0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x32, 0x38, 0x70, 
+	0x78, 0x7D, 0x2E, 0x61, 0x6C, 0x65, 0x72, 0x74, 0x2C, 0x70, 
+	0x72, 0x65, 0x7B, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x63, 
+	0x61, 0x6C, 0x63, 0x28, 0x31, 0x30, 0x30, 0x25, 0x20, 0x2D, 
+	0x20, 0x33, 0x30, 0x70, 0x78, 0x29, 0x7D, 0x2E, 0x61, 0x6C, 
+	0x65, 0x72, 0x74, 0x2C, 0x2E, 0x62, 0x74, 0x6E, 0x7B, 0x62, 
+	0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 
+	0x75, 0x73, 0x3A, 0x35, 0x70, 0x78, 0x7D, 0x2E, 0x68, 0x65, 
+	0x61, 0x72, 0x74, 0x3A, 0x61, 0x66, 0x74, 0x65, 0x72, 0x7B, 
+	0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x3A, 0x22, 0x5C, 
+	0x32, 0x37, 0x36, 0x34, 0x22, 0x3B, 0x63, 0x6F, 0x6C, 0x6F, 
+	0x72, 0x3A, 0x23, 0x66, 0x34, 0x35, 0x36, 0x36, 0x30, 0x7D, 
+	0x62, 0x6F, 0x64, 0x79, 0x2C, 0x68, 0x31, 0x2C, 0x68, 0x32, 
+	0x2C, 0x68, 0x33, 0x2C, 0x68, 0x34, 0x2C, 0x68, 0x35, 0x2C, 
+	0x68, 0x36, 0x7B, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 
+	0x35, 0x32, 0x36, 0x34, 0x37, 0x35, 0x7D, 0x62, 0x6F, 0x64, 
+	0x79, 0x7B, 0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x3A, 0x30, 
+	0x3B, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x30, 
+	0x3B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x66, 0x61, 0x6D, 0x69, 
+	0x6C, 0x79, 0x3A, 0x27, 0x4F, 0x70, 0x65, 0x6E, 0x20, 0x53, 
+	0x61, 0x6E, 0x73, 0x27, 0x3B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 
+	0x73, 0x69, 0x7A, 0x65, 0x3A, 0x31, 0x36, 0x70, 0x78, 0x3B, 
+	0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x77, 0x65, 0x69, 0x67, 0x68, 
+	0x74, 0x3A, 0x33, 0x30, 0x30, 0x3B, 0x62, 0x61, 0x63, 0x6B, 
+	0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x63, 0x6F, 0x6C, 
+	0x6F, 0x72, 0x3A, 0x23, 0x66, 0x66, 0x66, 0x7D, 0x2E, 0x61, 
+	0x6C, 0x65, 0x72, 0x74, 0x20, 0x61, 0x2C, 0x61, 0x7B, 0x74, 
+	0x65, 0x78, 0x74, 0x2D, 0x64, 0x65, 0x63, 0x6F, 0x72, 0x61, 
+	0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 
+	0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x77, 0x65, 0x69, 0x67, 0x68, 
+	0x74, 0x3A, 0x34, 0x30, 0x30, 0x7D, 0x62, 0x6C, 0x6F, 0x63, 
+	0x6B, 0x71, 0x75, 0x6F, 0x74, 0x65, 0x7B, 0x62, 0x6F, 0x72, 
+	0x64, 0x65, 0x72, 0x2D, 0x6C, 0x65, 0x66, 0x74, 0x3A, 0x34, 
+	0x70, 0x78, 0x20, 0x73, 0x6F, 0x6C, 0x69, 0x64, 0x20, 0x23, 
+	0x36, 0x61, 0x37, 0x65, 0x39, 0x35, 0x3B, 0x70, 0x61, 0x64, 
+	0x64, 0x69, 0x6E, 0x67, 0x3A, 0x35, 0x70, 0x78, 0x20, 0x35, 
+	0x70, 0x78, 0x20, 0x35, 0x70, 0x78, 0x20, 0x32, 0x30, 0x70, 
+	0x78, 0x7D, 0x61, 0x7B, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 
+	0x23, 0x30, 0x39, 0x61, 0x30, 0x66, 0x36, 0x3B, 0x74, 0x72, 
+	0x61, 0x6E, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x61, 
+	0x6C, 0x6C, 0x20, 0x2E, 0x33, 0x73, 0x7D, 0x61, 0x3A, 0x68, 
+	0x6F, 0x76, 0x65, 0x72, 0x7B, 0x74, 0x65, 0x78, 0x74, 0x2D, 
+	0x64, 0x65, 0x63, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 
+	0x3A, 0x75, 0x6E, 0x64, 0x65, 0x72, 0x6C, 0x69, 0x6E, 0x65, 
+	0x3B, 0x63, 0x75, 0x72, 0x73, 0x6F, 0x72, 0x3A, 0x70, 0x6F, 
+	0x69, 0x6E, 0x74, 0x65, 0x72, 0x7D, 0x70, 0x7B, 0x6D, 0x61, 
+	0x72, 0x67, 0x69, 0x6E, 0x2D, 0x62, 0x6F, 0x74, 0x74, 0x6F, 
+	0x6D, 0x3A, 0x32, 0x30, 0x70, 0x78, 0x3B, 0x6D, 0x61, 0x72, 
+	0x67, 0x69, 0x6E, 0x2D, 0x74, 0x6F, 0x70, 0x3A, 0x30, 0x3B, 
+	0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x62, 0x6C, 
+	0x6F, 0x63, 0x6B, 0x7D, 0x6F, 0x6C, 0x2C, 0x75, 0x6C, 0x7B, 
+	0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x2D, 0x62, 0x6F, 0x74, 
+	0x74, 0x6F, 0x6D, 0x3A, 0x31, 0x36, 0x70, 0x78, 0x3B, 0x6D, 
+	0x61, 0x72, 0x67, 0x69, 0x6E, 0x2D, 0x74, 0x6F, 0x70, 0x3A, 
+	0x30, 0x7D, 0x2E, 0x61, 0x6C, 0x65, 0x72, 0x74, 0x2C, 0x68, 
+	0x31, 0x2C, 0x68, 0x32, 0x2C, 0x68, 0x33, 0x2C, 0x68, 0x34, 
+	0x2C, 0x68, 0x35, 0x2C, 0x68, 0x36, 0x7B, 0x66, 0x6F, 0x6E, 
+	0x74, 0x2D, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x33, 
+	0x30, 0x30, 0x3B, 0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x2D, 
+	0x74, 0x6F, 0x70, 0x3A, 0x30, 0x3B, 0x6D, 0x61, 0x72, 0x67, 
+	0x69, 0x6E, 0x2D, 0x62, 0x6F, 0x74, 0x74, 0x6F, 0x6D, 0x3A, 
+	0x32, 0x30, 0x70, 0x78, 0x3B, 0x64, 0x69, 0x73, 0x70, 0x6C, 
+	0x61, 0x79, 0x3A, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x7D, 0x73, 
+	0x6D, 0x61, 0x6C, 0x6C, 0x7B, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 
+	0x3A, 0x23, 0x36, 0x61, 0x37, 0x65, 0x39, 0x35, 0x3B, 0x66, 
+	0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x31, 
+	0x34, 0x70, 0x78, 0x7D, 0x68, 0x31, 0x7B, 0x66, 0x6F, 0x6E, 
+	0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x33, 0x36, 0x70, 
+	0x78, 0x3B, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 
+	0x67, 0x68, 0x74, 0x3A, 0x35, 0x30, 0x70, 0x78, 0x7D, 0x68, 
+	0x32, 0x7B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 
+	0x65, 0x3A, 0x33, 0x32, 0x70, 0x78, 0x3B, 0x6C, 0x69, 0x6E, 
+	0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x34, 
+	0x36, 0x70, 0x78, 0x7D, 0x68, 0x33, 0x7B, 0x66, 0x6F, 0x6E, 
+	0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x32, 0x38, 0x70, 
+	0x78, 0x3B, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 
+	0x67, 0x68, 0x74, 0x3A, 0x34, 0x32, 0x70, 0x78, 0x7D, 0x68, 
+	0x34, 0x7B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 
+	0x65, 0x3A, 0x32, 0x34, 0x70, 0x78, 0x3B, 0x6C, 0x69, 0x6E, 
+	0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x33, 
+	0x38, 0x70, 0x78, 0x7D, 0x68, 0x35, 0x7B, 0x66, 0x6F, 0x6E, 
+	0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x32, 0x30, 0x70, 
+	0x78, 0x3B, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 
+	0x67, 0x68, 0x74, 0x3A, 0x33, 0x34, 0x70, 0x78, 0x7D, 0x2E, 
+	0x61, 0x6C, 0x65, 0x72, 0x74, 0x2C, 0x2E, 0x62, 0x74, 0x6E, 
+	0x2C, 0x68, 0x36, 0x7B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 
+	0x69, 0x7A, 0x65, 0x3A, 0x31, 0x36, 0x70, 0x78, 0x7D, 0x68, 
+	0x36, 0x7B, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 
+	0x67, 0x68, 0x74, 0x3A, 0x33, 0x30, 0x70, 0x78, 0x7D, 0x2E, 
+	0x61, 0x6C, 0x65, 0x72, 0x74, 0x7B, 0x74, 0x65, 0x78, 0x74, 
+	0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x6C, 0x65, 0x66, 
+	0x74, 0x3B, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x77, 
+	0x69, 0x64, 0x74, 0x68, 0x3A, 0x31, 0x70, 0x78, 0x3B, 0x62, 
+	0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x73, 0x74, 0x79, 0x6C, 
+	0x65, 0x3A, 0x73, 0x6F, 0x6C, 0x69, 0x64, 0x3B, 0x62, 0x61, 
+	0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x63, 
+	0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x45, 0x31, 0x46, 0x35, 
+	0x46, 0x45, 0x3B, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 
+	0x30, 0x33, 0x41, 0x39, 0x46, 0x34, 0x3B, 0x62, 0x6F, 0x72, 
+	0x64, 0x65, 0x72, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 
+	0x23, 0x30, 0x33, 0x41, 0x39, 0x46, 0x34, 0x3B, 0x70, 0x61, 
+	0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x31, 0x36, 0x70, 0x78, 
+	0x20, 0x31, 0x34, 0x70, 0x78, 0x3B, 0x70, 0x61, 0x64, 0x64, 
+	0x69, 0x6E, 0x67, 0x3A, 0x31, 0x36, 0x70, 0x78, 0x20, 0x31, 
+	0x34, 0x70, 0x78, 0x3B, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 
+	0x67, 0x3A, 0x31, 0x36, 0x70, 0x78, 0x20, 0x31, 0x34, 0x70, 
+	0x78, 0x7D, 0x2E, 0x62, 0x74, 0x6E, 0x2C, 0x2E, 0x62, 0x74, 
+	0x6E, 0x2D, 0x6F, 0x75, 0x74, 0x6C, 0x69, 0x6E, 0x65, 0x7B, 
+	0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x66, 0x61, 0x6D, 0x69, 0x6C, 
+	0x79, 0x3A, 0x27, 0x4F, 0x70, 0x65, 0x6E, 0x20, 0x53, 0x61, 
+	0x6E, 0x73, 0x27, 0x3B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x77, 
+	0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x33, 0x30, 0x30, 0x3B, 
+	0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x69, 0x6E, 
+	0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 
+	0x3B, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x69, 0x74, 0x69, 0x6F, 
+	0x6E, 0x3A, 0x61, 0x6C, 0x6C, 0x20, 0x2E, 0x33, 0x73, 0x3B, 
+	0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x74, 0x6F, 
+	0x75, 0x63, 0x68, 0x2D, 0x63, 0x61, 0x6C, 0x6C, 0x6F, 0x75, 
+	0x74, 0x3A, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x2D, 0x6B, 0x68, 
+	0x74, 0x6D, 0x6C, 0x2D, 0x75, 0x73, 0x65, 0x72, 0x2D, 0x73, 
+	0x65, 0x6C, 0x65, 0x63, 0x74, 0x3A, 0x6E, 0x6F, 0x6E, 0x65, 
+	0x3B, 0x2D, 0x6D, 0x6F, 0x7A, 0x2D, 0x75, 0x73, 0x65, 0x72, 
+	0x2D, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x3A, 0x6E, 0x6F, 
+	0x6E, 0x65, 0x3B, 0x2D, 0x6D, 0x73, 0x2D, 0x75, 0x73, 0x65, 
+	0x72, 0x2D, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x3A, 0x6E, 
+	0x6F, 0x6E, 0x65, 0x3B, 0x74, 0x65, 0x78, 0x74, 0x2D, 0x61, 
+	0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x63, 0x65, 0x6E, 0x74, 0x65, 
+	0x72, 0x3B, 0x63, 0x75, 0x72, 0x73, 0x6F, 0x72, 0x3A, 0x70, 
+	0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x3B, 0x6D, 0x61, 0x72, 
+	0x67, 0x69, 0x6E, 0x3A, 0x35, 0x70, 0x78, 0x20, 0x35, 0x70, 
+	0x78, 0x20, 0x32, 0x30, 0x70, 0x78, 0x7D, 0x2E, 0x61, 0x6C, 
+	0x65, 0x72, 0x74, 0x2D, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x7B, 
+	0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x44, 0x33, 0x32, 
+	0x46, 0x32, 0x46, 0x3B, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 
+	0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 
+	0x3A, 0x23, 0x46, 0x46, 0x45, 0x42, 0x45, 0x45, 0x3B, 0x62, 
+	0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 
+	0x72, 0x3A, 0x23, 0x46, 0x34, 0x34, 0x33, 0x33, 0x36, 0x7D, 
+	0x2E, 0x61, 0x6C, 0x65, 0x72, 0x74, 0x2D, 0x77, 0x61, 0x72, 
+	0x6E, 0x69, 0x6E, 0x67, 0x7B, 0x62, 0x61, 0x63, 0x6B, 0x67, 
+	0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 
+	0x72, 0x3A, 0x23, 0x46, 0x46, 0x46, 0x38, 0x45, 0x31, 0x3B, 
+	0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x46, 0x46, 0x38, 
+	0x46, 0x30, 0x30, 0x3B, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 
+	0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x46, 0x46, 
+	0x43, 0x31, 0x30, 0x37, 0x7D, 0x2E, 0x61, 0x6C, 0x65, 0x72, 
+	0x74, 0x2D, 0x64, 0x6F, 0x6E, 0x65, 0x7B, 0x62, 0x61, 0x63, 
+	0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x63, 0x6F, 
+	0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x45, 0x38, 0x46, 0x35, 0x45, 
+	0x39, 0x3B, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x33, 
+	0x38, 0x38, 0x45, 0x33, 0x43, 0x3B, 0x62, 0x6F, 0x72, 0x64, 
+	0x65, 0x72, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 
+	0x34, 0x43, 0x41, 0x46, 0x35, 0x30, 0x7D, 0x2E, 0x62, 0x74, 
+	0x6E, 0x7B, 0x74, 0x65, 0x78, 0x74, 0x2D, 0x64, 0x65, 0x63, 
+	0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x6E, 0x6F, 
+	0x6E, 0x65, 0x21, 0x69, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x61, 
+	0x6E, 0x74, 0x3B, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 
+	0x69, 0x67, 0x68, 0x74, 0x3A, 0x32, 0x38, 0x70, 0x78, 0x3B, 
+	0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x66, 0x66, 0x66, 
+	0x3B, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 
+	0x64, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x30, 
+	0x39, 0x61, 0x30, 0x66, 0x36, 0x3B, 0x62, 0x6F, 0x72, 0x64, 
+	0x65, 0x72, 0x3A, 0x30, 0x3B, 0x70, 0x61, 0x64, 0x64, 0x69, 
+	0x6E, 0x67, 0x3A, 0x35, 0x70, 0x78, 0x20, 0x32, 0x35, 0x70, 
+	0x78, 0x7D, 0x2E, 0x62, 0x74, 0x6E, 0x3A, 0x68, 0x6F, 0x76, 
+	0x65, 0x72, 0x7B, 0x74, 0x65, 0x78, 0x74, 0x2D, 0x64, 0x65, 
+	0x63, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x6E, 
+	0x6F, 0x6E, 0x65, 0x3B, 0x6F, 0x70, 0x61, 0x63, 0x69, 0x74, 
+	0x79, 0x3A, 0x2E, 0x38, 0x7D, 0x2E, 0x62, 0x74, 0x6E, 0x2D, 
+	0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x7B, 0x66, 0x6F, 0x6E, 0x74, 
+	0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x31, 0x34, 0x70, 0x78, 
+	0x21, 0x69, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x61, 0x6E, 0x74, 
+	0x3B, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 
+	0x68, 0x74, 0x3A, 0x32, 0x30, 0x70, 0x78, 0x21, 0x69, 0x6D, 
+	0x70, 0x6F, 0x72, 0x74, 0x61, 0x6E, 0x74, 0x3B, 0x70, 0x61, 
+	0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x34, 0x70, 0x78, 0x20, 
+	0x31, 0x35, 0x70, 0x78, 0x21, 0x69, 0x6D, 0x70, 0x6F, 0x72, 
+	0x74, 0x61, 0x6E, 0x74, 0x7D, 0x2E, 0x62, 0x74, 0x6E, 0x2D, 
+	0x62, 0x69, 0x67, 0x7B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 
+	0x69, 0x7A, 0x65, 0x3A, 0x32, 0x32, 0x70, 0x78, 0x21, 0x69, 
+	0x6D, 0x70, 0x6F, 0x72, 0x74, 0x61, 0x6E, 0x74, 0x3B, 0x6C, 
+	0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 
+	0x3A, 0x33, 0x34, 0x70, 0x78, 0x21, 0x69, 0x6D, 0x70, 0x6F, 
+	0x72, 0x74, 0x61, 0x6E, 0x74, 0x3B, 0x70, 0x61, 0x64, 0x64, 
+	0x69, 0x6E, 0x67, 0x3A, 0x38, 0x70, 0x78, 0x20, 0x33, 0x30, 
+	0x70, 0x78, 0x21, 0x69, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x61, 
+	0x6E, 0x74, 0x7D, 0x2E, 0x62, 0x74, 0x6E, 0x2D, 0x6F, 0x75, 
+	0x74, 0x6C, 0x69, 0x6E, 0x65, 0x2C, 0x70, 0x72, 0x65, 0x7B, 
+	0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 
+	0x74, 0x3A, 0x32, 0x38, 0x70, 0x78, 0x7D, 0x2E, 0x62, 0x74, 
+	0x6E, 0x2D, 0x6F, 0x75, 0x74, 0x6C, 0x69, 0x6E, 0x65, 0x7B, 
+	0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 
+	0x31, 0x36, 0x70, 0x78, 0x3B, 0x74, 0x65, 0x78, 0x74, 0x2D, 
+	0x64, 0x65, 0x63, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 
+	0x3A, 0x6E, 0x6F, 0x6E, 0x65, 0x21, 0x69, 0x6D, 0x70, 0x6F, 
+	0x72, 0x74, 0x61, 0x6E, 0x74, 0x3B, 0x62, 0x6F, 0x72, 0x64, 
+	0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 
+	0x35, 0x70, 0x78, 0x3B, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 
+	0x23, 0x30, 0x39, 0x61, 0x30, 0x66, 0x36, 0x3B, 0x62, 0x61, 
+	0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x63, 
+	0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x74, 0x72, 0x61, 0x6E, 0x73, 
+	0x70, 0x61, 0x72, 0x65, 0x6E, 0x74, 0x3B, 0x62, 0x6F, 0x72, 
+	0x64, 0x65, 0x72, 0x3A, 0x31, 0x70, 0x78, 0x20, 0x73, 0x6F, 
+	0x6C, 0x69, 0x64, 0x20, 0x23, 0x30, 0x39, 0x61, 0x30, 0x66, 
+	0x36, 0x3B, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 
+	0x35, 0x70, 0x78, 0x20, 0x32, 0x35, 0x70, 0x78, 0x7D, 0x2E, 
+	0x62, 0x74, 0x6E, 0x2D, 0x6F, 0x75, 0x74, 0x6C, 0x69, 0x6E, 
+	0x65, 0x3A, 0x68, 0x6F, 0x76, 0x65, 0x72, 0x7B, 0x74, 0x65, 
+	0x78, 0x74, 0x2D, 0x64, 0x65, 0x63, 0x6F, 0x72, 0x61, 0x74, 
+	0x69, 0x6F, 0x6E, 0x3A, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x63, 
+	0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x66, 0x66, 0x66, 0x3B, 
+	0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 
+	0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x30, 0x39, 
+	0x61, 0x30, 0x66, 0x36, 0x7D, 0x63, 0x6F, 0x64, 0x65, 0x2C, 
+	0x70, 0x72, 0x65, 0x7B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x66, 
+	0x61, 0x6D, 0x69, 0x6C, 0x79, 0x3A, 0x27, 0x4F, 0x70, 0x65, 
+	0x6E, 0x20, 0x53, 0x61, 0x6E, 0x73, 0x27, 0x3B, 0x66, 0x6F, 
+	0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x31, 0x36, 
+	0x70, 0x78, 0x3B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x77, 0x65, 
+	0x69, 0x67, 0x68, 0x74, 0x3A, 0x33, 0x30, 0x30, 0x3B, 0x62, 
+	0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 
+	0x75, 0x73, 0x3A, 0x35, 0x70, 0x78, 0x3B, 0x62, 0x61, 0x63, 
+	0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x63, 0x6F, 
+	0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x66, 0x31, 0x66, 0x35, 0x66, 
+	0x61, 0x7D, 0x63, 0x6F, 0x64, 0x65, 0x7B, 0x63, 0x6F, 0x6C, 
+	0x6F, 0x72, 0x3A, 0x23, 0x30, 0x39, 0x61, 0x30, 0x66, 0x36, 
+	0x3B, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x2D, 0x6C, 
+	0x65, 0x66, 0x74, 0x3A, 0x36, 0x70, 0x78, 0x3B, 0x70, 0x61, 
+	0x64, 0x64, 0x69, 0x6E, 0x67, 0x2D, 0x72, 0x69, 0x67, 0x68, 
+	0x74, 0x3A, 0x36, 0x70, 0x78, 0x7D, 0x70, 0x72, 0x65, 0x7B, 
+	0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x62, 0x6C, 
+	0x6F, 0x63, 0x6B, 0x3B, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 
+	0x67, 0x3A, 0x31, 0x34, 0x70, 0x78, 0x3B, 0x6D, 0x61, 0x72, 
+	0x67, 0x69, 0x6E, 0x2D, 0x62, 0x6F, 0x74, 0x74, 0x6F, 0x6D, 
+	0x3A, 0x32, 0x30, 0x70, 0x78, 0x3B, 0x63, 0x6F, 0x6C, 0x6F, 
+	0x72, 0x3A, 0x23, 0x35, 0x32, 0x36, 0x34, 0x37, 0x35, 0x3B, 
+	0x6F, 0x76, 0x65, 0x72, 0x66, 0x6C, 0x6F, 0x77, 0x2D, 0x78, 
+	0x3A, 0x61, 0x75, 0x74, 0x6F, 0x7D, 0x2E, 0x66, 0x6F, 0x72, 
+	0x6D, 0x2D, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x5B, 0x64, 0x69, 
+	0x73, 0x61, 0x62, 0x6C, 0x65, 0x64, 0x5D, 0x2C, 0x2E, 0x66, 
+	0x6F, 0x72, 0x6D, 0x2D, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x5B, 
+	0x74, 0x79, 0x70, 0x65, 0x3D, 0x74, 0x65, 0x78, 0x74, 0x5D, 
+	0x2C, 0x2E, 0x66, 0x6F, 0x72, 0x6D, 0x2D, 0x69, 0x6E, 0x70, 
+	0x75, 0x74, 0x5B, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x70, 0x61, 
+	0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x5D, 0x2C, 0x2E, 0x66, 
+	0x6F, 0x72, 0x6D, 0x2D, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x5B, 
+	0x74, 0x79, 0x70, 0x65, 0x3D, 0x6E, 0x75, 0x6D, 0x62, 0x65, 
+	0x72, 0x5D, 0x2C, 0x2E, 0x66, 0x6F, 0x72, 0x6D, 0x2D, 0x69, 
+	0x6E, 0x70, 0x75, 0x74, 0x5B, 0x74, 0x79, 0x70, 0x65, 0x3D, 
+	0x65, 0x6D, 0x61, 0x69, 0x6C, 0x5D, 0x2C, 0x2E, 0x66, 0x6F, 
+	0x72, 0x6D, 0x2D, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x5B, 0x74, 
+	0x79, 0x70, 0x65, 0x3D, 0x64, 0x61, 0x74, 0x65, 0x5D, 0x7B, 
+	0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x35, 0x32, 0x36, 
+	0x34, 0x37, 0x35, 0x3B, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 
+	0x67, 0x3A, 0x31, 0x30, 0x70, 0x78, 0x3B, 0x6F, 0x75, 0x74, 
+	0x6C, 0x69, 0x6E, 0x65, 0x3A, 0x30, 0x3B, 0x62, 0x6F, 0x78, 
+	0x2D, 0x73, 0x69, 0x7A, 0x69, 0x6E, 0x67, 0x3A, 0x62, 0x6F, 
+	0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x6D, 
+	0x61, 0x72, 0x67, 0x69, 0x6E, 0x3A, 0x30, 0x20, 0x35, 0x70, 
+	0x78, 0x20, 0x32, 0x30, 0x70, 0x78, 0x3B, 0x66, 0x6F, 0x6E, 
+	0x74, 0x2D, 0x66, 0x61, 0x6D, 0x69, 0x6C, 0x79, 0x3A, 0x27, 
+	0x4F, 0x70, 0x65, 0x6E, 0x20, 0x53, 0x61, 0x6E, 0x73, 0x27, 
+	0x3B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 
+	0x3A, 0x31, 0x36, 0x70, 0x78, 0x3B, 0x66, 0x6F, 0x6E, 0x74, 
+	0x2D, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x33, 0x30, 
+	0x30, 0x3B, 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 
+	0x69, 0x6E, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x62, 0x6C, 0x6F, 
+	0x63, 0x6B, 0x3B, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x69, 0x74, 
+	0x69, 0x6F, 0x6E, 0x3A, 0x61, 0x6C, 0x6C, 0x20, 0x2E, 0x33, 
+	0x73, 0x3B, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x34, 
+	0x30, 0x70, 0x78, 0x7D, 0x2E, 0x66, 0x6F, 0x72, 0x6D, 0x2D, 
+	0x69, 0x6E, 0x70, 0x75, 0x74, 0x5B, 0x74, 0x79, 0x70, 0x65, 
+	0x3D, 0x74, 0x65, 0x78, 0x74, 0x5D, 0x2C, 0x2E, 0x66, 0x6F, 
+	0x72, 0x6D, 0x2D, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x5B, 0x74, 
+	0x79, 0x70, 0x65, 0x3D, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 
+	0x72, 0x64, 0x5D, 0x2C, 0x2E, 0x66, 0x6F, 0x72, 0x6D, 0x2D, 
+	0x69, 0x6E, 0x70, 0x75, 0x74, 0x5B, 0x74, 0x79, 0x70, 0x65, 
+	0x3D, 0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x5D, 0x2C, 0x2E, 
+	0x66, 0x6F, 0x72, 0x6D, 0x2D, 0x69, 0x6E, 0x70, 0x75, 0x74, 
+	0x5B, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x65, 0x6D, 0x61, 0x69, 
+	0x6C, 0x5D, 0x7B, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x31, 
+	0x30, 0x30, 0x25, 0x3B, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 
+	0x3A, 0x31, 0x70, 0x78, 0x20, 0x73, 0x6F, 0x6C, 0x69, 0x64, 
+	0x20, 0x23, 0x64, 0x31, 0x65, 0x31, 0x65, 0x38, 0x3B, 0x62, 
+	0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 
+	0x75, 0x73, 0x3A, 0x35, 0x70, 0x78, 0x3B, 0x6C, 0x69, 0x6E, 
+	0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x34, 
+	0x30, 0x70, 0x78, 0x7D, 0x2E, 0x66, 0x6F, 0x72, 0x6D, 0x2D, 
+	0x69, 0x6E, 0x70, 0x75, 0x74, 0x5B, 0x74, 0x79, 0x70, 0x65, 
+	0x3D, 0x74, 0x65, 0x78, 0x74, 0x5D, 0x3A, 0x66, 0x6F, 0x63, 
+	0x75, 0x73, 0x2C, 0x2E, 0x66, 0x6F, 0x72, 0x6D, 0x2D, 0x69, 
+	0x6E, 0x70, 0x75, 0x74, 0x5B, 0x74, 0x79, 0x70, 0x65, 0x3D, 
+	0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 0x72, 0x64, 0x5D, 0x3A, 
+	0x66, 0x6F, 0x63, 0x75, 0x73, 0x2C, 0x2E, 0x66, 0x6F, 0x72, 
+	0x6D, 0x2D, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x5B, 0x74, 0x79, 
+	0x70, 0x65, 0x3D, 0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0x5D, 
+	0x3A, 0x66, 0x6F, 0x63, 0x75, 0x73, 0x2C, 0x2E, 0x66, 0x6F, 
+	0x72, 0x6D, 0x2D, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x5B, 0x74, 
+	0x79, 0x70, 0x65, 0x3D, 0x65, 0x6D, 0x61, 0x69, 0x6C, 0x5D, 
+	0x3A, 0x66, 0x6F, 0x63, 0x75, 0x73, 0x7B, 0x62, 0x6F, 0x72, 
+	0x64, 0x65, 0x72, 0x3A, 0x31, 0x70, 0x78, 0x20, 0x73, 0x6F, 
+	0x6C, 0x69, 0x64, 0x20, 0x23, 0x30, 0x39, 0x61, 0x30, 0x66, 
+	0x36, 0x7D, 0x2E, 0x66, 0x6F, 0x72, 0x6D, 0x2D, 0x69, 0x6E, 
+	0x70, 0x75, 0x74, 0x5B, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x64, 
+	0x61, 0x74, 0x65, 0x5D, 0x7B, 0x62, 0x6F, 0x72, 0x64, 0x65, 
+	0x72, 0x3A, 0x31, 0x70, 0x78, 0x20, 0x73, 0x6F, 0x6C, 0x69, 
+	0x64, 0x20, 0x23, 0x64, 0x31, 0x65, 0x31, 0x65, 0x38, 0x3B, 
+	0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 
+	0x69, 0x75, 0x73, 0x3A, 0x35, 0x70, 0x78, 0x3B, 0x77, 0x69, 
+	0x64, 0x74, 0x68, 0x3A, 0x61, 0x75, 0x74, 0x6F, 0x21, 0x69, 
+	0x6D, 0x70, 0x6F, 0x72, 0x74, 0x61, 0x6E, 0x74, 0x7D, 0x2E, 
+	0x66, 0x6F, 0x72, 0x6D, 0x2D, 0x69, 0x6E, 0x70, 0x75, 0x74, 
+	0x5B, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x64, 0x61, 0x74, 0x65, 
+	0x5D, 0x3A, 0x66, 0x6F, 0x63, 0x75, 0x73, 0x7B, 0x62, 0x6F, 
+	0x72, 0x64, 0x65, 0x72, 0x3A, 0x31, 0x70, 0x78, 0x20, 0x73, 
+	0x6F, 0x6C, 0x69, 0x64, 0x20, 0x23, 0x30, 0x39, 0x61, 0x30, 
+	0x66, 0x36, 0x7D, 0x2E, 0x66, 0x6F, 0x72, 0x6D, 0x2D, 0x69, 
+	0x6E, 0x70, 0x75, 0x74, 0x5B, 0x64, 0x69, 0x73, 0x61, 0x62, 
+	0x6C, 0x65, 0x64, 0x5D, 0x7B, 0x77, 0x69, 0x64, 0x74, 0x68, 
+	0x3A, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x62, 0x6F, 0x72, 0x64, 
+	0x65, 0x72, 0x3A, 0x31, 0x70, 0x78, 0x20, 0x73, 0x6F, 0x6C, 
+	0x69, 0x64, 0x20, 0x23, 0x64, 0x31, 0x65, 0x31, 0x65, 0x38, 
+	0x3B, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 
+	0x64, 0x69, 0x75, 0x73, 0x3A, 0x35, 0x70, 0x78, 0x3B, 0x63, 
+	0x75, 0x72, 0x73, 0x6F, 0x72, 0x3A, 0x6E, 0x6F, 0x74, 0x2D, 
+	0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x3B, 0x62, 0x61, 
+	0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x63, 
+	0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x64, 0x31, 0x65, 0x31, 
+	0x65, 0x38, 0x7D, 0x2E, 0x66, 0x6F, 0x72, 0x6D, 0x2D, 0x69, 
+	0x6E, 0x70, 0x75, 0x74, 0x5B, 0x64, 0x69, 0x73, 0x61, 0x62, 
+	0x6C, 0x65, 0x64, 0x5D, 0x3A, 0x66, 0x6F, 0x63, 0x75, 0x73, 
+	0x7B, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x31, 0x70, 
+	0x78, 0x20, 0x73, 0x6F, 0x6C, 0x69, 0x64, 0x20, 0x23, 0x30, 
+	0x39, 0x61, 0x30, 0x66, 0x36, 0x7D, 0x2E, 0x66, 0x6F, 0x72, 
+	0x6D, 0x2D, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x5B, 0x74, 0x79, 
+	0x70, 0x65, 0x3D, 0x73, 0x75, 0x62, 0x6D, 0x69, 0x74, 0x5D, 
+	0x2C, 0x2E, 0x66, 0x6F, 0x72, 0x6D, 0x2D, 0x69, 0x6E, 0x70, 
+	0x75, 0x74, 0x5B, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x62, 0x75, 
+	0x74, 0x74, 0x6F, 0x6E, 0x5D, 0x7B, 0x66, 0x6F, 0x6E, 0x74, 
+	0x2D, 0x66, 0x61, 0x6D, 0x69, 0x6C, 0x79, 0x3A, 0x27, 0x4F, 
+	0x70, 0x65, 0x6E, 0x20, 0x53, 0x61, 0x6E, 0x73, 0x27, 0x3B, 
+	0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 
+	0x31, 0x36, 0x70, 0x78, 0x3B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 
+	0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x33, 0x30, 0x30, 
+	0x3B, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x74, 
+	0x6F, 0x75, 0x63, 0x68, 0x2D, 0x63, 0x61, 0x6C, 0x6C, 0x6F, 
+	0x75, 0x74, 0x3A, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x2D, 0x6B, 
+	0x68, 0x74, 0x6D, 0x6C, 0x2D, 0x75, 0x73, 0x65, 0x72, 0x2D, 
+	0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x3A, 0x6E, 0x6F, 0x6E, 
+	0x65, 0x3B, 0x2D, 0x6D, 0x6F, 0x7A, 0x2D, 0x75, 0x73, 0x65, 
+	0x72, 0x2D, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x3A, 0x6E, 
+	0x6F, 0x6E, 0x65, 0x3B, 0x2D, 0x6D, 0x73, 0x2D, 0x75, 0x73, 
+	0x65, 0x72, 0x2D, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x3A, 
+	0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x74, 0x65, 0x78, 0x74, 0x2D, 
+	0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x63, 0x65, 0x6E, 0x74, 
+	0x65, 0x72, 0x3B, 0x74, 0x65, 0x78, 0x74, 0x2D, 0x64, 0x65, 
+	0x63, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x6E, 
+	0x6F, 0x6E, 0x65, 0x21, 0x69, 0x6D, 0x70, 0x6F, 0x72, 0x74, 
+	0x61, 0x6E, 0x74, 0x3B, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 
+	0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x32, 0x38, 0x70, 0x78, 
+	0x3B, 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x69, 
+	0x6E, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x62, 0x6C, 0x6F, 0x63, 
+	0x6B, 0x3B, 0x63, 0x75, 0x72, 0x73, 0x6F, 0x72, 0x3A, 0x70, 
+	0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x3B, 0x62, 0x6F, 0x72, 
+	0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 
+	0x3A, 0x35, 0x70, 0x78, 0x3B, 0x74, 0x72, 0x61, 0x6E, 0x73, 
+	0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x61, 0x6C, 0x6C, 0x20, 
+	0x2E, 0x33, 0x73, 0x3B, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 
+	0x23, 0x66, 0x66, 0x66, 0x3B, 0x62, 0x61, 0x63, 0x6B, 0x67, 
+	0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 
+	0x72, 0x3A, 0x23, 0x30, 0x39, 0x61, 0x30, 0x66, 0x36, 0x3B, 
+	0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x30, 0x3B, 0x6D, 
+	0x61, 0x72, 0x67, 0x69, 0x6E, 0x3A, 0x35, 0x70, 0x78, 0x20, 
+	0x35, 0x70, 0x78, 0x20, 0x32, 0x30, 0x70, 0x78, 0x3B, 0x70, 
+	0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x35, 0x70, 0x78, 
+	0x20, 0x32, 0x35, 0x70, 0x78, 0x7D, 0x2E, 0x66, 0x6F, 0x72, 
+	0x6D, 0x2D, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x2C, 0x2E, 
+	0x66, 0x6F, 0x72, 0x6D, 0x2D, 0x74, 0x65, 0x78, 0x74, 0x61, 
+	0x72, 0x65, 0x61, 0x7B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x66, 
+	0x61, 0x6D, 0x69, 0x6C, 0x79, 0x3A, 0x27, 0x4F, 0x70, 0x65, 
+	0x6E, 0x20, 0x53, 0x61, 0x6E, 0x73, 0x27, 0x3B, 0x66, 0x6F, 
+	0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x31, 0x36, 
+	0x70, 0x78, 0x3B, 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 
+	0x3A, 0x69, 0x6E, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x62, 0x6C, 
+	0x6F, 0x63, 0x6B, 0x3B, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 
+	0x31, 0x30, 0x30, 0x25, 0x3B, 0x74, 0x72, 0x61, 0x6E, 0x73, 
+	0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x61, 0x6C, 0x6C, 0x20, 
+	0x2E, 0x33, 0x73, 0x3B, 0x6F, 0x75, 0x74, 0x6C, 0x69, 0x6E, 
+	0x65, 0x3A, 0x30, 0x3B, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 
+	0x7A, 0x69, 0x6E, 0x67, 0x3A, 0x62, 0x6F, 0x72, 0x64, 0x65, 
+	0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x6D, 0x61, 0x72, 0x67, 
+	0x69, 0x6E, 0x3A, 0x30, 0x20, 0x35, 0x70, 0x78, 0x20, 0x32, 
+	0x30, 0x70, 0x78, 0x3B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x77, 
+	0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x33, 0x30, 0x30, 0x3B, 
+	0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x35, 0x32, 0x36, 
+	0x34, 0x37, 0x35, 0x7D, 0x2E, 0x66, 0x6F, 0x72, 0x6D, 0x2D, 
+	0x69, 0x6E, 0x70, 0x75, 0x74, 0x5B, 0x74, 0x79, 0x70, 0x65, 
+	0x3D, 0x73, 0x75, 0x62, 0x6D, 0x69, 0x74, 0x5D, 0x3A, 0x68, 
+	0x6F, 0x76, 0x65, 0x72, 0x2C, 0x2E, 0x66, 0x6F, 0x72, 0x6D, 
+	0x2D, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x5B, 0x74, 0x79, 0x70, 
+	0x65, 0x3D, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x5D, 0x3A, 
+	0x68, 0x6F, 0x76, 0x65, 0x72, 0x7B, 0x74, 0x65, 0x78, 0x74, 
+	0x2D, 0x64, 0x65, 0x63, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 
+	0x6E, 0x3A, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x6F, 0x70, 0x61, 
+	0x63, 0x69, 0x74, 0x79, 0x3A, 0x2E, 0x38, 0x7D, 0x2E, 0x66, 
+	0x6F, 0x72, 0x6D, 0x2D, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 
+	0x7B, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x36, 
+	0x70, 0x78, 0x20, 0x31, 0x30, 0x70, 0x78, 0x20, 0x31, 0x30, 
+	0x70, 0x78, 0x3B, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 
+	0x31, 0x70, 0x78, 0x20, 0x73, 0x6F, 0x6C, 0x69, 0x64, 0x20, 
+	0x23, 0x64, 0x31, 0x65, 0x31, 0x65, 0x38, 0x3B, 0x62, 0x6F, 
+	0x72, 0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 
+	0x73, 0x3A, 0x35, 0x70, 0x78, 0x3B, 0x68, 0x65, 0x69, 0x67, 
+	0x68, 0x74, 0x3A, 0x34, 0x30, 0x70, 0x78, 0x3B, 0x62, 0x61, 
+	0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x63, 
+	0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x66, 0x66, 0x66, 0x7D, 
+	0x2E, 0x66, 0x6F, 0x72, 0x6D, 0x2D, 0x73, 0x65, 0x6C, 0x65, 
+	0x63, 0x74, 0x3A, 0x66, 0x6F, 0x63, 0x75, 0x73, 0x7B, 0x62, 
+	0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x31, 0x70, 0x78, 0x20, 
+	0x73, 0x6F, 0x6C, 0x69, 0x64, 0x20, 0x23, 0x30, 0x39, 0x61, 
+	0x30, 0x66, 0x36, 0x7D, 0x2E, 0x66, 0x6F, 0x72, 0x6D, 0x2D, 
+	0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x7B, 0x70, 
+	0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x31, 0x30, 0x70, 
+	0x78, 0x3B, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x31, 
+	0x70, 0x78, 0x20, 0x73, 0x6F, 0x6C, 0x69, 0x64, 0x20, 0x23, 
+	0x64, 0x31, 0x65, 0x31, 0x65, 0x38, 0x3B, 0x62, 0x6F, 0x72, 
+	0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 
+	0x3A, 0x35, 0x70, 0x78, 0x3B, 0x72, 0x65, 0x73, 0x69, 0x7A, 
+	0x65, 0x3A, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6C, 
+	0x7D, 0x2E, 0x66, 0x6F, 0x72, 0x6D, 0x2D, 0x74, 0x65, 0x78, 
+	0x74, 0x61, 0x72, 0x65, 0x61, 0x3A, 0x66, 0x6F, 0x63, 0x75, 
+	0x73, 0x7B, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x31, 
+	0x70, 0x78, 0x20, 0x73, 0x6F, 0x6C, 0x69, 0x64, 0x20, 0x23, 
+	0x30, 0x39, 0x61, 0x30, 0x66, 0x36, 0x7D, 0x2E, 0x66, 0x6F, 
+	0x72, 0x6D, 0x2D, 0x61, 0x75, 0x74, 0x6F, 0x7B, 0x77, 0x69, 
+	0x64, 0x74, 0x68, 0x3A, 0x61, 0x75, 0x74, 0x6F, 0x21, 0x69, 
+	0x6D, 0x70, 0x6F, 0x72, 0x74, 0x61, 0x6E, 0x74, 0x7D, 0x2E, 
+	0x67, 0x72, 0x69, 0x64, 0x7B, 0x64, 0x69, 0x73, 0x70, 0x6C, 
+	0x61, 0x79, 0x3A, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x3B, 0x77, 
+	0x69, 0x64, 0x74, 0x68, 0x3A, 0x39, 0x36, 0x30, 0x70, 0x78, 
+	0x3B, 0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x2D, 0x6C, 0x65, 
+	0x66, 0x74, 0x3A, 0x61, 0x75, 0x74, 0x6F, 0x3B, 0x6D, 0x61, 
+	0x72, 0x67, 0x69, 0x6E, 0x2D, 0x72, 0x69, 0x67, 0x68, 0x74, 
+	0x3A, 0x61, 0x75, 0x74, 0x6F, 0x3B, 0x6D, 0x69, 0x6E, 0x2D, 
+	0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x34, 0x30, 0x70, 
+	0x78, 0x7D, 0x40, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x20, 0x28, 
+	0x6D, 0x61, 0x78, 0x2D, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 
+	0x39, 0x36, 0x30, 0x70, 0x78, 0x29, 0x7B, 0x2E, 0x67, 0x72, 
+	0x69, 0x64, 0x7B, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x39, 
+	0x34, 0x25, 0x7D, 0x7D, 0x2E, 0x67, 0x72, 0x69, 0x64, 0x2D, 
+	0x66, 0x6C, 0x75, 0x69, 0x64, 0x2C, 0x2E, 0x72, 0x6F, 0x77, 
+	0x7B, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x31, 0x30, 0x30, 
+	0x25, 0x7D, 0x2E, 0x72, 0x6F, 0x77, 0x7B, 0x64, 0x69, 0x73, 
+	0x70, 0x6C, 0x61, 0x79, 0x3A, 0x69, 0x6E, 0x6C, 0x69, 0x6E, 
+	0x65, 0x2D, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x3B, 0x6D, 0x61, 
+	0x72, 0x67, 0x69, 0x6E, 0x2D, 0x6C, 0x65, 0x66, 0x74, 0x3A, 
+	0x30, 0x3B, 0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x2D, 0x72, 
+	0x69, 0x67, 0x68, 0x74, 0x3A, 0x30, 0x7D, 0x2E, 0x72, 0x6F, 
+	0x77, 0x3A, 0x61, 0x66, 0x74, 0x65, 0x72, 0x7B, 0x63, 0x6F, 
+	0x6E, 0x74, 0x65, 0x6E, 0x74, 0x3A, 0x22, 0x20, 0x22, 0x3B, 
+	0x63, 0x6C, 0x65, 0x61, 0x72, 0x3A, 0x62, 0x6F, 0x74, 0x68, 
+	0x3B, 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x74, 
+	0x61, 0x62, 0x6C, 0x65, 0x3B, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 
+	0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x30, 0x7D, 0x2E, 
+	0x63, 0x6F, 0x6C, 0x2D, 0x31, 0x2C, 0x2E, 0x63, 0x6F, 0x6C, 
+	0x2D, 0x31, 0x30, 0x2C, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x31, 
+	0x31, 0x2C, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x31, 0x32, 0x2C, 
+	0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x32, 0x2C, 0x2E, 0x63, 0x6F, 
+	0x6C, 0x2D, 0x33, 0x2C, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x34, 
+	0x2C, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x35, 0x2C, 0x2E, 0x63, 
+	0x6F, 0x6C, 0x2D, 0x37, 0x2C, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 
+	0x38, 0x2C, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x39, 0x7B, 0x64, 
+	0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x69, 0x6E, 0x6C, 
+	0x69, 0x6E, 0x65, 0x2D, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x3B, 
+	0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6C, 0x2D, 0x61, 
+	0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x74, 0x6F, 0x70, 0x3B, 0x66, 
+	0x6C, 0x6F, 0x61, 0x74, 0x3A, 0x6C, 0x65, 0x66, 0x74, 0x3B, 
+	0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x31, 0x25, 
+	0x7D, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x31, 0x7B, 0x77, 0x69, 
+	0x64, 0x74, 0x68, 0x3A, 0x36, 0x2E, 0x33, 0x33, 0x25, 0x7D, 
+	0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x32, 0x7B, 0x77, 0x69, 0x64, 
+	0x74, 0x68, 0x3A, 0x31, 0x34, 0x2E, 0x36, 0x36, 0x25, 0x7D, 
+	0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x33, 0x7B, 0x77, 0x69, 0x64, 
+	0x74, 0x68, 0x3A, 0x32, 0x32, 0x2E, 0x39, 0x39, 0x25, 0x7D, 
+	0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x34, 0x7B, 0x77, 0x69, 0x64, 
+	0x74, 0x68, 0x3A, 0x33, 0x31, 0x2E, 0x33, 0x33, 0x25, 0x7D, 
+	0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x35, 0x7B, 0x77, 0x69, 0x64, 
+	0x74, 0x68, 0x3A, 0x33, 0x39, 0x2E, 0x36, 0x36, 0x25, 0x7D, 
+	0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x36, 0x7B, 0x77, 0x69, 0x64, 
+	0x74, 0x68, 0x3A, 0x34, 0x37, 0x2E, 0x39, 0x39, 0x25, 0x3B, 
+	0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x69, 0x6E, 
+	0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 
+	0x3B, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6C, 0x2D, 
+	0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x74, 0x6F, 0x70, 0x3B, 
+	0x66, 0x6C, 0x6F, 0x61, 0x74, 0x3A, 0x6C, 0x65, 0x66, 0x74, 
+	0x3B, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x31, 
+	0x25, 0x7D, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x37, 0x7B, 0x77, 
+	0x69, 0x64, 0x74, 0x68, 0x3A, 0x35, 0x36, 0x2E, 0x33, 0x33, 
+	0x25, 0x7D, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x38, 0x7B, 0x77, 
+	0x69, 0x64, 0x74, 0x68, 0x3A, 0x36, 0x34, 0x2E, 0x36, 0x36, 
+	0x25, 0x7D, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x39, 0x7B, 0x77, 
+	0x69, 0x64, 0x74, 0x68, 0x3A, 0x37, 0x32, 0x2E, 0x39, 0x39, 
+	0x25, 0x7D, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x31, 0x30, 0x7B, 
+	0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x38, 0x31, 0x2E, 0x33, 
+	0x33, 0x25, 0x7D, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x31, 0x31, 
+	0x7B, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x38, 0x39, 0x2E, 
+	0x36, 0x36, 0x25, 0x7D, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x31, 
+	0x32, 0x7B, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x39, 0x37, 
+	0x2E, 0x39, 0x39, 0x25, 0x7D, 0x40, 0x6D, 0x65, 0x64, 0x69, 
+	0x61, 0x20, 0x28, 0x6D, 0x61, 0x78, 0x2D, 0x77, 0x69, 0x64, 
+	0x74, 0x68, 0x3A, 0x34, 0x30, 0x30, 0x70, 0x78, 0x29, 0x7B, 
+	0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x31, 0x2C, 0x2E, 0x63, 0x6F, 
+	0x6C, 0x2D, 0x31, 0x30, 0x2C, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 
+	0x31, 0x31, 0x2C, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x31, 0x32, 
+	0x2C, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x32, 0x2C, 0x2E, 0x63, 
+	0x6F, 0x6C, 0x2D, 0x33, 0x2C, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 
+	0x34, 0x2C, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x35, 0x2C, 0x2E, 
+	0x63, 0x6F, 0x6C, 0x2D, 0x36, 0x2C, 0x2E, 0x63, 0x6F, 0x6C, 
+	0x2D, 0x37, 0x2C, 0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x38, 0x2C, 
+	0x2E, 0x63, 0x6F, 0x6C, 0x2D, 0x39, 0x7B, 0x77, 0x69, 0x64, 
+	0x74, 0x68, 0x3A, 0x39, 0x38, 0x25, 0x7D, 0x7D, 0x2E, 0x74, 
+	0x61, 0x62, 0x6C, 0x65, 0x7B, 0x64, 0x69, 0x73, 0x70, 0x6C, 
+	0x61, 0x79, 0x3A, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x3B, 0x77, 
+	0x69, 0x64, 0x74, 0x68, 0x3A, 0x31, 0x30, 0x30, 0x25, 0x3B, 
+	0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x77, 0x69, 0x64, 
+	0x74, 0x68, 0x3A, 0x30, 0x3B, 0x62, 0x6F, 0x72, 0x64, 0x65, 
+	0x72, 0x2D, 0x63, 0x6F, 0x6C, 0x6C, 0x61, 0x70, 0x73, 0x65, 
+	0x3A, 0x63, 0x6F, 0x6C, 0x6C, 0x61, 0x70, 0x73, 0x65, 0x3B, 
+	0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x77, 0x65, 0x69, 0x67, 0x68, 
+	0x74, 0x3A, 0x33, 0x30, 0x30, 0x3B, 0x63, 0x6F, 0x6C, 0x6F, 
+	0x72, 0x3A, 0x23, 0x35, 0x32, 0x36, 0x34, 0x37, 0x35, 0x3B, 
+	0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x2D, 0x74, 0x6F, 0x70, 
+	0x3A, 0x30, 0x3B, 0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x2D, 
+	0x62, 0x6F, 0x74, 0x74, 0x6F, 0x6D, 0x3A, 0x32, 0x30, 0x70, 
+	0x78, 0x7D, 0x2E, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x74, 
+	0x68, 0x65, 0x61, 0x64, 0x20, 0x74, 0x72, 0x20, 0x74, 0x64, 
+	0x7B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x77, 0x65, 0x69, 0x67, 
+	0x68, 0x74, 0x3A, 0x34, 0x30, 0x30, 0x3B, 0x62, 0x6F, 0x72, 
+	0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x74, 0x74, 0x6F, 0x6D, 
+	0x3A, 0x32, 0x70, 0x78, 0x20, 0x73, 0x6F, 0x6C, 0x69, 0x64, 
+	0x20, 0x23, 0x64, 0x31, 0x65, 0x31, 0x65, 0x38, 0x3B, 0x62, 
+	0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 
+	0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x66, 0x36, 0x66, 
+	0x38, 0x66, 0x61, 0x7D, 0x2E, 0x74, 0x61, 0x62, 0x6C, 0x65, 
+	0x20, 0x74, 0x72, 0x20, 0x74, 0x64, 0x7B, 0x62, 0x6F, 0x72, 
+	0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x74, 0x74, 0x6F, 0x6D, 
+	0x3A, 0x31, 0x70, 0x78, 0x20, 0x73, 0x6F, 0x6C, 0x69, 0x64, 
+	0x20, 0x23, 0x64, 0x31, 0x65, 0x31, 0x65, 0x38, 0x3B, 0x70, 
+	0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x2D, 0x74, 0x6F, 0x70, 
+	0x3A, 0x31, 0x30, 0x70, 0x78, 0x3B, 0x70, 0x61, 0x64, 0x64, 
+	0x69, 0x6E, 0x67, 0x2D, 0x62, 0x6F, 0x74, 0x74, 0x6F, 0x6D, 
+	0x3A, 0x31, 0x30, 0x70, 0x78, 0x3B, 0x70, 0x61, 0x64, 0x64, 
+	0x69, 0x6E, 0x67, 0x2D, 0x6C, 0x65, 0x66, 0x74, 0x3A, 0x31, 
+	0x30, 0x70, 0x78, 0x7D, };
+
+static const unsigned char data_css_style_css[] = {
+	/* /css/style.css */
+	0x2F, 0x63, 0x73, 0x73, 0x2F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x2E, 0x63, 0x73, 0x73, 0,
+	0x48, 0x54, 0x54, 0x50, 0x2F, 0x31, 0x2E, 0x30, 0x20, 0x32, 
+	0x30, 0x30, 0x20, 0x4F, 0x4B, 0x0D, 0x0A, 0x6C, 0x77, 0x49, 
+	0x50, 0x2F, 0x31, 0x2E, 0x34, 0x2E, 0x31, 0x20, 0x28, 0x68, 
+	0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x73, 0x61, 0x76, 0x61, 
+	0x6E, 0x6E, 0x61, 0x68, 0x2E, 0x6E, 0x6F, 0x6E, 0x67, 0x6E, 
+	0x75, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x70, 0x72, 0x6F, 0x6A, 
+	0x65, 0x63, 0x74, 0x73, 0x2F, 0x6C, 0x77, 0x69, 0x70, 0x29, 
+	0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x2D, 
+	0x74, 0x79, 0x70, 0x65, 0x3A, 0x20, 0x74, 0x65, 0x78, 0x74, 
+	0x2F, 0x63, 0x73, 0x73, 0x0D, 0x0A, 0x0D, 0x0A, 0x0D, 0x0A, 
+	0x75, 0x6C, 0x2E, 0x6E, 0x61, 0x76, 0x62, 0x61, 0x72, 0x20, 
+	0x7B, 0x0A, 0x09, 0x6C, 0x69, 0x73, 0x74, 0x2D, 0x73, 0x74, 
+	0x79, 0x6C, 0x65, 0x2D, 0x74, 0x79, 0x70, 0x65, 0x3A, 0x20, 
+	0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x0A, 0x09, 0x6D, 0x61, 0x72, 
+	0x67, 0x69, 0x6E, 0x2D, 0x62, 0x6F, 0x74, 0x74, 0x6F, 0x6D, 
+	0x3A, 0x20, 0x33, 0x32, 0x70, 0x78, 0x3B, 0x0A, 0x09, 0x70, 
+	0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x30, 0x3B, 
+	0x0A, 0x09, 0x6F, 0x76, 0x65, 0x72, 0x66, 0x6C, 0x6F, 0x77, 
+	0x3A, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6E, 0x3B, 0x0A, 
+	0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 
+	0x64, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 0x23, 
+	0x33, 0x33, 0x33, 0x3B, 0x0A, 0x7D, 0x0A, 0x75, 0x6C, 0x2E, 
+	0x6E, 0x61, 0x76, 0x62, 0x61, 0x72, 0x20, 0x6C, 0x69, 0x20, 
+	0x7B, 0x0A, 0x09, 0x66, 0x6C, 0x6F, 0x61, 0x74, 0x3A, 0x20, 
+	0x6C, 0x65, 0x66, 0x74, 0x3B, 0x0A, 0x7D, 0x0A, 0x75, 0x6C, 
+	0x2E, 0x6E, 0x61, 0x76, 0x62, 0x61, 0x72, 0x20, 0x6C, 0x69, 
+	0x20, 0x61, 0x20, 0x7B, 0x0A, 0x09, 0x64, 0x69, 0x73, 0x70, 
+	0x6C, 0x61, 0x79, 0x3A, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 
+	0x3B, 0x0A, 0x09, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 
+	0x77, 0x68, 0x69, 0x74, 0x65, 0x3B, 0x0A, 0x09, 0x74, 0x65, 
+	0x78, 0x74, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x20, 
+	0x63, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x3B, 0x0A, 0x09, 0x70, 
+	0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x31, 0x34, 
+	0x70, 0x78, 0x20, 0x31, 0x36, 0x70, 0x78, 0x3B, 0x0A, 0x09, 
+	0x74, 0x65, 0x78, 0x74, 0x2D, 0x64, 0x65, 0x63, 0x6F, 0x72, 
+	0x61, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x6E, 0x6F, 0x6E, 
+	0x65, 0x3B, 0x0A, 0x7D, 0x0A, 0x75, 0x6C, 0x2E, 0x6E, 0x61, 
+	0x76, 0x62, 0x61, 0x72, 0x20, 0x6C, 0x69, 0x20, 0x61, 0x3A, 
+	0x68, 0x6F, 0x76, 0x65, 0x72, 0x3A, 0x6E, 0x6F, 0x74, 0x28, 
+	0x2E, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x29, 0x20, 0x7B, 
+	0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 
+	0x6E, 0x64, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 
+	0x23, 0x31, 0x31, 0x31, 0x3B, 0x0A, 0x7D, 0x0A, 0x75, 0x6C, 
+	0x2E, 0x6E, 0x61, 0x76, 0x62, 0x61, 0x72, 0x20, 0x6C, 0x69, 
+	0x20, 0x61, 0x2E, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 
+	0x7B, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 
+	0x75, 0x6E, 0x64, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 
+	0x20, 0x23, 0x30, 0x39, 0x61, 0x30, 0x66, 0x36, 0x3B, 0x0A, 
+	0x7D, 0x0A, 0x40, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x20, 0x73, 
+	0x63, 0x72, 0x65, 0x65, 0x6E, 0x20, 0x61, 0x6E, 0x64, 0x20, 
+	0x28, 0x6D, 0x61, 0x78, 0x2D, 0x77, 0x69, 0x64, 0x74, 0x68, 
+	0x3A, 0x20, 0x36, 0x30, 0x30, 0x70, 0x78, 0x29, 0x7B, 0x0A, 
+	0x09, 0x75, 0x6C, 0x2E, 0x6E, 0x61, 0x76, 0x62, 0x61, 0x72, 
+	0x20, 0x6C, 0x69, 0x2E, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2C, 
+	0x20, 0x0A, 0x09, 0x75, 0x6C, 0x2E, 0x6E, 0x61, 0x76, 0x62, 
+	0x61, 0x72, 0x20, 0x6C, 0x69, 0x20, 0x7B, 0x66, 0x6C, 0x6F, 
+	0x61, 0x74, 0x3A, 0x20, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x7D, 
+	0x0A, 0x7D, 0x0A, 0x2E, 0x6F, 0x6E, 0x6F, 0x66, 0x66, 0x73, 
+	0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x7B, 0x0A, 0x09, 0x70, 
+	0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x72, 
+	0x65, 0x6C, 0x61, 0x74, 0x69, 0x76, 0x65, 0x3B, 0x20, 0x77, 
+	0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x39, 0x30, 0x70, 0x78, 
+	0x3B, 0x0A, 0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 
+	0x2D, 0x75, 0x73, 0x65, 0x72, 0x2D, 0x73, 0x65, 0x6C, 0x65, 
+	0x63, 0x74, 0x3A, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x20, 0x2D, 
+	0x6D, 0x6F, 0x7A, 0x2D, 0x75, 0x73, 0x65, 0x72, 0x2D, 0x73, 
+	0x65, 0x6C, 0x65, 0x63, 0x74, 0x3A, 0x6E, 0x6F, 0x6E, 0x65, 
+	0x3B, 0x20, 0x2D, 0x6D, 0x73, 0x2D, 0x75, 0x73, 0x65, 0x72, 
+	0x2D, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x3A, 0x20, 0x6E, 
+	0x6F, 0x6E, 0x65, 0x3B, 0x0A, 0x7D, 0x0A, 0x2E, 0x6F, 0x6E, 
+	0x6F, 0x66, 0x66, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2D, 
+	0x63, 0x68, 0x65, 0x63, 0x6B, 0x62, 0x6F, 0x78, 0x20, 0x7B, 
+	0x0A, 0x09, 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 
+	0x20, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x0A, 0x7D, 0x0A, 0x2E, 
+	0x6F, 0x6E, 0x6F, 0x66, 0x66, 0x73, 0x77, 0x69, 0x74, 0x63, 
+	0x68, 0x2D, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x0A, 
+	0x09, 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x20, 
+	0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x3B, 0x20, 0x6F, 0x76, 0x65, 
+	0x72, 0x66, 0x6C, 0x6F, 0x77, 0x3A, 0x20, 0x68, 0x69, 0x64, 
+	0x64, 0x65, 0x6E, 0x3B, 0x20, 0x63, 0x75, 0x72, 0x73, 0x6F, 
+	0x72, 0x3A, 0x20, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 
+	0x3B, 0x0A, 0x09, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 
+	0x20, 0x32, 0x70, 0x78, 0x20, 0x73, 0x6F, 0x6C, 0x69, 0x64, 
+	0x20, 0x23, 0x30, 0x33, 0x41, 0x39, 0x46, 0x34, 0x3B, 0x20, 
+	0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 
+	0x69, 0x75, 0x73, 0x3A, 0x20, 0x32, 0x30, 0x70, 0x78, 0x3B, 
+	0x0A, 0x7D, 0x0A, 0x2E, 0x6F, 0x6E, 0x6F, 0x66, 0x66, 0x73, 
+	0x77, 0x69, 0x74, 0x63, 0x68, 0x2D, 0x69, 0x6E, 0x6E, 0x65, 
+	0x72, 0x20, 0x7B, 0x0A, 0x09, 0x64, 0x69, 0x73, 0x70, 0x6C, 
+	0x61, 0x79, 0x3A, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x3B, 
+	0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x32, 0x30, 
+	0x30, 0x25, 0x3B, 0x20, 0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 
+	0x2D, 0x6C, 0x65, 0x66, 0x74, 0x3A, 0x20, 0x2D, 0x31, 0x30, 
+	0x30, 0x25, 0x3B, 0x0A, 0x09, 0x74, 0x72, 0x61, 0x6E, 0x73, 
+	0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x6D, 0x61, 0x72, 
+	0x67, 0x69, 0x6E, 0x20, 0x30, 0x2E, 0x33, 0x73, 0x20, 0x65, 
+	0x61, 0x73, 0x65, 0x2D, 0x69, 0x6E, 0x20, 0x30, 0x73, 0x3B, 
+	0x0A, 0x7D, 0x0A, 0x2E, 0x6F, 0x6E, 0x6F, 0x66, 0x66, 0x73, 
+	0x77, 0x69, 0x74, 0x63, 0x68, 0x2D, 0x69, 0x6E, 0x6E, 0x65, 
+	0x72, 0x3A, 0x62, 0x65, 0x66, 0x6F, 0x72, 0x65, 0x2C, 0x20, 
+	0x2E, 0x6F, 0x6E, 0x6F, 0x66, 0x66, 0x73, 0x77, 0x69, 0x74, 
+	0x63, 0x68, 0x2D, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x3A, 0x61, 
+	0x66, 0x74, 0x65, 0x72, 0x20, 0x7B, 0x0A, 0x09, 0x64, 0x69, 
+	0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x20, 0x62, 0x6C, 0x6F, 
+	0x63, 0x6B, 0x3B, 0x20, 0x66, 0x6C, 0x6F, 0x61, 0x74, 0x3A, 
+	0x20, 0x6C, 0x65, 0x66, 0x74, 0x3B, 0x20, 0x77, 0x69, 0x64, 
+	0x74, 0x68, 0x3A, 0x20, 0x35, 0x30, 0x25, 0x3B, 0x20, 0x68, 
+	0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x33, 0x30, 0x70, 
+	0x78, 0x3B, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 
+	0x3A, 0x20, 0x30, 0x3B, 0x20, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 
+	0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x33, 0x30, 
+	0x70, 0x78, 0x3B, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 
+	0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x31, 0x34, 0x70, 0x78, 
+	0x3B, 0x20, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 0x77, 
+	0x68, 0x69, 0x74, 0x65, 0x3B, 0x20, 0x66, 0x6F, 0x6E, 0x74, 
+	0x2D, 0x66, 0x61, 0x6D, 0x69, 0x6C, 0x79, 0x3A, 0x20, 0x54, 
+	0x72, 0x65, 0x62, 0x75, 0x63, 0x68, 0x65, 0x74, 0x2C, 0x20, 
+	0x41, 0x72, 0x69, 0x61, 0x6C, 0x2C, 0x20, 0x73, 0x61, 0x6E, 
+	0x73, 0x2D, 0x73, 0x65, 0x72, 0x69, 0x66, 0x3B, 0x20, 0x66, 
+	0x6F, 0x6E, 0x74, 0x2D, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 
+	0x3A, 0x20, 0x62, 0x6F, 0x6C, 0x64, 0x3B, 0x0A, 0x09, 0x62, 
+	0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A, 0x69, 0x6E, 0x67, 0x3A, 
+	0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 
+	0x78, 0x3B, 0x0A, 0x7D, 0x0A, 0x2E, 0x6F, 0x6E, 0x6F, 0x66, 
+	0x66, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2D, 0x69, 0x6E, 
+	0x6E, 0x65, 0x72, 0x3A, 0x62, 0x65, 0x66, 0x6F, 0x72, 0x65, 
+	0x20, 0x7B, 0x0A, 0x09, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 
+	0x74, 0x3A, 0x20, 0x22, 0x4F, 0x4E, 0x22, 0x3B, 0x0A, 0x09, 
+	0x74, 0x65, 0x78, 0x74, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 
+	0x3A, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x3B, 0x0A, 0x09, 0x70, 
+	0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x2D, 0x6C, 0x65, 0x66, 
+	0x74, 0x3A, 0x20, 0x31, 0x34, 0x70, 0x78, 0x3B, 0x0A, 0x09, 
+	0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 
+	0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 0x23, 0x45, 
+	0x31, 0x46, 0x35, 0x46, 0x45, 0x3B, 0x20, 0x63, 0x6F, 0x6C, 
+	0x6F, 0x72, 0x3A, 0x20, 0x23, 0x30, 0x33, 0x41, 0x39, 0x46, 
+	0x34, 0x3B, 0x0A, 0x7D, 0x0A, 0x2E, 0x6F, 0x6E, 0x6F, 0x66, 
+	0x66, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2D, 0x69, 0x6E, 
+	0x6E, 0x65, 0x72, 0x3A, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 
+	0x7B, 0x0A, 0x09, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 
+	0x3A, 0x20, 0x22, 0x4F, 0x46, 0x46, 0x22, 0x3B, 0x0A, 0x09, 
+	0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x2D, 0x72, 0x69, 
+	0x67, 0x68, 0x74, 0x3A, 0x20, 0x31, 0x34, 0x70, 0x78, 0x3B, 
+	0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 
+	0x6E, 0x64, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 
+	0x23, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x3B, 0x20, 0x63, 
+	0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 0x23, 0x39, 0x39, 0x39, 
+	0x39, 0x39, 0x39, 0x3B, 0x0A, 0x09, 0x74, 0x65, 0x78, 0x74, 
+	0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x20, 0x72, 0x69, 
+	0x67, 0x68, 0x74, 0x3B, 0x0A, 0x7D, 0x0A, 0x2E, 0x6F, 0x6E, 
+	0x6F, 0x66, 0x66, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2D, 
+	0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x7B, 0x0A, 0x09, 
+	0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x20, 0x62, 
+	0x6C, 0x6F, 0x63, 0x6B, 0x3B, 0x20, 0x77, 0x69, 0x64, 0x74, 
+	0x68, 0x3A, 0x20, 0x31, 0x38, 0x70, 0x78, 0x3B, 0x20, 0x6D, 
+	0x61, 0x72, 0x67, 0x69, 0x6E, 0x3A, 0x20, 0x36, 0x70, 0x78, 
+	0x3B, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 
+	0x75, 0x6E, 0x64, 0x3A, 0x20, 0x23, 0x46, 0x46, 0x46, 0x46, 
+	0x46, 0x46, 0x3B, 0x0A, 0x09, 0x70, 0x6F, 0x73, 0x69, 0x74, 
+	0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x61, 0x62, 0x73, 0x6F, 0x6C, 
+	0x75, 0x74, 0x65, 0x3B, 0x20, 0x74, 0x6F, 0x70, 0x3A, 0x20, 
+	0x30, 0x3B, 0x20, 0x62, 0x6F, 0x74, 0x74, 0x6F, 0x6D, 0x3A, 
+	0x20, 0x30, 0x3B, 0x0A, 0x09, 0x72, 0x69, 0x67, 0x68, 0x74, 
+	0x3A, 0x20, 0x35, 0x36, 0x70, 0x78, 0x3B, 0x0A, 0x09, 0x62, 
+	0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x20, 0x32, 0x70, 0x78, 
+	0x20, 0x73, 0x6F, 0x6C, 0x69, 0x64, 0x20, 0x23, 0x30, 0x33, 
+	0x41, 0x39, 0x46, 0x34, 0x3B, 0x20, 0x62, 0x6F, 0x72, 0x64, 
+	0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 
+	0x20, 0x32, 0x30, 0x70, 0x78, 0x3B, 0x0A, 0x09, 0x74, 0x72, 
+	0x61, 0x6E, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 
+	0x61, 0x6C, 0x6C, 0x20, 0x30, 0x2E, 0x33, 0x73, 0x20, 0x65, 
+	0x61, 0x73, 0x65, 0x2D, 0x69, 0x6E, 0x20, 0x30, 0x73, 0x3B, 
+	0x20, 0x0A, 0x7D, 0x0A, 0x2E, 0x6F, 0x6E, 0x6F, 0x66, 0x66, 
+	0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2D, 0x63, 0x68, 0x65, 
+	0x63, 0x6B, 0x62, 0x6F, 0x78, 0x3A, 0x63, 0x68, 0x65, 0x63, 
+	0x6B, 0x65, 0x64, 0x20, 0x2B, 0x20, 0x2E, 0x6F, 0x6E, 0x6F, 
+	0x66, 0x66, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2D, 0x6C, 
+	0x61, 0x62, 0x65, 0x6C, 0x20, 0x2E, 0x6F, 0x6E, 0x6F, 0x66, 
+	0x66, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2D, 0x69, 0x6E, 
+	0x6E, 0x65, 0x72, 0x20, 0x7B, 0x0A, 0x09, 0x6D, 0x61, 0x72, 
+	0x67, 0x69, 0x6E, 0x2D, 0x6C, 0x65, 0x66, 0x74, 0x3A, 0x20, 
+	0x30, 0x3B, 0x0A, 0x7D, 0x0A, 0x2E, 0x6F, 0x6E, 0x6F, 0x66, 
+	0x66, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2D, 0x63, 0x68, 
+	0x65, 0x63, 0x6B, 0x62, 0x6F, 0x78, 0x3A, 0x63, 0x68, 0x65, 
+	0x63, 0x6B, 0x65, 0x64, 0x20, 0x2B, 0x20, 0x2E, 0x6F, 0x6E, 
+	0x6F, 0x66, 0x66, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2D, 
+	0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x2E, 0x6F, 0x6E, 0x6F, 
+	0x66, 0x66, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2D, 0x73, 
+	0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x7B, 0x0A, 0x09, 0x72, 
+	0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 
+	0x20, 0x0A, 0x7D, };
+
+const struct fsdata_file file_index_ssi[] = {{
+NULL,
+data_index_ssi, data_index_ssi + 11,
+sizeof(data_index_ssi) - 11,
+1
+}};
+
+const struct fsdata_file file_404_html[] = {{
+file_index_ssi,
+data_404_html, data_404_html + 10,
+sizeof(data_404_html) - 10,
+1
+}};
+
+const struct fsdata_file file_about_html[] = {{
+file_404_html,
+data_about_html, data_about_html + 12,
+sizeof(data_about_html) - 12,
+1
+}};
+
+const struct fsdata_file file_img_favicon_png[] = {{
+file_about_html,
+data_img_favicon_png, data_img_favicon_png + 17,
+sizeof(data_img_favicon_png) - 17,
+1
+}};
+
+const struct fsdata_file file_css_siimple_min_css[] = {{
+file_img_favicon_png,
+data_css_siimple_min_css, data_css_siimple_min_css + 21,
+sizeof(data_css_siimple_min_css) - 21,
+1
+}};
+
+const struct fsdata_file file_css_style_css[] = {{
+file_css_siimple_min_css,
+data_css_style_css, data_css_style_css + 15,
+sizeof(data_css_style_css) - 15,
+1
+}};
+
+#define FS_ROOT file_css_style_css
+
+#define FS_NUMFILES 6
diff --git a/examples/http_server/fsdata/makefsdata b/examples/http_server/fsdata/makefsdata
new file mode 100755
index 0000000..5361370
--- /dev/null
+++ b/examples/http_server/fsdata/makefsdata
@@ -0,0 +1,114 @@
+#!/usr/bin/perl
+
+$incHttpHeader = 1;
+
+open(OUTPUT, "> fsdata.c");
+print(OUTPUT "#include \"httpd/fsdata.h\"\n\n");
+
+chdir("fs");
+open(FILES, "find . -type f |");
+
+while($file = <FILES>) {
+
+    # Do not include files in CVS directories nor backup files.
+    if($file =~ /(CVS|~)/) {
+        next;
+    }
+
+    chop($file);
+
+    if($incHttpHeader == 1) {
+        open(HEADER, "> /tmp/header") || die $!;
+        if($file =~ /404/) {
+            print(HEADER "HTTP/1.0 404 File not found\r\n");
+        } else {
+            print(HEADER "HTTP/1.0 200 OK\r\n");
+        }
+        print(HEADER "lwIP/1.4.1 (http://savannah.nongnu.org/projects/lwip)\r\n");
+        if($file =~ /\.html$/ || $file =~ /\.htm$/ || $file =~ /\.shtml$/ || $file =~ /\.shtm$/ || $file =~ /\.ssi$/) {
+            print(HEADER "Content-type: text/html\r\n");
+        } elsif($file =~ /\.js$/) {
+            print(HEADER "Content-type: application/x-javascript\r\n\r\n");
+        } elsif($file =~ /\.css$/) {
+            print(HEADER "Content-type: text/css\r\n\r\n");
+        } elsif($file =~ /\.ico$/) {
+            print(HEADER "Content-type: image/x-icon\r\n\r\n");
+        } elsif($file =~ /\.gif$/) {
+            print(HEADER "Content-type: image/gif\r\n");
+        } elsif($file =~ /\.png$/) {
+            print(HEADER "Content-type: image/png\r\n");
+        } elsif($file =~ /\.jpg$/) {
+            print(HEADER "Content-type: image/jpeg\r\n");
+        } elsif($file =~ /\.bmp$/) {
+            print(HEADER "Content-type: image/bmp\r\n\r\n");
+        } elsif($file =~ /\.class$/) {
+            print(HEADER "Content-type: application/octet-stream\r\n");
+        } elsif($file =~ /\.ram$/) {
+            print(HEADER "Content-type: audio/x-pn-realaudio\r\n");
+        } else {
+            print(HEADER "Content-type: text/plain\r\n");
+        }
+        print(HEADER "\r\n");
+        close(HEADER);
+
+        unless($file =~ /\.plain$/ || $file =~ /cgi/) {
+            system("cat /tmp/header $file > /tmp/file");
+        } else {
+            system("cp $file /tmp/file");
+        }
+    } else {
+        system("cp $file /tmp/file");
+    }
+
+    open(FILE, "/tmp/file");
+    unlink("/tmp/file");
+    unlink("/tmp/header");
+
+    $file =~ s/\.//;
+    $fvar = $file;
+    $fvar =~ s-/-_-g;
+    $fvar =~ s-\.-_-g;
+
+    print(OUTPUT "static const unsigned char data".$fvar."[] = {\n");
+    print(OUTPUT "\t/* $file */\n\t");
+    for($j = 0; $j < length($file); $j++) {
+        printf(OUTPUT "0x%02X, ", unpack("C", substr($file, $j, 1)));
+    }
+    printf(OUTPUT "0,\n");
+
+
+    $i = 0;
+    while(read(FILE, $data, 1)) {
+        if($i == 0) {
+            print(OUTPUT "\t");
+        }
+        printf(OUTPUT "0x%02X, ", unpack("C", $data));
+        $i++;
+        if($i == 10) {
+            print(OUTPUT "\n");
+            $i = 0;
+        }
+    }
+    print(OUTPUT "};\n\n");
+    close(FILE);
+    push(@fvars, $fvar);
+    push(@files, $file);
+}
+
+for($i = 0; $i < @fvars; $i++) {
+    $file = $files[$i];
+    $fvar = $fvars[$i];
+
+    if($i == 0) {
+        $prevfile = "NULL";
+    } else {
+        $prevfile = "file" . $fvars[$i - 1];
+    }
+    print(OUTPUT "const struct fsdata_file file".$fvar."[] = {{\n$prevfile,\ndata$fvar, ");
+    print(OUTPUT "data$fvar + ". (length($file) + 1) .",\n");
+    print(OUTPUT "sizeof(data$fvar) - ". (length($file) + 1) .",\n");
+    print(OUTPUT $incHttpHeader."\n}};\n\n");
+}
+
+print(OUTPUT "#define FS_ROOT file$fvars[$i - 1]\n\n");
+print(OUTPUT "#define FS_NUMFILES $i\n");
diff --git a/examples/http_server/fsdata/readme.txt b/examples/http_server/fsdata/readme.txt
new file mode 100644
index 0000000..a1db0c7
--- /dev/null
+++ b/examples/http_server/fsdata/readme.txt
@@ -0,0 +1,2 @@
+This directory contains a script ('makefsdata') to create C code suitable for
+httpd for given html pages (or other files) in a directory.
diff --git a/examples/http_server/http_server.c b/examples/http_server/http_server.c
new file mode 100644
index 0000000..fd1937c
--- /dev/null
+++ b/examples/http_server/http_server.c
@@ -0,0 +1,114 @@
+/*
+ * HTTP server example.
+ *
+ * This sample code is in the public domain.
+ */
+#include <espressif/esp_common.h>
+#include <esp8266.h>
+#include <esp/uart.h>
+#include <string.h>
+#include <stdio.h>
+#include <FreeRTOS.h>
+#include <task.h>
+#include <ssid_config.h>
+#include <httpd/httpd.h>
+
+#define LED_PIN 2
+
+enum {
+    SSI_UPTIME,
+    SSI_FREE_HEAP,
+    SSI_LED_STATE
+};
+
+char *gpio_cgi_handler(int iIndex, int iNumParams, char *pcParam[], char *pcValue[])
+{
+    for (int i = 0; i < iNumParams; i++) {
+        if (strcmp(pcParam[i], "on") == 0) {
+            uint8_t gpio_num = atoi(pcValue[i]);
+            gpio_enable(gpio_num, GPIO_OUTPUT);
+            gpio_write(gpio_num, true);
+        } else if (strcmp(pcParam[i], "off") == 0) {
+            uint8_t gpio_num = atoi(pcValue[i]);
+            gpio_enable(gpio_num, GPIO_OUTPUT);
+            gpio_write(gpio_num, false);
+        } else if (strcmp(pcParam[i], "toggle") == 0) {
+            uint8_t gpio_num = atoi(pcValue[i]);
+            gpio_enable(gpio_num, GPIO_OUTPUT);
+            gpio_toggle(gpio_num);
+        }
+    }
+    return "/index.ssi";
+}
+
+char *about_cgi_handler(int iIndex, int iNumParams, char *pcParam[], char *pcValue[])
+{
+    return "/about.html";
+}
+
+int32_t ssi_handler(int32_t iIndex, char *pcInsert, int32_t iInsertLen)
+{
+    switch (iIndex) {
+        case SSI_UPTIME:
+            snprintf(pcInsert, iInsertLen, "%d",
+                    xTaskGetTickCount() * portTICK_PERIOD_MS / 1000);
+            break;
+        case SSI_FREE_HEAP:
+            snprintf(pcInsert, iInsertLen, "%d", (int) xPortGetFreeHeapSize());
+            break;
+        case SSI_LED_STATE:
+            snprintf(pcInsert, iInsertLen, (GPIO.OUT & BIT(LED_PIN)) ? "Off" : "On");
+            break;
+        default:
+            snprintf(pcInsert, iInsertLen, "N/A");
+            break;
+    }
+
+    /* Tell the server how many characters to insert */
+    return (strlen(pcInsert));
+}
+
+void httpd_task(void *pvParameters)
+{
+    tCGI pCGIs[] = {
+        {"/gpio", (tCGIHandler) gpio_cgi_handler},
+        {"/about", (tCGIHandler) about_cgi_handler},
+    };
+
+    const char *pcConfigSSITags[] = {
+        "uptime", // SSI_UPTIME
+        "heap",   // SSI_FREE_HEAP
+        "led"     // SSI_LED_STATE
+    };
+
+    /* register handlers and start the server */
+    http_set_cgi_handlers(pCGIs, sizeof (pCGIs) / sizeof (pCGIs[0]));
+    http_set_ssi_handler((tSSIHandler) ssi_handler, pcConfigSSITags,
+            sizeof (pcConfigSSITags) / sizeof (pcConfigSSITags[0]));
+    httpd_init();
+
+    for (;;);
+}
+
+void user_init(void)
+{
+    uart_set_baud(0, 115200);
+    printf("SDK version:%s\n", sdk_system_get_sdk_version());
+
+    struct sdk_station_config config = {
+        .ssid = WIFI_SSID,
+        .password = WIFI_PASS,
+    };
+
+    /* required to call wifi_set_opmode before station_set_config */
+    sdk_wifi_set_opmode(STATION_MODE);
+    sdk_wifi_station_set_config(&config);
+    sdk_wifi_station_connect();
+
+    /* turn off LED */
+    gpio_enable(LED_PIN, GPIO_OUTPUT);
+    gpio_write(LED_PIN, true);
+
+    /* initialize tasks */
+    xTaskCreate(&httpd_task, "HTTP Daemon", 1024, NULL, 2, NULL);
+}
diff --git a/extras/httpd/component.mk b/extras/httpd/component.mk
new file mode 100644
index 0000000..c93f8f9
--- /dev/null
+++ b/extras/httpd/component.mk
@@ -0,0 +1,9 @@
+# Component makefile for extras/httpd
+
+# expected anyone using httpd includes it as 'httpd/httpd.h'
+INC_DIRS += $(httpd_ROOT)..
+
+# args for passing into compile rule generation
+httpd_SRC_DIR = $(httpd_ROOT)
+
+$(eval $(call component_compile_rules,httpd))
diff --git a/extras/httpd/fs.c b/extras/httpd/fs.c
new file mode 100644
index 0000000..2cb7575
--- /dev/null
+++ b/extras/httpd/fs.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved. 
+ * 
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ * 
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+#include "lwip/opt.h"
+#include "lwip/def.h"
+#include "fs.h"
+#include "fsdata.h"
+#include <string.h>
+
+/** Set this to 1 to include "fsdata_custom.c" instead of "fsdata.c" for the
+ * file system (to prevent changing the file included in CVS) */
+#ifndef HTTPD_USE_CUSTOM_FSDATA
+#define HTTPD_USE_CUSTOM_FSDATA 0
+#endif
+
+#if HTTPD_USE_CUSTOM_FSDATA
+#include "fsdata_custom.c"
+#else /* HTTPD_USE_CUSTOM_FSDATA */
+#include "fsdata.c"
+#endif /* HTTPD_USE_CUSTOM_FSDATA */
+
+/*-----------------------------------------------------------------------------------*/
+
+#if LWIP_HTTPD_CUSTOM_FILES
+int fs_open_custom(struct fs_file *file, const char *name);
+void fs_close_custom(struct fs_file *file);
+#if LWIP_HTTPD_FS_ASYNC_READ
+u8_t fs_canread_custom(struct fs_file *file);
+u8_t fs_wait_read_custom(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg);
+#endif /* LWIP_HTTPD_FS_ASYNC_READ */
+#endif /* LWIP_HTTPD_CUSTOM_FILES */
+
+/*-----------------------------------------------------------------------------------*/
+err_t
+fs_open(struct fs_file *file, const char *name)
+{
+  const struct fsdata_file *f;
+
+  if ((file == NULL) || (name == NULL)) {
+     return ERR_ARG;
+  }
+
+#if LWIP_HTTPD_CUSTOM_FILES
+  if (fs_open_custom(file, name)) {
+    file->is_custom_file = 1;
+    return ERR_OK;
+  }
+  file->is_custom_file = 0;
+#endif /* LWIP_HTTPD_CUSTOM_FILES */
+
+  for (f = FS_ROOT; f != NULL; f = f->next) {
+    if (!strcmp(name, (char *)f->name)) {
+      file->data = (const char *)f->data;
+      file->len = f->len;
+      file->index = f->len;
+      file->pextension = NULL;
+      file->http_header_included = f->http_header_included;
+#if HTTPD_PRECALCULATED_CHECKSUM
+      file->chksum_count = f->chksum_count;
+      file->chksum = f->chksum;
+#endif /* HTTPD_PRECALCULATED_CHECKSUM */
+#if LWIP_HTTPD_FILE_STATE
+      file->state = fs_state_init(file, name);
+#endif /* #if LWIP_HTTPD_FILE_STATE */
+      return ERR_OK;
+    }
+  }
+  /* file not found */
+  return ERR_VAL;
+}
+
+/*-----------------------------------------------------------------------------------*/
+void
+fs_close(struct fs_file *file)
+{
+#if LWIP_HTTPD_CUSTOM_FILES
+  if (file->is_custom_file) {
+    fs_close_custom(file);
+  }
+#endif /* LWIP_HTTPD_CUSTOM_FILES */
+#if LWIP_HTTPD_FILE_STATE
+  fs_state_free(file, file->state);
+#endif /* #if LWIP_HTTPD_FILE_STATE */
+  LWIP_UNUSED_ARG(file);
+}
+/*-----------------------------------------------------------------------------------*/
+#if LWIP_HTTPD_DYNAMIC_FILE_READ
+#if LWIP_HTTPD_FS_ASYNC_READ
+int
+fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg)
+#else /* LWIP_HTTPD_FS_ASYNC_READ */
+int
+fs_read(struct fs_file *file, char *buffer, int count)
+#endif /* LWIP_HTTPD_FS_ASYNC_READ */
+{
+  int read;
+
+  if(file->index == file->len) {
+    return FS_READ_EOF;
+  }
+#if LWIP_HTTPD_FS_ASYNC_READ
+#if LWIP_HTTPD_CUSTOM_FILES
+  if (!fs_canread_custom(file)) {
+    if (fs_wait_read_custom(file, callback_fn, callback_arg)) {
+      return FS_READ_DELAYED;
+    }
+  }
+#else /* LWIP_HTTPD_CUSTOM_FILES */
+  LWIP_UNUSED_ARG(callback_fn);
+  LWIP_UNUSED_ARG(callback_arg);
+#endif /* LWIP_HTTPD_CUSTOM_FILES */
+#endif /* LWIP_HTTPD_FS_ASYNC_READ */
+
+  read = file->len - file->index;
+  if(read > count) {
+    read = count;
+  }
+
+  MEMCPY(buffer, (file->data + file->index), read);
+  file->index += read;
+
+  return(read);
+}
+#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */
+/*-----------------------------------------------------------------------------------*/
+#if LWIP_HTTPD_FS_ASYNC_READ
+int
+fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg)
+{
+  if (file != NULL) {
+#if LWIP_HTTPD_FS_ASYNC_READ
+#if LWIP_HTTPD_CUSTOM_FILES
+    if (!fs_canread_custom(file)) {
+      if (fs_wait_read_custom(file, callback_fn, callback_arg)) {
+        return 0;
+      }
+    }
+#else /* LWIP_HTTPD_CUSTOM_FILES */
+    LWIP_UNUSED_ARG(callback_fn);
+    LWIP_UNUSED_ARG(callback_arg);
+#endif /* LWIP_HTTPD_CUSTOM_FILES */
+#endif /* LWIP_HTTPD_FS_ASYNC_READ */
+  }
+  return 1;
+}
+#endif /* LWIP_HTTPD_FS_ASYNC_READ */
+/*-----------------------------------------------------------------------------------*/
+int
+fs_bytes_left(struct fs_file *file)
+{
+  return file->len - file->index;
+}
diff --git a/extras/httpd/fs.h b/extras/httpd/fs.h
new file mode 100644
index 0000000..c021e2f
--- /dev/null
+++ b/extras/httpd/fs.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved. 
+ * 
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ * 
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+#ifndef __FS_H__
+#define __FS_H__
+
+#include "lwip/opt.h"
+#include "lwip/err.h"
+
+/** Set this to 1 and provide the functions:
+ * - "int fs_open_custom(struct fs_file *file, const char *name)"
+ *    Called first for every opened file to allow opening files
+ *    that are not included in fsdata(_custom).c
+ * - "void fs_close_custom(struct fs_file *file)"
+ *    Called to free resources allocated by fs_open_custom().
+ */
+#ifndef LWIP_HTTPD_CUSTOM_FILES
+#define LWIP_HTTPD_CUSTOM_FILES       0
+#endif
+
+/** Set this to 1 to support fs_read() to dynamically read file data.
+ * Without this (default=off), only one-block files are supported,
+ * and the contents must be ready after fs_open().
+ */
+#ifndef LWIP_HTTPD_DYNAMIC_FILE_READ
+#define LWIP_HTTPD_DYNAMIC_FILE_READ  0
+#endif
+
+/** Set this to 1 to include an application state argument per file
+ * that is opened. This allows to keep a state per connection/file.
+ */
+#ifndef LWIP_HTTPD_FILE_STATE
+#define LWIP_HTTPD_FILE_STATE         0
+#endif
+
+/** HTTPD_PRECALCULATED_CHECKSUM==1: include precompiled checksums for
+ * predefined (MSS-sized) chunks of the files to prevent having to calculate
+ * the checksums at runtime. */
+#ifndef HTTPD_PRECALCULATED_CHECKSUM
+#define HTTPD_PRECALCULATED_CHECKSUM  0
+#endif
+
+/** LWIP_HTTPD_FS_ASYNC_READ==1: support asynchronous read operations
+ * (fs_read_async returns FS_READ_DELAYED and calls a callback when finished).
+ */
+#ifndef LWIP_HTTPD_FS_ASYNC_READ
+#define LWIP_HTTPD_FS_ASYNC_READ      0
+#endif
+
+#define FS_READ_EOF     -1
+#define FS_READ_DELAYED -2
+
+#if HTTPD_PRECALCULATED_CHECKSUM
+struct fsdata_chksum {
+  u32_t offset;
+  u16_t chksum;
+  u16_t len;
+};
+#endif /* HTTPD_PRECALCULATED_CHECKSUM */
+
+struct fs_file {
+  const char *data;
+  int len;
+  int index;
+  void *pextension;
+#if HTTPD_PRECALCULATED_CHECKSUM
+  const struct fsdata_chksum *chksum;
+  u16_t chksum_count;
+#endif /* HTTPD_PRECALCULATED_CHECKSUM */
+  u8_t http_header_included;
+#if LWIP_HTTPD_CUSTOM_FILES
+  u8_t is_custom_file;
+#endif /* LWIP_HTTPD_CUSTOM_FILES */
+#if LWIP_HTTPD_FILE_STATE
+  void *state;
+#endif /* LWIP_HTTPD_FILE_STATE */
+};
+
+#if LWIP_HTTPD_FS_ASYNC_READ
+typedef void (*fs_wait_cb)(void *arg);
+#endif /* LWIP_HTTPD_FS_ASYNC_READ */
+
+err_t fs_open(struct fs_file *file, const char *name);
+void fs_close(struct fs_file *file);
+#if LWIP_HTTPD_DYNAMIC_FILE_READ
+#if LWIP_HTTPD_FS_ASYNC_READ
+int fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg);
+#else /* LWIP_HTTPD_FS_ASYNC_READ */
+int fs_read(struct fs_file *file, char *buffer, int count);
+#endif /* LWIP_HTTPD_FS_ASYNC_READ */
+#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */
+#if LWIP_HTTPD_FS_ASYNC_READ
+int fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg);
+#endif /* LWIP_HTTPD_FS_ASYNC_READ */
+int fs_bytes_left(struct fs_file *file);
+
+#if LWIP_HTTPD_FILE_STATE
+/** This user-defined function is called when a file is opened. */
+void *fs_state_init(struct fs_file *file, const char *name);
+/** This user-defined function is called when a file is closed. */
+void fs_state_free(struct fs_file *file, void *state);
+#endif /* #if LWIP_HTTPD_FILE_STATE */
+
+#endif /* __FS_H__ */
diff --git a/extras/httpd/fsdata.h b/extras/httpd/fsdata.h
new file mode 100644
index 0000000..6f6c557
--- /dev/null
+++ b/extras/httpd/fsdata.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved. 
+ * 
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ * 
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+#ifndef __FSDATA_H__
+#define __FSDATA_H__
+
+#include "lwip/opt.h"
+#include "fs.h"
+
+struct fsdata_file {
+  const struct fsdata_file *next;
+  const unsigned char *name;
+  const unsigned char *data;
+  int len;
+  u8_t http_header_included;
+#if HTTPD_PRECALCULATED_CHECKSUM
+  u16_t chksum_count;
+  const struct fsdata_chksum *chksum;
+#endif /* HTTPD_PRECALCULATED_CHECKSUM */
+};
+
+#endif /* __FSDATA_H__ */
diff --git a/extras/httpd/httpd.c b/extras/httpd/httpd.c
new file mode 100644
index 0000000..04e4bc5
--- /dev/null
+++ b/extras/httpd/httpd.c
@@ -0,0 +1,2504 @@
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *         Simon Goldschmidt
+ *
+ */
+
+/* This httpd supports for a
+ * rudimentary server-side-include facility which will replace tags of the form
+ * <!--#tag--> in any file whose extension is .shtml, .shtm or .ssi with
+ * strings provided by an include handler whose pointer is provided to the
+ * module via function http_set_ssi_handler().
+ * Additionally, a simple common
+ * gateway interface (CGI) handling mechanism has been added to allow clients
+ * to hook functions to particular request URIs.
+ *
+ * To enable SSI support, define label LWIP_HTTPD_SSI in lwipopts.h.
+ * To enable CGI support, define label LWIP_HTTPD_CGI in lwipopts.h.
+ *
+ * By default, the server assumes that HTTP headers are already present in
+ * each file stored in the file system.  By defining LWIP_HTTPD_DYNAMIC_HEADERS in
+ * lwipopts.h, this behavior can be changed such that the server inserts the
+ * headers automatically based on the extension of the file being served.  If
+ * this mode is used, be careful to ensure that the file system image used
+ * does not already contain the header information.
+ *
+ * File system images without headers can be created using the makefsfile
+ * tool with the -h command line option.
+ *
+ *
+ * Notes about valid SSI tags
+ * --------------------------
+ *
+ * The following assumptions are made about tags used in SSI markers:
+ *
+ * 1. No tag may contain '-' or whitespace characters within the tag name.
+ * 2. Whitespace is allowed between the tag leadin "<!--#" and the start of
+ *    the tag name and between the tag name and the leadout string "-->".
+ * 3. The maximum tag name length is LWIP_HTTPD_MAX_TAG_NAME_LEN, currently 8 characters.
+ *
+ * Notes on CGI usage
+ * ------------------
+ *
+ * The simple CGI support offered here works with GET method requests only
+ * and can handle up to 16 parameters encoded into the URI. The handler
+ * function may not write directly to the HTTP output but must return a
+ * filename that the HTTP server will send to the browser as a response to
+ * the incoming CGI request.
+ *
+ *
+ *
+ * The list of supported file types is quite short, so if makefsdata complains
+ * about an unknown extension, make sure to add it (and its doctype) to
+ * the 'g_psHTTPHeaders' list.
+ */
+#include "httpd.h"
+#include "lwip/debug.h"
+#include "lwip/stats.h"
+#include "httpd_structs.h"
+#include "lwip/tcp.h"
+#include "fs.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#if LWIP_TCP
+
+#ifndef HTTPD_DEBUG
+#define HTTPD_DEBUG         LWIP_DBG_OFF
+#endif
+
+/** Set this to 1 and add the next line to lwippools.h to use a memp pool
+ * for allocating struct http_state instead of the heap:
+ *
+ * LWIP_MEMPOOL(HTTPD_STATE, 20, 100, "HTTPD_STATE")
+ */
+#ifndef HTTPD_USE_MEM_POOL
+#define HTTPD_USE_MEM_POOL  0
+#endif
+
+/** The server port for HTTPD to use */
+#ifndef HTTPD_SERVER_PORT
+#define HTTPD_SERVER_PORT                   80
+#endif
+
+/** Maximum retries before the connection is aborted/closed.
+ * - number of times pcb->poll is called -> default is 4*500ms = 2s;
+ * - reset when pcb->sent is called
+ */
+#ifndef HTTPD_MAX_RETRIES
+#define HTTPD_MAX_RETRIES                   4
+#endif
+
+/** The poll delay is X*500ms */
+#ifndef HTTPD_POLL_INTERVAL
+#define HTTPD_POLL_INTERVAL                 4
+#endif
+
+/** Priority for tcp pcbs created by HTTPD (very low by default).
+ *  Lower priorities get killed first when running out of memroy.
+ */
+#ifndef HTTPD_TCP_PRIO
+#define HTTPD_TCP_PRIO                      TCP_PRIO_MIN
+#endif
+
+/** Set this to 1 to enabled timing each file sent */
+#ifndef LWIP_HTTPD_TIMING
+#define LWIP_HTTPD_TIMING                   0
+#endif
+#ifndef HTTPD_DEBUG_TIMING
+#define HTTPD_DEBUG_TIMING                  LWIP_DBG_OFF
+#endif
+
+/** Set this to 1 on platforms where strnstr is not available */
+#ifndef LWIP_HTTPD_STRNSTR_PRIVATE
+#define LWIP_HTTPD_STRNSTR_PRIVATE          1
+#endif
+
+/** Set this to one to show error pages when parsing a request fails instead
+    of simply closing the connection. */
+#ifndef LWIP_HTTPD_SUPPORT_EXTSTATUS
+#define LWIP_HTTPD_SUPPORT_EXTSTATUS        0
+#endif
+
+/** Set this to 0 to drop support for HTTP/0.9 clients (to save some bytes) */
+#ifndef LWIP_HTTPD_SUPPORT_V09
+#define LWIP_HTTPD_SUPPORT_V09              1
+#endif
+
+/** Set this to 1 to enable HTTP/1.1 persistent connections.
+ * ATTENTION: If the generated file system includes HTTP headers, these must
+ * include the "Connection: keep-alive" header (pass argument "-11" to makefsdata).
+ */
+#ifndef LWIP_HTTPD_SUPPORT_11_KEEPALIVE
+#define LWIP_HTTPD_SUPPORT_11_KEEPALIVE     0
+#endif
+
+/** Set this to 1 to support HTTP request coming in in multiple packets/pbufs */
+#ifndef LWIP_HTTPD_SUPPORT_REQUESTLIST
+#define LWIP_HTTPD_SUPPORT_REQUESTLIST      1
+#endif
+
+#if LWIP_HTTPD_SUPPORT_REQUESTLIST
+/** Number of rx pbufs to enqueue to parse an incoming request (up to the first
+    newline) */
+#ifndef LWIP_HTTPD_REQ_QUEUELEN
+#define LWIP_HTTPD_REQ_QUEUELEN             5
+#endif
+
+/** Number of (TCP payload-) bytes (in pbufs) to enqueue to parse and incoming
+    request (up to the first double-newline) */
+#ifndef LWIP_HTTPD_REQ_BUFSIZE
+#define LWIP_HTTPD_REQ_BUFSIZE              LWIP_HTTPD_MAX_REQ_LENGTH
+#endif
+
+/** Defines the maximum length of a HTTP request line (up to the first CRLF,
+    copied from pbuf into this a global buffer when pbuf- or packet-queues
+    are received - otherwise the input pbuf is used directly) */
+#ifndef LWIP_HTTPD_MAX_REQ_LENGTH
+#define LWIP_HTTPD_MAX_REQ_LENGTH           LWIP_MIN(1023, (LWIP_HTTPD_REQ_QUEUELEN * PBUF_POOL_BUFSIZE))
+#endif
+#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
+
+/** Maximum length of the filename to send as response to a POST request,
+ * filled in by the application when a POST is finished.
+ */
+#ifndef LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN
+#define LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN 63
+#endif
+
+/** Set this to 0 to not send the SSI tag (default is on, so the tag will
+ * be sent in the HTML page */
+#ifndef LWIP_HTTPD_SSI_INCLUDE_TAG
+#define LWIP_HTTPD_SSI_INCLUDE_TAG           1
+#endif
+
+/** Set this to 1 to call tcp_abort when tcp_close fails with memory error.
+ * This can be used to prevent consuming all memory in situations where the
+ * HTTP server has low priority compared to other communication. */
+#ifndef LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR
+#define LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR  0
+#endif
+
+/** Set this to 1 to kill the oldest connection when running out of
+ * memory for 'struct http_state' or 'struct http_ssi_state'.
+ * ATTENTION: This puts all connections on a linked list, so may be kind of slow.
+ */
+#ifndef LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
+#define LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED 0
+#endif
+
+/** Minimum length for a valid HTTP/0.9 request: "GET /\r\n" -> 7 bytes */
+#define MIN_REQ_LEN   7
+
+#define CRLF "\r\n"
+#define HTTP11_CONNECTIONKEEPALIVE "Connection: keep-alive"
+
+#if LWIP_HTTPD_SSI
+#define LWIP_HTTPD_IS_SSI(hs) ((hs)->ssi)
+#else /* LWIP_HTTPD_SSI */
+#define LWIP_HTTPD_IS_SSI(hs) 0
+#endif /* LWIP_HTTPD_SSI */
+
+/** These defines check whether tcp_write has to copy data or not */
+
+/** This was TI's check whether to let TCP copy data or not
+#define HTTP_IS_DATA_VOLATILE(hs) ((hs->file < (char *)0x20000000) ? 0 : TCP_WRITE_FLAG_COPY)*/
+#ifndef HTTP_IS_DATA_VOLATILE
+#if LWIP_HTTPD_SSI
+/* Copy for SSI files, no copy for non-SSI files */
+#define HTTP_IS_DATA_VOLATILE(hs)   ((hs)->ssi ? TCP_WRITE_FLAG_COPY : 0)
+#else /* LWIP_HTTPD_SSI */
+/** Default: don't copy if the data is sent from file-system directly */
+#define HTTP_IS_DATA_VOLATILE(hs) (((hs->file != NULL) && (hs->handle != NULL) && (hs->file == \
+                                   (char*)hs->handle->data + hs->handle->len - hs->left)) \
+                                   ? 0 : TCP_WRITE_FLAG_COPY)
+#endif /* LWIP_HTTPD_SSI */
+#endif
+
+/** Default: headers are sent from ROM */
+#ifndef HTTP_IS_HDR_VOLATILE
+#define HTTP_IS_HDR_VOLATILE(hs, ptr) 0
+#endif
+
+#if LWIP_HTTPD_SSI
+/** Default: Tags are sent from struct http_state and are therefore volatile */
+#ifndef HTTP_IS_TAG_VOLATILE
+#define HTTP_IS_TAG_VOLATILE(ptr) TCP_WRITE_FLAG_COPY
+#endif
+#endif /* LWIP_HTTPD_SSI */
+
+/* Return values for http_send_*() */
+#define HTTP_DATA_TO_SEND_BREAK    2
+#define HTTP_DATA_TO_SEND_CONTINUE 1
+#define HTTP_NO_DATA_TO_SEND       0
+
+#if HTTPD_USE_MEM_POOL
+#define HTTP_ALLOC_SSI_STATE()  (struct http_ssi_state *)memp_malloc(MEMP_HTTPD_SSI_STATE)
+#define HTTP_ALLOC_HTTP_STATE() (struct http_state *)memp_malloc(MEMP_HTTPD_STATE)
+#else /* HTTPD_USE_MEM_POOL */
+#define HTTP_ALLOC_SSI_STATE()  (struct http_ssi_state *)mem_malloc(sizeof(struct http_ssi_state))
+#define HTTP_ALLOC_HTTP_STATE() (struct http_state *)mem_malloc(sizeof(struct http_state))
+#endif /* HTTPD_USE_MEM_POOL */
+
+typedef struct
+{
+  const char *name;
+  u8_t shtml;
+} default_filename;
+
+const default_filename g_psDefaultFilenames[] = {
+  {"/index.shtml", 1 },
+  {"/index.ssi",   1 },
+  {"/index.shtm",  1 },
+  {"/index.html",  0 },
+  {"/index.htm",   0 }
+};
+
+#define NUM_DEFAULT_FILENAMES (sizeof(g_psDefaultFilenames) /   \
+                               sizeof(default_filename))
+
+#if LWIP_HTTPD_SUPPORT_REQUESTLIST
+/** HTTP request is copied here from pbufs for simple parsing */
+static char httpd_req_buf[LWIP_HTTPD_MAX_REQ_LENGTH+1];
+#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
+
+#if LWIP_HTTPD_SUPPORT_POST
+/** Filename for response file to send when POST is finished */
+static char http_post_response_filename[LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN+1];
+#endif /* LWIP_HTTPD_SUPPORT_POST */
+
+#if LWIP_HTTPD_DYNAMIC_HEADERS
+/* The number of individual strings that comprise the headers sent before each
+ * requested file.
+ */
+#define NUM_FILE_HDR_STRINGS 3
+#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
+
+#if LWIP_HTTPD_SSI
+
+#define HTTPD_LAST_TAG_PART 0xFFFF
+
+enum tag_check_state {
+  TAG_NONE,       /* Not processing an SSI tag */
+  TAG_LEADIN,     /* Tag lead in "<!--#" being processed */
+  TAG_FOUND,      /* Tag name being read, looking for lead-out start */
+  TAG_LEADOUT,    /* Tag lead out "-->" being processed */
+  TAG_SENDING     /* Sending tag replacement string */
+};
+
+struct http_ssi_state {
+  const char *parsed;     /* Pointer to the first unparsed byte in buf. */
+#if !LWIP_HTTPD_SSI_INCLUDE_TAG
+  const char *tag_started;/* Pointer to the first opening '<' of the tag. */
+#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG */
+  const char *tag_end;    /* Pointer to char after the closing '>' of the tag. */
+  u32_t parse_left; /* Number of unparsed bytes in buf. */
+  u16_t tag_index;   /* Counter used by tag parsing state machine */
+  u16_t tag_insert_len; /* Length of insert in string tag_insert */
+#if LWIP_HTTPD_SSI_MULTIPART
+  u16_t tag_part; /* Counter passed to and changed by tag insertion function to insert multiple times */
+#endif /* LWIP_HTTPD_SSI_MULTIPART */
+  u8_t tag_name_len; /* Length of the tag name in string tag_name */
+  char tag_name[LWIP_HTTPD_MAX_TAG_NAME_LEN + 1]; /* Last tag name extracted */
+  char tag_insert[LWIP_HTTPD_MAX_TAG_INSERT_LEN + 1]; /* Insert string for tag_name */
+  enum tag_check_state tag_state; /* State of the tag processor */
+};
+#endif /* LWIP_HTTPD_SSI */
+
+struct http_state {
+#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
+  struct http_state *next;
+#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
+  struct fs_file file_handle;
+  struct fs_file *handle;
+  char *file;       /* Pointer to first unsent byte in buf. */
+
+  struct tcp_pcb *pcb;
+#if LWIP_HTTPD_SUPPORT_REQUESTLIST
+  struct pbuf *req;
+#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
+
+#if LWIP_HTTPD_DYNAMIC_FILE_READ
+  char *buf;        /* File read buffer. */
+  int buf_len;      /* Size of file read buffer, buf. */
+#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */
+  u32_t left;       /* Number of unsent bytes in buf. */
+  u8_t retries;
+#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
+  u8_t keepalive;
+#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */
+#if LWIP_HTTPD_SSI
+  struct http_ssi_state *ssi;
+#endif /* LWIP_HTTPD_SSI */
+#if LWIP_HTTPD_CGI
+  char *params[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Params extracted from the request URI */
+  char *param_vals[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Values for each extracted param */
+#endif /* LWIP_HTTPD_CGI */
+#if LWIP_HTTPD_DYNAMIC_HEADERS
+  const char *hdrs[NUM_FILE_HDR_STRINGS]; /* HTTP headers to be sent. */
+  u16_t hdr_pos;     /* The position of the first unsent header byte in the
+                        current string */
+  u16_t hdr_index;   /* The index of the hdr string currently being sent. */
+#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
+#if LWIP_HTTPD_TIMING
+  u32_t time_started;
+#endif /* LWIP_HTTPD_TIMING */
+#if LWIP_HTTPD_SUPPORT_POST
+  u32_t post_content_len_left;
+#if LWIP_HTTPD_POST_MANUAL_WND
+  u32_t unrecved_bytes;
+  u8_t no_auto_wnd;
+  u8_t post_finished;
+#endif /* LWIP_HTTPD_POST_MANUAL_WND */
+#endif /* LWIP_HTTPD_SUPPORT_POST*/
+};
+
+static err_t http_close_conn(struct tcp_pcb *pcb, struct http_state *hs);
+static err_t http_close_or_abort_conn(struct tcp_pcb *pcb, struct http_state *hs, u8_t abort_conn);
+static err_t http_find_file(struct http_state *hs, const char *uri, int is_09);
+static err_t http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri, u8_t tag_check);
+static err_t http_poll(void *arg, struct tcp_pcb *pcb);
+#if LWIP_HTTPD_FS_ASYNC_READ
+static void http_continue(void *connection);
+#endif /* LWIP_HTTPD_FS_ASYNC_READ */
+
+#if LWIP_HTTPD_SSI
+/* SSI insert handler function pointer. */
+tSSIHandler g_pfnSSIHandler = NULL;
+int g_iNumTags = 0;
+const char **g_ppcTags = NULL;
+
+#define LEN_TAG_LEAD_IN 5
+const char * const g_pcTagLeadIn = "<!--#";
+
+#define LEN_TAG_LEAD_OUT 3
+const char * const g_pcTagLeadOut = "-->";
+#endif /* LWIP_HTTPD_SSI */
+
+#if LWIP_HTTPD_CGI
+/* CGI handler information */
+const tCGI *g_pCGIs;
+int g_iNumCGIs;
+#endif /* LWIP_HTTPD_CGI */
+
+#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
+/** global list of active HTTP connections, use to kill the oldest when
+    running out of memory */
+static struct http_state *http_connections;
+#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
+
+#if LWIP_HTTPD_STRNSTR_PRIVATE
+/** Like strstr but does not need 'buffer' to be NULL-terminated */
+static char*
+strnstr(const char* buffer, const char* token, size_t n)
+{
+  const char* p;
+  int tokenlen = (int)strlen(token);
+  if (tokenlen == 0) {
+    return (char *)buffer;
+  }
+  for (p = buffer; *p && (p + tokenlen <= buffer + n); p++) {
+    if ((*p == *token) && (strncmp(p, token, tokenlen) == 0)) {
+      return (char *)p;
+    }
+  }
+  return NULL;
+}
+#endif /* LWIP_HTTPD_STRNSTR_PRIVATE */
+
+#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
+static void
+http_kill_oldest_connection(u8_t ssi_required)
+{
+  struct http_state *hs = http_connections;
+  struct http_state *hs_free_next = NULL;
+  while(hs && hs->next) {
+    if (ssi_required) {
+      if (hs->next->ssi != NULL) {
+        hs_free_next = hs;
+      }
+    } else {
+      hs_free_next = hs;
+    }
+    hs = hs->next;
+  }
+  if (hs_free_next != NULL) {
+    LWIP_ASSERT("hs_free_next->next != NULL", hs_free_next->next != NULL);
+    LWIP_ASSERT("hs_free_next->next->pcb != NULL", hs_free_next->next->pcb != NULL);
+    /* send RST when killing a connection because of memory shortage */
+    http_close_or_abort_conn(hs_free_next->next->pcb, hs_free_next->next, 1); /* this also unlinks the http_state from the list */
+  }
+}
+#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
+
+#if LWIP_HTTPD_SSI
+/** Allocate as struct http_ssi_state. */
+static struct http_ssi_state*
+http_ssi_state_alloc(void)
+{
+  struct http_ssi_state *ret = HTTP_ALLOC_SSI_STATE();
+#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
+  if (ret == NULL) {
+    http_kill_oldest_connection(1);
+    ret = HTTP_ALLOC_SSI_STATE();
+  }
+#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
+  if (ret != NULL) {
+    memset(ret, 0, sizeof(struct http_ssi_state));
+  }
+  return ret;
+}
+
+/** Free a struct http_ssi_state. */
+static void
+http_ssi_state_free(struct http_ssi_state *ssi)
+{
+  if (ssi != NULL) {
+#if HTTPD_USE_MEM_POOL
+    memp_free(MEMP_HTTPD_SSI_STATE, ssi);
+#else /* HTTPD_USE_MEM_POOL */
+    mem_free(ssi);
+#endif /* HTTPD_USE_MEM_POOL */
+  }
+}
+#endif /* LWIP_HTTPD_SSI */
+
+/** Initialize a struct http_state.
+ */
+static void
+http_state_init(struct http_state* hs)
+{
+  /* Initialize the structure. */
+  memset(hs, 0, sizeof(struct http_state));
+#if LWIP_HTTPD_DYNAMIC_HEADERS
+  /* Indicate that the headers are not yet valid */
+  hs->hdr_index = NUM_FILE_HDR_STRINGS;
+#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
+}
+
+/** Allocate a struct http_state. */
+static struct http_state*
+http_state_alloc(void)
+{
+  struct http_state *ret = HTTP_ALLOC_HTTP_STATE();
+#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
+  if (ret == NULL) {
+    http_kill_oldest_connection(0);
+    ret = HTTP_ALLOC_HTTP_STATE();
+  }
+#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
+  if (ret != NULL) {
+    http_state_init(ret);
+#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
+    /* add the connection to the list */
+    if (http_connections == NULL) {
+      http_connections = ret;
+    } else {
+      struct http_state *last;
+      for(last = http_connections; last->next != NULL; last = last->next);
+      LWIP_ASSERT("last != NULL", last != NULL);
+      last->next = ret;
+    }
+#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
+  }
+  return ret;
+}
+
+/** Free a struct http_state.
+ * Also frees the file data if dynamic.
+ */
+static void
+http_state_eof(struct http_state *hs)
+{
+  if(hs->handle) {
+#if LWIP_HTTPD_TIMING
+    u32_t ms_needed = sys_now() - hs->time_started;
+    u32_t needed = LWIP_MAX(1, (ms_needed/100));
+    LWIP_DEBUGF(HTTPD_DEBUG_TIMING, ("httpd: needed %"U32_F" ms to send file of %d bytes -> %"U32_F" bytes/sec\n",
+      ms_needed, hs->handle->len, ((((u32_t)hs->handle->len) * 10) / needed)));
+#endif /* LWIP_HTTPD_TIMING */
+    fs_close(hs->handle);
+    hs->handle = NULL;
+  }
+#if LWIP_HTTPD_DYNAMIC_FILE_READ
+  if (hs->buf != NULL) {
+    mem_free(hs->buf);
+    hs->buf = NULL;
+  }
+#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */
+#if LWIP_HTTPD_SSI
+  if (hs->ssi) {
+    http_ssi_state_free(hs->ssi);
+    hs->ssi = NULL;
+  }
+#endif /* LWIP_HTTPD_SSI */
+}
+
+/** Free a struct http_state.
+ * Also frees the file data if dynamic.
+ */
+static void
+http_state_free(struct http_state *hs)
+{
+  if (hs != NULL) {
+    http_state_eof(hs);
+#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED
+    /* take the connection off the list */
+    if (http_connections) {
+      if (http_connections == hs) {
+        http_connections = hs->next;
+      } else {
+        struct http_state *last;
+        for(last = http_connections; last->next != NULL; last = last->next) {
+          if (last->next == hs) {
+            last->next = hs->next;
+            break;
+          }
+        }
+      }
+    }
+#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */
+#if HTTPD_USE_MEM_POOL
+    memp_free(MEMP_HTTPD_STATE, hs);
+#else /* HTTPD_USE_MEM_POOL */
+    mem_free(hs);
+#endif /* HTTPD_USE_MEM_POOL */
+  }
+}
+
+/** Call tcp_write() in a loop trying smaller and smaller length
+ *
+ * @param pcb tcp_pcb to send
+ * @param ptr Data to send
+ * @param length Length of data to send (in/out: on return, contains the
+ *        amount of data sent)
+ * @param apiflags directly passed to tcp_write
+ * @return the return value of tcp_write
+ */
+static err_t
+http_write(struct tcp_pcb *pcb, const void* ptr, u16_t *length, u8_t apiflags)
+{
+   u16_t len;
+   err_t err;
+   LWIP_ASSERT("length != NULL", length != NULL);
+   len = *length;
+   if (len == 0) {
+     return ERR_OK;
+   }
+   do {
+     LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Trying to send %d bytes\n", len));
+     err = tcp_write(pcb, ptr, len, apiflags);
+     if (err == ERR_MEM) {
+       if ((tcp_sndbuf(pcb) == 0) ||
+           (tcp_sndqueuelen(pcb) >= TCP_SND_QUEUELEN)) {
+         /* no need to try smaller sizes */
+         len = 1;
+       } else {
+         len /= 2;
+       }
+       LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE,
+                   ("Send failed, trying less (%d bytes)\n", len));
+     }
+   } while ((err == ERR_MEM) && (len > 1));
+
+   if (err == ERR_OK) {
+     LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Sent %d bytes\n", len));
+   } else {
+     LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Send failed with err %d (\"%s\")\n", err, lwip_strerr(err)));
+   }
+
+   *length = len;
+   return err;
+}
+
+/**
+ * The connection shall be actively closed (using RST to close from fault states).
+ * Reset the sent- and recv-callbacks.
+ *
+ * @param pcb the tcp pcb to reset callbacks
+ * @param hs connection state to free
+ */
+static err_t
+http_close_or_abort_conn(struct tcp_pcb *pcb, struct http_state *hs, u8_t abort_conn)
+{
+  err_t err;
+  LWIP_DEBUGF(HTTPD_DEBUG, ("Closing connection %p\n", (void*)pcb));
+
+#if LWIP_HTTPD_SUPPORT_POST
+  if (hs != NULL) {
+    if ((hs->post_content_len_left != 0)
+#if LWIP_HTTPD_POST_MANUAL_WND
+       || ((hs->no_auto_wnd != 0) && (hs->unrecved_bytes != 0))
+#endif /* LWIP_HTTPD_POST_MANUAL_WND */
+       ) {
+      /* make sure the post code knows that the connection is closed */
+      http_post_response_filename[0] = 0;
+      httpd_post_finished(hs, http_post_response_filename, LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN);
+    }
+  }
+#endif /* LWIP_HTTPD_SUPPORT_POST*/
+
+
+  tcp_arg(pcb, NULL);
+  tcp_recv(pcb, NULL);
+  tcp_err(pcb, NULL);
+  tcp_poll(pcb, NULL, 0);
+  tcp_sent(pcb, NULL);
+  if (hs != NULL) {
+    http_state_free(hs);
+  }
+
+  if (abort_conn) {
+    tcp_abort(pcb);
+    return ERR_OK;
+  }
+  err = tcp_close(pcb);
+  if (err != ERR_OK) {
+    LWIP_DEBUGF(HTTPD_DEBUG, ("Error %d closing %p\n", err, (void*)pcb));
+    /* error closing, try again later in poll */
+    tcp_poll(pcb, http_poll, HTTPD_POLL_INTERVAL);
+  }
+  return err;
+}
+
+/**
+ * The connection shall be actively closed.
+ * Reset the sent- and recv-callbacks.
+ *
+ * @param pcb the tcp pcb to reset callbacks
+ * @param hs connection state to free
+ */
+static err_t
+http_close_conn(struct tcp_pcb *pcb, struct http_state *hs)
+{
+   return http_close_or_abort_conn(pcb, hs, 0);
+}
+
+/** End of file: either close the connection (Connection: close) or
+ * close the file (Connection: keep-alive)
+ */
+static void
+http_eof(struct tcp_pcb *pcb, struct http_state *hs)
+{
+  /* HTTP/1.1 persistent connection? (Not supported for SSI) */
+#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
+  if (hs->keepalive && !LWIP_HTTPD_IS_SSI(hs)) {
+    http_state_eof(hs);
+    http_state_init(hs);
+    hs->keepalive = 1;
+  } else
+#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */
+  {
+    http_close_conn(pcb, hs);
+  }
+}
+
+#if LWIP_HTTPD_CGI
+/**
+ * Extract URI parameters from the parameter-part of an URI in the form
+ * "test.cgi?x=y" @todo: better explanation!
+ * Pointers to the parameters are stored in hs->param_vals.
+ *
+ * @param hs http connection state
+ * @param params pointer to the NULL-terminated parameter string from the URI
+ * @return number of parameters extracted
+ */
+static int
+extract_uri_parameters(struct http_state *hs, char *params)
+{
+  char *pair;
+  char *equals;
+  int loop;
+
+  /* If we have no parameters at all, return immediately. */
+  if(!params || (params[0] == '\0')) {
+      return(0);
+  }
+
+  /* Get a pointer to our first parameter */
+  pair = params;
+
+  /* Parse up to LWIP_HTTPD_MAX_CGI_PARAMETERS from the passed string and ignore the
+   * remainder (if any) */
+  for(loop = 0; (loop < LWIP_HTTPD_MAX_CGI_PARAMETERS) && pair; loop++) {
+
+    /* Save the name of the parameter */
+    hs->params[loop] = pair;
+
+    /* Remember the start of this name=value pair */
+    equals = pair;
+
+    /* Find the start of the next name=value pair and replace the delimiter
+     * with a 0 to terminate the previous pair string. */
+    pair = strchr(pair, '&');
+    if(pair) {
+      *pair = '\0';
+      pair++;
+    } else {
+       /* We didn't find a new parameter so find the end of the URI and
+        * replace the space with a '\0' */
+        pair = strchr(equals, ' ');
+        if(pair) {
+            *pair = '\0';
+        }
+
+        /* Revert to NULL so that we exit the loop as expected. */
+        pair = NULL;
+    }
+
+    /* Now find the '=' in the previous pair, replace it with '\0' and save
+     * the parameter value string. */
+    equals = strchr(equals, '=');
+    if(equals) {
+      *equals = '\0';
+      hs->param_vals[loop] = equals + 1;
+    } else {
+      hs->param_vals[loop] = NULL;
+    }
+  }
+
+  return loop;
+}
+#endif /* LWIP_HTTPD_CGI */
+
+#if LWIP_HTTPD_SSI
+/**
+ * Insert a tag (found in an shtml in the form of "<!--#tagname-->" into the file.
+ * The tag's name is stored in ssi->tag_name (NULL-terminated), the replacement
+ * should be written to hs->tag_insert (up to a length of LWIP_HTTPD_MAX_TAG_INSERT_LEN).
+ * The amount of data written is stored to ssi->tag_insert_len.
+ *
+ * @todo: return tag_insert_len - maybe it can be removed from struct http_state?
+ *
+ * @param hs http connection state
+ */
+static void
+get_tag_insert(struct http_state *hs)
+{
+  int loop;
+  size_t len;
+  struct http_ssi_state *ssi;
+  LWIP_ASSERT("hs != NULL", hs != NULL);
+  ssi = hs->ssi;
+  LWIP_ASSERT("ssi != NULL", ssi != NULL);
+#if LWIP_HTTPD_SSI_MULTIPART
+  u16_t current_tag_part = ssi->tag_part;
+  ssi->tag_part = HTTPD_LAST_TAG_PART;
+#endif /* LWIP_HTTPD_SSI_MULTIPART */
+
+  if(g_pfnSSIHandler && g_ppcTags && g_iNumTags) {
+
+    /* Find this tag in the list we have been provided. */
+    for(loop = 0; loop < g_iNumTags; loop++) {
+      if(strcmp(ssi->tag_name, g_ppcTags[loop]) == 0) {
+        ssi->tag_insert_len = g_pfnSSIHandler(loop, ssi->tag_insert,
+           LWIP_HTTPD_MAX_TAG_INSERT_LEN
+#if LWIP_HTTPD_SSI_MULTIPART
+           , current_tag_part, &ssi->tag_part
+#endif /* LWIP_HTTPD_SSI_MULTIPART */
+#if LWIP_HTTPD_FILE_STATE
+           , hs->handle->state
+#endif /* LWIP_HTTPD_FILE_STATE */
+           );
+        return;
+      }
+    }
+  }
+
+  /* If we drop out, we were asked to serve a page which contains tags that
+   * we don't have a handler for. Merely echo back the tags with an error
+   * marker. */
+#define UNKNOWN_TAG1_TEXT "<b>***UNKNOWN TAG "
+#define UNKNOWN_TAG1_LEN  18
+#define UNKNOWN_TAG2_TEXT "***</b>"
+#define UNKNOWN_TAG2_LEN  7
+  len = LWIP_MIN(strlen(ssi->tag_name),
+    LWIP_HTTPD_MAX_TAG_INSERT_LEN - (UNKNOWN_TAG1_LEN + UNKNOWN_TAG2_LEN));
+  MEMCPY(ssi->tag_insert, UNKNOWN_TAG1_TEXT, UNKNOWN_TAG1_LEN);
+  MEMCPY(&ssi->tag_insert[UNKNOWN_TAG1_LEN], ssi->tag_name, len);
+  MEMCPY(&ssi->tag_insert[UNKNOWN_TAG1_LEN + len], UNKNOWN_TAG2_TEXT, UNKNOWN_TAG2_LEN);
+  ssi->tag_insert[UNKNOWN_TAG1_LEN + len + UNKNOWN_TAG2_LEN] = 0;
+
+  len = strlen(ssi->tag_insert);
+  LWIP_ASSERT("len <= 0xffff", len <= 0xffff);
+  ssi->tag_insert_len = (u16_t)len;
+}
+#endif /* LWIP_HTTPD_SSI */
+
+#if LWIP_HTTPD_DYNAMIC_HEADERS
+/**
+ * Generate the relevant HTTP headers for the given filename and write
+ * them into the supplied buffer.
+ */
+static void
+get_http_headers(struct http_state *pState, char *pszURI)
+{
+  unsigned int iLoop;
+  char *pszWork;
+  char *pszExt;
+  char *pszVars;
+
+  /* Ensure that we initialize the loop counter. */
+  iLoop = 0;
+
+  /* In all cases, the second header we send is the server identification
+     so set it here. */
+  pState->hdrs[1] = g_psHTTPHeaderStrings[HTTP_HDR_SERVER];
+
+  /* Is this a normal file or the special case we use to send back the
+     default "404: Page not found" response? */
+  if (pszURI == NULL) {
+    pState->hdrs[0] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND];
+    pState->hdrs[2] = g_psHTTPHeaderStrings[DEFAULT_404_HTML];
+
+    /* Set up to send the first header string. */
+    pState->hdr_index = 0;
+    pState->hdr_pos = 0;
+    return;
+  } else {
+    /* We are dealing with a particular filename. Look for one other
+       special case.  We assume that any filename with "404" in it must be
+       indicative of a 404 server error whereas all other files require
+       the 200 OK header. */
+    if (strstr(pszURI, "404")) {
+      pState->hdrs[0] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND];
+    } else if (strstr(pszURI, "400")) {
+      pState->hdrs[0] = g_psHTTPHeaderStrings[HTTP_HDR_BAD_REQUEST];
+    } else if (strstr(pszURI, "501")) {
+      pState->hdrs[0] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_IMPL];
+    } else {
+      pState->hdrs[0] = g_psHTTPHeaderStrings[HTTP_HDR_OK];
+    }
+
+    /* Determine if the URI has any variables and, if so, temporarily remove
+       them. */
+    pszVars = strchr(pszURI, '?');
+    if(pszVars) {
+      *pszVars = '\0';
+    }
+
+    /* Get a pointer to the file extension.  We find this by looking for the
+       last occurrence of "." in the filename passed. */
+    pszExt = NULL;
+    pszWork = strchr(pszURI, '.');
+    while(pszWork) {
+      pszExt = pszWork + 1;
+      pszWork = strchr(pszExt, '.');
+    }
+
+    /* Now determine the content type and add the relevant header for that. */
+    for(iLoop = 0; (iLoop < NUM_HTTP_HEADERS) && pszExt; iLoop++) {
+      /* Have we found a matching extension? */
+      if(!strcmp(g_psHTTPHeaders[iLoop].extension, pszExt)) {
+        pState->hdrs[2] =
+          g_psHTTPHeaderStrings[g_psHTTPHeaders[iLoop].headerIndex];
+        break;
+      }
+    }
+
+    /* Reinstate the parameter marker if there was one in the original URI. */
+    if(pszVars) {
+      *pszVars = '?';
+    }
+  }
+
+  /* Does the URL passed have any file extension?  If not, we assume it
+     is a special-case URL used for control state notification and we do
+     not send any HTTP headers with the response. */
+  if(!pszExt) {
+    /* Force the header index to a value indicating that all headers
+       have already been sent. */
+    pState->hdr_index = NUM_FILE_HDR_STRINGS;
+  } else {
+    /* Did we find a matching extension? */
+    if(iLoop == NUM_HTTP_HEADERS) {
+      /* No - use the default, plain text file type. */
+      pState->hdrs[2] = g_psHTTPHeaderStrings[HTTP_HDR_DEFAULT_TYPE];
+    }
+
+    /* Set up to send the first header string. */
+    pState->hdr_index = 0;
+    pState->hdr_pos = 0;
+  }
+}
+
+/** Sub-function of http_send(): send dynamic headers
+ *
+ * @returns: - HTTP_NO_DATA_TO_SEND: no new data has been enqueued
+ *           - HTTP_DATA_TO_SEND_CONTINUE: continue with sending HTTP body
+ *           - HTTP_DATA_TO_SEND_BREAK: data has been enqueued, headers pending,
+ *                                      so don't send HTTP body yet
+ */
+static u8_t
+http_send_headers(struct tcp_pcb *pcb, struct http_state *hs)
+{
+  err_t err;
+  u16_t len;
+  u8_t data_to_send = HTTP_NO_DATA_TO_SEND;
+  u16_t hdrlen, sendlen;
+
+  /* How much data can we send? */
+  len = tcp_sndbuf(pcb);
+  sendlen = len;
+
+  while(len && (hs->hdr_index < NUM_FILE_HDR_STRINGS) && sendlen) {
+    const void *ptr;
+    u16_t old_sendlen;
+    /* How much do we have to send from the current header? */
+    hdrlen = (u16_t)strlen(hs->hdrs[hs->hdr_index]);
+
+    /* How much of this can we send? */
+    sendlen = (len < (hdrlen - hs->hdr_pos)) ? len : (hdrlen - hs->hdr_pos);
+
+    /* Send this amount of data or as much as we can given memory
+    * constraints. */
+    ptr = (const void *)(hs->hdrs[hs->hdr_index] + hs->hdr_pos);
+    old_sendlen = sendlen;
+    err = http_write(pcb, ptr, &sendlen, HTTP_IS_HDR_VOLATILE(hs, ptr));
+    if ((err == ERR_OK) && (old_sendlen != sendlen)) {
+      /* Remember that we added some more data to be transmitted. */
+      data_to_send = HTTP_DATA_TO_SEND_CONTINUE;
+    } else if (err != ERR_OK) {
+       /* special case: http_write does not try to send 1 byte */
+      sendlen = 0;
+    }
+
+    /* Fix up the header position for the next time round. */
+    hs->hdr_pos += sendlen;
+    len -= sendlen;
+
+    /* Have we finished sending this string? */
+    if(hs->hdr_pos == hdrlen) {
+      /* Yes - move on to the next one */
+      hs->hdr_index++;
+      hs->hdr_pos = 0;
+    }
+  }
+  /* If we get here and there are still header bytes to send, we send
+   * the header information we just wrote immediately. If there are no
+   * more headers to send, but we do have file data to send, drop through
+   * to try to send some file data too. */
+  if((hs->hdr_index < NUM_FILE_HDR_STRINGS) || !hs->file) {
+    LWIP_DEBUGF(HTTPD_DEBUG, ("tcp_output\n"));
+    return HTTP_DATA_TO_SEND_BREAK;
+  }
+  return data_to_send;
+}
+#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
+
+/** Sub-function of http_send(): end-of-file (or block) is reached,
+ * either close the file or read the next block (if supported).
+ *
+ * @returns: 0 if the file is finished or no data has been read
+ *           1 if the file is not finished and data has been read
+ */
+static u8_t
+http_check_eof(struct tcp_pcb *pcb, struct http_state *hs)
+{
+#if LWIP_HTTPD_DYNAMIC_FILE_READ
+  int count;
+#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */
+
+  /* Do we have a valid file handle? */
+  if (hs->handle == NULL) {
+    /* No - close the connection. */
+    http_eof(pcb, hs);
+    return 0;
+  }
+  if (fs_bytes_left(hs->handle) <= 0) {
+    /* We reached the end of the file so this request is done. */
+    LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n"));
+    http_eof(pcb, hs);
+    return 0;
+  }
+#if LWIP_HTTPD_DYNAMIC_FILE_READ
+  /* Do we already have a send buffer allocated? */
+  if(hs->buf) {
+    /* Yes - get the length of the buffer */
+    count = hs->buf_len;
+  } else {
+    /* We don't have a send buffer so allocate one up to 2mss bytes long. */
+    count = 2 * tcp_mss(pcb);
+    do {
+      hs->buf = (char*)mem_malloc((mem_size_t)count);
+      if (hs->buf != NULL) {
+        hs->buf_len = count;
+        break;
+      }
+      count = count / 2;
+    } while (count > 100);
+
+    /* Did we get a send buffer? If not, return immediately. */
+    if (hs->buf == NULL) {
+      LWIP_DEBUGF(HTTPD_DEBUG, ("No buff\n"));
+      return 0;
+    }
+  }
+
+  /* Read a block of data from the file. */
+  LWIP_DEBUGF(HTTPD_DEBUG, ("Trying to read %d bytes.\n", count));
+
+#if LWIP_HTTPD_FS_ASYNC_READ
+  count = fs_read_async(hs->handle, hs->buf, count, http_continue, hs);
+#else /* LWIP_HTTPD_FS_ASYNC_READ */
+  count = fs_read(hs->handle, hs->buf, count);
+#endif /* LWIP_HTTPD_FS_ASYNC_READ */
+  if (count < 0) {
+    if (count == FS_READ_DELAYED) {
+      /* Delayed read, wait for FS to unblock us */
+      return 0;
+    }
+    /* We reached the end of the file so this request is done.
+     * @todo: don't close here for HTTP/1.1? */
+    LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n"));
+    http_eof(pcb, hs);
+    return 0;
+  }
+
+  /* Set up to send the block of data we just read */
+  LWIP_DEBUGF(HTTPD_DEBUG, ("Read %d bytes.\n", count));
+  hs->left = count;
+  hs->file = hs->buf;
+#if LWIP_HTTPD_SSI
+  if (hs->ssi) {
+    hs->ssi->parse_left = count;
+    hs->ssi->parsed = hs->buf;
+  }
+#endif /* LWIP_HTTPD_SSI */
+#else /* LWIP_HTTPD_DYNAMIC_FILE_READ */
+  LWIP_ASSERT("SSI and DYNAMIC_HEADERS turned off but eof not reached", 0);
+#endif /* LWIP_HTTPD_SSI || LWIP_HTTPD_DYNAMIC_HEADERS */
+  return 1;
+}
+
+/** Sub-function of http_send(): This is the normal send-routine for non-ssi files
+ *
+ * @returns: - 1: data has been written (so call tcp_ouput)
+ *           - 0: no data has been written (no need to call tcp_output)
+ */
+static u8_t
+http_send_data_nonssi(struct tcp_pcb *pcb, struct http_state *hs)
+{
+  err_t err;
+  u16_t len;
+  u16_t mss;
+  u8_t data_to_send = 0;
+
+  /* We are not processing an SHTML file so no tag checking is necessary.
+   * Just send the data as we received it from the file. */
+
+  /* We cannot send more data than space available in the send
+     buffer. */
+  if (tcp_sndbuf(pcb) < hs->left) {
+    len = tcp_sndbuf(pcb);
+  } else {
+    len = (u16_t)hs->left;
+    LWIP_ASSERT("hs->left did not fit into u16_t!", (len == hs->left));
+  }
+  mss = tcp_mss(pcb);
+  if (len > (2 * mss)) {
+    len = 2 * mss;
+  }
+
+  err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs));
+  if (err == ERR_OK) {
+    data_to_send = 1;
+    hs->file += len;
+    hs->left -= len;
+  }
+
+  return data_to_send;
+}
+
+#if LWIP_HTTPD_SSI
+/** Sub-function of http_send(): This is the send-routine for ssi files
+ *
+ * @returns: - 1: data has been written (so call tcp_ouput)
+ *           - 0: no data has been written (no need to call tcp_output)
+ */
+static u8_t
+http_send_data_ssi(struct tcp_pcb *pcb, struct http_state *hs)
+{
+  err_t err = ERR_OK;
+  u16_t len;
+  u16_t mss;
+  u8_t data_to_send = 0;
+
+  struct http_ssi_state *ssi = hs->ssi;
+  LWIP_ASSERT("ssi != NULL", ssi != NULL);
+  /* We are processing an SHTML file so need to scan for tags and replace
+   * them with insert strings. We need to be careful here since a tag may
+   * straddle the boundary of two blocks read from the file and we may also
+   * have to split the insert string between two tcp_write operations. */
+
+  /* Do we have remaining data to send before parsing more? */
+  if(ssi->parsed > hs->file) {
+    /* We cannot send more data than space available in the send
+       buffer. */
+    if (tcp_sndbuf(pcb) < (ssi->parsed - hs->file)) {
+      len = tcp_sndbuf(pcb);
+    } else {
+      LWIP_ASSERT("Data size does not fit into u16_t!",
+                  (ssi->parsed - hs->file) <= 0xffff);
+      len = (u16_t)(ssi->parsed - hs->file);
+    }
+    mss = tcp_mss(pcb);
+    if(len > (2 * mss)) {
+      len = 2 * mss;
+    }
+
+    err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs));
+    if (err == ERR_OK) {
+      data_to_send = 1;
+      hs->file += len;
+      hs->left -= len;
+    }
+
+    /* If the send buffer is full, return now. */
+    if(tcp_sndbuf(pcb) == 0) {
+      return data_to_send;
+    }
+  }
+
+  LWIP_DEBUGF(HTTPD_DEBUG, ("State %d, %d left\n", ssi->tag_state, (int)ssi->parse_left));
+
+  /* We have sent all the data that was already parsed so continue parsing
+   * the buffer contents looking for SSI tags. */
+  while((ssi->parse_left) && (err == ERR_OK)) {
+    /* How much data could we send? */
+    len = tcp_sndbuf(pcb);
+    if (len == 0) {
+      return data_to_send;
+    }
+    switch(ssi->tag_state) {
+      case TAG_NONE:
+        /* We are not currently processing an SSI tag so scan for the
+         * start of the lead-in marker. */
+        if(*ssi->parsed == g_pcTagLeadIn[0]) {
+          /* We found what could be the lead-in for a new tag so change
+           * state appropriately. */
+          ssi->tag_state = TAG_LEADIN;
+          ssi->tag_index = 1;
+#if !LWIP_HTTPD_SSI_INCLUDE_TAG
+          ssi->tag_started = ssi->parsed;
+#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG */
+        }
+
+        /* Move on to the next character in the buffer */
+        ssi->parse_left--;
+        ssi->parsed++;
+        break;
+
+      case TAG_LEADIN:
+        /* We are processing the lead-in marker, looking for the start of
+         * the tag name. */
+
+        /* Have we reached the end of the leadin? */
+        if(ssi->tag_index == LEN_TAG_LEAD_IN) {
+          ssi->tag_index = 0;
+          ssi->tag_state = TAG_FOUND;
+        } else {
+          /* Have we found the next character we expect for the tag leadin? */
+          if(*ssi->parsed == g_pcTagLeadIn[ssi->tag_index]) {
+            /* Yes - move to the next one unless we have found the complete
+             * leadin, in which case we start looking for the tag itself */
+            ssi->tag_index++;
+          } else {
+            /* We found an unexpected character so this is not a tag. Move
+             * back to idle state. */
+            ssi->tag_state = TAG_NONE;
+          }
+
+          /* Move on to the next character in the buffer */
+          ssi->parse_left--;
+          ssi->parsed++;
+        }
+        break;
+
+      case TAG_FOUND:
+        /* We are reading the tag name, looking for the start of the
+         * lead-out marker and removing any whitespace found. */
+
+        /* Remove leading whitespace between the tag leading and the first
+         * tag name character. */
+        if((ssi->tag_index == 0) && ((*ssi->parsed == ' ') ||
+           (*ssi->parsed == '\t') || (*ssi->parsed == '\n') ||
+           (*ssi->parsed == '\r'))) {
+          /* Move on to the next character in the buffer */
+          ssi->parse_left--;
+          ssi->parsed++;
+          break;
+        }
+
+        /* Have we found the end of the tag name? This is signalled by
+         * us finding the first leadout character or whitespace */
+        if((*ssi->parsed == g_pcTagLeadOut[0]) ||
+           (*ssi->parsed == ' ')  || (*ssi->parsed == '\t') ||
+           (*ssi->parsed == '\n') || (*ssi->parsed == '\r')) {
+
+          if(ssi->tag_index == 0) {
+            /* We read a zero length tag so ignore it. */
+            ssi->tag_state = TAG_NONE;
+          } else {
+            /* We read a non-empty tag so go ahead and look for the
+             * leadout string. */
+            ssi->tag_state = TAG_LEADOUT;
+            LWIP_ASSERT("ssi->tag_index <= 0xff", ssi->tag_index <= 0xff);
+            ssi->tag_name_len = (u8_t)ssi->tag_index;
+            ssi->tag_name[ssi->tag_index] = '\0';
+            if(*ssi->parsed == g_pcTagLeadOut[0]) {
+              ssi->tag_index = 1;
+            } else {
+              ssi->tag_index = 0;
+            }
+          }
+        } else {
+          /* This character is part of the tag name so save it */
+          if(ssi->tag_index < LWIP_HTTPD_MAX_TAG_NAME_LEN) {
+            ssi->tag_name[ssi->tag_index++] = *ssi->parsed;
+          } else {
+            /* The tag was too long so ignore it. */
+            ssi->tag_state = TAG_NONE;
+          }
+        }
+
+        /* Move on to the next character in the buffer */
+        ssi->parse_left--;
+        ssi->parsed++;
+
+        break;
+
+      /* We are looking for the end of the lead-out marker. */
+      case TAG_LEADOUT:
+        /* Remove leading whitespace between the tag leading and the first
+         * tag leadout character. */
+        if((ssi->tag_index == 0) && ((*ssi->parsed == ' ') ||
+           (*ssi->parsed == '\t') || (*ssi->parsed == '\n') ||
+           (*ssi->parsed == '\r'))) {
+          /* Move on to the next character in the buffer */
+          ssi->parse_left--;
+          ssi->parsed++;
+          break;
+        }
+
+        /* Have we found the next character we expect for the tag leadout? */
+        if(*ssi->parsed == g_pcTagLeadOut[ssi->tag_index]) {
+          /* Yes - move to the next one unless we have found the complete
+           * leadout, in which case we need to call the client to process
+           * the tag. */
+
+          /* Move on to the next character in the buffer */
+          ssi->parse_left--;
+          ssi->parsed++;
+
+          if(ssi->tag_index == (LEN_TAG_LEAD_OUT - 1)) {
+            /* Call the client to ask for the insert string for the
+             * tag we just found. */
+#if LWIP_HTTPD_SSI_MULTIPART
+            ssi->tag_part = 0; /* start with tag part 0 */
+#endif /* LWIP_HTTPD_SSI_MULTIPART */
+            get_tag_insert(hs);
+
+            /* Next time through, we are going to be sending data
+             * immediately, either the end of the block we start
+             * sending here or the insert string. */
+            ssi->tag_index = 0;
+            ssi->tag_state = TAG_SENDING;
+            ssi->tag_end = ssi->parsed;
+#if !LWIP_HTTPD_SSI_INCLUDE_TAG
+            ssi->parsed = ssi->tag_started;
+#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/
+
+            /* If there is any unsent data in the buffer prior to the
+             * tag, we need to send it now. */
+            if (ssi->tag_end > hs->file) {
+              /* How much of the data can we send? */
+#if LWIP_HTTPD_SSI_INCLUDE_TAG
+              if(len > ssi->tag_end - hs->file) {
+                len = (u16_t)(ssi->tag_end - hs->file);
+              }
+#else /* LWIP_HTTPD_SSI_INCLUDE_TAG*/
+              if(len > ssi->tag_started - hs->file) {
+                /* we would include the tag in sending */
+                len = (u16_t)(ssi->tag_started - hs->file);
+              }
+#endif /* LWIP_HTTPD_SSI_INCLUDE_TAG*/
+
+              err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs));
+              if (err == ERR_OK) {
+                data_to_send = 1;
+#if !LWIP_HTTPD_SSI_INCLUDE_TAG
+                if(ssi->tag_started <= hs->file) {
+                  /* pretend to have sent the tag, too */
+                  len += ssi->tag_end - ssi->tag_started;
+                }
+#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/
+                hs->file += len;
+                hs->left -= len;
+              }
+            }
+          } else {
+            ssi->tag_index++;
+          }
+        } else {
+          /* We found an unexpected character so this is not a tag. Move
+           * back to idle state. */
+          ssi->parse_left--;
+          ssi->parsed++;
+          ssi->tag_state = TAG_NONE;
+        }
+        break;
+
+      /*
+       * We have found a valid tag and are in the process of sending
+       * data as a result of that discovery. We send either remaining data
+       * from the file prior to the insert point or the insert string itself.
+       */
+      case TAG_SENDING:
+        /* Do we have any remaining file data to send from the buffer prior
+         * to the tag? */
+        if(ssi->tag_end > hs->file) {
+          /* How much of the data can we send? */
+#if LWIP_HTTPD_SSI_INCLUDE_TAG
+          if(len > ssi->tag_end - hs->file) {
+            len = (u16_t)(ssi->tag_end - hs->file);
+          }
+#else /* LWIP_HTTPD_SSI_INCLUDE_TAG*/
+          LWIP_ASSERT("hs->started >= hs->file", ssi->tag_started >= hs->file);
+          if (len > ssi->tag_started - hs->file) {
+            /* we would include the tag in sending */
+            len = (u16_t)(ssi->tag_started - hs->file);
+          }
+#endif /* LWIP_HTTPD_SSI_INCLUDE_TAG*/
+          if (len != 0) {
+            err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs));
+          } else {
+            err = ERR_OK;
+          }
+          if (err == ERR_OK) {
+            data_to_send = 1;
+#if !LWIP_HTTPD_SSI_INCLUDE_TAG
+            if(ssi->tag_started <= hs->file) {
+              /* pretend to have sent the tag, too */
+              len += ssi->tag_end - ssi->tag_started;
+            }
+#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/
+            hs->file += len;
+            hs->left -= len;
+          }
+        } else {
+#if LWIP_HTTPD_SSI_MULTIPART
+          if(ssi->tag_index >= ssi->tag_insert_len) {
+            /* Did the last SSIHandler have more to send? */
+            if (ssi->tag_part != HTTPD_LAST_TAG_PART) {
+              /* If so, call it again */
+              ssi->tag_index = 0;
+              get_tag_insert(hs);
+            }
+          }
+#endif /* LWIP_HTTPD_SSI_MULTIPART */
+
+          /* Do we still have insert data left to send? */
+          if(ssi->tag_index < ssi->tag_insert_len) {
+            /* We are sending the insert string itself. How much of the
+             * insert can we send? */
+            if(len > (ssi->tag_insert_len - ssi->tag_index)) {
+              len = (ssi->tag_insert_len - ssi->tag_index);
+            }
+
+            /* Note that we set the copy flag here since we only have a
+             * single tag insert buffer per connection. If we don't do
+             * this, insert corruption can occur if more than one insert
+             * is processed before we call tcp_output. */
+            err = http_write(pcb, &(ssi->tag_insert[ssi->tag_index]), &len,
+                             HTTP_IS_TAG_VOLATILE(hs));
+            if (err == ERR_OK) {
+              data_to_send = 1;
+              ssi->tag_index += len;
+              /* Don't return here: keep on sending data */
+            }
+          } else {
+#if LWIP_HTTPD_SSI_MULTIPART
+            if (ssi->tag_part == HTTPD_LAST_TAG_PART)
+#endif /* LWIP_HTTPD_SSI_MULTIPART */
+            {
+              /* We have sent all the insert data so go back to looking for
+               * a new tag. */
+              LWIP_DEBUGF(HTTPD_DEBUG, ("Everything sent.\n"));
+              ssi->tag_index = 0;
+              ssi->tag_state = TAG_NONE;
+#if !LWIP_HTTPD_SSI_INCLUDE_TAG
+              ssi->parsed = ssi->tag_end;
+#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/
+            }
+          }
+          break;
+      }
+    }
+  }
+
+  /* If we drop out of the end of the for loop, this implies we must have
+   * file data to send so send it now. In TAG_SENDING state, we've already
+   * handled this so skip the send if that's the case. */
+  if((ssi->tag_state != TAG_SENDING) && (ssi->parsed > hs->file)) {
+    /* We cannot send more data than space available in the send
+       buffer. */
+    if (tcp_sndbuf(pcb) < (ssi->parsed - hs->file)) {
+      len = tcp_sndbuf(pcb);
+    } else {
+      LWIP_ASSERT("Data size does not fit into u16_t!",
+                  (ssi->parsed - hs->file) <= 0xffff);
+      len = (u16_t)(ssi->parsed - hs->file);
+    }
+    if(len > (2 * tcp_mss(pcb))) {
+      len = 2 * tcp_mss(pcb);
+    }
+
+    err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs));
+    if (err == ERR_OK) {
+      data_to_send = 1;
+      hs->file += len;
+      hs->left -= len;
+    }
+  }
+  return data_to_send;
+}
+#endif /* LWIP_HTTPD_SSI */
+
+/**
+ * Try to send more data on this pcb.
+ *
+ * @param pcb the pcb to send data
+ * @param hs connection state
+ */
+static u8_t
+http_send(struct tcp_pcb *pcb, struct http_state *hs)
+{
+  u8_t data_to_send = HTTP_NO_DATA_TO_SEND;
+
+  LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_send: pcb=%p hs=%p left=%d\n", (void*)pcb,
+    (void*)hs, hs != NULL ? (int)hs->left : 0));
+
+#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
+  if (hs->unrecved_bytes != 0) {
+    return 0;
+  }
+#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */
+
+  /* If we were passed a NULL state structure pointer, ignore the call. */
+  if (hs == NULL) {
+    return 0;
+  }
+
+#if LWIP_HTTPD_FS_ASYNC_READ
+  /* Check if we are allowed to read from this file.
+     (e.g. SSI might want to delay sending until data is available) */
+  if (!fs_is_file_ready(hs->handle, http_continue, hs)) {
+    return 0;
+  }
+#endif /* LWIP_HTTPD_FS_ASYNC_READ */
+
+#if LWIP_HTTPD_DYNAMIC_HEADERS
+  /* Do we have any more header data to send for this file? */
+  if(hs->hdr_index < NUM_FILE_HDR_STRINGS) {
+    data_to_send = http_send_headers(pcb, hs);
+    if (data_to_send != HTTP_DATA_TO_SEND_CONTINUE) {
+      return data_to_send;
+    }
+  }
+#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
+
+  /* Have we run out of file data to send? If so, we need to read the next
+   * block from the file. */
+  if (hs->left == 0) {
+    if (!http_check_eof(pcb, hs)) {
+      return 0;
+    }
+  }
+
+#if LWIP_HTTPD_SSI
+  if(hs->ssi) {
+    data_to_send = http_send_data_ssi(pcb, hs);
+  } else
+#endif /* LWIP_HTTPD_SSI */
+  {
+    data_to_send = http_send_data_nonssi(pcb, hs);
+  }
+
+  if((hs->left == 0) && (fs_bytes_left(hs->handle) <= 0)) {
+    /* We reached the end of the file so this request is done.
+     * This adds the FIN flag right into the last data segment. */
+    LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n"));
+    http_eof(pcb, hs);
+    return 0;
+  }
+  LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("send_data end.\n"));
+  return data_to_send;
+}
+
+#if LWIP_HTTPD_SUPPORT_EXTSTATUS
+/** Initialize a http connection with a file to send for an error message
+ *
+ * @param hs http connection state
+ * @param error_nr HTTP error number
+ * @return ERR_OK if file was found and hs has been initialized correctly
+ *         another err_t otherwise
+ */
+static err_t
+http_find_error_file(struct http_state *hs, u16_t error_nr)
+{
+  const char *uri1, *uri2, *uri3;
+  err_t err;
+
+  if (error_nr == 501) {
+    uri1 = "/501.html";
+    uri2 = "/501.htm";
+    uri3 = "/501.shtml";
+  } else {
+    /* 400 (bad request is the default) */
+    uri1 = "/400.html";
+    uri2 = "/400.htm";
+    uri3 = "/400.shtml";
+  }
+  err = fs_open(&hs->file_handle, uri1);
+  if (err != ERR_OK) {
+    err = fs_open(&hs->file_handle, uri2);
+    if (err != ERR_OK) {
+      err = fs_open(&hs->file_handle, uri3);
+      if (err != ERR_OK) {
+        LWIP_DEBUGF(HTTPD_DEBUG, ("Error page for error %"U16_F" not found\n",
+          error_nr));
+        return ERR_ARG;
+      }
+    }
+  }
+  return http_init_file(hs, &hs->file_handle, 0, NULL, 0);
+}
+#else /* LWIP_HTTPD_SUPPORT_EXTSTATUS */
+#define http_find_error_file(hs, error_nr) ERR_ARG
+#endif /* LWIP_HTTPD_SUPPORT_EXTSTATUS */
+
+/**
+ * Get the file struct for a 404 error page.
+ * Tries some file names and returns NULL if none found.
+ *
+ * @param uri pointer that receives the actual file name URI
+ * @return file struct for the error page or NULL no matching file was found
+ */
+static struct fs_file *
+http_get_404_file(struct http_state *hs, const char **uri)
+{
+  err_t err;
+
+  *uri = "/404.html";
+  err = fs_open(&hs->file_handle, *uri);
+  if (err != ERR_OK) {
+    /* 404.html doesn't exist. Try 404.htm instead. */
+    *uri = "/404.htm";
+    err = fs_open(&hs->file_handle, *uri);
+    if (err != ERR_OK) {
+      /* 404.htm doesn't exist either. Try 404.shtml instead. */
+      *uri = "/404.shtml";
+      err = fs_open(&hs->file_handle, *uri);
+      if (err != ERR_OK) {
+        /* 404.htm doesn't exist either. Indicate to the caller that it should
+         * send back a default 404 page.
+         */
+        *uri = NULL;
+        return NULL;
+      }
+    }
+  }
+
+  return &hs->file_handle;
+}
+
+#if LWIP_HTTPD_SUPPORT_POST
+static err_t
+http_handle_post_finished(struct http_state *hs)
+{
+#if LWIP_HTTPD_POST_MANUAL_WND
+  /* Prevent multiple calls to httpd_post_finished, since it might have already
+     been called before from httpd_post_data_recved(). */
+  if (hs->post_finished) {
+    return ERR_OK;
+  }
+  hs->post_finished = 1;
+#endif /* LWIP_HTTPD_POST_MANUAL_WND */
+  /* application error or POST finished */
+  /* NULL-terminate the buffer */
+  http_post_response_filename[0] = 0;
+  httpd_post_finished(hs, http_post_response_filename, LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN);
+  return http_find_file(hs, http_post_response_filename, 0);
+}
+
+/** Pass received POST body data to the application and correctly handle
+ * returning a response document or closing the connection.
+ * ATTENTION: The application is responsible for the pbuf now, so don't free it!
+ *
+ * @param hs http connection state
+ * @param p pbuf to pass to the application
+ * @return ERR_OK if passed successfully, another err_t if the response file
+ *         hasn't been found (after POST finished)
+ */
+static err_t
+http_post_rxpbuf(struct http_state *hs, struct pbuf *p)
+{
+  err_t err;
+
+  /* adjust remaining Content-Length */
+  if (hs->post_content_len_left < p->tot_len) {
+    hs->post_content_len_left = 0;
+  } else {
+    hs->post_content_len_left -= p->tot_len;
+  }
+  err = httpd_post_receive_data(hs, p);
+  if ((err != ERR_OK) || (hs->post_content_len_left == 0)) {
+#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
+    if (hs->unrecved_bytes != 0) {
+       return ERR_OK;
+    }
+#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */
+    /* application error or POST finished */
+    return http_handle_post_finished(hs);
+  }
+
+  return ERR_OK;
+}
+
+/** Handle a post request. Called from http_parse_request when method 'POST'
+ * is found.
+ *
+ * @param p The input pbuf (containing the POST header and body).
+ * @param hs The http connection state.
+ * @param data HTTP request (header and part of body) from input pbuf(s).
+ * @param data_len Size of 'data'.
+ * @param uri The HTTP URI parsed from input pbuf(s).
+ * @param uri_end Pointer to the end of 'uri' (here, the rest of the HTTP
+ *                header starts).
+ * @return ERR_OK: POST correctly parsed and accepted by the application.
+ *         ERR_INPROGRESS: POST not completely parsed (no error yet)
+ *         another err_t: Error parsing POST or denied by the application
+ */
+static err_t
+http_post_request(struct pbuf **inp, struct http_state *hs,
+                  char *data, u16_t data_len, char *uri, char *uri_end)
+{
+  err_t err;
+  /* search for end-of-header (first double-CRLF) */
+  char* crlfcrlf = strnstr(uri_end + 1, CRLF CRLF, data_len - (uri_end + 1 - data));
+
+  if (crlfcrlf != NULL) {
+    /* search for "Content-Length: " */
+#define HTTP_HDR_CONTENT_LEN                "Content-Length: "
+#define HTTP_HDR_CONTENT_LEN_LEN            16
+#define HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN  10
+    char *scontent_len = strnstr(uri_end + 1, HTTP_HDR_CONTENT_LEN, crlfcrlf - (uri_end + 1));
+    if (scontent_len != NULL) {
+      char *scontent_len_end = strnstr(scontent_len + HTTP_HDR_CONTENT_LEN_LEN, CRLF, HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN);
+      if (scontent_len_end != NULL) {
+        int content_len;
+        char *conten_len_num = scontent_len + HTTP_HDR_CONTENT_LEN_LEN;
+        *scontent_len_end = 0;
+        content_len = atoi(conten_len_num);
+        if (content_len > 0) {
+          /* adjust length of HTTP header passed to application */
+          const char *hdr_start_after_uri = uri_end + 1;
+          u16_t hdr_len = LWIP_MIN(data_len, crlfcrlf + 4 - data);
+          u16_t hdr_data_len = LWIP_MIN(data_len, crlfcrlf + 4 - hdr_start_after_uri);
+          u8_t post_auto_wnd = 1;
+          http_post_response_filename[0] = 0;
+          err = httpd_post_begin(hs, uri, hdr_start_after_uri, hdr_data_len, content_len,
+            http_post_response_filename, LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN, &post_auto_wnd);
+          if (err == ERR_OK) {
+            /* try to pass in data of the first pbuf(s) */
+            struct pbuf *q = *inp;
+            u16_t start_offset = hdr_len;
+#if LWIP_HTTPD_POST_MANUAL_WND
+            hs->no_auto_wnd = !post_auto_wnd;
+#endif /* LWIP_HTTPD_POST_MANUAL_WND */
+            /* set the Content-Length to be received for this POST */
+            hs->post_content_len_left = (u32_t)content_len;
+
+            /* get to the pbuf where the body starts */
+            while((q != NULL) && (q->len <= start_offset)) {
+              struct pbuf *head = q;
+              start_offset -= q->len;
+              q = q->next;
+              /* free the head pbuf */
+              head->next = NULL;
+              pbuf_free(head);
+            }
+            *inp = NULL;
+            if (q != NULL) {
+              /* hide the remaining HTTP header */
+              pbuf_header(q, -(s16_t)start_offset);
+#if LWIP_HTTPD_POST_MANUAL_WND
+              if (!post_auto_wnd) {
+                /* already tcp_recved() this data... */
+                hs->unrecved_bytes = q->tot_len;
+              }
+#endif /* LWIP_HTTPD_POST_MANUAL_WND */
+              return http_post_rxpbuf(hs, q);
+            } else {
+              return ERR_OK;
+            }
+          } else {
+            /* return file passed from application */
+            return http_find_file(hs, http_post_response_filename, 0);
+          }
+        } else {
+          LWIP_DEBUGF(HTTPD_DEBUG, ("POST received invalid Content-Length: %s\n",
+            conten_len_num));
+          return ERR_ARG;
+        }
+      }
+    }
+  }
+  /* if we come here, the POST is incomplete */
+#if LWIP_HTTPD_SUPPORT_REQUESTLIST
+  return ERR_INPROGRESS;
+#else /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
+  return ERR_ARG;
+#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
+}
+
+#if LWIP_HTTPD_POST_MANUAL_WND
+/** A POST implementation can call this function to update the TCP window.
+ * This can be used to throttle data reception (e.g. when received data is
+ * programmed to flash and data is received faster than programmed).
+ *
+ * @param connection A connection handle passed to httpd_post_begin for which
+ *        httpd_post_finished has *NOT* been called yet!
+ * @param recved_len Length of data received (for window update)
+ */
+void httpd_post_data_recved(void *connection, u16_t recved_len)
+{
+  struct http_state *hs = (struct http_state*)connection;
+  if (hs != NULL) {
+    if (hs->no_auto_wnd) {
+      u16_t len = recved_len;
+      if (hs->unrecved_bytes >= recved_len) {
+        hs->unrecved_bytes -= recved_len;
+      } else {
+        LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_LEVEL_WARNING, ("httpd_post_data_recved: recved_len too big\n"));
+        len = (u16_t)hs->unrecved_bytes;
+        hs->unrecved_bytes = 0;
+      }
+      if (hs->pcb != NULL) {
+        if (len != 0) {
+          tcp_recved(hs->pcb, len);
+        }
+        if ((hs->post_content_len_left == 0) && (hs->unrecved_bytes == 0)) {
+          /* finished handling POST */
+          http_handle_post_finished(hs);
+          http_send(hs->pcb, hs);
+        }
+      }
+    }
+  }
+}
+#endif /* LWIP_HTTPD_POST_MANUAL_WND */
+
+#endif /* LWIP_HTTPD_SUPPORT_POST */
+
+#if LWIP_HTTPD_FS_ASYNC_READ
+/** Try to send more data if file has been blocked before
+ * This is a callback function passed to fs_read_async().
+ */
+static void
+http_continue(void *connection)
+{
+  struct http_state *hs = (struct http_state*)connection;
+  if (hs && (hs->pcb) && (hs->handle)) {
+    LWIP_ASSERT("hs->pcb != NULL", hs->pcb != NULL);
+    LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("httpd_continue: try to send more data\n"));
+    if (http_send(hs->pcb, hs)) {
+      /* If we wrote anything to be sent, go ahead and send it now. */
+      LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("tcp_output\n"));
+      tcp_output(hs->pcb);
+    }
+  }
+}
+#endif /* LWIP_HTTPD_FS_ASYNC_READ */
+
+/**
+ * When data has been received in the correct state, try to parse it
+ * as a HTTP request.
+ *
+ * @param p the received pbuf
+ * @param hs the connection state
+ * @param pcb the tcp_pcb which received this packet
+ * @return ERR_OK if request was OK and hs has been initialized correctly
+ *         ERR_INPROGRESS if request was OK so far but not fully received
+ *         another err_t otherwise
+ */
+static err_t
+http_parse_request(struct pbuf **inp, struct http_state *hs, struct tcp_pcb *pcb)
+{
+  char *data;
+  char *crlf;
+  u16_t data_len;
+  struct pbuf *p = *inp;
+#if LWIP_HTTPD_SUPPORT_REQUESTLIST
+  u16_t clen;
+#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
+#if LWIP_HTTPD_SUPPORT_POST
+  err_t err;
+#endif /* LWIP_HTTPD_SUPPORT_POST */
+
+  LWIP_UNUSED_ARG(pcb); /* only used for post */
+  LWIP_ASSERT("p != NULL", p != NULL);
+  LWIP_ASSERT("hs != NULL", hs != NULL);
+
+  if ((hs->handle != NULL) || (hs->file != NULL)) {
+    LWIP_DEBUGF(HTTPD_DEBUG, ("Received data while sending a file\n"));
+    /* already sending a file */
+    /* @todo: abort? */
+    return ERR_USE;
+  }
+
+#if LWIP_HTTPD_SUPPORT_REQUESTLIST
+
+  LWIP_DEBUGF(HTTPD_DEBUG, ("Received %"U16_F" bytes\n", p->tot_len));
+
+  /* first check allowed characters in this pbuf? */
+
+  /* enqueue the pbuf */
+  if (hs->req == NULL) {
+    LWIP_DEBUGF(HTTPD_DEBUG, ("First pbuf\n"));
+    hs->req = p;
+  } else {
+    LWIP_DEBUGF(HTTPD_DEBUG, ("pbuf enqueued\n"));
+    pbuf_cat(hs->req, p);
+  }
+
+  if (hs->req->next != NULL) {
+    data_len = LWIP_MIN(hs->req->tot_len, LWIP_HTTPD_MAX_REQ_LENGTH);
+    pbuf_copy_partial(hs->req, httpd_req_buf, data_len, 0);
+    data = httpd_req_buf;
+  } else
+#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
+  {
+    data = (char *)p->payload;
+    data_len = p->len;
+    if (p->len != p->tot_len) {
+      LWIP_DEBUGF(HTTPD_DEBUG, ("Warning: incomplete header due to chained pbufs\n"));
+    }
+  }
+
+  /* received enough data for minimal request? */
+  if (data_len >= MIN_REQ_LEN) {
+    /* wait for CRLF before parsing anything */
+    crlf = strnstr(data, CRLF, data_len);
+    if (crlf != NULL) {
+#if LWIP_HTTPD_SUPPORT_POST
+      int is_post = 0;
+#endif /* LWIP_HTTPD_SUPPORT_POST */
+      int is_09 = 0;
+      char *sp1, *sp2;
+      u16_t left_len, uri_len;
+      LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("CRLF received, parsing request\n"));
+      /* parse method */
+      if (!strncmp(data, "GET ", 4)) {
+        sp1 = data + 3;
+        /* received GET request */
+        LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Received GET request\"\n"));
+#if LWIP_HTTPD_SUPPORT_POST
+      } else if (!strncmp(data, "POST ", 5)) {
+        /* store request type */
+        is_post = 1;
+        sp1 = data + 4;
+        /* received GET request */
+        LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Received POST request\n"));
+#endif /* LWIP_HTTPD_SUPPORT_POST */
+      } else {
+        /* null-terminate the METHOD (pbuf is freed anyway wen returning) */
+        data[4] = 0;
+        /* unsupported method! */
+        LWIP_DEBUGF(HTTPD_DEBUG, ("Unsupported request method (not implemented): \"%s\"\n",
+          data));
+        return http_find_error_file(hs, 501);
+      }
+      /* if we come here, method is OK, parse URI */
+      left_len = data_len - ((sp1 +1) - data);
+      sp2 = strnstr(sp1 + 1, " ", left_len);
+#if LWIP_HTTPD_SUPPORT_V09
+      if (sp2 == NULL) {
+        /* HTTP 0.9: respond with correct protocol version */
+        sp2 = strnstr(sp1 + 1, CRLF, left_len);
+        is_09 = 1;
+#if LWIP_HTTPD_SUPPORT_POST
+        if (is_post) {
+          /* HTTP/0.9 does not support POST */
+          goto badrequest;
+        }
+#endif /* LWIP_HTTPD_SUPPORT_POST */
+      }
+#endif /* LWIP_HTTPD_SUPPORT_V09 */
+      uri_len = sp2 - (sp1 + 1);
+      if ((sp2 != 0) && (sp2 > sp1)) {
+        /* wait for CRLFCRLF (indicating end of HTTP headers) before parsing anything */
+        if (strnstr(data, CRLF CRLF, data_len) != NULL) {
+          char *uri = sp1 + 1;
+#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE
+          if (!is_09 && strnstr(data, HTTP11_CONNECTIONKEEPALIVE, data_len)) {
+            hs->keepalive = 1;
+          }
+#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */
+          /* null-terminate the METHOD (pbuf is freed anyway wen returning) */
+          *sp1 = 0;
+          uri[uri_len] = 0;
+          LWIP_DEBUGF(HTTPD_DEBUG, ("Received \"%s\" request for URI: \"%s\"\n",
+                      data, uri));
+#if LWIP_HTTPD_SUPPORT_POST
+          if (is_post) {
+#if LWIP_HTTPD_SUPPORT_REQUESTLIST
+            struct pbuf **q = &hs->req;
+#else /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
+            struct pbuf **q = inp;
+#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
+            err = http_post_request(q, hs, data, data_len, uri, sp2);
+            if (err != ERR_OK) {
+              /* restore header for next try */
+              *sp1 = ' ';
+              *sp2 = ' ';
+              uri[uri_len] = ' ';
+            }
+            if (err == ERR_ARG) {
+              goto badrequest;
+            }
+            return err;
+          } else
+#endif /* LWIP_HTTPD_SUPPORT_POST */
+          {
+            return http_find_file(hs, uri, is_09);
+          }
+        }
+      } else {
+        LWIP_DEBUGF(HTTPD_DEBUG, ("invalid URI\n"));
+      }
+    }
+  }
+
+#if LWIP_HTTPD_SUPPORT_REQUESTLIST
+  clen = pbuf_clen(hs->req);
+  if ((hs->req->tot_len <= LWIP_HTTPD_REQ_BUFSIZE) &&
+    (clen <= LWIP_HTTPD_REQ_QUEUELEN)) {
+    /* request not fully received (too short or CRLF is missing) */
+    return ERR_INPROGRESS;
+  } else
+#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
+  {
+#if LWIP_HTTPD_SUPPORT_POST
+badrequest:
+#endif /* LWIP_HTTPD_SUPPORT_POST */
+    LWIP_DEBUGF(HTTPD_DEBUG, ("bad request\n"));
+    /* could not parse request */
+    return http_find_error_file(hs, 400);
+  }
+}
+
+/** Try to find the file specified by uri and, if found, initialize hs
+ * accordingly.
+ *
+ * @param hs the connection state
+ * @param uri the HTTP header URI
+ * @param is_09 1 if the request is HTTP/0.9 (no HTTP headers in response)
+ * @return ERR_OK if file was found and hs has been initialized correctly
+ *         another err_t otherwise
+ */
+static err_t
+http_find_file(struct http_state *hs, const char *uri, int is_09)
+{
+  size_t loop;
+  struct fs_file *file = NULL;
+  char *params;
+  err_t err;
+#if LWIP_HTTPD_CGI
+  int i;
+  int count;
+#endif /* LWIP_HTTPD_CGI */
+#if !LWIP_HTTPD_SSI
+  const
+#endif /* !LWIP_HTTPD_SSI */
+  /* By default, assume we will not be processing server-side-includes tags */
+  u8_t tag_check = 0;
+
+  /* Have we been asked for the default root file? */
+  if((uri[0] == '/') &&  (uri[1] == 0)) {
+    /* Try each of the configured default filenames until we find one
+       that exists. */
+    for (loop = 0; loop < NUM_DEFAULT_FILENAMES; loop++) {
+      LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Looking for %s...\n", g_psDefaultFilenames[loop].name));
+      err = fs_open(&hs->file_handle, (char *)g_psDefaultFilenames[loop].name);
+      uri = (char *)g_psDefaultFilenames[loop].name;
+      if(err == ERR_OK) {
+        file = &hs->file_handle;
+        LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Opened.\n"));
+#if LWIP_HTTPD_SSI
+        tag_check = g_psDefaultFilenames[loop].shtml;
+#endif /* LWIP_HTTPD_SSI */
+        break;
+      }
+    }
+    if (file == NULL) {
+      /* None of the default filenames exist so send back a 404 page */
+      file = http_get_404_file(hs, &uri);
+#if LWIP_HTTPD_SSI
+      tag_check = 0;
+#endif /* LWIP_HTTPD_SSI */
+    }
+  } else {
+    /* No - we've been asked for a specific file. */
+    /* First, isolate the base URI (without any parameters) */
+    params = (char *)strchr(uri, '?');
+    if (params != NULL) {
+      /* URI contains parameters. NULL-terminate the base URI */
+      *params = '\0';
+      params++;
+    }
+
+#if LWIP_HTTPD_CGI
+    /* Does the base URI we have isolated correspond to a CGI handler? */
+    if (g_iNumCGIs && g_pCGIs) {
+      for (i = 0; i < g_iNumCGIs; i++) {
+        if (strcmp(uri, g_pCGIs[i].pcCGIName) == 0) {
+          /*
+           * We found a CGI that handles this URI so extract the
+           * parameters and call the handler.
+           */
+           count = extract_uri_parameters(hs, params);
+           uri = g_pCGIs[i].pfnCGIHandler(i, count, hs->params,
+                                          hs->param_vals);
+           break;
+        }
+      }
+    }
+#endif /* LWIP_HTTPD_CGI */
+
+    LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Opening %s\n", uri));
+
+    err = fs_open(&hs->file_handle, uri);
+    if (err == ERR_OK) {
+       file = &hs->file_handle;
+    } else {
+      file = http_get_404_file(hs, &uri);
+    }
+#if LWIP_HTTPD_SSI
+    if (file != NULL) {
+      /* See if we have been asked for an shtml file and, if so,
+         enable tag checking. */
+      tag_check = 0;
+      for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) {
+        if (strstr(uri, g_pcSSIExtensions[loop])) {
+          tag_check = 1;
+          break;
+        }
+      }
+    }
+#endif /* LWIP_HTTPD_SSI */
+  }
+  return http_init_file(hs, file, is_09, uri, tag_check);
+}
+
+/** Initialize a http connection with a file to send (if found).
+ * Called by http_find_file and http_find_error_file.
+ *
+ * @param hs http connection state
+ * @param file file structure to send (or NULL if not found)
+ * @param is_09 1 if the request is HTTP/0.9 (no HTTP headers in response)
+ * @param uri the HTTP header URI
+ * @param tag_check enable SSI tag checking
+ * @return ERR_OK if file was found and hs has been initialized correctly
+ *         another err_t otherwise
+ */
+static err_t
+http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri, u8_t tag_check)
+{
+  if (file != NULL) {
+    /* file opened, initialise struct http_state */
+#if LWIP_HTTPD_SSI
+    if (tag_check) {
+      struct http_ssi_state *ssi = http_ssi_state_alloc();
+      if (ssi != NULL) {
+        ssi->tag_index = 0;
+        ssi->tag_state = TAG_NONE;
+        ssi->parsed = file->data;
+        ssi->parse_left = file->len;
+        ssi->tag_end = file->data;
+        hs->ssi = ssi;
+      }
+    }
+#else /* LWIP_HTTPD_SSI */
+    LWIP_UNUSED_ARG(tag_check);
+#endif /* LWIP_HTTPD_SSI */
+    hs->handle = file;
+    hs->file = (char*)file->data;
+    LWIP_ASSERT("File length must be positive!", (file->len >= 0));
+    hs->left = file->len;
+    hs->retries = 0;
+#if LWIP_HTTPD_TIMING
+    hs->time_started = sys_now();
+#endif /* LWIP_HTTPD_TIMING */
+#if !LWIP_HTTPD_DYNAMIC_HEADERS
+    LWIP_ASSERT("HTTP headers not included in file system", hs->handle->http_header_included);
+#endif /* !LWIP_HTTPD_DYNAMIC_HEADERS */
+#if LWIP_HTTPD_SUPPORT_V09
+    if (hs->handle->http_header_included && is_09) {
+      /* HTTP/0.9 responses are sent without HTTP header,
+         search for the end of the header. */
+      char *file_start = strnstr(hs->file, CRLF CRLF, hs->left);
+      if (file_start != NULL) {
+        size_t diff = file_start + 4 - hs->file;
+        hs->file += diff;
+        hs->left -= (u32_t)diff;
+      }
+    }
+#endif /* LWIP_HTTPD_SUPPORT_V09*/
+  } else {
+    hs->handle = NULL;
+    hs->file = NULL;
+    hs->left = 0;
+    hs->retries = 0;
+  }
+#if LWIP_HTTPD_DYNAMIC_HEADERS
+    /* Determine the HTTP headers to send based on the file extension of
+   * the requested URI. */
+  if ((hs->handle == NULL) || !hs->handle->http_header_included) {
+    get_http_headers(hs, (char*)uri);
+  }
+#else /* LWIP_HTTPD_DYNAMIC_HEADERS */
+  LWIP_UNUSED_ARG(uri);
+#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
+  return ERR_OK;
+}
+
+/**
+ * The pcb had an error and is already deallocated.
+ * The argument might still be valid (if != NULL).
+ */
+static void
+http_err(void *arg, err_t err)
+{
+  struct http_state *hs = (struct http_state *)arg;
+  LWIP_UNUSED_ARG(err);
+
+  LWIP_DEBUGF(HTTPD_DEBUG, ("http_err: %s", lwip_strerr(err)));
+
+  if (hs != NULL) {
+    http_state_free(hs);
+  }
+}
+
+/**
+ * Data has been sent and acknowledged by the remote host.
+ * This means that more data can be sent.
+ */
+static err_t
+http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
+{
+  struct http_state *hs = (struct http_state *)arg;
+
+  LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_sent %p\n", (void*)pcb));
+
+  LWIP_UNUSED_ARG(len);
+
+  if (hs == NULL) {
+    return ERR_OK;
+  }
+
+  hs->retries = 0;
+
+  http_send(pcb, hs);
+
+  return ERR_OK;
+}
+
+/**
+ * The poll function is called every 2nd second.
+ * If there has been no data sent (which resets the retries) in 8 seconds, close.
+ * If the last portion of a file has not been sent in 2 seconds, close.
+ *
+ * This could be increased, but we don't want to waste resources for bad connections.
+ */
+static err_t
+http_poll(void *arg, struct tcp_pcb *pcb)
+{
+  struct http_state *hs = (struct http_state *)arg;
+  LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_poll: pcb=%p hs=%p pcb_state=%s\n",
+    (void*)pcb, (void*)hs, tcp_debug_state_str(pcb->state)));
+
+  if (hs == NULL) {
+    err_t closed;
+    /* arg is null, close. */
+    LWIP_DEBUGF(HTTPD_DEBUG, ("http_poll: arg is NULL, close\n"));
+    closed = http_close_conn(pcb, NULL);
+    LWIP_UNUSED_ARG(closed);
+#if LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR
+    if (closed == ERR_MEM) {
+       tcp_abort(pcb);
+       return ERR_ABRT;
+    }
+#endif /* LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR */
+    return ERR_OK;
+  } else {
+    hs->retries++;
+    if (hs->retries == HTTPD_MAX_RETRIES) {
+      LWIP_DEBUGF(HTTPD_DEBUG, ("http_poll: too many retries, close\n"));
+      http_close_conn(pcb, hs);
+      return ERR_OK;
+    }
+
+    /* If this connection has a file open, try to send some more data. If
+     * it has not yet received a GET request, don't do this since it will
+     * cause the connection to close immediately. */
+    if(hs && (hs->handle)) {
+      LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_poll: try to send more data\n"));
+      if(http_send(pcb, hs)) {
+        /* If we wrote anything to be sent, go ahead and send it now. */
+        LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("tcp_output\n"));
+        tcp_output(pcb);
+      }
+    }
+  }
+
+  return ERR_OK;
+}
+
+/**
+ * Data has been received on this pcb.
+ * For HTTP 1.0, this should normally only happen once (if the request fits in one packet).
+ */
+static err_t
+http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
+{
+  err_t parsed = ERR_ABRT;
+  struct http_state *hs = (struct http_state *)arg;
+  LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_recv: pcb=%p pbuf=%p err=%s\n", (void*)pcb,
+    (void*)p, lwip_strerr(err)));
+
+  if ((err != ERR_OK) || (p == NULL) || (hs == NULL)) {
+    /* error or closed by other side? */
+    if (p != NULL) {
+      /* Inform TCP that we have taken the data. */
+      tcp_recved(pcb, p->tot_len);
+      pbuf_free(p);
+    }
+    if (hs == NULL) {
+      /* this should not happen, only to be robust */
+      LWIP_DEBUGF(HTTPD_DEBUG, ("Error, http_recv: hs is NULL, close\n"));
+    }
+    http_close_conn(pcb, hs);
+    return ERR_OK;
+  }
+
+#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND
+  if (hs->no_auto_wnd) {
+     hs->unrecved_bytes += p->tot_len;
+  } else
+#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */
+  {
+    /* Inform TCP that we have taken the data. */
+    tcp_recved(pcb, p->tot_len);
+  }
+
+#if LWIP_HTTPD_SUPPORT_POST
+  if (hs->post_content_len_left > 0) {
+    /* reset idle counter when POST data is received */
+    hs->retries = 0;
+    /* this is data for a POST, pass the complete pbuf to the application */
+    http_post_rxpbuf(hs, p);
+    /* pbuf is passed to the application, don't free it! */
+    if (hs->post_content_len_left == 0) {
+      /* all data received, send response or close connection */
+      http_send(pcb, hs);
+    }
+    return ERR_OK;
+  } else
+#endif /* LWIP_HTTPD_SUPPORT_POST */
+  {
+    if (hs->handle == NULL) {
+      parsed = http_parse_request(&p, hs, pcb);
+      LWIP_ASSERT("http_parse_request: unexpected return value", parsed == ERR_OK
+        || parsed == ERR_INPROGRESS ||parsed == ERR_ARG || parsed == ERR_USE);
+    } else {
+      LWIP_DEBUGF(HTTPD_DEBUG, ("http_recv: already sending data\n"));
+    }
+#if LWIP_HTTPD_SUPPORT_REQUESTLIST
+    if (parsed != ERR_INPROGRESS) {
+      /* request fully parsed or error */
+      if (hs->req != NULL) {
+        pbuf_free(hs->req);
+        hs->req = NULL;
+      }
+    }
+#else /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
+    if (p != NULL) {
+      /* pbuf not passed to application, free it now */
+      pbuf_free(p);
+    }
+#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */
+    if (parsed == ERR_OK) {
+#if LWIP_HTTPD_SUPPORT_POST
+      if (hs->post_content_len_left == 0)
+#endif /* LWIP_HTTPD_SUPPORT_POST */
+      {
+        LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_recv: data %p len %"S32_F"\n", hs->file, hs->left));
+        http_send(pcb, hs);
+      }
+    } else if (parsed == ERR_ARG) {
+      /* @todo: close on ERR_USE? */
+      http_close_conn(pcb, hs);
+    }
+  }
+  return ERR_OK;
+}
+
+/**
+ * A new incoming connection has been accepted.
+ */
+static err_t
+http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
+{
+  struct http_state *hs;
+  struct tcp_pcb_listen *lpcb = (struct tcp_pcb_listen*)arg;
+  LWIP_UNUSED_ARG(err);
+  LWIP_DEBUGF(HTTPD_DEBUG, ("http_accept %p / %p\n", (void*)pcb, arg));
+
+  /* Decrease the listen backlog counter */
+  tcp_accepted(lpcb);
+  /* Set priority */
+  tcp_setprio(pcb, HTTPD_TCP_PRIO);
+
+  /* Allocate memory for the structure that holds the state of the
+     connection - initialized by that function. */
+  hs = http_state_alloc();
+  if (hs == NULL) {
+    LWIP_DEBUGF(HTTPD_DEBUG, ("http_accept: Out of memory, RST\n"));
+    return ERR_MEM;
+  }
+  hs->pcb = pcb;
+
+  /* Tell TCP that this is the structure we wish to be passed for our
+     callbacks. */
+  tcp_arg(pcb, hs);
+
+  /* Set up the various callback functions */
+  tcp_recv(pcb, http_recv);
+  tcp_err(pcb, http_err);
+  tcp_poll(pcb, http_poll, HTTPD_POLL_INTERVAL);
+  tcp_sent(pcb, http_sent);
+
+  return ERR_OK;
+}
+
+/**
+ * Initialize the httpd with the specified local address.
+ */
+static void
+httpd_init_addr(ip_addr_t *local_addr)
+{
+  struct tcp_pcb *pcb;
+  err_t err;
+
+  pcb = tcp_new();
+  LWIP_ASSERT("httpd_init: tcp_new failed", pcb != NULL);
+  tcp_setprio(pcb, HTTPD_TCP_PRIO);
+  /* set SOF_REUSEADDR here to explicitly bind httpd to multiple interfaces */
+  err = tcp_bind(pcb, local_addr, HTTPD_SERVER_PORT);
+  LWIP_ASSERT("httpd_init: tcp_bind failed", err == ERR_OK);
+  pcb = tcp_listen(pcb);
+  LWIP_ASSERT("httpd_init: tcp_listen failed", pcb != NULL);
+  /* initialize callback arg and accept callback */
+  tcp_arg(pcb, pcb);
+  tcp_accept(pcb, http_accept);
+}
+
+/**
+ * Initialize the httpd: set up a listening PCB and bind it to the defined port
+ */
+void
+httpd_init(void)
+{
+#if HTTPD_USE_MEM_POOL
+  LWIP_ASSERT("memp_sizes[MEMP_HTTPD_STATE] >= sizeof(http_state)",
+     memp_sizes[MEMP_HTTPD_STATE] >= sizeof(http_state));
+  LWIP_ASSERT("memp_sizes[MEMP_HTTPD_SSI_STATE] >= sizeof(http_ssi_state)",
+     memp_sizes[MEMP_HTTPD_SSI_STATE] >= sizeof(http_ssi_state));
+#endif
+  LWIP_DEBUGF(HTTPD_DEBUG, ("httpd_init\n"));
+
+  httpd_init_addr(IP_ADDR_ANY);
+}
+
+#if LWIP_HTTPD_SSI
+/**
+ * Set the SSI handler function.
+ *
+ * @param ssi_handler the SSI handler function
+ * @param tags an array of SSI tag strings to search for in SSI-enabled files
+ * @param num_tags number of tags in the 'tags' array
+ */
+void
+http_set_ssi_handler(tSSIHandler ssi_handler, const char **tags, int num_tags)
+{
+  LWIP_DEBUGF(HTTPD_DEBUG, ("http_set_ssi_handler\n"));
+
+  LWIP_ASSERT("no ssi_handler given", ssi_handler != NULL);
+  LWIP_ASSERT("no tags given", tags != NULL);
+  LWIP_ASSERT("invalid number of tags", num_tags > 0);
+
+  g_pfnSSIHandler = ssi_handler;
+  g_ppcTags = tags;
+  g_iNumTags = num_tags;
+}
+#endif /* LWIP_HTTPD_SSI */
+
+#if LWIP_HTTPD_CGI
+/**
+ * Set an array of CGI filenames/handler functions
+ *
+ * @param cgis an array of CGI filenames/handler functions
+ * @param num_handlers number of elements in the 'cgis' array
+ */
+void
+http_set_cgi_handlers(const tCGI *cgis, int num_handlers)
+{
+  LWIP_ASSERT("no cgis given", cgis != NULL);
+  LWIP_ASSERT("invalid number of handlers", num_handlers > 0);
+
+  g_pCGIs = cgis;
+  g_iNumCGIs = num_handlers;
+}
+#endif /* LWIP_HTTPD_CGI */
+
+#endif /* LWIP_TCP */
diff --git a/extras/httpd/httpd.h b/extras/httpd/httpd.h
new file mode 100644
index 0000000..88cefce
--- /dev/null
+++ b/extras/httpd/httpd.h
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * This version of the file has been modified by Texas Instruments to offer
+ * simple server-side-include (SSI) and Common Gateway Interface (CGI)
+ * capability.
+ */
+
+#ifndef __HTTPD_H__
+#define __HTTPD_H__
+
+#include "lwip/opt.h"
+#include "lwip/err.h"
+#include "lwip/pbuf.h"
+
+
+/** Set this to 1 to support CGI */
+#ifndef LWIP_HTTPD_CGI
+#define LWIP_HTTPD_CGI            0
+#endif
+
+/** Set this to 1 to support SSI (Server-Side-Includes) */
+#ifndef LWIP_HTTPD_SSI
+#define LWIP_HTTPD_SSI            0
+#endif
+
+/** Set this to 1 to support HTTP POST */
+#ifndef LWIP_HTTPD_SUPPORT_POST
+#define LWIP_HTTPD_SUPPORT_POST   0
+#endif
+
+
+#if LWIP_HTTPD_CGI
+
+/*
+ * Function pointer for a CGI script handler.
+ *
+ * This function is called each time the HTTPD server is asked for a file
+ * whose name was previously registered as a CGI function using a call to
+ * http_set_cgi_handler. The iIndex parameter provides the index of the
+ * CGI within the ppcURLs array passed to http_set_cgi_handler. Parameters
+ * pcParam and pcValue provide access to the parameters provided along with
+ * the URI. iNumParams provides a count of the entries in the pcParam and
+ * pcValue arrays. Each entry in the pcParam array contains the name of a
+ * parameter with the corresponding entry in the pcValue array containing the
+ * value for that parameter. Note that pcParam may contain multiple elements
+ * with the same name if, for example, a multi-selection list control is used
+ * in the form generating the data.
+ *
+ * The function should return a pointer to a character string which is the
+ * path and filename of the response that is to be sent to the connected
+ * browser, for example "/thanks.htm" or "/response/error.ssi".
+ *
+ * The maximum number of parameters that will be passed to this function via
+ * iNumParams is defined by LWIP_HTTPD_MAX_CGI_PARAMETERS. Any parameters in the incoming
+ * HTTP request above this number will be discarded.
+ *
+ * Requests intended for use by this CGI mechanism must be sent using the GET
+ * method (which encodes all parameters within the URI rather than in a block
+ * later in the request). Attempts to use the POST method will result in the
+ * request being ignored.
+ *
+ */
+typedef const char *(*tCGIHandler)(int iIndex, int iNumParams, char *pcParam[],
+                             char *pcValue[]);
+
+/*
+ * Structure defining the base filename (URL) of a CGI and the associated
+ * function which is to be called when that URL is requested.
+ */
+typedef struct
+{
+    const char *pcCGIName;
+    tCGIHandler pfnCGIHandler;
+} tCGI;
+
+void http_set_cgi_handlers(const tCGI *pCGIs, int iNumHandlers);
+
+
+/* The maximum number of parameters that the CGI handler can be sent. */
+#ifndef LWIP_HTTPD_MAX_CGI_PARAMETERS
+#define LWIP_HTTPD_MAX_CGI_PARAMETERS 16
+#endif
+
+#endif /* LWIP_HTTPD_CGI */
+
+#if LWIP_HTTPD_SSI
+
+/** LWIP_HTTPD_SSI_MULTIPART==1: SSI handler function is called with 2 more
+ * arguments indicating a counter for insert string that are too long to be
+ * inserted at once: the SSI handler function must then set 'next_tag_part'
+ * which will be passed back to it in the next call. */
+#ifndef LWIP_HTTPD_SSI_MULTIPART
+#define LWIP_HTTPD_SSI_MULTIPART    0
+#endif
+
+/*
+ * Function pointer for the SSI tag handler callback.
+ *
+ * This function will be called each time the HTTPD server detects a tag of the
+ * form <!--#name--> in a .shtml, .ssi or .shtm file where "name" appears as
+ * one of the tags supplied to http_set_ssi_handler in the ppcTags array.  The
+ * returned insert string, which will be appended after the the string
+ * "<!--#name-->" in file sent back to the client,should be written to pointer
+ * pcInsert.  iInsertLen contains the size of the buffer pointed to by
+ * pcInsert.  The iIndex parameter provides the zero-based index of the tag as
+ * found in the ppcTags array and identifies the tag that is to be processed.
+ *
+ * The handler returns the number of characters written to pcInsert excluding
+ * any terminating NULL or a negative number to indicate a failure (tag not
+ * recognized, for example).
+ *
+ * Note that the behavior of this SSI mechanism is somewhat different from the
+ * "normal" SSI processing as found in, for example, the Apache web server.  In
+ * this case, the inserted text is appended following the SSI tag rather than
+ * replacing the tag entirely.  This allows for an implementation that does not
+ * require significant additional buffering of output data yet which will still
+ * offer usable SSI functionality.  One downside to this approach is when
+ * attempting to use SSI within JavaScript.  The SSI tag is structured to
+ * resemble an HTML comment but this syntax does not constitute a comment
+ * within JavaScript and, hence, leaving the tag in place will result in
+ * problems in these cases.  To work around this, any SSI tag which needs to
+ * output JavaScript code must do so in an encapsulated way, sending the whole
+ * HTML <script>...</script> section as a single include.
+ */
+typedef u16_t (*tSSIHandler)(int iIndex, char *pcInsert, int iInsertLen
+#if LWIP_HTTPD_SSI_MULTIPART
+                             , u16_t current_tag_part, u16_t *next_tag_part
+#endif /* LWIP_HTTPD_SSI_MULTIPART */
+#if LWIP_HTTPD_FILE_STATE
+                             , void *connection_state
+#endif /* LWIP_HTTPD_FILE_STATE */
+                             );
+
+void http_set_ssi_handler(tSSIHandler pfnSSIHandler,
+                          const char **ppcTags, int iNumTags);
+
+/* The maximum length of the string comprising the tag name */
+#ifndef LWIP_HTTPD_MAX_TAG_NAME_LEN
+#define LWIP_HTTPD_MAX_TAG_NAME_LEN 8
+#endif
+
+/* The maximum length of string that can be returned to replace any given tag */
+#ifndef LWIP_HTTPD_MAX_TAG_INSERT_LEN
+#define LWIP_HTTPD_MAX_TAG_INSERT_LEN 192
+#endif
+
+#endif /* LWIP_HTTPD_SSI */
+
+#if LWIP_HTTPD_SUPPORT_POST
+
+/* These functions must be implemented by the application */
+
+/** Called when a POST request has been received. The application can decide
+ * whether to accept it or not.
+ *
+ * @param connection Unique connection identifier, valid until httpd_post_end
+ *        is called.
+ * @param uri The HTTP header URI receiving the POST request.
+ * @param http_request The raw HTTP request (the first packet, normally).
+ * @param http_request_len Size of 'http_request'.
+ * @param content_len Content-Length from HTTP header.
+ * @param response_uri Filename of response file, to be filled when denying the
+ *        request
+ * @param response_uri_len Size of the 'response_uri' buffer.
+ * @param post_auto_wnd Set this to 0 to let the callback code handle window
+ *        updates by calling 'httpd_post_data_recved' (to throttle rx speed)
+ *        default is 1 (httpd handles window updates automatically)
+ * @return ERR_OK: Accept the POST request, data may be passed in
+ *         another err_t: Deny the POST request, send back 'bad request'.
+ */
+err_t httpd_post_begin(void *connection, const char *uri, const char *http_request,
+                       u16_t http_request_len, int content_len, char *response_uri,
+                       u16_t response_uri_len, u8_t *post_auto_wnd);
+
+/** Called for each pbuf of data that has been received for a POST.
+ * ATTENTION: The application is responsible for freeing the pbufs passed in!
+ *
+ * @param connection Unique connection identifier.
+ * @param p Received data.
+ * @return ERR_OK: Data accepted.
+ *         another err_t: Data denied, http_post_get_response_uri will be called.
+ */
+err_t httpd_post_receive_data(void *connection, struct pbuf *p);
+
+/** Called when all data is received or when the connection is closed.
+ * The application must return the filename/URI of a file to send in response
+ * to this POST request. If the response_uri buffer is untouched, a 404
+ * response is returned.
+ *
+ * @param connection Unique connection identifier.
+ * @param response_uri Filename of response file, to be filled when denying the request
+ * @param response_uri_len Size of the 'response_uri' buffer.
+ */
+void httpd_post_finished(void *connection, char *response_uri, u16_t response_uri_len);
+
+#ifndef LWIP_HTTPD_POST_MANUAL_WND
+#define LWIP_HTTPD_POST_MANUAL_WND  0
+#endif
+
+#if LWIP_HTTPD_POST_MANUAL_WND
+void httpd_post_data_recved(void *connection, u16_t recved_len);
+#endif /* LWIP_HTTPD_POST_MANUAL_WND */
+
+#endif /* LWIP_HTTPD_SUPPORT_POST */
+
+void httpd_init(void);
+
+#endif /* __HTTPD_H__ */
diff --git a/extras/httpd/httpd_structs.h b/extras/httpd/httpd_structs.h
new file mode 100644
index 0000000..51dc807
--- /dev/null
+++ b/extras/httpd/httpd_structs.h
@@ -0,0 +1,125 @@
+#ifndef __HTTPD_STRUCTS_H__
+#define __HTTPD_STRUCTS_H__
+
+#include "httpd.h"
+
+/** This string is passed in the HTTP header as "Server: " */
+#ifndef HTTPD_SERVER_AGENT
+#define HTTPD_SERVER_AGENT "lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip)"
+#endif
+
+/** Set this to 1 if you want to include code that creates HTTP headers
+ * at runtime. Default is off: HTTP headers are then created statically
+ * by the makefsdata tool. Static headers mean smaller code size, but
+ * the (readonly) fsdata will grow a bit as every file includes the HTTP
+ * header. */
+#ifndef LWIP_HTTPD_DYNAMIC_HEADERS
+#define LWIP_HTTPD_DYNAMIC_HEADERS 0
+#endif
+
+
+#if LWIP_HTTPD_DYNAMIC_HEADERS
+/** This struct is used for a list of HTTP header strings for various
+ * filename extensions. */
+typedef struct
+{
+  const char *extension;
+  int headerIndex;
+} tHTTPHeader;
+
+/** A list of strings used in HTTP headers */
+static const char * const g_psHTTPHeaderStrings[] =
+{
+ "Content-type: text/html\r\n\r\n",
+ "Content-type: text/html\r\nExpires: Fri, 10 Apr 2008 14:00:00 GMT\r\nPragma: no-cache\r\n\r\n",
+ "Content-type: image/gif\r\n\r\n",
+ "Content-type: image/png\r\n\r\n",
+ "Content-type: image/jpeg\r\n\r\n",
+ "Content-type: image/bmp\r\n\r\n",
+ "Content-type: image/x-icon\r\n\r\n",
+ "Content-type: application/octet-stream\r\n\r\n",
+ "Content-type: application/x-javascript\r\n\r\n",
+ "Content-type: application/x-javascript\r\n\r\n",
+ "Content-type: text/css\r\n\r\n",
+ "Content-type: application/x-shockwave-flash\r\n\r\n",
+ "Content-type: text/xml\r\n\r\n",
+ "Content-type: text/plain\r\n\r\n",
+ "HTTP/1.0 200 OK\r\n",
+ "HTTP/1.0 404 File not found\r\n",
+ "HTTP/1.0 400 Bad Request\r\n",
+ "HTTP/1.0 501 Not Implemented\r\n",
+ "HTTP/1.1 200 OK\r\n",
+ "HTTP/1.1 404 File not found\r\n",
+ "HTTP/1.1 400 Bad Request\r\n",
+ "HTTP/1.1 501 Not Implemented\r\n",
+ "Content-Length: ",
+ "Connection: Close\r\n",
+ "Connection: keep-alive\r\n",
+ "Server: "HTTPD_SERVER_AGENT"\r\n",
+ "\r\n<html><body><h2>404: The requested file cannot be found.</h2></body></html>\r\n"
+};
+
+/* Indexes into the g_psHTTPHeaderStrings array */
+#define HTTP_HDR_HTML           0  /* text/html */
+#define HTTP_HDR_SSI            1  /* text/html Expires... */
+#define HTTP_HDR_GIF            2  /* image/gif */
+#define HTTP_HDR_PNG            3  /* image/png */
+#define HTTP_HDR_JPG            4  /* image/jpeg */
+#define HTTP_HDR_BMP            5  /* image/bmp */
+#define HTTP_HDR_ICO            6  /* image/x-icon */
+#define HTTP_HDR_APP            7  /* application/octet-stream */
+#define HTTP_HDR_JS             8  /* application/x-javascript */
+#define HTTP_HDR_RA             9  /* application/x-javascript */
+#define HTTP_HDR_CSS            10 /* text/css */
+#define HTTP_HDR_SWF            11 /* application/x-shockwave-flash */
+#define HTTP_HDR_XML            12 /* text/xml */
+#define HTTP_HDR_DEFAULT_TYPE   13 /* text/plain */
+#define HTTP_HDR_OK             14 /* 200 OK */
+#define HTTP_HDR_NOT_FOUND      15 /* 404 File not found */
+#define HTTP_HDR_BAD_REQUEST    16 /* 400 Bad request */
+#define HTTP_HDR_NOT_IMPL       17 /* 501 Not Implemented */
+#define HTTP_HDR_OK_11          18 /* 200 OK */
+#define HTTP_HDR_NOT_FOUND_11   19 /* 404 File not found */
+#define HTTP_HDR_BAD_REQUEST_11 20 /* 400 Bad request */
+#define HTTP_HDR_NOT_IMPL_11    21 /* 501 Not Implemented */
+#define HTTP_HDR_CONTENT_LENGTH 22 /* Content-Length: (HTTP 1.1)*/
+#define HTTP_HDR_CONN_CLOSE     23 /* Connection: Close (HTTP 1.1) */
+#define HTTP_HDR_CONN_KEEPALIVE 24 /* Connection: keep-alive (HTTP 1.1) */
+#define HTTP_HDR_SERVER         25 /* Server: HTTPD_SERVER_AGENT */
+#define DEFAULT_404_HTML        26 /* default 404 body */
+
+/** A list of extension-to-HTTP header strings */
+const static tHTTPHeader g_psHTTPHeaders[] =
+{
+ { "html", HTTP_HDR_HTML},
+ { "htm",  HTTP_HDR_HTML},
+ { "shtml",HTTP_HDR_SSI},
+ { "shtm", HTTP_HDR_SSI},
+ { "ssi",  HTTP_HDR_SSI},
+ { "gif",  HTTP_HDR_GIF},
+ { "png",  HTTP_HDR_PNG},
+ { "jpg",  HTTP_HDR_JPG},
+ { "bmp",  HTTP_HDR_BMP},
+ { "ico",  HTTP_HDR_ICO},
+ { "class",HTTP_HDR_APP},
+ { "cls",  HTTP_HDR_APP},
+ { "js",   HTTP_HDR_JS},
+ { "ram",  HTTP_HDR_RA},
+ { "css",  HTTP_HDR_CSS},
+ { "swf",  HTTP_HDR_SWF},
+ { "xml",  HTTP_HDR_XML},
+ { "xsl",  HTTP_HDR_XML}
+};
+
+#define NUM_HTTP_HEADERS (sizeof(g_psHTTPHeaders) / sizeof(tHTTPHeader))
+
+#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */
+
+#if LWIP_HTTPD_SSI
+static const char * const g_pcSSIExtensions[] = {
+  ".shtml", ".shtm", ".ssi", ".xml"
+};
+#define NUM_SHTML_EXTENSIONS (sizeof(g_pcSSIExtensions) / sizeof(const char *))
+#endif /* LWIP_HTTPD_SSI */
+
+#endif /* __HTTPD_STRUCTS_H__ */
diff --git a/extras/httpd/readme.txt b/extras/httpd/readme.txt
new file mode 100644
index 0000000..8cf4ed7
--- /dev/null
+++ b/extras/httpd/readme.txt
@@ -0,0 +1,2 @@
+Note: this module expects your project to provide "fsdata.c" created with "makefsdata" utility.
+See examples/http_server.