Problem with HTTP Basic Authentication

Hi everybody.
I want to securise the acces to my server with a login/password
I found on the forum a sketch working fine.
But I wanted to add a button :

          client.println("<a href=\"/?TEST\"\">TEST</a>");

and a condition on that button:

          if (readString.indexOf("?TEST") > 0) {
              Serial.print("It works Fine !!!");//   Doesn't works!!!
              }

It doesn't works...

I have no problem with that if I don't want securise my server.

I tried to put the condition at differents places in the sketch: same problem

Someone as an idea?
Please, find my sketch below ( Login= Patrick Password= Homidom)

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,0, 111);
String readString;
// Initialize the Ethernet server library
// with the IP address and port you want to use 
// (port 80 is default for HTTP):
EthernetServer server(80);

void setup() {
// Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}


void SendOKpage(EthernetClient &client)
{
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connnection: close");
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
                   
          client.println("<a href=\"/?TEST\"\">TEST</a>");
        
        
        
              
          client.println("</html>");
          
          if (readString.indexOf("?TEST") > 0) {
              Serial.print("It works Fine !!!");//   Doesn't works!!!
              }
          
              
}


void SendAuthentificationpage(EthernetClient &client)
{
          client.println("HTTP/1.1 401 Authorization Required");
          client.println("WWW-Authenticate: Basic realm=\"Secure Area\"");
          client.println("Content-Type: text/html");
          client.println("Connnection: close");
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<HTML>  <HEAD>   <TITLE>Error</TITLE>");
          client.println(" </HEAD> <BODY><H1>401 Unauthorized.</H1></BODY> </HTML>");
}

char linebuf[80];
int charcount=0;
boolean authentificated=false;

void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    memset(linebuf,0,sizeof(linebuf));
    charcount=0;
    authentificated=false;
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        linebuf[charcount]=c;
        if (charcount<sizeof(linebuf)-1) charcount++;
        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
        
        if (c == '\n' && currentLineIsBlank) {
          if (authentificated)
            SendOKpage(client);
          else
            SendAuthentificationpage(client);  
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
          if (strstr(linebuf,"Authorization: Basic")>0 && strstr(linebuf,"UGF0cmljazpIb21pZG9t")>0)//  Patrick Homidom
            authentificated=true;
          memset(linebuf,0,sizeof(linebuf));
          charcount=0;
        } 
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    
     
              
              
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disonnected");
  }
}

Someone as an idea?

Ditch the String class altogether. The loop() function deals with strings. Quit using crutches in other functions.

Serial.write() to send a character looks sills.

Print the ENTIRE response, between start and end markers, so you have some idea what you are parsing.

Which Arduino are you using? How much free memory do you have? You can save a lot of it by using the F() macro.
client.println(F("HTTP/1.1 200 OK"));

Thank you paul for your response
But m'y poor english doesnt permit me to understand the first part....
So sorry for that!
For the second part: this is not a memory problem:
i tried with a mega and this is the same
Did you test my sketch?
Does It works?
Regards

Did you test my sketch?

No. I didn't need to. You already said that it doesn't.

I'm trying to help you figure out why it doesn't.

        if (c == '\n' && currentLineIsBlank) {
          if (authentificated)
            SendOKpage(client);
          else
            SendAuthentificationpage(client);  
          break;
        }

What is in linebuf[] when the '\n' arrives?

Serial.print("Client request: [");
Serial.print(linebuf);
Serial.println("]");

Of course, for that to work, you need to understand what a string is. A string is not JUST an array of chars. It is a NULL-terminated array of chars. Your array is not NULL terminated, therefore it is not a string, therefore it is inappropriate to treat it as a string.

This:

        linebuf[charcount]=c;
        if (charcount<sizeof(linebuf)-1) charcount++;

should be:

        linebuf[charcount]=c;
        if (charcount<sizeof(linebuf)-1) charcount++;
        linebuf[charcount] = '\0'; // Add a NULL terminator

PaulS:
I'm trying to help you figure out why it doesn't.

I'd not put too much efforts in it.

I think, he is just joking:

  • grabs working code from the forum
  • keeps the working code as a secret for himself

From the fully working code (I know the working code, I posted it into this forum), he just made a few changes, and that was enough. Declare a "String" object:

String readString;

So that object is an "empty String object" that doesn't contain anything. Always.
He never ever assigns anything to that variable in his code.

But then he does a comparison:

        if (readString.indexOf("?TEST") > 0) {
              Serial.print("It works Fine !!!");//   Doesn't works!!!
              }

Hahaha. Good joke!

I think he knows where in this forum he found the working code.

So if he'd like to discuss changes or additions to the working code, he should know where he could find the thread and ask additional questions about.

And of course you are absolutely right Paul: He should ditch the String class that he introduced into the sketch, and the relevant information he wants to extract run through the "linebuf" string during the HTTP request.

Of course, for that to work, you need to understand what a string is. A string is not JUST an array of chars. It is a NULL-terminated array of chars. Your array is not NULL terminated, therefore it is not a string, therefore it is inappropriate to treat it as a string.

A string of characters and a null terminated c-string should not confuse you.

Also note that having three !!! in your code can some times cause the compiler to have issues.

Also note that having three !!! in your code can some times cause the compiler to have issues.

Nope. The compiler has no problems. The bootloader on an older Mega might, but that's way downstream from the compiler.

I'm having trouble working what you want to accomplish.

You want a "condition on the button". What? What does "on" mean? Do you mean that you want something to happen when the user presses the button? When the sketch receives the form? Do you mean that you want the sketch to only include the button on the html form if the user is authenticated?

What has ''?TEST' got to do with anything? Why have you put it in the HREF attribute of an A tag? What is readString, and what is it supposed to contain at the time when SendOKPage is executed? I can't see that you are puting anything into it anywhere - what did you think it would contain?

Why do you send the OK or Authentication page as soon as you have read the HTTP headers? What about if there is a body to the request? Why are the nasty details of parsing an HTTP request jammed into the same loop that does your overall flow of control? Why not find an arduino HTTP library that works properly, and use that?

What - from the point of view of a user, not the point of view of the arduino - what happens when they interact with your HTTP form?