Example #1
0
    def send(self, data = None):
        """
Invoke an SSDP M-SEARCH method on the unicast or multicast recipient.

:return: (bool) Request result
:since:  v0.2.00
        """

        if (data is not None): data = Binary.utf8_bytes(data)

        headers = self.headers.copy()
        headers['CONTENT-LENGTH'] = (0 if (data is None) else len(data))
        headers['SERVER'] = AbstractSsdp.get_pas_upnp_sddp_identifier_string()

        ssdp_header = "{0} {1}\r\n".format(AbstractSsdp.get_pas_upnp_http_header_string(True),
                                           self.http_status
                                          )

        for header_name in headers:
            if (type(headers[header_name]) is list):
                for header_value in headers[header_name]: ssdp_header += "{0}: {1}\r\n".format(header_name, header_value)
            else: ssdp_header += "{0}: {1}\r\n".format(header_name, headers[header_name])
        #

        ssdp_header = Binary.utf8_bytes("{0}\r\n".format(ssdp_header))

        data = (ssdp_header if (data is None) else ssdp_header + data)
        return self._write_data(data)
Example #2
0
    def get_native(native_type, value):
        """
Returns the native value for the given variable definition and UPnP encoded
value.

:param native_type: Native type definition
:param value: Native python value

:return: (str) UPnP encoded value
:since:  v0.2.00
        """

        if (type(native_type) is tuple):
            if (native_type[1] == "xmlns"): _return = value
            elif (native_type[1] == "base64"): _return = Binary.raw_str(b64decode(Binary.utf8_bytes(value)))
            elif (native_type[1] == "date"): _return = RfcBasics.get_iso8601_timestamp(value, has_time = False)
            elif (native_type[1] == "dateTime"): _return = RfcBasics.get_iso8601_timestamp(value, has_timezone = False)
            elif (native_type[1] == "dateTime.tz"): _return = RfcBasics.get_iso8601_timestamp(value)
            elif (native_type[1] == "hex"): _return = Binary.raw_str(unhexlify(Binary.utf8_bytes(value)))
            elif (native_type[1] == "time"): _return = RfcBasics.get_iso8601_timestamp(value, False, has_timezone = False)
            elif (native_type[1] == "time.tz"): _return = RfcBasics.get_iso8601_timestamp(value, False)
            elif (native_type[1] == "uri" and re.match("^\\w+\\:\\w", value) is None): raise ValueException("Given value mismatches defined format for URIs")
            elif (native_type[1] == "uuid" and (not value.startswith("uuid:"))): raise ValueException("Given value mismatches defined format for UUIDs")
            elif (native_type[0] is not str): _return = native_type[0](value)
        elif (native_type is not str): _return = native_type(value)
        else: _return = value

        return _return
Example #3
0
    def request(self, method, data = None):
        """
Invoke a given SSDP method on the unicast or multicast recipient.

:param method: HTTP method
:param data: HTTP body

:return: (bool) Request result
:since:  v0.2.00
        """

        if (data is not None): data = Binary.utf8_bytes(data)

        headers = self.headers.copy()

        headers['HOST'] = "{0}:{1:d}".format(self.host, self.port)
        headers['CONTENT-LENGTH'] = (0 if (data is None) else len(data))
        headers['SERVER'] = AbstractSsdp.get_pas_upnp_sddp_identifier_string()

        ssdp_header = "{0} {1} {2}\r\n".format(method.upper(),
                                               self.path,
                                               AbstractSsdp.get_pas_upnp_http_header_string(True)
                                              )

        for header_name in headers:
            if (type(headers[header_name]) is list):
                for header_value in headers[header_name]: ssdp_header += "{0}: {1}\r\n".format(header_name, header_value)
            else: ssdp_header += "{0}: {1}\r\n".format(header_name, headers[header_name])
        #

        ssdp_header = Binary.utf8_bytes("{0}\r\n".format(ssdp_header))

        data = (ssdp_header if (data is None) else ssdp_header + data)
        return self._write_data(data)
    def read(self, n = 0):
        """
Reads data using the given body reader and parse the JSON response. Chunked
transfer-encoded data is handled automatically.

:param n: Bytes to read

:return: (bytes) Data received
:since:  v1.0.0
        """

        # pylint: disable=access-member-before-definition, attribute-defined-outside-init, not-callable, used-before-assignment

        if (n > 0): raise OperationNotSupportedException()

        if (self.json_resource is None):
            json_data = self.body_reader()
            self.body_reader = None

            self.json_resource = JsonResource()
            self.json_resource.parse(Binary.str(json_data))
            if (self.json_resource.data is None): raise ValueException("Data received is not a valid JSON encoded response")

            _return = Binary.bytes(json_data)
        else: _return = Binary.bytes("")

        return _return
    def _get_blake2_password(self, variant, password, username = None):
        """
Returns the BLAKE2 generated password hash.

:param password: User profile password
:param username: User name used while generating BLAKE2 hash

:return: (str) Hash on success; None if not supported
:since:  v0.2.00
        """

        blake2 = None
        blake2_person = None
        blake2_salt = None

        salt = Settings.get("pas_user_profile_password_salt")
        if (salt is None): raise ValueException("User profile password salt is not defined")

        if (variant == PasswordGeneratorsMixin.PASSWORD_TYPE_BLAKE2B):
            blake2 = blake2b
            blake2_salt = Binary.bytes(salt[:blake2b.SALT_SIZE])
            blake2_person = Binary.utf8_bytes(username[:blake2b.PERSON_SIZE])
        #

        if (variant == PasswordGeneratorsMixin.PASSWORD_TYPE_BLAKE2S):
            blake2 = blake2s
            blake2_salt = Binary.bytes(salt[:blake2s.SALT_SIZE])
            blake2_person = Binary.utf8_bytes(username[:blake2s.PERSON_SIZE])
        #

        if (blake2 is None): raise ValueException("BLAKE2 variant given is invalid")

        return blake2(Binary.utf8_bytes(password), salt = blake2_salt, person = blake2_person).hexdigest()
