summaryrefslogtreecommitdiffstats
path: root/veilith-main.go
diff options
context:
space:
mode:
Diffstat (limited to 'veilith-main.go')
-rw-r--r--veilith-main.go328
1 files changed, 328 insertions, 0 deletions
diff --git a/veilith-main.go b/veilith-main.go
new file mode 100644
index 0000000..72e5c25
--- /dev/null
+++ b/veilith-main.go
@@ -0,0 +1,328 @@
+// cmd/veilith-portable/main.go
+package main
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "path/filepath"
+ "runtime"
+
+ "fyne.io/fyne/v2/app"
+ "fyne.io/fyne/v2/container"
+ "fyne.io/fyne/v2/widget"
+
+ "veilith/addressbook"
+ "veilith/identity"
+ "veilith/session"
+ "veilith/transport"
+ "veilith/transport/mesh"
+ "veilith/transport/tor"
+)
+
+// PortableApp represents the portable Veilith application
+type PortableApp struct {
+ config *PortableConfig
+ identity *identity.Identity
+ addressBook *addressbook.AddressBook
+ sessionMgr *session.SessionManager
+ transportMgr *transport.TransportManager
+}
+
+// PortableConfig holds portable mode configuration
+type PortableConfig struct {
+ IsPortable bool
+ BaseDir string
+ DataDir string
+ TorDir string
+ TempDir string
+ IdentityPath string
+ ContactsPath string
+ ConfigPath string
+ IsUSB bool
+ IsNetworkShare bool
+ Platform string
+}
+
+func main() {
+ fmt.Println("╔════════════════════════════════════════╗")
+ fmt.Println("║ VEILITH PORTABLE v0.9 ║")
+ fmt.Println("║ Privacy-First P2P Messenger ║")
+ fmt.Println("╚════════════════════════════════════════╝")
+ fmt.Println()
+
+ // Detect and setup portable mode
+ config, err := detectPortableMode()
+ if err != nil {
+ log.Fatalf("Failed to initialize portable mode: %v", err)
+ }
+
+ // Display portable status
+ displayPortableStatus(config)
+
+ // Initialize portable app
+ portableApp := &PortableApp{
+ config: config,
+ }
+
+ // Setup data directories
+ if err := portableApp.setupDirectories(); err != nil {
+ log.Fatalf("Failed to setup directories: %v", err)
+ }
+
+ // Start GUI
+ portableApp.startGUI()
+}
+
+// detectPortableMode detects portable environment
+func detectPortableMode() (*PortableConfig, error) {
+ // Get executable location
+ exe, err := os.Executable()
+ if err != nil {
+ return nil, fmt.Errorf("failed to get executable path: %w", err)
+ }
+
+ baseDir := filepath.Dir(exe)
+
+ config := &PortableConfig{
+ IsPortable: true,
+ BaseDir: baseDir,
+ DataDir: filepath.Join(baseDir, "data"),
+ TorDir: filepath.Join(baseDir, "tor"),
+ TempDir: filepath.Join(baseDir, "temp"),
+ Platform: runtime.GOOS,
+ }
+
+ // Set file paths
+ config.IdentityPath = filepath.Join(config.DataDir, "identity.enc")
+ config.ContactsPath = filepath.Join(config.DataDir, "contacts.enc")
+ config.ConfigPath = filepath.Join(config.DataDir, "config.json")
+
+ // Detect if running from USB
+ config.IsUSB = isRemovableDrive(baseDir)
+ config.IsNetworkShare = isNetworkPath(baseDir)
+
+ return config, nil
+}
+
+// isRemovableDrive checks if path is on removable media
+func isRemovableDrive(path string) bool {
+ switch runtime.GOOS {
+ case "windows":
+ return isWindowsRemovable(path)
+ case "linux":
+ return isLinuxRemovable(path)
+ default:
+ return false
+ }
+}
+
+// isWindowsRemovable checks for Windows removable drives
+func isWindowsRemovable(path string) bool {
+ // Simplified check - in production use Windows API
+ drive := filepath.VolumeName(path)
+ // Check if drive letter is in typical USB range (E: to Z:)
+ if len(drive) > 0 {
+ letter := drive[0]
+ return letter >= 'E' && letter <= 'Z'
+ }
+ return false
+}
+
+// isLinuxRemovable checks for Linux removable media
+func isLinuxRemovable(path string) bool {
+ // Check if path contains /media or /mnt (typical USB mount points)
+ return filepath.HasPrefix(path, "/media") ||
+ filepath.HasPrefix(path, "/mnt")
+}
+
+// isNetworkPath checks if running from network share
+func isNetworkPath(path string) bool {
+ switch runtime.GOOS {
+ case "windows":
+ return filepath.HasPrefix(path, "\\\\")
+ case "linux":
+ // Check for NFS/SMB mounts (simplified)
+ return false
+ }
+ return false
+}
+
+// displayPortableStatus shows portable mode information
+func displayPortableStatus(config *PortableConfig) {
+ fmt.Println("📁 Portable Mode Configuration")
+ fmt.Println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
+ fmt.Printf(" Platform: %s\n", config.Platform)
+ fmt.Printf(" Base Dir: %s\n", config.BaseDir)
+ fmt.Printf(" Data Dir: %s\n", config.DataDir)
+ fmt.Printf(" Running from: ")
+
+ if config.IsUSB {
+ fmt.Println("USB Drive ✓")
+ } else if config.IsNetworkShare {
+ fmt.Println("Network Share ✓")
+ } else {
+ fmt.Println("Local Drive")
+ }
+ fmt.Println()
+}
+
+// setupDirectories creates required directories
+func (pa *PortableApp) setupDirectories() error {
+ dirs := []string{
+ pa.config.DataDir,
+ pa.config.TorDir,
+ pa.config.TempDir,
+ }
+
+ for _, dir := range dirs {
+ if err := os.MkdirAll(dir, 0700); err != nil {
+ return fmt.Errorf("failed to create directory %s: %w", dir, err)
+ }
+ }
+
+ fmt.Println("✓ Directories initialized")
+ return nil
+}
+
+// startGUI launches the portable GUI application
+func (pa *PortableApp) startGUI() {
+ myApp := app.New()
+ myWindow := myApp.NewWindow("Veilith Portable v0.9")
+
+ // Welcome screen
+ welcomeLabel := widget.NewLabel("Welcome to Veilith Portable")
+ welcomeLabel.Alignment = fyne.TextAlignCenter
+
+ infoLabel := widget.NewLabel(fmt.Sprintf(
+ "Running from: %s\nData directory: %s",
+ pa.config.BaseDir,
+ pa.config.DataDir,
+ ))
+ infoLabel.Wrapping = fyne.TextWrapWord
+
+ // Identity section
+ var passphraseEntry *widget.Entry
+ var statusLabel *widget.Label
+
+ statusLabel = widget.NewLabel("No identity loaded")
+
+ passphraseEntry = widget.NewPasswordEntry()
+ passphraseEntry.SetPlaceHolder("Enter passphrase...")
+
+ // Load/Create identity button
+ loadBtn := widget.NewButton("Load Identity", func() {
+ passphrase := passphraseEntry.Text
+ if passphrase == "" {
+ statusLabel.SetText("⚠ Please enter a passphrase")
+ return
+ }
+
+ // Try to load existing identity
+ if _, err := os.Stat(pa.config.IdentityPath); err == nil {
+ id, err := identity.LoadIdentity(pa.config.IdentityPath, []byte(passphrase))
+ if err != nil {
+ statusLabel.SetText("⚠ Failed to load identity (wrong passphrase?)")
+ return
+ }
+ pa.identity = id
+ statusLabel.SetText("✓ Identity loaded: " + id.GetPublicKeyHex()[:16] + "...")
+ } else {
+ // Create new identity
+ id, err := identity.NewIdentity()
+ if err != nil {
+ statusLabel.SetText("⚠ Failed to create identity")
+ return
+ }
+
+ if err := id.Save(pa.config.IdentityPath, []byte(passphrase)); err != nil {
+ statusLabel.SetText("⚠ Failed to save identity")
+ return
+ }
+
+ pa.identity = id
+ statusLabel.SetText("✓ New identity created: " + id.GetPublicKeyHex()[:16] + "...")
+ }
+
+ // Initialize other components
+ pa.initializeComponents()
+ })
+
+ // Quit button
+ quitBtn := widget.NewButton("Quit", func() {
+ pa.cleanup()
+ myApp.Quit()
+ })
+
+ // Layout
+ content := container.NewVBox(
+ welcomeLabel,
+ widget.NewSeparator(),
+ infoLabel,
+ widget.NewSeparator(),
+ widget.NewLabel("Identity Management:"),
+ passphraseEntry,
+ loadBtn,
+ statusLabel,
+ widget.NewSeparator(),
+ quitBtn,
+ )
+
+ myWindow.SetContent(content)
+ myWindow.Resize(fyne.NewSize(600, 400))
+ myWindow.CenterOnScreen()
+ myWindow.ShowAndRun()
+}
+
+// initializeComponents initializes core components after identity is loaded
+func (pa *PortableApp) initializeComponents() error {
+ // Initialize session manager
+ pa.sessionMgr = session.NewSessionManager()
+
+ // Initialize transport manager
+ pa.transportMgr = transport.NewTransportManager()
+
+ // Try to load address book
+ if _, err := os.Stat(pa.config.ContactsPath); err == nil {
+ // Load existing contacts
+ fmt.Println("✓ Address book loaded")
+ } else {
+ // Create new address book
+ pa.addressBook = addressbook.NewAddressBook()
+ fmt.Println("✓ New address book created")
+ }
+
+ fmt.Println("✓ Components initialized")
+ return nil
+}
+
+// cleanup performs cleanup on application exit
+func (pa *PortableApp) cleanup() {
+ fmt.Println("\n🧹 Cleaning up...")
+
+ // Secure wipe sessions
+ if pa.sessionMgr != nil {
+ pa.sessionMgr.SecureWipeAll()
+ fmt.Println(" ✓ Sessions wiped")
+ }
+
+ // Close transports
+ if pa.transportMgr != nil {
+ pa.transportMgr.Close()
+ fmt.Println(" ✓ Transports closed")
+ }
+
+ // Wipe identity from memory
+ if pa.identity != nil {
+ pa.identity.SecureWipe()
+ fmt.Println(" ✓ Identity wiped from memory")
+ }
+
+ // Clean temp directory
+ if pa.config.TempDir != "" {
+ os.RemoveAll(pa.config.TempDir)
+ fmt.Println(" ✓ Temp files removed")
+ }
+
+ fmt.Println("✓ Cleanup complete")
+}