Split di un char array

Buongiorno a tutti

Avrei bisogno di splittare un HTTP header il quale è una sequenza di char che arrivano in modalità seriale.
Non si può caricare tutto su stringhe perchè sono troppe, fare l'indexOf() dei parametri non mi serve perchè essi variano, quindi gestire i char non è proprio così facile e sono molte le parti che devo prelevare

Sapendo che:

  • ogni riga termina con un '\n'
  • le righe possono arrivare in ordine differente
  • ogni singolo parametro di linea è separato da una ','
  • ogni argomento di linea è separato da un solo ':' iniziale ...

esempio di header da spilttare

TWS: Returning 401
TWS: New request: GET / HTTP/1.1
path: /
Host: 192.168.2.177:9900
Connection: keep-alive
Accept-Encoding: gzip, deflate

User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53

Accept-Language: it-it

Authorization: Digest username="admin", realm="Remote Control", nonce="GyhtDk", uri="/", algorithm=MD5, response="1301b531398b24e975d079b9a2158078", opaque="012345"

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: y5GGHNbSD1AcLhh67wVIj==
Sec-WebSocket-Version: 13
Cookie: browser_aperto=mio_cookie

il tutto arriva da un while read ()
"ch" è il char seriale
prendiamo come esempio questa linea dove "admin" è il nome dell'utente e response="....." è la codifica MD5 di tutta la baracca che useremo come passw a 128 bit

Authorization: Digest username="admin", realm="Remote Control", nonce="GyhtDk", uri="/", algorithm=MD5, response="1301b531398b24e975d079b9a2158078", opaque="012345"

if (ch == ':'){ pos_copy_buff = 0;
copy_buffer[pos_copy_buff] = ch;
            if (pos_copy_buff + 1 <= sizeof(copy_buffer)) pos_copy_buff++;  // controllo che non superi la capienza [160]
      
      if (ch == ',' || ch == '\n') {
            copy_buffer[pos_copy_buff-1] = NULL;  // tolgo la ',' mettendo il terminatore indietro di 1
            pos_copy_buff = 0;  
            //Serial.println(String(copy_buffer)); // debug

Fino qui problemi non ci sono, la riga ottenuta è

: Digest username="admin"

ora devo trovare il nome dell'utente che si è collegato o che ci ha provato "admin" che si trova tra le " "

Andando avanti mi perdo con i terminatori

if(String(copy_buffer).indexOf("username") != -1) {
                //if(String(copy_buffer).indexOf("response") != -1) {
                  Serial.println(String(copy_buffer)); //debug
                  Serial.println(); //debug
                      
                      byte i;
                      for (i = 0; i < sizeof(copy_buffer) - 1; i++) {
                          
                         if (copy_buffer[i] == '=') {
                             pos_copy_buff = 0; // azzero la posizione  
                             i=i+2; // mi metto sul primo char dopo '"' (in questo esempio 'a')
                         }
                             
                          name_user[pos_copy_buff] = copy_buffer[i]; // copio tutti i char in sequenza su name_user
                          if (pos_copy_buff + 1 <= sizeof(name_user)) pos_copy_buff++; // controllo che non superi la capienza
                               
                         if (copy_buffer[i] == NULL){ // se trovo il terminatore
                           name_user[pos_copy_buff-2] = NULL; // chiudo col terminatore name_user 
                           pos_copy_buff = 0; 
                           break; //esco dal For 
                           }
                          
                          //Serial.print(copy_buffer[i]); //debug
                      }
                       //Serial.println(); //debug
                       Serial.print("name_user ");  //debug
                       Serial.println(String(name_user));  //debug
                       
                } 
                      
          }

A volte name_user è giusto, a volte è mozzato, a volte si pianta tutto :cold_sweat:
dov'è che sbaglio?
c'è un metodo un po' meno macchinoso?
usare miochar[0]=NULL; equivale a usare miochar[0]='\0'; ?

grazie, ciao

tempo fa scrissi una libreria che fa esattamente quello che cerchi, è leggera e "pulita" nella sua esecuzione: [completo]parser HTTP quasi REST aka "webServer" - Software - Arduino Forum

Grazie Lesto,
in realtà il GET, POST, PUT, Content-Type, estensioni dei FILE, PATH, lo faccio già da 2-3 anni e va perfettamente, ma è nata dopo la necessità di verificare chi ha accesso con diversi utenti e il relativo log eventi, un po' come

codice MASTER
codice INSTALLATORE
codice USER 1
codice USER 2
codice USER 3
codice USER 4

ciascuno con i suoi livelli e abilitazioni nel girare dentro alla programmazione e/o visualizzazione, è uscita poi la necessità di verificare con quale dispositivo l'utente si collega

iPhone
Samsung
tablet
Pc fisso
...

Con quale browser
Crhome
IE
Firefox
Opera

con quale sistema OP
Windows
Unix
Android

Ho aggiunto i cookie nel frattempo che ottimizzano e perfezionano le connessioni personalizzandole, questi sono tutti dati che si trovano in modo casuale da cercare, ma che rispettano comunque degli schemi

Ci do un occhiata ... grazie (non mi è nuovo sto file rest, devo averlo già visto quando lo hai pubblicato :slight_smile:

ciao

pablos:
usare miochar[0]=NULL; equivale a usare miochar[0]='\0'; ?

Penso che NULL non sia altro che una define di '\0'

che a sua volta non è altro che una define di 0 (zero), ma per leggibilità per favore usare NULL dove hai puntatori, '\0' dove hai un terminatore di stringa, un == invece che il valore secco negli if, etc..

pablos, la libreria se a apri e la guardi capirati come funziona e sono sicuro che ti stizzica; essa infatti NON ha bisogno di elaborare riga per riga, ma lavora lettera per lettera, quindi in memoria hai solo le righe che ti interessano, e in falsh (o in memoria) le stringe "di ricerca"

la mia lib butta via gli header, ma in pratica tu vorrai usare lo stesso codice che uso per estrapolare il path per estrapolare gli header; dovrebbe bastare sostituire la stringa di ricerca "GET" con quella dell'header (poi ovviamente duplicando la cosa, ma forse c'è già il spporto.. devo riverede il codice anche io, ma ricordo essere stato un gioco di stile e non un codice accozzaglia "che funziona")

Per la verità, l'inventore di NULL si è pentito di avere inventato il NULL. :stuck_out_tongue_closed_eyes:

basta che non lo usi :smiley: