Beispiel #1
0
 def test_dataState(self):
     """
     Test the internal state of the Data object
     """
     self.assert_(hasattr(self.data, "created_time"))
     self.assertEquals(self.data.data, self.text)
     self.assertEquals(self.data.type, http_headers.MimeType("text", "plain"))
     self.assertEquals(self.data.contentType(), http_headers.MimeType("text", "plain"))
Beispiel #2
0
        def check_result(response):
            response = IResponse(response)

            if response.code != responsecode.MULTI_STATUS:
                self.fail("Incorrect response code for PROPFIND (%s != %s)"
                          % (response.code, responsecode.MULTI_STATUS))

            content_type = response.headers.getHeader("content-type")
            if content_type not in (http_headers.MimeType("text", "xml"),
                                    http_headers.MimeType("application", "xml")):
                self.fail("Incorrect content-type for PROPFIND response (%r not in %r)"
                          % (content_type, (http_headers.MimeType("text", "xml"),
                                            http_headers.MimeType("application", "xml"))))

            return davXMLFromStream(response.stream).addCallback(check_xml)
Beispiel #3
0
    def test_multipartMaxSize(self):
        """
        Check that the C{maxSize} parameter makes the parsing raise an
        exception if the data is too big.
        """
        ctype = http_headers.MimeType('multipart', 'form-data',
                                      (('boundary', '---weeboundary'),))
        content = """-----weeboundary\r
Content-Disposition: form-data; name="FileNameOne"; filename="myfilename"\r
Content-Type: text/html\r
\r
my great content wooo
and even more and more\r
-----weeboundary--\r
"""
        root = resource.Resource()
        request = SimpleRequest(
            server.Site(root), "GET", "/",
            http_headers.Headers({'content-type': ctype}), content)

        def cb(res):
            self.assertEquals(
                res.response.description,
                "Maximum length of 10 bytes exceeded.")
        return self.assertFailure(
            server.parsePOSTData(request, maxSize=10),
            http.HTTPError).addCallback(cb)
Beispiel #4
0
 def __init__(self, code, jobj):
     """
     @param jobj: a Python object that can be serialized to JSON.
     """
     Response.__init__(self, code, stream=json.dumps(jobj))
     self.headers.setHeader("content-type",
                            http_headers.MimeType("application", "json"))
    def test_logging(self):
        """
        Test permissions when creating accounting
        """
        class FakeRequest(object):
            def handleContentChunk(self, data):
                pass

            def handleContentComplete(self):
                pass

        # Make log root a file
        channelRequest = HTTPLoggingChannelRequest(HTTPChannel(), queued=1)
        channelRequest.request = FakeRequest()

        channelRequest.gotInitialLine("GET / HTTP/1.1")
        channelRequest.lineReceived("Host:localhost")
        channelRequest.lineReceived("Content-Length:5")
        channelRequest.handleContentChunk("Bogus")
        channelRequest.handleContentComplete()
        channelRequest.writeHeaders(
            200,
            http_headers.Headers({
                "Content-Type":
                http_headers.MimeType('text', 'plain'),
                "Content-Length":
                "4"
            }))
        channelRequest.transport.write("Data")
        channelRequest.finish()
Beispiel #6
0
 def __init__(self, code, element):
     """
     @param xml_responses: an iterable of davxml.Response objects.
     """
     Response.__init__(self, code, stream=element.toxml())
     self.headers.setHeader("content-type",
                            http_headers.MimeType("text", "xml"))
Beispiel #7
0
    def _processingReallyFailed(self, reason, origReason):
        """
        An error occurred when attempting to report an error to the HTTP
        client.
        """
        log.failure("Exception rendering error page", reason)
        log.failure("Original exception", origReason)

        try:
            body = ("<html><head><title>Internal Server Error</title></head>"
                    "<body><h1>Internal Server Error</h1>"
                    "An error occurred rendering the requested page. "
                    "Additionally, an error occurred rendering the error page."
                    "</body></html>")
            response = http.Response(
                responsecode.INTERNAL_SERVER_ERROR,
                {'content-type': http_headers.MimeType('text', 'html')}, body)
            self.writeResponse(response)
        except:
            log.failure(
                "An error occurred.  We tried to report that error.  "
                "Reporting that error caused an error.  "
                "In the process of reporting the error-reporting error to "
                "the client, there was *yet another* error.  Here it is.  "
                "I give up.")
            self.chanRequest.abortConnection()