Example #6
0
    def set_data_attributes(self, **kwargs):
        """
Sets values given as keyword arguments to this method.

:since: v0.2.00
        """

        with self:
            if ("type" in kwargs):
                _type = (kwargs['type'] if (type(kwargs['type']) is int) else self.__class__.get_type_int(kwargs['type']))
                self.local.db_instance.type = _type
            #

            if ("type_ex" in kwargs): self.local.db_instance.type_ex = kwargs['type_ex']
            if ("banned" in kwargs): self.local.db_instance.banned = kwargs['banned']
            if ("deleted" in kwargs): self.local.db_instance.deleted = kwargs['deleted']
            if ("locked" in kwargs): self.local.db_instance.locked = kwargs['locked']
            if ("name" in kwargs): self.local.db_instance.name = Binary.utf8(kwargs['name'])
            if ("password" in kwargs): self.local.db_instance.password = kwargs['password']
            if ("lang" in kwargs): self.local.db_instance.lang = kwargs['lang']
            if ("theme" in kwargs): self.local.db_instance.theme = kwargs['theme']
            if ("email" in kwargs): self.local.db_instance.email = Binary.utf8(kwargs['email'])
            if ("email_public" in kwargs): self.local.db_instance.email_public = kwargs['email_public']
            if ("credits" in kwargs): self.local.db_instance.credits = kwargs['credits']
            if ("title" in kwargs): self.local.db_instance.title = Binary.utf8(kwargs['title'])
            if ("avatar" in kwargs): self.local.db_instance.avatar = kwargs['avatar']
            if ("signature" in kwargs): self.local.db_instance.signature = Binary.utf8(kwargs['signature'])
            if ("registration_ip" in kwargs): self.local.db_instance.registration_ip = kwargs['registration_ip']
            if ("registration_time" in kwargs): self.local.db_instance.registration_time = int(kwargs['registration_time'])
            if ("secid" in kwargs): self.local.db_instance.secid = kwargs['secid']
            if ("lastvisit_ip" in kwargs): self.local.db_instance.lastvisit_ip = kwargs['lastvisit_ip']
            if ("lastvisit_time" in kwargs): self.local.db_instance.lastvisit_time = int(kwargs['lastvisit_time'])
            if ("rating" in kwargs): self.local.db_instance.rating = kwargs['rating']
            if ("timezone" in kwargs): self.local.db_instance.timezone = kwargs['timezone']
Example #7
0
    def set_data_attributes(self, **kwargs):
        """
Sets values given as keyword arguments to this method.

:since: v0.2.00
        """

        with self, self.local.connection.no_autoflush:
            DataLinker.set_data_attributes(self, **kwargs)

            if ("entry_type" in kwargs): self.local.db_instance.entry_type = kwargs['entry_type']
            if ("owner_type" in kwargs): self.local.db_instance.owner_type = kwargs['owner_type']
            if ("author_id" in kwargs): self.local.db_instance.author_id = kwargs['author_id']
            if ("author_ip" in kwargs): self.local.db_instance.author_ip = kwargs['author_ip']
            if ("time_published" in kwargs): self.local.db_instance.time_published = int(kwargs['time_published'])
            if ("description" in kwargs): self.local.db_instance.description = Binary.utf8(kwargs['description'])
            if ("locked" in kwargs): self.local.db_instance.locked = kwargs['locked']
            if ("guest_permission" in kwargs): self.local.db_instance.guest_permission = kwargs['guest_permission']
            if ("user_permission" in kwargs): self.local.db_instance.user_permission = kwargs['user_permission']

            if ("content" in kwargs):
                if (self.local.db_instance.rel_text_entry is None):
                    self.local.db_instance.rel_text_entry = _DbTextEntry()
                    self.local.db_instance.rel_text_entry.id = self.local.db_instance.id
                    db_text_entry = self.local.db_instance.rel_text_entry
                else: db_text_entry = self.local.db_instance.rel_text_entry

                db_text_entry.content = Binary.utf8(kwargs['content'])
