mirror of
https://github.com/PeernetOfficial/core.git
synced 2026-07-17 02:47:51 +01:00
138 lines
3.1 KiB
Go
138 lines
3.1 KiB
Go
/*
|
|
File Name: Read Package.go
|
|
Copyright: 2021 Peernet s.r.o.
|
|
Author: Peter Kleissner
|
|
*/
|
|
|
|
package system
|
|
|
|
import (
|
|
"archive/zip"
|
|
"io/ioutil"
|
|
"path"
|
|
"strings"
|
|
|
|
"gopkg.in/ini.v1"
|
|
)
|
|
|
|
type UpdatePackage struct {
|
|
Filename string // Filename of the update package
|
|
Err error // Parsing error if any
|
|
Header *IniFile // Header info
|
|
Reader *zip.ReadCloser // Access to files in the ZIP file
|
|
}
|
|
|
|
// IniFile contains the parsed data from the info.ini file
|
|
type IniFile struct {
|
|
Name string // Name of the package
|
|
Organization string // Organization that created this package
|
|
Architecture string // Target architecture. For example "windows/amd64".
|
|
Actions []IniAction // Actions to take
|
|
}
|
|
|
|
type IniAction struct {
|
|
Action string `ini:"action"` // Action: extract, delete
|
|
Source string `ini:"source"` // Folder or file in the ZIP file
|
|
Target string `ini:"target"` // Target folder or file. Certain virtual folders such as "%plugins%" are supported.
|
|
}
|
|
|
|
const IniFilename = "info.ini"
|
|
|
|
// ParseUpdateFiles returns a list of parsed update packages.
|
|
// It will check each file in the directory if a ZIP file containing a valid info.ini file.
|
|
// The caller must close all returned readers.
|
|
func ParseUpdateFiles(Directory string) (files []UpdatePackage, err error) {
|
|
// check all files in the directory
|
|
filesDir, err := ioutil.ReadDir(Directory)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, file := range filesDir {
|
|
if file.IsDir() {
|
|
continue
|
|
}
|
|
|
|
filename := file.Name()
|
|
|
|
// ZIP file?
|
|
if strings.ToLower(path.Ext(filename)) == ".zip" {
|
|
filenamePath := path.Join(Directory, filename)
|
|
|
|
// check if the ZIP archive contains a info.ini file
|
|
reader, err := zip.OpenReader(filenamePath)
|
|
if err != nil { // invalid ZIP file
|
|
continue
|
|
}
|
|
|
|
// read info.ini file
|
|
file, err := reader.Open(IniFilename)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
data, err := ioutil.ReadAll(file)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
header, err := ParseIniFile(data)
|
|
|
|
files = append(files, UpdatePackage{Filename: filenamePath, Err: err, Header: header, Reader: reader})
|
|
}
|
|
}
|
|
|
|
return files, nil
|
|
}
|
|
|
|
func ParseIniFile(data []byte) (header *IniFile, err error) {
|
|
inidata, err := ini.Load(data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// parse the main section first
|
|
section, err := inidata.GetSection("main")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
name, err := section.GetKey("name")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
organization, err := section.GetKey("organization")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
architecture, err := section.GetKey("architecture")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
header = &IniFile{
|
|
Name: name.String(),
|
|
Organization: organization.String(),
|
|
Architecture: architecture.String(),
|
|
}
|
|
|
|
// parse any other section
|
|
for _, section := range inidata.Sections() {
|
|
if section.Name() == "main" || section.Name() == "DEFAULT" {
|
|
continue
|
|
}
|
|
|
|
var action IniAction
|
|
|
|
if section.MapTo(&action) != nil {
|
|
continue
|
|
}
|
|
|
|
header.Actions = append(header.Actions, action)
|
|
}
|
|
|
|
return header, nil
|
|
}
|