# Pantera - Web Pen-Test Proxy
#
# FILENAME      : panteraDB.py
# CODER         : Simon Roses Femerling
# DATE          : 11/29/2005
# LAST UPDATE   : 07/05/2006
# ABSTRACT      : Pantera DB support.
#       
# - Roses Labs Innovations (RL+I)
# Roses Labs
# http://www.roseslabs.com
#
# Copyright (c) 2003-2006 Roses Labs.
#
# You may not distribute, transmit, repost this software for commercial 
# purposes without Roses Labs written permission. 
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, publish,
# distribute the Software, and to permit persons to whom the Software 
# is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#

'''
@author:       Simon Roses Femerling
@license:      GNU General Public License 2.0 or later
@contact:      pantera.proxy@gmail.com
@organization: OWASP / Roses Labs
'''

import threading
import re
import sets
import types

try:
    import MySQLdb
    from MySQLdb.connections import Connection
except:
    print "Error: Pantera needs mysqldb, read documentation please!"

#############################################################################################
# DDBB internal classes
#############################################################################################

#############################################################################################
# FUNC     : class DBPoolError
# PARAMS   : Exception
# RETURN   : ...
# ABSTRACT : Pool Error
class DBPoolError(Exception): 
    '''
    
    '''
    """ DBPoolError class """
    pass

#############################################################################################
# FUNC     : class UnsupportedError
# PARAMS   : Exception
# RETURN   : ...
# ABSTRACT : Not supported
class UnsupportedError(DBPoolError): 
    '''
    
    '''
    """ UnsupportedError class """
    pass

#############################################################################################
# FUNC     : class PooledConnection
# PARAMS   : ...
# RETURN   : ...
# ABSTRACT : Pool class
class PooledConnection:
    '''
    
    '''
    """ A wrapper for database connections to help with DBPool. You don't normally deal with this class directly, but use DBPool to get new connections. """

    #############################################################################################
    # FUNC     : def __init__
    # PARAMS   : pool, con
    # RETURN   : ...
    # ABSTRACT : Init func and set internal variables
    def __init__(self, pool, con):
        '''
    
        '''
        """ __init__ func """
        self._con = con
        self._pool = pool
    # EOF: def __init__

    #############################################################################################
    # FUNC     : def close
    # PARAMS   : ...
    # RETURN   : ...
    # ABSTRACT : Close con
    def close(self):
        '''
    
        '''
        """ close func """
        if self._con is not None:
            self._pool.returnConnection(self)
            self._con = None
    # EOF: def close
    
    #############################################################################################
    # FUNC     : def __getattr__
    # PARAMS   : string
    # RETURN   : attr
    # ABSTRACT : get attr
    def __getattr__(self, name):
        '''
    
        '''
        """ __getattr__ func """
        return getattr(self._con, name)
    # EOF: def __getattr__

    #############################################################################################
    # FUNC     : def __del__
    # PARAMS   : ...
    # RETURN   : ...
    # ABSTRACT : Delete con
    def __del__(self):
        '''
    
        '''
        """ __del__ func """
        self.close()
    # EOF: def __del__

#############################################################################################
# FUNC     : class PanteraDBPool
# PARAMS   : ...
# RETURN   : ...
# ABSTRACT : Pantera DDBB pool class
class PanteraDBPool:
    '''
    
    '''
    """ PanteraDBPool class """

    #############################################################################################
    # FUNC     : def __init__
    # PARAMS   : dbModule, maxConnextions, *args, **kwargs
    # RETURN   : ...
    # ABSTRACT : Init DDBB ppol
    def __init__(self, dbModule, maxConnections, *args, **kwargs):
        '''
    
        '''
        """ __init__ func """
        if dbModule.threadsafety==0:
            raise UnsupportedError, "Database module does not support any level of threading."
        elif dbModule.threadsafety==1:
            from Queue import Queue
            self._queue = Queue(maxConnections)
            self.addConnection = self._unthreadsafe_addConnection
            self.getConnection = self._unthreadsafe_getConnection
            self.returnConnection = self._unthreadsafe_returnConnection
        elif dbModule.threadsafety>=2:
            self._lock = threading.Lock()
            self._nextCon = 0
            self._connections = []
            self.addConnection = self._threadsafe_addConnection
            self.getConnection = self._threadsafe_getConnection
            self.returnConnection = self._threadsafe_returnConnection

        # @@ 2000-12-04 ce: Should we really make all the connections now?
        # Couldn't we do this on demand?
        for i in range(maxConnections):
            con = apply(dbModule.connect, args, kwargs)
            self.addConnection(con)
    # EOF: def __init__

    # threadsafe/unthreadsafe refers to the database _module_, not THIS class..
    # this class is definitely threadsafe (um. that is, I hope so - Dan)

    #############################################################################################
    # FUNC     : def _threadsafe_addConnection
    # PARAMS   : com
    # RETURN   : ...
    # ABSTRACT : Add con
    def _threadsafe_addConnection(self, con):
        '''
    
        '''
        """ _threadsafe_addConnection func """
        self._connections.append(con)
    # EOF: def _threadsafe_addConnection

    #############################################################################################
    # FUNC     : def _threadsafe_getConnection
    # PARAMS   : ...
    # RETURN   : con
    # ABSTRACT : Return con
    def _threadsafe_getConnection(self):
        '''
    
        '''
        """ _threadsafe_getConnection func """
        self._lock.acquire()
        try:
            con = PooledConnection(self, self._connections[self._nextCon])
            self._nextCon = self._nextCon + 1
            if self._nextCon >= len(self._connections):
                self._nextCon = 0
                return con
        finally:
            self._lock.release()
    # EOF: def _threadsafe_getConnection

    #############################################################################################
    # FUNC     : def _threadsafe_returnConnection
    # PARAMS   : con
    # RETURN   : ...
    # ABSTRACT : Return con
    def _threadsafe_returnConnection(self, con):
        '''
    
        '''
        return
    # EOF: def _threadsafe_returnConnection

    # These functions are used with DB modules that have connection level threadsafety, like PostgreSQL.
    #

    #############################################################################################
    # FUNC     : def _unthreadsafe_addConnection
    # PARAMS   : con 
    # RETURN   : ...
    # ABSTRACT : Add con
    def _unthreadsafe_addConnection(self, con):
        '''
    
        '''
        """ _unthreadsafe_addConnection func """
        self._queue.put(con)
    # EOF: def _unthreadsafe_addConnection

    #############################################################################################
    # FUNC     : def _unthreadsafe_getConnection
    # PARAMS   : ...
    # RETURN   : pool con
    # ABSTRACT : Get con
    def _unthreadsafe_getConnection(self):
        '''
    
        '''
        """ _unthreadsafe_getConnection func """
        return PooledConnection(self, self._queue.get())
    # EOF: def _unthreadsafe_getConnection

    #############################################################################################
    # FUNC     : def _unthreadsafe_returnConnection
    # PARAMS   : conpool
    # RETURN   : ...
    # ABSTRACT : Return con
    def _unthreadsafe_returnConnection(self, conpool):
        '''
    
        '''
        """ _unthreadsafe_returnConnection func """
        """
        This should never be called explicitly outside of this module.
        """
        #self.addConnection(conpool.con)
        self.addConnection(conpool._con)
    # EOF: def _unthreadsafe_returnConnection

#############################################################################################
# FUNC     : class PanteraDB
# PARAMS   : ...
# RETURN   : ...
# ABSTRACT : Pantera DDBB class
class PanteraDB:
    '''
    
    '''
    """ PanteraDB class """

    #############################################################################################
    # FUNC     : def __init__
    # PARAMS   : conn
    # RETURN   : ...
    # ABSTRACT : Init internal variables
    def __init__(self, conn):
        '''
    
        '''
        self.conn = conn
        self.error_msg = ""
        self.quote_for_escape = {'\0': '\\0', "'": "\\'", '"': '\\"', '\\': '\\\\'}
        return
    # EOF: def __init__
        
    #############################################################################################
    # FUNC     : def PanteraDB
    # PARAMS   : ...
    # RETURN   : coon
    # ABSTRACT : Return con
    def PanteraDB(self):
        '''
    
        '''
        """ PanteraDB func """
        return self.conn
    # EOF: def PanteraDB

    #############################################################################################
    # FUNC     : def SetDBLogin
    # PARAMS   : string
    # RETURN   : ...
    # ABSTRACT : Set DDBB login
    def SetDBLogin(self, l):
        '''
    
        '''
        """ SetDBLogin func """
        self.dblogin = l
    # EOF: def SetDBLogin

    #############################################################################################
    # FUNC     : def GetDBLogin
    # PARAMS   : ...
    # RETURN   : string
    # ABSTRACT : Get DDBB login
    def GetDBLogin(self):
        '''
    
        '''
        """ GetDBLogin func """
        return self.dblogin
    # EOF: def GetDBLogin

    #############################################################################################
    # FUNC     : def SetDBPass
    # PARAMS   : string 
    # RETURN   : ...
    # ABSTRACT : Set DDBB password
    def SetDBPass(self, p):
        '''
    
        '''
        """ SetDBPass func """
        self.dbpass = p
    # EOF: def SetDBPass

    #############################################################################################
    # FUNC     : def GetDBPass
    # PARAMS   : ...
    # RETURN   : string
    # ABSTRACT : Get DDBB password
    def GetDBPass(self):
        '''
    
        '''
        """ GetDBPass func """
        return self.dbpass
    # EOF: def GetDBPass

    #############################################################################################
    # FUNC     : def SetDBHost
    # PARAMS   : string
    # RETURN   : ...
    # ABSTRACT : Set DDBB host
    def SetDBHost(self, h):
        '''
    
        '''
        """ SetDBHost func """
        self.dbhost = h
    # EOF: def SetDBHost

    #############################################################################################
    # FUNC     : def GetDBHost
    # PARAMS   : ...
    # RETURN   : string
    # ABSTRACT : Get DDBB host
    def GetDBHost(self):
        '''
    
        '''
        """ GetDBHost func """
        return self.dbhost
    # EOF: def GetDBHost

    #############################################################################################
    # FUNC     : def SetDBName
    # PARAMS   : string
    # RETURN   : ...
    # ABSTRACT : Set DDBB name
    def SetDBName(self, n):
        '''
    
        '''
        """ SetDBName func """
        self.dbname = n
    # EOF: def SetDBName

    #############################################################################################
    # FUNC     : def GetDBName
    # PARAMS   : ...
    # RETURN   : string
    # ABSTRACT : Return DDBB name
    def GetDBName(self):
        '''
    
        '''
        """ GetDBName func """
        return self.dbname
    # EOF: def GetDBName

    #############################################################################################
    # FUNC     : def InitDB
    # PARAMS   : ...
    # RETURN   : 0 on success and emtry string | 1 on error and error message
    # ABSTRACT : Connect to DDBB
    def InitDB(self):
        '''
    
        '''
        """ InitDB func """
        try:
            self.conn = MySQLdb.connect (host = self.dbhost,
                               user = self.dblogin,
                               passwd = self.dbpass,
                               db = self.dbname)
        except MySQLdb.Error, e:
            return 1, "Error %d: %s" % (e.args[0], e.args[1])
        return 0, ""
    # EOF: def InitDB

    #############################################################################################
    # FUNC     : def CloseDB
    # PARAMS   : ...
    # RETURN   : ...
    # ABSTRACT : Close DDBB
    def CloseDB(self):
        '''
    
        '''
        """ CloseDB func """
        self.conn.close()
    # EOF: def CloseDB

    #############################################################################################
    # FUNC     : def ReturnDBConn
    # PARAMS   : ...
    # RETURN   : con
    # ABSTRACT : Return con
    def ReturnDBConn(self):
        '''
    
        '''
        """ ReturnDBConn func """
        return self.conn
    # EOF: def ReturnDBConn

    #############################################################################################
    # FUNC     : def GetCursor
    # PARAMS   : ...
    # RETURN   : cursor
    # ABSTRACT : Return cursor
    def GetCursor(self):
        '''
    
        '''
        """ GetCursor func """
        return self.conn.cursor()
    # EOF: def GetCursor      
        
    #############################################################################################
    # FUNC     : def Normalize_String
    # PARAMS   : string
    # RETURN   : string
    # ABSTRACT : Normalize string to be inserted in DDBB
    def Normalize_String(self, s):
        '''
    
        '''
        """ Normalize_String func """
        return "'%s'" % s
    # EOF: def Normalize_String
        
    #############################################################################################
    # FUNC     : def Normalize_File
    # PARAMS   : string
    # RETURN   : string
    # ABSTRACT : Normalize file name to be inserted in DDBB
    def Normalize_File(self, f):
        '''
    
        '''
        p = re.compile('\\\\')
        return p.sub('#',f)
    # EOF: def Normalize_File
    
    #############################################################################################
    # FUNC     : def Unormalize_File
    # PARAMS   : string
    # RETURN   : string
    # ABSTRACT : Unormalize file to be used in pantera
    def Unormalize_File(self, f):
        '''
    
        '''
        """ Unormalize_File func """
        p = re.compile('#')
        return p.sub('\\\\',f)
    # EOF: def Unormalize_File

    #############################################################################################
    # FUNC     : def Ping
    # PARAMS   : ...
    # RETURN   : ...
    # ABSTRACT : Do DDBB ping
    def Ping(self):
        '''
    
        '''
        """ Ping func """
        self.conn.ping()
    # EOF: def Ping

    #############################################################################################
    # FUNC     : def SetErrorMsg
    # PARAMS   : string
    # RETURN   : ...
    # ABSTRACT : Set Error msg
    def SetErrorMsg(self, msg):
        '''
    
        '''
        """ SetErrorMsg func """
        self.error_msg = msg
    # EOF: def SetErrorMsg

    #############################################################################################
    # FUNC     : def GetErrorMsg
    # PARAMS   : ...
    # RETURN   : string
    # ABSTRACT : Get Error Msg
    def GetErrorMsg(self):
        '''
    
        '''
        """ GetErrorMsg func """
        return self.error_msg
    # EOF: def GetErrorMsg
    
    def Escape(self,s):
        '''
    
        '''
        quote = self.quote_for_escape
        if type(s) == types.IntType:
            return str(s)
        elif s == None:
            return ""
        elif type(s) == types.StringType:
            r = range(len(s))
            r.reverse()          # iterate backwards, so as not to destroy indexing

            for i in r:
                if quote.has_key(s[i]):
                    s = s[:i] + quote[s[i]] + s[i+1:]

            return s
        else:
            return s

#############################################################################################
# panteraDB internal functions
#############################################################################################
    
    #############################################################################################
    # FUNC     : def iSelect
    # PARAMS   : string, list, dict
    # RETURN   : ddbb query or -1 on error
    # ABSTRACT : SELECT
    def iSelect(self, table=None, fields=[], where={}):
        '''
    
        '''
        """ iSelect func """
        cursor = self.GetCursor()
        stmt="SELECT "
        if table is None:
            stmt+=fields[0]
        else:
            i = 0
            l = len(fields) - 1
            for v in fields:
                stmt += v
                if i < l:
                    stmt += ","
                    i += 1
            stmt += " FROM %s" % table
        if where:
            stmt += " WHERE "
            dl = len(where) - 1
            i = 0
            for k,v in where.iteritems():
                stmt += "%s = %s" % (k,str(v))
                if i < dl:
                    stmt += " AND "
                    i += 1
        #print stmt
        try:
            cursor.execute(stmt)
        except MySQLdb.Error, e:
            #print e
            self.SetErrorMsg(e)
            return -1
        self.conn.commit()
        d = cursor.fetchall()
        cursor.close()
        return d
    # EOF: def iSelect

    #############################################################################################
    # FUNC     : def iInsert
    # PARAMS   : string, dict
    # RETURN   : 0 on success or -1 on error
    # ABSTRACT : INSERT
    def iInsert(self, table, di={}):
        '''
    
        '''
        """ iInsert func """
        self.Ping()
        cursor = self.GetCursor()
        stmt = "INSERT INTO %s (" % table
        dl = len(di) - 1
        i = 0
        for k,_ in di.iteritems():
            stmt += k
            if i < dl:
                stmt += ","
                i += 1
        stmt += ") VALUES ("
        i = 0
        dl = len(di) - 1
        for _,v in di.iteritems():
            stmt += str(v)
            if i < dl:
                stmt += ","
                i += 1
        stmt += ")"
        #print stmt
        try:
            cursor.execute (stmt)
        except MySQLdb.Error, e:
            #print e
            self.SetErrorMsg(e)
            return -1
        self.conn.commit() 
        cursor.close()
        return 0
    # EOF: def iInsert

    #############################################################################################
    # FUNC     : def iAlter
    # PARAMS   : string, string
    # RETURN   : 0 on success or -1 on error
    # ABSTRACT : ALTER
    def iAlter(self, table, st):
        '''
    
        '''
        """ iAlter func """
        cursor = self.GetCursor()
        stmt = "ALTER TABLE %s %s" % (table,st)
        try:
            cursor.execute (stmt)
        except MySQLdb.Error, e:
            #print e
            self.SetErrorMsg(e)
            return -1
        self.conn.commit() 
        cursor.close()
        return 0
    # EOF: def iAlter

    #############################################################################################
    # FUNC     : def iDelete
    # PARAMS   : string, value, dict
    # RETURN   : DDBB query
    # ABSTRACT : DELETE
    def iDelete(self, table, only_table=0,where={}):
        '''
    
        '''
        """ iDelete func """
        cursor = self.GetCursor()
        if only_table==0:
            stmt="DELETE FROM %s WHERE " % table 
            dl = len(where) - 1
            i = 0
            for k,v in where.iteritems():
                stmt += "%s = %s" % (k,str(v))
                if i < dl:
                    stmt += " AND "
                    i += 1
        else:
            stmt="DELETE FROM %s" % table
        try:
            cursor.execute (stmt)
        except MySQLdb.Error, e:
            #print e
            self.SetErrorMsg(e)
            return -1
        self.conn.commit()
        cursor.close()
        return 0
    # EOF: def iDelete

    #############################################################################################
    # FUNC     : def iUpdate
    # PARAMS   : string, dict, dict, value
    # RETURN   : 
    # ABSTRACT :  UPDATE
    def iUpdate(self, table, d={}, where={}, mode=0):
        '''
    
        '''
        """ iUpdate func """
        cursor = self.GetCursor()
        stmt="UPDATE "
        stmt += "%s SET " % table
        dl = len(d) - 1
        i = 0
        for k,v in d.iteritems():
            if mode==0:
                stmt += "%s = \'%s\'" % (k,str(v))
            else:
                stmt += "%s = %s" % (k,str(v))
            if i < dl:
                stmt += " , "
                i += 1
        if where:
            stmt += " WHERE "
            dl = len(where) - 1
            i = 0
            for k,v in where.iteritems():
                stmt += "%s = %s" % (k,str(v))
                if i < dl:
                    stmt += " AND "
                    i += 1
        #print stmt
        try:
            cursor.execute(stmt)
        except MySQLdb.Error, e:
            #print e
            self.SetErrorMsg(e)
            return -1
        self.conn.commit()
        d = cursor.fetchall()
        cursor.close()
        return d
    # EOF: def iUpdate

    #############################################################################################
    # FUNC     : def iRawExecute
    # PARAMS   : string
    # RETURN   : DDBB query
    # ABSTRACT : Do raw query
    def iRawExecute(self,s):
        '''
    
        '''
        """ iRawExecute func """
        cursor = self.conn.cursor()
        #print s
        try:
            cursor.execute("""%s""",s)
        except MySQLdb.Error, e:
            #print e
            self.SetErrorMsg(e)
            return -1            
        self.conn.commit()
        d = cursor.fetchone ()
        cursor.close()
        return d
    # EOF: def iRawExecute

    #############################################################################################
    # FUNC     : def iSet
    # PARAMS   : string
    # RETURN   : ...
    # ABSTRACT : SET
    def iSet(self, set):
        '''
    
        '''
        """ iSet func """
        cursor = self.GetCursor()
        stmt = "SET %s" % set
        try:
            cursor.execute (stmt)
        except MySQLdb.Error, e:
            #print e
            self.SetErrorMsg(e)
            return -1
        self.conn.commit()
        cursor.close()
        return 0
    # EOF: def iSet

    #############################################################################################
    # FUNC     : def iCounter_Links
    # PARAMS   : id, string
    # RETURN   : int
    # ABSTRACT : Return the COUNT of a table
    def iCounter_Links(self, project_id,table='links_t'):
        '''
    
        '''
        where = {'project_id':project_id}
        r = self.iSelect(table,['COUNT(*)'], where)
        if r == -1: return -1
        z = r[0]
        return int(z[0])
    # EOF: def iCounter_Links

    #############################################################################################
    # FUNC     : def iCounter
    # PARAMS   : id, string, dict
    # RETURN   : int
    # ABSTRACT : Return the element COUNT of a table
    def iCounter(self, project_id,table='links_t',where={}):
        '''
    
        '''
        iwhere = {'project_id':project_id}
        for k,v in where.iteritems():
            iwhere[k] = v
        r = self.iSelect(table,['COUNT(*)'], iwhere)
        if r == -1: return -1
        z = r[0]
        return int(z[0])
    # EOF: def iCounter

