forked from icaruslab/decoy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
transform_content.py
90 lines (63 loc) · 2.91 KB
/
transform_content.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import os
import re
import urlparse
################################################################################
# URLs that have absolute addresses
ABSOLUTE_URL_REGEX = r"(http(s?):)?//(?P<url>[^\"'> \t\)]+)"
# URLs that are relative to the base of the current hostname.
BASE_RELATIVE_URL_REGEX = r"/(?!(/)|(http(s?)://)|(url\())(?P<url>[^\"'> \t\)]*)"
# URLs that have '../' or './' to start off their paths.
TRAVERSAL_URL_REGEX = r"(?P<relative>\.(\.)?)/(?!(/)|(http(s?)://)|(url\())(?P<url>[^\"'> \t\)]*)"
# URLs that are in the same directory as the requested URL.
SAME_DIR_URL_REGEX = r"(?!(/)|(http(s?)://)|(url\())(?P<url>[^\"'> \t\)]+)"
# URL matches the root directory.
ROOT_DIR_URL_REGEX = r"(?!//(?!>))/(?P<url>)(?=[ \t\n]*[\"'\)>/])"
# Start of a tag using 'src' or 'href'
TAG_START = r"(?i)\b(?P<tag>src|srcset|href|action|url|background)(?P<equals>[\t ]*=[\t ]*)(?P<quote>[\"']?)"
# Start of a CSS import
CSS_IMPORT_START = r"(?i)@import(?P<spacing>[\t ]+)(?P<quote>[\"']?)"
# CSS url() call
CSS_URL_START = r"(?i)\burl\((?P<quote>[\"']?)"
REPLACEMENT_REGEXES = [
(TAG_START + SAME_DIR_URL_REGEX,
"\g<tag>\g<equals>\g<quote>%(accessed_dir)s\g<url>"),
(TAG_START + TRAVERSAL_URL_REGEX,
"\g<tag>\g<equals>\g<quote>%(accessed_dir)s/\g<relative>/\g<url>"),
(TAG_START + BASE_RELATIVE_URL_REGEX,
"\g<tag>\g<equals>\g<quote>/%(base)s/\g<url>"),
(TAG_START + ROOT_DIR_URL_REGEX,
"\g<tag>\g<equals>\g<quote>/%(base)s/"),
# Need this because HTML tags could end with '/>', which confuses the
# tag-matching regex above, since that's the end-of-match signal.
(TAG_START + ABSOLUTE_URL_REGEX,
"\g<tag>\g<equals>\g<quote>/\g<url>"),
(CSS_IMPORT_START + SAME_DIR_URL_REGEX,
"@import\g<spacing>\g<quote>%(accessed_dir)s\g<url>"),
(CSS_IMPORT_START + TRAVERSAL_URL_REGEX,
"@import\g<spacing>\g<quote>%(accessed_dir)s/\g<relative>/\g<url>"),
(CSS_IMPORT_START + BASE_RELATIVE_URL_REGEX,
"@import\g<spacing>\g<quote>/%(base)s/\g<url>"),
(CSS_IMPORT_START + ABSOLUTE_URL_REGEX,
"@import\g<spacing>\g<quote>/\g<url>"),
(CSS_URL_START + SAME_DIR_URL_REGEX,
"url(\g<quote>%(accessed_dir)s\g<url>"),
(CSS_URL_START + TRAVERSAL_URL_REGEX,
"url(\g<quote>%(accessed_dir)s/\g<relative>/\g<url>"),
(CSS_URL_START + BASE_RELATIVE_URL_REGEX,
"url(\g<quote>/%(base)s/\g<url>"),
(CSS_URL_START + ABSOLUTE_URL_REGEX,
"url(\g<quote>/\g<url>"),
]
################################################################################
def TransformContent(base_url, accessed_url, content):
url_obj = urlparse.urlparse(accessed_url)
accessed_dir = os.path.dirname(url_obj.path)
if not accessed_dir.endswith("/"):
accessed_dir += "/"
for pattern, replacement in REPLACEMENT_REGEXES:
fixed_replacement = replacement % {
"base": base_url,
"accessed_dir": accessed_dir,
}
content = re.sub(pattern, fixed_replacement, content)
return content