// Package main provides system-level utilities for EMLy. // This file contains methods for Windows registry access, character encoding // conversion, and file system operations. package main import ( "fmt" "os" "os/exec" "path/filepath" "strings" "unicode/utf8" "golang.org/x/sys/windows/registry" "golang.org/x/text/encoding/charmap" "golang.org/x/text/transform" ) // ============================================================================= // Windows Default App Handler // ============================================================================= // CheckIsDefaultEMLHandler checks if EMLy is registered as the default handler // for .eml files in Windows. // // This works by: // 1. Getting the current executable path // 2. Reading the UserChoice registry key for .eml files // 3. Finding the command associated with the chosen ProgId // 4. Comparing the command with our executable // // Returns: // - bool: True if EMLy is the default handler // - error: Error if registry access fails func (a *App) CheckIsDefaultEMLHandler() (bool, error) { // Get current executable path for comparison exePath, err := os.Executable() if err != nil { return false, err } exePath = strings.ToLower(exePath) // Open the UserChoice key for .eml extension // This is where Windows stores the user's chosen default app k, err := registry.OpenKey( registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.eml\UserChoice`, registry.QUERY_VALUE, ) if err != nil { // Key doesn't exist - user hasn't made a specific choice // or system default is active (which is usually not us) return false, nil } defer k.Close() // Get the ProgId (program identifier) for the chosen app progId, _, err := k.GetStringValue("ProgId") if err != nil { return false, err } // Find the command associated with this ProgId classKeyPath := fmt.Sprintf(`%s\shell\open\command`, progId) classKey, err := registry.OpenKey(registry.CLASSES_ROOT, classKeyPath, registry.QUERY_VALUE) if err != nil { return false, fmt.Errorf("unable to find command for ProgId %s", progId) } defer classKey.Close() // Get the command string cmd, _, err := classKey.GetStringValue("") if err != nil { return false, err } // Compare command with our executable // Check if the command contains our executable name cmdLower := strings.ToLower(cmd) if strings.Contains(cmdLower, strings.ToLower(filepath.Base(exePath))) { return true, nil } return false, nil } // OpenDefaultAppsSettings opens the Windows Settings app to the Default Apps page. // This allows users to easily set EMLy as the default handler for email files. // // Returns: // - error: Error if launching settings fails func (a *App) OpenDefaultAppsSettings() error { cmd := exec.Command("cmd", "/c", "start", "ms-settings:defaultapps") return cmd.Start() } // ============================================================================= // Character Encoding // ============================================================================= // ConvertToUTF8 attempts to convert a string to valid UTF-8. // If the string is already valid UTF-8, it's returned as-is. // Otherwise, it assumes Windows-1252 encoding (common for legacy emails) // and attempts to decode it. // // This is particularly useful for email body content that may have been // encoded with legacy Western European character sets. // // Parameters: // - s: The string to convert // // Returns: // - string: UTF-8 encoded string func (a *App) ConvertToUTF8(s string) string { // If already valid UTF-8, return as-is if utf8.ValidString(s) { return s } // Assume Windows-1252 (superset of ISO-8859-1) // This is the most common encoding for legacy Western European text decoder := charmap.Windows1252.NewDecoder() decoded, _, err := transform.String(decoder, s) if err != nil { // Return original if decoding fails return s } return decoded } // ============================================================================= // File System Operations // ============================================================================= // OpenFolderInExplorer opens the specified folder in Windows Explorer. // This is used to show the user where bug report files are saved. // // Parameters: // - folderPath: The path to the folder to open // // Returns: // - error: Error if launching explorer fails func (a *App) OpenFolderInExplorer(folderPath string) error { cmd := exec.Command("explorer", folderPath) return cmd.Start() } // OpenURLInBrowser opens the specified URL in the system's default web browser. // Uses the Windows "start" command to launch the default browser. // // Parameters: // - url: The URL to open (must be a valid http/https URL) // // Returns: // - error: Error if launching the browser fails func (a *App) OpenURLInBrowser(url string) error { cmd := exec.Command("cmd", "/c", "start", "", url) return cmd.Start() }