예제 #1
0
파일: marshal.py 프로젝트: rheenen/txdbus
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'
    ]
예제 #2
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']
예제 #3
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
예제 #4
0
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)))
예제 #5
0
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')
예제 #6
0
파일: marshal.py 프로젝트: rheenen/txdbus
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))
예제 #7
0
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))
예제 #8
0
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
예제 #9
0
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)))
예제 #10
0
def validateErrorName(n):
    try:
        validateInterfaceName(n)
    except MarshallingError as e:
        raise MarshallingError(str(e).replace('interface', 'error', 1))