Example #8
0
    def set_data_attributes(self, **kwargs):
        """
Sets values given as keyword arguments to this method.

:since: v0.2.00
        """

        with self:
            if ("type" in kwargs):
                _type = (kwargs['type'] if (type(kwargs['type']) is int) else
                         self.__class__.get_type_int(kwargs['type']))
                self.local.db_instance.type = _type
            #

            if ("type_ex" in kwargs):
                self.local.db_instance.type_ex = kwargs['type_ex']
            if ("banned" in kwargs):
                self.local.db_instance.banned = kwargs['banned']
            if ("deleted" in kwargs):
                self.local.db_instance.deleted = kwargs['deleted']
            if ("locked" in kwargs):
                self.local.db_instance.locked = kwargs['locked']
            if ("name" in kwargs):
                self.local.db_instance.name = Binary.utf8(kwargs['name'])
            if ("password" in kwargs):
                self.local.db_instance.password = kwargs['password']
            if ("lang" in kwargs): self.local.db_instance.lang = kwargs['lang']
            if ("theme" in kwargs):
                self.local.db_instance.theme = kwargs['theme']
            if ("email" in kwargs):
                self.local.db_instance.email = Binary.utf8(kwargs['email'])
            if ("email_public" in kwargs):
                self.local.db_instance.email_public = kwargs['email_public']
            if ("credits" in kwargs):
                self.local.db_instance.credits = kwargs['credits']
            if ("title" in kwargs):
                self.local.db_instance.title = Binary.utf8(kwargs['title'])
            if ("avatar" in kwargs):
                self.local.db_instance.avatar = kwargs['avatar']
            if ("signature" in kwargs):
                self.local.db_instance.signature = Binary.utf8(
                    kwargs['signature'])
            if ("registration_ip" in kwargs):
                self.local.db_instance.registration_ip = kwargs[
                    'registration_ip']
            if ("registration_time" in kwargs):
                self.local.db_instance.registration_time = int(
                    kwargs['registration_time'])
            if ("secid" in kwargs):
                self.local.db_instance.secid = kwargs['secid']
            if ("lastvisit_ip" in kwargs):
                self.local.db_instance.lastvisit_ip = kwargs['lastvisit_ip']
            if ("lastvisit_time" in kwargs):
                self.local.db_instance.lastvisit_time = int(
                    kwargs['lastvisit_time'])
            if ("rating" in kwargs):
                self.local.db_instance.rating = kwargs['rating']
            if ("timezone" in kwargs):
                self.local.db_instance.timezone = kwargs['timezone']
Example #9
0
    def init_metadata_xml_tree(self, device_identifier, url_base, xml_resource):
        """
Initialize the service metadata from a UPnP description.

:param device_identifier: Parsed UPnP device identifier
:param url_base: HTTP base URL
:param xml_resource: UPnP description XML parser instance

:return: (bool) True if parsed successfully
:since:  v0.2.00
        """

        _return = True

        if (xml_resource.count_node("upnp:service") > 0): xml_resource.set_cached_node("upnp:service")
        else: _return = False

        if (_return):
            value = xml_resource.get_node_value("upnp:service upnp:serviceType")
            re_result = (None if (value is None) else Service.RE_USN_URN.match(value))

            if (re_result is None or re_result.group(2) != "service"): _return = False
            else:
                self.name = "{0}:service:{1}".format(re_result.group(1), re_result.group(3))
                urn = "{0}:{1}".format(self.name, re_result.group(4))

                self._set_identifier({ "device": device_identifier['device'],
                                       "bootid": device_identifier['bootid'],
                                       "configid": device_identifier['configid'],
                                       "uuid": device_identifier['uuid'],
                                       "class": "service",
                                       "usn": "uuid:{0}::{1}".format(device_identifier['uuid'], value),
                                       "urn": urn,
                                       "domain": re_result.group(1),
                                       "type": re_result.group(3),
                                       "version": re_result.group(4)
                                     })
            #
        #

        if (_return):
            value = xml_resource.get_node_value("upnp:service upnp:serviceId")
            re_result = (None if (value is None) else Service.RE_SERVICE_ID_URN.match(value))

            if (re_result is None or re_result.group(2) != "serviceId"): _return = False
            else: self.service_id = { "urn": value[4:], "domain": re_result.group(1), "id": re_result.group(3) }
        #

        if (_return):
            self.url_scpd = Binary.str(urljoin(url_base, xml_resource.get_node_value("upnp:service upnp:SCPDURL")))
            self.url_control = Binary.str(urljoin(url_base, xml_resource.get_node_value("upnp:service upnp:controlURL")))

            value = xml_resource.get_node_value("upnp:service upnp:eventSubURL")
            self.url_event_control = (None if (value.strip == "") else Binary.str(urljoin(url_base, value)))
        #

        return _return
Example #10
0
    def get_url_base(self, _type, parameters):
        """
Returns the base URL for the given type and parameters.

:param _type: Link type (see constants)
:param parameters: Link parameters

:return: (str) Base URL
:since:  v0.2.00
        """

        _return = ""

        if (_type & Link.TYPE_PREDEFINED_URL == Link.TYPE_PREDEFINED_URL):
            if ("__link__" not in parameters): raise ValueException("Required parameter not defined for the predefined URL")
            _return = parameters['__link__']
        elif (self.path is not None):
            if (_type & Link.TYPE_RELATIVE_URL != Link.TYPE_RELATIVE_URL):
                if (self.scheme is None): raise ValueException("Can't construct an absolute URL without an URI scheme")
                _return = "{0}://".format(Binary.str(self.scheme))

                if (self.host is None): raise ValueException("Can't construct an absolute URL without a host")
                _return += Binary.str(self.host)

                if (self.port is not None):
                    port = Link.filter_well_known_port(self.scheme, self.port)
                    if (port > 0): _return += ":{0:d}".format(port)
                #
            #

            path = ("/" if (self.path is None) else Binary.str(self.path))
            _return += ("/" if (path == "") else path)
        else:
            request = AbstractHttpRequest.get_instance()
            if (request is None): raise ValueException("Can't construct an URL from a request instance if it is not provided")

            if (_type & Link.TYPE_ABSOLUTE_URL == Link.TYPE_ABSOLUTE_URL):
                scheme = request.get_server_scheme()

                _return = "{0}://".format(Binary.str(scheme))

                host = request.get_server_host()
                if (host is not None): _return += Binary.str(host)

                port = Link.filter_well_known_port(scheme, request.get_server_port())
                if (port > 0): _return += ":{0:d}".format(port)

                if (_type & Link.TYPE_BASE_PATH == Link.TYPE_BASE_PATH
                    or _type & Link.TYPE_VIRTUAL_PATH == Link.TYPE_VIRTUAL_PATH
                   ): _return += self._get_url_path(request, False)
                else: _return += self._get_url_path(request)
            else: _return = self._get_url_path(request)
        #

        return _return
Example #11
0
    def set_data_attributes(self, **kwargs):
        """
Sets values given as keyword arguments to this method.

:since: v0.2.00
        """

        with self:
            MpEntry.set_data_attributes(self, **kwargs)

            if ("duration" in kwargs): self.local.db_instance.duration = kwargs['duration']
            if ("description" in kwargs): self.local.db_instance.description = Binary.utf8(kwargs['description'])
            if ("genre" in kwargs): self.local.db_instance.genre = Binary.utf8(kwargs['genre'])
            if ("series" in kwargs): self.local.db_instance.series = Binary.utf8(kwargs['series'])
            if ("episode" in kwargs): self.local.db_instance.episode = kwargs['episode']
            if ("actor" in kwargs): self.local.db_instance.actor = Binary.utf8(kwargs['actor'])
            if ("author" in kwargs): self.local.db_instance.author = Binary.utf8(kwargs['author'])
            if ("director" in kwargs): self.local.db_instance.director = Binary.utf8(kwargs['director'])
            if ("producer" in kwargs): self.local.db_instance.producer = Binary.utf8(kwargs['producer'])
            if ("publisher" in kwargs): self.local.db_instance.publisher = Binary.utf8(kwargs['publisher'])
            if ("width" in kwargs): self.local.db_instance.width = kwargs['width']
            if ("height" in kwargs): self.local.db_instance.height = kwargs['height']
            if ("codec" in kwargs): self.local.db_instance.codec = kwargs['codec']
            if ("bitrate" in kwargs): self.local.db_instance.bitrate = kwargs['bitrate']
            if ("bpp" in kwargs): self.local.db_instance.bpp = kwargs['bpp']
            if ("encoder" in kwargs): self.local.db_instance.encoder = Binary.utf8(kwargs['encoder'])
Example #12
0
    def request(self, _hook, **kwargs):
        """
Requests the IPC aware application to call the given hook.

:param _hook: Hook
:param args: Parameters

:return: (mixed) Result data; None on error
:since:  v0.3.00
        """

        _hook = Binary.str(_hook)

        if (self.log_handler is not None): self.log_handler.debug("#echo(__FILEPATH__)# -{0!r}.request({1})- (#echo(__LINE__)#)", self, _hook, context = "pas_bus")
        _return = None

        if (not self.connected): raise IOException("Connection already closed")

        request_message = self._get_message_call_template()
        if (_hook == "dNG.pas.Status.stop"): request_message.set_flags(Message.FLAG_NO_REPLY_EXPECTED)

        request_message_body = { "method": _hook }
        if (len(kwargs) > 0): request_message_body['params'] = TypeObject("a{sv}", kwargs)

        request_message.set_body(request_message_body)

        if (not self._write_message(request_message)): raise IOException("Failed to transmit request")

        if (_hook == "dNG.pas.Status.stop"): self.connected = False
        else:
            response_message = self._get_response_message()

            if (((not response_message.is_error()) and (not response_message.is_method_reply()))
                or response_message.get_reply_serial() != 1
                or response_message.get_serial() != 2
               ): raise IOException("IPC response received is invalid")

            if (response_message.is_error()):
                response_body = response_message.get_body()

                raise IOException(Binary.str(response_body)
                                  if (type(response_body) == Binary.BYTES_TYPE) else
                                  response_message.get_error_name()
                                 )
            else: _return = response_message.get_body()
        #

        return _return
Example #13
0
    def read(self, n = None):
        """
Reads from the current streamer session.

:param n: How many bytes to read from the current position (0 means until
          EOF)

:return: (bytes) Data; None if EOF
:since:  v1.0.0
        """

        if (self._wrapped_resource is None): raise IOException("Wrapped resource not available for reading with {0!r}".format(self))
        _return = self._wrapped_resource.read(n)

        is_data_uncompressed = (self.compressor is not None)

        while (is_data_uncompressed):
            if (_return is None):
                _return = self.compressor.flush()
                self.compressor = None

                break
            else:
                _return = self.compressor.compress(Binary.bytes(_return))

                # Feed compressor object with data until it returns at least one byte
                if (len(_return) < 1): _return = self._wrapped_resource.read(self.io_chunk_size)
                else: is_data_uncompressed = False
            #
        #

        return _return
Example #14
0
    def set_data_attributes(self, **kwargs):
        """
Sets values given as keyword arguments to this method.

:since: v0.2.00
        """

        with self:
            MpEntry.set_data_attributes(self, **kwargs)

            if ("artist" in kwargs): self.local.db_instance.artist = Binary.utf8(kwargs['artist'])
            if ("description" in kwargs): self.local.db_instance.description = Binary.utf8(kwargs['description'])
            if ("width" in kwargs): self.local.db_instance.width = kwargs['width']
            if ("height" in kwargs): self.local.db_instance.height = kwargs['height']
            if ("bpp" in kwargs): self.local.db_instance.bpp = kwargs['bpp']
            if ("creator" in kwargs): self.local.db_instance.creator = Binary.utf8(kwargs['creator'])
Example #15
0
    def _handle_mime_part_headers(self, mime_part_id, data):
        """
Handles MIME part header.

:param mime_part_id: MIME part ID
:param data: Data read from input

:since: v1.0.0
        """

        mime_headers = Header.get_headers(Binary.str(data))

        if (mime_part_id not in self.parts):
            part_position = len(self.parts)
            self.parts[mime_part_id] = { "headers": mime_headers, "position": part_position }
        elif ("list" in self.parts[mime_part_id]): self.parts[mime_part_id]['list'].append({ "headers": mime_headers })
        else:
            single_mime_part = { "headers": self.parts[mime_part_id]['headers'] }
            if ("data" in self.parts[mime_part_id]): single_mime_part['data'] = self.parts[mime_part_id]['data']

            self.parts[mime_part_id] = { "position": self.parts[mime_part_id]['position'],
                                         "list": [ single_mime_part,
                                                   { "headers": mime_headers }
                                                 ]
                                       }
Example #16
0
    def _add_metadata_to_didl_xml_node(self, xml_resource, xml_node_path, parent_id = None):
        """
Uses the given XML resource to add the DIDL metadata of this UPnP resource.

:param xml_resource: XML resource
:param xml_base_path: UPnP resource XML base path (e.g. "DIDL-Lite
       item")

:since: v0.2.00
        """

        if (self.get_type() & AbstractResource.TYPE_CDS_RESOURCE == AbstractResource.TYPE_CDS_RESOURCE):
            attributes = { }
            didl_fields = self.get_didl_fields()
            res_protocol = self.get_didl_res_protocol()
            size = self.get_size()

            if (res_protocol is not None): attributes['protocolInfo'] = res_protocol
            if (size is not None): attributes['size'] = size

            didl_fields_filtered = (len(didl_fields) > 0)

            metadata = self.get_metadata()

            for key in metadata:
                if ((not didl_fields_filtered) or "res@{0}".format(key) in didl_fields): attributes[key] = metadata[key]
            #

            url = Binary.str(self.get_content(0))
            value = (url if (type(url) is str) else "")

            xml_resource.add_node(xml_node_path, value, attributes)
Example #17
0
    def compress(self, string):
        """
python.org: Compress string, returning a string containing compressed data
for at least part of the data in string.

:param string: Original string

:return: (bytes) Compressed string
:since:  v1.0.0
        """

        if (self.compressor is None): raise IOException("Gzip compressor already flushed and closed")
        data = Binary.bytes(string)

        if (self.size is None): compressed_data = self.compressor.compress(data)
        else:
            self.crc32 = (crc32(data) if (self.crc32 is None) else crc32(data, self.crc32))
            self.size += len(data)

            compressed_data = (self.compressor.compress(data) if (self.header is None) else self.compressor.compress(data)[2:])
        #

        if (self.header is None): _return = compressed_data
        else:
            _return = self.header + compressed_data
            self.header = None
        #

        return _return
Example #18
0
    def __init__(self, level = 6):
        """
Constructor __init__(GzipCompressor)

:since: v1.0.0
        """

        self.compressor = None
        """
Deflate compressor instance
        """
        self.crc32 = None
        """
CRC32 from previous run
        """
        self.header = None
        """
Gzip header
        """
        self.size = None
        """
Total size of compressed data
        """

        # Use the zlib magic +16 to generate the GZip header and trailer on flush() if supported
        try: self.compressor = compressobj(level, wbits = 16 + MAX_WBITS)
        except TypeError:
            self.compressor = compressobj(level)

            if (level == 9): deflate_flag = 2
            elif (level == 1): deflate_flag = 4
            else: deflate_flag = 0

            self.header = pack("<8s2B", Binary.bytes("\x1f\x8b" + ("\x00" if (level == 0) else "\x08") + "\x00\x00\x00\x00\x00"), deflate_flag, 255)
            self.size = 0
