package main import ( "fmt" "io" "net/http" "os" "strings" "time" ) func parseVersion(v string) [3]int { var t [3]int for i, p := range strings.SplitN(strings.TrimSpace(v), ".", 3) { fmt.Sscanf(p, "%d", &t[i]) } return t } func versionGreater(remote, local string) bool { r, l := parseVersion(remote), parseVersion(local) for i := 0; i < 3; i++ { if r[i] > l[i] { return true } if r[i] < l[i] { return false } } return false } func checkSelfUpdate(cfg SelfUpdateConfig) (needsUpdate bool, info string, err error) { if cfg.URL == "" { return false, "", nil } url := fmt.Sprintf("%s/raw/branch/%s/version.txt", cfg.URL, cfg.Branch) client := &http.Client{Timeout: 10 * time.Second} resp, err := client.Get(url) if err != nil { return false, "", err } defer resp.Body.Close() data, _ := io.ReadAll(resp.Body) remote := strings.TrimSpace(string(data)) if !versionGreater(remote, VERSION) { return false, "", nil } return true, fmt.Sprintf("Version actuelle : %s\nVersion disponible : %s", VERSION, remote), nil } func doSelfUpdate(cfg SelfUpdateConfig) error { exePath, err := os.Executable() if err != nil { return err } newPath := exePath + ".new" oldPath := exePath + ".old" url := fmt.Sprintf("%s/raw/branch/%s/%s", cfg.URL, cfg.Branch, cfg.ExeName) client := &http.Client{Timeout: 120 * time.Second} resp, err := client.Get(url) if err != nil { return err } defer resp.Body.Close() f, err := os.Create(newPath) if err != nil { return err } n, copyErr := io.Copy(f, resp.Body) f.Close() if copyErr != nil { os.Remove(newPath) return copyErr } if n < 1000 { os.Remove(newPath) return fmt.Errorf("fichier telecharge invalide (%d octets)", n) } // Supprimer le Mark of the Web (Zone.Identifier) os.Remove(newPath + ":Zone.Identifier") if err := os.Rename(exePath, oldPath); err != nil { os.Remove(newPath) return err } if err := os.Rename(newPath, exePath); err != nil { os.Rename(oldPath, exePath) // restaurer return err } return nil }