diff --git a/webcgi/eurocampo/documentazione.doc b/webcgi/eurocampo/documentazione.doc
new file mode 100755
index 000000000..aafd4f8b5
Binary files /dev/null and b/webcgi/eurocampo/documentazione.doc differ
diff --git a/webcgi/formazione/README b/webcgi/formazione/README
new file mode 100755
index 000000000..53fb4313d
--- /dev/null
+++ b/webcgi/formazione/README
@@ -0,0 +1,135 @@
+Software di gestione moduli didattici per la formazione a distanza ver. 0.1
+==================================================================
+Copyright Aga informatica 1999.
+
+
+DISCLAIMER
+----------
+Le seguenti note sono solo indicative e vanno prese così come sono; ovvero
+come promemoria. Quando avrò un poco più di tempo provvederò a farne una
+stesura completa ed esauriente, con tanto di discussione della logica dei
+programmi, per la gioia ed il gaudio di tutti. Per ora accontentatevi...
+Teoricamente potrebbe essere possibile compilarlo anche sotto NT, basta avere
+gcc. Al posto di postgres si dovrebbe adattare il sorgente creando un piccolo
+middleware per utilizzare SQL server od un DBMS generico.
+
+
+
+NOTE
+----
+Per l'installazione del software cambiare l'install directory presente nel
+Makefile e quindi dare il comando make install come root.
+
+Per l'installazione dei tracciati, dopo aver installato Postgres 6.3,
+creare il database corsi:
+
+createdb corsi
+
+creare le tabelle:
+
+psql -e corsi < tracciato
+
+impostare eventuali opzioni di sicurezza/accessi esterni in pg_hba.conf e garantire l'accesso
+all'utente nobody, o comunque a quello per mezzo del quale vengono eseguiti
+i CGI dall'http server tramite lo statement SQL:
+
+GRANT ALL ON TO PUBLIC;
+
+La struttura dei direttori deve essere siffatta:
+
+
+---/corsi/----/cgi-bin/
+ |
+ |-/corso_
+ |
+ |-/corso_
+ |
+ |-/corso_
+
+Ogni direttorio del corso deve avere un direttorio documenti ed eventualmente
+un direttorio upload. Tali direttori devono essere protetti in lettura, ovvero
+non possono essere letti da chiunque se non dal gruppo appartenente al personale
+di servizio.
+Il direttorio cgi-bin invece, oltre ad essere configurato dal server http come
+direttorio di esecuzione CGI, deve avere l'accesso possibile oltre che dal personale
+di servizio, anche dai membri dei corsi.
+In cgi-bin andrà anche installato il direttorio HyperNews debitamente configurato.
+Ricordarsi di compilare per ogni utente anche il corso del quale fa parte. Tale
+indicazione deve essere uguale ai vari direttori dei corsi , o etc.
+All'interno del direttorio documenti vi sono tanti direttori quanti i moduli
+validi per il corso; ognuno è contraddistinto dal suo numero registrato sul
+database con una "M" davanti. All'interno di ognuno di questi direttori, M1,M2,
+M3 etc, vi sarà la pagina iniziale (index.htm) di presentazione e riferimento
+ai vari materiali. I materiali presenti in tale direttorio possono essere files
+di qualsiasi tipo. Infine oltre ai materiali vi sono anche i test necessari
+per l'ingresso e passaggio da una unità didattica all'altra: test_a.htm, test_b.htm
+test_c.htm... test_z.htm, dove test_a.htm è quello obbligatorio per l'ingresso
+e test_z.htm è quello per verificare la conoscenza finale del modulo.o
+
+
+--/corsi/--/corso_/upload/
+ |
+ /documenti/
+ |
+ |-/M1/..index.htm, materiali, test
+ |
+ |-/M2/
+ |
+ |-/M3/
+
+
+
+I riferimenti alle class-room per i singoli moduli devono avere lo stesso
+nome col quale il modulo stesso viene registrato nel database. Fare attenzione
+perche' la cosa e' case sensitive.
+
+TODO
+----
+
+*) Possibilità di gestione utente tutore, in modo che possa accedere liberamente
+ad ogni corso, ad ogni modulo, ad ogni classroom, ad ogni test senza memorizzarne
+risultati etc. Questa modifica è collegata alla memorizzazione delle informazioni
+relative ad ogni singolo corso. E' da decidere se ci vuole una tabella in più
+(corsi, con nome e descrizione) e dove mettere le informazioni di appartenenza
+al corso: sul modulo o sull'utente. Se si mettono sull'utente è necessario
+trovare un modo, nel caso del tutor, affinchè si possa ricostruire il path
+completo del modulo. Probabilmente si dovrà unificare tutti i direttori documenti
+dei vari corsi, e tener distinti i moduli, visto che ognuno è cmq diverso.
+In tal modo probabilmente si avrà un unico direttorio "documenti" sotto "corsi"
+e non tanti ognuno sotto corso_, facilitando la composizione del path del
+file da reperire, siano essi tests o materiali. In effetti visto che i moduli
+sono n, non vi è motivo di tenerli separati per corso. Per coerenza l'unica
+cosa che si può implementare è un campo in più sulla tabella moduli nel
+quale evidenziare di quale corso fa parte ma sarebbe una informazione ridondante.
+
+*) Interfaccia NSAPI per Netscape Fasttrack, in modo che l'autenticazione sia effettuata
+controllando il database utenti postgres. Così facendo si evitano duplicazioni
+di user-ID. Ovvio che tale interfaccia NSAPI, sarà valida solo per Fasttrack
+server. Nel caso di altro http server, ad esempio Apache, la cosa è da studiare.
+
+*) Verificare le potenzialità di HyperNews ed eventualmente cercare una message board
+più flessibile per i nostri scopi. Attualmente il sistema di autenticazione
+manuale incapsulato all'interno non è un gran ché; fare in modo che utilizzi
+quello del browser. In genere per HyperNews, basta impostare un unico utente,
+il creatore dei forum ed amministratore del sito.
+
+*) Implementare un miglior metodo per far sì che i client non mettano in cache
+i risultati dei vari cgi. Attualmente l'header expires non funziona molto bene,
+infatti quando si torna indietro col browser, dice sempre che il documento
+è spirato. Analogamente se si decide di stampare una qualsiasi pagina. Forse
+tramite i cookies...
+
+*) Maggior parametrizzazione per l'installazione, in modo da fare un bell'RPM
+cosicchè si possa vendere il prodotto!
+
+*) Maggior documentazione... ma questo si sapeva già...
+
+*) Se possibile trovare un modo per togliere i pulsanti di azione dalle pagine
+di ogni modulo (quelli per scaricare le lezioni, accedere ai tests ecc) e
+sostituirli con hyperlink. Il problema è che si tratta di forms che spediscono
+col metodo POST. Forse implementando una riga unica con i paramateri necessari
+ci si può riuscire.
+
+
+--Angelo
+
diff --git a/webcgi/formazione/applicat.cpp b/webcgi/formazione/applicat.cpp
new file mode 100755
index 000000000..3b94ed59d
--- /dev/null
+++ b/webcgi/formazione/applicat.cpp
@@ -0,0 +1,56 @@
+#include "applicat.h"
+
+
+void Application::print_content()
+{
+ cout << "Content-type: text/html" << endl ;
+ // Force expiring action, since these are CGI outputs...
+ // Guess this date...
+ cout << "Expires: Tue, 10 Nov 1992 00:00:00 GMT" << endl << endl;
+}
+
+void Application::print_bin_content()
+{
+ cout << "Content-type: application/octet-stream" << endl << endl;
+}
+
+void Application::print_database_error()
+{
+ cout << "
L'utente "<< _utente << " non ha i permessi necessari per accedere al modulo indicato.
";
+ print_footer();
+ }
+ }
+ else {
+ // Se non trova l'utente indicato oppure non era loggato
+ // visualizza ugualmente un messaggio ingannatore
+ print_access_error();
+ }
+
+ return;
+}
+
+void Get_module_Application::main_func()
+{
+ // Controllo utente: se il CGI viene chiamato senza indicazioni d'utente e/o modulo
+ // rimanda al normale login
+ if (_utente.empty() || _modulo.empty()) {
+ print_access_error();
+ return;
+ }
+ // Se e' stato impostato l'utente, prende il documento indicato dal numero di modulo,
+ // non prima di aver controllato che l'utente sia loggato!
+ // Inizia la transazione
+ _db = new PgTransaction(_environment, _dbname);
+ if ( _db->ConnectionBad() ) {
+ print_header("Errore sul database");
+ print_database_error();
+ print_footer();
+ }
+ else
+ get_module();
+ if (_db != NULL)
+ delete _db; // Termina la transazione
+ return;
+}
+
+int main(int argc, char* argv[])
+{
+ Get_module_Application* a = new Get_module_Application();
+
+ a->run(argc, argv);
+
+ delete a;
+
+ exit(0);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/webcgi/formazione/html_parser.cpp b/webcgi/formazione/html_parser.cpp
new file mode 100755
index 000000000..7789466a2
--- /dev/null
+++ b/webcgi/formazione/html_parser.cpp
@@ -0,0 +1,72 @@
+// Applicazione di prova per la classe Questionnaire
+
+#include "applicat.h"
+#include "questionnaire.h"
+
+
+class Parsing_Application : public Application
+{
+private:
+
+protected:
+ virtual bool create();
+ virtual bool destroy();
+ virtual void main_func();
+public:
+ Parsing_Application() {}
+ virtual ~Parsing_Application() {};
+};
+
+
+bool Parsing_Application::create()
+{
+ return TRUE;
+}
+
+bool Parsing_Application::destroy()
+{
+ return TRUE;
+}
+
+void Parsing_Application::main_func()
+{
+ Questionnaire q;
+
+ String s1,s2,s3;
+ s1 = "Q_1=VVVF;Q_2=FVFV;Q_3=VVVV;Q_4=VVFF;Q_5=VFFF;";
+ s2 = "Q_1=VVFFF;Q_2=FFFVF;Q_3=VVVVF;Q_4=VVFFF;Q_5=VFFFF;";
+ s3 = "volare";
+
+ q.load(s1,s2);
+ q.dump_html(s3, 1, 'a');
+}
+
+int main(int argc, char* argv[])
+{
+ Parsing_Application* a = new Parsing_Application();
+
+ a->run(argc, argv);
+
+ delete a;
+
+ exit(0);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/webcgi/formazione/login.cpp b/webcgi/formazione/login.cpp
new file mode 100755
index 000000000..f450b1df0
--- /dev/null
+++ b/webcgi/formazione/login.cpp
@@ -0,0 +1,193 @@
+// login.cgi: applicazione per registrare l'ingresso nell'area
+// dei corsi. Modifica il template con i dati personali
+// dell'utente (percorso formativo con moduli disponibili)
+
+#include
+#include "applicat.h"
+
+class Login_Application : public Application
+{
+private:
+
+ String _dbname;
+ String _utente; // Utente corrente
+ String _realname;
+ String _moduli; // Moduli attivi per l'utente corrente
+ PgEnv _environment;
+ PgTransaction *_db;
+
+protected:
+ virtual bool create();
+ virtual bool destroy();
+ virtual void main_func();
+ void login();
+ void print_access_error();
+public:
+ Login_Application() {_db = NULL;}
+ virtual ~Login_Application() {};
+};
+
+void Login_Application::print_access_error()
+{
+ cout << "
Accesso al corso
" << endl;
+ cout << "
Si prega di effettuare regolarmente l'accesso al corso, fornendo le indicazioni ";
+ cout << "di utente e password in vostro possesso.
" << endl;
+}
+
+bool Login_Application::create()
+{
+
+ _dbname = POSTGRES_DB;
+ _environment.Port(POSTGRES_PORT);
+ _environment.Host(POSTGRES_HOST);
+ print_header("Accesso all'area corsi");
+ _utente = getenv("REMOTE_USER");
+ return TRUE;
+}
+
+bool Login_Application::destroy()
+{
+ print_footer();
+ return TRUE;
+}
+
+void Login_Application::login()
+{
+ // Controlla se l'utente fornito è' un utente valido
+ String command;
+ // Compone la stringa di selezione utente.
+ command = "SELECT * FROM UTENTI WHERE loginname='";
+ command += _utente;
+ command += "'";
+ // Esegue il comando SQL, dovrebbe venir ritornata una sola tupla
+ // al limite se ne vengono ritornate piu' di una verranno ignorate
+ _db->ExecCommandOk(command);
+ const int tuples = _db->Tuples();
+ if (tuples > 0) {
+ // Cosa deve fare:
+ // Sistema le informazioni di logging dell'utente (anche sulla tabella ACCESSI)
+ // Carica il percorso formativo (campo modules) e compone la pagina
+ const bool logged = (_db->GetValue(0, "logged"))[0] == 't';
+ _realname = _db->GetValue(0, "realname");
+ _moduli = _db->GetValue(0, "modules");
+ // Aggiorna le informazioni di logging
+ if (!logged){
+ // Prende il progressivo per il logging sulla tabella accessi
+ long progressivo = 0L;
+ command = "LOCK PROGRESSIVI"; // Blocca la tabell all'interno di questa transazione per evitare sovrapposizioni
+ _db->ExecCommandOk(command); // Verrà automaticamente sbloccata al termine della transazione
+ command = "SELECT * FROM PROGRESSIVI"; // In caso il CGI si pianti la transazione viene abortita dal server, e di fatto non verrà fatto nessun aggiornamento alle tabelle
+ if (_db->ExecTuplesOk(command) && _db->Tuples() > 0){
+ progressivo = atol(_db->GetValue(0, "progaccessi"));
+ }
+ else { // Se non c'è nessuna riga viene aggiunta
+ command = "INSERT INTO PROGRESSIVI VALUES(0,0)";
+ _db->ExecCommandOk(command);
+ }
+ progressivo++;
+ command = "UPDATE PROGRESSIVI SET progaccessi=progaccessi+1"; // Incrementa il progressivo
+ _db->ExecCommandOk(command); // Aggiorna la tabella relativa
+ command = "UPDATE UTENTI SET logged=1, logindate=current_timestamp, ";
+ command += "progaccesso=";
+ command += ltoa(progressivo);
+ command += " WHERE loginname='";
+ command += _utente;
+ command += "'";
+ _db->ExecCommandOk(command); // Aggiorna la tabella utenti
+ command = "INSERT INTO ACCESSI VALUES (";
+ command += ltoa(progressivo);
+ command += ",'";
+ command += _utente;
+ command += "',current_timestamp, null)";
+ _db->ExecCommandOk(command); // Aggiunge un record alla tabella accessi
+ }
+ // Seleziona i moduli abilitati
+ command = "SELECT * FROM MODULI ORDER BY modulenum";
+ _db->ExecCommandOk(command);
+ cout << "
Percorso formativo
" << endl;
+ cout << "
Benvenuto/a, " << _realname << ".
" << endl;
+ cout << "
Ecco l'elenco dei moduli disponibili, clicca sull'immagine relativa al modulo per entrare nell'area di formazione prescelta. Si ricorda che i moduli contraddistinti da una piccola spirale fanno parte delle lezioni avanzate.
" << endl;
+ const int nt = _db->Tuples();
+ if (nt > 0) {
+ // Seleziona i moduli abilitati per costui
+ cout << "
" << endl;
+ int curr_module=0;
+ for (int i=0; iGetValue(i, "modulenum"))-1;
+ if (_moduli.length() > mod_num+1 && _moduli[mod_num] == 'X') { // Se il modulo e' abilitato visualizza
+ const bool new_row = curr_module % 2 == 0;
+ curr_module++;
+ if (new_row)
+ cout << "
" << endl;
+ cout << "
" << endl;
+ if (!new_row || i == nt - 1) // Se non è nuova riga o è l'ultimo elemento
+ cout << "
" << endl;
+ }
+ }
+ cout << "
" << endl;
+ }
+ cout << "
" << endl;
+ }
+ else { // Se non trova i dati dell'utente indicato (con il percorso formativo)
+ // visualizza la mancanza di informazioni per completare la pagina.
+ cout << "
Mancanza di informazioni
" << endl;
+ cout << "
Impossibile reperire le informazioni relative al percorso formativo dell'utente " << _utente << ".
";
+ cout << "
Controllare l'esattezza delle informazioni inserite.
";
+ }
+ return;
+}
+
+void Login_Application::main_func()
+{
+ // Controllo utente: se il CGI viene chiamato senza indicazioni d'utente (impossibile o quasi)
+ // Allora mostra un avvertimento
+ if (_utente.empty()) {
+ print_access_error();
+ return;
+ }
+ // Se e' stato impostato l'utente, effettua la login()
+ // Inizia la transazione
+ _db = new PgTransaction(_environment, _dbname);
+ if ( _db->ConnectionBad() )
+ print_database_error();
+ else
+ login();
+ delete _db; // Termina la transazione
+ return;
+}
+
+int main(int argc, char* argv[])
+{
+ Login_Application* a = new Login_Application();
+
+ a->run(argc, argv);
+
+ delete a;
+
+ exit(0);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/webcgi/formazione/logout.cpp b/webcgi/formazione/logout.cpp
new file mode 100755
index 000000000..11f57b61d
--- /dev/null
+++ b/webcgi/formazione/logout.cpp
@@ -0,0 +1,127 @@
+// logout.cgi: applicazione per registrare l'uscita dall'area
+// dei corsi.
+
+#include
+#include "applicat.h"
+
+class Logout_Application : public Application
+{
+private:
+
+ String _dbname;
+ String _utente; // Utente corrente
+ PgEnv _environment;
+ PgTransaction *_db;
+
+protected:
+ virtual bool create();
+ virtual bool destroy();
+ virtual void main_func();
+ void logout();
+public:
+ Logout_Application() {_db = NULL;}
+ virtual ~Logout_Application() {};
+};
+
+bool Logout_Application::create()
+{
+
+ _dbname = POSTGRES_DB;
+ _environment.Port(POSTGRES_PORT);
+ _environment.Host(POSTGRES_HOST);
+ print_header("Uscita dall'area corsi");
+ _utente = getenv("REMOTE_USER");;
+ return TRUE;
+}
+
+bool Logout_Application::destroy()
+{
+ print_footer();
+ return TRUE;
+}
+
+void Logout_Application::logout()
+{
+ //
+ String command;
+ // Compone la stringa di selezione utente: nome utente & logged altrimenti nisba logout!
+ command = "SELECT * FROM UTENTI WHERE loginname='";
+ command += _utente;
+ command += "' AND logged='t'";
+ _db->ExecCommandOk(command);
+ const int tuples = _db->Tuples();
+ if (tuples > 0) { // E' loggato oppure no...
+ // Cosa deve fare:
+ // Sistema le informazioni di logging dell'utente (anche sulla tabella ACCESSI)
+ String progressivo;
+ progressivo = _db->GetValue(0, "progaccesso");
+ command = "UPDATE UTENTI SET logged=0, logindate=null ";
+ command += " WHERE loginname='";
+ command += _utente;
+ command += "'";
+ _db->ExecCommandOk(command); // Aggiorna la tabella utenti
+ command = "UPDATE ACCESSI SET logoutdate=current_timestamp WHERE loginname='";
+ command += _utente;
+ command += "' AND progressivo=";
+ command += progressivo;
+ _db->ExecCommandOk(command); // Aggiorna la tabella accessi
+ }
+ // Se non trova l'utente indicato oppure non era loggato
+ // visualizza ugualmente un messaggio ingannatoreà
+ cout << "
Uscita dall'area corsi
" << endl;
+ cout << "
Uscita dall'area corsi effettuata con successo.
";
+ cout << "
Le informazioni necessarie sono state registrate.
";
+ cout << "
Grazie.
";
+
+ return;
+}
+
+void Logout_Application::main_func()
+{
+ // Controllo utente: se il CGI viene chiamato senza indicazioni d'utente
+ // non mostra proprio nulla (null logout)
+ if (_utente.empty()) {
+ cout << "