Пример #1
0
    def __init__(self, database):
        """
        Initialisierung

        @param database: Pfad zur Datenbank
        @type database: str

        @return: None
        """
        self.db = sqlite3.connect(database)
        self.db.text_factory = str
        self.cursor = self.db.cursor()
        self.init_db()
        self.mid_Pool = Pool(0, self.get_start_mid())
        self.bid_Pool = Pool(0, self.get_start_brdc_mid())
        self.fid_Pool = Pool(0, self.get_start_fid())
        self.uid_Pool = Pool(0, self.get_start_uid())
Пример #2
0
    def __init__(self, port=False):
        """
        Initialisierung und Binden des Ports.
        Der Port kann via Shell-Argument uebergeben werden, sonst wird versucht, Port 32323 zu binden.

        @return: None
        """

        self.database = DatabaseHandler("gu.db")
        self.crypt = EncryptionHandler()
        self.sid_Pool = Pool(0)

        self.file_storage = "./files/"
        self.max_rcv = 2048

        self.users = []         # Nutzer, die zum Index Session-ID gehoeren
        self.ivs = []           # Initialiserungsvektoren
        self.ctr = []           # Counter
        self.sesskey = []       # Sessionkeys
        self.uidstrings = []    # User-ID-Strings
        
        #serv_soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        #file_soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        serv_soc = socket.socket()

        if port != False:
            serv_soc.bind(("", port))
        elif len(sys.argv) < 2:
            serv_soc.bind(("", 32323))
        else:
            serv_soc.bind(("", int(sys.argv[1])))

        serv_soc.listen(1)
        
        try:
            while True:

                komm, addr = serv_soc.accept()
                data = ""
                data = komm.recv(self.max_rcv)

                # Default-Antwort
                resp = "error - invalid-client-request"

                # Leere Verbindung
                if not data: 
                    komm.close()
                    continue

                # Datenpaket ist verschluesslt (= Kein DHEX-Paket)    
                if self.crypt.is_encrypted(data):
                    #body = self.decrypt(data)

                    tmp = split(";", data, 1)
                    body = tmp[1]
                    #print "getting messages :" + body

                    # Wenn nicht entschluesselbar -> Fehler
                    if body == None:
                       komm.send(resp)
                       komm.close()
                       continue 

                    body = body.decode("utf-8", "ignore")

                try:
                    # Kopfdaten und Nutzdaten trennen
                    data = split(";", data, 1)
                    self.header = self.parse_header(data[0])
                    data = data[1]
                except IndexError:
                    komm.send(resp)
                    komm.close()
                    continue

                # Datenpaket encoden
                #if self.header[0] != "dhex":

                try:

                    if self.header[0] == "dhex":
                        resp = self.init_dh(data)                      
                    elif self.header[0] == "auth":
                        resp = self.auth_user(body)
                    elif self.header[0] == "msg":
                        resp = self.recv_msg(body)
                    elif self.header[0] == "getmsg":
                        resp = self.get_msg(body)
                    elif self.header[0] == "gmsg":
                        resp = self.recv_gmsg(body)
                    elif self.header[0] == "getgmsg":
                        resp = self.get_gmsg(body)
                    elif self.header[0] == "reqfile":
                        resp = self.request_file()
                    elif self.header[0] == "regfile":
                        resp = self.register_file(body)
                    elif self.header[0] == "getfile":
                        resp = self.get_globalname(body)
                    elif self.header[0] == "getpic":
                        resp = self.get_profile_pic(body)
                    elif self.header[0] == "adduser":
                        resp = self.add_user(body)
                    elif self.header[0] == "adressbook":
                        resp = self.get_address_book(body)


                    # Antwortpaket senden
                    if self.header[0] == "dhex":
                        komm.send(resp)

                    elif isinstance(resp, list):
                        #for item in resp:
                            #item = (str(item[0]).encode("utf-8", "ignore"), item[1].encode("utf-8", "ignore"))

                        komm.send(self.build_pack(json.dumps(resp)))

                    else:
                        if self.is_error(resp):
                            print "error:  " + resp
                            komm.send(resp)
                        else:
                            resp = self.crypt.encode_string(resp)
                            komm.send(self.build_pack(resp))
                        
                    komm.close()

                except IndexError:
                    komm.send(resp)
                    komm.close()

                        
        finally:
            #for client in clients: 
            #    client.close() 
            serv_soc.close()
Пример #3
0
class ConnectionHandler:
    """
    Infolib.ConnectionHandler ist eine Klasse, die die Grundfunktionalitaet des Infoservers bereitstellt.
    Sie bindet einen Port, an dem alle Verbindungen eigehen und verteilt die Pakete nach den entsprechenden Kopfinformationen.
    Sie baut auf allen anderen Klassen in der Infolib auf.

    Eine Verwendung ausserhalb des Infobook-Projektes wird nicht empfohlen.

    Eine Dokumentation des Ablaufes finden Sie im GitHub-Wiki unter https://github.org/hansau22/infobook/
    """

    def __init__(self, port=False):
        """
        Initialisierung und Binden des Ports.
        Der Port kann via Shell-Argument uebergeben werden, sonst wird versucht, Port 32323 zu binden.

        @return: None
        """

        self.database = DatabaseHandler("gu.db")
        self.crypt = EncryptionHandler()
        self.sid_Pool = Pool(0)

        self.file_storage = "./files/"
        self.max_rcv = 2048

        self.users = []         # Nutzer, die zum Index Session-ID gehoeren
        self.ivs = []           # Initialiserungsvektoren
        self.ctr = []           # Counter
        self.sesskey = []       # Sessionkeys
        self.uidstrings = []    # User-ID-Strings
        
        #serv_soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        #file_soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        serv_soc = socket.socket()

        if port != False:
            serv_soc.bind(("", port))
        elif len(sys.argv) < 2:
            serv_soc.bind(("", 32323))
        else:
            serv_soc.bind(("", int(sys.argv[1])))

        serv_soc.listen(1)
        
        try:
            while True:

                komm, addr = serv_soc.accept()
                data = ""
                data = komm.recv(self.max_rcv)

                # Default-Antwort
                resp = "error - invalid-client-request"

                # Leere Verbindung
                if not data: 
                    komm.close()
                    continue

                # Datenpaket ist verschluesslt (= Kein DHEX-Paket)    
                if self.crypt.is_encrypted(data):
                    #body = self.decrypt(data)

                    tmp = split(";", data, 1)
                    body = tmp[1]
                    #print "getting messages :" + body

                    # Wenn nicht entschluesselbar -> Fehler
                    if body == None:
                       komm.send(resp)
                       komm.close()
                       continue 

                    body = body.decode("utf-8", "ignore")

                try:
                    # Kopfdaten und Nutzdaten trennen
                    data = split(";", data, 1)
                    self.header = self.parse_header(data[0])
                    data = data[1]
                except IndexError:
                    komm.send(resp)
                    komm.close()
                    continue

                # Datenpaket encoden
                #if self.header[0] != "dhex":

                try:

                    if self.header[0] == "dhex":
                        resp = self.init_dh(data)                      
                    elif self.header[0] == "auth":
                        resp = self.auth_user(body)
                    elif self.header[0] == "msg":
                        resp = self.recv_msg(body)
                    elif self.header[0] == "getmsg":
                        resp = self.get_msg(body)
                    elif self.header[0] == "gmsg":
                        resp = self.recv_gmsg(body)
                    elif self.header[0] == "getgmsg":
                        resp = self.get_gmsg(body)
                    elif self.header[0] == "reqfile":
                        resp = self.request_file()
                    elif self.header[0] == "regfile":
                        resp = self.register_file(body)
                    elif self.header[0] == "getfile":
                        resp = self.get_globalname(body)
                    elif self.header[0] == "getpic":
                        resp = self.get_profile_pic(body)
                    elif self.header[0] == "adduser":
                        resp = self.add_user(body)
                    elif self.header[0] == "adressbook":
                        resp = self.get_address_book(body)


                    # Antwortpaket senden
                    if self.header[0] == "dhex":
                        komm.send(resp)

                    elif isinstance(resp, list):
                        #for item in resp:
                            #item = (str(item[0]).encode("utf-8", "ignore"), item[1].encode("utf-8", "ignore"))

                        komm.send(self.build_pack(json.dumps(resp)))

                    else:
                        if self.is_error(resp):
                            print "error:  " + resp
                            komm.send(resp)
                        else:
                            resp = self.crypt.encode_string(resp)
                            komm.send(self.build_pack(resp))
                        
                    komm.close()

                except IndexError:
                    komm.send(resp)
                    komm.close()

                        
        finally:
            #for client in clients: 
            #    client.close() 
            serv_soc.close()



    def is_error(self, data):
        """
        Prueft ob eine Antwort eine Fehlermeldung ist

        @param data: Antwort
        @type data: str

        @return: Boolean Ergebnis
        """

        if string.find(data, "error", 0, 4) == -1 :
            return False
        else:
            return True


    def init_dh(self, data):
        """
        Initialisiert den DH-Schluesselaustausch anhand der Informationen aus der Anfrage des Clients.

        @param data: Enthaelt den Oeffentlichen Teil vom Partner
        @type data: str

        @return: str - Sessionkey
        """

        # DH-Antwort (B) auf die Anfrage (A)
        ret = self.crypt.init_dh_b(self.sid_Pool.give_next(),data)

        if ret == False:
            return "error - DH-initiation-error - DHEX"

        try:
            # Alle Felder fuer die neu Initialiserte Session reservieren (befuellen)
            self.users.append("")
            self.uidstrings.append("")
            self.ivs.append(ret[0])
            self.ctr.append(ret[1])
            self.sesskey.append(ret[2])

            #print "sesskey :  " + ret[2]

            return ret[3]
        except IndexError:
            return "error - DH-initiation-server-error - DHEX"
        



    def decrypt(self, data):
        """
        Entschluesselt ein Datenpaket mit dem Sessionkey, der zur Session-ID gehoert.

        @param data: Verschluesseltes Paket mit unverschluesselten Kopfinformationen
        @type data: str

        @return: str - Unverschluesseltes Paket ohne Kopfinformationen
        """

        try:
            tmp = split(";", data, 1)       # ";" Seperiert Nutz- und Kopfdaten
            sid = split(":", tmp[0], 2)     # Extrahiere Session-ID
            sid = int(sid[2])
            data = self.crypt.decrypt(self.sesskey[sid], self.ctr[sid], tmp[1])
            return data
        except IndexError:
            return None



    
    def encrypt(self, data):
        """
        Verschluesselt die Daten fuer ein Paket.

        @param data: Daten-String ohne Kopfinformationen
        @type data: str

        @return: Verschluesselt Datenpaket ohne Kopfinformationen
        """
        try:
            sid = self.header[2]
            #return self.crypt.encrypt(self.sesskey[sid], self.ctr[sid], data)
            return data
        except IndexError:
            return None

            
    def parse_header(self, data):
        """
        Verarbeitet Kopfinformationen und wandelt die Informationen in benoetigte Typen

        @param data: Kopfinformationen
        @type data: str

        @return: Array - Kopfinformationen
        """

        try:
            header = split(":", data, 2)
            if not header[0] == "dhex":
                header[2] = int(header[2])
            return header
        except IndexError:
            pass
        


    def build_pack(self, msg):
        """
        Erstellt die Kopfinformationen fuer ein Datenpaket und fuegt die Nachricht an.

        @param msg: Nachricht ohne Kopfinformationen
        @type msg: str

        @return: str - Nachrichtenpaket mit Kopfinformationen
        """

        try:
            package = "sresp" + ":" + str(self.header[2]) + ";"
            #enc_msg = self.encrypt(msg)
            #if enc_msg == None:
            #    return msg
            package += msg
            return package
        except IndexError:
            return msg



    def auth_user(self, data):
        """
        Prueft ob eine Nutzer-Passwort Kombination valid ist.

        @param data: Paket des Clients ohne Kopfinformationen
        @type data: str

        @return: str - Digest, der den Nutzer-ID-String enthaelt
        """
        cred = split(":", data, 1)
        if len(cred) < 2:
            return "error - not-enough-arguments - AUTH"
        try:
            if self.database.auth_user(cred[0], cred[1]) == True:

                # User-ID String erzeugen
                dig = self.crypt.get_hash(self.sesskey[self.header[2]] + str(cred[0])) 

                self.uidstrings[self.header[2]] = dig
                self.users[self.header[2]] = self.database.get_user_id(cred[0])

                return dig
            else:
                return "error - wrong-credentials - AUTH"
        except IndexError:
            return "error - invalid-header - AUTH"



    def check_uidstring(self, index, string):
        """
        Vergleicht einen Nutzer-ID-String mit dem, der zu dem Nutzer mit der Session-ID gehoert.

        @param index: Session-ID
        @type index: int

        @param string: Nutzer-ID-String
        @type string: str

        @return: Boolean - Ergebnis
        """

        try:
            if self.uidstrings[index] == string:
                return True
            return False
        except IndexError:
            return False


        
    def recv_msg(self, data):
        """
        Traegt eine Nachricht in die Datenbank ein.

        @param data: Datenpaket des Clients ohne Kopfinformationen
        @type data: str

        @return: str - Erfolgs-/Fehlermeldung
        """

        try:
            sid = self.header[2]
            tmp = split(":", data, 2)


            # Nicht alle Felder gegeben
            if len(tmp) != 3:
                return "error - not-long-enough - MSG"

            if self.check_uidstring(sid, tmp[0]):
                rcv_uid = self.database.get_user_id(tmp[1])
                snd_uid = self.users[self.header[2]]
                print "writing message:" + tmp[2]
                if not self.database.rcv_message(snd_uid, rcv_uid, tmp[2]):
                    return "error - server-database-error - MSG"
                return "success - MSG"
            else:
                return "error - wrong-uidstring - MSG"
        except IndexError:
            return "error - invalid-header - MSG"



    def get_msg(self, data):
        """
        Gibt dem Client die Nachrichten zurueck. 

        @param data: Letzte MID, die der Client an den Server gibt.
        @type data: str

        @return: Array - Nachrichten
        """

        data = split(":", data, 2)

        try:

            if not self.check_uidstring(self.header[2], data[0]):
              #  print "wrong uid string :" + data[0]
                return "error - wrong-credentials - GetMessage"

            messages = self.database.get_messages_by_last_mid(self.header[2], data[1])
            ret_msg = []

            for item in messages:
                username = self.database.get_user_by_id(item[0])

                if (username == None) or (item[0] == "False"):
                    username = "******"

                ret_msg.append((username, item[1]))

            return ret_msg
        except IndexError:
            return "error - internal-database-request-error - MSG"



    def get_gmsg(self, data):
        """
        Gibt dem Client die Gruppennachrichten zurueck.

        @param data: Letzte GID, die der Client an den Server gibt.
        @type data: str

        @return: Array - Nachrichten
        """

        data = split(":", data, 2)

        try:

            if not self.check_uidstring(self.header[2], data[0]):
                print "wrong uid string"
                return "error - wrong-credentials - GetGroupMessage"

            messages = self.database.get_messages_by_last_gid(self.header[2], data[1])
            ret_msg = []

            for item in messages:
                groupname = self.database.get_group_by_id(item[0])

                if groupname == None:
                    groupname = "Gruppenname unbekannt"

                ret_msg.append(item[1] + ":" + groupname + ":" + item[2])

            return ret_msg
        except IndexError:
            return "error - internal-database-request-error - GroupMessage"



    def recv_gmsg(self, data):
        """
        Traegt eine Broadcast-Nachricht in die Datenbank ein.

        @param data: Datenpaket des Clients ohne Kopfinformationen
        @type data: str

        @return: str - Erfolgs-/Fehlermeldung
        """

        try:
            sid = self.header[2]
            tmp = split(":", data, 2)

            # Nicht alle Felder gegeben
            if len(tmp) != 3:
                return "error - not-enough-arguments - GroupMessage"

            if self.check_uidstring(sid, tmp[0]):
                rcv_gid = self.database.get_group_id(tmp[1])
                snd_uid = self.users[self.header[2]]
                print "writing group message:" + tmp[2]
                if not self.database.rcv_brdc_message(snd_uid, rcv_gid, tmp[2]):
                    return "error - server-database-error - GroupMessage"
                return "success - GroupMessage"
            else:
                print "error in uidstring"
                return "error - wrong-uidstring - GroupMessage"
        except IndexError:
            return "error - invalid-header - GroupMessage"


    def request_file(self):
        """
        Gibt einen Dateistring fuer eine neue Datei zurueck, die ueber FTP hochgeladen werden kann

        @return: str - Dateistring
        """

        ret_value = self.generate_file_string()

        if ret_value == None:
            return "error - storage-full - REQFILE"
        else:
            self.database.add_file(ret_value)
            return ret_value



    def register_file(self, data):
        """
        Registriert eine Datei (Setzt den Besitzer zu einem Upload und gibt Dateinamen an)

        @param data: Datenpaket des Clients ohne Kopfinformationen
        @type data: str

        @return: str - Erfolgs-/Fehlermeldung
        """
        values = split(":", data, 2)
        print  values
    
        try: 
               

            filestring = values[0]
            global_name = values[1]
            del values


            if not self.database.check_filestring(filestring):
                return "error - wrong-filestring"

            if not self.database.register_file(self.users[self.header[2]], global_name, filestring):
                return "error - server-storage-error"
            else:
                return "success - FILE"
        except IndexError:
            return "error - invalid-header - FILE"


    def get_globalname(self, data):
        """
        Sucht eine Datei nach dem Dateinamen und gibt den filestring zuruekc

        @param data: Datenpaket des Clients ohne Kopfinformationen
        @type data: str

        @return: str - filestring / str - error
        """

        filestring = self.database.get_name_by_filestring(data)

        if not filestring:
            return "error - file-not-found - FILE"
        return filestring


    def generate_file_string(self):
        """
        Generiert einen Datei-String fuer eine neu empfangene Datei
        Prueft ausserdem, ob eine Datei mit diesem Namen in ./files vorhanden ist

        @return: str - Dateistring
        """
        for i in range(0, 14):
            filestring = ""
            for i in range(0, 10):
                filestring = filestring + choice(string.ascii_letters)

            if os.path.exists(self.file_storage + filestring):
                break
            else:
                return filestring

        return None



    def get_profile_pic(self, data):
        """
        Gibt dem Nutzer den String zum Profilfoto zurueck

        @param data: Datenpaket des Clients ohne Kopfinformationen
        @type data: str

        @return: str - Dateistring zum Profilbild
        """

        string = self.database.get_profile_pic(data)

        if not string:
            return "-"
        return string


    def add_user(self, data):
        """
        Fuegt einen neuen Benutzer hinzu

        @param data: Daten vom Client
        @type data: str

        @return: str - Nachricht an den Client
        """

        tmp = split(":", data, 2)

        if not len(tmp) == 2:
            return "error - not-enough-arguments - ADDUSER"        

        username = tmp[0]
        pwhash = tmp[1]

        if not self.database.check_user(username):
            return "error - already-present-username - ADDUSER"

        self.database.add_user(username, pwhash)
        return "success - ADDUSER"


    def get_address_book(self, data):
        """
        Gibt das Nutzer-Addressbuch zurueck

        @param data: uidstring
        @type data: str

        @return: Array - [int UID, str Name]
        """

        if not self.check_uidstring(int(self.header[2]), data):
            return "error - wrong-uidstring - GETADRBOOK"

        return self.database.get_address_book(self.users[int(self.header[2])])
