627
625
def _get_all_dbus_properties(self):
628
626
"""Returns a generator of (name, attribute) pairs
630
return ((prop.__get__(self)._dbus_name, prop.__get__(self))
631
for cls in self.__class__.__mro__
632
for name, prop in inspect.getmembers(cls, self._is_dbus_property))
628
return ((prop._dbus_name, prop)
630
inspect.getmembers(self, self._is_dbus_property))
634
632
def _get_dbus_property(self, interface_name, property_name):
635
633
"""Returns a bound method if one exists which is a D-Bus
636
634
property with the specified name and interface.
638
for cls in self.__class__.__mro__:
639
for name, value in inspect.getmembers(cls, self._is_dbus_property):
640
if value._dbus_name == property_name and value._dbus_interface == interface_name:
641
return value.__get__(self)
636
for name in (property_name,
637
property_name + "_dbus_property"):
638
prop = getattr(self, name, None)
640
or not self._is_dbus_property(prop)
641
or prop._dbus_name != property_name
642
or (interface_name and prop._dbus_interface
643
and interface_name != prop._dbus_interface)):
643
646
# No such property
644
647
raise DBusPropertyNotFound(self.dbus_object_path + ":"
645
648
+ interface_name + "."
754
757
return dbus.String(dt.isoformat(),
755
758
variant_level=variant_level)
757
class AlternateDBusNamesMetaclass(DBusObjectWithProperties.__metaclass__):
758
"""Applied to an empty subclass of a D-Bus object, this metaclass
759
will add additional D-Bus attributes matching a certain pattern.
761
def __new__(mcs, name, bases, attr):
762
# Go through all the base classes which could have D-Bus
763
# methods, signals, or properties in them
764
for base in (b for b in bases
765
if issubclass(b, dbus.service.Object)):
766
# Go though all attributes of the base class
767
for attrname, attribute in inspect.getmembers(base):
768
# Ignore non-D-Bus attributes, and D-Bus attributes
769
# with the wrong interface name
770
if (not hasattr(attribute, "_dbus_interface")
771
or not attribute._dbus_interface
772
.startswith("se.recompile.Mandos")):
774
# Create an alternate D-Bus interface name based on
776
alt_interface = (attribute._dbus_interface
777
.replace("se.recompile.Mandos",
778
"se.bsnet.fukt.Mandos"))
779
# Is this a D-Bus signal?
780
if getattr(attribute, "_dbus_is_signal", False):
781
# Extract the original non-method function by
783
nonmethod_func = (dict(
784
zip(attribute.func_code.co_freevars,
785
attribute.__closure__))["func"]
787
# Create a new, but exactly alike, function
788
# object, and decorate it to be a new D-Bus signal
789
# with the alternate D-Bus interface name
790
new_function = (dbus.service.signal
792
attribute._dbus_signature)
794
nonmethod_func.func_code,
795
nonmethod_func.func_globals,
796
nonmethod_func.func_name,
797
nonmethod_func.func_defaults,
798
nonmethod_func.func_closure)))
799
# Define a creator of a function to call both the
800
# old and new functions, so both the old and new
801
# signals gets sent when the function is called
802
def fixscope(func1, func2):
803
"""This function is a scope container to pass
804
func1 and func2 to the "call_both" function
805
outside of its arguments"""
806
def call_both(*args, **kwargs):
807
"""This function will emit two D-Bus
808
signals by calling func1 and func2"""
809
func1(*args, **kwargs)
810
func2(*args, **kwargs)
812
# Create the "call_both" function and add it to
814
attr[attrname] = fixscope(attribute,
816
# Is this a D-Bus method?
817
elif getattr(attribute, "_dbus_is_method", False):
818
# Create a new, but exactly alike, function
819
# object. Decorate it to be a new D-Bus method
820
# with the alternate D-Bus interface name. Add it
822
attr[attrname] = (dbus.service.method
824
attribute._dbus_in_signature,
825
attribute._dbus_out_signature)
827
(attribute.func_code,
828
attribute.func_globals,
830
attribute.func_defaults,
831
attribute.func_closure)))
832
# Is this a D-Bus property?
833
elif getattr(attribute, "_dbus_is_property", False):
834
# Create a new, but exactly alike, function
835
# object, and decorate it to be a new D-Bus
836
# property with the alternate D-Bus interface
837
# name. Add it to the class.
838
attr[attrname] = (dbus_service_property
840
attribute._dbus_signature,
841
attribute._dbus_access,
843
._dbus_get_args_options
846
(attribute.func_code,
847
attribute.func_globals,
849
attribute.func_defaults,
850
attribute.func_closure)))
851
return type.__new__(mcs, name, bases, attr)
853
760
class ClientDBus(Client, DBusObjectWithProperties):
854
761
"""A Client class using D-Bus
880
787
def notifychangeproperty(transform_func,
881
788
dbus_name, type_func=lambda x: x,
882
789
variant_level=1):
883
""" Modify a variable so that it's a property which announces
886
transform_fun: Function that takes a value and transforms it
888
dbus_name: D-Bus name of the variable
790
""" Modify a variable so that its a property that announce its
792
transform_fun: Function that takes a value and transform it to
794
dbus_name: DBus name of the variable
889
795
type_func: Function that transform the value before sending it
890
to the D-Bus. Default: no transform
891
variant_level: D-Bus variant level. Default: 1
797
variant_level: DBus variant level. default: 1
893
799
real_value = [None,]
894
800
def setter(self, value):
1281
1185
unicode(self.client_address))
1282
1186
logger.debug("Pipe FD: %d",
1283
1187
self.server.child_pipe.fileno())
1285
1189
session = (gnutls.connection
1286
1190
.ClientSession(self.request,
1287
1191
gnutls.connection
1288
1192
.X509Credentials()))
1290
1194
# Note: gnutls.connection.X509Credentials is really a
1291
1195
# generic GnuTLS certificate credentials object so long as
1292
1196
# no X.509 keys are added to it. Therefore, we can use it
1293
1197
# here despite using OpenPGP certificates.
1295
1199
#priority = ':'.join(("NONE", "+VERS-TLS1.1",
1296
1200
# "+AES-256-CBC", "+SHA1",
1297
1201
# "+COMP-NULL", "+CTYPE-OPENPGP",