Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac44f12d85 | ||
|
|
b6f0c644f8 | ||
|
|
66c4b3c911 | ||
|
|
924696c015 | ||
|
|
81aa00c2ea | ||
|
|
6c1f58e2e7 | ||
|
|
d3c995df34 | ||
|
|
6f4a2daeca | ||
|
|
f728b2c1de | ||
|
|
bc346a3954 | ||
|
|
5442da81b9 | ||
|
|
73b13914fe | ||
|
|
b127f81a9b | ||
|
|
79438a0b59 | ||
|
|
1aa917e0c1 | ||
|
|
84617b32e3 | ||
|
|
501dfb106a |
15
README.md
15
README.md
@@ -120,13 +120,22 @@ It is possible to apply custom rules to modify the response. This can be used to
|
|||||||
See in [ruleset.yaml](ruleset.yaml) for an example.
|
See in [ruleset.yaml](ruleset.yaml) for an example.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- domain: www.example.com
|
- domain: example.com # Inbcludes all subdomains
|
||||||
|
domains: # Additional domains to apply the rule
|
||||||
|
- www.example.de
|
||||||
|
- www.beispiel.de
|
||||||
|
headers:
|
||||||
|
x-forwarded-for: none # override X-Forwarded-For header or delete with none
|
||||||
|
referer: none # override Referer header or delete with none
|
||||||
|
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
|
||||||
|
content-security-policy: script-src 'self'; # override response header
|
||||||
|
cookie: privacy=1
|
||||||
regexRules:
|
regexRules:
|
||||||
- match: <script\s+([^>]*\s+)?src="(/)([^"]*)"
|
- match: <script\s+([^>]*\s+)?src="(/)([^"]*)"
|
||||||
replace: <script $1 script="/https://www.example.com/$3"
|
replace: <script $1 script="/https://www.example.com/$3"
|
||||||
injections:
|
injections:
|
||||||
- position: head # Position where to inject the code
|
- position: head # Position where to inject the code
|
||||||
append: |
|
append: | # possible keys: append, prepend, replace
|
||||||
<script>
|
<script>
|
||||||
window.localStorage.clear();
|
window.localStorage.clear();
|
||||||
console.log("test");
|
console.log("test");
|
||||||
@@ -135,7 +144,7 @@ See in [ruleset.yaml](ruleset.yaml) for an example.
|
|||||||
- domain: www.anotherdomain.com # Domain where the rule applies
|
- domain: www.anotherdomain.com # Domain where the rule applies
|
||||||
paths: # Paths where the rule applies
|
paths: # Paths where the rule applies
|
||||||
- /article
|
- /article
|
||||||
googleCache: false # Search also in Google Cache
|
googleCache: false # Use Google Cache to fetch the content
|
||||||
regexRules: # Regex rules to apply
|
regexRules: # Regex rules to apply
|
||||||
- match: <script\s+([^>]*\s+)?src="(/)([^"]*)"
|
- match: <script\s+([^>]*\s+)?src="(/)([^"]*)"
|
||||||
replace: <script $1 script="/https://www.example.com/$3"
|
replace: <script $1 script="/https://www.example.com/$3"
|
||||||
|
|||||||
@@ -22,9 +22,13 @@ func main() {
|
|||||||
|
|
||||||
parser := argparse.NewParser("ladder", "Every Wall needs a Ladder")
|
parser := argparse.NewParser("ladder", "Every Wall needs a Ladder")
|
||||||
|
|
||||||
|
portEnv := os.Getenv("PORT")
|
||||||
|
if os.Getenv("PORT") == "" {
|
||||||
|
portEnv = "8080"
|
||||||
|
}
|
||||||
port := parser.String("p", "port", &argparse.Options{
|
port := parser.String("p", "port", &argparse.Options{
|
||||||
Required: false,
|
Required: false,
|
||||||
Default: os.Getenv("PORT"),
|
Default: portEnv,
|
||||||
Help: "Port the webserver will listen on"})
|
Help: "Port the webserver will listen on"})
|
||||||
|
|
||||||
prefork := parser.Flag("P", "prefork", &argparse.Options{
|
prefork := parser.Flag("P", "prefork", &argparse.Options{
|
||||||
@@ -43,6 +47,7 @@ func main() {
|
|||||||
app := fiber.New(
|
app := fiber.New(
|
||||||
fiber.Config{
|
fiber.Config{
|
||||||
Prefork: *prefork,
|
Prefork: *prefork,
|
||||||
|
GETOnly: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,17 @@ services:
|
|||||||
ladder:
|
ladder:
|
||||||
image: ghcr.io/kubero-dev/ladder:latest
|
image: ghcr.io/kubero-dev/ladder:latest
|
||||||
container_name: ladder
|
container_name: ladder
|
||||||
build: .
|
#build: .
|
||||||
#restart: always
|
#restart: always
|
||||||
#command: sh -c ./ladder
|
#command: sh -c ./ladder
|
||||||
environment:
|
environment:
|
||||||
- PORT=8080
|
- PORT=8080
|
||||||
- RULESET=/app/ruleset.yaml
|
- RULESET=/app/ruleset.yaml
|
||||||
#- PREFORK=true
|
#- ALLOWED_DOMAINS_RULESET=false
|
||||||
|
#- EXPOSE_RULESET=true
|
||||||
|
#- PREFORK=false
|
||||||
|
#- DISABLE_FORM=fase
|
||||||
|
#- FORM_PATH=/app/form.html
|
||||||
#- X_FORWARDED_FOR=66.249.66.1
|
#- X_FORWARDED_FOR=66.249.66.1
|
||||||
#- USER_AGENT=Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
|
#- USER_AGENT=Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
|
||||||
#- USERPASS=foo:bar
|
#- USERPASS=foo:bar
|
||||||
@@ -19,11 +23,4 @@ services:
|
|||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- ./ruleset.yaml:/app/ruleset.yaml
|
- ./ruleset.yaml:/app/ruleset.yaml
|
||||||
deploy:
|
- ./handlers/form.html:/app/form.html
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: "0.50"
|
|
||||||
memory: 512M
|
|
||||||
reservations:
|
|
||||||
cpus: "0.25"
|
|
||||||
memory: 128M
|
|
||||||
@@ -33,6 +33,8 @@ func ProxySite(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.Set("Content-Type", resp.Header.Get("Content-Type"))
|
c.Set("Content-Type", resp.Header.Get("Content-Type"))
|
||||||
|
c.Set("Content-Security-Policy", resp.Header.Get("Content-Security-Policy"))
|
||||||
|
|
||||||
return c.SendString(body)
|
return c.SendString(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,17 +58,49 @@ func fetchSite(urlpath string, queries map[string]string) (string, *http.Request
|
|||||||
return "", nil, nil, fmt.Errorf("domain not allowed. %s not in %s", u.Host, allowedDomains)
|
return "", nil, nil, fmt.Errorf("domain not allowed. %s not in %s", u.Host, allowedDomains)
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.Getenv("LOG_URLS ") == "true" {
|
if os.Getenv("LOG_URLS") == "true" {
|
||||||
log.Println(u.String() + urlQuery)
|
log.Println(u.String() + urlQuery)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rule := fetchRule(u.Host, u.Path)
|
||||||
|
|
||||||
|
if rule.GoogleCache {
|
||||||
|
u, err = url.Parse("https://webcache.googleusercontent.com/search?q=cache:" + u.String())
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch the site
|
// Fetch the site
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
req, _ := http.NewRequest("GET", u.String()+urlQuery, nil)
|
req, _ := http.NewRequest("GET", u.String()+urlQuery, nil)
|
||||||
req.Header.Set("User-Agent", UserAgent)
|
|
||||||
req.Header.Set("X-Forwarded-For", ForwardedFor)
|
if rule.Headers.UserAgent != "" {
|
||||||
req.Header.Set("Referer", u.String())
|
req.Header.Set("User-Agent", rule.Headers.UserAgent)
|
||||||
req.Header.Set("Host", u.Host)
|
} else {
|
||||||
|
req.Header.Set("User-Agent", UserAgent)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rule.Headers.XForwardedFor != "" {
|
||||||
|
if rule.Headers.XForwardedFor != "none" {
|
||||||
|
req.Header.Set("X-Forwarded-For", rule.Headers.XForwardedFor)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
req.Header.Set("X-Forwarded-For", ForwardedFor)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rule.Headers.Referer != "" {
|
||||||
|
if rule.Headers.Referer != "none" {
|
||||||
|
req.Header.Set("Referer", rule.Headers.Referer)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
req.Header.Set("Referer", u.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if rule.Headers.Cookie != "" {
|
||||||
|
req.Header.Set("Cookie", rule.Headers.Cookie)
|
||||||
|
}
|
||||||
|
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -79,11 +113,16 @@ func fetchSite(urlpath string, queries map[string]string) (string, *http.Request
|
|||||||
return "", nil, nil, err
|
return "", nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
body := rewriteHtml(bodyB, u)
|
if rule.Headers.CSP != "" {
|
||||||
|
resp.Header.Set("Content-Security-Policy", rule.Headers.CSP)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Print("rule", rule)
|
||||||
|
body := rewriteHtml(bodyB, u, rule)
|
||||||
return body, req, resp, nil
|
return body, req, resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func rewriteHtml(bodyB []byte, u *url.URL) string {
|
func rewriteHtml(bodyB []byte, u *url.URL, rule Rule) string {
|
||||||
// Rewrite the HTML
|
// Rewrite the HTML
|
||||||
body := string(bodyB)
|
body := string(bodyB)
|
||||||
|
|
||||||
@@ -104,7 +143,7 @@ func rewriteHtml(bodyB []byte, u *url.URL) string {
|
|||||||
body = strings.ReplaceAll(body, "href=\"https://"+u.Host, "href=\"/https://"+u.Host+"/")
|
body = strings.ReplaceAll(body, "href=\"https://"+u.Host, "href=\"/https://"+u.Host+"/")
|
||||||
|
|
||||||
if os.Getenv("RULESET") != "" {
|
if os.Getenv("RULESET") != "" {
|
||||||
body = applyRules(u.Host, u.Path, body)
|
body = applyRules(body, rule)
|
||||||
}
|
}
|
||||||
return body
|
return body
|
||||||
}
|
}
|
||||||
@@ -155,75 +194,75 @@ func loadRules() RuleSet {
|
|||||||
yaml.Unmarshal(yamlFile, &ruleSet)
|
yaml.Unmarshal(yamlFile, &ruleSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
domains := []string{}
|
||||||
for _, rule := range ruleSet {
|
for _, rule := range ruleSet {
|
||||||
//log.Println("Loaded rules for", rule.Domain)
|
|
||||||
|
domains = append(domains, rule.Domain)
|
||||||
|
domains = append(domains, rule.Domains...)
|
||||||
if os.Getenv("ALLOWED_DOMAINS_RULESET") == "true" {
|
if os.Getenv("ALLOWED_DOMAINS_RULESET") == "true" {
|
||||||
allowedDomains = append(allowedDomains, rule.Domain)
|
allowedDomains = append(allowedDomains, domains...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("Loaded rules for", len(ruleSet), "Domains")
|
log.Println("Loaded ", len(ruleSet), " rules for", len(domains), "Domains")
|
||||||
return ruleSet
|
return ruleSet
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyRules(domain string, path string, body string) string {
|
func fetchRule(domain string, path string) Rule {
|
||||||
|
if len(rulesSet) == 0 {
|
||||||
|
return Rule{}
|
||||||
|
}
|
||||||
|
rule := Rule{}
|
||||||
|
for _, rule := range rulesSet {
|
||||||
|
domains := rule.Domains
|
||||||
|
if rule.Domain != "" {
|
||||||
|
domains = append(domains, rule.Domain)
|
||||||
|
}
|
||||||
|
for _, ruleDomain := range domains {
|
||||||
|
if ruleDomain == domain || strings.HasSuffix(domain, ruleDomain) {
|
||||||
|
if len(rule.Paths) > 0 && !StringInSlice(path, rule.Paths) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// return first match
|
||||||
|
return rule
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rule
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyRules(body string, rule Rule) string {
|
||||||
if len(rulesSet) == 0 {
|
if len(rulesSet) == 0 {
|
||||||
return body
|
return body
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, rule := range rulesSet {
|
for _, regexRule := range rule.RegexRules {
|
||||||
if rule.Domain != domain {
|
re := regexp.MustCompile(regexRule.Match)
|
||||||
continue
|
body = re.ReplaceAllString(body, regexRule.Replace)
|
||||||
|
}
|
||||||
|
for _, injection := range rule.Injections {
|
||||||
|
doc, err := goquery.NewDocumentFromReader(strings.NewReader(body))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if len(rule.Paths) > 0 && !StringInSlice(path, rule.Paths) {
|
if injection.Replace != "" {
|
||||||
continue
|
doc.Find(injection.Position).ReplaceWithHtml(injection.Replace)
|
||||||
}
|
}
|
||||||
for _, regexRule := range rule.RegexRules {
|
if injection.Append != "" {
|
||||||
re := regexp.MustCompile(regexRule.Match)
|
doc.Find(injection.Position).AppendHtml(injection.Append)
|
||||||
body = re.ReplaceAllString(body, regexRule.Replace)
|
|
||||||
}
|
}
|
||||||
for _, injection := range rule.Injections {
|
if injection.Prepend != "" {
|
||||||
doc, err := goquery.NewDocumentFromReader(strings.NewReader(body))
|
doc.Find(injection.Position).PrependHtml(injection.Prepend)
|
||||||
if err != nil {
|
}
|
||||||
log.Fatal(err)
|
body, err = doc.Html()
|
||||||
}
|
if err != nil {
|
||||||
if injection.Replace != "" {
|
log.Fatal(err)
|
||||||
doc.Find(injection.Position).ReplaceWithHtml(injection.Replace)
|
|
||||||
}
|
|
||||||
if injection.Append != "" {
|
|
||||||
doc.Find(injection.Position).AppendHtml(injection.Append)
|
|
||||||
}
|
|
||||||
if injection.Prepend != "" {
|
|
||||||
doc.Find(injection.Position).PrependHtml(injection.Prepend)
|
|
||||||
}
|
|
||||||
body, err = doc.Html()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return body
|
return body
|
||||||
}
|
}
|
||||||
|
|
||||||
type Rule struct {
|
|
||||||
Match string `yaml:"match"`
|
|
||||||
Replace string `yaml:"replace"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RuleSet []struct {
|
|
||||||
Domain string `yaml:"domain"`
|
|
||||||
Paths []string `yaml:"paths,omitempty"`
|
|
||||||
GoogleCache bool `yaml:"googleCache,omitempty"`
|
|
||||||
RegexRules []Rule `yaml:"regexRules"`
|
|
||||||
Injections []struct {
|
|
||||||
Position string `yaml:"position"`
|
|
||||||
Append string `yaml:"append"`
|
|
||||||
Prepend string `yaml:"prepend"`
|
|
||||||
Replace string `yaml:"replace"`
|
|
||||||
} `yaml:"injections"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func StringInSlice(s string, list []string) bool {
|
func StringInSlice(s string, list []string) bool {
|
||||||
for _, x := range list {
|
for _, x := range list {
|
||||||
if strings.HasPrefix(s, x) {
|
if strings.HasPrefix(s, x) {
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ func TestRewriteHtml(t *testing.T) {
|
|||||||
</html>
|
</html>
|
||||||
`
|
`
|
||||||
|
|
||||||
actual := rewriteHtml(bodyB, u)
|
actual := rewriteHtml(bodyB, u, Rule{})
|
||||||
assert.Equal(t, expected, actual)
|
assert.Equal(t, expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
29
handlers/types.go
Normal file
29
handlers/types.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
type Regex struct {
|
||||||
|
Match string `yaml:"match"`
|
||||||
|
Replace string `yaml:"replace"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RuleSet []Rule
|
||||||
|
|
||||||
|
type Rule struct {
|
||||||
|
Domain string `yaml:"domain,omitempty"`
|
||||||
|
Domains []string `yaml:"domains,omitempty"`
|
||||||
|
Paths []string `yaml:"paths,omitempty"`
|
||||||
|
Headers struct {
|
||||||
|
UserAgent string `yaml:"user-agent,omitempty"`
|
||||||
|
XForwardedFor string `yaml:"x-forwarded-for,omitempty"`
|
||||||
|
Referer string `yaml:"referer,omitempty"`
|
||||||
|
Cookie string `yaml:"cookie,omitempty"`
|
||||||
|
CSP string `yaml:"content-security-policy,omitempty"`
|
||||||
|
} `yaml:"headers,omitempty"`
|
||||||
|
GoogleCache bool `yaml:"googleCache,omitempty"`
|
||||||
|
RegexRules []Regex `yaml:"regexRules"`
|
||||||
|
Injections []struct {
|
||||||
|
Position string `yaml:"position"`
|
||||||
|
Append string `yaml:"append"`
|
||||||
|
Prepend string `yaml:"prepend"`
|
||||||
|
Replace string `yaml:"replace"`
|
||||||
|
} `yaml:"injections"`
|
||||||
|
}
|
||||||
126
ruleset.yaml
126
ruleset.yaml
@@ -1,24 +1,32 @@
|
|||||||
- domain: www.example.com
|
- domain: example.com
|
||||||
|
domains:
|
||||||
|
- www.beispiel.de
|
||||||
|
googleCache: true
|
||||||
|
headers:
|
||||||
|
x-forwarded-for: none
|
||||||
|
referer: none
|
||||||
|
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
|
||||||
|
cookie: privacy=1
|
||||||
regexRules:
|
regexRules:
|
||||||
- match: <script\s+([^>]*\s+)?src="(/)([^"]*)"
|
- match: <script\s+([^>]*\s+)?src="(/)([^"]*)"
|
||||||
replace: <script $1 script="/https://www.example.com/$3"
|
replace: <script $1 script="/https://www.example.com/$3"
|
||||||
injections:
|
injections:
|
||||||
- position: head # Position where to inject the code
|
- position: head # Position where to inject the code
|
||||||
append: |
|
append: |
|
||||||
<script>
|
<script>
|
||||||
window.localStorage.clear();
|
window.localStorage.clear();
|
||||||
console.log("test");
|
console.log("test");
|
||||||
alert("Hello!");
|
alert("Hello!");
|
||||||
</script>
|
</script>
|
||||||
- position: h1
|
- position: h1
|
||||||
replace: |
|
replace: |
|
||||||
<h1>An example with a ladder ;-)</h1>
|
<h1>An example with a ladder ;-)</h1>
|
||||||
- domain: www.americanbanker.com
|
- domain: www.americanbanker.com
|
||||||
paths:
|
paths:
|
||||||
- /news
|
- /news
|
||||||
injections:
|
injections:
|
||||||
- position: head
|
- position: head
|
||||||
append: |
|
append: |
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
const inlineGate = document.querySelector('.inline-gate');
|
const inlineGate = document.querySelector('.inline-gate');
|
||||||
@@ -30,7 +38,7 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
- domain: www.nzz.ch
|
- domain: www.nzz.ch
|
||||||
paths:
|
paths:
|
||||||
- /international
|
- /international
|
||||||
- /sport
|
- /sport
|
||||||
- /wirtschaft
|
- /wirtschaft
|
||||||
@@ -46,10 +54,112 @@
|
|||||||
- /finanze
|
- /finanze
|
||||||
injections:
|
injections:
|
||||||
- position: head
|
- position: head
|
||||||
append: |
|
append: |
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
const paywall = document.querySelector('.dynamic-regwall');
|
const paywall = document.querySelector('.dynamic-regwall');
|
||||||
removeDOMElement(paywall)
|
removeDOMElement(paywall)
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
- domains:
|
||||||
|
- www.architecturaldigest.com
|
||||||
|
- www.bonappetit.com
|
||||||
|
- www.cntraveler.com
|
||||||
|
- www.epicurious.com
|
||||||
|
- www.gq.com
|
||||||
|
- www.newyorker.com
|
||||||
|
- www.vanityfair.com
|
||||||
|
- www.vogue.com
|
||||||
|
- www.wired.com
|
||||||
|
injections:
|
||||||
|
- position: head
|
||||||
|
append: |
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const banners = document.querySelectorAll('.paywall-bar, div[class^="MessageBannerWrapper-"');
|
||||||
|
banners.forEach(el => { el.remove(); });
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
- domains:
|
||||||
|
- www.nytimes.com
|
||||||
|
- www.time.com
|
||||||
|
headers:
|
||||||
|
ueser-agent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
|
||||||
|
cookie: nyt-a=; nyt-gdpr=0; nyt-geo=DE; nyt-privacy=1
|
||||||
|
referer: https://www.google.com/
|
||||||
|
injections:
|
||||||
|
- position: head
|
||||||
|
append: |
|
||||||
|
<script>
|
||||||
|
window.localStorage.clear();
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const banners = document.querySelectorAll('div[data-testid="inline-message"], div[id^="ad-"], div[id^="leaderboard-"], div.expanded-dock, div.pz-ad-box, div[id="top-wrapper"], div[id="bottom-wrapper"]');
|
||||||
|
banners.forEach(el => { el.remove(); });
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
- domains:
|
||||||
|
- www.thestar.com
|
||||||
|
- www.niagarafallsreview.ca
|
||||||
|
- www.stcatharinesstandard.ca
|
||||||
|
- www.thepeterboroughexaminer.com
|
||||||
|
- www.therecord.com
|
||||||
|
- www.thespec.com
|
||||||
|
- www.wellandtribune.ca
|
||||||
|
injections:
|
||||||
|
- position: head
|
||||||
|
append: |
|
||||||
|
<script>
|
||||||
|
window.localStorage.clear();
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const paywall = document.querySelectorAll('div.subscriber-offers');
|
||||||
|
paywall.forEach(el => { el.remove(); });
|
||||||
|
const subscriber_only = document.querySelectorAll('div.subscriber-only');
|
||||||
|
for (const elem of subscriber_only) {
|
||||||
|
if (elem.classList.contains('encrypted-content') && dompurify_loaded) {
|
||||||
|
const parser = new DOMParser();
|
||||||
|
const doc = parser.parseFromString('<div>' + DOMPurify.sanitize(unscramble(elem.innerText)) + '</div>', 'text/html');
|
||||||
|
const content_new = doc.querySelector('div');
|
||||||
|
elem.parentNode.replaceChild(content_new, elem);
|
||||||
|
}
|
||||||
|
elem.removeAttribute('style');
|
||||||
|
elem.removeAttribute('class');
|
||||||
|
}
|
||||||
|
const banners = document.querySelectorAll('div.subscription-required, div.redacted-overlay, div.subscriber-hide, div.tnt-ads-container');
|
||||||
|
banners.forEach(el => { el.remove(); });
|
||||||
|
const ads = document.querySelectorAll('div.tnt-ads-container, div[class*="adLabelWrapper"]');
|
||||||
|
ads.forEach(el => { el.remove(); });
|
||||||
|
const recommendations = document.querySelectorAll('div[id^="tncms-region-article"]');
|
||||||
|
recommendations.forEach(el => { el.remove(); });
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
- domain: www.usatoday.com
|
||||||
|
injections:
|
||||||
|
- position: head
|
||||||
|
append: |
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const banners = document.querySelectorAll('div.roadblock-container, .gnt_nb, [aria-label="advertisement"], div[id="main-frame-error"]');
|
||||||
|
banners.forEach(el => { el.remove(); });
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
- domain: www.washingtonpost.com
|
||||||
|
injections:
|
||||||
|
- position: head
|
||||||
|
append: |
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
let paywall = document.querySelectorAll('div[data-qa$="-ad"], div[id="leaderboard-wrapper"], div[data-qa="subscribe-promo"]');
|
||||||
|
paywall.forEach(el => { el.remove(); });
|
||||||
|
const images = document.querySelectorAll('img');
|
||||||
|
images.forEach(image => { image.parentElement.style.filter = ''; });
|
||||||
|
const headimage = document.querySelectorAll('div .aspect-custom');
|
||||||
|
headimage.forEach(image => { image.style.filter = ''; });
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
- domain: medium.com
|
||||||
|
headers:
|
||||||
|
referer: https://t.co/x?amp=1
|
||||||
|
x-forwarded-for: none
|
||||||
|
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
|
||||||
|
content-security-policy: script-src 'self';
|
||||||
|
cookie:
|
||||||
Reference in New Issue
Block a user