def _preview(is_request): if is_request: template = "request_preview.html" else: template = "response_preview.html" spec = request.args["spec"] args = dict( spec = spec, section = "main", syntaxerror = None, error = None, pauses = None ) if not spec.strip(): args["error"] = "Can't parse an empty spec." return render(template, False, **args) try: if is_request: r = rparse.parse_request(app.config["pathod"].request_settings, spec) else: r = rparse.parse_response(app.config["pathod"].request_settings, spec) except rparse.ParseException, v: args["syntaxerror"] = str(v) args["marked"] = v.marked() return render(template, False, **args)
def __init__(self, addr, ssloptions=None, craftanchor="/p/", staticdir=None, anchors=None, sizelimit=None, noweb=False, nocraft=False, noapi=False, nohang=False, timeout=None, logreq=False, logresp=False, hexdump=False): """ addr: (address, port) tuple. If port is 0, a free port will be automatically chosen. ssloptions: a dictionary containing certfile and keyfile specifications. craftanchor: string specifying the path under which to anchor response generation. staticdir: path to a directory of static resources, or None. anchors: A list of (regex, spec) tuples, or None. sizelimit: Limit size of served data. nocraft: Disable response crafting. noapi: Disable the API. nohang: Disable pauses. """ tcp.TCPServer.__init__(self, addr) self.ssloptions = ssloptions self.staticdir = staticdir self.craftanchor = craftanchor self.sizelimit = sizelimit self.noweb, self.nocraft, self.noapi, self.nohang = noweb, nocraft, noapi, nohang self.timeout, self.logreq, self.logresp, self.hexdump = timeout, logreq, logresp, hexdump if not noapi: app.api() self.app = app.app self.app.config["pathod"] = self self.log = [] self.logid = 0 self.anchors = [] if anchors: for i in anchors: try: arex = re.compile(i[0]) except re.error: raise PathodError("Invalid regex in anchor: %s" % i[0]) try: aresp = rparse.parse_response(self.request_settings, i[1]) except rparse.ParseException, v: raise PathodError("Invalid page spec in anchor: '%s', %s" % (i[1], str(v))) self.anchors.append((arex, i[1]))
def __init__( self, addr, ssloptions=None, craftanchor="/p/", staticdir=None, anchors=None, sizelimit=None, noweb=False, nocraft=False, noapi=False, nohang=False, timeout=None, logreq=False, logresp=False, hexdump=False ): """ addr: (address, port) tuple. If port is 0, a free port will be automatically chosen. ssloptions: a dictionary containing certfile and keyfile specifications. craftanchor: string specifying the path under which to anchor response generation. staticdir: path to a directory of static resources, or None. anchors: A list of (regex, spec) tuples, or None. sizelimit: Limit size of served data. nocraft: Disable response crafting. noapi: Disable the API. nohang: Disable pauses. """ tcp.TCPServer.__init__(self, addr) self.ssloptions = ssloptions self.staticdir = staticdir self.craftanchor = craftanchor self.sizelimit = sizelimit self.noweb, self.nocraft, self.noapi, self.nohang = noweb, nocraft, noapi, nohang self.timeout, self.logreq, self.logresp, self.hexdump = timeout, logreq, logresp, hexdump if not noapi: app.api() self.app = app.app self.app.config["pathod"] = self self.log = [] self.logid = 0 self.anchors = [] if anchors: for i in anchors: try: arex = re.compile(i[0]) except re.error: raise PathodError("Invalid regex in anchor: %s"%i[0]) try: aresp = rparse.parse_response(self.request_settings, i[1]) except rparse.ParseException, v: raise PathodError("Invalid page spec in anchor: '%s', %s"%(i[1], str(v))) self.anchors.append((arex, i[1]))
class PathodHandler(tcp.BaseHandler): wbufsize = 0 sni = None def info(self, s): logger.info("%s:%s: %s" % (self.client_address[0], self.client_address[1], str(s))) def handle_sni(self, connection): self.sni = connection.get_servername() def serve_crafted(self, crafted, request_log): response_log = crafted.serve(self.wfile, self.server.check_policy) log = dict(type="crafted", request=request_log, response=response_log) if response_log["disconnect"]: return False, log return True, log def handle_request(self): """ Returns a (again, log) tuple. again: True if request handling should continue. log: A dictionary, or None """ line = self.rfile.readline() if line == "\r\n" or line == "\n": # Possible leftover from previous message line = self.rfile.readline() if line == "": # Normal termination return False, None parts = http.parse_init_http(line) if not parts: s = "Invalid first line: %s" % repr(line) self.info(s) return False, dict(type="error", msg=s) method, path, httpversion = parts headers = http.read_headers(self.rfile) if headers is None: s = "Invalid headers" self.info(s) return False, dict(type="error", msg=s) request_log = dict( path=path, method=method, headers=headers.lst, httpversion=httpversion, sni=self.sni, remote_address=self.client_address, ) try: content = http.read_http_body_request(self.rfile, self.wfile, headers, httpversion, None) except http.HttpError, s: s = str(s) self.info(s) return False, dict(type="error", msg=s) for i in self.server.anchors: if i[0].match(path): self.info("crafting anchor: %s" % path) aresp = rparse.parse_response(self.server.request_settings, i[1]) return self.serve_crafted(aresp, request_log) if not self.server.nocraft and path.startswith( self.server.craftanchor): spec = urllib.unquote(path)[len(self.server.craftanchor):] self.info("crafting spec: %s" % spec) try: crafted = rparse.parse_response(self.server.request_settings, spec) except rparse.ParseException, v: self.info("Parse error: %s" % v.msg) crafted = rparse.PathodErrorResponse( "Parse Error", "Error parsing response spec: %s\n" % v.msg + v.marked()) except rparse.FileAccessDenied: self.info("File access denied") crafted = rparse.PathodErrorResponse("Access Denied")