示例#1
0
文件: util.py 项目: Ivoz/pipa
    def read_headers(cls, fp):
        headers = httputil.HeaderMap()
        while True:
            line = fp.readline()
            if not line:
                # No more data--illegal end of headers
                raise EOFError("Illegal end of headers.")

            if line == ntob('\n'):
                # Normal end of headers
                break
            # if not line.endswith(ntob('\r\n')):
            #     raise ValueError("MIME requires CRLF terminators: %r" % line)

            if line[0] in ntob(' \t'):
                # It's a continuation line.
                v = line.strip().decode('ISO-8859-1')
            else:
                k, v = line.split(ntob(":"), 1)
                k = k.strip().decode('ISO-8859-1')
                v = v.strip().decode('ISO-8859-1')

            existing = headers.get(k)
            if existing:
                v = ", ".join((existing, v))
            headers[k] = v

        return headers
示例#2
0
 def test_empty_string_app(environ, start_response):
     status = '200 OK'
     response_headers = [('Content-type', 'text/plain')]
     start_response(status, response_headers)
     return [
         ntob('Hello'), ntob(''), ntob(' '), ntob(''), ntob('world')
     ]
    def test_encoded_headers(self):
        # First, make sure the innards work like expected.
        self.assertEqual(httputil.decode_TEXT(ntou("=?utf-8?q?f=C3=BCr?=")), ntou("f\xfcr"))

        if cherrypy.server.protocol_version == "HTTP/1.1":
            # Test RFC-2047-encoded request and response header values
            u = ntou('\u212bngstr\xf6m', 'escape')
            c = ntou("=E2=84=ABngstr=C3=B6m")
            self.getPage("/headers/ifmatch", [('If-Match', ntou('=?utf-8?q?%s?=') % c)])
            # The body should be utf-8 encoded.
            self.assertBody(ntob("\xe2\x84\xabngstr\xc3\xb6m"))
            # But the Etag header should be RFC-2047 encoded (binary)
            self.assertHeader("ETag", ntou('=?utf-8?b?4oSrbmdzdHLDtm0=?='))

            # Test a *LONG* RFC-2047-encoded request and response header value
            self.getPage("/headers/ifmatch",
                         [('If-Match', ntou('=?utf-8?q?%s?=') % (c * 10))])
            self.assertBody(ntob("\xe2\x84\xabngstr\xc3\xb6m") * 10)
            # Note: this is different output for Python3, but it decodes fine.
            etag = self.assertHeader("ETag",
                '=?utf-8?b?4oSrbmdzdHLDtm3ihKtuZ3N0csO2beKEq25nc3Ryw7Zt'
                '4oSrbmdzdHLDtm3ihKtuZ3N0csO2beKEq25nc3Ryw7Zt'
                '4oSrbmdzdHLDtm3ihKtuZ3N0csO2beKEq25nc3Ryw7Zt'
                '4oSrbmdzdHLDtm0=?=')
            self.assertEqual(httputil.decode_TEXT(etag), u * 10)
示例#4
0
 def test_decode_tool(self):
     # An extra charset should be tried first, and succeed if it matches.
     # Here, we add utf-16 as a charset and pass a utf-16 body.
     body = ntob("\xff\xfeq\x00=\xff\xfe\xa3\x00")
     self.getPage('/decode/extra_charset', method='POST',
                  headers=[("Content-Type", "application/x-www-form-urlencoded"),
                           ("Content-Length", str(len(body))),
                           ],
                  body=body),
     self.assertBody(ntob("q: \xc2\xa3"))
     
     # An extra charset should be tried first, and continue to other default
     # charsets if it doesn't match.
     # Here, we add utf-16 as a charset but still pass a utf-8 body.
     body = ntob("q=\xc2\xa3")
     self.getPage('/decode/extra_charset', method='POST',
                  headers=[("Content-Type", "application/x-www-form-urlencoded"),
                           ("Content-Length", str(len(body))),
                           ],
                  body=body),
     self.assertBody(ntob("q: \xc2\xa3"))
     
     # An extra charset should error if force is True and it doesn't match.
     # Here, we force utf-16 as a charset but still pass a utf-8 body.
     body = ntob("q=\xc2\xa3")
     self.getPage('/decode/force_charset', method='POST',
                  headers=[("Content-Type", "application/x-www-form-urlencoded"),
                           ("Content-Length", str(len(body))),
                           ],
                  body=body),
     self.assertErrorPage(400,
         "The request entity could not be decoded. The following charsets "
         "were attempted: ['utf-16']")
示例#5
0
    def finish(self):
        self.done = True
        if self.has_trailers and hasattr(self.fp, 'read_trailer_lines'):
            self.trailers = {}

            try:
                for line in self.fp.read_trailer_lines():
                    if line[0] in ntob(' \t'):
                        # It's a continuation line.
                        v = line.strip()
                    else:
                        try:
                            k, v = line.split(ntob(":"), 1)
                        except ValueError:
                            raise ValueError("Illegal header line.")
                        k = k.strip().title()
                        v = v.strip()

                    if k in comma_separated_headers:
                        existing = self.trailers.get(envname)
                        if existing:
                            v = ntob(", ").join((existing, v))
                    self.trailers[k] = v
            except Exception:
                e = sys.exc_info()[1]
                if e.__class__.__name__ == 'MaxSizeExceeded':
                    # Post data is too big
                    raise cherrypy.HTTPError(
                        413, "Maximum request length: %r" % e.args[1])
                else:
                    raise
示例#6
0
    def set_response(self):
        """Modify cherrypy.response status, headers, and body to represent
        self.

        CherryPy uses this internally, but you can also use it to create an
        HTTPRedirect object and set its output without *raising* the exception.
        """
        import cherrypy
        response = cherrypy.serving.response
        response.status = status = self.status

        if status in (300, 301, 302, 303, 307):
            response.headers['Content-Type'] = 'text/html;charset=utf-8'
            # "The ... URI SHOULD be given by the Location field
            # in the response."
            response.headers['Location'] = self.urls[0]

            # "Unless the request method was HEAD, the entity of the response
            # SHOULD contain a short hypertext note with a hyperlink to the
            # new URI(s)."
            msg = {
                300: 'This resource can be found at ',
                301: 'This resource has permanently moved to ',
                302: 'This resource resides temporarily at ',
                303: 'This resource can be found at ',
                307: 'This resource has moved temporarily to ',
            }[status]
            msg += '<a href=%s>%s</a>.'
            msgs = [msg % (saxutils.quoteattr(u), u) for u in self.urls]
            response.body = ntob('<br />\n'.join(msgs), 'utf-8')
            # Previous code may have set C-L, so we have to reset it
            # (allow finalize to set it).
            response.headers.pop('Content-Length', None)
        elif status == 304:
            # Not Modified.
            # "The response MUST include the following header fields:
            # Date, unless its omission is required by section 14.18.1"
            # The "Date" header should have been set in Response.__init__

            # "...the response SHOULD NOT include other entity-headers."
            for key in ('Allow', 'Content-Encoding', 'Content-Language',
                        'Content-Length', 'Content-Location', 'Content-MD5',
                        'Content-Range', 'Content-Type', 'Expires',
                        'Last-Modified'):
                if key in response.headers:
                    del response.headers[key]

            # "The 304 response MUST NOT contain a message-body."
            response.body = None
            # Previous code may have set C-L, so we have to reset it.
            response.headers.pop('Content-Length', None)
        elif status == 305:
            # Use Proxy.
            # self.urls[0] should be the URI of the proxy.
            response.headers['Location'] = ntob(self.urls[0], 'utf-8')
            response.body = None
            # Previous code may have set C-L, so we have to reset it.
            response.headers.pop('Content-Length', None)
        else:
            raise ValueError('The %s status code is unknown.' % status)
示例#7
0
    def test_file_stream(self):
        if cherrypy.server.protocol_version != "HTTP/1.1":
            return self.skip()

        self.PROTOCOL = "HTTP/1.1"

        # Make an initial request
        self.persistent = True
        conn = self.HTTP_CONN
        conn.putrequest("GET", "/bigfile", skip_host=True)
        conn.putheader("Host", self.HOST)
        conn.endheaders()
        response = conn.response_class(conn.sock, method="GET")
        response.begin()
        self.assertEqual(response.status, 200)

        body = ntob('')
        remaining = BIGFILE_SIZE
        while remaining > 0:
            data = response.fp.read(65536)
            if not data:
                break
            body += data
            remaining -= len(data)

            if self.scheme == "https":
                newconn = HTTPSConnection
            else:
                newconn = HTTPConnection
            s, h, b = helper.webtest.openURL(
                ntob("/tell"), headers=[], host=self.HOST, port=self.PORT,
                http_conn=newconn)
            if not b:
                # The file was closed on the server.
                tell_position = BIGFILE_SIZE
            else:
                tell_position = int(b)

            expected = len(body)
            if tell_position >= BIGFILE_SIZE:
                # We can't exactly control how much content the server asks
                # for.
                # Fudge it by only checking the first half of the reads.
                if expected < (BIGFILE_SIZE / 2):
                    self.fail(
                        "The file should have advanced to position %r, but "
                        "has already advanced to the end of the file. It "
                        "may not be streamed as intended, or at the wrong "
                        "chunk size (64k)" % expected)
            elif tell_position < expected:
                self.fail(
                    "The file should have advanced to position %r, but has "
                    "only advanced to position %r. It may not be streamed "
                    "as intended, or at the wrong chunk size (65536)" %
                    (expected, tell_position))

        if body != ntob("x" * BIGFILE_SIZE):
            self.fail("Body != 'x' * %d. Got %r instead (%d bytes)." %
                      (BIGFILE_SIZE, body[:50], len(body)))
        conn.close()
示例#8
0
    def test_file_stream_deadlock(self):
        if cherrypy.server.protocol_version != "HTTP/1.1":
            return self.skip()

        self.PROTOCOL = "HTTP/1.1"

        # Make an initial request but abort early.
        self.persistent = True
        conn = self.HTTP_CONN
        conn.putrequest("GET", "/bigfile", skip_host=True)
        conn.putheader("Host", self.HOST)
        conn.endheaders()
        response = conn.response_class(conn.sock, method="GET")
        response.begin()
        self.assertEqual(response.status, 200)
        body = response.fp.read(65536)
        if body != ntob("x" * len(body)):
            self.fail("Body != 'x' * %d. Got %r instead (%d bytes)." %
                      (65536, body[:50], len(body)))
        response.close()
        conn.close()

        # Make a second request, which should fetch the whole file.
        self.persistent = False
        self.getPage("/bigfile")
        if self.body != ntob("x" * BIGFILE_SIZE):
            self.fail("Body != 'x' * %d. Got %r instead (%d bytes)." %
                      (BIGFILE_SIZE, self.body[:50], len(body)))
示例#9
0
    def finalize(self):
        try:
            code, reason, _ = httputil.valid_status(self.status)
        except ValueError:
            raise cherrypy.HTTPError(500, sys.exc_info()[1].args[0])

        headers = self.headers
        self.output_status = ntob(str(code), 'ascii') + ntob(' ') + headers.encode(reason)
        if self.stream:
            if dict.get(headers, 'Content-Length') is None:
                dict.pop(headers, 'Content-Length', None)
        elif code < 200 or code in (204, 205, 304):
            dict.pop(headers, 'Content-Length', None)
            self.body = ntob('')
        elif dict.get(headers, 'Content-Length') is None:
            content = self.collapse_body()
            dict.__setitem__(headers, 'Content-Length', len(content))
        self.header_list = h = headers.output()
        cookie = self.cookie.output()
        if cookie:
            for line in cookie.split('\n'):
                if line.endswith('\r'):
                    line = line[:-1]
                name, value = line.split(': ', 1)
                if isinstance(name, unicodestr):
                    name = name.encode('ISO-8859-1')
                if isinstance(value, unicodestr):
                    value = headers.encode(value)
                h.append((name, value))
示例#10
0
    def test_HTTP11_pipelining(self):
        if cherrypy.server.protocol_version != 'HTTP/1.1':
            return self.skip()
        self.PROTOCOL = 'HTTP/1.1'
        self.persistent = True
        conn = self.HTTP_CONN
        conn.putrequest('GET', '/hello', skip_host=True)
        conn.putheader('Host', self.HOST)
        conn.endheaders()
        for trial in range(5):
            conn._output(ntob('GET /hello HTTP/1.1'))
            conn._output(ntob('Host: %s' % self.HOST, 'ascii'))
            conn._send_output()
            response = conn.response_class(conn.sock, method='GET')
            response.begin()
            body = response.read(13)
            self.assertEqual(response.status, 200)
            self.assertEqual(body, ntob('Hello, world!'))

        response = conn.response_class(conn.sock, method='GET')
        response.begin()
        body = response.read()
        self.assertEqual(response.status, 200)
        self.assertEqual(body, ntob('Hello, world!'))
        conn.close()
示例#11
0
 def test_Chunked_Encoding(self):
     if cherrypy.server.protocol_version != 'HTTP/1.1':
         return self.skip()
     if hasattr(self, 'harness') and 'modpython' in self.harness.__class__.__name__.lower():
         return self.skip()
     self.PROTOCOL = 'HTTP/1.1'
     self.persistent = True
     conn = self.HTTP_CONN
     body = ntob('8;key=value\r\nxx\r\nxxxx\r\n5\r\nyyyyy\r\n0\r\nContent-Type: application/json\r\n\r\n')
     conn.putrequest('POST', '/upload', skip_host=True)
     conn.putheader('Host', self.HOST)
     conn.putheader('Transfer-Encoding', 'chunked')
     conn.putheader('Trailer', 'Content-Type')
     conn.putheader('Content-Length', '3')
     conn.endheaders()
     conn.send(body)
     response = conn.getresponse()
     self.status, self.headers, self.body = webtest.shb(response)
     self.assertStatus('200 OK')
     self.assertBody("thanks for '%s'" % ntob('xx\r\nxxxxyyyyy'))
     body = ntob('3e3\r\n' + 'x' * 995 + '\r\n0\r\n\r\n')
     conn.putrequest('POST', '/upload', skip_host=True)
     conn.putheader('Host', self.HOST)
     conn.putheader('Transfer-Encoding', 'chunked')
     conn.putheader('Content-Type', 'text/plain')
     conn.endheaders()
     conn.send(body)
     response = conn.getresponse()
     self.status, self.headers, self.body = webtest.shb(response)
     self.assertStatus(413)
     conn.close()
示例#12
0
    def testCaching(self):
        elapsed = 0.0
        for trial in range(10):
            self.getPage('/')
            self.assertBody('visit #1')
            if trial != 0:
                age = int(self.assertHeader('Age'))
                self.assert_(age >= elapsed)
                elapsed = age

        self.getPage('/', method='POST')
        self.assertBody('visit #2')
        self.assertHeader('Vary', 'Accept-Encoding')
        self.getPage('/', method='GET')
        self.assertBody('visit #3')
        self.getPage('/', method='GET')
        self.assertBody('visit #3')
        self.getPage('/', method='DELETE')
        self.assertBody('visit #4')
        self.getPage('/', method='GET', headers=[('Accept-Encoding', 'gzip')])
        self.assertHeader('Content-Encoding', 'gzip')
        self.assertHeader('Vary')
        self.assertEqual(cherrypy.lib.encoding.decompress(self.body), ntob('visit #5'))
        self.getPage('/', method='GET', headers=[('Accept-Encoding', 'gzip')])
        self.assertHeader('Content-Encoding', 'gzip')
        self.assertEqual(cherrypy.lib.encoding.decompress(self.body), ntob('visit #5'))
        self.getPage('/', method='GET')
        self.assertNoHeader('Content-Encoding')
        self.assertBody('visit #6')
示例#13
0
    def assertErrorPage(self, status, message=None, pattern=''):
        """Compare the response body with a built in error page.

        The function will optionally look for the regexp pattern,
        within the exception embedded in the error page."""

        # This will never contain a traceback
        page = cherrypy._cperror.get_error_page(status, message=message)

        # First, test the response body without checking the traceback.
        # Stick a match-all group (.*) in to grab the traceback.
        def esc(text):
            return re.escape(ntob(text))
        epage = re.escape(page)
        epage = epage.replace(
            esc('<pre id="traceback"></pre>'),
            esc('<pre id="traceback">') + ntob('(.*)') + esc('</pre>'))
        m = re.match(epage, self.body, re.DOTALL)
        if not m:
            self._handlewebError(
                'Error page does not match; expected:\n' + page)
            return

        # Now test the pattern against the traceback
        if pattern is None:
            # Special-case None to mean that there should be *no* traceback.
            if m and m.group(1):
                self._handlewebError('Error page contains traceback')
        else:
            if (m is None) or (
                not re.search(ntob(re.escape(pattern), self.encoding),
                              m.group(1))):
                msg = 'Error page does not contain %s in traceback'
                self._handlewebError(msg % repr(pattern))
示例#14
0
                def file_ranges():
                    # Apache compatibility:
                    yield b'\r\n'

                    for start, stop in r:
                        if debug:
                            cherrypy.log(
                                'Multipart; start: %r, stop: %r' % (
                                    start, stop),
                                'TOOLS.STATIC')
                        yield ntob('--' + boundary, 'ascii')
                        yield ntob('\r\nContent-type: %s' % content_type,
                                   'ascii')
                        yield ntob(
                            '\r\nContent-range: bytes %s-%s/%s\r\n\r\n' % (
                                start, stop - 1, content_length),
                            'ascii')
                        fileobj.seek(start)
                        gen = file_generator_limited(fileobj, stop - start)
                        for chunk in gen:
                            yield chunk
                        yield b'\r\n'
                    # Final boundary
                    yield ntob('--' + boundary + '--', 'ascii')

                    # Apache compatibility:
                    yield b'\r\n'
示例#15
0
    def read(self, size = None, fp_out = None):
        if self.length is None:
            if size is None:
                remaining = inf
            else:
                remaining = size
        else:
            remaining = self.length - self.bytes_read
            if size and size < remaining:
                remaining = size
        if remaining == 0:
            self.finish()
            if fp_out is None:
                return ntob('')
            else:
                return
        chunks = []
        if self.buffer:
            if remaining is inf:
                data = self.buffer
                self.buffer = ntob('')
            else:
                data = self.buffer[:remaining]
                self.buffer = self.buffer[remaining:]
            datalen = len(data)
            remaining -= datalen
            self.bytes_read += datalen
            if self.maxbytes and self.bytes_read > self.maxbytes:
                raise cherrypy.HTTPError(413)
            if fp_out is None:
                chunks.append(data)
            else:
                fp_out.write(data)
        while remaining > 0:
            chunksize = min(remaining, self.bufsize)
            try:
                data = self.fp.read(chunksize)
            except Exception:
                e = sys.exc_info()[1]
                if e.__class__.__name__ == 'MaxSizeExceeded':
                    raise cherrypy.HTTPError(413, 'Maximum request length: %r' % e.args[1])
                else:
                    raise 

            if not data:
                self.finish()
                break
            datalen = len(data)
            remaining -= datalen
            self.bytes_read += datalen
            if self.maxbytes and self.bytes_read > self.maxbytes:
                raise cherrypy.HTTPError(413)
            if fp_out is None:
                chunks.append(data)
            else:
                fp_out.write(data)

        if fp_out is None:
            return ntob('').join(chunks)
示例#16
0
    def test_100_Continue(self):
        if cherrypy.server.protocol_version != 'HTTP/1.1':
            return self.skip()

        self.PROTOCOL = 'HTTP/1.1'

        self.persistent = True
        conn = self.HTTP_CONN

        # Try a page without an Expect request header first.
        # Note that httplib's response.begin automatically ignores
        # 100 Continue responses, so we must manually check for it.
        try:
            conn.putrequest('POST', '/upload', skip_host=True)
            conn.putheader('Host', self.HOST)
            conn.putheader('Content-Type', 'text/plain')
            conn.putheader('Content-Length', '4')
            conn.endheaders()
            conn.send(ntob("d'oh"))
            response = conn.response_class(conn.sock, method='POST')
            version, status, reason = response._read_status()
            self.assertNotEqual(status, 100)
        finally:
            conn.close()

        # Now try a page with an Expect header...
        try:
            conn.connect()
            conn.putrequest('POST', '/upload', skip_host=True)
            conn.putheader('Host', self.HOST)
            conn.putheader('Content-Type', 'text/plain')
            conn.putheader('Content-Length', '17')
            conn.putheader('Expect', '100-continue')
            conn.endheaders()
            response = conn.response_class(conn.sock, method='POST')

            # ...assert and then skip the 100 response
            version, status, reason = response._read_status()
            self.assertEqual(status, 100)
            while True:
                line = response.fp.readline().strip()
                if line:
                    self.fail(
                        '100 Continue should not output any headers. Got %r' %
                        line)
                else:
                    break

            # ...send the body
            body = ntob('I am a small file')
            conn.send(body)

            # ...get the final response
            response.begin()
            self.status, self.headers, self.body = webtest.shb(response)
            self.assertStatus(200)
            self.assertBody("thanks for '%s'" % body)
        finally:
            conn.close()
示例#17
0
 def test_query_string_decoding(self):
     europoundUtf8 = europoundUnicode.encode('utf-8')
     self.getPage(ntob('/?param=') + europoundUtf8)
     self.assertBody(europoundUtf8)
     self.getPage('/reqparams?q=%C2%A3')
     self.assertBody(ntob('q: \xc2\xa3'))
     self.getPage('/reqparams?q=%A3')
     self.assertStatus(404)
     self.assertErrorPage(404, "The given query string could not be processed. Query strings for this resource must be encoded with 'utf8'.")
示例#18
0
 def test_decode_tool(self):
     body = ntob('\xff\xfeq\x00=\xff\xfe\xa3\x00')
     (self.getPage('/decode/extra_charset', method='POST', headers=[('Content-Type', 'application/x-www-form-urlencoded'), ('Content-Length', str(len(body)))], body=body),)
     self.assertBody(ntob('q: \xc2\xa3'))
     body = ntob('q=\xc2\xa3')
     (self.getPage('/decode/extra_charset', method='POST', headers=[('Content-Type', 'application/x-www-form-urlencoded'), ('Content-Length', str(len(body)))], body=body),)
     self.assertBody(ntob('q: \xc2\xa3'))
     body = ntob('q=\xc2\xa3')
     (self.getPage('/decode/force_charset', method='POST', headers=[('Content-Type', 'application/x-www-form-urlencoded'), ('Content-Length', str(len(body)))], body=body),)
     self.assertErrorPage(400, "The request entity could not be decoded. The following charsets were attempted: ['utf-16']")
示例#19
0
 def test_config_errors(self):
     # Check that we get an error if no .file or .dir
     self.getPage("/error/thing.html")
     self.assertErrorPage(500)
     if sys.version_info >= (3, 3):
         errmsg = ntob("TypeError: staticdir\(\) missing 2 "
                       "required positional arguments")
     else:
         errmsg = ntob("TypeError: staticdir\(\) takes at least 2 "
                       "(positional )?arguments \(0 given\)")
     self.assertMatchesBody(errmsg)
示例#20
0
 def test_app(environ, start_response):
     status = ntob('200 OK')
     response_headers = [(ntob('Content-type'), ntob('text/plain'))]
     start_response(status, response_headers)
     output = ['Hello, world!\n',
               'This is a wsgi app running within CherryPy!\n\n']
     keys = list(environ.keys())
     keys.sort()
     for k in keys:
         output.append('%s: %s\n' % (k,environ[k]))
     return [ntob(x, 'utf-8') for x in output]
示例#21
0
    def encode(self, v):
        for enc in self.encodings:
            try:
                return v.encode(enc)
            except UnicodeEncodeError:
                continue

        if self.protocol == (1, 1) and self.use_rfc_2047:
            v = b2a_base64(v.encode('utf-8'))
            return ntob('=?utf-8?b?') + v.strip(ntob('\n')) + ntob('?=')
        raise ValueError('Could not encode header part %r using any of the encodings %r.' % (v, self.encodings))
示例#22
0
def urljoin_bytes(*atoms):
    """Return the given path *atoms, joined into a single URL.

    This will correctly join a SCRIPT_NAME and PATH_INFO into the
    original URL, even if either atom is blank.
    """
    url = ntob("/").join([x for x in atoms if x])
    while ntob("//") in url:
        url = url.replace(ntob("//"), ntob("/"))
    # Special-case the final url of "", and return "/" instead.
    return url or ntob("/")
示例#23
0
 def test_multipart_decoding_no_charset(self):
     body = ntob('\r\n'.join(['--X',
      'Content-Disposition: form-data; name="text"',
      '',
      '\xe2\x80\x9c',
      '--X',
      'Content-Disposition: form-data; name="submit"',
      '',
      'Create',
      '--X--']))
     (self.getPage('/reqparams', method='POST', headers=[('Content-Type', 'multipart/form-data;boundary=X'), ('Content-Length', str(len(body)))], body=body),)
     self.assertBody(ntob('text: \xe2\x80\x9c, submit: Create'))
示例#24
0
 def unquote_plus(bs):
     """Bytes version of urllib.parse.unquote_plus."""
     bs = bs.replace(ntob('+'), ntob(' '))
     atoms = bs.split(ntob('%'))
     for i in range(1, len(atoms)):
         item = atoms[i]
         try:
             pct = int(item[:2], 16)
             atoms[i] = bytes([pct]) + item[2:]
         except ValueError:
             pass
     return ntob('').join(atoms)
示例#25
0
    def test_basic_HTTPMethods(self):
        helper.webtest.methods_with_bodies = ('POST', 'PUT', 'PROPFIND')
        for m in defined_http_methods:
            self.getPage('/method/', method=m)
            if m == 'HEAD':
                self.assertBody('')
            elif m == 'TRACE':
                self.assertEqual(self.body[:5], ntob('TRACE'))
            else:
                self.assertBody(m)

        self.getPage('/method/parameterized', method='PUT', body='data=on+top+of+other+things')
        self.assertBody('on top of other things')
        b = 'one thing on top of another'
        h = [('Content-Type', 'text/plain'), ('Content-Length', str(len(b)))]
        self.getPage('/method/request_body', headers=h, method='PUT', body=b)
        self.assertStatus(200)
        self.assertBody(b)
        b = ntob('one thing on top of another')
        self.persistent = True
        try:
            conn = self.HTTP_CONN
            conn.putrequest('PUT', '/method/request_body', skip_host=True)
            conn.putheader('Host', self.HOST)
            conn.putheader('Content-Length', str(len(b)))
            conn.endheaders()
            conn.send(b)
            response = conn.response_class(conn.sock, method='PUT')
            response.begin()
            self.assertEqual(response.status, 200)
            self.body = response.read()
            self.assertBody(b)
        finally:
            self.persistent = False

        h = [('Content-Type', 'text/plain')]
        self.getPage('/method/reachable', headers=h, method='PUT')
        self.assertStatus(411)
        b = '<?xml version="1.0" encoding="utf-8" ?>\n\n<propfind xmlns="DAV:"><prop><getlastmodified/></prop></propfind>'
        h = [('Content-Type', 'text/xml'), ('Content-Length', str(len(b)))]
        self.getPage('/method/request_body', headers=h, method='PROPFIND', body=b)
        self.assertStatus(200)
        self.assertBody(b)
        self.getPage('/method/', method='LINK')
        self.assertStatus(405)
        self.getPage('/method/', method='SEARCH')
        self.assertStatus(501)
        self.getPage('/divorce/get?ID=13')
        self.assertBody('Divorce document 13: empty')
        self.assertStatus(200)
        self.getPage('/divorce/', method='GET')
        self.assertBody('<h1>Choose your document</h1>\n<ul>\n</ul>')
        self.assertStatus(200)
示例#26
0
文件: util.py 项目: Ivoz/pipa
def digest(password, conf=None):

    if conf is None:
        conf = cherrypy.request.app.root.pipa

    p = ntob(password)
    s = ntob(conf['salt'])
    digest = sha256(b'36'*16).digest()

    for i in range(5000):
        digest = sha256(digest + s + p + digest).digest()
    return sha256(digest + s + p + digest).hexdigest()
示例#27
0
 def test_Flash_Upload(self):
     headers = [('Accept', 'text/*'),
      ('Content-Type', 'multipart/form-data; boundary=----------KM7Ij5cH2KM7Ef1gL6ae0ae0cH2gL6'),
      ('User-Agent', 'Shockwave Flash'),
      ('Host', 'www.example.com:8080'),
      ('Content-Length', '499'),
      ('Connection', 'Keep-Alive'),
      ('Cache-Control', 'no-cache')]
     filedata = ntob('<?xml version="1.0" encoding="UTF-8"?>\r\n<projectDescription>\r\n</projectDescription>\r\n')
     body = ntob('------------KM7Ij5cH2KM7Ef1gL6ae0ae0cH2gL6\r\nContent-Disposition: form-data; name="Filename"\r\n\r\n.project\r\n------------KM7Ij5cH2KM7Ef1gL6ae0ae0cH2gL6\r\nContent-Disposition: form-data; name="Filedata"; filename=".project"\r\nContent-Type: application/octet-stream\r\n\r\n') + filedata + ntob('\r\n------------KM7Ij5cH2KM7Ef1gL6ae0ae0cH2gL6\r\nContent-Disposition: form-data; name="Upload"\r\n\r\nSubmit Query\r\n------------KM7Ij5cH2KM7Ef1gL6ae0ae0cH2gL6--')
     self.getPage('/flashupload', headers, 'POST', body)
     self.assertBody("Upload: u'Submit Query', Filename: u'.project', Filedata: %r" % filedata)
示例#28
0
    def read_lines_to_boundary(self, fp_out=None):
        """Read bytes from self.fp and return or write them to a file.

        If the 'fp_out' argument is None (the default), all bytes read are
        returned in a single byte string.

        If the 'fp_out' argument is not None, it must be a file-like
        object that supports the 'write' method; all bytes read will be
        written to the fp, and that fp is returned.
        """
        endmarker = self.boundary + ntob('--')
        delim = ntob('')
        prev_lf = True
        lines = []
        seen = 0
        while True:
            line = self.fp.readline(1 << 16)
            if not line:
                raise EOFError('Illegal end of multipart body.')
            if line.startswith(ntob('--')) and prev_lf:
                strippedline = line.strip()
                if strippedline == self.boundary:
                    break
                if strippedline == endmarker:
                    self.fp.finish()
                    break

            line = delim + line

            if line.endswith(ntob('\r\n')):
                delim = ntob('\r\n')
                line = line[:-2]
                prev_lf = True
            elif line.endswith(ntob('\n')):
                delim = ntob('\n')
                line = line[:-1]
                prev_lf = True
            else:
                delim = ntob('')
                prev_lf = False

            if fp_out is None:
                lines.append(line)
                seen += len(line)
                if seen > self.maxrambytes:
                    fp_out = self.make_file()
                    for line in lines:
                        fp_out.write(line)
            else:
                fp_out.write(line)

        if fp_out is None:
            result = ntob('').join(lines)
            return result
        else:
            fp_out.seek(0)
            return fp_out
示例#29
0
    def read_lines_to_boundary(self, fp_out = None):
        endmarker = self.boundary + ntob('--')
        delim = ntob('')
        prev_lf = True
        lines = []
        seen = 0
        while True:
            line = self.fp.readline(65536)
            if not line:
                raise EOFError('Illegal end of multipart body.')
            if line.startswith(ntob('--')) and prev_lf:
                strippedline = line.strip()
                if strippedline == self.boundary:
                    break
                if strippedline == endmarker:
                    self.fp.finish()
                    break
            line = delim + line
            if line.endswith(ntob('\r\n')):
                delim = ntob('\r\n')
                line = line[:-2]
                prev_lf = True
            elif line.endswith(ntob('\n')):
                delim = ntob('\n')
                line = line[:-1]
                prev_lf = True
            else:
                delim = ntob('')
                prev_lf = False
            if fp_out is None:
                lines.append(line)
                seen += len(line)
                if seen > self.maxrambytes:
                    fp_out = self.make_file()
                    for line in lines:
                        fp_out.write(line)

            else:
                fp_out.write(line)

        if fp_out is None:
            result = ntob('').join(lines)
            for charset in self.attempt_charsets:
                try:
                    result = result.decode(charset)
                except UnicodeDecodeError:
                    pass
                else:
                    self.charset = charset
                    return result

            else:
                raise cherrypy.HTTPError(400, 'The request entity could not be decoded. The following charsets were attempted: %s' % repr(self.attempt_charsets))

        else:
            fp_out.seek(0)
            return fp_out
示例#30
0
 def test_multipart_decoding(self):
     body = ntob('\r\n'.join(['--X',
      'Content-Type: text/plain;charset=utf-16',
      'Content-Disposition: form-data; name="text"',
      '',
      '\xff\xfea\x00b\x00\x1c c\x00',
      '--X',
      'Content-Type: text/plain;charset=utf-16',
      'Content-Disposition: form-data; name="submit"',
      '',
      '\xff\xfeC\x00r\x00e\x00a\x00t\x00e\x00',
      '--X--']))
     (self.getPage('/reqparams', method='POST', headers=[('Content-Type', 'multipart/form-data;boundary=X'), ('Content-Length', str(len(body)))], body=body),)
     self.assertBody(ntob('text: ab\xe2\x80\x9cc, submit: Create'))
示例#31
0
 def test_Flash_Upload(self):
     headers = [
         ('Accept', 'text/*'),
         ('Content-Type', 'multipart/form-data; '
              'boundary=----------KM7Ij5cH2KM7Ef1gL6ae0ae0cH2gL6'),
         ('User-Agent', 'Shockwave Flash'),
         ('Host', 'www.example.com:8080'),
         ('Content-Length', '499'),
         ('Connection', 'Keep-Alive'),
         ('Cache-Control', 'no-cache'),
         ]
     filedata = ntob('<?xml version="1.0" encoding="UTF-8"?>\r\n'
                     '<projectDescription>\r\n'
                     '</projectDescription>\r\n')
     body = (ntob(
         '------------KM7Ij5cH2KM7Ef1gL6ae0ae0cH2gL6\r\n'
         'Content-Disposition: form-data; name="Filename"\r\n'
         '\r\n'
         '.project\r\n'
         '------------KM7Ij5cH2KM7Ef1gL6ae0ae0cH2gL6\r\n'
         'Content-Disposition: form-data; '
             'name="Filedata"; filename=".project"\r\n'
         'Content-Type: application/octet-stream\r\n'
         '\r\n')
         + filedata + 
         ntob('\r\n'
         '------------KM7Ij5cH2KM7Ef1gL6ae0ae0cH2gL6\r\n'
         'Content-Disposition: form-data; name="Upload"\r\n'
         '\r\n'
         'Submit Query\r\n'
         # Flash apps omit the trailing \r\n on the last line:
         '------------KM7Ij5cH2KM7Ef1gL6ae0ae0cH2gL6--'
         ))
     self.getPage('/flashupload', headers, "POST", body)
     self.assertBody("Upload: Submit Query, Filename: .project, "
                     "Filedata: %r" % filedata)
示例#32
0
 def __init__(self,
              fp,
              length,
              maxbytes,
              bufsize=io.DEFAULT_BUFFER_SIZE,
              has_trailers=False):
     # Wrap our fp in a buffer so peek() works
     self.fp = fp
     self.length = length
     self.maxbytes = maxbytes
     self.buffer = ntob('')
     self.bufsize = bufsize
     self.bytes_read = 0
     self.done = False
     self.has_trailers = has_trailers
示例#33
0
    def collapse_body(self):
        """Collapse self.body to a single string; replace it and return it."""
        if isinstance(self.body, text_or_bytes):
            return self.body

        newbody = []
        for chunk in self.body:
            if six.PY3 and not isinstance(chunk, bytes):
                raise TypeError("Chunk %s is not of type 'bytes'." %
                                repr(chunk))
            newbody.append(chunk)
        newbody = ntob('').join(newbody)

        self.body = newbody
        return newbody
示例#34
0
    def test_HTTP11_pipelining(self):
        if cherrypy.server.protocol_version != "HTTP/1.1":
            return self.skip()

        self.PROTOCOL = "HTTP/1.1"

        # Test pipelining. httplib doesn't support this directly.
        self.persistent = True
        conn = self.HTTP_CONN

        # Put request 1
        conn.putrequest("GET", "/hello", skip_host=True)
        conn.putheader("Host", self.HOST)
        conn.endheaders()

        for trial in range(5):
            # Put next request
            conn._output(ntob('GET /hello HTTP/1.1'))
            conn._output(ntob("Host: %s" % self.HOST, 'ascii'))
            conn._send_output()

            # Retrieve previous response
            response = conn.response_class(conn.sock, method="GET")
            response.begin()
            body = response.read(13)
            self.assertEqual(response.status, 200)
            self.assertEqual(body, ntob("Hello, world!"))

        # Retrieve final response
        response = conn.response_class(conn.sock, method="GET")
        response.begin()
        body = response.read()
        self.assertEqual(response.status, 200)
        self.assertEqual(body, ntob("Hello, world!"))

        conn.close()
示例#35
0
    def test_malformed_header(self):
        if self.scheme == 'https':
            c = HTTPSConnection('%s:%s' % (self.interface(), self.PORT))
        else:
            c = HTTPConnection('%s:%s' % (self.interface(), self.PORT))
        c.putrequest('GET', '/')
        c.putheader('Content-Type', 'text/plain')
        # See http://www.cherrypy.org/ticket/941
        c._output(ntob('Re, 1.2.3.4#015#012'))
        c.endheaders()

        response = c.getresponse()
        self.status = str(response.status)
        self.assertStatus(400)
        self.body = response.fp.read(20)
        self.assertBody("Illegal header line.")
示例#36
0
    def tee(body):
        if 'no-cache' in response.headers.values('Pragma') or 'no-store' in response.headers.values('Cache-Control'):
            for chunk in body:
                yield chunk

            return
        output = []
        for chunk in body:
            output.append(chunk)
            yield chunk

        body = ntob('').join(output)
        cherrypy._cache.put((response.status,
         response.headers or {},
         body,
         response.time), len(body))
 def getpage():
     host = '%s:%s' % (self.interface(), self.PORT)
     if self.scheme == 'https':
         c = HTTPSConnection(host)
     else:
         c = HTTPConnection(host)
     try:
         c.putrequest('GET', '/')
         c.endheaders()
         response = c.getresponse()
         body = response.read()
         self.assertEqual(response.status, 200)
         self.assertEqual(body, ntob("Hello world!"))
     finally:
         c.close()
     success.append(True)
示例#38
0
def read_process(cmd, args=''):
    fullcmd = '%s %s' % (cmd, args)
    pipeout = popen(fullcmd)
    try:
        firstline = pipeout.readline()
        cmd_not_found = re.search(
            ntob('(not recognized|No such file|not found)'),
            firstline,
            re.IGNORECASE
        )
        if cmd_not_found:
            raise IOError('%s must be on your system path.' % cmd)
        output = firstline + pipeout.read()
    finally:
        pipeout.close()
    return output
示例#39
0
    def test_urlencoded_decoding(self):
        # Test the decoding of an application/x-www-form-urlencoded entity.
        europoundUtf8 = europoundUnicode.encode('utf-8')
        body = ntob("param=") + europoundUtf8
        self.getPage('/',
                     method='POST',
                     headers=[
                         ("Content-Type", "application/x-www-form-urlencoded"),
                         ("Content-Length", str(len(body))),
                     ],
                     body=body),
        self.assertBody(europoundUtf8)

        # Encoded utf8 entities MUST be parsed and decoded correctly.
        # Here, q is the POUND SIGN U+00A3 encoded in utf8
        body = ntob("q=\xc2\xa3")
        self.getPage('/reqparams',
                     method='POST',
                     headers=[
                         ("Content-Type", "application/x-www-form-urlencoded"),
                         ("Content-Length", str(len(body))),
                     ],
                     body=body),
        self.assertBody(ntob("q: \xc2\xa3"))

        # ...and in utf16, which is not in the default attempt_charsets list:
        body = ntob("\xff\xfeq\x00=\xff\xfe\xa3\x00")
        self.getPage('/reqparams',
                     method='POST',
                     headers=[
                         ("Content-Type",
                          "application/x-www-form-urlencoded;charset=utf-16"),
                         ("Content-Length", str(len(body))),
                     ],
                     body=body),
        self.assertBody(ntob("q: \xc2\xa3"))

        # Entities that are incorrectly encoded MUST raise 400.
        # Here, q is the POUND SIGN U+00A3 encoded in utf16, but
        # the Content-Type incorrectly labels it utf-8.
        body = ntob("\xff\xfeq\x00=\xff\xfe\xa3\x00")
        self.getPage('/reqparams',
                     method='POST',
                     headers=[
                         ("Content-Type",
                          "application/x-www-form-urlencoded;charset=utf-8"),
                         ("Content-Length", str(len(body))),
                     ],
                     body=body),
        self.assertStatus(400)
        self.assertErrorPage(
            400,
            "The request entity could not be decoded. The following charsets "
            "were attempted: ['utf-8']")
 def test_multipart_decoding_no_charset(self):
     # Test the decoding of a multipart entity when the charset (utf8) is
     # NOT explicitly given, but is in the list of charsets to attempt.
     body = ntob('\r\n'.join([
         '--X', 'Content-Disposition: form-data; name="text"', '',
         '\xe2\x80\x9c', '--X',
         'Content-Disposition: form-data; name="submit"', '', 'Create',
         '--X--'
     ]))
     self.getPage('/reqparams',
                  method='POST',
                  headers=[
                      ('Content-Type', 'multipart/form-data;boundary=X'),
                      ('Content-Length', str(len(body))),
                  ],
                  body=body),
     self.assertBody(b'submit: Create, text: \xe2\x80\x9c')
示例#41
0
    def setup_server():
        class Root:

            def index(self):
                return "This is public."
            index.exposed = True

        class BasicProtected:

            def index(self):
                return "Hello %s, you've been authorized." % (
                    cherrypy.request.login)
            index.exposed = True

        class BasicProtected2:

            def index(self):
                return "Hello %s, you've been authorized." % (
                    cherrypy.request.login)
            index.exposed = True

        userpassdict = {'xuser': '******'}
        userhashdict = {'xuser': md5(ntob('xpassword')).hexdigest()}

        def checkpasshash(realm, user, password):
            p = userhashdict.get(user)
            return p and p == md5(ntob(password)).hexdigest() or False

        basic_checkpassword_dict = auth_basic.checkpassword_dict(userpassdict)
        conf = {
            '/basic': {
                'tools.auth_basic.on': True,
                'tools.auth_basic.realm': 'wonderland',
                'tools.auth_basic.checkpassword': basic_checkpassword_dict
            },
            '/basic2': {
                'tools.auth_basic.on': True,
                'tools.auth_basic.realm': 'wonderland',
                'tools.auth_basic.checkpassword': checkpasshash
            },
        }

        root = Root()
        root.basic = BasicProtected()
        root.basic2 = BasicProtected2()
        cherrypy.tree.mount(root, config=conf)
示例#42
0
def read_process(cmd, args=""):
    fullcmd = "%s %s" % (cmd, args)
    p = subprocess.Popen(fullcmd,
                         shell=True,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.STDOUT,
                         close_fds=True)
    pipeout = p.stdout
    try:
        firstline = pipeout.readline()
        if (re.search(ntob("(not recognized|No such file|not found)"),
                      firstline, re.IGNORECASE)):
            raise IOError('%s must be on your system path.' % cmd)
        output = firstline + pipeout.read()
    finally:
        pipeout.close()
    return output
示例#43
0
    def tee(body):
        """Tee response.body into a list."""
        if ('no-cache' in response.headers.values('Pragma') or
            'no-store' in response.headers.values('Cache-Control')):
            for chunk in body:
                yield chunk
            return

        output = []
        for chunk in body:
            output.append(chunk)
            yield chunk

        # save the cache data
        body = ntob('').join(output)
        cherrypy._cache.put((response.status, response.headers or {},
                             body, response.time), len(body))
    def setup_server():
        class Root:
            def index(self):
                return "This is public."
            index.exposed = True

        class DigestProtected:
            def index(self):
                return "Hello %s, you've been authorized." % cherrypy.request.login
            index.exposed = True

        class BasicProtected:
            def index(self):
                return "Hello %s, you've been authorized." % cherrypy.request.login
            index.exposed = True

        class BasicProtected2:
            def index(self):
                return "Hello %s, you've been authorized." % cherrypy.request.login
            index.exposed = True

        def fetch_users():
            return {'test': 'test'}

        def sha_password_encrypter(password):
            return sha(ntob(password)).hexdigest()
        
        def fetch_password(username):
            return sha(ntob('test')).hexdigest()

        conf = {'/digest': {'tools.digest_auth.on': True,
                            'tools.digest_auth.realm': 'localhost',
                            'tools.digest_auth.users': fetch_users},
                '/basic': {'tools.basic_auth.on': True,
                           'tools.basic_auth.realm': 'localhost',
                           'tools.basic_auth.users': {'test': md5(ntob('test')).hexdigest()}},
                '/basic2': {'tools.basic_auth.on': True,
                            'tools.basic_auth.realm': 'localhost',
                            'tools.basic_auth.users': fetch_password,
                            'tools.basic_auth.encrypt': sha_password_encrypter}}
                
        root = Root()
        root.digest = DigestProtected()
        root.basic = BasicProtected()
        root.basic2 = BasicProtected2()
        cherrypy.tree.mount(root, config=conf)
示例#45
0
                def file_ranges():
                    yield ntob('\r\n')
                    for start, stop in r:
                        if debug:
                            cherrypy.log('Multipart; start: %r, stop: %r' % (start, stop), 'TOOLS.STATIC')
                        yield ntob('--' + boundary, 'ascii')
                        yield ntob('\r\nContent-type: %s' % content_type, 'ascii')
                        yield ntob('\r\nContent-range: bytes %s-%s/%s\r\n\r\n' % (start, stop - 1, content_length), 'ascii')
                        fileobj.seek(start)
                        for chunk in file_generator_limited(fileobj, stop - start):
                            yield chunk

                        yield ntob('\r\n')

                    yield ntob('--' + boundary + '--', 'ascii')
                    yield ntob('\r\n')
示例#46
0
    def finalize(self):
        """Transform headers (and cookies) into self.header_list. (Core)"""
        try:
            code, reason, _ = httputil.valid_status(self.status)
        except ValueError:
            raise cherrypy.HTTPError(500, sys.exc_info()[1].args[0])

        headers = self.headers

        self.status = '%s %s' % (code, reason)
        self.output_status = ntob(str(code), 'ascii') + \
            b' ' + headers.encode(reason)

        if self.stream:
            # The upshot: wsgiserver will chunk the response if
            # you pop Content-Length (or set it explicitly to None).
            # Note that lib.static sets C-L to the file's st_size.
            if dict.get(headers, 'Content-Length') is None:
                dict.pop(headers, 'Content-Length', None)
        elif code < 200 or code in (204, 205, 304):
            # "All 1xx (informational), 204 (no content),
            # and 304 (not modified) responses MUST NOT
            # include a message-body."
            dict.pop(headers, 'Content-Length', None)
            self._flush_body()
            self.body = b''
        else:
            # Responses which are not streamed should have a Content-Length,
            # but allow user code to set Content-Length if desired.
            if dict.get(headers, 'Content-Length') is None:
                content = self.collapse_body()
                dict.__setitem__(headers, 'Content-Length', len(content))

        # Transform our header dict into a list of tuples.
        self.header_list = h = headers.output()

        cookie = self.cookie.output()
        if cookie:
            for line in cookie.split('\r\n'):
                name, value = line.split(': ', 1)
                if isinstance(name, six.text_type):
                    name = name.encode('ISO-8859-1')
                if isinstance(value, six.text_type):
                    value = headers.encode(value)
                h.append((name, value))
示例#47
0
    def start_apache(self):
        fcgiconf = CONF_PATH
        if not os.path.isabs(fcgiconf):
            fcgiconf = os.path.join(curdir, fcgiconf)
        f = open(fcgiconf, 'wb')
        try:
            server = repr(os.path.join(curdir, 'fastcgi.pyc'))[1:-1]
            output = self.template % {'port': self.port,
             'root': curdir,
             'server': server}
            output = ntob(output.replace('\r\n', '\n'))
            f.write(output)
        finally:
            f.close()

        result = read_process(APACHE_PATH, '-k start -f %s' % fcgiconf)
        if result:
            print result
示例#48
0
    def test_598(self):
        remote_data_conn = urlopen('%s://%s:%s/one_megabyte_of_a/' %
                                   (self.scheme, self.HOST, self.PORT))
        buf = remote_data_conn.read(512)
        time.sleep(timeout * 0.6)
        remaining = 1048064
        while remaining:
            data = remote_data_conn.read(remaining)
            if not data:
                break
            else:
                buf += data
            remaining -= len(data)

        self.assertEqual(len(buf), 1048576)
        self.assertEqual(buf, ntob('a' * 1024 * 1024))
        self.assertEqual(remaining, 0)
        remote_data_conn.close()
示例#49
0
 def test_multipart_decoding_no_successful_charset(self):
     body = ntob('\r\n'.join([
         '--X', 'Content-Disposition: form-data; name="text"', '',
         '\xff\xfea\x00b\x00\x1c c\x00', '--X',
         'Content-Disposition: form-data; name="submit"', '',
         '\xff\xfeC\x00r\x00e\x00a\x00t\x00e\x00', '--X--'
     ]))
     (self.getPage('/reqparams',
                   method='POST',
                   headers=[('Content-Type',
                             'multipart/form-data;boundary=X'),
                            ('Content-Length', str(len(body)))],
                   body=body), )
     self.assertStatus(400)
     self.assertErrorPage(
         400,
         "The request entity could not be decoded. The following charsets were attempted: ['us-ascii', 'utf-8']"
     )
示例#50
0
 def write_conf(self, extra=''):
     if self.ssl:
         serverpem = os.path.join(thisdir, 'test.pem')
         ssl = "\nserver.ssl_certificate: r'%s'\nserver.ssl_private_key: r'%s'\n" % (
             serverpem, serverpem)
     else:
         ssl = ''
     conf = self.config_template % {
         'host': self.host,
         'port': self.port,
         'error_log': self.error_log,
         'access_log': self.access_log,
         'ssl': ssl,
         'extra': extra
     }
     f = open(self.config_file, 'wb')
     f.write(ntob(conf, 'utf-8'))
     f.close()
 def test_multipart_decoding(self):
     # Test the decoding of a multipart entity when the charset (utf16) is
     # explicitly given.
     body = ntob('\r\n'.join([
         '--X', 'Content-Type: text/plain;charset=utf-16',
         'Content-Disposition: form-data; name="text"', '',
         '\xff\xfea\x00b\x00\x1c c\x00', '--X',
         'Content-Type: text/plain;charset=utf-16',
         'Content-Disposition: form-data; name="submit"', '',
         '\xff\xfeC\x00r\x00e\x00a\x00t\x00e\x00', '--X--'
     ]))
     self.getPage('/reqparams',
                  method='POST',
                  headers=[
                      ('Content-Type', 'multipart/form-data;boundary=X'),
                      ('Content-Length', str(len(body))),
                  ],
                  body=body),
     self.assertBody(b'submit: Create, text: ab\xe2\x80\x9cc')
示例#52
0
    def test_signal_handler_unsubscribe(self):
        try:
            from signal import SIGTERM
        except ImportError:
            return self.skip('skipped (no SIGTERM) ')

        try:
            from os import kill
        except ImportError:
            return self.skip('skipped (no os.kill) ')

        p = helper.CPProcess(ssl=self.scheme.lower() == 'https')
        p.write_conf(extra='unsubsig: True\ntest_case_name: "test_signal_handler_unsubscribe"\n')
        p.start(imports='cherrypy.test._test_states_demo')
        os.kill(p.get_pid(), SIGTERM)
        p.join()
        target_line = open(p.error_log, 'rb').readlines()[-10]
        if ntob('I am an old SIGTERM handler.') not in target_line:
            self.fail('Old SIGTERM handler did not run.\n%r' % target_line)
示例#53
0
    def login_screen(self,
                     from_page='..',
                     username='',
                     error_msg='',
                     **kwargs):
        return ntob(
            """<html><body>
Message: %(error_msg)s
<form method="post" action="do_login">
    Login: <input type="text" name="username" value="%(username)s" size="10" /><br />
    Password: <input type="password" name="password" size="10" /><br />
    <input type="hidden" name="from_page" value="%(from_page)s" /><br />
    <input type="submit" />
</form>
</body></html>""" % {
                'from_page': from_page,
                'username': username,
                'error_msg': error_msg
            }, "utf-8")
示例#54
0
 def test_no_content_length(self):
     if self.scheme == 'https':
         c = HTTPSConnection('%s:%s' % (self.interface(), self.PORT))
     else:
         c = HTTPConnection('%s:%s' % (self.interface(), self.PORT))
     c.request('POST', '/no_body')
     response = c.getresponse()
     self.body = response.fp.read()
     self.status = str(response.status)
     self.assertStatus(200)
     self.assertBody(ntob('Hello world!'))
     if self.scheme == 'https':
         c = HTTPSConnection('%s:%s' % (self.interface(), self.PORT))
     else:
         c = HTTPConnection('%s:%s' % (self.interface(), self.PORT))
     c.request('POST', '/')
     response = c.getresponse()
     self.body = response.fp.read()
     self.status = str(response.status)
     self.assertStatus(411)
示例#55
0
 def test_urlencoded_decoding(self):
     europoundUtf8 = europoundUnicode.encode('utf-8')
     body = ntob('param=') + europoundUtf8
     (self.getPage('/', method='POST', headers=[('Content-Type', 'application/x-www-form-urlencoded'), ('Content-Length', str(len(body)))], body=body),)
     self.assertBody(europoundUtf8)
     body = ntob('q=\xc2\xa3')
     (self.getPage('/reqparams', method='POST', headers=[('Content-Type', 'application/x-www-form-urlencoded'), ('Content-Length', str(len(body)))], body=body),)
     self.assertBody(ntob('q: \xc2\xa3'))
     body = ntob('\xff\xfeq\x00=\xff\xfe\xa3\x00')
     (self.getPage('/reqparams', method='POST', headers=[('Content-Type', 'application/x-www-form-urlencoded;charset=utf-16'), ('Content-Length', str(len(body)))], body=body),)
     self.assertBody(ntob('q: \xc2\xa3'))
     body = ntob('\xff\xfeq\x00=\xff\xfe\xa3\x00')
     (self.getPage('/reqparams', method='POST', headers=[('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8'), ('Content-Length', str(len(body)))], body=body),)
     self.assertStatus(400)
     self.assertErrorPage(400, "The request entity could not be decoded. The following charsets were attempted: ['utf-8']")
示例#56
0
    def test_HTTP11_pipelining(self):
        if cherrypy.server.protocol_version != 'HTTP/1.1':
            return self.skip()

        self.PROTOCOL = 'HTTP/1.1'

        # Test pipelining. httplib doesn't support this directly.
        self.persistent = True
        conn = self.HTTP_CONN

        # Put request 1
        conn.putrequest('GET', '/hello', skip_host=True)
        conn.putheader('Host', self.HOST)
        conn.endheaders()

        for trial in range(5):
            # Put next request
            conn._output(b'GET /hello HTTP/1.1')
            conn._output(ntob('Host: %s' % self.HOST, 'ascii'))
            conn._send_output()

            # Retrieve previous response
            response = conn.response_class(conn.sock, method='GET')
            # there is a bug in python3 regarding the buffering of
            # ``conn.sock``. Until that bug get's fixed we will
            # monkey patch the ``response`` instance.
            # https://bugs.python.org/issue23377
            response.fp = conn.sock.makefile('rb', 0)
            response.begin()
            body = response.read(13)
            self.assertEqual(response.status, 200)
            self.assertEqual(body, b'Hello, world!')

        # Retrieve final response
        response = conn.response_class(conn.sock, method='GET')
        response.begin()
        body = response.read()
        self.assertEqual(response.status, 200)
        self.assertEqual(body, b'Hello, world!')

        conn.close()
示例#57
0
def _be_ie_unfriendly(status):
    response = cherrypy.serving.response

    # For some statuses, Internet Explorer 5+ shows "friendly error
    # messages" instead of our response.body if the body is smaller
    # than a given size. Fix this by returning a body over that size
    # (by adding whitespace).
    # See http://support.microsoft.com/kb/q218155/
    s = _ie_friendly_error_sizes.get(status, 0)
    if s:
        s += 1
        # Since we are issuing an HTTP error status, we assume that
        # the entity is short, and we should just collapse it.
        content = response.collapse_body()
        content_length = len(content)
        if content_length and content_length < s:
            # IN ADDITION: the response must be written to IE
            # in one chunk or it will still get replaced! Bah.
            content = content + (ntob(' ') * (s - content_length))
        response.body = content
        response.headers['Content-Length'] = str(len(content))
示例#58
0
 def test_multipart_decoding_no_successful_charset(self):
     # Test the decoding of a multipart entity when the charset (utf16) is
     # NOT explicitly given, and is NOT in the list of charsets to attempt.
     body = ntob('\r\n'.join([
         '--X', 'Content-Disposition: form-data; name="text"', '',
         '\xff\xfea\x00b\x00\x1c c\x00', '--X',
         'Content-Disposition: form-data; name="submit"', '',
         '\xff\xfeC\x00r\x00e\x00a\x00t\x00e\x00', '--X--'
     ]))
     self.getPage('/reqparams',
                  method='POST',
                  headers=[
                      ("Content-Type", "multipart/form-data;boundary=X"),
                      ("Content-Length", str(len(body))),
                  ],
                  body=body),
     self.assertStatus(400)
     self.assertErrorPage(
         400,
         "The request entity could not be decoded. The following charsets "
         "were attempted: ['us-ascii', 'utf-8']")
示例#59
0
    def test_query_string_decoding(self):
        URI_TMPL = '/reqparams?q={q}'

        europoundUtf8_2_bytes = europoundUnicode.encode('utf-8')
        europoundUtf8_2nd_byte = europoundUtf8_2_bytes[1:2]

        # Encoded utf8 query strings MUST be parsed correctly.
        # Here, q is the POUND SIGN U+00A3 encoded in utf8 and then %HEX
        self.getPage(URI_TMPL.format(q=url_quote(europoundUtf8_2_bytes)))
        # The return value will be encoded as utf8.
        self.assertBody(ntob('q: ') + europoundUtf8_2_bytes)

        # Query strings that are incorrectly encoded MUST raise 404.
        # Here, q is the second byte of POUND SIGN U+A3 encoded in utf8
        # and then %HEX
        # TODO: check whether this shouldn't raise 400 Bad Request instead
        self.getPage(URI_TMPL.format(q=url_quote(europoundUtf8_2nd_byte)))
        self.assertStatus(404)
        self.assertErrorPage(
            404, 'The given query string could not be processed. Query '
            "strings for this resource must be encoded with 'utf8'.")
示例#60
0
 def trap(self, func, *args, **kwargs):
     try:
         return func(*args, **kwargs)
     except self.throws:
         raise
     except StopIteration:
         raise
     except:
         tb = _cperror.format_exc()
         #print('trapped (started %s):' % self.started_response, tb)
         _cherrypy.log(tb, severity=40)
         if not _cherrypy.request.show_tracebacks:
             tb = ""
         s, h, b = _cperror.bare_error(tb)
         if py3k:
             # What fun.
             s = s.decode('ISO-8859-1')
             h = [(k.decode('ISO-8859-1'), v.decode('ISO-8859-1'))
                  for k, v in h]
         if self.started_response:
             # Empty our iterable (so future calls raise StopIteration)
             self.iter_response = iter([])
         else:
             self.iter_response = iter(b)
         
         try:
             self.start_response(s, h, _sys.exc_info())
         except:
             # "The application must not trap any exceptions raised by
             # start_response, if it called start_response with exc_info.
             # Instead, it should allow such exceptions to propagate
             # back to the server or gateway."
             # But we still log and call close() to clean up ourselves.
             _cherrypy.log(traceback=True, severity=40)
             raise
         
         if self.started_response:
             return ntob("").join(b)
         else:
             return b