PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : html code für User Login + password (esp8266 + Arduino IDE)



HaWe
08.08.2018, 15:15
hi,
ich komme nicht weiter bei meinem Versuch,eine Funktion mit html code für Login mit username + password zu schreiben (esp8266 + Arduino IDE).
Sie soll aufgerufen werden, solange eine globale Variable (noch) auf authorized==false steht.
Dann heißt es in loop:
if (!authorized) handleLogin(); // Website mit je 1 Feld für username + password
if (authorized) handleWebsite(); // vollständige Website mit Messwerten

Kennt jemand einen (möglichst selber schon mal verwendeten) Code, mit dem man einfach nur 2 Felder auf einer html Website hat, um deren Eingabestrings getrennt zu erfassen + 1 Bestätigungs-Button in der Art




Username: [_________]

Password: [_________]

[LOGIN]


edit - ah, habe das System verstanden, man erhält einen langen String, aus dem man die Einzelstrings der betr. Textfelder herausisolieren muss... :idea:

Moppi
12.08.2018, 06:24
Zum Zeitpunkt weiß ich zwar nicht, wie das mit Arduino funktioniert, aber da es ja nur um Webseiten-Verarbeitung geht, muss man sich beim Arduino sicher auch an die Standards halten. Dazu ein kleiner Überblick, wirst Du aber sicher auch schon so oder ähnlich gefunden haben: https://wiki.selfhtml.org/wiki/HTTP/Anfragemethoden

Die einfachste Methode Formular-Daten zu versenden ist unverschlüsselt. Dazu wird auf dem Webserver eine Seite aufgerufen (z.B. PHP) an die die Werte aus dem Formular geschickt werden. Einfach beispielsweise in etwas so:
http://.../eingabe.xxx?feld1=hallo&feld2=ballo
Das macht der Client, die Serveranwendung muss die Daten auswerten. Zuerst kommt natürlich der gesamte String so an. Da ist Dir ja auch irgendwo das Licht aufgegangen. :)

Bei komplizierteren Strings, die nach dieser Methode geschickt werden sollen, gibt es noch Kodierungsmöglichkeiten, weil man sonst bestimmte Zeichen nicht verschicken kann (wie eben das '=' oder das '&'). Das muss dann Serverseitig decodiert werden, aber eben nur, wenn der Web-Client das auch kodiert verschickt, das liegt dann aber an Dir, ob Du die Login-Seite so programmierst oder nicht.

HaWe
12.08.2018, 10:09
hallo,
ja, danke, das mit
feld1=hallo&feld2=ballo..
meinte ich oben mit " langen String, aus dem man die Einzelstrings der betr. Textfelder herausisolieren muss".
Ich verwende kein php, nur html unverschlüsselt, und ich habe auch einen vereinfachten Test-Code fürs Login inzwischen, welcher eine Website aufbaut und dort in 2 Textfeldern nach username und passwort fragt.
Nur funktioniert es noch nicht mit den neueren esp8266-cores für Arduino, sondern nur mit älteren.
Wenn es hier html-Fachleute gibt, die versuchen möchten ihn zu debuggen, kann ich ihn sehr gerne mal posten, ich denke aber, da sind evtl so versteckte Fehler drin, dass es auch verwirren könnte.


Besser wäre es sicher, mit etwas anzufangen, das jemand anderes geschrieben hat und das wirklich funktioniert.

Moppi
12.08.2018, 11:20
Zu Arduino kann ich nichts beitragen, aber HTML-Formulare sind nicht schwer: https://wiki.selfhtml.org/wiki/HTML/Tutorials/Formulare/Was_ist_ein_Webformular%3F

HaWe
12.08.2018, 12:04
Zu Arduino kann ich nichts beitragen, aber HTML-Formulare sind nicht schwer: https://wiki.selfhtml.org/wiki/HTML/Tutorials/Formulare/Was_ist_ein_Webformular%3F

Grundsätzlich ist das ja auch nicht das Problem, sondern die Arduino-mäßige Umsetzung. Aber ich mache es gerne mal konkret: Was ist an diesem Code fehlerhaft, dass er nicht mit esp8266 cores 4.4.1 und 4.4.2 läuft sondern nur mit cores 4.3.0 und 4.4.0?



#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

WiFiServer wifiserver(http_port);
const int MAXLEN = 1024;
const int TOKLEN = 64;
char website_uname[20]; // website user name log in "MyWebsiteLoginName"
char website_upwd[20]; // website user pwd log in "MyWebsiteLoginPwd"

bool authorized = false;

void handleNotAuthorized() {
String readString="";
char strinput[MAXLEN], strupwd[TOKLEN], struname[TOKLEN];

WiFiClient client = wifiserver.available();

//---------------------------------------
// debug
// authorized=true;

strcpy(strinput, "");
strcpy(strupwd, "");
strcpy(struname, "");

while ( client.connected() ) {
if (authorized) return;

readString.toCharArray(strinput, MAXLEN);
// cstringarg( char* haystack, char* vname, char* sarg )
// haystack pattern: &varname=1234abc, delimiters &, \n, \0, SPACE, EOF
cstringarg(strinput, "uname", struname); // uname
cstringarg(strinput, "upwd", strupwd); // upwd

if ( strlen(strupwd) == strlen(website_upwd)
&& strncmp(strupwd, website_upwd, strlen(website_upwd) ) == 0) {
authorized = true;
//debug
//Serial.print("check: authorized="); Serial.println(authorized);
readString = "";
return;
}

if ( client.available() ) {
char c = client.read();

//read char by request
if (readString.length() < TOKLEN) {

//store characters to string
readString += c;
//Serial.print(c);
}

//if HTTP request has ended
if (c == '\n') {
client.flush();
Serial.println(readString);

//now output html data header

String script = "";

script += ("HTTP/1.1 401 Log-In Required");
script += ("Content-Type: text/html \n");
script += ("\n");
script += ("<!DOCTYPE html> \n");
script += ("<html> \n");
script += ("<head> \n");


// utf-8 für "°" Zeichen
script += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> \n" ;
script += "<title>" ;
script += website_title ;
script += "</title> \n" ;
script += "</head> \n" ;
script += "<body> \n" ;

script += "<h1><p style=\"color:rgb(255,0,191);\"> " + (String)website_url ;
script += (String)": &nbsp; <wbr> <wbr> " + "Not authorized !</p> </h1> \n" ;
script += ("<h2><p style=\"color:rgb(255,0,191);\"> log in to proceed: </p> </h2> \n");

script += ("<FORM ACTION='/' method=GET > \n");
script += ("<h2>user name: <INPUT TYPE=text NAME='uname' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2>password : <INPUT TYPE=PASSWORD NAME='upwd' VALUE='' MAXLENGTH='50'> </h2> \n");

script += ("<h2><INPUT TYPE=SUBMIT></h2> \n");

script += ("</FORM> \n");
script += ("<BR> \n");
script += ("</body> \n");
script += ("</html> \n");

client.print(script);

//stopping client
client.stop();
delay(1);

//clearing string for next read
readString = "";
}
}
delay(1);
}
}


Bei den beiden neueren Cores springt er zur Laufzeit sofort aus dieser Funktion heraus und bricht ab mit der Meldung "Die Website ist nicht verfügbar", und dann kann man sich auch nicht erneut einloggen oder die Standard-Website aufrufen.
Ansonsten wird bei den älteren Cores bei korrektem Login auch anschließend die Standard-Seite korrekt geladen.
Setzt man authorized dagegen vorher manuell auf true, wird bei jedem Core, neu wie alt, auch sofort die Standardseite korrekt erzeugt.

oder sind es evt bugs in den esp-cores selber?

Moppi
12.08.2018, 13:59
Bei PHP änderten sich mal die Variablen, weswegen ältere Scripte auf neuen Versionen nicht funktionierten. Man musste nur die Variablennamen ändern. Es könnte sich auch die Zugriffsart oder die Methode ändern - eine Funktion wurde geändert oder durch eine andere ersetzt. Syntax wurde irgendwo geändert, Funktion erwartet mehr oder erwartet weniger Parameter als vorher und stürzt ab, bzw. erzeugt Fehler.
Kannst Du eine Rückmeldung erzeugen im Script? Sowas wie alert() in Javascript? Irgendwas, was man vor jeder Codezeile einbaut und dann sieht man, wo was hängt - wenn ich vom Absturz ausgehe. Ein Debuger ist natürlich besser. Irgendwie muss man die Fehlerquelle einkreisen und sich dann mit dem was übrig bleibt im Detail beschäftigen. Oder man muss die Befehle überprüfen, ob die alle auf "den beiden neueren Cores" auch so nach außen implementiert sind, wie auf den "alten" - ob es dort irgendwo an einer Stelle Änderungen gab. Es sollte Befehlslisten mit Beschreibung geben. An sich ist nichts Schweres dran am Code. Bloß ich habe damit noch nie gearbeitet. Deshalb meinerseits notdürftige Denkanstöße und hier keine Gewähr auf irgendeine Richtigkeit.

Man kann auch handleNotAuthorized() neu aufbauen. Erst mal alles raus nehmen und dann Codezeile um Codezeile hinzufügen. Nur man braucht eine Rückmeldung, damit man feststellen kann ab wann es nicht mehr funktioniert.


Nachtrag:

Compilerversion und Bibliotheken passen auch zu den "neuen Cores"?

HaWe
12.08.2018, 14:37
Bei PHP änderten sich mal die Variablen, weswegen ältere Scripte auf neuen Versionen nicht funktionierten. Man musste nur die Variablennamen ändern. Es könnte sich auch die Zugriffsart oder die Methode ändern - eine Funktion wurde geändert oder durch eine andere ersetzt. Syntax wurde irgendwo geändert, Funktion erwartet mehr oder erwartet weniger Parameter als vorher und stürzt ab, bzw. erzeugt Fehler.
Kannst Du eine Rückmeldung erzeugen im Script? Sowas wie alert() in Javascript? Irgendwas, was man vor jeder Codezeile einbaut und dann sieht man, wo was hängt - wenn ich vom Absturz ausgehe. Ein Debuger ist natürlich besser. Irgendwie muss man die Fehlerquelle einkreisen und sich dann mit dem was übrig bleibt im Detail beschäftigen. Oder man muss die Befehle überprüfen, ob die alle auf "den beiden neueren Cores" auch so nach außen implementiert sind, wie auf den "alten" - ob es dort irgendwo an einer Stelle Änderungen gab. Es sollte Befehlslisten mit Beschreibung geben. An sich ist nichts Schweres dran am Code. Bloß ich habe damit noch nie gearbeitet. Deshalb meinerseits notdürftige Denkanstöße und hier keine Gewähr auf irgendeine Richtigkeit.

Man kann auch handleNotAuthorized() neu aufbauen. Erst mal alles raus nehmen und dann Codezeile um Codezeile hinzufügen. Nur man braucht eine Rückmeldung, damit man feststellen kann ab wann es nicht mehr funktioniert.
nein, leider kenne ich mich mit all dem nicht aus.
Alles was ich habe ist obiger Code, der nicht bei den neuen cores funktioniert und den ein fähiger Programmierer debuggen können müsste, ansonsten bitte lieber auch gerne einen alternativen, lauffähigen eigenen Code, den ich direkt in die Arduino IDE c+p'en kann.

HaWe
17.08.2018, 16:53
updae:
ich habe jetzt einen Code zusammengebastelt, der einigermaßen, aber noch nicht 100%ig funktioniert.
Fürs erste teste ich nur aufs Passwort wegen der Debug-Phase.
ist es völlig falsch, wird es zurückgewiesen, ist es 100% richtig, dann auch angenommen.

Problem aber:
wenn das Pwd zB "12345" ist, und der usr gibt "1234567" ein, wird es auch akzeptiert. Ich kriege nicht raus, wo der Fehler liegt.
Wer weiß wo der Hase im Pfeffer liegt?

Hier erst mal 2 Hilfsfunktionen, um Passwort etc. aus dem html-String rauszufischen (funktioniert ansonsten einwandfrei):



int16_t strstrpos(char * haystack, char * needle) // find 1st occurance of substr in str
{
char *p = strstr(haystack, needle);
if (p) return p - haystack;
return -1; // Not found = -1.
}

//----------------------------------------------------------------------------
const int MAXLEN = 1024;
const int TOKLEN = 64;

char * cstringarg( char* haystack, char* vname, char* sarg ) {
int i=0, pos=-1;
unsigned char ch=0xff;
char kini[3] = "&"; // start of varname: '&':
char kequ[3] = "="; // end of varname, start of argument: '='
char needle[TOKLEN]=""; // complete pattern: &varname=abc1234

//kequ[0] = '='; // customize
strcpy(sarg,"");
strcpy(needle, kini);
strcat(needle, vname);
strcat(needle, kequ);
pos = strstrpos(haystack, needle);
if(pos==-1) return sarg;
pos=pos+strlen(vname)+2; // start of value = kini+vname+kequ
while( (ch!='&')&&(ch!='\0') ) {
ch=haystack[pos+i];
if( (ch=='&')||(ch==';')||(ch==' ')||(ch=='\0') ||(ch=='\n')
||(i+pos>=strlen(haystack))||(i>TOKLEN-1) ) {
sarg[i]='\0';
return sarg;
}
if( (ch!='&') ) {
sarg[i]=ch;
i++;
}
}
return sarg;
}


und hier jetzt die eigentliche Website, die username und passwort anfordert zum Login:



char website_uname[20]="abcde"; // website user name
char website_upwd[20]="12345"; // website user pwd

void handleNotAuthorized() {
String readString="";
char strinput[MAXLEN], strupwd[TOKLEN], struname[TOKLEN];

WiFiClient client = wifiserver.available();

//---------------------------------------

strcpy(strinput, "");
strcpy(strupwd, "");
strcpy(struname, "");

while ( client.connected() ) {
if (authorized) return;

readString.toCharArray(strinput, MAXLEN);

// cstringarg( char* haystack, char* vname, char* sarg )
// haystack pattern: &varname=1234abc, delimiters &, \n, \0, SPACE, EOF
cstringarg(strinput, "uname", struname); // uname
cstringarg(strinput, "upwd", strupwd); // upwd

if ( strlen(strupwd) == strlen(website_upwd)
&& strcmp(strupwd, website_upwd ) == 0) {
authorized = true;
readString = "";
return;
}

if ( client.available() ) {
char c = client.read();

//read char by request
if (readString.length() < TOKLEN) {

//store characters to string
readString += c;
//Serial.print(c);
}

//if HTTP request has ended
if (c == '\n') {
client.flush();
Serial.println(readString);

//now output html data header

String script = "";

script += ("HTTP/1.1 401 Log-In Required");
script += ("Content-Type: text/html \n");
script += ("\n"); // do not forget this one //????
script += ("<!DOCTYPE html> \n");
script += ("<html> \n");
script += ("<head> \n");


// utf-8 für "°" Zeichen
script += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> \n" ;
script += "<title>" ;
script += website_title ;
script += "</title> \n" ;
script += "</head> \n" ;
script += "<body> \n" ;

script += "<h1><p style=\"color:rgb(255,0,191);\"> " + (String)website_url ;
script += (String)": &nbsp; <wbr> <wbr> " + "Not authorized !</p> </h1> \n" ;
script += ("<h2><p style=\"color:rgb(255,0,191);\"> log in to proceed: </p> </h2> \n");

script += ("<FORM ACTION='/' method=GET > \n");
script += ("<h2>user name: <INPUT TYPE=text NAME='uname' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2>password : <INPUT TYPE=PASSWORD NAME='upwd' VALUE='' MAXLENGTH='50'> </h2> \n");

script += ("<h2><INPUT TYPE=SUBMIT></h2> \n");

script += ("</FORM> \n");
script += ("<BR> \n");
script += ("</body> \n");
script += ("</html> \n");

client.print(script);

//stopping client
client.stop();
delay(1);

//clearing string for next read
readString = "";
}
}
delay(1);
}
}

Moppi
18.08.2018, 09:12
Das if() funktioniert:



if (strlen(strupwd) == strlen(website_upwd)
&& strcmp(strupwd, website_upwd ) == 0) .....


Wenn die Eingangsstrings korrekt sind. Also 12456 und 1234567, wird korrekt als falsch erkannt, sowie 123456 und 123456 als richtig.
Also musst Du davor nach dem Problem suchen.

Ich tippe hier auf das Problem, habe ich noch nicht richtig angeschaut:


cstringarg(strinput, "upwd", strupwd); // upwd

HaWe
18.08.2018, 11:16
Das if() funktioniert:



if (strlen(strupwd) == strlen(website_upwd)
&& strcmp(strupwd, website_upwd ) == 0) .....


Wenn die Eingangsstrings korrekt sind. Also 12456 und 1234567, wird korrekt als falsch erkannt, sowie 123456 und 123456 als richtig.
Also musst Du davor nach dem Problem suchen.

Ich tippe hier auf das Problem, habe ich noch nicht richtig angeschaut:


cstringarg(strinput, "upwd", strupwd); // upwd

hallo,
das cstringarg habe ich als isolierte Funktion mit mehreren Teststrings geprüft, es hat immer den richtigen arg-Teilstring zurückgegeben, aber ich kann tatsächlich nicht ausschleißen, dass nicht doch irgendein verdeckter Bug drin steckt.
Du hast ja auch völlig Recht, die Abfrage
if (strlen(strupwd) == strlen(website_upwd)
müsste diesen Fehler 12345 != 1234567 heraussieben.
Die Ungleichheit "1245" != "12345" etc wird ja hingegen korrekt erkannt., und die Gleichheit "12345" == "12345" ebenfalls.

Es sei denn die Länge wird nicht richtig ermittelt, z.B. wegen fehlender '\0' in den beiden cstrings (wofür ich allerdings auch keinen Anhaltspunkt habe),
oder die Funktion macht bereits einen Vergleich auf Identität, ohne dass bereits "Enter" gedrückt wurde, und überspringt dabei die folgenden Eingaben - doch auch dafür sehe ich keinen Anlass.

Es ist mir ein absolutes Rätsel.

- - - Aktualisiert - - -



update:
hier ein testcode für cstringarg(), und er funktioniert bestens, sowohl mit direkt aneinanderhängenden als auch bei durch (fälschlich) mit Leerzeichen getrennten Teilstrings:



int16_t strstrpos(char * haystack, char * needle) // find 1st occurance of substr in str
{
char *p = strstr(haystack, needle);
if (p) return p - haystack;
return -1; // Not found = -1.
}

//----------------------------------------------------------------------------
const int MAXLEN = 1024;
const int TOKLEN = 64;

char * cstringarg( char* haystack, char* vname, char* sarg ) {
int i=0, pos=-1;
unsigned char ch=0xff;
char kini[3] = "&"; // start of varname: '&':
char kequ[3] = "="; // end of varname, start of argument: '='
char needle[TOKLEN]=""; // complete pattern: &varname=abc1234

//kequ[0] = '='; // customize
strcpy(sarg,"");
strcpy(needle, kini);
strcat(needle, vname);
strcat(needle, kequ);
pos = strstrpos(haystack, needle);
if(pos==-1) return sarg;
pos=pos+strlen(vname)+2; // start of value = kini+vname+kequ
while( (ch!='&')&&(ch!='\0') ) {
ch=haystack[pos+i];
if( (ch=='&')||(ch==';')||(ch==' ')||(ch=='\0') ||(ch=='\n')
||(i+pos>=strlen(haystack))||(i>TOKLEN-1) ) {
sarg[i]='\0';
return sarg;
}
if( (ch!='&') ) {
sarg[i]=ch;
i++;
}
}
return sarg;
}

void setup() {
Serial.begin(115200);
Serial.println();
Serial.println("Test mit cstringarg()");
Serial.println();

char htmlstring[1024]="html teststring mit und ohne Leerzeichen &upwd1=testupwd1&upwd2=testupwd2 &upwd13=testupwd13&upwd224=testupwd224 EndeTststring";
char argstring[64]="";

cstringarg(htmlstring, "upwd1", argstring);
Serial.print("upwd1 >>"); Serial.print(argstring); Serial.println("<< soll: >>testupwd1<<");

cstringarg(htmlstring, "upwd2", argstring);
Serial.print("upwd2 >>"); Serial.print(argstring); Serial.println("<< soll: >>testupwd2<<");

cstringarg(htmlstring, "upwd13", argstring);
Serial.print("upwd13 >>"); Serial.print(argstring); Serial.println("<< soll: >>testupwd13<<");

cstringarg(htmlstring, "upwd224", argstring);
Serial.print("upwd224 >>"); Serial.print(argstring); Serial.println("<< soll: >>testupwd224<<");

}

void loop() {

}



das einzige, was ich vermuten würde, wäre daher etwas in der "Logik", wie die html-Seite aufgebaut ist und wie ihr html string mit dem Text der Eingabefelder zusammengesetzt, gesendet und ausgewertet wird.

Moppi
18.08.2018, 14:34
Wenn man vor dem if(....) ein Serial.println(strupwd); macht, sieht man, was dort vor dem if ankommt. Man muss mal die beteiligten Variablen (Strings) ausgeben, dann sieht man mehr. Dann kann man auch gleich die Länge mit ausgeben (Serial.println(strlen(strupwd));)

HaWe
18.08.2018, 14:37
dann sieht man nur das verkürzte pwd, also bei Eingabe im Textfeld
"1234567"
dann als strupwd nur "12345",
und website_upwd auch "12345"

d.h. hier kommen sie identisch an, obwohl strupwd eigentlich vorher länger war.
im html String, steht es aber noch als &upwd=1234567
Dabei funktioniert aber nach allen Tests ja cstringarg fehlerfrei.

Mir ist die Logik des html-Codes und seiner Auswertung aber auch absolut schleierhaft: warum z.B. die Auswertung vor dem html Code steht, und was das ganze Brimborium mit client = wifiserver.available(); und client.available, client.flush und client.stop soll und der ganze Rest, und was ein "client" hier überhaupt ist und was wann macht.

Moppi
18.08.2018, 16:15
Wenn statt 1234567 nur 12345 ankommt, ist es doch nicht richtig, was cstringarg als Ergebnis liefert? website_upwd ist ja '12345', das ändert sich nicht, so weit ich das gesehen habe. Wichtig ist dann nur strupwd, was cstringarg liefert. Oder?

Wenn Du mal website_upwd="abcde" schreibst, kommt dann als strupwd auch "12345" statt "1234567" oder kommt dann "abcde" vor dem if an?

HaWe
18.08.2018, 16:20
genau, das strupwd wird aus dem html string mit cstringarg extrahiert, und cstringarg arbeitet aber korrekt nach allen Tests.
Genau deshalb bin ich ja dermaßen ratlos.
Es wird irgendwie mit dem Aufbau und der Logik des html codes und des wifi servers zu tun haben.

Versuch du es dochmal selber mit esp8266 und Arduino 1.8.5 zu debuggen, ich weiß nicht mehr, wo ich suchen soll.
Ich kann dir gerne den kompletten lauffähigen Code hier posten.

Moppi
18.08.2018, 16:21
ich hatte die Vermutung, dass er das "12345" vielleicht nicht aus der HTML-Eingabe nimmt sondern irgendwie aus website_upwd klaut.

HaWe
18.08.2018, 17:29
nein, eigentlich nicht:
readString ist der String, der von der html-Seite mit den Text-Eingabefeldern kommt, der wird in einen cstring namens strinput umgewandelt:


readString.toCharArray(strinput, MAXLEN);

Dann wird in diesm strinput nach user name und pwd gefischt:

// cstringarg( char* haystack, char* vname, char* sarg )
// haystack pattern: &varname=1234abc, delimiters &, \n, \0, SPACE, EOF
cstringarg(strinput, "uname", struname); // uname
cstringarg(strinput, "upwd", strupwd); // upwd
//...
if ( (strlen(strupwd)==strlen(website_upwd) )
&& (strcmp(website_upwd, strupwd )==0)
)
{
authorized = true;
//...
}

Hier mal der komplette, abgespeckte Code:



//----------------------------------------------------------------------------
// board: ESP8266 NodeMCU 1.0 (ESP12-E module)
// Arduino IDE 1.8.5
// esp8266 core 2.4.0
//----------------------------------------------------------------------------


// Wifi + website data

extern const char* ssid =""; // WIFI network name
extern const char* password =""; // WIFI network password

// define
char website_uname[20] ="" ; // website user name log in "MyWebsiteLoginName"
char website_upwd[20] =""; // website user pwd log in "MyWebsiteLoginPwd"
char* website_title =""; // website caption "MySiteCaption"
char* website_url =""; // website url "http:\\mysite.com"



//----------------------------------------------------------------------------
// OLED SSD1306

#include <ESP_SSD1306.h> // Modification of Adafruit_SSD1306 for ESP8266 compatibility
#include <Adafruit_GFX.h> // Needs a little change in original Adafruit library (See README.txt file)
#include <Fonts/FreeSansBold12pt7b.h> //
#include <Fonts/FreeSans9pt7b.h> //
//#include <Fonts/FreeMono12pt7b.h> //

// i2c Wire
#include <Wire.h>

#define SCL D1 // SCL
#define SDA D2 // SDA

#define D12 10 // GPIO intern
#define OLED_RESET 10 // GPIO10=D12 Pin RESET signal

ESP_SSD1306 display(OLED_RESET);



//----------------------------------------------------------------------------
// IO pins
//----------------------------------------------------------------------------

#define PIN_BTND3 D3 // Btn 0=D3 reset Alarm
// #define PIN_IN4 D4 // N/A

#define PIN_OUT1 D5 // out
#define PIN_OUT2 D7 // out
// #define PIN_OUT3 D8 // N/A



//----------------------------------------------------------------------------
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>


#define ORANGE 255,102,0


// WiFi Router

#define this_iph 200 // <<< local host ip
#define http_port 80


IPAddress this_ip(192, 168, 2, this_iph); // <<< Feste lokale IP dieses ESP8266-Servers
IPAddress gateway(192, 168, 2, 1); // <<< LAN Gateway IP
IPAddress subnet(255, 255, 255, 0); // <<< LAN Subnet Mask

WiFiServer wifiserver(http_port);

ESP8266WebServer lanserver(8081);

bool authorized = false;




//----------------------------------------------------------------------------
// Tools


//----------------------------------------------------------------------------

int16_t strstrpos(char * haystack, char * needle) // find 1st occurance of substr in str
{
char *p = strstr(haystack, needle);
if (p) return p - haystack;
return -1; // Not found = -1.
}

//----------------------------------------------------------------------------
const int MAXLEN = 1024;
const int TOKLEN = 64;

char * cstringarg( char* haystack, char* vname, char* sarg ) {
int i=0, pos=-1;
unsigned char ch=0xff;
char kini[3] = "&"; // start of varname: '&':
char kequ[3] = "="; // end of varname, start of argument: '='
char needle[TOKLEN]=""; // complete pattern: &varname=abc1234

//kequ[0] = '='; // customize
strcpy(sarg,"");
strcpy(needle, kini);
strcat(needle, vname);
strcat(needle, kequ);
pos = strstrpos(haystack, needle);
if(pos==-1) return sarg;
pos=pos+strlen(vname)+2; // start of value = kini+vname+kequ
while( (ch!='&')&&(ch!='\0') ) {
ch=haystack[pos+i];
if( (ch=='&')||(ch==';')||(ch==' ')||(ch=='\0') ||(ch=='\n')
||(i+pos>=strlen(haystack))||(i>TOKLEN-1) ) {
sarg[i]='\0';
return sarg;
}
if( (ch!='&') ) {
sarg[i]=ch;
i++;
}
}
return sarg;
}



//----------------------------------------------------------------------------
// OLED dashboard
//----------------------------------------------------------------------------
void dashboard(int mode) {
display.clearDisplay();

if (mode >= 0) {
display.setCursor( 0, 0);
display.print(this_ip);
display.setCursor (0, 16);
display.print(gateway);
display.display();


}

display.setFont();
}


//----------------------------------------------------------------------------
// SETUP
//----------------------------------------------------------------------------


void setup() {

int IORes;

//STR_DEGREE[0] = CHR_DEGREE; // ° symbol as ANSI C string

int progress = 0;


//----------------------------------------
Serial.begin(115200);
delay(1000);





//----------------------------------------
// i2c: init

Wire.pins(SDA, SCL); // SDA, SCL
Wire.begin();
delay(1);


//----------------------------------------
// OLED

display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x64)

display.setFont();
display.setTextSize(1);
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor( 0, 0); display.print("OLED TEST OK");
display.display();
delay(1);
Serial.println("OLED sensor init...");


//----------------------------------------
// Connect to WiFi network
Serial.println();
Serial.println();
Serial.println("Connecting to Router: ");
Serial.println( WiFi.gatewayIP().toString() );

WiFi.begin(ssid, password);
WiFi.config(this_ip, gateway, subnet); // feste IP

while (WiFi.status() != WL_CONNECTED) {

delay(500);
Serial.print(".");

display.clearDisplay();
display.setCursor( 0, 20); display.print("WiFi connecting...");

display.setCursor( 0, 40); display.print((String)progress + "%");
if (progress >= 98) {
progress = 80;
Serial.println();
}
display.display();

if (progress < 10) progress += 5;
else if (progress < 50) progress += 2;
else if (progress < 90) progress += 1;
}
display.clearDisplay();
progress = 100;
display.setCursor( 0, 20); display.print("WiFi connecting...");
display.setCursor( 0, 40); display.print((String)progress + "%");
display.display();
delay(300);

Serial.println("");
Serial.print("WiFi connected: ");
Serial.println(WiFi.gatewayIP());


//----------------------------------------
// Start the WiFi server (-> www)
wifiserver.begin();
Serial.println("WiFi Server started");

//----------------------------------------
// Start the ESP LAN server (-> ESP client)
lanserver.on("/",handleRoot) ;
lanserver.on("/client/client0/", handleClients);
delay(10);
lanserver.on("/client/client1/", handleClients);
delay(10);
lanserver.on("/client/client2/", handleClients);
delay(10);
lanserver.on("/client/client3/", handleClients);
delay(10);
lanserver.begin();
Serial.println("ESP Server started");

// Print the IP address
Serial.print("Use this URL to connect: ");
Serial.print("http://");
Serial.print(WiFi.localIP());
Serial.print(":");
Serial.print(http_port);
Serial.println("/");
Serial.print((String)website_url + ":" + http_port + "/");

delay(1);



//----------------------------------------
// setup done

dashboard(1);
Serial.println("setup done \n");

}



