Merge branch 'origin/proxy_v2' into proxy_v2/playground
This commit is contained in:
@@ -12,7 +12,7 @@ tmp_dir = "tmp"
|
|||||||
exclude_regex = ["_test.go"]
|
exclude_regex = ["_test.go"]
|
||||||
exclude_unchanged = false
|
exclude_unchanged = false
|
||||||
follow_symlink = false
|
follow_symlink = false
|
||||||
full_bin = "./tmp/main --ruleset ./ruleset_v2.yaml"
|
full_bin = "./tmp/main --ruleset ./rulesets_v2"
|
||||||
include_dir = []
|
include_dir = []
|
||||||
include_ext = ["go", "tpl", "tmpl", "yaml", "html", "js"]
|
include_ext = ["go", "tpl", "tmpl", "yaml", "html", "js"]
|
||||||
include_file = []
|
include_file = []
|
||||||
|
|||||||
2
.github/workflows/build-css.yaml
vendored
2
.github/workflows/build-css.yaml
vendored
@@ -29,7 +29,7 @@ jobs:
|
|||||||
name: Build Tailwind CSS
|
name: Build Tailwind CSS
|
||||||
run: pnpm build
|
run: pnpm build
|
||||||
-
|
-
|
||||||
name: Commit generated stylesheet
|
name: Commit generated stylesheet for handlers/styles.css
|
||||||
run: |
|
run: |
|
||||||
if git diff --quiet handlers/styles.css; then
|
if git diff --quiet handlers/styles.css; then
|
||||||
echo "No changes to commit."
|
echo "No changes to commit."
|
||||||
|
|||||||
@@ -6,10 +6,11 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"ladder/handlers"
|
"github.com/everywall/ladder/handlers"
|
||||||
"ladder/internal/cli"
|
"github.com/everywall/ladder/internal/cli"
|
||||||
"ladder/proxychain/requestmodifiers/bot"
|
|
||||||
ruleset_v2 "ladder/proxychain/ruleset"
|
"github.com/everywall/ladder/proxychain/requestmodifiers/bot"
|
||||||
|
ruleset_v2 "github.com/everywall/ladder/proxychain/ruleset"
|
||||||
|
|
||||||
"github.com/akamensky/argparse"
|
"github.com/akamensky/argparse"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -1,4 +1,4 @@
|
|||||||
module ladder
|
module github.com/everywall/ladder
|
||||||
|
|
||||||
go 1.21.1
|
go 1.21.1
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
rx "github.com/everywall/ladder/proxychain/requestmodifiers"
|
||||||
rx "ladder/proxychain/requestmodifiers"
|
tx "github.com/everywall/ladder/proxychain/responsemodifiers"
|
||||||
tx "ladder/proxychain/responsemodifiers"
|
|
||||||
|
"github.com/everywall/ladder/proxychain"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ package handlers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/everywall/ladder/proxychain/responsemodifiers/api"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"ladder/proxychain/responsemodifiers/api"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewAPIModifersListHandler(opts *ProxyOptions) fiber.Handler {
|
func NewAPIModifersListHandler(opts *ProxyOptions) fiber.Handler {
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ package handlers
|
|||||||
// for use in proxychains.
|
// for use in proxychains.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain/responsemodifiers/api"
|
"github.com/everywall/ladder/proxychain/responsemodifiers/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ModifiersAPIResponse struct {
|
type ModifiersAPIResponse struct {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ package handlers
|
|||||||
// for use in proxychains.
|
// for use in proxychains.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain/responsemodifiers/api"
|
"github.com/everywall/ladder/proxychain/responsemodifiers/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ModifiersAPIResponse struct {
|
type ModifiersAPIResponse struct {
|
||||||
@@ -160,7 +160,7 @@ var AllMods Modifiers = Modifiers{
|
|||||||
Description: "DeleteOutGoingCookiesExcept prevents non-whitelisted cookies from being sent from the client to the upstream proxy server. Cookies whose names are in the whitelist are not removed.",
|
Description: "DeleteOutGoingCookiesExcept prevents non-whitelisted cookies from being sent from the client to the upstream proxy server. Cookies whose names are in the whitelist are not removed.",
|
||||||
CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_outgoing_cookies.go",
|
CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_outgoing_cookies.go",
|
||||||
Params: []Param{
|
Params: []Param{
|
||||||
{Name: "whitelist", Type: "&{Ellipsis:12348 Elt:string}"},
|
{Name: "whitelist", Type: "&{Ellipsis:12476 Elt:string}"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -485,7 +485,7 @@ var AllMods Modifiers = Modifiers{
|
|||||||
Description: "DeleteIncomingCookies prevents ALL cookies from being sent from the proxy server back down to the client.",
|
Description: "DeleteIncomingCookies prevents ALL cookies from being sent from the proxy server back down to the client.",
|
||||||
CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/modify_incoming_cookies.go",
|
CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/modify_incoming_cookies.go",
|
||||||
Params: []Param{
|
Params: []Param{
|
||||||
{Name: "_", Type: "&{Ellipsis:16319 Elt:string}"},
|
{Name: "_", Type: "&{Ellipsis:18780 Elt:string}"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -493,7 +493,7 @@ var AllMods Modifiers = Modifiers{
|
|||||||
Description: "DeleteIncomingCookiesExcept prevents non-whitelisted cookies from being sent from the proxy server to the client. Cookies whose names are in the whitelist are not removed.",
|
Description: "DeleteIncomingCookiesExcept prevents non-whitelisted cookies from being sent from the proxy server to the client. Cookies whose names are in the whitelist are not removed.",
|
||||||
CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/modify_incoming_cookies.go",
|
CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/modify_incoming_cookies.go",
|
||||||
Params: []Param{
|
Params: []Param{
|
||||||
{Name: "whitelist", Type: "&{Ellipsis:16864 Elt:string}"},
|
{Name: "whitelist", Type: "&{Ellipsis:19325 Elt:string}"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -513,6 +513,15 @@ var AllMods Modifiers = Modifiers{
|
|||||||
{Name: "val", Type: "string"},
|
{Name: "val", Type: "string"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "ModifyIncomingScriptsWithRegex",
|
||||||
|
Description: "ModifyIncomingScriptsWithRegex modifies all incoming javascript (application/javascript and inline <script> in text/html) using a regex match and replacement.",
|
||||||
|
CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/modify_incoming_scripts_with_regex.go",
|
||||||
|
Params: []Param{
|
||||||
|
{Name: "matchRegex", Type: "string"},
|
||||||
|
{Name: "replacement", Type: "string"},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "SetResponseHeader",
|
Name: "SetResponseHeader",
|
||||||
Description: "SetResponseHeader modifies response headers from the upstream server",
|
Description: "SetResponseHeader modifies response headers from the upstream server",
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
rx "github.com/everywall/ladder/proxychain/requestmodifiers"
|
||||||
rx "ladder/proxychain/requestmodifiers"
|
tx "github.com/everywall/ladder/proxychain/responsemodifiers"
|
||||||
tx "ladder/proxychain/responsemodifiers"
|
|
||||||
|
"github.com/everywall/ladder/proxychain"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
rx "github.com/everywall/ladder/proxychain/requestmodifiers"
|
||||||
rx "ladder/proxychain/requestmodifiers"
|
tx "github.com/everywall/ladder/proxychain/responsemodifiers"
|
||||||
tx "ladder/proxychain/responsemodifiers"
|
|
||||||
|
"github.com/everywall/ladder/proxychain"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
rx "github.com/everywall/ladder/proxychain/requestmodifiers"
|
||||||
rx "ladder/proxychain/requestmodifiers"
|
tx "github.com/everywall/ladder/proxychain/responsemodifiers"
|
||||||
tx "ladder/proxychain/responsemodifiers"
|
|
||||||
"ladder/proxychain/ruleset"
|
"github.com/everywall/ladder/proxychain"
|
||||||
|
ruleset_v2 "github.com/everywall/ladder/proxychain/ruleset"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
@@ -44,7 +45,7 @@ func NewProxySiteHandler(opts *ProxyOptions) fiber.Handler {
|
|||||||
).
|
).
|
||||||
AddResponseModifications(
|
AddResponseModifications(
|
||||||
tx.ForwardResponseHeaders(),
|
tx.ForwardResponseHeaders(),
|
||||||
//tx.BlockThirdPartyScripts(),
|
tx.BlockThirdPartyScripts(),
|
||||||
tx.DeleteIncomingCookies(),
|
tx.DeleteIncomingCookies(),
|
||||||
tx.DeleteLocalStorageData(),
|
tx.DeleteLocalStorageData(),
|
||||||
tx.DeleteSessionStorageData(),
|
tx.DeleteSessionStorageData(),
|
||||||
@@ -53,7 +54,7 @@ func NewProxySiteHandler(opts *ProxyOptions) fiber.Handler {
|
|||||||
tx.RewriteHTMLResourceURLs(),
|
tx.RewriteHTMLResourceURLs(),
|
||||||
tx.PatchDynamicResourceURLs(),
|
tx.PatchDynamicResourceURLs(),
|
||||||
tx.PatchTrackerScripts(),
|
tx.PatchTrackerScripts(),
|
||||||
tx.BlockElementRemoval(".article-content"), // techcrunch
|
//tx.BlockElementRemoval(".article-content"), // techcrunch
|
||||||
//tx.BlockElementRemoval(".available-content"), // substack
|
//tx.BlockElementRemoval(".available-content"), // substack
|
||||||
// tx.SetContentSecurityPolicy("default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;"),
|
// tx.SetContentSecurityPolicy("default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;"),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"ladder/proxychain/ruleset"
|
ruleset_v2 "github.com/everywall/ladder/proxychain/ruleset"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HandleRulesetMerge merges a set of ruleset files, specified by the rulesetPath or RULESET env variable, into either YAML or Gzip format.
|
// HandleRulesetMerge merges a set of ruleset files, specified by the rulesetPath or RULESET env variable, into either YAML or Gzip format.
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ package ruleset_v2
|
|||||||
// for use in proxychains.
|
// for use in proxychains.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
tx "ladder/proxychain/responsemodifiers"
|
tx "github.com/everywall/ladder/proxychain/responsemodifiers"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ResponseModifierFactory func(params ...string) proxychain.ResponseModification
|
type ResponseModifierFactory func(params ...string) proxychain.ResponseModification
|
||||||
@@ -142,8 +142,8 @@ package ruleset_v2
|
|||||||
// for use in proxychains.
|
// for use in proxychains.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
rx "ladder/proxychain/requestmodifiers"
|
rx "github.com/everywall/ladder/proxychain/requestmodifiers"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RequestModifierFactory func(params ...string) proxychain.RequestModification
|
type RequestModifierFactory func(params ...string) proxychain.RequestModification
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package requestmodifiers
|
package requestmodifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
|
||||||
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddCacheBusterQuery modifies query params to add a random parameter key
|
// AddCacheBusterQuery modifies query params to add a random parameter key
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package requestmodifiers
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
//"fmt"
|
//"fmt"
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
var forwardBlacklist map[string]bool
|
var forwardBlacklist map[string]bool
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package requestmodifiers
|
package requestmodifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain/requestmodifiers/bot"
|
||||||
"ladder/proxychain/requestmodifiers/bot"
|
|
||||||
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MasqueradeAsGoogleBot modifies user agent and x-forwarded for
|
// MasqueradeAsGoogleBot modifies user agent and x-forwarded for
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ModifyDomainWithRegex(matchRegex string, replacement string) proxychain.RequestModification {
|
func ModifyDomainWithRegex(matchRegex string, replacement string) proxychain.RequestModification {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
//http "github.com/Danny-Dasilva/fhttp"
|
//http "github.com/Danny-Dasilva/fhttp"
|
||||||
http "github.com/bogdanfinn/fhttp"
|
http "github.com/bogdanfinn/fhttp"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetOutgoingCookie modifes a specific cookie name
|
// SetOutgoingCookie modifes a specific cookie name
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ModifyPathWithRegex(matchRegex string, replacement string) proxychain.RequestModification {
|
func ModifyPathWithRegex(matchRegex string, replacement string) proxychain.RequestModification {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
//"fmt"
|
//"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ModifyQueryParams replaces query parameter values in URL's query params in a ProxyChain's URL.
|
// ModifyQueryParams replaces query parameter values in URL's query params in a ProxyChain's URL.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package requestmodifiers
|
package requestmodifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetRequestHeader modifies a specific outgoing header
|
// SetRequestHeader modifies a specific outgoing header
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"ladder/proxychain"
|
tx "github.com/everywall/ladder/proxychain/responsemodifiers"
|
||||||
tx "ladder/proxychain/responsemodifiers"
|
|
||||||
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
const archivistUrl string = "https://archive.is/latest"
|
const archivistUrl string = "https://archive.is/latest"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package requestmodifiers
|
|||||||
import (
|
import (
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
const googleCacheUrl string = "https://webcache.googleusercontent.com/search?q=cache:"
|
const googleCacheUrl string = "https://webcache.googleusercontent.com/search?q=cache:"
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"ladder/proxychain"
|
tx "github.com/everywall/ladder/proxychain/responsemodifiers"
|
||||||
tx "ladder/proxychain/responsemodifiers"
|
|
||||||
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
const waybackUrl string = "https://web.archive.org/web/"
|
const waybackUrl string = "https://web.archive.org/web/"
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
//"net/http"
|
//"net/http"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// resolveWithGoogleDoH resolves DNS using Google's DNS-over-HTTPS
|
// resolveWithGoogleDoH resolves DNS using Google's DNS-over-HTTPS
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package requestmodifiers
|
package requestmodifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SpoofOrigin modifies the origin header
|
// SpoofOrigin modifies the origin header
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ package requestmodifiers
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"ladder/proxychain"
|
tx "github.com/everywall/ladder/proxychain/responsemodifiers"
|
||||||
tx "ladder/proxychain/responsemodifiers"
|
|
||||||
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SpoofReferrer modifies the referrer header.
|
// SpoofReferrer modifies the referrer header.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SpoofReferrerFromBaiduSearch modifies the referrer header
|
// SpoofReferrerFromBaiduSearch modifies the referrer header
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package requestmodifiers
|
package requestmodifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SpoofReferrerFromBingSearch modifies the referrer header
|
// SpoofReferrerFromBingSearch modifies the referrer header
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package requestmodifiers
|
package requestmodifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SpoofReferrerFromGoogleSearch modifies the referrer header
|
// SpoofReferrerFromGoogleSearch modifies the referrer header
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package requestmodifiers
|
package requestmodifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SpoofReferrerFromLinkedInPost modifies the referrer header
|
// SpoofReferrerFromLinkedInPost modifies the referrer header
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package requestmodifiers
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SpoofReferrerFromNaverSearch modifies the referrer header
|
// SpoofReferrerFromNaverSearch modifies the referrer header
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package requestmodifiers
|
package requestmodifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SpoofReferrerFromPinterestPost modifies the referrer header
|
// SpoofReferrerFromPinterestPost modifies the referrer header
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package requestmodifiers
|
package requestmodifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SpoofReferrerFromQQPost modifies the referrer header
|
// SpoofReferrerFromQQPost modifies the referrer header
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package requestmodifiers
|
package requestmodifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SpoofReferrerFromRedditPost modifies the referrer header
|
// SpoofReferrerFromRedditPost modifies the referrer header
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package requestmodifiers
|
package requestmodifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SpoofReferrerFromTumblrPost modifies the referrer header
|
// SpoofReferrerFromTumblrPost modifies the referrer header
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package requestmodifiers
|
package requestmodifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SpoofReferrerFromTwitterPost modifies the referrer header
|
// SpoofReferrerFromTwitterPost modifies the referrer header
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package requestmodifiers
|
package requestmodifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SpoofReferrerFromVkontaktePost modifies the referrer header
|
// SpoofReferrerFromVkontaktePost modifies the referrer header
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SpoofReferrerFromWeiboPost modifies the referrer header
|
// SpoofReferrerFromWeiboPost modifies the referrer header
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ import (
|
|||||||
_ "embed"
|
_ "embed"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"ladder/proxychain"
|
tx "github.com/everywall/ladder/proxychain/responsemodifiers"
|
||||||
tx "ladder/proxychain/responsemodifiers"
|
|
||||||
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// https://github.com/faisalman/ua-parser-js/tree/master
|
// https://github.com/faisalman/ua-parser-js/tree/master
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package requestmodifiers
|
package requestmodifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SpoofXForwardedFor modifies the X-Forwarded-For header
|
// SpoofXForwardedFor modifies the X-Forwarded-For header
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ import (
|
|||||||
|
|
||||||
"github.com/markusmobius/go-trafilatura"
|
"github.com/markusmobius/go-trafilatura"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain/responsemodifiers/api"
|
||||||
"ladder/proxychain/responsemodifiers/api"
|
|
||||||
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// APIContent creates an JSON representation of the article and returns it as an API response.
|
// APIContent creates an JSON representation of the article and returns it as an API response.
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"ladder/proxychain/responsemodifiers/api"
|
"github.com/everywall/ladder/proxychain/responsemodifiers/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCreateAPIErrReader(t *testing.T) {
|
func TestCreateAPIErrReader(t *testing.T) {
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ import (
|
|||||||
_ "embed"
|
_ "embed"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain/responsemodifiers/rewriters"
|
||||||
"ladder/proxychain/responsemodifiers/rewriters"
|
|
||||||
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed vendor/block_element_removal.js
|
//go:embed vendor/block_element_removal.js
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain/responsemodifiers/rewriters"
|
||||||
"ladder/proxychain/responsemodifiers/rewriters"
|
|
||||||
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BlockThirdPartyScripts rewrites HTML and injects JS to block all third party JS from loading.
|
// BlockThirdPartyScripts rewrites HTML and injects JS to block all third party JS from loading.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package responsemodifiers
|
package responsemodifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BypassCORS modifies response headers to prevent the browser
|
// BypassCORS modifies response headers to prevent the browser
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package responsemodifiers
|
package responsemodifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: handle edge case where CSP is specified in meta tag:
|
// TODO: handle edge case where CSP is specified in meta tag:
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
_ "embed"
|
_ "embed"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeleteLocalStorageData deletes localstorage cookies.
|
// DeleteLocalStorageData deletes localstorage cookies.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
_ "embed"
|
_ "embed"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeleteSessionStorageData deletes localstorage cookies.
|
// DeleteSessionStorageData deletes localstorage cookies.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
var forwardBlacklist map[string]bool
|
var forwardBlacklist map[string]bool
|
||||||
|
|||||||
@@ -7,16 +7,15 @@ import (
|
|||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
"math"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
|
"github.com/markusmobius/go-trafilatura"
|
||||||
"golang.org/x/net/html"
|
"golang.org/x/net/html"
|
||||||
"golang.org/x/net/html/atom"
|
"golang.org/x/net/html/atom"
|
||||||
|
|
||||||
//"github.com/go-shiori/dom"
|
|
||||||
"github.com/markusmobius/go-trafilatura"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed vendor/generate_readable_outline.html
|
//go:embed vendor/generate_readable_outline.html
|
||||||
@@ -63,19 +62,24 @@ func GenerateReadableOutline() proxychain.ResponseModification {
|
|||||||
html.Render(&b, extract.ContentNode)
|
html.Render(&b, extract.ContentNode)
|
||||||
distilledHTML := b.String()
|
distilledHTML := b.String()
|
||||||
|
|
||||||
|
siteName := strings.Split(extract.Metadata.Sitename, ";")[0]
|
||||||
|
title := strings.Split(extract.Metadata.Title, "|")[0]
|
||||||
|
fmtDate := createWikipediaDateLink(extract.Metadata.Date)
|
||||||
|
readingTime := formatDuration(estimateReadingTime(extract.ContentText))
|
||||||
|
|
||||||
// populate template parameters
|
// populate template parameters
|
||||||
data := map[string]interface{}{
|
data := map[string]interface{}{
|
||||||
"Success": true,
|
"Success": true,
|
||||||
"Image": extract.Metadata.Image,
|
"Image": extract.Metadata.Image,
|
||||||
"Description": extract.Metadata.Description,
|
"Description": extract.Metadata.Description,
|
||||||
"Sitename": extract.Metadata.Sitename,
|
"Sitename": siteName,
|
||||||
"Hostname": extract.Metadata.Hostname,
|
"Hostname": extract.Metadata.Hostname,
|
||||||
"Url": "/" + chain.Request.URL.String(),
|
"Url": "/" + chain.Request.URL.String(),
|
||||||
"Title": extract.Metadata.Title, // todo: modify CreateReadableDocument so we don't have <h1> titles duplicated?
|
"Title": title,
|
||||||
"Date": extract.Metadata.Date.String(),
|
"Date": fmtDate,
|
||||||
"Author": createWikipediaSearchLinks(extract.Metadata.Author),
|
"Author": createDDGFeelingLuckyLinks(extract.Metadata.Author, extract.Metadata.Hostname),
|
||||||
//"Author": extract.Metadata.Author,
|
"Body": distilledHTML,
|
||||||
"Body": distilledHTML,
|
"ReadingTime": readingTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -157,9 +161,20 @@ func rewriteHrefLinks(n *html.Node, baseURL string, apiPath string) {
|
|||||||
recurse(n)
|
recurse(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// createWikipediaSearchLinks takes in comma or semicolon separated terms,
|
// createWikipediaDateLink takes in a date
|
||||||
// then turns them into <a> links searching for the term.
|
// and returns an <a> link pointing to the current events page for that day
|
||||||
func createWikipediaSearchLinks(searchTerms string) string {
|
func createWikipediaDateLink(t time.Time) string {
|
||||||
|
url := fmt.Sprintf("https://en.wikipedia.org/wiki/Portal:Current_events#%s", t.Format("2006_January_02"))
|
||||||
|
date := t.Format("January 02, 2006")
|
||||||
|
return fmt.Sprintf("<a rel=\"noreferrer\" href=\"%s\">%s</a>", url, date)
|
||||||
|
}
|
||||||
|
|
||||||
|
// createDDGFeelingLuckyLinks takes in comma or semicolon separated terms,
|
||||||
|
// then turns them into <a> links searching for the term using DuckDuckGo's I'm
|
||||||
|
// feeling lucky feature. It will redirect the user immediately to the first search result.
|
||||||
|
func createDDGFeelingLuckyLinks(searchTerms string, siteHostname string) string {
|
||||||
|
|
||||||
|
siteHostname = strings.TrimSpace(siteHostname)
|
||||||
semiColonSplit := strings.Split(searchTerms, ";")
|
semiColonSplit := strings.Split(searchTerms, ";")
|
||||||
|
|
||||||
var links []string
|
var links []string
|
||||||
@@ -171,11 +186,13 @@ func createWikipediaSearchLinks(searchTerms string) string {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
encodedTerm := url.QueryEscape(trimmedTerm)
|
ddgQuery := fmt.Sprintf(` site:%s intitle:"%s"`, strings.TrimPrefix(siteHostname, "www."), trimmedTerm)
|
||||||
|
|
||||||
wikiURL := fmt.Sprintf("https://en.wikipedia.org/w/index.php?search=%s", encodedTerm)
|
encodedTerm := `\%s:` + url.QueryEscape(ddgQuery)
|
||||||
|
//ddgURL := `https://html.duckduckgo.com/html/?q=` + encodedTerm
|
||||||
|
ddgURL := `https://www.duckduckgo.com/?q=` + encodedTerm
|
||||||
|
|
||||||
link := fmt.Sprintf("<a href=\"%s\">%s</a>", wikiURL, trimmedTerm)
|
link := fmt.Sprintf("<a rel=\"noreferrer\" href=\"%s\">%s</a>", ddgURL, trimmedTerm)
|
||||||
links = append(links, link)
|
links = append(links, link)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,3 +204,66 @@ func createWikipediaSearchLinks(searchTerms string) string {
|
|||||||
|
|
||||||
return strings.Join(links, " ")
|
return strings.Join(links, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// estimateReadingTime estimates how long the given text will take to read using the given configuration.
|
||||||
|
func estimateReadingTime(text string) time.Duration {
|
||||||
|
if len(text) == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init options with default values.
|
||||||
|
WordsPerMinute := 200
|
||||||
|
WordBound := func(b byte) bool {
|
||||||
|
return b == ' ' || b == '\n' || b == '\r' || b == '\t'
|
||||||
|
}
|
||||||
|
|
||||||
|
words := 0
|
||||||
|
start := 0
|
||||||
|
end := len(text) - 1
|
||||||
|
|
||||||
|
// Fetch bounds.
|
||||||
|
for WordBound(text[start]) {
|
||||||
|
start++
|
||||||
|
}
|
||||||
|
for WordBound(text[end]) {
|
||||||
|
end--
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the number of words.
|
||||||
|
for i := start; i <= end; {
|
||||||
|
for i <= end && !WordBound(text[i]) {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
words++
|
||||||
|
|
||||||
|
for i <= end && WordBound(text[i]) {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reading time stats.
|
||||||
|
minutes := math.Ceil(float64(words) / float64(WordsPerMinute))
|
||||||
|
duration := time.Duration(math.Ceil(minutes) * float64(time.Minute))
|
||||||
|
|
||||||
|
return duration
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatDuration(d time.Duration) string {
|
||||||
|
// Check if the duration is less than one minute
|
||||||
|
if d < time.Minute {
|
||||||
|
seconds := int(d.Seconds())
|
||||||
|
return fmt.Sprintf("%d seconds", seconds)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the duration to minutes
|
||||||
|
minutes := int(d.Minutes())
|
||||||
|
|
||||||
|
// Format the string for one or more minutes
|
||||||
|
if minutes == 1 {
|
||||||
|
return "1 minute"
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%d minutes", minutes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ import (
|
|||||||
_ "embed"
|
_ "embed"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain/responsemodifiers/rewriters"
|
||||||
"ladder/proxychain/responsemodifiers/rewriters"
|
|
||||||
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// injectScript modifies HTTP responses
|
// injectScript modifies HTTP responses
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
//"net/http"
|
//"net/http"
|
||||||
//http "github.com/Danny-Dasilva/fhttp"
|
//http "github.com/Danny-Dasilva/fhttp"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeleteIncomingCookies prevents ALL cookies from being sent from the proxy server
|
// DeleteIncomingCookies prevents ALL cookies from being sent from the proxy server
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package responsemodifiers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/everywall/ladder/proxychain"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ModifyIncomingScriptsWithRegex modifies all incoming javascript (application/javascript and inline <script> in text/html) using a regex match and replacement.
|
||||||
|
func ModifyIncomingScriptsWithRegex(matchRegex string, replacement string) proxychain.ResponseModification {
|
||||||
|
return func(chain *proxychain.ProxyChain) error {
|
||||||
|
path := chain.Request.URL.Path
|
||||||
|
ct := chain.Response.Header.Get("content-type")
|
||||||
|
isJavascript := strings.HasSuffix(path, ".js") || ct == "text/javascript" || ct == "application/javascript"
|
||||||
|
isHTML := strings.HasSuffix(chain.Request.URL.Path, ".html") || ct == "text/html"
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case isJavascript:
|
||||||
|
rBody, err := modifyResponse(chain.Response.Body, matchRegex, replacement)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
chain.Response.Body = rBody
|
||||||
|
case isHTML:
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func modifyResponse(body io.ReadCloser, matchRegex, replacement string) (io.ReadCloser, error) {
|
||||||
|
content, err := io.ReadAll(body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
re, err := regexp.Compile(matchRegex)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = body.Close()
|
||||||
|
if err != nil {
|
||||||
|
return body, err
|
||||||
|
}
|
||||||
|
|
||||||
|
modifiedContent := re.ReplaceAll(content, []byte(replacement))
|
||||||
|
|
||||||
|
return io.NopCloser(bytes.NewReader(modifiedContent)), nil
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package responsemodifiers
|
package responsemodifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetResponseHeader modifies response headers from the upstream server
|
// SetResponseHeader modifies response headers from the upstream server
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain/responsemodifiers/rewriters"
|
||||||
"ladder/proxychain/responsemodifiers/rewriters"
|
|
||||||
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed vendor/patch_dynamic_resource_urls.js
|
//go:embed vendor/patch_dynamic_resource_urls.js
|
||||||
@@ -51,6 +52,19 @@ func PatchDynamicResourceURLs() proxychain.ResponseModification {
|
|||||||
htmlRewriter := rewriters.NewHTMLRewriter(chain.Response.Body, rr)
|
htmlRewriter := rewriters.NewHTMLRewriter(chain.Response.Body, rr)
|
||||||
chain.Response.Body = htmlRewriter
|
chain.Response.Body = htmlRewriter
|
||||||
|
|
||||||
|
// window.location
|
||||||
|
/*
|
||||||
|
spoofedLocationAPI := fmt.Sprintf(`{href:"%s", origin:"%s", pathname:"%s", protocol:"%s:", port:"%s"}`,
|
||||||
|
reqURL.String(), reqURL.Host,
|
||||||
|
reqURL.Path, reqURL.Scheme, reqURL.Port())
|
||||||
|
spoofedLocationAPI := fmt.Sprintf(`{origin: "%s"}`, reqURL.Host)
|
||||||
|
fmt.Println(spoofedLocationAPI)
|
||||||
|
|
||||||
|
chain.AddOnceResponseModifications(
|
||||||
|
ModifyIncomingScriptsWithRegex(`window\.location`, spoofedLocationAPI),
|
||||||
|
)
|
||||||
|
*/
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed vendor/ddg-tracker-surrogates/mapping.json
|
//go:embed vendor/ddg-tracker-surrogates/mapping.json
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain/responsemodifiers/rewriters"
|
||||||
"ladder/proxychain/responsemodifiers/rewriters"
|
|
||||||
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RewriteHTMLResourceURLs modifies HTTP responses
|
// RewriteHTMLResourceURLs modifies HTTP responses
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
viewBox="0 0 512 512"
|
viewBox="0 0 512 512"
|
||||||
class="h-8 focus:outline-none focus:ring focus:border-[#7AA7D1] ring-offset-2"
|
class="noprint h-8 focus:outline-none focus:ring focus:border-[#7AA7D1] ring-offset-2"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
fill="#7AA7D1"
|
fill="#7AA7D1"
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-center z-10">
|
<div class="noprint flex justify-center z-10">
|
||||||
<div class="relative" id="dropdown">
|
<div class="relative" id="dropdown">
|
||||||
<button
|
<button
|
||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
@@ -95,6 +95,15 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
aria-expanded="closed"
|
||||||
|
onclick="document.getElementById('readingtime').innerText = 'Date Accessed: '+(new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })); [...document.querySelectorAll('.noprint')].forEach(e => e.remove()); window.print()"
|
||||||
|
type="button"
|
||||||
|
class="inline-flex items-center justify-center whitespace-nowrap rounded-full h-12 px-4 py-2 text-sm font-medium text-slate-600 dark:text-slate-400 ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-white dark:bg-slate-900 hover:bg-slate-200 dark:hover:bg-slate-700 hover:text-slate-500 dark:hover:text-slate-200"
|
||||||
|
>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" height="16" width="16" viewBox="0 0 512 512"><path d="M128 0C92.7 0 64 28.7 64 64v96h64V64H354.7L384 93.3V160h64V93.3c0-17-6.7-33.3-18.7-45.3L400 18.7C388 6.7 371.7 0 354.7 0H128zM384 352v32 64H128V384 368 352H384zm64 32h32c17.7 0 32-14.3 32-32V256c0-35.3-28.7-64-64-64H64c-35.3 0-64 28.7-64 64v96c0 17.7 14.3 32 32 32H64v64c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V384zM432 248a24 24 0 1 1 0 48 24 24 0 1 1 0-48z"/></svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
id="dropdown_panel"
|
id="dropdown_panel"
|
||||||
class="hidden absolute right-0 mt-2 w-52 rounded-md bg-white dark:bg-slate-900 shadow-md border border-slate-400 dark:border-slate-700"
|
class="hidden absolute right-0 mt-2 w-52 rounded-md bg-white dark:bg-slate-900 shadow-md border border-slate-400 dark:border-slate-700"
|
||||||
@@ -329,6 +338,7 @@
|
|||||||
{{.Error}}
|
{{.Error}}
|
||||||
</code>
|
</code>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
||||||
<div class="flex flex-col gap-1 mt-3">
|
<div class="flex flex-col gap-1 mt-3">
|
||||||
<h1>
|
<h1>
|
||||||
<a href="{{.Url}}" class="text-slate-900 dark:text-slate-200 no-underline hover:underline"> {{.Title}} </a>
|
<a href="{{.Url}}" class="text-slate-900 dark:text-slate-200 no-underline hover:underline"> {{.Title}} </a>
|
||||||
@@ -347,6 +357,27 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
<a href="{{.Url}}" class="text-slate-900 dark:text-slate-200"> {{.Title}} </a>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div class="flex justify-between items-center gap-1 mt-3">
|
||||||
|
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{{if ne .Author ""}}
|
||||||
|
<small class="text-sm font-medium leading-none text-slate-600 dark:text-slate-400">{{.Author}} | </small>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{if ne .Date ""}}
|
||||||
|
<small class="text-sm font-medium leading-none text-slate-600 dark:text-slate-400">{{.Date}}</small>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<small id="readingtime" class="text-sm font-medium leading-none text-slate-600 dark:text-slate-400">Reading Time: {{.ReadingTime}}</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="flex flex-col space-y-3">
|
<div class="flex flex-col space-y-3">
|
||||||
<div>
|
<div>
|
||||||
<div class="grid grid-cols-1 justify-items-center">
|
<div class="grid grid-cols-1 justify-items-center">
|
||||||
@@ -360,21 +391,22 @@
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
<div class="my-2"></div>
|
<div class="my-2"></div>
|
||||||
<footer class="mx-4 text-center text-slate-600 dark:text-slate-400">
|
<footer class="noprint mx-4 my-2 pt-2 border-t border-gray-300 dark:border-gray-700 text-center text-slate-600 dark:text-slate-400">
|
||||||
<p>
|
|
||||||
Code Licensed Under GPL v3.0 |
|
<small>
|
||||||
<a
|
|
||||||
href="https://github.com/everywall/ladder"
|
|
||||||
class="hover:text-blue-500 dark:hover:text-blue-500 hover:underline underline-offset-2 transition-colors duration-300"
|
|
||||||
>View Source</a
|
|
||||||
>
|
|
||||||
|
|
|
||||||
<a
|
<a
|
||||||
href="https://github.com/everywall"
|
href="https://github.com/everywall"
|
||||||
class="hover:text-blue-500 dark:hover:text-blue-500 hover:underline underline-offset-2 transition-colors duration-300"
|
class="hover:text-blue-500 dark:hover:text-blue-500 hover:underline underline-offset-2 transition-colors duration-300"
|
||||||
>Everywall</a
|
>Everywall</a
|
||||||
>
|
>
|
||||||
</p>
|
|
|
||||||
|
<a
|
||||||
|
href="https://github.com/everywall/ladder"
|
||||||
|
class="hover:text-blue-500 dark:hover:text-blue-500 hover:underline underline-offset-2 transition-colors duration-300"
|
||||||
|
>Source</a
|
||||||
|
>
|
||||||
|
| Code Licensed Under GPL v3.0
|
||||||
|
</small>
|
||||||
</footer>
|
</footer>
|
||||||
<div class="my-2"></div>
|
<div class="my-2"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
//"gopkg.in/yaml.v3"
|
//"gopkg.in/yaml.v3"
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Rule struct {
|
type Rule struct {
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ package ruleset_v2
|
|||||||
// for use in proxychains.
|
// for use in proxychains.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
rx "ladder/proxychain/requestmodifiers"
|
rx "github.com/everywall/ladder/proxychain/requestmodifiers"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RequestModifierFactory func(params ...string) proxychain.RequestModification
|
type RequestModifierFactory func(params ...string) proxychain.RequestModification
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ package ruleset_v2
|
|||||||
// for use in proxychains.
|
// for use in proxychains.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ladder/proxychain"
|
"github.com/everywall/ladder/proxychain"
|
||||||
tx "ladder/proxychain/responsemodifiers"
|
tx "github.com/everywall/ladder/proxychain/responsemodifiers"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ResponseModifierFactory func(params ...string) proxychain.ResponseModification
|
type ResponseModifierFactory func(params ...string) proxychain.ResponseModification
|
||||||
@@ -84,6 +84,10 @@ func init() {
|
|||||||
return tx.SetIncomingCookie(params[0], params[1])
|
return tx.SetIncomingCookie(params[0], params[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rsmModMap["ModifyIncomingScriptsWithRegex"] = func(params ...string) proxychain.ResponseModification {
|
||||||
|
return tx.ModifyIncomingScriptsWithRegex(params[0], params[1])
|
||||||
|
}
|
||||||
|
|
||||||
rsmModMap["SetResponseHeader"] = func(params ...string) proxychain.ResponseModification {
|
rsmModMap["SetResponseHeader"] = func(params ...string) proxychain.ResponseModification {
|
||||||
return tx.SetResponseHeader(params[0], params[1])
|
return tx.SetResponseHeader(params[0], params[1])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,14 +33,21 @@ func (rs *Ruleset) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|||||||
type AuxRuleset struct {
|
type AuxRuleset struct {
|
||||||
Rules []Rule `yaml:"rules"`
|
Rules []Rule `yaml:"rules"`
|
||||||
}
|
}
|
||||||
yr := &AuxRuleset{}
|
yamlRuleset := &AuxRuleset{}
|
||||||
|
|
||||||
if err := unmarshal(&yr); err != nil {
|
// First, try to unmarshal as AuxRuleset
|
||||||
return err
|
err := unmarshal(yamlRuleset)
|
||||||
|
if err != nil {
|
||||||
|
// If that fails, try to unmarshal directly into a slice of Rules
|
||||||
|
var directRules []Rule
|
||||||
|
if err := unmarshal(&directRules); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
yamlRuleset.Rules = directRules
|
||||||
}
|
}
|
||||||
|
|
||||||
rs._rulemap = make(map[string]*Rule)
|
rs._rulemap = make(map[string]*Rule)
|
||||||
rs.Rules = yr.Rules
|
rs.Rules = yamlRuleset.Rules
|
||||||
|
|
||||||
// create a map of pointers to rules loaded above based on domain string keys
|
// create a map of pointers to rules loaded above based on domain string keys
|
||||||
// this way we don't have two copies of the rule in ruleset
|
// this way we don't have two copies of the rule in ruleset
|
||||||
@@ -214,6 +221,7 @@ func (rs *Ruleset) loadRulesFromLocalDir(path string) error {
|
|||||||
if !isYAML {
|
if !isYAML {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
fmt.Printf("loadRulesFromLocalDir :: loading rule: %s\n", path)
|
||||||
|
|
||||||
tmpRs := Ruleset{_rulemap: make(map[string]*Rule)}
|
tmpRs := Ruleset{_rulemap: make(map[string]*Rule)}
|
||||||
err = tmpRs.loadRulesFromLocalFile(path)
|
err = tmpRs.loadRulesFromLocalFile(path)
|
||||||
@@ -258,6 +266,7 @@ func (rs *Ruleset) loadRulesFromLocalFile(path string) error {
|
|||||||
e := fmt.Errorf("failed to read rules from local file: '%s'", path)
|
e := fmt.Errorf("failed to read rules from local file: '%s'", path)
|
||||||
return errors.Join(e, err)
|
return errors.Join(e, err)
|
||||||
}
|
}
|
||||||
|
fmt.Printf("loadRulesFromLocalFile :: %s\n", path)
|
||||||
|
|
||||||
isJSON := strings.HasSuffix(path, ".json")
|
isJSON := strings.HasSuffix(path, ".json")
|
||||||
if isJSON {
|
if isJSON {
|
||||||
|
|||||||
@@ -15,3 +15,22 @@ rules:
|
|||||||
requestmodifications:
|
requestmodifications:
|
||||||
- name: ForwardRequestHeaders
|
- name: ForwardRequestHeaders
|
||||||
params: []
|
params: []
|
||||||
|
|
||||||
|
- domains:
|
||||||
|
- quantamagzine.org
|
||||||
|
responsemodifications:
|
||||||
|
- name: BlockElementRemoval
|
||||||
|
params:
|
||||||
|
- "#postContent"
|
||||||
|
|
||||||
|
- domains:
|
||||||
|
- techcrunch.com
|
||||||
|
responsemodifications:
|
||||||
|
- name: ModifyIncomingScriptsWithRegex
|
||||||
|
params:
|
||||||
|
- "window\\.location"
|
||||||
|
- |
|
||||||
|
{origin: "techcrunch.com"}
|
||||||
|
- name: BlockElementRemoval
|
||||||
|
params:
|
||||||
|
- ".article-content"
|
||||||
|
|||||||
23
rulesets_v2/BE_Belgium/demorgen-be.yaml
Normal file
23
rulesets_v2/BE_Belgium/demorgen-be.yaml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
- domains:
|
||||||
|
- demorgen.be
|
||||||
|
|
||||||
|
requestmodifiers:
|
||||||
|
- name: MasqueradeAsGoogleBot
|
||||||
|
|
||||||
|
- name: SpoofReferrer
|
||||||
|
params: ["https://news.google.com"]
|
||||||
|
|
||||||
|
- name: SetOutgoingCookie
|
||||||
|
params: ["isBot", "true"]
|
||||||
|
|
||||||
|
- name: SetOutgoingCookie
|
||||||
|
params: ["authId", "1"]
|
||||||
|
|
||||||
|
responsemodifiers:
|
||||||
|
- name: BypassContentSecurityPolicy
|
||||||
|
- name: InjectScriptAfterDOMContentLoaded
|
||||||
|
params:
|
||||||
|
- |
|
||||||
|
let paywall = document.querySelectorAll('script[src*="advertising-cdn.dpgmedia.cloud"], div[data-temptation-position="ARTICLE_BOTTOM"]');
|
||||||
|
paywall.forEach(el => { el.remove(); });
|
||||||
|
document.querySelector('div[data-advert-placeholder-collapses]').remove();
|
||||||
44
rulesets_v2/BE_Belgium/dpg-media.yaml
Normal file
44
rulesets_v2/BE_Belgium/dpg-media.yaml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
- domains:
|
||||||
|
- myprivacy.dpgmedia.be
|
||||||
|
- myprivacy.dpgmedia.nl
|
||||||
|
|
||||||
|
requestmodifiers:
|
||||||
|
- name: SpoofReferrer
|
||||||
|
params: ["https://news.google.com"]
|
||||||
|
|
||||||
|
- name: SetOutgoingCookie
|
||||||
|
params: ["isBot", "true"]
|
||||||
|
|
||||||
|
- name: SetOutgoingCookie
|
||||||
|
params: ["authId", "1"]
|
||||||
|
|
||||||
|
- name: SpoofXForwardedFor
|
||||||
|
params: ["none"]
|
||||||
|
|
||||||
|
|
||||||
|
- domains:
|
||||||
|
- demorgen.be
|
||||||
|
|
||||||
|
requestmodifiers:
|
||||||
|
- name: MasqueradeAsGoogleBot
|
||||||
|
|
||||||
|
- name: SpoofReferrer
|
||||||
|
params: ["https://news.google.com"]
|
||||||
|
|
||||||
|
- name: SetOutgoingCookie
|
||||||
|
params: ["isBot", "true"]
|
||||||
|
|
||||||
|
- name: SetOutgoingCookie
|
||||||
|
params: ["authId", "1"]
|
||||||
|
|
||||||
|
- name: SpoofXForwardedFor
|
||||||
|
params: ["none"]
|
||||||
|
|
||||||
|
responsemodifiers:
|
||||||
|
- name: BypassContentSecurityPolicy
|
||||||
|
- name: InjectScriptAfterDOMContentLoaded
|
||||||
|
params:
|
||||||
|
- |
|
||||||
|
let paywall = document.querySelectorAll('script[src*="advertising-cdn.dpgmedia.cloud"], div[data-temptation-position="ARTICLE_BOTTOM"]');
|
||||||
|
paywall.forEach(el => { el.remove(); });
|
||||||
|
document.querySelector('div[data-advert-placeholder-collapses]').remove();
|
||||||
34
rulesets_v2/CA_Canada/_multi-metroland-media-group.yaml
Normal file
34
rulesets_v2/CA_Canada/_multi-metroland-media-group.yaml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
rules:
|
||||||
|
- domains:
|
||||||
|
- thestar.com
|
||||||
|
- niagarafallsreview.ca
|
||||||
|
- stcatharinesstandard.ca
|
||||||
|
- thepeterboroughexaminer.com
|
||||||
|
- therecord.com
|
||||||
|
- thespec.com
|
||||||
|
- wellandtribune.ca
|
||||||
|
responsemodifications:
|
||||||
|
- name: DeleteLocalStorageData
|
||||||
|
- name: DeleteSessionStorageData
|
||||||
|
- name: InjectScriptAfterDOMContentLoaded
|
||||||
|
params:
|
||||||
|
- |
|
||||||
|
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(); });
|
||||||
Reference in New Issue
Block a user