From 7bc5761b3e6093031f288d16678b8b6248e57e25 Mon Sep 17 00:00:00 2001 From: reprappro Date: Fri, 22 Feb 2013 22:03:46 +0000 Subject: [PATCH] Implemented very simple PHP for embedding stuff in control pages. --- Platform.h | 1 + SD-image/control.php | 130 +++++++++ SD-image/control.php~ | 130 +++++++++ SD-image/html404.htm | 11 + SD-image/html404.htm~ | 17 +- SD-image/logout.php | 6 + SD-image/logout.php~ | 8 + SD-image/passwd.php | 13 + SD-image/passwd.php~ | 13 + SD-image/print.php | 30 +++ SD-image/print.php~ | 30 +++ SD-image/settings.php | 30 +++ SD-image/settings.php~ | 30 +++ Webserver.h | 49 +++- Webserver.ino | 596 ++++++++++++++++++++++------------------- 15 files changed, 802 insertions(+), 292 deletions(-) create mode 100644 SD-image/control.php create mode 100644 SD-image/control.php~ create mode 100644 SD-image/html404.htm create mode 100644 SD-image/logout.php create mode 100644 SD-image/logout.php~ create mode 100644 SD-image/passwd.php create mode 100644 SD-image/passwd.php~ create mode 100644 SD-image/print.php create mode 100644 SD-image/print.php~ create mode 100644 SD-image/settings.php create mode 100644 SD-image/settings.php~ diff --git a/Platform.h b/Platform.h index b738fc8..d459147 100644 --- a/Platform.h +++ b/Platform.h @@ -37,6 +37,7 @@ Licence: GPL // Language-specific includes #include +#include // Platform-specific includes diff --git a/SD-image/control.php b/SD-image/control.php new file mode 100644 index 0000000..83ee6ab --- /dev/null +++ b/SD-image/control.php @@ -0,0 +1,130 @@ + + + + + + + +

RepRap: + +RepRapPro logo'; ?> +



+ +    Control    + +    Print    + +    Help    + + +    Settings    + +    Logout    + + +

'; ?> + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Move X Y Z
- mm+ mm
-100-10-1-0.10.1110100
+ +

Send a G Code:
+ + +

diff --git a/SD-image/control.php~ b/SD-image/control.php~ new file mode 100644 index 0000000..83ee6ab --- /dev/null +++ b/SD-image/control.php~ @@ -0,0 +1,130 @@ + + + + + + + +

RepRap: + +RepRapPro logo'; ?> +



+ +    Control    + +    Print    + +    Help    + + +    Settings    + +    Logout    + + +

'; ?> + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Move X Y Z
- mm+ mm
-100-10-1-0.10.1110100
+ +

Send a G Code:
+ + +

diff --git a/SD-image/html404.htm b/SD-image/html404.htm new file mode 100644 index 0000000..e307dfa --- /dev/null +++ b/SD-image/html404.htm @@ -0,0 +1,11 @@ + + +
+ +



RepRap Firmware

404 Error: page not found.

+ + +
+ + + diff --git a/SD-image/html404.htm~ b/SD-image/html404.htm~ index 90ab579..d9cc16a 100644 --- a/SD-image/html404.htm~ +++ b/SD-image/html404.htm~ @@ -1,18 +1,11 @@ - -404 Error - - +
+ +



404 Error: page not found.

+
-

-RepRap Web Interface -


-RepRapPro Firmware - 404 Error: page not found. -

+ -
- - diff --git a/SD-image/logout.php b/SD-image/logout.php new file mode 100644 index 0000000..5752e07 --- /dev/null +++ b/SD-image/logout.php @@ -0,0 +1,6 @@ + + + + + + diff --git a/SD-image/logout.php~ b/SD-image/logout.php~ new file mode 100644 index 0000000..cc03980 --- /dev/null +++ b/SD-image/logout.php~ @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/SD-image/passwd.php b/SD-image/passwd.php new file mode 100644 index 0000000..153b282 --- /dev/null +++ b/SD-image/passwd.php @@ -0,0 +1,13 @@ + + + + +

