init
This commit is contained in:
104
main.go
Normal file
104
main.go
Normal file
@ -0,0 +1,104 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// maxRedirects defines the maximum number of redirects to follow.
|
||||
const maxRedirects = 10
|
||||
|
||||
// isValidURLAndFetchContent checks if the URL is valid and fetches its content.
|
||||
// It handles redirects and checks for the .sh extension.
|
||||
// It returns the content, a boolean indicating validity, and an error if any.
|
||||
func isValidURLAndFetchContent(url string, redirectCount int) ([]byte, bool, error) {
|
||||
if redirectCount > maxRedirects {
|
||||
return nil, false, fmt.Errorf("too many redirects")
|
||||
}
|
||||
|
||||
// Check if the URL ends with .sh
|
||||
if strings.HasSuffix(strings.ToLower(url), ".sh") {
|
||||
// If it ends with .sh, try to download it directly
|
||||
fmt.Printf("Attempting to download: %s\n", url)
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("failed to download from %s: %w", url, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
|
||||
content, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("failed to read content from %s: %w", url, err)
|
||||
}
|
||||
return content, true, nil
|
||||
}
|
||||
// If status is not OK, but it ended with .sh, we treat it as a failed download for a .sh file.
|
||||
return nil, false, fmt.Errorf("failed to download %s: status code %d", url, resp.StatusCode)
|
||||
}
|
||||
|
||||
// If it doesn't end with .sh, check for redirect
|
||||
fmt.Printf("URL %s does not end with .sh, checking for redirect...\n", url)
|
||||
client := &http.Client{
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse // Do not follow redirects automatically
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := client.Get(url) // Using Get to be able to read body if needed, though Head is often used for just status/headers
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("failed to request %s: %w", url, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
switch resp.StatusCode {
|
||||
case http.StatusMovedPermanently, http.StatusFound, http.StatusSeeOther, http.StatusTemporaryRedirect, http.StatusPermanentRedirect:
|
||||
location, err := resp.Location()
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("failed to get redirect location from %s: %w", url, err)
|
||||
}
|
||||
fmt.Printf("Redirected to: %s\n", location.String())
|
||||
return isValidURLAndFetchContent(location.String(), redirectCount+1)
|
||||
default:
|
||||
// Not a .sh and not a redirect status code
|
||||
return nil, false, fmt.Errorf("URL %s does not end in .sh and did not redirect (status: %d)", url, resp.StatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
// hasShebang checks if the content starts with "#!".
|
||||
func hasShebang(content []byte) bool {
|
||||
return len(content) >= 2 && content[0] == '#' && content[1] == '!'
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Println("Usage: go run script_downloader.go <URL>")
|
||||
os.Exit(1)
|
||||
}
|
||||
initialURL := os.Args[1]
|
||||
|
||||
content, isValid, err := isValidURLAndFetchContent(initialURL, 0)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if !isValid {
|
||||
// This case should ideally be covered by errors from isValidURLAndFetchContent
|
||||
fmt.Fprintf(os.Stderr, "The provided URL is invalid or does not point to a valid .sh file after redirects.\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if hasShebang(content) {
|
||||
fmt.Println("Valid script found. Content:")
|
||||
fmt.Println("--- SCRIPT START ---")
|
||||
fmt.Print(string(content))
|
||||
fmt.Println("--- SCRIPT END ---")
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "Error: The file from URL %s does not start with a shebang '#!'.\n", initialURL)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user