Andrew Boyson / web

Dependents:   oldheating gps motorhome heating

Files at this revision

API Documentation at this revision

Comitter:
andrewboyson
Date:
Mon Apr 29 14:45:30 2019 +0000
Parent:
108:91bfb40e7487
Child:
110:8ab752842d25
Commit message:
Tidied names from http to web

Changed in this revision

clock/web-clock-ajax.c Show annotated file Show diff for this revision Revisions of this file
clock/web-clock-html.c Show annotated file Show diff for this revision Revisions of this file
clock/web-clock-script.c Show annotated file Show diff for this revision Revisions of this file
css/web-base-css.c Show annotated file Show diff for this revision Revisions of this file
css/web-nav-css.c Show annotated file Show diff for this revision Revisions of this file
fault/web-fault-html.c Show annotated file Show diff for this revision Revisions of this file
favicon/web-favicon.c Show annotated file Show diff for this revision Revisions of this file
firmware/web-firmware-html.c Show annotated file Show diff for this revision Revisions of this file
firmware/web-firmware-script.c Show annotated file Show diff for this revision Revisions of this file
log/web-log-html.c Show annotated file Show diff for this revision Revisions of this file
login/web-login-html.c Show annotated file Show diff for this revision Revisions of this file
login/web-login-session-name.c Show annotated file Show diff for this revision Revisions of this file
net-trace/web-trace-html.c Show annotated file Show diff for this revision Revisions of this file
net-trace/web-trace-script.c Show annotated file Show diff for this revision Revisions of this file
net/web-net-html.c Show annotated file Show diff for this revision Revisions of this file
net/web-net4-html.c Show annotated file Show diff for this revision Revisions of this file
net/web-net4-script.c Show annotated file Show diff for this revision Revisions of this file
net/web-net6-html.c Show annotated file Show diff for this revision Revisions of this file
net/web-net6-script.c Show annotated file Show diff for this revision Revisions of this file
page/page.c Show diff for this revision Revisions of this file
page/page.h Show diff for this revision Revisions of this file
page/web-nav-base.c Show annotated file Show diff for this revision Revisions of this file
page/web-nav-base.h Show annotated file Show diff for this revision Revisions of this file
page/web-page-base.h Show annotated file Show diff for this revision Revisions of this file
web-add.c Show annotated file Show diff for this revision Revisions of this file
web-add.h Show annotated file Show diff for this revision Revisions of this file
web-base.c Show diff for this revision Revisions of this file
web-base.h Show annotated file Show diff for this revision Revisions of this file
web-server-base.c Show annotated file Show diff for this revision Revisions of this file
web-server-base.h Show annotated file Show diff for this revision Revisions of this file
web.c Show annotated file Show diff for this revision Revisions of this file
web.h Show annotated file Show diff for this revision Revisions of this file
--- a/clock/web-clock-ajax.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/clock/web-clock-ajax.c	Mon Apr 29 14:45:30 2019 +0000
@@ -2,14 +2,13 @@
 #include   <stdio.h>
 
 #include "http.h"
-#include "web-base.h"
 #include "rtc.h"
 #include "clk.h"
 #include "clktime.h"
 #include "clkgov.h"
 #include "clkutc.h"
+#include "ntpclient.h"
 #include "scan.h"
