def __init__(self, req): self.req = req self.response_started = 0 # reqpb self.reqpb = apache.make_table() self.reqpb["clf-request"] = self.req.the_request self.reqpb["method"] = self.req.method self.reqpb["protocol"] = self.req.subprocess_env["SERVER_PROTOCOL"] self.reqpb["uri"] = self.req.uri self.reqpb["query"] = self.req.subprocess_env["QUERY_STRING"] # headers self.headers = self.req.headers_in # srvhdrs self.srvhdrs = self.req.headers_out # vars self.vars = apache.make_table() pw = self.req.get_basic_auth_pw() if pw: self.vars["auth-password"] = pw if self.req.connection.ap_auth_type: self.vars["auth-type"] = self.req.connection.ap_auth_type if self.req.connection.user: self.vars["auth-user"] = self.req.connection.user if self.req.path_info: self.vars["path-info"] = self.req.path_info if self.req.subprocess_env.has_key("PATH_TRANSLATED"): self.vars["path-translated"] = self.req.subprocess_env["PATH_TRANSLATED"] if self.req.filename: self.vars["path"] = self.req.filename
def NSAPI_ParameterBlock(req): pb = apache.make_table() conf = req.get_config() opt = req.get_options() for k in conf.keys(): pb[k] = conf[k] for k in opt.keys(): pb[k] = opt[k] pb["fn"] = "python_request_handler" pb["method"] = "GET|HEAD|POST" pb["server-software"] = "Apache" pb["type"] = req.content_type pw = req.get_basic_auth_pw() pb["auth-password"] = pw pb["auth-type"] = req.connection.ap_auth_type pb["auth-user"] = req.connection.user return NSAPI_Pblock(pb)
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)
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)
def __init__(self, req, keep_blank_values=0, strict_parsing=0): self._req =_req = req._req self.list = [] # always process GET-style parameters if _req.args: pairs = parse_qsl(req.args, keep_blank_values) for pair in pairs: file = StringIO.StringIO(pair[1]) self.list.append(Field(pair[0], file, "text/plain", {}, None, {})) if _req.method == "POST": 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 not _req.headers_in.has_key("content-type"): ctype = "application/x-www-form-urlencoded" else: ctype = _req.headers_in["content-type"] if ctype == "application/x-www-form-urlencoded": pairs = parse_qsl(req.read(clen), keep_blank_values) for pair in pairs: file = StringIO.StringIO(pair[1]) self.list.append(Field(pair[0], file, "text/plain", {}, None, {})) elif ctype[:10] == "multipart/": # figure out boundary # XXX what about req.boundary? try: i = string.rindex(string.lower(ctype), "boundary=") boundary = ctype[i+9:] if len(boundary) >= 2 and boundary[0] == boundary[-1] == '"': boundary = boundary[1:-1] boundary = "--" + boundary except ValueError: raise apache.SERVER_RETURN, apache.HTTP_BAD_REQUEST #read until boundary line = _req.readline() sline = string.strip(line) while line and sline != boundary: line = _req.readline() while 1: ## parse headers ctype, type_options = "text/plain", {} disp, disp_options = None, {} headers = apache.make_table() line = _req.readline() while line and line not in ["\n", "\r\n"]: h, v = string.split(line, ":", 1) headers.add(h, v) h = string.lower(h) if h == "content-disposition": disp, disp_options = parse_header(v) elif h == "content-type": ctype, type_options = parse_header(v) line = _req.readline() if disp_options.has_key("name"): name = disp_options["name"] else: name = None # is this a file? if disp_options.has_key("filename"): file = self.make_file() else: file = StringIO.StringIO() # read it in self.read_to_boundary(_req, boundary, file) file.seek(0) # make a Field field = Field(name, file, ctype, type_options, disp, disp_options) field.headers = headers if disp_options.has_key("filename"): field.filename = disp_options["filename"] self.list.append(field) if not line or sline == (boundary + "--"): break else: # we don't understand this content-type raise apache.SERVER_RETURN, apache.HTTP_NOT_IMPLEMENTED
def client(self): client = apache.make_table() client["ip"] = self.req.connection.remote_ip client["dns"] = self.req.connection.remote_host return client