Example #19
0
    def write_data(self, data):
        """
Write data to the socket.

:param data: Data to be written

:return: (bool) True on success
:since:  v0.2.00
        """

        # pylint: disable=broad-except

        _return = True

        data = Binary.bytes(data)

        if (self.socket is not None and len(data) > 0):
            try: self.socket.sendall(data)
            except Exception as handled_exception:
                if (self.log_handler is not None): self.log_handler.error(handled_exception, context = "pas_server")
                _return = False
            #
        #

        return _return
    def __init__(self, url, gst_stream_metadata):
        """
Constructor __init__(GstAudioStreamMetadata)

:since: v0.2.00
        """

        # pylint: disable=star-args

        mimetype_definition = MimeType.get_instance().get(mimetype = gst_stream_metadata['codec'])
        if (mimetype_definition is None): mimetype_definition = { "type": gst_stream_metadata['codec'], "class": gst_stream_metadata['codec'].split("/", 1)[0] }
        if (mimetype_definition['class'] != "audio"): LogLine.debug("Metadata '{0}' do not correspond to audio".format(mimetype_definition['type']), context = "pas_media")

        kwargs = { }

        kwargs['codec'] = gst_stream_metadata['codec']
        if (gst_stream_metadata['bitrate'] > 0): kwargs['bitrate'] = gst_stream_metadata['bitrate']
        if (gst_stream_metadata['bits_per_sample'] > 0): kwargs['bps'] = gst_stream_metadata['bits_per_sample']
        if (gst_stream_metadata['channels'] > 0): kwargs['channels'] = gst_stream_metadata['channels']

        if ("profile" in gst_stream_metadata):
        #
            profile = Binary.str(gst_stream_metadata['profile']).lower()
            if ("level" in gst_stream_metadata): profile += "-{0}".format(gst_stream_metadata['level'].lower())
            kwargs['codec_profile'] = profile
        #
        elif ("format" in gst_stream_metadata): kwargs['codec_profile'] = gst_stream_metadata['format'].lower()

        if ("language-code" in gst_stream_metadata['tags']): kwargs['lang'] = GstMetadataMixin._parse_tag(gst_stream_metadata['tags']['language-code'])
        kwargs['mimeclass'] = mimetype_definition['class']
        kwargs['mimetype'] = mimetype_definition['type']
        if (gst_stream_metadata['sample_rate'] > 0): kwargs['sample_rate'] = gst_stream_metadata['sample_rate']

        AudioStreamMetadata.__init__(self, url, **kwargs)
Example #21
0
    def parse(self):
        """
Parses the content of the request body.

:since: v1.0.0
        """

        byte_buffer = self.get_buffer()

        field_arrays = { }

        parsed_fields = ([ ]
                         if (byte_buffer is None or byte_buffer.size < 1) else
                         parse_qsl(Binary.str(byte_buffer.read()), True, True)
                        )

        for parsed_field in parsed_fields:
            re_result = Urlencoded.RE_ARRAY.match(parsed_field[0])

            if (re_result is None): self.parsed_data[parsed_field[0]] = parsed_field[1]
            elif (re_result.group(1) in field_arrays): field_arrays[re_result.group(1)].append({ "key": re_result.group(2), "value": parsed_field[1] })
            else: field_arrays[re_result.group(1)] = [ { "key": re_result.group(2), "value": parsed_field[1] } ]
        #

        for field in field_arrays:
            element_position = 0
            if (field in self.parsed_data): field_arrays[field].insert(0, self.parsed_data[field])
            self.parsed_data[field] = { }

            for element in field_arrays[field]:
                if (len(element['key']) > 0): self.parsed_data[field][element['key']] = element['value']
                else:
                    self.parsed_data[field][element_position] = element['value']
                    element_position += 1
Example #22
0
    def theme(self, theme):
        """
Sets the theme to use.

:param theme: Output theme

:since: v1.0.0
        """

        theme = Binary.str(theme)

        """
Set theme or reset to None to use the default one configured
        """

        if (theme is None): self._theme = None
        else:
            theme_path = InputFilter.filter_file_path(theme).replace(".", path.sep)
            file_path_name = path.join(self.path, theme_path, "site.tsc")

            if (os.access(file_path_name, os.R_OK)): self._theme = theme
            else: self._theme = None
        #

        """
Read corresponding theme configuration
        """

        if (self._theme is None): file_path_name = path.join(self.path, self.theme.replace(".", path.sep), "site.tsc")

        file_path_name = file_path_name[:-3] + "json"
        Settings.read_file(file_path_name)
Example #23
0
    def handle_result(self, urn, action, result):
        """
Returns a UPNP response for the given URN and SOAP action.

:param urn: UPnP URN called
:param action: SOAP action called
:param result: UPnP result arguments

:since: v0.2.00
        """

        if (isinstance(result, Exception)):
            if (isinstance(result, UpnpException)): self.send_error(result.get_upnp_code(), "{0:l10n_message}".format(result))
            else: self.send_error(501, L10n.get("errors_core_unknown_error"))
        else:
            xml_resource = XmlResource(node_type = OrderedDict)

            client_settings = self.get_client_settings()
            if (not client_settings.get("upnp_xml_cdata_encoded", False)): xml_resource.set_cdata_encoding(False)

            xml_resource.add_node("s:Envelope", attributes = { "xmlns:s": "http://schemas.xmlsoap.org/soap/envelope/", "s:encodingStyle": "http://schemas.xmlsoap.org/soap/encoding/" })

            xml_base_path = "s:Envelope s:Body u:{0}Response".format(action)
            xml_resource.add_node(xml_base_path, attributes = { "xmlns:u": urn })
            xml_resource.set_cached_node(xml_base_path)

            for result_value in result: xml_resource.add_node("{0} {1}".format(xml_base_path, result_value['name']), result_value['value'])

            self.data = Binary.utf8_bytes("<?xml version='1.0' encoding='UTF-8' ?>{0}".format(xml_resource.export_cache(True)))
Example #24
0
    def send_error(self, code, description):
        """
Returns a UPNP response for the requested SOAP action.

:param code: UPnP error code
:param description: UPnP error description

:since: v0.2.00
        """

        xml_resource = XmlResource()

        xml_resource.add_node("s:Envelope", attributes = { "xmlns:s": "http://schemas.xmlsoap.org/soap/envelope/", "s:encodingStyle": "http://schemas.xmlsoap.org/soap/encoding/" })

        xml_resource.add_node("s:Envelope s:Body s:Fault faultcode", "Client")
        xml_resource.set_cached_node("s:Envelope s:Body")

        xml_resource.add_node("s:Envelope s:Body s:Fault faultstring", "UPnPError")
        xml_resource.add_node("s:Envelope s:Body s:Fault detail UPnPError", attributes = { "xmlns": "urn:schemas-upnp-org:control-1.0" })
        xml_resource.set_cached_node("s:Envelope s:Body s:Fault detail UPnPError")

        xml_resource.add_node("s:Envelope s:Body s:Fault detail UPnPError errorCode", code)
        xml_resource.add_node("s:Envelope s:Body s:Fault detail UPnPError errorDescription", description)

        self.data = Binary.utf8_bytes("<?xml version='1.0' encoding='UTF-8' ?>{0}".format(xml_resource.export_cache(True)))
        self.send()
Example #25
0
    def _get_hook_proxy_params(self, hook, timeout = None, kwargs = None):
        """
Returns serializable parameters for the persistent proxy.

:param hook: Task hook to be called
:param timeout: Timeout in seconds; None to use global task timeout
:param kwargs: Keyword arguments

:return: (dict)
:since:  v0.2.00
        """

        _return = { }

        if (isinstance(hook, PersistentLrtHook)):
            _return['hook'] = hook.get_hook()

            _return['kwargs'] = ({ } if (kwargs is None) else kwargs)
            _return['kwargs'].update(hook.get_params())
            _return['kwargs']['_lrt_hook'] = True
        else:
            hook = Binary.str(hook)
            if (type(hook) is not str): raise TypeException("Hook given is invalid")

            _return['hook'] = hook
            if (kwargs is not None): _return['kwargs'] = kwargs
        #

        if (timeout is not None): _return['timeout'] = timeout

        return _return
Example #26
0
    def prepare_socket(listener_type, *listener_data):
        """
Prepare socket returns a bound socket for the given listener data.

:param listener_type: Listener type
:param listener_data: Listener data

:since: v0.2.00
        """

        _return = None

        if (listener_type == socket.AF_INET or listener_type == socket.AF_INET6):
            listener_data = ( Binary.str(listener_data[0]), listener_data[1] )

            _return = socket.socket(listener_type, socket.SOCK_STREAM)
            _return.setblocking(0)
            if (hasattr(socket, "SO_REUSEADDR")): _return.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            _return.bind(listener_data)
        elif (listener_type == socket.AF_UNIX):
            unixsocket_path_name = path.normpath(Binary.str(listener_data[0]))
            if (os.access(unixsocket_path_name, os.F_OK)): os.unlink(unixsocket_path_name)

            _return = socket.socket(listener_type, socket.SOCK_STREAM)
            if (hasattr(socket, "SO_REUSEADDR")): _return.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            _return.bind(unixsocket_path_name)

            socket_chmod = 0
            socket_chmod_value = int(Settings.get("pas_global_server_chmod_unix_sockets", "600"), 8)

            if ((1000 & socket_chmod_value) == 1000): socket_chmod |= stat.S_ISVTX
            if ((2000 & socket_chmod_value) == 2000): socket_chmod |= stat.S_ISGID
            if ((4000 & socket_chmod_value) == 4000): socket_chmod |= stat.S_ISUID
            if ((0o100 & socket_chmod_value) == 0o100): socket_chmod |= stat.S_IXUSR
            if ((0o200 & socket_chmod_value) == 0o200): socket_chmod |= stat.S_IWUSR
            if ((0o400 & socket_chmod_value) == 0o400): socket_chmod |= stat.S_IRUSR
            if ((0o010 & socket_chmod_value) == 0o010): socket_chmod |= stat.S_IXGRP
            if ((0o020 & socket_chmod_value) == 0o020): socket_chmod |= stat.S_IWGRP
            if ((0o040 & socket_chmod_value) == 0o040): socket_chmod |= stat.S_IRGRP
            if ((0o001 & socket_chmod_value) == 0o001): socket_chmod |= stat.S_IXOTH
            if ((0o002 & socket_chmod_value) == 0o002): socket_chmod |= stat.S_IWOTH
            if ((0o004 & socket_chmod_value) == 0o004): socket_chmod |= stat.S_IROTH

            os.chmod(unixsocket_path_name, socket_chmod)
        #

        return _return
    def chunkify(self, data):
        """
Returns the formats the client accepts.

:return: (list) Accepted formats
:since:  v1.0.0
        """

        data = Binary.bytes(data)

        if (data is None): _return = Binary.bytes("0\r\n\r\n")
        elif (type(data) is type(ChunkedReaderMixin.BINARY_NEWLINE)
              and len(data) > 0
             ): _return = Binary.bytes("{0:x}\r\n".format(len(data))) + data + ChunkedReaderMixin.BINARY_NEWLINE
        else: _return = Binary.BYTES_TYPE()

        return _return
    def data(self):
        """
Returns buffered data to be transmitted.

:return: (bytes) Data to be send
:since:  v1.0.0
        """

        return Binary.bytes(JsonResource().data_to_json(self.result))
Example #29
0
    def save(self):
        """
Saves changes of the database task instance.

:since: v0.2.00
        """

        with self:
            self.local.db_instance.tid = Binary.utf8(Md5.hash(self.tid))
            self.params['_tid'] = self.tid

            if (self.local.db_instance.name == ""): self.local.db_instance.name = Binary.utf8(self.hook[-100:])
            if (self.local.db_instance.status is None): self.local.db_instance.status = DatabaseTask.STATUS_WAITING
            self.local.db_instance.hook = Binary.utf8(self.hook)
            self.local.db_instance.params = Binary.utf8(JsonResource().data_to_json(self.params))
            self.local.db_instance.time_updated = int(time())

            Instance.save(self)
    def data(self):
        """
Returns buffered data to be transmitted.

:return: (bytes) Data to be send
:since:  v1.0.0
        """

        return Binary.utf8_bytes(self._data)
Example #31
0
    def unmarshal(data):
        """
Unmarshals a D-Bus message and returns a Message instance.

:param data: Wire-formatted data

:return: (object) Message instance
:since:  v0.2.00
        """

        # pylint: disable=protected-access

        data = Binary.bytes(data)
        data_size = len(data)
        if (data_size < 16): raise IOException("D-Bus message is invalid")

        header = [ Message.unmarshal_data("y", data[:1]) ]
        is_le = (Binary.str(header[0]) == "l")
        header += Message.unmarshal_data("yyyuu", data[:12], is_le, 1)

        header_size = 12
        body_size = header[4]

        header_size += Message.get_marshaled_data_size("a(yv)", data, is_le, 12)
        if (header_size > data_size): raise IOException("D-Bus message is invalid (calculated header size < size)")

        header_fields = Message.unmarshal_data("a(yv)", data[:header_size], is_le, 12)

        if (header_size + body_size > data_size): raise IOException("D-Bus message truncated")
        elif (header_size + body_size < data_size): raise IOException("D-Bus message is invalid (calculated message size < size)")

        _return = Message(header[1])
        _return.set_flags(unpack(("<" if (is_le) else ">") + "B", header[2])[0])
        _return.set_serial(header[5])

        for header_field in header_fields: _return._set_header_field(header_field[0], header_field[1])

        if (body_size > 0):
            body_signature = _return.get_body_signature()
            if (body_signature is None): raise IOException("D-Bus message contains a body without a signature header")
            _return.set_body(Message.unmarshal_data(body_signature, data, is_le, header_size))
        #

        return _return
Example #32
0
    def set_data_attributes(self, **kwargs):
        """
Sets values given as keyword arguments to this method.

:since: v0.2.00
        """

        with self:
            if ("name" in kwargs):
                self.local.db_instance.name = Binary.utf8(kwargs['name'])
            if ("permitted" in kwargs):
                self.local.db_instance.permitted = kwargs['permitted']
Example #33
0
    def unset_permission(self, name):
        """
Unsets the permission with the specified name.

:since: v0.2.00
        """

        name = Binary.str(name)
        if (self.log_handler is not None): self.log_handler.debug("#echo(__FILEPATH__)# -{0!r}.set_permission({1})- (#echo(__LINE__)#)", self, name, context = "pas_database")

        self._ensure_thread_local_permission_cache()

        with self:
            if (self.local.permission_cache is not None
                and name in self.local.permission_cache
               ):
                self.remove_permission(Permission(self.local.permission_cache[name]['db_instance']))
                del(self.local.permission_cache[name])
Example #34
0
    def set_permission(self, name, permitted = True):
        """
Sets the permission with the specified name.

:since: v0.2.00
        """

        name = Binary.str(name)
        if (self.log_handler is not None): self.log_handler.debug("#echo(__FILEPATH__)# -{0!r}.set_permission({1})- (#echo(__LINE__)#)", self, name, context = "pas_database")

        self._ensure_thread_local_permission_cache()

        with self:
            if (self.local.permission_cache is None): self._init_permission_cache()

            if (name not in self.local.permission_cache):
                permission = Permission()
                permission.set_data_attributes(name = name, permitted = permitted)

                self.add_permission(permission)
                self.local.permission_cache[name] = { "permitted": permitted, "db_instance": permission }