160 lines
4.9 KiB
Go
160 lines
4.9 KiB
Go
// 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()
|
|
}
|