//----------------------------------------------------------------------------
// LOOP
//----------------------------------------------------------------------------

void loop() {

static double ftmp;
static unsigned long tsec=millis(), tms = millis();
static int8_t LEDmode=0;



//---------------------------------------
// Check log-in

if (!authorized) {
handleNotAuthorized();
delay(100);
}

if (authorized) {
handleWebsite();
delay(10);
}

lanserver.handleClient();
delay(10);



//---------------------------------------
// Read local + Udp data
if ( millis() - tms >= 100 ) { // refresh data rate
tms = millis();


//---------------------------------------
// display on OLED
if ( millis() - tsec >= 4000 ) {
tsec=millis();
LEDmode++;
if(LEDmode>8) LEDmode=0;
}
dashboard(LEDmode);
delay(1);
}


}

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

void handleNotAuthorized() {
String readString="";
char strinput[MAXLEN], strupwd[TOKLEN], struname[TOKLEN], test[TOKLEN] ;

WiFiClient client = wifiserver.available();

//---------------------------------------
// debug
// authorized=true;

strcpy(strinput, "");
strcpy(strupwd, "");
strcpy(struname, "");

while ( client.connected() ) {
if (authorized) return;


readString.toCharArray(strinput, MAXLEN);
// cstringarg( char* haystack, char* vname, char* sarg )
// haystack pattern: &varname=1234abc, delimiters &, \n, \0, SPACE, EOF
cstringarg(strinput, "uname", struname); // uname
cstringarg(strinput, "upwd", strupwd); // upwd

// debug
Serial.print("strupwd >>>"); Serial.print(strupwd); Serial.println("<<<");
Serial.print("website_upwd>>>"); Serial.print(website_upwd); Serial.println("<<<");


if ( (strlen(strupwd)==strlen(website_upwd) )
&& (strcmp(website_upwd, strupwd )==0)
)
{
authorized = true;
//debug
//Serial.print("check: authorized="); Serial.println(authorized);
readString = "";
return;
}

if ( client.available() ) {
char c = client.read();

//read char by request
if (readString.length() < TOKLEN) {

//store characters to string
readString += c;
Serial.println(c);
}

//if HTTP request has ended
if (c == '\n') {
client.flush();


//now output html data header

String script = "";

script += ("HTTP/1.1 401 Log-In Required");
script += ("Content-Type: text/html \n");
script += ("\n"); // do not forget this one //????
script += ("<!DOCTYPE html> \n");
script += ("<html> \n");
script += ("<head> \n");


// utf-8 für "°" Zeichen
script += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> \n" ;
script += "<title>" ;
script += website_title ;
script += "</title> \n" ;
script += "</head> \n" ;
script += "<body> \n" ;

script += "<h1><p style=\"color:rgb(255,0,191);\"> " + (String)website_url ;
script += (String)": &nbsp; <wbr> <wbr> " + "Not authorized !</p> </h1> \n" ;
script += ("<h2><p style=\"color:rgb(255,0,191);\"> log in to proceed: </p> </h2> \n");

script += ("<FORM ACTION='/' method=GET > \n");
script += ("<h2>user name: <INPUT TYPE=text NAME='uname' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2>password : <INPUT TYPE=PASSWORD NAME='upwd' VALUE='' MAXLENGTH='50'> </h2> \n");

script += ("<h2><INPUT TYPE=SUBMIT></h2> \n");

script += ("</FORM> \n");
script += ("<BR> \n");
script += ("</body> \n");
script += ("</html> \n");

client.print(script);

//stopping client
client.stop();

delay(1);

//clearing string for next read
readString = "";
}
}
delay(1);
}
}


//----------------------------------------------------------------------------

void handleWebsite() {

WiFiClient client = wifiserver.available();

//---------------------------------------
// Check if a client has connected


// Read the first line of the request
String request = client.readStringUntil('\r');
Serial.println(request);
client.flush();



//---------------------------------------
// LogOut
if (request.indexOf("/logout") != -1) {
authorized = false;
return;
}


delay(1);

//---------------------------------------
// Return the response

String script = "";

// init website

script += ("HTTP/1.1 200 OK \n");
script += ("Content-Type: text/html \n");
script += ("\n"); // do not forget this one
script += ("<!DOCTYPE html> \n");
script += ("<html> \n");

// head + title
script += ("<head> \n");
// autom. Aktualisierung alle 20 sec.

script += "<meta http-equiv=\"refresh\" content=\"20; URL=";
script += (String)website_url + ":" + (String)http_port + "\"> \n" ;


// utf-8 für "°" Zeichen
script += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> \n" ;
script += ("<title>");
script += (website_title);
script += ("</title> \n");
script += ("</head> \n");

// body + caption
script += ("<body> \n");
script += ("<h1> <p> ");
script += ("<font style=\"color:rgb(255,0,204);\"> HELLO WORLD! ");
script += ("&nbsp; <wbr> <wbr> ");
script += ("<font style=\"color:rgb(0,205,102);\"> Welcome to " + (String)website_url );
script += ("! </p> </h1> "); // script+= ("! </p> </h1> \n");


delay(1);


//---------------------------------------
script += "<h2> <br> \n HEIMSERVER <br> \n </h2>";
//---------------------------------------
// remote buttons Server
// <input type="button" value="submit" style="height: 100px; width: 100px; left: 250; top: 250;">
// <button style=\"height:200px;width:200px\"> </button>



client.print(script);
script = "";


//---------------------------------------
// sensors Server
// chart table
//---------------------------------------
// text font Courier, color black
script += ("<p> <font face=\"courier\"> "); // <<< Courier
script += "<h2> ";
script += "<p style=\"color:rgb(0,0,0);\" > </p> " ;
script += ("<br> \n");
script += "</h2>";

client.print(script);
script = "";


script += ("<br> \n");


// log out
script += ("<h3>Log Out: ");
script += ("<a href=\" /logout\"\"> <button style=\"height:70px;width:140px\" > Log Out </button></a> </h3> ");

script += WiFi.localIP().toString() +" "+ (String)ssid + " <br>" ;
script += "</font> </p> \n";

script += "</body> \n";
script += "</html> \n";

client.print(script);

delay(1);

}

//----------------------------------------------------------------------------
// handle root +clients
//----------------------------------------------------------------------------

void handleRoot() {
handleClients();
}


//----------------------------------------------------------------------------

void handleClients() {
double ftmp;
String msgtok;



//------------------------------------------

//client-Werte auch bei Url-Aufruf zurückgeben

String message = "*** ";
// re CLIENT 0
/*
message += (String)"&c0t1=" + c0t1.sact + "&c0h1=" + c0h1.sact;
message += (String)"&c0t2=" + c0t2.sact + "&c0h2=" + c0h2.sact;
message += "&c0out1=" + (String)c0out1 + "&c0out2=" + (String)c0out2 + "&c0out3=" + (String)c0out3 ;
*/
message += " ###";
//Serial.println(message);
lanserver.send(200, "text/plain", message);

}



// END OF FILE

Moppi
18.08.2018, 17:51
Manche Bibliotheken fehlen bei mir:

//#include <ESP_SSD1306.h> // Modification of Adafruit_SSD1306 for ESP8266 compatibility
//#include <Adafruit_GFX.h> // Needs a little change in original Adafruit library (See README.txt file)
//#include <Fonts/FreeSansBold12pt7b.h> //
//#include <Fonts/FreeSans9pt7b.h> //
//#include <Fonts/FreeMono12pt7b.h> //

Die habe ich deshalb rausgenommen. Dann kann er mit display nichts anfangen: 'display' was not declared in this scope

HaWe
18.08.2018, 18:23
Manche Bibliotheken fehlen bei mir:

//#include <ESP_SSD1306.h> // Modification of Adafruit_SSD1306 for ESP8266 compatibility
//#include <Adafruit_GFX.h> // Needs a little change in original Adafruit library (See README.txt file)
//#include <Fonts/FreeSansBold12pt7b.h> //
//#include <Fonts/FreeSans9pt7b.h> //
//#include <Fonts/FreeMono12pt7b.h> //

Die habe ich deshalb rausgenommen. Dann kann er mit display nichts anfangen: 'display' was not declared in this scope

ich hatte sie drin gelassen, weil man dann auch strings aufs OLED ausgeben kann, unabh. von Serial.
wenn du kein OLED hast, macht das dann auch nichts.
Adafriut libs gehen über den library manager oder hier: https://github.com/adafruit/Adafruit-GFX-Library
<ESP_SSD1306.h> ist hier: https://github.com/ThingPulse/esp8266-oled-ssd1306

Moppi
19.08.2018, 00:18
<ESP_SSD1306.h>,<Adafruit_GFX.h>, <Fonts/FreeSansBold12pt7b.h>: Fehler beim Kompilieren für das Board NodeMCU 1.0 (ESP-12E Module)


Aber was mir noch aufgefallen ist: dieses cstringarg ist noch nicht ganz durchdacht.
Da wird doch GET verwendet, um die Daten an den Server zu übertragen. Von daher müsste die Übermittlung der Daten in etwa so aussehen: http://.../xxxxx.htm?name=uschi&password=12345

Ist zwar schon eine Zeit her, als ich damit gearbeitet habe, aber so müsste es sein. Diese Daten werden vom Browser verschickt, so dass man auf diesen Übermittlungsstring nur bedingt Einfluß hat. Man muss darauf achten, dass alle Feldbezeichner (für name und password das &-Zeichen vorangestellt haben. So wird es dann wohl auch sein. Aber wenn nicht und wenn der String dann so aussieht (wie ich oben hingeschrieben habe), kommt es mit dieser cstringarg zu einer Ausnahme, weil dort nur mit dem & operiert, dass der cstringarg übergeben wird:


Test mit cstringarg()

haystack: index.htm?upwd1=testupwd1&upwd2=testupwd2 &upwd13=testupwd13&upwd224=testupwd224 EndeTststring
needle: &upwd1=
*p:
Exception (28):


cstringarg verursacht demnach einen Fehler, wenn etwas nicht gefunden wird.

Was mir als Bindeglied noch fehlt, ist so ein String, vom Webbrowser, so wie er an den Server übermittelt wird - das wird in readString übertragen. So weit habe ich das nachvollzogen und bis auf die Ausnahme oben ist mir bis jetzt nicht aufgefallen, dass es nicht funktioniert. Ich hätte jetzt den Gedanken, selber das so zu programmieren, dass ich die Kommunikation mit dem Browser ausprobieren kann. Aber das ist dann sicherlich abweichend von dem Code, den Du verwendest. Und wenn es dann bei mir funktionieren würde, nutzt Dir das nicht.

HaWe
19.08.2018, 09:43
<ESP_SSD1306.h>,<Adafruit_GFX.h>, <Fonts/FreeSansBold12pt7b.h>: Fehler beim Kompilieren für das Board NodeMCU 1.0 (ESP-12E Module)


Aber was mir noch aufgefallen ist: dieses cstringarg ist noch nicht ganz durchdacht.
Da wird doch GET verwendet, um die Daten an den Server zu übertragen. Von daher müsste die Übermittlung der Daten in etwa so aussehen: http://.../xxxxx.htm?name=uschi&password=12345

Ist zwar schon eine Zeit her, als ich damit gearbeitet habe, aber so müsste es sein. Diese Daten werden vom Browser verschickt, so dass man auf diesen Übermittlungsstring nur bedingt Einfluß hat. Man muss darauf achten, dass alle Feldbezeichner (für name und password das &-Zeichen vorangestellt haben. So wird es dann wohl auch sein. Aber wenn nicht und wenn der String dann so aussieht (wie ich oben hingeschrieben habe), kommt es mit dieser cstringarg zu einer Ausnahme, weil dort nur mit dem & operiert, dass der cstringarg übergeben wird:


Test mit cstringarg()

haystack: index.htm?upwd1=testupwd1&upwd2=testupwd2 &upwd13=testupwd13&upwd224=testupwd224 EndeTststring
needle: &upwd1=
*p:
Exception (28):


cstringarg verursacht demnach einen Fehler, wenn etwas nicht gefunden wird.

Was mir als Bindeglied noch fehlt, ist so ein String, vom Webbrowser, so wie er an den Server übermittelt wird - das wird in readString übertragen. So weit habe ich das nachvollzogen und bis auf die Ausnahme oben ist mir bis jetzt nicht aufgefallen, dass es nicht funktioniert. Ich hätte jetzt den Gedanken, selber das so zu programmieren, dass ich die Kommunikation mit dem Browser ausprobieren kann. Aber das ist dann sicherlich abweichend von dem Code, den Du verwendest. Und wenn es dann bei mir funktionieren würde, nutzt Dir das nicht.

danke für den Hinweis!
Ich war tatsächlich immer der Meinung, jeder Variablenname würde immer mit einem '&' beginnen und mit einem '=' enden, direkt anschließend kommt dann der Variablenwert, als arg.
Dann wäre es korrekt, dass bei xxxx nur diese Muster &xxxx= gesucht und gefunden werden, ansonsten eben "nicht gefunden", also Rückgabewert -1, ein Laufzeitfehler dürfte allerdings nicht auftreten.

Stimmt es also, dass auch '?' ein Start-delimiter sein kann? Das einzubauen wäre nicht kompliziert, allerdings beträfe es ja nur die erste Textvariable (uname) und nicht die zweite (upwd), indes nur bei der zweiten tritt der Fehler mit überlangen Eingabestrings ja auf - und der fängt ja korrekt mit '&' an und hört korrekt mit '=' auf.

Einen "Standard-GET-html-string kann ich dir nicht zeigen, denn davon verstehe ich nichts - du müsstest ihn dir selber aus dem Programm per Serial.println mal genau angucken, sowohl in meinem Programm als auch in anderen.

Ich habe hier auch noch einmal einen noch stärker verkürzten Testcode ohne OLED und mit DHCP IP (die wird per Serial am Anfang angezeigt, dann kannst du dich damit per Browser anmelden (z.B. http://192.168.2.111)




//----------------------------------------------------------------------------
// board: ESP8266 NodeMCU 1.0 (ESP12-E module)
// Arduino IDE 1.8.5
// esp8266 core 2.4.0
//----------------------------------------------------------------------------


// Wifi + website data

const char* ssid = "SSID"; // WIFI network name
const char* password = "PSK"; // WIFI network password

// define
char website_uname[20] = "xx" ; // website user name log in "MyWebsiteLoginName"
char website_upwd[20] = "yy"; // website user pwd log in "MyWebsiteLoginPwd"
const char* website_title = "#5021"; // website caption "MySiteCaption"
const char* website_url = "http://givemeluck"; // website url "http:\\mysite.com"
int http_port = 80;

//----------------------------------------------------------------------------
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

WiFiServer wifiserver(http_port);
ESP8266WebServer lanserver(8081);
bool authorized = false;

//----------------------------------------------------------------------------
// handle root +clients
//----------------------------------------------------------------------------

void handleRoot() {
handleClients();
}


//----------------------------------------------------------------------------

void handleClients() {
String msgtok;
//------------------------------------------

//client-Werte auch bei Url-Aufruf zurückgeben

String message = "*** ";
// re CLIENT 0
/*
message += (String)"&c0t1=" + c0t1.sact + "&c0h1=" + c0h1.sact;
message += (String)"&c0t2=" + c0t2.sact + "&c0h2=" + c0h2.sact;
message += "&c0out1=" + (String)c0out1 + "&c0out2=" + (String)c0out2 + "&c0out3=" + (String)c0out3 ;
*/
message += " ###";
//Serial.println(message);
lanserver.send(200, "text/plain", message);

}

//----------------------------------------------------------------------------
// Tools
//----------------------------------------------------------------------------

int16_t strstrpos(char * haystack, char * needle) // find 1st occurance of substr in str
{
char *p = strstr(haystack, needle);
if (p) return p - haystack;
return -1; // Not found = -1.
}

//----------------------------------------------------------------------------
const int MAXLEN = 1024;
const int TOKLEN = 64;

char * cstringarg( char* haystack, char* vname, char* sarg ) {
int i = 0, pos = -1;
unsigned char ch = 0xff;
char kini[3] = "&"; // start of varname: '&':
char kequ[3] = "="; // end of varname, start of argument: '='
char needle[TOKLEN] = ""; // complete pattern: &varname=abc1234

//kequ[0] = '='; // customize
strcpy(sarg, "");
strcpy(needle, kini);
strcat(needle, vname);
strcat(needle, kequ);
pos = strstrpos(haystack, needle);
if (pos == -1) return sarg;
pos = pos + strlen(vname) + 2; // start of value = kini+vname+kequ
while ( (ch != '&') && (ch != '\0') ) {
ch = haystack[pos + i];
if ( (ch == '&') || (ch == ';') || (ch == ' ') || (ch == '\0') || (ch == '\n')
|| (i + pos >= strlen(haystack)) || (i > TOKLEN - 1) ) {
sarg[i] = '\0';
return sarg;
}
if ( (ch != '&') ) {
sarg[i] = ch;
i++;
}
}
return sarg;
}


//----------------------------------------------------------------------------
// SETUP
//----------------------------------------------------------------------------


void setup() {

//STR_DEGREE[0] = CHR_DEGREE; // ° symbol as ANSI C string


//----------------------------------------
Serial.begin(115200);
delay(1000);

//----------------------------------------
// Connect to WiFi network
Serial.println();
Serial.println();
Serial.println("Connecting to Router: ");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("WiFi connected: ");
Serial.println(WiFi.gatewayIP());


//----------------------------------------
// Start the WiFi server (-> www)
wifiserver.begin();
Serial.println("WiFi Server started");

//----------------------------------------
// Start the ESP LAN server (-> ESP client)
lanserver.on("/", handleRoot) ;
lanserver.on("/client/client0/", handleClients);
delay(10);
lanserver.on("/client/client1/", handleClients);
delay(10);
lanserver.on("/client/client2/", handleClients);
delay(10);
lanserver.on("/client/client3/", handleClients);
delay(10);
lanserver.begin();
Serial.println("ESP Server started");

// Print the IP address
Serial.print("Use this URL to connect: ");
Serial.print("http://");
Serial.print(WiFi.localIP());
Serial.print(":");
Serial.print(http_port);
Serial.println("/");
Serial.print((String)website_url + ":" + http_port + "/");

delay(1);

//----------------------------------------
// setup done
Serial.println("setup done \n");
}

//----------------------------------------------------------------------------
// LOOP
//----------------------------------------------------------------------------

void loop() {

//---------------------------------------
// Check log-in

if (!authorized) {
handleNotAuthorized();
delay(100);
}

if (authorized) {
handleWebsite();
delay(10);
}

lanserver.handleClient();
delay(10);
}

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

void handleNotAuthorized() {
String readString = "";
char strinput[MAXLEN], strupwd[TOKLEN], struname[TOKLEN] ;

WiFiClient client = wifiserver.available();

//---------------------------------------
// debug
// authorized=true;

strcpy(strinput, "");
strcpy(strupwd, "");
strcpy(struname, "");

while ( client.connected() ) {
if (authorized) return;


readString.toCharArray(strinput, MAXLEN);
// cstringarg( char* haystack, char* vname, char* sarg )
// haystack pattern: &varname=1234abc, delimiters &, \n, \0, SPACE, EOF
cstringarg(strinput, "uname", struname); // uname
cstringarg(strinput, "upwd", strupwd); // upwd

// debug
Serial.print("strupwd >>>"); Serial.print(strupwd); Serial.println("<<<");
Serial.print("website_upwd>>>"); Serial.print(website_upwd); Serial.println("<<<");


if ( (strlen(strupwd) == strlen(website_upwd) )
&& (strcmp(website_upwd, strupwd ) == 0)
)
{
authorized = true;
//debug
//Serial.print("check: authorized="); Serial.println(authorized);
readString = "";
return;
}

if ( client.available() ) {
char c = client.read();

//read char by request
if (readString.length() < TOKLEN) {

//store characters to string
readString += c;
Serial.println(c);
}

//if HTTP request has ended
if (c == '\n') {
client.flush();


//now output html data header

String script = "";

script += ("HTTP/1.1 401 Log-In Required");
script += ("Content-Type: text/html \n");
script += ("\n"); // do not forget this one //????
script += ("<!DOCTYPE html> \n");
script += ("<html> \n");
script += ("<head> \n");


// utf-8 für "°" Zeichen
script += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> \n" ;
script += "<title>" ;
script += website_title ;
script += "</title> \n" ;
script += "</head> \n" ;
script += "<body> \n" ;

script += "<h1><p style=\"color:rgb(255,0,191);\"> " + (String)website_url ;
script += (String)": &nbsp; <wbr> <wbr> " + "Not authorized !</p> </h1> \n" ;
script += ("<h2><p style=\"color:rgb(255,0,191);\"> log in to proceed: </p> </h2> \n");

script += ("<FORM ACTION='/' method=GET > \n");
script += ("<h2>user name: <INPUT TYPE=text NAME='uname' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2>password : <INPUT TYPE=PASSWORD NAME='upwd' VALUE='' MAXLENGTH='50'> </h2> \n");

script += ("<h2><INPUT TYPE=SUBMIT></h2> \n");

script += ("</FORM> \n");
script += ("<BR> \n");
script += ("</body> \n");
script += ("</html> \n");

client.print(script);

//stopping client
client.stop();

delay(1);

//clearing string for next read
readString = "";
}
}
delay(1);
}
}


//----------------------------------------------------------------------------

void handleWebsite() {

WiFiClient client = wifiserver.available();

//---------------------------------------
// Check if a client has connected


// Read the first line of the request
String request = client.readStringUntil('\r');
Serial.println(request);
client.flush();

//---------------------------------------
// LogOut
if (request.indexOf("/logout") != -1) {
authorized = false;
return;
}

delay(1);

//---------------------------------------
// Return the response

String script = "";

// init website

script += ("HTTP/1.1 200 OK \n");
script += ("Content-Type: text/html \n");
script += ("\n"); // do not forget this one
script += ("<!DOCTYPE html> \n");
script += ("<html> \n");

// head + title
script += ("<head> \n");
// autom. Aktualisierung alle 20 sec.

script += "<meta http-equiv=\"refresh\" content=\"20; URL=";
script += (String)website_url + ":" + (String)http_port + "\"> \n" ;


// utf-8 für "°" Zeichen
script += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> \n" ;
script += ("<title>");
script += (website_title);
script += ("</title> \n");
script += ("</head> \n");

// body + caption
script += ("<body> \n");
script += ("<h1> <p> ");
script += ("<font style=\"color:rgb(255,0,204);\"> HELLO WORLD! ");
script += ("&nbsp; <wbr> <wbr> ");
script += ("<font style=\"color:rgb(0,205,102);\"> Welcome to " + (String)website_url );
script += ("! </p> </h1> "); // script+= ("! </p> </h1> \n");


delay(1);


//---------------------------------------
script += "<h2> <br> \n HEIMSERVER <br> \n </h2>";
//---------------------------------------
// remote buttons Server
// <input type="button" value="submit" style="height: 100px; width: 100px; left: 250; top: 250;">
// <button style=\"height:200px;width:200px\"> </button>



client.print(script);
script = "";


//---------------------------------------
// sensors Server
// chart table
//---------------------------------------
// text font Courier, color black
script += ("<p> <font face=\"courier\"> "); // <<< Courier
script += "<h2> ";
script += "<p style=\"color:rgb(0,0,0);\" > </p> " ;
script += ("<br> \n");
script += "</h2>";

client.print(script);
script = "";


script += ("<br> \n");


// log out
script += ("<h3>Log Out: ");
script += ("<a href=\" /logout\"\"> <button style=\"height:70px;width:140px\" > Log Out </button></a> </h3> ");

script += WiFi.localIP().toString() + " " + (String)ssid + " <br>" ;
script += "</font> </p> \n";

script += "</body> \n";
script += "</html> \n";

client.print(script);

delay(1);

}


- - - Aktualisiert - - -

beide codes lassen sich aber fehlerfrei compilieren bei mir, evtl versuche es unmittelbar ein 2. oder 3. Mal hinterher. Manchmal liegt es an einer temp. Datei, die momentan nicht überschrieben werden konnte.
Falls es doch nicht funzt: wie ist die exakte vollständige Fehlermeldung?

Moppi
19.08.2018, 10:26
ESP8266WebServer.h als alternative Lösung

Beispiel: http://.../xxxx.htm?uname=uschi


ESP8266WebServer webserver(80); //Webserver-Instanz für Port 80 erstellen
String filename = webserver.uri(); //Liefert "xxxx.htm"
String par1 = webserver.arg(F("uname")); //Liefert "uschi"

Wenn Du als Webseite nur "/" angibst, liefert webserver.arg(F("uname")); ebenfalls "uschi" und webserver.uri() liefert "/".

Mit ESP8266WebServer.h lassen sich Parameter sehr einfach abfragen. Du kannst jeden beliebigen Parameter abfragen, die Anzahl Parameter ermitteln etc.
Allerdings verwendest Du WiFiServer, auf Port 80.

Allerdings kannst Du auch eine Instanz von ESP8266WebServer auf Port 80 erstellen und dann so die Argumente auslesen.


Der erste Parameter wird an eine Webseite immer mit ? übergeben und jeder weitere mit &.

HaWe
19.08.2018, 10:50
ja, das mit ESP8266WebServer webserver.arg("uname") weiß ich und nutze ich auch für die Verbindung zu meinen Clients (Port 8081):
ESP8266WebServer lanserver(8081);
(ich habe ja beide libs eingebunden), aber ich wüsste nicht, wie mein Code umgestrickt werden müsste, damit auch die websites zusätzlich mit ESP8266WebServer statt mit WiFiServer laufen.

Immerhin aber funktioniert doch cstringarg korrekt, er findet alle Suchstrings korrekt in allen testcodes, in meinem speziellen Fall steht da ja auch
&upwd=yy
drin, und auch das wird gefunden, also wo ist das Problem dann?
Was macht das Programm bei dir, wenn du es compilierst und ausführst, ggf. mit weiteren Serial.println zum debuggen?

- - - Aktualisiert - - -

den cstrinarg code habe ich jetzt umgestrickt auch für '?', trotzdem der alte upwd Fehler:


int16_t strstrpos(char * haystack, char * needle) // find 1st occurance of substr in str
{
char *p = strstr(haystack, needle);
if (p) return p - haystack;
return -1; // Not found = -1.
}

//----------------------------------------------------------------------------
const int MAXLEN = 1024;
const int TOKLEN = 64;

char * cstringarg( char* haystack, char* vname, char* sarg ) {
int i=0, pos=-1;
unsigned char ch=0xff;
char kini[3] = "&"; // start of varname: '&':
char kequ[3] = "="; // end of varname, start of argument: '='
char needle[TOKLEN]=""; // complete pattern: &varname=abc1234


strcpy(sarg,"");
strcpy(needle, kini);
strcat(needle, vname);
strcat(needle, kequ);
pos = strstrpos(haystack, needle);
if(pos==-1) {
needle[0]='?';
pos = strstrpos(haystack, needle);
if(pos==-1) return sarg;
}
pos=pos+strlen(vname)+2; // start of value = kini+vname+kequ
while( (ch!='&')&&(ch!='\0') ) {
ch=haystack[pos+i];
if( (ch=='&')||(ch==';')||(ch==' ')||(ch=='\0') ||(ch=='\n')
||(i+pos>=strlen(haystack))||(i>TOKLEN-1) ) {
sarg[i]='\0';
return sarg;
}
if( (ch!='&') ) {
sarg[i]=ch;
i++;
}
}
return sarg;
}

void setup() {
Serial.begin(115200);
Serial.println();
Serial.println("Test mit cstringarg()");
Serial.println();

char htmlstring[1024]="html teststring evtl mit Fehlern ?upwd0=QMARKupwd0&upwd1=testupwd1&upwd2=testupwd2 &upwd13=testupwd13&upwd224=testupwd224 EndeTststring";
char argstring[64]="";

cstringarg(htmlstring, "upwd0", argstring);
Serial.print("upwd0 >>"); Serial.print(argstring); Serial.println("<< soll: >>QMARKupwd0<<");

cstringarg(htmlstring, "upwd1", argstring);
Serial.print("upwd1 >>"); Serial.print(argstring); Serial.println("<< soll: >>testupwd1<<");

cstringarg(htmlstring, "upwd2", argstring);
Serial.print("upwd2 >>"); Serial.print(argstring); Serial.println("<< soll: >>testupwd2<<");

cstringarg(htmlstring, "upwd13", argstring);
Serial.print("upwd13 >>"); Serial.print(argstring); Serial.println("<< soll: >>testupwd13<<");

cstringarg(htmlstring, "upwd224", argstring);
Serial.print("upwd224 >>"); Serial.print(argstring); Serial.println("<< soll: >>testupwd224<<");

cstringarg(htmlstring, "upwd9", argstring);
Serial.print("upwd9 >>"); Serial.print(argstring); Serial.println("<< soll: >><< (// not found)");

}

void loop() {

}



wo also liegt das TOP Problem, wenn der Eingabestring anfangs identisch, aber insgesamt zu lang ist?

Moppi
19.08.2018, 10:53
Ich denke, Du machst eine neue Instanz: ESP8266WebServer nocheinwebserver(80); //Webserver-Instanz für Port 80 erstellen

Und wenn Du auf Deine Argumente abfragen willst, operierst Du dann mit: nocheinwebserver.arg(F("uname"));
Wobei man wohl nicht vergessen darf, auch ein nocheinwebserver.handleClient(); einzubauen.

HaWe
19.08.2018, 10:58
das ist mir jetzt zu kompliziert mit einer zusätzlichen ESP8266WebServer instanz, und man kann ja WiFiServer nicht durch ESP8266WebServer ersetzen , insb. hat ja 'class ESP8266WebServer' keine Methode 'available' etc.
cstringarg funktioniert jetzt einwandfrei, auch mit '?', ich brauche also auch kein ESP8266WebServer webserver.arg("uname")

hast du es jetzt mal gestartet und nach dem Fehler gesucht?

Moppi
19.08.2018, 11:24
er bringt auf jeden fall Hinweise:



C:\Users\TT\Documents\Arduino\sketch_aug19a\sketch _aug19a.ino: In function 'void handleNotAuthorized()':

C:\Users\TT\Documents\Arduino\sketch_aug19a\sketch _aug19a.ino:218:43: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

cstringarg(strinput, "uname", struname); // uname

^

C:\Users\TT\Documents\Arduino\sketch_aug19a\sketch _aug19a.ino:219:41: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

cstringarg(strinput, "upwd", strupwd); // upwd


^

aber meldet sich nicht am Router an.

HaWe
19.08.2018, 11:25
das sind doch keine Fehler, es läuft trotzdem.

Moppi
19.08.2018, 11:28
Moment ... jetzt ... Anmeldung hat funkt.

Wenn ich auf den Server gehe, kommt die Seite, dann gebe ich Passwort "manfred" ein und bekomme diese Ausgabe:


strupwd >>><<<
website_upwd>>>yy<<<
G
strupwd >>><<<
website_upwd>>>yy<<<
E
strupwd >>><<<
website_upwd>>>yy<<<
T
strupwd >>><<<
website_upwd>>>yy<<<

strupwd >>><<<
website_upwd>>>yy<<<
/
strupwd >>><<<
website_upwd>>>yy<<<
?
strupwd >>><<<
website_upwd>>>yy<<<
u
strupwd >>><<<
website_upwd>>>yy<<<
n
strupwd >>><<<
website_upwd>>>yy<<<
a
strupwd >>><<<
website_upwd>>>yy<<<
m
strupwd >>><<<
website_upwd>>>yy<<<
e
strupwd >>><<<
website_upwd>>>yy<<<
=
strupwd >>><<<
website_upwd>>>yy<<<
&
strupwd >>><<<
website_upwd>>>yy<<<
u
strupwd >>><<<
website_upwd>>>yy<<<
p
strupwd >>><<<
website_upwd>>>yy<<<
w
strupwd >>><<<
website_upwd>>>yy<<<
d
strupwd >>><<<
website_upwd>>>yy<<<
=
strupwd >>><<<
website_upwd>>>yy<<<
m
strupwd >>>m<<<
website_upwd>>>yy<<<
a
strupwd >>>ma<<<
website_upwd>>>yy<<<
n
strupwd >>>man<<<
website_upwd>>>yy<<<
f
strupwd >>>manf<<<
website_upwd>>>yy<<<
r
strupwd >>>manfr<<<
website_upwd>>>yy<<<
e
strupwd >>>manfre<<<
website_upwd>>>yy<<<
d
strupwd >>>manfred<<<
website_upwd>>>yy<<<

strupwd >>>manfred<<<
website_upwd>>>yy<<<
H
strupwd >>>manfred<<<
website_upwd>>>yy<<<
T
strupwd >>>manfred<<<
website_upwd>>>yy<<<
T
strupwd >>>manfred<<<
website_upwd>>>yy<<<
P
strupwd >>>manfred<<<
website_upwd>>>yy<<<
/
strupwd >>>manfred<<<
website_upwd>>>yy<<<
1
strupwd >>>manfred<<<
website_upwd>>>yy<<<
.
strupwd >>>manfred<<<
website_upwd>>>yy<<<
1
strupwd >>>manfred<<<
website_upwd>>>yy<<<


strupwd >>>manfred<<<
website_upwd>>>yy<<<



Bei Eingabe von "yy":



strupwd >>><<<
website_upwd>>>yy<<<
G
strupwd >>><<<
website_upwd>>>yy<<<
E
strupwd >>><<<
website_upwd>>>yy<<<
T
strupwd >>><<<
website_upwd>>>yy<<<

strupwd >>><<<
website_upwd>>>yy<<<
/
strupwd >>><<<
website_upwd>>>yy<<<
?
strupwd >>><<<
website_upwd>>>yy<<<
u
strupwd >>><<<
website_upwd>>>yy<<<
n
strupwd >>><<<
website_upwd>>>yy<<<
a
strupwd >>><<<
website_upwd>>>yy<<<
m
strupwd >>><<<
website_upwd>>>yy<<<
e
strupwd >>><<<
website_upwd>>>yy<<<
=
strupwd >>><<<
website_upwd>>>yy<<<
&
strupwd >>><<<
website_upwd>>>yy<<<
u
strupwd >>><<<
website_upwd>>>yy<<<
p
strupwd >>><<<
website_upwd>>>yy<<<
w
strupwd >>><<<
website_upwd>>>yy<<<
d
strupwd >>><<<
website_upwd>>>yy<<<
=
strupwd >>><<<
website_upwd>>>yy<<<
y
strupwd >>>y<<<
website_upwd>>>yy<<<
y
strupwd >>>yy<<<
website_upwd>>>yy<<<
GET /?uname=&upwd=yy HTTP/1.1


Dann kommt die richtige Seite, weil angemeldet und bei Klicken auf Logout kehrt er zurück zur Login-Seite.

HaWe
19.08.2018, 14:00
ja,
so sollte es auch sein.

auf user name wird noch nicht geprüft in dieser debug-Version, hier werden noch alle möglichen Eingaben akzeptiert.

yy
ist dann auch das korrekte Passwort für alle User.

allerdings wird eben auch
yy67
als korrekt akzeptiert, was nicht sein dürfte (IMO)

- - - Aktualisiert - - -

PS,
Finden kann er hier uname und struname auch noch nicht im html string, da dort ja '?uname=' steht und nicht '&uname=', was aber nachrangig ist, da ja auch noch nicht darauf geprüft wird.

- - - Aktualisiert - - -

PS,
hier ist die neue cstringarg Version mit testcode, wo auch ?varname= neben &varname= akzeptiert wird:



int16_t strstrpos(char * haystack, char * needle) // find 1st occurance of substr in str
{
char *p = strstr(haystack, needle);
if (p) return p - haystack;
return -1; // Not found = -1.
}

//----------------------------------------------------------------------------
const int MAXLEN = 1024;
const int TOKLEN = 64;

char * cstringarg( char* haystack, char* vname, char* sarg ) {
int i=0, pos=-1;
unsigned char ch=0xff;
char kini[3] = "&"; // start of varname: '&':
char kequ[3] = "="; // end of varname, start of argument: '='
char needle[TOKLEN]=""; // complete pattern: &varname=abc1234


strcpy(sarg,"");
strcpy(needle, kini);
strcat(needle, vname);
strcat(needle, kequ);
pos = strstrpos(haystack, needle);
if(pos==-1) {
needle[0]='?';
pos = strstrpos(haystack, needle);
if(pos==-1) return sarg;
}
pos=pos+strlen(vname)+2; // start of value = kini+vname+kequ
while( (ch!='&')&&(ch!='\0') ) {
ch=haystack[pos+i];
if( (ch=='&')||(ch==';')||(ch==' ')||(ch=='\0') ||(ch=='\n')
||(i+pos>=strlen(haystack))||(i>TOKLEN-1) ) {
sarg[i]='\0';
return sarg;
}
if( (ch!='&') ) {
sarg[i]=ch;
i++;
}
}
return sarg;
}

void setup() {
Serial.begin(115200);
Serial.println();
Serial.println("Test mit cstringarg()");
Serial.println();

char htmlstring[1024]="html teststring evtl mit Fehlern ?upwd0=QMARKupwd0&upwd1=testupwd1&upwd2=testupwd2 &upwd13=testupwd13&upwd224=testupwd224 EndeTststring";
char argstring[64]="";

cstringarg(htmlstring, "upwd0", argstring);
Serial.print("upwd0 >>"); Serial.print(argstring); Serial.println("<< soll: >>QMARKupwd0<<");

cstringarg(htmlstring, "upwd1", argstring);
Serial.print("upwd1 >>"); Serial.print(argstring); Serial.println("<< soll: >>testupwd1<<");

cstringarg(htmlstring, "upwd2", argstring);
Serial.print("upwd2 >>"); Serial.print(argstring); Serial.println("<< soll: >>testupwd2<<");

cstringarg(htmlstring, "upwd13", argstring);
Serial.print("upwd13 >>"); Serial.print(argstring); Serial.println("<< soll: >>testupwd13<<");

cstringarg(htmlstring, "upwd224", argstring);
Serial.print("upwd224 >>"); Serial.print(argstring); Serial.println("<< soll: >>testupwd224<<");

cstringarg(htmlstring, "upwd9", argstring);
Serial.print("upwd9 >>"); Serial.print(argstring); Serial.println("<< soll: >><< (// not found)");

}

void loop() {

}

Moppi
19.08.2018, 16:28
So wie ich das sehe wird in einer Schleife der String zusammengesetzt vom Parameter upwd. Und nach jedem Zeichen wird geprüft, ob das Password stimmt. Irgendwann gibt es eine Übereinstimmung und die restlichen Zeichen des gesendeten Passwords werden nicht mehr berücksichtigt. Erst muss der gesamte String zusammen sein, von upwd. Dann erst darf geprüft werden.

Hier sieht man das:


strupwd >>><<<
website_upwd>>>yy<<<
y
strupwd >>>y<<<
website_upwd>>>yy<<<
y
strupwd >>>yy<<<
website_upwd>>>yy<<<
GET /?uname=&upwd=yy11111111111111 HTTP/1.1

HaWe
19.08.2018, 16:33
ja, den Verdacht hatte ich ja auch schon, aber wie kann man das ändern`?

Moppi
19.08.2018, 16:55
Änderungen:



if ( client.available() ) {
char c = client.read();
....
}else stringok = true;


if ( stringok && (strlen(strupwd) == strlen(website_upwd)) && (strcmp(website_upwd, strupwd) == 0) )
{
authorized = true;
//debug
//Serial.print("check: authorized="); Serial.println(authorized);
readString = "", stringok = false;
return;
}

void handleNotAuthorized() {
....
bool stringok = false;


Dann funktioniert es. Allerdings wahrscheinlich nur, weil nach dem Password der String auch endet. Sollte nach &upwd=yy noch was stehen wie: &upwd=yy&name=uschi könnte es sein, dass es wieder nicht funktioniert. Das habe ich nicht probiert.

HaWe
19.08.2018, 17:33
außerhalb von handleNotAuthorized() testen? oder ist da dein Code irgendwie durcheinander?

Könntest du evtl bitte mal den kompletten Code posten?

- - - Aktualisiert - - -

klappt nicht bei mir, oder dein Code ist unvollständig... :(

Moppi
19.08.2018, 17:58
Erst hat es funktioniert, nun wieder nicht. Merkwürdige Sache!

Fest steht, dass in der Schleife die Variable readString zusammengesetzt wird. Das muss von der Prüfung des Passwortes abgekoppelt werden. Zurzeit läuft das Ding in einer Schleife und macht nach jedem Zeichen den Test, ob das Passwort schon stimmig ist. Das geht nicht. Warum nach mehrfachen Versuchen meine Änderungen auch nichts mehr bringen, zuvor aber schon, ist auch ein Rätsel. Daher kann man das erst mal vergessen. Ich hatte nur Codeschnipsel aufgeführt und die Änderungen in Rot, damit man sieht wo die im Quelltext stehen.

- - - Aktualisiert - - -

Dieses Konstrukt:




//read char by request
if (readString.length() < TOKLEN) {

//store characters to string
readString += c;
Serial.println(c);
}



müsste erstmal geändert werden in das:




//read char by request
while (readString.length() < TOKLEN) {

//store characters to string
readString += c;
Serial.println(c);
}



damit der String komplett gelesen wird.
Und hier erkennt man das erste Problem, dass sich nämlich das Lesen der Zeichen einzig nach TOKLEN richtet. TOKLEN muss daher zuerst die Länge haben, die das vom Browser übermittelte Passwort eben hat.
Die Schwierigkeit daran ist, dass die Abarbeitung des gesamten Input-Strings (der vom Browser kommt) Zeichen um Zeichen geschieht, in einer Schleife, wo dann auch auf '\n' geprüft wird und ob das Passwort richtig ist. Und das ist alles ineinander verschachtelt.

HaWe
19.08.2018, 18:26
hast du denn einen Vorschlag (neuer Code für handleNotAuthorized ), wie es korrekt funktioniert?

bisher hat der Code (auch deiner oben mit den roten Änderungen) noch nicht funktioniert, bei diesem wurde noch nicht einmal das 100%ig korrekte Passwort akzeptiert...
Aber wie gesagt, wenn dein Code von dir getestet wurde, dann poste ihn doch bitte einmal vollständig (handleNotAuthorized)!

Moppi
19.08.2018, 18:41
Ich glaub ja:


void handleNotAuthorized() {
String readString = "";
char strinput[MAXLEN], strupwd[TOKLEN], struname[TOKLEN] ;

WiFiClient client = wifiserver.available();

//---------------------------------------
// debug
// authorized=true;

strcpy(strinput, "");
strcpy(strupwd, "");
strcpy(struname, "");

while ( client.connected() ) {
if (authorized) return;


if ( client.available() ) {
char c = client.read();

//read char by request
readString = "";
while ( (readString.length() < TOKLEN) && (c != '\n') ) {
readString += c;
c = client.read();
}


readString.toCharArray(strinput, MAXLEN);
// cstringarg( char* haystack, char* vname, char* sarg )
// haystack pattern: &varname=1234abc, delimiters &, \n, \0, SPACE, EOF
cstringarg(strinput, "uname", struname); // uname
cstringarg(strinput, "upwd", strupwd); // upwd

// debug
Serial.print("strupwd >>>"); Serial.print(strupwd); Serial.println("<<<");
Serial.print("website_upwd>>>"); Serial.print(website_upwd); Serial.println("<<<");
Serial.print("readString>>>");Serial.println(readString);


if ( (strlen(strupwd) == strlen(website_upwd)) && (strcmp(website_upwd, strupwd) == 0) )
{
authorized = true;
//debug
//Serial.print("check: authorized="); Serial.println(authorized);
readString = "";
return;
}



//if HTTP request has ended
if (c == '\n') {
client.flush();


//now output html data header

String script = "";

script += ("HTTP/1.1 401 Log-In Required");
script += ("Content-Type: text/html \n");
script += ("\n"); // do not forget this one //????
script += ("<!DOCTYPE html> \n");
script += ("<html> \n");
script += ("<head> \n");


// utf-8 für "°" Zeichen
script += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> \n" ;
script += "<title>" ;
script += website_title ;
script += "</title> \n" ;
script += "</head> \n" ;
script += "<body> \n" ;

script += "<h1><p style=\"color:rgb(255,0,191);\"> " + (String)website_url ;
script += (String)": &nbsp; <wbr> <wbr> " + "Not authorized !</p> </h1> \n" ;
script += ("<h2><p style=\"color:rgb(255,0,191);\"> log in to proceed: </p> </h2> \n");

script += ("<FORM ACTION='/' method=GET > \n");
script += ("<h2>user name: <INPUT TYPE=text NAME='uname' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2>password : <INPUT TYPE=PASSWORD NAME='upwd' VALUE='' MAXLENGTH='50'> </h2> \n");

script += ("<h2><INPUT TYPE=SUBMIT></h2> \n");

script += ("</FORM> \n");
script += ("<BR> \n");
script += ("</body> \n");
script += ("</html> \n");

client.print(script);

//stopping client
client.stop();

delay(1);

//clearing string for next read
//readString = "";
}
}
delay(1);
}
}


Ersetzen tust Du bitte nur die Funktion handleNotAuthorized().

Zuerst muss der gesamte String vom Browser gelesen werden oder bis TOKLEN erreicht ist. Danach kann man die Parameter mit cstringarg rausfischen und das dann prüfen.
Vorher war es anders herum: Erst wurde der Parameter für Passwort geprüft und dann ein Zeichen von den gesendeten Browserdaten gelesen, das eine Zeichen wurde angehängt und dann begann der Spaß von vorn.
:confused:

HaWe
19.08.2018, 19:10
JAAAAAAA !!
PERFEKT! WUNDERBAR! \\:D/\\:D/\\:D/
TAUSEND DANK! :cool::cool::cool: