754
763
return dbus.String(dt.isoformat(),
755
764
variant_level=variant_level)
757
class transitional_dbus_metaclass(DBusObjectWithProperties.__metaclass__):
766
class AlternateDBusNamesMetaclass(DBusObjectWithProperties
768
"""Applied to an empty subclass of a D-Bus object, this metaclass
769
will add additional D-Bus attributes matching a certain pattern.
758
771
def __new__(mcs, name, bases, attr):
759
for attrname, old_dbusobj in inspect.getmembers(bases[0]):
760
new_interface = getattr(old_dbusobj, "_dbus_interface", "").replace("se.bsnet.fukt.", "se.recompile.")
761
if (getattr(old_dbusobj, "_dbus_is_signal", False)
762
and old_dbusobj._dbus_interface.startswith("se.bsnet.fukt.Mandos")):
763
unwrappedfunc = dict(zip(old_dbusobj.func_code.co_freevars,
764
old_dbusobj.__closure__))["func"].cell_contents
765
newfunc = types.FunctionType(unwrappedfunc.func_code,
766
unwrappedfunc.func_globals,
767
unwrappedfunc.func_name,
768
unwrappedfunc.func_defaults,
769
unwrappedfunc.func_closure)
770
new_dbusfunc = dbus.service.signal(
771
new_interface, old_dbusobj._dbus_signature)(newfunc)
772
attr["_transitional_" + attrname] = new_dbusfunc
774
def fixscope(func1, func2):
775
def newcall(*args, **kwargs):
776
func1(*args, **kwargs)
777
func2(*args, **kwargs)
780
attr[attrname] = fixscope(old_dbusobj, new_dbusfunc)
782
elif (getattr(old_dbusobj, "_dbus_is_method", False)
783
and old_dbusobj._dbus_interface.startswith("se.bsnet.fukt.Mandos")):
784
new_dbusfunc = (dbus.service.method
786
old_dbusobj._dbus_in_signature,
787
old_dbusobj._dbus_out_signature)
789
(old_dbusobj.func_code,
790
old_dbusobj.func_globals,
791
old_dbusobj.func_name,
792
old_dbusobj.func_defaults,
793
old_dbusobj.func_closure)))
795
attr[attrname] = new_dbusfunc
796
elif (getattr(old_dbusobj, "_dbus_is_property", False)
797
and old_dbusobj._dbus_interface.startswith("se.bsnet.fukt.Mandos")):
798
new_dbusfunc = (dbus_service_property
800
old_dbusobj._dbus_signature,
801
old_dbusobj._dbus_access,
802
old_dbusobj._dbus_get_args_options["byte_arrays"])
804
(old_dbusobj.func_code,
805
old_dbusobj.func_globals,
806
old_dbusobj.func_name,
807
old_dbusobj.func_defaults,
808
old_dbusobj.func_closure)))
810
attr[attrname] = new_dbusfunc
772
# Go through all the base classes which could have D-Bus
773
# methods, signals, or properties in them
774
for base in (b for b in bases
775
if issubclass(b, dbus.service.Object)):
776
# Go though all attributes of the base class
777
for attrname, attribute in inspect.getmembers(base):
778
# Ignore non-D-Bus attributes, and D-Bus attributes
779
# with the wrong interface name
780
if (not hasattr(attribute, "_dbus_interface")
781
or not attribute._dbus_interface
782
.startswith("se.recompile.Mandos")):
784
# Create an alternate D-Bus interface name based on
786
alt_interface = (attribute._dbus_interface
787
.replace("se.recompile.Mandos",
788
"se.bsnet.fukt.Mandos"))
789
# Is this a D-Bus signal?
790
if getattr(attribute, "_dbus_is_signal", False):
791
# Extract the original non-method function by
793
nonmethod_func = (dict(
794
zip(attribute.func_code.co_freevars,
795
attribute.__closure__))["func"]
797
# Create a new, but exactly alike, function
798
# object, and decorate it to be a new D-Bus signal
799
# with the alternate D-Bus interface name
800
new_function = (dbus.service.signal
802
attribute._dbus_signature)
804
nonmethod_func.func_code,
805
nonmethod_func.func_globals,
806
nonmethod_func.func_name,
807
nonmethod_func.func_defaults,
808
nonmethod_func.func_closure)))
809
# Define a creator of a function to call both the
810
# old and new functions, so both the old and new
811
# signals gets sent when the function is called
812
def fixscope(func1, func2):
813
"""This function is a scope container to pass
814
func1 and func2 to the "call_both" function
815
outside of its arguments"""
816
def call_both(*args, **kwargs):
817
"""This function will emit two D-Bus
818
signals by calling func1 and func2"""
819
func1(*args, **kwargs)
820
func2(*args, **kwargs)
822
# Create the "call_both" function and add it to
824
attr[attrname] = fixscope(attribute,
826
# Is this a D-Bus method?
827
elif getattr(attribute, "_dbus_is_method", False):
828
# Create a new, but exactly alike, function
829
# object. Decorate it to be a new D-Bus method
830
# with the alternate D-Bus interface name. Add it
832
attr[attrname] = (dbus.service.method
834
attribute._dbus_in_signature,
835
attribute._dbus_out_signature)
837
(attribute.func_code,
838
attribute.func_globals,
840
attribute.func_defaults,
841
attribute.func_closure)))
842
# Is this a D-Bus property?
843
elif getattr(attribute, "_dbus_is_property", False):
844
# Create a new, but exactly alike, function
845
# object, and decorate it to be a new D-Bus
846
# property with the alternate D-Bus interface
847
# name. Add it to the class.
848
attr[attrname] = (dbus_service_property
850
attribute._dbus_signature,
851
attribute._dbus_access,
853
._dbus_get_args_options
856
(attribute.func_code,
857
attribute.func_globals,
859
attribute.func_defaults,
860
attribute.func_closure)))
811
861
return type.__new__(mcs, name, bases, attr)
813
863
class ClientDBus(Client, DBusObjectWithProperties):
840
890
def notifychangeproperty(transform_func,
841
891
dbus_name, type_func=lambda x: x,
842
892
variant_level=1):
843
""" Modify a variable so that its a property that announce its
845
transform_fun: Function that takes a value and transform it to
847
dbus_name: DBus name of the variable
893
""" Modify a variable so that it's a property which announces
896
transform_fun: Function that takes a value and a variant_level
897
and transforms it to a D-Bus type.
898
dbus_name: D-Bus name of the variable
848
899
type_func: Function that transform the value before sending it
850
variant_level: DBus variant level. default: 1
900
to the D-Bus. Default: no transform
901
variant_level: D-Bus variant level. Default: 1
903
attrname = "_{0}".format(dbus_name)
853
904
def setter(self, value):
854
old_value = real_value[0]
855
real_value[0] = value
856
905
if hasattr(self, "dbus_object_path"):
857
if type_func(old_value) != type_func(real_value[0]):
858
dbus_value = transform_func(type_func(real_value[0]),
906
if (not hasattr(self, attrname) or
907
type_func(getattr(self, attrname, None))
908
!= type_func(value)):
909
dbus_value = transform_func(type_func(value),
860
912
self.PropertyChanged(dbus.String(dbus_name),
914
setattr(self, attrname, value)
863
return property(lambda self: real_value[0], setter)
916
return property(lambda self: getattr(self, attrname), setter)
866
919
expires = notifychangeproperty(datetime_to_dbus, "Expires")
871
924
last_enabled = notifychangeproperty(datetime_to_dbus,
873
926
checker = notifychangeproperty(dbus.Boolean, "CheckerRunning",
874
type_func = lambda checker: checker is not None)
927
type_func = lambda checker:
875
929
last_checked_ok = notifychangeproperty(datetime_to_dbus,
877
last_approval_request = notifychangeproperty(datetime_to_dbus,
878
"LastApprovalRequest")
931
last_approval_request = notifychangeproperty(
932
datetime_to_dbus, "LastApprovalRequest")
879
933
approved_by_default = notifychangeproperty(dbus.Boolean,
880
934
"ApprovedByDefault")
881
approval_delay = notifychangeproperty(dbus.UInt16, "ApprovalDelay",
882
type_func = _timedelta_to_milliseconds)
883
approval_duration = notifychangeproperty(dbus.UInt16, "ApprovalDuration",
884
type_func = _timedelta_to_milliseconds)
935
approval_delay = notifychangeproperty(dbus.UInt16,
938
_timedelta_to_milliseconds)
939
approval_duration = notifychangeproperty(
940
dbus.UInt16, "ApprovalDuration",
941
type_func = _timedelta_to_milliseconds)
885
942
host = notifychangeproperty(dbus.String, "Host")
886
943
timeout = notifychangeproperty(dbus.UInt16, "Timeout",
887
type_func = _timedelta_to_milliseconds)
888
extended_timeout = notifychangeproperty(dbus.UInt16, "ExtendedTimeout",
889
type_func = _timedelta_to_milliseconds)
890
interval = notifychangeproperty(dbus.UInt16, "Interval",
891
type_func = _timedelta_to_milliseconds)
945
_timedelta_to_milliseconds)
946
extended_timeout = notifychangeproperty(
947
dbus.UInt16, "ExtendedTimeout",
948
type_func = _timedelta_to_milliseconds)
949
interval = notifychangeproperty(dbus.UInt16,
952
_timedelta_to_milliseconds)
892
953
checker_command = notifychangeproperty(dbus.String, "Checker")
894
955
del notifychangeproperty
1615
1686
"dress: %s", fpr, address)
1616
1687
if self.use_dbus:
1617
1688
# Emit D-Bus signal
1618
mandos_dbus_service.ClientNotFound(fpr, address[0])
1689
mandos_dbus_service.ClientNotFound(fpr,
1619
1691
parent_pipe.send(False)
1622
1694
gobject.io_add_watch(parent_pipe.fileno(),
1623
1695
gobject.IO_IN | gobject.IO_HUP,
1624
1696
functools.partial(self.handle_ipc,
1625
parent_pipe = parent_pipe,
1626
client_object = client))
1627
1702
parent_pipe.send(True)
1628
# remove the old hook in favor of the new above hook on same fileno
1703
# remove the old hook in favor of the new above hook on
1630
1706
if command == 'funcall':
1631
1707
funcname = request[1]
1632
1708
args = request[2]
1633
1709
kwargs = request[3]
1635
parent_pipe.send(('data', getattr(client_object, funcname)(*args, **kwargs)))
1711
parent_pipe.send(('data', getattr(client_object,
1637
1715
if command == 'getattr':
1638
1716
attrname = request[1]
1639
1717
if callable(client_object.__getattribute__(attrname)):
1640
1718
parent_pipe.send(('function',))
1642
parent_pipe.send(('data', client_object.__getattribute__(attrname)))
1720
parent_pipe.send(('data', client_object
1721
.__getattribute__(attrname)))
1644
1723
if command == 'setattr':
1645
1724
attrname = request[1]