Ejemplo n.º 1
0
 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)
Ejemplo n.º 2
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"))
Ejemplo n.º 3
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))
Ejemplo n.º 4
0
def defaultErrorHandler(request, response):
    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': _escape(request.uri),
        'location': _escape(response.headers.getHeader('location')),
        'method': _escape(request.method)
    }

    title = RESPONSES.get(response.code, "")
    body = ("<html><head><title>%d %s</title></head>"
            "<body><h1>%s</h1>%s</body></html>") % (response.code, title,
                                                    title, message)

    response.headers.setHeader("content-type",
                               http_headers.MimeType('text', 'html'))
    response.stream = stream.MemoryStream(body)

    return response
Ejemplo n.º 5
0
    def render(self, request):
        title = "Directory listing for %s" % urllib.unquote(request.path)

        s = """<html><head><title>%s</title><style>
          th, .even td, .odd td { padding-right: 0.5em; font-family: monospace}
          .even-dir { background-color: #efe0ef }
          .even { background-color: #eee }
          .odd-dir {background-color: #f0d0ef }
          .odd { background-color: #dedede }
          .icon { text-align: center }
          .listing {
              margin-left: auto;
              margin-right: auto;
              width: 50%%;
              padding: 0.1em;
              }

          body { border: 0; padding: 0; margin: 0; background-color: #efefef;}
          h1 {padding: 0.1em; background-color: #777; color: white; border-bottom: thin white dashed;}
</style></head><body><div class="directory-listing"><h1>%s</h1>""" % (title,
                                                                      title)
        s += "<table>"
        s += "<tr><th>Filename</th><th>Size</th><th>Last Modified</th><th>File Type</th></tr>"
        even = False
        for row in self.data_listing(request, None):
            s += '<tr class="%s">' % (even and 'even' or 'odd', )
            s += '<td><a href="%(link)s">%(linktext)s</a></td><td align="right">%(size)s</td><td>%(lastmod)s</td><td>%(type)s</td></tr>' % row
            even = not even

        s += "</table></div></body></html>"
        response = http.Response(200, {}, s)
        response.headers.setHeader("content-type",
                                   http_headers.MimeType('text', 'html'))
        return response
Ejemplo n.º 6
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 = cgi.escape(responsecode.RESPONSES[code])

        output = "".join((
            "<html>",
            "<head>",
            "<title>%s</title>" % (title,),
            "</head>",
            "<body>",
            "<h1>%s</h1>" % (title,),
            "<p>%s</p>" % (cgi.escape(description),),
            "</body>",
            "</html>",
        ))

        if type(output) == unicode:
            output = output.encode("utf-8")
            mime_params = {"charset": "utf-8"}
        else:
            mime_params = {}

        super(StatusResponse, self).__init__(code=code, stream=output)

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

        self.description = description
Ejemplo n.º 7
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)
Ejemplo n.º 8
0
    def render(self, request):
        # For GET/HEAD: Return an error message
        s = (
            "<html><head><title>XML-RPC responder</title></head>"
            "<body><h1>XML-RPC responder</h1>POST your XML-RPC here.</body></html>"
        )

        return http.Response(
            responsecode.OK,
            {'content-type': http_headers.MimeType('text', 'html')}, s)
Ejemplo n.º 9
0
    def _generateResponse(self, result):
        if not isinstance(result, http.Response):
            result = http.Response()

        result.code = responsecode.OK
        result.headers.setHeader(
            'content-type',
            http_headers.MimeType("text", "html", {"charset": "utf-8"}))
        result.stream = stream.IByteStream("")
        return result
Ejemplo n.º 10
0
 def _cbRender(self, result, request):
     if not isinstance(result, Fault):
         result = (result, )
     try:
         s = xmlrpclib.dumps(result, methodresponse=1)
     except:
         f = Fault(self.FAILURE, "can't serialize output")
         s = xmlrpclib.dumps(f, methodresponse=1)
     return http.Response(
         responsecode.OK,
         {'content-type': http_headers.MimeType('text', 'xml')}, s)
Ejemplo n.º 11
0
 def _renderError(self, failure):
     result = http.Response()
     result.headers.setHeader(
         'content-type',
         http_headers.MimeType("text", "html", {"charset": "utf-8"}))
     error = u'Unknown error'
     try:
         failure.raiseException()
     except Exception as err:
         error = {'class': err.__class__.__name__, 'message': unicode(err)}
         error = toJson({"id": None, "result": None, "error": error})
     result.stream = stream.IByteStream(error.encode('utf-8'))
     return result
Ejemplo n.º 12
0
    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)
Ejemplo n.º 13
0
 def _renderError(self, failure):
     result = http.Response()
     result.headers.setHeader(
         'content-type',
         http_headers.MimeType("text", "html", {"charset": "utf-8"}))
     error = u'Unknown error'
     try:
         failure.raiseException()
     except Exception as error:
         error = forceUnicode(error)
     result.stream = stream.IByteStream(
         stream.IByteStream(error.encode('utf-8')))
     return result
Ejemplo n.º 14
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)
Ejemplo n.º 15
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
Ejemplo n.º 16
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
Ejemplo n.º 17
0
    def _generateResponse(self, result):
        invalidMime = False  # For handling the invalid MIME type "gzip-application/json-rpc"
        encoding = None
        try:
            if 'gzip' in self.request.headers.getHeader('Accept-Encoding'):
                encoding = 'gzip'
            elif 'deflate' in self.request.headers.getHeader(
                    'Accept-Encoding'):
                encoding = 'deflate'
        except Exception as error:
            logger.debug2(
                "Failed to get Accept-Encoding from request header: {0}".
                format(error))

        try:
            if self.request.headers.getHeader('Accept'):
                for accept in self.request.headers.getHeader('Accept').keys():
                    if accept.mediaType.startswith('gzip'):
                        invalidMime = True
                        encoding = 'gzip'
                        break
        except Exception as error:
            logger.error(u"Failed to get accepted mime types from header: {0}",
                         error)

        response = [serialize(rpc.getResponse()) for rpc in self._rpcs]

        if len(response) == 1:
            response = response[0]
        if not response:
            response = None

        if not isinstance(result, http.Response):
            result = http.Response()
        result.code = responsecode.OK

        result.headers.setHeader(
            'content-type',
            http_headers.MimeType("application", "json", {"charset": "utf-8"}))

        if invalidMime:
            # The invalid requests expect the encoding set to
            # gzip but the content is deflated.
            result.headers.setHeader('content-encoding', ["gzip"])
            result.headers.setHeader(
                'content-type',
                http_headers.MimeType("gzip-application", "json",
                                      {"charset": "utf-8"}))
            logger.debug(
                u"Sending deflated data (backwards compatible - with content-encoding 'gzip')"
            )
            result.stream = stream.IByteStream(
                deflateEncode(toJson(response).encode('utf-8')))
        elif encoding == "deflate":
            logger.debug(u"Sending deflated data")
            result.headers.setHeader('content-encoding', [encoding])
            result.stream = stream.IByteStream(
                deflateEncode(toJson(response).encode('utf-8')))
        elif encoding == "gzip":
            logger.debug(u"Sending gzip compressed data")
            result.headers.setHeader('content-encoding', [encoding])
            result.stream = stream.IByteStream(
                gzipEncode(toJson(response).encode('utf-8')))
        else:
            logger.debug(u"Sending plain data")
            result.stream = stream.IByteStream(
                toJson(response).encode('utf-8'))

        return result
Ejemplo n.º 18
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 isWriteable to make
        sure it's safe to write this file.
        """
        filestream = stream.FileStream(fileobject)

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

            fileobject = os.fdopen(
                os.open(outname, os.O_WRONLY | os.O_CREAT | os.O_EXCL,
                        self.permissions), 'w', 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:
Ejemplo n.º 19
0
    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)