diff --git a/additions/dom/mask/MaskConfig.hpp b/additions/dom/mask/MaskConfig.hpp index 5c7b9bf..676d6d7 100644 --- a/additions/dom/mask/MaskConfig.hpp +++ b/additions/dom/mask/MaskConfig.hpp @@ -1,5 +1,5 @@ /* -Helper to extract values from the Mask Config JSON file. +Helper to extract values from the CAMOU_CONFIG environment variable(s). Written by daijro. */ @@ -15,17 +15,60 @@ Written by daijro. #include #include +#ifdef _WIN32 +# include +#endif + namespace MaskConfig { +inline std::optional get_env_utf8(const std::string& name) { +#ifdef _WIN32 + std::wstring wName(name.begin(), name.end()); + DWORD size = GetEnvironmentVariableW(wName.c_str(), nullptr, 0); + if (size == 0) return std::nullopt; // Environment variable not found + + std::vector buffer(size); + GetEnvironmentVariableW(wName.c_str(), buffer.data(), size); + std::wstring wValue(buffer.data()); + + // Convert UTF-16 to UTF-8 + std::wstring_convert> converter; + return converter.to_bytes(wValue); +#else + const char* value = getenv(name.c_str()); + if (!value) return std::nullopt; + return std::string(value); +#endif +} + inline const nlohmann::json& GetJson() { static const nlohmann::json jsonConfig = []() { - const char* jsonString = getenv("CAMOU_CONFIG"); - if (!jsonString) return nlohmann::json{}; + std::string jsonString; + int index = 1; + + while (true) { + std::string envName = "CAMOU_CONFIG_" + std::to_string(index); + auto partialConfig = get_env_utf8(envName); + if (!partialConfig) break; + + jsonString += *partialConfig; + index++; + } + + if (jsonString.empty()) { + // Check for the original CAMOU_CONFIG as fallback + auto originalConfig = get_env_utf8("CAMOU_CONFIG"); + if (originalConfig) jsonString = *originalConfig; + } + + if (jsonString.empty()) return nlohmann::json{}; + // Validate if (!nlohmann::json::accept(jsonString)) { printf_stderr("ERROR: Invalid JSON passed to CAMOU_CONFIG!\n"); return nlohmann::json{}; } + nlohmann::json result = nlohmann::json::parse(jsonString); return result; }(); diff --git a/launcher/constants.go b/launcher/constants.go index 8277dce..412ac7d 100644 --- a/launcher/constants.go +++ b/launcher/constants.go @@ -1,7 +1,7 @@ package main // List of fonts for each OS -var fontsByOS = map[string][]string{ +var FontsByOS = map[string][]string{ "windows": { "Arial", "Arial Black", "Bahnschrift", "Calibri", "Calibri Light", "Cambria", "Cambria Math", "Candara", "Candara Light", "Comic Sans MS", "Consolas", "Constantia", "Corbel", "Corbel Light", "Courier New", "Ebrima", "Franklin Gothic Medium", "Gabriola", "Gadugi", "Georgia", "HoloLens MDL2 Assets", "Impact", "Ink Free", "Javanese Text", "Leelawadee UI", "Leelawadee UI Semilight", "Lucida Console", "Lucida Sans Unicode", "MS Gothic", "MS PGothic", "MS UI Gothic", "MV Boli", "Malgun Gothic", "Malgun Gothic Semilight", "Marlett", "Microsoft Himalaya", "Microsoft JhengHei", "Microsoft JhengHei Light", "Microsoft JhengHei UI", "Microsoft JhengHei UI Light", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Sans Serif", "Microsoft Tai Le", "Microsoft YaHei", "Microsoft YaHei Light", "Microsoft YaHei UI", "Microsoft YaHei UI Light", "Microsoft Yi Baiti", "MingLiU-ExtB", "MingLiU_HKSCS-ExtB", "Mongolian Baiti", "Myanmar Text", "NSimSun", "Nirmala UI", "Nirmala UI Semilight", "PMingLiU-ExtB", "Palatino Linotype", "Segoe Fluent Icons", "Segoe MDL2 Assets", "Segoe Print", "Segoe Script", "Segoe UI", "Segoe UI Black", "Segoe UI Emoji", "Segoe UI Historic", "Segoe UI Light", "Segoe UI Semibold", "Segoe UI Semilight", "Segoe UI Symbol", "Segoe UI Variable", "SimSun", "SimSun-ExtB", "Sitka", "Sitka Text", "Sylfaen", "Symbol", "Tahoma", "Times New Roman", "Trebuchet MS", "Twemoji Mozilla", "Verdana", "Webdings", "Wingdings", "Yu Gothic", "Yu Gothic Light", "Yu Gothic Medium", "Yu Gothic UI", "Yu Gothic UI Light", "Yu Gothic UI Semibold", "Yu Gothic UI Semilight", "\u5b8b\u4f53", "\u5fae\u8edf\u6b63\u9ed1\u9ad4", "\u5fae\u8edf\u6b63\u9ed1\u9ad4 Light", "\u5fae\u8f6f\u96c5\u9ed1", "\u5fae\u8f6f\u96c5\u9ed1 Light", "\u65b0\u5b8b\u4f53", "\u65b0\u7d30\u660e\u9ad4-ExtB", "\u6e38\u30b4\u30b7\u30c3\u30af", "\u6e38\u30b4\u30b7\u30c3\u30af Light", "\u6e38\u30b4\u30b7\u30c3\u30af Medium", "\u7d30\u660e\u9ad4-ExtB", "\u7d30\u660e\u9ad4_HKSCS-ExtB", "\ub9d1\uc740 \uace0\ub515", "\ub9d1\uc740 \uace0\ub515 Semilight", "\uff2d\uff33 \u30b4\u30b7\u30c3\u30af", "\uff2d\uff33 \uff30\u30b4\u30b7\u30c3\u30af", }, diff --git a/launcher/go.mod b/launcher/go.mod index e581c2c..322cee8 100644 --- a/launcher/go.mod +++ b/launcher/go.mod @@ -2,4 +2,6 @@ module launch go 1.22.5 -require github.com/mileusna/useragent v1.3.4 // indirect +require github.com/mileusna/useragent v1.3.4 + +require github.com/goccy/go-json v0.10.3 // indirect diff --git a/launcher/go.sum b/launcher/go.sum index a22bdea..c82eb6f 100644 --- a/launcher/go.sum +++ b/launcher/go.sum @@ -1,2 +1,4 @@ +github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= +github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/mileusna/useragent v1.3.4 h1:MiuRRuvGjEie1+yZHO88UBYg8YBC/ddF6T7F56i3PCk= github.com/mileusna/useragent v1.3.4/go.mod h1:3d8TOmwL/5I8pJjyVDteHtgDGcefrFUX4ccGOMKNYYc= diff --git a/launcher/main.go b/launcher/main.go index 0fa33b0..fb91e46 100644 --- a/launcher/main.go +++ b/launcher/main.go @@ -1,7 +1,6 @@ package main import ( - "encoding/json" "fmt" "io" "os" @@ -9,7 +8,9 @@ import ( "path/filepath" "runtime" "strings" + "unicode/utf8" + json "github.com/goccy/go-json" "github.com/mileusna/useragent" ) @@ -112,7 +113,7 @@ func updateFonts(configMap map[string]interface{}, userAgentOS string) { existingFonts[f] = true } } - for _, font := range fontsByOS[userAgentOS] { + for _, font := range FontsByOS[userAgentOS] { if !existingFonts[font] { fonts = append(fonts, font) } @@ -127,7 +128,35 @@ func setEnvironmentVariables(configMap map[string]interface{}, userAgentOS strin os.Exit(1) } - os.Setenv("CAMOU_CONFIG", string(updatedConfigData)) + // Validate utf8 + if !utf8.Valid(updatedConfigData) { + fmt.Println("Config is not valid UTF-8") + os.Exit(1) + } + + // Split the config into chunks of 2047 characters if the OS is Windows, + // otherwise split into 32767 characters + var chunkSize int + if normalizeOS(runtime.GOOS) == "windows" { + chunkSize = 2047 + } else { + chunkSize = 32767 + } + + configStr := string(updatedConfigData) + for i := 0; i < len(configStr); i += chunkSize { + end := i + chunkSize + if end > len(configStr) { + end = len(configStr) + } + chunk := configStr[i:end] + envName := fmt.Sprintf("CAMOU_CONFIG_%d", (i/chunkSize)+1) + if err := os.Setenv(envName, chunk); err != nil { + fmt.Printf("Error setting %s: %v\n", envName, err) + os.Exit(1) + } + } + if normalizeOS(runtime.GOOS) == "linux" { fontconfigPath := filepath.Join("fontconfig", userAgentOS) os.Setenv("FONTCONFIG_PATH", fontconfigPath) @@ -141,7 +170,7 @@ func getExecutableName() string { case "macos": return "./Camoufox.app" case "windows": - return "camoufox.exe" + return "./camoufox.exe" default: // This should never be reached due to the check in normalizeOS return ""