/* * linux/lib/string.c * * Copyright (C) 1991, 1992 Linus Torvalds */ #include #include #include #ifndef __HAVE_ARCH_STRNICMP /** * strnicmp - Case insensitive, length-limited string comparison * @s1: One string * @s2: The other string * @len: the maximum number of characters to compare */ int strnicmp(const char *s1, const char *s2, size_t len) { /* Yes, Virginia, it had better be unsigned */ unsigned char c1, c2; c1 = 0; c2 = 0; if (len) { do { c1 = *s1; c2 = *s2; s1++; s2++; if (!c1) break; if (!c2) break; if (c1 == c2) continue; c1 = tolower(c1); c2 = tolower(c2); if (c1 != c2) break; } while (--len); } return (int)c1 - (int)c2; } #endif #ifndef __HAVE_ARCH_STRCPY /** * strcpy - Copy a %NUL terminated string * @dest: Where to copy the string to * @src: Where to copy the string from */ char * strcpy(char * dest,const char *src) { char *tmp = dest; while ((*dest++ = *src++) != '\0') /* nothing */; return tmp; } #endif #ifndef __HAVE_ARCH_STRNCPY /** * strncpy - Copy a length-limited, %NUL-terminated string * @dest: Where to copy the string to * @src: Where to copy the string from * @count: The maximum number of bytes to copy * * Note that unlike userspace strncpy, this does not %NUL-pad the buffer. * However, the result is not %NUL-terminated if the source exceeds * @count bytes. */ char * strncpy(char * dest,const char *src,size_t count) { char *tmp = dest; while (count-- && (*dest++ = *src++) != '\0') /* nothing */; return tmp; } #endif #ifndef __HAVE_ARCH_STRLCPY /** * strlcpy - Copy a %NUL terminated string into a sized buffer * @dest: Where to copy the string to * @src: Where to copy the string from * @size: size of destination buffer * * Compatible with *BSD: the result is always a valid * NUL-terminated string that fits in the buffer (unless, * of course, the buffer size is zero). It does not pad * out the result like strncpy() does. */ size_t strlcpy(char *dest, const char *src, size_t size) { size_t ret = strlen(src); if (size) { size_t len = (ret >= size) ? size-1 : ret; memcpy(dest, src, len); dest[len] = '\0'; } return ret; } EXPORT_SYMBOL(strlcpy); #endif #ifndef __HAVE_ARCH_STRCAT /** * strcat - Append one %NUL-terminated string to another * @dest: The string to be appended to * @src: The string to append to it */ char * strcat(char * dest, const char * src) { char *tmp = dest; while (*dest) dest++; while ((*dest++ = *src++) != '\0') ; return tmp; } #endif #ifndef __HAVE_ARCH_STRNCAT /** * strncat - Append a length-limited, %NUL-terminated string to another * @dest: The string to be appended to * @src: The string to append to it * @count: The maximum numbers of bytes to copy * * Note that in contrast to strncpy, strncat ensures the result is * terminated. */ char * strncat(char *dest, const char *src, size_t count) { char *tmp = dest; if (count) { while (*dest) dest++; while ((*dest++ = *src++)) { if (--count == 0) { *dest = '\0'; break; } } } return tmp; } #endif #ifndef __HAVE_ARCH_STRCMP /** * strcmp - Compare two strings * @cs: One string * @ct: Another string */ int strcmp(const char * cs,const char * ct) { register signed char __res; while (1) { if ((__res = *cs - *ct++) != 0 || !*cs++) break; } return __res; } #endif #ifndef __HAVE_ARCH_STRNCMP /** * strncmp - Compare two length-limited strings * @cs: One string * @ct: Another string * @count: The maximum number of bytes to compare */ int strncmp(const char * cs,const char * ct,size_t count) { register signed char __res = 0; while (count) { if ((__res = *cs - *ct++) != 0 || !*cs++) break; count--; } return __res; } #endif #ifndef __HAVE_ARCH_STRCHR /** * strchr - Find the first occurrence of a character in a string * @s: The string to be searched * @c: The character to search for */ char * strchr(const char * s, int c) { for(; *s != (char) c; ++s) if (*s == '\0') return NULL; return (char *) s; } #endif #ifndef __HAVE_ARCH_STRRCHR /** * strrchr - Find the last occurrence of a character in a string * @s: The string to be searched * @c: The character to search for */ char * strrchr(const char * s, int c) { const char *p = s + strlen(s); do { if (*p == (char)c) return (char *)p; } while (--p >= s); return NULL; } #endif #ifndef __HAVE_ARCH_STRLEN /** * strlen - Find the length of a string * @s: The string to be sized */ size_t strlen(const char * s) { const char *sc; for (sc = s; *sc != '\0'; ++sc) /* nothing */; return sc - s; } #endif #ifndef __HAVE_ARCH_STRNLEN /** * strnlen - Find the length of a length-limited string * @s: The string to be sized * @count: The maximum number of bytes to search */ size_t strnlen(const char * s, size_t count) { const char *sc; for (sc = s; count-- && *sc != '\0'; ++sc) /* nothing */; return sc - s; } #endif #ifndef __HAVE_ARCH_STRSPN /** * strspn - Calculate the length of the initial substring of @s which only * contain letters in @accept * @s: The string to be searched * @accept: The string to search for */ size_t strspn(const char *s, const char *accept) { const char *p; const char *a; size_t count = 0; for (p = s; *p != '\0'; ++p) { for (a = accept; *a != '\0'; ++a) { if (*p == *a) break; } if (*a == '\0') return count; ++count; } return count; } #endif #ifndef __HAVE_ARCH_STRPBRK /** * strpbrk - Find the first occurrence of a set of characters * @cs: The string to be searched * @ct: The characters to search for */ char * strpbrk(const char * cs,const char * ct) { const char *sc1,*sc2; for( sc1 = cs; *sc1 != '\0'; ++sc1) { for( sc2 = ct; *sc2 != '\0'; ++sc2) { if (*sc1 == *sc2) return (char *) sc1; } } return NULL; } #endif #ifndef __HAVE_ARCH_STRSEP /** * strsep - Split a string into tokens * @s: The string to be searched * @ct: The characters to search for * * strsep() updates @s to point after the token, ready for the next call. * * It returns empty tokens, too, behaving exactly like the libc function * of that name. In fact, it was stolen from glibc2 and de-fancy-fied. * Same semantics, slimmer shape. ;) */ char * strsep(char **s, const char *ct) { char *sbegin = *s, *end; if (sbegin == NULL) return NULL; end = strpbrk(sbegin, ct); if (
from mitmproxy import contentviews
from mitmproxy.test import tflow
from mitmproxy.test import tutils
from mitmproxy.test import taddons
from mitmproxy.net.http import Headers

from ..mitmproxy import tservers


class TestScripts(tservers.MasterTest):
    def test_add_header(self, tdata):
        with taddons.context() as tctx:
            a = tctx.script(tdata.path("../examples/simple/add_header.py"))
            f = tflow.tflow(resp=tutils.tresp())
            a.response(f)
            assert f.response.headers["newheader"] == "foo"

    def test_custom_contentviews(self, tdata):
        with taddons.context() as tctx:
            tctx.script(tdata.path("../examples/simple/custom_contentview.py"))
            swapcase = contentviews.get("swapcase")
            _, fmt = swapcase(b"<html>Test!</html>")
            assert any(b'tEST!' in val[0][1] for val in fmt)

    def test_iframe_injector(self, tdata):
        with taddons.context() as tctx:
            sc = tctx.script(tdata.path("../examples/simple/modify_body_inject_iframe.py"))
            tctx.configure(
                sc,
                iframe = "http://example.org/evil_iframe"
            )
            f = tflow.tflow(
                resp=tutils.tresp(content=b"<html><body>mitmproxy</body></html>")
            )
            tctx.master.addons.invoke_addon(sc, "response", f)
            content = f.response.content
            assert b'iframe' in content and b'evil_iframe' in content

    def test_modify_form(self, tdata):
        with taddons.context() as tctx:
            sc = tctx.script(tdata.path("../examples/simple/modify_form.py"))

            form_header = Headers(content_type="application/x-www-form-urlencoded")
            f = tflow.tflow(req=tutils.treq(headers=form_header))
            sc.request(f)

            assert f.request.urlencoded_form["mitmproxy"] == "rocks"

            f.request.headers["content-type"] = ""
            sc.request(f)
            assert list(f.request.urlencoded_form.items()) == [("foo", "bar")]

    def test_modify_querystring(self, tdata):
        with taddons.context() as tctx:
            sc = tctx.script(tdata.path("../examples/simple/modify_querystring.py"))
            f = tflow.tflow(req=tutils.treq(path="/search?q=term"))

            sc.request(f)
            assert f.request.query["mitmproxy"] == "rocks"

            f.request.path = "/"
            sc.request(f)
            assert f.request.query["mitmproxy"] == "rocks"

    def test_redirect_requests(self, tdata):
        with taddons.context() as tctx:
            sc = tctx.script(tdata.path("../examples/simple/redirect_requests.py"))
            f = tflow.tflow(req=tutils.treq(host="example.org"))
            sc.request(f)
            assert f.request.host == "mitmproxy.org"

    def test_send_reply_from_proxy(self, tdata):
        with taddons.context() as tctx:
            sc = tctx.script(tdata.path("../examples/simple/send_reply_from_proxy.py"))
            f = tflow.tflow(req=tutils.treq(host="example.com", port=80))
            sc.request(f)
            assert f.response.content == b"Hello World"

    def test_dns_spoofing(self, tdata):
        with taddons.context() as tctx:
            sc = tctx.script(tdata.path("../examples/complex/dns_spoofing.py"))

            original_host = "example.com"

            host_header = Headers(host=original_host)
            f = tflow.tflow(req=tutils.treq(headers=host_header, port=80))

            tctx.master.addons.invoke_addon(sc, "requestheaders", f)

            # Rewrite by reverse proxy mode
            f.request.scheme = "https"
            f.request.port = 443

            tctx.master.addons.invoke_addon(sc, "request", f)

            assert f.request.scheme == "http"
            assert f.request.port == 80

            assert f.request.headers["Host"] == original_host