/* SDWebServer Partageoir - Example WebServer with SD Card backend for esp8266 From Copyright (c) 2015 Hristo Gochkov. All rights reserved. This file is part of the ESP8266WebServer library for Arduino environment. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Have a FAT Formatted SD Card connected to the SPI port of the ESP8266 The web root is the SD Card root folder SdFat accept long name index.htm is the default index (works on subfolders as well) upload the contents of SdRoot to the root of the SDcard and access the editor by going to http://esp8266sd.local/edit Addon gepeto@SNHack.org , + take parameters from partageoir.cfg on the SD + make a independant AP (softAP) + change default ssid/hostname depend on other local wifi if present */ #include #include //#include #include #include #include "./DNSServer.h" // Patched lib #include #include #include //#include #define DBG_OUTPUT_PORT Serial const byte BUFFER_SIZE = 60; const byte DNS_PORT = 53; // Capture DNS requests on port 53 IPAddress apIP(10, 10, 10, 1); // Private network for server DNSServer dnsServer; // Create the DNS object ESP8266WebServer server(80); // HTTP server // si pas de param.txt // char nomssid[20] = "partage"; // default ssid partage deviendra partage.local char passssid[] = ""; // ssid pass char nomhost[20] = "partage"; // HOST.local partage int IPC = 4; int IPD = 1; char modifpass[] = "admin"; // password to edit int SDGPIO = 16; // ESP8266-12 SdFat sd; SdFile file; SdFile dirFile; static bool hasSD = false; File uploadFile; String responseHTML = "" "CaptivePortal" "

Hello World!

This is a captive portal example. All requests will " "be redirected here.

"; void returnOK() { server.sendHeader("Connection", "close"); server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(200, "text/plain", ""); } void returnFail(String msg) { server.sendHeader("Connection", "close"); server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(500, "text/plain", msg + "\r\n"); } bool loadFromSdCard(String path) { String dataType = "text/plain"; if (path.endsWith("/")) path += "index.htm"; if (path.endsWith(".src")) path = path.substring(0, path.lastIndexOf(".")); else if (path.endsWith(".htm")) dataType = "text/html"; else if (path.endsWith(".css")) dataType = "text/css"; else if (path.endsWith(".js")) dataType = "application/javascript"; else if (path.endsWith(".png")) dataType = "image/png"; else if (path.endsWith(".gif")) dataType = "image/gif"; else if (path.endsWith(".jpg")) dataType = "image/jpeg"; else if (path.endsWith(".ico")) dataType = "image/x-icon"; else if (path.endsWith(".xml")) dataType = "text/xml"; else if (path.endsWith(".pdf")) dataType = "application/pdf"; else if (path.endsWith(".zip")) dataType = "application/zip"; File dataFile = sd.open(path.c_str()); if (dataFile.isDirectory()) { path += "/index.htm"; dataType = "text/html"; dataFile = sd.open(path.c_str()); } if (!dataFile) return false; if (server.hasArg("download")) dataType = "application/octet-stream"; if (server.streamFile(dataFile, dataType) != dataFile.size()) { DBG_OUTPUT_PORT.println("Sent less data than expected!"); } dataFile.close(); return true; } void handleFileUpload() { if (server.uri() != "/edit") return; HTTPUpload& upload = server.upload(); if (upload.status == UPLOAD_FILE_START) { if (sd.exists((char *)upload.filename.c_str())) sd.remove((char *)upload.filename.c_str()); uploadFile = sd.open(upload.filename.c_str(), FILE_WRITE); DBG_OUTPUT_PORT.print("Upload: START, filename: "); DBG_OUTPUT_PORT.println(upload.filename); } else if (upload.status == UPLOAD_FILE_WRITE) { if (uploadFile) uploadFile.write(upload.buf, upload.currentSize); DBG_OUTPUT_PORT.print("Upload: WRITE, Bytes: "); DBG_OUTPUT_PORT.println(upload.currentSize); } else if (upload.status == UPLOAD_FILE_END) { if (uploadFile) uploadFile.close(); DBG_OUTPUT_PORT.print("Upload: END, Size: "); DBG_OUTPUT_PORT.println(upload.totalSize); } } void deleteRecursive(String path) { File file = sd.open((char *)path.c_str()); if (!file.isDirectory()) { file.close(); sd.remove((char *)path.c_str()); return; } file.rewindDirectory(); while (true) { File entry = file.openNextFile(); if (!entry) break; String entryPath = path + "/" + entry.name(); if (entry.isDirectory()) { entry.close(); deleteRecursive(entryPath); } else { entry.close(); sd.remove((char *)entryPath.c_str()); } yield(); } sd.rmdir((char *)path.c_str()); file.close(); } void handleDelete() { if (server.args() == 0) return returnFail("BAD ARGS"); String path = server.arg(0); if (path == "/" || !sd.exists((char *)path.c_str())) { returnFail("BAD PATH"); return; } deleteRecursive(path); returnOK(); } void handleCreate() { if (server.args() == 0) return returnFail("BAD ARGS"); String path = server.arg(0); if (path == "/" || sd.exists((char *)path.c_str())) { returnFail("BAD PATH"); return; } if (path.indexOf('.') > 0) { File file = sd.open((char *)path.c_str(), FILE_WRITE); if (file) { file.write((const char *)0); file.close(); } } else { sd.mkdir((char *)path.c_str()); } returnOK(); } void printDirectory() { if (!server.hasArg("dir")) return returnFail("BAD ARGS"); String path = server.arg("dir"); if (path != "/" && !sd.exists((char *)path.c_str())) return returnFail("BAD PATH"); File dir = sd.open((char *)path.c_str()); path = String(); if (!dir.isDirectory()) { dir.close(); return returnFail("NOT DIR"); } dir.rewindDirectory(); server.setContentLength(CONTENT_LENGTH_UNKNOWN); server.send(200, "text/json", ""); WiFiClient client = server.client(); server.sendContent("["); for (int cnt = 0; true; ++cnt) { File entry = dir.openNextFile(); if (!entry) break; String output; if (cnt > 0) output = ','; output += "{\"type\":\""; output += (entry.isDirectory()) ? "dir" : "file"; output += "\",\"name\":\""; output += entry.name(); output += "\""; output += "}"; server.sendContent(output); entry.close(); } server.sendContent("]"); dir.close(); } void handleNotFound() { if (hasSD && loadFromSdCard(server.uri())) return; String message = "SDCARD Not Detected\n\n"; message += SDGPIO; message += "\nURI: "; 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 += " NAME:" + server.argName(i) + "\n VALUE:" + server.arg(i) + "\n"; } server.send(404, "text/plain", message); DBG_OUTPUT_PORT.print(message); } void setup(void) { DBG_OUTPUT_PORT.begin(115200); DBG_OUTPUT_PORT.setDebugOutput(true); DBG_OUTPUT_PORT.print("\n"); if (sd.begin(SDGPIO)) { DBG_OUTPUT_PORT.println("SD Card initialized."); hasSD = true; } delay(1000); int i , buffer_lenght, line_counter ; char buffer[80], *key, *value; WiFi.mode(WIFI_AP_STA); WiFi.disconnect(); delay(100); // recherche fichier partageoir.cfg pour y prendre des choses File config_file = sd.open("partageoir.cfg", FILE_READ); if (config_file) { while (config_file.available() > 0 ) { i = 0; while ((buffer[i++] = config_file.read()) != '\n') { /* Si la ligne dépasse la taille du buffer */ if (i == BUFFER_SIZE) { /* On finit de lire la ligne mais sans stocker les données */ while (config_file.read() != '\n'); break; // Et on arrête la lecture de cette ligne } } buffer_lenght = i; /* Gestion des lignes trop grande */ if (i == BUFFER_SIZE) { DBG_OUTPUT_PORT.println("Ligne trop longue à la ligne "); DBG_OUTPUT_PORT.println(line_counter, DEC); DBG_OUTPUT_PORT.println(i); } /* Finalise la chaine de caractéres ASCIIZ en supprimant le \n au passage */ buffer[--i] = '\0'; /* Incrémente le compteur de lignes */ ++line_counter; /* Ignore les lignes vides ou les lignes de commentaires */ if (buffer[0] == '\0' || buffer[0] == '#') continue; /* Cherche l'emplacement de la clef en ignorant les espaces et les tabulations en début de ligne */ i = 0; while (buffer[i] == ' ' || buffer[i] == '\t') { if (++i == buffer_lenght) break; // Ignore les lignes contenant uniquement des espaces et/ou des tabulations } if (i == buffer_lenght) continue; // Gère les lignes contenant uniquement des espaces et/ou des tabulations key = &buffer[i]; /* Cherche l'emplacement du séparateur = en ignorant les espaces et les tabulations âpres la clef */ while (buffer[i] != '=') { /* Ignore les espaces et les tabulations */ if (buffer[i] == ' ' || buffer[i] == '\t') buffer[i] = '\0'; if (++i == buffer_lenght) { DBG_OUTPUT_PORT.println("Ligne mal forme a la ligne "); DBG_OUTPUT_PORT.println(line_counter, DEC); break; // Ignore les lignes mal formé } } if (i == buffer_lenght) continue; // Gère les lignes mal formé /* Transforme le séparateur = en \0 et continue */ buffer[i++] = '\0'; /* Cherche l'emplacement de la valeur en ignorant les espaces et les tabulations âpres le séparateur */ while (buffer[i] == ' ' || buffer[i] == '\t') { if (++i == buffer_lenght) { DBG_OUTPUT_PORT.println("Ligne mal forme a la ligne "); DBG_OUTPUT_PORT.println(line_counter, DEC); break; // Ignore les lignes mal formé } } if (i == buffer_lenght) continue; // Gère les lignes mal formé value = &buffer[i]; DBG_OUTPUT_PORT.print(key); DBG_OUTPUT_PORT.print(" : "); DBG_OUTPUT_PORT.println(value); /* Transforme les données texte en valeur utilisable */ if (strcmp(key, "SSID") == 0) { sprintf(nomssid, "%s", value); DBG_OUTPUT_PORT.print("ssid "); DBG_OUTPUT_PORT.println(nomssid); } else if (strcmp(key, "HOSTNAME") == 0) { sprintf(nomhost, "%s", value); DBG_OUTPUT_PORT.print("nomhost "); DBG_OUTPUT_PORT.println(nomhost); } else if (strcmp(key, "PASSWORD") == 0) { sprintf(passssid, "%s", value); DBG_OUTPUT_PORT.print("password "); DBG_OUTPUT_PORT.println(passssid); } else if (strcmp(key, "IPC") == 0) { IPC = atoi(value); DBG_OUTPUT_PORT.println(IPC); } else if (strcmp(key, "IPD") == 0) { IPD = atoi(value); DBG_OUTPUT_PORT.println(IPD); } else if (strcmp(key, "MODIFPASS") == 0) { sprintf(modifpass, "%s", value); DBG_OUTPUT_PORT.print("modifpass "); DBG_OUTPUT_PORT.println(modifpass); } else { // Default DBG_OUTPUT_PORT.print("Clef inconnu "); DBG_OUTPUT_PORT.println(key); } key = ""; value = ""; } /* Ferme le fichier de configuration */ config_file.close(); } WiFi.mode(WIFI_AP); WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); //WiFi.softAP("DNSServer CaptivePortal example"); if (strlen(passssid) == 0) { WiFi.softAP(nomssid); // open !! DBG_OUTPUT_PORT.print("ouverture de "); DBG_OUTPUT_PORT.println(nomssid); } else { WiFi.softAP(nomssid, passssid); // open !! DBG_OUTPUT_PORT.print("ouverture et paswd de "); DBG_OUTPUT_PORT.print(nomssid); DBG_OUTPUT_PORT.print(" "); DBG_OUTPUT_PORT.println(passssid); } DBG_OUTPUT_PORT.print("Connected! IP address: "); DBG_OUTPUT_PORT.println(WiFi.softAPIP()); dnsServer.start(DNS_PORT, "*", apIP); server.on("/list", HTTP_GET, printDirectory); server.on("/edit", HTTP_DELETE, handleDelete); server.on("/edit", HTTP_PUT, handleCreate); server.on("/edit", HTTP_POST, []() { returnOK(); }); //server.onFileUpload(handleFileUpload); // server.onNotFound(handleNotFound); // replay to all requests with same HTML server.onNotFound([]() { server.send(200, "text/html", responseHTML); }); server.begin(); DBG_OUTPUT_PORT.println("HTTP server started"); } void loop(void) { dnsServer.processNextRequest(); server.handleClient(); }