From 7a5f7e443a51455acb307e9212377d7cfaedefac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Henrique=20Guard=C3=A3o=20Gandarez?= <782854+gandarez@users.noreply.github.com> Date: Sat, 21 Nov 2020 03:46:17 -0300 Subject: [PATCH] Make more libraries available (#1917) * Make more libraries available to plugin dvelopment * Add Unzip function to util --- cmd/micro/initlua.go | 3 +++ internal/lua/lua.go | 26 +++++++++++++++++++ internal/util/util.go | 55 +++++++++++++++++++++++++++++++++++++++++ runtime/help/plugins.md | 3 +++ 4 files changed, 87 insertions(+) diff --git a/cmd/micro/initlua.go b/cmd/micro/initlua.go index 9d90b482..2ed94c3d 100644 --- a/cmd/micro/initlua.go +++ b/cmd/micro/initlua.go @@ -144,6 +144,9 @@ func luaImportMicroUtil() *lua.LTable { ulua.L.SetField(pkg, "GetLeadingWhitespace", luar.New(ulua.L, util.LuaGetLeadingWhitespace)) ulua.L.SetField(pkg, "IsWordChar", luar.New(ulua.L, util.LuaIsWordChar)) ulua.L.SetField(pkg, "String", luar.New(ulua.L, util.String)) + ulua.L.SetField(pkg, "Unzip", luar.New(ulua.L, util.Unzip)) + ulua.L.SetField(pkg, "Version", luar.New(ulua.L, util.Version)) + ulua.L.SetField(pkg, "SemVersion", luar.New(ulua.L, util.SemVersion)) ulua.L.SetField(pkg, "CharacterCountInString", luar.New(ulua.L, util.CharacterCountInString)) ulua.L.SetField(pkg, "RuneStr", luar.New(ulua.L, func(r rune) string { return string(r) diff --git a/internal/lua/lua.go b/internal/lua/lua.go index 9e502533..59ca6c45 100644 --- a/internal/lua/lua.go +++ b/internal/lua/lua.go @@ -1,6 +1,7 @@ package lua import ( + "archive/zip" "bytes" "errors" "fmt" @@ -9,6 +10,7 @@ import ( "math" "math/rand" "net" + "net/http" "os" "path" "path/filepath" @@ -74,6 +76,10 @@ func Import(pkg string) *lua.LTable { return importUtf8() case "humanize": return importHumanize() + case "net/http", "http": + return importHTTP() + case "archive/zip": + return importArchiveZip() default: return nil } @@ -383,6 +389,7 @@ func importOs() *lua.LTable { L.SetField(pkg, "Symlink", luar.New(L, os.Symlink)) L.SetField(pkg, "TempDir", luar.New(L, os.TempDir)) L.SetField(pkg, "Truncate", luar.New(L, os.Truncate)) + L.SetField(pkg, "UserHomeDir", luar.New(L, os.UserHomeDir)) return pkg } @@ -570,3 +577,22 @@ func importHumanize() *lua.LTable { return pkg } + +func importHTTP() *lua.LTable { + pkg := L.NewTable() + + L.SetField(pkg, "Get", luar.New(L, http.Get)) + L.SetField(pkg, "Post", luar.New(L, http.Post)) + + return pkg +} + +func importArchiveZip() *lua.LTable { + pkg := L.NewTable() + + L.SetField(pkg, "OpenReader", luar.New(L, zip.OpenReader)) + L.SetField(pkg, "NewReader", luar.New(L, zip.NewReader)) + L.SetField(pkg, "NewWriter", luar.New(L, zip.NewWriter)) + + return pkg +} diff --git a/internal/util/util.go b/internal/util/util.go index a40f9062..667b8565 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -1,9 +1,11 @@ package util import ( + "archive/zip" "bytes" "errors" "fmt" + "io" "os" "os/user" "path/filepath" @@ -435,3 +437,56 @@ func ParseSpecial(s string) string { func String(s []byte) string { return string(s) } + +// Unzip unzips a file to given folder +func Unzip(src, dest string) error { + r, err := zip.OpenReader(src) + if err != nil { + return err + } + defer r.Close() + + os.MkdirAll(dest, 0755) + + // Closure to address file descriptors issue with all the deferred .Close() methods + extractAndWriteFile := func(f *zip.File) error { + rc, err := f.Open() + if err != nil { + return err + } + defer rc.Close() + + path := filepath.Join(dest, f.Name) + + // Check for ZipSlip (Directory traversal) + if !strings.HasPrefix(path, filepath.Clean(dest)+string(os.PathSeparator)) { + return fmt.Errorf("illegal file path: %s", path) + } + + if f.FileInfo().IsDir() { + os.MkdirAll(path, f.Mode()) + } else { + os.MkdirAll(filepath.Dir(path), f.Mode()) + f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) + if err != nil { + return err + } + defer f.Close() + + _, err = io.Copy(f, rc) + if err != nil { + return err + } + } + return nil + } + + for _, f := range r.File { + err := extractAndWriteFile(f) + if err != nil { + return err + } + } + + return nil +} diff --git a/runtime/help/plugins.md b/runtime/help/plugins.md index eff48d06..1818b96b 100644 --- a/runtime/help/plugins.md +++ b/runtime/help/plugins.md @@ -285,6 +285,7 @@ The packages and functions are listed below (in Go type signatures): string is a word character. - `String(b []byte) string`: converts a byte array to a string. - `RuneStr(r rune) string`: converts a rune to a string. + - `Unzip(src, dest string) error`: unzips a file to given folder. This may seem like a small list of available functions but some of the objects returned by the functions have many methods. The Lua plugin may access any @@ -358,6 +359,8 @@ strings regexp errors time +archive/zip +net/http ``` For documentation for each of these functions, see the Go standard