Beispiel #8
0
    def uploadFile(self,
                   fieldname,
                   filename,
                   mimetype,
                   content,
                   resrc=None,
                   host='foo',
                   path='/'):
        if not resrc:
            resrc = self.root

        ctype = http_headers.MimeType('multipart', 'form-data',
                                      (('boundary', '---weeboundary'), ))

        return self.getResponseFor(resrc,
                                   '/',
                                   headers={
                                       'host': 'foo',
                                       'content-type': ctype
                                   },
                                   length=len(content),
                                   method='POST',
                                   content="""-----weeboundary\r
Content-Disposition: form-data; name="%s"; filename="%s"\r
Content-Type: %s\r
\r
%s\r
-----weeboundary--\r
""" % (fieldname, filename, mimetype, content))
    def test_maxFields(self):
        """
        Check that the C{maxSize} parameter makes the parsing raise an
        exception if the data contains too many fields.
        """
        ctype = http_headers.MimeType('multipart', 'form-data',
                                      (('boundary', '---xyz'),))
        content = """-----xyz\r
Content-Disposition: form-data; name="foo"\r
\r
Foo Bar\r
-----xyz\r
Content-Disposition: form-data; name="foo"\r
\r
Baz\r
-----xyz\r
Content-Disposition: form-data; name="file"; filename="filename"\r
Content-Type: text/html\r
\r
blah\r
-----xyz\r
Content-Disposition: form-data; name="file"; filename="filename"\r
Content-Type: text/plain\r
\r
bleh\r
-----xyz--\r
"""
        root = resource.Resource()
        request = SimpleRequest(server.Site(root), "GET", "/",
                http_headers.Headers({'content-type': ctype}), content)
        def cb(res):
            self.assertEquals(res.response.description,
                "Maximum number of fields 3 exceeded")
        return self.assertFailure(server.parsePOSTData(request, maxFields=3),
            http.HTTPError).addCallback(cb)
 def cb(ign):
     self.assertEquals(request.args, {})
     self.assertEquals(request.files.keys(), ['FileNameOne'])
     self.assertEquals(request.files.values()[0][0][:2],
           ('myfilename', http_headers.MimeType('text', 'html', {})))
     f = request.files.values()[0][0][2]
     self.assertEquals(f.read(), "my great content wooo")
Beispiel #11
0
    def test_multipart(self):
        """
        Test parsing data in multipart format: it should fill the C{files}
        attribute.
        """
        ctype = http_headers.MimeType('multipart', 'form-data',
                                      (('boundary', '---weeboundary'),))
        content = """-----weeboundary\r
Content-Disposition: form-data; name="FileNameOne"; filename="myfilename"\r
Content-Type: text/html\r
\r
my great content wooo\r
-----weeboundary--\r
"""
        root = resource.Resource()
        request = SimpleRequest(
            server.Site(root), "GET", "/",
            http_headers.Headers({'content-type': ctype}), content)

        def cb(ign):
            self.assertEquals(request.args, {})
            self.assertEquals(request.files.keys(), ['FileNameOne'])
            self.assertEquals(
                request.files.values()[0][0][:2],
                ('myfilename', http_headers.MimeType('text', 'html', {})))
            f = request.files.values()[0][0][2]
            self.assertEquals(f.read(), "my great content wooo")
        return server.parsePOSTData(request).addCallback(cb)
Beispiel #12
0
    def renderHTTP_exception(self, req, reason):
        log.failure("Exception rendering request: {request}", reason, request=req)

        body = ("<html><head><title>Internal Server Error</title></head>"
                "<body><h1>Internal Server Error</h1>An error occurred rendering the requested page. More information is available in the server log.</body></html>")

        return http.Response(
            responsecode.INTERNAL_SERVER_ERROR,
            {'content-type': http_headers.MimeType('text', 'html')},
            body)
Beispiel #13
0
 def __init__(self, code, jobj, contentType="application/json", pretty=False):
     """
     @param jobj: a Python object that can be serialized to JSON.
     """
     kwargs = {}
     if pretty:
         kwargs["indent"] = 2
         kwargs["separators"] = (',', ':')
     Response.__init__(self, code, stream=json.dumps(jobj, **kwargs))
     self.headers.setHeader("content-type", http_headers.MimeType(*contentType.split("/")))
    def testEquality(self):
        """Test that various uses of the constructer are equal
        """

        kwargMime = http_headers.MimeType('text', 'plain',
                                          key='value',
                                          param=None)
        dictMime = http_headers.MimeType('text', 'plain',
                                         {'param': None,
                                          'key': 'value'})
        tupleMime = http_headers.MimeType('text', 'plain',
                                          (('param', None),
                                           ('key', 'value')))

        stringMime = http_headers.MimeType.fromString('text/plain;key=value;param')

        self.assertEquals(kwargMime, dictMime)
        self.assertEquals(dictMime, tupleMime)
        self.assertEquals(kwargMime, tupleMime)
        self.assertEquals(kwargMime, stringMime)
Beispiel #15
0
 def test_wrongContentType(self):
     """
     Check that a content-type not handled raise a C{http.HTTPError}.
     """
     ctype = http_headers.MimeType('application', 'foobar')
     content = "key=value&multiple=two+words&multiple=more%20words"
     root = resource.Resource()
     request = SimpleRequest(
         server.Site(root), "GET", "/",
         http_headers.Headers({'content-type': ctype}), content)
     return self.assertFailure(server.parsePOSTData(request), http.HTTPError)
Beispiel #16
0
def doTrace(request):
    request = iweb.IRequest(request)
    txt = "%s %s HTTP/%d.%d\r\n" % (request.method, request.uri,
                                    request.clientproto[0],
                                    request.clientproto[1])

    l = []
    for name, valuelist in request.headers.getAllRawHeaders():
        for value in valuelist:
            l.append("%s: %s\r\n" % (name, value))
    txt += ''.join(l)

    return http.Response(
        responsecode.OK,
        {'content-type': http_headers.MimeType('message', 'http')}, txt)
Beispiel #17
0
 def test_render(self):
     """
     Test that the result from Data.render is acceptable, including the
     response code, the content-type header, and the actual response body
     itself.
     """
     response = iweb.IResponse(self.data.render(None))
     self.assertEqual(response.code, 200)
     self.assert_(response.headers.hasHeader("content-type"))
     self.assertEqual(response.headers.getHeader("content-type"),
                      http_headers.MimeType("text", "plain"))
     def checkStream(data):
         self.assertEquals(str(data), self.text)
     return stream.readStream(iweb.IResponse(self.data.render(None)).stream,
                              checkStream)
 def test_urlencoded(self):
     """
     Test parsing data in urlencoded format: it should end in the C{args}
     attribute.
     """
     ctype = http_headers.MimeType('application', 'x-www-form-urlencoded')
     content = "key=value&multiple=two+words&multiple=more%20words"
     root = resource.Resource()
     request = SimpleRequest(server.Site(root), "GET", "/",
             http_headers.Headers({'content-type': ctype}), content)
     def cb(ign):
         self.assertEquals(request.files, {})
         self.assertEquals(request.args,
             {'multiple': ['two words', 'more words'], 'key': ['value']})
     return server.parsePOSTData(request).addCallback(cb)
Beispiel #19
0
def _readHeaders(stream):
    """Read the MIME headers. Assumes we've just finished reading in the
    boundary string."""

    ctype = fieldname = filename = None
    headers = []

    # Now read headers
    while 1:
        line = stream.readline(size=1024)
        if isinstance(line, defer.Deferred):
            line = defer.waitForDeferred(line)
            yield line
            line = line.getResult()
        # print("GOT", line)
        if not line.endswith('\r\n'):
            if line == "":
                raise MimeFormatError("Unexpected end of stream.")
            else:
                raise MimeFormatError("Header line too long")

        line = line[:-2]  # strip \r\n
        if line == "":
            break  # End of headers

        parts = line.split(':', 1)
        if len(parts) != 2:
            raise MimeFormatError("Header did not have a :")
        name, value = parts
        name = name.lower()
        headers.append((name, value))

        if name == "content-type":
            ctype = http_headers.parseContentType(
                http_headers.tokenize((value, ), foldCase=False))
        elif name == "content-disposition":
            fieldname, filename = parseContentDispositionFormData(value)

    if ctype is None:
        ctype = http_headers.MimeType('application', 'octet-stream')
    if fieldname is None:
        raise MimeFormatError('Content-disposition invalid or omitted.')

    # End of headers, return (field name, content-type, filename)
    yield fieldname, filename, ctype
    return
Beispiel #20
0
def defaultErrorHandler(request, response):
    """
    Handle errors which do not have any stream (i.e. output) associated with
    them, so that users will see a nice message in their browser.

    This is used as a response filter in L{txweb2.server.Request}.
    """
    if response.stream is not None:
        # Already got an error message
        return response

    if response.code < 300:
        # We only do error messages
        return response

    message = ERROR_MESSAGES.get(response.code, None)
    if message is None:
        # No message specified for that code
        return response

    message = message % {
        'uri': request.uri,
        'location': response.headers.getHeader('location'),
        'method': request.method,
    }

    data = []
    error = []

    (flattenString(request, DefaultErrorElement(request,
                                                response)).addCallbacks(
                                                    data.append, error.append))

    # No deferreds from our renderers above, so this has always already fired.
    if data:
        subtype = 'html'
        body = data[0]
    else:
        subtype = 'error'
        body = 'Error in default error handler:\n' + error[0].getTraceback()

    ctype = http_headers.MimeType('text', subtype, {'charset': 'utf-8'})
    response.headers.setHeader("content-type", ctype)
    response.stream = stream.MemoryStream(body)
    return response
Beispiel #21
0
    def test_otherErrors(self):
        """
        Test that errors durign parsing other than C{MimeFormatError} are
        propagated.
        """
        ctype = http_headers.MimeType('multipart', 'form-data',
                                      (('boundary', '---weeboundary'),))
        # XXX: maybe this is not a good example
        # parseContentDispositionFormData could handle this problem
        content = """-----weeboundary\r
Content-Disposition: form-data; name="FileNameOne"; filename="myfilename and invalid data \r
-----weeboundary--\r
"""
        root = resource.Resource()
        request = SimpleRequest(
            server.Site(root), "GET", "/",
            http_headers.Headers({'content-type': ctype}), content)
        return self.assertFailure(server.parsePOSTData(request), ValueError)
Beispiel #22
0
    def test_multipartWithNoBoundary(self):
        """
        If the boundary type is not specified, parsing should fail with a
        C{http.HTTPError}.
        """
        ctype = http_headers.MimeType('multipart', 'form-data')
        content = """-----weeboundary\r
Content-Disposition: form-data; name="FileNameOne"; filename="myfilename"\r
Content-Type: text/html\r
\r
my great content wooo\r
-----weeboundary--\r
"""
        root = resource.Resource()
        request = SimpleRequest(
            server.Site(root), "GET", "/",
            http_headers.Headers({'content-type': ctype}), content)
        return self.assertFailure(server.parsePOSTData(request), http.HTTPError)
Beispiel #23
0
    def test_mimeParsingError(self):
        """
        A malformed content should result in a C{http.HTTPError}.

        The tested content has an invalid closing boundary.
        """
        ctype = http_headers.MimeType('multipart', 'form-data',
                                      (('boundary', '---weeboundary'),))
        content = """-----weeboundary\r
Content-Disposition: form-data; name="FileNameOne"; filename="myfilename"\r
Content-Type: text/html\r
\r
my great content wooo\r
-----weeoundary--\r
"""
        root = resource.Resource()
        request = SimpleRequest(
            server.Site(root), "GET", "/",
            http_headers.Headers({'content-type': ctype}), content)
        return self.assertFailure(server.parsePOSTData(request), http.HTTPError)
Beispiel #24
0
    def __init__(self, code, description, title=None):
        """
        @param code: a response code in L{responsecode.RESPONSES}.
        @param description: a string description.
        @param title: the message title.  If not specified or C{None}, defaults
            to C{responsecode.RESPONSES[code]}.
        """
        if title is None:
            title = responsecode.RESPONSES[code]

        element = StatusResponseElement(title, description)
        out = []
        flattenString(None, element).addCallback(out.append)

        mime_params = {"charset": "utf-8"}
        super(StatusResponse, self).__init__(code=code, stream=out[0])

        self.headers.setHeader(
            "content-type", http_headers.MimeType("text", "html", mime_params))

        self.description = description
    def testAccept(self):
        table = (
            ("audio/*;q=0.2, audio/basic",
             {http_headers.MimeType('audio', '*'): 0.2,
              http_headers.MimeType('audio', 'basic'): 1.0}),

            ("text/plain;q=0.5, text/html, text/x-dvi;q=0.8, text/x-c",
             {http_headers.MimeType('text', 'plain'): 0.5,
              http_headers.MimeType('text', 'html'): 1.0,
              http_headers.MimeType('text', 'x-dvi'): 0.8,
              http_headers.MimeType('text', 'x-c'): 1.0}),

            ("text/*, text/html, text/html;level=1, */*",
             {http_headers.MimeType('text', '*'): 1.0,
              http_headers.MimeType('text', 'html'): 1.0,
              http_headers.MimeType('text', 'html', (('level', '1'),)): 1.0,
              http_headers.MimeType('*', '*'): 1.0}),

       ("text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5",
             {http_headers.MimeType('text', '*'): 0.3,
              http_headers.MimeType('text', 'html'): 0.7,
              http_headers.MimeType('text', 'html', (('level', '1'),)): 1.0,
              http_headers.MimeType('text', 'html', (('level', '2'),)): 0.4,
              http_headers.MimeType('*', '*'): 0.5}),
            )

        self.runRoundtripTest("Accept", table)
 def testContentType(self):
     table = (
         ("text/html;charset=iso-8859-4", http_headers.MimeType('text', 'html', (('charset', 'iso-8859-4'),))),
         ("text/html", http_headers.MimeType('text', 'html')),
         )
     self.runRoundtripTest("Content-Type", table)
