Converts value to expected type
Fixes openbmc/openbmc#1160
Change-Id: I5c36f5bc065a0b2fdac56c2ee92b0ed54258f238
Signed-off-by: Leonel Gonzalez <lgonzalez@us.ibm.com>
diff --git a/module/obmc/wsgi/apps/rest_dbus.py b/module/obmc/wsgi/apps/rest_dbus.py
index c51e4f9..605956c 100644
--- a/module/obmc/wsgi/apps/rest_dbus.py
+++ b/module/obmc/wsgi/apps/rest_dbus.py
@@ -27,6 +27,7 @@
import grp
import crypt
import tempfile
+import re
DBUS_UNKNOWN_INTERFACE = 'org.freedesktop.UnknownInterface'
DBUS_UNKNOWN_INTERFACE_ERROR = 'org.freedesktop.DBus.Error.UnknownInterface'
@@ -45,6 +46,85 @@
abort(401, 'Login required')
+def get_type_signature_by_introspection(bus, service, object_path,
+ property_name):
+ obj = bus.get_object(service, object_path)
+ iface = dbus.Interface(obj, 'org.freedesktop.DBus.Introspectable')
+ xml_string = iface.Introspect()
+ for child in ElementTree.fromstring(xml_string):
+ # Iterate over each interfaces's properties to find
+ # matching property_name, and return its signature string
+ if child.tag == 'interface':
+ for i in child.iter():
+ if ('name' in i.attrib) and \
+ (i.attrib['name'] == property_name):
+ type_signature = i.attrib['type']
+ return type_signature
+
+
+def split_struct_signature(signature):
+ struct_regex = r'(b|y|n|i|x|q|u|t|d|s|a\(.+?\)|\(.+?\))|a\{.+?\}+?'
+ struct_matches = re.findall(struct_regex, signature)
+ return struct_matches
+
+
+def convert_type(signature, value):
+ # Basic Types
+ converted_value = None
+ converted_container = None
+ basic_types = {'b': bool, 'y': dbus.Byte, 'n': dbus.Int16, 'i': int,
+ 'x': long, 'q': dbus.UInt16, 'u': dbus.UInt32,
+ 't': dbus.UInt64, 'd': float, 's': str}
+ array_matches = re.match(r'a\((\S+)\)', signature)
+ struct_matches = re.match(r'\((\S+)\)', signature)
+ dictionary_matches = re.match(r'a{(\S+)}', signature)
+ if signature in basic_types:
+ converted_value = basic_types[signature](value)
+ return converted_value
+ # Array
+ if array_matches:
+ element_type = array_matches.group(1)
+ converted_container = list()
+ # Test if value is a list
+ # to avoid iterating over each character in a string.
+ # Iterate over each item and convert type
+ if isinstance(value, list):
+ for i in value:
+ converted_element = convert_type(element_type, i)
+ converted_container.append(converted_element)
+ # Convert non-sequence to expected type, and append to list
+ else:
+ converted_element = convert_type(element_type, value)
+ converted_container.append(converted_element)
+ return converted_container
+ # Struct
+ if struct_matches:
+ element_types = struct_matches.group(1)
+ split_element_types = split_struct_signature(element_types)
+ converted_container = list()
+ # Test if value is a list
+ if isinstance(value, list):
+ for index, val in enumerate(value):
+ converted_element = convert_type(split_element_types[index],
+ value[index])
+ converted_container.append(converted_element)
+ else:
+ converted_element = convert_type(element_types, value)
+ converted_container.append(converted_element)
+ return tuple(converted_container)
+ # Dictionary
+ if dictionary_matches:
+ element_types = dictionary_matches.group(1)
+ split_element_types = split_struct_signature(element_types)
+ converted_container = dict()
+ # Convert each element of dict
+ for key, val in value.iteritems():
+ converted_key = convert_type(split_element_types[0], key)
+ converted_val = convert_type(split_element_types[1], val)
+ converted_container[converted_key] = converted_val
+ return converted_container
+
+
class UserInGroup:
''' Authorization plugin callback that checks that the user is logged in
and a member of a group. '''
@@ -313,6 +393,21 @@
abort(400, str(e))
except dbus.exceptions.DBusException, e:
if e.get_dbus_name() == DBUS_INVALID_ARGS:
+ bus_name = properties_iface.bus_name
+ expected_type = get_type_signature_by_introspection(self.bus,
+ bus_name,
+ path,
+ prop)
+ if not expected_type:
+ abort(403, "Failed to get expected type: %s" % str(e))
+ converted_value = None
+ try:
+ converted_value = convert_type(expected_type, value)
+ self.do_put(path, prop, converted_value)
+ return
+ except Exception as ex:
+ abort(403, "Failed to convert %s to type %s" %
+ (value, expected_type))
abort(403, str(e))
raise