Selaa lähdekoodia

Working tar extract code (see -stop).

Steve Thielemann 7 tuntia sitten
vanhempi
commit
9ed20e6295
1 muutettua tiedostoa jossa 155 lisäystä ja 31 poistoa
  1. 155 31
      rar-upgrade.go

+ 155 - 31
rar-upgrade.go

@@ -1,11 +1,14 @@
 package main
 
 import (
+	"archive/tar"
 	"bytes"
+	"compress/gzip"
 	"flag"
 	"fmt"
 	"io"
 	"io/fs"
+	"log"
 	"net/http"
 	"net/url"
 	"os"
@@ -18,6 +21,8 @@ import (
 	"golang.org/x/net/html"
 )
 
+var DEBUG = false
+
 /* UserAgent */
 
 // The value I want is (unfortunately) private http.Request.defaultUserAgent
@@ -59,16 +64,44 @@ func init() {
 }
 
 // Get go version from the download URL.
-func GetVersionFromUrl(url string, arch string) string {
-	part, _, _ := strings.Cut(url, arch)
-	part, _ = strings.CutSuffix(part, ".")
-	_, version, _ := strings.Cut(part, "/go")
-	return version
+//
+// /rar/rarlinux-x64-720.tar.gz
+
+func GetVersionFromUrl(url string) string {
+	part, _, _ := strings.Cut(url, ".") // /rar/rarlinux-x64-720
+	index := strings.LastIndex(part, "-")
+	if index != -1 {
+		return part[index+1:]
+	}
+	return ""
 }
 
+/*
+This is what I'm looking for:
+
+<tr>
+  <td><a href="/rar/winrar-x64-720.exe">
+  <b>WinRAR x64 (64 bit) 7.20</b></a></td>
+  <td>Graphical and command line</td>
+  <td align="center">Trial</td>
+  <td align="right">3683 KB</td>
+</tr>
+...
+<tr>
+  <td><a href="/rar/rarlinux-x64-720.tar.gz">
+  <b>RAR for Linux x64 7.20</b></a></td>
+  <td>Command line only</td>
+  <td align="center">Trial</td>
+  <td align="right">728 KB</td>
+</tr>
+*/
+
 func ParseHtml(read io.Reader, os_arch string) string {
 	var tokens = html.NewTokenizer(read)
+	var result string
 	var arch_link string
+	var found_links bool = false
+	var done bool = false
 
 tloop:
 	for {
@@ -79,7 +112,7 @@ tloop:
 			break tloop
 
 		case html.StartTagToken:
-			if len(arch_link) != 0 {
+			if done {
 				continue
 			}
 
@@ -96,27 +129,34 @@ tloop:
 				key, value, more := tokens.TagAttr()
 				_ = more
 
-				if bytes.Equal(key, []byte("class")) {
-					if bytes.Equal(value, []byte("download")) {
-						// Ok! This is the href we want.
-						key, value, more = tokens.TagAttr()
-						if bytes.Equal(key, []byte("href")) {
-							// Does it contain link to go?
-							if bytes.Contains(value, []byte("/go")) {
-								if bytes.Contains(value, []byte(os_arch)) {
-									// This contains our OS and ARCH!
-									arch_link = string(value)
-									// a href=/dl/go1.25.6.linux-amd64.tar.gz
-									fmt.Printf("a href=%s\n", value)
-								}
-							}
+				if bytes.Equal(key, []byte("href")) {
+					// Does it contain link to go?
+					if bytes.Contains(value, []byte("/rar/")) {
+						found_links = true
+						arch_link = string(value)
+						if strings.Contains(arch_link, os_arch) {
+							result = arch_link
+						}
+						if DEBUG {
+							// a href=/dl/go1.25.6.linux-amd64.tar.gz
+							fmt.Printf("a href=%s\n", value)
 						}
 					}
 				}
 			}
+		case html.EndTagToken:
+			tn, _ := tokens.TagName()
+			// fmt.Printf("End token : [%s]\n", tn)
+
+			if bytes.Equal(tn, []byte("table")) {
+				if found_links == true {
+					done = true
+				}
+			}
 		}
+
 	}
-	return arch_link
+	return result
 }
 
 // This function has been fixed.  It works correctly now.
@@ -249,7 +289,9 @@ func CacheExpire(dir string, days int) (int, error) {
 				return err
 			} else {
 				result += 1
-				// fmt.Println("Deleted:", path)
+				if DEBUG {
+					fmt.Println("Deleted:", path)
+				}
 			}
 		}
 		return nil
@@ -269,7 +311,6 @@ func RarVersion() string {
 	if err != nil {
 		return ""
 	}
-
 	line, _ = strings.CutSuffix(line, "\n")
 
 	for len(line) == 0 {
@@ -281,7 +322,10 @@ func RarVersion() string {
 		line, _ = strings.CutSuffix(line, "\n")
 	}
 
-	fmt.Printf("RAR: [%s]\n", line)
+	if DEBUG {
+		fmt.Printf("RAR: [%s]\n", line)
+	}
+
 	if line != "" {
 		rarver, _, found := strings.Cut(line, "   ")
 		if found {
@@ -298,6 +342,54 @@ func RarVersion() string {
 	return line
 }
 
+func read_tarball(fp *os.File) {
+	// https://gauravgahlot.in/extracting-files-gzipped-tar-archive-go/
+
+	gzipReader, err := gzip.NewReader(fp)
+	if err != nil {
+		panic(err) // for now
+	}
+	tarReader := tar.NewReader(gzipReader)
+
+	for {
+		header, err := tarReader.Next()
+		if err == io.EOF {
+			break
+		}
+
+		if err != nil {
+			log.Fatalln(err)
+		}
+
+		if header.Typeflag == tar.TypeReg {
+			var basefilename string
+			index := strings.LastIndex(header.Name, "/")
+			if index != -1 {
+				basefilename = header.Name[index+1:]
+			} else {
+				basefilename = header.Name
+			}
+
+			if header.Mode == 0755 {
+				fmt.Printf("Name: %s Mode %o\n", basefilename, header.Mode)
+				fpout, err := os.OpenFile(basefilename, os.O_CREATE|os.O_WRONLY, os.FileMode(header.Mode))
+				if err != nil {
+					panic(err)
+				}
+				defer fpout.Close()
+
+				size, err := io.Copy(fpout, tarReader)
+				if err != nil {
+					panic(err)
+				} else {
+					fmt.Printf("Wrote %d bytes.\n", size)
+				}
+			}
+			fmt.Printf("Header: %+v\n", header)
+		}
+	}
+}
+
 /*
 I also would like this program to be able to fresh/new install go!
 
@@ -313,8 +405,6 @@ const RAR_URL = "https://www.rarlab.com/download.htm"
 // Save html to this filename.
 var RAR_URL_FILE = UrlToFilename(RAR_URL)
 
-// "go.dev-dl.html"
-
 func main() {
 	HOME := os.Getenv("HOME")
 	if len(HOME) == 0 {
@@ -332,6 +422,7 @@ func main() {
 	)
 
 	flag.BoolVar(&info, "info", false, "Display information")
+	flag.BoolVar(&DEBUG, "debug", false, "Debug information")
 	flag.IntVar(&expire, "expire", 30, "Number of days to expire")
 	flag.BoolVar(&stop, "stop", false, "Stop execution (before fetching anything)")
 	flag.Parse()
@@ -369,12 +460,12 @@ func main() {
 	if rarerr == nil {
 		// Ok, rar has been located in the path.
 		rarversion = RarVersion()
-		fmt.Printf("%s => %s\n", rar, rarversion)
 	}
 
 	var arch_link string
 
 	if info {
+		fmt.Printf("RAR @ %s => Version %s\n", rar, rarversion)
 		/*
 			fmt.Printf("Current version: %s\n", go_version)
 			fmt.Printf("OS Arch: %s\n", go_os_arch)
@@ -386,10 +477,40 @@ func main() {
 	}
 
 	if stop {
-		fmt.Println("And we'll stop right here for now...")
+		fmt.Println("Ok, parse HTML file:")
+		var filename = CACHE_DIR + "/" + RAR_URL_FILE
+		var parse_link string
+		fp, err := os.Open(filename)
+		if err == nil {
+			defer fp.Close()
+			parse_link = ParseHtml(fp, "linux")
+			fmt.Printf("Parse HTML link: %s\n", parse_link)
+		} else {
+			fmt.Printf("Missing cache file: %s\n", filename)
+		}
+
+		// parse_link => /rar/rarlinux-x64-720.tar.gz
+		index := strings.LastIndex(parse_link, "/")
+		if index != -1 {
+			parse_link = parse_link[index+1:]
+		}
+
+		filename = CACHE_DIR + "/" + parse_link
+		fp, err = os.Open(filename)
+		if err == nil {
+			defer fp.Close()
+			// Ok! We have open tarball file.
+			fmt.Printf("Tarball %s:\n", filename)
+			read_tarball(fp)
+		} else {
+			fmt.Printf("Missing cache file: %s\n", filename)
+		}
+
+		fmt.Println("Get user-agent string from httpbin site:")
 		var resp, _ = client.Get("https://httpbin.org/user-agent")
 		defer resp.Body.Close()
 		io.Copy(os.Stdout, resp.Body)
+		fmt.Println("And we'll stop right here for now...")
 		return
 	}
 
@@ -423,7 +544,10 @@ func main() {
 	var read = io.TeeReader(resp.Body, fp)
 	_ = read
 	var download_link, rar_version string
-	// arch_link = ParseHtml(read, go_os_arch)
+	// Remove . from version
+	rar_version = strings.ReplaceAll(rarversion, ".", "")
+
+	arch_link = ParseHtml(read, "linux")
 
 	if len(arch_link) == 0 {
 		fmt.Printf("I wasn't able to locate the go download URL link for %s.\n", download_link)
@@ -431,9 +555,9 @@ func main() {
 		return
 	}
 
-	dl_version := GetVersionFromUrl(arch_link, download_link)
+	dl_version := GetVersionFromUrl(arch_link)
 	if dl_version == rar_version {
-		fmt.Println("You're already good to GO.")
+		fmt.Println("You have the latest version of RAR.")
 		return
 	}