RepRap: + +
+ +
Password: + +

+ + diff --git a/SD-image/passwd.php~ b/SD-image/passwd.php~ new file mode 100644 index 0000000..d06dc17 --- /dev/null +++ b/SD-image/passwd.php~ @@ -0,0 +1,13 @@ + + + + +

RepRap: + +
+ +Password: + +

+ + diff --git a/SD-image/print.php b/SD-image/print.php new file mode 100644 index 0000000..4b218d1 --- /dev/null +++ b/SD-image/print.php @@ -0,0 +1,30 @@ + + + + + + + +

RepRap: + +RepRapPro logo'; ?> +



+ +    Control    + +    Print    + +    Help    + + +    Settings    + +    Logout    + + +

'; ?> + +

Print: allow user to click a file to print it, upload files, delete files. + + + diff --git a/SD-image/print.php~ b/SD-image/print.php~ new file mode 100644 index 0000000..5568bda --- /dev/null +++ b/SD-image/print.php~ @@ -0,0 +1,30 @@ + + + + + + + +

RepRap: + +RepRapPro logo'; ?> +



+ +    Control    + +    Print    + +    Help    + + +    Settings    + +    Logout    + + +

'; ?> + +

Print: allow user to click a file to print it, upload files, delete files. + + + diff --git a/SD-image/settings.php b/SD-image/settings.php new file mode 100644 index 0000000..6a76fbd --- /dev/null +++ b/SD-image/settings.php @@ -0,0 +1,30 @@ + + + + + + + +

RepRap: + +RepRapPro logo'; ?> +



+ +    Control    + +    Print    + +    Help    + + +    Settings    + +    Logout    + + +

'; ?> + +

Settings: allow user to rename machine, set password, set steps/mm etc etc and record the lot. + + + diff --git a/SD-image/settings.php~ b/SD-image/settings.php~ new file mode 100644 index 0000000..24d7092 --- /dev/null +++ b/SD-image/settings.php~ @@ -0,0 +1,30 @@ + + + + + + + +

RepRap: + +RepRapPro logo'; ?> +



+ +    Control    + +    Print    + +    Help    + + +    Settings    + +    Logout    + + +

'; ?> + +

