# C/Le applicazioni CGI

C
Copertina Tutti i moduli · Sviluppo
* LinguaggioC/Linguaggio
** PanoramicaC/Linguaggio/Panoramica
** Struttura del linguaggioC/Linguaggio/Struttura del linguaggio
* Variabili, operatori e costantiC/Variabili, operatori e costanti
** VariabiliC/Variabili, operatori e costanti/Variabili
** Operatori aritmeticiC/Variabili, operatori e costanti/Operatori aritmetici
** Operatori sui bitC/Variabili, operatori e costanti/Operatori sui bit
** CostantiC/Variabili, operatori e costanti/Costanti
* Blocchi e funzioniC/Blocchi e funzioni
** Blocchi if e switchC/Blocchi e funzioni/Blocchi if e switch
** Operatori logiciC/Blocchi e funzioni/Operatori logici
** CicliC/Blocchi e funzioni/Cicli
** FunzioniC/Blocchi e funzioni/Funzioni
** mainC/Blocchi e funzioni/main
** LibrerieC/Blocchi e funzioni/Librerie
** RicorsivitàC/Blocchi e funzioni/Ricorsività
* Vettori e puntatoriC/Vettori e puntatori
** VettoriC/Vettori e puntatori/Vettori
** PuntatoriC/Vettori e puntatori/Puntatori
** Interscambiabilità tra puntatori e vettoriC/Vettori e puntatori/Interscambiabilità tra puntatori e vettori
* StringheC/Variabili, operatori e costanti/Stringhe
* Enumerazioni, strutture e unioniC/Enumerazioni, strutture e unioni
** EnumerazioniC/Enumerazioni, strutture e unioni/Enumerazioni
** StruttureC/Enumerazioni, strutture e unioni/Strutture
** UnioniC/Enumerazioni, strutture e unioni/Unioni
* Conversioni di tipoC/Conversioni di tipo
* Lettura e scrittura su fileC/Lettura e scrittura su file
** File di TestoC/Lettura e scrittura su file/File di Testo
** File BinariC/Lettura e scrittura su file/File Binari
* Compilatore e precompilatoreC/Compilatore e precompilatore
** CompilatoreC/Compilatore e precompilatore/Compilatore
** DirettiveC/Compilatore e precompilatore/Direttive
** HeaderC/Compilatore e precompilatore/Header
* VisibilitàC/Visibilità
* Gestione della memoriaC/Gestione della memoria
* Le applicazioni CGIC/Le applicazioni CGI
* Appendice
** Librerie standardC/Appendice/Librerie standard
*** assert.hC/Appendice/Librerie standard/assert.h
*** ctype.hC/Appendice/Librerie standard/ctype.h
*** errno.hC/Appendice/Librerie standard/errno.h
*** float.hC/Appendice/Librerie standard/float.h
*** limits.hC/Appendice/Librerie standard/limits.h
*** locale.hC/Appendice/Librerie standard/locale.h
*** math.hC/Appendice/Librerie standard/math.h
*** setjmp.hC/Appendice/Librerie standard/setjmp.h
*** signal.hC/Appendice/Librerie standard/signal.h
*** stdarg.hC/Appendice/Librerie standard/stdarg.h
*** stddef.hC/Appendice/Librerie standard/stddef.h
*** stdio.hC/Appendice/Librerie standard/stdio.h
*** stdlib.hC/Appendice/Librerie standard/stdlib.h
*** string.hC/Appendice/Librerie standard/string.h
*** time.hC/Appendice/Librerie standard/time.h
** StrumentiC/Appendice/Strumenti
*** InstallerC/Appendice/Strumenti/Installer
** Librerie esterneC/Appendice/Librerie esterne
* Bibliografia
    IndiceC/Indice
Modifica il sommario
Utilizzando il meccanismo dei CGI (Common Gateway Interface) è possibile innescare vere e proprie applicazioni che hanno la libertà di svolgere qualsiasi funzione eseguibile sul web server da un programma, per poi restituire un risultato in forma di pagina HTML.

## Pagine statiche e pagine dinamiche

Sono dette pagine statiche quella pagine presenti sul web server che non richiedono alcuna elaborazione da parte del server se non quella di prendere la pagina così com'è e inviarla al browser. Per pagina dinamica si intende una pagina non presente fisicamente sul disco rigido del Web Server, ma costruita al volo, per mezzo di un'applicazione (interfaccia CGI) o uno script dedicato (in PHP o ASP). Il meccanismo dei CGI estende e generalizza l'interazione richiesta/risposta del protocollo HTTP. Ora descriviamo passo passo il meccanismo dei CGI, il processo si può dividere in 4 fasi:
* Invio della richiesta - Il browser (client HTTP) effettua una richiesta a un server HTTP identificato dal seguente indirizzo o URL: http://www.nomesito.it/cgi-bin/hello.cgi? Possiamo identificare il server HTTP:http://www.nomesito.it e il riferimento alla procedura CGI: cgi-bin/hello.cgi. La directory /cgi-bin è una sottodirectory della directory del web server che contiene le applicazioni CGI.
* Attivazione del CGI - Il server HTTP riceve la URL, la interpreta e lancia il processo (o thread) che esegue il CGI.
* Risposta del CGI - Il risultato della computazione deve dar luogo a una pagina HTML di risposta, che il CGI invia verso il suo Standard Output (per i CGI lo STDOUT viene intercettato dal server HTTP) tenendo conto di quale deve essere il formato di una risposta HTTP.
* Risposta del server HTTP - Sarà poi il server HTTP ad inviare la risposta verso il client che aveva effettuato la richiesta. Passiamo adesso a vedere come si scrive un CGI in C, prendendo come spunto un'applicazione che stampa all'interno di una pagina web 'hello world':
Compilando questo programma all'interno della directory /cgi-bin del nostro server web con estensione .cgi (leggere la documentazione del proprio compilatore per far questo) otteniamo un eseguibile CGI che possiamo richiamare all'interno del nostro browser nel modo visto sopra http://www.miosito.it/cgi-bin/hello.cgi L'esame del codice non è nulla di assurdo, tenendo sempre presente che lo STDOUT di una CGI viene rediretto direttamente al client HTTP. Degna di nota è questa riga:
Il suo scopo è quello di specificare al client HTTP il tipo di contenuto che si sta per inviare (in questo caso del testo HTML). Senza questa specifica il client non sa come comportarsi e stamperà una pagina bianca. Si notino le due linee vuote; sono assolutamente necessarie, per le convenzioni del protocollo HTTP. Il segnale di STDOUT viene quindi intercettato dal browser, e viene generata una pagina web con i contenuti specificati. Prendiamo ora in esame un rudimentale orologio che invia al client HTTP una pagina web contenente l'ora del server sfruttando la libreria time.h:

## Richieste GET e POST

L'utilità principale delle CGI, è quella di poter anche interagire con l'utente finale, leggendo dati inseriti da un utente via form o tramite altre vie. Per far questo il protocollo HTTP prevede due strade: il metodo GET e il metodo POST.

### GET

Nel metodo GET i dati inseriti dall'utente o previsti dal programmatore vengono caricati nell'URL, e il loro contenuto, a livello del sistema server, finisce in una variabile d'ambiente chiamata QUERY_STRING. Immaginiamo ad esempio di avere il seguente codice HTML (ricordate che la scelta del metodo, GET o POST, va fatta a livello del codice del form HTML):
È un semplice form HTML che chiede all'utente come si chiama e invia la stringa inserita dall'utente all'eseguibile 'cgi1' tramite metodo GET (per convenzione gli eseguibili CGI si mettono nella directory /cgi-bin del server). Se salviamo questa pagina come 'user.html' dopo aver cliccato sul tasto 'Clicca' la richiesta verrà inoltrata tramite metodo GET a cgi1, che quindi verrà richiamato nel seguente modo: http://www.miosito.org/cgi-bin/my_cgi?nome=Nome_inserito_dall_utente Nel caso ci fossero stati più campi oltre al nome (ad esempio un campo 'password') avremmo avuto una cosa del genere: http://www.miosito.org/cgi-bin/cgi1?nome=Nome_inserito_dall_utente&password=Password_inserita In pratica quando inviamo una richiesta tramite GET l'eseguibile CGI viene richiamato passando nell'URL una struttura del genere: http://www.miosito.org/cgi-bin/my_cgi? campo1=val1&campo2=val2&campo3=val3... Ora immaginiamo che il nostro eseguibile cgi1 debba leggere il nome inserito dall'utente e generare per lui una pagina HTML di benvenuto (es. 'Benvenuto pippo!'). Ecco un potenziale codice C:
La funzione unencode è indispensabile. Infatti, se l'utente dovesse inserire degli spazi o dei caratteri speciali qualsiasi all'interno del form (ovvero caratteri non alfanumerici) questi all'interno della QUERY_STRING verranno tradotti con i codici ASCII corrispondenti preceduti da un '%'. Ad esempio, se l'utente dovesse inserire 'pippo pappo', la query diventerà 'nome=pippo+pappo'. Per convertire il carattere a quello inizialmente inserito dall'utente è quindi necessario passare per unencode. Per comodità conviene tenersi le funzioni get_field e unencode da qualche parte pronte per l'uso, vista la loro utilità all'interno delle CGI in C.

### POST

La scelta tra metodo GET e metodo POST è legata ad un preciso criterio di programmazione, in genere le richieste GET vanno usate solo per campi di piccole dimensioni. Non è una buona idea utilizzare richieste GET, ad esempio, per inviare un messaggio postato da un utente in un forum, in quanto verrà fuori un URL lunghissimo senza senso. È anche rischioso usare GET per form di login, in quanto i dati di autenticazione passerebbero in chiaro nell'URL. In tutti questi casi (e altri) è consigliabile l'uso del metodo POST.
Il metodo POST genera una query string che è uguale in tutto e per tutto a quella generata dal metodo GET (nel nostro caso, sempre nome=nome_inserito). La differenza è che il metodo GET prevede che la query venga inviata al server tramite la variabile d'ambiente QUERY_STRING, mentre a livello client viene integrata nell'URL stesso. Il metodo POST invece prevede che la query venga inviata dal client al server all'interno del pacchetto HTTP stesso, e viene letta dal server come se fosse un normale input (quindi con scanf, gets o fgets). Prima di inviare la query vera e propria il client invia al server una stringa che identifica la lunghezza della query che sta per essere inviata. Questa stringa viene salvata dal server nella variabile d'ambiente CONTENT_LENGTH. In questo modo il server riceve la lunghezza della query che sta per essere inviata, prepara un buffer di dimensioni adatte e quindi legge la query con le funzioni per la lettura dell'input già viste. Dopo la procedura rimane uguale (ovvero lettura del contenuto di una variabile con un metodo come get_field e decodifica dei caratteri con un metodo come unencode).
Ecco un esempio di codice HTML che invia i dati di un form tramite metodo POST (esempio tipico, l'invio di un messaggio in un form che viene poi inviato ad un eseguibile CGI e stampato su schermo):
Ed ecco una potenziale applicazione CGI per elaborarlo: