Keyserver - Dateienaustausch und Abruf

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
dankegut
User
Beiträge: 29
Registriert: Montag 16. Oktober 2006, 18:56
Kontaktdaten:

ah.. ja da war was mit den bestimmten datentypen. ich habs jetzt so gelöst.

Code: Alles auswählen

def listAllKeys(self):
        tmp = ''
        for key in keys.itervalues():
            tmp += str([key.algo, key.key, key.hashval, key.name, key.host]) + "\n"
        bintmp = xmlrpclib.Binary(tmp)
        return bintmp
und es klappt, nur so zur info :)
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Hi gerold!

Ich würde das nicht so umständlich machen sondern gleich ein "IF EXIST" einbauen. So wird die Tabelle dann nur erzeugt wenn sie auch existiert.

Code: Alles auswählen

def create_dbstructure(self):
        """
        Erstellt die Tabellen
        """
       
        cur = self.cur
        conn = self.conn
       
        # keys-Tabelle erstellen, falls noch nicht erstellt.
        sql = """
        SELECT name FROM sqlite_master
        WHERE (type = 'table') AND (name = 'keys')
        """
        cur.execute(sql)
        if not self.cur.fetchone():
            # Die Tabelle existiert noch nicht. Sie kann erstellt werden.
            sql = """
            CREATE TABLE keys (
              key TEXT PRIMARY KEY NOT NULL,
              algo TEXT,
              name TEXT,
              hashval TEXT
            )
            """
            cur.execute(sql)
       
        # Index(e) erstellen
        sql = """
        SELECT name FROM sqlite_master
        WHERE (type = 'index') AND (name = 'i_keys_algo')
        """
        cur.execute(sql)
        if not cur.fetchone():
            sql = "CREATE INDEX i_keys_algo ON keys (algo)"
            cur.execute(sql)
       
        conn.commit() 
Hier die geändeerte Version: Funktioniert 100%ig, wiel ich meine Tabellen auch mit "IF EXIST" so erzeuge :)

Code: Alles auswählen

def create_dbstructure(self):
        """
        Erstellt die Tabellen
        """
       
        cur = self.cur
        conn = self.conn
       
        # Erstellt die Tabelle falls sie noch nicht existiert. 
        # Dies wird durch die Abfrage IF EXIST erreicht die glücklicherweise
        # auch in SQLite funktioniert :)
        sql = """
            CREATE TABLE IF NOT EXISTS keys (
                 key TEXT PRIMARY KEY NOT NULL,
                 algo TEXT,
                 name TEXT,
                 hashval TEXT
        )
        """
        cur.execute(sql)
       
        # Index(e) erstellen
        sql = """
        SELECT name FROM sqlite_master
        WHERE (type = 'index') AND (name = 'i_keys_algo')
        """
        cur.execute(sql)
        if not cur.fetchone():
            sql = "CREATE INDEX i_keys_algo ON keys (algo)"
            cur.execute(sql)
       
        conn.commit() 
lg
xtra

P.S.: Das hat neben der kürzeren Schreibweise noch den vorteil das ein Query weniger erzeugt werden muss.

EDIT: Falsche Einrückung von mir korrigiert.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

XtraNine hat geschrieben:Ich würde das nicht so umständlich machen sondern gleich ein "IF EXIST" einbauen.
Hi XtraNine!

Wenn es bei dir funktioniert, dann ist das korrekt. Leider funktioniert es bei vielen noch nicht. Deshalb habe ich es im Beispiel nicht verwendet.

Hier die Begründung: http://gelb.bcom.at/trac/misc/browser/s ... sdb.py#L79

lg
Gerold
:-)

PS: Und jetzt gehe ich wieder ins Bett, meine Grippe ausschlafen. :(
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Und die harten Jungs, erzeugen einfach die Tabelle und fangen den Fehler, wenn diese schon existiert, mit try-except ab 8)

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Hi Gerold :)

Ich danke dir! Das wusste ich nicht :oops: Ich werde in meinen Programm das auch ändern, damit es mit älteren Versionen von SQLite kompatibel ist.
PS: Und jetzt gehe ich wieder ins Bett, meine Grippe ausschlafen.
Wünsch dir eine gute Besserung :)

lg
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

jens hat geschrieben:Und die harten Jungs, erzeugen einfach die Tabelle und fangen den Fehler, wenn diese schon existiert, mit try-except ab 8)
;) Also EAFP oder? Naja, die Idee ist so Simple da hätte ich auch drauf kommen können ;) Ehrliche Meinung? Hmm, Ich benutze "try: except:" zwar auch häufig aber es ist nicht mMn ein besonders guter Stil das permanent zu benutzen. Außerdem sehen 20 "try:, except:" Blöcke einfach nur hässliche aus (wie in meine momentanen Programm das ich ändern werde ^^)

Aber das wäre mal ein Thema für nen neune Thread ^^ -> Wann sollte man "try, except" benutzen und wo man es vermeiden sollte ^^
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ja, in dem Falle ist das so eine Sache. Man kann nicht gut explizit nur den Fehler "Tabelle existiert schon" abfangen. Das ist das Problem...

Letztens hatte ich aber das so gemacht:

Code: Alles auswählen

        try:
            filelist = self.get_filedata()
        except Exception, e:
            if not "doesn't exist" in str(e):
                raise Exception(e)
                self.page_msg.red("Error: %s" % e)
            else:
                self.create_table()
http://pylucid.net/trac/browser/PyLucid ... v=575#L230

Funktioniert aber nur bei MySQL, es sei den SQLite wirft auch einen Fehler mit dem String "doesn't exist"...

Ist aber eh nur eine vorübergehende Lösung :wink:

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Stimmt, das ist mir auch schon aufgefallen das ein und die selber exception für verschiedene Sachen ausgelöst wird, mit unterschiedlicher Fehlermeldung :(

Du könntes mal kucken ob die Exception Klasse ein errno hat, oder so was ähnliches, und das dann mal abfragen. Das müsste unterschiedliche Nummern für verschiedene Fehlermeldungen beinhalten (so wie IOError wenn ich das nicht mit ner anderen exception verwechsele).

Allgemein ist die Überprüfung ob der string in der Meldung vorhanden ist, sehr unsauber. Wenn die diese Meldung bei den nächsten release änder (ok, ist unwahrscheinlich) dann funktioniert diese abfrage nicht mehr.

Aber du sagst ja bereits das es ehe nur vorübergehend ist. von daher i.O.

lg
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mit Nummern hab ich es nicht probiert... Aber das ist IMHO das selbe: Können sich in der nächsten Release ändern und dürften zwischen SQLite und MySQL unterschiedlich sein...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
dankegut
User
Beiträge: 29
Registriert: Montag 16. Oktober 2006, 18:56
Kontaktdaten:

hallo nochmal :)

also ich bin soweit schon gut weiter gekommen dank eurer hilfe. Nun aber wieder n problem.

Wenn das shelve file leer ist, oder sozusagen keine Einträge vorhanden sind, krieg ich bei allen funktionen folgende Fehlermeldung:

Exception in thread Thread-1:
Traceback (most recent call last):
File "threading.py", line 442, in __bootstrap
self.run()
File "client.py", line 59, in run
print server.sendKey(key1)
File "xmlrpclib.py", line 1096, in __call__
return self.__send(self.__name, args)
File "xmlrpclib.py", line 1383, in __request
verbose=self.__verbose
File "xmlrpclib.py", line 1147, in request
return self._parse_response(h.getfile(), sock)
File "xmlrpclib.py", line 1286, in _parse_response
return u.close()
File "xmlrpclib.py", line 744, in close
raise Fault(**self._stack[0])
Fault: <Fault 1: 'exceptions.TypeError:cannot marshal None unless allow_none is enabled'>

Sobald ein Eintrag voreingestellt vorhanden ist, den ich beim Server sozusagen als dummy Eintrag erstelle klappt es, ist dieser jedoch nicht vorhanden und ich möchte über den Client den ersten Eintrag machen möchte, kommt die Fehlermeldung oben. Gibt es eine möglich dies zu umgehen

Hier mal eine Beispielmethode:

Code: Alles auswählen

def receiveKey(self, key):
        # check if key exists
        for k in keys.itervalues():
            if k.key == key: 
                key = keys.get_key(key)
                return key.algo, key.key, key.hashval, key.name, key.host
            else:
                return "Key not found"
Das return statement, "Key not found" greift hier leider irgendwie noch, doch wie soll ich dass den anders abfragen?

Jemand eine Idee?

Gruß
Christian
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Du pastest den falschen Code, wenn ich

Code: Alles auswählen

 File "client.py", line 59, in run
print server.sendKey(key1) 
richtig lese, dann scheinst du an dieser Stelle ein Problem zu haben, so dass None gesendet wird.

Wie lang ist dein Programm? Kannst du es komplett ins LodgeIt pasten?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
dankegut
User
Beiträge: 29
Registriert: Montag 16. Oktober 2006, 18:56
Kontaktdaten:

hallo,

also das war nur eine beispielmethode. es passiert bei JEDER methode die auf das leere shelve zugreifen will. hier aber trotzdem der code

Code: Alles auswählen


def sendKey(self, key_dict):
        # check algorithm type
        if key_dict["algo"] == "RSA":
            # check if name/key already exists
            for key in keys.itervalues():
                if key.name == key_dict["name"]:
                    return "Name already exists"
                else:
                    # save key if it doesn't exist
                    keys.set_rsa_key(key_dict["algo"],key_dict["key"],key_dict["hashval"],key_dict["name"],key_dict["host"])
                    return "successfully saved RSA Key"
        if key_dict["algo"] == "ElGamal":
            for k in keys.itervalues():
                if k.name == key_dict["name"]:
                    return "Name already exists"
                else:
                    keys.set_elgamal_key(key_dict["algo"], key_dict["key1"], key_dict["key2"],
                                    key_dict["key3"], key_dict["hashval"], key_dict["name"], key_dict["host"])
                    return "successfully saved ElGamal Key"
        else:
            return "No valid Key"


vielleicht wer ne idee?
BlackJack

Erstmal zu dem Quelltext: Da ist ein bzw. zwei logische Fehler enthalten. Das setzen des Schlüssels gehört bestimmt nicht in den ``else``-Zweig sondern *hinter* die Schleife, die prüft ob es die Name/Algorithmus-Kombination schon gibt.

Es gibt zweimal den selben Fehler, weil sich der entsprechende Quelltext nahezu identisch wiederholt. Die Unterschiede lassen sich herausziehen. Vom Algorithmusnamen sind die `set_*()`-Methode und die Argumente abhängig, alles andere scheint gleich zu bleiben. Das könnte man so schreiben (ungetestet):

Code: Alles auswählen

    def send_key(self, key_dict):
        algo_map = { 'RSA': (keys.set_rsa_key, ('algo', 'key', 'hashval',
                                                'name', 'host')),
                     'ElGamal': (keys.set_elgamal_key, ('algo', 'key1', 'key2',
                                                        'key3', 'hashval',
                                                        'name', 'host')) }
        algo_name = key_dict['algo']
        if algo_name in algo_map:
            name = key_dict['name']
            for key in keys.itervalues():
                if key.name == name and key.algo == algo_name:
                    return 'Name already exists'
            set_func, attr_names = algo_map[algo_name]
            set_func(*[key_dict[attr_name] for attr_name in attr_names])
            return 'Successfully saved %s key' % algo_name
        else:
            return 'No valid Key'
Ich sehe in diesem Forums-Thread auch ziemlich oft, dass Du mit `itervalues()` über das `Shelve` läufst um etwas zu suchen -- nutzt Du überhaupt irgendwo sinnvoll aus, dass es sich bei einem `Shelve` um ein `Dictionary`-ähnliches Objekt handelt?
dankegut hat geschrieben:vielleicht wer ne idee?
Modul(e) im Interpretierer importieren und die Funktionen alle mal per Hand austesten und/oder Doctests und/oder Unit-Tests schreiben.
dankegut
User
Beiträge: 29
Registriert: Montag 16. Oktober 2006, 18:56
Kontaktdaten:

Hallo,

hmm... danke für deinen Vorschlag. Ich seh ja ein, dass das so halb doppelt gemoppelter Code ist, aber ich bin in python auch noch nicht so fit, dass ich da sowas, wie du es jetzt geschrieben hast eben so aus der Nase saugen und implementieren kann. Ich hab das Problem jetzt zum Glück noch gelöst, durch eine length Abfrage auf das shelve. :)

Gruß
Christian
BlackJack

Hast Du den logischen Fehler auch behoben!? Bei einem leeren `Shelve` wird nämlich nie ein Schlüssel gespeichert, weil die ``for``-Schleifen ja gar nicht ausgeführt werden. Dann wird auch kein explizites ``return`` ausgeführt und damit gibt die Methode `None` zurück. Das wäre wohl das Problem. Ist mir beim letzten Posting gar nicht aufgefallen. :oops:
dankegut
User
Beiträge: 29
Registriert: Montag 16. Oktober 2006, 18:56
Kontaktdaten:

also er gibt folgendes aus:


File "keyserver.py", line 119
set_func, (*[key_dict[attr_name] for attr_name in attr_names])
^
SyntaxError: invalid syntax

Also beim * meckert er.

diese Zeile und die davor verstehe ich leider auch nicht so ganz, da ich mit set_func noch nie gearbeitet habe. Also algo_map stellt ja ein dict dar, oder? Ich bin mir nicht sicher, ob das mit dem

(keys.set_rsa_key, ('algo', 'key', 'hashval',
'name', 'host'))

so richtig ist, wegen dem komma nach set_rsa_key?![/code]
BlackJack

dankegut hat geschrieben:

Code: Alles auswählen

File "keyserver.py", line 119
    set_func, (*[key_dict[attr_name] for attr_name in attr_names])
                   ^
SyntaxError: invalid syntax
Also beim * meckert er.
Ja das darf auch nicht einfach so vor einer List-Comprehension stehen, sondern ist Teil eines Funktionsaufrufes. In der Zeile ist das aber kein Funktionsaufruf, weil Du zwischen den Funtkionsnamen und die Argumente ein Komma gesetzt hast. Nimm das mal weg, dann sollte es gehen.
diese Zeile und die davor verstehe ich leider auch nicht so ganz, da ich mit set_func noch nie gearbeitet habe.
`set_func` ist ein ganz normaler Name, den kannst Du auch durch etwas anderes ersetzen. Die Funktion, an die dieser Name gebunden ist, wird aus dem Dictionary `algo_map` geholt.
Also algo_map stellt ja ein dict dar, oder? Ich bin mir nicht sicher, ob das mit dem

(keys.set_rsa_key, ('algo', 'key', 'hashval',
'name', 'host'))

so richtig ist, wegen dem komma nach set_rsa_key?![/code]
Doch das ist schon richtig. Das ist ein Tupel mit zwei Werten, ein Funktionsobjekt und ein weiteres Tupel mit Zeichenketten. Und in dem Dictionary `algo_map` wird der Name des Algoritmus auf so ein Tupel abgebildet. Du kannst also über den Namen die entsprechende Funktion zum Hinzufügen eines Schlüssels und die Namen der Werte aus dem `key_dict` aus dem Dictionary holen.

Was dann noch gemacht wird, ist das automatische Verteilen einer Sequenz, in diesem Fall das Tupel, auf mehrere Namen, in diesem Fall `set_func` und `attr_names`.

Und die *-Notation beim Aufruf "entpackt" auch eine Sequenz. Das Tupel ist ja *ein* Objekt bzw. das Ergebnis der List-Comprehension ist *eine* Liste, die Funktion erwartet aber die Elemente dieser Liste als einzelne Argumente. Das erreicht man mit der *-Notation.

Vielleicht hilft folgende Live-Session ein wenig beim Verständnis:

Code: Alles auswählen

In [14]: max(1, 5, 4)
Out[14]: 5

In [15]: a = (max, (1, 5, 4))

In [16]: a[0]
Out[16]: <built-in function max>

In [17]: a[1]
Out[17]: (1, 5, 4)

In [18]: b = { 'maximum':  (max, (1, 5, 4)) }

In [19]: b
Out[19]: {'maximum': (<built-in function max>, (1, 5, 4))}

