292 lines
7.7 KiB
Go
292 lines
7.7 KiB
Go
package main
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"database/sql"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"html/template"
|
|
"log/slog"
|
|
"net/http"
|
|
"os"
|
|
"os/exec"
|
|
"regexp"
|
|
"runtime"
|
|
"strconv"
|
|
"strings"
|
|
|
|
_ "modernc.org/sqlite"
|
|
)
|
|
|
|
type jsonStruct struct {
|
|
Vendor string
|
|
Package string
|
|
Version string
|
|
Type string
|
|
Location string
|
|
Checksum string
|
|
Url string
|
|
}
|
|
|
|
// packages struct represents a package with its details.
|
|
type packages struct {
|
|
Id string
|
|
Name string
|
|
Version string
|
|
ExtraCommand *string
|
|
Tag string
|
|
Warning bool
|
|
Element *elements
|
|
}
|
|
type yaml struct {
|
|
PID string
|
|
VER string
|
|
TYPE string
|
|
URL string
|
|
HASH string
|
|
PUB string
|
|
NAME string
|
|
INIT string
|
|
LOCATION string
|
|
FILELOCATION string
|
|
}
|
|
|
|
// ConvertStringsToPackage converts a slice of strings to a packages struct.
|
|
// It returns an error if the input slice does not have exactly 6 elements or if the Warning value cannot be parsed as a boolean.
|
|
func ConvertStringsToPackage(strs []string) (packages, error) {
|
|
var pkg packages
|
|
if len(strs) != 6 {
|
|
return pkg, fmt.Errorf("input slice must have exactly 6 elements")
|
|
}
|
|
|
|
warning, err := strconv.ParseBool(strs[5])
|
|
if err != nil {
|
|
return pkg, fmt.Errorf("error parsing Warning value: %s", err)
|
|
}
|
|
|
|
return packages{
|
|
Id: strs[0],
|
|
Name: strs[1],
|
|
Version: strs[2],
|
|
ExtraCommand: &strs[3],
|
|
Tag: strs[4],
|
|
Warning: warning,
|
|
}, nil
|
|
}
|
|
|
|
// elements struct represents the elements of a the webpage.
|
|
type elements struct {
|
|
Title string
|
|
Header string
|
|
Help string
|
|
Packagename string
|
|
Packageversion string
|
|
Allow string
|
|
Warning string
|
|
Explain string
|
|
}
|
|
|
|
// DownloadElements struct represents the elements to be downloaded.
|
|
type DownloadElements struct {
|
|
ID string
|
|
Version *string
|
|
Counter int
|
|
}
|
|
|
|
// Printer struct is an empty struct. Its purpose is not clear from the provided code.
|
|
type Printer struct{}
|
|
|
|
func getDataFromFile(path string) jsonStruct {
|
|
slog.Debug(regexp.MustCompile(`\.\w+$`).FindString(path))
|
|
switch extention := regexp.MustCompile(`\.\w+$`).FindString(path); extention {
|
|
case ".exe":
|
|
return getParamsFromExif(path)
|
|
|
|
case ".msi":
|
|
return getParamsFromMsi(path)
|
|
}
|
|
return jsonStruct{}
|
|
}
|
|
|
|
// getParamsFromExif extracts EXIF parameters from a file at the given path using the exiftool command.
|
|
// It returns a map where the keys are the EXIF parameter names and the values are the corresponding EXIF parameter values.
|
|
func getParamsFromExif(path string) jsonStruct {
|
|
exiftool := os.Getenv("exiftool")
|
|
e, _ := exec.Command(exiftool, "-f", path).Output()
|
|
data := splitData(e)
|
|
data["Extention"] = data["File Type Extension"]
|
|
data["Path"] = path
|
|
return createObject(data)
|
|
}
|
|
func splitData(commandOutput []byte) map[string]string {
|
|
tags := make(map[string]string)
|
|
spliter := regexp.MustCompile(`\r?\n`)
|
|
crop := spliter.Split(string(commandOutput), -1)
|
|
head := regexp.MustCompile(`\t|(\s+:\s?)`)
|
|
for _, c := range crop {
|
|
if len(c) > 1 {
|
|
data := head.Split(c, -1)
|
|
slog.Debug("My Raw Data: ", c)
|
|
tags[data[0]] = data[1]
|
|
}
|
|
}
|
|
slog.Debug(fmt.Sprint(tags))
|
|
return tags
|
|
}
|
|
func getParamsFromMsi(path string) jsonStruct {
|
|
if runtime.GOOS == "windows" {
|
|
|
|
// orca :=os.Getenv("orca")
|
|
// err:=os.Mkdir("tmpdir/extract", os.ModeAppend)
|
|
// if err != nil {
|
|
// log.Println("There was an error", err)
|
|
// }
|
|
// run:=exec.Command(orca, "-q", "-s", path, "-x", "tmpdir/extract")
|
|
// run.
|
|
} else {
|
|
msiinfo := os.Getenv("msiinfo")
|
|
e, _ := exec.Command(msiinfo, "export", path, "Property").Output()
|
|
data := splitData(e)
|
|
data["Extention"] = "msi"
|
|
data["Path"] = path
|
|
return createObject(data)
|
|
}
|
|
return jsonStruct{}
|
|
}
|
|
func getVendor(data map[string]string) string {
|
|
for key, val := range data {
|
|
switch key {
|
|
case "Author":
|
|
return strings.ToLower(strings.Replace(val, " ", "", -1))
|
|
|
|
case "Company Name":
|
|
return strings.ToLower(strings.Replace(val, " ", "", -1))
|
|
case "Manufacturer":
|
|
return strings.ToLower(strings.Replace(val, " ", "", -1))
|
|
case "Publisher":
|
|
return strings.ToLower(strings.Replace(val, " ", "", -1))
|
|
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
func getProgram(data map[string]string) string {
|
|
for key, val := range data {
|
|
switch key {
|
|
case "Title":
|
|
return strings.ToLower(strings.Replace(val, " ", "", -1))
|
|
|
|
case "Product Name":
|
|
return strings.ToLower(strings.Replace(val, " ", "", -1))
|
|
case "ProductName":
|
|
return strings.ToLower(strings.Replace(val, " ", "", -1))
|
|
case "Subject":
|
|
return strings.ToLower(strings.Replace(val, " ", "", -1))
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
func getVersion(data map[string]string) string {
|
|
replacer := regexp.MustCompile(`[, ]+`)
|
|
for key, val := range data {
|
|
switch key {
|
|
case "Version":
|
|
return replacer.ReplaceAllString(val, ".")
|
|
case "Product Version":
|
|
return replacer.ReplaceAllString(val, ".")
|
|
case "ProductVersion":
|
|
return replacer.ReplaceAllString(val, ".")
|
|
case "File Version":
|
|
return replacer.ReplaceAllString(val, ".")
|
|
case "FileVersion":
|
|
return replacer.ReplaceAllString(val, ".")
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
func detectProblems(data map[string]string) bool {
|
|
exe, err := data["Extention"]
|
|
mime, _ := data["MIME Type"]
|
|
if !err || (exe == "exe" && !(mime == "application/octet-stream")) {
|
|
return false
|
|
}
|
|
if exe != "msi" && exe != "exe" && exe != "zip" {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
func getInstallerType(data map[string]string) string {
|
|
for _, val := range data {
|
|
if val == "msi" {
|
|
return "msi"
|
|
}
|
|
if strings.Contains(strings.ToLower(val), "nullsoft") {
|
|
return "nullsoft"
|
|
}
|
|
if strings.Contains(strings.ToLower(val), "inno") {
|
|
return "inno"
|
|
}
|
|
}
|
|
return "exe"
|
|
}
|
|
func moveToNewLocationAndName(data map[string]string) string {
|
|
newLoc := os.Getenv("installationDirectory") + "/"
|
|
newFileLoc := getVendor(data) + "." + getProgram(data) + ".v."
|
|
newFileLoc += getVersion(data) + "."
|
|
newFileLoc += data["Extention"]
|
|
newLoc += newFileLoc
|
|
file, _ := os.OpenFile(newLoc, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
|
|
defer file.Close()
|
|
oldFile, _ := os.ReadFile(data["Path"])
|
|
file.Write(oldFile)
|
|
return newFileLoc
|
|
}
|
|
func createObject(object map[string]string) jsonStruct {
|
|
if detectProblems(object) {
|
|
prop := jsonStruct{
|
|
Vendor: getVendor(object),
|
|
Package: getProgram(object),
|
|
Version: getVersion(object),
|
|
Type: getInstallerType(object),
|
|
}
|
|
|
|
loc, _ := os.ReadFile(object["Directory"] + "/" + object["File Name"])
|
|
chksum := sha256.Sum256(loc)
|
|
prop.Checksum = hex.EncodeToString(chksum[:])
|
|
lc := moveToNewLocationAndName(object)
|
|
prop.Url = os.Getenv("uri") + lc
|
|
prop.Location = os.Getenv("installationDirectory") + "/" + lc
|
|
newJson(prop)
|
|
return prop
|
|
}
|
|
return jsonStruct{}
|
|
}
|
|
func newJson(object jsonStruct) {
|
|
|
|
sqldb, err := sql.Open("sqlite", "file:progs.db")
|
|
if err != nil {
|
|
slog.Error(err.Error())
|
|
}
|
|
sqldb.Exec("INSERT OR IGNORE INTO newapps(vendor, package, version, type, location, checksum, url) values (?,?,?,?,?,?,?)", object.Vendor, object.Package, object.Version, object.Type, object.Location, object.Checksum, object.Url)
|
|
|
|
}
|
|
func getJson(sqldb *sql.DB) http.Handler {
|
|
return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
|
|
quer := generateSQL("newapps", []string{"vendor", "package", "version", "type", "location", "checksum", "url"}) + " ORDER BY ROWID DESC LIMIT 1"
|
|
data := sqldb.QueryRow(quer)
|
|
jsonelement := jsonStruct{}
|
|
err := data.Scan(&jsonelement.Vendor, &jsonelement.Package, &jsonelement.Version, &jsonelement.Type, &jsonelement.Location, &jsonelement.Checksum, &jsonelement.Url)
|
|
if err != nil {
|
|
slog.Error(err.Error())
|
|
}
|
|
temp, err := template.ParseFiles("html/lastob.json")
|
|
if err != nil {
|
|
slog.Error(err.Error())
|
|
}
|
|
err = temp.ExecuteTemplate(res, "main", jsonelement)
|
|
if err != nil {
|
|
slog.Error(err.Error())
|
|
}
|
|
})
|
|
}
|