def console_choose_cmd( self, prompt: str, choicecmd: mitmproxy.types.Cmd, subcmd: mitmproxy.types.Cmd, *args: mitmproxy.types.Arg ) -> None: """ Prompt the user to choose from a list of strings returned by a command, then invoke another command with all occurrences of {choice} replaced by the choice the user made. """ choices = ctx.master.commands.call_strings(choicecmd, []) def callback(opt): # We're now outside of the call context... repl = shlex.quote(" ".join(args)) repl = repl.replace("{choice}", opt) try: self.master.commands.call(subcmd + " " + repl) except exceptions.CommandError as e: signals.status_message.send(message=str(e)) self.master.overlay( overlay.Chooser(self.master, prompt, choices, "", callback) )
def console_choose_cmd( self, prompt: str, choicecmd: mitmproxy.types.Cmd, subcmd: mitmproxy.types.Cmd, *args: mitmproxy.types.CmdArgs ) -> None: """ Prompt the user to choose from a list of strings returned by a command, then invoke another command with all occurrences of {choice} replaced by the choice the user made. """ choices = ctx.master.commands.execute(choicecmd) def callback(opt): # We're now outside of the call context... repl = [arg.replace("{choice}", opt) for arg in args] try: self.master.commands.call_strings(subcmd, repl) except exceptions.CommandError as e: ctx.log.error(str(e)) self.master.overlay( overlay.Chooser(self.master, prompt, choices, "", callback) )
def list_flows(self) -> None: """ Show server responses list. """ recorded_flows = [] for flows in _find_addon().flowmap.values(): for f in flows: recorded_flows.append(f) if len(recorded_flows) == 0: ctx.log.alert("No flows.") return choices = [] for flow in recorded_flows: c = FlowChoice(flow.request.url) c.flow = flow choices.append(c) def callback(opt): if opt.flow not in ctx.master.view: ctx.log.alert("Not found.") else: ctx.master.view.focus.flow = opt.flow ctx.master.overlay( overlay.Chooser(ctx.master, "Flows", choices, "", callback))
def keypress(self, size, key): if self.walker.editing: if key == "enter": foc, idx = self.get_focus() v = self.walker.get_edit_text() try: d = self.master.options.parse_setval(foc.opt, v) self.master.options.update(**{foc.opt.name: d}) except exceptions.OptionsError as v: signals.status_message.send(message=str(v)) self.walker.stop_editing() return None elif key == "esc": self.walker.stop_editing() return None else: if key == "m_start": self.set_focus(0) self.walker._modified() elif key == "m_end": self.set_focus(len(self.walker.opts) - 1) self.walker._modified() elif key == "m_select": foc, idx = self.get_focus() if foc.opt.typespec == bool: self.master.options.toggler(foc.opt.name)() # Bust the focus widget cache self.set_focus(self.walker.index) elif can_edit_inplace(foc.opt): self.walker.start_editing() self.walker._modified() elif foc.opt.choices: self.master.overlay( overlay.Chooser( self.master, foc.opt.name, foc.opt.choices, foc.opt.current(), self.master.options.setter(foc.opt.name) ) ) elif foc.opt.typespec == Sequence[str]: self.master.overlay( overlay.OptionsOverlay( self.master, foc.opt.name, foc.opt.current(), HELP_HEIGHT + 5 ), valign="top" ) else: raise NotImplementedError() return super().keypress(size, key)
def console_choose(self, prompt: str, choices: typing.Sequence[str], cmd: mitmproxy.types.Cmd, *args: mitmproxy.types.CmdArgs) -> None: """ Prompt the user to choose from a specified list of strings, then invoke another command with all occurrences of {choice} replaced by the choice the user made. """ def callback(opt): # We're now outside of the call context... repl = [arg.replace("{choice}", opt) for arg in args] try: self.master.commands.call_strings(cmd, repl) except exceptions.CommandError as e: ctx.log.error(str(e)) self.master.overlay( overlay.Chooser(self.master, prompt, choices, "", callback))
def console_choose(self, prompt: str, choices: typing.Sequence[str], *cmd: str) -> None: """ Prompt the user to choose from a specified list of strings, then invoke another command with all occurances of {choice} replaced by the choice the user made. """ def callback(opt): # We're now outside of the call context... repl = " ".join(cmd) repl = repl.replace("{choice}", opt) try: self.master.commands.call(repl) except exceptions.CommandError as e: signals.status_message.send(message=str(e)) self.master.overlay( overlay.Chooser(self.master, prompt, choices, "", callback))
def list(self): """ Show added matchers """ if len(self.matchermap) == 0: ctx.log.alert("No matchers") return choices = [] for (key, matcher) in self.matchermap.items(): choices.append("%s | %s | %s" % (key, matcher.code, matcher.path)) def callback(opt): pass ctx.master.overlay( overlay.Chooser(ctx.master, "Matchers", choices, "", callback) )
def flowview_mode_set(self) -> None: """ Set the display mode for the current flow view. """ fv = self.master.window.current("flowview") if not fv: raise exceptions.CommandError("Not viewing a flow.") idx = fv.body.tab_offset def callback(opt): try: self.master.commands.call_args( "view.setval", ["@focus", "flowview_mode_%s" % idx, opt] ) except exceptions.CommandError as e: signals.status_message.send(message=str(e)) opts = [i.name.lower() for i in contentviews.views] self.master.overlay(overlay.Chooser(self.master, "Mode", opts, "", callback))
def keypress(self, size, key): conn = None # type: Optional[Union[http.HTTPRequest, http.HTTPResponse]] if self.tab_offset == TAB_REQ: conn = self.flow.request elif self.tab_offset == TAB_RESP: conn = self.flow.response key = super().keypress(size, key) # Special case: Space moves over to the next flow. # We need to catch that before applying common.shortcuts() if key == " ": self.view_next_flow(self.flow) return key = common.shortcuts(key) if key in ("up", "down", "page up", "page down"): # Pass scroll events to the wrapped widget self._w.keypress(size, key) elif key == "a": self.flow.resume() self.master.view.update(self.flow) elif key == "A": for f in self.view: if f.intercepted: f.resume() self.master.view.update(self.flow) elif key == "d": if self.flow.killable: self.flow.kill() self.view.remove(self.flow) if not self.view.focus.flow: self.master.view_flowlist() else: self.view_flow(self.view.focus.flow) elif key == "D": cp = self.flow.copy() self.master.view.add(cp) self.master.view.focus.flow = cp self.view_flow(cp) signals.status_message.send(message="Duplicated.") elif key == "p": self.view_prev_flow(self.flow) elif key == "r": try: self.master.replay_request(self.flow) except exceptions.ReplayException as e: signals.add_log("Replay error: %s" % e, "warn") signals.flow_change.send(self, flow=self.flow) elif key == "V": if self.flow.modified(): self.flow.revert() signals.flow_change.send(self, flow=self.flow) signals.status_message.send(message="Reverted.") else: signals.status_message.send(message="Flow not modified.") elif key == "W": signals.status_prompt_path.send(prompt="Save this flow", callback=self.master.save_one_flow, args=(self.flow, )) elif key == "|": signals.status_prompt_path.send( prompt="Send flow to script", callback=self.master.run_script_once, args=(self.flow, )) elif key == "e": if self.tab_offset == TAB_REQ: signals.status_prompt_onekey.send(prompt="Edit request", keys=( ("cookies", "c"), ("query", "q"), ("path", "p"), ("url", "u"), ("header", "h"), ("form", "f"), ("raw body", "r"), ("method", "m"), ), callback=self.edit) elif self.tab_offset == TAB_RESP: signals.status_prompt_onekey.send(prompt="Edit response", keys=( ("cookies", "c"), ("code", "o"), ("message", "m"), ("header", "h"), ("raw body", "r"), ), callback=self.edit) else: signals.status_message.send( message="Tab to the request or response", expire=1) elif key in set("bfgmxvzEC") and not conn: signals.status_message.send( message="Tab to the request or response", expire=1) return elif key == "b": if self.tab_offset == TAB_REQ: common.ask_save_body("q", self.flow) else: common.ask_save_body("s", self.flow) elif key == "f": self.view.settings[self.flow][(self.tab_offset, "fullcontents")] = True signals.flow_change.send(self, flow=self.flow) signals.status_message.send(message="Loading all body data...") elif key == "m": opts = [i.name.lower() for i in contentviews.views] self.master.overlay( overlay.Chooser("display mode", opts, self.viewmode_get(), self.change_this_display_mode)) elif key == "E": if self.tab_offset == TAB_REQ: scope = "q" else: scope = "s" signals.status_prompt_onekey.send( self, prompt="Export to file", keys=[(e[0], e[1]) for e in export.EXPORTERS], callback=common.export_to_clip_or_file, args=(scope, self.flow, common.ask_save_path)) elif key == "C": if self.tab_offset == TAB_REQ: scope = "q" else: scope = "s" signals.status_prompt_onekey.send( self, prompt="Export to clipboard", keys=[(e[0], e[1]) for e in export.EXPORTERS], callback=common.export_to_clip_or_file, args=(scope, self.flow, common.copy_to_clipboard_or_prompt)) elif key == "x": conn.content = None signals.flow_change.send(self, flow=self.flow) elif key == "v": if conn.raw_content: t = conn.headers.get("content-type") if "EDITOR" in os.environ or "PAGER" in os.environ: self.master.spawn_external_viewer( conn.get_content(strict=False), t) else: signals.status_message.send( message="Error! Set $EDITOR or $PAGER.") elif key == "z": self.flow.backup() e = conn.headers.get("content-encoding", "identity") if e != "identity": try: conn.decode() except ValueError: signals.status_message.send( message="Could not decode - invalid data?") else: signals.status_prompt_onekey.send( prompt="Select encoding: ", keys=( ("gzip", "z"), ("deflate", "d"), ("brotli", "b"), ), callback=self.encode_callback, args=(conn, )) signals.flow_change.send(self, flow=self.flow) else: # Key is not handled here. return key