diff --git a/proxy/domains.go b/proxy/domains.go new file mode 100644 index 0000000..2a3b63b --- /dev/null +++ b/proxy/domains.go @@ -0,0 +1,112 @@ +package main + +import ( + "strings" + "github.com/vishalkuo/bimap" + "golang.org/x/net/idna" +) + +var DOMAINS *bimap.BiMap[string, string] = bimap.NewBiMapFromMap(map[string]string { + "www.docs.kernel.org": "ввв.доктора.ядро.орг", + "www.wiki.kernel.org": "ввв.грешник.ядро.орг", + "am.mirrors.kernel.org": "являются.зеркалами.ядро.орг", + "ams.source.kernel.org": "источник.амс.ядро.орг", + "android.kernel.org": "андроид.ядро.орг", + "ap.edge.kernel.org": "край.ап.ядро.орг", + "archive.kernel.org": "архив.ядро.орг", + "b4.docs.kernel.org": "доктора.б4.ядро.орг", + "btrfs.docs.kernel.org": "доктора.битрифс.ядро.орг", + "bugzilla.kernel.org": "бугзила.ядро.орг", + "cdn.kernel.org": "раздатчик.ядро.орг", + "cregit.origin.kernel.org": "происхождение.крегит.ядро.орг", + "cxl.docs.kernel.org": "доктора.схл.ядро.орг", + "dfw.source.kernel.org": "источник.дфв.ядро.орг", + "docs.kernel.org": "доктора.ядро.орг", + "erofs.docs.kernel.org": "доктора.эротическаяфс.ядро.орг", + "erol.kernel.org": "эротика.ядро.орг", + "eu.edge.kernel.org": "край.евросоюза.ядро.орг", + "git.kernel.org": "мерзавец.ядро.орг", + "ieee1394.docs.kernel.org": "доктора.иеее1394.ядро.орг", + "kernel.org": "ядро.орг", + "linux-mmp.docs.kernel.org": "доктора.линукс-карта.ядро.орг", + "linux.kernel.org": "линукс.ядро.орг", + "lkml.kernel.org": "саял.ядро.орг", + "lore.kernel.org": "уздечка.ядро.орг", + "mail.kernel.org": "почта.ядро.орг", + "media.social.kernel.org": "социальные.сми.ядро.орг", + "mirrors.edge.kernel.org": "край.зеркал.ядро.орг", + "mirrors.kernel.org": "зеркала.ядро.орг", + "na.edge.kernel.org": "край.на.ядро.орг", + "nntp.lore.kernel.org": "уздечка.сппн.ядро.орг", + "ny.mirrors.kernel.org": "нью-йоркские.зеркала.ядро.орг", + "nyc.source.kernel.org": "источник.нук.ядро.орг", + "pad.kernel.org": "клавиатура.ядро.орг", + "parisc.docs.kernel.org": "доктора.париж.ядро.орг", + "patchwork.kernel.org": "путаница.ядро.орг", + "people.kernel.org": "люди.ядро.орг", + "planet.kernel.org": "планета.ядро.орг", + "pop.lore.kernel.org": "уздечка.популярности.ядро.орг", + "remail.kernel.org": "перепочта.ядро.орг", + "sin.source.kernel.org": "источник.греха.ядро.орг", + "smtp.kernel.org": "пппп.ядро.орг", + "smtp.lore.kernel.org": "уздечка.пппп.ядро.орг", + "smtp.subspace.kernel.org": "подместо.пппп.ядро.орг", + "smtp1.kernel.org": "пппп1.ядро.орг", + "smtp2.kernel.org": "пппп2.ядро.орг", + "smtp3.kernel.org": "пппп3.ядро.орг", + "social.kernel.org": "социальный.ядро.орг", + "sparse.docs.kernel.org": "редкие.доктора.ядро.орг", + "subspace.kernel.org": "подместо.ядро.орг", + "sv.mirrors.kernel.org": "зеркала.резюме.ядро.орг", + "sy.mirrors.kernel.org": "сай.отражает.ядро.орг", + "vger.kernel.org": "мпук.ядро.орг", + "wiki.kernel.org": "грешник.ядро.орг", + "wireless.docs.kernel.org": "беспроводные.доктора.ядро.орг", + "wireless.kernel.org": "радио.ядро.орг", + "www.kernel.org": "ввв.ядро.орг", + "yul.archive.kernel.org": "архив.юл.ядро.орг", +}); + +var WILDCARD_DOMAINS = [][]string{ + {".docs.kernel.org", ".доктора.ядро.орг"}, + {".wiki.kernel.org", ".грешник.ядро.орг"}, +}; + + +func Kernel2Yadro(str string) (string, bool) { + if yadro, found := DOMAINS.Get(str); found { + return yadro, true + } + + for _, kernel_yadro := range WILDCARD_DOMAINS { + if stem, found := strings.CutSuffix(str, kernel_yadro[0]); found { + return stem + kernel_yadro[1], true + } + } + + return "", false +} + +func Yadro2Kernel(str string, punycode bool) (string, bool) { + var err error + + if punycode { + str, err = idna.ToUnicode(str) + + if err != nil { + return "", false + } + } + + if kernel, found := DOMAINS.GetInverse(str); found { + return kernel, true + } + + for _, kernel_yadro := range WILDCARD_DOMAINS { + if stem, found := strings.CutSuffix(str, kernel_yadro[1]); found { + return stem + kernel_yadro[0], true + } + } + + return "", false +} diff --git a/proxy/go.mod b/proxy/go.mod new file mode 100644 index 0000000..3ccbf16 --- /dev/null +++ b/proxy/go.mod @@ -0,0 +1,9 @@ +module github.com/wzray/promty/proxy + +go 1.23.3 + +require ( + github.com/vishalkuo/bimap v0.0.0-20230830142743-a9fb9b52066c // indirect + golang.org/x/net v0.31.0 // indirect + golang.org/x/text v0.20.0 // indirect +) diff --git a/proxy/go.sum b/proxy/go.sum new file mode 100644 index 0000000..d9882d0 --- /dev/null +++ b/proxy/go.sum @@ -0,0 +1,6 @@ +github.com/vishalkuo/bimap v0.0.0-20230830142743-a9fb9b52066c h1:KEcyvVSSrD/dq45OZpwFG7/gi608xzyriB8kgquCgPU= +github.com/vishalkuo/bimap v0.0.0-20230830142743-a9fb9b52066c/go.mod h1:oVZgsxuZOVCkAVcgSitAfucCKX0Ani+R8bIbfGdqAkg= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= diff --git a/proxy/main.go b/proxy/main.go new file mode 100644 index 0000000..94f6ee6 --- /dev/null +++ b/proxy/main.go @@ -0,0 +1,115 @@ +package main + +import ( + "fmt" + "io" + "bytes" + "regexp" + "strings" + "compress/gzip" + "net/url" + "net/http" + "net/http/httputil" + "golang.org/x/text/encoding/charmap" +) + +func main() { + proxy := &httputil.ReverseProxy{ + Rewrite: func(r *httputil.ProxyRequest) { + host, _ := Yadro2Kernel(r.In.Host, true) + url, err := url.Parse("https://" + host) + + if err != nil { + // TODO... + } + + r.SetURL(url) + + // We only support gzip decoding + r.Out.Header.Set("Accept-Encoding", "gzip") + }, + ModifyResponse: func(r *http.Response) error { + // Disable security policy because of the domain restrictions. + r.Header.Del("Content-Security-Policy") + + // Skip non-html pages. + contentType := r.Header.Get("Content-Type") + if !strings.HasPrefix(contentType, "text/") { + return nil + } + + // Read response body into data. If body is encoded, decode it. + var data []byte + + switch r.Header.Get("Content-Encoding") { + case "gzip": + reader, _ := gzip.NewReader(r.Body) + data, _ = io.ReadAll(reader) + r.Body.Close() + default: + data, _ = io.ReadAll(r.Body) + r.Body.Close() + } + + // Modify the response. + data = modifyResponse(data) + + // Remove headers that mess with body encoding and set the body. + r.Header.Del("Content-Encoding") + r.Header.Del("Content-Length") + // r.Header.Set("Content-Type", "text/html; charset=windows-1251") + + r.Body = io.NopCloser(bytes.NewReader(data)) + + return nil + }, + } + + http.ListenAndServe("localhost:8000", proxy) +} + +func replaceDomains(response []byte) []byte { + re := regexp.MustCompile(`(?i)[A-Za-z\-\.]*\.?kernel\.org`) + response = re.ReplaceAllFunc(response, func(original_raw []byte) []byte { + kernel := strings.ToLower(string(original_raw)) + + // Strip `www.` + kernel = strings.TrimPrefix(kernel, "www.") + + yadro, exists := Kernel2Yadro(kernel) + + if !exists { + return original_raw + } + + return []byte(yadro) + }) + + return response +} + +func translateWithPromtPuppies(response []byte) []byte { + enc := charmap.Windows1251.NewEncoder() + cp1521, _ := enc.Bytes(response) + + req, _ := http.NewRequest("POST", "http://localhost:2390/", bytes.NewReader(cp1521)) // TODO + + resp, err := http.DefaultClient.Do(req) + fmt.Println(err) + fmt.Println(resp.StatusCode) + + response, _ = io.ReadAll(resp.Body) + dec, _ := charmap.Windows1251.NewDecoder().Bytes(response) + // fmt.Println(len(dec)) + // fmt.Println(string(dec)) + + resp.Body.Close() + + return dec +} + +func modifyResponse(response []byte) []byte { + response = replaceDomains(response) + response = translateWithPromtPuppies(response) + return response +}