Esempio n. 1
0
    def render_POST(self, request):
        response = {}

        logger.info('Received a new request from the client')
        try :
            # process the message encoding
            encoding = request.getHeader('Content-Type')
            data = request.content.read()
            if encoding == 'application/json' :

                try:
                    input_json_str = json.loads(data.decode('utf-8'))
                    input_json = json.loads(input_json_str)
                    jrpc_id = input_json["id"]
                    response = self._process_request(input_json_str)

                except AttributeError:
                    logger.error("Error while loading input json")
                    response = utility.create_error_response(
                        WorkorderError.UNKNOWN_ERROR,
                        jrpc_id,
                        "UNKNOWN_ERROR: Error while loading the input JSON file")
                    return response

            else :
                # JRPC response with 0 as id is returned because id can't be fecthed
                # from a request with unknown encoding
                response = utility.create_error_response(
                        WorkorderError.UNKNOWN_ERROR,
                        0,
                        "UNKNOWN_ERROR: unknown message encoding")
                return response

        except :
            logger.exception('exception while decoding http request %s', request.path)
            # JRPC response with 0 as id is returned because id can't be
            # fetched from improper request
            response = utility.create_error_response(
                    WorkorderError.UNKNOWN_ERROR,
                    0,
                    "UNKNOWN_ERROR: unable to decode incoming request")
            return response

        # send back the results
        try :
            if encoding == 'application/json' :
                response = json.dumps(response)
            logger.info('response[%s]: %s', encoding, response)
            request.setHeader('content-type', encoding)
            request.setResponseCode(http.OK)
            return response.encode('utf8')

        except :
            logger.exception('unknown exception while processing request %s', request.path)
            response = utility.create_error_response(
                    WorkorderError.UNKNOWN_ERROR,
                    jrpc_id,
                    "UNKNOWN_ERROR: unknown exception processing http \
                    request {0}".format(request.path))
            return response
Esempio n. 2
0
    def render_POST(self, request):
        response = ""

        logger.info('Received a new request from the client')

        try:
            # Process the message encoding
            encoding = request.getHeader('Content-Type')
            data = request.content.read().decode('utf-8')

            if encoding == 'text/plain; charset=utf-8':
                response = self._process_request(data)
            else:
                response = 'UNKNOWN_ERROR: unknown message encoding'
                return response

        except:
            logger.exception('exception while decoding http request %s',
                             request.path)
            response = 'UNKNOWN_ERROR: unable to decode incoming request '
            return response

        # Send back the results
        try:
            logger.info('response[%s]: %s', encoding, response.encode('utf-8'))
            request.setHeader('content-type', encoding)
            request.setResponseCode(http.OK)
            return response.encode('utf-8')

        except:
            logger.exception('unknown exception while processing request %s',
                             request.path)
            response = 'UNKNOWN_ERROR: unknown exception processing ' + \
                'http request {0}'.format(request.path)
            return response
Esempio n. 3
0
 def got_item(ch):
     if ch is not None:
         request.setResponseCode(200)
         file = ch.get_cover()
         if file and os.path.exists(file):
             self.info("got cover %s", file)
             return StaticFile(file)
     request.setResponseCode(404)
     return static.Data(
         '<html><p>cover requested not found</p></html>',
         'text/html')
Esempio n. 4
0
    def render_POST(self, request):
        response = {}
        response['error'] = {}
        response['error']['code'] = WorkorderError.UNKNOWN_ERROR

        logger.info('Received a new request from the client')

        try:
            # process the message encoding
            encoding = request.getHeader('Content-Type')
            data = request.content.read()

            if encoding == 'application/json':

                try:
                    input_json = json.loads(data.decode('utf-8'))
                    response = self._process_request(input_json)

                except AttributeError:
                    logger.error("Error while loading input json")
                    response['error'][
                        'message'] = 'UNKNOWN_ERROR: Error while loading the input JSON file'
                    return response

            else:
                response['error'][
                    'message'] = 'UNKNOWN_ERROR: unknown message encoding'
                return response

        except:
            logger.exception('exception while decoding http request %s',
                             request.path)
            response['error'][
                'message'] = 'UNKNOWN_ERROR: unable to decode incoming request '
            return response

        # send back the results
        try:
            if encoding == 'application/json':
                response = json.dumps(response)

            logger.info('response[%s]: %s', encoding, response)
            request.setHeader('content-type', encoding)
            request.setResponseCode(http.OK)
            return response.encode('utf8')

        except:
            logger.exception('unknown exception while processing request %s',
                             request.path)
            response['error'][
                'message'] = 'UNKNOWN_ERROR: unknown exception processing http request {0}'.format(
                    request.path)
            return response
Esempio n. 5
0
 def render_GET(self, request):
     global config
     debug("Request '%s'" % request.uri.decode("utf-8"))
     try:
         resp = urllib.request.urlopen(
             'http://%s:%d%s' %
             (config['mip']['host'], int(config['mip']['port']),
              fixPaths(request.uri, 'lms', 'mip').decode("utf-8"))).read()
         return fixPaths(resp, 'mip', 'lms')
     except urllib.error.HTTPError as e:
         request.setResponseCode(e.code)
         return e.read()
Esempio n. 6
0
 def got_file(ch):
     print("ch", ch)
     if ch is not None:
         if hasattr(self.store, 'backend_import'):
             response_code = self.store.backend_import(
                 ch, request.content)
             if isinstance(response_code, defer.Deferred):
                 return response_code
             request.setResponseCode(response_code)
             return
     else:
         request.setResponseCode(404)
Esempio n. 7
0
    def render_GET(self, request):
        self.info(f'render GET {request}')
        request.setResponseCode(200)
        if self.contentType is not None:
            request.setHeader(b'Content-Type', self.contentType)
        request.write(b'')

        headers = request.getAllHeaders()
        if ('connection' in headers and headers['connection'] == 'close'):
            pass

        self.start(request)
        return server.NOT_DONE_YET
Esempio n. 8
0
    def render_GET(self, request):
        self.info('render GET %r', request)
        request.setResponseCode(200)
        if hasattr(self, 'contentType'):
            request.setHeader('Content-Type', self.contentType)
        request.write('')

        headers = request.getAllHeaders()
        if ('connection' in headers and headers['connection'] == 'close'):
            pass

        self.start(request)
        return server.NOT_DONE_YET
Esempio n. 9
0
 def got_stuff_to_transcode(ch):
     #FIXME create a generic transcoder class and sort the details there
     format = request.uri.split('/')[
         -1]  # request.args['transcoded'][0]
     uri = ch.get_path()
     try:
         from coherence.transcoder import TranscoderManager
         manager = TranscoderManager(self.server.coherence)
         return manager.select(format, uri)
     except:
         self.debug(traceback.format_exc())
         request.setResponseCode(404)
         return static.Data(
             '<html><p>the requested transcoded file was not found</p></html>',
             'text/html')
Esempio n. 10
0
    def got_streams(streams):
      if self.stream_id not in streams:
        self.warning("stream not found for %s@%s", self.url, self.stream_id)
        request.setResponseCode(http.NOT_FOUND)
        request.write('')
        return

      request.setHeader('Content-Type', self.content_type)
      request.setResponseCode(http.OK)

      if request.method == 'HEAD':
        request.write('')
        return

      d_open_stream = threads.deferToThread(streams[self.stream_id].open)
      d_open_stream.addCallback(stream_opened)
Esempio n. 11
0
        def got_streams(streams):
            if self.stream_id not in streams:
                self.warning(f'stream not found for '
                             f'{self.url}@{self.stream_id}')
                request.setResponseCode(http.NOT_FOUND)
                request.write(b'')
                return

            request.setHeader(b'Content-Type',
                              self.content_type.encode('ascii'))
            request.setResponseCode(http.OK)

            if request.method == b'HEAD':
                request.write(b'')
                return

            d_open_stream = threads.deferToThread(streams[self.stream_id].open)
            d_open_stream.addCallback(stream_opened)
Esempio n. 12
0
    def render_GET(self, request):
        self.info(f'render GET {request}')
        request.setResponseCode(200)
        if hasattr(self, 'contentType'):
            request.setHeader(b'Content-Type', self.contentType)
        request.write(b'')

        headers = request.getAllHeaders()
        if ('connection' in headers and headers['connection'] == 'close'):
            pass
        if self.requests:
            if self.streamheader:
                self.debug('writing streamheader')
                for h in self.streamheader:
                    request.write(h.data)
            self.requests.append(request)
        else:
            self.parse_pipeline()
            self.start(request)
        return server.NOT_DONE_YET
Esempio n. 13
0
                def got_attachment(ch):
                    try:
                        # FIXME same as below
                        if 'transcoded' in request.args:
                            if (
                                self.server.coherence.config.get(
                                    'transcoding', 'no'
                                )
                                == 'yes'
                            ):
                                format = request.args['transcoded'][0]
                                type = request.args['type'][0]
                                self.info(
                                    f'request transcoding {format} {type}'
                                )
                                try:
                                    from coherence.transcoder import (
                                        TranscoderManager,
                                    )

                                    manager = TranscoderManager(
                                        self.server.coherence
                                    )
                                    return manager.select(
                                        format,
                                        ch.item.attachments[
                                            request.args['attachment'][0]
                                        ],
                                    )
                                except Exception:
                                    self.debug(traceback.format_exc())
                                request.setResponseCode(404)
                                return static.Data(
                                    b'<html><p>the requested transcoded file '
                                    b'was not found</p></html>',
                                    'text/html',
                                )
                            else:
                                request.setResponseCode(404)
                                return static.Data(
                                    b'<html><p>This MediaServer '
                                    b'doesn\'t support transcoding</p></html>',
                                    'text/html',
                                )
                        else:
                            return ch.item.attachments[
                                request.args['attachment'][0]
                            ]
                    except Exception:
                        request.setResponseCode(404)
                        return static.Data(
                            b'<html><p>the requested attachment '
                            b'was not found</p></html>',
                            'text/html',
                        )
Esempio n. 14
0
 def got_attachment(ch):
     try:
         #FIXME same as below
         if 'transcoded' in request.args:
             if self.server.coherence.config.get(
                     'transcoding', 'no') == 'yes':
                 format = request.args['transcoded'][0]
                 type = request.args['type'][0]
                 self.info("request transcoding %r %r", format,
                           type)
                 try:
                     from coherence.transcoder import TranscoderManager
                     manager = TranscoderManager(
                         self.server.coherence)
                     return manager.select(
                         format, ch.item.attachments[
                             request.args['attachment'][0]])
                 except:
                     self.debug(traceback.format_exc())
                 request.setResponseCode(404)
                 return static.Data(
                     '<html><p>the requested transcoded file was not found</p></html>',
                     'text/html')
             else:
                 request.setResponseCode(404)
                 return static.Data(
                     "<html><p>This MediaServer doesn't support transcoding</p></html>",
                     'text/html')
         else:
             return ch.item.attachments[
                 request.args['attachment'][0]]
     except:
         request.setResponseCode(404)
         return static.Data(
             '<html><p>the requested attachment was not found</p></html>',
             'text/html')
Esempio n. 15
0
    def getChildWithDefault(self, path, request):
        self.info(
            f'{self.server.device_type} getChildWithDefault, '
            f'{request.method}, {path}, {request.uri} {request.client}'
        )
        headers = request.getAllHeaders()
        self.debug(f'\t-> headers are: {headers}')
        if not isinstance(path, bytes):
            path = path.encode('ascii')
        if path.endswith(b'\''):
            self.warning(f'\t modified wrong path from {path} to {path[:-1]}')
            path = path[:-1]
        self.debug(f'\t-> path is: {path} [{type(path)}]')

        try:
            if (
                b'getcontentfeatures.dlna.org' in headers
                and headers[b'getcontentfeatures.dlna.org'] != b'1'
            ):
                request.setResponseCode(400)
                return static.Data(
                    b'<html><p>wrong value for '
                    b'getcontentFeatures.dlna.org</p></html>',
                    'text/html',
                )
        except Exception as e1:
            self.error(f'MSRoot.getChildWithDefault: {e1}')

        if request.method == b'HEAD':
            if b'getcaptioninfo.sec' in headers:
                self.warning(f'requesting srt file for id {path}')
                ch = self.store.get_by_id(path)
                try:
                    location = ch.get_path()
                    caption = ch.caption
                    if caption is None:
                        raise KeyError
                    request.setResponseCode(200)
                    request.setHeader(b'CaptionInfo.sec', caption)
                    return static.Data(b'', 'text/html')
                except Exception as e2:
                    self.error(
                        f'MSRoot.getChildWithDefault (method: HEAD): {e2}'
                    )
                    print(traceback.format_exc())
                    request.setResponseCode(404)
                    return static.Data(
                        b'<html><p>the requested srt file '
                        b'was not found</p></html>',
                        'text/html',
                    )

        try:
            request._dlna_transfermode = headers[b'transfermode.dlna.org']
        except KeyError:
            request._dlna_transfermode = b'Streaming'
        if request.method in (b'GET', b'HEAD'):
            if COVER_REQUEST_INDICATOR.match(request.uri.decode('utf-8')):
                self.info(f'request cover for id {path}')

                def got_item(ch):
                    if ch is not None:
                        request.setResponseCode(200)
                        file = ch.get_cover()
                        if file and os.path.exists(file):
                            self.info(f'got cover {file}')
                            return StaticFile(file)
                    request.setResponseCode(404)
                    return static.Data(
                        b'<html><p>cover requested not found</p></html>',
                        'text/html',
                    )

                dfr = defer.maybeDeferred(self.store.get_by_id, path)
                dfr.addCallback(got_item)
                dfr.isLeaf = True
                return dfr

            if ATTACHMENT_REQUEST_INDICATOR.match(request.uri.decode('utf-8')):
                self.info(f'request attachment {request.args} for id {path}')

                def got_attachment(ch):
                    try:
                        # FIXME same as below
                        if 'transcoded' in request.args:
                            if (
                                self.server.coherence.config.get(
                                    'transcoding', 'no'
                                )
                                == 'yes'
                            ):
                                format = request.args['transcoded'][0]
                                type = request.args['type'][0]
                                self.info(
                                    f'request transcoding {format} {type}'
                                )
                                try:
                                    from coherence.transcoder import (
                                        TranscoderManager,
                                    )

                                    manager = TranscoderManager(
                                        self.server.coherence
                                    )
                                    return manager.select(
                                        format,
                                        ch.item.attachments[
                                            request.args['attachment'][0]
                                        ],
                                    )
                                except Exception:
                                    self.debug(traceback.format_exc())
                                request.setResponseCode(404)
                                return static.Data(
                                    b'<html><p>the requested transcoded file '
                                    b'was not found</p></html>',
                                    'text/html',
                                )
                            else:
                                request.setResponseCode(404)
                                return static.Data(
                                    b'<html><p>This MediaServer '
                                    b'doesn\'t support transcoding</p></html>',
                                    'text/html',
                                )
                        else:
                            return ch.item.attachments[
                                request.args['attachment'][0]
                            ]
                    except Exception:
                        request.setResponseCode(404)
                        return static.Data(
                            b'<html><p>the requested attachment '
                            b'was not found</p></html>',
                            'text/html',
                        )

                dfr = defer.maybeDeferred(self.store.get_by_id, path)
                dfr.addCallback(got_attachment)
                dfr.isLeaf = True
                return dfr

        if request.method in (
            b'GET',
            b'HEAD',
        ) and TRANSCODED_REQUEST_INDICATOR.match(request.uri.decode('utf-8')):
            self.info(
                f'request transcoding to '
                f'{request.uri.split(b"/")[-1]} for id {path}'
            )
            if self.server.coherence.config.get('transcoding', 'no') == 'yes':

                def got_stuff_to_transcode(ch):
                    # FIXME create a generic transcoder class
                    # and sort the details there
                    format = request.uri.split(b'/')[
                        -1
                    ]  # request.args['transcoded'][0]
                    uri = ch.get_path()
                    try:
                        from coherence.transcoder import TranscoderManager

                        manager = TranscoderManager(self.server.coherence)
                        return manager.select(format, uri)
                    except Exception:
                        self.debug(traceback.format_exc())
                        request.setResponseCode(404)
                        return static.Data(
                            b'<html><p>the requested transcoded file '
                            b'was not found</p></html>',
                            'text/html',
                        )

                dfr = defer.maybeDeferred(self.store.get_by_id, path)
                dfr.addCallback(got_stuff_to_transcode)
                dfr.isLeaf = True
                return dfr

            request.setResponseCode(404)
            return static.Data(
                b'<html><p>This MediaServer '
                b'doesn\'t support transcoding</p></html>',
                'text/html',
            )

        if request.method == b'POST' and request.uri.endswith(b'?import'):
            d = self.import_file(path, request)
            if isinstance(d, defer.Deferred):
                d.addBoth(self.import_response, path)
                d.isLeaf = True
                return d
            return self.import_response(None, path)

        if (
            b'user-agent' in headers
            and (
                headers[b'user-agent'].find(b'Xbox/') in [0, None]
                or headers[b'user-agent'].startswith(  # XBox  # wmp11
                    b'''Mozilla/4.0 (compatible; UPnP/1.0; Windows'''
                )
            )
            and path in [b'description-1.xml', b'description-2.xml']
        ):
            self.info(
                'XBox/WMP alert, we need to '
                'simulate a Windows Media Connect server'
            )
            if b'xbox-description-1.xml' in self.children:
                self.msg('returning xbox-description-1.xml')
                return self.children[b'xbox-description-1.xml']

        # resource http://XXXX/<deviceID>/config
        # configuration for the given device
        # accepted methods:
        # GET, HEAD:
        #       returns the configuration data (in XML format)
        # POST: stop the current device and restart it
        #       with the posted configuration data
        if path in (b'config'):
            backend = self.server.backend
            backend_type = backend.__class__.__name__

            def constructConfigData(backend):
                msg = '<plugin active="yes">'
                msg += '<backend>' + to_string(backend_type) + '</backend>'
                for key, value in list(backend.config.items()):
                    msg += (
                        '<' + to_string(key) + '>'
                        + to_string(value)
                        + '</' + to_string(key) + '>'
                    )
                msg += '</plugin>'
                return to_bytes(msg)

            if request.method in (b'GET', b'HEAD'):
                # the client wants to retrieve the
                #  configuration parameters for the backend
                msg = constructConfigData(backend)
                request.setResponseCode(200)
                return static.Data(msg, 'text/xml')
            elif request.method in (b'POST'):
                # the client wants to update the configuration parameters
                # for the backend we relaunch the backend with the
                # new configuration (after content validation)

                def convert_elementtree_to_dict(root):
                    active = False
                    for name, value in list(root.items()):
                        if name == 'active':
                            if value in ('yes'):
                                active = True
                        break
                    if active is False:
                        return None
                    dict = {}
                    for element in root.getchildren():
                        key = element.tag
                        text = element.text
                        if key != 'backend':
                            dict[key] = text
                    return dict

                new_config = None
                try:
                    element_tree = etree.fromstring(request.content.getvalue())
                    new_config = convert_elementtree_to_dict(element_tree)
                    self.server.coherence.remove_plugin(self.server)
                    self.warning(
                        f'{backend.name} {self.server.device_type} ({backend})'
                        f' with id {str(self.server.uuid)[5:]} deactivated'
                    )
                    if new_config is None:
                        msg = '<plugin active="no"/>'
                    else:
                        new_backend = self.server.coherence.add_plugin(
                            backend_type, **new_config
                        )
                        if self.server.coherence.writeable_config():
                            self.server.coherence.store_plugin_config(
                                new_backend.uuid, new_config
                            )
                            msg = (
                                '<html><p>Device restarted. Config file '
                                + 'has been modified with posted data.</p>'
                                + '</html>'
                            )  # constructConfigData(new_backend)
                        else:
                            msg = (
                                '<html><p>Device restarted. '
                                + 'Config file not modified</p>'
                                + '</html>'
                            )  # constructConfigData(new_backend)
                    request.setResponseCode(202)
                    return static.Data(msg.encode('ascii'), 'text/html')
                except SyntaxError as e:
                    request.setResponseCode(400)
                    return static.Data(
                        f'<html>'
                        f'<p>Invalid data posted:<BR>{e}</p>'
                        f'</html>'.encode('ascii'),
                        'text/html',
                    )
            else:
                # invalid method requested
                request.setResponseCode(405)
                return static.Data(
                    b'<html><p>This resource does not allow '
                    + b'the requested HTTP method</p></html>',
                    'text/html',
                )

        if path in self.children:
            return self.children[path]
        if request.uri == b'/':
            return self
        return self.getChild(path, request)
Esempio n. 16
0
    def render(self, request):
        logger.info('in render, request: {request}, post_path is {post_path}',
                    request=request,
                    post_path=request.postpath)
        x_self_string_headers = request.requestHeaders.getRawHeaders(
            'X-Self-String')
        if x_self_string_headers and (self_string in x_self_string_headers):
            logger.info('called by self, returning 302')
            request.setResponseCode(302)
            return 'ok'.encode()

        # we have support for setting time for testing purposes
        x_time_for_testing = request.requestHeaders.getRawHeaders(
            'X-Testing-Time')
        if ('True' == config.get('Testing')) and x_time_for_testing:
            x_time_for_testing = float(x_time_for_testing[0])
            logger.info(
                'In testing and current time is being overridden with {time}',
                time=x_time_for_testing)
            set_current_time_for_testing(x_time_for_testing)

        content_type_headers = request.requestHeaders.getRawHeaders(
            'content-type')
        if content_type_headers and ('application/json'
                                     in content_type_headers):
            try:
                data = json.load(request.content)
            except json.JSONDecodeError:
                logger.error('Passed bad JSON in request: {content}',
                             content=request.content)
                request.setResponseCode(500)
                ret = {"error": "Bad JSON in request"}
                return ret
        else:
            data = request.content.read()
        logger.info('request content: {data}', data=data)

        args = {
            k.decode(): [item for item in v]
            for k, v in request.args.items()
        }

        path = request.path.decode()
        method = request.method.decode()
        path_method = '%s:%s' % (path, method)
        logger.info('{method} {path}', method=method, path=path)
        if method == "OPTIONS":
            request.setResponseCode(204)
            request.responseHeaders.addRawHeader(b"Allow",
                                                 b"OPTIONS, GET, POST")
            request.responseHeaders.addRawHeader(
                b"Access-Control-Allow-Methods", b"GET, POST, OPTIONS")
            request.responseHeaders.addRawHeader(b"Connection", b"Keep-Alive")
            request.responseHeaders.addRawHeader(
                b"Access-Control-Allow-Headers", b"Content-Type")
            # The cross-origin headers were needed for some health provider portal work that isn't happening yet so commented out.
            # before this gets commented back in, the origins should come from config file
            # request.responseHeaders.addRawHeader(b"Access-Control-Allow-Origin", b"*")
            # request.responseHeaders.addRawHeader(b"Vary", b"Origin")
            return b""
        else:
            request.responseHeaders.addRawHeader(b"content-type",
                                                 b"application/json")
            # Commented out until we need it for access to server from locally generated or third party server.
            # before this gets commented back in, the origins should come from config file
            # request.responseHeaders.addRawHeader(b"access-control-allow-origin", b"*")
            if path_method in allowable_methods:
                ret = contacts.execute_route(path, data, args)
                if 'error' in ret:
                    request.setResponseCode(ret.get('status', 400))
                    ret = ret['error']
                    logger.error('error return is {ret}', ret=ret)
                else:
                    # if any values functions in ret, then run then asynchronously and return None here
                    # if they aren't then return ret

                    ret = resolve_all_functions(ret, request)
                    logger.info('legal return is {ret}', ret=ret)
            else:
                request.setResponseCode(402)
                ret = {"error": "no such request"}
                logger.error('return is {ret}', ret=ret)
            if twserver.NOT_DONE_YET != ret:
                return json.dumps(ret).encode()
            else:
                return ret
Esempio n. 17
0
def deferred_result_error(failure, request):
    logger.failure("Logging an uncaught exception", failure=failure)
    request.setResponseCode(400)
    request.write(json.dumps({'error': 'internal error'}).encode())
    request.finish()
    return
Esempio n. 18
0
 def render_HEAD(self, request):
     self.info(f'render HEAD {request}')
     request.setResponseCode(200)
     request.setHeader(b'Content-Type', self.contentType)
     request.write(b'')
Esempio n. 19
0
 def render_HEAD(self, request):
     self.info('render HEAD %r', request)
     request.setResponseCode(200)
     request.setHeader('Content-Type', self.contentType)
     request.write('')
Esempio n. 20
0
    def getChildWithDefault(self, path, request):
        self.info('%s getChildWithDefault, %s, %s, %s %s',
                  self.server.device_type, request.method, path, request.uri,
                  request.client)
        headers = request.getAllHeaders()
        self.msg(request.getAllHeaders())

        try:
            if headers['getcontentfeatures.dlna.org'] != '1':
                request.setResponseCode(400)
                return static.Data(
                    '<html><p>wrong value for getcontentFeatures.dlna.org</p></html>',
                    'text/html')
        except:
            pass

        if request.method == 'HEAD':
            if 'getcaptioninfo.sec' in headers:
                self.warning("requesting srt file for id %s", path)
                ch = self.store.get_by_id(path)
                try:
                    location = ch.get_path()
                    caption = ch.caption
                    if caption is None:
                        raise KeyError
                    request.setResponseCode(200)
                    request.setHeader('CaptionInfo.sec', caption)
                    return static.Data('', 'text/html')
                except:
                    print(traceback.format_exc())
                    request.setResponseCode(404)
                    return static.Data(
                        '<html><p>the requested srt file was not found</p></html>',
                        'text/html')

        try:
            request._dlna_transfermode = headers['transfermode.dlna.org']
        except KeyError:
            request._dlna_transfermode = 'Streaming'
        if request.method in ('GET', 'HEAD'):
            if COVER_REQUEST_INDICATOR.match(request.uri):
                self.info("request cover for id %s", path)

                def got_item(ch):
                    if ch is not None:
                        request.setResponseCode(200)
                        file = ch.get_cover()
                        if file and os.path.exists(file):
                            self.info("got cover %s", file)
                            return StaticFile(file)
                    request.setResponseCode(404)
                    return static.Data(
                        '<html><p>cover requested not found</p></html>',
                        'text/html')

                dfr = defer.maybeDeferred(self.store.get_by_id, path)
                dfr.addCallback(got_item)
                dfr.isLeaf = True
                return dfr

            if ATTACHMENT_REQUEST_INDICATOR.match(request.uri):
                self.info("request attachment %r for id %s", request.args,
                          path)

                def got_attachment(ch):
                    try:
                        #FIXME same as below
                        if 'transcoded' in request.args:
                            if self.server.coherence.config.get(
                                    'transcoding', 'no') == 'yes':
                                format = request.args['transcoded'][0]
                                type = request.args['type'][0]
                                self.info("request transcoding %r %r", format,
                                          type)
                                try:
                                    from coherence.transcoder import TranscoderManager
                                    manager = TranscoderManager(
                                        self.server.coherence)
                                    return manager.select(
                                        format, ch.item.attachments[
                                            request.args['attachment'][0]])
                                except:
                                    self.debug(traceback.format_exc())
                                request.setResponseCode(404)
                                return static.Data(
                                    '<html><p>the requested transcoded file was not found</p></html>',
                                    'text/html')
                            else:
                                request.setResponseCode(404)
                                return static.Data(
                                    "<html><p>This MediaServer doesn't support transcoding</p></html>",
                                    'text/html')
                        else:
                            return ch.item.attachments[
                                request.args['attachment'][0]]
                    except:
                        request.setResponseCode(404)
                        return static.Data(
                            '<html><p>the requested attachment was not found</p></html>',
                            'text/html')

                dfr = defer.maybeDeferred(self.store.get_by_id, path)
                dfr.addCallback(got_attachment)
                dfr.isLeaf = True
                return dfr

        if request.method in ('GET',
                              'HEAD') and TRANSCODED_REQUEST_INDICATOR.match(
                                  request.uri):
            self.info("request transcoding to %s for id %s",
                      request.uri.split('/')[-1], path)
            if self.server.coherence.config.get('transcoding', 'no') == 'yes':

                def got_stuff_to_transcode(ch):
                    #FIXME create a generic transcoder class and sort the details there
                    format = request.uri.split('/')[
                        -1]  # request.args['transcoded'][0]
                    uri = ch.get_path()
                    try:
                        from coherence.transcoder import TranscoderManager
                        manager = TranscoderManager(self.server.coherence)
                        return manager.select(format, uri)
                    except:
                        self.debug(traceback.format_exc())
                        request.setResponseCode(404)
                        return static.Data(
                            '<html><p>the requested transcoded file was not found</p></html>',
                            'text/html')

                dfr = defer.maybeDeferred(self.store.get_by_id, path)
                dfr.addCallback(got_stuff_to_transcode)
                dfr.isLeaf = True
                return dfr

            request.setResponseCode(404)
            return static.Data(
                "<html><p>This MediaServer doesn't support transcoding</p></html>",
                'text/html')

        if request.method == 'POST' and request.uri.endswith('?import'):
            d = self.import_file(path, request)
            if isinstance(d, defer.Deferred):
                d.addBoth(self.import_response, path)
                d.isLeaf = True
                return d
            return self.import_response(None, path)

        if ('user-agent' in headers
                and (headers['user-agent'].find('Xbox/') == 0 or  # XBox
                     headers['user-agent'].startswith(
                         """Mozilla/4.0 (compatible; UPnP/1.0; Windows"""))
                and  # wmp11
                path in ['description-1.xml', 'description-2.xml']):
            self.info(
                'XBox/WMP alert, we need to simulate a Windows Media Connect server'
            )
            if 'xbox-description-1.xml' in self.children:
                self.msg('returning xbox-description-1.xml')
                return self.children['xbox-description-1.xml']

        # resource http://XXXX/<deviceID>/config
        # configuration for the given device
        # accepted methods:
        # GET, HEAD: returns the configuration data (in XML format)
        # POST: stop the current device and restart it with the posted configuration data
        if path in ('config'):
            backend = self.server.backend
            backend_type = backend.__class__.__name__

            def constructConfigData(backend):
                msg = "<plugin active=\"yes\">"
                msg += "<backend>" + backend_type + "</backend>"
                for key, value in list(backend.config.items()):
                    msg += "<" + key + ">" + value + "</" + key + ">"
                msg += "</plugin>"
                return msg

            if request.method in ('GET', 'HEAD'):
                # the client wants to retrieve the configuration parameters for the backend
                msg = constructConfigData(backend)
                request.setResponseCode(200)
                return static.Data(msg, 'text/xml')
            elif request.method in ('POST'):
                # the client wants to update the configuration parameters for the backend
                # we relaunch the backend with the new configuration (after content validation)

                def convert_elementtree_to_dict(root):
                    active = False
                    for name, value in list(root.items()):
                        if name == 'active':
                            if value in ('yes'):
                                active = True
                        break
                    if active is False:
                        return None
                    dict = {}
                    for element in root.getchildren():
                        key = element.tag
                        text = element.text
                        if key != 'backend':
                            dict[key] = text
                    return dict

                new_config = None
                try:
                    element_tree = etree.fromstring(request.content.getvalue())
                    new_config = convert_elementtree_to_dict(element_tree)
                    self.server.coherence.remove_plugin(self.server)
                    self.warning("%s %s (%s) with id %s desactivated",
                                 backend.name, self.server.device_type,
                                 backend,
                                 str(self.server.uuid)[5:])
                    if new_config is None:
                        msg = "<plugin active=\"no\"/>"
                    else:
                        new_backend = self.server.coherence.add_plugin(
                            backend_type, **new_config)
                        if self.server.coherence.writeable_config():
                            self.server.coherence.store_plugin_config(
                                new_backend.uuid, new_config)
                            msg = "<html><p>Device restarted. Config file has been modified with posted data.</p></html>"  # constructConfigData(new_backend)
                        else:
                            msg = "<html><p>Device restarted. Config file not modified</p></html>"  # constructConfigData(new_backend)
                    request.setResponseCode(202)
                    return static.Data(msg, 'text/html')  # 'text/xml')
                except SyntaxError as e:
                    request.setResponseCode(400)
                    return static.Data(
                        "<html><p>Invalid data posted:<BR>%s</p></html>" % e,
                        'text/html')
            else:
                # invalid method requested
                request.setResponseCode(405)
                return static.Data(
                    "<html><p>This resource does not allow the requested HTTP method</p></html>",
                    'text/html')

        if path in self.children:
            return self.children[path]
        if request.uri == '/':
            return self
        return self.getChild(path, request)