func downloadHttpExtractZip()

in codecatalyst-runner/pkg/workflows/workflow_plans_provider.go [195:258]


func downloadHttpExtractZip(_ context.Context, url string, destDir string) error {
	response, err := http.Get(url) // #nosec G107 -- URLs are generated above from trusted host
	if err != nil {
		return fmt.Errorf("unable to get object from url %s: %w", url, err)
	}
	defer response.Body.Close()

	actionZip, err := os.CreateTemp("", "actions-*.zip")
	if err != nil {
		return fmt.Errorf("unable to create temp file: %w", err)
	}
	defer os.Remove(actionZip.Name())
	if _, err = io.Copy(actionZip, response.Body); err != nil {
		return fmt.Errorf("unable to copy zip to temp file: %w", err)
	}
	_ = actionZip.Close()

	archive, err := zip.OpenReader(actionZip.Name())
	if err != nil {
		return fmt.Errorf("unable to open zip: %w", err)
	}
	defer archive.Close()
	for _, f := range archive.File {
		filePath := filepath.Join(destDir, f.Name) //#nosec G305 -- mitigated through next line
		if !strings.HasPrefix(filePath, filepath.Clean(destDir)+string(os.PathSeparator)) {
			return fmt.Errorf("invalid file path: %s", filePath)
		}
		if f.FileInfo().IsDir() {
			err = os.MkdirAll(filePath, os.ModePerm)
			if err != nil {
				return fmt.Errorf("unable to create directory: %w", err)
			}
			continue
		}

		if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
			return fmt.Errorf("unable to create directory: %w", err)
		}

		dstFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
		if err != nil {
			return fmt.Errorf("unable to open file: %w", err)
		}

		fileInArchive, err := f.Open()
		if err != nil {
			return fmt.Errorf("unable to open file in archive: %w", err)
		}

		for {
			_, err := io.CopyN(dstFile, fileInArchive, 1024)
			if err != nil {
				if err == io.EOF {
					break
				}
				return fmt.Errorf("unable to copy file: %w", err)
			}
		}

		dstFile.Close()
		fileInArchive.Close()
	}
	return nil
}