Settings: allow user to rename machine, set password, set steps/mm etc etc and record the lot. + + + diff --git a/Webserver.h b/Webserver.h index 52f44ef..5874550 100644 --- a/Webserver.h +++ b/Webserver.h @@ -7,6 +7,15 @@ RepRap machine. It interprests returned values from those pages and uses them t which it sends to the RepRap. It also collects values from the RepRap like temperature and uses those to construct the web pages. +It implements very very restricted PHP. It can do: + + + + + +Note that by printing a function that returns "" you can just call +that function in this C++ code with no effect on the loaded web page. + ----------------------------------------------------------------------------------------------------- Version 0.1 @@ -26,8 +35,13 @@ Licence: GPL #define CLIENT_CLOSE_DELAY 1000 // Microseconds to wait after serving a page -#define PASSWORD_PAGE "passwd.htm" +#define PASSWORD_PAGE "passwd.php" #define STRING_LENGTH 1000 +#define PHP_TAG_LENGTH 200 +#define PHP_IF 1 +#define PHP_ECHO 2 +#define PHP_PRINT 3 +#define NO_PHP 99 class Webserver { @@ -49,22 +63,21 @@ class Webserver void ParseQualifier(); void CheckPassword(); boolean LoadGcodeBuffer(char* gc, boolean convertWeb); - boolean InternalFile(char* nameOfFileToSend); - void InternalHead(boolean sendTab, int noLink, char* headString); - void InternalTail(); void CloseClient(); - void SendControlPage(); - void SendPrintPage(); - void SendHelpPage(); - void SendSettingsPage(); - void SendLogoutPage(); - void SendPasswordPage(); - void Send404Page(); + void initialisePHP(); + char PHPParse(char* phpString); + boolean printHeadString(); + boolean printLinkTable(); + boolean callPHPBoolean(char* phpRecord); + char* callPHPString(char* phpRecord); + void ProcessPHPByte(char b); + void WritePHPByte(); Platform* platform; unsigned long lastTime; int fileBeingSent; boolean writing; + boolean inPHPFile; boolean clientLineIsBlank; unsigned long clientCloseTime; boolean needToCloseClient; @@ -78,6 +91,20 @@ class Webserver boolean gotPassword; char* password; char* myName; + char phpTag[PHP_TAG_LENGTH]; + char phpRecord[PHP_TAG_LENGTH]; + int inPHPString; + int phpPointer; + boolean phpEchoing; + boolean phpIfing; + boolean phpPrinting; + boolean eatInput; + boolean recordInput; + boolean ifWasTrue; + boolean sendTable; + char eatInputChar; + int phpRecordPointer; + boolean ifwasTrue; }; diff --git a/Webserver.ino b/Webserver.ino index 8d4ec2b..2e84e2e 100644 --- a/Webserver.ino +++ b/Webserver.ino @@ -7,6 +7,16 @@ RepRap machine. It interprests returned values from those pages and uses them t which it sends to the RepRap. It also collects values from the RepRap like temperature and uses those to construct the web pages. +It implements very very restricted PHP. It can do: + + + + + +Note that by printing a function that returns "" you can just call +that function in this C++ code with no effect on the loaded web page. + + ----------------------------------------------------------------------------------------------------- Version 0.1 @@ -29,6 +39,8 @@ Webserver::Webserver(Platform* p) platform = p; lastTime = platform->time(); writing = false; + inPHPFile = false; + initialisePHP(); clientLineIsBlank = true; needToCloseClient = false; clientLinePointer = 0; @@ -39,6 +51,8 @@ Webserver::Webserver(Platform* p) gotPassword = false; gcodeAvailable = false; gcodePointer = 0; + sendTable = true; + phpRecordPointer = 0; } boolean Webserver::Available() @@ -81,22 +95,19 @@ boolean Webserver::LoadGcodeBuffer(char* gc, boolean convertWeb) { if(c == '+' && convertWeb) c = ' '; - if(c == '%'&& convertWeb) // FIXME - just convert the next two hex bytes to a char + if(c == '%'&& convertWeb) { - if(StringStartsWith(&gc[gcp], "2B")) - c = '+'; - else if(StringStartsWith(&gc[gcp], "20")) - c = ' '; - else if(StringStartsWith(&gc[gcp], "0A")) - c = '\n'; + c = 0; + if(isalpha(gc[gcp])) + c += 16*(gc[gcp] - 'A' + 10); else - { - platform->Message(HOST_MESSAGE, "Webserver: Dud web-form byte: "); - platform->Message(HOST_MESSAGE, gc); - platform->Message(HOST_MESSAGE, "\n"); - } - gcp += 2; - + c += 16*(gc[gcp] - '0'); + gcp++; + if(isalpha(gc[gcp])) + c += gc[gcp] - 'A' + 10; + else + c += gc[gcp] - '0'; + gcp++; } gcodeBuffer[gcodePointer++] = c; } @@ -104,7 +115,6 @@ boolean Webserver::LoadGcodeBuffer(char* gc, boolean convertWeb) gcodeBuffer[gcodePointer] = 0; gcodePointer = 0; gcodeAvailable = true; - return true; } @@ -132,262 +142,24 @@ boolean Webserver::StringStartsWith(char* string, char* starting) return true; } - -void Webserver::InternalHead(boolean sendTab, int noLink, char* headString) -{ - platform->SendToClient(""); - if(headString) - platform->SendToClient(headString); - platform->SendToClient("

