// get_module.cgi: applicazione per reperire la pagina (costruita dal docente) // relativa al modulo passato. Tale pagina rimane fuori dall'albero del sito WWW // Serve inoltre per ritornare le lezioni da scaricare ed i test da eseguire. // Il comportamento del programma viene determinato in base alla presenza o meno // di variabili passate sullo stdin: // - se è presente solo la variabile MODULO allora introduce nella pagina iniziale del modulo // - se sono presenti sia la variabile MODULO che TESTNUM allora ritorna il test indicato per tale modulo (eseguendo controlli se il test è già stato eseguito // - se sono presenti MODULO TESTNUM e LEZIONE ritorna la lezione indicata, controllando il livello di test necessario per scaricarla #include #include "applicat.h" enum behaviour { normal, get_test, get_lesson }; class Get_module_Application : public Application { private: String _dbname; String _utente; // Utente corrente String _modulo; // Modulo String _testnum; // Livello del test String _lezione; // Nome della lezione PgEnv _environment; PgTransaction *_db; behaviour _what; // Comportamento: reperisce l'indice del modulo, i test o le lezioni protected: virtual bool create(); virtual bool destroy(); virtual void main_func(); virtual void print_header(const char* title); void print_access_error(); void get_module(); public: Get_module_Application() {_db = NULL;} virtual ~Get_module_Application() {}; }; bool Get_module_Application::create() { _dbname = POSTGRES_DB; _environment.Port(POSTGRES_PORT); _environment.Host(POSTGRES_HOST); _utente = getenv("REMOTE_USER"); _modulo = ""; _what = normal; char *t1, *t2; char *ccc = getenv("CONTENT_LENGTH"); int cl = ccc != NULL ? atoi(ccc) : 0; if (cl < 512) { // Evita di ricevere troppa roba sullo stdin for (int x = 0; cl && (!feof(stdin)); x++) { t1 = fmakeword(stdin, '&', &cl); t2 = makeword(t1, '='); unescape_url(t1); unescape_url(t2); if (!strcmp(t2,"MODULO")) _modulo = t1; if (!strcmp(t2,"TESTNUM")) _testnum = t1; if (!strcmp(t2,"LEZIONE")) _lezione = t1; } if (!_testnum.empty()) _what = get_test; if (!_lezione.empty()) _what = get_lesson; } else { print_header("Troppi dati inviati"); cout << "

Troppi dati inviati



" << endl; cout << "

L'applicazione ha ricevuto troppi dati sul buffer d'ingresso.


" << endl; print_footer(); return FALSE; } return TRUE; } bool Get_module_Application::destroy() { return TRUE; } void Get_module_Application::print_header(const char * title) { print_content(); cout << "" << endl; cout << "" << endl; cout << "" << title << "" << endl; cout << "" << endl; cout << "" << endl; cout << "" << endl; } void Get_module_Application::print_access_error() { print_header("Errore di accesso"); cout << "

Errore di accesso



"; cout << "

Utilizzare la normale procedura di accesso ai corsi.


"; print_footer(); return; } void Get_module_Application::get_module() { // Another one bites the dust... String command; // Compone la stringa di selezione utente: nome utente & logged 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: // Verifica che il modulo passato sia effettivamente attivo per l'utente indicato String moduli; String corso; moduli = _db->GetValue(0, "modules"); corso = _db->GetValue(0, "course"); trim(corso); const unsigned int int_mod = atoi(_modulo)-1; if (moduli.length() >= int_mod && moduli[int_mod] == 'X' && int_mod <= MAXMODULES -1) { // Se si tratta del primo accesso al modulo, spedisce il questionario di inizio modulo // Legge da FAD_ROOT il documento indicato da _modulo e lo restituisce sullo stdout così com'è String filename, base_path; FILE * html_page; // La pagina base di ogni modulo sarà in FAD_ROOT/M/index.htm // Il test di inizio modulo sarà in FAD_ROOT/M/test_a.htm const char * sv = _db->GetValue(0, "verifiche"); const char level = strlen(sv) > int_mod ? sv[int_mod] : ' '; const bool first_test = (level == ' '); base_path = FAD_ROOT; base_path += corso; base_path += "/documenti/M"; base_path += _modulo; base_path += "/"; filename = base_path; switch (_what) { case normal: if (first_test) { command = "SELECT * FROM MODULI WHERE modulenum="; command += _modulo; _db->ExecCommandOk(command); bool faked = 0; if (_db->Tuples() > 0) faked = _db->GetValue(0,"faked")[0] == 't'; if (faked) filename += "index.htm"; else filename += "test_a.htm"; } else filename += "index.htm"; break; case get_test: if (level+1 == _testnum[0] || _testnum == "z") { // Caso speciale per l'ultimo test (z) filename += "test_"; filename += _testnum; filename += ".htm"; // Last test Handling: controlla qual'è l'ultimo test possibile per questo modulo if (_testnum == "z") { command = "SELECT * FROM MODULI WHERE modulenum="; command += _modulo; _db->ExecCommandOk(command); if (_db->Tuples() > 0) { // Modulo presente? const char * last_test = _db->GetValue(0,"lasttest"); if (last_test[0] != level) // Se non ha raggiunto l'ultimo test possibile, nega l'accesso all'ultimo test filename = ERROR_FILE; } else filename = ERROR_FILE; } } else filename = ERROR_FILE; // File inesistente per segnalare l'errore di livello sul test richiesto break; case get_lesson: // Reperisce la lezione indicata if (level >= _testnum[0]) { filename += _lezione; } else filename = ERROR_FILE; break; } html_page = fopen(filename, "r"); if (html_page != NULL) { // Save some system resources, since sending the lessons may take some time // So it seems to be quite reasonable freeing semaphores and shared memory allocated by Postgres connections. delete _db; _db = NULL; const off_t sz = fsize(filename); if (sz > 0) cout << "Content-length: " << sz << endl; if (_what == get_lesson) { print_bin_content(); // Necessario per inviare files binari } else print_content(); // Necessario per i files testo/html send_fd(html_page, stdout); fclose(html_page); } else { // Se non trova la risorsa da inviare, visualizza l'errore switch (_what) { case normal: print_header(first_test ? "Questionario iniziale non implementato" : "Modulo non implementato"); if (first_test){ cout << "

Questionario iniziale non implementato



" << endl; cout << "

Il questionario iniziale per il modulo selezionato non è presente.


"; cout << "

Per ritornare alla pagina iniziale del modulo premete il pulsante INDIETRO del vostro browser o cliccate qui.


"; } else { cout << "

Modulo non implementato



" << endl; cout << "

I materiali didattici per il modulo selezionato non sono presenti.


"; cout << "

Per ritornare alla pagina iniziale del modulo premete il pulsante INDIETRO del vostro browser o cliccate qui.


"; } break; case get_test: if (filename == ERROR_FILE) { print_header("Accesso al livello di test non consentito"); cout << "

Accesso al livello di test non consentito



" << endl; cout << "

L'utente " << _utente << " non ha i permessi necessari per accedere al livello di test richiesto oppure il test è già stato svolto.


" << endl; cout << "

Per ritornare alla pagina iniziale del modulo premete il pulsante INDIETRO del vostro browser o cliccate qui.


"; } else { print_header("Questionario non ancora implementato"); cout << "

Questionario non ancora implementato



" << endl; cout << "

Il questionario per il modulo selezionato non è presente.


"; cout << "

Per ritornare alla pagina iniziale del modulo premete il pulsante INDIETRO del vostro browser o cliccate qui.


"; } break; case get_lesson: if (filename == ERROR_FILE) { print_header("Accesso alla lezione non consentito"); cout << "

Accesso alla lezione non consentito



" << endl; cout << "

L'utente " << _utente << " non ha i permessi necessari per accedere al livello di lezione richiesto.


" << endl; cout << "

Per ritornare alla pagina iniziale del modulo premete il pulsante INDIETRO del vostro browser o cliccate qui.


"; } else { print_header("Lezione non ancora implementata"); cout << "

Lezione non ancora implementata



" << endl; cout << "

La lezione per il modulo selezionato non è presente.


"; cout << "

Per ritornare alla pagina iniziale del modulo premete il pulsante INDIETRO del vostro browser o cliccate qui.


"; } break; } print_footer(); } } else { print_header("Accesso al modulo non consentito"); cout << "

Accesso al modulo non consentito



" << endl; cout << "

L'utente "<< _utente << " non ha i permessi necessari per accedere al modulo indicato.


"; cout << "

Per ritornare alla pagina iniziale del modulo premete il pulsante INDIETRO del vostro browser o cliccate qui.


"; 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); }