def _echo_headers(self, headers): for k, v in headers.fields: k = strutils.bytes_to_escaped_str(k) v = strutils.bytes_to_escaped_str(v) out = "{}: {}".format( click.style(k, fg="blue"), click.style(v) ) self.echo(out, ident=4)
def _echo_message(self, message): if self.flow_detail >= 2 and hasattr(message, "headers"): headers = "\r\n".join( "{}: {}".format( click.style( strutils.bytes_to_escaped_str(k), fg="blue", bold=True ), click.style( strutils.bytes_to_escaped_str(v), fg="blue" ) ) for k, v in message.headers.fields ) self.echo(headers, ident=4) if self.flow_detail >= 3: _, lines, error = contentviews.get_message_content_view( self.default_contentview, message ) if error: ctx.log.debug(error) styles = dict( highlight=dict(bold=True), offset=dict(fg="blue"), header=dict(fg="green", bold=True), text=dict(fg="green") ) def colorful(line): yield u" " # we can already indent here for (style, text) in line: yield click.style(text, **styles.get(style, {})) if self.flow_detail == 3: lines_to_echo = itertools.islice(lines, 70) else: lines_to_echo = lines content = u"\r\n".join( u"".join(colorful(line)) for line in lines_to_echo ) if content: self.echo("") self.echo(content) if next(lines, None): self.echo("(cut off)", ident=4, dim=True) if self.flow_detail >= 2: self.echo("")
def freeze(self, settings): f = self.parsed.freeze(settings).spec() return self.__class__( base.TokValueLiteral( strutils.bytes_to_escaped_str(f.encode(), escape_single_quotes=True) ) )
def _handle_pong_received(self, event, source_conn, other_conn, is_server): self.log( "Pong Received from {}".format("server" if is_server else "client"), "info", [strutils.bytes_to_escaped_str(bytes(event.payload))] ) return True
def __init__(self, data: typing.Any) -> None: self.data = data if isinstance(data, bytes): data = strutils.bytes_to_escaped_str(data) if not isinstance(data, str): data = repr(data) w = urwid.Text(data, wrap="any") super().__init__(w)
def __init__(self, data: strbytes) -> None: self.data = data if isinstance(data, bytes): escaped = strutils.bytes_to_escaped_str(data) else: escaped = data.encode() w = urwid.Text(escaped, wrap="any") super().__init__(w)
def __init__(self, data: strbytes) -> None: if isinstance(data, bytes): escaped = strutils.bytes_to_escaped_str(data) else: escaped = data.encode() self.type = type(data) # type: typing.Type w = urwid.Edit(edit_text=escaped, wrap="any", multiline=True) w = urwid.AttrWrap(w, "editfield") super().__init__(w)
def log(self, settings): """ A dictionary that should be logged if this message is served. """ ret = {} for i in self.logattrs: v = getattr(self, i) # Careful not to log any VALUE specs without sanitizing them first. # We truncate at 1k. if hasattr(v, "values"): v = [x[:LOG_TRUNCATE] for x in v.values(settings)] v = strutils.bytes_to_escaped_str(b"".join(v)) elif hasattr(v, "__len__"): v = v[:LOG_TRUNCATE] v = strutils.bytes_to_escaped_str(v) ret[i] = v ret["spec"] = self.spec() return ret
def tcp_message(self, f): super().tcp_message(f) message = f.messages[-1] direction = "->" if message.from_client else "<-" signals.add_log("{client} {direction} tcp {direction} {server}".format( client=repr(f.client_conn.address), server=repr(f.server_conn.address), direction=direction, ), "info") signals.add_log(strutils.bytes_to_escaped_str(message.content), "debug")
def _handle_ping_received(self, event, source_conn, other_conn, is_server): # PING is automatically answered with a PONG by wsproto self.connections[other_conn].ping() other_conn.send(self.connections[other_conn].bytes_to_send()) source_conn.send(self.connections[source_conn].bytes_to_send()) self.log( "Ping Received from {}".format("server" if is_server else "client"), "info", [strutils.bytes_to_escaped_str(bytes(event.payload))] ) return True
def tcp_message(self, f): message = f.messages[-1] direction = "->" if message.from_client else "<-" ctx.log.info("{client_host}:{client_port} {direction} tcp {direction} {server_host}:{server_port}".format( client_host=f.client_conn.address[0], client_port=f.client_conn.address[1], server_host=f.server_conn.address[0], server_port=f.server_conn.address[1], direction=direction, )) ctx.log.debug(strutils.bytes_to_escaped_str(message.content))
def tcp_message(flow: tcp.TCPFlow): message = flow.messages[-1] old_content = message.content #message.content = old_content.replace(b"foo", b"bar") message.content = old_content.replace(b"@webview_devtools_remote_", b"@.*.*.*._devtools_remote_") ctx.log.info("[tcp_message{}] from {} to {}:\n{}".format( " (modified)" if message.content != old_content else "", "client" if message.from_client else "server", "server" if message.from_client else "client", strutils.bytes_to_escaped_str(message.content)))
def _handle_ping(self, event, source_conn, other_conn, is_server): # Use event.response to create the approprate Pong response data = self.connections[other_conn].send(Ping()) other_conn.send(data) data = self.connections[source_conn].send(event.response()) source_conn.send(data) self.log( "Ping Received from {}".format("server" if is_server else "client"), "info", [strutils.bytes_to_escaped_str(bytes(event.payload))] ) return True
def tcp_message(flow: tcp.TCPFlow): message = flow.messages[-1] old_content = message.content message.content = old_content.replace(b"foo", b"bar") ctx.log.info( "[tcp_message{}] from {} to {}:\n{}".format( " (modified)" if message.content != old_content else "", "client" if message.from_client else "server", "server" if message.from_client else "client", strutils.bytes_to_escaped_str(message.content)) )
def __repr__(self): if self.alpn_proto_negotiated: alpn = "[ALPN: {}] ".format( strutils.bytes_to_escaped_str(self.alpn_proto_negotiated) ) else: alpn = "" return "<ClientConnection: {ssl}{alpn}{address}>".format( ssl="[ssl] " if self.ssl_established else "", alpn=alpn, address=repr(self.address) )
def _echo_message(self, message): if self.flow_detail >= 2 and hasattr(message, "headers"): headers = "\r\n".join("{}: {}".format( click.style( strutils.bytes_to_escaped_str(k), fg="blue", bold=True), click.style(strutils.bytes_to_escaped_str(v), fg="blue")) for k, v in message.headers.fields) self.echo(headers, ident=4) if self.flow_detail >= 3: _, lines, error = contentviews.get_message_content_view( contentviews.get("Auto"), message) if error: ctx.log.debug(error) styles = dict(highlight=dict(bold=True), offset=dict(fg="blue"), header=dict(fg="green", bold=True), text=dict(fg="green")) def colorful(line): yield u" " # we can already indent here for (style, text) in line: yield click.style(text, **styles.get(style, {})) if self.flow_detail == 3: lines_to_echo = itertools.islice(lines, 70) else: lines_to_echo = lines content = u"\r\n".join(u"".join(colorful(line)) for line in lines_to_echo) if content: self.echo("") self.echo(content) if next(lines, None): self.echo("(cut off)", ident=4, dim=True) if self.flow_detail >= 2: self.echo("")
def tcp_message(self, f): message = f.messages[-1] direction = "->" if message.from_client else "<-" ctx.log.info( "{client_host}:{client_port} {direction} tcp {direction} {server_host}:{server_port}" .format( client_host=f.client_conn.address[0], client_port=f.client_conn.address[1], server_host=f.server_conn.address[0], server_port=f.server_conn.address[1], direction=direction, )) ctx.log.debug(strutils.bytes_to_escaped_str(message.content))
def curl_command(f: flow.Flow) -> str: data = "curl " request = cleanup_request(f) for k, v in request.headers.items(multi=True): data += "--compressed " if k == 'accept-encoding' else "" data += "-H '%s:%s' " % (k, v) if request.method != "GET": data += "-X %s " % request.method data += "'%s'" % request.url if request.content: data += " --data-binary '%s'" % strutils.bytes_to_escaped_str( request.content, escape_single_quotes=True) return data
def tcp_message(tcp_msg): modified_msg = tcp_msg.message.replace("foo", "bar") is_modified = False if modified_msg == tcp_msg.message else True tcp_msg.message = modified_msg print("[tcp_message{}] from {} {} to {} {}:\r\n{}".format( " (modified)" if is_modified else "", "client" if tcp_msg.sender == tcp_msg.client_conn else "server", tcp_msg.sender.address, "server" if tcp_msg.receiver == tcp_msg.server_conn else "client", tcp_msg.receiver.address, strutils.bytes_to_escaped_str(tcp_msg.message)))
def httpie_command(f: flow.Flow) -> str: raise_if_missing_request(f) request = f.request.copy() # type: ignore data = "http %s " % request.method request.decode(strict=False) data += "%s" % request.url for k, v in request.headers.items(multi=True): data += " '%s:%s'" % (k, v) if request.content: data += " <<< '%s'" % strutils.bytes_to_escaped_str( request.content, escape_single_quotes=True ) return data
def tcp_message(tcp_msg): modified_msg = tcp_msg.message.replace("foo", "bar") is_modified = False if modified_msg == tcp_msg.message else True tcp_msg.message = modified_msg print( "[tcp_message{}] from {} {} to {} {}:\r\n{}".format( " (modified)" if is_modified else "", "client" if tcp_msg.sender == tcp_msg.client_conn else "server", tcp_msg.sender.address, "server" if tcp_msg.receiver == tcp_msg.server_conn else "client", tcp_msg.receiver.address, strutils.bytes_to_escaped_str(tcp_msg.message)) )
def curl_command(f: flow.Flow) -> str: raise_if_missing_request(f) data = "curl --dump-header " request = f.request.copy() # type: ignore request.decode(strict=False) for k, v in request.headers.items(multi=True): data += "-H '%s:%s' " % (k, v) if request.method != "GET": data += "-X %s " % request.method data += "'%s'" % request.url if request.content: data += " --data-binary '%s'" % strutils.bytes_to_escaped_str( request.content, escape_single_quotes=True) return data
def __repr__(self): if self.ssl_established and self.sni: ssl = "[ssl: {0}] ".format(self.sni) elif self.ssl_established: ssl = "[ssl] " else: ssl = "" if self.alpn_proto_negotiated: alpn = "[ALPN: {}] ".format( strutils.bytes_to_escaped_str(self.alpn_proto_negotiated)) else: alpn = "" return "<ServerConnection: {ssl}{alpn}{address}>".format( ssl=ssl, alpn=alpn, address=repr(self.address))
def curl_command(f: flow.Flow) -> str: if not hasattr(f, "request"): raise exceptions.CommandError("Can't export flow with no request.") data = "curl " request = f.request.copy() # type: ignore request.decode(strict=False) for k, v in request.headers.items(multi=True): data += "-H '%s:%s' " % (k, v) if request.method != "GET": data += "-X %s " % request.method data += "'%s'" % request.url if request.content: data += " --data-binary '%s'" % strutils.bytes_to_escaped_str( request.content, escape_single_quotes=True) return data
def tcp_message(self, f): super().tcp_message(f) message = f.messages[-1] direction = "->" if message.from_client else "<-" signals.add_log( "{client_host}:{client_port} {direction} tcp {direction} {server_host}:{server_port}" .format( client_host=f.client_conn.address[0], client_port=f.client_conn.address[1], server_host=f.server_conn.address[0], server_port=f.server_conn.address[1], direction=direction, ), "info") signals.add_log(strutils.bytes_to_escaped_str(message.content), "debug")
def curl_command(f: flow.Flow) -> str: raise_if_missing_request(f) data = "curl " request = f.request.copy() # type: ignore request.decode(strict=False) for k, v in request.headers.items(multi=True): data += "-H '%s:%s' " % (k, v) if request.method != "GET": data += "-X %s " % request.method data += "'%s'" % request.url if request.content: data += " --data-binary '%s'" % strutils.bytes_to_escaped_str( request.content, escape_single_quotes=True ) return data
def tcp_message(flow: tcp.TCPFlow): message: tcp.TCPMessage = flow.messages[-1] server_conn: ServerConnection = flow.server_conn client_conn: ClientConnection = flow.client_conn flag = "*" * 10 extra_data: dict = { "client_conn.address": client_conn.address, "client_conn": client_conn, "server_conn.address": server_conn.address, "server_conn": server_conn, } if server_conn.address in [("mitmdump", 8080), ("127.0.0.1", "8080")]: server_conn.address = ("127.0.0.1", 80) content = strutils.bytes_to_escaped_str(message.content) extra_data.update(content=content) ctx.log.info(f"{flag} tcp_message: {extra_data} {flag}")
def curl_command(f: flow.Flow) -> str: if not hasattr(f, "request"): raise exceptions.CommandError("Can't export flow with no request.") data = "curl " request = f.request.copy() # type: ignore request.decode(strict=False) for k, v in request.headers.items(multi=True): data += "-H '%s:%s' " % (k, v) if request.method != "GET": data += "-X %s " % request.method data += "'%s'" % request.url if request.content: data += " --data-binary '%s'" % strutils.bytes_to_escaped_str( request.content, escape_single_quotes=True ) return data
def __repr__(self): if self.tls_established: tls = f"[{self.tls_version}] " else: tls = "" if self.alpn_proto_negotiated: alpn = "[ALPN: {}] ".format( strutils.bytes_to_escaped_str(self.alpn_proto_negotiated)) else: alpn = "" return "<ClientConnection: {tls}{alpn}{address}>".format( tls=tls, alpn=alpn, address=human.format_address(self.address), )
def __repr__(self): if self.tls_established and self.sni: tls = "[{}: {}] ".format(self.tls_version or "TLS", self.sni) elif self.tls_established: tls = "[{}] ".format(self.tls_version or "TLS") else: tls = "" if self.alpn_proto_negotiated: alpn = "[ALPN: {}] ".format( strutils.bytes_to_escaped_str(self.alpn_proto_negotiated)) else: alpn = "" return "<ServerConnection: {tls}{alpn}{address}>".format( tls=tls, alpn=alpn, address=human.format_address(self.address), )
def _handle_frame(self, frame, source_conn, other_conn, is_server): sender = "server" if is_server else "client" self.log("WebSockets Frame received from {}".format(sender), "debug", [repr(frame)]) if frame.header.opcode & 0x8 == 0: self.log( "{direction} websocket {direction} {server}".format( server=repr(self.server_conn.address), direction="<-" if is_server else "->", ), "info", strutils.bytes_to_escaped_str(frame.payload, keep_spacing=True).splitlines()) # forward the data frame to the other side other_conn.send(bytes(frame)) elif frame.header.opcode in (websockets.OPCODE.PING, websockets.OPCODE.PONG): # just forward the ping/pong to the other side other_conn.send(bytes(frame)) elif frame.header.opcode == websockets.OPCODE.CLOSE: code = '(status code missing)' msg = None reason = '(message missing)' if len(frame.payload) >= 2: code, = struct.unpack('!H', frame.payload[:2]) msg = websockets.CLOSE_REASON.get_name( code, default='unknown status code') if len(frame.payload) > 2: reason = frame.payload[2:] self.log( "WebSockets connection closed by {}: {} {}, {}".format( sender, code, msg, reason), "info") other_conn.send(bytes(frame)) # close the connection return False else: self.log( "Unknown WebSockets frame received from {}".format(sender), "info", [repr(frame)]) # unknown frame - just forward it other_conn.send(bytes(frame)) # continue the connection return True
def __repr__(self): if self.tls_established: tls = "[{}] ".format(self.tls_version) else: tls = "" if self.alpn_proto_negotiated: alpn = "[ALPN: {}] ".format( strutils.bytes_to_escaped_str(self.alpn_proto_negotiated) ) else: alpn = "" return "<ClientConnection: {tls}{alpn}{address}>".format( tls=tls, alpn=alpn, address=human.format_address(self.address), )
def __repr__(self): if self.tls_established: tls = "[{}] ".format(self.tls_version) else: tls = "" if self.alpn_proto_negotiated: alpn = "[ALPN: {}] ".format( strutils.bytes_to_escaped_str(self.alpn_proto_negotiated)) else: alpn = "" return "<ClientConnection: {tls}{alpn}{host}:{port}>".format( tls=tls, alpn=alpn, host=self.address[0], port=self.address[1], )
def __repr__(self): if self.ssl_established and self.sni: ssl = "[ssl: {0}] ".format(self.sni) elif self.ssl_established: ssl = "[ssl] " else: ssl = "" if self.alpn_proto_negotiated: alpn = "[ALPN: {}] ".format( strutils.bytes_to_escaped_str(self.alpn_proto_negotiated) ) else: alpn = "" return "<ServerConnection: {ssl}{alpn}{address}>".format( ssl=ssl, alpn=alpn, address=repr(self.address) )
def __repr__(self): if self.ssl_established: tls = "[{}] ".format(self.tls_version) else: tls = "" if self.alpn_proto_negotiated: alpn = "[ALPN: {}] ".format( strutils.bytes_to_escaped_str(self.alpn_proto_negotiated) ) else: alpn = "" return "<ClientConnection: {tls}{alpn}{host}:{port}>".format( tls=tls, alpn=alpn, host=self.address[0], port=self.address[1], )
def _handle_frame(self, frame, source_conn, other_conn, is_server): sender = "server" if is_server else "client" self.log( "WebSockets Frame received from {}".format(sender), "debug", [repr(frame)] ) if frame.header.opcode & 0x8 == 0: self.log( "{direction} websocket {direction} {server}".format( server=repr(self.server_conn.address), direction="<-" if is_server else "->", ), "info", strutils.bytes_to_escaped_str(frame.payload, keep_spacing=True).splitlines() ) # forward the data frame to the other side other_conn.send(bytes(frame)) elif frame.header.opcode in (websockets.OPCODE.PING, websockets.OPCODE.PONG): # just forward the ping/pong to the other side other_conn.send(bytes(frame)) elif frame.header.opcode == websockets.OPCODE.CLOSE: code = '(status code missing)' msg = None reason = '(message missing)' if len(frame.payload) >= 2: code, = struct.unpack('!H', frame.payload[:2]) msg = websockets.CLOSE_REASON.get_name(code, default='unknown status code') if len(frame.payload) > 2: reason = frame.payload[2:] self.log("WebSockets connection closed by {}: {} {}, {}".format(sender, code, msg, reason), "info") other_conn.send(bytes(frame)) # close the connection return False else: self.log("Unknown WebSockets frame received from {}".format(sender), "info", [repr(frame)]) # unknown frame - just forward it other_conn.send(bytes(frame)) # continue the connection return True
def curl_command(flow: http.HTTPFlow) -> str: data = "curl " request = flow.request.copy() request.decode(strict=False) for k, v in request.headers.items(multi=True): data += "-H '%s:%s' " % (k, v) if request.method != "GET": data += "-X %s " % request.method data += "'%s'" % request.url if request.content: data += " --data-binary '%s'" % strutils.bytes_to_escaped_str( request.content, escape_single_quotes=True) return data
def __init__(self, data: bytes) -> None: self.data = data escaped = strutils.bytes_to_escaped_str(data) w = urwid.Text(escaped, wrap="any") super().__init__(w)
def __repr__(self): return "binary message: {}".format( strutils.bytes_to_escaped_str(self.content))
def conn_text(self, conn): if conn: hdrs = [] for k, v in conn.headers.fields: # This will always force an ascii representation of headers. For example, if the server sends a # # X-Authors: Made with ❤ in Hamburg # # header, mitmproxy will display the following: # # X-Authors: Made with \xe2\x9d\xa4 in Hamburg. # # The alternative would be to just use the header's UTF-8 representation and maybe # do `str.replace("\t", "\\t")` to exempt tabs from urwid's special characters escaping [1]. # That would in some terminals allow rendering UTF-8 characters, but the mapping # wouldn't be bijective, i.e. a user couldn't distinguish "\\t" and "\t". # Also, from a security perspective, a mitmproxy user couldn't be fooled by homoglyphs. # # 1) https://github.com/mitmproxy/mitmproxy/issues/1833 # https://github.com/urwid/urwid/blob/6608ee2c9932d264abd1171468d833b7a4082e13/urwid/display_common.py#L35-L36, k = strutils.bytes_to_escaped_str(k) + ":" v = strutils.bytes_to_escaped_str(v) hdrs.append((k, v)) txt = common.format_keyvals( hdrs, key_format="header" ) viewmode = self.master.commands.call("console.flowview.mode") msg, body = self.content_view(viewmode, conn) cols = [ urwid.Text( [ ("heading", msg), ] ), urwid.Text( [ " ", ('heading', "["), ('heading_key', "m"), ('heading', (":%s]" % viewmode)), ], align="right" ) ] title = urwid.AttrWrap(urwid.Columns(cols), "heading") txt.append(title) txt.extend(body) else: txt = [ urwid.Text(""), urwid.Text( [ ("highlight", "No response. Press "), ("key", "e"), ("highlight", " and edit any aspect to add one."), ] ) ] return searchable.Searchable(txt)
def test_bytes_to_escaped_str(): assert strutils.bytes_to_escaped_str(b"foo") == "foo" assert strutils.bytes_to_escaped_str(b"\b") == r"\x08" assert strutils.bytes_to_escaped_str(br"&!?=\)") == r"&!?=\\)" assert strutils.bytes_to_escaped_str(b'\xc3\xbc') == r"\xc3\xbc" assert strutils.bytes_to_escaped_str(b"'") == r"'" assert strutils.bytes_to_escaped_str(b'"') == r'"' assert strutils.bytes_to_escaped_str(b"'", escape_single_quotes=True) == r"\'" assert strutils.bytes_to_escaped_str(b'"', escape_single_quotes=True) == r'"' assert strutils.bytes_to_escaped_str(b"\r\n\t") == "\\r\\n\\t" assert strutils.bytes_to_escaped_str(b"\r\n\t", True) == "\r\n\t" assert strutils.bytes_to_escaped_str(b"\n", True) == "\n" assert strutils.bytes_to_escaped_str(b"\\n", True) == "\\ \\ n".replace(" ", "") assert strutils.bytes_to_escaped_str(b"\\\n", True) == "\\ \\ \n".replace(" ", "") assert strutils.bytes_to_escaped_str(b"\\\\n", True) == "\\ \\ \\ \\ n".replace( " ", "") with pytest.raises(ValueError): strutils.bytes_to_escaped_str(u"such unicode")
def websocket_message(self, f): message = f.messages[-1] ctx.log.info(f.message_info(message)) ctx.log.debug(message.content if isinstance(message.content, str) else strutils.bytes_to_escaped_str(message.content))
def _echo_headers(self, headers: http.Headers): for k, v in headers.fields: ks = strutils.bytes_to_escaped_str(k) ks = self.style(ks, fg='blue') vs = strutils.bytes_to_escaped_str(v) self.echo(f"{ks}: {vs}", ident=4)
def freeze(self, settings): f = self.parsed.freeze(settings).spec() return self.__class__(TokValueLiteral(strutils.bytes_to_escaped_str(f.encode(), escape_single_quotes=True)))
def __init__(self, data: bytes) -> None: data = strutils.bytes_to_escaped_str(data) w = urwid.Edit(edit_text=data, wrap="any", multiline=True) w = urwid.AttrWrap(w, "editfield") super().__init__(w)
def freeze(self, settings): g = self.get_generator(settings) return TokValueLiteral(strutils.bytes_to_escaped_str(g[:], escape_single_quotes=True))
def spec(self): return strutils.bytes_to_escaped_str(self.val, escape_single_quotes=True)
def spec(self): inner = strutils.bytes_to_escaped_str(self.val) inner = inner.replace(r"'", r"\x27") return "'" + inner + "'"
def __repr__(self): if self.type == websockets.OPCODE.TEXT: return "text message: {}".format(repr(self.content)) else: return "binary message: {}".format(strutils.bytes_to_escaped_str(self.content))
def __call__(self, data, **metadata): return "Raw", base.format_text(strutils.bytes_to_escaped_str(data, True))
def websocket_message(self, f): super().websocket_message(f) message = f.messages[-1] signals.add_log(message.info, "info") signals.add_log(strutils.bytes_to_escaped_str(message.content), "debug")
def __repr__(self): if self.type == websockets.OPCODE.TEXT: return "text message: {}".format(repr(self.content)) else: return "binary message: {}".format( strutils.bytes_to_escaped_str(self.content))
def _handle_pong(self, event, source_conn, other_conn, is_server): self.log( "Pong Received from {}".format( "server" if is_server else "client"), "info", [strutils.bytes_to_escaped_str(bytes(event.payload))]) return True
def websocket_message(self, f): message = f.messages[-1] ctx.log.info(f.message_info(message)) ctx.log.debug( message.content if isinstance(message.content, str) else strutils.bytes_to_escaped_str(message.content))
def test_bytes_to_escaped_str(): assert strutils.bytes_to_escaped_str(b"foo") == "foo" assert strutils.bytes_to_escaped_str(b"\b") == r"\x08" assert strutils.bytes_to_escaped_str(br"&!?=\)") == r"&!?=\\)" assert strutils.bytes_to_escaped_str(b'\xc3\xbc') == r"\xc3\xbc" assert strutils.bytes_to_escaped_str(b"'") == r"'" assert strutils.bytes_to_escaped_str(b'"') == r'"' assert strutils.bytes_to_escaped_str(b"'", escape_single_quotes=True) == r"\'" assert strutils.bytes_to_escaped_str(b'"', escape_single_quotes=True) == r'"' assert strutils.bytes_to_escaped_str(b"\r\n\t") == "\\r\\n\\t" assert strutils.bytes_to_escaped_str(b"\r\n\t", True) == "\r\n\t" assert strutils.bytes_to_escaped_str(b"\n", True) == "\n" assert strutils.bytes_to_escaped_str(b"\\n", True) == "\\ \\ n".replace(" ", "") assert strutils.bytes_to_escaped_str(b"\\\n", True) == "\\ \\ \n".replace(" ", "") assert strutils.bytes_to_escaped_str(b"\\\\n", True) == "\\ \\ \\ \\ n".replace(" ", "") with tutils.raises(ValueError): strutils.bytes_to_escaped_str(u"such unicode")