Beispiel #27
0
def rangefilter(request, oldresponse):
    if oldresponse.stream is None:
        return oldresponse
    size = oldresponse.stream.length
    if size is None:
        # Does not deal with indeterminate length outputs
        return oldresponse

    oldresponse.headers.setHeader('accept-ranges', ('bytes',))

    rangespec = request.headers.getHeader('range')

    # If we've got a range header and the If-Range header check passes, and
    # the range type is bytes, do a partial response.
    if (
        rangespec is not None and http.checkIfRange(request, oldresponse) and
        rangespec[0] == 'bytes'
    ):
        # If it's a single range, return a simple response
        if len(rangespec[1]) == 1:
            try:
                start, end = canonicalizeRange(rangespec[1][0], size)
            except UnsatisfiableRangeRequest:
                return makeUnsatisfiable(request, oldresponse)

            response = http.Response(responsecode.PARTIAL_CONTENT, oldresponse.headers)
            response.headers.setHeader('content-range', ('bytes', start, end, size))

            content, after = makeSegment(oldresponse.stream, 0, start, end)
            after.close()
            response.stream = content
            return response
        else:
            # Return a multipart/byteranges response
            lastOffset = -1
            offsetList = []
            for arange in rangespec[1]:
                try:
                    start, end = canonicalizeRange(arange, size)
                except UnsatisfiableRangeRequest:
                    continue
                if start <= lastOffset:
                    # Stupid client asking for out-of-order or overlapping ranges, PUNT!
                    return oldresponse
                offsetList.append((start, end))
                lastOffset = end

            if not offsetList:
                return makeUnsatisfiable(request, oldresponse)

            content_type = oldresponse.headers.getRawHeaders('content-type')
            boundary = "%x%x" % (int(time.time() * 1000000), os.getpid())
            response = http.Response(responsecode.PARTIAL_CONTENT, oldresponse.headers)

            response.headers.setHeader(
                'content-type',
                http_headers.MimeType('multipart', 'byteranges',
                                      [('boundary', boundary)])
            )
            response.stream = out = stream.CompoundStream()


            lastOffset = 0
            origStream = oldresponse.stream

            headerString = "\r\n--%s" % boundary
            if len(content_type) == 1:
                headerString += '\r\nContent-Type: %s' % content_type[0]
            headerString += "\r\nContent-Range: %s\r\n\r\n"

            for start, end in offsetList:
                out.addStream(
                    headerString %
                    http_headers.generateContentRange(('bytes', start, end, size))
                )

                content, origStream = makeSegment(origStream, lastOffset, start, end)
                lastOffset = end + 1
                out.addStream(content)
            origStream.close()
            out.addStream("\r\n--%s--\r\n" % boundary)
            return response
    else:
        return oldresponse
Beispiel #28
0
class FileSaver(resource.PostableResource):
    allowedTypes = (http_headers.MimeType('text', 'plain'),
                    http_headers.MimeType('text', 'html'),
                    http_headers.MimeType('text', 'css'))

    def __init__(self,
                 destination,
                 expectedFields=[],
                 allowedTypes=None,
                 maxBytes=1000000,
                 permissions=0644):
        self.destination = destination
        self.allowedTypes = allowedTypes or self.allowedTypes
        self.maxBytes = maxBytes
        self.expectedFields = expectedFields
        self.permissions = permissions

    def makeUniqueName(self, filename):
        """Called when a unique filename is needed.

        filename is the name of the file as given by the client.

        Returns the fully qualified path of the file to create. The
        file must not yet exist.
        """

        return tempfile.mktemp(suffix=os.path.splitext(filename)[1],
                               dir=self.destination)

    def isSafeToWrite(self, filename, mimetype, filestream):
        """Returns True if it's "safe" to write this file,
        otherwise it raises an exception.
        """

        if filestream.length > self.maxBytes:
            raise IOError("%s: File exceeds maximum length (%d > %d)" %
                          (filename, filestream.length, self.maxBytes))

        if mimetype not in self.allowedTypes:
            raise IOError("%s: File type not allowed %s" %
                          (filename, mimetype))

        return True

    def writeFile(self, filename, mimetype, fileobject):
        """Does the I/O dirty work after it calls isSafeToWrite to make
        sure it's safe to write this file.
        """
        filestream = stream.FileStream(fileobject)

        if self.isSafeToWrite(filename, mimetype, filestream):
            outname = self.makeUniqueName(filename)

            flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(
                os, "O_BINARY", 0)

            fileobject = os.fdopen(os.open(outname, flags, self.permissions),
                                   'wb', 0)

            stream.readIntoFile(filestream, fileobject)

        return outname

    def render(self, req):
        content = ["<html><body>"]

        if req.files:
            for fieldName in req.files:
                if fieldName in self.expectedFields:
                    for finfo in req.files[fieldName]:
                        try:
                            outname = self.writeFile(*finfo)
                            content.append("Saved file %s<br />" % outname)
                        except IOError, err:
                            content.append(str(err) + "<br />")
                else:
                    content.append("%s is not a valid field" % fieldName)

        else: