8d5786295a
Files correlati : Ricompilazione Demo : [ ] Commento : Modifiche di marco git-svn-id: svn://10.65.10.50/trunk@8858 c028cbd2-c16b-5b4b-a496-9718f37d4682
327 lines
11 KiB
C++
Executable File
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);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|