campo-sirio/webcgi/formazione/get_module.cpp
luca 8d5786295a Patch level :
Files correlati     :
Ricompilazione Demo : [ ]
Commento            : Modifiche di marco


git-svn-id: svn://10.65.10.50/trunk@8858 c028cbd2-c16b-5b4b-a496-9718f37d4682
2000-03-02 15:26:30 +00:00

327 lines
11 KiB
C++
Executable File

// 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 <libpq++.h>
#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 << "<H2>Troppi dati inviati</H2><BR><BR>" << endl;
cout << "<P>L'applicazione ha ricevuto troppi dati sul buffer d'ingresso.</P><BR>" << 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 << "<HTML>" << endl;
cout << "<HEAD>" << endl;
cout << "<TITLE>" << title << "</TITLE>" << endl;
cout << "<link rel=\"stylesheet\" href=\"/def_style.css\" type=\"text/css\">" << endl;
cout << "</HEAD>" << endl;
cout << "<BODY>" << endl;
}
void Get_module_Application::print_access_error()
{
print_header("Errore di accesso");
cout << "<H2>Errore di accesso</H2><BR><BR>";
cout << "<P>Utilizzare la normale procedura di <A HREF=\"";
cout << LOGIN_CGI << "\">accesso</A> ai corsi.</P><BR>";
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<modulo>/index.htm
// Il test di inizio modulo sarà in FAD_ROOT/M<modulo>/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 << "<H2>Questionario iniziale non implementato</H2><BR><BR>" << endl;
cout << "<P>Il questionario iniziale per il modulo selezionato non è presente.</P><BR>";
cout << "<P>Per ritornare alla pagina iniziale del modulo premete il pulsante INDIETRO del vostro browser o cliccate <a onclick=window.history.back(1)> qui</a>.</P><BR>";
}
else {
cout << "<H2>Modulo non implementato</H2><BR><BR>" << endl;
cout << "<P>I materiali didattici per il modulo selezionato non sono presenti.</P><BR>";
cout << "<P>Per ritornare alla pagina iniziale del modulo premete il pulsante INDIETRO del vostro browser o cliccate <a onclick=window.history.back(1)> qui</a>.</P><BR>";
}
break;
case get_test:
if (filename == ERROR_FILE) {
print_header("Accesso al livello di test non consentito");
cout << "<H2>Accesso al livello di test non consentito</H2><BR><BR>" << endl;
cout << "<P>L'utente <STRONG>" << _utente << "</STRONG> non ha i permessi necessari per accedere al livello di test richiesto oppure il test è già stato svolto.</P><BR>" << endl;
cout << "<P>Per ritornare alla pagina iniziale del modulo premete il pulsante INDIETRO del vostro browser o cliccate <a onclick=window.history.back(1)> qui</a>.</P><BR>";
}
else {
print_header("Questionario non ancora implementato");
cout << "<H2>Questionario non ancora implementato</H2><BR><BR>" << endl;
cout << "<P>Il questionario per il modulo selezionato non è presente.</P><BR>";
cout << "<P>Per ritornare alla pagina iniziale del modulo premete il pulsante INDIETRO del vostro browser o cliccate <a onclick=window.history.back(1)> qui</a>.</P><BR>";
}
break;
case get_lesson:
if (filename == ERROR_FILE) {
print_header("Accesso alla lezione non consentito");
cout << "<H2>Accesso alla lezione non consentito</H2><BR><BR>" << endl;
cout << "<P>L'utente <STRONG>" << _utente << "</STRONG> non ha i permessi necessari per accedere al livello di lezione richiesto.</P><BR>" << endl;
cout << "<P>Per ritornare alla pagina iniziale del modulo premete il pulsante INDIETRO del vostro browser o cliccate <a onclick=window.history.back(1)> qui</a>.</P><BR>";
}
else {
print_header("Lezione non ancora implementata");
cout << "<H2>Lezione non ancora implementata</H2><BR><BR>" << endl;
cout << "<P>La lezione per il modulo selezionato non è presente.</P><BR>";
cout << "<P>Per ritornare alla pagina iniziale del modulo premete il pulsante INDIETRO del vostro browser o cliccate <a onclick=window.history.back(1)> qui</a>.</P><BR>";
}
break;
}
print_footer();
}
}
else {
print_header("Accesso al modulo non consentito");
cout << "<H2>Accesso al modulo non consentito</H2><BR><BR>" << endl;
cout << "<P>L'utente <STRONG>"<< _utente << "</STRONG> non ha i permessi necessari per accedere al modulo indicato.</P><BR>";
cout << "<P>Per ritornare alla pagina iniziale del modulo premete il pulsante INDIETRO del vostro browser o cliccate <a onclick=window.history.back(1)> qui</a>.</P><BR>";
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);
}