RepRap: "); - platform->SendToClient(myName); - if(gotPassword) - platform->SendToClient("         \"RepRapPro"); - platform->SendToClient("



"); - if(sendTab) - { - platform->SendToClient(""); // border=\"1\" - - if(noLink == 0) - platform->SendToClient(""); - else - platform->SendToClient(""); - - if(noLink == 1) - platform->SendToClient(""); - else - platform->SendToClient(""); - - platform->SendToClient(""); - - if(noLink == 3) - platform->SendToClient(""); - else - platform->SendToClient(""); - - platform->SendToClient(""); - - platform->SendToClient("
   Control      Control      Print      Print      Help      Settings      Settings      Logout   
"); - } - platform->SendToClient("

"); -} - void Webserver::CloseClient() { writing = false; + inPHPFile = false; + initialisePHP(); clientCloseTime = platform->time(); needToCloseClient = true; } -void Webserver::InternalTail() -{ - platform->SendToClient("

\n"); - CloseClient(); -} - -void Webserver::SendControlPage() -{ - InternalHead(true, 0, ""); - - platform->SendToClient("
"); - - - platform->SendToClient("
"); - platform->SendToClient(""); - platform->SendToClient(""); - - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - platform->SendToClient(""); - - platform->SendToClient("
Move X Y Z
- mm+ mm
-100-10-1-0.10.1110100
"); - - platform->SendToClient("

Send a G Code:
\n"); - - platform->SendToClient(""); - InternalTail(); -} - -void Webserver::SendPrintPage() -{ - InternalHead(true, 1, 0); - platform->SendToClient("Print Page - List files in a table: click one to print it; upload a file; delete a file\n"); - InternalTail(); -} - -void Webserver::SendHelpPage() -{ - InternalHead(true, 2, 0); - platform->SendToClient("Help Page"); - InternalTail(); -} - -void Webserver::SendSettingsPage() -{ - InternalHead(true, 3, 0); - platform->SendToClient("Settings Page - Change things and save the result: machine name, password, e steps/mm etc etc"); - InternalTail(); -} - -void Webserver::SendLogoutPage() -{ - gotPassword = false; - SendPasswordPage(); -} - -void Webserver::SendPasswordPage() -{ - InternalHead(false, -1, 0); - platform->SendToClient("
Password: "); - InternalTail(); -} - -void Webserver::Send404Page() -{ - InternalHead(false, -1, 0); - platform->SendToClient("



404 Error: page not found.

"); - InternalTail(); -} - -boolean Webserver::InternalFile(char* nameOfFileToSend) -{ - if(StringStartsWith(nameOfFileToSend, "index.htm") || - StringStartsWith(nameOfFileToSend, "control.htm")) - { - SendControlPage(); - return true; - } - - if(StringStartsWith(nameOfFileToSend, "print.htm")) - { - SendPrintPage(); - return true; - } - - if(StringStartsWith(nameOfFileToSend, "help.htm")) - { - SendHelpPage(); - return true; - } - - if(StringStartsWith(nameOfFileToSend, "settings.htm")) - { - SendSettingsPage(); - return true; - } - - if(StringStartsWith(nameOfFileToSend, "logout.htm")) - { - SendLogoutPage(); - return true; - } - - if(StringStartsWith(nameOfFileToSend, "passwd.htm")) - { - SendPasswordPage(); - return true; - } - - if(StringStartsWith(nameOfFileToSend, "html404.htm")) - { - Send404Page(); - return true; - } - - return false; -} void Webserver::SendFile(char* nameOfFileToSend) { if(!gotPassword) + { + sendTable = false; nameOfFileToSend = PASSWORD_PAGE; + } else + sendTable = true; platform->SendToClient("HTTP/1.1 200 OK\n"); @@ -406,8 +178,8 @@ void Webserver::SendFile(char* nameOfFileToSend) platform->SendToClient('\n'); - if(InternalFile(nameOfFileToSend)) - return; +// if(InternalFile(nameOfFileToSend)) +// return; //Serial.print("File requested: "); //Serial.println(nameOfFileToSend); @@ -415,10 +187,14 @@ void Webserver::SendFile(char* nameOfFileToSend) fileBeingSent = platform->OpenFile(nameOfFileToSend, false); if(fileBeingSent < 0) { - InternalFile("html404.htm"); - return; + sendTable = false; + nameOfFileToSend = "html404.htm"; + fileBeingSent = platform->OpenFile(nameOfFileToSend, false); } - + + inPHPFile = StringEndsWith(nameOfFileToSend, ".php"); + if(inPHPFile) + initialisePHP(); writing = true; } @@ -435,6 +211,277 @@ void Webserver::WriteByte() } +void Webserver::initialisePHP() +{ + phpTag[0] = 0; + inPHPString = 0; + phpPointer = 0; + phpEchoing = false; + phpIfing = false; + phpPrinting = false; + eatInput = false; + recordInput = false; + phpRecordPointer = 0; + phpRecord[phpRecordPointer] = 0; + ifWasTrue = true; +} + +char Webserver::PHPParse(char* phpString) +{ + if(!strcmp(phpString, "if(")) + return PHP_IF; + + if(!strcmp(phpString, "echo")) + return PHP_ECHO; + + if(!strcmp(phpString, "print(")) + return PHP_PRINT; + + return NO_PHP; +} + + +boolean Webserver::printLinkTable() { boolean r = sendTable; sendTable = true; return r; } + +boolean Webserver::callPHPBoolean(char* phpRecord) +{ + if(!strcmp(phpRecord, "gotPassword(")) + return gotPassword; + + if(!strcmp(phpRecord, "printLinkTable(")) + return printLinkTable(); + + platform->Message(HOST_MESSAGE, "callPHPBoolean(): non-existent function - "); + platform->Message(HOST_MESSAGE, phpRecord); + platform->Message(HOST_MESSAGE, "\n"); + + return true; // Best default +} + +char* Webserver::callPHPString(char* phpRecord) +{ + if(!strcmp(phpRecord, "getMyName(")) + return myName; + + if(!strcmp(phpRecord, "logout(")) + { + gotPassword = false; + return ""; + } + + platform->Message(HOST_MESSAGE, "callPHPString(): non-existent function - "); + platform->Message(HOST_MESSAGE, phpRecord); + platform->Message(HOST_MESSAGE, "\n"); + + return ""; +} + +void Webserver::ProcessPHPByte(char b) +{ + if(eatInput) + { + if(b == eatInputChar) + eatInput = false; + return; + } + + if(recordInput) + { + if(b == eatInputChar) + { + recordInput = false; + phpRecordPointer = 0; + return; + } + + phpRecord[phpRecordPointer++] = b; + if(phpRecordPointer >= PHP_TAG_LENGTH) + { + platform->Message(HOST_MESSAGE, "ProcessPHPByte: PHP record buffer overflow.\n"); + initialisePHP(); + } + phpRecord[phpRecordPointer] = 0; + return; + } + + if(phpEchoing) + { + if(b != '\'') + { + if(ifwasTrue) + platform->SendToClient(b); + } else + { + initialisePHP(); + eatInput = true; + eatInputChar = '>'; + } + return; + } + + if(phpIfing) + { + boolean ifWas = callPHPBoolean(phpRecord); + initialisePHP(); + ifWasTrue = ifWas; + inPHPString = 5; + if(b != ')') + { + eatInput = true; + eatInputChar = ')'; + } + return; + } + + if(phpPrinting) + { + char* thingToSend = callPHPString(phpRecord); + platform->SendToClient(thingToSend); + initialisePHP(); + eatInput = true; + eatInputChar = '>'; + return; + } + + if(inPHPString >= 5) + { + // We are in a PHP expression + + if(isspace(b)) + return; + phpTag[phpPointer++] = b; + phpTag[phpPointer] = 0; + if(phpPointer >= PHP_TAG_LENGTH) + { + platform->Message(HOST_MESSAGE, "ProcessPHPByte: PHP buffer overflow: "); + platform->Message(HOST_MESSAGE, phpTag); + platform->Message(HOST_MESSAGE, "\n"); + initialisePHP(); + return; + } + + switch(PHPParse(phpTag)) + { + case PHP_ECHO: + phpEchoing = true; + eatInput = true; + eatInputChar = '\''; + break; + + case PHP_IF: + phpIfing = true; + recordInput = true; + phpRecordPointer = 0; + phpRecord[phpRecordPointer] = 0; + eatInputChar = ')'; + break; + + case PHP_PRINT: + phpPrinting = true; + recordInput = true; + phpRecordPointer = 0; + phpRecord[phpRecordPointer] = 0; + eatInputChar = ')'; + break; + + default: + break; + } + + return; + } + + // We are not in a PHP expression + + phpTag[inPHPString] = b; + + switch(inPHPString) + { + case 0: + if(b == '<') + { + inPHPString = 1; + } else + { + phpTag[1] = 0; + inPHPString = 0; + platform->SendToClient(phpTag); + } + return; + + case 1: + if(b == '?') + { + inPHPString = 2; + } else + { + phpTag[2] = 0; + inPHPString = 0; + platform->SendToClient(phpTag); + } + return; + + case 2: + if(b == 'p') + { + inPHPString = 3; + } else + { + phpTag[3] = 0; + inPHPString = 0; + platform->SendToClient(phpTag); + } + return; + + case 3: + if(b == 'h') + { + inPHPString = 4; + } else + { + phpTag[4] = 0; + inPHPString = 0; + platform->SendToClient(phpTag); + } + return; + + case 4: + if(b == 'p') + { + inPHPString = 5; + phpTag[0] = 0; + phpPointer = 0; + } else + { + phpTag[5] = 0; + inPHPString = 0; + platform->SendToClient(phpTag); + } + return; + + // Should never get here... + + default: + platform->Message(HOST_MESSAGE, "ProcessPHPByte: PHP tag runout."); + platform->SendToClient(b); + initialisePHP(); + } +} + +void Webserver::WritePHPByte() +{ + unsigned char b; + if(platform->Read(fileBeingSent, b)) + ProcessPHPByte(b); + else + { + platform->Close(fileBeingSent); + initialisePHP(); + CloseClient(); + } +} + + /* Parse a string in clientLine[] from the user's web browser @@ -455,6 +502,9 @@ void Webserver::ParseClientLine() { if(!StringStartsWith(clientLine, "GET")) return; + + Serial.print("HTTP request: "); + Serial.println(clientLine); int i = 5; int j = 0; @@ -479,9 +529,10 @@ void Webserver::ParseClientLine() } clientQualifier[j] = 0; } + if(!clientRequest[0]) - strcpy(clientRequest, "index.htm"); + strcpy(clientRequest, "control.php"); } void Webserver::CheckPassword() @@ -490,7 +541,7 @@ void Webserver::CheckPassword() return; gotPassword = true; - strcpy(clientRequest, "index.htm"); + strcpy(clientRequest, "control.php"); } @@ -498,13 +549,17 @@ void Webserver::ParseQualifier() { if(!clientQualifier[0]) return; + if(StringStartsWith(clientQualifier, "pwd=")) CheckPassword(); + if(!gotPassword) //Doan work fur nuffink + return; + if(StringStartsWith(clientQualifier, "gcode=")) { if(!LoadGcodeBuffer(&clientQualifier[6], true)) platform->Message(HOST_MESSAGE, "Webserver: buffer not free!"); - strcpy(clientRequest, "index.htm"); // FIXME + strcpy(clientRequest, "control.php"); // FIXME } } @@ -515,7 +570,10 @@ void Webserver::spin() if(writing) { - WriteByte(); + if(inPHPFile) + WritePHPByte(); + else + WriteByte(); return; } @@ -524,7 +582,7 @@ void Webserver::spin() if (platform->ClientStatus() & AVAILABLE) { char c = platform->ClientRead(); - Serial.write(c); + //Serial.write(c); // if you've gotten to the end of the line (received a newline // character) and the line is blank, the http request has ended, // so you can send a reply