"Basic" Programming Difficult

Hi,

I'm trying to implement a Basic Authentication to my web server, using an Arduino Uno with a Ethernet Shield.
But my knowledge of programing is really basic, so I'm having troubles trying to handle a HTTP Header.

What I need to do is save this "Authorization: Basic YWRtaW46YWRtaW4=" (from the example header above) to a char or a string to compare, and see if the user is authorized (and send a 200 OK response) or no (and send a 401 Authorization Required Response).

GET / HTTP/1.1
Authorization: Basic YWRtaW46YWRtaW4=

I already burned my brains trying to do it, using a char array and / or strings, but I couldn't figure it out.

I was trying to use the HTTP_request, but it's buffer is to small to handle all the HTTP header (I already try to increase it, but if pass from 100 the Arduino frezzes, something with the 2k memory I think). So I need to create another char array to store the Authorization, but I can't figure how to do to it start saving only the caracters I need and stop when it ended.

Thanks in advance, any help or suggestion are really welcome.

I'd suggest stop burning your brains and buy, borrow or steal an elementary programming textbook and work through it. Or there are many free tutorials available on line. This is better than wasting time doing random nonsense without knowing what you are doing.

Well, for a start: Gammon Forum : Electronics : Microprocessors : Arduino programming traps, tips and style guide

void HTTP_401(EthernetClient client) {
  client.println("HTTP/1.1 401 Authorization Required");
  client.println("Content-Type: text/html");
  client.println("WWW-Authenticate: Basic realm=\"Automacao Residencial\"");
  client.println();
}

That's where most of your memory is going.

That's where most of your memory is going.

More of it is getting pissed away here:

            String POST = client.readString();
            String command = POST.substring(POST.indexOf('=') + 1, POST.indexOf('&'));
            String value = POST.substring(POST.lastIndexOf('=') + 1, POST.length());

Hello, thanks, for the suggestions, as I said, any suggestions are welcome!!

michinyon, I'm looking for many online tutorials and trying to learn while doing it, but I couldn't understand this case, that's why I came here looking for some advice.

Nick Gammon, Thank's for your advice, I already saw that (F) function, but I tought in doing this when the code was ready, but I will surely do it now to clear some memory...

PaulS, Yeah, I know that, but I couldn't figure any other way to do it. I tried using chars and strstr too, but couldn't make it to work. Do you have any suggestion?

Other than that, any suggestion how can I handle the Authorization part I need from the header?

I tried using chars and strstr too, but couldn't make it to work. Do you have any suggestion?

Banish the phrase "it didn't work" from your vocabulary. Post some code. Explain what it does, and does not do. Do not use the phrase "it didn't work". All that does is tempt us to hit the back key and go to the next post.

I'm sorry, I didn't have the code anymore. But actually my problem was the same that I have with the HTTP header, parse the POST parameters to a char to compare... Something like:

String POST = client.readString()

My post parameters looks like this:

command=Light&value=1
control=100&button=8

I made this script to exctract the information I needed, but I don't know how to save the exact parameters I need into a char...

  char* control = (strstr(HTTP_request, "=") + 1);
  char* button = (strstr(control, "=") + 1);
  (strstr(control, "&"))[0] = 0;

but I don't know how to save the exact parameters I need into a char...

Well, I don't either, since I don't know what "exact parameters" you need. Saving them into a char is probably not what you want to do, either.

strtok() will parse the string (assuming that it is a string, not a String). You can determine if the token is the name of interest ("command" vs "Light" vs "value" vs "1"). If it is, the next token is the value of interest.

Hmm.. You are right, but my problem is exactly that

(assuming that it is a string, not a String)

Let me try to explain better what I'm trying to do.

The part of handling the data, I already understand, I already tried strok, and strstr and bought worked for what I need that is compare it something else (command, value, etc.).

Lets say I received this data from the web server:

GET / HTTP/1.1
Authorization: Basic YWRtaW46YWRtaW4=

First of all this part of the sketch read and print the data received and "saves" it to a char named HTTP_request.

if (client.available()) { // client data available to read
        char c = client.read(); // read 1 byte (character) from client
        Serial.write(c); // print HTTP request character to serial monitor
        if (request_index < (REQUEST_BUF_SZ - 1)) {
          HTTP_request[request_index] = c; // save HTTP request character
          request_index++;
        }

Ok, then I use the HTTP_request to see if it's a post or get and execute the rest of the commands...

My problem is the HTTP_request have the size of only 25 characters, I already tried to increase to store all the HTTP request, (+- 250), but when it pass 100 the arduino freezes...

So, my problem, and what I'm looking for a solution is: How can I set another char, to store another 25 characters, and start on "Authorization: Basic" and finish on "YWRtaW46YWRtaW4="...

And even another char, to start on the POST parameters, something like "command=Light&value=1" that is received after the header of the HTTP request....

My english isn't good enough, I hope you understand what I tried to say.

My problem is the HTTP_request have the size of only 25 characters, I already tried to increase to store all the HTTP request, (+- 250), but when it pass 100 the arduino freezes...

You only need to store one record at a time.

GET / HTTP/1.1
Host: 192.168.1.5
Connection: keep-alive
Cache-Control: max-age=0
Authorization: Basic YWRtaW46YWRtaW4=
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2107.3 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4

That's 9 records.

Since the first character in the record of interest is 'A', you don't even need to store the others. You could even look at the second character to decide whether to continue storing, or not. That way, you'd only need to store and parse one record.

And, that's a far simpler task, isn't it?

So, my problem, and what I'm looking for a solution is: How can I set another char, to store another 25 characters, and start on "Authorization: Basic" and finish on "YWRtaW46YWRtaW4="...

Two things. First, you'll never store that record in a char. You need a char ARRAY. Life will get easier when you can use the terminology correctly.

Second, the Authorization record will not fit in a 25 character array. Make an 80 character array, and store each record as it arrives, IF it starts with 'A'. Continue saving the data if the next character is a 'u'.

For that matter, you can use a state machine. State machines let you parse incoming data "on the fly" in which case you only need to store one byte.

For example, this line:

Authorization: Basic YWRtaW46YWRtaW4=

You have a string in memory which is what you want to match on:

Authorization: Basic

As incoming characters arrive, you compare to that. As PaulS says, if, following a newline, you don't get "A" you can just ignore the entire rest of the line (until the next newline), storing nothing.

If you get "A" then you go to a new state (needing "u"). You do this by advancing a counter. If you don't get "u" you then do the same thing, ignore the line.

If you now have "Au" you check for a "t" (again, advancing a counter of what you are comparing against). And so on. If it passes all these tests you only have to save 14 characters (the authorisation code) and check they are followed by "=". Or you could even check that on-the-fly.

So you can see that needing to save 100 bytes or more just isn't necessary.

Welcome to the world of microcontrollers. You just have to do things a bit differently, than you do on a PC with a Gb of RAM.

That was exactly what I was thinking, after reading your posts so many times I finally understand it!!

Thanks very much Nick Gammon and PaulS.

:smiley: :smiley: :smiley: :smiley: :smiley: :smiley: :smiley: :smiley: