  /** 
   * NOTA:
   * Quest'oggetto viene utilizzato sia lato server che lato client.
   * Per l'utilizzo lato server:
   * <script language="javascript" runat="server" src="interpreter.inc"></script>
   *
   * Per l'utilizzo lato client:
   * <script language="javascript" src="interpreter.inc"></script>
   **/
   
  /** Costanti per azioni e sotto-azioni **/
  INTR_ACTION_CHANGE_AREA = 1;
  INTR_ACTION_CHANGE_SUB  = 2;    
  INTR_ACTION_CHANGE_LANGUAGE  = 3; 
  INTR_ACTION_SELECT_FACULTY = 4;
  
  /** Costanti per i flag **/
  INTR_FLAG_LOAD_LEARNENV    = 1;    // Carica il menu del learning environment
  INTR_FLAG_CLEARLEFTMENU    = 2;   // Pulisce il menu a sinistra
  INTR_FLAG_DONTSETACTION    = 4;  
  INTR_FLAG_LOAD_VETENV      = 8;    // Carica i menu learning environment vet  
  INTR_FLAG_SSL              = 16;   // La connessione è criptata con protocollo SSL 
  INTR_FLAG_LOGOUT           = 32;   // Viene effettuato il logout
  INTR_FLAG_SEARCH           = 64;   // E' stata chiamata la ricerca
  INTR_FLAG_NOSELECTION      = 128;   
  INTR_FLAG_ISCONTENT        = 256;  // E' una pagina di contenuto  
  INTR_FLAG_LOADPERSONALMENU = 512 	  // Carica un menu personalizzato 
  INTR_FLAG_LOADHOMEPAGE     = 1024		// Carica la my home page
  INTR_FLAG_LOADMODULE			 = 2048   // Carica un modulo specifico
  INTR_FLAG_SELSUB0					 = 4096;	// Forza un menu a sinistra senza sottovoci selezionate
  INTR_FLAG_FULLSCREEN			 = 8192;	// Carica la pagina senza menu di sinistra
  INTR_FLAG_CLEARNAV         = 16384; // Pulisce le informazioni di navigazione nell'insegnamento
  
  function InterpreterObjectClient(bparse)
  {
    this.selarea  = "";
    this.selsub   = "";
    this.pageid   = "";
    this.language = "";
    this.userid   = "";
    this.action   = "";
    this.action2  = "";
    this.flags    = "";
    
    if (bparse) this.parse();
  }
  
  InterpreterObjectClient.prototype.parse = intrParse;
  InterpreterObjectClient.prototype.makeUrl = intrMakeUrl;
  InterpreterObjectClient.prototype.repeatChar = intrRepeatChar;
  InterpreterObjectClient.prototype.findPage = intrFindPage;
  InterpreterObjectClient.prototype.loadPage   = intrLoadPage;
  InterpreterObjectClient.prototype.loadCenter = intrLoadCenter;
  InterpreterObjectClient.prototype.loadHalf  = intrLoadHalf;
  InterpreterObjectClient.prototype.loadContent = intrLoadContent;
  InterpreterObjectClient.prototype.parseRest = intrParseRest;
  InterpreterObjectClient.prototype.clear     = intrClear;
  InterpreterObjectClient.prototype.parsePath = intrParsePath;
  
  /** 
   ** Data la querystring, estrae la parte che non è strettamente
   ** utilizzata dall'oggetto interpreter.
   **/
  function intrParseRest(qstring)
  {
    if (!qstring)
      qstring = window.location.search;
  	
    qstring = ""+qstring;
    qstring = qstring.toLowerCase();
    if (!qstring) return "";
    if (qstring.indexOf("id") == -1) return "";
    
    var ipos = qstring.indexOf("id");
    var iend = qstring.indexOf("&", qstring.indexOf("id"));
    
    if (iend != -1)
      qstring = qstring.substr(1, ipos-1) + qstring.substr(iend+1, qstring.length-iend-1);
    else
      qstring = "";
      
    return qstring;
  }
  
  /**
   * Effettua il parse di una informazione passata
   * sulla linea di comando.
   * 
   * L'informazione è così composta:
   * - caratteri 0-1: selezione corrente area principale
   * - caratteri 2-3: selezione corrente sotto-area
   * - caratteri 4-15: id della pagina da caricare
   * - caratteri 16-17: lingua corrente
   * - caratteri 18-23: id dell'utente corrente
   * - caratteri 24-25: azione principale
   * - caratteri 26-27: azione secondaria
   * - caratteri 28-31: flags
   */
  function intrParse(s)
  {
    var selarea = "", selsub = "", pageid = "", language = "", userid = "";
    var action = "", action2 = "", flags = "", parm1 = "", parm2 = "", parm3 = "";
    
    if (!s)
      s = queryString("id")
      
    s = ""+s;
    
    if (!s)
      return false;

    // Prende l'id dell'area principale
    if (s.length < 2) return false;
    selarea = s.substr(0,2);
    
    // Prende l'id della sottoarea
    if (s.length >= 4) selsub  = s.substr(2,2);
    
    // Id della pagina corrente
    if (s.length >= 16) pageid  = s.substr(4,12);
    
    // Prende la lingua corrente
    if (s.length >= 18) language = s.substr(16,2);
    
    // Prende l'id dell'utente corrente
    if (s.length >= 24) userid = s.substr(18,6);
    
    // Prende l'id dell'azione primaria
    if (s.length >= 26) action = s.substr(24,2);
    
    // Prende l'id dell'azione secondaria
    if (s.length >= 28) action2 = s.substr(26,2);
    
    // Prende i flag
    if (s.length >= 30) flags = s.substr(28,4);
    
    // Prende parametro 1
    if (s.length >= 34) parm1 = s.substr(32,2);
    
    // Prende parametro 2
    if (s.length >= 36) parm2 = s.substr(34,2);    
      
    // Conversioni dall'esadecimale
    if (selarea && !isNaN(parseInt(selarea, 16)))
      this.selarea = parseInt(selarea, 16);
    if (selsub && !isNaN(parseInt(selsub, 16)))
      this.selsub = parseInt(selsub, 16);
    if (pageid)
    {
      // Rimuove gli "00" inutili
      var ipos = pageid.indexOf("00");
      if (ipos != -1)
      {
        // deve essere cifra pari per non prendere una cifra che termina con 0        
        if (ipos % 2) ipos++;     
        if (ipos < pageid.length-1) pageid = pageid.substr(0, ipos);
      }

      this.pageid = pageid;
    }      
    if (language && !isNaN(parseInt(language, 16)))
      this.language = parseInt(language, 16)
    if (userid && !isNaN(parseInt(userid, 16)))
      this.userid = parseInt(userid, 16);
    if (action && !isNaN(parseInt(action, 16)))
      this.action = parseInt(action, 16);
    if (action2 && !isNaN(parseInt(action2, 16)))
      this.action2 = parseInt(action2, 16);
    if (flags && !isNaN(parseInt(flags, 16)))
      this.flags = parseInt(flags, 16);
    if (parm1 && !isNaN(parseInt(parm1, 16)))
    	this.parm1 = parseInt(parm1, 16);
    if (parm2 && !isNaN(parseInt(parm2, 16)))
    	this.parm2 = parseInt(parm2, 16);    	      
    
    return true;
  }
  
  function intrMakeUrl()
  {
    var selarea = "", selsub = "", pageid = "", language = "", userid = "", action = "", action2 = "", parm1 = "", parm2 = "";
    
    // Trasforma i valori in esadecimale
    selarea  = this.selarea ? this.selarea.toString(16) : "00";
    selsub   = this.selsub  ? this.selsub.toString(16) : "00";
    pageid   = this.pageid  ? this.pageid : "000000000000";
    language = this.language  ? this.language.toString(16) : "00";
    userid   = this.userid  ? this.userid.toString(16) : "000000";
    action   = this.action  ? this.action.toString(16) : "00";
    action2  = this.action2 ? this.action2.toString(16) : "00";
    flags    = this.flags ? this.flags.toString(16) : "0000";
    parm1    = this.parm1 ? this.parm1.toString(16) : "00";
    parm2    = this.parm2 ? this.parm2.toString(16) : "00";    
    
    // Si assicura che ci sia un numero sufficiente di caratteri
    if (selarea.length < 2) selarea   = this.repeatChar("0",2-selarea.length) + selarea;
    if (selsub.length <  2)  selsub   = this.repeatChar("0",2-selsub.length) + selsub;
    if (pageid.length <  12)  pageid  = pageid + this.repeatChar("0",12-pageid.length);
    if (language.length < 2) language = this.repeatChar("0",2-language.length) + language;
    if (userid.length < 6) userid     = this.repeatChar("0",6-userid.length) + userid;
    if (action.length < 2) action     = this.repeatChar("0",2-action.length) + action;
    if (action2.length < 2) action2   = this.repeatChar("0",2-action2.length) + action2;
    if (flags.length < 4) flags       = this.repeatChar("0", 4-flags.length) + flags;
    if (parm1.length < 2) parm1       = this.repeatChar("0", 2-parm1.length) + parm1;
    if (parm2.length < 2) parm2       = this.repeatChar("0", 2-parm2.length) + parm2;    
    
    return selarea + selsub + pageid + language + userid + action + action2 + flags + parm1 + parm2;
  }
  
  function intrRepeatChar(c, n)
  {
    var s = "";
    
    for (var i=0; i<n; i++) s += c;
    
    return s;
  }
  
  /** 
   * USABILE SOLO LATO SERVER
   * Trova il percorso di una pagina a partire
   * dal codice. Il codice di una pagina
   * è composto da una sequenza di coppie
   * di caratteri, ognuna specifica una
   * cartellina da attraversare per arrivare
   * alla pagina finale. L'ultima coppia di
   * cifre rappresenta il nome del file da caricare con
   * estensione .asp.
   * I nomi delle cartelline e dei file possono anche 
   * semplicemente iniziare per le cifre del codice, e poi
   * continuare con un nome descrittivo, ad es. "01informazioni". 
   */
  function intrFindPage(rpath, s)
  {
    var path = "";
    var upath = "";
    
    var fs = Server.CreateObject("Scripting.Filesystemobject");
    
    if (!s)
      s = this.pageid;
    if (s.length == 0)
      return "";
      
    // Naviga le cartelline con i codici specificati
    while (s.length > 2)
    {
      var p = s.substr(0,2).toLowerCase();
      
      fo = fs.getFolder(Server.MapPath(rpath + (path.length ? "/" : "") + path));
      fc = new Enumerator(fo.SubFolders);
      bFound = false;
      for (; !fc.atEnd(); fc.moveNext())
      {
        // Se la cartellina inizia con i due caratteri del codice...
        if ( ("" + fc.item().name).substr(0,2).toLowerCase() == p)
        {
          path += (path.length ? "/" : "") + fc.item().name;  // Costruisci il path
          bFound = true;                                      // Cartellina trovata
          break;                                              // Interrompi il loop
        }
      }
      
      // Se non ho trovato la cartellina, non esiste
      if (!bFound)  
        return "";
        
      // Passa al prossimo codice
      s = s.substr(2);
    }
    
    // In uscita: fc contiene un puntatore all'ultimo folder visitato
    //             s contiene gli ultimi due caratteri del codice
    bFound = false;

    // Trova il file con il codice specificato
    fc = new Enumerator(fc.item().files)
    for (; !fc.atEnd(); fc.moveNext())
    {
      if ( ("" + fc.item().name).substr(0,2).toLowerCase() == s)
      {
        path += (path.length ? "/" : "") + fc.item().name;
        bFound = true;
        break;
      }
    }
    
    if (!bFound)
      return "";
    else
      return path;
  }
  
  /**
   * Dato un file, prende la self.location.href e calcola
   * la posizione relativa del file rispetto ad essa.
   * Ad esempio: f = "../main.asp", self.location.href = "http://localhost/pippo/pluto/index.html"
   * ritorna: "http://localhost/pippo/main.asp"
   **/
  function intrParsePath(f)
  {
    var l = self.location.href;
    var p = l.lastIndexOf("/")
    if (p > -1) l = l.substr(0, p)    
    
    while (f.indexOf("..") == 0)
    {
      f = f.substr(3);
      var p = l.lastIndexOf("/") 
      if (p > -1) l = l.substr(0, p)          
    }
    
    l += "/" + f;
    
    p = l.toLowerCase().indexOf("https");
    
    /** Aggiunge https:// in caso di flag SSL **/
    if (p == -1 && (this.flags & INTR_FLAG_SSL))
    {
      p = l.toLowerCase().indexOf("http");
      if (p > -1)
        l = l.substr(0, p) + "https" + l.substr(p + "http".length);
    }          
    /** Rimuove l'https sostituendolo con http:// in caso contrario **/
    else if (p > -1 && !(this.flags & INTR_FLAG_SSL))
    {
      l = l.substr(0, p) + "http" + l.substr(p + "https".length);
    }
    
    return l;
  }
  
  function intrLoadContent(pageid, selarea, selsub, mainfile, parms, parentlevels)
  {
  	this.loadPage(pageid, selarea, selsub, mainfile, parms, parentlevels, true);
  }  
  
  function intrLoadCenter(pageid, parms, iscontent, path_to_e_folder)
  {
    this.pageid = pageid;
    
    if (iscontent)
    	this.flags |= INTR_FLAG_ISCONTENT;
    
    var s = this.makeUrl();
    var newurl = "hiddenloader.asp" + "?id=" + s;
    if (parms) newurl += "&" + parms;
    
    if (path_to_e_folder != null)
    	newurl = path_to_e_folder + newurl;

    top.centerFrame.location.href = newurl;
    
    return newurl;  	
  }
  
  function intrLoadHalf(url, parms, path_to_e_folder)
  {
  	var leftframe = "left.asp"
  	var newurl;
  	
	  if (this.flags & INTR_FLAG_LOAD_LEARNENV)
	  {
	    leftframe = "menu_prof.asp"
	  } 
	  if (this.flags & INTR_FLAG_CLEARLEFTMENU)
	  {
	    leftframe = "empty2.asp"
	  }
	  
  	var s = this.makeUrl();
  	
  	newurl = url + "?id=" + s
  	leftframe += "?id=" + s;
  	
  	if (parms) 
  	{
  		newurl += "&" + parms;
  		leftframe += "&" + parms;
  	}

  	if (path_to_e_folder != null)
  	{
  		newurl = path_to_e_folder + newurl;	  
  		leftframe = path_to_e_folder + leftframe;
  	}
  	
  	//alert(leftframe + "***" + window.location.search); 
	  top.leftFrame.location.href = leftframe;
	  top.centerFrame.location.href = newurl; 
  }
  
  /** 
   * USABILE SOLO LATO CLIENT
   * Carica una pagina specifica
   * @param pageid codice della pagina
   * @param selsub opzione da selezionare nel menu di sinistra   
   * @param mainfile percorso del file principale dell'applicazione
   * @param parametri addizionali
   * @param parentlevels numero di livelli di annidamento del frame corrente
   */
  function intrLoadPage(pageid, selarea, selsub, mainfile, parms, parentlevels, iscontent)
  {
    this.pageid = pageid;
    
    if (selsub)
      this.selsub = selsub;
      
    mainfile = this.parsePath(mainfile);
    
    if (selarea && this.selarea != selarea)
    {
      if (!(this.flags & INTR_FLAG_DONTSETACTION))
      {
        this.action = INTR_ACTION_CHANGE_AREA;
        this.flags   = 0;
      }
      
      this.selarea = selarea;
    }     
    
    if (iscontent)
    	this.flags |= INTR_FLAG_ISCONTENT;
    
    var s = this.makeUrl();
    var newurl = mainfile + "?id=" + s;
    if (parms) newurl += "&" + parms;

    /** Se è specificato un numero di livelli di annidamento
     ** frame, esegue un comando con un numero corrispondente
     ** di parent annidati. 
     **/    
    if (parentlevels)
    {
      plev = "";
      for (i=0; i<parentlevels; i++)
        plev += (plev.length ? "." : "") + "parent";
        
      plev += ".location.href = '" + newurl + "'";
      eval(plev);        
    } 
    /** Altrimenti, di default esegue il comando
     ** nel frame padre
     **/
    else
    {
      parent.location.href = newurl;
    }
    
    return newurl;
  }  
  
  /**
   * Pulisce le variabili 
   */
  function intrClear(keepflag)
  {
  	keepflag = this.flags & keepflag;
  	
    this.action = 0;
    this.action2 = 0;
    this.flags = 0;
    this.parm1 = 0;
    this.parm2 = 0;
    this.parm3 = 0;
        
    if (keepflag)
    	this.flags |= keepflag
  }  
  
	function PageQuery(q) {
		if(q.length > 1) this.q = q.substring(1, q.length);
		else this.q = null;
		this.keyValuePairs = new Array();
		if(q) {
			for(var i=0; i < this.q.split("&").length; i++) {
				this.keyValuePairs[i] = this.q.split("&")[i];
			}
		}
		this.getKeyValuePairs = function() { return this.keyValuePairs; }
		this.getValue = function(s) {
			for(var j=0; j < this.keyValuePairs.length; j++) {
				if(this.keyValuePairs[j].split("=")[0] == s)
				return this.keyValuePairs[j].split("=")[1];
			}
			return false;
		}
		this.getParameters = function() {
			var a = new Array(this.getLength());
			for(var j=0; j < this.keyValuePairs.length; j++) {
				a[j] = this.keyValuePairs[j].split("=")[0];
			}
			return a;
		}
		this.getLength = function() { return this.keyValuePairs.length; } 
	}
	
	function queryString(key){
		var page = new PageQuery(window.location.search); 
		return unescape(page.getValue(key)); 
	}
	
	function displayItem(key){
		if(queryString(key)=='false') 
		{
			document.write("you didn't enter a ?name=value querystring item.");
		}else{
			document.write(queryString(key));
		}
	}
	
	
	
