Pagina 1 di 3

Richiesta http

MessaggioInviato: 15 ott 2021, 22:54
da daniele1996
Sto sviluppando un web server, e sono arrivato al punto di upload dei file.
Ho sviluppato un programma che accetta la richiesta e restituisce una risposta da me prefissata da me. e un esempio di richiesta http con upload è questa:

Codice: Seleziona tutto
POST /upload.php HTTP/1.1\r\n
Host: 127.0.0.1:8083\r\n
Connection: keep-alive\r\n
Content-Length: 429\r\n
Cache-Control: max-age=0\r\n
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"\r\n
sec-ch-ua-mobile: ?0\r\n
Upgrade-Insecure-Requests: 1\r\n
Origin: null\r\n
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryyAgwyAoOAfBRKxZd\r\n
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\n
Sec-Fetch-Site: cross-site\r\n
Sec-Fetch-Mode: navigate\r\n
Sec-Fetch-User: ?1\r\n
Sec-Fetch-Dest: document\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7\r\n\r\n
------WebKitFormBoundaryyAgwyAoOAfBRKxZd\r\n
Content-Disposition: form-data; name="the_file"; filename="miofile.txt"\r\n
Content-Type: text/plain\r\n\r\n
riga 1\n
riga 2\n
riga 3\n
\n
\n
riga 6\n
riga 7\n
\n
\n
riga 10\n
\r\n
------WebKitFormBoundaryyAgwyAoOAfBRKxZd\r\n
Content-Disposition: form-data; name="the_file1"; filename="miofile.txt"\r\n
Content-Type: text/plain\r\n\r\n
riga 1\n
riga 2\n
riga 3\n
\n
\n
riga 6\n
riga 7\n
\n
\n
riga 10\n
\r\n
------WebKitFormBoundaryyAgwyAoOAfBRKxZd--\r\n




la richiesta è divisa in due segmenti: la parte della richiesta (ottenuta con una prima chiamata a funzione :
Codice: Seleziona tutto
recv(clientfd, recvstr, 10KB,0);

e l'upload richiamando di nuovo la recv questa volta il buffer viene allocato temporaneamente e la sua dimensione viene fornita in "Content-Lenght: 429\r\n" e quindi viene allocata e riempita con la successiva recv.

fin qua tutto a posto, dividendo la stringa e memorizzandola in una lista i singoli elementi vengono memorizzati e visualizzati correttamente.
Codice: Seleziona tutto
tmphead = searchRequestField(req->requestrx,"Content-Length:");
   if(tmphead != NULL){
      sscanf(tmphead->str,"Content-Length: %ld",&req->upload_size);
      req->upload = malloc(req->upload_size * sizeof(char));
      create_upload(req);
      //printf(req->upload);
      //size_t intestazione = 0;
      //size_t iniziofile = 0;
      //size_t finefile = 0;
      /*for(size_t i = 0; i < req->upload_size; i++){
         if(*(req->upload+i) == '\r' && *(req->upload+i+1) == '\n' ){

         }
      }
      */
      size_t a = 0;
      size_t b = 0;
      void * tmpptr;
      void * tmpptr1;
      size_t next = 0;
      /*
      FILE *fp;


      char * namefile;//in a list
      char * fieldname;
*/
      struct upload_request *uptmp;
      //strcat(tmp->upload,"------WebKitFormBoundaryyAgwyAoOAfBRKxZd\r\n");
      //strcat(tmp->upload,"Content-Disposition: form-data; name=\"the_file\"; filename=\"miofile.txt\"\r\n");
      //strcat(tmp->upload,"Content-Type: text/plain\r\n\r\n");
      tmpptr1 = malloc(req->upload_size);
      memcpy(tmpptr1,req->upload,req->upload_size);
      //printf("%s\n",(char *)tmpptr);
      req->upreq = (struct upload_request *)malloc(sizeof(struct upload_request));
      uptmp = req->upreq;
      uptmp->fieldname    = (char *) malloc(50 * sizeof(char));
      uptmp->name       = (char *) malloc(50 * sizeof(char));
      uptmp->ctype       = (char *) malloc(50 * sizeof(char));
      uptmp->cdisposition = (char *) malloc(50 * sizeof(char));
      uptmp->next = NULL;
      do{
         //if(next == 0){
            token = strtok((char *)(tmpptr1+next),"\r\n");
         /*}else{
            token = strtok(NULL,"\r\n");
            printf("->>%s<<-",token);
            break;
         }*/
         //token = strtok(NULL,"\r\n");

         token = strtok(NULL," ");
         token = strtok(NULL,";");
         strcpy(uptmp->cdisposition,token);

         //sscanf(token,"Content-Disposition: %s\0",uptmp->cdisposition);
         //strcpy(uptmp->cdisposition,token + strlen("Content-Disposition: "));
         token = strtok(NULL,"\"");
         token = strtok(NULL,"\"");
         strcpy(uptmp->fieldname,token);
         token = strtok(NULL,"\"");
         token = strtok(NULL,"\"");
         //printf("%s\n",token);
         strcpy(uptmp->name,token);
         token = strtok(NULL," ");
         token = strtok(NULL,"\r\n\r\n");
         strcpy(uptmp->ctype,token);
         /*while(1);
         //sscanf(token,"Content-Disposition: %s",uptmp->cdisposition);
         //sscanf(token,"Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n",uptmp->fieldname,uptmp->name);
         token = strtok(NULL,"\r\n\r\n");
         sscanf(token,"Content-Type: %s",uptmp->ctype);

         */
         printf("Field Name: %s\n",uptmp->fieldname);
         printf("File Name: %s\n",uptmp->name);
         printf("Content Type: %s\n",uptmp->ctype);
         printf("Content Disposition: %s\n",uptmp->cdisposition);

         /*token = strtok(NULL,"\n\r\n");//\n\r\n
         uptmp->file = malloc(strlen(token));
         strcpy(uptmp->file,token);
         printf("File: \n\n\n %s \n\n\n",(char *)uptmp->file); not working
         */

         memcpy(tmpptr1,req->upload,req->upload_size);

         tmpptr = strstr(tmpptr1+next,"\r\n\r\n");
         a = tmpptr - (tmpptr1) + 4 ;
         //printf("%s\n",tmpptr1+a);
         printf("%ld\n",a);
         tmpptr = strstr(tmpptr1+next+a,"\n\r\n");
         printf("%p",tmpptr);
         b = (tmpptr - tmpptr1) - a + 1;//+1;
         printf("%ld\n",b);
         uptmp->file = malloc(b);
         memcpy(uptmp->file,tmpptr1+next+a,b);
         printf("File:\n%s",(char *)uptmp->file);
         token = strtok((char *)(tmpptr1+next+b+a),"\r\n");
         //if(token == NULL)break;
         memcpy(tmpptr1,req->upload,req->upload_size);
         next = next + (token - (char *)tmpptr1)+2;
         printf("\n\n%s\n",token);

         uptmp->next = (struct upload_request *)malloc(sizeof(struct upload_request));
         uptmp = uptmp->next;
         uptmp->fieldname    = (char *) malloc(50 * sizeof(char));
         uptmp->name       = (char *) malloc(50 * sizeof(char));
         uptmp->ctype       = (char *) malloc(50 * sizeof(char));
         uptmp->cdisposition = (char *) malloc(50 * sizeof(char));
         uptmp->next = NULL;
         //next = 1;
         //
         //printf("\n\n%s\n",token);
         //token = strtok(NULL,"\r\n");

         }while(next < req->upload_size);
         while(1);

Come è possibile notare nell'upload la stringa fino al content type va divisa e a questo confine continua con il file, quindi va calcolato l'inizio del file, e questa parte di codice lo svolge correttamente, sscanf non funziona bene, però comunque ho risolto con strtok(..).
Arrivato alla seconda esecuzione il programma crasha
Codice: Seleziona tutto
server@server:~/Documenti/eclipse_workspace_c1/request_parser/Debug$ ./request_parser
POST /upload.php? HTTP/1.1
Host: 127.0.0.1:8083
Connection: keep-alive
Content-Length: 429
Cache-Control: max-age=0
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"
sec-ch-ua-mobile: ?0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryyAgwyAoOAfBRKxZd
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Cookie: Test1=Testata; Test2=Testata; Test3=Testata
Accept-Language: it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7
fname=aaa&lname=bbb





Field Name: the_file
File Name: miofile.txt
Content Type: text/plain
Content Disposition: form-data
143
0x556d424c293d47
File:
riga 1
riga 2
riga 3


riga 6
riga 7


riga 10


------WebKitFormBoundaryyAgwyAoOAfBRKxZd
Content-Disposition: form-data; name="the_file1"; filename="miofile.txt"
Content-Type: text/plain

riga 1
riga 2
riga 3


riga 6
riga 7


riga 10

------WebKitFormBoundaryyAgwyAoOAfBRKxZd--

Field Name: the_file1
File Name: miofile.txt
Content Type: text/plain
Content Disposition: form-data
336
(nil)-93927752083919
Errore di segmentazione (core dump creato)
server@server:~/Documenti/eclipse_workspace_c1/request_parser/Debug$


Mi domando: esiste un metodo migliore per scrivere questo codice?
Tipo, strtok non rischia di crashare se mando dati?
altrimenti devo ricorrere al for che scansiona tutta l'area di memoria...

Re: Richiesta http

MessaggioInviato: 16 ott 2021, 8:02
da alev
Che linguaggio di programmazione stai usando?

Re: Richiesta http

MessaggioInviato: 16 ott 2021, 12:02
da GioArca67
memcpy
strstr
printf
malloc
Tutte le istruzioni terminate da ;
...sarà Algol? o BCPL?

Re: Richiesta http

MessaggioInviato: 16 ott 2021, 13:16
da alev
Boh, so solo che sembra fatto con qualche linguaggio interpretato :shock:

'Ste cose sarebbe sempre meglio usare linguaggi compilabili in linguaggio macchina, al massimo a runtime

Re: Richiesta http

MessaggioInviato: 16 ott 2021, 13:39
da nicsergio
È PHP.

Re: Richiesta http

MessaggioInviato: 16 ott 2021, 14:12
da alev
Mi pare una scelta perfetta: un webserver in PHP per pubblicare un'applicazione in PHP :roll: :shock:
Sicuramente, è un ottimo metodo per imparare la programmazione in PHP

Re: Richiesta http

MessaggioInviato: 16 ott 2021, 16:08
da fairyvilje
Gente, quello è C.

Edit: tutti i punti negativi di questo mondo non cambieranno il fatto che sia C :).

Re: Richiesta http

MessaggioInviato: 16 ott 2021, 16:12
da fairyvilje
In risposta all'OP, quello è ciò che succede con un linguaggio di programmazione che ti lascia lavorare coi puntatori in modo... discutibile.
PHP sarebbe molto più sicuro in questo contesto :D. Realisticamente se è una tua scelta, ti consiglio di valutare rust per questo tipo di applicazioni. Se è per un esame, buona fortuna!

Ti consiglio di installare valgrind che un profiler per i problemi legati alla memoria. Dovrebbe aiutarti ad isolare il problema. Ha una curva di apprendimento, specialmente per capire il senso dei suoi log, ma è uno strumento insostituibile :).

Re: Richiesta http

MessaggioInviato: 16 ott 2021, 16:34
da GioArca67
nicsergio ha scritto:È PHP.

Non è PHP.
Il PHP non è tipizzato e le variabili iniziano con $
Mentre nello stralcio pubblicato è evidente la dichiarazione del tipo.

Re: Richiesta http

MessaggioInviato: 16 ott 2021, 17:11
da nicsergio
GioArca67 ha scritto:Il PHP non è tipizzato e le variabili iniziano con $
Mentre nello stralcio pubblicato è evidente la dichiarazione del tipo.

Hai ragione, ho guardato troppo velocemente :ok: