Esempio n. 1
0
def redirect(req, location, permanent=0, text=None):
    """
    A convenience function to provide redirection
    """

    if not isinstance(location, str):
        raise TypeError("location must be of type str")

    if req.sent_bodyct:
        raise IOError("Cannot redirect after headers have already been sent.")

    req.err_headers_out["Location"] = location
    if permanent:
        req.status = apache.HTTP_MOVED_PERMANENTLY
    else:
        req.status = apache.HTTP_MOVED_TEMPORARILY

    if text is None:
        req.write('<p>The document has moved'
                 ' <a href="%s">here</a></p>\n'
                 % location)
    else:
        req.write(text)

    raise apache.SERVER_RETURN(apache.DONE)
Esempio n. 2
0
    def __init__(self,
                 req,
                 keep_blank_values=0,
                 strict_parsing=0,
                 file_callback=None,
                 field_callback=None):
        #
        # Whenever readline is called ALWAYS use the max size EVEN when
        # not expecting a long line. - this helps protect against
        # malformed content from exhausting memory.
        #

        self.list = FieldList()

        # always process GET-style parameters
        if req.args:
            pairs = parse_qsl(req.args, keep_blank_values)
            for pair in pairs:
                self.add_field(pair[0], pair[1])

        if req.method != "POST":
            return

        try:
            clen = int(req.headers_in["content-length"])
        except (KeyError, ValueError):
            # absent content-length is not acceptable
            raise apache.SERVER_RETURN(apache.HTTP_LENGTH_REQUIRED)

        if "content-type" not in req.headers_in:
            ctype = b"application/x-www-form-urlencoded"
        else:
            ctype = req.headers_in["content-type"].encode("latin1")

        if not isinstance(ctype, bytes):
            raise TypeError("ctype must be of type bytes")

        if ctype.startswith(b"application/x-www-form-urlencoded"):
            v = req.read(clen)
            if not isinstance(v, bytes):
                raise TypeError("req.read() must return bytes")
            pairs = parse_qsl(v, keep_blank_values)
            for pair in pairs:
                self.add_field(pair[0], pair[1])
            return

        if not ctype.startswith(b"multipart/"):
            # we don't understand this content-type
            raise apache.SERVER_RETURN(apache.HTTP_NOT_IMPLEMENTED)

        # figure out boundary
        try:
            i = ctype.lower().rindex(b"boundary=")
            boundary = ctype[i + 9:]
            if len(boundary) >= 2 and boundary[:1] == boundary[-1:] == b'"':
                boundary = boundary[1:-1]
            boundary = re.compile(b"--" + re.escape(boundary) + b"(--)?\r?\n")

        except ValueError:
            raise apache.SERVER_RETURN(apache.HTTP_BAD_REQUEST)

        # read until boundary
        self.read_to_boundary(req, boundary, None)

        end_of_stream = False
        while not end_of_stream:
            ## parse headers

            ctype, type_options = b"text/plain", {}
            disp, disp_options = None, {}
            headers = apache.make_table()

            line = req.readline(readBlockSize)
            if not isinstance(line, bytes):
                raise TypeError("req.readline() must return bytes")
            match = boundary.match(line)
            if (not line) or match:
                # we stop if we reached the end of the stream or a stop
                # boundary (which means '--' after the boundary) we
                # continue to the next part if we reached a simple
                # boundary in either case this would mean the entity is
                # malformed, but we're tolerating it anyway.
                end_of_stream = (not line) or (match.group(1) is not None)
                continue

            skip_this_part = False
            while line not in (b'\r', b'\r\n'):
                nextline = req.readline(readBlockSize)
                while nextline and nextline[:1] in [b' ', b'\t']:
                    line = line + nextline
                    nextline = req.readline(readBlockSize)
                # we read the headers until we reach an empty line
                # NOTE : a single \n would mean the entity is malformed, but
                # we're tolerating it anyway
                h, v = line.split(b":", 1)
                headers.add(
                    h, v)  # mp_table accepts bytes, but always returns str
                h = h.lower()
                if h == b"content-disposition":
                    disp, disp_options = parse_header(v)
                elif h == b"content-type":
                    ctype, type_options = parse_header(v)
                    #
                    # NOTE: FIX up binary rubbish sent as content type
                    # from Microsoft IE 6.0 when sending a file which
                    # does not have a suffix.
                    #
                    if ctype.find(b'/') == -1:
                        ctype = b'application/octet-stream'

                line = nextline
                match = boundary.match(line)
                if (not line) or match:
                    # we stop if we reached the end of the stream or a
                    # stop boundary (which means '--' after the
                    # boundary) we continue to the next part if we
                    # reached a simple boundary in either case this
                    # would mean the entity is malformed, but we're
                    # tolerating it anyway.
                    skip_this_part = True
                    end_of_stream = (not line) or (match.group(1) is not None)
                    break

            if skip_this_part:
                continue

            if b"name" in disp_options:
                name = disp_options[b"name"]
            else:
                name = None

            # create a file object
            # is this a file?
            filename = None
            if b"filename" in disp_options:
                filename = disp_options[b"filename"]
                if file_callback and isinstance(file_callback,
                                                collections.Callable):
                    file = file_callback(filename)
                else:
                    file = tempfile.TemporaryFile("w+b")
            else:
                if field_callback and isinstance(field_callback,
                                                 collections.Callable):
                    file = field_callback()
                else:
                    file = BytesIO()

            # read it in
            self.read_to_boundary(req, boundary, file)
            file.seek(0)

            # make a Field
            if filename:
                field = Field(name)
                field.filename = filename
            else:
                field = StringField(file.read())
                field.name = name
            field.file = file
            field.type = PY2 and ctype or ctype.decode('latin1')
            field.type_options = type_options
            field.disposition = PY2 and disp or disp.decode('latin1')
            field.disposition_options = disp_options
            field.headers = headers
            self.list.append(field)