-#include "ntpclient.h"
 
 void WebClockAjax()
 {
--- a/clock/web-clock-html.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/clock/web-clock-html.c	Mon Apr 29 14:45:30 2019 +0000
@@ -1,69 +1,68 @@
 #include <time.h>
 
 #include "http.h"
-#include "page.h"
-#include "page-derived.h"
-#include "web-base.h"
+#include "web-page-base.h"
+#include "web-add.h"
 
 void WebClockHtml()
 {
     HttpOk("text/html; charset=UTF-8", "no-cache", NULL, NULL);
-    PageAddHeader(PageSite, "Clock", "settings.css", "clock.js");
-    PageAddNav(CLOCK_PAGE);
-    PageAddH1(PageSite, "Clock");
+    WebAddHeader("Clock", "settings.css", "clock.js");
+    WebAddNav(CLOCK_PAGE);
+    WebAddH1("Clock");
     
-    PageAddH2("Status");
-    PageAddAjaxLed("RTC is set"           , "ajax-rtc-set"    );
-    PageAddAjaxLed("Clock is set"         , "ajax-clock-set"  );
-    PageAddAjaxLed("External source is ok", "ajax-source-ok"  );
-    PageAddAjaxLed("Time synchronised"    , "ajax-time-locked");
-    PageAddAjaxLed("Rate synchronised"    , "ajax-rate-locked");
+    WebAddH2("Status");
+    WebAddAjaxLed("RTC is set"           , "ajax-rtc-set"    );
+    WebAddAjaxLed("Clock is set"         , "ajax-clock-set"  );
+    WebAddAjaxLed("External source is ok", "ajax-source-ok"  );
+    WebAddAjaxLed("Time synchronised"    , "ajax-time-locked");
+    WebAddAjaxLed("Rate synchronised"    , "ajax-rate-locked");
     
-    PageAddH2("Server UTC time");
+    WebAddH2("Server UTC time");
     HttpAddText("<div id='ajax-date-utc'></div>\r\n");
 
-    PageAddH2("Server local time");
+    WebAddH2("Server local time");
     HttpAddText("<div id='ajax-date-pc'></div>\r\n");
     
-    PageAddH2("Server - PC (ms)");
+    WebAddH2("Server - PC (ms)");
     HttpAddText("<div id='ajax-date-diff'></div>\r\n");    
     
-    PageAddH2("UTC");
-    PageAddAjaxInputToggle("Enable epoch change"     ,    "ajax-leap-enable"  , "chg-clock-leap-enable" );
-    PageAddAjaxInputToggle("Direction of next epoch" ,    "ajax-leap-forward" , "chg-clock-leap-forward");
-    PageAddAjaxInput      ("Year next epoch starts"  , 4, "ajax-leap-year"    , "set-clock-leap-year"   );
-    PageAddAjaxInput      ("Month next epoch starts" , 4, "ajax-leap-month"   , "set-clock-leap-month"  );
-    PageAddAjaxInput      ("Current era offset"      , 4, "ajax-leap-count"   , "set-clock-leap-count"  );
+    WebAddH2("UTC");
+    WebAddAjaxInputToggle("Enable epoch change"     ,    "ajax-leap-enable"  , "chg-clock-leap-enable" );
+    WebAddAjaxInputToggle("Direction of next epoch" ,    "ajax-leap-forward" , "chg-clock-leap-forward");
+    WebAddAjaxInput      ("Year next epoch starts"  , 4, "ajax-leap-year"    , "set-clock-leap-year"   );
+    WebAddAjaxInput      ("Month next epoch starts" , 4, "ajax-leap-month"   , "set-clock-leap-month"  );
+    WebAddAjaxInput      ("Current era offset"      , 4, "ajax-leap-count"   , "set-clock-leap-count"  );
 
     HttpAddText("<div><button type='button' onclick='displayLeap()'>Display leap</button></div>\r\n");
     
     HttpAddText("<div>The leap seconds list is available <a href='https://www.ietf.org/timezones/data/leap-seconds.list' target='_blank'>here</a></div>\r\n");
         
-    PageAddH2("Governer");
-    PageAddAjaxInput      ("Ppb"                     , 5, "ajax-ppb"          , "ppb"           );
-    PageAddAjaxInput      ("Ppb divisor"             , 5, "ajax-ppb-divisor"  , "ppbdivisor"    );
-    PageAddAjaxInput      ("Ppb max change"          , 5, "ajax-ppb-max-chg"  , "ppbmaxchange"  );
-    PageAddAjaxInput      ("Ppb synced limit"        , 5, "ajax-ppb-syn-lim"  , "syncedlimitppb");
-    PageAddAjaxInput      ("Ppb synced hysteresis"   , 5, "ajax-ppb-syn-hys"  , "syncedhysppb"  );
-    PageAddAjaxInput      ("Offset divisor"          , 5, "ajax-off-divisor"  , "slewdivisor"   );
-    PageAddAjaxInput      ("Offset max (ms)"         , 5, "ajax-off-max"      , "slewmax"       );
-    PageAddAjaxInput      ("Offset synced limit (ms)", 5, "ajax-off-syn-lim"  , "syncedlimitns" );
-    PageAddAjaxInput      ("Offset synced hys (ms)"  , 5, "ajax-off-syn-hys"  , "syncedhysns"   );
-    PageAddAjaxInput      ("Offset reset limit (s)"  , 5, "ajax-off-rst-lim"  , "maxoffsetsecs" );
-    PageAddAjaxInputToggle("Trace"                      , "ajax-gov-trace"    , "clockgovtrace" );
+    WebAddH2("Governer");
+    WebAddAjaxInput      ("Ppb"                     , 5, "ajax-ppb"          , "ppb"           );
+    WebAddAjaxInput      ("Ppb divisor"             , 5, "ajax-ppb-divisor"  , "ppbdivisor"    );
+    WebAddAjaxInput      ("Ppb max change"          , 5, "ajax-ppb-max-chg"  , "ppbmaxchange"  );
+    WebAddAjaxInput      ("Ppb synced limit"        , 5, "ajax-ppb-syn-lim"  , "syncedlimitppb");
+    WebAddAjaxInput      ("Ppb synced hysteresis"   , 5, "ajax-ppb-syn-hys"  , "syncedhysppb"  );
+    WebAddAjaxInput      ("Offset divisor"          , 5, "ajax-off-divisor"  , "slewdivisor"   );
+    WebAddAjaxInput      ("Offset max (ms)"         , 5, "ajax-off-max"      , "slewmax"       );
+    WebAddAjaxInput      ("Offset synced limit (ms)", 5, "ajax-off-syn-lim"  , "syncedlimitns" );
+    WebAddAjaxInput      ("Offset synced hys (ms)"  , 5, "ajax-off-syn-hys"  , "syncedhysns"   );
+    WebAddAjaxInput      ("Offset reset limit (s)"  , 5, "ajax-off-rst-lim"  , "maxoffsetsecs" );
+    WebAddAjaxInputToggle("Trace"                      , "ajax-gov-trace"    , "clockgovtrace" );
 
-    PageAddH2("NTP");
-    PageAddAjaxInput      ("Server url"              , 5, "ajax-ntp-server"   , "ntpserver"     );
-    PageAddAjaxInput      ("Initial interval (s)"    , 5, "ajax-ntp-initial"  , "clockinitial"  );
-    PageAddAjaxInput      ("Normal interval (m)"     , 5, "ajax-ntp-normal"   , "clocknormal"   );
-    PageAddAjaxInput      ("Retry interval (s)"      , 5, "ajax-ntp-retry"    , "clockretry"    );
-    PageAddAjaxInput      ("Offset (ms)"             , 5, "ajax-ntp-offset"   , "clockoffset"   );
-    PageAddAjaxInput      ("Max delay (ms)"          , 5, "ajax-ntp-max-delay", "clockmaxdelay" );
+    WebAddH2("NTP");
+    WebAddAjaxInput      ("Server url"              , 5, "ajax-ntp-server"   , "ntpserver"     );
+    WebAddAjaxInput      ("Initial interval (s)"    , 5, "ajax-ntp-initial"  , "clockinitial"  );
+    WebAddAjaxInput      ("Normal interval (m)"     , 5, "ajax-ntp-normal"   , "clocknormal"   );
+    WebAddAjaxInput      ("Retry interval (s)"      , 5, "ajax-ntp-retry"    , "clockretry"    );
+    WebAddAjaxInput      ("Offset (ms)"             , 5, "ajax-ntp-offset"   , "clockoffset"   );
+    WebAddAjaxInput      ("Max delay (ms)"          , 5, "ajax-ntp-max-delay", "clockmaxdelay" );
 
-    PageAddH2("Scan times");
-    PageAddAjaxLabelled   ("Program cycles avg", "ajax-scan-avg");
-    PageAddAjaxLabelled   ("Program cycles max", "ajax-scan-max");
-    PageAddAjaxLabelled   ("Program cycles min", "ajax-scan-min");
+    WebAddH2("Scan times");
+    WebAddAjaxLabelled   ("Program cycles avg", "ajax-scan-avg");
+    WebAddAjaxLabelled   ("Program cycles max", "ajax-scan-max");
+    WebAddAjaxLabelled   ("Program cycles min", "ajax-scan-min");
 
-    PageAddEnd();
+    WebAddEnd();
 }
--- a/clock/web-clock-script.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/clock/web-clock-script.c	Mon Apr 29 14:45:30 2019 +0000
@@ -1,5 +1,4 @@
 #include "http.h"
-#include "web-base.h"
 
 //Use http://tomeko.net/online_tools/cpp_text_escape.php   to convert from text to c-multiline
 //Use http://tomeko.net/online_tools/cpp_text_unescape.php to convert from c-multiline to text
--- a/css/web-base-css.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/css/web-base-css.c	Mon Apr 29 14:45:30 2019 +0000
@@ -1,5 +1,4 @@
 #include "http.h"
-#include "web-base.h"
 
 static const char* cssBase =
 #include "web-base-css.inc"
--- a/css/web-nav-css.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/css/web-nav-css.c	Mon Apr 29 14:45:30 2019 +0000
@@ -1,5 +1,4 @@
 #include "http.h"
-#include "web-base.h"
 
 static const char* cssNav =
 #include "web-nav-css.inc"
--- a/fault/web-fault-html.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/fault/web-fault-html.c	Mon Apr 29 14:45:30 2019 +0000
@@ -1,35 +1,34 @@
 #include <stdio.h>
 
 #include "http.h"
-#include "page.h"
-#include "page-derived.h"
-#include "web-base.h"
+#include "web-page-base.h"
+#include "web-add.h"
 #include "fault.h"
 
 void WebFaultHtml()
 {
     HttpOk("text/html; charset=UTF-8", "no-cache", NULL, NULL);
-    PageAddHeader(PageSite, "Fault", "settings.css", NULL);
-    PageAddNav(FAULT_PAGE);
-    PageAddH1(PageSite, "Fault");
+    WebAddHeader("Fault", "settings.css", NULL);
+    WebAddNav(FAULT_PAGE);
+    WebAddH1("Fault");
     
-    PageAddH2("Last fault");
+    WebAddH2("Last fault");
     int faultType = FaultTypeGet();
     char text[20];
     FaultTypeToString(faultType, sizeof(text), text);
-    PageAddLabelledText("Fault type", text);
+    WebAddLabelledText("Fault type", text);
     if (faultType)
     {
         FaultZoneToString(FaultZoneGet(), sizeof(text), text);
-        PageAddLabelledText("Fault zone" , text);
-        PageAddLabelledInt ("After point", FaultPointGet());
-        PageAddInputButton ("Clear fault", "Clear", "/fault", "faultclear");
+        WebAddLabelledText("Fault zone" , text);
+        WebAddLabelledInt ("After point", FaultPointGet());
+        WebAddInputButton ("Clear fault", "Clear", "/fault", "faultclear");
     }
     else
     {
-        PageAddInputButton("Test fault"   ,  "Test",  "/fault", "faulttest");
+        WebAddInputButton("Test fault"   ,  "Test",  "/fault", "faulttest");
     }
     
-    PageAddEnd();
+    WebAddEnd();
 }
 
--- a/favicon/web-favicon.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/favicon/web-favicon.c	Mon Apr 29 14:45:30 2019 +0000
@@ -1,5 +1,4 @@
 #include "http.h"
-#include "web-base.h"
 
 //Use http://tomeko.net/online_tools/file_to_hex.php to convert a favicon.ico into hex readable as an array
 static const char bytes[] = {
--- a/firmware/web-firmware-html.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/firmware/web-firmware-html.c	Mon Apr 29 14:45:30 2019 +0000
@@ -1,35 +1,34 @@
 #include <stdio.h>
 
-#include "web-base.h"
 #include "http.h"
-#include "page.h"
-#include "page-derived.h"
+#include "web-page-base.h"
+#include "web-add.h"
 #include "web-firmware.h"
 
 void WebFirmwareHtml()
 {
     HttpOk("text/html; charset=UTF-8", "no-cache", NULL, NULL);
-    PageAddHeader(PageSite, "Firmware", "settings.css", "firmware.js");
-    PageAddNav(FIRMWARE_PAGE);
-    PageAddH1(PageSite, "Firmware");
+    WebAddHeader("Firmware", "settings.css", "firmware.js");
+    WebAddNav(FIRMWARE_PAGE);
+    WebAddH1("Firmware");
     
-    PageAddH2("Existing files on the device");
+    WebAddH2("Existing files on the device");
 
     HttpAddText("<code id='list'>");
     WebFirmwareListSemihostFiles();
     HttpAddText("</code>\r\n");
     
-    PageAddH2("Choose a local file");
+    WebAddH2("Choose a local file");
     HttpAddText("<div><input type='file' id='fileInput'/></div>\r\n");
     
-    PageAddH2("Upload the local file to the device");
+    WebAddH2("Upload the local file to the device");
     HttpAddText("<div><button onclick='startUpload();'>Upload</button></div>\r\n");
     HttpAddText("<code id='uploadresult'></code>\r\n");
     
-    PageAddH2("Restart the device");
+    WebAddH2("Restart the device");
     HttpAddText("<div><button onclick='restart();'>Restart</button></div>\r\n");
     HttpAddText("<code id='restartresult'></code>\r\n");
 
 
-    PageAddEnd();
+    WebAddEnd();
 }
--- a/firmware/web-firmware-script.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/firmware/web-firmware-script.c	Mon Apr 29 14:45:30 2019 +0000
@@ -1,5 +1,4 @@
 #include "http.h"
-#include "web-base.h"
 
 //Use http://tomeko.net/online_tools/cpp_text_escape.php   to convert from text to c-multiline
 //Use http://tomeko.net/online_tools/cpp_text_unescape.php to convert from c-multiline to text
--- a/log/web-log-html.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/log/web-log-html.c	Mon Apr 29 14:45:30 2019 +0000
@@ -1,22 +1,22 @@
 #include "http.h"
-#include "page.h"
+#include "web-page-base.h"
+#include "web-add.h"
 #include "log.h"
-#include "web-base.h"
 
 void WebLogHtml()
 {
     HttpOk("text/html; charset=UTF-8", "no-cache", NULL, NULL);
-    PageAddHeader(PageSite, "Log", "settings.css", NULL);
-    PageAddNav(LOG_PAGE);
-    PageAddH1(PageSite, "Log");
+    WebAddHeader("Log", "settings.css", NULL);
+    WebAddNav(LOG_PAGE);
+    WebAddH1("Log");
     
-                 PageAddInputButton("Existing content",      "Clear",    "/log", "clearlog"    );
-    if (LogUart) PageAddInputButton("Output to uart is on",  "Turn off", "/log", "chg-log-uart");
-    else         PageAddInputButton("Output to uart is off", "Turn on",  "/log", "chg-log-uart");
+                 WebAddInputButton("Existing content",      "Clear",    "/log", "clearlog"    );
+    if (LogUart) WebAddInputButton("Output to uart is on",  "Turn off", "/log", "chg-log-uart");
+    else         WebAddInputButton("Output to uart is off", "Turn on",  "/log", "chg-log-uart");
     
     HttpAddText("<code>");
     HttpAddStream(LogEnumerateStart, LogEnumerate);
     HttpAddText("</code>");
     
-    PageAddEnd();
+    WebAddEnd();
 }
--- a/login/web-login-html.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/login/web-login-html.c	Mon Apr 29 14:45:30 2019 +0000
@@ -1,26 +1,26 @@
 #include "http.h"
-#include "web-base.h"
+#include "web-add.h"
 #include "web-login.h"
-#include "page.h"
-#include "led.h"
+#include "web-base.h"
+#include "web-page-base.h"
 
 void WebLoginHtml()
 {
     HttpOk("text/html; charset=UTF-8", "no-cache", NULL, NULL);
-    PageAddHeader(PageSite, "Login", NULL, NULL);
+    WebAddHeader("Login", NULL, NULL);
     HttpAddText(
 "<style>"
 #include "web-login-css.inc"
 "</style>"
     );
-    PageAddH1(PageSite, "Login");
+    WebAddH1("Login");
     if (WebLoginPasswordIsSet())
     {
-        PageAddH2("Welcome - please enter the password");
+        WebAddH2("Welcome - please enter the password");
     }
     else
     {
-        PageAddH2("Please enter a new password following user reset");
+        WebAddH2("Please enter a new password following user reset");
         HttpAddText("<p>Be careful to make it the one people expect!</p>");
     }
     
@@ -31,7 +31,7 @@
     HttpAddText("  <input type='submit'                 value='' >\r\n");
     HttpAddF   ("</form>\r\n");
 
-    PageAddEnd();
+    WebAddEnd();
 }
 
 /*
--- a/login/web-login-session-name.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/login/web-login-session-name.c	Mon Apr 29 14:45:30 2019 +0000
@@ -1,4 +1,4 @@
-#include "page.h"
+#include "web-site-name.h"
 
 #define SESSION_LIFE 10 * 365 * 24 * 60 * 60
 
@@ -18,7 +18,7 @@
     while (1)
     {
         if (i >= sizeof(sessionName) - 4 - 1) break; //Leave room for the "_sid" and the terminating NUL character
-        char c = PageSite[j++];
+        char c = WEB_SITE_NAME[j++];
         if (!c) break;                               //Stop if run out of site name
         if (c >= 'A' && c <= 'Z') c |= 0x20;         //Make lower case
         if (c < 'a' || c > 'z') continue;            //Skip anything other than letters
--- a/net-trace/web-trace-html.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/net-trace/web-trace-html.c	Mon Apr 29 14:45:30 2019 +0000
@@ -1,56 +1,55 @@
-#include "web-base.h"
-#include "page.h"
+#include "web-add.h"
+#include "web-page-base.h"
 #include "http.h"
-#include  "net.h"
 
 void WebTraceHtml()
 {
     HttpOk("text/html; charset=UTF-8", "no-cache", NULL, NULL);
-    PageAddHeader(PageSite, "Net Trace", "settings.css", "trace.js");
-    PageAddNav(TRACE_PAGE);
-    PageAddH1(PageSite, "Net Trace");
+    WebAddHeader("Net Trace", "settings.css", "trace.js");
+    WebAddNav(TRACE_PAGE);
+    WebAddH1("Net Trace");
     
-    PageAddH2("General");
-    PageAddAjaxInput      ("Trace host"      , 5  , "ajax-trace-net-host"   , "set-trace-net-host"   );
-    PageAddAjaxInputToggle("Trace stack"          , "ajax-trace-net-stack"  , "chg-trace-net-stack"  );
-    PageAddAjaxInputToggle("Trace new line"       , "ajax-trace-net-newline", "chg-trace-net-newline");
-    PageAddAjaxInputToggle("Trace verbose"        , "ajax-trace-net-verbose", "chg-trace-net-verbose");
-    PageAddH2("Net");
-    PageAddAjaxInputToggle("MAC"                  , "ajax-trace-link"       , "chg-trace-link"       );
-    PageAddAjaxInputToggle("Ip4 filtered"         , "ajax-trace-ip4"        , "chg-trace-ip4"        );
-    PageAddAjaxInputToggle("Ip6 filtered"         , "ajax-trace-ip6"        , "chg-trace-ip6"        );
-    PageAddAjaxInputToggle("Udp filtered"         , "ajax-trace-udp"        , "chg-trace-udp"        );
-    PageAddAjaxInputToggle("Tcp filtered"         , "ajax-trace-tcp"        , "chg-trace-tcp"        );
-    PageAddAjaxInputToggle("Echo4 (ping4)"        , "ajax-trace-echo4"      , "chg-trace-echo4"      );
-    PageAddAjaxInputToggle("Echo6 (ping6)"        , "ajax-trace-echo6"      , "chg-trace-echo6"      );
-    PageAddAjaxInputToggle("Dest6 unreacheable"   , "ajax-trace-dest6"      , "chg-trace-dest6"      );
-    PageAddAjaxInputToggle("HTTP"                 , "ajax-trace-http"       , "chg-trace-http"       );
-    PageAddAjaxInputToggle("TFTP"                 , "ajax-trace-tftp"       , "chg-trace-tftp"       );
-    PageAddH2("Send requests via IPv4");
-    PageAddAjaxInputToggle("DNS request via IPv4" , "ajax-trace-dns-ip4"    , "chg-send-dns-ip4"     );
-    PageAddAjaxInputToggle("NTP request via IPv4" , "ajax-trace-ntp-ip4"    , "chg-send-ntp-ip4"     );
-    PageAddAjaxInputToggle("TFTP request via IPv4", "ajax-trace-tftp-ip4"   , "chg-send-tftp-ip4"    );
-    PageAddH2("Router Resolution");
-    PageAddAjaxInputToggle("Router advertise"     , "ajax-trace-ra"         , "chg-trace-ra"         );
-    PageAddAjaxInputToggle("Router solicit"       , "ajax-trace-rs"         , "chg-trace-rs"         );
-    PageAddAjaxInputToggle("DHCP"                 , "ajax-trace-dhcp"       , "chg-trace-dhcp"       );
-    PageAddH2("Address Resolution");
-    PageAddAjaxInputToggle("IP4 cache"            , "ajax-trace-ar4"        , "chg-trace-ar4"        );
-    PageAddAjaxInputToggle("IP6 cache"            , "ajax-trace-ar6"        , "chg-trace-ar6"        );
-    PageAddAjaxInputToggle("ARP"                  , "ajax-trace-arp"        , "chg-trace-arp"        );
-    PageAddAjaxInputToggle("NS server"            , "ajax-trace-ns-recv-sol", "chg-trace-ns-recv-sol");
-    PageAddAjaxInputToggle("NS client reply"      , "ajax-trace-ns-recv-adv", "chg-trace-ns-recv-adv");
-    PageAddAjaxInputToggle("NS client query"      , "ajax-trace-ns-send-sol", "chg-trace-ns-send-sol");
-    PageAddH2("Name Resolution");
-    PageAddAjaxInputToggle("IP4 cache"            , "ajax-trace-nr4"        , "chg-trace-nr4"        );
-    PageAddAjaxInputToggle("IP6 cache"            , "ajax-trace-nr6"        , "chg-trace-nr6"        );
-    PageAddAjaxInputToggle("DNS name"             , "ajax-trace-dns-name"   , "chg-trace-dns-name"   );
-    PageAddAjaxInputToggle("DNS client query"     , "ajax-trace-dns-query"  , "chg-trace-dns-query"  );
-    PageAddAjaxInputToggle("DNS client reply"     , "ajax-trace-dns-reply"  , "chg-trace-dns-reply"  );
-    PageAddAjaxInputToggle("DNS server"           , "ajax-trace-dns-server" , "chg-trace-dns-server" );
-    PageAddH2("NTP");
-    PageAddAjaxInputToggle("NTP"                  , "ajax-trace-ntp"        , "chg-trace-ntp"        );
-    PageAddAjaxInputToggle("NTP client"           , "ajax-trace-ntp-client" , "chg-trace-ntp-client" );
+    WebAddH2("General");
+    WebAddAjaxInput      ("Trace host"      , 5  , "ajax-trace-net-host"   , "set-trace-net-host"   );
+    WebAddAjaxInputToggle("Trace stack"          , "ajax-trace-net-stack"  , "chg-trace-net-stack"  );
+    WebAddAjaxInputToggle("Trace new line"       , "ajax-trace-net-newline", "chg-trace-net-newline");
+    WebAddAjaxInputToggle("Trace verbose"        , "ajax-trace-net-verbose", "chg-trace-net-verbose");
+    WebAddH2("Net");
+    WebAddAjaxInputToggle("MAC"                  , "ajax-trace-link"       , "chg-trace-link"       );
+    WebAddAjaxInputToggle("Ip4 filtered"         , "ajax-trace-ip4"        , "chg-trace-ip4"        );
+    WebAddAjaxInputToggle("Ip6 filtered"         , "ajax-trace-ip6"        , "chg-trace-ip6"        );
+    WebAddAjaxInputToggle("Udp filtered"         , "ajax-trace-udp"        , "chg-trace-udp"        );
+    WebAddAjaxInputToggle("Tcp filtered"         , "ajax-trace-tcp"        , "chg-trace-tcp"        );
+    WebAddAjaxInputToggle("Echo4 (ping4)"        , "ajax-trace-echo4"      , "chg-trace-echo4"      );
+    WebAddAjaxInputToggle("Echo6 (ping6)"        , "ajax-trace-echo6"      , "chg-trace-echo6"      );
+    WebAddAjaxInputToggle("Dest6 unreacheable"   , "ajax-trace-dest6"      , "chg-trace-dest6"      );
+    WebAddAjaxInputToggle("HTTP"                 , "ajax-trace-http"       , "chg-trace-http"       );
+    WebAddAjaxInputToggle("TFTP"                 , "ajax-trace-tftp"       , "chg-trace-tftp"       );
+    WebAddH2("Send requests via IPv4");
+    WebAddAjaxInputToggle("DNS request via IPv4" , "ajax-trace-dns-ip4"    , "chg-send-dns-ip4"     );
+    WebAddAjaxInputToggle("NTP request via IPv4" , "ajax-trace-ntp-ip4"    , "chg-send-ntp-ip4"     );
+    WebAddAjaxInputToggle("TFTP request via IPv4", "ajax-trace-tftp-ip4"   , "chg-send-tftp-ip4"    );
+    WebAddH2("Router Resolution");
+    WebAddAjaxInputToggle("Router advertise"     , "ajax-trace-ra"         , "chg-trace-ra"         );
+    WebAddAjaxInputToggle("Router solicit"       , "ajax-trace-rs"         , "chg-trace-rs"         );
+    WebAddAjaxInputToggle("DHCP"                 , "ajax-trace-dhcp"       , "chg-trace-dhcp"       );
+    WebAddH2("Address Resolution");
+    WebAddAjaxInputToggle("IP4 cache"            , "ajax-trace-ar4"        , "chg-trace-ar4"        );
+    WebAddAjaxInputToggle("IP6 cache"            , "ajax-trace-ar6"        , "chg-trace-ar6"        );
+    WebAddAjaxInputToggle("ARP"                  , "ajax-trace-arp"        , "chg-trace-arp"        );
+    WebAddAjaxInputToggle("NS server"            , "ajax-trace-ns-recv-sol", "chg-trace-ns-recv-sol");
+    WebAddAjaxInputToggle("NS client reply"      , "ajax-trace-ns-recv-adv", "chg-trace-ns-recv-adv");
+    WebAddAjaxInputToggle("NS client query"      , "ajax-trace-ns-send-sol", "chg-trace-ns-send-sol");
+    WebAddH2("Name Resolution");
+    WebAddAjaxInputToggle("IP4 cache"            , "ajax-trace-nr4"        , "chg-trace-nr4"        );
+    WebAddAjaxInputToggle("IP6 cache"            , "ajax-trace-nr6"        , "chg-trace-nr6"        );
+    WebAddAjaxInputToggle("DNS name"             , "ajax-trace-dns-name"   , "chg-trace-dns-name"   );
+    WebAddAjaxInputToggle("DNS client query"     , "ajax-trace-dns-query"  , "chg-trace-dns-query"  );
+    WebAddAjaxInputToggle("DNS client reply"     , "ajax-trace-dns-reply"  , "chg-trace-dns-reply"  );
+    WebAddAjaxInputToggle("DNS server"           , "ajax-trace-dns-server" , "chg-trace-dns-server" );
+    WebAddH2("NTP");
+    WebAddAjaxInputToggle("NTP"                  , "ajax-trace-ntp"        , "chg-trace-ntp"        );
+    WebAddAjaxInputToggle("NTP client"           , "ajax-trace-ntp-client" , "chg-trace-ntp-client" );
     
-    PageAddEnd();
+    WebAddEnd();
 }
--- a/net-trace/web-trace-script.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/net-trace/web-trace-script.c	Mon Apr 29 14:45:30 2019 +0000
@@ -1,5 +1,4 @@
 #include "http.h"
-#include "web-base.h"
 
 //Use http://tomeko.net/online_tools/cpp_text_escape.php   to convert from text to c-multiline
 //Use http://tomeko.net/online_tools/cpp_text_unescape.php to convert from c-multiline to text
--- a/net/web-net-html.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/net/web-net-html.c	Mon Apr 29 14:45:30 2019 +0000
@@ -1,23 +1,18 @@
-#include  "http.h"
-#include  "web-base.h"
-#include  "page.h"
-#include   "net.h"
-#include   "mac.h"
-#include   "ip4.h"
-#include   "ar4.h"
-#include   "nr4.h"
-#include  "dhcp.h"
+#include "http.h"
+#include "web-page-base.h"
+#include "web-add.h"
+#include "mac.h"
 
 void WebNetHtml()
 {
     HttpOk("text/html; charset=UTF-8", "no-cache", NULL, NULL);
-    PageAddHeader(PageSite, "Net", "settings.css", NULL);
-    PageAddNav(NET_PAGE);
-    PageAddH1(PageSite, "Net");
+    WebAddHeader("Net", "settings.css", NULL);
+    WebAddNav(NET_PAGE);
+    WebAddH1("Net");
                      
-    PageAddH2("Ethernet");
-    PageAddLabelledMac  ("MAC",                   MacLocal);
+    WebAddH2("Ethernet");
+    WebAddLabelledMac  ("MAC",                   MacLocal);
     
-    PageAddEnd();
+    WebAddEnd();
                         
 }
--- a/net/web-net4-html.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/net/web-net4-html.c	Mon Apr 29 14:45:30 2019 +0000
@@ -1,35 +1,34 @@
 #include "http.h"
-#include "web-base.h"
-#include "page.h"
-#include "net.h"
+#include "web-add.h"
+#include "web-page-base.h"
 
 void WebNet4Html()
 {
     HttpOk("text/html; charset=UTF-8", "no-cache", NULL, NULL);
-    PageAddHeader(PageSite, "Net IPv4", "settings.css", "net4.js");
-    PageAddNav(NET4_PAGE);
-    PageAddH1(PageSite, "Net IPv4");
+    WebAddHeader("Net IPv4", "settings.css", "net4.js");
+    WebAddNav(NET4_PAGE);
+    WebAddH1("Net IPv4");
     
-    PageAddH2("ARP");
+    WebAddH2("ARP");
     HttpAddText("<code id='ajax-arp'></code>\r\n");
-    PageAddH2("DNS");
+    WebAddH2("DNS");
     HttpAddText("<code id='ajax-dns'></code>\r\n");
     
-    PageAddH2("DHCP");
-    PageAddAjaxLabelled("IP4 address",   "ajax-local-ip"    );
-    PageAddAjaxLabelled("Domain",        "ajax-domain-name" );
-    PageAddAjaxLabelled("Host name",     "ajax-host-name"   );
-    PageAddAjaxLabelled("NTP server",    "ajax-ntp-ip"      );
-    PageAddAjaxLabelled("DNS server",    "ajax-dns-ip"      );
-    PageAddAjaxLabelled("DHCP server",   "ajax-dhcp-ip"     );
-    PageAddAjaxLabelled("Router",        "ajax-router-ip"   );
-    PageAddAjaxLabelled("Subnet mask",   "ajax-subnet-mask" );
-    PageAddAjaxLabelled("Broadcast IP",  "ajax-broadcast-ip");
-    PageAddAjaxLabelled("Lease time IP", "ajax-lease-time"  );
-    PageAddAjaxLabelled("Renewal T1",    "ajax-renewal-t1"  );
-    PageAddAjaxLabelled("Renewal T2",    "ajax-renewal-t2"  );
-    PageAddAjaxLabelled("Elapsed",       "ajax-elapsed"     );
+    WebAddH2("DHCP");
+    WebAddAjaxLabelled("IP4 address",   "ajax-local-ip"    );
+    WebAddAjaxLabelled("Domain",        "ajax-domain-name" );
+    WebAddAjaxLabelled("Host name",     "ajax-host-name"   );
+    WebAddAjaxLabelled("NTP server",    "ajax-ntp-ip"      );
+    WebAddAjaxLabelled("DNS server",    "ajax-dns-ip"      );
+    WebAddAjaxLabelled("DHCP server",   "ajax-dhcp-ip"     );
+    WebAddAjaxLabelled("Router",        "ajax-router-ip"   );
+    WebAddAjaxLabelled("Subnet mask",   "ajax-subnet-mask" );
+    WebAddAjaxLabelled("Broadcast IP",  "ajax-broadcast-ip");
+    WebAddAjaxLabelled("Lease time IP", "ajax-lease-time"  );
+    WebAddAjaxLabelled("Renewal T1",    "ajax-renewal-t1"  );
+    WebAddAjaxLabelled("Renewal T2",    "ajax-renewal-t2"  );
+    WebAddAjaxLabelled("Elapsed",       "ajax-elapsed"     );
     
-    PageAddEnd();
+    WebAddEnd();
                         
 }
--- a/net/web-net4-script.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/net/web-net4-script.c	Mon Apr 29 14:45:30 2019 +0000
@@ -1,5 +1,4 @@
 #include "http.h"
-#include "web-base.h"
 
 //Use http://tomeko.net/online_tools/cpp_text_escape.php   to convert from text to c-multiline
 //Use http://tomeko.net/online_tools/cpp_text_unescape.php to convert from c-multiline to text
--- a/net/web-net6-html.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/net/web-net6-html.c	Mon Apr 29 14:45:30 2019 +0000
@@ -1,38 +1,37 @@
-#include  "http.h"
-#include  "web-base.h"
-#include  "page.h"
-#include   "net.h"
+#include "http.h"
+#include "web-page-base.h"
+#include "web-add.h"
 
 void WebNet6Html()
 {
     HttpOk("text/html; charset=UTF-8", "no-cache", NULL, NULL);
-    PageAddHeader(PageSite, "Net IPv6", "settings.css", "net6.js");
-    PageAddNav(NET6_PAGE);
-    PageAddH1(PageSite, "Net IPv6");
+    WebAddHeader("Net IPv6", "settings.css", "net6.js");
+    WebAddNav(NET6_PAGE);
+    WebAddH1("Net IPv6");
 
-    PageAddH2("ARP");
+    WebAddH2("ARP");
     HttpAddText("<code id='ajax-arp'></code>\r\n");
-    PageAddH2("DNS");
+    WebAddH2("DNS");
     HttpAddText("<code id='ajax-dns'></code>\r\n");
     
-    PageAddH2("NDP");
-    PageAddAjaxLabelled("Hop limit",             "ajax-hop-limit");
-    PageAddAjaxLed     ("Managed address",       "ajax-managed");
-    PageAddAjaxLed     ("Other configuration",   "ajax-other");
-    PageAddAjaxLabelled("Router MAC",            "ajax-router-mac");
-    PageAddAjaxLabelled("Prefix length",         "ajax-prefix-length");
-    PageAddAjaxLed     ("Prefix flag L",         "ajax-prefix-l");
-    PageAddAjaxLed     ("Prefix flag A",         "ajax-prefix-a");
-    PageAddAjaxLabelled("Prefix valid secs",     "ajax-prefix-limit");
-    PageAddAjaxLabelled("Prefix preferred secs", "ajax-prefix-preferred");
-    PageAddAjaxLabelled("Prefix",                "ajax-prefix");
-    PageAddAjaxLabelled("DNS life secs",         "ajax-dns-life");
-    PageAddAjaxLabelled("DNS server",            "ajax-dns-ip");
-    PageAddAjaxLabelled("Lease time",            "ajax-ndp-lease");
-    PageAddAjaxLabelled("Elapsed",               "ajax-ndp-elapsed");
-    PageAddAjaxLabelled("SLAAC",                 "ajax-slaac");
-    PageAddAjaxLabelled("MTU",                   "ajax-mtu");
+    WebAddH2("NDP");
+    WebAddAjaxLabelled("Hop limit",             "ajax-hop-limit");
+    WebAddAjaxLed     ("Managed address",       "ajax-managed");
+    WebAddAjaxLed     ("Other configuration",   "ajax-other");
+    WebAddAjaxLabelled("Router MAC",            "ajax-router-mac");
+    WebAddAjaxLabelled("Prefix length",         "ajax-prefix-length");
+    WebAddAjaxLed     ("Prefix flag L",         "ajax-prefix-l");
+    WebAddAjaxLed     ("Prefix flag A",         "ajax-prefix-a");
+    WebAddAjaxLabelled("Prefix valid secs",     "ajax-prefix-limit");
+    WebAddAjaxLabelled("Prefix preferred secs", "ajax-prefix-preferred");
+    WebAddAjaxLabelled("Prefix",                "ajax-prefix");
+    WebAddAjaxLabelled("DNS life secs",         "ajax-dns-life");
+    WebAddAjaxLabelled("DNS server",            "ajax-dns-ip");
+    WebAddAjaxLabelled("Lease time",            "ajax-ndp-lease");
+    WebAddAjaxLabelled("Elapsed",               "ajax-ndp-elapsed");
+    WebAddAjaxLabelled("SLAAC",                 "ajax-slaac");
+    WebAddAjaxLabelled("MTU",                   "ajax-mtu");
     
-    PageAddEnd();
+    WebAddEnd();
                         
 }
--- a/net/web-net6-script.c	Sun Apr 28 09:56:42 2019 +0000
+++ b/net/web-net6-script.c	Mon Apr 29 14:45:30 2019 +0000
@@ -1,5 +1,4 @@
 #include "http.h"
-#include "web-base.h"
 
 //Use http://tomeko.net/online_tools/cpp_text_escape.php   to convert from text to c-multiline
 //Use http://tomeko.net/online_tools/cpp_text_unescape.php to convert from c-multiline to text
--- a/page/page.c	Sun Apr 28 09:56:42 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,224 +0,0 @@
-#include <stdio.h>
-#include "http.h"
-#include "web-derived.h"
-#include "page.h"
-#include "page-derived.h"
-#include "mac.h"
-#include "ip4addr.h"
-#include "ip6addr.h"
-
-void PageAddHeader(const char* site, const char* title, const char* style, const char* script)
-{
-    HttpAddText("<!DOCTYPE html>\r\n"
-                     "<html>\r\n"
-                     "<head>\r\n");
-    if (site)
-    {
-        HttpAddText("   <title>");
-        HttpAddText(site);
-        if (title)
-        {
-            HttpAddText(" - ");
-            HttpAddText(title);
-        }
-        HttpAddText("</title>\r\n");
-    }
-    HttpAddText("   <link rel='stylesheet' href='/base.css' type='text/css'/>\r\n");
-    if (style)
-    {
-        HttpAddText("   <link rel='stylesheet' href='/");
-        HttpAddText(style);
-        HttpAddText("' type='text/css'/>\r\n");
-    }
-    if (script)
-    {
-        HttpAddText("   <script src='/");
-        HttpAddText(script);
-        HttpAddText("' type='text/javascript'></script>\r\n");
-    }
-    HttpAddText("   <meta name='viewport' content='width=device-width, initial-scale=1'>\r\n"
-                     "   <link rel='icon'       href='/favicon.ico' type='image/x-icon'/>\r\n"
-                     "</head>\r\n"
-                     "<body>\r\n");
-
-}
-void PageAddH1(const char* site, const char* pageName)
-{
-    HttpAddText("<h1 id='main-content'>");
-    HttpAddText(site);
-    HttpAddText(" - ");
-    HttpAddText(pageName);
-    HttpAddText("</h1>\r\n");
-}
-void PageAddH2(const char* text)
-{
-    HttpAddText("<h2>");
-    HttpAddText(text);
-    HttpAddText("</h2>\r\n");
-}
-void PageAddEnd()
-{
-    HttpAddText("</body>\r\n"
-                "</html>\r\n");
-}
-
-void PageAddNavItem(int highlight, char* href, char* title)
-{
-    char *p;
-    HttpAddText("<li ");
-    if (highlight) p = "class='this'";
-    else           p = "            ";
-    HttpAddText(p);
-    HttpAddText("><a href='");
-    HttpAddText(href);
-    HttpAddText("'>");
-    HttpAddText(title);
-    HttpAddText("</a></li>\r\n");
-
-}
-void PageAddNav(int page)
-{
-    HttpAddText("<a class='tab-shortcut' href='#main-content'>Skip to content</a>\r\n");
-
-    HttpAddText("<nav><ul>\r\n");
-    PageAddNavDerived(page);
-    PageAddNavItem(page ==    CLOCK_PAGE, "/clock",    "Clock"    );
-    PageAddNavItem(page ==    FAULT_PAGE, "/fault",    "Fault"    );
-    PageAddNavItem(page ==      NET_PAGE, "/net",      "Net"      );
-    PageAddNavItem(page ==     NET4_PAGE, "/net4",     "Net IPv4" );
-    PageAddNavItem(page ==     NET6_PAGE, "/net6",     "Net IPv6" );
-    PageAddNavItem(page ==    TRACE_PAGE, "/trace",    "Net Trace");
-    PageAddNavItem(page ==      LOG_PAGE, "/log",      "Log"      );
-    PageAddNavItem(page == FIRMWARE_PAGE, "/firmware", "Firmware" );
-    HttpAddText("</ul></nav>\r\n");
-}
-
-void PageAddLabelledPrefixSuffix(char* label, char* prefix, char* text, char* suffix)
-{
-    HttpAddText("<div class='line'>\r\n");
-    HttpAddF   ("  <div>%s</div>\r\n", label);
-    HttpAddF   ("  <div>%s%s%s</div>\r\n", prefix, text, suffix);
-    HttpAddText("</div>\r\n");
-}
-void PageAddLabelledText(char* label, char* text)
-{
-    HttpAddText("<div class='line'>\r\n");
-    HttpAddF   ("  <div>%s</div>\r\n", label);
-    HttpAddF   ("  <div>%s</div>\r\n", text);
-    HttpAddText("</div>\r\n");
-}
-
-void PageAddLabelledMac(char* label, char* mac)
-{
-    HttpAddText("<div class='line'>\r\n");
-    HttpAddF   ("  <div>%s</div>\r\n", label);
-    HttpAddText("  <div>"); MacHttp(mac); HttpAddText("</div>\r\n");
-    HttpAddText("</div>\r\n");
-}
-
-void PageAddLabelledIp4(char* label, uint32_t ip)
-{
-    HttpAddText("<div class='line'>\r\n");
-    HttpAddF   ("  <div>%s</div>\r\n", label);
-    HttpAddText("  <div>"); Ip4AddressHttp(ip); HttpAddText("</div>\r\n");
-    HttpAddText("</div>\r\n");
-}
-
-void PageAddLabelledIp6(char* label, char* ip)
-{
-    HttpAddText("<div class='line'>\r\n");
-    HttpAddF   ("  <div>%s</div>\r\n", label);
-    HttpAddText("  <div>"); Ip6AddressHttp(ip); HttpAddText("</div>\r\n");
-    HttpAddText("</div>\r\n");
-}
-void PageAddLabelledOnOff(char* label, bool value)
-{
-    if (value) PageAddLabelledText(label, "On");
-    else       PageAddLabelledText(label, "Off");
-}
-void PageAddLabelledInt(char* label, int value)
-{
-    char text[30];
-    snprintf(text, sizeof(text), "%8d", value); //Right align with enough spaces so that the length is always constant. 
-    PageAddLabelledText(label, text);
-}
-void PageAddInputText(char* label, float inputwidth, char* value, char* action, char* name)
-{
-    HttpAddF   ("<form action='%s' method='get'>\r\n", action);
-    HttpAddText("<div class='line'>\r\n");
-    HttpAddF   ("  <div>%s</div>\r\n", label);
-    HttpAddF   ("  <input type='text' name='%s' style='width:%.1fem;' value='%s'>\r\n", name, inputwidth, value);
-    HttpAddText("</div>\r\n");
-    HttpAddText("<input type='submit' value='Set' style='display:none;'>\r\n");
-    HttpAddF   ("</form>\r\n");
-
-}
-void PageAddInputInt(char* label, float inputwidth, int value, char* action, char* name)
-{    
-    char text[30];
-    snprintf(text, sizeof(text), "%d", value);
-    PageAddInputText(label, inputwidth, text, action, name);
-}
-void PageAddInputButton(char* label, char* value, char* action, char* name)
-{
-    HttpAddF   ("<form action='%s' method='get'>\r\n", action);
-    HttpAddF   ("<input type='hidden' name='%s'>\r\n", name);
-    HttpAddText("<div class='line'>\r\n");
-    HttpAddF   ("  <div>%s</div>\r\n", label);
-    HttpAddF   ("  <input type='submit' value='%s'>\r\n", value);
-    HttpAddText("</div>\r\n");
-    HttpAddText("</form>\r\n");
-}
-void PageAddAjaxInputToggle(char* label, char* id, char* name)
-{
-    HttpAddText("<div class='line'>\r\n");
-    HttpAddF   ("  <div>%s</div>\r\n", label);
-    HttpAddF   ("  <div class='toggle' id='%s' tabindex='0' dir='ltr' onclick='AjaxRequest(\"%s=1\")' onkeydown='return event.keyCode != 13 || AjaxRequest(\"%s=1\")'>\r\n", id, name, name);
-    HttpAddText("    <div class='slot'></div><div class='knob'></div>\r\n");
-    HttpAddText("  </div>\r\n");
-    HttpAddText("</div>\r\n");
-}
-void PageAddAjaxLed(char* label, char* id)
-{
-    HttpAddText("<div class='line'>\r\n");
-    HttpAddF   ("  <div>%s</div>\r\n", label);
-    HttpAddF   ("  <div class='led' id='%s' dir='ltr'></div>\r\n", id);
-    HttpAddText("</div>\r\n");
-}
-void PageAddAjaxInput(char* label, float inputwidth, char* id, char* name)
-{
-    HttpAddText("<div class='line'>\r\n");
-    HttpAddF   ("  <div>%s</div>\r\n", label);
-    HttpAddF   ("  <input type='text' style='width:%.1fem;' id='%s' onchange='AjaxRequest(\"%s=\" + this.value)'>\r\n", inputwidth, id, name);
-    HttpAddText("</div>\r\n");
-}
-void PageAddAjaxInputSuffix(char* label, float inputwidth, char* id, char* name, char* suffix)
-{
-    HttpAddText("<div class='line'>\r\n");
-    HttpAddF   ("  <div>%s</div>\r\n", label);
-    HttpAddF   ("  <input type='text' style='width:%.1fem;' id='%s' onchange='AjaxRequest(\"%s=\" + this.value)'>%s\r\n", inputwidth, id, name, suffix);
-    HttpAddText("</div>\r\n");
-}
-void PageAddAjaxLabelled(char* label, char* id)
-{
-    HttpAddText("<div class='line'>\r\n");
-    HttpAddF   ("  <div>%s</div>\r\n", label);
-    HttpAddF   ("  <div id='%s'></div>\r\n", id);
-    HttpAddText("</div>\r\n");
-}
-void PageAddAjaxLabelledSuffix(char* label, char* id, char* suffix)
-{
-    HttpAddText("<div class='line'>\r\n");
-    HttpAddF   ("  <div>%s</div>\r\n", label);
-    HttpAddF   ("  <div><span id='%s'></span>%s</div>\r\n", id, suffix);
-    HttpAddText("</div>\r\n");
-}
-void PageAddAjaxInputLabelId(char* labelId, float inputwidth, char* id, char* name)
-{
-    HttpAddText("<div class='line'>\r\n");
-    HttpAddF   ("  <div id='%s'></div>\r\n", labelId);
-    HttpAddF   ("  <input type='text' style='width:%.1fem;' id='%s' onchange='AjaxRequest(\"%s=\" + this.value)'>\r\n", inputwidth, id, name);
-    HttpAddText("</div>\r\n");
-}
-
-
--- a/page/page.h	Sun Apr 28 09:56:42 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-#include <stdint.h>
-#include <stdbool.h>
-
-#define    FAULT_PAGE 0
-#define    CLOCK_PAGE 1
-#define      NET_PAGE 2
-#define     NET4_PAGE 3
-#define     NET6_PAGE 4
-#define    TRACE_PAGE 5
-#define      LOG_PAGE 6
-#define FIRMWARE_PAGE 7
-#define ONE_WIRE_PAGE 8
-
-extern const char* PageSite;
-extern void PageAddNav(int page);
-
-extern void PageAddHeader       (const char* site, const char* title, const char* style, const char* script);
-extern void PageAddNavItem      (int highlight, char* href, char* title);
-extern void PageAddH1           (const char* site, const char* pageName);
-extern void PageAddH2           (const char* text);
-extern void PageAddEnd          (void);
-
-extern void PageAddLabelledText        (char* label,                     char* text);
-extern void PageAddLabelledPrefixSuffix(char* label,   char* prefix,     char* text,  char* suffix);
-extern void PageAddLabelledMac         (char* label,                     char*   mac);
-extern void PageAddLabelledIp4         (char* label,                     uint32_t ip);
-extern void PageAddLabelledIp6         (char* label,                     char*    ip);
-extern void PageAddLabelledOnOff       (char* label,                     bool  value);
-extern void PageAddLabelledInt         (char* label,                     int   value);
-
-extern void PageAddInputText           (char* label,   float inputwidth, char* value, char* action, char* name);
-extern void PageAddInputInt            (char* label,   float inputwidth, int   value, char* action, char* name);
-extern void PageAddInputButton         (char* label,                     char* value, char* action, char* name);
-
-extern void PageAddAjaxLed             (char* label,                     char* id);
-extern void PageAddAjaxLabelled        (char* label,                     char* id);
-extern void PageAddAjaxLabelledSuffix  (char* label,                     char* id, char* suffix);
-extern void PageAddAjaxInputToggle     (char* label,                     char* id, char* name);
-extern void PageAddAjaxInput           (char* label,   float inputwidth, char* id, char* name);
-extern void PageAddAjaxInputSuffix     (char* label,   float inputwidth, char* id, char* name, char* suffix);
-extern void PageAddAjaxInputLabelId    (char* labelId, float inputwidth, char* id, char* name);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/page/web-nav-base.c	Mon Apr 29 14:45:30 2019 +0000
@@ -0,0 +1,14 @@
+#include "web-add.h"
+#include "web-page-base.h"
+
+void WebNavBase(int page)
+{
+    WebAddNavItem(page ==    CLOCK_PAGE, "/clock",    "Clock"    );
+    WebAddNavItem(page ==    FAULT_PAGE, "/fault",    "Fault"    );
+    WebAddNavItem(page ==      NET_PAGE, "/net",      "Net"      );
+    WebAddNavItem(page ==     NET4_PAGE, "/net4",     "Net IPv4" );
+    WebAddNavItem(page ==     NET6_PAGE, "/net6",     "Net IPv6" );
+    WebAddNavItem(page ==    TRACE_PAGE, "/trace",    "Net Trace");
+    WebAddNavItem(page ==      LOG_PAGE, "/log",      "Log"      );
+    WebAddNavItem(page == FIRMWARE_PAGE, "/firmware", "Firmware" );
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/page/web-nav-base.h	Mon Apr 29 14:45:30 2019 +0000
@@ -0,0 +1,1 @@
+extern void WebNavBase(int page);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/page/web-page-base.h	Mon Apr 29 14:45:30 2019 +0000
@@ -0,0 +1,9 @@
+#define    FAULT_PAGE 0
+#define    CLOCK_PAGE 1
+#define      NET_PAGE 2
+#define     NET4_PAGE 3
+#define     NET6_PAGE 4
+#define    TRACE_PAGE 5
+#define      LOG_PAGE 6
+#define FIRMWARE_PAGE 7
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web-add.c	Mon Apr 29 14:45:30 2019 +0000
@@ -0,0 +1,215 @@
+#include <stdio.h>
+
+#include "http.h"
+#include "web-nav-base.h"
+#include "web-nav-derived.h"
+#include "web-site-name.h"
+#include "mac.h"
+#include "ip4addr.h"
+#include "ip6addr.h"
+
+void WebAddNavItem(int highlight, char* href, char* title)
+{
+    char *p;
+    HttpAddText("<li ");
+    if (highlight) p = "class='this'";
+    else           p = "            ";
+    HttpAddText(p);
+    HttpAddText("><a href='");
+    HttpAddText(href);
+    HttpAddText("'>");
+    HttpAddText(title);
+    HttpAddText("</a></li>\r\n");
+}
+void WebAddNav(int page)
+{
+    HttpAddText("<a class='tab-shortcut' href='#main-content'>Skip to content</a>\r\n");
+
+    HttpAddText("<nav><ul>\r\n");
+    WebNavDerived(page);
+    WebNavBase(page);
+    HttpAddText("</ul></nav>\r\n");
+}
+
+void WebAddHeader(const char* title, const char* style, const char* script)
+{
+    HttpAddText("<!DOCTYPE html>\r\n"
+                     "<html>\r\n"
+                     "<head>\r\n");
+    HttpAddText("   <title>");
+    HttpAddText(WEB_SITE_NAME);
+    if (title)
+    {
+        HttpAddText(" - ");
+        HttpAddText(title);
+    }
+    HttpAddText("</title>\r\n");
+
+    HttpAddText("   <link rel='stylesheet' href='/base.css' type='text/css'/>\r\n");
+    if (style)
+    {
+        HttpAddText("   <link rel='stylesheet' href='/");
+        HttpAddText(style);
+        HttpAddText("' type='text/css'/>\r\n");
+    }
+    if (script)
+    {
+        HttpAddText("   <script src='/");
+        HttpAddText(script);
+        HttpAddText("' type='text/javascript'></script>\r\n");
+    }
+    HttpAddText("   <meta name='viewport' content='width=device-width, initial-scale=1'>\r\n"
+                     "   <link rel='icon'       href='/favicon.ico' type='image/x-icon'/>\r\n"
+                     "</head>\r\n"
+                     "<body>\r\n");
+
+}
+void WebAddH1(const char* pageName)
+{
+    HttpAddText("<h1 id='main-content'>");
+    HttpAddText(WEB_SITE_NAME);
+    HttpAddText(" - ");
+    HttpAddText(pageName);
+    HttpAddText("</h1>\r\n");
+}
+void WebAddH2(const char* text)
+{
+    HttpAddText("<h2>");
+    HttpAddText(text);
+    HttpAddText("</h2>\r\n");
+}
+void WebAddEnd()
+{
+    HttpAddText("</body>\r\n"
+                "</html>\r\n");
+}
+
+void WebAddLabelledPrefixSuffix(char* label, char* prefix, char* text, char* suffix)
+{
+    HttpAddText("<div class='line'>\r\n");
+    HttpAddF   ("  <div>%s</div>\r\n", label);
+    HttpAddF   ("  <div>%s%s%s</div>\r\n", prefix, text, suffix);
+    HttpAddText("</div>\r\n");
+}
+void WebAddLabelledText(char* label, char* text)
+{
+    HttpAddText("<div class='line'>\r\n");
+    HttpAddF   ("  <div>%s</div>\r\n", label);
+    HttpAddF   ("  <div>%s</div>\r\n", text);
+    HttpAddText("</div>\r\n");
+}
+
+void WebAddLabelledMac(char* label, char* mac)
+{
+    HttpAddText("<div class='line'>\r\n");
+    HttpAddF   ("  <div>%s</div>\r\n", label);
+    HttpAddText("  <div>"); MacHttp(mac); HttpAddText("</div>\r\n");
+    HttpAddText("</div>\r\n");
+}
+
+void WebAddLabelledIp4(char* label, uint32_t ip)
+{
+    HttpAddText("<div class='line'>\r\n");
+    HttpAddF   ("  <div>%s</div>\r\n", label);
+    HttpAddText("  <div>"); Ip4AddressHttp(ip); HttpAddText("</div>\r\n");
+    HttpAddText("</div>\r\n");
+}
+
+void WebAddLabelledIp6(char* label, char* ip)
+{
+    HttpAddText("<div class='line'>\r\n");
+    HttpAddF   ("  <div>%s</div>\r\n", label);
+    HttpAddText("  <div>"); Ip6AddressHttp(ip); HttpAddText("</div>\r\n");
+    HttpAddText("</div>\r\n");
+}
+void WebAddLabelledOnOff(char* label, bool value)
+{
+    if (value) WebAddLabelledText(label, "On");
+    else       WebAddLabelledText(label, "Off");
+}
+void WebAddLabelledInt(char* label, int value)
+{
+    char text[30];
+    snprintf(text, sizeof(text), "%8d", value); //Right align with enough spaces so that the length is always constant. 
+    WebAddLabelledText(label, text);
+}
+void WebAddInputText(char* label, float inputwidth, char* value, char* action, char* name)
+{
+    HttpAddF   ("<form action='%s' method='get'>\r\n", action);
+    HttpAddText("<div class='line'>\r\n");
+    HttpAddF   ("  <div>%s</div>\r\n", label);
+    HttpAddF   ("  <input type='text' name='%s' style='width:%.1fem;' value='%s'>\r\n", name, inputwidth, value);
+    HttpAddText("</div>\r\n");
+    HttpAddText("<input type='submit' value='Set' style='display:none;'>\r\n");
+    HttpAddF   ("</form>\r\n");
+
+}
+void WebAddInputInt(char* label, float inputwidth, int value, char* action, char* name)
+{    
+    char text[30];
+    snprintf(text, sizeof(text), "%d", value);
+    WebAddInputText(label, inputwidth, text, action, name);
+}
+void WebAddInputButton(char* label, char* value, char* action, char* name)
+{
+    HttpAddF   ("<form action='%s' method='get'>\r\n", action);
+    HttpAddF   ("<input type='hidden' name='%s'>\r\n", name);
+    HttpAddText("<div class='line'>\r\n");
+    HttpAddF   ("  <div>%s</div>\r\n", label);
+    HttpAddF   ("  <input type='submit' value='%s'>\r\n", value);
+    HttpAddText("</div>\r\n");
+    HttpAddText("</form>\r\n");
+}
+void WebAddAjaxInputToggle(char* label, char* id, char* name)
+{
+    HttpAddText("<div class='line'>\r\n");
+    HttpAddF   ("  <div>%s</div>\r\n", label);
+    HttpAddF   ("  <div class='toggle' id='%s' tabindex='0' dir='ltr' onclick='AjaxRequest(\"%s=1\")' onkeydown='return event.keyCode != 13 || AjaxRequest(\"%s=1\")'>\r\n", id, name, name);
+    HttpAddText("    <div class='slot'></div><div class='knob'></div>\r\n");
+    HttpAddText("  </div>\r\n");
+    HttpAddText("</div>\r\n");
+}
+void WebAddAjaxLed(char* label, char* id)
+{
+    HttpAddText("<div class='line'>\r\n");
+    HttpAddF   ("  <div>%s</div>\r\n", label);
+    HttpAddF   ("  <div class='led' id='%s' dir='ltr'></div>\r\n", id);
+    HttpAddText("</div>\r\n");
+}
+void WebAddAjaxInput(char* label, float inputwidth, char* id, char* name)
+{
+    HttpAddText("<div class='line'>\r\n");
+    HttpAddF   ("  <div>%s</div>\r\n", label);
+    HttpAddF   ("  <input type='text' style='width:%.1fem;' id='%s' onchange='AjaxRequest(\"%s=\" + this.value)'>\r\n", inputwidth, id, name);
+    HttpAddText("</div>\r\n");
+}
+void WebAddAjaxInputSuffix(char* label, float inputwidth, char* id, char* name, char* suffix)
+{
+    HttpAddText("<div class='line'>\r\n");
+    HttpAddF   ("  <div>%s</div>\r\n", label);
+    HttpAddF   ("  <input type='text' style='width:%.1fem;' id='%s' onchange='AjaxRequest(\"%s=\" + this.value)'>%s\r\n", inputwidth, id, name, suffix);
+    HttpAddText("</div>\r\n");
+}
+void WebAddAjaxLabelled(char* label, char* id)
+{
+    HttpAddText("<div class='line'>\r\n");
+    HttpAddF   ("  <div>%s</div>\r\n", label);
+    HttpAddF   ("  <div id='%s'></div>\r\n", id);
+    HttpAddText("</div>\r\n");
+}
+void WebAddAjaxLabelledSuffix(char* label, char* id, char* suffix)
+{
+    HttpAddText("<div class='line'>\r\n");
+    HttpAddF   ("  <div>%s</div>\r\n", label);
+    HttpAddF   ("  <div><span id='%s'></span>%s</div>\r\n", id, suffix);
+    HttpAddText("</div>\r\n");
+}
+void WebAddAjaxInputLabelId(char* labelId, float inputwidth, char* id, char* name)
+{
+    HttpAddText("<div class='line'>\r\n");
+    HttpAddF   ("  <div id='%s'></div>\r\n", labelId);
+    HttpAddF   ("  <input type='text' style='width:%.1fem;' id='%s' onchange='AjaxRequest(\"%s=\" + this.value)'>\r\n", inputwidth, id, name);
+    HttpAddText("</div>\r\n");
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web-add.h	Mon Apr 29 14:45:30 2019 +0000
@@ -0,0 +1,29 @@
+#include <stdint.h>
+#include <stdbool.h>
+
+extern void WebAddNavItem      (int highlight, char* href, char* title);
+extern void WebAddNav          (int page);
+extern void WebAddHeader       (const char* title, const char* style, const char* script);
+extern void WebAddH1           (const char* pageName);
+extern void WebAddH2           (const char* text);
+extern void WebAddEnd          (void);
+
+extern void WebAddLabelledText        (char* label,                     char* text);
+extern void WebAddLabelledPrefixSuffix(char* label,   char* prefix,     char* text,  char* suffix);
+extern void WebAddLabelledMac         (char* label,                     char*   mac);
+extern void WebAddLabelledIp4         (char* label,                     uint32_t ip);
+extern void WebAddLabelledIp6         (char* label,                     char*    ip);
+extern void WebAddLabelledOnOff       (char* label,                     bool  value);
+extern void WebAddLabelledInt         (char* label,                     int   value);
+
+extern void WebAddInputText           (char* label,   float inputwidth, char* value, char* action, char* name);
+extern void WebAddInputInt            (char* label,   float inputwidth, int   value, char* action, char* name);
+extern void WebAddInputButton         (char* label,                     char* value, char* action, char* name);
+
+extern void WebAddAjaxLed             (char* label,                     char* id);
+extern void WebAddAjaxLabelled        (char* label,                     char* id);
+extern void WebAddAjaxLabelledSuffix  (char* label,                     char* id, char* suffix);
+extern void WebAddAjaxInputToggle     (char* label,                     char* id, char* name);
+extern void WebAddAjaxInput           (char* label,   float inputwidth, char* id, char* name);
+extern void WebAddAjaxInputSuffix     (char* label,   float inputwidth, char* id, char* name, char* suffix);
+extern void WebAddAjaxInputLabelId    (char* labelId, float inputwidth, char* id, char* name);
--- a/web-base.c	Sun Apr 28 09:56:42 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-#include "web-base.h"
-#include "web-derived.h"
-#include "http.h"
-#include "fault.h"
-#include "led.h"
-#include "mstimer.h"
-
-#define DO_LOGIN            DO_SERVER  +   0
-#define DO_FAVICON          DO_SERVER  +   1
-#define DO_BASE_CSS         DO_SERVER  +   2
-#define DO_NAV_CSS          DO_SERVER  +   3
-#define DO_TRACE_HTML       DO_SERVER  +   4
-#define DO_TRACE_AJAX       DO_SERVER  +   5
-#define DO_TRACE_SCRIPT     DO_SERVER  +   6
-#define DO_CLOCK_HTML       DO_SERVER  +   7
-#define DO_CLOCK_AJAX       DO_SERVER  +   8
-#define DO_CLOCK_SCRIPT     DO_SERVER  +   9
-#define DO_NET_HTML         DO_SERVER  +  10
-#define DO_NET4_HTML        DO_SERVER  +  11
-#define DO_NET4_AJAX        DO_SERVER  +  12
-#define DO_NET4_SCRIPT      DO_SERVER  +  13
-#define DO_NET6_HTML        DO_SERVER  +  14
-#define DO_NET6_AJAX        DO_SERVER  +  15
-#define DO_NET6_SCRIPT      DO_SERVER  +  16
-#define DO_LOG_HTML         DO_SERVER  +  17
-#define DO_FAULT_HTML       DO_SERVER  +  18
-#define DO_FIRMWARE_HTML    DO_SERVER  +  19
-#define DO_FIRMWARE_AJAX    DO_SERVER  +  20
-#define DO_FIRMWARE_SCRIPT  DO_SERVER  +  21
-#define DO_SEND_SESSION_ID  DO_DERIVED + 100
-
-#define LOGIN_DELAY_MS 200
-
-static int decideWhatToDoFromPath(char *pPath, char* pLastModified)
-{
-    if (HttpSameStr(pPath, "/login"        )) return DO_LOGIN;
-    if (HttpSameStr(pPath, "/clock"        )) return DO_CLOCK_HTML;
-    if (HttpSameStr(pPath, "/clock-ajax"   )) return DO_CLOCK_AJAX;
-    if (HttpSameStr(pPath, "/net"          )) return DO_NET_HTML;
-    if (HttpSameStr(pPath, "/net4"         )) return DO_NET4_HTML;
-    if (HttpSameStr(pPath, "/net4-ajax"    )) return DO_NET4_AJAX;
-    if (HttpSameStr(pPath, "/net6"         )) return DO_NET6_HTML;
-    if (HttpSameStr(pPath, "/net6-ajax"    )) return DO_NET6_AJAX;
-    if (HttpSameStr(pPath, "/log"          )) return DO_LOG_HTML;
-    if (HttpSameStr(pPath, "/trace"        )) return DO_TRACE_HTML;
-    if (HttpSameStr(pPath, "/trace-ajax"   )) return DO_TRACE_AJAX;
-    if (HttpSameStr(pPath, "/fault"        )) return DO_FAULT_HTML;
-    if (HttpSameStr(pPath, "/firmware"     )) return DO_FIRMWARE_HTML;
-    if (HttpSameStr(pPath, "/firmware-ajax")) return DO_FIRMWARE_AJAX;
-
-    if (HttpSameStr(pPath, "/favicon.ico"  )) return HttpSameDate(WebFaviconDate,        WebFaviconTime,        pLastModified) ? DO_NOT_MODIFIED : DO_FAVICON;
-    if (HttpSameStr(pPath, "/base.css"     )) return HttpSameDate(WebBaseCssDate,        WebBaseCssTime,        pLastModified) ? DO_NOT_MODIFIED : DO_BASE_CSS;
-    if (HttpSameStr(pPath, "/settings.css" )) return HttpSameDate(WebNavCssDate,         WebNavCssTime,         pLastModified) ? DO_NOT_MODIFIED : DO_NAV_CSS;
-    if (HttpSameStr(pPath, "/net4.js"      )) return HttpSameDate(WebNet4ScriptDate,     WebNet4ScriptTime,     pLastModified) ? DO_NOT_MODIFIED : DO_NET4_SCRIPT;
-    if (HttpSameStr(pPath, "/net6.js"      )) return HttpSameDate(WebNet6ScriptDate,     WebNet6ScriptTime,     pLastModified) ? DO_NOT_MODIFIED : DO_NET6_SCRIPT;
-    if (HttpSameStr(pPath, "/trace.js"     )) return HttpSameDate(WebTraceScriptDate,    WebTraceScriptTime,    pLastModified) ? DO_NOT_MODIFIED : DO_TRACE_SCRIPT;
-    if (HttpSameStr(pPath, "/clock.js"     )) return HttpSameDate(WebClockScriptDate,    WebClockScriptTime,    pLastModified) ? DO_NOT_MODIFIED : DO_CLOCK_SCRIPT;
-    if (HttpSameStr(pPath, "/firmware.js"  )) return HttpSameDate(WebFirmwareScriptDate, WebFirmwareScriptTime, pLastModified) ? DO_NOT_MODIFIED : DO_FIRMWARE_SCRIPT;
-
-    return WebDerivedRequest(pPath, pLastModified);
-}
-static void handleQuery(int todo, char* pQuery)
-{
-    switch (todo)
-    {
-        case DO_LOGIN:         WebLoginQuery   (pQuery); return;
-        case DO_TRACE_AJAX:    WebTraceQuery   (pQuery); return;
-        case DO_CLOCK_AJAX:    WebClockQuery   (pQuery); return;
-        case DO_CLOCK_HTML:    WebClockQuery   (pQuery); return;
-        case DO_LOG_HTML:      WebLogQuery     (pQuery); return;
-        case DO_FAULT_HTML:    WebFaultQuery   (pQuery); return;
-        case DO_FIRMWARE_HTML: WebFirmwareQuery(pQuery); return;
-        case DO_FIRMWARE_AJAX: WebFirmwareQuery(pQuery); return;
-    }
-    WebDerivedGet(todo, pQuery);
-}
-static bool handlePost(int todo, int contentLength, int contentStart, int size, char* pRequestStream, uint32_t positionInRequestStream)
-{
-    switch (todo)
-    {
-        case DO_FIRMWARE_AJAX: return WebFirmwarePost(contentLength, contentStart, size, pRequestStream, positionInRequestStream);
-    }
-    return WebDerivedPost(todo, contentLength, size, pRequestStream, positionInRequestStream);
-}
-
-static void serverRequest(int size, char* pRequestStream, uint32_t positionInRequestStream, int* pToDo, bool* pPostComplete, uint32_t* pDelayUntil)
-{
-    //Handle request for the first packet of data received but leave todo the same after that.
-    int contentLength = 0;
-    int contentStart  = 0;
-    if (size && positionInRequestStream == 0)
-    {
-        //Read the headers
-        char* pMethod;
-        char* pPath;
-        char* pQuery;
-        char* pLastModified;
-        char* pCookies;
-        contentStart = HttpRequestRead(pRequestStream, size, &pMethod, &pPath, &pQuery, &pLastModified, &pCookies, &contentLength);
-        
-        //Ask the web server what to do
-        *pToDo = decideWhatToDoFromPath(pPath, pLastModified);
-        
-        //If what to do is NOTHING, NOT_FOUND or NOT_MODIFIED then no query or post will be valid so stop now
-        if (*pToDo < DO_SERVER) { *pPostComplete = true; return; }
-        
-        //If what to do is LOGIN then the user has just returned the login form
-        if (*pToDo == DO_LOGIN)
-        {
-            handleQuery(*pToDo, pQuery);                  //Read the password and the original location
-            if (WebLoginQueryPasswordOk)
-            {
-                if (!WebLoginSessionIdIsSet())           //If there isn't a session id already
-                {
-                    WebLoginSessionIdNew();              //Create a new session id
-                }
-                *pToDo =  WebLoginOriginalToDo;          //Load the original todo and SEND_SESSION_ID
-                *pToDo += DO_SEND_SESSION_ID;
-            }
-            *pDelayUntil = MsTimerCount + LOGIN_DELAY_MS; //To prevent brute forcing the hash delay the reply to the login
-            *pPostComplete = true;
-            return;                                       //Either way no query or post will be valid
-        }
-        
-        //Have a normal request so authenticate
-        if (!WebLoginCookiesContainValidSessionId(pCookies))
-        {
-            WebLoginOriginalToDo = *pToDo; //Record the original destination for redirection
-            *pToDo = DO_LOGIN;
-            *pPostComplete = true;
-            return; //Ignore any query or post as the user is not authenticated
-        }
-        
-        //Handle the query
-        handleQuery(*pToDo, pQuery);
-    }
-    
-    //Do the upload of anything that needs it. Todos it doesn't understand are ignored.
-    if (!*pPostComplete) *pPostComplete = handlePost(*pToDo, contentLength, contentStart, size, pRequestStream, positionInRequestStream);
-}
-
-static void serverReply(int todo)
-{
-    //Check if todo includes the need to send a cookie
-    if (todo >= DO_SEND_SESSION_ID)
-    {
-        HttpOkCookieName   = WebLoginSessionNameGet();
-        HttpOkCookieValue  = WebLoginSessionIdGet();
-        HttpOkCookieMaxAge = WebLoginSessionNameLife();
-        todo -= DO_SEND_SESSION_ID;
-    }
-    else
-    {
-        HttpOkCookieName   = NULL;
-        HttpOkCookieValue  = NULL;
-        HttpOkCookieMaxAge = -1;
-    }
-    
-    //Try all the base modules
-    switch (todo)
-    {
-        case DO_NOT_FOUND:       HttpNotFound      (); return;
-        case DO_NOT_MODIFIED:    HttpNotModified   (); return;
-        case DO_LOGIN:           WebLoginHtml     (); return;
-        case DO_FAVICON:         WebFavicon       (); return;
-        case DO_BASE_CSS:        WebBaseCss       (); return;
-        case DO_NAV_CSS:         WebNavCss        (); return;
-        case DO_TRACE_HTML:      WebTraceHtml     (); return;
-        case DO_TRACE_AJAX:      WebTraceAjax     (); return;
-        case DO_TRACE_SCRIPT:    WebTraceScript   (); return;
-        case DO_CLOCK_HTML:      WebClockHtml     (); return;
-        case DO_CLOCK_AJAX:      WebClockAjax     (); return;
-        case DO_CLOCK_SCRIPT:    WebClockScript   (); return;
-        case DO_NET_HTML:        WebNetHtml       (); return;
-        case DO_NET4_HTML:       WebNet4Html      (); return;
-        case DO_NET4_AJAX:       WebNet4Ajax      (); return;
-        case DO_NET4_SCRIPT:     WebNet4Script    (); return;
-        case DO_NET6_HTML:       WebNet6Html      (); return;
-        case DO_NET6_AJAX:       WebNet6Ajax      (); return;
-        case DO_NET6_SCRIPT:     WebNet6Script    (); return;
-        case DO_LOG_HTML:        WebLogHtml       (); return;
-        case DO_FAULT_HTML:      WebFaultHtml     (); return;
-        case DO_FIRMWARE_HTML:   WebFirmwareHtml  (); return;
-        case DO_FIRMWARE_AJAX:   WebFirmwareAjax  (); return;
-        case DO_FIRMWARE_SCRIPT: WebFirmwareScript(); return;
-    }
-    
-    //If not called then call the derived (child) module
-    WebDerivedReply(todo);
-}
-
-int WebInit()
-{
-    HttpRequestFunction = serverRequest;
-    HttpReplyFunction   = serverReply;
-    
-    WebLoginInit();
-    
-    return 0;
-}
--- a/web-base.h	Sun Apr 28 09:56:42 2019 +0000
+++ b/web-base.h	Mon Apr 29 14:45:30 2019 +0000
@@ -69,11 +69,3 @@
 extern char*       WebFirmwareFileName;
 extern bool        WebFirmwarePost  (int contentLength, int contentStart, int size, char* pRequestStream, uint32_t positionInRequestStream);
 extern void        WebFirmwareAjax  (void);
-
-extern int  WebInit(void);
-
-#define DO_NOTHING         0
-#define DO_NOT_FOUND       1
-#define DO_NOT_MODIFIED    2
-#define DO_SERVER          3
-#define DO_DERIVED       100
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web-server-base.c	Mon Apr 29 14:45:30 2019 +0000
@@ -0,0 +1,116 @@
+#include "web-base.h"
+#include "web-server-derived.h"
+#include "web-server-base.h"
+#include "http.h"
+#include "fault.h"
+#include "led.h"
+
+#define DO_FAVICON         DO_BASE +  0
+#define DO_BASE_CSS        DO_BASE +  1
+#define DO_NAV_CSS         DO_BASE +  2
+#define DO_TRACE_HTML      DO_BASE +  3
+#define DO_TRACE_AJAX      DO_BASE +  4
+#define DO_TRACE_SCRIPT    DO_BASE +  5
+#define DO_CLOCK_HTML      DO_BASE +  6
+#define DO_CLOCK_AJAX      DO_BASE +  7
+#define DO_CLOCK_SCRIPT    DO_BASE +  8
+#define DO_NET_HTML        DO_BASE +  9
+#define DO_NET4_HTML       DO_BASE + 10
+#define DO_NET4_AJAX       DO_BASE + 11
+#define DO_NET4_SCRIPT     DO_BASE + 12
+#define DO_NET6_HTML       DO_BASE + 13
+#define DO_NET6_AJAX       DO_BASE + 14
+#define DO_NET6_SCRIPT     DO_BASE + 15
+#define DO_LOG_HTML        DO_BASE + 16
+#define DO_FAULT_HTML      DO_BASE + 17
+#define DO_FIRMWARE_HTML   DO_BASE + 18
+#define DO_FIRMWARE_AJAX   DO_BASE + 19
+#define DO_FIRMWARE_SCRIPT DO_BASE + 20
+
+int WebServerBaseDecideWhatToDo(char *pPath, char* pLastModified)
+{
+    if (HttpSameStr(pPath, "/login"        )) return DO_LOGIN;
+    if (HttpSameStr(pPath, "/clock"        )) return DO_CLOCK_HTML;
+    if (HttpSameStr(pPath, "/clock-ajax"   )) return DO_CLOCK_AJAX;
+    if (HttpSameStr(pPath, "/net"          )) return DO_NET_HTML;
+    if (HttpSameStr(pPath, "/net4"         )) return DO_NET4_HTML;
+    if (HttpSameStr(pPath, "/net4-ajax"    )) return DO_NET4_AJAX;
+    if (HttpSameStr(pPath, "/net6"         )) return DO_NET6_HTML;
+    if (HttpSameStr(pPath, "/net6-ajax"    )) return DO_NET6_AJAX;
+    if (HttpSameStr(pPath, "/log"          )) return DO_LOG_HTML;
+    if (HttpSameStr(pPath, "/trace"        )) return DO_TRACE_HTML;
+    if (HttpSameStr(pPath, "/trace-ajax"   )) return DO_TRACE_AJAX;
+    if (HttpSameStr(pPath, "/fault"        )) return DO_FAULT_HTML;
+    if (HttpSameStr(pPath, "/firmware"     )) return DO_FIRMWARE_HTML;
+    if (HttpSameStr(pPath, "/firmware-ajax")) return DO_FIRMWARE_AJAX;
+
+    if (HttpSameStr(pPath, "/favicon.ico"  )) return HttpSameDate(WebFaviconDate,        WebFaviconTime,        pLastModified) ? DO_NOT_MODIFIED : DO_FAVICON;
+    if (HttpSameStr(pPath, "/base.css"     )) return HttpSameDate(WebBaseCssDate,        WebBaseCssTime,        pLastModified) ? DO_NOT_MODIFIED : DO_BASE_CSS;
+    if (HttpSameStr(pPath, "/settings.css" )) return HttpSameDate(WebNavCssDate,         WebNavCssTime,         pLastModified) ? DO_NOT_MODIFIED : DO_NAV_CSS;
+    if (HttpSameStr(pPath, "/net4.js"      )) return HttpSameDate(WebNet4ScriptDate,     WebNet4ScriptTime,     pLastModified) ? DO_NOT_MODIFIED : DO_NET4_SCRIPT;
+    if (HttpSameStr(pPath, "/net6.js"      )) return HttpSameDate(WebNet6ScriptDate,     WebNet6ScriptTime,     pLastModified) ? DO_NOT_MODIFIED : DO_NET6_SCRIPT;
+    if (HttpSameStr(pPath, "/trace.js"     )) return HttpSameDate(WebTraceScriptDate,    WebTraceScriptTime,    pLastModified) ? DO_NOT_MODIFIED : DO_TRACE_SCRIPT;
+    if (HttpSameStr(pPath, "/clock.js"     )) return HttpSameDate(WebClockScriptDate,    WebClockScriptTime,    pLastModified) ? DO_NOT_MODIFIED : DO_CLOCK_SCRIPT;
+    if (HttpSameStr(pPath, "/firmware.js"  )) return HttpSameDate(WebFirmwareScriptDate, WebFirmwareScriptTime, pLastModified) ? DO_NOT_MODIFIED : DO_FIRMWARE_SCRIPT;
+
+    return WebServerDerivedRequest(pPath, pLastModified);
+}
+void WebServerBaseHandleQuery(int todo, char* pQuery)
+{
+    switch (todo)
+    {
+        case DO_LOGIN:         WebLoginQuery   (pQuery); return;
+        case DO_TRACE_AJAX:    WebTraceQuery   (pQuery); return;
+        case DO_CLOCK_AJAX:    WebClockQuery   (pQuery); return;
+        case DO_CLOCK_HTML:    WebClockQuery   (pQuery); return;
+        case DO_LOG_HTML:      WebLogQuery     (pQuery); return;
+        case DO_FAULT_HTML:    WebFaultQuery   (pQuery); return;
+        case DO_FIRMWARE_HTML: WebFirmwareQuery(pQuery); return;
+        case DO_FIRMWARE_AJAX: WebFirmwareQuery(pQuery); return;
+    }
+    WebServerDerivedGet(todo, pQuery);
+}
+bool WebServerBaseHandlePost(int todo, int contentLength, int contentStart, int size, char* pRequestStream, uint32_t positionInRequestStream)
+{
+    switch (todo)
+    {
+        case DO_FIRMWARE_AJAX: return WebFirmwarePost(contentLength, contentStart, size, pRequestStream, positionInRequestStream);
+    }
+    return WebServerDerivedPost(todo, contentLength, size, pRequestStream, positionInRequestStream);
+}
+
+void WebServerBaseReply(int todo)
+{
+    //Try all the base modules
+    switch (todo)
+    {
+        case DO_NOT_FOUND:       HttpNotFound     (); return;
+        case DO_NOT_MODIFIED:    HttpNotModified  (); return;
+        case DO_LOGIN:           WebLoginHtml     (); return;
+        case DO_FAVICON:         WebFavicon       (); return;
+        case DO_BASE_CSS:        WebBaseCss       (); return;
+        case DO_NAV_CSS:         WebNavCss        (); return;
+        case DO_TRACE_HTML:      WebTraceHtml     (); return;
+        case DO_TRACE_AJAX:      WebTraceAjax     (); return;
+        case DO_TRACE_SCRIPT:    WebTraceScript   (); return;
+        case DO_CLOCK_HTML:      WebClockHtml     (); return;
+        case DO_CLOCK_AJAX:      WebClockAjax     (); return;
+        case DO_CLOCK_SCRIPT:    WebClockScript   (); return;
+        case DO_NET_HTML:        WebNetHtml       (); return;
+        case DO_NET4_HTML:       WebNet4Html      (); return;
+        case DO_NET4_AJAX:       WebNet4Ajax      (); return;
+        case DO_NET4_SCRIPT:     WebNet4Script    (); return;
+        case DO_NET6_HTML:       WebNet6Html      (); return;
+        case DO_NET6_AJAX:       WebNet6Ajax      (); return;
+        case DO_NET6_SCRIPT:     WebNet6Script    (); return;
+        case DO_LOG_HTML:        WebLogHtml       (); return;
+        case DO_FAULT_HTML:      WebFaultHtml     (); return;
+        case DO_FIRMWARE_HTML:   WebFirmwareHtml  (); return;
+        case DO_FIRMWARE_AJAX:   WebFirmwareAjax  (); return;
+        case DO_FIRMWARE_SCRIPT: WebFirmwareScript(); return;
+    }
+    
+    //If not called then call the derived (child) module
+    WebServerDerivedReply(todo);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web-server-base.h	Mon Apr 29 14:45:30 2019 +0000
@@ -0,0 +1,13 @@
+extern int  WebServerBaseDecideWhatToDo(char *pPath, char* pLastModified);
+extern void WebServerBaseHandleQuery(int todo, char* pQuery);
+extern bool WebServerBaseHandlePost(int todo, int contentLength, int contentStart, int size, char* pRequestStream, uint32_t positionInRequestStream);
+
+extern void WebServerBaseReply(int todo);
+
+#define DO_NOTHING           0
+#define DO_NOT_FOUND         1
+#define DO_NOT_MODIFIED      2
+#define DO_LOGIN             3
+#define DO_BASE            100
+#define DO_DERIVED         200
+#define DO_SEND_SESSION_ID 300
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web.c	Mon Apr 29 14:45:30 2019 +0000
@@ -0,0 +1,92 @@
+#include "http.h"
+#include "web-server-base.h"
+#include "web-base.h"
+#include "mstimer.h"
+
+#define LOGIN_DELAY_MS 200
+
+static void handleRequest(int size, char* pRequestStream, uint32_t positionInRequestStream, int* pToDo, bool* pPostComplete, uint32_t* pDelayUntil)
+{
+    //Handle request for the first packet of data received but leave todo the same after that.
+    int contentLength = 0;
+    int contentStart  = 0;
+    if (size && positionInRequestStream == 0)
+    {
+        //Read the headers
+        char* pMethod;
+        char* pPath;
+        char* pQuery;
+        char* pLastModified;
+        char* pCookies;
+        contentStart = HttpRequestRead(pRequestStream, size, &pMethod, &pPath, &pQuery, &pLastModified, &pCookies, &contentLength);
+        
+        //Ask the web server what to do
+        *pToDo = WebServerBaseDecideWhatToDo(pPath, pLastModified);
+        
+        //If what to do is NOTHING, NOT_FOUND or NOT_MODIFIED then no query or post will be valid so stop now
+        if (*pToDo < DO_LOGIN) { *pPostComplete = true; return; }
+        
+        //If what to do is LOGIN then the user has just returned the login form
+        if (*pToDo == DO_LOGIN)
+        {
+            WebServerBaseHandleQuery(*pToDo, pQuery);                  //Read the password and the original location
+            if (WebLoginQueryPasswordOk)
+            {
+                if (!WebLoginSessionIdIsSet())           //If there isn't a session id already
+                {
+                    WebLoginSessionIdNew();              //Create a new session id
+                }
+                *pToDo =  WebLoginOriginalToDo;          //Load the original todo and SEND_SESSION_ID
+                *pToDo += DO_SEND_SESSION_ID;
+            }
+            *pDelayUntil = MsTimerCount + LOGIN_DELAY_MS; //To prevent brute forcing the hash delay the reply to the login
+            *pPostComplete = true;
+            return;                                       //Either way no query or post will be valid
+        }
+        
+        //Have a normal request so authenticate
+        if (!WebLoginCookiesContainValidSessionId(pCookies))
+        {
+            WebLoginOriginalToDo = *pToDo; //Record the original destination for redirection
+            *pToDo = DO_LOGIN;
+            *pPostComplete = true;
+            return; //Ignore any query or post as the user is not authenticated
+        }
+        
+        //Handle the query
+        WebServerBaseHandleQuery(*pToDo, pQuery);
+    }
+    
+    //Do the upload of anything that needs it. Todos it doesn't understand are ignored.
+    if (!*pPostComplete) *pPostComplete = WebServerBaseHandlePost(*pToDo, contentLength, contentStart, size, pRequestStream, positionInRequestStream);
+}
+
+static void sendReply(int todo)
+{
+    //Check if todo includes the need to send a cookie
+    if (todo >= DO_SEND_SESSION_ID)
+    {
+        HttpOkCookieName   = WebLoginSessionNameGet();
+        HttpOkCookieValue  = WebLoginSessionIdGet();
+        HttpOkCookieMaxAge = WebLoginSessionNameLife();
+        todo -= DO_SEND_SESSION_ID;
+    }
+    else
+    {
+        HttpOkCookieName   = NULL;
+        HttpOkCookieValue  = NULL;
+        HttpOkCookieMaxAge = -1;
+    }
+    
+    WebServerBaseReply(todo);
+}
+
+int WebInit()
+{
+    HttpRequestFunction = handleRequest;
+    HttpReplyFunction   = sendReply;
+    
+    WebLoginInit();
+    
+    return 0;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web.h	Mon Apr 29 14:45:30 2019 +0000
@@ -0,0 +1,2 @@
+
+extern int  WebInit(void);