From 518f4d65d2586c4dd504ea58020e1224e8dbaa33 Mon Sep 17 00:00:00 2001 From: joncrangle <94425204+joncrangle@users.noreply.github.com> Date: Fri, 8 Dec 2023 00:42:10 -0500 Subject: [PATCH 01/23] Migrate code and utilize api/modifiers endpoint --- .github/workflows/build-css.yaml | 4 +- cmd/main.go | 15 +- handlers/api_modifiers_structdef.gen.go | 128 +++---- handlers/playground-script.js | 365 ++++++++++++++++++++ handlers/playground.go | 41 +++ handlers/playground.html | 432 ++++++++++++++++++++++++ handlers/script.go | 28 +- handlers/styles.css | 2 +- 8 files changed, 928 insertions(+), 87 deletions(-) create mode 100644 handlers/playground-script.js create mode 100644 handlers/playground.go create mode 100644 handlers/playground.html diff --git a/.github/workflows/build-css.yaml b/.github/workflows/build-css.yaml index ced8ee6..06e7771 100644 --- a/.github/workflows/build-css.yaml +++ b/.github/workflows/build-css.yaml @@ -4,6 +4,7 @@ on: push: paths: - "handlers/form.html" + - "handlers/playground.html" - "proxychain/responsemodifiers/vendor/generate_readable_outline.html" workflow_dispatch: @@ -37,7 +38,8 @@ jobs: echo "Changes detected, committing..." git config --global user.name "Github action" git config --global user.email "username@users.noreply.github.com" - git add cmd + git add handlers + git add "proxychain/responsemodifiers/vendor/ git commit -m "Generated stylesheet" git push fi diff --git a/cmd/main.go b/cmd/main.go index 997b655..c8c6c80 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -3,18 +3,16 @@ package main import ( _ "embed" "fmt" - "html/template" "log" "os" "ladder/handlers" "ladder/internal/cli" "ladder/proxychain/requestmodifiers/bot" - "ladder/proxychain/ruleset" + ruleset_v2 "ladder/proxychain/ruleset" "github.com/akamensky/argparse" "github.com/gofiber/fiber/v2" - "github.com/gofiber/template/html/v2" ) //go:embed VERSION @@ -129,21 +127,12 @@ func main() { rs = ruleset_v2.NewRulesetFromEnv() } - engine := html.New("./handlers", ".html") - engine.AddFunc( - // add unescape function - "unescape", func(s string) template.HTML { - return template.HTML(s) - }, - ) - app := fiber.New( fiber.Config{ Prefork: *prefork, GETOnly: false, ReadBufferSize: 4096 * 4, // increase max header size DisableStartupMessage: true, - Views: engine, }, ) @@ -167,6 +156,7 @@ func main() { app.Get("styles.css", handlers.Styles) app.Get("script.js", handlers.Script) + app.Get("playground-script.js", handlers.Script) app.All("api/raw/*", handlers.NewRawProxySiteHandler(proxyOpts)) @@ -175,6 +165,7 @@ func main() { app.Get("api/content/*", handlers.NewAPIContentHandler("api/outline/*", proxyOpts)) app.Get("outline/*", handlers.NewOutlineHandler("outline/*", proxyOpts)) + app.All("playground/*", handlers.PlaygroundHandler("playground/*", proxyOpts)) app.All("/*", handlers.NewProxySiteHandler(proxyOpts)) diff --git a/handlers/api_modifiers_structdef.gen.go b/handlers/api_modifiers_structdef.gen.go index ae24f52..b6ae548 100644 --- a/handlers/api_modifiers_structdef.gen.go +++ b/handlers/api_modifiers_structdef.gen.go @@ -36,7 +36,7 @@ var AllMods Modifiers = Modifiers{ { Name: "AddCacheBusterQuery", Description: "AddCacheBusterQuery modifies query params to add a random parameter key In order to get the upstream network stack to serve a fresh copy of the page.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/add_cache_buster_query.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/add_cache_buster_query.go", Params: []Param{ }, @@ -44,7 +44,7 @@ var AllMods Modifiers = Modifiers{ { Name: "ForwardRequestHeaders", Description: "ForwardRequestHeaders forwards the requests headers sent from the client to the upstream server", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/forward_request_headers.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/forward_request_headers.go", Params: []Param{ }, @@ -52,7 +52,7 @@ var AllMods Modifiers = Modifiers{ { Name: "MasqueradeAsGoogleBot", Description: "MasqueradeAsGoogleBot modifies user agent and x-forwarded for to appear to be a Google Bot", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", Params: []Param{ }, @@ -60,7 +60,7 @@ var AllMods Modifiers = Modifiers{ { Name: "MasqueradeAsBingBot", Description: "MasqueradeAsBingBot modifies user agent and x-forwarded for to appear to be a Bing Bot", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", Params: []Param{ }, @@ -68,7 +68,7 @@ var AllMods Modifiers = Modifiers{ { Name: "MasqueradeAsWaybackMachineBot", Description: "MasqueradeAsWaybackMachineBot modifies user agent and x-forwarded for to appear to be a archive.org (wayback machine) Bot", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", Params: []Param{ }, @@ -76,7 +76,7 @@ var AllMods Modifiers = Modifiers{ { Name: "MasqueradeAsFacebookBot", Description: "MasqueradeAsFacebookBot modifies user agent and x-forwarded for to appear to be a Facebook Bot (link previews?)", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", Params: []Param{ }, @@ -84,7 +84,7 @@ var AllMods Modifiers = Modifiers{ { Name: "MasqueradeAsYandexBot", Description: "MasqueradeAsYandexBot modifies user agent and x-forwarded for to appear to be a Yandex Spider Bot", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", Params: []Param{ }, @@ -92,7 +92,7 @@ var AllMods Modifiers = Modifiers{ { Name: "MasqueradeAsBaiduBot", Description: "MasqueradeAsBaiduBot modifies user agent and x-forwarded for to appear to be a Baidu Spider Bot", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", Params: []Param{ }, @@ -100,7 +100,7 @@ var AllMods Modifiers = Modifiers{ { Name: "MasqueradeAsDuckDuckBot", Description: "MasqueradeAsDuckDuckBot modifies user agent and x-forwarded for to appear to be a DuckDuckGo Bot", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", Params: []Param{ }, @@ -108,7 +108,7 @@ var AllMods Modifiers = Modifiers{ { Name: "MasqueradeAsYahooBot", Description: "MasqueradeAsYahooBot modifies user agent and x-forwarded for to appear to be a Yahoo Bot", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", Params: []Param{ }, @@ -116,7 +116,7 @@ var AllMods Modifiers = Modifiers{ { Name: "ModifyDomainWithRegex", Description: "", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/modify_domain_with_regex.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_domain_with_regex.go", Params: []Param{ {Name: "matchRegex", Type: "string"}, {Name: "replacement", Type: "string"}, @@ -125,7 +125,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SetOutgoingCookie", Description: "SetOutgoingCookie modifes a specific cookie name by modifying the request cookie headers going to the upstream server. If the cookie name does not already exist, it is created.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/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{ {Name: "name", Type: "string"}, {Name: "val", Type: "string"}, @@ -134,7 +134,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SetOutgoingCookies", Description: "SetOutgoingCookies modifies a client request's cookie header to a raw Cookie string, overwriting existing cookies", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/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{ {Name: "cookies", Type: "string"}, }, @@ -142,7 +142,7 @@ var AllMods Modifiers = Modifiers{ { Name: "DeleteOutgoingCookie", Description: "DeleteOutgoingCookie modifies the http request's cookies header to delete a specific request cookie going to the upstream server. If the cookie does not exist, it does not do anything.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/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{ {Name: "name", Type: "string"}, }, @@ -150,7 +150,7 @@ var AllMods Modifiers = Modifiers{ { Name: "DeleteOutgoingCookies", Description: "DeleteOutgoingCookies removes the cookie header entirely, preventing any cookies from reaching the upstream server.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/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{ }, @@ -158,7 +158,7 @@ var AllMods Modifiers = Modifiers{ { Name: "DeleteOutgoingCookiesExcept", 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/everywall/ladder/edit/origin/proxy_v2/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{ {Name: "whitelist", Type: "&{Ellipsis:12348 Elt:string}"}, }, @@ -166,7 +166,7 @@ var AllMods Modifiers = Modifiers{ { Name: "ModifyPathWithRegex", Description: "", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/modify_path_with_regex.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_path_with_regex.go", Params: []Param{ {Name: "matchRegex", Type: "string"}, {Name: "replacement", Type: "string"}, @@ -175,7 +175,7 @@ var AllMods Modifiers = Modifiers{ { Name: "ModifyQueryParams", Description: "ModifyQueryParams replaces query parameter values in URL's query params in a ProxyChain's URL. If the query param key doesn't exist, it is created.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/modify_query_params.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_query_params.go", Params: []Param{ {Name: "key", Type: "string"}, {Name: "value", Type: "string"}, @@ -184,7 +184,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SetRequestHeader", Description: "SetRequestHeader modifies a specific outgoing header This is the header that the upstream server will see.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/modify_request_headers.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_request_headers.go", Params: []Param{ {Name: "name", Type: "string"}, {Name: "val", Type: "string"}, @@ -193,7 +193,7 @@ var AllMods Modifiers = Modifiers{ { Name: "DeleteRequestHeader", Description: "DeleteRequestHeader modifies a specific outgoing header This is the header that the upstream server will see.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/modify_request_headers.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_request_headers.go", Params: []Param{ {Name: "name", Type: "string"}, }, @@ -201,7 +201,7 @@ var AllMods Modifiers = Modifiers{ { Name: "RequestArchiveIs", Description: "RequestArchiveIs modifies a ProxyChain's URL to request an archived version from archive.is", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/request_archive_is.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/request_archive_is.go", Params: []Param{ }, @@ -209,7 +209,7 @@ var AllMods Modifiers = Modifiers{ { Name: "RequestGoogleCache", Description: "RequestGoogleCache modifies a ProxyChain's URL to request its Google Cache version.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/request_google_cache.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/request_google_cache.go", Params: []Param{ }, @@ -217,7 +217,7 @@ var AllMods Modifiers = Modifiers{ { Name: "RequestWaybackMachine", Description: "RequestWaybackMachine modifies a ProxyChain's URL to request the wayback machine (archive.org) version.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/request_wayback_machine.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/request_wayback_machine.go", Params: []Param{ }, @@ -225,7 +225,7 @@ var AllMods Modifiers = Modifiers{ { Name: "ResolveWithGoogleDoH", Description: "ResolveWithGoogleDoH modifies a ProxyChain's client to make the request by resolving the URL using Google's DNS over HTTPs service", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/resolve_with_google_doh.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/resolve_with_google_doh.go", Params: []Param{ }, @@ -233,7 +233,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SpoofOrigin", Description: "SpoofOrigin modifies the origin header if the upstream server returns a Vary header it means you might get a different response if you change this", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/spoof_origin.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_origin.go", Params: []Param{ {Name: "url", Type: "string"}, }, @@ -241,7 +241,7 @@ var AllMods Modifiers = Modifiers{ { Name: "HideOrigin", Description: "HideOrigin modifies the origin header so that it is the original origin, not the proxy", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/spoof_origin.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_origin.go", Params: []Param{ }, @@ -249,7 +249,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SpoofReferrer", Description: "SpoofReferrer modifies the referrer header. It is useful if the page can be accessed from a search engine or social media site, but not by browsing the website itself. if url is \"\", then the referrer header is removed.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/spoof_referrer.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer.go", Params: []Param{ {Name: "url", Type: "string"}, }, @@ -257,7 +257,7 @@ var AllMods Modifiers = Modifiers{ { Name: "HideReferrer", Description: "HideReferrer modifies the referrer header so that it is the original referrer, not the proxy", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/spoof_referrer.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer.go", Params: []Param{ }, @@ -265,7 +265,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SpoofReferrerFromBaiduSearch", Description: "SpoofReferrerFromBaiduSearch modifies the referrer header pretending to be from a BaiduSearch", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/spoof_referrer_from_baidu_post.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_baidu_post.go", Params: []Param{ }, @@ -273,7 +273,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SpoofReferrerFromBingSearch", Description: "SpoofReferrerFromBingSearch modifies the referrer header pretending to be from a bing search site", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/spoof_referrer_from_bing_search.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_bing_search.go", Params: []Param{ }, @@ -281,7 +281,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SpoofReferrerFromGoogleSearch", Description: "SpoofReferrerFromGoogleSearch modifies the referrer header pretending to be from a google search site", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/spoof_referrer_from_google_search.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_google_search.go", Params: []Param{ }, @@ -289,7 +289,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SpoofReferrerFromLinkedInPost", Description: "SpoofReferrerFromLinkedInPost modifies the referrer header pretending to be from a linkedin post", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/spoof_referrer_from_linkedin_post.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_linkedin_post.go", Params: []Param{ }, @@ -297,7 +297,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SpoofReferrerFromNaverSearch", Description: "SpoofReferrerFromNaverSearch modifies the referrer header pretending to be from a Naver search (popular in South Korea)", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/spoof_referrer_from_naver_post.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_naver_post.go", Params: []Param{ }, @@ -305,7 +305,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SpoofReferrerFromPinterestPost", Description: "SpoofReferrerFromPinterestPost modifies the referrer header pretending to be from a pinterest post", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/spoof_referrer_from_pinterest_post.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_pinterest_post.go", Params: []Param{ }, @@ -313,7 +313,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SpoofReferrerFromQQPost", Description: "SpoofReferrerFromQQPost modifies the referrer header pretending to be from a QQ post (popular social media in China)", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/spoof_referrer_from_qq_post.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_qq_post.go", Params: []Param{ }, @@ -321,7 +321,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SpoofReferrerFromRedditPost", Description: "SpoofReferrerFromRedditPost modifies the referrer header pretending to be from a reddit post", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/spoof_referrer_from_reddit_post.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_reddit_post.go", Params: []Param{ }, @@ -329,7 +329,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SpoofReferrerFromTumblrPost", Description: "SpoofReferrerFromTumblrPost modifies the referrer header pretending to be from a tumblr post", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/spoof_referrer_from_tumblr_post.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_tumblr_post.go", Params: []Param{ }, @@ -337,7 +337,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SpoofReferrerFromTwitterPost", Description: "SpoofReferrerFromTwitterPost modifies the referrer header pretending to be from a twitter post", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/spoof_referrer_from_twitter_post.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_twitter_post.go", Params: []Param{ }, @@ -345,7 +345,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SpoofReferrerFromVkontaktePost", Description: "SpoofReferrerFromVkontaktePost modifies the referrer header pretending to be from a vkontakte post (popular in Russia)", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/spoof_referrer_from_vkontake_post.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_vkontake_post.go", Params: []Param{ }, @@ -353,7 +353,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SpoofReferrerFromWeiboPost", Description: "SpoofReferrerFromWeiboPost modifies the referrer header pretending to be from a Weibo post (popular in China)", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/spoof_referrer_from_weibo_post.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_weibo_post.go", Params: []Param{ }, @@ -361,7 +361,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SpoofUserAgent", Description: "SpoofUserAgent modifies the user agent", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/spoof_user_agent.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_user_agent.go", Params: []Param{ {Name: "ua", Type: "string"}, }, @@ -369,7 +369,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SpoofXForwardedFor", Description: "SpoofXForwardedFor modifies the X-Forwarded-For header in some cases, a forward proxy may interpret this as the source IP", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/requestmodifiers/spoof_x_forwarded_for.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_x_forwarded_for.go", Params: []Param{ {Name: "ip", Type: "string"}, }, @@ -379,7 +379,7 @@ var AllMods Modifiers = Modifiers{ { Name: "APIContent", Description: "APIContent creates an JSON representation of the article and returns it as an API response.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/api_content.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/api_content.go", Params: []Param{ }, @@ -387,7 +387,7 @@ var AllMods Modifiers = Modifiers{ { Name: "BlockElementRemoval", Description: "BlockElementRemoval prevents paywall javascript from removing a particular element by detecting the removal, then immediately reinserting it. This is useful when a page will return a \"fake\" 404, after flashing the content briefly. If the /outline/ API works, but the regular API doesn't, try this modifier.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/block_element_removal.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/block_element_removal.go", Params: []Param{ {Name: "cssSelector", Type: "string"}, }, @@ -395,7 +395,7 @@ var AllMods Modifiers = Modifiers{ { Name: "BlockThirdPartyScripts", Description: "BlockThirdPartyScripts rewrites HTML and injects JS to block all third party JS from loading.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/block_third_party_scripts.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/block_third_party_scripts.go", Params: []Param{ }, @@ -403,7 +403,7 @@ var AllMods Modifiers = Modifiers{ { Name: "BypassCORS", Description: "BypassCORS modifies response headers to prevent the browser from enforcing any CORS restrictions. This should run at the end of the chain.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/bypass_cors.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/bypass_cors.go", Params: []Param{ }, @@ -411,7 +411,7 @@ var AllMods Modifiers = Modifiers{ { Name: "BypassContentSecurityPolicy", Description: "BypassContentSecurityPolicy modifies response headers to prevent the browser from enforcing any CSP restrictions. This should run at the end of the chain.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/bypass_csp.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/bypass_csp.go", Params: []Param{ }, @@ -419,7 +419,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SetContentSecurityPolicy", Description: "SetContentSecurityPolicy modifies response headers to a specific CSP", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/bypass_csp.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/bypass_csp.go", Params: []Param{ {Name: "csp", Type: "string"}, }, @@ -427,7 +427,7 @@ var AllMods Modifiers = Modifiers{ { Name: "DeleteLocalStorageData", Description: "DeleteLocalStorageData deletes localstorage cookies. If the page works once in a fresh incognito window, but fails for subsequent loads, try this response modifier alongside DeleteSessionStorageData and DeleteIncomingCookies", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/delete_localstorage_data.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/delete_localstorage_data.go", Params: []Param{ }, @@ -435,7 +435,7 @@ var AllMods Modifiers = Modifiers{ { Name: "DeleteSessionStorageData", Description: "DeleteSessionStorageData deletes localstorage cookies. If the page works once in a fresh incognito window, but fails for subsequent loads, try this response modifier alongside DeleteLocalStorageData and DeleteIncomingCookies", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/delete_sessionstorage_data.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/delete_sessionstorage_data.go", Params: []Param{ }, @@ -443,7 +443,7 @@ var AllMods Modifiers = Modifiers{ { Name: "ForwardResponseHeaders", Description: "ForwardResponseHeaders forwards the response headers from the upstream server to the client", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/forward_response_headers.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/forward_response_headers.go", Params: []Param{ }, @@ -451,7 +451,7 @@ var AllMods Modifiers = Modifiers{ { Name: "GenerateReadableOutline", Description: "GenerateReadableOutline creates an reader-friendly distilled representation of the article. This is a reliable way of bypassing soft-paywalled articles, where the content is hidden, but still present in the DOM.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/generate_readable_outline.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/generate_readable_outline.go", Params: []Param{ }, @@ -459,7 +459,7 @@ var AllMods Modifiers = Modifiers{ { Name: "InjectScriptBeforeDOMContentLoaded", Description: "InjectScriptBeforeDOMContentLoaded modifies HTTP responses to inject a JS before DOM Content is loaded (script tag in head)", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/inject_script.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/inject_script.go", Params: []Param{ {Name: "js", Type: "string"}, }, @@ -467,7 +467,7 @@ var AllMods Modifiers = Modifiers{ { Name: "InjectScriptAfterDOMContentLoaded", Description: "InjectScriptAfterDOMContentLoaded modifies HTTP responses to inject a JS after DOM Content is loaded (script tag in head)", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/inject_script.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/inject_script.go", Params: []Param{ {Name: "js", Type: "string"}, }, @@ -475,7 +475,7 @@ var AllMods Modifiers = Modifiers{ { Name: "InjectScriptAfterDOMIdle", Description: "InjectScriptAfterDOMIdle modifies HTTP responses to inject a JS after the DOM is idle (ie: js framework loaded)", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/inject_script.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/inject_script.go", Params: []Param{ {Name: "js", Type: "string"}, }, @@ -483,7 +483,7 @@ var AllMods Modifiers = Modifiers{ { Name: "DeleteIncomingCookies", Description: "DeleteIncomingCookies prevents ALL cookies from being sent from the proxy server back down to the client.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/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{ {Name: "_", Type: "&{Ellipsis:16319 Elt:string}"}, }, @@ -491,7 +491,7 @@ var AllMods Modifiers = Modifiers{ { Name: "DeleteIncomingCookiesExcept", 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/everywall/ladder/edit/origin/proxy_v2/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{ {Name: "whitelist", Type: "&{Ellipsis:16864 Elt:string}"}, }, @@ -499,7 +499,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SetIncomingCookies", Description: "SetIncomingCookies adds a raw cookie string being sent from the proxy server down to the client", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/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{ {Name: "cookies", Type: "string"}, }, @@ -507,7 +507,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SetIncomingCookie", Description: "SetIncomingCookie modifies a specific cookie in the response from the proxy server to the client.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/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{ {Name: "name", Type: "string"}, {Name: "val", Type: "string"}, @@ -516,7 +516,7 @@ var AllMods Modifiers = Modifiers{ { Name: "SetResponseHeader", Description: "SetResponseHeader modifies response headers from the upstream server", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/modify_response_header.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/modify_response_header.go", Params: []Param{ {Name: "key", Type: "string"}, {Name: "value", Type: "string"}, @@ -525,7 +525,7 @@ var AllMods Modifiers = Modifiers{ { Name: "DeleteResponseHeader", Description: "DeleteResponseHeader removes response headers from the upstream server", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/modify_response_header.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/modify_response_header.go", Params: []Param{ {Name: "key", Type: "string"}, }, @@ -533,7 +533,7 @@ var AllMods Modifiers = Modifiers{ { Name: "PatchDynamicResourceURLs", Description: "PatchDynamicResourceURLs patches the javascript runtime to rewrite URLs client-side. - This function is designed to allow the proxified page to still be browsible by routing all resource URLs through the proxy. - Native APIs capable of network requests will be hooked and the URLs arguments modified to point to the proxy instead. - fetch('/relative_path') -> fetch('/https://proxiedsite.com/relative_path') - Element.setAttribute('src', \"/assets/img.jpg\") -> Element.setAttribute('src', \"/https://proxiedsite.com/assets/img.jpg\") -> fetch('/https://proxiedsite.com/relative_path')", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/patch_dynamic_resource_urls.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/patch_dynamic_resource_urls.go", Params: []Param{ }, @@ -541,7 +541,7 @@ var AllMods Modifiers = Modifiers{ { Name: "PatchTrackerScripts", Description: "PatchTrackerScripts replaces any request to tracker scripts such as google analytics with a no-op stub that mocks the API structure of the original scripts they replace. Some pages depend on the existence of these structures for proper loading, so this may fix some broken elements. Surrogate script code borrowed from: DuckDuckGo Privacy Essentials browser extension for Firefox, Chrome. (Apache 2.0 license)", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/patch_tracker_scripts.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/patch_tracker_scripts.go", Params: []Param{ }, @@ -549,7 +549,7 @@ var AllMods Modifiers = Modifiers{ { Name: "RewriteHTMLResourceURLs", Description: "RewriteHTMLResourceURLs modifies HTTP responses to rewrite URLs attributes in HTML content (such as src, href) - `` -> `` - This function is designed to allow the proxified page to still be browsible by routing all resource URLs through the proxy.", - CodeEditLink: "https://github.com/everywall/ladder/edit/origin/proxy_v2/proxychain/responsemodifiers/rewrite_http_resource_urls.go", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/rewrite_http_resource_urls.go", Params: []Param{ }, diff --git a/handlers/playground-script.js b/handlers/playground-script.js new file mode 100644 index 0000000..3352243 --- /dev/null +++ b/handlers/playground-script.js @@ -0,0 +1,365 @@ +// Export button +// TODO: Parse JSON to YAML +// TODO: Download YAML +// Injection scripts +// TODO: Javascript syntax highlighting within textarea layout, styling and event listeners +// TODO: Textarea handlers and logic for javascript (e.g. tab, newline) +// TODO: Javascript escaping/unescaping as required +// TODO: remove tailwind play cdn script in head of playground.html after syntax highlighting work complete +// Ninja Keys improvements +// TODO: Group related items for Ninja Keys +// TODO: Untoggle related items that may be toggled (e.g. should only have one masquerade as bot toggled) +// Testing +// TODO: Testing + +const modifierContainer = document.getElementById("modifierContainer"); +const modalContainer = document.getElementById("modalContainer"); +const modalBody = document.getElementById("modal-body"); +const modalContent = document.getElementById("modal-content"); +const modalSubmitButton = document.getElementById("modal-submit"); +const modalClose = document.getElementById("modal-close"); + +let hasFetched = false; +let payload = { + requestmodifications: [], + responsemodifications: [], +}; +let ninjaData = []; + +initialize(); + +// Rerun handleThemeChange() so style is applied to Ninja Keys +handleThemeChange(); + +// Add event listener to the iframe so it closes dropdown when clicked +closeDropdownOnClickWithinIframe(); + +async function initialize() { + if (!hasFetched) { + try { + await fetchPayload(); + hasFetched = true; + } catch (error) { + console.error("Fetch error:", error); + } + } +} + +function closeDropdownOnClickWithinIframe() { + const iframe = document.getElementById("resultIframe"); + iframe.contentWindow.document.addEventListener( + "click", + () => { + if ( + !document.getElementById("dropdown_panel").classList.contains("hidden") + ) { + toggleDropdown(); + } + }, + true + ); +} + +async function fetchPayload() { + try { + const response = await fetch("/api/modifiers"); + const data = await response.json(); + + Object.entries(data.result.requestmodifiers ?? {}).forEach(([_, value]) => { + addModifierToNinjaData( + value.name, + value.description, + value.params, + "requestmodifications" + ); + }); + + Object.entries(data.result.responsemodifiers ?? {}).forEach( + ([_, value]) => { + addModifierToNinjaData( + value.name, + value.description, + value.params, + "responsemodifications" + ); + } + ); + + return data; + } catch (error) { + console.error("Fetch error:", error); + throw error; + } +} + +async function submitForm() { + if (!document.getElementById("inputForm").checkValidity()) { + return; + } + + try { + const response = await fetch("/playground/" + inputField.value, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(payload), + }); + + if (!response.ok) { + throw new Error("Request failed"); + } + + const result = await response.text(); + updateResultIframe(result); + } catch (error) { + console.error(error); + } +} + +function updateResultIframe(result) { + const resultIframe = parent.document.getElementById("resultIframe"); + resultIframe.contentDocument.open(); + resultIframe.contentDocument.write(result); + closeDropdownOnClickWithinIframe(); + resultIframe.contentDocument.close(); +} + +document.getElementById("inputForm").addEventListener("submit", function (e) { + e.preventDefault(); + submitForm(); +}); + +if (navigator.userAgent.includes("Mac")) { + document.getElementById("ninjaKey").innerHTML = "⌘"; +} else { + document.getElementById("ninjaKey").innerHTML = "Ctrl"; +} + +function downloadYaml() { + function parseYaml() { + //* PARSE PAYLOAD TO YAML + return payload; + } + + const yamlData = parseYaml(); + const blob = new Blob([yamlData], { type: "text/yaml;charset=utf-8" }); + const url = URL.createObjectURL(blob); + const link = document.createElement("a"); + link.href = url; + //* CONSTRUCT FILENAME FROM HOSTNAME + link.download = `name_of_report.yaml`; + link.click(); + URL.revokeObjectURL(url); +} + +function getValues(id, description, params) { + const focusTrap = trap(modalBody); + let values = []; + const inputs = []; + const inputEventListeners = []; + + function closeModal() { + focusTrap.destroy(); + modalBody.removeEventListener("keydown", handleEscapeKey); + modalBody.removeEventListener("keydown", handleEnterKey); + modalContainer.removeEventListener("click", handleClickOutside); + modalSubmitButton.removeEventListener("click", closeModal); + modalClose.removeEventListener("click", closeModal); + inputEventListeners.forEach((listener, index) => { + inputs[index].removeEventListener("input", listener); + }); + inputEventListeners.length = 0; + inputs.length = 0; + values = []; + modalContainer.classList.add("hidden"); + modalContent.innerHTML = ""; + } + + function handleClickOutside(e) { + if (modalBody !== null && !modalBody.contains(e.target)) { + closeModal(); + } + } + + function handleEscapeKey(e) { + if (e.key === "Escape") { + closeModal(); + } + } + + function handleEnterKey(e) { + if (e.key === "Enter") { + if (e.target.tagName.toLowerCase() === "textarea") { + return; + } else { + modalSubmitButton.click(); + } + } + } + + document.getElementById("modal-title").innerHTML = id; + document.getElementById("modal-description").innerHTML = description; + + params.map((param, i) => { + function textareaEventListener(event) { + codeElement = document.querySelector("code"); + codeElement.innerText = event.target.value; + Prism.highlightElement(codeElement); + values[i] = "|" + " " + event.target.value; + } + function inputEventListener(event) { + values[i] = event.target.value; + } + + const label = document.createElement("label"); + label.innerHTML = param.name; + label.setAttribute("for", `input-${i}`); + let input; + if (param.name === "js") { + input = document.createElement("textarea"); + input.type = "textarea"; + input.classList.add( + "min-h-[200px]", + "font-mono", + "whitespace-break-spaces", + "font-semibold" + ); + } else { + input = document.createElement("input"); + input.type = "text"; + } + input.id = `input-${i}`; + input.classList.add( + "w-full", + "text-sm", + "leading-6", + "text-slate-400", + "rounded-md", + "ring-1", + "ring-slate-900/10", + "shadow-sm", + "py-1.5", + "pl-2", + "pr-3", + "hover:ring-slate-300", + "dark:bg-slate-800", + "dark:highlight-white/5" + ); + modalContent.appendChild(label); + modalContent.appendChild(input); + if (input.type === "textarea") { + preElement = document.createElement("pre"); + codeElement = document.createElement("code"); + preElement.setAttribute("aria-hidden", "true"); + preElement.setAttribute("tabindex", "-1"); + codeElement.classList.add("language-javascript"); + preElement.appendChild(codeElement); + modalContent.appendChild(preElement); + input.addEventListener("input", textareaEventListener); + inputEventListeners.push(textareaEventListener); + } else { + input.addEventListener("input", inputEventListener); + inputEventListeners.push(inputEventListener); + } + inputs.push(input); + }); + + modalContainer.classList.remove("hidden"); + document.getElementById("input-0").focus(); + + return new Promise((resolve) => { + modalBody.addEventListener("keydown", handleEscapeKey); + modalBody.addEventListener("keydown", handleEnterKey); + modalContainer.addEventListener("click", handleClickOutside); + modalClose.addEventListener("click", () => { + closeModal(); + }); + modalSubmitButton.addEventListener("click", () => { + resolve(values); + closeModal(); + }); + }); +} + +function toggleModifier(type, id, params = []) { + function pillClickHandler(pill) { + toggleModifier(pill.getAttribute("type"), pill.id); + pill.removeEventListener("click", () => pillClickHandler(pill)); + pill.remove(); + } + + function createPill(type, id) { + const pill = document.createElement("span"); + pill.classList.add( + "inline-flex", + "items-center", + "rounded-md", + "bg-slate-100", + "dark:bg-slate-800", + "px-2", + "py-1", + "h-4", + "text-xs", + "font-medium", + "border", + "border-slate-400", + "dark:border-slate-700", + "cursor-pointer" + ); + pill.id = id; + pill.setAttribute("type", type); + pill.textContent = id; + modifierContainer.appendChild(pill); + pill.addEventListener("click", () => pillClickHandler(pill)); + } + + if (payload[type].some((modifier) => modifier.name === id)) { + payload[type] = payload[type].filter((modifier) => modifier.name !== id); + const existingPill = document.getElementById(id); + if (existingPill !== null) { + existingPill.removeEventListener("click", () => pillClickHandler(pill)); + existingPill.remove(); + } + } else { + payload[type].push({ name: id, params: params }); + createPill(type, id); + } + + submitForm(); +} + +function addModifierToNinjaData(id, description, params, type) { + const section = + type === "requestmodifications" + ? "Request Modifiers" + : "Response Modifiers"; + const modifier = { + id: id, + title: id, + section: section, + + handler: () => { + if (Object.keys(params).length === 0) { + toggleModifier(type, id); + } else { + if (params[0].name === "_") { + toggleModifier(type, id, (params = [""])); + } else { + getValues(id, description, params).then((values) => { + if (Object.keys(values).length === 0) return; + toggleModifier(type, id, values); + }); + } + } + }, + }; + + ninjaData.push(modifier); +} + +const ninja = document.querySelector("ninja-keys"); +ninja.data = ninjaData; +document.getElementById("btnNinja").addEventListener("click", () => { + ninja.open(); +}); diff --git a/handlers/playground.go b/handlers/playground.go new file mode 100644 index 0000000..a2b2c78 --- /dev/null +++ b/handlers/playground.go @@ -0,0 +1,41 @@ +package handlers + +import ( + _ "embed" + "ladder/proxychain" + ruleset_v2 "ladder/proxychain/ruleset" + + "net/http" + + "github.com/gofiber/fiber/v2" +) + +//go:embed playground.html +var playgroundHtml string + +func PlaygroundHandler(path string, opts *ProxyOptions) fiber.Handler { + return func(c *fiber.Ctx) error { + if c.Method() == fiber.MethodGet { + c.Set("Content-Type", "text/html") + + return c.SendString(playgroundHtml) + } else if c.Method() == fiber.MethodPost { + var modificationData ruleset_v2.Rule + if err := c.BodyParser(&modificationData); err != nil { + return err + } + + c.Method(fiber.MethodGet) + + return proxychain. + NewProxyChain(). + SetFiberCtx(c). + WithAPIPath(path). + AddOnceRequestModifications(modificationData.RequestModifications...). + AddOnceResponseModifications(modificationData.ResponseModifications...). + Execute() + } + + return c.Status(http.StatusMethodNotAllowed).SendString("Method not allowed") + } +} diff --git a/handlers/playground.html b/handlers/playground.html new file mode 100644 index 0000000..d5614d7 --- /dev/null +++ b/handlers/playground.html @@ -0,0 +1,432 @@ + + + + + + ladder | playground + + + + + + + + + + + + + +
+
+
+
+ + +
+ +
+
+
+
+
+ + +
+ +
+
+
+
+ +
+
+
+ + + + + + +
+ + diff --git a/handlers/script.go b/handlers/script.go index c35e6ca..4e00327 100644 --- a/handlers/script.go +++ b/handlers/script.go @@ -9,15 +9,25 @@ import ( //go:embed script.js var scriptData embed.FS +//go:embed playground-script.js +var playgroundScriptData embed.FS + func Script(c *fiber.Ctx) error { - - scriptData, err := scriptData.ReadFile("script.js") - if err != nil { - return c.Status(fiber.StatusInternalServerError).SendString("Internal Server Error") + if c.Path() == "/script.js" { + scriptData, err := scriptData.ReadFile("script.js") + if err != nil { + return c.Status(fiber.StatusInternalServerError).SendString("Internal Server Error") + } + c.Set("Content-Type", "text/javascript") + return c.Send(scriptData) } - - c.Set("Content-Type", "text/javascript") - - return c.Send(scriptData) - + if c.Path() == "/playground-script.js" { + playgroundScriptData, err := playgroundScriptData.ReadFile("playground-script.js") + if err != nil { + return c.Status(fiber.StatusInternalServerError).SendString("Internal Server Error") + } + c.Set("Content-Type", "text/javascript") + return c.Send(playgroundScriptData) + } + return nil } diff --git a/handlers/styles.css b/handlers/styles.css index 4234618..211d48b 100644 --- a/handlers/styles.css +++ b/handlers/styles.css @@ -1 +1 @@ -*,::after,::before{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}::after,::before{--tw-content:''}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}a{--tw-text-opacity:1;color:rgb(71 85 105 / var(--tw-text-opacity));text-underline-offset:2px;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4,0,0.2,1);transition-duration:.3s}a:hover{--tw-text-opacity:1;color:rgb(59 130 246 / var(--tw-text-opacity));text-decoration-line:underline}:is(.dark a){--tw-text-opacity:1;color:rgb(148 163 184 / var(--tw-text-opacity))}:is(.dark a:hover){--tw-text-opacity:1;color:rgb(59 130 246 / var(--tw-text-opacity))}h1{scroll-margin:5rem;font-size:2.25rem;line-height:2.5rem;font-weight:800;letter-spacing:-.025em;--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}:is(.dark h1){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}@media (min-width:1024px){h1{font-size:3rem;line-height:1}}h2{scroll-margin:5rem;border-bottom-width:1px;padding-bottom:.5rem;font-size:1.875rem;line-height:2.25rem;font-weight:600;letter-spacing:-.025em;--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}h2:first-child{margin-top:0}:is(.dark h2){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}h3{scroll-margin:5rem;font-size:1.5rem;line-height:2rem;font-weight:600;letter-spacing:-.025em;--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}:is(.dark h3){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}h4,h5,h6{scroll-margin:5rem;font-size:1.25rem;line-height:1.75rem;font-weight:600;letter-spacing:-.025em;--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}:is(.dark h4),:is(.dark h5),:is(.dark h6){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}p{line-height:1.75rem;--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}:is(.dark p){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}p:not(:first-child){margin-top:1.5rem}code,kbd,pre{position:relative;white-space:break-spaces;border-radius:.25rem;--tw-bg-opacity:1;background-color:rgb(226 232 240 / var(--tw-bg-opacity));padding-top:.2rem;padding-bottom:.2rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:.875rem;line-height:1.25rem;font-weight:600}:is(.dark code),:is(.dark kbd),:is(.dark pre){--tw-bg-opacity:1;background-color:rgb(30 41 59 / var(--tw-bg-opacity))}blockquote{margin-top:1.5rem;border-left-width:2px;padding-left:1.5rem;font-style:italic}ul{margin-top:1.5rem;margin-bottom:1.5rem;margin-left:1.5rem;list-style-type:disc;--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}:is(.dark ul){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}ul>li{margin-top:.5rem}ol{margin-top:1.5rem;margin-bottom:1.5rem;margin-left:1.5rem;list-style-type:decimal;--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}:is(.dark ol){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}ol>li{margin-top:.5rem}dl{margin-top:1.5rem;margin-bottom:1.5rem;font-weight:700;--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}:is(.dark dl){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}dl>dd{margin-left:1.5rem;font-weight:400}dl>dt{margin-top:.75rem}li{--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}:is(.dark li){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}table{width:100%;caption-side:bottom;font-size:.875rem;line-height:1.25rem}thead tr{border-bottom-width:1px}tbody tr:last-child{border-width:0}tfoot{border-top-width:1px;--tw-border-opacity:1;border-color:rgb(148 163 184 / var(--tw-border-opacity));background-color:rgb(51 65 85 / .5);font-weight:500}:is(.dark tfoot){--tw-border-opacity:1;border-color:rgb(51 65 85 / var(--tw-border-opacity));background-color:rgb(226 232 240 / .5)}tfoot:last-child>tr{border-bottom-width:0}tr{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(148 163 184 / var(--tw-border-opacity));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4,0,0.2,1);transition-duration:150ms}tr:hover{background-color:rgb(226 232 240 / .5)}tr[data-state=selected]{--tw-bg-opacity:1;background-color:rgb(51 65 85 / var(--tw-bg-opacity))}:is(.dark tr){--tw-border-opacity:1;border-color:rgb(51 65 85 / var(--tw-border-opacity))}:is(.dark tr:hover){background-color:rgb(51 65 85 / .5)}:is(.dark tr[data-state=selected]){--tw-bg-opacity:1;background-color:rgb(226 232 240 / var(--tw-bg-opacity))}th{height:3rem;padding-left:1rem;padding-right:1rem;text-align:left;vertical-align:middle;font-weight:500;--tw-text-opacity:1;color:rgb(71 85 105 / var(--tw-text-opacity))}:is(.dark th){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}th:has([role=checkbox]){padding-right:0}td{padding:1rem;vertical-align:middle}td:has([role=checkbox]){padding-right:0}caption{margin-top:1rem;font-size:.875rem;line-height:1.25rem;--tw-text-opacity:1;color:rgb(71 85 105 / var(--tw-text-opacity))}:is(.dark caption){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}img{margin-left:auto;margin-right:auto;height:auto;width:auto;max-width:100%;border-radius:.375rem;-o-object-fit:cover;object-fit:cover;--tw-shadow:0 4px 6px -1px rgb(0 0 0 / 0.1),0 2px 4px -2px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}:is(.dark img){--tw-shadow-color:#334155;--tw-shadow:var(--tw-shadow-colored)}figcaption{margin-top:.5rem;font-size:.875rem;line-height:1.25rem;--tw-text-opacity:1;color:rgb(71 85 105 / var(--tw-text-opacity))}:is(.dark figcaption){--tw-text-opacity:1;color:rgb(148 163 184 / var(--tw-text-opacity))}hr{height:1px;width:100%;flex-shrink:0;--tw-bg-opacity:1;background-color:rgb(226 232 240 / var(--tw-bg-opacity))}:is(.dark hr){--tw-bg-opacity:1;background-color:rgb(51 65 85 / var(--tw-bg-opacity))}*,::after,::before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.collapse{visibility:collapse}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-y-0{top:0;bottom:0}.right-0{right:0}.z-10{z-index:10}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-2{margin-top:.5rem;margin-bottom:.5rem}.-ml-2{margin-left:-.5rem}.-mt-12{margin-top:-3rem}.ml-1{margin-left:.25rem}.mr-1{margin-right:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-5{margin-top:1.25rem}.block{display:block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-12{height:3rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-8{height:2rem}.h-\[1px\]{height:1px}.h-\[250px\]{height:250px}.h-auto{height:auto}.w-10{width:2.5rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-52{width:13rem}.w-auto{width:auto}.w-full{width:100%}.max-w-3xl{max-width:48rem}.max-w-full{max-width:100%}.shrink-0{flex-shrink:0}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize{resize:both}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap-reverse{flex-wrap:wrap-reverse}.place-items-center{place-items:center}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-items-center{justify-items:center}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-x-10{-moz-column-gap:2.5rem;column-gap:2.5rem}.gap-y-4{row-gap:1rem}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.place-self-end{place-self:end}.whitespace-nowrap{white-space:nowrap}.rounded-full{border-radius:9999px}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-slate-400{--tw-border-opacity:1;border-color:rgb(148 163 184 / var(--tw-border-opacity))}.bg-slate-200{--tw-bg-opacity:1;background-color:rgb(226 232 240 / var(--tw-bg-opacity))}.bg-slate-400{--tw-bg-opacity:1;background-color:rgb(148 163 184 / var(--tw-bg-opacity))}.bg-slate-800{--tw-bg-opacity:1;background-color:rgb(30 41 59 / var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.object-cover{-o-object-fit:cover;object-fit:cover}.p-2{padding:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.px-8{padding-left:2rem;padding-right:2rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.pl-2{padding-left:.5rem}.pr-2{padding-right:.5rem}.pr-3{padding-right:.75rem}.pt-10{padding-top:2.5rem}.text-left{text-align:left}.text-center{text-align:center}.align-middle{vertical-align:middle}.font-sans{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"}.font-serif{font-family:ui-serif,Georgia,Cambria,"Times New Roman",Times,serif}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-5xl{font-size:3rem;line-height:1}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-extrabold{font-weight:800}.font-medium{font-weight:500}.leading-6{line-height:1.5rem}.leading-8{line-height:2rem}.leading-none{line-height:1}.tracking-tight{letter-spacing:-.025em}.text-\[\#7AA7D1\]{--tw-text-opacity:1;color:rgb(122 167 209 / var(--tw-text-opacity))}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68 / var(--tw-text-opacity))}.text-slate-200{--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184 / var(--tw-text-opacity))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105 / var(--tw-text-opacity))}.text-slate-900{--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}.underline-offset-2{text-underline-offset:2px}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.shadow-md{--tw-shadow:0 4px 6px -1px rgb(0 0 0 / 0.1),0 2px 4px -2px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgb(0 0 0 / 0.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-slate-900\/10{--tw-ring-color:rgb(15 23 42 / 0.1)}.ring-offset-2{--tw-ring-offset-width:2px}.ring-offset-white{--tw-ring-offset-color:#fff}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4,0,0.2,1);transition-duration:150ms}.duration-300{transition-duration:.3s}.first-of-type\:rounded-t-md:first-of-type{border-top-left-radius:.375rem;border-top-right-radius:.375rem}.last-of-type\:rounded-b-md:last-of-type{border-bottom-right-radius:.375rem;border-bottom-left-radius:.375rem}.hover\:bg-slate-200:hover{--tw-bg-opacity:1;background-color:rgb(226 232 240 / var(--tw-bg-opacity))}.hover\:bg-slate-200\/90:hover{background-color:rgb(226 232 240 / .9)}.hover\:bg-slate-800\/90:hover{background-color:rgb(30 41 59 / .9)}.hover\:text-blue-500:hover{--tw-text-opacity:1;color:rgb(59 130 246 / var(--tw-text-opacity))}.hover\:text-slate-400:hover{--tw-text-opacity:1;color:rgb(148 163 184 / var(--tw-text-opacity))}.hover\:text-slate-500:hover{--tw-text-opacity:1;color:rgb(100 116 139 / var(--tw-text-opacity))}.hover\:underline:hover{text-decoration-line:underline}.hover\:no-underline:hover{text-decoration-line:none}.hover\:ring-slate-300:hover{--tw-ring-opacity:1;--tw-ring-color:rgb(203 213 225 / var(--tw-ring-opacity))}.hover\:drop-shadow-\[0_0px_10px_rgba\(122\2c 167\2c 209\2c \.3\)\]:hover{--tw-drop-shadow:drop-shadow(0 0px 10px rgba(122,167,209,.3));filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.hover\:drop-shadow-\[0_0px_4px_rgba\(122\2c 167\2c 209\2c \.3\)\]:hover{--tw-drop-shadow:drop-shadow(0 0px 4px rgba(122,167,209,.3));filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus\:border-\[\#7AA7D1\]:focus{--tw-border-opacity:1;border-color:rgb(122 167 209 / var(--tw-border-opacity))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}.peer:checked~.peer-checked\:bg-slate-200{--tw-bg-opacity:1;background-color:rgb(226 232 240 / var(--tw-bg-opacity))}:is(.dark .dark\:border-slate-700){--tw-border-opacity:1;border-color:rgb(51 65 85 / var(--tw-border-opacity))}:is(.dark .dark\:bg-slate-200){--tw-bg-opacity:1;background-color:rgb(226 232 240 / var(--tw-bg-opacity))}:is(.dark .dark\:bg-slate-700){--tw-bg-opacity:1;background-color:rgb(51 65 85 / var(--tw-bg-opacity))}:is(.dark .dark\:bg-slate-800){--tw-bg-opacity:1;background-color:rgb(30 41 59 / var(--tw-bg-opacity))}:is(.dark .dark\:bg-slate-900){--tw-bg-opacity:1;background-color:rgb(15 23 42 / var(--tw-bg-opacity))}:is(.dark .dark\:text-red-400){--tw-text-opacity:1;color:rgb(248 113 113 / var(--tw-text-opacity))}:is(.dark .dark\:text-slate-200){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}:is(.dark .dark\:text-slate-400){--tw-text-opacity:1;color:rgb(148 163 184 / var(--tw-text-opacity))}:is(.dark .dark\:text-slate-900){--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}:is(.dark .dark\:shadow-slate-700){--tw-shadow-color:#334155;--tw-shadow:var(--tw-shadow-colored)}:is(.dark .dark\:ring-offset-slate-900){--tw-ring-offset-color:#0f172a}:is(.dark .dark\:hover\:bg-slate-200\/90:hover){background-color:rgb(226 232 240 / .9)}:is(.dark .dark\:hover\:bg-slate-700:hover){--tw-bg-opacity:1;background-color:rgb(51 65 85 / var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-slate-800\/90:hover){background-color:rgb(30 41 59 / .9)}:is(.dark .dark\:hover\:text-blue-500:hover){--tw-text-opacity:1;color:rgb(59 130 246 / var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-slate-200:hover){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}:is(.dark .hover\:dark\:text-slate-300):hover{--tw-text-opacity:1;color:rgb(203 213 225 / var(--tw-text-opacity))}:is(.dark .peer:checked ~ .dark\:peer-checked\:bg-slate-700){--tw-bg-opacity:1;background-color:rgb(51 65 85 / var(--tw-bg-opacity))}@media (min-width:640px){.sm\:text-4xl{font-size:2.25rem;line-height:2.5rem}}@media (min-width:1024px){.lg\:mx-auto{margin-left:auto;margin-right:auto}.lg\:text-4xl{font-size:2.25rem;line-height:2.5rem}.lg\:text-5xl{font-size:3rem;line-height:1}.lg\:text-6xl{font-size:3.75rem;line-height:1}} +*,::after,::before{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}::after,::before{--tw-content:''}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}a{--tw-text-opacity:1;color:rgb(71 85 105 / var(--tw-text-opacity));text-underline-offset:2px;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4,0,0.2,1);transition-duration:.3s}a:hover{--tw-text-opacity:1;color:rgb(59 130 246 / var(--tw-text-opacity));text-decoration-line:underline}:is(.dark a){--tw-text-opacity:1;color:rgb(148 163 184 / var(--tw-text-opacity))}:is(.dark a:hover){--tw-text-opacity:1;color:rgb(59 130 246 / var(--tw-text-opacity))}h1{scroll-margin:5rem;font-size:2.25rem;line-height:2.5rem;font-weight:800;letter-spacing:-.025em;--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}:is(.dark h1){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}@media (min-width:1024px){h1{font-size:3rem;line-height:1}}h2{scroll-margin:5rem;border-bottom-width:1px;padding-bottom:.5rem;font-size:1.875rem;line-height:2.25rem;font-weight:600;letter-spacing:-.025em;--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}h2:first-child{margin-top:0}:is(.dark h2){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}h3{scroll-margin:5rem;font-size:1.5rem;line-height:2rem;font-weight:600;letter-spacing:-.025em;--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}:is(.dark h3){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}h4,h5,h6{scroll-margin:5rem;font-size:1.25rem;line-height:1.75rem;font-weight:600;letter-spacing:-.025em;--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}:is(.dark h4),:is(.dark h5),:is(.dark h6){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}p{line-height:1.75rem;--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}:is(.dark p){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}p:not(:first-child){margin-top:1.5rem}code,kbd,pre{position:relative;white-space:break-spaces;border-radius:.25rem;--tw-bg-opacity:1;background-color:rgb(226 232 240 / var(--tw-bg-opacity));padding-top:.2rem;padding-bottom:.2rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:.875rem;line-height:1.25rem;font-weight:600}:is(.dark code),:is(.dark kbd),:is(.dark pre){--tw-bg-opacity:1;background-color:rgb(30 41 59 / var(--tw-bg-opacity))}blockquote{margin-top:1.5rem;border-left-width:2px;padding-left:1.5rem;font-style:italic}ul{margin-top:1.5rem;margin-bottom:1.5rem;margin-left:1.5rem;list-style-type:disc;--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}:is(.dark ul){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}ul>li{margin-top:.5rem}ol{margin-top:1.5rem;margin-bottom:1.5rem;margin-left:1.5rem;list-style-type:decimal;--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}:is(.dark ol){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}ol>li{margin-top:.5rem}dl{margin-top:1.5rem;margin-bottom:1.5rem;font-weight:700;--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}:is(.dark dl){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}dl>dd{margin-left:1.5rem;font-weight:400}dl>dt{margin-top:.75rem}li{--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}:is(.dark li){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}table{width:100%;caption-side:bottom;font-size:.875rem;line-height:1.25rem}thead tr{border-bottom-width:1px}tbody tr:last-child{border-width:0}tfoot{border-top-width:1px;--tw-border-opacity:1;border-color:rgb(148 163 184 / var(--tw-border-opacity));background-color:rgb(51 65 85 / .5);font-weight:500}:is(.dark tfoot){--tw-border-opacity:1;border-color:rgb(51 65 85 / var(--tw-border-opacity));background-color:rgb(226 232 240 / .5)}tfoot:last-child>tr{border-bottom-width:0}tr{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(148 163 184 / var(--tw-border-opacity));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4,0,0.2,1);transition-duration:150ms}tr:hover{background-color:rgb(226 232 240 / .5)}tr[data-state=selected]{--tw-bg-opacity:1;background-color:rgb(51 65 85 / var(--tw-bg-opacity))}:is(.dark tr){--tw-border-opacity:1;border-color:rgb(51 65 85 / var(--tw-border-opacity))}:is(.dark tr:hover){background-color:rgb(51 65 85 / .5)}:is(.dark tr[data-state=selected]){--tw-bg-opacity:1;background-color:rgb(226 232 240 / var(--tw-bg-opacity))}th{height:3rem;padding-left:1rem;padding-right:1rem;text-align:left;vertical-align:middle;font-weight:500;--tw-text-opacity:1;color:rgb(71 85 105 / var(--tw-text-opacity))}:is(.dark th){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}th:has([role=checkbox]){padding-right:0}td{padding:1rem;vertical-align:middle}td:has([role=checkbox]){padding-right:0}caption{margin-top:1rem;font-size:.875rem;line-height:1.25rem;--tw-text-opacity:1;color:rgb(71 85 105 / var(--tw-text-opacity))}:is(.dark caption){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}img{margin-left:auto;margin-right:auto;height:auto;width:auto;max-width:100%;border-radius:.375rem;-o-object-fit:cover;object-fit:cover;--tw-shadow:0 4px 6px -1px rgb(0 0 0 / 0.1),0 2px 4px -2px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}:is(.dark img){--tw-shadow-color:#334155;--tw-shadow:var(--tw-shadow-colored)}figcaption{margin-top:.5rem;font-size:.875rem;line-height:1.25rem;--tw-text-opacity:1;color:rgb(71 85 105 / var(--tw-text-opacity))}:is(.dark figcaption){--tw-text-opacity:1;color:rgb(148 163 184 / var(--tw-text-opacity))}hr{height:1px;width:100%;flex-shrink:0;--tw-bg-opacity:1;background-color:rgb(226 232 240 / var(--tw-bg-opacity))}:is(.dark hr){--tw-bg-opacity:1;background-color:rgb(51 65 85 / var(--tw-bg-opacity))}*,::after,::before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.collapse{visibility:collapse}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0px}.inset-x-0{left:0;right:0}.inset-y-0{top:0;bottom:0}.bottom-0{bottom:0}.right-0{right:0}.top-0{top:0}.z-10{z-index:10}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-auto{margin-top:auto;margin-bottom:auto}.-ml-2{margin-left:-.5rem}.-mt-12{margin-top:-3rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-48{margin-top:12rem}.mt-5{margin-top:1.25rem}.block{display:block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-12{height:3rem}.h-4{height:1rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-\[1px\]{height:1px}.h-\[250px\]{height:250px}.h-\[calc\(100vh-14\.5rem\)\]{height:calc(100vh - 14.5rem)}.h-auto{height:auto}.h-screen{height:100vh}.max-h-14{max-height:3.5rem}.min-h-\[200px\]{min-height:200px}.min-h-full{min-height:100%}.w-10{width:2.5rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-52{width:13rem}.w-6{width:1.5rem}.w-auto{width:auto}.w-full{width:100%}.w-screen{width:100vw}.max-w-3xl{max-width:48rem}.max-w-full{max-width:100%}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize{resize:both}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.flex-wrap-reverse{flex-wrap:wrap-reverse}.place-items-center{place-items:center}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-items-center{justify-items:center}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-x-10{-moz-column-gap:2.5rem;column-gap:2.5rem}.gap-y-4{row-gap:1rem}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.place-self-end{place-self:end}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.overflow-x-hidden{overflow-x:hidden}.whitespace-nowrap{white-space:nowrap}.whitespace-break-spaces{white-space:break-spaces}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-b-2{border-bottom-width:2px}.border-t-2{border-top-width:2px}.border-slate-400{--tw-border-opacity:1;border-color:rgb(148 163 184 / var(--tw-border-opacity))}.bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249 / var(--tw-bg-opacity))}.bg-slate-200{--tw-bg-opacity:1;background-color:rgb(226 232 240 / var(--tw-bg-opacity))}.bg-slate-400{--tw-bg-opacity:1;background-color:rgb(148 163 184 / var(--tw-bg-opacity))}.bg-slate-500\/50{background-color:rgb(100 116 139 / .5)}.bg-slate-800{--tw-bg-opacity:1;background-color:rgb(30 41 59 / var(--tw-bg-opacity))}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.object-cover{-o-object-fit:cover;object-fit:cover}.p-2{padding:.5rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.px-8{padding-left:2rem;padding-right:2rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pl-0{padding-left:0}.pl-2{padding-left:.5rem}.pr-2{padding-right:.5rem}.pr-3{padding-right:.75rem}.pt-10{padding-top:2.5rem}.pt-4{padding-top:1rem}.pt-5{padding-top:1.25rem}.text-left{text-align:left}.text-center{text-align:center}.align-middle{vertical-align:middle}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}.font-sans{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"}.font-serif{font-family:ui-serif,Georgia,Cambria,"Times New Roman",Times,serif}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-5xl{font-size:3rem;line-height:1}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-extrabold{font-weight:800}.font-medium{font-weight:500}.font-semibold{font-weight:600}.leading-6{line-height:1.5rem}.leading-8{line-height:2rem}.leading-none{line-height:1}.tracking-tight{letter-spacing:-.025em}.text-\[\#7AA7D1\]{--tw-text-opacity:1;color:rgb(122 167 209 / var(--tw-text-opacity))}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68 / var(--tw-text-opacity))}.text-slate-200{--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184 / var(--tw-text-opacity))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105 / var(--tw-text-opacity))}.text-slate-900{--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}.underline-offset-2{text-underline-offset:2px}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.shadow-md{--tw-shadow:0 4px 6px -1px rgb(0 0 0 / 0.1),0 2px 4px -2px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgb(0 0 0 / 0.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgb(0 0 0 / 0.1),0 8px 10px -6px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-slate-900\/10{--tw-ring-color:rgb(15 23 42 / 0.1)}.ring-offset-2{--tw-ring-offset-width:2px}.ring-offset-white{--tw-ring-offset-color:#fff}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(0.4,0,0.2,1);transition-duration:150ms}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4,0,0.2,1);transition-duration:150ms}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(0.4,0,0.2,1);transition-duration:150ms}.duration-300{transition-duration:.3s}.first-of-type\:rounded-t-md:first-of-type{border-top-left-radius:.375rem;border-top-right-radius:.375rem}.last-of-type\:rounded-b-md:last-of-type{border-bottom-right-radius:.375rem;border-bottom-left-radius:.375rem}.hover\:bg-slate-200:hover{--tw-bg-opacity:1;background-color:rgb(226 232 240 / var(--tw-bg-opacity))}.hover\:bg-slate-200\/90:hover{background-color:rgb(226 232 240 / .9)}.hover\:bg-slate-800\/90:hover{background-color:rgb(30 41 59 / .9)}.hover\:text-blue-500:hover{--tw-text-opacity:1;color:rgb(59 130 246 / var(--tw-text-opacity))}.hover\:text-slate-400:hover{--tw-text-opacity:1;color:rgb(148 163 184 / var(--tw-text-opacity))}.hover\:text-slate-500:hover{--tw-text-opacity:1;color:rgb(100 116 139 / var(--tw-text-opacity))}.hover\:underline:hover{text-decoration-line:underline}.hover\:no-underline:hover{text-decoration-line:none}.hover\:ring-slate-300:hover{--tw-ring-opacity:1;--tw-ring-color:rgb(203 213 225 / var(--tw-ring-opacity))}.hover\:drop-shadow-\[0_0px_10px_rgba\(122\2c 167\2c 209\2c \.3\)\]:hover{--tw-drop-shadow:drop-shadow(0 0px 10px rgba(122,167,209,.3));filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.hover\:drop-shadow-\[0_0px_4px_rgba\(122\2c 167\2c 209\2c \.3\)\]:hover{--tw-drop-shadow:drop-shadow(0 0px 4px rgba(122,167,209,.3));filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus\:border-\[\#7AA7D1\]:focus{--tw-border-opacity:1;border-color:rgb(122 167 209 / var(--tw-border-opacity))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}.peer:checked~.peer-checked\:bg-slate-200{--tw-bg-opacity:1;background-color:rgb(226 232 240 / var(--tw-bg-opacity))}:is(.dark .dark\:border-slate-700){--tw-border-opacity:1;border-color:rgb(51 65 85 / var(--tw-border-opacity))}:is(.dark .dark\:bg-slate-200){--tw-bg-opacity:1;background-color:rgb(226 232 240 / var(--tw-bg-opacity))}:is(.dark .dark\:bg-slate-700){--tw-bg-opacity:1;background-color:rgb(51 65 85 / var(--tw-bg-opacity))}:is(.dark .dark\:bg-slate-800){--tw-bg-opacity:1;background-color:rgb(30 41 59 / var(--tw-bg-opacity))}:is(.dark .dark\:bg-slate-900){--tw-bg-opacity:1;background-color:rgb(15 23 42 / var(--tw-bg-opacity))}:is(.dark .dark\:text-red-400){--tw-text-opacity:1;color:rgb(248 113 113 / var(--tw-text-opacity))}:is(.dark .dark\:text-slate-200){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}:is(.dark .dark\:text-slate-400){--tw-text-opacity:1;color:rgb(148 163 184 / var(--tw-text-opacity))}:is(.dark .dark\:text-slate-900){--tw-text-opacity:1;color:rgb(15 23 42 / var(--tw-text-opacity))}:is(.dark .dark\:shadow-slate-700){--tw-shadow-color:#334155;--tw-shadow:var(--tw-shadow-colored)}:is(.dark .dark\:ring-offset-slate-900){--tw-ring-offset-color:#0f172a}:is(.dark .dark\:hover\:bg-slate-200\/90:hover){background-color:rgb(226 232 240 / .9)}:is(.dark .dark\:hover\:bg-slate-500:hover){--tw-bg-opacity:1;background-color:rgb(100 116 139 / var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-slate-700:hover){--tw-bg-opacity:1;background-color:rgb(51 65 85 / var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-slate-800\/90:hover){background-color:rgb(30 41 59 / .9)}:is(.dark .dark\:hover\:text-blue-500:hover){--tw-text-opacity:1;color:rgb(59 130 246 / var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-slate-200:hover){--tw-text-opacity:1;color:rgb(226 232 240 / var(--tw-text-opacity))}:is(.dark .hover\:dark\:text-slate-300):hover{--tw-text-opacity:1;color:rgb(203 213 225 / var(--tw-text-opacity))}:is(.dark .peer:checked ~ .dark\:peer-checked\:bg-slate-700){--tw-bg-opacity:1;background-color:rgb(51 65 85 / var(--tw-bg-opacity))}@media (min-width:640px){.sm\:my-8{margin-top:2rem;margin-bottom:2rem}.sm\:ml-4{margin-left:1rem}.sm\:mt-0{margin-top:0}.sm\:flex{display:flex}.sm\:w-full{width:100%}.sm\:max-w-lg{max-width:32rem}.sm\:flex-row-reverse{flex-direction:row-reverse}.sm\:p-0{padding:0}.sm\:p-6{padding:1.5rem}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:pb-4{padding-bottom:1rem}.sm\:text-4xl{font-size:2.25rem;line-height:2.5rem}}@media (min-width:1024px){.lg\:mx-auto{margin-left:auto;margin-right:auto}.lg\:text-4xl{font-size:2.25rem;line-height:2.5rem}.lg\:text-5xl{font-size:3rem;line-height:1}.lg\:text-6xl{font-size:3.75rem;line-height:1}} From aabc34bac774e34de5ffc96ce5724b6cc9c9aaf7 Mon Sep 17 00:00:00 2001 From: joncrangle <94425204+joncrangle@users.noreply.github.com> Date: Fri, 8 Dec 2023 00:51:33 -0500 Subject: [PATCH 02/23] Delete handlers/api_modifiers_structdef.gen.go --- handlers/api_modifiers_structdef.gen.go | 558 ------------------------ 1 file changed, 558 deletions(-) delete mode 100644 handlers/api_modifiers_structdef.gen.go diff --git a/handlers/api_modifiers_structdef.gen.go b/handlers/api_modifiers_structdef.gen.go deleted file mode 100644 index b6ae548..0000000 --- a/handlers/api_modifiers_structdef.gen.go +++ /dev/null @@ -1,558 +0,0 @@ - -package handlers -// DO NOT EDIT THIS FILE. It is automatically generated by ladder/handlers/api_modifiers_codegen/api_modifiers_codegen.go -// The purpose of this is to produce an API reponse listing all the available modifier, their parameters and usage instructions. -// for use in proxychains. - -import ( - "ladder/proxychain/responsemodifiers/api" -) - -type ModifiersAPIResponse struct { - Success bool `json:"success"` - Error api.ErrorDetails `json:"error"` - Result Modifiers `json:"result"` -} - -type Modifiers struct { - RequestModifiers []Modifier `json:"requestmodifiers"` - ResponseModifiers []Modifier `json:"responsemodifiers"` -} - -type Modifier struct { - Name string `json:"name"` - Description string `json:"description"` - CodeEditLink string `json:"code_edit_link"` - Params []Param `json:"params"` -} - -type Param struct { - Name string `json:"name"` - Type string `json:"type"` -} - -var AllMods Modifiers = Modifiers{ - RequestModifiers: []Modifier{ -{ - Name: "AddCacheBusterQuery", - Description: "AddCacheBusterQuery modifies query params to add a random parameter key In order to get the upstream network stack to serve a fresh copy of the page.", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/add_cache_buster_query.go", - Params: []Param{ - - }, -}, -{ - Name: "ForwardRequestHeaders", - Description: "ForwardRequestHeaders forwards the requests headers sent from the client to the upstream server", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/forward_request_headers.go", - Params: []Param{ - - }, -}, -{ - Name: "MasqueradeAsGoogleBot", - Description: "MasqueradeAsGoogleBot modifies user agent and x-forwarded for to appear to be a Google Bot", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", - Params: []Param{ - - }, -}, -{ - Name: "MasqueradeAsBingBot", - Description: "MasqueradeAsBingBot modifies user agent and x-forwarded for to appear to be a Bing Bot", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", - Params: []Param{ - - }, -}, -{ - Name: "MasqueradeAsWaybackMachineBot", - Description: "MasqueradeAsWaybackMachineBot modifies user agent and x-forwarded for to appear to be a archive.org (wayback machine) Bot", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", - Params: []Param{ - - }, -}, -{ - Name: "MasqueradeAsFacebookBot", - Description: "MasqueradeAsFacebookBot modifies user agent and x-forwarded for to appear to be a Facebook Bot (link previews?)", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", - Params: []Param{ - - }, -}, -{ - Name: "MasqueradeAsYandexBot", - Description: "MasqueradeAsYandexBot modifies user agent and x-forwarded for to appear to be a Yandex Spider Bot", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", - Params: []Param{ - - }, -}, -{ - Name: "MasqueradeAsBaiduBot", - Description: "MasqueradeAsBaiduBot modifies user agent and x-forwarded for to appear to be a Baidu Spider Bot", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", - Params: []Param{ - - }, -}, -{ - Name: "MasqueradeAsDuckDuckBot", - Description: "MasqueradeAsDuckDuckBot modifies user agent and x-forwarded for to appear to be a DuckDuckGo Bot", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", - Params: []Param{ - - }, -}, -{ - Name: "MasqueradeAsYahooBot", - Description: "MasqueradeAsYahooBot modifies user agent and x-forwarded for to appear to be a Yahoo Bot", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", - Params: []Param{ - - }, -}, -{ - Name: "ModifyDomainWithRegex", - Description: "", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_domain_with_regex.go", - Params: []Param{ - {Name: "matchRegex", Type: "string"}, - {Name: "replacement", Type: "string"}, - }, -}, -{ - Name: "SetOutgoingCookie", - Description: "SetOutgoingCookie modifes a specific cookie name by modifying the request cookie headers going to the upstream server. If the cookie name does not already exist, it is created.", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_outgoing_cookies.go", - Params: []Param{ - {Name: "name", Type: "string"}, - {Name: "val", Type: "string"}, - }, -}, -{ - Name: "SetOutgoingCookies", - Description: "SetOutgoingCookies modifies a client request's cookie header to a raw Cookie string, overwriting existing cookies", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_outgoing_cookies.go", - Params: []Param{ - {Name: "cookies", Type: "string"}, - }, -}, -{ - Name: "DeleteOutgoingCookie", - Description: "DeleteOutgoingCookie modifies the http request's cookies header to delete a specific request cookie going to the upstream server. If the cookie does not exist, it does not do anything.", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_outgoing_cookies.go", - Params: []Param{ - {Name: "name", Type: "string"}, - }, -}, -{ - Name: "DeleteOutgoingCookies", - Description: "DeleteOutgoingCookies removes the cookie header entirely, preventing any cookies from reaching the upstream server.", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_outgoing_cookies.go", - Params: []Param{ - - }, -}, -{ - Name: "DeleteOutgoingCookiesExcept", - 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", - Params: []Param{ - {Name: "whitelist", Type: "&{Ellipsis:12348 Elt:string}"}, - }, -}, -{ - Name: "ModifyPathWithRegex", - Description: "", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_path_with_regex.go", - Params: []Param{ - {Name: "matchRegex", Type: "string"}, - {Name: "replacement", Type: "string"}, - }, -}, -{ - Name: "ModifyQueryParams", - Description: "ModifyQueryParams replaces query parameter values in URL's query params in a ProxyChain's URL. If the query param key doesn't exist, it is created.", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_query_params.go", - Params: []Param{ - {Name: "key", Type: "string"}, - {Name: "value", Type: "string"}, - }, -}, -{ - Name: "SetRequestHeader", - Description: "SetRequestHeader modifies a specific outgoing header This is the header that the upstream server will see.", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_request_headers.go", - Params: []Param{ - {Name: "name", Type: "string"}, - {Name: "val", Type: "string"}, - }, -}, -{ - Name: "DeleteRequestHeader", - Description: "DeleteRequestHeader modifies a specific outgoing header This is the header that the upstream server will see.", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_request_headers.go", - Params: []Param{ - {Name: "name", Type: "string"}, - }, -}, -{ - Name: "RequestArchiveIs", - Description: "RequestArchiveIs modifies a ProxyChain's URL to request an archived version from archive.is", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/request_archive_is.go", - Params: []Param{ - - }, -}, -{ - Name: "RequestGoogleCache", - Description: "RequestGoogleCache modifies a ProxyChain's URL to request its Google Cache version.", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/request_google_cache.go", - Params: []Param{ - - }, -}, -{ - Name: "RequestWaybackMachine", - Description: "RequestWaybackMachine modifies a ProxyChain's URL to request the wayback machine (archive.org) version.", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/request_wayback_machine.go", - Params: []Param{ - - }, -}, -{ - Name: "ResolveWithGoogleDoH", - Description: "ResolveWithGoogleDoH modifies a ProxyChain's client to make the request by resolving the URL using Google's DNS over HTTPs service", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/resolve_with_google_doh.go", - Params: []Param{ - - }, -}, -{ - Name: "SpoofOrigin", - Description: "SpoofOrigin modifies the origin header if the upstream server returns a Vary header it means you might get a different response if you change this", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_origin.go", - Params: []Param{ - {Name: "url", Type: "string"}, - }, -}, -{ - Name: "HideOrigin", - Description: "HideOrigin modifies the origin header so that it is the original origin, not the proxy", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_origin.go", - Params: []Param{ - - }, -}, -{ - Name: "SpoofReferrer", - Description: "SpoofReferrer modifies the referrer header. It is useful if the page can be accessed from a search engine or social media site, but not by browsing the website itself. if url is \"\", then the referrer header is removed.", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer.go", - Params: []Param{ - {Name: "url", Type: "string"}, - }, -}, -{ - Name: "HideReferrer", - Description: "HideReferrer modifies the referrer header so that it is the original referrer, not the proxy", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer.go", - Params: []Param{ - - }, -}, -{ - Name: "SpoofReferrerFromBaiduSearch", - Description: "SpoofReferrerFromBaiduSearch modifies the referrer header pretending to be from a BaiduSearch", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_baidu_post.go", - Params: []Param{ - - }, -}, -{ - Name: "SpoofReferrerFromBingSearch", - Description: "SpoofReferrerFromBingSearch modifies the referrer header pretending to be from a bing search site", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_bing_search.go", - Params: []Param{ - - }, -}, -{ - Name: "SpoofReferrerFromGoogleSearch", - Description: "SpoofReferrerFromGoogleSearch modifies the referrer header pretending to be from a google search site", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_google_search.go", - Params: []Param{ - - }, -}, -{ - Name: "SpoofReferrerFromLinkedInPost", - Description: "SpoofReferrerFromLinkedInPost modifies the referrer header pretending to be from a linkedin post", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_linkedin_post.go", - Params: []Param{ - - }, -}, -{ - Name: "SpoofReferrerFromNaverSearch", - Description: "SpoofReferrerFromNaverSearch modifies the referrer header pretending to be from a Naver search (popular in South Korea)", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_naver_post.go", - Params: []Param{ - - }, -}, -{ - Name: "SpoofReferrerFromPinterestPost", - Description: "SpoofReferrerFromPinterestPost modifies the referrer header pretending to be from a pinterest post", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_pinterest_post.go", - Params: []Param{ - - }, -}, -{ - Name: "SpoofReferrerFromQQPost", - Description: "SpoofReferrerFromQQPost modifies the referrer header pretending to be from a QQ post (popular social media in China)", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_qq_post.go", - Params: []Param{ - - }, -}, -{ - Name: "SpoofReferrerFromRedditPost", - Description: "SpoofReferrerFromRedditPost modifies the referrer header pretending to be from a reddit post", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_reddit_post.go", - Params: []Param{ - - }, -}, -{ - Name: "SpoofReferrerFromTumblrPost", - Description: "SpoofReferrerFromTumblrPost modifies the referrer header pretending to be from a tumblr post", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_tumblr_post.go", - Params: []Param{ - - }, -}, -{ - Name: "SpoofReferrerFromTwitterPost", - Description: "SpoofReferrerFromTwitterPost modifies the referrer header pretending to be from a twitter post", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_twitter_post.go", - Params: []Param{ - - }, -}, -{ - Name: "SpoofReferrerFromVkontaktePost", - Description: "SpoofReferrerFromVkontaktePost modifies the referrer header pretending to be from a vkontakte post (popular in Russia)", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_vkontake_post.go", - Params: []Param{ - - }, -}, -{ - Name: "SpoofReferrerFromWeiboPost", - Description: "SpoofReferrerFromWeiboPost modifies the referrer header pretending to be from a Weibo post (popular in China)", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_weibo_post.go", - Params: []Param{ - - }, -}, -{ - Name: "SpoofUserAgent", - Description: "SpoofUserAgent modifies the user agent", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_user_agent.go", - Params: []Param{ - {Name: "ua", Type: "string"}, - }, -}, -{ - Name: "SpoofXForwardedFor", - Description: "SpoofXForwardedFor modifies the X-Forwarded-For header in some cases, a forward proxy may interpret this as the source IP", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_x_forwarded_for.go", - Params: []Param{ - {Name: "ip", Type: "string"}, - }, -}, - }, - ResponseModifiers: []Modifier{ -{ - Name: "APIContent", - Description: "APIContent creates an JSON representation of the article and returns it as an API response.", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/api_content.go", - Params: []Param{ - - }, -}, -{ - Name: "BlockElementRemoval", - Description: "BlockElementRemoval prevents paywall javascript from removing a particular element by detecting the removal, then immediately reinserting it. This is useful when a page will return a \"fake\" 404, after flashing the content briefly. If the /outline/ API works, but the regular API doesn't, try this modifier.", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/block_element_removal.go", - Params: []Param{ - {Name: "cssSelector", Type: "string"}, - }, -}, -{ - Name: "BlockThirdPartyScripts", - Description: "BlockThirdPartyScripts rewrites HTML and injects JS to block all third party JS from loading.", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/block_third_party_scripts.go", - Params: []Param{ - - }, -}, -{ - Name: "BypassCORS", - Description: "BypassCORS modifies response headers to prevent the browser from enforcing any CORS restrictions. This should run at the end of the chain.", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/bypass_cors.go", - Params: []Param{ - - }, -}, -{ - Name: "BypassContentSecurityPolicy", - Description: "BypassContentSecurityPolicy modifies response headers to prevent the browser from enforcing any CSP restrictions. This should run at the end of the chain.", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/bypass_csp.go", - Params: []Param{ - - }, -}, -{ - Name: "SetContentSecurityPolicy", - Description: "SetContentSecurityPolicy modifies response headers to a specific CSP", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/bypass_csp.go", - Params: []Param{ - {Name: "csp", Type: "string"}, - }, -}, -{ - Name: "DeleteLocalStorageData", - Description: "DeleteLocalStorageData deletes localstorage cookies. If the page works once in a fresh incognito window, but fails for subsequent loads, try this response modifier alongside DeleteSessionStorageData and DeleteIncomingCookies", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/delete_localstorage_data.go", - Params: []Param{ - - }, -}, -{ - Name: "DeleteSessionStorageData", - Description: "DeleteSessionStorageData deletes localstorage cookies. If the page works once in a fresh incognito window, but fails for subsequent loads, try this response modifier alongside DeleteLocalStorageData and DeleteIncomingCookies", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/delete_sessionstorage_data.go", - Params: []Param{ - - }, -}, -{ - Name: "ForwardResponseHeaders", - Description: "ForwardResponseHeaders forwards the response headers from the upstream server to the client", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/forward_response_headers.go", - Params: []Param{ - - }, -}, -{ - Name: "GenerateReadableOutline", - Description: "GenerateReadableOutline creates an reader-friendly distilled representation of the article. This is a reliable way of bypassing soft-paywalled articles, where the content is hidden, but still present in the DOM.", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/generate_readable_outline.go", - Params: []Param{ - - }, -}, -{ - Name: "InjectScriptBeforeDOMContentLoaded", - Description: "InjectScriptBeforeDOMContentLoaded modifies HTTP responses to inject a JS before DOM Content is loaded (script tag in head)", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/inject_script.go", - Params: []Param{ - {Name: "js", Type: "string"}, - }, -}, -{ - Name: "InjectScriptAfterDOMContentLoaded", - Description: "InjectScriptAfterDOMContentLoaded modifies HTTP responses to inject a JS after DOM Content is loaded (script tag in head)", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/inject_script.go", - Params: []Param{ - {Name: "js", Type: "string"}, - }, -}, -{ - Name: "InjectScriptAfterDOMIdle", - Description: "InjectScriptAfterDOMIdle modifies HTTP responses to inject a JS after the DOM is idle (ie: js framework loaded)", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/inject_script.go", - Params: []Param{ - {Name: "js", Type: "string"}, - }, -}, -{ - Name: "DeleteIncomingCookies", - 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", - Params: []Param{ - {Name: "_", Type: "&{Ellipsis:16319 Elt:string}"}, - }, -}, -{ - Name: "DeleteIncomingCookiesExcept", - 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", - Params: []Param{ - {Name: "whitelist", Type: "&{Ellipsis:16864 Elt:string}"}, - }, -}, -{ - Name: "SetIncomingCookies", - Description: "SetIncomingCookies adds a raw cookie string being sent from the proxy server down to the client", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/modify_incoming_cookies.go", - Params: []Param{ - {Name: "cookies", Type: "string"}, - }, -}, -{ - Name: "SetIncomingCookie", - Description: "SetIncomingCookie modifies a specific cookie in the response from the proxy server to the client.", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/modify_incoming_cookies.go", - Params: []Param{ - {Name: "name", Type: "string"}, - {Name: "val", Type: "string"}, - }, -}, -{ - Name: "SetResponseHeader", - Description: "SetResponseHeader modifies response headers from the upstream server", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/modify_response_header.go", - Params: []Param{ - {Name: "key", Type: "string"}, - {Name: "value", Type: "string"}, - }, -}, -{ - Name: "DeleteResponseHeader", - Description: "DeleteResponseHeader removes response headers from the upstream server", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/modify_response_header.go", - Params: []Param{ - {Name: "key", Type: "string"}, - }, -}, -{ - Name: "PatchDynamicResourceURLs", - Description: "PatchDynamicResourceURLs patches the javascript runtime to rewrite URLs client-side. - This function is designed to allow the proxified page to still be browsible by routing all resource URLs through the proxy. - Native APIs capable of network requests will be hooked and the URLs arguments modified to point to the proxy instead. - fetch('/relative_path') -> fetch('/https://proxiedsite.com/relative_path') - Element.setAttribute('src', \"/assets/img.jpg\") -> Element.setAttribute('src', \"/https://proxiedsite.com/assets/img.jpg\") -> fetch('/https://proxiedsite.com/relative_path')", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/patch_dynamic_resource_urls.go", - Params: []Param{ - - }, -}, -{ - Name: "PatchTrackerScripts", - Description: "PatchTrackerScripts replaces any request to tracker scripts such as google analytics with a no-op stub that mocks the API structure of the original scripts they replace. Some pages depend on the existence of these structures for proper loading, so this may fix some broken elements. Surrogate script code borrowed from: DuckDuckGo Privacy Essentials browser extension for Firefox, Chrome. (Apache 2.0 license)", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/patch_tracker_scripts.go", - Params: []Param{ - - }, -}, -{ - Name: "RewriteHTMLResourceURLs", - Description: "RewriteHTMLResourceURLs modifies HTTP responses to rewrite URLs attributes in HTML content (such as src, href) - `` -> `` - This function is designed to allow the proxified page to still be browsible by routing all resource URLs through the proxy.", - CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/rewrite_http_resource_urls.go", - Params: []Param{ - - }, -}, - }, -} From 424893a5a36610b54049928f5da4672caacac93d Mon Sep 17 00:00:00 2001 From: joncrangle <94425204+joncrangle@users.noreply.github.com> Date: Fri, 8 Dec 2023 01:04:43 -0500 Subject: [PATCH 03/23] Undo delete -> don't merge --- handlers/api_modifiers_structdef.gen.go | 558 ++++++++++++++++++++++++ 1 file changed, 558 insertions(+) create mode 100644 handlers/api_modifiers_structdef.gen.go diff --git a/handlers/api_modifiers_structdef.gen.go b/handlers/api_modifiers_structdef.gen.go new file mode 100644 index 0000000..b6ae548 --- /dev/null +++ b/handlers/api_modifiers_structdef.gen.go @@ -0,0 +1,558 @@ + +package handlers +// DO NOT EDIT THIS FILE. It is automatically generated by ladder/handlers/api_modifiers_codegen/api_modifiers_codegen.go +// The purpose of this is to produce an API reponse listing all the available modifier, their parameters and usage instructions. +// for use in proxychains. + +import ( + "ladder/proxychain/responsemodifiers/api" +) + +type ModifiersAPIResponse struct { + Success bool `json:"success"` + Error api.ErrorDetails `json:"error"` + Result Modifiers `json:"result"` +} + +type Modifiers struct { + RequestModifiers []Modifier `json:"requestmodifiers"` + ResponseModifiers []Modifier `json:"responsemodifiers"` +} + +type Modifier struct { + Name string `json:"name"` + Description string `json:"description"` + CodeEditLink string `json:"code_edit_link"` + Params []Param `json:"params"` +} + +type Param struct { + Name string `json:"name"` + Type string `json:"type"` +} + +var AllMods Modifiers = Modifiers{ + RequestModifiers: []Modifier{ +{ + Name: "AddCacheBusterQuery", + Description: "AddCacheBusterQuery modifies query params to add a random parameter key In order to get the upstream network stack to serve a fresh copy of the page.", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/add_cache_buster_query.go", + Params: []Param{ + + }, +}, +{ + Name: "ForwardRequestHeaders", + Description: "ForwardRequestHeaders forwards the requests headers sent from the client to the upstream server", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/forward_request_headers.go", + Params: []Param{ + + }, +}, +{ + Name: "MasqueradeAsGoogleBot", + Description: "MasqueradeAsGoogleBot modifies user agent and x-forwarded for to appear to be a Google Bot", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", + Params: []Param{ + + }, +}, +{ + Name: "MasqueradeAsBingBot", + Description: "MasqueradeAsBingBot modifies user agent and x-forwarded for to appear to be a Bing Bot", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", + Params: []Param{ + + }, +}, +{ + Name: "MasqueradeAsWaybackMachineBot", + Description: "MasqueradeAsWaybackMachineBot modifies user agent and x-forwarded for to appear to be a archive.org (wayback machine) Bot", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", + Params: []Param{ + + }, +}, +{ + Name: "MasqueradeAsFacebookBot", + Description: "MasqueradeAsFacebookBot modifies user agent and x-forwarded for to appear to be a Facebook Bot (link previews?)", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", + Params: []Param{ + + }, +}, +{ + Name: "MasqueradeAsYandexBot", + Description: "MasqueradeAsYandexBot modifies user agent and x-forwarded for to appear to be a Yandex Spider Bot", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", + Params: []Param{ + + }, +}, +{ + Name: "MasqueradeAsBaiduBot", + Description: "MasqueradeAsBaiduBot modifies user agent and x-forwarded for to appear to be a Baidu Spider Bot", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", + Params: []Param{ + + }, +}, +{ + Name: "MasqueradeAsDuckDuckBot", + Description: "MasqueradeAsDuckDuckBot modifies user agent and x-forwarded for to appear to be a DuckDuckGo Bot", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", + Params: []Param{ + + }, +}, +{ + Name: "MasqueradeAsYahooBot", + Description: "MasqueradeAsYahooBot modifies user agent and x-forwarded for to appear to be a Yahoo Bot", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/masquerade_as_trusted_bot.go", + Params: []Param{ + + }, +}, +{ + Name: "ModifyDomainWithRegex", + Description: "", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_domain_with_regex.go", + Params: []Param{ + {Name: "matchRegex", Type: "string"}, + {Name: "replacement", Type: "string"}, + }, +}, +{ + Name: "SetOutgoingCookie", + Description: "SetOutgoingCookie modifes a specific cookie name by modifying the request cookie headers going to the upstream server. If the cookie name does not already exist, it is created.", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_outgoing_cookies.go", + Params: []Param{ + {Name: "name", Type: "string"}, + {Name: "val", Type: "string"}, + }, +}, +{ + Name: "SetOutgoingCookies", + Description: "SetOutgoingCookies modifies a client request's cookie header to a raw Cookie string, overwriting existing cookies", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_outgoing_cookies.go", + Params: []Param{ + {Name: "cookies", Type: "string"}, + }, +}, +{ + Name: "DeleteOutgoingCookie", + Description: "DeleteOutgoingCookie modifies the http request's cookies header to delete a specific request cookie going to the upstream server. If the cookie does not exist, it does not do anything.", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_outgoing_cookies.go", + Params: []Param{ + {Name: "name", Type: "string"}, + }, +}, +{ + Name: "DeleteOutgoingCookies", + Description: "DeleteOutgoingCookies removes the cookie header entirely, preventing any cookies from reaching the upstream server.", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_outgoing_cookies.go", + Params: []Param{ + + }, +}, +{ + Name: "DeleteOutgoingCookiesExcept", + 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", + Params: []Param{ + {Name: "whitelist", Type: "&{Ellipsis:12348 Elt:string}"}, + }, +}, +{ + Name: "ModifyPathWithRegex", + Description: "", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_path_with_regex.go", + Params: []Param{ + {Name: "matchRegex", Type: "string"}, + {Name: "replacement", Type: "string"}, + }, +}, +{ + Name: "ModifyQueryParams", + Description: "ModifyQueryParams replaces query parameter values in URL's query params in a ProxyChain's URL. If the query param key doesn't exist, it is created.", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_query_params.go", + Params: []Param{ + {Name: "key", Type: "string"}, + {Name: "value", Type: "string"}, + }, +}, +{ + Name: "SetRequestHeader", + Description: "SetRequestHeader modifies a specific outgoing header This is the header that the upstream server will see.", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_request_headers.go", + Params: []Param{ + {Name: "name", Type: "string"}, + {Name: "val", Type: "string"}, + }, +}, +{ + Name: "DeleteRequestHeader", + Description: "DeleteRequestHeader modifies a specific outgoing header This is the header that the upstream server will see.", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/modify_request_headers.go", + Params: []Param{ + {Name: "name", Type: "string"}, + }, +}, +{ + Name: "RequestArchiveIs", + Description: "RequestArchiveIs modifies a ProxyChain's URL to request an archived version from archive.is", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/request_archive_is.go", + Params: []Param{ + + }, +}, +{ + Name: "RequestGoogleCache", + Description: "RequestGoogleCache modifies a ProxyChain's URL to request its Google Cache version.", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/request_google_cache.go", + Params: []Param{ + + }, +}, +{ + Name: "RequestWaybackMachine", + Description: "RequestWaybackMachine modifies a ProxyChain's URL to request the wayback machine (archive.org) version.", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/request_wayback_machine.go", + Params: []Param{ + + }, +}, +{ + Name: "ResolveWithGoogleDoH", + Description: "ResolveWithGoogleDoH modifies a ProxyChain's client to make the request by resolving the URL using Google's DNS over HTTPs service", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/resolve_with_google_doh.go", + Params: []Param{ + + }, +}, +{ + Name: "SpoofOrigin", + Description: "SpoofOrigin modifies the origin header if the upstream server returns a Vary header it means you might get a different response if you change this", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_origin.go", + Params: []Param{ + {Name: "url", Type: "string"}, + }, +}, +{ + Name: "HideOrigin", + Description: "HideOrigin modifies the origin header so that it is the original origin, not the proxy", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_origin.go", + Params: []Param{ + + }, +}, +{ + Name: "SpoofReferrer", + Description: "SpoofReferrer modifies the referrer header. It is useful if the page can be accessed from a search engine or social media site, but not by browsing the website itself. if url is \"\", then the referrer header is removed.", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer.go", + Params: []Param{ + {Name: "url", Type: "string"}, + }, +}, +{ + Name: "HideReferrer", + Description: "HideReferrer modifies the referrer header so that it is the original referrer, not the proxy", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer.go", + Params: []Param{ + + }, +}, +{ + Name: "SpoofReferrerFromBaiduSearch", + Description: "SpoofReferrerFromBaiduSearch modifies the referrer header pretending to be from a BaiduSearch", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_baidu_post.go", + Params: []Param{ + + }, +}, +{ + Name: "SpoofReferrerFromBingSearch", + Description: "SpoofReferrerFromBingSearch modifies the referrer header pretending to be from a bing search site", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_bing_search.go", + Params: []Param{ + + }, +}, +{ + Name: "SpoofReferrerFromGoogleSearch", + Description: "SpoofReferrerFromGoogleSearch modifies the referrer header pretending to be from a google search site", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_google_search.go", + Params: []Param{ + + }, +}, +{ + Name: "SpoofReferrerFromLinkedInPost", + Description: "SpoofReferrerFromLinkedInPost modifies the referrer header pretending to be from a linkedin post", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_linkedin_post.go", + Params: []Param{ + + }, +}, +{ + Name: "SpoofReferrerFromNaverSearch", + Description: "SpoofReferrerFromNaverSearch modifies the referrer header pretending to be from a Naver search (popular in South Korea)", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_naver_post.go", + Params: []Param{ + + }, +}, +{ + Name: "SpoofReferrerFromPinterestPost", + Description: "SpoofReferrerFromPinterestPost modifies the referrer header pretending to be from a pinterest post", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_pinterest_post.go", + Params: []Param{ + + }, +}, +{ + Name: "SpoofReferrerFromQQPost", + Description: "SpoofReferrerFromQQPost modifies the referrer header pretending to be from a QQ post (popular social media in China)", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_qq_post.go", + Params: []Param{ + + }, +}, +{ + Name: "SpoofReferrerFromRedditPost", + Description: "SpoofReferrerFromRedditPost modifies the referrer header pretending to be from a reddit post", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_reddit_post.go", + Params: []Param{ + + }, +}, +{ + Name: "SpoofReferrerFromTumblrPost", + Description: "SpoofReferrerFromTumblrPost modifies the referrer header pretending to be from a tumblr post", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_tumblr_post.go", + Params: []Param{ + + }, +}, +{ + Name: "SpoofReferrerFromTwitterPost", + Description: "SpoofReferrerFromTwitterPost modifies the referrer header pretending to be from a twitter post", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_twitter_post.go", + Params: []Param{ + + }, +}, +{ + Name: "SpoofReferrerFromVkontaktePost", + Description: "SpoofReferrerFromVkontaktePost modifies the referrer header pretending to be from a vkontakte post (popular in Russia)", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_vkontake_post.go", + Params: []Param{ + + }, +}, +{ + Name: "SpoofReferrerFromWeiboPost", + Description: "SpoofReferrerFromWeiboPost modifies the referrer header pretending to be from a Weibo post (popular in China)", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_referrer_from_weibo_post.go", + Params: []Param{ + + }, +}, +{ + Name: "SpoofUserAgent", + Description: "SpoofUserAgent modifies the user agent", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_user_agent.go", + Params: []Param{ + {Name: "ua", Type: "string"}, + }, +}, +{ + Name: "SpoofXForwardedFor", + Description: "SpoofXForwardedFor modifies the X-Forwarded-For header in some cases, a forward proxy may interpret this as the source IP", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/requestmodifiers/spoof_x_forwarded_for.go", + Params: []Param{ + {Name: "ip", Type: "string"}, + }, +}, + }, + ResponseModifiers: []Modifier{ +{ + Name: "APIContent", + Description: "APIContent creates an JSON representation of the article and returns it as an API response.", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/api_content.go", + Params: []Param{ + + }, +}, +{ + Name: "BlockElementRemoval", + Description: "BlockElementRemoval prevents paywall javascript from removing a particular element by detecting the removal, then immediately reinserting it. This is useful when a page will return a \"fake\" 404, after flashing the content briefly. If the /outline/ API works, but the regular API doesn't, try this modifier.", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/block_element_removal.go", + Params: []Param{ + {Name: "cssSelector", Type: "string"}, + }, +}, +{ + Name: "BlockThirdPartyScripts", + Description: "BlockThirdPartyScripts rewrites HTML and injects JS to block all third party JS from loading.", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/block_third_party_scripts.go", + Params: []Param{ + + }, +}, +{ + Name: "BypassCORS", + Description: "BypassCORS modifies response headers to prevent the browser from enforcing any CORS restrictions. This should run at the end of the chain.", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/bypass_cors.go", + Params: []Param{ + + }, +}, +{ + Name: "BypassContentSecurityPolicy", + Description: "BypassContentSecurityPolicy modifies response headers to prevent the browser from enforcing any CSP restrictions. This should run at the end of the chain.", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/bypass_csp.go", + Params: []Param{ + + }, +}, +{ + Name: "SetContentSecurityPolicy", + Description: "SetContentSecurityPolicy modifies response headers to a specific CSP", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/bypass_csp.go", + Params: []Param{ + {Name: "csp", Type: "string"}, + }, +}, +{ + Name: "DeleteLocalStorageData", + Description: "DeleteLocalStorageData deletes localstorage cookies. If the page works once in a fresh incognito window, but fails for subsequent loads, try this response modifier alongside DeleteSessionStorageData and DeleteIncomingCookies", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/delete_localstorage_data.go", + Params: []Param{ + + }, +}, +{ + Name: "DeleteSessionStorageData", + Description: "DeleteSessionStorageData deletes localstorage cookies. If the page works once in a fresh incognito window, but fails for subsequent loads, try this response modifier alongside DeleteLocalStorageData and DeleteIncomingCookies", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/delete_sessionstorage_data.go", + Params: []Param{ + + }, +}, +{ + Name: "ForwardResponseHeaders", + Description: "ForwardResponseHeaders forwards the response headers from the upstream server to the client", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/forward_response_headers.go", + Params: []Param{ + + }, +}, +{ + Name: "GenerateReadableOutline", + Description: "GenerateReadableOutline creates an reader-friendly distilled representation of the article. This is a reliable way of bypassing soft-paywalled articles, where the content is hidden, but still present in the DOM.", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/generate_readable_outline.go", + Params: []Param{ + + }, +}, +{ + Name: "InjectScriptBeforeDOMContentLoaded", + Description: "InjectScriptBeforeDOMContentLoaded modifies HTTP responses to inject a JS before DOM Content is loaded (script tag in head)", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/inject_script.go", + Params: []Param{ + {Name: "js", Type: "string"}, + }, +}, +{ + Name: "InjectScriptAfterDOMContentLoaded", + Description: "InjectScriptAfterDOMContentLoaded modifies HTTP responses to inject a JS after DOM Content is loaded (script tag in head)", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/inject_script.go", + Params: []Param{ + {Name: "js", Type: "string"}, + }, +}, +{ + Name: "InjectScriptAfterDOMIdle", + Description: "InjectScriptAfterDOMIdle modifies HTTP responses to inject a JS after the DOM is idle (ie: js framework loaded)", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/inject_script.go", + Params: []Param{ + {Name: "js", Type: "string"}, + }, +}, +{ + Name: "DeleteIncomingCookies", + 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", + Params: []Param{ + {Name: "_", Type: "&{Ellipsis:16319 Elt:string}"}, + }, +}, +{ + Name: "DeleteIncomingCookiesExcept", + 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", + Params: []Param{ + {Name: "whitelist", Type: "&{Ellipsis:16864 Elt:string}"}, + }, +}, +{ + Name: "SetIncomingCookies", + Description: "SetIncomingCookies adds a raw cookie string being sent from the proxy server down to the client", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/modify_incoming_cookies.go", + Params: []Param{ + {Name: "cookies", Type: "string"}, + }, +}, +{ + Name: "SetIncomingCookie", + Description: "SetIncomingCookie modifies a specific cookie in the response from the proxy server to the client.", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/modify_incoming_cookies.go", + Params: []Param{ + {Name: "name", Type: "string"}, + {Name: "val", Type: "string"}, + }, +}, +{ + Name: "SetResponseHeader", + Description: "SetResponseHeader modifies response headers from the upstream server", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/modify_response_header.go", + Params: []Param{ + {Name: "key", Type: "string"}, + {Name: "value", Type: "string"}, + }, +}, +{ + Name: "DeleteResponseHeader", + Description: "DeleteResponseHeader removes response headers from the upstream server", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/modify_response_header.go", + Params: []Param{ + {Name: "key", Type: "string"}, + }, +}, +{ + Name: "PatchDynamicResourceURLs", + Description: "PatchDynamicResourceURLs patches the javascript runtime to rewrite URLs client-side. - This function is designed to allow the proxified page to still be browsible by routing all resource URLs through the proxy. - Native APIs capable of network requests will be hooked and the URLs arguments modified to point to the proxy instead. - fetch('/relative_path') -> fetch('/https://proxiedsite.com/relative_path') - Element.setAttribute('src', \"/assets/img.jpg\") -> Element.setAttribute('src', \"/https://proxiedsite.com/assets/img.jpg\") -> fetch('/https://proxiedsite.com/relative_path')", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/patch_dynamic_resource_urls.go", + Params: []Param{ + + }, +}, +{ + Name: "PatchTrackerScripts", + Description: "PatchTrackerScripts replaces any request to tracker scripts such as google analytics with a no-op stub that mocks the API structure of the original scripts they replace. Some pages depend on the existence of these structures for proper loading, so this may fix some broken elements. Surrogate script code borrowed from: DuckDuckGo Privacy Essentials browser extension for Firefox, Chrome. (Apache 2.0 license)", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/patch_tracker_scripts.go", + Params: []Param{ + + }, +}, +{ + Name: "RewriteHTMLResourceURLs", + Description: "RewriteHTMLResourceURLs modifies HTTP responses to rewrite URLs attributes in HTML content (such as src, href) - `` -> `` - This function is designed to allow the proxified page to still be browsible by routing all resource URLs through the proxy.", + CodeEditLink: "https://github.com/joncrangle/ladder.git/edit/proxy_v2/playground/proxychain/responsemodifiers/rewrite_http_resource_urls.go", + Params: []Param{ + + }, +}, + }, +} From b76a941164287f0b8e1310bfdd12083e275c7026 Mon Sep 17 00:00:00 2001 From: joncrangle <94425204+joncrangle@users.noreply.github.com> Date: Fri, 8 Dec 2023 01:35:48 -0500 Subject: [PATCH 04/23] Remove extra quote --- .github/workflows/build-css.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-css.yaml b/.github/workflows/build-css.yaml index 06e7771..175949b 100644 --- a/.github/workflows/build-css.yaml +++ b/.github/workflows/build-css.yaml @@ -39,7 +39,7 @@ jobs: git config --global user.name "Github action" git config --global user.email "username@users.noreply.github.com" git add handlers - git add "proxychain/responsemodifiers/vendor/ + git add proxychain/responsemodifiers/vendor/ git commit -m "Generated stylesheet" git push fi From b94e64a4d354ed530fe909dfd651a7e9d59d64ce Mon Sep 17 00:00:00 2001 From: joncrangle <94425204+joncrangle@users.noreply.github.com> Date: Fri, 8 Dec 2023 01:37:27 -0500 Subject: [PATCH 05/23] Empty array instead of empty object in null coalesce --- handlers/playground-script.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/handlers/playground-script.js b/handlers/playground-script.js index 3352243..a640b64 100644 --- a/handlers/playground-script.js +++ b/handlers/playground-script.js @@ -65,7 +65,7 @@ async function fetchPayload() { const response = await fetch("/api/modifiers"); const data = await response.json(); - Object.entries(data.result.requestmodifiers ?? {}).forEach(([_, value]) => { + Object.entries(data.result.requestmodifiers ?? []).forEach(([_, value]) => { addModifierToNinjaData( value.name, value.description, @@ -74,7 +74,7 @@ async function fetchPayload() { ); }); - Object.entries(data.result.responsemodifiers ?? {}).forEach( + Object.entries(data.result.responsemodifiers ?? []).forEach( ([_, value]) => { addModifierToNinjaData( value.name, From b3d799e36dae541048b9fc7da15fd646a315e393 Mon Sep 17 00:00:00 2001 From: Jonathan Crangle Date: Fri, 8 Dec 2023 12:03:22 -0500 Subject: [PATCH 06/23] a11y improvements --- handlers/form.html | 17 ++++++--------- handlers/playground.html | 21 ++++++++++++++----- handlers/script.js | 3 +++ .../vendor/generate_readable_outline.html | 5 ++++- styles/input.css | 2 +- 5 files changed, 30 insertions(+), 18 deletions(-) diff --git a/handlers/form.html b/handlers/form.html index ffd3500..308dc86 100644 --- a/handlers/form.html +++ b/handlers/form.html @@ -32,7 +32,9 @@
diff --git a/handlers/playground.html b/handlers/playground.html index d5614d7..fd77da1 100644 --- a/handlers/playground.html +++ b/handlers/playground.html @@ -80,6 +80,7 @@ @@ -113,7 +121,9 @@