In [20]: b['maximum']
Out[20]: (<built-in function max>, (1, 5, 4))

In [21]: func, values = b['maximum']

In [22]: func
Out[22]: <built-in function max>

In [23]: values
Out[23]: (1, 5, 4)

In [24]: func(*values)
Out[24]: 5
dankegut
User
Beiträge: 29
Registriert: Montag 16. Oktober 2006, 18:56
Kontaktdaten:

hallo,

so, nach längerer winterpause meld ich mich mal wieder :roll: erstmal danke blackjack, ich habs verstanden :)

jetzt möchte ich gerne, das ganze in was grafisches umsetzen, also den client. Problem was sich mir stellt ist die Vererbung.

Code: Alles auswählen

import wx       
                
class clientGUI(wx.Panel):  
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)                                
        
        self.search = wx.StaticBitmap(self, -1, wx.Bitmap("images/keysearch.gif", wx.BITMAP_TYPE_ANY))
        #self.upload = wx.StaticBitmap(self, -1, wx.Bitmap("images/uploadkey.gif", wx.BITMAP_TYPE_ANY))                                        
        #self.delete = wx.StaticBitmap(self, -1, wx.Bitmap("images/deletekey.gif", wx.BITMAP_TYPE_ANY))
        
        self.searchTxt = wx.TextCtrl(self, -1, "")                     
        self.searchB = wx.Button(self, -1, "search")                   
        
        self.Bind(wx.EVT_BUTTON, self.searchKey, self.searchB)         
        
        self.__set_properties()
        self.__do_layout()
        
    def __set_properties(self):                                        
        # begin wxGlade: MyFrame.__set_properties                      
        self.SetTitle("frame_1")                                       
        self.search.SetMinSize((100,100))                              
    def __do_layout(self):                                             
        # begin wxGlade: MyFrame.__do_layout                           
        
        sizer_1 = wx.BoxSizer(wx.VERTICAL)                             
        sizer_2 = wx.BoxSizer(wx.VERTICAL)                             
        grid_sizer_1 = wx.GridSizer(1, 3, 0, 0)                        
        gs_KeyS = wx.GridSizer(1,2,0,0)                                
        # adjust search key
        grid_sizer_1.Add(self.search, 0, wx.ADJUST_MINSIZE, 0)         
        grid_sizer_1.Add(gs_KeyS, 1, wx.EXPAND, 0)                     
        grid_sizer_1.Add(self.searchTxt, 0, wx.ADJUST_MINSIZE, 0)      
        grid_sizer_1.Add(self.searchB, 0, wx.ADJUST_MINSIZE, 0)        
        sizer_2.Add(grid_sizer_1, 1, wx.EXPAND, 0)                     
        sizer_1.Add(sizer_2, 1, wx.EXPAND, 0)                          
        self.SetAutoLayout(True)
        self.SetSizer(sizer_1)                                         
        sizer_1.Fit(self)                                              
        sizer_1.SetSizeHints(self)                                     
        self.Layout() 

    def searchKey(self, event):                                        
        x = self.searchTxt.GetValue()                                  
        print x
    def uploadKey():                                                   
        pass
    def deleteKey():
        pass                                                           
if __name__ == "__main__":             
    app = wx.PySimpleApp(0)
    frame = wx.Frame(None, -1, "Client",
                               size=(380, 380))
    clientGUI(frame)
    frame.Show(True)
    app.MainLoop()

das ganze ist erstmal nur ein kleine testumgebung, um etwas grafisch am server abzufragen. ich mochte jetzt gerne in der searchKey Methode einen Key beim server suchen, doch, ausserhalb der run Methode im Client, wo praktisch steht wo der Server zu erreichen ist, kann ich den nicht mehr ansprechen, wie mache ich es mögliche, dass ein

Code: Alles auswählen

class Client(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        server = xmlrpclib.Server("http://192.168.0.1:8000")
und die "Variable" server auch in anderen Methoden sichtbar ist?! Da steh ich mal wieder aufm Schlauch.

Jemand vielleicht nen kleinen Tipp? :)

Frohes Neues

Christian

**EDIT**

hat sich schon erledigt :)
Antworten