Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9da352a315 | |||
| 34b8f7c926 | |||
| 5d5cedec58 | |||
| 8441a8b752 | |||
| d64d88e0a5 | |||
| 5eeb9cc702 | |||
| fc3411e568 | |||
| 77ce9e8ad4 | |||
| 63dd8ebb83 | |||
| 7cf45c9ac8 | |||
| 2f8de0bed2 | |||
| 67ca030bb2 | |||
| da46399ded | |||
| e5d0b6a9a2 | |||
| f4ca2115d4 | |||
| 0cc7f8f445 | |||
| 767e894acd | |||
| 06e2afef1d |
@@ -1,32 +1,37 @@
|
|||||||
# LinuxPA
|
# LinuxPA
|
||||||
LinuxPA is a try to bring a PortableApps.com type launcher to Linux.
|
LinuxPA is a try to bring a [PortableApps.com](http://portableapps.com) type launcher to Linux.
|
||||||
|
|
||||||
# App Detection
|
# How to use
|
||||||
LinuxPA looks in all folders in the PortableApps folder for, first, a script file (starts with the shebang (`#!`)) and, secondly, a native linux executable (starts with ELF). It will only add the first one it finds.
|
Just double click on an app to launch it! If there are multiple executables, you can either select the specific executable, or if you just double click the app it'll launch the first linux executable (.sh script files have priority), but if one isn't found it launches the first executable in general.
|
||||||
|
|
||||||
# PortableApps.com Compatability
|
# Apps:
|
||||||
|
Both of the below places provide linux executables that don't need libs installed on the host system:
|
||||||
|
[AppImage](https://bintray.com/probono/AppImages)
|
||||||
|
|
||||||
|
# PortableApps.com Compatibility
|
||||||
LinuxPA works will with the PortableApps.com launcher, as it looks for apps in the PortableApps folder and grabs the app's name and icon from where it should be in the PortableApps.com format.
|
LinuxPA works will with the PortableApps.com launcher, as it looks for apps in the PortableApps folder and grabs the app's name and icon from where it should be in the PortableApps.com format.
|
||||||
|
My forum at PortableApps.com can be found [here](http://portableapps.com/node/54998).
|
||||||
|
|
||||||
# common.sh
|
# common.sh
|
||||||
common.sh is found in the PortableApps/LinuxPACom folder and is executed before the app. I mainly use it to set environment variables (such as HOME).
|
common.sh is found in the PortableApps/LinuxPACom folder and is executed before the app. I mainly use it to set environment variables (such as HOME).
|
||||||
|
|
||||||
# Simple App Setup
|
# Simple App Setup
|
||||||
Because apps aren't natively formated in the PortableApps.com format, if LinuxPA doesn't find the AppInfo.ini or appicon_\*.png in the App/AppInfo folder of the app it looks for them in the root direcory of the app (except it looks, nor for appicon_\*.png, but appicon.png)
|
Because apps aren't natively formated in the PortableApps.com format, if LinuxPA doesn't find the AppInfo.ini or appicon_\*.png in the App/AppInfo folder of the app it looks for them in the root directory of the app (except it looks, nor for appicon_\*.png, but appicon.png). If an AppInfo.ini file isn't found then the name of the app is grabbed from the folder name and it's category is set to other. It specifically looks for the lines starting with `Name=` and `Category=`
|
||||||
|
|
||||||
# AppImage Support
|
# AppImage Support
|
||||||
[AppImage Website](http://appimage.org)
|
[AppImage Website](http://appimage.org)
|
||||||
Right now AppImages are simply supported via the native linux executable support, but later I'm hoping to add downloading and automatic downloading support.
|
Right now AppImages are simply supported via the native linux executable support, but later I'm hoping to add downloading and automatic updating support later on.
|
||||||
|
|
||||||
# USB mount
|
# USB mount
|
||||||
Unfortunately Linux, by default, doesn't support running executables off of flash drives, requiring you to mount your drive with special mount arguments, I personally use the arguments `exec,noauto,nodev,nosuid,umask=0000`
|
Unfortunately Linux, by default, doesn't support running executables off of FAT formated flash drives, requiring you to mount your drive with special mount arguments or format in a linux friendly format (such as EXT4). I personally use the arguments `exec,noauto,nodev,nosuid,umask=0000`
|
||||||
|
|
||||||
# Screenshots
|
# Screenshots
|
||||||
Photos are found [Here](https://goo.gl/photos/VtBUL6DyZTMidj5n6)
|
Photos are found [Here](https://goo.gl/photos/VtBUL6DyZTMidj5n6)
|
||||||
|
|
||||||
# TODO (Might be in order)
|
# TODO (Might be in order)
|
||||||
1. MAKE IT BETTER
|
1. MAKE IT BETTER
|
||||||
1. Launching of .exe files via wine (wine will have to be installed on the host system, unless there is some portable wine (I may have found one))
|
|
||||||
1. Add settings menu
|
1. Add settings menu
|
||||||
1. Add updater for .AppImage files
|
1. Add updater for .AppImage files
|
||||||
1. Download .AppImage files (maybe)
|
1. Download .AppImage files (maybe)
|
||||||
1. Check if all apps are closed when it closes and ask if you want to force stop the apps.
|
1. Check if all apps are closed when it closes and ask if you want to force stop the apps.
|
||||||
|
1. Portable wine (Should be able to get a working version from PlayOnLinux, but I need to add a check to see if filesystem is EXT as Wine doesn't like filesystems w/o permission control)
|
||||||
|
|||||||
@@ -0,0 +1,272 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/nelsam/gxui"
|
||||||
|
"github.com/nelsam/gxui/math"
|
||||||
|
)
|
||||||
|
|
||||||
|
type app struct {
|
||||||
|
name string
|
||||||
|
cat string
|
||||||
|
appimg []string
|
||||||
|
lin []string
|
||||||
|
ex []string
|
||||||
|
icon gxui.Texture
|
||||||
|
dir string
|
||||||
|
ini *os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
type appExNode struct {
|
||||||
|
ap app
|
||||||
|
exInd int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *appExNode) launch() {
|
||||||
|
if wine {
|
||||||
|
var cmd *exec.Cmd
|
||||||
|
if !contains(a.ap.lin, a.ap.ex[a.exInd]) {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; wine \""+a.ap.ex[a.exInd]+"\"")
|
||||||
|
} else {
|
||||||
|
if comEnbld {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"")
|
||||||
|
} else {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Start()
|
||||||
|
}
|
||||||
|
var cmd *exec.Cmd
|
||||||
|
if comEnbld {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"")
|
||||||
|
} else {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"")
|
||||||
|
}
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *appExNode) Count() int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *appExNode) NodeAt(int) gxui.TreeNode {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *appExNode) ItemIndex(gxui.AdapterItem) int {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *appExNode) Item() gxui.AdapterItem {
|
||||||
|
if wine {
|
||||||
|
return a.ap.ex[a.exInd]
|
||||||
|
}
|
||||||
|
return a.ap.lin[a.exInd]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *appExNode) Create(the gxui.Theme) gxui.Control {
|
||||||
|
box := the.CreateLinearLayout()
|
||||||
|
box.SetDirection(gxui.LeftToRight)
|
||||||
|
box.SetVerticalAlignment(gxui.AlignMiddle)
|
||||||
|
img := the.CreateImage()
|
||||||
|
img.SetTexture(a.ap.icon)
|
||||||
|
img.SetExplicitSize(math.Size{H: 32, W: 32})
|
||||||
|
lbl := the.CreateLabel()
|
||||||
|
lbl.SetText(a.ap.ex[a.exInd])
|
||||||
|
box.AddChild(img)
|
||||||
|
box.AddChild(lbl)
|
||||||
|
box.OnDoubleClick(func(gxui.MouseEvent) {
|
||||||
|
a.launch()
|
||||||
|
})
|
||||||
|
return box
|
||||||
|
}
|
||||||
|
|
||||||
|
type appNode struct {
|
||||||
|
ap app
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *appNode) launch() {
|
||||||
|
if len(a.ap.ex) == 1 {
|
||||||
|
if wine {
|
||||||
|
var cmd *exec.Cmd
|
||||||
|
if !contains(a.ap.lin, a.ap.ex[0]) {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; wine \""+a.ap.ex[0]+"\"")
|
||||||
|
} else {
|
||||||
|
if comEnbld {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"")
|
||||||
|
} else {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Start()
|
||||||
|
} else {
|
||||||
|
var cmd *exec.Cmd
|
||||||
|
if comEnbld {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"")
|
||||||
|
} else {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"")
|
||||||
|
}
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Start()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if wine {
|
||||||
|
var cmd *exec.Cmd
|
||||||
|
if len(a.ap.lin) == 0 {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; wine \""+a.ap.ex[0]+"\"")
|
||||||
|
} else {
|
||||||
|
var ind int
|
||||||
|
for i, v := range a.ap.lin {
|
||||||
|
if strings.HasSuffix(v, ".sh") {
|
||||||
|
ind = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if comEnbld {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[ind]+"\"")
|
||||||
|
} else {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[ind]+"\"")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Start()
|
||||||
|
} else {
|
||||||
|
if len(a.ap.lin) != 0 {
|
||||||
|
var ind int
|
||||||
|
for i, v := range a.ap.lin {
|
||||||
|
if strings.HasSuffix(v, ".sh") {
|
||||||
|
ind = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var cmd *exec.Cmd
|
||||||
|
if comEnbld {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[ind]+"\"")
|
||||||
|
} else {
|
||||||
|
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[ind]+"\"")
|
||||||
|
}
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *appNode) Count() int {
|
||||||
|
if wine {
|
||||||
|
if len(a.ap.ex) > 1 {
|
||||||
|
return len(a.ap.ex)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if len(a.ap.lin) > 1 {
|
||||||
|
return len(a.ap.lin)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *appNode) NodeAt(i int) gxui.TreeNode {
|
||||||
|
return &appExNode{ap: a.ap, exInd: i}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *appNode) ItemIndex(item gxui.AdapterItem) int {
|
||||||
|
if wine {
|
||||||
|
for i, v := range a.ap.ex {
|
||||||
|
if v == item {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for i, v := range a.ap.lin {
|
||||||
|
if v == item {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *appNode) Item() gxui.AdapterItem {
|
||||||
|
return a.ap.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *appNode) Create(the gxui.Theme) gxui.Control {
|
||||||
|
box := the.CreateLinearLayout()
|
||||||
|
box.SetDirection(gxui.LeftToRight)
|
||||||
|
box.SetPadding(math.CreateSpacing(2))
|
||||||
|
box.SetVerticalAlignment(gxui.AlignMiddle)
|
||||||
|
img := the.CreateImage()
|
||||||
|
if a.ap.icon != nil {
|
||||||
|
img.SetTexture(a.ap.icon)
|
||||||
|
}
|
||||||
|
img.SetExplicitSize(math.Size{H: 32, W: 32})
|
||||||
|
lbl := the.CreateLabel()
|
||||||
|
lbl.SetText(a.ap.name)
|
||||||
|
box.AddChild(img)
|
||||||
|
box.AddChild(lbl)
|
||||||
|
box.OnDoubleClick(func(gxui.MouseEvent) {
|
||||||
|
a.launch()
|
||||||
|
})
|
||||||
|
return box
|
||||||
|
}
|
||||||
|
|
||||||
|
type catAdap struct {
|
||||||
|
gxui.AdapterBase
|
||||||
|
cat string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *catAdap) setCat(cat string) {
|
||||||
|
a.cat = cat
|
||||||
|
a.DataChanged(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *catAdap) refresh() {
|
||||||
|
a.DataChanged(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *catAdap) Count() int {
|
||||||
|
if wine {
|
||||||
|
return len(master[a.cat])
|
||||||
|
}
|
||||||
|
return len(linmaster[a.cat])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *catAdap) NodeAt(i int) gxui.TreeNode {
|
||||||
|
if wine {
|
||||||
|
return &appNode{ap: master[a.cat][i]}
|
||||||
|
}
|
||||||
|
return &appNode{ap: linmaster[a.cat][i]}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *catAdap) Size(gxui.Theme) math.Size {
|
||||||
|
return math.Size{H: 34, W: math.MaxSize.W}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *catAdap) ItemIndex(item gxui.AdapterItem) int {
|
||||||
|
if wine {
|
||||||
|
for i, v := range master[a.cat] {
|
||||||
|
if v.name == item {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for i, v := range linmaster[a.cat] {
|
||||||
|
if v.name == item {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
@@ -1,150 +1,83 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"os/exec"
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
|
"github.com/nelsam/gxui"
|
||||||
"github.com/nelsam/gxui/drivers/gl"
|
"github.com/nelsam/gxui/drivers/gl"
|
||||||
|
"github.com/nelsam/gxui/themes/dark"
|
||||||
|
"github.com/nelsam/gxui/themes/light"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
version = "1.1.0.0"
|
||||||
|
defIni = "[basic]\ntheme=dk"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
appMaster map[string][]prtap
|
dr gxui.Driver
|
||||||
|
th gxui.Theme
|
||||||
|
master map[string][]app
|
||||||
|
linmaster map[string][]app
|
||||||
cats []string
|
cats []string
|
||||||
conf *os.File
|
lin []string
|
||||||
common string
|
wine bool
|
||||||
commEnbl bool
|
comEnbld bool
|
||||||
|
darkTheme = true
|
||||||
)
|
)
|
||||||
|
|
||||||
type prtap struct {
|
|
||||||
name string
|
|
||||||
cat string
|
|
||||||
ex string
|
|
||||||
desc string
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
commEnbl = true
|
updated := false
|
||||||
appMaster = make(map[string][]prtap)
|
os.MkdirAll("PortableApps/LinuxPACom", 0777)
|
||||||
os.Mkdir("PortableApps", 0777)
|
stat := versionDL()
|
||||||
os.Mkdir("PortableApps/LinuxPACom", 0777)
|
if stat {
|
||||||
common = "PortableApps/LinuxPACom/common.sh"
|
res := getVersionFileInfo()
|
||||||
_, err := os.Open(common)
|
if res != "Error!" {
|
||||||
if os.IsNotExist(err) {
|
stat = checkForUpdate(res)
|
||||||
commEnbl = false
|
if stat {
|
||||||
}
|
downloadUpdate(res)
|
||||||
pa, err := os.Open("PortableApps")
|
updated = true
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
appstmp, _ := pa.Readdir(-1)
|
|
||||||
var folds []string
|
|
||||||
for _, v := range appstmp {
|
|
||||||
if v.IsDir() && v.Name() != "LinuxPACom" {
|
|
||||||
folds = append(folds, v.Name())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.Strings(folds)
|
|
||||||
for _, v := range folds {
|
|
||||||
fi, _ := os.Open("PortableApps/" + v)
|
|
||||||
pat := processApp(fi)
|
|
||||||
if (pat != prtap{}) {
|
|
||||||
if _, ok := appMaster[pat.cat]; !ok {
|
|
||||||
cats = append(cats, pat.cat)
|
|
||||||
}
|
|
||||||
appMaster[pat.cat] = append(appMaster[pat.cat], pat)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gl.StartDriver(uiMain)
|
|
||||||
}
|
|
||||||
|
|
||||||
func processApp(fi *os.File) (out prtap) {
|
|
||||||
fis, _ := fi.Readdir(-1)
|
|
||||||
if fil, err := os.Open(fi.Name() + "/App/AppInfo/appinfo.ini"); err == nil {
|
|
||||||
out.name = getName(fil)
|
|
||||||
fil, _ = os.Open(fi.Name() + "/App/AppInfo/appinfo.ini")
|
|
||||||
out.cat = getCat(fil)
|
|
||||||
} else if fil, err := os.Open(fi.Name() + "/appinfo.ini"); err == nil {
|
|
||||||
out.name = getName(fil)
|
|
||||||
fil, _ = os.Open(fi.Name() + "/appinfo.ini")
|
|
||||||
out.cat = getCat(fil)
|
|
||||||
} else {
|
} else {
|
||||||
out.cat = "other"
|
fmt.Println("Failed DL")
|
||||||
}
|
}
|
||||||
if out.name == "" {
|
} else {
|
||||||
out.name = path.Base(fi.Name())
|
fmt.Println("Failed Version File Info")
|
||||||
}
|
}
|
||||||
if out.cat == "" {
|
} else {
|
||||||
out.cat = "other"
|
fmt.Println("Failed Version DL")
|
||||||
}
|
}
|
||||||
//executable detection
|
if updated {
|
||||||
wd, _ := os.Getwd()
|
cmd := exec.Command("./LinuxPA")
|
||||||
var rdr *bufio.Reader
|
cmd.Stdin = os.Stdin
|
||||||
for _, v := range fis {
|
cmd.Stdout = os.Stdout
|
||||||
fil, err := os.Open(wd + "/" + fi.Name() + "/" + v.Name())
|
cmd.Start()
|
||||||
if err == nil {
|
fmt.Println("updated!")
|
||||||
stat, _ := fil.Stat()
|
} else {
|
||||||
if !stat.IsDir() {
|
master = make(map[string][]app)
|
||||||
rdr = bufio.NewReader(fil)
|
linmaster = make(map[string][]app)
|
||||||
shebang := []byte{'#', '!'}
|
gl.StartDriver(appMain)
|
||||||
two := make([]byte, 2)
|
|
||||||
rdr.Read(two)
|
|
||||||
if reflect.DeepEqual(shebang, two) {
|
|
||||||
out.ex = wd + "/" + fi.Name() + "/" + v.Name()
|
|
||||||
rdr.Reset(fil)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, v := range fis {
|
|
||||||
fil, err := os.Open(wd + "/" + fi.Name() + "/" + v.Name())
|
|
||||||
if err == nil {
|
|
||||||
stat, _ := fil.Stat()
|
|
||||||
if !stat.IsDir() {
|
|
||||||
rdr = bufio.NewReader(fil)
|
|
||||||
thr := make([]byte, 4)
|
|
||||||
rdr.Read(thr)
|
|
||||||
if strings.Contains(string(thr), "ELF") {
|
|
||||||
out.ex = wd + "/" + fi.Name() + "/" + v.Name()
|
|
||||||
rdr.Reset(fil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return prtap{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCat(fi *os.File) (out string) {
|
func appMain(dri gxui.Driver) {
|
||||||
rdr := bufio.NewReader(fi)
|
dr = dri
|
||||||
var err error
|
setup()
|
||||||
var ln []byte
|
if darkTheme {
|
||||||
for err == nil {
|
th = dark.CreateTheme(dr)
|
||||||
ln, _, err = rdr.ReadLine()
|
} else {
|
||||||
str := string(ln)
|
th = light.CreateTheme(dr)
|
||||||
if strings.HasPrefix(str, "Category=") {
|
|
||||||
out = strings.TrimPrefix(str, "Category=")
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
th = dark.CreateTheme(dr)
|
||||||
return
|
ui()
|
||||||
}
|
}
|
||||||
|
|
||||||
func getName(fi *os.File) (out string) {
|
func contains(arr []string, str string) bool {
|
||||||
rdr := bufio.NewReader(fi)
|
for _, v := range arr {
|
||||||
var err error
|
if v == str {
|
||||||
var ln []byte
|
return true
|
||||||
for err == nil {
|
|
||||||
ln, _, err = rdr.ReadLine()
|
|
||||||
str := string(ln)
|
|
||||||
if strings.HasPrefix(str, "Name=") {
|
|
||||||
out = strings.TrimPrefix(str, "Name=")
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
-103
@@ -1,103 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
"image/draw"
|
|
||||||
_ "image/png"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/nelsam/gxui"
|
|
||||||
"github.com/nelsam/gxui/math"
|
|
||||||
)
|
|
||||||
|
|
||||||
type prtapAdap struct {
|
|
||||||
gxui.AdapterBase
|
|
||||||
apps []prtap
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *prtapAdap) SetApps(apps []prtap) {
|
|
||||||
p.apps = apps
|
|
||||||
p.DataChanged(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *prtapAdap) Count() int {
|
|
||||||
return len(p.apps)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *prtapAdap) Create(th gxui.Theme, index int) gxui.Control {
|
|
||||||
box := th.CreateLinearLayout()
|
|
||||||
box.SetPadding(math.CreateSpacing(2))
|
|
||||||
box.SetDirection(gxui.LeftToRight)
|
|
||||||
box.SetVerticalAlignment(gxui.AlignMiddle)
|
|
||||||
dir := path.Dir(p.apps[index].ex)
|
|
||||||
if fold, err := os.Open(dir + "/App/AppInfo"); err == nil {
|
|
||||||
var pics []string
|
|
||||||
fi, _ := fold.Readdirnames(-1)
|
|
||||||
for _, v := range fi {
|
|
||||||
if strings.HasPrefix(v, "appicon_") && strings.HasSuffix(v, ".png") {
|
|
||||||
pics = append(pics, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(pics) > 0 {
|
|
||||||
ind := sort.SearchStrings(pics, "appicon_128.png")
|
|
||||||
if ind == len(pics) {
|
|
||||||
ind = len(pics) - 1
|
|
||||||
}
|
|
||||||
imgfi, _ := os.Open(dir + "/App/AppInfo/" + pics[ind])
|
|
||||||
img, _, err := image.Decode(imgfi)
|
|
||||||
if err == nil {
|
|
||||||
rgba := image.NewRGBA(img.Bounds())
|
|
||||||
draw.Draw(rgba, img.Bounds(), img, image.ZP, draw.Src)
|
|
||||||
tex := dr.CreateTexture(rgba, 1)
|
|
||||||
icon := th.CreateImage()
|
|
||||||
icon.SetExplicitSize(math.Size{H: 32, W: 32})
|
|
||||||
icon.SetTexture(tex)
|
|
||||||
box.AddChild(icon)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if fi, err := os.Open(dir + "/appicon.png"); err == nil {
|
|
||||||
img, _, err := image.Decode(fi)
|
|
||||||
if err == nil {
|
|
||||||
rgba := image.NewRGBA(img.Bounds())
|
|
||||||
draw.Draw(rgba, img.Bounds(), img, image.ZP, draw.Src)
|
|
||||||
tex := dr.CreateTexture(rgba, 1)
|
|
||||||
icon := th.CreateImage()
|
|
||||||
icon.SetExplicitSize(math.Size{H: 32, W: 32})
|
|
||||||
icon.SetTexture(tex)
|
|
||||||
box.AddChild(icon)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//Creating empty Image so that names line up
|
|
||||||
icon := th.CreateImage()
|
|
||||||
icon.SetExplicitSize(math.Size{H: 32, W: 32})
|
|
||||||
box.AddChild(icon)
|
|
||||||
}
|
|
||||||
lbl := th.CreateLabel()
|
|
||||||
lbl.SetText(p.apps[index].name)
|
|
||||||
box.AddChild(lbl)
|
|
||||||
return box
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *prtapAdap) ItemAt(index int) gxui.AdapterItem {
|
|
||||||
return p.apps[index]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *prtapAdap) ItemIndex(item gxui.AdapterItem) int {
|
|
||||||
it, ok := item.(prtap)
|
|
||||||
if !ok {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
for i, v := range p.apps {
|
|
||||||
if v == it {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *prtapAdap) Size(gxui.Theme) math.Size {
|
|
||||||
return math.Size{W: math.MaxSize.W, H: 36}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,210 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
"image/draw"
|
||||||
|
_ "image/png"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/nelsam/gxui"
|
||||||
|
)
|
||||||
|
|
||||||
|
const ()
|
||||||
|
|
||||||
|
func setup() {
|
||||||
|
PortableAppsFold, err := os.Open("PortableApps")
|
||||||
|
if PAStat, _ := PortableAppsFold.Stat(); err != nil || !PAStat.IsDir() {
|
||||||
|
os.Mkdir("PortableApps", 0777)
|
||||||
|
PortableAppsFold, err = os.Open("PortableApps")
|
||||||
|
if err != nil {
|
||||||
|
panic("Can't find PortableApps folder and can't create one!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, err = os.Open("PortableApps/LinuxPACom"); err != nil {
|
||||||
|
os.Mkdir("PortableApps/LinuxPACom", 0777)
|
||||||
|
}
|
||||||
|
fmt.Println(err)
|
||||||
|
_, err = os.Open("PortableApps/LinuxPACom/common.sh")
|
||||||
|
if err == nil {
|
||||||
|
comEnbld = true
|
||||||
|
}
|
||||||
|
fi, err := os.Open("PortableApps/LinuxPACom/Info.ini")
|
||||||
|
if err != nil {
|
||||||
|
fi, err = os.Create("PortableApps/LinuxPACom/Info.ini")
|
||||||
|
if err == nil {
|
||||||
|
wrt := bufio.NewWriter(fi)
|
||||||
|
wrt.WriteString(defIni)
|
||||||
|
wrt.Flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
rdr := bufio.NewReader(fi)
|
||||||
|
for err != nil {
|
||||||
|
ln, _, error := rdr.ReadLine()
|
||||||
|
err = error
|
||||||
|
str := string(ln)
|
||||||
|
if strings.HasPrefix(str, "theme=") {
|
||||||
|
str = strings.TrimPrefix(str, "theme=")
|
||||||
|
if str == "lt" {
|
||||||
|
darkTheme = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PAFolds, _ := PortableAppsFold.Readdirnames(-1)
|
||||||
|
sort.Strings(PAFolds)
|
||||||
|
for _, v := range PAFolds {
|
||||||
|
fold, _ := os.Open("PortableApps/" + v)
|
||||||
|
if stat, _ := fold.Stat(); stat.IsDir() && stat.Name() != "PortableApps.com" && stat.Name() != "LinuxPACom" {
|
||||||
|
ap := processApp("PortableApps/" + v)
|
||||||
|
if !reflect.DeepEqual(ap, app{}) {
|
||||||
|
if _, ok := master[ap.cat]; !ok {
|
||||||
|
cats = append(cats, ap.cat)
|
||||||
|
sort.Strings(cats)
|
||||||
|
}
|
||||||
|
if len(ap.lin) != 0 {
|
||||||
|
if _, ok := linmaster[ap.cat]; !ok {
|
||||||
|
lin = append(lin, ap.cat)
|
||||||
|
sort.Strings(lin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
master[ap.cat] = append(master[ap.cat], ap)
|
||||||
|
if len(ap.lin) != 0 {
|
||||||
|
linmaster[ap.cat] = append(linmaster[ap.cat], ap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func processApp(fold string) (out app) {
|
||||||
|
wd, _ := os.Getwd()
|
||||||
|
out.dir = wd + "/" + fold
|
||||||
|
out.ini = findInfo(fold)
|
||||||
|
if out.ini != nil {
|
||||||
|
out.name = getName(out.ini)
|
||||||
|
out.ini = findInfo(fold)
|
||||||
|
out.cat = getCat(out.ini)
|
||||||
|
out.ini = findInfo(fold)
|
||||||
|
}
|
||||||
|
if out.name == "" {
|
||||||
|
out.name = strings.TrimPrefix(fold, "PortableApps/")
|
||||||
|
}
|
||||||
|
if out.cat == "" {
|
||||||
|
out.cat = "Other"
|
||||||
|
}
|
||||||
|
out.icon = getIcon(fold)
|
||||||
|
folder, _ := os.Open(fold)
|
||||||
|
fis, _ := folder.Readdirnames(-1)
|
||||||
|
for _, v := range fis {
|
||||||
|
tmp, _ := os.Open(fold + "/" + v)
|
||||||
|
if stat, _ := tmp.Stat(); stat.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(strings.ToLower(v), ".appimage") {
|
||||||
|
out.appimg = append(out.appimg, v)
|
||||||
|
out.ex = append(out.ex, v)
|
||||||
|
out.lin = append(out.lin, v)
|
||||||
|
} else if strings.HasSuffix(strings.ToLower(v), ".exe") {
|
||||||
|
out.ex = append(out.ex, v)
|
||||||
|
} else {
|
||||||
|
btys := make([]byte, 4)
|
||||||
|
rdr := bufio.NewReader(tmp)
|
||||||
|
rdr.Read(btys)
|
||||||
|
if (strings.Contains(strings.ToLower(string(btys)), "elf") && !strings.HasSuffix(strings.ToLower(v), ".so") && !strings.Contains(v, ".so.")) || strings.HasPrefix(strings.ToLower(string(btys)), "#!") {
|
||||||
|
out.ex = append(out.ex, v)
|
||||||
|
out.lin = append(out.lin, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(out.ex) == 0 {
|
||||||
|
return app{}
|
||||||
|
}
|
||||||
|
if len(out.lin) == 0 {
|
||||||
|
out.name += " (Wine)"
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCat(ini *os.File) string {
|
||||||
|
rdr := bufio.NewReader(ini)
|
||||||
|
var ret string
|
||||||
|
for line, _, err := rdr.ReadLine(); err == nil; line, _, err = rdr.ReadLine() {
|
||||||
|
if strings.HasPrefix(string(line), "Category=") {
|
||||||
|
ret = strings.TrimPrefix(string(line), "Category=")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rdr.Reset(ini)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func getName(ini *os.File) string {
|
||||||
|
rdr := bufio.NewReader(ini)
|
||||||
|
var ret string
|
||||||
|
for line, _, err := rdr.ReadLine(); err == nil; line, _, err = rdr.ReadLine() {
|
||||||
|
if strings.HasPrefix(string(line), "Name=") {
|
||||||
|
ret = strings.TrimPrefix(string(line), "Name=")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rdr.Reset(ini)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func getIcon(fold string) gxui.Texture {
|
||||||
|
var pic *os.File
|
||||||
|
if folder, err := os.Open(fold + "/App/AppInfo"); err == nil {
|
||||||
|
fis, _ := folder.Readdir(-1)
|
||||||
|
var pics []string
|
||||||
|
for _, v := range fis {
|
||||||
|
if !v.IsDir() && strings.HasSuffix(strings.ToLower(v.Name()), ".png") && strings.HasPrefix(strings.ToLower(v.Name()), "appicon_") {
|
||||||
|
pics = append(pics, v.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(pics)
|
||||||
|
if len(pics) > 1 {
|
||||||
|
var ind int
|
||||||
|
if !contains(pics, "appicon_32.png") {
|
||||||
|
ind = len(pics) - 1
|
||||||
|
} else {
|
||||||
|
ind = sort.SearchStrings(pics, "appicon_32.png")
|
||||||
|
}
|
||||||
|
pic, _ = os.Open(fold + "/App/AppInfo/" + pics[ind])
|
||||||
|
}
|
||||||
|
} else if fi, err := os.Open(fold + "/appicon.png"); err == nil {
|
||||||
|
pic = fi
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
img, _, err := image.Decode(pic)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
rgba := image.NewRGBA(img.Bounds())
|
||||||
|
draw.Draw(rgba, img.Bounds(), img, image.ZP, draw.Src)
|
||||||
|
ret := dr.CreateTexture(rgba, 1)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func findInfo(fold string) *os.File {
|
||||||
|
tmp, err := os.Open(fold + "/App/AppInfo")
|
||||||
|
if err == nil {
|
||||||
|
fis, _ := tmp.Readdirnames(-1)
|
||||||
|
for _, v := range fis {
|
||||||
|
if strings.ToLower(v) == "appinfo.ini" {
|
||||||
|
tmp, _ := os.Open(fold + "/App/AppInfo/" + v)
|
||||||
|
return tmp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if fi, err := os.Open(fold + "/appinfo.ini"); err == nil {
|
||||||
|
return fi
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Executable → Regular
@@ -3,62 +3,64 @@ package main
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
|
||||||
|
|
||||||
"github.com/nelsam/gxui"
|
"github.com/nelsam/gxui"
|
||||||
"github.com/nelsam/gxui/themes/dark"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func ui() {
|
||||||
dr gxui.Driver
|
catListAdap := &StrList{}
|
||||||
)
|
appListAdap := &catAdap{}
|
||||||
|
catListAdap.SetStrings(lin)
|
||||||
func uiMain(dri gxui.Driver) {
|
|
||||||
dr = dri
|
|
||||||
catAdap := &StrList{}
|
|
||||||
catAdap.SetStrings(cats)
|
|
||||||
appAdap := &prtapAdap{}
|
|
||||||
th := dark.CreateTheme(dr)
|
|
||||||
win := th.CreateWindow(500, 500, "LinuxPA")
|
win := th.CreateWindow(500, 500, "LinuxPA")
|
||||||
top := th.CreateLinearLayout()
|
top := th.CreateLinearLayout()
|
||||||
top.SetDirection(gxui.BottomToTop)
|
top.SetDirection(gxui.BottomToTop)
|
||||||
top.SetHorizontalAlignment(gxui.AlignRight)
|
splBox := th.CreateLinearLayout()
|
||||||
spl := th.CreateSplitterLayout()
|
spl := th.CreateSplitterLayout()
|
||||||
spl.SetOrientation(gxui.Horizontal)
|
spl.SetOrientation(gxui.Horizontal)
|
||||||
catlist := th.CreateList()
|
catList := th.CreateList()
|
||||||
catlist.SetAdapter(catAdap)
|
catList.SetAdapter(catListAdap)
|
||||||
catlist.OnItemClicked(func(_ gxui.MouseEvent, it gxui.AdapterItem) {
|
catList.OnSelectionChanged(func(it gxui.AdapterItem) {
|
||||||
str := it.(string)
|
appListAdap.setCat(it.(string))
|
||||||
appAdap.SetApps(appMaster[str])
|
|
||||||
})
|
})
|
||||||
applist := th.CreateList()
|
appList := th.CreateTree()
|
||||||
applist.SetAdapter(appAdap)
|
appList.SetAdapter(appListAdap)
|
||||||
spl.AddChild(catlist)
|
spl.AddChild(catList)
|
||||||
spl.AddChild(applist)
|
spl.AddChild(appList)
|
||||||
but := th.CreateLinearLayout()
|
splBox.AddChild(spl)
|
||||||
but.SetDirection(gxui.RightToLeft)
|
butBox := th.CreateLinearLayout()
|
||||||
launch := th.CreateButton()
|
butBox.SetDirection(gxui.LeftToRight)
|
||||||
launch.SetText("Launch!")
|
if _, err := exec.LookPath("wine"); err == nil {
|
||||||
launch.OnClick(func(gxui.MouseEvent) {
|
wineBut := th.CreateButton()
|
||||||
if appAdap.ItemIndex(applist.Selected()) != -1 {
|
wineBut.SetType(gxui.ToggleButton)
|
||||||
app := applist.Selected().(prtap)
|
wineBut.SetChecked(wine)
|
||||||
dir, fi := path.Split(app.ex)
|
wineBut.SetText("Show Windows Apps")
|
||||||
var cmd *exec.Cmd
|
wineBut.OnClick(func(gxui.MouseEvent) {
|
||||||
if commEnbl {
|
wine = wineBut.IsChecked()
|
||||||
cmd = exec.Command("/bin/sh", "-c", ". "+common+" || exit 1;cd \""+dir+"\"; \"./"+fi+"\"")
|
appListAdap.refresh()
|
||||||
|
if wineBut.IsChecked() {
|
||||||
|
catListAdap.SetStrings(cats)
|
||||||
|
wineBut.SetText("Hide Windows Apps")
|
||||||
} else {
|
} else {
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+dir+"\"; \"./"+fi+"\"")
|
catListAdap.SetStrings(lin)
|
||||||
|
wineBut.SetText("Show Windows Apps")
|
||||||
}
|
}
|
||||||
cmd.Stdin = os.Stdin
|
})
|
||||||
|
_, err := os.Open("Start.exe")
|
||||||
|
if err == nil {
|
||||||
|
pa := th.CreateButton()
|
||||||
|
pa.SetText("Open PortableApps Launcher")
|
||||||
|
pa.OnClick(func(gxui.MouseEvent) {
|
||||||
|
cmd := exec.Command("wine", "Start.exe")
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
cmd.Start()
|
cmd.Start()
|
||||||
|
})
|
||||||
|
butBox.AddChild(pa)
|
||||||
}
|
}
|
||||||
})
|
butBox.AddChild(wineBut)
|
||||||
but.AddChild(launch)
|
}
|
||||||
top.AddChild(but)
|
top.AddChild(butBox)
|
||||||
top.AddChild(spl)
|
top.AddChild(splBox)
|
||||||
win.AddChild(top)
|
win.AddChild(top)
|
||||||
win.OnClose(func() {
|
win.OnClose(dr.Terminate)
|
||||||
dr.Terminate()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
versionURL = "https://www.dropbox.com/s/a0xizzo0a4vsfqt/Version?dl=1"
|
||||||
|
downloadURL = "https://github.com/CalebQ42/LinuxPA/releases/download/vXXX/LinuxPA"
|
||||||
|
)
|
||||||
|
|
||||||
|
//Thanks to https://www.socketloop.com/tutorials/golang-download-file-example
|
||||||
|
//For some of the code
|
||||||
|
|
||||||
|
//Returns if success
|
||||||
|
func versionDL() bool {
|
||||||
|
versionFile, err := os.Create("PortableApps/LinuxPACom/Version")
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
versionFile.Chmod(0777)
|
||||||
|
check := http.Client{
|
||||||
|
CheckRedirect: func(r *http.Request, via []*http.Request) error {
|
||||||
|
r.URL.Opaque = r.URL.Path
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
response, err := check.Get(versionURL)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
_, err = io.Copy(versionFile, response.Body)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func getVersionFileInfo() string {
|
||||||
|
fil, err := os.Open("PortableApps/LinuxPACom/Version")
|
||||||
|
if err != nil {
|
||||||
|
return "Error!"
|
||||||
|
}
|
||||||
|
rdr := bufio.NewReader(fil)
|
||||||
|
out, _, _ := rdr.ReadLine()
|
||||||
|
return string(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkForUpdate(new string) bool {
|
||||||
|
curSlice := strings.Split(version, ".")
|
||||||
|
newSlice := strings.Split(new, ".")
|
||||||
|
curNums := make([]int, 4)
|
||||||
|
newNums := make([]int, 4)
|
||||||
|
for i, v := range curSlice {
|
||||||
|
num, err := strconv.Atoi(v)
|
||||||
|
if err == nil {
|
||||||
|
curNums[i] = num
|
||||||
|
}
|
||||||
|
num, err = strconv.Atoi(newSlice[i])
|
||||||
|
if err == nil {
|
||||||
|
newNums[i] = num
|
||||||
|
}
|
||||||
|
if newNums[i] > curNums[i] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadUpdate(newVersion string) bool {
|
||||||
|
url := strings.Replace(downloadURL, "XXX", newVersion, -1)
|
||||||
|
err := os.Rename("LinuxPA", ".LinuxPA.old")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
fil, err := os.Create("LinuxPA")
|
||||||
|
fil.Chmod(0777)
|
||||||
|
defer fil.Close()
|
||||||
|
if err != nil {
|
||||||
|
os.Rename(".LinuxPA.old", "LinuxPA")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
check := http.Client{
|
||||||
|
CheckRedirect: func(r *http.Request, via []*http.Request) error {
|
||||||
|
r.URL.Opaque = r.URL.Path
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
re, err := check.Get(url)
|
||||||
|
defer re.Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
_, err = io.Copy(fil, re.Body)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user