public class RootTaintedSymbol extends Symbol{
    String nameRootSymbol;
    List<RelatedTaintedSymbol> symbolsTainted;
    List<Integer> lines; // Lista que armazenara as linhas de vars, fun tainteds
    List<String> files; // Lista que armazenara os files names de vars, fun tainteds
    
    /* CONSTRUCTOR */
    public RootTaintedSymbol(String name, int line, int tainted, Boolean alfanumeric, String file){
        super(name, tainted, line, alfanumeric, file);
        symbolsTainted = new ArrayList<RelatedTaintedSymbol>();
        this.nameRootSymbol = name;
        lines = new ArrayList<Integer>();
        files = new ArrayList<String>();
        RelatedTaintedSymbol rrt = new RelatedTaintedSymbol(line, file);
        this.define(rrt);
    }
    
    /* METHODS that satisfy TaintedScope interface*/

    /*
     * Give the the name of taintedScope. How this scope don't have parent, then
     * your name is "globaltainted"
     */
    public String getScopeTaintedName() {
        return nameRootSymbol;
    }

    /*
     * If the tainted scope is enclosing in another (if have parent), give the
     * name of the parent scope.
     * How the Tainted Table is the main scope, then don't have parent (null)
     */
    public ScopeTainted getEnclosingScopeTainted() {
    	return null;
    }

    /*
     * Give the main Map that contain the tainted variables
     */
    public List getListTaintedMembers() {
        return symbolsTainted;
    }

    /*
     * Give the List of line codes from the variable included in main Map
     */
    public List getLinesList (){
        return lines;
    }

    /*
     * Give the List of the files names from the variable included in main Map
     */
    public List getFilesList (){
        return files;
    }    
    
    /*
     * Insert a tainted variable in main Map.
     * Each member of main Map is a RelatedTaintedSymbol, composed by:
     * Map VariableTaintedSymbol and List to store code lines of tainted variables
     */
    public final void define(RelatedTaintedSymbol rtt) {
    	symbolsTainted.add(rtt);
        lines.add(rtt.getLineRts());
        files.add(rtt.getFileRts());
    }
    
    /*
     * Insert a code line in List of the tainted variable included in main Map.
     * This appened when new tainted variable is identified, and your code line
     * is included in List
     */
    public void setLineCode (int line){
        lines.add(line);
    }

    /*
     * Insert a file name in List of the tainted variable included in main Map.
     * This appened when new tainted variable is identified, and your code line
     * is included in List
     */
    public void setFile (String file){
       files.add(file);
    }
    
} public class UntaintedTable {
    Map<String, Symbol> symbolsUntainted;

    /* CONSTRUCTOR */
    public UntaintedTable() {
     symbolsUntainted = new LinkedHashMap<String, Symbol>();
    }


    /* METHODS of the class*/

    /*
     * Give the Map that contain the untainted variables
     */
    public Map getUntaintedMembers() {
        return symbolsUntainted;
    }

    /*
     * Verify if a untainted variable exist in Map
     */
    public Boolean existSymbol(String s) {
        return symbolsUntainted.containsKey(s);
    }

    /*
     * Insert a untainted variable in Map
     */
    public void insertUntaintSymbol(Symbol sym) {
    	symbolsUntainted.put(sym.getName(), sym);
    }

    /*
     * Remove a untainted variable from Map
     */
    public void removeUntaintSymbol(Symbol sym) {
    	symbolsUntainted.remove(sym.getName());
    }

    public void copyToMUS(UntaintedTable m) { // m = mus
        Iterator <Symbol> it = this.getUntaintedMembers().values().iterator(); // mus_aux
        Symbol sym;
        for(;it.hasNext();){
            sym = it.next();
            if (!sym.getName().equals("return"))
                m.getUntaintedMembers().put(sym.getName(), sym);
        }
    }

    public void copyGlobalsToMUS(TaintedTable mts_princ , UntaintedTable mus_princ, MethodSymbol meth_sym_clone){
        for(Iterator <Symbol> it = meth_sym_clone.getGlobalVarsOfFunction().values().iterator(); it.hasNext();){
            Symbol sym = it.next();
            if (this.getUntaintedMembers().containsKey(sym.getName()) == true && mts_princ.getTaintedMembers().containsKey(sym.getName()) == true) {
                if (mus_princ.existSymbol(sym.getName()) == false){
                    // Se passou de tainted para untainted, colocar em untainted
                    mus_princ.insertUntaintSymbol(sym);
                }
            }
        }
    }    
    
    
    public UntaintedTable copyUntaintedTable() {
        UntaintedTable tab = new UntaintedTable();
        for(Iterator <Symbol> it = this.getUntaintedMembers().values().iterator(); it.hasNext();){
		Symbol cs = it.next();
            try {
                tab.getUntaintedMembers().put(cs.getName(), cs.clone());
            } catch (CloneNotSupportedException ex) {
                Logger.getLogger(UntaintedTable.class.getName()).log(Level.SEVERE, null, ex);
            }
	 }
    	return tab;
    }
    
     public void cleanAll(){
        Collection <Symbol> c = this.symbolsUntainted.values();
    	c.removeAll(c);
    	this.symbolsUntainted.clear();
    }

} public class TaintedTable implements ScopeTainted{
    String nameFile;
    String functionNameCall = "";
    Map<String, RootTaintedSymbol> symbolsRootTainted;

    
    /* CONSTRUCTOR */
    public TaintedTable(String filename) {
     symbolsRootTainted = new LinkedHashMap<String, RootTaintedSymbol>();
     this.nameFile = filename;
    }
    
    // Constructor to user function and class method tainted table
    public TaintedTable(String functionName, String filename) {
     symbolsRootTainted = new LinkedHashMap<String, RootTaintedSymbol>();
     this.nameFile = filename;
     this.functionNameCall = functionName;
    }

    /* METHODS that satisfy TaintedScope interface*/

    /*
     * Give the the name of taintedScope. How this scope don't have parent, then
     * your name is "globaltainted"
     */
    public String getScopeTaintedName() {
        return nameFile;
    }
    
    /*
     * Give the the name of user function or class method.
     */
    public String getFunctionNameCall() {
        return functionNameCall;
    }    

    /*
     * If the tainted scope is enclosing in another (if have parent), give the
     * name of the parent scope.
     * How the Tainted Table is the main scope, then don't have parent (null)
     */
    public ScopeTainted getEnclosingScopeTainted() {
    	return null;
    }

    /*
     * Give the main Map that contain the tainted variables
     */
    public Map getTaintedMembers() {
        return symbolsRootTainted;
    }

    /*
     * Insert a tainted variable in main Map.
     * Each member of main Map is a RelatedTaintedSymbol, composed by:
     * Map VariableTaintedSymbol and List to store code lines of tainted variables
     */
    public void define(RootTaintedSymbol rts) {
    	symbolsRootTainted.put(rts.getScopeTaintedName(), rts);
    }

    /*
     * Give RelatedTaintedSymbol from main Map, search by a gived name
     */
    public RootTaintedSymbol resolve(String name) {
    	return symbolsRootTainted.get(name);
    }

    public TaintedTable copyTaintedTable() {
        TaintedTable tab = new TaintedTable("aux");
        for(Iterator <Symbol> it = this.getTaintedMembers().values().iterator(); it.hasNext();){
		Symbol cs = it.next();
            try {
                tab.getTaintedMembers().put(cs.getName(), cs.clone());
            } catch (CloneNotSupportedException ex) {
                Logger.getLogger(TaintedTable.class.getName()).log(Level.SEVERE, null, ex);
            }
	 }
    	return tab;
        
    }
    
    public void copyToMTS(TaintedTable m, UntaintedTable mu) { // m = mts
        Iterator <RootTaintedSymbol> it = this.getTaintedMembers().values().iterator(); // mts_aux
        RootTaintedSymbol rts, rts_m;
        RelatedTaintedSymbol rtt=null, rtt_m=null;
        VariableTaintedSymbol vts = null, vts_m;
        for(;it.hasNext();){//mts_aux
            rts = it.next();
            if (m.getTaintedMembers().containsKey(rts.getScopeTaintedName()) == false)
                m.getTaintedMembers().put(rts.getScopeTaintedName(), rts);
            else{
                rts_m = (RootTaintedSymbol) m.getTaintedMembers().get(rts.getScopeTaintedName());
                Iterator <Integer> it1;
                Iterator <String> it2 = rts.getFilesList().iterator();
                int i;
                String s;
                for (it1 = rts.getLinesList().iterator(); it1.hasNext();){
                    i = it1.next();
                    s = it2.next();
                    if (i != 0){ // as var globais em mts_aux tem linha = 0
                        if (rts_m.getLinesList().contains(i) == false ||
                            rts_m.getLinesList().contains(i) == true && rts_m.getFilesList().contains(s) == false){
                            rts_m.getLinesList().add(i);
                            rts_m.getFilesList().add(s);
                            for (Iterator <RelatedTaintedSymbol> it3 = rts.getListTaintedMembers().iterator(); it3.hasNext();){
                                rtt = it3.next();
                                if (rtt.getLineRts() == i && rtt.getFileRts().equals(s)){
                                    rts_m.define(rtt);
                                    break;
                                }
                            }
                        }
                        else{
                            // Obter RelatedTaintedSymbol de mts_princ de i e s
                            for (Iterator <RelatedTaintedSymbol> it3 = rts_m.getListTaintedMembers().iterator(); it3.hasNext();){
                                rtt_m = it3.next();
                                if (rtt_m.getLineRts() == i && rtt_m.getFileRts().equals(s))
                                    break;
                            }
                            // Obter RelatedTaintedSymbol de mts_aux de i e s para copiar os vts para mts_princ
                            for (Iterator <RelatedTaintedSymbol> it3 = rts.getListTaintedMembers().iterator(); it3.hasNext();){
                                rtt = it3.next();
                                if (rtt.getLineRts() == i && rtt.getFileRts().equals(s))
                                    break;
                            }
                            
                            Iterator <VariableTaintedSymbol> it3 = rtt.getTaintedMembers().values().iterator();
                            for (;it3.hasNext();){
                                vts = it3.next();
                                if (rtt_m.getTaintedMembers().containsKey(vts.getName()) == false){
                                    rtt_m.define(vts);
                                }
                                else{
                                    vts_m = (VariableTaintedSymbol) rtt_m.getTaintedMembers().get(vts.getName());
                                    Iterator <Integer> it4 = vts.getVariableLines().iterator();
                                    Iterator <String> it5 = vts.getVariableFiles().iterator();
                                    for (; it4.hasNext();){
                                        int ii = it4.next();
                                        String ss = it5.next();
                                        if (vts_m.getVariableLines().contains(ii) == false ||
                                            vts_m.getVariableLines().contains(ii) == true && vts_m.getVariableFiles().contains(ss) == false){
                                            vts_m.getVariableLines().add(ii);
                                            vts_m.getVariableFiles().add(ss);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                
                // Se rts passou de untainted (vindo de mus) para tainted (em mts_aux), retirar rts de mus
                Symbol sym = rts.getSymbol();
                if (mu.existSymbol(sym.getName()) == true) // verify if symbol pass to untaint to taint
                    mu.removeUntaintSymbol(sym);
            }
        }
    }
    
    public void copyGlobalsToMTS(TaintedTable mts_princ , UntaintedTable mus_princ , UntaintedTable mus_aux, MethodSymbol meth_sym_clone){
        for(Iterator <Symbol> it = meth_sym_clone.getGlobalVarsOfFunction().values().iterator(); it.hasNext();){
            Symbol sym = it.next();
            if (this.getTaintedMembers().containsKey(sym.getName()) == true && mus_aux.existSymbol(sym.getName()) == false){
                if (mts_princ.getTaintedMembers().containsKey(sym.getName()) == true){
                    // Se passou de untainted para tainted, retirar de untainted
                    if(mus_princ.existSymbol(sym.getName()) == true)
                        mus_princ.removeUntaintSymbol(sym);                   
                else{
                    RootTaintedSymbol rts_aux = (RootTaintedSymbol) this.getTaintedMembers().get(sym.getName());
                    RootTaintedSymbol rts_princ = (RootTaintedSymbol) mts_princ.getTaintedMembers().get(sym.getName());
                    int index = rts_aux.getLinesList().size()-1;
                    int i = (Integer) rts_aux.getLinesList().get(index);
                    String s = (String) rts_aux.getFilesList().get(index);
                    RelatedTaintedSymbol rtt_aux = (RelatedTaintedSymbol) rts_aux.getListTaintedMembers().get(index);
                    if (rts_princ.getLinesList().contains(i) == false){
                        rts_princ.getLinesList().add(i);
                        rts_princ.getFilesList().add(s);
                        rts_princ.getListTaintedMembers().add(rtt_aux);
                    }
                    else{
                        int index_princ = rts_princ.getLinesList().indexOf(i);
                        if (rts_princ.getFilesList().get(index_princ).equals(s) == false){
                            rts_princ.getLinesList().add(i);
                            rts_princ.getFilesList().add(s);
                            rts_princ.getListTaintedMembers().add(rtt_aux);
                        }
                        else{
                            rts_princ.getListTaintedMembers().set(index_princ, rtt_aux);
                        }
                    }
                }
                }
            }
        }
    }

public void removeDuplicates(Symbol sym){
    if (this.getTaintedMembers().containsKey(sym.getScope().getScopeName()) == true){
        RootTaintedSymbol Rrt = (RootTaintedSymbol) this.getTaintedMembers().get(sym.getScope().getScopeName());
        if (Rrt.getLinesList().size() > 1){
            int last_i = (Integer) Rrt.getLinesList().get(Rrt.getLinesList().size()-1);
            String last_s = (String) Rrt.getFilesList().get(Rrt.getFilesList().size()-1);
            
            int penultimate_i = (Integer) Rrt.getLinesList().get(Rrt.getLinesList().size()-2);
            String penultimate_s = (String) Rrt.getFilesList().get(Rrt.getFilesList().size()-2);
            if (last_i == penultimate_i && last_s.equals(penultimate_s) == true){
                Rrt.getLinesList().remove(Rrt.getLinesList().size()-1);
                Rrt.getFilesList().remove(Rrt.getFilesList().size()-1);
            }
        }
     }
}    
    
    
    public void printMTS(){
        TaintedTable mts = this;
        Iterator <RootTaintedSymbol> it = mts.getTaintedMembers().values().iterator();
        System.out.println("\n\nTainted File = "+mts.getScopeTaintedName()+"\n");
        System.out.println("Nº de Vars/funcoes tainted = "+mts.getTaintedMembers().size()+"\n");
        System.out.println("Mapa de Vars/funcoes tainted e suas dependencias:\n");
        System.out.println("**************************************************\n");
        VariableTaintedSymbol aux1;
        RelatedTaintedSymbol aux;
        RootTaintedSymbol raux;
        for(; it.hasNext();){
            raux = it.next();
            System.out.println("\nROOT_VAR: "+raux.getName());
            for(Iterator <RelatedTaintedSymbol> it2 = raux.getListTaintedMembers().iterator(); it2.hasNext();){
                aux = it2.next();
                System.out.println("\tLine: "+aux.getLineRts()+"  FILE: "+aux.getFileRts());
                Iterator <VariableTaintedSymbol> it3 = aux.getTaintedMembers().values().iterator();
                for(;it3.hasNext(); ){
                    aux1 = it3.next();
                    System.out.println("\t\tName: "+aux1.getName()+"  Lines: "+aux1.getVariableLines().toString()+
                                       "  FILES: "+aux1.getVariableFiles().toString());
                }
            }
        }
    }    
    
    
    public void cleanAll(){
        Collection <RootTaintedSymbol> c = symbolsRootTainted.values();
    	c.removeAll(c);
    	symbolsRootTainted.clear();
    }
    
    @Override
    public String toString() {
    	return getScopeTaintedName()+":"+symbolsRootTainted;
    }

    public void define(Symbol sym) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public List getListTaintedMembers() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

} public class VariableTaintedSymbol extends Symbol{
    // criacao do mapa de variaveis/funcoes tainted a inserir nos mapas das relacoes
    List<Integer> linesVars; // Lista que armazenara as linhas de vars, fun tainteds
    List<String> filesVars; // Lista que armazenara as ficheiros a que pertencem as vars, fun tainteds

    /* CONSTRUCTOR */
    public VariableTaintedSymbol(String name, int line, int tainted, String file){
        super(name, tainted, line, file);
        linesVars = new ArrayList<Integer>();
        filesVars = new ArrayList<String>();
        linesVars.add(line);
        filesVars.add(file);
    }


    /* METHODS of the class*/

    /*
     * Insert a code line in List of the tainted variable included in RelatedTaintedSymbol Map.
     * This appened when dependent tainted variable is identified, and your code line
     * is included in List
     */
    public void InsertLine (int line){
        linesVars.add(line);
    }

    /*
     * Give the List of line codes from the variable included in RelatedTainted Map
     */
    public List getVariableLines (){
        return linesVars;
    }    

    /*
     * Insert name of file in List of the tainted variable included in RelatedTaintedSymbol Map.
     * This appened when dependent tainted variable is identified, and your file name
     * is included in List
     */
    public void InsertFile (String file){
        filesVars.add(file);
    }

    /*
     * Give the List of files from the variable included in RelatedTainted Map
     */
    public List getVariableFiles (){
        return filesVars;
    }
} public class RelatedTaintedSymbol implements ScopeTainted{
    // criacao do mapa de variaveis/funcoes tainted e relacoes
    Map<String, VariableTaintedSymbol> MapVarTaint;
    int lineRts; // Lista que armazenara as linhas de vars, fun tainteds
    String fileRts; // Lista que armazenara os files names de vars, fun tainteds


    /* CONSTRUCTOR */
    public RelatedTaintedSymbol(int line, String file){
        MapVarTaint = new LinkedHashMap<String, VariableTaintedSymbol>();
        this.lineRts = line;
        this.fileRts = file;
    }


    /* METHODS that satisfy TaintedScope interface*/

    /*
     * Give the the name of RelatedTaintedSymbol scope.
     */
    public String getScopeTaintedName() {
    	throw new UnsupportedOperationException("Not supported yet.");
    }

     /*
     * If the tainted scope is enclosing in another (if have parent), give the
     * name of the parent scope.
     */
    public ScopeTainted getEnclosingScopeTainted() {
    	throw new UnsupportedOperationException("Not supported yet.");
    }

    /*
     * Give the Map that contain the tainted variables dependents of the
     * variable included in main Map
     */
    public Map getTaintedMembers() {
        return MapVarTaint;
    }

    /*
     * Give the List of line codes from the variable included in main Map
     */
    public int getLineRts (){
        return lineRts;
    }

    /*
     * Give the List of the files names from the variable included in main Map
     */
    public String getFileRts (){
        return fileRts;
    }

    /*
     * Insert a tainted variable in Map of the tainted variable included in main Map.
     * Each member of this Map is a VariableTaintedSymbol, composed by:
     * Symbol and List to store code lines of tainted variables
     */
    public void define(VariableTaintedSymbol sym) {
        MapVarTaint.put(sym.getName(), sym);
    }

    /*
     * Insert a code line in List of the tainted variable included in main Map.
     * This appened when new tainted variable is identified, and your code line
     * is included in List
     */
    public void setLineRts (int line){
        lineRts = line;
    }

    /*
     * Insert a file name in List of the tainted variable included in main Map.
     * This appened when new tainted variable is identified, and your code line
     * is included in List
     */
    public void setFileRts (String file){
       fileRts = file;
    }

    public void define(Symbol sym) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public List getListTaintedMembers() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

} public class ArgFunctionSymbol implements Cloneable{
    String paramName;
    int line;
    String type; // var => $var; pointer => &$var; equal => $var = qq
    String equal; // -; -; atom
    String callFunctionArg; //var que entra na chamada da funcao
    int positionParam; //primeiro, segundo,... parametro
    int taintedValueCallFunctionArg; //tainted value da var que entra na chamada da funcao
    
    // *** CONSTRUCTORS
    //public ArgFunctionSymbol(String name, int tainted, int line, String file, String t, String e, int p) {
    public ArgFunctionSymbol(String name, int line, String t, String e, int p) {    
        this.paramName = name;
        this.line = line;
        this.type = t;
        this.equal = e;
        this.positionParam = p;
        this.callFunctionArg = "";
        this.taintedValueCallFunctionArg = 0;
    }

    // *** METHODS
    
    public String getParamName() {
        return paramName;
    }
    
    public int getLine() {
        return line;
    }
    
    public String getType() {
        return type;
    }

    public String getEqual() {
        return equal;
    }
    
    public String getCallFunctionArg() {
        return this.callFunctionArg;
    }
    
    public int getTaintedValueCallFunctionArg() {
        return taintedValueCallFunctionArg;
    }
    
    public int getPositionParam() {
        return positionParam;
    }

    public void setParamName(String name) {
        this.paramName = name;
    }
    
    public void setLine(int l) {
        this.line = l;
    }
    
    public void setType(String t) {
        this.type = t;
    }
    
    public void setEqual(String e) {
        this.equal = e;
    }
    
    public void setCallFunctionArg(String arg) {
        this.callFunctionArg = arg;
    }
    
    public void setTaintedValueCallFunctionArg(int t) {
        this.taintedValueCallFunctionArg = t;
    }
    
    public void setPositionParam(int p) {
        positionParam = p;
    }
    
     @Override
     public Object clone() throws CloneNotSupportedException {
    	return super.clone();
    }
} public class SymbolTable implements Scope{
    String name;
    //Map<String, Symbol> symbols;
    List<Symbol> symbols;
    Boolean haveFunctions;
    Boolean haveClasses;
    List<String> includeFiles;
    Map <String, Symbol> aliases;
    Map <String, Symbol> globalVars;
    MethodTableCalls methodCallInstance;    // para somente os StaticMemberAccees diferentes de self e parent
    MethodTaintedTable methTaintedInstance; // para somente os StaticMemberAccees diferentes de self e parent


    // *** CONSTRUCTORS
    public SymbolTable(String name) {
        this.name = name;
        //symbols = new LinkedHashMap<String, Symbol>();
        symbols = new ArrayList<Symbol>();
        haveFunctions = false;
        haveClasses = false;
        includeFiles = new ArrayList<String>();
        this.aliases = new LinkedHashMap<String, Symbol>();
        this.globalVars = new LinkedHashMap<String, Symbol>();

        // cria a tabela para as st dos StaticMemberAccees que serao chamados diferentes de self e parent
        methodCallInstance = new MethodTableCalls(name);

        // cria a tainted table para as chamadas dos StaticMemberAccees diferentes de self e parent
        methTaintedInstance = new MethodTaintedTable(name);
   }

    // *** METHODS

    // Satisfy Scope interface
    public String getScopeName() {
    	//return "global";
        return name;
    }

    // am I nested in another?
    public Scope getEnclosingScope() {
    	return null;
    }

    /*
     * Give the Map that contain the Symbols of main Map
     * This symbols are root symbol the scopes CallSymbol (for Callfunction
     * or assign instrutions) or MethodSymbol (for user function definition)
     */
    public List getMembers() {
        return symbols;
    }

    /*
     * Give the root Symbol of the scope. In another words, give the symbol
     * that create a new scope.
     * Here, in main table of symbols, don't exist root symbol.
     */
    public Symbol getScopeSymbol() {
    	return null;
    }

    /*
     * Tell if file have functions definied by the programmer
     */
    public Boolean getHaveFunctions() {
    	return haveFunctions;
    }

    /*
     * Tell if file have classes definied by the programmer
     */
    public Boolean getHaveClasses() {
    	return haveClasses;
    }

    /*
     * Give the list of the include files that the analysed file have
     */
    public List<String> getIncludeFiles() {
    	return includeFiles;
    }

    /*
     * Give the Map of the alises defined inthe symbolTable
     */
    public Map getAliases(){
        return this.aliases;
    }

    public Map getGlobalVarsOfSymbolTable() {
        return globalVars;
    }

    public MethodTableCalls getMethodCallInstance() {
        return this.methodCallInstance;
    }

    public MethodTaintedTable getMethodTaintedInstance() {
        return this.methTaintedInstance;
    }
    
    public String getInstanceNameFromAliases(String s, InstanceTable instTab){
        String instName = "";
        boolean found = false;
        while (found == false){
            if (instTab.containsInstance(s) == true){
                instName = s;
                found = true;
            }
            else{
                if (this.getAliases().containsKey(s)){
                    Symbol sym = (Symbol) this.getAliases().get(s);
                    s = sym.getName();
                }
            }
        }
        return instName;
    }

    /*
     * Return a specific symbol
     */
    public Symbol getSymbolOfListSymbols(String symName){
        Symbol sym_final = null;
        Iterator <Symbol> it = this.getMembers().iterator();
        Symbol sym;
        for (;it.hasNext();){
                sym = it.next();
                if (sym.getName().equals(symName) == true){
                    sym_final = sym;
                    break;
                }
        }
        return sym_final;
    }

    /*
     * Tells if the symbols list contains a gived symbol
     */
    public Boolean containsSymbol(String symName){
        Iterator <Symbol> it = this.getMembers().iterator();
        Symbol sym;
        Boolean haveSymbol = false;
        for (;it.hasNext();){
                sym = it.next();
                if (sym.getName().equals(symName) == true){
                    haveSymbol = true;
                    break;
                }
        }
        return haveSymbol;
    }

    /*
     * Insert a root symbol (new scope) in main Map.
     */
    public void define(Symbol sym, Scope scp, Boolean IsVariableSymbol) {
        symbols.add(sym);
        sym.setRootScope(scp);
        sym.setScope(this);
        sym.setIsVariableSymbol(IsVariableSymbol);
    }

    /*
     * Set true if the analysed file have functions defined by user
     */
    public void setHaveFunctions(){
        haveFunctions = true;
    }

    /*
     * Set true if the analysed file have classes defined by user
     */
    public void setHaveClasses(){
        haveClasses = true;
    }
    
    public void setGlobalVarSymbolTable(String varName, Symbol gvar) {
        globalVars.put(varName, gvar);
    }

    /*
     * Set true if the analysed file have functions defined by user
     */
    public void setAllSymbols(List<Symbol> syms){
        symbols.addAll(syms);
    }
    
    /*
     * Set true if the analysed file have functions defined by user
     */
    public void setAllIncludeFiles(List<String> incs){
        includeFiles.addAll(incs);
    }    

    /*
     * Not relevant here!
     */
    //public Boolean resolve(String name, TaintedTable mts, UntaintedTable mus) {
    public void resolveSymbol(Scope scp, Symbol sy, TaintedTable mts, UntaintedTable mus, String file){
    	//return symbols.get(name);
    //    return true;
    }


    public Boolean resolve(Symbol symb, TaintedTable mts, UntaintedTable mus) {
        return true;
    }
     
    /*
     * Move include file symbolTable from mst to mift
     */
    public void mvIncludeFiles(List fileList) throws IOException{
        for(Iterator <String> it1 = this.getIncludeFiles().iterator(); it1.hasNext();){
            String s = it1.next();
            if(GlobalDataApp.args_flags[3] == 1){
                if (GlobalDataSqli.MainSymbolTable.containsKey(s) == true){
                    GlobalDataSqli.MainIncludeFilesTable.put(s, (SymbolTable)GlobalDataSqli.MainSymbolTable.get(s));
                    GlobalDataSqli.MainSymbolTable.remove(s);
                }
                else{
                    if (GlobalDataSqli.MainIncludeFilesTable.containsKey(s) == false){
                        try {
                            // file include do not exists in mst and mift
                            // Create AST
                            buildAST ast = new buildAST(s, 0);
                            CommonTreeNodeStream nodes = ast.getNodes();
                            
                            // build walker tree to SQLI
                            buildWalkerTree_sqli sqli = new buildWalkerTree_sqli(nodes, s, GlobalDataSqli.MainSymbolTable, GlobalDataSqli.MainIncludeFilesTable,
                                    GlobalDataSqli.MainFunctionsTable, GlobalDataSqli.MainFunctionsTaintedTable,
                                    GlobalDataSqli.MainTaintedTable, GlobalDataSqli.mus, GlobalDataSqli.MainLinesToCorrect,
                                    GlobalDataSqli.MainClassesTable, GlobalDataSqli.MainInstancesTable, fileList);
                            
                            GlobalDataSqli.MainIncludeFilesTable.put(s, (SymbolTable)GlobalDataSqli.MainSymbolTable.get(s));
                            GlobalDataSqli.MainSymbolTable.remove(s);
                        } catch (RecognitionException ex) {
                            Logger.getLogger(SymbolTable.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                }

                SymbolTable st_aux = GlobalDataSqli.MainIncludeFilesTable.get(s);
                if (st_aux.getIncludeFiles().isEmpty() == false){
                    st_aux.mvIncludeFiles(fileList);
                }
            }

            if(GlobalDataApp.args_flags[6] == 1){
                if (GlobalDataCodeInj.MainSymbolTable.containsKey(s) == true){
                    GlobalDataCodeInj.MainIncludeFilesTable.put(s, (SymbolTable)GlobalDataCodeInj.MainSymbolTable.get(s));
                    GlobalDataCodeInj.MainSymbolTable.remove(s);
                }
                else{
                    if (GlobalDataCodeInj.MainIncludeFilesTable.containsKey(s) == false){
                        // file include do not exists in mst and mift
                        // Create AST
                        buildAST ast = new buildAST(s, 0);
                        CommonTreeNodeStream nodes = ast.getNodes();

                        // build walker tree to SQLI
                        buildWalkerTree_CodeInj ci = new buildWalkerTree_CodeInj(nodes, s, GlobalDataCodeInj.MainSymbolTable, GlobalDataCodeInj.MainIncludeFilesTable,
                                                                            GlobalDataCodeInj.MainFunctionsTable, GlobalDataCodeInj.MainFunctionsTaintedTable,
                                                                            GlobalDataCodeInj.MainTaintedTable, GlobalDataCodeInj.mus, GlobalDataCodeInj.MainLinesToCorrect,
                                                                            GlobalDataCodeInj.MainClassesTable, GlobalDataCodeInj.MainInstancesTable, fileList); 

                        GlobalDataCodeInj.MainIncludeFilesTable.put(s, (SymbolTable)GlobalDataCodeInj.MainSymbolTable.get(s));
                        GlobalDataCodeInj.MainSymbolTable.remove(s);
                    }
                }

                SymbolTable st_aux = GlobalDataCodeInj.MainIncludeFilesTable.get(s);
                if (st_aux.getIncludeFiles().isEmpty() == false){
                    st_aux.mvIncludeFiles(fileList);
                }
            }

            if(GlobalDataApp.args_flags[7] == 1){
                if (GlobalDataXSS.MainSymbolTable.containsKey(s) == true){
                    GlobalDataXSS.MainIncludeFilesTable.put(s, (SymbolTable)GlobalDataXSS.MainSymbolTable.get(s));
                    GlobalDataXSS.MainSymbolTable.remove(s);
                }
                else{
                    if (GlobalDataXSS.MainIncludeFilesTable.containsKey(s) == false){
                        // file include do not exists in mst and mift
                        // Create AST
                        buildAST ast = new buildAST(s, 0);
                        CommonTreeNodeStream nodes = ast.getNodes();

                        // build walker tree to SQLI
                        buildWalkerTree_XSS xss = new buildWalkerTree_XSS(nodes, s, GlobalDataXSS.MainSymbolTable, GlobalDataXSS.MainIncludeFilesTable,
                                                                            GlobalDataXSS.MainFunctionsTable, GlobalDataXSS.MainFunctionsTaintedTable,
                                                                            GlobalDataXSS.MainTaintedTable, GlobalDataXSS.mus, GlobalDataXSS.MainLinesToCorrect,
                                                                            GlobalDataXSS.MainClassesTable, GlobalDataXSS.MainInstancesTable, fileList);

                        GlobalDataXSS.MainIncludeFilesTable.put(s, (SymbolTable)GlobalDataXSS.MainSymbolTable.get(s));
                        GlobalDataXSS.MainSymbolTable.remove(s);
                    }
                }

                SymbolTable st_aux = GlobalDataXSS.MainIncludeFilesTable.get(s);
                if (st_aux.getIncludeFiles().isEmpty() == false){
                    st_aux.mvIncludeFiles(fileList);
                }
            }
        }        
    }

    
    
    /*
     * Move include file symbolTable from mst to mift
     */
    public void mvIncludeFiles(List fileList, String file) throws IOException{
    if(GlobalDataApp.args_flags[3] == 1){
        if (GlobalDataSqli.MainIncludeFilesTable.containsKey(file) == false){
            if (GlobalDataSqli.MainSymbolTable.containsKey(file) == true){                               
                GlobalDataSqli.MainIncludeFilesTable.put(file, (SymbolTable)GlobalDataSqli.MainSymbolTable.get(file));
                GlobalDataSqli.MainSymbolTable.remove(file);
            }
            else{
                try {
                    // file include do not exists in mst and mift
                    // Create AST
                    buildAST ast = new buildAST(file, 0);
                    CommonTreeNodeStream nodes = ast.getNodes();
                    
                    // build walker tree to SQLI
                    buildWalkerTree_sqli sqli = new buildWalkerTree_sqli(nodes, file, GlobalDataSqli.MainSymbolTable, GlobalDataSqli.MainIncludeFilesTable,
                            GlobalDataSqli.MainFunctionsTable, GlobalDataSqli.MainFunctionsTaintedTable,
                            GlobalDataSqli.MainTaintedTable, GlobalDataSqli.mus, GlobalDataSqli.MainLinesToCorrect,
                            GlobalDataSqli.MainClassesTable, GlobalDataSqli.MainInstancesTable, fileList);
                    
                    GlobalDataSqli.MainIncludeFilesTable.put(file, (SymbolTable)GlobalDataSqli.MainSymbolTable.get(file));
                    GlobalDataSqli.MainSymbolTable.remove(file);
                } catch (RecognitionException ex) {
                    Logger.getLogger(SymbolTable.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        } 
    }
        
    if(GlobalDataApp.args_flags[6] == 1){
        if (GlobalDataCodeInj.MainIncludeFilesTable.containsKey(file) == false){
            if (GlobalDataCodeInj.MainSymbolTable.containsKey(file) == true){
                GlobalDataCodeInj.MainIncludeFilesTable.put(file, (SymbolTable)GlobalDataCodeInj.MainSymbolTable.get(file));
                GlobalDataCodeInj.MainSymbolTable.remove(file);
            }
            else{
                try{
                    // file include do not exists in mst and mift
                    // Create AST
                    buildAST ast = new buildAST(file, 0);
                    CommonTreeNodeStream nodes = ast.getNodes();

                    // build walker tree to Code Injection
                    buildWalkerTree_CodeInj ci = new buildWalkerTree_CodeInj(nodes, file, GlobalDataCodeInj.MainSymbolTable, GlobalDataCodeInj.MainIncludeFilesTable,
                                                                        GlobalDataCodeInj.MainFunctionsTable, GlobalDataCodeInj.MainFunctionsTaintedTable,
                                                                        GlobalDataCodeInj.MainTaintedTable, GlobalDataCodeInj.mus, GlobalDataCodeInj.MainLinesToCorrect,
                                                                        GlobalDataCodeInj.MainClassesTable, GlobalDataCodeInj.MainInstancesTable, fileList);                                

                    GlobalDataCodeInj.MainIncludeFilesTable.put(file, (SymbolTable)GlobalDataCodeInj.MainSymbolTable.get(file));
                    GlobalDataCodeInj.MainSymbolTable.remove(file);
                } catch (Exception ex) {
                    Logger.getLogger(SymbolTable.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        } 
    }        
 
    if(GlobalDataApp.args_flags[7] == 1){
        if (GlobalDataXSS.MainIncludeFilesTable.containsKey(file) == false){
            if (GlobalDataXSS.MainSymbolTable.containsKey(file) == true){
                GlobalDataXSS.MainIncludeFilesTable.put(file, (SymbolTable)GlobalDataXSS.MainSymbolTable.get(file));
                GlobalDataXSS.MainSymbolTable.remove(file);
            }
            else{
                try{
                    // file include do not exists in mst and mift
                    // Create AST
                    buildAST ast = new buildAST(file, 0);
                    CommonTreeNodeStream nodes = ast.getNodes();

                    // build walker tree to XSS
                    buildWalkerTree_XSS xss = new buildWalkerTree_XSS(nodes, file, GlobalDataXSS.MainSymbolTable, GlobalDataXSS.MainIncludeFilesTable,
                                                                        GlobalDataXSS.MainFunctionsTable, GlobalDataXSS.MainFunctionsTaintedTable,
                                                                        GlobalDataXSS.MainTaintedTable, GlobalDataXSS.mus, GlobalDataXSS.MainLinesToCorrect,
                                                                        GlobalDataXSS.MainClassesTable, GlobalDataXSS.MainInstancesTable, fileList);                                

                    GlobalDataXSS.MainIncludeFilesTable.put(file, (SymbolTable)GlobalDataXSS.MainSymbolTable.get(file));
                    GlobalDataXSS.MainSymbolTable.remove(file);
                } catch (Exception ex) {
                    Logger.getLogger(SymbolTable.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        } 
    }           
}    
      

    /*
     * Print the elements of the main Map scope.
     */
    public void print(Scope scp){
        Symbol aux1;
        Scope s;
        if (!scp.getMembers().isEmpty()){
            System.out.println("\nScope: "+scp.getScopeName()+"\tsize="+scp.getMembers().size());
            Iterator <Symbol> it = scp.getMembers().iterator();
            for(; it.hasNext();){
                aux1 = it.next();
                if ( aux1.getRootScope() != null ) { // is a root of a new scope?
                        s = aux1.getRootScope();
                        s.print(s);
                }
            }
        }
         else{
            aux1 = scp.getScopeSymbol();
             System.out.println("Name: "+aux1.getName()+"\t\tline: "+aux1.getCodeLine()+"\t\ttainted: "
                                +aux1.getTainted()+"\t\tScope: "+aux1.getScope().getScopeName()+"\n");
         }
    }


    @Override
    public String toString() {
    	return getScopeName()+":"+symbols;
    }

    public void resolveSymbolIncludeSQLI(Scope scp, TaintedTable mts, UntaintedTable mus, Map mift, String filename, Map mft, Map mst, Map varsDB, Map mftt, Map MainLinesToCorrect) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public String resolveVarInclude(Scope scp, SymbolTable st) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void resolveSymbolFunctionSQLI(MethodSymbol mt, Scope rootScope, TaintedTable mts, UntaintedTable mus, Map mift, String filename, Map mft, Map mst, Map varsDB, Map mftt, Map MainLinesToCorrect) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Boolean verifyNumberVarList(int num_var){
        throw new UnsupportedOperationException("Not supported yet.");    
    }
    
    public void populateList(Scope scp_left, Scope scp_right, int num_var, TaintedTable mts, UntaintedTable mus, String filename){
        throw new UnsupportedOperationException("Not supported yet.");    
    }

    public String buildCorrectSQL(String connDB, String nameDB, int lineMysqliBindParam, List UserInput, TaintedTable mts_princ, SymbolTable st, Map MainLinesToCorrect) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Boolean buildCorrectCodeInj(String fileInc, List UserInput, TaintedTable mts_princ, SymbolTable st, Map MainLinesToCorrect){
            throw new UnsupportedOperationException("Not supported yet.");
    }

    public void resolveSymbolClass(TaintedTable mts, UntaintedTable mus, String filename) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void printtt(String string, Scope cp){
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void resolveSymbolParam(TaintedTable mts, UntaintedTable mus, String filename) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    public void resolveParam(Symbol symb, TaintedTable mts, UntaintedTable mus) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

} public interface Scope {
    public String getScopeName();		// do I have a name?
    public Scope getEnclosingScope();		// am I nested in another?
    //public Map getMembers();                    // list of my symbols
    public List getMembers();                    // list of my symbols
    public Symbol getScopeSymbol();             // get the symbol that create the scope (the root symbol)
    public void define(Symbol sym, Scope scp, Boolean IsVariableSymbol);	// define sym in this scope
    //public Boolean resolve(String name, TaintedTable mts, UntaintedTable mus);	// look up name in scope
    public Boolean resolve(Symbol symb, TaintedTable mts, UntaintedTable mus);	// look up name in scope
    public void resolveSymbol(Scope scp, Symbol sy, TaintedTable mts, UntaintedTable mus, String file); // resolve symbol in scope
    //public void resolveSymbolInclude(Scope scp1, TaintedTable mts, UntaintedTable mus); // resolve symbols in include/function file
    public void resolveSymbolClass(TaintedTable mts, UntaintedTable mus, String filename);
    //public void resolveSymbolIncludeSQLI(Scope scp, TaintedTable mts, UntaintedTable mus, Map mift, String filename, Map mft, Map mst, Map varsDB, Map mftt, Map MainLinesToCorrect);
    public String resolveVarInclude(Scope scp, SymbolTable st); // resolve name of include/require file
    public void print(Scope scp);
    //public void resolveSymbolFunctionSQLI(MethodSymbol mt, Scope rootScope, TaintedTable mts, UntaintedTable mus, Map mift, String filename, Map mft, Map mst, Map varsDB, Map mftt, Map MainLinesToCorrect);

    public Boolean verifyNumberVarList(int num_var);
    public void populateList(Scope scp_left, Scope scp_right, int num_var, TaintedTable mts, UntaintedTable mus, String filename);
    
    public String buildCorrectSQL(String connDB, String nameDB, int lineMysqliBindParam, List UserInput, TaintedTable mts_princ, SymbolTable st, Map MainLinesToCorrect);

    public Boolean buildCorrectCodeInj(String fileInc, List UserInput, TaintedTable mts_princ, SymbolTable st, Map MainLinesToCorrect);

    public void printtt(String string, Scope cp);
    
} public class ClassSymbol implements Cloneable{
    String className;
    String fileClass;
    String extendsNameClass;
    String fileExtendsClass;
    SymbolTable attributes;
    MethodTable membersMethods;
    
    
    // ****** CONSTRUCTORS ***********
     public ClassSymbol(String class_name, String file, String extendsClass) {
        this.className = class_name;
        this.fileClass = file;
        this.extendsNameClass = extendsClass;
        //this.attributes = new ArrayList<CallSymbol>();
        //this.membersMethods = new ArrayList<MethodSymbol>();
    }
    
    
    // *** METHODS ********
    public String getClassName() {
        return this.className;
    }

    public String getExtendsClassName() {
        return this.extendsNameClass;
    }

    public String getFileClass() {
        return this.fileClass;
    }

    public String getFileExtendsClass() {
        return this.fileExtendsClass;
    }
    
    public SymbolTable getAttributes() {
        return this.attributes;
    }
       
    public MethodTable getMembersMethods() {
        return this.membersMethods;
    }

    public MethodClass getMethodClass(String methName, String methType, Map mct) {
        MethodSymbol mss_final = null;
        ClassSymbol cs = null;
        MethodClass mc = null;
        int i;
        String f = "";
        Iterator <MethodSymbol> it = this.getMembersMethods().getMembers().iterator();
        MethodSymbol ms = null;
        Boolean contConstruct = false;
        Boolean cont_methName = false;
        for (;it.hasNext();){
            ms = it.next();
            if (ms.getFunctionName().equals(methName) == true){
                f = methName;
                cont_methName = true;
                break;
            }
            if (methType.equals("construct") == true && ms.getFunctionName().equals("__construct") == true){
                f = "__construct";
                contConstruct = true;
                break;
            }
        }

        if (cont_methName == true || contConstruct == true){
            mss_final = ms;
            cs = this;
        }
        else{
            String ff = this.fileExtendsClass;
            String fff = this.extendsNameClass;
            try{
                ClassTable ct = (ClassTable) mct.get(ff);
                cs = ct.getClassOfListClasses(fff);
                mc = cs.getMethodClass(methName, methType, mct);
            } catch (Exception e){}
        }

        if (mss_final != null)
            mc = new MethodClass(mss_final, cs);
        return mc;
    }



    /*
    public void setFunctionName(String name) {
        this.setName(name);
    }    
    
    public void setHaveSubFunctions() {
        this.haveSubFunctions = true;
    }
    
    public void setProgenitorFunction(String p) {
        this.Progenitorfunction = p;
    }

     *
     */

    public void setClassName(String n) {
        this.className = n;
        this.attributes = new SymbolTable(n);
        this.membersMethods = new MethodTable(n);
    }

    public void setExtendedNameClass(String n, String filename, Map mct) {
        this.extendsNameClass = n;
        ClassTable ct = (ClassTable) mct.get(filename);
        if (ct.containsClass(n) == true)
            this.fileExtendsClass = filename;
        else{
            for (Object key : mct.keySet()){
                //String k = (String) key;
                ct = (ClassTable) mct.get(key);
                if (ct.containsClass(n) == true){
                    this.fileExtendsClass = (String) key;
                    break;
                }
            }
        }
    }

/*
    public void setAttribut(CallSymbol attribute) {
        attributes.define(attribute, attribute, false);
        //attributes.add(attribute);
    }
    
    public void setMemberMethod(MethodSymbol mth) {
        membersMethods.add(mth);

    }
*/

    public SymbolTable copyListAttributes(SymbolTable st_toCopy) {
        SymbolTable att = new SymbolTable(null);
        SymbolTable st_ori;
        //List <CallSymbol> att = new ArrayList<CallSymbol>();
        Symbol sym;

        if (st_toCopy == null)
            st_ori = this.getAttributes();
        else
            st_ori = st_toCopy;

        //copia a lista de atributos da classe
        Scope scp, scpRoot=null;
        CallSymbol curScope;
        for(Iterator <Symbol> it = st_ori.getMembers().iterator(); it.hasNext();){
            scp = (Scope) it.next();
            sym = scp.getScopeSymbol();
            curScope = new CallSymbol (sym.getName(), sym.getCodeLine(), null, sym.getTainted(), sym.getFileSymbol());
            curScope.setRootScope(curScope);
            curScope.setScope(curScope);
            curScope.setIsVariableSymbol(false);
            copyScope(scp, curScope);
            att.define(curScope, curScope, false);
            //att.add(curScope);
         }
/*
         System.out.println("\n\n\t\tPRINT COPY\n");
         for(Iterator <Symbol> it = mt.getMembers().iterator(); it.hasNext();){
            scp = (Scope) it.next();
            scp.print(scp);
         }
 *
 */

        return att;
    }

    private void copyScope(Scope cs, Scope csClone){
        Symbol aux1, aux2;
        Scope s, s1 = null;
        CallSymbol curScope1;
        if (!cs.getMembers().isEmpty()){
            for(Iterator <Symbol> it = cs.getMembers().iterator(); it.hasNext();){
                aux1 = it.next();
                if ( aux1.getRootScope() != null ) { // is a root of a new scope?
                        s = aux1.getRootScope();
                        try {
                            s1 = (Scope) cs.getScopeSymbol().clone();
                        } catch (CloneNotSupportedException ex) {
                            Logger.getLogger(MethodSymbol.class.getName()).log(Level.SEVERE, null, ex);
                        }                        
                        curScope1 = new CallSymbol (aux1.getName(), aux1.getCodeLine(), s1, aux1.getTainted(), aux1.getFileSymbol());
                        curScope1.getScopeSymbol().setIsFunction(aux1.getIsFunction());
                        curScope1.getScopeSymbol().setIsSecureFunction(aux1.getIsSecureFunction());
                        curScope1.getScopeSymbol().setIsTaintedFunction(aux1.getIsTaintedFunction());
                        csClone.define(curScope1, curScope1, false);
                        copyScope(s, curScope1);
                }
                else{
                    VariableSymbol vs = new VariableSymbol(aux1.getName(), aux1.getTainted(), aux1.getCodeLine(), aux1.getFileSymbol());
                    csClone.define(vs, null, true);
                }
                    
            }
        }       
    }

} public class ClassTable  implements Scope{
    String name;
    List<ClassSymbol> classes;
    

    // *** CONSTRUCTORS
    public ClassTable(String name) {
        this.name = name;
        classes = new ArrayList<ClassSymbol>();
    }


    // *** METHODS

    // Satisfy Scope interface
    public String getScopeName() {
        return name;
    }

    // am I nested in another?
    public Scope getEnclosingScope() {
    	return null;
    }

    /*
     * Give the List that contain the methods (functions defined by user) of the file
     */
    public List getMembers() {       
        return classes;
    }
    
    public List getMembersList() {
        return null;
    }

    /*
     * Give the root Symbol of the scope. In another words, give the symbol
     * that create a new scope.
     * Here, in main table of symbols, don't exist root symbol.
     */
    public Symbol getScopeSymbol() {
    	return null;
    }

    /*
     * Insert a root symbol (new scope) in main Map.
     */
    public void define(ClassSymbol cl) {
    	//symbols.put(sym.getName(), sym);
        classes.add(cl);
    }
    
   /*
     * Return a specific ClassSymbol
     */
    public ClassSymbol getClassOfListClasses(String className){
        ClassSymbol cssym_final = null;
        Iterator <ClassSymbol> it = this.getMembers().iterator();
        ClassSymbol cssym;
        for (;it.hasNext();){
            cssym = it.next();
            if (cssym.getClassName().equals(className) == true){
                cssym_final = cssym;
                break;
            }
        }
        return cssym_final;
    }

    /*
     * Tells if the symbols list contains a gived symbol
     */
    
    public Boolean containsClass(String className){
        Iterator <ClassSymbol> it = this.getMembers().iterator();
        ClassSymbol cssym;
        Boolean haveClass = false;
        for (;it.hasNext();){
            cssym = it.next();
            if (cssym.getClassName().equals(className) == true){
                haveClass = true;
                break;
            }
        }
        return haveClass;
    }
     

    /*
     * Not relevant here!
     */
    //public Boolean resolve(String name, TaintedTable mts, UntaintedTable mus) {
    public void resolveSymbol(Scope scp, Symbol sy, TaintedTable mts, UntaintedTable mus, String file){
    }


    public Boolean resolve(Symbol symb, TaintedTable mts, UntaintedTable mus) {
    	//return symbols.get(name);
        return true;
    }

    @Override
    public String toString() {
    	return getScopeName()+":"+classes;
    }

    public void define(Symbol sym, Scope scp, Boolean IsVariableSymbol) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void resolveSymbolIncludeSQLI(Scope scp, TaintedTable mts, UntaintedTable mus, Map mift, String filename, Map mft, Map mst, Map varsDB, Map mftt, Map MainLinesToCorrect) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public String resolveVarInclude(Scope scp, SymbolTable st) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void print(Scope scp) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void resolveSymbolFunctionSQLI(MethodSymbol mt, Scope rootScope, TaintedTable mts, UntaintedTable mus, Map mift, String filename, Map mft, Map mst, Map varsDB, Map mftt, Map MainLinesToCorrect) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Boolean verifyNumberVarList(int num_var) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void populateList(Scope scp_left, Scope scp_right, int num_var, TaintedTable mts, UntaintedTable mus, String filename) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public String buildCorrectSQL(String connDB, String nameDB, int lineMysqliBindParam, List UserInput, TaintedTable mts_princ, SymbolTable st, Map MainLinesToCorrect) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Boolean buildCorrectCodeInj(String fileInc, List UserInput, TaintedTable mts_princ, SymbolTable st, Map MainLinesToCorrect) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void resolveSymbolClass(TaintedTable mts, UntaintedTable mus, String filename) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

        public void printtt(String string, Scope cp){
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void resolveSymbolParam(TaintedTable mts, UntaintedTable mus, String filename) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    public void resolveParam(Symbol symb, TaintedTable mts, UntaintedTable mus) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    public void copyScope(Scope src, Scope dest) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

} public class Instance implements Cloneable{
    String nameInstance;
    int createLine;
    int tainted = 0;
    String fileInstance;
    String classObject;
    String fileClass;
    SymbolTable instanceAttributes;
    //List <CallSymbol> instanceAttributes;
    TaintedTable mtsInstanceAttributes;
    UntaintedTable musInstanceAttributes;;
    MethodTableCalls methodCallInstance;
    MethodTaintedTable methTaintedInstance;
    InstanceTable objtsOfInstance; // objects que sao criados na instancia
    
    // ****** CONSTRUCTORS ***********
     public Instance(String nameInst, int line, String filename, String class_name, String file_class, ClassSymbol cl, Boolean isMysqli) {
        this.nameInstance = nameInst;
        this.createLine = line;
        this.fileInstance = filename;
        this.classObject = class_name;
        this.fileClass = file_class;

        if (isMysqli == false){
            // copiar da class
            instanceAttributes = cl.copyListAttributes(null);
            // Cria a taintedTable para os atributos da instancia.
            // Esta vai sendo actualizada 'a medida que os metodos vao sendo chamados
            mtsInstanceAttributes = new TaintedTable(nameInst);
            musInstanceAttributes = new UntaintedTable();
            
            // cria uma tabela de objectos que pertencem ao objecto em analise
            objtsOfInstance = new InstanceTable(nameInst);
         }
        // cria a tabela para as st dos metodos que serao chamados
        methodCallInstance = new MethodTableCalls(nameInst);

        // cria a tainted table para as chamadas dos metodos da instancia
        methTaintedInstance = new MethodTaintedTable(nameInst);


    }

     public Instance(Instance inst, ClassSymbol inst_cl) {
        this.nameInstance = inst.getInstanceName();
        this.createLine = inst.getCreateLineInstance();
        this.fileInstance = inst.getFileInstance();
        this.classObject = inst.getInstanceClass();
        this.fileClass = inst.getFileOfClass();
        this.tainted = inst.getTainted();

        // copiar atributos da instancia de input
        instanceAttributes = inst_cl.copyListAttributes(inst.getInstanceAttributes());

        // copiar mts_att e mus_att da instancia de input
        // Esta vai sendo actualizada 'a medida que os metodos vao sendo chamados
        mtsInstanceAttributes = new TaintedTable(inst.getInstanceName());
        mtsInstanceAttributes = inst.getMtsInstanceAttributes().copyTaintedTable();
        musInstanceAttributes = new UntaintedTable();
        musInstanceAttributes = inst.getMusInstanceAttributes().copyUntaintedTable();

        // cria uma tabela de objectos que pertencem ao objecto em analise
        objtsOfInstance = new InstanceTable(inst.getInstanceName());

        // cria a tabela para as st dos metodos que serao chamados
        methodCallInstance = new MethodTableCalls(inst.getInstanceName());

        // cria a tainted table para as chamadas dos metodos da instancia
        methTaintedInstance = new MethodTaintedTable(inst.getInstanceName());
    }
    
    // *** METHODS ********
    public String getInstanceName() {
        return this.nameInstance;
    }

    public int getCreateLineInstance() {
        return this.createLine;
    }

    public int getTainted() {
        return this.tainted;
    }

    public String getFileInstance() {
        return this.fileInstance;
    }

    public String getInstanceClass() {
        return this.classObject;
    }

    public String getFileOfClass() {
        return this.fileClass;
    }
    
    public SymbolTable getInstanceAttributes() {
        return this.instanceAttributes;
    }
       
    public TaintedTable getMtsInstanceAttributes() {
        return this.mtsInstanceAttributes;
    }

    public UntaintedTable getMusInstanceAttributes() {
        return this.musInstanceAttributes;
    }

    public MethodTableCalls getMethodCallInstance() {
        return this.methodCallInstance;
    }

    public MethodTaintedTable getMethodTaintedInstance() {
        return this.methTaintedInstance;
    }

    public InstanceTable getObjectsOfInstance() {
        return this.objtsOfInstance;
    }

    public Instance getInstanceOfReturn(String methName, int line, MethodSymbolCall mscAnaliseMeth, Scope sc, Boolean inAnaliseMeth) {
        Instance inst_final = null;
        MethodSymbolCall msc = mscAnaliseMeth;

        if (inAnaliseMeth == false){
            Iterator <MethodSymbolCall> it;
            for (it = this.methodCallInstance.getListMethodsMembers().iterator(); it.hasNext();){
                msc = it.next();
                if (msc.getFunctionNameCall().equals(methName) == true && msc.getLineNumberCall() == line)
                    break;
            }
        }

        try{
            Scope scp = sc;
            Iterator <Symbol> it1;
            if (inAnaliseMeth == false){
                for (it1 = msc.getCallFunctionSymbols().iterator(); it1.hasNext();){
                    scp = (Scope) it1.next();
                    if (scp.getScopeName().equals("return")){
                        break;
                    }
                }
            }
            
            Symbol sy = (Symbol) scp.getMembers().get(0);

            if (sy.getRootScope() != null){
                scp = (Scope) sy;
                String s = scp.getScopeSymbol().getName();
                Instance inst = getInstanceFromAliases(s, msc);
                if (inst != null){
                    scp = (Scope) scp.getMembers().get(0);
                    String methName_aux = scp.getScopeSymbol().getName();
                    inst.getInstanceOfReturn(methName_aux, scp.getScopeSymbol().getCodeLine(), null, null, false);
                }
            }
            else{
                Instance inst = getInstanceFromAliases(sy.getName(), msc);
                inst_final = inst;
            }
        } catch (Exception e){}

        return inst_final;
    }

    private static Instance getInstanceFromAliases(String s, MethodSymbolCall methSymCall){
        Instance inst = null;
        boolean found = false;
        while (found == false){
            if (methSymCall.getObjectsOfMethod().containsInstance(s) == true){
                inst = (Instance) methSymCall.getObjectsOfMethod().getInstanceOfListInstances(s);
                found = true;
            }
            else{
                if (methSymCall.getAliases().containsKey(s)){
                    Symbol sym = (Symbol) methSymCall.getAliases().get(s);
                    s = sym.getName();
                }
                else
                    break;
            }
        }

        return inst;
    }


    public void setTainted(int t) {
        this.tainted = t;
    }


    public void updateTainted(Scope cs_att, Symbol sym) {
        cs_att.getScopeSymbol().setTainted(sym.getTainted());
        cs_att.resolveSymbol(cs_att, sym, this.getMtsInstanceAttributes(), this.getMusInstanceAttributes(), sym.getFileSymbol());
        if (cs_att.getScopeSymbol().getTainted() == 1)
            this.setTainted(1);
        else{
            if (this.getTainted() == 1){
                Symbol sy;
                int numTaints = 0;
                for (int j = 0; j < this.getInstanceAttributes().getMembers().size(); j++){
                    sy = (Symbol) this.getInstanceAttributes().getMembers().get(j);
                    if (sy.getTainted() == 1)
                        numTaints++;
                }
                if (numTaints == 0)
                    this.setTainted(0);
            }
        }
    }
} public abstract class ScopedSymbol extends Symbol implements Scope, Cloneable{
    public Scope parent;

    // *** CONSTRUCTORS
    public ScopedSymbol(String name, int line, int tainted, Scope parent, String file) {
        super(name, tainted, line, file);
        this.parent = parent;
    }


    // *** METHODS

    // give the scope name
    public String getScopeName() {
    	return this.getName();
    }

    // am I nested in another?
    public Scope getEnclosingScope() {
        return parent;

    }
  
    // get the taint value of scope root symbol
    public Integer getTainted(Scope sc) {
        return sc.getScopeSymbol().getTainted();
    }

    // give the root symbol of the scope
     public Symbol getScopeSymbol() {
    	return super.getSymbol();
    }

    /* Insert symbol in Map
     * This symbol is a member of an assign instruction or a call function instruction
     */
    public void define(Symbol sym, Scope scp, Boolean IsVariableSymbol) {
        getMembers().add(sym); 
        sym.setRootScope(scp);
        sym.setScope(this);
        sym.setIsVariableSymbol(IsVariableSymbol); 
    }

    /*
     * Resolve Symbol... Bottom-Up navegation
     * This method occur after all symbols of one assign/call function instruction
     * are inserted in scope. After that, one by one is analyse (taint/untaint)
     */
    public void resolveSymbol(Scope scp, Symbol sy, TaintedTable mts, UntaintedTable mus, String file) {
        Boolean b = scp.resolve(sy, mts, mus);
        Symbol sym = scp.getScopeSymbol();

	// if symbol is tainted, then insert the symbol scope in the main TaintedTable, if it don't exist yet
	// if don't, then verify if it pass to taint to untaint, and insert in main UntaintedTable
	if (b == true){
            sy.setTainted(1);
            if (mts.getTaintedMembers().containsKey(sym.getName()) == false){ // verify if the tainted symbol exist in mts TaintedTable
                RootTaintedSymbol Rrt = new RootTaintedSymbol(sym.getName(), sym.getCodeLine(), sym.getTainted(), sym.getAlfanumeric(), sym.getFileSymbol());
                mts.define(Rrt); // insert in mts TaintedTable
            }
            else{
                RootTaintedSymbol Rrt = (RootTaintedSymbol) mts.getTaintedMembers().get(sym.getName());
                if (Rrt.getLinesList().contains(sym.getCodeLine()) == false ||
                   (Rrt.getLinesList().contains(sym.getCodeLine()) == true && Rrt.getFilesList().contains(sym.getFileSymbol()) == false)){
			Rrt.setLineCode(sym.getCodeLine());
			Rrt.setFile(sym.getFileSymbol());
                        RelatedTaintedSymbol rtt = new RelatedTaintedSymbol(sym.getCodeLine(), sym.getFileSymbol());
                        Rrt.define(rtt);
                }
	   }
	   if (mus.existSymbol(sym.getName()) == true) // verify if symbol pass to untaint to taint
		mus.removeUntaintSymbol(sym);
	}
	else{
            // verify if symbol pertence to mts and not to mus, then pass to taint to untaint
            if (mts.getTaintedMembers().containsKey(sym.getName()) == true && mus.existSymbol(sym.getName()) == false){
                RootTaintedSymbol Rrt = (RootTaintedSymbol) mts.getTaintedMembers().get(sym.getName());
		if (Rrt.getLinesList().contains(sy.getCodeLine()) == false)
                    mus.insertUntaintSymbol(sym);
            }
	}
    }


    /*
     * Give if the symbol is taint or not.
     * This method occur after all symbols of one assign/call function instruction
     * are inserted in scope. After that, one by one symbol is analyse (taint/untaint)
     */
    public Boolean resolve(Symbol symb, TaintedTable mts, UntaintedTable mus) {
    	Symbol aux;
        String s, nam;
        RelatedTaintedSymbol rtt;
        RootTaintedSymbol Rrt;
        Scope scp;

        // Caso o symbol ja seja tainted. Coloca o parent scope a taint
        Symbol sym = symb;
        nam = sym.getName();
        if (sym.getTainted() == 1 && sym.getAlfanumeric() == false){
            scp =sym.getScope();
            scp.getScopeSymbol().setTainted(1);

            // No caso de nome da funcao ser tainted
            if (mts.getTaintedMembers().containsKey(nam) == true){
                // Inserir o socpe parent como dependente da funcao tainted
                Rrt = (RootTaintedSymbol) mts.getTaintedMembers().get(nam);
                rtt = (RelatedTaintedSymbol) Rrt.getListTaintedMembers().get(Rrt.getListTaintedMembers().size()-1);

                // Caso o parent nao pertenca 'a lista da funcao tainted
                if (rtt.getTaintedMembers().containsKey(scp.getScopeName()) == false){
                    VariableTaintedSymbol var = new VariableTaintedSymbol(scp.getScopeName(),
                                                scp.getScopeSymbol().getCodeLine(), scp.getScopeSymbol().getTainted(),
                                                scp.getScopeSymbol().getFileSymbol());
                    rtt.define(var);
                }
                else{ // Caso o parent pertenca 'a lista da funcao tainted
                    VariableTaintedSymbol var = (VariableTaintedSymbol) rtt.getTaintedMembers().get(scp.getScopeName());
                    var.InsertLine(scp.getScopeSymbol().getCodeLine());
                    var.InsertFile(scp.getScopeSymbol().getFileSymbol());
                }
                return true;
            }
            
            // Se uma userfunction ver se os seus parametros sao tainted e inserir a function como dependente deles
            if (sym.getIsUserFunction() == true){
                Scope scp_aux = (Scope) sym;
                String sy_name;
                Symbol sy_aux;
                Iterator <Symbol> it;
                for (it = scp_aux.getMembers().iterator(); it.hasNext(); ){
                    sy_aux = it.next();
                    sy_name = sy_aux.getName();
                    if (sy_aux.getTainted() == 1){
                        if (mts.getTaintedMembers().containsKey(sy_name) == true){
                            // Inserir o nome da user function como dependente do seu parametro
                            Rrt = (RootTaintedSymbol) mts.getTaintedMembers().get(sy_name);
                            rtt = (RelatedTaintedSymbol) Rrt.getListTaintedMembers().get(Rrt.getListTaintedMembers().size()-1);

                            // Caso a user function nao pertenca 'a lista do parametro tainted
                            if (rtt.getTaintedMembers().containsKey(sym.getName()) == false){
                                VariableTaintedSymbol var = new VariableTaintedSymbol(sym.getName(),
                                                            sym.getCodeLine(), sym.getTainted(),
                                                            sym.getFileSymbol());
                                rtt.define(var);                            
                            }
                            else{ // Caso a user function pertenca 'a lista do parametro tainted
                                VariableTaintedSymbol var = (VariableTaintedSymbol) rtt.getTaintedMembers().get(sym.getName());
                                var.InsertLine(sym.getCodeLine());
                                var.InsertFile(sym.getFileSymbol());
                            }
                        
                        }
                    }
                }
                
                //if (mts.getTaintedMembers().containsKey(nam) == false){ // verify if the tainted symbol exist in mts TaintedTable
                Rrt = new RootTaintedSymbol(sym.getName(), sym.getCodeLine(), sym.getTainted(), sym.getAlfanumeric(), sym.getFileSymbol());
                mts.define(Rrt); // insert in mts TaintedTable
            }
            
            return true;
        }

        // Caso o symbol seja uma var ja tainted e pertenca a tabela das vars tainteds
        if (mts.getTaintedMembers().containsKey(nam) == true && mus.existSymbol(sym.getName()) == false) {
            // colocar scope parent tainted
            scp =sym.getScope();
            scp.getScopeSymbol().setTainted(1);

            // Inserir o socpe parent como dependente do symbol tainted
            Rrt = (RootTaintedSymbol) mts.getTaintedMembers().get(nam);
            rtt = (RelatedTaintedSymbol) Rrt.getListTaintedMembers().get(Rrt.getListTaintedMembers().size()-1);

            // Caso o parent nao pertenca 'a lista do symbol tainted
            if (rtt.getTaintedMembers().containsKey(scp.getScopeName()) == false){
                VariableTaintedSymbol var = new VariableTaintedSymbol(scp.getScopeName(), scp.getScopeSymbol().getCodeLine(),
                                                scp.getScopeSymbol().getTainted(), scp.getScopeSymbol().getFileSymbol());
                rtt.define(var);
            }
            else{ // Caso o parent pertenca 'a lista do symbol tainted
                VariableTaintedSymbol var = (VariableTaintedSymbol) rtt.getTaintedMembers().get(scp.getScopeName());
                var.InsertLine(scp.getScopeSymbol().getCodeLine());
                var.InsertFile(scp.getScopeSymbol().getFileSymbol());
            }
            return true;
        }

        // Caso o symbol seja um alfanumeric e contenha uma var tainted da tabela das vars tainteds
        if (sym.getAlfanumeric() == true) {
            Boolean existe = false;
            Iterator <Symbol> it = mts.getTaintedMembers().values().iterator();
            for(;it.hasNext(); ){
                s = it.next().getName();

                if (nam.contains("$"+s) == true && mus.existSymbol(s) == false){
                    // colocar scope parent tainted
                    scp =sym.getScope();
                    scp.getScopeSymbol().setTainted(1);
                    
                    // Inserir o socpe parent como dependente do symbol tainted
                    Rrt = (RootTaintedSymbol) mts.getTaintedMembers().get(s);
                    rtt = (RelatedTaintedSymbol) Rrt.getListTaintedMembers().get(Rrt.getListTaintedMembers().size()-1);

                    // Caso o parent nao pertenca 'a lista do symbol tainted
                    if (rtt.getTaintedMembers().containsKey(scp.getScopeName()) == false){
                        VariableTaintedSymbol var = new VariableTaintedSymbol(scp.getScopeName(),
                                                        scp.getScopeSymbol().getCodeLine(), scp.getScopeSymbol().getTainted(),
                                                        scp.getScopeSymbol().getFileSymbol());
                        rtt.define(var);
                    }
                    else{ // Caso o parent pertenca 'a lista do symbol tainted
                        VariableTaintedSymbol var = (VariableTaintedSymbol) rtt.getTaintedMembers().get(scp.getScopeName());
                        var.InsertLine(scp.getScopeSymbol().getCodeLine());
                        var.InsertFile(scp.getScopeSymbol().getFileSymbol());
                    }

                    existe = true;
                }
            }
            
            if (sym.getTainted() == 1){
                scp =sym.getScope();
                scp.getScopeSymbol().setTainted(1);

                // No caso de nome da funcao ser tainted
                if (mts.getTaintedMembers().containsKey(nam) == true){
                    // Inserir o socpe parent como dependente da funcao tainted
                    Rrt = (RootTaintedSymbol) mts.getTaintedMembers().get(nam);
                    rtt = (RelatedTaintedSymbol) Rrt.getListTaintedMembers().get(Rrt.getListTaintedMembers().size()-1);

                    // Caso o parent nao pertenca 'a lista da funcao tainted
                    if (rtt.getTaintedMembers().containsKey(scp.getScopeName()) == false){
                        VariableTaintedSymbol var = new VariableTaintedSymbol(scp.getScopeName(),
                                                    scp.getScopeSymbol().getCodeLine(), scp.getScopeSymbol().getTainted(),
                                                    scp.getScopeSymbol().getFileSymbol());
                        rtt.define(var);
                    }
                    else{ // Caso o parent pertenca 'a lista da funcao tainted
                        VariableTaintedSymbol var = (VariableTaintedSymbol) rtt.getTaintedMembers().get(scp.getScopeName());
                        var.InsertLine(scp.getScopeSymbol().getCodeLine());
                        var.InsertFile(scp.getScopeSymbol().getFileSymbol());
                    }
                }
                existe = true;
            }           
            return existe;
        }

        return false; // nao e' tainted a var
    }


     public void resolveSymbolClass(TaintedTable mts, UntaintedTable mus, String filename){
         if (!this.getMembers().isEmpty()){
            Symbol sym1;
            for(Iterator <Symbol> it1 = this.getMembers().iterator(); it1.hasNext();){
                sym1 = it1.next();
                this.resolveSymbol(this, sym1, mts, mus, filename);
            }
         }
     }
       

    // Resolve the name of include/require files.
    // The resolution can be a normal path or a concatenation of parts of the path (inclusive vars)
    public String resolveVarInclude(Scope scp, SymbolTable st){
        Symbol sym;
	String ss, s, string_final = "";
	Scope scp_aux = scp;

        // verifica se o nome da var a resolver não se chama a si propria. $a = $var.$a
        // evita ciclo infinito, na resolucao.
        Boolean call_Itself = verifyCallItself(scp, scp.getScopeName());
        if (call_Itself == true)
            return string_final;
        
	for(Iterator <Symbol> it = scp_aux.getMembers().iterator();it.hasNext(); ){
            sym = it.next();          
            if (sym.getRootScope() != null && sym.getAlfanumeric() == false){
                scp_aux = (Scope)sym;
                try{
                    ss = scp_aux.resolveVarInclude(scp_aux, st);
                    string_final = string_final + ss;
                } catch (Exception e) {}              
            }
            else{               
                if (sym.getAlfanumeric() == true){
                    ss = sym.getName();
                    if (ss.startsWith("\"") || ss.startsWith("\'"))
                        ss = ss.substring(1,ss.length()-1);
                }

                Boolean found = false;
                ss = sym.getName();
                for(Iterator <Symbol> it1 = st.getMembers().iterator();it1.hasNext(); ){
                    sym = it1.next();
                    s = sym.getName();                        
                    if (s.equals(ss) == true){
                        int i = st.getMembers().indexOf(sym);
                        scp_aux = (Scope) st.getMembers().get(i);
                        try{
                        ss = scp_aux.resolveVarInclude(scp_aux, st);
                        } catch (Exception e){}
                        found = true;
                        break;
                    } 
                }
                string_final = string_final + ss;              
            }
	}

        try{
        // remover ' ou " do path do file
        String AA[];
        AA = string_final.split("\"");
        if (AA[0].equals(string_final))
            AA = string_final.split("\'");
        
        
        String sss="";
        for (int i=0; i< AA.length; i++){
            sss = sss + AA[i];
        }

        if (sss.isEmpty() == false)
            string_final = sss;
        // fim remover
        } catch (Exception e) {}
	return string_final;
    }


   private Boolean verifyCallItself(Scope scp, String scp_name_resolve){
        Symbol sym;
        int i;
        Boolean equalItself = false;
	for(Iterator <Symbol> it = scp.getMembers().iterator(); it.hasNext();){
            sym = it.next();           
            if (sym.getRootScope() != null){
                Scope scp_aux = (Scope) sym;
                equalItself = verifyCallItself(scp_aux, scp_name_resolve);
                if (equalItself == true)
                    return true;
            }
            else{
                if (sym.getName().equals(scp_name_resolve) == true)
                    return true;
            }
        }      
       
       return equalItself;
   } 
    
    
    // Verify if the number of items of list right member (on fedinition) is equal to left member  
    public Boolean verifyNumberVarList(int num_var){
        Iterator <Symbol> it1 = this.getMembers().iterator();
        Symbol sym1;
        int i;
        for(i = 1; i < num_var; i++){
            sym1 = it1.next();
            if(sym1.getIsVariableSymbol() == false)
                break;
        }
        
        if (i == num_var)
            return true;
        else
            return false;
    }
    
    public void populateList(Scope scp_main, Scope scp_right, int num_var, TaintedTable mts, UntaintedTable mus, String filename){
        Iterator <Symbol> it = this.getMembers().iterator();
        Iterator <Symbol> it1 = scp_right.getMembers().iterator();
        Symbol sym, sym1;
        for(int i = 1; i < num_var; i++){
            sym1 = it1.next();
            sym = it.next();
            CallSymbol ms_aux = new CallSymbol(sym.getName(), sym.getCodeLine(), scp_main, 0, sym.getFileSymbol());
            VariableSymbol vs = new VariableSymbol(sym1.getName(), sym1.getTainted(), sym1.getCodeLine(), sym1.getFileSymbol()) {};
            ms_aux.define(vs, null, true);
            ms_aux.resolveSymbol(ms_aux, (Symbol) vs, mts, mus, filename);
            scp_main.define(ms_aux, ms_aux, false);
        }    
    }
    
    

    // set the scope root symbol taint
    public void setTainted(Scope sc, int taint) {
        sc.getScopeSymbol().setTainted(taint);
    }
  
    
//########################    
    // set the scope root symbol taint
    public void printtt(String sp, Scope cp) {
        System.out.println(sp+"Scope: "+cp.getScopeName());
        
        Iterator <Symbol> it=cp.getMembers().iterator();
        Symbol sy;
        for(;it.hasNext();){
            sy = it.next();
            if (sy.getRootScope() == null){
                System.out.println(sp+"\tmember: "+sy.getName());
            }
            else{
                cp = (Scope) sy;
                sp = sp + "\t";
                cp.printtt(sp, cp);
            }
        }
        
    }
    

    // give the members map
    // is implemented in CallSymbol
    //public abstract Map<String, Symbol> getMembers();
    public abstract List<Symbol> getMembers();
    
   
    public String buildCorrectSQL(String connDB, String nameDB, int lineMysqliBindParam, List UserInput, TaintedTable mts_princ, SymbolTable st, Map MainLinesToCorrect) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Boolean buildCorrectCodeInj(String fileInc, List UserInput, TaintedTable mts_princ, SymbolTable st, Map MainLinesToCorrect){
            throw new UnsupportedOperationException("Not supported yet.");
    }
} public class MethodSymbolCall {
    String functionNameCall;
    int lineCall;
    String fileOfMethod;
    List<Symbol> symbols;
    InstanceTable objectsOfMethod; //objs criados na chamada de um metodo
    Map <String, Symbol> aliases;
    //SymbolTable tabsymb;
    
    /* CONSTRUCTOR */
    public MethodSymbolCall(String func, int line, Boolean meth, String file) {
        this.functionNameCall = func;
        this.lineCall = line;
        this.fileOfMethod = file;
        this.symbols = new ArrayList<Symbol>();
        if (meth == true)
            this.objectsOfMethod = new InstanceTable(func);
        this.aliases = new LinkedHashMap<String, Symbol>();
        //this.tabsymb = new SymbolTable(func); //entra o nome da funcao, em vez do nome do ficheiro
    }

    
    /* METHODS*/
    public String getFunctionNameCall(){
        return this.functionNameCall;
    }
    
    public int getLineNumberCall(){
        return this.lineCall;
    }
    
    public String getFileOfMethod(){
        return this.fileOfMethod;
    }    
    
    public List getCallFunctionSymbols(){
        //return this.tabsymb;
        return this.symbols;
    }

    public InstanceTable getObjectsOfMethod(){
        return this.objectsOfMethod;
    }

    public Map getAliases(){
        return this.aliases;
    }

    public String getInstanceNameFromAliases(String s, InstanceTable instTab){
        String instName = "";
        boolean found = false;
        while (found == false){
            if (instTab.containsInstance(s) == true){
                instName = s;
                found = true;
            }
            else{
                if (this.getAliases().containsKey(s)){
                    Symbol sym = (Symbol) this.getAliases().get(s);
                    s = sym.getName();
                }
            }
        }
        return instName;
    }
} public class MethodClass {
    MethodSymbol meth;
    ClassSymbol cl;

    // *** CONSTRUCTORS
    public MethodClass(MethodSymbol m, ClassSymbol c) {
        this.meth = m;
        this.cl = c;
    }

    // *** METHODS

    public MethodSymbol getMeth() {
        return this.meth;
    }

     public ClassSymbol getClassMeth() {
        return this.cl;
    }
} public class InstanceTable implements Scope {
    String name;
    List <Instance> instances;
    

    // *** CONSTRUCTORS
    public InstanceTable(String name) {
        this.name = name;
        instances = new ArrayList <Instance>();
    }


    // *** METHODS

    // Satisfy Scope interface
    public String getScopeName() {
        return name;
    }

    // am I nested in another?
    public Scope getEnclosingScope() {
    	return null;
    }

    /*
     * Give the List that contain the methods (functions defined by user) of the file
     */
    public List getMembers() {       
        return instances;
    }
    
    public List getMembersList() {
        return null;
    }

    /*
     * Give the root Symbol of the scope. In another words, give the symbol
     * that create a new scope.
     * Here, in main table of symbols, don't exist root symbol.
     */
    public Symbol getScopeSymbol() {
    	return null;
    }

 /*
     * Return a specific Instance
     */
    public Instance getInstanceOfListInstances(String instName){
        Instance inst_final = null;
        Iterator <Instance> it = this.getMembers().iterator();
        Instance ins;
        for (;it.hasNext();){
                ins = it.next();
                if (ins.getInstanceName().equals(instName) == true){
                    inst_final = ins;
                    break;
                }
        }
        return inst_final;
    }

    /*
     * Tells if the Instance list contains a gived Instance
     */

    public Boolean containsInstance(String instName){
        Iterator <Instance> it = this.getMembers().iterator();
        Instance ins;
        Boolean haveInst = false;
        for (;it.hasNext();){
                ins = it.next();
                if (ins.getInstanceName().equals(instName) == true){
                    haveInst = true;
                    break;
                }
        }
        return haveInst;
    }



    /*
     * Insert a root symbol (new scope) in main Map.
     */
    public void define(Instance obj) {
    	//symbols.put(sym.getName(), sym);
        instances.add(obj);
    }
    
    /*
     * Not relevant here!
     */
    //public Boolean resolve(String name, TaintedTable mts, UntaintedTable mus) {
    public void resolveSymbol(Scope scp, Symbol sy, TaintedTable mts, UntaintedTable mus, String file){
    	//return symbols.get(name);
    //    return true;
    }


    public Boolean resolve(Symbol symb, TaintedTable mts, UntaintedTable mus) {
    	//return symbols.get(name);
        return true;
    }



    @Override
    public String toString() {
    	return getScopeName()+":"+instances;
    }


    public void resolveSymbolIncludeSQLI(Scope scp, TaintedTable mts, UntaintedTable mus, Map mift, String filename, Map mft, Map mst, Map varsDB, Map mftt, Map MainLinesToCorrect) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public String resolveVarInclude(Scope scp, SymbolTable st) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void define(Symbol sym, Scope scp, Boolean IsVariableSymbol) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void resolveSymbolFunctionSQLI(MethodSymbol mt, Scope rootScope, TaintedTable mts, UntaintedTable mus, Map mift, String filename, Map mft, Map mst, Map varsDB, Map mftt, Map MainLinesToCorrect) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Boolean verifyNumberVarList(int num_var){
        throw new UnsupportedOperationException("Not supported yet.");    
    }
    
    public void populateList(Scope scp_left, Scope scp_right, int num_var, TaintedTable mts, UntaintedTable mus, String filename){
        throw new UnsupportedOperationException("Not supported yet.");    
    }    
    
    public String buildCorrectSQL(String connDB, String nameDB, int lineMysqliBindParam, List UserInput, TaintedTable mts_princ, SymbolTable st, Map MainLinesToCorrect) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Boolean buildCorrectCodeInj(String fileInc, List UserInput, TaintedTable mts_princ, SymbolTable st, Map MainLinesToCorrect){
            throw new UnsupportedOperationException("Not supported yet.");
    }

    public void print(Scope scp) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void resolveSymbolClass(TaintedTable mts, UntaintedTable mus, String filename) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

        public void printtt(String string, Scope cp){
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void resolveSymbolParam(TaintedTable mts, UntaintedTable mus, String filename) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    public void resolveParam(Symbol symb, TaintedTable mts, UntaintedTable mus) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    public void copyScope(Scope src, Scope dest) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

} public class Symbol implements Cloneable{
    private String name;                // All symbols at least have a name
    private int tainted = 0;                // All symbols are untainted (0), when are initialized
    private int line;                   // Code Line of the symbol
    private Scope scope;                // Symbol have a scope
    private Scope rootScope;            // Symbol can be a new scope
    private Boolean alfanumeric = false; // parameters, arguments or values are alfanumerics
    private String fileSymbol; // Symbol pertence a file - string is the completed path of the file
    private Boolean isVariableSymbol=false;   // if the symbol is a object of VariableSymbol class
    private Boolean isSecureFunction = false; // if the symbol represents a mysql secure function
    private Boolean isFunction = false;  // if the symbol is call function
    private Boolean isUserFunction = false;  // if the symbol is call user function
    private Boolean isParameterUserFunction = false;  // if the symbol is a parameter of a user funcrion or a method class
    private Boolean isTaintedFunction = false; // if the symbol represents a tainted function (ex. mysql sqli)
    private Boolean isVulDetected = false; // if the symbol is a tainted function and it was detected as vulnerable (ex. mysql sqli)
    private Boolean isInstance = false;  // if the symbol is a new instance of a class
    private Boolean isClone = false;  // if the symbol is a clone of a instance class
    private Boolean isStaticMember = false;  // if the symbol is a call the one method in static way
    private Boolean isClassInstruction = false;  // if the symbol represents a class instruction
    private Boolean isClassMethod = false;  // if the symbol is call method of the class
    // public Type type;   // Symbols have types

    // *** CONSTRUCTORS
    public Symbol(String name, int line, String file) {
	this.name = name;
        this.line = line;
        this.fileSymbol = file;
    }
    public Symbol(String name, int tainted, int line, String file) {
	this.name = name;
	this.tainted = tainted;
        this.line = line;
        this.fileSymbol = file;
    }
    public Symbol(String name, int line, Boolean alfanumeric, String file) {
	this.name = name;
        this.line = line;
        this.alfanumeric = alfanumeric;
        this.fileSymbol = file;
    }

    public Symbol(String name, int tainted, int line, Boolean alfanumeric, String file) {
	this.name = name;
	this.tainted = tainted;
        this.line = line;
        this.alfanumeric = alfanumeric;
        this.fileSymbol = file;
    }


    // *** METHODS

    // Get the name of the symbol
    public String getName() {
	return name;
    }

    // Get the tainted value of the symbol
    public int getTainted() {
	return tainted;
    }

    // Get the number code line of the symbol
    public int getCodeLine() {
	return line;
    }

    // Get the alfanumeric value of the symbol
    public Boolean getAlfanumeric() {
	return alfanumeric;
    }

    // Get the Scope of the Symbol
    public Scope getScope() {
	return scope;
    }

    // Get rootScope of Symbol
    public Scope getRootScope() {
	return rootScope;
    }

    // Get Symbol
    public Symbol getSymbol() {
	return this;
    }

    // give the file that the symbol pertence
    public String getFileSymbol() {
        return fileSymbol;
    }

    // Tell if the symcol is a vaiable or not (callSymbol ou other)
    public Boolean getIsVariableSymbol() {
        return isVariableSymbol;
    }
    
    // Tell if the symbol is represents a mysql secure function
    public Boolean getIsSecureFunction() {
        return isSecureFunction;
    }
    
    // Tell if the symbol is a call function
    public Boolean getIsFunction() {
        return isFunction;
    }

    // Tell if the symbol is a User function
    public Boolean getIsUserFunction() {
        return isUserFunction;
    }
    
    // Tell if the symbol is a parameter of a User function or method class
    public Boolean getIsParamUserFunction() {
        return isParameterUserFunction;
    }
    
    // Tell if the symbol represents a mysql sqli function
    public Boolean getIsTaintedFunction() {
        return isTaintedFunction;
    }

    // Tell if the symbol is detected as vulnerable
    public Boolean getIsVulDetected() {
        return isVulDetected;
    }    
    
    // Tell if the symbol represents a instance of a class
    public Boolean getIsInstance() {
        return isInstance;
    }   

    // Tell if the symbol is a clone of a instance class
    public Boolean getIsClone() {
        return isClone;
    }

    // Tell if the symbol is a call of method class in static way
    public Boolean getIsStaticMember() {
        return isStaticMember;
    }

    // Tell if the symbol represents a class instruction
    public Boolean getIsClassInstruction() {
        return isClassInstruction;
    }

    // Tell if the symbol is a call class method
    public Boolean getIsClassMethod() {
        return isClassMethod;
    }

    // Set the tainted or untainted value
    public void setTainted(int t) {
	tainted = t;
    }

    // Set the name of the symbol
    public void setName(String nome) {
	name = nome;
    }

    // Set the code line of the symbol
    public void setCodeLine(int l) {
	line = l;
    }

    // Set the scope of the symbol
    public void setScope(Scope scp) {
	scope = scp;
    }

    // Set the rootScope of the symbol
    public void setRootScope(Scope scp) {
	rootScope = scp;
    }

    // set the file of the symbol pertence
    public void setFileSymbol(String file) {
        this.fileSymbol = file;
    }

    // set true if the symbol is a variableSymbol
    public void setIsVariableSymbol(Boolean a) {
        isVariableSymbol = a;
    }

    // set true if the symbol is a alfanumeric
    public void setAlfanumeric(Boolean a) {
        alfanumeric = a;
        this.setNameMultiline();
    }
    
    // set true if the symbol represents a mysql secure function
    public void setIsSecureFunction(Boolean a) {
        isSecureFunction = a;
    }

    // set true if the symbol is a call function
    public void setIsFunction(Boolean a) {
        isFunction = a;
    }
 
    // set true if the symbol is a user function
    public void setIsUserFunction(Boolean a) {
        isUserFunction = a;
    }

    // set true if the symbol is a parameter of a User function or method class
    public void setIsParamUserFunction(Boolean a) {
        isParameterUserFunction = a;
    }
    
    // set true if the symbol represents a mysql sqli function
    public void setIsTaintedFunction(Boolean a) {
        isTaintedFunction = a;
    }

    // set true when a vul is detected. Just sqli functions have this attribute true
    public void setIsVulDetected(Boolean a) {
        isVulDetected = a;
    }    
    
    // set true if the symbol represents a instance class
    public void setIsInstance(Boolean a) {
        isInstance = a;
    }

    // set true if the symbol is a clone of a instance class
    public void setIsClone(Boolean a) {
        isClone = a;
    }

    // set true if the symbol is a call of method class in static way
    public void setIsStaticMember(Boolean a) {
        isStaticMember = a;
    }

    // set true if the symbol represents a class instruction
    public void setIsClassInstruction(Boolean a) {
        isClassInstruction = a;
    }

    // set true if the symbol is a call class method
    public void setIsClassMethod(Boolean a) {
        isClassMethod = a;
    }

    // set Symbol name if it is composed by n lines
    public void setNameMultiline() {
        if (this.name.contains("\n")){
            String s[] = this.name.split("\n");
            String ss = s[0].trim();
            
            for (int i = 1; i < s.length; i++) {
                ss += " " + s[i].trim();
            }
            this.setName(ss);
        }
    }    
    

    // Print the name and tainted of the symbol
    @Override
    public String toString() {
	return '<'+ line + ":" + getName()+":" +tainted+'>' ;
    }

     @Override
     public Object clone() throws CloneNotSupportedException {
    	return super.clone();
    }
} public class MethodSymbol extends ScopedSymbol implements Cloneable{
    Boolean haveSubFunctions;
    String Progenitorfunction = "";
    Map <String, ArgFunctionSymbol> argsFunction;
    Map<String, Symbol> globalVars;
    List<Symbol> symbols;
    
    
    // ****** CONSTRUCTORS ***********
     public MethodSymbol(String function_name, int line, int tainted, Scope parent, String filename) {
        //this.functionName = fname;
        super (function_name, line, tainted, parent, filename);
	haveSubFunctions = false;
        argsFunction = new HashMap <String, ArgFunctionSymbol>();
        globalVars = new HashMap<String, Symbol>();
        //staticVars = new HashMap<String, Object>();
        symbols = new ArrayList<Symbol>(); //instructions of the function, except global instruction
    }
    
    
    // *** METHODS ********
    public String getFunctionName() {
        return this.getName();
    }

    public Boolean getHaveSubFunctions() {
        return haveSubFunctions;
    }
    
    public String getProgenitorFunction() {
        return this.Progenitorfunction;
    }
    
    public Map getArgsFunction() {
        return argsFunction;
    }
    
   
    public Map getGlobalVarsOfFunction() {
        return globalVars;
    }
    
    
    public void setFunctionName(String name) {
        this.setName(name);
    }    
    
    public void setHaveSubFunctions() {
        this.haveSubFunctions = true;
    }
    
    public void setProgenitorFunction(String p) {
        this.Progenitorfunction = p;
    }
    
    public void setArgFunction(String argName, ArgFunctionSymbol arg) {
        argsFunction.put(argName, arg);
    }
    
    public void setGlobalVarFunction(String varName, Symbol gvar) {
        globalVars.put(varName, gvar);

    }

    public MethodSymbol copyMethodSymbol(MethodSymbol meth_sym, String function_name, int line, Scope parent, String filename) {
        MethodSymbol mt = new MethodSymbol(function_name, line, 0, parent, filename);
        Symbol sym;

        //copia o map de argumentos da funcao
        ArgFunctionSymbol arg;
        for(Iterator <ArgFunctionSymbol> it = meth_sym.getArgsFunction().values().iterator(); it.hasNext();){
            arg = it.next();
            try {
                mt.argsFunction.put(arg.getParamName(), (ArgFunctionSymbol) arg.clone());
            } catch (CloneNotSupportedException ex) {
                Logger.getLogger(MethodSymbol.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
          
        //copia o map das vars globais da funcao
        for(Iterator <Symbol> it = meth_sym.getGlobalVarsOfFunction().values().iterator(); it.hasNext();){
            sym = it.next();
                try {
                    mt.getGlobalVarsOfFunction().put(sym.getName(), (Symbol) sym.clone());
                } catch (CloneNotSupportedException ex) {
                    Logger.getLogger(MethodSymbol.class.getName()).log(Level.SEVERE, null, ex);
                }
	 }
 
                
        //copia a lista de instrucoes da funcao
        Scope scp, scpRoot=null;
        CallSymbol curScope;
        Symbol sy;
        for(Iterator <Symbol> it = meth_sym.getMembers().iterator(); it.hasNext();){
            sy = it.next();
            if (sy.getIsVariableSymbol() == false){
                scp = (Scope) sy; 
                sym = scp.getScopeSymbol();
                curScope = new CallSymbol (sym.getName(), sym.getCodeLine(), null, sym.getTainted(), sym.getFileSymbol());
                curScope.setRootScope(curScope);
                curScope.setScope(curScope);
                curScope.setIsVariableSymbol(false);
                curScope.getScopeSymbol().setIsInstance(sym.getIsInstance());
                curScope.getScopeSymbol().setIsClone(sym.getIsClone());
                curScope.getScopeSymbol().setIsStaticMember(sym.getIsStaticMember());
                curScope.getScopeSymbol().setIsClassInstruction(sym.getIsClassInstruction());
                
                curScope.getScopeSymbol().setIsFunction(sym.getIsFunction());
                curScope.getScopeSymbol().setIsSecureFunction(sym.getIsSecureFunction());
                curScope.getScopeSymbol().setIsTaintedFunction(sym.getIsTaintedFunction());
                curScope.getScopeSymbol().setAlfanumeric(sym.getAlfanumeric());
                curScope.getScopeSymbol().setIsUserFunction(sym.getIsUserFunction());
                curScope.getScopeSymbol().setIsClassMethod(sym.getIsClassMethod());                
                
                copyScope(scp, curScope);
                mt.getMembers().add(curScope);
            }
         }
        
        return mt;
    }

    public void copyScope(Scope cs, Scope csClone){
        Symbol aux1, aux2;
        Scope s, s1 = null;
        CallSymbol curScope1;
        if (!cs.getMembers().isEmpty()){
            for(Iterator <Symbol> it = cs.getMembers().iterator(); it.hasNext();){
                aux1 = it.next();
                if ( aux1.getRootScope() != null ) { // is a root of a new scope?
                        s = aux1.getRootScope();
                        //aux2 = s.getScopeSymbol();
                        try {
                            s1 = (Scope) cs.getScopeSymbol().clone();
                        } catch (CloneNotSupportedException ex) {
                            Logger.getLogger(MethodSymbol.class.getName()).log(Level.SEVERE, null, ex);
                        }                        
                        curScope1 = new CallSymbol (aux1.getName(), aux1.getCodeLine(), s1, aux1.getTainted(), aux1.getFileSymbol());
                        curScope1.getScopeSymbol().setIsFunction(aux1.getIsFunction());
                        curScope1.getScopeSymbol().setIsSecureFunction(aux1.getIsSecureFunction());
                        curScope1.getScopeSymbol().setIsTaintedFunction(aux1.getIsTaintedFunction());
                        curScope1.getScopeSymbol().setAlfanumeric(aux1.getAlfanumeric());
                        curScope1.getScopeSymbol().setIsUserFunction(aux1.getIsUserFunction());
                        curScope1.getScopeSymbol().setIsInstance(aux1.getIsInstance());
                        curScope1.getScopeSymbol().setIsClone(aux1.getIsClone());
                        curScope1.getScopeSymbol().setIsStaticMember(aux1.getIsStaticMember());
                        curScope1.getScopeSymbol().setIsClassInstruction(aux1.getIsClassInstruction());
                        curScope1.getScopeSymbol().setIsClassMethod(aux1.getIsClassMethod());

                        csClone.define(curScope1, curScope1, false);
                        copyScope(s, curScope1);
                }
                else{
                    VariableSymbol vs = new VariableSymbol(aux1.getName(), aux1.getTainted(), aux1.getCodeLine(), aux1.getAlfanumeric(), aux1.getFileSymbol());
                    csClone.define(vs, null, true);

                }
                    
            }
        }       
    }


    public void cleanAll(){
            haveSubFunctions = false;
            Progenitorfunction = "";

            Collection <ArgFunctionSymbol> c = argsFunction.values();
            c.removeAll(c);
            argsFunction.clear();

            Collection <Symbol> c1 = globalVars.values();
            c1.removeAll(c1);
            globalVars.clear();

            Collection <Symbol> c2 = symbols;
            c2.removeAll(c2);
            symbols.clear();
    }
    
    // give the members (instructions) of the function
    public List<Symbol> getMembers() {
        return symbols;
    }

    public void printMethodSymbol() {
        System.out.println("FUNCTION: "+this.getFunctionName()+"\tTAINTED: "+this.getTainted());
        System.out.println("\tHave SubFunctions: "+ this.getHaveSubFunctions());
        System.out.println("\tFunction Progenitor: "+ this.getProgenitorFunction());
        
        System.out.println("\tPARAMETERS");
        Iterator <ArgFunctionSymbol> it;
        ArgFunctionSymbol afs;
        for(it = this.getArgsFunction().values().iterator(); it.hasNext();){
            afs = it.next();
            System.out.println("\t\tName: "+afs.getParamName()+"\tType: "+afs.getType()+"\tPosition: "+afs.getPositionParam()+
                                "\tTainted: "+afs.getTaintedValueCallFunctionArg()+"\tArgCallFunction: "+afs.getCallFunctionArg());
        }
        
        System.out.println("\tGLOBALS");
        Iterator <Symbol> it1;
        Symbol sym;
        for(it1 = this.getGlobalVarsOfFunction().values().iterator(); it1.hasNext();){
            sym = it1.next();
            System.out.println("\t\tName: "+sym.getName()+"\tTainted: "+sym.getTainted());
        }
        
        System.out.println("\tINSTRUCTIONS");
        Scope sc;
        for(it1 = this.getMembers().iterator(); it1.hasNext();){
            sc = (Scope) it1.next();
            System.out.println("ScopeName: "+sc.getScopeName()+"\tTainted: "+sc.getScopeSymbol().getTainted()
                                +"\tRootScope: "+sc.getScopeSymbol().getRootScope().getScopeName()
                                +"\tTaintedRootScope: "+sc.getScopeSymbol().getRootScope().getScopeSymbol().getTainted());
            sc.print(sc);
        }        
    }    
    
    public void print(Scope scp) {

    }

} public class MethodTable implements Scope{
    String name;
    List<MethodSymbol> methods;
    

    // *** CONSTRUCTORS
    public MethodTable(String name) {
        this.name = name;
        //symbols = new LinkedHashMap<String, Symbol>();
        methods = new ArrayList<MethodSymbol>();
    }


    // *** METHODS

    // Satisfy Scope interface
    public String getScopeName() {
        return name;
    }

    // am I nested in another?
    public Scope getEnclosingScope() {
    	return null;
    }

    /*
     * Give the List that contain the methods (functions defined by user) of the file
     */
    public List getMembers() {       
        return methods;
    }
    
    public List getMembersList() {
        return null;
    }

    /*
     * Give the root Symbol of the scope. In another words, give the symbol
     * that create a new scope.
     * Here, in main table of symbols, don't exist root symbol.
     */
    public Symbol getScopeSymbol() {
    	return null;
    }

    /*
     * Insert a root symbol (new scope) in main Map.
     */
    public void define(MethodSymbol meth) {
        methods.add(meth);
    }
    
        /*
     * Insert a root symbol (new scope) in main Map.
     */
    //public void define(Symbol sym, Scope scp, Boolean IsVariableSymbol) {
    public void define(MethodSymbol meth, Scope scp, Boolean IsVariableSymbol) {        
        methods.add(meth);
        meth.setRootScope(scp);
        meth.setScope(this);
        meth.setIsVariableSymbol(IsVariableSymbol);
    }


    /*
     * Not relevant here!
     */
    //public Boolean resolve(String name, TaintedTable mts, UntaintedTable mus) {
    public void resolveSymbol(Scope scp, Symbol sy, TaintedTable mts, UntaintedTable mus, String file){
    	//return symbols.get(name);
    //    return true;
    }


    public Boolean resolve(Symbol symb, TaintedTable mts, UntaintedTable mus) {
    	//return symbols.get(name);
        return true;
    }



    /*
     * Print the elements of the main Map scope.
     */
    public void print(Scope scp){
        Symbol aux1 = null;
        Scope s;
        if (!scp.getMembers().isEmpty()){
            System.out.println("\nScope: "+scp.getScopeName()+"\tsize="+scp.getMembers().size());
            Iterator <Symbol> it = scp.getMembers().iterator();
            for(; it.hasNext();){
                aux1 = it.next();
                //System.out.println("Name: "+aux1.getName()+"\t\tline: "+aux1.getCodeLine()+"\t\ttainted: "
                //                +aux1.getTainted()+"\t\tScope: "+aux1.getScope().getScopeName()+"\n");
                if ( aux1.getRootScope() != null ) { // is a root of a new scope?
                        s = aux1.getRootScope();
                        s.print(s);
                }
            }
        }
         else{
            aux1 = scp.getScopeSymbol();
             System.out.println("Name: "+aux1.getName()+"\t\tline: "+aux1.getCodeLine()+"\t\ttainted: "
                                +aux1.getTainted()+"\t\tScope: "+aux1.getScope().getScopeName()+"\n");
         }
    }

    @Override
    public String toString() {
    	return getScopeName()+":"+methods;
    }

    public void resolveSymbolIncludeSQLI(Scope scp, TaintedTable mts, UntaintedTable mus, Map mift, String filename, Map mft, Map mst, Map varsDB, Map mftt, Map MainLinesToCorrect) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public String resolveVarInclude(Scope scp, SymbolTable st) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void define(Symbol sym, Scope scp, Boolean IsVariableSymbol) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void resolveSymbolFunctionSQLI(MethodSymbol mt, Scope rootScope, TaintedTable mts, UntaintedTable mus, Map mift, String filename, Map mft, Map mst, Map varsDB, Map mftt, Map MainLinesToCorrect) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Boolean verifyNumberVarList(int num_var){
        throw new UnsupportedOperationException("Not supported yet.");    
    }
    
    public void populateList(Scope scp_left, Scope scp_right, int num_var, TaintedTable mts, UntaintedTable mus, String filename){
        throw new UnsupportedOperationException("Not supported yet.");    
    }    
    
    public String buildCorrectSQL(String connDB, String nameDB, int lineMysqliBindParam, List UserInput, TaintedTable mts_princ, SymbolTable st, Map MainLinesToCorrect) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Boolean buildCorrectCodeInj(String fileInc, List UserInput, TaintedTable mts_princ, SymbolTable st, Map MainLinesToCorrect){
            throw new UnsupportedOperationException("Not supported yet.");
    }

    public void resolveSymbolClass(TaintedTable mts, UntaintedTable mus, String filename) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void printtt(String string, Scope cp){
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void resolveSymbolParam(TaintedTable mts, UntaintedTable mus, String filename) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    public void resolveParam(Symbol symb, TaintedTable mts, UntaintedTable mus) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

}
import java.io.IOException;
import org.homeunix.wap.table.tainted.RootTaintedSymbol;
import org.homeunix.wap.table.tainted.UntaintedTable;
import org.homeunix.wap.table.tainted.TaintedTable;
import org.homeunix.wap.table.tainted.VariableTaintedSymbol;
import org.homeunix.wap.table.tainted.RelatedTaintedSymbol;
import org.homeunix.wap.table.symbol.ArgFunctionSymbol;
import org.homeunix.wap.table.symbol.SymbolTable;
import org.homeunix.wap.table.symbol.Scope;
import org.homeunix.wap.table.symbol.ClassSymbol;
import org.homeunix.wap.table.symbol.ClassTable;
import org.homeunix.wap.table.symbol.Instance;
import org.homeunix.wap.table.symbol.ScopedSymbol;
import org.homeunix.wap.table.symbol.MethodSymbolCall;
import org.homeunix.wap.table.symbol.MethodClass;
import org.homeunix.wap.table.symbol.InstanceTable;
import org.homeunix.wap.table.symbol.Symbol;
import org.homeunix.wap.table.symbol.MethodSymbol;
import org.homeunix.wap.table.symbol.MethodTable;
import java.util.*;
/*
 * Represent a symbol in scope
 */

package org.homeunix.wap.XSS;



/**
 *
 * @author Iberia Medeiros
 */
//public class FuncAndIncCodeInj extends CallSymbol{
public class FuncAndIncXSS extends ScopedSymbol{    

    // *** CONSTRUCTORS
    public FuncAndIncXSS(Scope scp) {
        super(scp.getScopeSymbol().getName(), scp.getScopeSymbol().getCodeLine(), scp.getScopeSymbol().getTainted(), scp.getEnclosingScope(), scp.getScopeSymbol().getFileSymbol());   
    }
   

    // *** METHODS
    public void resolveSymbolClassXSS(MethodSymbol ms, Scope scp, TaintedTable mts, UntaintedTable mus, String filename, MethodSymbolCall mtsc, Instance inst, Map mct, Boolean ftime, Scope cs_att, Scope cs_acc, String typeMeth, Boolean isClassInstruction) throws IOException{
    if (scp.getScopeSymbol().getIsSecureFunction() == false){ 
    Scope csAtt_acc = cs_att;
    Scope csAtt_att = cs_acc;
    String s = scp.getScopeName();
    Instance ret = null;
    Boolean exit_for = false;
    
    if (inst != null){   
    SymbolTable t = inst.getInstanceAttributes();
  
    //pegar no atributo do objecto numa atribuicao ou acesso
    if (t.containsSymbol(s) || (scp.getEnclosingScope() != null && scp.getEnclosingScope().getScopeName().equals("this") && t.containsSymbol(s))){
       //pegar no atributo do objecto numa atribuicao ou acesso
       if (ftime == true){
           csAtt_att = (Scope) t.getSymbolOfListSymbols(s);
           try{
               csAtt_att.getMembers().clear();
               for(int i=0; i< scp.getMembers().size(); i++)
                    csAtt_att.getMembers().add(scp.getMembers().get(i));
           } catch (Exception e) {}
           ftime = false;

           if (scp.getEnclosingScope() != null && scp.getEnclosingScope().getScopeName().equals("this")){
                Symbol sym_this = scp.getEnclosingScope().getScopeSymbol();
                scp.getScopeSymbol().setIsInstance(sym_this.getIsInstance());
                scp.getScopeSymbol().setIsClone(sym_this.getIsClone());
           }
       }
       else{
           //csAtt_acc = (Scope) t.getMembers().get(i);
           csAtt_acc = (Scope) t.getSymbolOfListSymbols(s);
       }
        }

    }

    Iterator <Symbol> it;
    Symbol sym;
    for (it = scp.getMembers().iterator(); it.hasNext();){
        sym = it.next();
        if (isClassInstruction == true){
        int op = 0;

        // criacao de um objecto
        // do tipo $a = new A_class()
        if (scp.getScopeSymbol().getIsInstance() == true)
            op = 2;

        // atribuicao e' um clone
        // do tipo $a = clone $obj
        if (scp.getScopeSymbol().getIsClone() == true)
            op = 3;

        // staticMember
        // A::meth()
        if (scp.getScopeSymbol().getIsStaticMember() == true)
            op = 4;

        // chamada de um metodo
        if(scp.getScopeSymbol().getIsFunction() == true && scp.getScopeSymbol().getIsClassMethod() == true &&
           scp.getScopeSymbol().getIsSecureFunction()==false && scp.getScopeSymbol().getIsTaintedFunction()==false){
            if (ms != null)
                op = 5; // metodo dentro de um metodo
            else
                op = 1; //metodo normal
        }

        switch (op){
            case 1:{ // chamada de um metodo normal
                ftime = false;
                
                // 1. obter instancia
                String instName = scp.getEnclosingScope().getScopeName();
                String fileInst = scp.getEnclosingScope().getScopeSymbol().getFileSymbol();
                InstanceTable instTable = GlobalDataXSS.MainInstancesTable.get(fileInst);
                SymbolTable st = GlobalDataXSS.MainSymbolTable.get(fileInst);
                String instName_aux = instName;
                Instance inst1 = null;
                if (st.getAliases().containsKey(instName_aux) == true)
                        instName_aux = st.getInstanceNameFromAliases(instName_aux, instTable);                
                
                if (instTable != null && instTable.containsInstance(instName_aux) == true)
                    inst1 = (Instance) instTable.getInstanceOfListInstances(instName_aux);

                // 2. obter classe
                String c_name = inst1.getInstanceClass();
                String cf_name = inst1.getFileOfClass();
                ClassTable ct = GlobalDataXSS.MainClassesTable.get(cf_name);
                ClassSymbol currentClass = ct.getClassOfListClasses(c_name);

                // * 3. procurar metodo
                MethodClass mc = currentClass.getMethodClass(scp.getScopeName(), "", mct);
                MethodSymbol mss_final = mc.getMeth();
                String mss_final_file = mc.getClassMeth().getFileClass();

                ret = null;
                ret = instanceMethod(mss_final, scp, filename, mss_final_file, mts, mus, inst1, null, mct, "", ret, instTable, st);                

                if (ret != null && instTable.containsInstance(ret.getInstanceName()) == true){
                        Boolean a = true;
                        Scope enc_f = scp;
                        Scope enc_b;
                        while (a == true){
                                enc_b = enc_f.getEnclosingScope();
                                if (enc_b.getScopeName().equals(st.getScopeName()) == false)
                                        enc_f = enc_b;
                                else
                                        a = false;
                        }

                        Symbol sy = new Symbol(ret.getInstanceName(), ret.getTainted(), ret.getCreateLineInstance(), ret.getFileInstance());
                        sy.setIsClassInstruction(true);
                        st.getAliases().put(enc_f.getScopeName(), sy);
                        scp.resolveSymbol(scp, sym, mts, mus, sym.getFileSymbol());
                        mts.removeDuplicates(sym);

                        if (cs_att != null){
                                cs_att.getScopeSymbol().setTainted(ret.getTainted());
                                inst1.updateTainted(cs_att, sym);
                        }
                }
                exit_for = true;
                //break;
                return;
            }
            case 2:{
                ftime = false;
                // criacao de um objecto

                Instance inst1 = null;
                InstanceTable instances_table = null;
                if (ms == null){
                    String file_inst = sym.getFileSymbol();
                    instances_table = GlobalDataXSS.MainInstancesTable.get(file_inst);
                    Iterator <Instance> it1 = instances_table.getMembers().iterator();
                    for (; it1.hasNext();){
                        inst1 = it1.next();
                        if (inst1.getInstanceName().equals(s) && inst1.getCreateLineInstance() == sym.getCodeLine()){
                            break;
                        }
                    }
                }

                /* 1. Procurar classe */
                ClassTable class_table = null;
                ClassSymbol currentClass = null;

                for (Iterator <ClassTable> it3 = GlobalDataXSS.MainClassesTable.values().iterator(); it3.hasNext();){
                    class_table = it3.next();

                    if (class_table.containsClass(sym.getName()) == true){
                        currentClass = (ClassSymbol) class_table.getClassOfListClasses(sym.getName());
                        break;
                    }
                }
                
                    if (ms != null){
                        if (typeMeth.equals("constructor") == true)
                            instances_table = inst.getObjectsOfInstance();
                        else
                            instances_table = mtsc.getObjectsOfMethod();
                    }

                    if (currentClass.getExtendsClassName() != null){
                        inst1 = new Instance(scp.getScopeName(), scp.getScopeSymbol().getCodeLine(), inst.getFileInstance(), sym.getName(), class_table.getScopeName(), currentClass, true);
                        instances_table.define(inst1);
                        return;
                    }
                    if (ms != null){
                        inst1 = new Instance(scp.getScopeName(), scp.getScopeSymbol().getCodeLine(), inst.getFileInstance(), sym.getName(), class_table.getScopeName(), currentClass, false);
                        instances_table.define(inst1);
                    }

                /* 2. procurar metodo construtor*/
                MethodClass mc = currentClass.getMethodClass(sym.getName(), "construct", mct);
                MethodSymbol mss_final = mc.getMeth();
                String mss_final_file = mc.getClassMeth().getFileClass();

                /* Fazer a analise do construtor */
                if (mss_final == null){ // a classe nao tem metodo construtor. logo fazer taint analise aos atributos
                    SymbolTable t1 = inst1.getInstanceAttributes();
                    TaintedTable tt1 = inst1.getMtsInstanceAttributes();
                    UntaintedTable ut1 = inst1.getMusInstanceAttributes();
                    Scope scp1;
                    for(Iterator <Symbol> it4 = t1.getMembers().iterator(); it4.hasNext();){
                         scp1 = (Scope) it4.next();
                         scp1.resolveSymbolClass(tt1, ut1, inst1.getFileOfClass());
                    }
                }
                else{
                    typeMeth = "constructor";
                    MethodSymbolXSS meth_sym = new MethodSymbolXSS(mss_final);
                    int valueFinal = meth_sym.analyseMethodXSS(mss_final,scp.getScopeSymbol().getCodeLine(), (Scope)sym, mts, mus, filename, mss_final_file, inst1, mct, typeMeth);
                    scp.getScopeSymbol().setTainted(valueFinal);
                    scp.resolveSymbol(scp, sym, mts, mus, scp.getScopeSymbol().getFileSymbol());

                    if (cs_att != null){
                        cs_att.getScopeSymbol().setTainted(valueFinal);
                        inst.updateTainted(cs_att, sym);
                    }
                }
                return;
            }

            case 3:{
                ftime = false;

                // atribuicao e' um clone
                if (ms != null)
                    mtsc.getAliases().put(s, sym);
                
                scp.resolveSymbol(scp, sym, mts, mus, sym.getFileSymbol());
                if (cs_att != null){
                    cs_att.getScopeSymbol().setTainted(scp.getScopeSymbol().getTainted());
                    inst.updateTainted(cs_att, sym);
                }
                return;
            }

            case 4:{
                ftime = false;

                // staticMember
                // obter classe
                String clas = "";
                String clas_file = "";
                if (s.equals("self") == true){
                    clas = inst.getInstanceClass();
                    clas_file = inst.getFileOfClass();
                }
                else{
                    if (s.equals("parent") == true){
                        clas = inst.getInstanceClass();
                        clas_file = inst.getFileOfClass();
                        ClassTable ct = GlobalDataXSS.MainClassesTable.get(clas_file);
                        ClassSymbol cls = (ClassSymbol) ct.getClassOfListClasses(clas);
                        clas = cls.getExtendsClassName();
                        clas_file = cls.getFileExtendsClass();

                    }
                    else{
                        // obter nome e file da class
                        for (Iterator <ClassTable> it1 = mct.values().iterator(); it1.hasNext();){
                            ClassTable class_table = it1.next();
                            if (class_table.containsClass(s) == true){
                                clas = s;
                                clas_file = class_table.getScopeName();
                                break;
                            }
                        }
                    }
                }
                if (clas.equals("") == false && sym.getIsClassMethod() == true){
                    ClassTable class_table = (ClassTable) mct.get(clas_file);
                    ClassSymbol currentClass  = (ClassSymbol) class_table.getClassOfListClasses(clas);

                    // obter metodo
                    //Symbol sy = (Symbol) scp.getMembers().get(0);
                    String ss = "";
                    if (sym.getName().equals("__construct"))
                        ss = "construct";
                    MethodClass mc = currentClass.getMethodClass(sym.getName(), ss, mct);
                    MethodSymbol mss_final = mc.getMeth();
                    String mss_final_file = mc.getClassMeth().getFileClass();
                    /* Fazer a analise do metodo */
                    if (mss_final != null){
                        Instance inst1 = null;
                        if (s.equals("self") == true || s.equals("parent") == true)
                            inst1 = inst;
                        
                        Scope scp1 = (Scope) sym;
                        MethodSymbolXSS meth_sym = new MethodSymbolXSS(mss_final);
                        int valueFinal = meth_sym.analyseMethodXSS(mss_final,scp.getScopeSymbol().getCodeLine(), scp1, mts, mus, filename, mss_final_file, inst, mct, typeMeth);
                        scp1.getScopeSymbol().setTainted(valueFinal);
                        scp.resolveSymbol(scp, scp1.getScopeSymbol(), mts, mus, scp1.getScopeSymbol().getFileSymbol());
                    }
                }
                return;
            }

            case 5:{
                ftime = false;
                InstanceTable instTable = null;
                SymbolTable st = null;
                
                ret = instanceMethod(ms, scp, filename, "", mts, mus, inst, mtsc, mct, typeMeth, ret, null, null);

                InstanceTable instances_table = null;
                if (typeMeth.equals("constructor") == true)
                    instances_table = inst.getObjectsOfInstance();
                else
                    instances_table = mtsc.getObjectsOfMethod();

                //if (ret != null && instances_table.getMembers().contains(ret) == true){
                if (ret != null && instances_table.containsInstance(ret.getInstanceName()) == true){
                    Boolean a = true;
                    Scope enc_f = scp;
                    Scope enc_b;
                    while (a == true){
                        enc_b = enc_f.getEnclosingScope();
                        if (enc_b.getScopeName().equals(ms.getFunctionName()) == false)
                            enc_f = enc_b;
                        else
                            a = false;
                    }

                    Symbol sy = new Symbol(ret.getInstanceName(), ret.getTainted(), ret.getCreateLineInstance(), ret.getFileInstance());
                    sy.setIsClassInstruction(true);
                    mtsc.getAliases().put(enc_f.getScopeName(), sy);
                    scp.resolveSymbol(scp, sym, mts, mus, sym.getFileSymbol());
                    mts.removeDuplicates(sym);

                    if (cs_att != null){
                        cs_att.getScopeSymbol().setTainted(ret.getTainted());
                        inst.updateTainted(cs_att, sym);
                    }
                }
                exit_for = true;
                return;
            }
            default:{
                if (scp.getEnclosingScope() != null && scp.getEnclosingScope().getScopeName().equals("this") == false)
                    ftime = false;

                if (sym.getRootScope() == null && (sym.getIsClassMethod() == false && sym.getIsUserFunction() == false)){
                    if (ms != null){                  
                      if (ms.getArgsFunction().containsKey(sym.getName()) == true){
                          ArgFunctionSymbol arg = (ArgFunctionSymbol) ms.getArgsFunction().get(sym.getName());