|
@@ -1,11 +1,14 @@
|
|
|
package main
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
import (
|
|
|
|
|
+ "archive/tar"
|
|
|
"bytes"
|
|
"bytes"
|
|
|
|
|
+ "compress/gzip"
|
|
|
"flag"
|
|
"flag"
|
|
|
"fmt"
|
|
"fmt"
|
|
|
"io"
|
|
"io"
|
|
|
"io/fs"
|
|
"io/fs"
|
|
|
|
|
+ "log"
|
|
|
"net/http"
|
|
"net/http"
|
|
|
"net/url"
|
|
"net/url"
|
|
|
"os"
|
|
"os"
|
|
@@ -18,6 +21,8 @@ import (
|
|
|
"golang.org/x/net/html"
|
|
"golang.org/x/net/html"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+var DEBUG = false
|
|
|
|
|
+
|
|
|
/* UserAgent */
|
|
/* UserAgent */
|
|
|
|
|
|
|
|
// The value I want is (unfortunately) private http.Request.defaultUserAgent
|
|
// The value I want is (unfortunately) private http.Request.defaultUserAgent
|
|
@@ -59,16 +64,44 @@ func init() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Get go version from the download URL.
|
|
// 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 {
|
|
func ParseHtml(read io.Reader, os_arch string) string {
|
|
|
var tokens = html.NewTokenizer(read)
|
|
var tokens = html.NewTokenizer(read)
|
|
|
|
|
+ var result string
|
|
|
var arch_link string
|
|
var arch_link string
|
|
|
|
|
+ var found_links bool = false
|
|
|
|
|
+ var done bool = false
|
|
|
|
|
|
|
|
tloop:
|
|
tloop:
|
|
|
for {
|
|
for {
|
|
@@ -79,7 +112,7 @@ tloop:
|
|
|
break tloop
|
|
break tloop
|
|
|
|
|
|
|
|
case html.StartTagToken:
|
|
case html.StartTagToken:
|
|
|
- if len(arch_link) != 0 {
|
|
|
|
|
|
|
+ if done {
|
|
|
continue
|
|
continue
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -96,27 +129,34 @@ tloop:
|
|
|
key, value, more := tokens.TagAttr()
|
|
key, value, more := tokens.TagAttr()
|
|
|
_ = more
|
|
_ = 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.
|
|
// This function has been fixed. It works correctly now.
|
|
@@ -249,7 +289,9 @@ func CacheExpire(dir string, days int) (int, error) {
|
|
|
return err
|
|
return err
|
|
|
} else {
|
|
} else {
|
|
|
result += 1
|
|
result += 1
|
|
|
- // fmt.Println("Deleted:", path)
|
|
|
|
|
|
|
+ if DEBUG {
|
|
|
|
|
+ fmt.Println("Deleted:", path)
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
return nil
|
|
return nil
|
|
@@ -269,7 +311,6 @@ func RarVersion() string {
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return ""
|
|
return ""
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
line, _ = strings.CutSuffix(line, "\n")
|
|
line, _ = strings.CutSuffix(line, "\n")
|
|
|
|
|
|
|
|
for len(line) == 0 {
|
|
for len(line) == 0 {
|
|
@@ -281,7 +322,10 @@ func RarVersion() string {
|
|
|
line, _ = strings.CutSuffix(line, "\n")
|
|
line, _ = strings.CutSuffix(line, "\n")
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- fmt.Printf("RAR: [%s]\n", line)
|
|
|
|
|
|
|
+ if DEBUG {
|
|
|
|
|
+ fmt.Printf("RAR: [%s]\n", line)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if line != "" {
|
|
if line != "" {
|
|
|
rarver, _, found := strings.Cut(line, " ")
|
|
rarver, _, found := strings.Cut(line, " ")
|
|
|
if found {
|
|
if found {
|
|
@@ -298,6 +342,54 @@ func RarVersion() string {
|
|
|
return line
|
|
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!
|
|
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.
|
|
// Save html to this filename.
|
|
|
var RAR_URL_FILE = UrlToFilename(RAR_URL)
|
|
var RAR_URL_FILE = UrlToFilename(RAR_URL)
|
|
|
|
|
|
|
|
-// "go.dev-dl.html"
|
|
|
|
|
-
|
|
|
|
|
func main() {
|
|
func main() {
|
|
|
HOME := os.Getenv("HOME")
|
|
HOME := os.Getenv("HOME")
|
|
|
if len(HOME) == 0 {
|
|
if len(HOME) == 0 {
|
|
@@ -332,6 +422,7 @@ func main() {
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
flag.BoolVar(&info, "info", false, "Display information")
|
|
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.IntVar(&expire, "expire", 30, "Number of days to expire")
|
|
|
flag.BoolVar(&stop, "stop", false, "Stop execution (before fetching anything)")
|
|
flag.BoolVar(&stop, "stop", false, "Stop execution (before fetching anything)")
|
|
|
flag.Parse()
|
|
flag.Parse()
|
|
@@ -369,12 +460,12 @@ func main() {
|
|
|
if rarerr == nil {
|
|
if rarerr == nil {
|
|
|
// Ok, rar has been located in the path.
|
|
// Ok, rar has been located in the path.
|
|
|
rarversion = RarVersion()
|
|
rarversion = RarVersion()
|
|
|
- fmt.Printf("%s => %s\n", rar, rarversion)
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
var arch_link string
|
|
var arch_link string
|
|
|
|
|
|
|
|
if info {
|
|
if info {
|
|
|
|
|
+ fmt.Printf("RAR @ %s => Version %s\n", rar, rarversion)
|
|
|
/*
|
|
/*
|
|
|
fmt.Printf("Current version: %s\n", go_version)
|
|
fmt.Printf("Current version: %s\n", go_version)
|
|
|
fmt.Printf("OS Arch: %s\n", go_os_arch)
|
|
fmt.Printf("OS Arch: %s\n", go_os_arch)
|
|
@@ -386,10 +477,40 @@ func main() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if stop {
|
|
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")
|
|
var resp, _ = client.Get("https://httpbin.org/user-agent")
|
|
|
defer resp.Body.Close()
|
|
defer resp.Body.Close()
|
|
|
io.Copy(os.Stdout, resp.Body)
|
|
io.Copy(os.Stdout, resp.Body)
|
|
|
|
|
+ fmt.Println("And we'll stop right here for now...")
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -423,7 +544,10 @@ func main() {
|
|
|
var read = io.TeeReader(resp.Body, fp)
|
|
var read = io.TeeReader(resp.Body, fp)
|
|
|
_ = read
|
|
_ = read
|
|
|
var download_link, rar_version string
|
|
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 {
|
|
if len(arch_link) == 0 {
|
|
|
fmt.Printf("I wasn't able to locate the go download URL link for %s.\n", download_link)
|
|
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
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- dl_version := GetVersionFromUrl(arch_link, download_link)
|
|
|
|
|
|
|
+ dl_version := GetVersionFromUrl(arch_link)
|
|
|
if dl_version == rar_version {
|
|
if dl_version == rar_version {
|
|
|
- fmt.Println("You're already good to GO.")
|
|
|
|
|
|
|
+ fmt.Println("You have the latest version of RAR.")
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|