Пример #4
0
class DatabaseHandler:
    """
    Infolib.DatabaseHandler ist eine Klasse, die den Datenbankzugriff auf eine sqlite3-Datenbank fuer den Infobook-Server
    regelt.

    Eine Verwendung ausserhalb des Infobook-Projektes wird nicht empfohlen.
    """

    def __init__(self, database):
        """
        Initialisierung

        @param database: Pfad zur Datenbank
        @type database: str

        @return: None
        """
        self.db = sqlite3.connect(database)
        self.db.text_factory = str
        self.cursor = self.db.cursor()
        self.init_db()
        self.mid_Pool = Pool(0, self.get_start_mid())
        self.bid_Pool = Pool(0, self.get_start_brdc_mid())
        self.fid_Pool = Pool(0, self.get_start_fid())
        self.uid_Pool = Pool(0, self.get_start_uid())


    
    def init_db(self):
        """
        Initialisert die Datenbank

        @return: None
        """
        self.cursor.execute("CREATE TABLE IF NOT EXISTS users(uid INTEGER, username TEXT, password TEXT, profilepic TEXT)")
        self.cursor.execute("CREATE TABLE IF NOT EXISTS groups(gid INTEGER, member INTEGER, name Text)")
        self.cursor.execute("CREATE TABLE IF NOT EXISTS messages(mid INTEGER, uidsender INTEGER, uidreceiver INTEGER, content TEXT)")
        self.cursor.execute("CREATE TABLE IF NOT EXISTS groupmessages(bid INTEGER, uidsender INTEGER, gidreceiver INTEGER, content TEXT)")
        self.cursor.execute("CREATE TABLE IF NOT EXISTS files(fid INTEGER, localname Text, globalname Text, owner INTEGER)")
        self.cursor.execute("CREATE TABLE IF NOT EXISTS addressbook(uid INTEGER, addid INTEGER)")
        self.db.commit()

        self.cursor.execute("SELECT uid FROM users WHERE uid = 0")
        if self.cursor.fetchone() == None:
            self.cursor.execute("INSERT INTO users VALUES(0, 'initial', 'nohash', 'none')")

        self.cursor.execute("SELECT fid FROM files WHERE fid = 0")
        if self.cursor.fetchone() == None:
            self.cursor.execute("INSERT INTO files VALUES(0, 'initial', 'initial', 0)")

        self.cursor.execute("SELECT mid FROM messages WHERE mid = 0")
        if self.cursor.fetchone() == None:
            self.cursor.execute("INSERT INTO messages VALUES(0, 0, 0, 'initial')")

        self.cursor.execute("SELECT bid FROM groupmessages WHERE bid = 0")
        if self.cursor.fetchone() == None:
            self.cursor.execute("INSERT INTO groupmessages VALUES(0, 0, 0, 'initial')")

        self.cursor.execute("SELECT gid FROM groups WHERE gid = 0")
        if self.cursor.fetchone() == None:
            self.cursor.execute("INSERT INTO groups VALUES(0, 0, 'initial')")

        self.db.commit()

        
    def add_user(self, username, pwhash):
        """
        Fuegt einen Nutzer zur Datenbank hinzu

        @param username: Nutzername
        @type username: str

        @param pwhash: SHA256-Verschluesselter Passwort-Hash
        @type pwhash: str

        @return: None, False wenn Parameter nicht stimmen
        """

        self.cursor.execute("INSERT INTO users VALUES(?, ?, ?)", (self.uid_Pool.give_next(), username, pwhash))
        self.db.commit()


    def check_user(self, username):
        """
        Prueft ob Nutzer bereits vorhanden ist

        @param username: Nutzername
        @type username: str

        @return: Boolean Erfolg
        """

        self.cursor.execute("SELECT * FROM users WHERE username = ?", [username])
        if self.cursor.fetchone() != None:
            return False
        return True


        
    def auth_user(self, username, pwhash):
        """
        Prueft Nutzer-Passwort Kombination

        @param username: Nutzername
        @type username: str

        @param pwhash: SHA256-Verschluesselter Passwort-Hash
        @type pwhash: str

        @return: True, False wenn Parameter nicht stimmen oder Nutzer-Passwort Kombination falsch
        """ 

        self.cursor.execute("SELECT * FROM users WHERE username=? AND password=?", (str(username), str(pwhash)))
        if self.cursor.fetchone() != None:
            return True
        return False



    def get_user_id(self, username):
        """
        Gibt die Nutzer-ID eines Benutzers zurueck

        @param username: Nutzername
        @type username: str

        @return: int Nutzer-ID, False bei unbekanntem Nutzer
        """


        self.cursor.execute("SELECT uid FROM users WHERE username=?", [username])
        result = self.cursor.fetchone()
        if result == None:
            return False
        return int(result[0])



    def get_username_by_id(self, uid):
        """
        Gibt den Nutzernamen nach einer ID zurueck

        @param uid: Nutzer-ID
        @type uid: int

        @return: str - Name
        """

        self.cursor.execute("SELECT username FROM users WHERE uid = ?", [uid])
        result = self.cursor.fetchone()
        if result == None:
            return False
        return result[0]


    def get_group_id(self, name):
        """
        Gibt die Gruppen-ID einer Gruppe zurueck

        @param name: Gruppenname
        @type name: str

        @return: int Gruppen-ID, False bei unbekannter Gruppe
        """

        self.cursor.execute("SELECT gid FROM groups WHERE name=?", [name])
        result = self.cursor.fetchone()
        if result == None:
            return False
        return int(result[0])


    def get_user_by_id(self, id):
        """
        Gibt den Namen des Nutzers anhand der ID zurueck.

        @param id: Nutzer-ID
        @type id: int

        @return: str Name, None falls Name nicht gefunden
        """

        self.cursor.execute("SELECT username FROM users WHERE uid=?", str(id))
        return self.cursor.fetchone()



    def get_group_by_id(self, gid):
        """
        Gibt den Namen einer Gruppe anhand der ID zurueck.

        @param gid: Gruppen-ID
        @type gid: int

        @return: str Name - None falls Name nicht gefunden
        """

        self.cursor.execute("SELECT name FROM groups WHERE gid=?", gid)
        return self.cursor.fetchone()

        
    def rcv_message(self, uidSender, uidReceiver, data):
        """
        Traegt eine Nachricht in die Datenbank ein

        @param uidSender: Nutzer-ID des Senders
        @type uidSender: int

        @param uidReceiver: Nutzer-ID des Empfaengers
        @type uidReceiver: int

        @param data: Nachricht
        @type data: Nachricht

        @return: Boolean Erfolg
        """

        data = data.strip()

        if not isinstance(uidReceiver, list):
            self.cursor.execute("INSERT INTO messages VALUES(?, ?, ?, ?)", (self.mid_Pool.give_next(), uidSender, uidReceiver, data.encode("utf-8", "ignore")))
        else:
            for item in uidReceiver:
                self.cursor.execute("INSERT INTO messages VALUES(?, ?, ?, ?)", (self.mid_Pool.give_next(), uidSender, item, data.encode("utf-8", "ignore")))
        
        self.db.commit()
        return True



    def get_messages_by_last_mid(self, uidReceiver, last_mid):
        """
        Sendet dem Client die neuen Nachrichten.
        Alle Nachrichten sind neu, wenn sie eine groessere MID als die uebergebene hat.

        @param uidReceiver: Empfaenger der Nachrichten
        @type uidReceiver: str

        @param last_mid: Letzte bekannte MID
        @type last_mid: int

        @return Array - [Sender(str), Nachrichten(str)]
        """

        self.cursor.execute("SELECT uidSender, content FROM messages WHERE MID > ?", [last_mid])
        
        ret_value = []
        result = self.cursor.fetchone()
        while result != None:
            ret_value.append(result)
            result = self.cursor.fetchone()

        return ret_value




    def get_messages_by_last_group_id(self, uidReceiver, last_gid):
        """
        Sendet dem Client die neuen Gruppennachrichten.
        Alle Gruppennachrichten sind neu, wenn sie eine groessere GID als die uebergebene hat.

        @param uidReceiver: Empfaenger der Gruppennachrichten
        @type uidReceiver: str

        @param last_gid: Letzte bekannte GID
        @type last_gid: int

        @return Array - [Sender(str), Gruppennachrichten(str)]
        """

        self.cursor.execute("SELECT gidreceiver, uidsender, content FROM groupmessages WHERE bid > ?", last_gid)

        ret_value = []
        result = self.cursor.fetchone()
        while result != None:
            ret_value.append(result)
            result = self.cursor.fetchone()

        return ret_value



    def rcv_brdc_message(self, uidSender, gidReceiver, data):
            """
            Traegt eine Broadcast-Nachricht in die Datenbank ein

            @param uidSender: Nutzer-ID des Senders
            @type uidSender: int

            @param gidReceiver: Gruppen-ID des Empfaengers
            @type gidReceiver: int

            @param data: Nachricht
            @type data: Nachricht

            @return: Boolean Erfolg
            """
            self.cursor.execute("INSERT INTO groupmessages VALUES(?, ?, ?, ?)", (self.bid_Pool.give_next(), uidSender, gidReceiver, data))
            self.db.commit()
            return True



    def add_file(self, local_name):
        """
        Erzeugt einen neuen Dateieintrag

        @param local_name: Name der Datei auf dem Server
        @type local_name: str

        @return: Boolean Erfolg
        """

        self.cursor.execute("INSERT INTO files VALUES(?, ?, ?, ?)", (self.fid_Pool.give_next(), local_name, "", 0))
        self.db.commit()
        return True



    def register_file(self, owner, globalname, filestring):
        """
        Registriert eine Datei (Setzt Besitzer und Dateinamen)

        @param owner: Nutzer-ID des Besitzers
        @type owner: int

        @param globalname: Dateiname der Datei
        @type globalname: str

        @param filestring: Dateistring der Datei
        @type filestring: str

        @return: Boolean Erfolg
        """

        self.cursor.execute("UPDATE files SET owner=?, globalname=? WHERE localname=?", (owner, globalname, filestring))
        self.db.commit()
        return True



    def check_filestring(self, filestring):
        """
        Ueberprueft, ob ein Dateistring existiert

        @param filestring: Dateistring
        @type filestring: str

        @return Boolean Erfolg
        """

        self.cursor.execute("SELECT localname FROM files WHERE localname = ?", [filestring])
        if self.cursor.fetchone() != None:
            return True
        return False



    def get_name_by_filestring(self, name):
        """
        Sucht den Dateinamen anhand des Dateistrings 

        @param name: String der Datei
        @type name: str

        @return: str Dateiname
        """

        self.cursor.execute("SELECT globalname FROM files WHERE localname = ?", [name])
        result = self.cursor.fetchone()

        if result != None:
            try:
                return result[0]
            except IndexError:
                return result
        return False 



    def get_profile_pic(self, uid):
        """
        Gibt den Dateistring zu einem Nutzer zurueck

        @param uid: Nutzer ID
        @type uid: int

        @return: str - Filestring, False falls kein String bekannt
        """

        self.cursor.execute("SELECT profilepic FROM users WHERE uid=?", [uid])
        result = self.cursor.fetchone()
        if result == "None":
            return False
        return result


    
    def get_start_mid(self):
        """
        Gibt die erste freie Nachrichten-ID zurueck

        @return: int ID
        """
        self.cursor.execute("SELECT mid FROM messages ORDER BY mid DESC")
        result = self.cursor.fetchone()
        if result == None:
            return 0
        return (result[0] + 1)



    def get_start_brdc_mid(self):
        """
        Gibt die erste freie Broadcast-Nachrichten-ID zurueck

        @return: int ID
        """
        self.cursor.execute("SELECT bid FROM groupmessages ORDER BY bid DESC")
        result = self.cursor.fetchone()
        if result == None:
            return 0
        return (result[0] + 1)



    def get_start_fid(self):
        """
        Gibt die erste freie Datei-ID

        @return: int ID
        """
        self.cursor.execute("SELECT fid FROM files ORDER BY fid DESC")
        result = self.cursor.fetchone()
        if result == None:
            return 0
        return (result[0] + 1)


    def get_start_uid(self):
        """
        Gibt die erste freie UID zurueck

        @return: int ID
        """
        self.cursor.execute("SELECT uid FROM users ORDER BY uid DESC")
        result = self.cursor.fetchone()
        if result == None:
            return 0
        return (result[0] + 1)  



    def get_address_book(self, uid):
        """
        User-ID des Senders

        @param uid: Nutzer-ID
        @type uid: int

        @return: Array - [int UID, str Name]
        """

        self.cursor.execute("SELECT addid FROM addressbook WHERE uid = ?", [uid])

        ret_value = []
        result = self.cursor.fetchone()
        while result != None:
            ret_value.append((result[0], self.get_username_by_id(int(result[0]))))
            result = self.cursor.fetchone()

        return ret_value