def request(self, spec): """ Return an (httpversion, code, msg, headers, content) tuple. May raise language.ParseException, netlib.http.HttpError or language.FileAccessDenied. """ r = language.parse_request(self.settings, spec) language.serve(r, self.wfile, self.settings, self.address.host) self.wfile.flush() return Response(*http.read_response(self.rfile, r.method, None))
def request(self, spec): """ Return an (httpversion, code, msg, headers, content) tuple. May raise language.ParseException, netlib.http.HttpError or language.FileAccessDenied. """ r = language.parse_request(self.settings, spec) language.serve(r, self.wfile, self.settings, self.address.host) self.wfile.flush() ret = list(http.read_response(self.rfile, r.method.string(), None)) ret.append(self.sslinfo) return Response(*ret)
def http(self, r): """ Performs a single request. r: A language.Request object, or a string representing one request. Returns Response if we have a non-ignored response. May raise http.HTTPError, tcp.NetLibError """ if isinstance(r, basestring): r = language.parse_requests(r)[0] resp, req = None, None if self.showreq: self.wfile.start_log() if self.showresp: self.rfile.start_log() try: req = language.serve(r, self.wfile, self.settings) self.wfile.flush() resp = list( http.read_response( self.rfile, req["method"], None ) ) resp.append(self.sslinfo) resp = Response(*resp) except http.HttpError, v: if self.showsummary: print >> self.fp, "<< HTTP Error:", v.message raise
def websocket_send_frame(self, r): """ Sends a single websocket frame. """ req = None if isinstance(r, basestring): r = language.parse_requests(r)[0] if self.showreq: self.wfile.start_log() try: req = language.serve(r, self.wfile, self.settings) self.wfile.flush() except tcp.NetLibTimeout: if self.ignoretimeout: return None if self.showsummary: print >> self.fp, "<<", "Timeout" raise except tcp.NetLibDisconnect: # pragma: nocover if self.showsummary: print >> self.fp, "<<", "Disconnect" raise finally: if req: if self.explain: print >> self.fp, ">> Spec:", r.spec() if self.showreq: self._show( self.fp, ">> Request", self.wfile.get_log(), self.hexdump )
def http(self, r): """ Performs a single request. r: A language.Request object, or a string representing one request. Returns Response if we have a non-ignored response. May raise http.HTTPError, tcp.NetLibError """ if isinstance(r, basestring): r = language.parse_requests(r)[0] resp, req = None, None if self.showreq: self.wfile.start_log() if self.showresp: self.rfile.start_log() try: req = language.serve(r, self.wfile, self.settings) self.wfile.flush() resp = list(http.read_response(self.rfile, req["method"], None)) resp.append(self.sslinfo) resp = Response(*resp) except http.HttpError, v: if self.showsummary: print >> self.fp, "<< HTTP Error:", v.message raise
def websocket_send_frame(self, r): """ Sends a single websocket frame. """ req = None if isinstance(r, basestring): r = language.parse_requests(r)[0] if self.showreq: self.wfile.start_log() try: req = language.serve(r, self.wfile, self.settings) self.wfile.flush() except tcp.NetLibTimeout: if self.ignoretimeout: return None if self.showsummary: print >> self.fp, "<<", "Timeout" raise except tcp.NetLibDisconnect: # pragma: nocover if self.showsummary: print >> self.fp, "<<", "Disconnect" raise finally: if req: if self.explain: print >> self.fp, ">> Spec:", r.spec() if self.showreq: self._show(self.fp, ">> Request", self.wfile.get_log(), self.hexdump)
def serve_crafted(self, crafted): c = self.server.check_policy(crafted, self.server.request_settings) if c: err = language.make_error_response(c) language.serve(err, self.wfile, self.server.request_settings) log = dict(type="error", msg=c) return False, log if self.server.explain and not isinstance( crafted, language.PathodErrorResponse): crafted = crafted.freeze(self.server.request_settings, None) self.info(">> Spec: %s" % crafted.spec()) response_log = language.serve(crafted, self.wfile, self.server.request_settings, None) if response_log["disconnect"]: return False, response_log return True, response_log
def serve_crafted(self, crafted): c = self.server.check_policy(crafted, self.server.request_settings) if c: err = language.make_error_response(c) language.serve(err, self.wfile, self.server.request_settings) log = dict( type = "error", msg = c ) return False, log if self.server.explain and not isinstance(crafted, language.PathodErrorResponse): crafted = crafted.freeze(self.server.request_settings, None) self.info(">> Spec: %s"%crafted.spec()) response_log = language.serve(crafted, self.wfile, self.server.request_settings, None) if response_log["disconnect"]: return False, response_log return True, response_log
def request(self, spec): """ Return a PathocResult namedtuple. May raise language.ParseException, netlib.http.HttpError or language.FileAccessDenied. """ r = language.parse_request(self.settings, spec) ret = language.serve(r, self.wfile, self.settings, self.host) self.wfile.flush() return PathocResult._make(http.read_response(self.rfile, r.method, None))
def serve_crafted(self, crafted, request_log): c = self.server.check_policy(crafted, self.server.request_settings) if c: err = language.PathodErrorResponse(c) language.serve(err, self.wfile, self.server.request_settings) log = dict( type = "error", msg = c ) return False, log if self.server.explain: crafted = crafted.freeze(self.server.request_settings, None) response_log = language.serve(crafted, self.wfile, self.server.request_settings, None) log = dict( type = "crafted", request=request_log, response=response_log ) if response_log["disconnect"]: return False, log return True, log
def pipelined_requests(self, specs): """ Return a list of PathocResult namedtuple's. The requests defined by the list of spec are sent using http pipelining. May raise language.ParseException, netlib.http.HttpError or language.FileAccessDenied. """ parsed_specs = {} # spec -> r, ret for spec in specs: r = language.parse_request(self.settings, spec) ret = language.serve(r, self.wfile, self.settings, self.host) parsed_specs[spec] = r, ret self.wfile.flush() rval = [] for spec in specs: r, ret = parsed_specs[spec] result = PathocResult._make(http.read_response(self.rfile, r.method, None)) rval.append(result) return rval
self.server.craftanchor): spec = urllib.unquote(path)[len(self.server.craftanchor):] self.info("crafting spec: %s" % spec) try: crafted = language.parse_response(self.server.request_settings, spec) except language.ParseException, v: self.info("Parse error: %s" % v.msg) crafted = language.make_error_response( "Parse Error", "Error parsing response spec: %s\n" % v.msg + v.marked()) again, retlog["response"] = self.serve_crafted(crafted) return again, retlog elif self.server.noweb: crafted = language.make_error_response("Access Denied") language.serve(crafted, self.wfile, self.server.request_settings) return False, dict(type="error", msg="Access denied: web interface disabled") else: self.info("app: %s %s" % (method, path)) req = wsgi.Request("http", method, path, headers, content) flow = wsgi.Flow(self.address, req) sn = self.connection.getsockname() a = wsgi.WSGIAdaptor(self.server.app, sn[0], self.server.address.port, version.NAMEVERSION) a.serve(flow, self.wfile) return True, None def _log_bytes(self, header, data, hexdump): s = [] if hexdump:
def make_app(noapi): app = Flask(__name__) if not noapi: @app.route('/api/info') def api_info(): return jsonify( version = version.IVERSION ) @app.route('/api/log') def api_log(): return jsonify( log = app.config["pathod"].get_log() ) @app.route('/api/clear_log') def api_clear_log(): app.config["pathod"].clear_log() return "OK" def render(s, cacheable, **kwargs): kwargs["noapi"] = app.config["pathod"].noapi kwargs["nocraft"] = app.config["pathod"].nocraft kwargs["craftanchor"] = app.config["pathod"].craftanchor resp = make_response(render_template(s, **kwargs), 200) if cacheable: resp.headers["Cache-control"] = "public, max-age=4320" return resp @app.route('/') @app.route('/index.html') def index(): return render("index.html", True, section="main") @app.route('/download') @app.route('/download.html') def download(): return render("download.html", True, section="download", version=version.VERSION) @app.route('/about') @app.route('/about.html') def about(): return render("about.html", True, section="about") @app.route('/docs/pathod') def docs_pathod(): return render("docs_pathod.html", True, section="docs") @app.route('/docs/language') def docs_language(): return render("docs_lang.html", True, section="docs", uastrings=http_uastrings.UASTRINGS) @app.route('/docs/pathoc') def docs_pathoc(): return render("docs_pathoc.html", True, section="docs") @app.route('/docs/libpathod') def docs_libpathod(): return render("docs_libpathod.html", True, section="docs") @app.route('/docs/test') def docs_test(): return render("docs_test.html", True, section="docs") @app.route('/log') def log(): if app.config["pathod"].noapi: abort(404) return render("log.html", False, section="log", log=app.config["pathod"].get_log()) @app.route('/log/<int:lid>') def onelog(lid): item = app.config["pathod"].log_by_id(int(lid)) if not item: abort(404) l = pprint.pformat(item) return render("onelog.html", False, section="log", alog=l, lid=lid) 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, ) if not spec.strip(): args["error"] = "Can't parse an empty spec." return render(template, False, **args) try: if is_request: r = language.parse_request(app.config["pathod"].request_settings, spec) else: r = language.parse_response(app.config["pathod"].request_settings, spec) except language.ParseException, v: args["syntaxerror"] = str(v) args["marked"] = v.marked() return render(template, False, **args) s = cStringIO.StringIO() safe = r.preview_safe() c = app.config["pathod"].check_policy(safe, app.config["pathod"].request_settings) if c: args["error"] = c return render(template, False, **args) if is_request: language.serve(safe, s, app.config["pathod"].request_settings, "example.com") else: language.serve(safe, s, app.config["pathod"].request_settings, None) args["output"] = utils.escape_unprintables(s.getvalue()) return render(template, False, **args)
def make_app(noapi): app = Flask(__name__) if not noapi: @app.route('/api/info') def api_info(): return jsonify(version=version.IVERSION) @app.route('/api/log') def api_log(): return jsonify(log=app.config["pathod"].get_log()) @app.route('/api/clear_log') def api_clear_log(): app.config["pathod"].clear_log() return "OK" def render(s, cacheable, **kwargs): kwargs["noapi"] = app.config["pathod"].noapi kwargs["nocraft"] = app.config["pathod"].nocraft kwargs["craftanchor"] = app.config["pathod"].craftanchor resp = make_response(render_template(s, **kwargs), 200) if cacheable: resp.headers["Cache-control"] = "public, max-age=4320" return resp @app.route('/') @app.route('/index.html') def index(): return render("index.html", True, section="main") @app.route('/download') @app.route('/download.html') def download(): return render("download.html", True, section="download", version=version.VERSION) @app.route('/about') @app.route('/about.html') def about(): return render("about.html", True, section="about") @app.route('/docs/pathod') def docs_pathod(): return render("docs_pathod.html", True, section="docs", subsection="pathod") @app.route('/docs/language') def docs_language(): return render("docs_lang.html", True, section="docs", uastrings=http_uastrings.UASTRINGS, subsection="lang") @app.route('/docs/pathoc') def docs_pathoc(): return render("docs_pathoc.html", True, section="docs", subsection="pathoc") @app.route('/docs/libpathod') def docs_libpathod(): return render("docs_libpathod.html", True, section="docs", subsection="libpathod") @app.route('/docs/test') def docs_test(): return render("docs_test.html", True, section="docs", subsection="test") @app.route('/log') def log(): if app.config["pathod"].noapi: abort(404) return render("log.html", False, section="log", log=app.config["pathod"].get_log()) @app.route('/log/<int:lid>') def onelog(lid): item = app.config["pathod"].log_by_id(int(lid)) if not item: abort(404) l = pprint.pformat(item) return render("onelog.html", False, section="log", alog=l, lid=lid) 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, ) if not spec.strip(): args["error"] = "Can't parse an empty spec." return render(template, False, **args) try: if is_request: r = language.parse_request( app.config["pathod"].request_settings, spec) else: r = language.parse_response( app.config["pathod"].request_settings, spec) except language.ParseException, v: args["syntaxerror"] = str(v) args["marked"] = v.marked() return render(template, False, **args) s = cStringIO.StringIO() safe = r.preview_safe() c = app.config["pathod"].check_policy( safe, app.config["pathod"].request_settings) if c: args["error"] = c return render(template, False, **args) if is_request: language.serve(safe, s, app.config["pathod"].request_settings, "example.com") else: language.serve(safe, s, app.config["pathod"].request_settings, None) args["output"] = utils.escape_unprintables(s.getvalue()) return render(template, False, **args)
print >> fp, v.marked() return except language.FileAccessDenied, v: print >> fp, "File access error: %s"%v return if explain: r = r.freeze(self.settings, self.host) resp, req = None, None if showreq: self.wfile.start_log() if showresp: self.rfile.start_log() try: req = language.serve(r, self.wfile, self.settings, self.host) self.wfile.flush() resp = http.read_response(self.rfile, r.method, None) except http.HttpError, v: print >> fp, "<< HTTP Error:", v.msg except tcp.NetLibTimeout: if ignoretimeout: return print >> fp, "<<", "Timeout" except tcp.NetLibDisconnect: # pragma: nocover print >> fp, "<<", "Disconnect" if req: if ignorecodes and resp and resp[1] in ignorecodes: return if explain:
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 = language.parse_response(self.server.request_settings, spec) except language.ParseException, v: self.info("Parse error: %s"%v.msg) crafted = language.PathodErrorResponse( "Parse Error", "Error parsing response spec: %s\n"%v.msg + v.marked() ) return self.serve_crafted(crafted, request_log) elif self.server.noweb: crafted = language.PathodErrorResponse("Access Denied") language.serve(crafted, self.wfile, self.server.request_settings) return False, dict(type = "error", msg="Access denied: web interface disabled") else: self.info("app: %s %s"%(method, path)) cc = wsgi.ClientConn(self.client_address) req = wsgi.Request(cc, "http", method, path, headers, content) sn = self.connection.getsockname() app = wsgi.WSGIAdaptor( self.server.app, sn[0], self.server.port, version.NAMEVERSION ) app.serve(req, self.wfile) return True, None
print >> fp, v.marked() return except language.FileAccessDenied, v: print >> fp, "File access error: %s" % v return if explain: r = r.freeze(self.settings, self.address.host) resp, req = None, None if showreq: self.wfile.start_log() if showresp: self.rfile.start_log() try: req = language.serve(r, self.wfile, self.settings, self.address.host) self.wfile.flush() resp = http.read_response(self.rfile, r.method.string(), None) except http.HttpError, v: print >> fp, "<< HTTP Error:", v.message except tcp.NetLibTimeout: if ignoretimeout: return print >> fp, "<<", "Timeout" except tcp.NetLibDisconnect: # pragma: nocover print >> fp, "<<", "Disconnect" if req: if ignorecodes and resp and resp[1] in ignorecodes: return
else: r = language.parse_response(app.config["pathod"].request_settings, spec) except language.ParseException, v: args["syntaxerror"] = str(v) args["marked"] = v.marked() return render(template, False, **args) s = cStringIO.StringIO() safe = r.preview_safe() c = app.config["pathod"].check_policy(safe, app.config["pathod"].request_settings) if c: args["error"] = c return render(template, False, **args) if is_request: language.serve(safe, s, app.config["pathod"].request_settings, "example.com") else: language.serve(safe, s, app.config["pathod"].request_settings, None) args["output"] = utils.escape_unprintables(s.getvalue()) return render(template, False, **args) @app.route("/response_preview") def response_preview(): return _preview(False) @app.route("/request_preview") def request_preview(): return _preview(True)