diff --git a/doc/aclmanager.html b/doc/aclmanager.html index 64d04c9..b765e24 100644 --- a/doc/aclmanager.html +++ b/doc/aclmanager.html @@ -18,9 +18,6 @@ Classes AclManager Hauptfenster des ACL-Managers. - -IpAclManager -Verwaltung fuer IP Adressen und deren ACL Level.

@@ -66,9 +63,15 @@ Methods

_changesdone Prüft ob sich die Einstellungen geändert haben. +_checkback +Springt bei Backspace in vorheriges Feld. + _checkclose Prüft ob Fenster beendet werden soll. +_checkdot +Prüft auf . + _clearfields Leert die Eingabefelder. @@ -149,6 +152,23 @@ Prüft ob sich die Einstellungen geändert haben.
True, wenn min. eine Einstellung geändert wurde
+ +

+AclManager._checkback

+_checkback(event, tkvar, pretxt) +

+Springt bei Backspace in vorheriges Feld. +

+
event
+
+TK Event +
tkvar
+
+TK Variable zum prüfen +
nexttxt
+
+Vorheriges IP Feld für Fokus +

AclManager._checkclose

@@ -160,6 +180,23 @@ Prüft ob Fenster beendet werden soll.
tkinter-Event
+ +

+AclManager._checkdot

+_checkdot(event, tkvar, nexttxt) +

+Prüft auf . und geht weiter. +

+
event
+
+TK Event +
tkvar
+
+TK Variable zum prüfen +
nexttxt
+
+Nächstes IP Feld für Fokus +

AclManager._clearfields

@@ -215,137 +252,5 @@ ACL als
Up
-

- -

IpAclManager

-

-Verwaltung fuer IP Adressen und deren ACL Level. -

-

-Derived from

-None -

-Class Attributes

- - -
acl
regex_acl
-

-Class Methods

- - -
None
-

-Methods

- - - - - - - - - - - - - - - - - - - - - - - -
IpAclManagerInit IpAclManager class.
__get_aclGetter fuer den rohen ACL-String.
__get_regex_aclGibt formatierten RegEx-String zurueck.
__iter__Gibt einzelne ACLs als aus.
__set_aclUebernimmt neue ACL-Liste fuer die Ausertung der Level.
get_acllevelPrueft IP gegen ACL List und gibt ACL-Wert aus.
loadaclLaed ACL String und gibt erfolg zurueck.
-

-Static Methods

- - -
None
- -

-IpAclManager (Constructor)

-IpAclManager(minlevel, maxlevel, acl=None) -

-Init IpAclManager class. -

-
minlevel
-
-Smallest access level (min. 0) -
maxlevel
-
-Biggest access level (max. 9) -
acl
-
-ACL Liste fuer Berechtigungen als -
-
-

-IpAclManager.__get_acl

-__get_acl() -

-Getter fuer den rohen ACL-String. - return ACLs als -

-

-IpAclManager.__get_regex_acl

-__get_regex_acl() -

-Gibt formatierten RegEx-String zurueck. - return RegEx Code als -

-

-IpAclManager.__iter__

-__iter__() -

-Gibt einzelne ACLs als aus. -

-

-IpAclManager.__set_acl

-__set_acl(value) -

-Uebernimmt neue ACL-Liste fuer die Ausertung der Level. -

-
value
-
-Neue ACL-Liste als -
-
-

-IpAclManager.get_acllevel

-get_acllevel(ipaddress) -

-Prueft IP gegen ACL List und gibt ACL-Wert aus. -

-
ipaddress
-
-zum pruefen -
-
-
Returns:
-
- ACL Wert oder -1 wenn nicht gefunden -
-
-

-IpAclManager.loadacl

-loadacl(str_acl) -

-Laed ACL String und gibt erfolg zurueck. -

-
str_acl
-
-ACL als -
-
-
Returns:
-
-True, wenn erfolgreich uebernommen -
-
-
Up

\ No newline at end of file diff --git a/doc/index-revpipycontrol.shared.html b/doc/index-revpipycontrol.shared.html new file mode 100644 index 0000000..00f7dd6 --- /dev/null +++ b/doc/index-revpipycontrol.shared.html @@ -0,0 +1,20 @@ + + +revpipycontrol.shared + + + +

+revpipycontrol.shared

+ + + +

+Modules

+ + + + + +
ipaclmanagerVerwaltet IP Adressen und deren ACLs.
+ \ No newline at end of file diff --git a/doc/index.html b/doc/index.html index aa29915..1a15819 100644 --- a/doc/index.html +++ b/doc/index.html @@ -8,6 +8,14 @@ Table of contents +

+Packages

+ + + + + +
shared

Modules

diff --git a/doc/revpipycontrol.shared.ipaclmanager.html b/doc/revpipycontrol.shared.ipaclmanager.html new file mode 100644 index 0000000..2c5cb69 --- /dev/null +++ b/doc/revpipycontrol.shared.ipaclmanager.html @@ -0,0 +1,239 @@ + + +revpipycontrol.shared.ipaclmanager + + + +

+revpipycontrol.shared.ipaclmanager

+

+Verwaltet IP Adressen und deren ACLs. +

+

+Global Attributes

+ + +
None
+

+Classes

+ + + + + +
IpAclManagerVerwaltung fuer IP Adressen und deren ACL Level.
+

+Functions

+ + + + + +
refullmatchre.fullmatch wegen alter python version aus wheezy nachgebaut.
+

+ +

IpAclManager

+

+Verwaltung fuer IP Adressen und deren ACL Level. +

+

+Derived from

+None +

+Class Attributes

+ + +
acl
filename
regex_acl
+

+Class Methods

+ + +
None
+

+Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IpAclManagerInit IpAclManager class.
__get_aclGetter fuer den rohen ACL-String.
__get_filenameGetter fuer Dateinamen.
__get_regex_aclGibt formatierten RegEx-String zurueck.
__iter__Gibt einzelne ACLs als aus.
__set_aclUebernimmt neue ACL-Liste fuer die Ausertung der Level.
get_acllevelPrueft IP gegen ACL List und gibt ACL-Wert aus.
loadaclLaed ACL String und gibt erfolg zurueck.
loadaclfileLaed ACL Definitionen aus Datei.
writeaclfileSchreibt ACL Definitionen in Datei.
+

+Static Methods

+ + +
None
+ +

+IpAclManager (Constructor)

+IpAclManager(minlevel, maxlevel, acl=None) +

+Init IpAclManager class. +

+
minlevel
+
+Smallest access level (min. 0) +
maxlevel
+
+Biggest access level (max. 9) +
acl
+
+ACL Liste fuer Berechtigungen als +
+
+

+IpAclManager.__get_acl

+__get_acl() +

+Getter fuer den rohen ACL-String. + return ACLs als +

+

+IpAclManager.__get_filename

+__get_filename() +

+Getter fuer Dateinamen. +

+
Returns:
+
+Filename der ACL +
+
+

+IpAclManager.__get_regex_acl

+__get_regex_acl() +

+Gibt formatierten RegEx-String zurueck. + return RegEx Code als +

+

+IpAclManager.__iter__

+__iter__() +

+Gibt einzelne ACLs als aus. +

+

+IpAclManager.__set_acl

+__set_acl(value) +

+Uebernimmt neue ACL-Liste fuer die Ausertung der Level. +

+
value
+
+Neue ACL-Liste als +
+
+

+IpAclManager.get_acllevel

+get_acllevel(ipaddress) +

+Prueft IP gegen ACL List und gibt ACL-Wert aus. +

+
ipaddress
+
+zum pruefen +
+
+
Returns:
+
+ ACL Wert oder -1 wenn nicht gefunden +
+
+

+IpAclManager.loadacl

+loadacl(str_acl) +

+Laed ACL String und gibt erfolg zurueck. +

+
str_acl
+
+ACL als +
+
+
Returns:
+
+True, wenn erfolgreich uebernommen +
+
+

+IpAclManager.loadaclfile

+loadaclfile(filename) +

+Laed ACL Definitionen aus Datei. +

+
filename
+
+Dateiname fuer Definitionen +
+
+
Returns:
+
+True, wenn Laden erfolgreich war +
+
+

+IpAclManager.writeaclfile

+writeaclfile(filename=None, aclname=None) +

+Schreibt ACL Definitionen in Datei. +

+
filename
+
+Dateiname fuer Definitionen +
+
+
Returns:
+
+True, wenn Schreiben erfolgreich war +
+
+
Up
+

+ +

refullmatch

+refullmatch(regex, string) +

+re.fullmatch wegen alter python version aus wheezy nachgebaut. +

+
regex
+
+RegEx Statement +
string
+
+Zeichenfolge gegen die getestet wird +
+
+
Returns:
+
+True, wenn komplett passt sonst False +
+
+
Up
+
+ \ No newline at end of file diff --git a/revpipycontrol.api b/revpipycontrol.api index 4ce4859..4822d28 100644 --- a/revpipycontrol.api +++ b/revpipycontrol.api @@ -2,7 +2,9 @@ aclmanager.AclManager.__get_acltext?6() aclmanager.AclManager.__set_acltext?6(value) aclmanager.AclManager._ask_delete?5() aclmanager.AclManager._changesdone?5() +aclmanager.AclManager._checkback?5(event, tkvar, pretxt) aclmanager.AclManager._checkclose?5(event=None) +aclmanager.AclManager._checkdot?5(event, tkvar, nexttxt) aclmanager.AclManager._clearfields?5() aclmanager.AclManager._createwidgets?5() aclmanager.AclManager._loadfields?5() @@ -15,15 +17,6 @@ aclmanager.AclManager.acltext?7 aclmanager.AclManager.get_acl?4() aclmanager.AclManager.root?7 aclmanager.AclManager?1(master, minlevel, maxlevel, acl_str="", readonly=False) -aclmanager.IpAclManager.__get_acl?6() -aclmanager.IpAclManager.__get_regex_acl?6() -aclmanager.IpAclManager.__iter__?6() -aclmanager.IpAclManager.__set_acl?6(value) -aclmanager.IpAclManager.acl?7 -aclmanager.IpAclManager.get_acllevel?4(ipaddress) -aclmanager.IpAclManager.loadacl?4(str_acl) -aclmanager.IpAclManager.regex_acl?7 -aclmanager.IpAclManager?1(minlevel, maxlevel, acl=None) aclmanager._?8 mytools.addroot?4(filename) mytools.gettrans?4(proglang=None) @@ -141,3 +134,17 @@ revpipycontrol.RevPiPyControl.visitwebsite?4() revpipycontrol.RevPiPyControl?1(master=None) revpipycontrol._?8 revpipycontrol.pycontrolversion?7 +revpipycontrol.shared.ipaclmanager.IpAclManager.__get_acl?6() +revpipycontrol.shared.ipaclmanager.IpAclManager.__get_filename?6() +revpipycontrol.shared.ipaclmanager.IpAclManager.__get_regex_acl?6() +revpipycontrol.shared.ipaclmanager.IpAclManager.__iter__?6() +revpipycontrol.shared.ipaclmanager.IpAclManager.__set_acl?6(value) +revpipycontrol.shared.ipaclmanager.IpAclManager.acl?7 +revpipycontrol.shared.ipaclmanager.IpAclManager.filename?7 +revpipycontrol.shared.ipaclmanager.IpAclManager.get_acllevel?4(ipaddress) +revpipycontrol.shared.ipaclmanager.IpAclManager.loadacl?4(str_acl) +revpipycontrol.shared.ipaclmanager.IpAclManager.loadaclfile?4(filename) +revpipycontrol.shared.ipaclmanager.IpAclManager.regex_acl?7 +revpipycontrol.shared.ipaclmanager.IpAclManager.writeaclfile?4(filename=None, aclname=None) +revpipycontrol.shared.ipaclmanager.IpAclManager?1(minlevel, maxlevel, acl=None) +revpipycontrol.shared.ipaclmanager.refullmatch?4(regex, string) diff --git a/revpipycontrol.e4p b/revpipycontrol.e4p index fa98f89..11cb786 100644 --- a/revpipycontrol.e4p +++ b/revpipycontrol.e4p @@ -1,7 +1,7 @@ - + en_US @@ -25,6 +25,8 @@ revpipycontrol/revpiinfo.py revpipycontrol/aclmanager.py revpipycontrol/revpilegacy.py + revpipycontrol/shared/ipaclmanager.py + revpipycontrol/shared/__init__.py diff --git a/revpipycontrol/aclmanager.py b/revpipycontrol/aclmanager.py index d773182..72e19b2 100644 --- a/revpipycontrol/aclmanager.py +++ b/revpipycontrol/aclmanager.py @@ -9,117 +9,13 @@ u"""Manager für ACL Einträge.""" import tkinter import tkinter.messagebox as tkmsg from mytools import gettrans -from re import fullmatch +from shared.ipaclmanager import IpAclManager from tkinter import ttk # Übersetzung laden _ = gettrans() -class IpAclManager(): - - """Verwaltung fuer IP Adressen und deren ACL Level.""" - - def __init__(self, minlevel, maxlevel, acl=None): - """Init IpAclManager class. - - @param minlevel Smallest access level (min. 0) - @param maxlevel Biggest access level (max. 9) - @param acl ACL Liste fuer Berechtigungen als - - """ - if type(minlevel) != int: - raise ValueError("parameter minlevel must be ") - if type(maxlevel) != int: - raise ValueError("parameter maxlevel must be ") - if minlevel < 0: - raise ValueError("minlevel must be 0 or more") - if maxlevel > 9: - raise ValueError("maxlevel maximum is 9") - if minlevel > maxlevel: - raise ValueError("minlevel is smaller than maxlevel") - - self.__dict_acl = {} - self.__dict_regex = {} - self.__dict_knownips = {} - self.__re_ipacl = "(([\\d\\*]{1,3}\\.){3}[\\d\\*]{1,3},[" \ - + str(minlevel) + "-" + str(maxlevel) + "] ?)*" - - # Liste erstellen, wenn übergeben - if acl is not None: - self.__set_acl(acl) - - def __iter__(self): - """Gibt einzelne ACLs als aus.""" - for aclip in sorted(self.__dict_acl): - yield (aclip, self.__dict_acl[aclip]) - - def __get_acl(self): - """Getter fuer den rohen ACL-String. - return ACLs als """ - str_acl = "" - for aclip in sorted(self.__dict_acl): - str_acl += "{},{} ".format(aclip, self.__dict_acl[aclip]) - return str_acl.strip() - - def __get_regex_acl(self): - """Gibt formatierten RegEx-String zurueck. - return RegEx Code als """ - return self.__re_ipacl - - def __set_acl(self, value): - """Uebernimmt neue ACL-Liste fuer die Ausertung der Level. - @param value Neue ACL-Liste als """ - if type(value) != str: - raise ValueError("parameter acl must be ") - - value = value.strip() - if fullmatch(self.__re_ipacl, value) is None: - raise ValueError("acl format ist not okay - 1.2.3.4,0 5.6.7.8,1") - - # Klassenwerte übernehmen - self.__dict_acl = {} - self.__dict_regex = {} - self.__dict_knownips = {} - - # Liste neu füllen mit regex Strings - for ip_level in value.split(): - ip, level = ip_level.split(",", 1) - self.__dict_acl[ip] = int(level) - self.__dict_regex[ip] = \ - ip.replace(".", "\\.").replace("*", "\\d{1,3}") - - def get_acllevel(self, ipaddress): - """Prueft IP gegen ACL List und gibt ACL-Wert aus. - @param ipaddress zum pruefen - @return ACL Wert oder -1 wenn nicht gefunden""" - # Bei bereits aufgelösten IPs direkt ACL auswerten - if ipaddress in self.__dict_knownips: - return self.__dict_knownips[ipaddress] - - for aclip in sorted(self.__dict_acl, reverse=True): - if fullmatch(self.__dict_regex[aclip], ipaddress) is not None: - # IP und Level merken - self.__dict_knownips[ipaddress] = self.__dict_acl[aclip] - - # Level zurückgeben - return self.__dict_acl[aclip] - - return -1 - - def loadacl(self, str_acl): - """Laed ACL String und gibt erfolg zurueck. - @param str_acl ACL als - @return True, wenn erfolgreich uebernommen""" - if fullmatch(self.__re_ipacl, str_acl) is None: - return False - self.__set_acl(str_acl) - return True - - acl = property(__get_acl, __set_acl) - regex_acl = property(__get_regex_acl) - - class AclManager(ttk.Frame): u"""Hauptfenster des ACL-Managers.""" @@ -258,22 +154,68 @@ class AclManager(ttk.Frame): self.var_ip4 = tkinter.StringVar(frame) self.var_acl = tkinter.StringVar(frame, self.minlevel) - ip_block = ttk.Entry(frame, width=4) - ip_block["state"] = self.__ro - ip_block["textvariable"] = self.var_ip1 - ip_block.grid(row=row, column=1) - ip_block = ttk.Entry(frame, width=4) - ip_block["state"] = self.__ro - ip_block["textvariable"] = self.var_ip2 - ip_block.grid(row=row, column=3) - ip_block = ttk.Entry(frame, width=4) - ip_block["state"] = self.__ro - ip_block["textvariable"] = self.var_ip3 - ip_block.grid(row=row, column=5) - ip_block = ttk.Entry(frame, width=4) - ip_block["state"] = self.__ro - ip_block["textvariable"] = self.var_ip4 - ip_block.grid(row=row, column=7) + ip_block1 = ttk.Entry(frame, width=4) + ip_block2 = ttk.Entry(frame, width=4) + ip_block3 = ttk.Entry(frame, width=4) + ip_block4 = ttk.Entry(frame, width=4) + + ip_block1.bind( + "", + lambda event, tkvar=self.var_ip1: self._checkdot( + event, tkvar, ip_block2 + ) + ) + ip_block1["state"] = self.__ro + ip_block1["textvariable"] = self.var_ip1 + ip_block1.grid(row=row, column=1) + + ip_block2.bind( + "", + lambda event, tkvar=self.var_ip2: self._checkdot( + event, tkvar, ip_block3 + ) + ) + ip_block2.bind( + "", + lambda event, tkvar=self.var_ip2: self._checkback( + event, tkvar, ip_block1 + ) + ) + ip_block2["state"] = self.__ro + ip_block2["textvariable"] = self.var_ip2 + ip_block2.grid(row=row, column=3) + + ip_block3.bind( + "", + lambda event, tkvar=self.var_ip3: self._checkdot( + event, tkvar, ip_block4 + ) + ) + ip_block3.bind( + "", + lambda event, tkvar=self.var_ip3: self._checkback( + event, tkvar, ip_block2 + ) + ) + ip_block3["state"] = self.__ro + ip_block3["textvariable"] = self.var_ip3 + ip_block3.grid(row=row, column=5) + + ip_block4.bind( + "", + lambda event, tkvar=self.var_ip4: self._checkdot( + event, tkvar, None + ) + ) + ip_block4.bind( + "", + lambda event, tkvar=self.var_ip4: self._checkback( + event, tkvar, ip_block3 + ) + ) + ip_block4["state"] = self.__ro + ip_block4["textvariable"] = self.var_ip4 + ip_block4.grid(row=row, column=7) # Punkte zwischen IP-Feldern for i in range(2, 7, 2): @@ -338,12 +280,44 @@ class AclManager(ttk.Frame): parent=self.master, default="no" ) if ask: - self.__acl.loadacl( - self.__acl.acl.replace( - "{},{}".format(*lst_ipacl), "" - ).replace(" ", " ") - ) - self._refreshacls() + new_acl = self.__acl.acl.replace( + "{},{}".format(*lst_ipacl), "" + ).replace(" ", " ") + + if self.__acl.loadacl(new_acl.strip()): + # Liste neu aufbauen + self._refreshacls() + else: + tkmsg.showerror( + _("Error"), + _("Can not delete ACL! Check format."), + parent=self.master + ) + + def _checkback(self, event, tkvar, pretxt): + u"""Springt bei Backspace in vorheriges Feld. + + @param event TK Event + @param tkvar TK Variable zum prüfen + @param nexttxt Vorheriges IP Feld für Fokus + + """ + if pretxt is not None and event.keycode == 22 and tkvar.get() == "": + pretxt.focus_set() + + def _checkdot(self, event, tkvar, nexttxt): + u"""Prüft auf . und geht weiter. + + @param event TK Event + @param tkvar TK Variable zum prüfen + @param nexttxt Nächstes IP Feld für Fokus + + """ + val = tkvar.get() + if val.find(".") >= 0: + tkvar.set(val[:-1]) + if nexttxt is not None: + nexttxt.focus_set() def _clearfields(self): u"""Leert die Eingabefelder.""" @@ -387,7 +361,7 @@ class AclManager(ttk.Frame): self.var_ip4.get(), self.var_acl.get() ) - if self.__acl.loadacl(self.__acl.acl + " " + new_acl): + if self.__acl.loadacl((self.__acl.acl + " " + new_acl).strip()): self._refreshacls() else: tkmsg.showerror( diff --git a/revpipycontrol/revpicheckclient.py b/revpipycontrol/revpicheckclient.py index 303ad18..f75b103 100644 --- a/revpipycontrol/revpicheckclient.py +++ b/revpipycontrol/revpicheckclient.py @@ -205,7 +205,7 @@ class RevPiCheckClient(tkinter.Frame): def _createwidgets(self): """Erstellt den Fensterinhalt.""" - cFxPxy53 = {"fill": "x", "padx": 5, "pady": 3} + cfxpxy53 = {"fill": "x", "padx": 5, "pady": 3} devgrp = tkinter.LabelFrame(self) devgrp["text"] = _("Devices of RevPi") @@ -236,7 +236,7 @@ class RevPiCheckClient(tkinter.Frame): btn = tkinter.Button(devgrp) btn["command"] = lambda win=win: self.__showwin(win) btn["text"] = "{} | {}".format(dev, self.dict_devices[dev]) - btn.pack(**cFxPxy53) + btn.pack(**cfxpxy53) # Steuerungsfunktionen cntgrp = tkinter.LabelFrame(self) @@ -246,19 +246,19 @@ class RevPiCheckClient(tkinter.Frame): self.btn_refresh = tkinter.Button(cntgrp) self.btn_refresh["text"] = _("Read all IOs") self.btn_refresh["command"] = self.refreshvalues - self.btn_refresh.pack(**cFxPxy53) + self.btn_refresh.pack(**cfxpxy53) self.btn_read = tkinter.Button(cntgrp) self.btn_read["text"] = _("Read just Inputs") self.btn_read["command"] = self.readvalues - self.btn_read.pack(**cFxPxy53) + self.btn_read.pack(**cfxpxy53) self.btn_write = tkinter.Button(cntgrp) self.btn_write["state"] = "normal" if self.xmlmode >= 3 \ else "disabled" self.btn_write["text"] = _("Write Outputs") self.btn_write["command"] = self.writevalues - self.btn_write.pack(**cFxPxy53) + self.btn_write.pack(**cfxpxy53) self.chk_auto = tkinter.Checkbutton(cntgrp) self.chk_auto["command"] = self.toggleauto diff --git a/revpipycontrol/revpioption.py b/revpipycontrol/revpioption.py index cb772e4..4d78532 100644 --- a/revpipycontrol/revpioption.py +++ b/revpipycontrol/revpioption.py @@ -293,14 +293,22 @@ class RevPiOption(tkinter.Frame): if not self._checkvalues(): return None - ask = tkmsg.askyesnocancel( +# ask = tkmsg.askyesnocancel( +# _("Question"), +# _("The settings are now saved on the Revolution Pi. \n\n" +# "Should the new settings take effect immediately? \nThis " +# "means a restart of the service and the PLC program!"), +# parent=self.master +# ) + ask = tkmsg.askokcancel( _("Question"), - _("The settings are now saved on the Revolution Pi. \n\n" - "Should the new settings take effect immediately? \nThis " - "means a restart of the service and the PLC program!"), + _("The settings will be set on the Revolution Pi now. \n\n" + "If you made changes on the 'PCL Program' section, your plc " + "program will restart! \n" + "ACL changes and service settings are applied immediately."), parent=self.master ) - if ask is not None: + if ask: self.dc["autoreload"] = int(self.var_reload.get()) self.dc["autoreloaddelay"] = int(self.var_reload_delay.get()) self.dc["autostart"] = int(self.var_start.get()) diff --git a/revpipycontrol/revpiprogram.py b/revpipycontrol/revpiprogram.py index d15ae4b..899fadf 100644 --- a/revpipycontrol/revpiprogram.py +++ b/revpipycontrol/revpiprogram.py @@ -51,8 +51,7 @@ class RevPiProgram(tkinter.Frame): self.uploaded = False self.revpi = revpi self.xmlcli = xmlcli - self.xmlmode = xmlmode - self.xmlstate = "normal" if xmlmode == 3 else "disabled" + self.xmlstate = "normal" if xmlmode >= 3 else "disabled" # Letzte Einstellungen übernehmen self.opt = self._loaddefault() diff --git a/revpipycontrol/revpipycontrol.py b/revpipycontrol/revpipycontrol.py index e20eb7b..cc6cea3 100755 --- a/revpipycontrol/revpipycontrol.py +++ b/revpipycontrol/revpipycontrol.py @@ -326,7 +326,6 @@ class RevPiPyControl(tkinter.Frame): win.grab_set() # Gegenstelle prüfen und passende Optionen laden - print(self.revpipyversion) if self.revpipyversion[0] == 0 and self.revpipyversion[1] < 6: self.tkoptions = \ revpilegacy.RevPiOption(win, self.cli) @@ -338,7 +337,7 @@ class RevPiPyControl(tkinter.Frame): if self.tkoptions.dc is not None and self.tkoptions.dorestart: # Wenn XML-Modus anders und Dienstneustart - if self.xmlmode != self.tkoptions.dc["xmlrpc"]: + if self.xmlmode != self.cli.xmlmodus(): self.serverdisconnect() self._opt_conn(self.revpiname, True) diff --git a/revpipycontrol/shared/__init__.py b/revpipycontrol/shared/__init__.py new file mode 100644 index 0000000..d059206 --- /dev/null +++ b/revpipycontrol/shared/__init__.py @@ -0,0 +1 @@ +"""Shared modules.""" diff --git a/revpipycontrol/shared/ipaclmanager.py b/revpipycontrol/shared/ipaclmanager.py new file mode 100644 index 0000000..5bf9aea --- /dev/null +++ b/revpipycontrol/shared/ipaclmanager.py @@ -0,0 +1,189 @@ +# -*- coding: utf-8 -*- +# +# IpAclManager +# +# (c) Sven Sager, License: LGPLv3 +# Version 0.1.0 +# +"""Verwaltet IP Adressen und deren ACLs.""" +from os import access, R_OK, W_OK +from re import match as rematch + + +def refullmatch(regex, string): + """re.fullmatch wegen alter python version aus wheezy nachgebaut. + + @param regex RegEx Statement + @param string Zeichenfolge gegen die getestet wird + @return True, wenn komplett passt sonst False + + """ + m = rematch(regex, string) + return m is not None and m.end() == len(string) + + +class IpAclManager(): + + """Verwaltung fuer IP Adressen und deren ACL Level.""" + + def __init__(self, minlevel, maxlevel, acl=None): + """Init IpAclManager class. + + @param minlevel Smallest access level (min. 0) + @param maxlevel Biggest access level (max. 9) + @param acl ACL Liste fuer Berechtigungen als + + """ + if type(minlevel) != int: + raise ValueError("parameter minlevel must be ") + if type(maxlevel) != int: + raise ValueError("parameter maxlevel must be ") + if minlevel < 0: + raise ValueError("minlevel must be 0 or more") + if maxlevel > 9: + raise ValueError("maxlevel maximum is 9") + if minlevel > maxlevel: + raise ValueError("minlevel is smaller than maxlevel") + + self.__dict_acl = {} + self.__dict_regex = {} + self.__dict_knownips = {} + self.__filename = None + self.__re_ipacl = "(([\\d\\*]{1,3}\\.){3}[\\d\\*]{1,3},[" \ + + str(minlevel) + "-" + str(maxlevel) + "] ?)*" + + # Liste erstellen, wenn übergeben + if acl is not None: + self.__set_acl(acl) + + def __iter__(self): + """Gibt einzelne ACLs als aus.""" + for aclip in sorted(self.__dict_acl): + yield (aclip, self.__dict_acl[aclip]) + + def __get_acl(self): + """Getter fuer den rohen ACL-String. + return ACLs als """ + str_acl = "" + for aclip in sorted(self.__dict_acl): + str_acl += "{},{} ".format(aclip, self.__dict_acl[aclip]) + return str_acl.strip() + + def __get_filename(self): + """Getter fuer Dateinamen. + @return Filename der ACL """ + return "" if self.__filename is None else self.__filename + + def __get_regex_acl(self): + """Gibt formatierten RegEx-String zurueck. + return RegEx Code als """ + return self.__re_ipacl + + def __set_acl(self, value): + """Uebernimmt neue ACL-Liste fuer die Ausertung der Level. + @param value Neue ACL-Liste als """ + if type(value) != str: + raise ValueError("parameter acl must be ") + + value = value.strip() + if not refullmatch(self.__re_ipacl, value): + raise ValueError("acl format ist not okay - 1.2.3.4,0 5.6.7.8,1") + + # Klassenwerte übernehmen + self.__dict_acl = {} + self.__dict_regex = {} + self.__dict_knownips = {} + + # Liste neu füllen mit regex Strings + for ip_level in value.split(): + ip, level = ip_level.split(",", 1) + self.__dict_acl[ip] = int(level) + self.__dict_regex[ip] = \ + ip.replace(".", "\\.").replace("*", "\\d{1,3}") + + def get_acllevel(self, ipaddress): + """Prueft IP gegen ACL List und gibt ACL-Wert aus. + @param ipaddress zum pruefen + @return ACL Wert oder -1 wenn nicht gefunden""" + # Bei bereits aufgelösten IPs direkt ACL auswerten + if ipaddress in self.__dict_knownips: + return self.__dict_knownips[ipaddress] + + for aclip in sorted(self.__dict_acl, reverse=True): + if refullmatch(self.__dict_regex[aclip], ipaddress): + # IP und Level merken + self.__dict_knownips[ipaddress] = self.__dict_acl[aclip] + + # Level zurückgeben + return self.__dict_acl[aclip] + + return -1 + + def loadacl(self, str_acl): + """Laed ACL String und gibt erfolg zurueck. + @param str_acl ACL als + @return True, wenn erfolgreich uebernommen""" + if not refullmatch(self.__re_ipacl, str_acl): + return False + self.__set_acl(str_acl) + return True + + def loadaclfile(self, filename): + """Laed ACL Definitionen aus Datei. + @param filename Dateiname fuer Definitionen + @return True, wenn Laden erfolgreich war""" + if type(filename) != str: + raise ValueError("parameter filename must be ") + + # Zugriffsrecht prüfen + if not access(filename, R_OK): + return False + + str_acl = "" + with open(filename, "r") as fh: + while True: + buff = fh.readline() + if buff == "": + break + buff = buff.split("#")[0].strip() + if len(buff) > 0: + str_acl += buff + " " + + acl_okay = self.loadacl(str_acl.strip()) + if acl_okay: + # Dateinamen für Schreiben übernehmen + self.__filename = filename + + return acl_okay + + def writeaclfile(self, filename=None, aclname=None): + """Schreibt ACL Definitionen in Datei. + @param filename Dateiname fuer Definitionen + @return True, wenn Schreiben erfolgreich war""" + if filename is not None and type(filename) != str: + raise ValueError("parameter filename must be ") + if aclname is not None and type(aclname) != str: + raise ValueError("parameter aclname must be ") + + # Dateinamen prüfen + if filename is None and self.__filename is not None: + filename = self.__filename + + # Zugriffsrecht prüfen + if not access(filename, W_OK): + return False + + header = "# {}Access Control List (acl)\n" \ + "# One entry per Line IPADRESS,LEVEL\n" \ + "#\n".format("" if aclname is None else aclname + " ") + + with open(filename, "w") as fh: + fh.write(header) + for aclip in sorted(self.__dict_acl): + fh.write("{},{}\n".format(aclip, self.__dict_acl[aclip])) + + return True + + acl = property(__get_acl, __set_acl) + filename = property(__get_filename) + regex_acl = property(__get_regex_acl) diff --git a/setup.py b/setup.py index fbf68c0..5c40fb6 100644 --- a/setup.py +++ b/setup.py @@ -48,6 +48,7 @@ if platform == "linux": ("share/applications", ["data/revpipycontrol.desktop"]), ("share/icons/hicolor/32x32/apps", ["data/revpipycontrol.png"]), ("share/revpipycontrol", glob("revpipycontrol/*.*")), + ("share/revpipycontrol/shared", glob("revpipycontrol/shared/*.*")), ( "share/revpipycontrol/locale/de/LC_MESSAGES", glob("revpipycontrol/locale/de/LC_MESSAGES/*.mo")