 ESP8266WebServer *server;
 File fsUploadFile;
 
-void handleRoot() {
-	server->send(200, "text/plain", "hello from esp8266!");
-}
-
 void handleNotFound() {
-	String message = "File Not Found\n\n";
+	if (!handleFileRead(server->uri())) {
+		String message = "File Not Found\n\n";
+		message += "URI: ";
+		message += server->uri();
+		message += "\nMethod: ";
+		message += (server->method() == HTTP_GET)?"GET":"POST";
+		message += "\nArguments: ";
+		message += server->args();
+		message += "\n";
+		for (uint8_t i=0; i<server->args(); i++) {
+			message += " " + server->argName(i) + ": " + server->arg(i) + "\n";
+		}
+		server->send(404, "text/plain", message);
+	}
+}
+
+static String formatBytes(size_t bytes)
+{
+	if (bytes < 1024) {
+		return String(bytes)+"B";
+	} else if (bytes < (1024 * 1024)) {
+		return String(bytes/1024.0)+"KB";
+	} else if (bytes < (1024 * 1024 * 1024)) {
+		return String(bytes/1024.0/1024.0)+"MB";
+	} else {
+		return String(bytes/1024.0/1024.0/1024.0)+"GB";
+	}
+}
+
+String getContentType(String filename)
+{
+	if (server->hasArg("download")) return "application/octet-stream";
+	else if (filename.endsWith(".htm")) return "text/html";
+	else if (filename.endsWith(".html")) return "text/html";
+	else if (filename.endsWith(".css")) return "text/css";
+	else if (filename.endsWith(".js")) return "application/javascript";
+	else if (filename.endsWith(".png")) return "image/png";
+	else if (filename.endsWith(".gif")) return "image/gif";
+	else if (filename.endsWith(".jpg")) return "image/jpeg";
+	else if (filename.endsWith(".ico")) return "image/x-icon";
+	else if (filename.endsWith(".xml")) return "text/xml";
+	else if (filename.endsWith(".pdf")) return "application/x-pdf";
+	else if (filename.endsWith(".zip")) return "application/x-zip";
+	else if (filename.endsWith(".gz")) return "application/x-gzip";
+	return "text/plain";
+}
+
+bool handleFileRead(String path)
+{
+	LOG_SERIAL.println("handleFileRead: " + path);
+	if (path.endsWith("/"))
+		path += "index.htm";
+	String contentType = getContentType(path);
+	String pathWithGz = path + ".gz";
+	if (SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) {
+		if (SPIFFS.exists(pathWithGz))
+			path += ".gz";
+		File file = SPIFFS.open(path, "r");
+		size_t sent = server->streamFile(file, contentType);
+		file.close();
+		return true;
+	}
+	return false;
+}
+
+void handleFileUpload()
+{
+	if (server->uri() != "/edit")
+		return;
+	HTTPUpload& upload = server->upload();
+	if (upload.status == UPLOAD_FILE_START) {
+		String filename = upload.filename;
+		if (!filename.startsWith("/"))
+			filename = "/"+filename;
+		log_info(": ");
+		LOG_SERIAL.println(filename);
+		fsUploadFile = SPIFFS.open(filename, "w");
+		filename = String();
+	} else if (upload.status == UPLOAD_FILE_WRITE) {
+		//LOG_SERIAL.print("handleFileUpload Data: "); LOG_SERIAL.println(upload.currentSize);
+		if (fsUploadFile)
+			fsUploadFile.write(upload.buf, upload.currentSize);
+	} else if (upload.status == UPLOAD_FILE_END) {
+		if (fsUploadFile)
+			fsUploadFile.close();
+		log_info("done, size: ");
+		LOG_SERIAL.println(upload.totalSize);
+	}
+}
+
+void handleFileDelete()
+{
+	if (server->args() == 0) return server->send(500, "text/plain", "BAD ARGS");
+	String path = server->arg(0);
+	log_info(": ");
+	LOG_SERIAL.println(path);
+	if (path == "/")
+		return server->send(500, "text/plain", "BAD PATH");
+	if (!SPIFFS.exists(path))
+		return server->send(404, "text/plain", "FileNotFound");
+	SPIFFS.remove(path);
+	server->send(200, "text/plain", "");
+	path = String();
+}
+
+void handleFileCreate()
+{
+	if (server->args() == 0)
+		return server->send(500, "text/plain", "BAD ARGS");
+	String path = server->arg(0);
+	log_info(": ");
+	LOG_SERIAL.println(path);
+	if (path == "/")
+		return server->send(500, "text/plain", "BAD PATH");
+	if (SPIFFS.exists(path))
+		return server->send(500, "text/plain", "FILE EXISTS");
+	File file = SPIFFS.open(path, "w");
+	if (file)
+		file.close();
+	else
+		return server->send(500, "text/plain", "CREATE FAILED");
+	server->send(200, "text/plain", "");
+	path = String();
+}
+
+void handleFileList()
+{
+	if (!server->hasArg("dir"))
+		server->send(500, "text/plain", "BAD ARGS"); return;
+	String path = server->arg("dir");
+	log_info(": ");
+	LOG_SERIAL.println(path);
+	Dir dir = SPIFFS.openDir(path);
+	path = String();
+
+	String output = "[";
+	while (dir.next()) {
+		File entry = dir.openFile("r");
+		if (output != "[") output += ',';
+		bool isDir = false;
+		output += "{\"type\":\"";
+		output += (isDir)?"dir":"file";
+		output += "\",\"name\":\"";
+		output += String(entry.name()).substring(1);
+		output += "\"}";
+		entry.close();
+	}
+	output += "]";
+	server->send(200, "text/json", output);
+}
+
+void handleRoot()
+{
+	if (!handleFileRead("/index.html"))
+		server->send(404, "text/plain", "FileNotFound");
+}
+
+void handleSave()
+{
+	String message = "Jolly good config!\n\n";
 	message += "URI: ";
 	message += server->uri();
 	message += "\nMethod: ";

			*/
			server = new ESP8266WebServer(80);
			server->on("/list", HTTP_GET, handleFileList);
			server->on("/edit", HTTP_GET, [](){
					if(!handleFileRead("/edit.htm")) server->send(404, "text/plain", "FileNotFound");
					});
			server->on("/edit", HTTP_PUT, handleFileCreate);
			server->on("/edit", HTTP_DELETE, handleFileDelete);
			server->on("/edit", HTTP_POST, [](){ server->send(200, "text/plain", ""); }, handleFileUpload);

			server->onNotFound([](){
				if (!handleFileRead(server->uri())) {
					String message = "File Not Found\n\n";
					message += "URI: ";
					message += server->uri();
					message += "\nMethod: ";
					message += (server->method() == HTTP_GET)?"GET":"POST";
					message += "\nArguments: ";
					message += server->args();
					message += "\n";
					for (uint8_t i=0; i<server->args(); i++)
						message += " " + server->argName(i) + ": " + server->arg(i) + "\n";
					server->send(404, "text/plain", message);
				}
			});

			server->on("/all", HTTP_GET, [](){
					String json = "{";
					json += "\"heap\":"+String(ESP.getFreeHeap());
					json += ", \"analog\":"+String(analogRead(A0));
					json += ", \"gpio\":"+String((uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16)));
					json += "}";
					server->send(200, "text/json", json);
					json = String();
					});

			server->on("/", handleRoot);
			server->begin();

	message += "\nArguments: ";
	message += server->args();
	message += "\n";
	for (uint8_t i=0; i<server->args(); i++) {
		message += " " + server->argName(i) + ": " + server->arg(i) + "\n";
	}
	server->send(404, "text/plain", message);
}

/* server test end */
