package main import ( "archive/zip" "encoding/json" "fmt" "io" "io/ioutil" "net/http" "os" "path/filepath" "strings" ) type Author struct { Login string `json:"login"` ID int `json:"id"` NodeID string `json:"node_id"` AvatarURL string `json:"avatar_url"` GravatarID string `json:"gravatar_id"` URL string `json:"url"` HTMLURL string `json:"html_url"` FollowersURL string `json:"followers_url"` FollowingURL string `json:"following_url"` GistsURL string `json:"gists_url"` StarredURL string `json:"starred_url"` SubscriptionsURL string `json:"subscriptions_url"` OrganizationsURL string `json:"organizations_url"` ReposURL string `json:"repos_url"` EventsURL string `json:"events_url"` ReceivedEventsURL string `json:"received_events_url"` Type string `json:"type"` SiteAdmin bool `json:"site_admin"` } // Define a struct for the Release type Release struct { URL string `json:"url"` AssetsURL string `json:"assets_url"` UploadURL string `json:"upload_url"` HTMLURL string `json:"html_url"` ID int `json:"id"` Author Author `json:"author"` NodeID string `json:"node_id"` TagName string `json:"tag_name"` TargetCommitish string `json:"target_commitish"` Name string `json:"name"` Draft bool `json:"draft"` Prerelease bool `json:"prerelease"` CreatedAt string `json:"created_at"` PublishedAt string `json:"published_at"` Assets []interface{} `json:"assets"` // Assuming assets is an array of unknown types TarballURL string `json:"tarball_url"` ZipballURL string `json:"zipball_url"` Body string `json:"body"` } func Unzip(src, dest string) error { r, err := zip.OpenReader(src) if err != nil { return err } defer func() { if err := r.Close(); err != nil { panic(err) } }() os.MkdirAll(dest, 0755) // Closure to address file descriptors issue with all the deferred .Close() methods extractAndWriteFile := func(f *zip.File) error { rc, err := f.Open() if err != nil { return err } defer func() { if err := rc.Close(); err != nil { panic(err) } }() path := filepath.Join(dest, f.Name) // Check for ZipSlip (Directory traversal) if !strings.HasPrefix(path, filepath.Clean(dest)+string(os.PathSeparator)) { return fmt.Errorf("illegal file path: %s", path) } if f.FileInfo().IsDir() { os.MkdirAll(path, f.Mode()) } else { os.MkdirAll(filepath.Dir(path), f.Mode()) f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) if err != nil { return err } defer func() { if err := f.Close(); err != nil { panic(err) } }() _, err = io.Copy(f, rc) if err != nil { return err } } return nil } for _, f := range r.File { err := extractAndWriteFile(f) if err != nil { return err } } return nil } func getLatestVersion(repoU string) (string, error) { jsonBody := []byte("") res := sendRequest(http.MethodGet, fmt.Sprintf("https://api.github.com/repos%s/releases/latest", repoU), jsonBody) var release Release err := json.Unmarshal([]byte(string(res.Body)), &release) if err != nil || res.StatusCode != 200 { return "", err } return release.TagName, nil } func downloadPackage(repoU, tag string) error { resp, err := http.Get(fmt.Sprintf("https://github.com/%s/archive/refs/tags/%s.zip", strings.Trim(repoU, "/"), tag)) if err != nil { return err } defer resp.Body.Close() out, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading body:", err) return err } err = ioutil.WriteFile("temp.zip", out, 0644) if err != nil { fmt.Println("Error writing file:", err) return err } return nil }