#############################################################################################
# Project DDBB functions
#############################################################################################

    #############################################################################################
    # FUNC     : def ReturnLastProjectID
    # PARAMS   : ...
    # RETURN   : int
    # ABSTRACT : Return last Project ID
    def ReturnLastProjectID(self):
        '''
    
        '''
        """ ReturnLastProjectID func """
        i = self.iSelect("project_t",["LAST_INSERT_ID()"])
        if i == -1: return -1
        z = i[0]
        return int(z[0])
    # EOF: def ReturnLastProjectID

    #############################################################################################
    # FUNC     : def ReturnLastIDFromTable
    # PARAMS   : string
    # RETURN   : int
    # ABSTRACT : Return last ID from a table
    def ReturnLastIDFromTable(self, t="links_t"):
        '''
    
        '''
        """ ReturnLastIDFromTable func """
        i = self.iSelect(t,["LAST_INSERT_ID()"])
        if i == -1: return -1
        z = i[0]
        return int(z[0])
    # EOF: def ReturnLastIDFromTable
        
    #############################################################################################
    # FUNC     : def Insert_New_Project
    # PARAMS   : string 
    # RETURN   : ...
    # ABSTRACT : Insert a new project
    def Insert_New_Project(self,name):
        '''
    
        '''
        """ Insert_New_Project func """
        di = {'project_name':self.Normalize_String(name),'start_date':'CURDATE()','start_time':'CURTIME()','last_date':'CURDATE()','last_time':'CURTIME()'}
        r = self.iInsert("project_t",di)
        if r == -1: 
            return -1
        else:
            return 0
    # EOF: def Insert_New_Project
        
    #############################################################################################
    # FUNC     : def Select_All_Project
    # PARAMS   : ...
    # RETURN   : DDBB query
    # ABSTRACT : Select all projects
    def Select_All_Project(self):
        '''
    
        '''
        """ Select_All_Project func """
        d = ['project_id','project_name']
        r = self.iSelect('project_t',d)
        if r == -1: return -1
        if r != 1:
            return r
    # EOF: def Select_All_Project(

    #############################################################################################
    # FUNC     : def Reset_TableID
    # PARAMS   : string, string
    # RETURN   : ...
    # ABSTRACT : Reset table ID
    def Reset_TableID(self, table, st="AUTO_INCREMENT=0"):
        '''
    
        '''
        """ Reset_TableID func """
        i = self.iAlter(table,st)
        if i == -1: 
            return -1
        else:
            return 0
    # EOF: def Reset_TableID

    #############################################################################################
    # FUNC     : def Delete_Project
    # PARAMS   : value
    # RETURN   : ...
    # ABSTRACT : Delete a entire project
    def Delete_Project(self, id):
        '''
    
        '''
        """ Delete_Project func """
        d = {'project_id':id}
        i = self.iDelete("project_t",0,d)
        if i == -1: return -1
        i = self.iDelete("links_t",0,d)
        if i == -1: return -1
        i = self.iDelete("not_save_links_t",0,d)
        if i == -1: return -1
        i = self.iDelete("page_info_t",0,d)
        if i == -1: return -1
        i = self.iDelete("project_info_t",0,d)
        if i == -1: return -1
        i = self.iDelete("snitch_t",0,d)
        if i == -1: return -1
        return 0
    # EOF: def Delete_Project
        
    #############################################################################################
    # FUNC     : def Insert_New_Link
    # PARAMS   : value, string
    # RETURN   : ...
    # ABSTRACT : Insert a link
    def Insert_New_Link(self, project_id, file,url):
        '''
    
        '''
        """ Insert_New_Link func """
        # check for uniqueness
        r = self.Return_All_Links(project_id)
        if r == -1: return -1
        l = []
        l = map(l.append, r)
        if not file in l:
            di = {'project_id':project_id,'link_file':self.Normalize_String(self.Normalize_File(file)),'link_url':self.Normalize_String(self.Normalize_File(url))}
            r = self.iInsert("links_t",di)
            if r == -1: return -1
        else:
            return 1
        return 0
    # EOF: def Insert_New_Link

    #############################################################################################
    # FUNC     : def Insert_New_Not_Save_Link
    # PARAMS   : value, file
    # RETURN   : ...
    # ABSTRACT : Do insert
    def Insert_New_Not_Save_Link(self, d):
        '''
    
        '''
        """ Insert_New_Not_Save_Link func """
        sf,di,f = d
        # we need to make sure we are not saving repeated stuff...
        where = {'project_id':di['project_id']}
        s = self.iSelect("not_save_links_t",['not_save_link_url'], where)
        if s == -1: return -1
        l = [c[0] for c in s if c[0] != '']
        if sf in l: # check url in table, if exists then return
            return 0 
        di['not_save_link_file'] = self.Normalize_String(self.Normalize_File(f))
        di['not_save_link_url'] = self.Normalize_String(self.Normalize_File(sf))
        di['not_save_link_time'] = 'CURTIME()'
        di['not_save_link_date'] = 'CURDATE()'
        r = self.iInsert("not_save_links_t",di)
        if r == -1: return -1
        return 0
    # EOF: def Insert_New_Not_Save_Link

    #############################################################################################
    # FUNC     : def Return_All_Links
    # PARAMS   : value
    # RETURN   : DDBB query
    # ABSTRACT : Return all links from a project
    def Return_All_Links(self, project_id):
        '''
    
        '''
        """ Return_All_Links func """
        d = ['link_id','link_file']
        where = {'project_id': project_id}
        s = self.iSelect("links_t",d, where)
        if s == -1: return -1
        d = []
        # fix data
        add = d.append
        for c in s:
            z,x = int(c[0]),self.Unormalize_File(c[1])
            a = (z,x)
            add(a)    
        return d # a list with tuples (id,file)
    # EOF: def Return_All_Links

    #############################################################################################
    # FUNC     : def Return_Link_File
    # PARAMS   : value, value
    # RETURN   : DDBB query
    # ABSTRACT : Return link file 
    def Return_Link_File(self, project_id, link_id):
        '''
    
        '''
        """ Return_Link_File func """
        d = ['link_file']
        where = {'project_id': project_id,'link_id':link_id}
        s = self.iSelect("links_t",d, where)
        if s == -1: return -1
        z = ""
        for c in s:
            z = c[0]
        return self.Unormalize_File(z)
    # EOF: def Return_Link_File

    #############################################################################################
    # FUNC     : def Return_Link_File_With_ID
    # PARAMS   : value, value
    # RETURN   : DDBB query
    # ABSTRACT : Return link file 
    def Return_Link_File_With_ID(self, project_id, link_id):
        '''
    
        '''
        """ Return_Link_File_With_ID func """
        d = ['link_id','link_file']
        where = {'project_id': project_id,'link_id':link_id}
        s = self.iSelect("links_t",d, where)
        if s == -1: return -1
        for c in s:
            z = (c[0],self.Unormalize_File(c[1]))
        return z
    # EOF: def Return_Link_File_With_ID

    #############################################################################################
    # FUNC     : def Return_DateTime_Link
    # PARAMS   : value, value
    # RETURN   : DDBB query
    # ABSTRACT : Return date and time of a link
    def Return_DateTime_Link(self, project_id, link_id):
        '''
    
        '''
        """ Return_DateTime_Link func """
        d = ['page_date','page_time']
        where = {'project_id': project_id,'link_id':link_id}
        s = self.iSelect("page_info_t ",d, where)
        if s == -1: return -1
        for c in s:
            z,x = c[0],c[1]
        return (z,x)
    # EOF: def Return_DateTime_Link

    #############################################################################################
    # FUNC     : def Return_ProjectName
    # PARAMS   : value
    # RETURN   : DDBB query
    # ABSTRACT : Return project name
    def Return_ProjectName(self, project_id):
        '''
    
        '''
        """ Return_ProjectName func """
        d = ['project_name']
        where = {'project_id': project_id}
        s = self.iSelect("project_t",d, where)
        if s == -1: return -1
        return s
    # EOF: def Return_ProjectName

    #############################################################################################
    # FUNC     : 
    # PARAMS   : 
    # RETURN   : 
    # ABSTRACT : 
    def Update_Project(self, project_id,d={}):
        '''
    
        '''
        pass

    #############################################################################################
    # FUNC     : def Set_ProjectID
    # PARAMS   : value
    # RETURN   : ...
    # ABSTRACT : Set project ID into variable
    def Set_ProjectID(self, project_id):
        '''
    
        '''
        """ Set_ProjectID func """
        i = self.iSet("@current_project_id =" + str(project_id))
        if i == -1: return -1
        return 0
    # EOF: def Set_ProjectID
    
    #############################################################################################
    # FUNC     : def Insert_New_Page
    # PARAMS   : dict
    # RETURN   : ...
    # ABSTRACT : Insert a new page info
    def Insert_New_Page(self, d): 
        '''
    
        '''
        """ Insert_New_Page func """
        
        di = {'page_time':'CURTIME()','page_date':'CURDATE()'}
        for z in d.keys():
            di[z] = d[z]
        r = self.iInsert("page_info_t",di)
        if r == -1: return -1
        return 0
    # EOF: def Insert_New_Page
    
    #############################################################################################
    # FUNC     : def Select_Page_Info
    # PARAMS   : value, value
    # RETURN   : dict
    # ABSTRACT : Select all page info
    def Select_Page_Info(self, project_id, page_id):
        '''
    
        '''
        """ Select_Page_Info func """
        d = ['page_date','page_time','have_ssl','have_email','have_script','have_form','have_auth_form','have_cookie','have_session_id','have_external_link','have_comment','have_vuln','have_hidden','have_object','have_postauth','have_querystr','have_auth','method','page_hash','return_code','return_msg','version','host','vuln_data']
        where = {'project_id': project_id,'link_id':page_id}
        s = self.iSelect("page_info_t",d, where)
        if s == -1: return -1
        dat = {}
        for page_date,page_time,have_ssl,have_email,have_script,have_form,have_auth_form,have_cookie,have_session_id,have_external_link,have_comment,have_vuln,have_hidden,have_object,have_postauth,have_querystr,have_auth,method,page_hash,return_code,return_msg,version,host,vuln_data in s:
            dat['page_date'] = page_date
            dat['page_time'] = page_time
            dat['have_ssl'] = have_ssl
            dat['have_email'] = have_email
            dat['have_script'] = have_script
            dat['have_form'] = have_form
            dat['have_auth_form'] = have_auth_form
            dat['have_cookie'] = have_cookie
            dat['have_session_id'] = have_session_id 
            dat['have_external_link'] = have_external_link
            dat['have_comment'] = have_comment
            dat['have_vuln'] = have_vuln
            dat['have_hidden'] = have_hidden
            dat['have_object'] = have_object
            dat['have_postauth'] = have_postauth
            dat['have_querystr'] = have_querystr
            dat['have_auth'] = have_auth
            dat['method'] = method
            dat['page_hash'] = page_hash
            dat['return_code'] = return_code
            dat['return_msg'] = return_msg
            dat['version'] = version
            dat['host'] = host
            dat['vuln_data'] = vuln_data
        return dat
    # EOF: def Select_Page_Info
    
    #############################################################################################
    def Select_All_Page_Info(self,project_id):
        '''
    
        '''
        """ Select_Page_Info func """
        d = ['link_id','page_date','page_time','have_ssl','have_email','have_script','have_form','have_auth_form','have_cookie','have_session_id','have_external_link','have_comment','have_vuln','have_hidden','have_object','have_postauth','have_querystr','have_auth','method','page_hash','return_code','return_msg','version','host','vuln_data']
        where = {'project_id': project_id}
        s = self.iSelect("page_info_t",d, where)
        if s == -1: return -1
        a = []
        add = a.append
        for c in s:
            dat = {}
            dat['link_id'] = int(c[0])
            dat['page_date'] = c[1]
            dat['page_time'] = c[2]
            dat['have_ssl'] = c[3]
            dat['have_email'] = c[4]
            dat['have_script'] = c[5]
            dat['have_form'] = c[6]
            dat['have_auth_form'] = c[7]
            dat['have_cookie'] = c[8]
            dat['have_session_id'] = c[9] 
            dat['have_external_link'] = c[10]
            dat['have_comment'] = c[11]
            dat['have_vuln'] = c[12]
            dat['have_hidden'] = c[13]
            dat['have_object'] = c[14]
            dat['have_postauth'] = c[15]
            dat['have_querystr'] = c[16]
            dat['have_auth'] = c[17]
            dat['method'] = c[18]
            dat['page_hash'] = c[19]
            dat['return_code'] = c[20]
            dat['return_msg'] = c[21]
            dat['version'] = c[22]
            dat['host'] = c[23]
            dat['vuln_data'] = c[24]
            add(dat)            
        return a
    
    #############################################################################################
    # FUNC     : def Delete_Link
    # PARAMS   : value, value
    # RETURN   : ...
    # ABSTRACT : Delete a link
    def Delete_Link(self, project_id, link_id):
        '''
    
        '''
        """ Delete_Link func """
        d = {'project_id':project_id,'link_id':link_id}
        i = self.iDelete("links_t",0,d)
        if i == -1: return -1
        i = self.iDelete("page_info_t",0,d)
        if i == -1: return -1
        return 0
    # EOF: def Delete_Link
    
    #############################################################################################
    # FUNC     : def Delete_Not_Save_Link
    # PARAMS   : value, value
    # RETURN   : ...
    # ABSTRACT : Delete a link
    def Delete_Not_Save_Link(self, project_id, link_id):
        '''
    
        '''
        """ Delete_Not_Save_Link func """
        d = {'project_id':project_id,'not_save_link_id':link_id}
        i = self.iDelete("not_save_links_t",0,d)
        if i == -1: return -1
        return 0
    # EOF: def Delete_Not_Save_Link    
    
    #############################################################################################
    # FUNC     : def Return_Project_Notes
    # PARAMS   : value
    # RETURN   : DDBB query
    # ABSTRACT : Return project notes
    def Return_Project_Notes(self, project_id):
        '''
    
        '''
        d = ['notes']
        where = {'project_id':project_id}
        s = self.iSelect("project_t",d, where)
        if s == -1: return -1
        return s
    # EOF: def Return_Project_Notes
    
    #############################################################################################
    # FUNC     : def Update_Project_Notes
    # PARAMS   : value, string, value
    # RETURN   : ...
    # ABSTRACT : Update project notes
    def Update_Project_Notes(self, project_id,text, mode=0):
        '''
    
        '''
        """ Update_Project_Notes func """
        d = {'notes':MySQLdb.escape_string(text)}
        where = {'project_id':project_id}
        i = self.iUpdate("project_t",d, where, mode)
        if i == -1: return -1
        return 0
        #return s
    # EOF: def Update_Project_Notes

    #############################################################################################
    # FUNC     : def Return_Link_Notes
    # PARAMS   : value, value
    # RETURN   : DDBB query
    # ABSTRACT : Return link notes
    def Return_Link_Notes(self, project_id, id):
        '''
    
        '''
        """ Return_Link_Notes func """
        d = ['notes']
        where = {'project_id':project_id,'link_id':id}
        s = self.iSelect("page_info_t",d, where)
        if s == -1: return -1
        return s
    # EOF: def Return_Link_Notes
        
    #############################################################################################
    # FUNC     : def Update_Link_Notes
    # PARAMS   : value, value, string, value
    # RETURN   : ...
    # ABSTRACT : Update link notes
    def Update_Link_Notes(self, project_id, id, text, mode=0):
        '''
    
        '''
        """ Update_Link_Notes func """
        d = {'notes':MySQLdb.escape_string(text)}
        where = {'project_id':project_id,'link_id':id}
        i = self.iUpdate("page_info_t",d, where, mode)    
        if i == -1: return -1
        return 0
    # EOF: def Update_Link_Notes
 
    #############################################################################################
    # FUNC     : 
    # PARAMS   : 
    # RETURN   : 
    # ABSTRACT : 
    def Insert_Project_Info(self, d={}):
        '''
    
        '''
        """ Insert_Project_Info func """
        #Check for unique!
        dat = self.Select_Project_Info(d['project_id'],d['type'])
        if dat == -1: return -1
        l = []
        do = []
        add = l.append
        add1 = do.append
        for i in dat:
            add(i['value'])
            add1(i['domain'])
        if d['value'] not in l and d['domain'] not in do:
            # normalize value for DDBB
            d['value'] = "'%s'" % d['value']
            d['project_info_time'] = 'CURTIME()'
            d['project_info_date'] = 'CURDATE()'
            r = self.iInsert("project_info_t",d)
            if r == -1: return -1
        return 0
    # EOF: def

    #############################################################################################
    # FUNC     : 
    # PARAMS   : 
    # RETURN   : 
    # ABSTRACT : 
    def Select_Project_Info(self, project_id, type):
        '''
    
        '''
        where = {'project_id':project_id,'type':type}
        s = self.iSelect("project_info_t",['value','domain'], where)
        if s == -1: return -1
        l = []
        add = l.append
        for c in s:
            if c[0] != '':
                k = {}
                k['value'] = c[0]
                k['domain'] = c[1]
                add(k)
        return l # return list with values
    
    #############################################################################################
    # FUNC     : 
    # PARAMS   : 
    # RETURN   : 
    # ABSTRACT : 
    def Select_Project_Info_With_ID(self, project_id, type):
        '''
    
        '''
        where = {'project_id':project_id,'type':type}
        s = self.iSelect("project_info_t",['project_info_id','value','domain'], where)
        if s == -1: return -1
        l = []
        add = l.append
        for c in s:
            k = {}
            k['project_info_id'] = c[0]
            k['value'] = c[1]
            k['domain'] = c[2]
            add(k)
        return l # return list with values
    
    def Count_Links(self,project_id):
        '''
    
        '''
        r = self.iCounter_Links(project_id)
        if r == -1: return 0
        return r
    
    def Count_All_Links(self,project_id):
        '''
    
        '''
        r = self.Count_Links(project_id)
        if r == -1: return -1
        r1 = self.iCounter_Links(project_id,'not_save_links_t')
        if r1 == -1: return 0
        return r + r1
    
    def Return_Unique_Types_Project_Info(self, project_id):
        '''
    
        '''
        where = {'project_id':project_id}
        s = self.iSelect("project_info_t",['DISTINCT type'], where)
        if s == -1: return -1
        #l = []
        #for c in s:
        #    if c[0] != '':
        #        l.append(c[0])
        l = [c[0] for c in s if c[0] != '']
        return l # return list with values
    
    #############################################################################################
    # FUNC     : 
    # PARAMS   : 
    # RETURN   : 
    # ABSTRACT : 
    def Select_Domains_For_Type(self, project_id, type):
        '''
    
        '''
        where = {'project_id':project_id,'type':type}
        s = self.iSelect("project_info_t",['domain'], where)
        if s == -1: return -1
        #l = []
        #for c in s:
        #    if c[0] != '':
        #        l.append(c[0])
        l = [c[0] for c in s if c[0] != '']        
        return l # return list with values    
    
    def Return_Count_Project_Info(self, project_id, type):
        '''
    
        '''
        d = {'type':type}
        r = self.iCounter(project_id,'project_info_t',d)
        if r == -1: return 0
        return r
    
    def Return_Count_Links_Info(self, project_id, have=''):
        '''
    
        '''
        t = 'have_%s' % have
        d = {t:1}
        r = self.iCounter(project_id,'page_info_t',d)
        if r == -1: return 0
        return r

    #############################################################################################
    # FUNC     : def Delete_Project_Info
    # PARAMS   : value, value
    # RETURN   : ...
    # ABSTRACT : Delete data from project info table
    def Delete_Project_Info(self, project_id, project_info_id):
        '''
    
        '''
        """ Delete_Project_Info func """
        d = {'project_id':project_id,'project_info_id':project_info_id}
        i = self.iDelete("project_info_t",0,d)
        if i == -1: return -1
        return 0
    # EOF: def Delete_Project_Info

    #############################################################################################
    # FUNC     : def Update_Project_Info
    # PARAMS   : value, value, string, value
    # RETURN   : ...
    # ABSTRACT : Update Project Info
    def Update_Project_Info(self, project_id, id, value, domain, mode=0):
        '''
    
        '''
        """ Update_Project_Info func """
        d = {'value':value,'domain':domain,'project_info_date':'CURDATE()','project_info_time':'CURTIME()'}
        where = {'project_id':project_id,'project_info_id':id}
        i = self.iUpdate("project_info_t",d, where, mode)    
        if i == -1: return -1
        return 0
    # EOF: def Update_Project_Info

    def Select_Links_With(self, project_id, have=''):
        '''
    
        '''
        myh = 'have_%s' % have
        where = {'project_id':project_id,myh:1}
        s = self.iSelect("page_info_t",['link_id'], where)
        links = []
        add = links.append
        for c in s:
            if c[0] != '':
                r = self.Return_Link_File_With_ID(project_id,c[0])
                if r == -1: return -1
                add(r)
        return links

    #############################################################################################
    # FUNC     : def Return_Entire_Links
    # PARAMS   : value
    # RETURN   : DDBB query
    # ABSTRACT : Return all links from a project
    def Return_Entire_Links(self, project_id):
        '''
    
        '''
        """ Return_Entire_Links func """
        l1 = []
        d = ['link_id','link_file']
        where = {'project_id': project_id}
        s = self.iSelect("links_t",d, where)
        if s == -1: return (-1,-1)
        # fix data
        add = l1.append
        for c in s:
            z,x = int(c[0]),self.Unormalize_File(c[1])
            a = (z,x)
            add(a) 
        l2 = []
        d = ['not_save_link_id','not_save_link_url']
        where = {'project_id': project_id}
        s = self.iSelect("not_save_links_t",d, where)
        if s == -1: return (-1,-1)
        # fix data
        add2 = l2.append
        for c in s:
            z,x = int(c[0]),self.Unormalize_File(c[1])
            a = (z,x)
            add2(a) 
        return (l1,l2) # a list with tuples (id,file)
    # EOF: def Return_Entire_Links

    def Return_Links_Criteria(self, project_id, links, select_criteria, criteria):
        '''
    
        '''
        """ Return_Links_Criteria func """
        
        if links == 'Interesting':
            
            r = self.ReturnInterestingLinks(project_id, select_criteria, criteria)
            if r == 1: return (-1,-1)
            return (r,[])
            
        elif links == 'NotInteresting':
            
            r = self.ReturnNotInterestingLinks(project_id, select_criteria, criteria)
            if r == 1: return (-1,-1)
            return ([],r)
                        
        elif links == 'All':
            
            r = self.ReturnInterestingLinks(project_id, select_criteria, criteria)
            if r == 1: return (-1,-1)
            r1 = self.ReturnNotInterestingLinks(project_id, select_criteria, criteria)
            if r1 == 1: return (-1,-1)
            return (r,r1)
            
        else: # unknow links selection
            return (-1,-1)
        return (-1,-1)

    def ReturnInterestingLinks(self, project_id, select_criteria, criteria):
        '''
    
        '''
        l1 = []
        q = "'%s'" % criteria
        where = {'project_id':project_id,select_criteria:q}
        s = self.iSelect("page_info_t",['link_id','method','return_code'], where)
        if s == -1: return -1
        l = []
        add = l.append
        for c in s:
            d = {}
            d['id'] = c[0]
            d['method'] = c[1]
            d['return_code'] = c[2]
            add(d)
        add1 = l1.append 
        for i in l:
            where = {'project_id':project_id,'link_id':i['id']}
            r = self.iSelect("links_t",['link_url'], where)
            if r != -1:
                for x in r:
                    i['url'] = x[0]
                    add1(i)
        return l1

    def ReturnNotInterestingLinks(self, project_id, select_criteria, criteria):
        '''
    
        '''
        l2 = []
        q = "'%s'" % criteria
        where = {'project_id':project_id,select_criteria:q}
        s = self.iSelect("not_save_links_t",['not_save_link_id','not_save_link_url','method','return_code'], where)
        if s == -1: return -1
        add = l2.append
        for c in s:
            d = {}
            d['id'] = c[0]
            d['url'] = c[1]
            d['method'] = c[2]
            d['return_code'] = c[3]
            add(d)
        return l2

    #############################################################################################
    # FUNC     : def Update_Page_Info
    # PARAMS   : value, dict, value
    # RETURN   : ...
    # ABSTRACT : Update Page Info
    def Update_Page_Info(self, project_id, di, mode=0):
        '''
    
        '''
        """ Update_Page_Info func """
        
        where = {'project_id':project_id,'page_info_id':di['page_info_id']}
        i = self.iUpdate("page_info_t",di, where, 1)
        if i == -1: return -1
        return 0
    # EOF: def Update_Page_Info

    #############################################################################################
    # FUNC     : def Insert_Snitch  
    # PARAMS   : 
    # RETURN   : 
    # ABSTRACT : 
    def Insert_Snitch(self, project_id, id, snitch_data):
        '''
    
        '''
        """ Insert_Snitch func """
        # normalize value for DDBB
        d = {}
        d['project_id'] = project_id
        d['link_id'] = id
        d['data'] = "'" + MySQLdb.escape_string(snitch_data) + "'"
        r = self.iInsert("snitch_t",d)
        if r == -1: return -1
        return 0
    # EOF: def Insert_Snitch
    
    def Return_Link_Snitch(self, project_id, id):
        '''
    
        '''
        where = {'project_id':project_id,'link_id':id}
        s = self.iSelect("snitch_t",['data'], where)
        if s == -1: return -1
        d = ''
        for c in s:
            if c[0] != '':
                d = c[0]
        return d # return list with values

    def Return_All_Link_Snitch(self, project_id):
        '''
    
        '''
        where = {'project_id':project_id}
        s = self.iSelect("snitch_t",['data'], where)
        if s == -1: return -1
        #l = []
        #add = l.append
        #for c in s:
        #    add(c[0].tostring())
        l = [c[0].tostring() for c in s] 
        return l # return list with values

    def Return_All_Links_ID(self, project_id):
        '''
    
        '''
        """ """
        d = ['link_id']
        where = {'project_id': project_id}
        s = self.iSelect("links_t",d, where)
        if s == -1: return -1
        #a = []
        #add = a.append
        #for c in s:
        #    add(c[0])
        a = [c[0] for c in s]    
        return a
    
    def Return_Not_Link_Save_File(self, project_id, id):
        '''
    
        '''
        where = {'project_id':project_id,'not_save_link_id':id}
        s = self.iSelect("not_save_links_t",['not_save_link_file'], where)
        if s == -1: return -1
        l = ''
        for c in s:
            if c[0] != '':
                l = self.Unormalize_File(c[0])
        return l
    
    #############################################################################################
    # FUNC     : def Delete_Not_Save_Link
    # PARAMS   : value, value
    # RETURN   : ...
    # ABSTRACT : Delete data from not save link table
    def Delete_Not_Save_link(self, project_id, project_info_id):
        '''
    
        '''
        """ Delete_Not_Save_link func """
        d = {'project_id':project_id,'not_save_link_id':project_info_id}
        i = self.iDelete("not_save_links_t",0,d)
        if i == -1: return -1
        return 0
    # EOF: def Delete_Not_Save_link

    def Return_Extension_Count(self, project_id, ext=[]):
        '''
    
        '''
        d = {}
        u = sets.Set([])
        where = {'project_id':project_id}
        s = self.iSelect("page_info_t",['DISTINCT extension'], where)
        if s == -1: return -1
        l = [c[0] for c in s if c[0] != '']
        s = self.iSelect("not_save_links_t",['DISTINCT extension'], where)
        if s == -1: return -1
        l1 = [c[0] for c in s if c[0] != '']
        for i in l:
            u.add(i)
        for i in l1:
            u.add(i)
        for i in u:
            z = "'" + i + "'"
            x = {'extension':z}
            r = self.iCounter(project_id,'page_info_t',x)
            if r == -1: r = 0
            r1 = self.iCounter(project_id,'not_save_links_t',x)
            if r1 == -1: r1 = 0
            if i in ext:
                d[i] = r + r1
            else:
                d['unknow'] = r + r1
        return d
                
# RL+I EOF