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