def marshal_string(ct, var, start_byte, lendian): if not isinstance(var, basestring): raise MarshallingError('Required string. Received: ' + repr(var)) if var.find('\0') != -1: raise MarshallingError( 'Embedded nul characters are not allowed within DBus strings') return 4 + len(var) + 1, [ struct.pack(lendian and '<I' or '>I', len(var)), var, '\0' ]
def marshal_string(ct, var, start_byte, lendian, oobFDs): if not isinstance(var, six.string_types): raise MarshallingError('Required string. Received: ' + repr(var)) if var.find('\0') != -1: raise MarshallingError( 'Embedded nul characters are not allowed within DBus strings') var = codecs.encode(var, 'utf-8') return 4 + \ len(var) + \ 1, [struct.pack(lendian and '<I' or '>I', len(var)), var, b'\0']
def unmarshal_array(ct, data, offset, lendian, oobFDs): start_offset = offset values = [] data_len = struct.unpack_from(lendian and '<I' or '>I', data, offset)[0] tsig = ct[1:] # strip of leading 'a' tcode = tsig[0] # type of array element offset += 4 # 4-byte data length offset += len(pad[tcode](offset)) # padding length end_offset = offset + data_len while offset < end_offset: offset += len(pad[tcode](offset)) nbytes, value = unmarshallers[tcode]( tsig, data, offset, lendian, oobFDs) offset += nbytes values.append(value) if not offset == end_offset: raise MarshallingError('Invalid array encoding') if tcode == '{': d = {} for item in values: d[item[0]] = item[1] values = d return offset - start_offset, values
def validateBusName(n): """ Verifies that the supplied name is a valid DBus Bus name. Throws an L{error.MarshallingError} if the format is invalid @type n: C{string} @param n: A DBus bus name """ try: if '.' not in n: raise Exception('At least two components required') if '..' in n: raise Exception('".." not allowed in bus names') if len(n) > 255: raise Exception('Name exceeds maximum length of 255') if n[0] == '.': raise Exception('Names may not begin with a "."') if n[0].isdigit(): raise Exception('Names may not begin with a digit') if bus_re.search(n): raise Exception( 'Names contains a character outside the set [A-Za-z0-9_.\\-:]') if not n[0] == ':' and dot_digit_re.search(n): raise Exception( 'No coponents of an interface name may begin with a digit') except Exception as e: raise MarshallingError('Invalid bus name "%s": %s' % (n, str(e)))
def validateObjectPath(p): """ Ensures that the provided object path conforms to the DBus standard. Throws a L{error.MarshallingError} if non-conformant @type p: C{string} @param p: A DBus object path """ if not p.startswith('/'): raise MarshallingError('Object paths must begin with a "/"') if len(p) > 1 and p[-1] == '/': raise MarshallingError('Object paths may not end with "/"') if '//' in p: raise MarshallingError('"//" is not allowed in object paths"') if invalid_obj_path_re.search(p): raise MarshallingError('Invalid characters contained in object path')
def sigFromPy(pobj): """ Returns the DBus signature type for the argument. If the argument is an instance of one of the type wrapper classes, the exact type signature corresponding to the wrapper class will be used. If the object has a variable named 'dbusSignature', the value of that variable will be used. Otherwise, a generic type will be used (i.e "i" for a Python int) @rtype: C{string} @returns: The DBus signature for the supplied Python object """ sig = getattr(pobj, 'dbusSignature', None) if sig is not None: return sig elif isinstance(pobj, int): return 'i' elif isinstance(pobj, long): return 'x' elif isinstance(pobj, float): return 'd' elif isinstance(pobj, basestring): return 's' elif isinstance(pobj, list): return 'a' + sigFromPy(pobj[0]) elif isinstance(pobj, dict): return 'a{' + sigFromPy(pobj.keys()[0]) + sigFromPy( pobj.values()[0]) + '}' else: raise MarshallingError('Invalid Python type for variant: ' + repr(pobj))
def sigFromPy(pobj): """ Returns the DBus signature type for the argument. If the argument is an instance of one of the type wrapper classes, the exact type signature corresponding to the wrapper class will be used. If the object has a variable named 'dbusSignature', the value of that variable will be used. Otherwise, a generic type will be used (i.e "i" for a Python int) @rtype: C{string} @returns: The DBus signature for the supplied Python object """ sig = getattr(pobj, 'dbusSignature', None) if sig is not None: return sig elif isinstance(pobj, bool): return 'b' elif isinstance(pobj, int): return 'i' elif isinstance(pobj, six.integer_types): return 'x' elif isinstance(pobj, float): return 'd' elif isinstance(pobj, six.string_types): return 's' elif isinstance(pobj, bytearray): return 'ay' elif isinstance(pobj, list): vtype = type(pobj[0]) same = True for v in pobj[1:]: if not isinstance(v, vtype): same = False if same: return 'a' + sigFromPy(pobj[0]) else: return 'av' elif isinstance(pobj, tuple): return '(' + ''.join(sigFromPy(e) for e in pobj) + ')' elif isinstance(pobj, dict): same = True vtype = None for k, v in six.iteritems(pobj): if vtype is None: vtype = type(v) elif not isinstance(v, vtype): same = False if same: return 'a{' + sigFromPy(k) + sigFromPy(v) + '}' else: return 'a{' + sigFromPy(k) + 'v}' else: raise MarshallingError('Invalid Python type for variant: ' + repr(pobj))
def marshal_array(ct, var, start_byte, lendian, oobFDs): chunks = [] data_len = 0 tsig = ct[1:] # strip of leading 'a' tcode = tsig[0] # type of array element start_byte += 4 # for array size initial_padding = pad[tcode](start_byte) if initial_padding: start_byte += len(initial_padding) chunks.append(initial_padding) if isinstance(var, (list, tuple, bytearray)): arr_list = var elif isinstance(var, dict): arr_list = [tpl for tpl in six.iteritems(var)] else: raise MarshallingError( 'List, Tuple, Bytearray, or Dictionary required for DBus array. ' ' Received: ' + repr(var) ) for item in arr_list: padding = pad[tcode](start_byte) if padding: start_byte += len(padding) data_len += len(padding) chunks.append(padding) nbytes, vchunks = marshallers[tcode]( tsig, item, start_byte, lendian, oobFDs) start_byte += nbytes data_len += nbytes chunks.extend(vchunks) chunks.insert(0, struct.pack(lendian and '<I' or '>I', data_len)) return 4 + len(initial_padding) + data_len, chunks
def validateMemberName(n): """ Verifies that the supplied name is a valid DBus member name. Throws an L{error.MarshallingError} if the format is invalid @type n: C{string} @param n: A DBus member name """ try: if len(n) < 1: raise Exception('Name must be at least one byte in length') if len(n) > 255: raise Exception('Name exceeds maximum length of 255') if n[0].isdigit(): raise Exception('Names may not begin with a digit') if mbr_re.search(n): raise Exception( 'Names contains a character outside the set [A-Za-z0-9_]') except Exception as e: raise MarshallingError('Invalid member name "%s": %s' % (n, str(e)))
def validateErrorName(n): try: validateInterfaceName(n) except MarshallingError as e: raise MarshallingError(str(e).replace('interface', 'error', 1))