diff --git a/base/aaa/role.go b/base/aaa/role.go index 2632bda8..ec81ea5a 100644 --- a/base/aaa/role.go +++ b/base/aaa/role.go @@ -132,8 +132,8 @@ func RoleRight(m *ice.Message, role string, key ...string) bool { return m.Cmdx(ROLE, RIGHT, role, key) == ice.OK } func Right(m *ice.Message, key ...ice.Any) bool { - return m.Option(ice.MSG_USERROLE) == ROOT || !m.Warn(m.Cmdx(ROLE, RIGHT, m.Option(ice.MSG_USERROLE), key) != ice.OK, - ice.ErrNotRight, kit.Keys(key...), USERROLE, m.Option(ice.MSG_USERROLE), logs.FileLineMeta(2)) + return m.Option(ice.MSG_USERROLE) == ROOT || !m.Warn(m.Cmdx(ROLE, RIGHT, m.Option(ice.MSG_USERROLE), key, logs.FileLineMeta(-1)) != ice.OK, + ice.ErrNotRight, kit.Keys(key...), USERROLE, m.Option(ice.MSG_USERROLE), logs.FileLineMeta(-1)) } func White(m *ice.Message, key ...string) { for _, key := range key { diff --git a/base/cli/system.go b/base/cli/system.go index 6d6c465d..7106b277 100644 --- a/base/cli/system.go +++ b/base/cli/system.go @@ -31,6 +31,11 @@ func _system_cmd(m *ice.Message, arg ...string) *exec.Cmd { } } } + if bin == "" { + if bin = _system_find(m, arg[0], ice.BIN, m.Option(CMD_DIR)); bin != "" { + m.Logs(mdb.SELECT, "contexts cmd", bin) + } + } if bin == "" { if bin = _system_find(m, arg[0], ice.BIN, nfs.PWD); bin != "" { m.Logs(mdb.SELECT, "contexts cmd", bin) diff --git a/base/mdb/list.go b/base/mdb/list.go index e4242e93..7809f9ea 100644 --- a/base/mdb/list.go +++ b/base/mdb/list.go @@ -117,8 +117,8 @@ func ListAction(arg ...ice.Any) ice.Actions { func PageListAction(arg ...ice.Any) ice.Actions { return ice.MergeActions(ice.Actions{ SELECT: {Name: "select id auto insert page", Hand: func(m *ice.Message, arg ...string) { PageListSelect(m, arg...) }}, - NEXT: {Hand: func(m *ice.Message, arg ...string) { NextPage(m, m.Config(COUNT), kit.Slice(arg, 1)...) }}, - PREV: {Hand: func(m *ice.Message, arg ...string) { PrevPageLimit(m, m.Config(COUNT), kit.Slice(arg, 1)...) }}, + NEXT: {Hand: func(m *ice.Message, arg ...string) { NextPage(m, kit.Select(m.Config(COUNT), arg, 0), kit.Slice(arg, 1)...) }}, + PREV: {Hand: func(m *ice.Message, arg ...string) { PrevPageLimit(m, kit.Select(m.Config(COUNT), arg, 0), kit.Slice(arg, 1)...) }}, }, ListAction(arg...)) } func ListField(m *ice.Message) string { return kit.Select(LIST_FIELD, m.Config(FIELD)) } diff --git a/base/nfs/cat.go b/base/nfs/cat.go index 9ca30b6c..fed5c1da 100644 --- a/base/nfs/cat.go +++ b/base/nfs/cat.go @@ -94,7 +94,6 @@ const ( BINARY = "binary" TARGET = "target" TAGS = "tags" - TAR = "tar" TEMPLATE = "template" VERSION = "version" diff --git a/base/nfs/nfs.go b/base/nfs/nfs.go index 6eca7b64..1fd5a267 100644 --- a/base/nfs/nfs.go +++ b/base/nfs/nfs.go @@ -7,5 +7,5 @@ const NFS = "nfs" var Index = &ice.Context{Name: NFS, Help: "存储模块"} func init() { - ice.Index.Register(Index, nil, CAT, DIR, PACK, DEFS, SAVE, PUSH, COPY, LINK, GREP, TRASH) + ice.Index.Register(Index, nil, TAR, CAT, DIR, PACK, DEFS, SAVE, PUSH, COPY, LINK, GREP, TRASH) } diff --git a/base/nfs/tar.go b/base/nfs/tar.go new file mode 100644 index 00000000..235b0593 --- /dev/null +++ b/base/nfs/tar.go @@ -0,0 +1,115 @@ +package nfs + +import ( + "archive/tar" + "compress/gzip" + "io" + "os" + "path" + "strings" + + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/mdb" + kit "shylinux.com/x/toolkits" +) + +func _tar_list(m *ice.Message, p string, cb func(*tar.Header, *tar.Reader, int)) *ice.Message { + const ( + GZ = "gz" + ) + var r io.Reader + if f, e := os.Open(p); m.Warn(e, ice.ErrNotValid, p) { + return m + } else { + defer f.Close() + r = f + } + for { + switch kit.Ext(p) { + case GZ: + if f, e := gzip.NewReader(r); m.Warn(e, ice.ErrNotValid, p) { + return m + } else { + defer f.Close() + r = f + } + p = kit.TrimExt(p, GZ) + case TAR: + i := 0 + for r := tar.NewReader(r); ; i++ { + h, e := r.Next() + if m.Warn(e) { + break + } + cb(h, r, i) + } + m.StatusTimeCount(mdb.TOTAL, i) + m.Debug("what %v", i) + return m + default: + return m + } + } + return m +} + +const TAR = "tar" + +func init() { + Index.MergeCommands(ice.Commands{ + TAR: {Name: "tar path file auto page", Help: "打包", Actions: ice.MergeActions(ice.Actions{ + mdb.NEXT: {Hand: func(m *ice.Message, arg ...string) { mdb.PrevPage(m, arg[0], kit.Slice(arg, 1)...) }}, + mdb.PREV: {Hand: func(m *ice.Message, arg ...string) { mdb.NextPageLimit(m, arg[0], kit.Slice(arg, 1)...) }}, + mdb.EXPORT: {Hand: func(m *ice.Message, arg ...string) { + list := map[string]bool{} + _tar_list(m, m.Option(PATH), func(h *tar.Header, r *tar.Reader, i int) { + if h.Name == m.Option(FILE) || m.Option(FILE) == "" { + p := path.Join(path.Dir(m.Option(PATH)), h.Name) + if strings.HasSuffix(h.Name, ice.PS) { + MkdirAll(m, p) + return + } + if !list[path.Dir(p)] { + list[path.Dir(p)] = true + MkdirAll(m, path.Dir(p)) + } + if f, p, e := CreateFile(m, p); !m.Warn(e) { + defer f.Close() + if m.Option(FILE) != "" { + defer m.Cmdy(DIR, p, "time,path,size") + defer m.Cmdy(CAT, p) + } + n, e := io.Copy(f, r) + m.Logs(mdb.EXPORT, FILE, p, SIZE, n).Warn(e) + os.Chmod(p, os.FileMode(h.Mode)) + } + } + }) + }}, + }, mdb.PageListAction()), Hand: func(m *ice.Message, arg ...string) { + if len(arg) == 0 || strings.HasSuffix(arg[0], ice.PS) { + m.Cmdy(DIR, arg) + return + } + page, size := mdb.OptionPages(m, kit.Slice(arg, 2)...) + _tar_list(m, arg[0], func(h *tar.Header, r *tar.Reader, i int) { + if len(kit.Slice(arg, 0, 2)) > 1 { + if h.Name != arg[1] { + return + } + m.Echo(string(ReadAll(m, r)[:])) + } + if i >= (page-1)*size && i < page*size { + m.Push(mdb.TIME, h.ModTime.Format(ice.MOD_TIME)).Push(FILE, h.Name).Push(SIZE, kit.FmtSize(h.Size)) + } + }).PushAction(mdb.EXPORT) + }}, + }) +} +func ReadAll(m *ice.Message, r io.Reader) []byte { + if buf, e := io.ReadAll(r); m.Warn(e) { + return buf + } else { + return buf + } +} diff --git a/base/web/serve.go b/base/web/serve.go index 4b825e2c..fd28bb9d 100644 --- a/base/web/serve.go +++ b/base/web/serve.go @@ -58,7 +58,7 @@ func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool { if m.Logs(r.Method, r.Header.Get(ice.MSG_USERIP), r.URL.String()); m.Config(LOGHEADERS) == ice.TRUE { kit.Fetch(r.Header, func(k string, v []string) { m.Logs("Header", k, v) }) } - if r.Method == http.MethodGet { + if r.Method == http.MethodGet && r.URL.Path != PP(SPACE) { repos := kit.Select(ice.INTSHELL, ice.VOLCANOS, strings.Contains(r.Header.Get(UserAgent), MOZILLA)) if msg := gdb.Event(m.Spawn(w, r), SERVE_REWRITE, r.Method, r.URL.Path, path.Join(m.Conf(SERVE, kit.Keym(repos, nfs.PATH)), r.URL.Path), repos); msg.Option(ice.MSG_OUTPUT) != "" { Render(msg, msg.Option(ice.MSG_OUTPUT), kit.List(msg.Optionv(ice.MSG_ARGS))...) @@ -68,7 +68,7 @@ func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool { return true } func _serve_handle(key string, cmd *ice.Command, m *ice.Message, w http.ResponseWriter, r *http.Request) { - if u, e := url.Parse(r.Header.Get(Referer)); e == nil { + if u, e := url.Parse(r.Header.Get(Referer)); e == nil && r.URL.Path != PP(SPACE) { gdb.Event(m, SERVE_PARSE, strings.Split(strings.TrimPrefix(u.Path, ice.PS), ice.PS)) kit.Fetch(u.Query(), func(k string, v []string) { m.Logs("Refer", k, v).Optionv(k, v) }) } @@ -121,7 +121,7 @@ func _serve_domain(m *ice.Message) string { ) } func _serve_login(m *ice.Message, key string, cmds []string, w http.ResponseWriter, r *http.Request) ([]string, bool) { - if aaa.SessCheck(m, m.Option(ice.MSG_SESSID)); m.Option(ice.MSG_USERNAME) == "" { + if aaa.SessCheck(m, m.Option(ice.MSG_SESSID)); m.Option(ice.MSG_USERNAME) == "" && r.URL.Path != PP(SPACE) { gdb.Event(m, SERVE_LOGIN) } if _, ok := m.Target().Commands[WEB_LOGIN]; ok { diff --git a/base/web/space.go b/base/web/space.go index c7d9234a..93679cc1 100644 --- a/base/web/space.go +++ b/base/web/space.go @@ -48,7 +48,7 @@ func _space_fork(m *ice.Message) { case WORKER: defer gdb.EventDeferEvent(m, DREAM_OPEN, args)(DREAM_CLOSE, args) case CHROME: - m.Cmd(SPACE, name, cli.PWD, name) + m.Go(func() { m.Sleep("10ms").Cmd(SPACE, name, cli.PWD, name) }) } _space_handle(m, false, name, conn) }) @@ -57,7 +57,8 @@ func _space_fork(m *ice.Message) { func _space_handle(m *ice.Message, safe bool, name string, conn *websocket.Conn) { for { _, b, e := conn.ReadMessage() - if m.Warn(e, SPACE, name) { + if e != nil { + m.Logs("sock", SPACE, name, "error", e) break } msg := m.Spawn(b) @@ -126,12 +127,17 @@ func _space_send(m *ice.Message, space string, arg ...string) { } }) m.Set(ice.MSG_DETAIL, arg...).Optionv(ice.MSG_OPTION, m.Optionv(ice.MSG_OPTS, m.Optionv(ice.MSG_OPTS))) - if target := kit.Split(space, ice.PT, ice.PT); !m.Warn(!mdb.HashSelectDetail(m, target[0], func(value ice.Map) { + target := kit.Split(space, ice.PT, ice.PT) + if mdb.HashSelectDetail(m, target[0], func(value ice.Map) { if conn, ok := value[mdb.TARGET].(*websocket.Conn); !m.Warn(!ok, ice.ErrNotValid, mdb.TARGET) { _space_echo(m, []string{addSend(m, m)}, target, conn) } - }), ice.ErrNotFound, space) { + }) { call(m, m.Config(kit.Keys(TIMEOUT, "c")), func(res *ice.Message) { m.Copy(res) }) + } else if kit.IndexOf([]string{ice.OPS, ice.DEV, ice.SHY}, target[0]) > -1 { + return + } else { + m.Warn(true, ice.ErrNotFound, space) } } diff --git a/core/code/install.go b/core/code/install.go index 453e13b8..415b2538 100644 --- a/core/code/install.go +++ b/core/code/install.go @@ -23,7 +23,7 @@ func _install_path(m *ice.Message, link string) string { return p } if p := path.Join(ice.USR_INSTALL, path.Base(link)); nfs.ExistsFile(m, p) { - return path.Join(ice.USR_INSTALL, strings.Split(cli.SystemCmds(m, "tar tf %s| head -n1", p), ice.PS)[0]) + return path.Join(ice.USR_INSTALL, strings.Split(m.Cmd(nfs.TAR, p, "", "1").Append(nfs.FILE), ice.PS)[0]) } m.Warn(true, ice.ErrNotFound, link) return "" @@ -32,29 +32,28 @@ func _install_download(m *ice.Message) { link := m.Option(mdb.LINK) name := path.Base(strings.Split(link, "?")[0]) file := path.Join(kit.Select(ice.USR_INSTALL, m.Option(nfs.PATH)), name) - if nfs.ExistsFile(m, file) { m.Cmdy(nfs.DIR, file) web.ToastSuccess(m) - return // 文件存在 + return } - m.Cmd(nfs.SAVE, file, "") - begin, last := time.Now(), time.Now() + begin := time.Now() mdb.HashCreate(m, mdb.NAME, name, nfs.PATH, file, mdb.LINK, link) web.GoToast(m, name, func(toast func(string, int, int)) { + last, base := 0, 10 web.SpideSave(m, file, link, func(count int, total int, step int) { - mdb.HashSelectUpdate(m, name, func(value ice.Map) { value[mdb.COUNT], value[mdb.TOTAL], value[mdb.VALUE] = count, total, step }) - - if now := time.Now(); now.Sub(last) > 500*time.Millisecond { - cost := now.Sub(begin) - toast(kit.FormatShow("from", begin.Format("15:04:05"), "cost", kit.FmtDuration(cost), - "rest", kit.FmtDuration(cost*time.Duration(100)/time.Duration(step+1)-cost), - ), count, total) - last = now + if step/base == last { + return } + last = step / base + cost := time.Now().Sub(begin) + mdb.HashSelectUpdate(m, name, func(value ice.Map) { value[mdb.COUNT], value[mdb.TOTAL], value[mdb.VALUE] = count, total, step }) + toast(kit.FormatShow("from", begin.Format("15:04:05"), "cost", kit.FmtDuration(cost), + "rest", kit.FmtDuration(cost*time.Duration(101)/time.Duration(step+1)-cost), + ), count, total) }) - m.Cmd(nfs.TAR, mdb.EXPORT, name, kit.Dict(cli.CMD_DIR, path.Dir(file))) + m.Cmd(nfs.TAR, mdb.EXPORT, ice.Maps{nfs.PATH: file, nfs.FILE: ""}) web.ToastSuccess(m) }) m.Cmdy(nfs.DIR, file).SetResult() @@ -62,30 +61,21 @@ func _install_download(m *ice.Message) { func _install_build(m *ice.Message, arg ...string) string { p := m.Option(cli.CMD_DIR, _install_path(m, "")) pp := kit.Path(path.Join(p, _INSTALL)) - - // 推流 - web.PushStream(m) defer m.ProcessHold() - - // 配置 - switch cb := m.Optionv(PREPARE).(type) { + switch web.PushStream(m); cb := m.Optionv(PREPARE).(type) { case func(string): cb(p) case nil: if msg := m.Cmd(cli.SYSTEM, "./configure", "--prefix="+pp, arg[1:]); !cli.IsSuccess(msg) { - return msg.Append(cli.CMD_ERR) + return msg.Append(cli.CMD_ERR) + msg.Append(cli.CMD_OUT) } default: m.ErrorNotImplement(cb) return m.Result() } - - // 编译 if msg := m.Cmd(cli.SYSTEM, cli.MAKE, "-j"+m.Cmdx(cli.RUNTIME, cli.MAXPROCS)); !cli.IsSuccess(msg) { return msg.Append(cli.CMD_ERR) + msg.Append(cli.CMD_OUT) } - - // 安装 if msg := m.Cmd(cli.SYSTEM, cli.MAKE, "PREFIX="+pp, INSTALL); !cli.IsSuccess(msg) { return msg.Append(cli.CMD_ERR) + msg.Append(cli.CMD_OUT) } @@ -112,12 +102,10 @@ func _install_spawn(m *ice.Message, arg ...string) { } else { m.Option(tcp.PORT, m.Cmdx(tcp.PORT, aaa.RIGHT)) } - target := path.Join(ice.USR_LOCAL_DAEMON, m.Option(tcp.PORT)) source := _install_path(m, "") nfs.MkdirAll(m, target) defer m.Echo(target) - if m.Option(INSTALL) == "" && nfs.ExistsFile(m, kit.Path(source, _INSTALL)) { m.Option(INSTALL, _INSTALL) } @@ -127,7 +115,6 @@ func _install_spawn(m *ice.Message, arg ...string) { } func _install_start(m *ice.Message, arg ...string) { p := m.Option(cli.CMD_DIR, m.Cmdx(INSTALL, cli.SPAWN)) - args := []string{} switch cb := m.Optionv(PREPARE).(type) { case func(string) []string: @@ -141,7 +128,6 @@ func _install_start(m *ice.Message, arg ...string) { m.ErrorNotImplement(cb) return } - bin := kit.Split(path.Base(arg[0]), "-.")[0] m.Cmdy(cli.DAEMON, kit.Select(path.Join(ice.BIN, bin), arg, 1), kit.Slice(arg, 2), args) } @@ -168,6 +154,14 @@ func _install_service(m *ice.Message, arg ...string) { if strings.Contains(value[ice.CMD], path.Join(ice.BIN, arg[0])) { m.Push("", value, kit.Split(m.OptionFields())) } + switch value[mdb.STATUS] { + case cli.START: + m.PushButton(gdb.DEBUG, cli.STOP) + case cli.STOP: + m.PushButton(cli.START) + default: + m.PushButton("") + } }) m.Set(tcp.PORT).Tables(func(value ice.Maps) { m.Push(tcp.PORT, path.Base(value[nfs.DIR])) }) m.StatusTimeCount() @@ -182,13 +176,11 @@ const INSTALL = "install" func init() { Index.MergeCommands(ice.Commands{ INSTALL: {Name: "install name port path:text auto download", Help: "安装", Actions: ice.MergeActions(ice.Actions{ - nfs.PATH: {Name: "path", Help: "路径", Hand: func(m *ice.Message, arg ...string) { - m.Echo(_install_path(m, kit.Select("", arg, 0))) - }}, - web.DOWNLOAD: {Name: "download link path", Help: "下载", Hand: func(m *ice.Message, arg ...string) { + nfs.PATH: {Hand: func(m *ice.Message, arg ...string) { m.Echo(_install_path(m, kit.Select("", arg, 0))) }}, + web.DOWNLOAD: {Name: "download link* path", Help: "下载", Hand: func(m *ice.Message, arg ...string) { _install_download(m) }}, - cli.BUILD: {Name: "build link", Help: "构建", Hand: func(m *ice.Message, arg ...string) { + cli.BUILD: {Name: "build link*", Help: "构建", Hand: func(m *ice.Message, arg ...string) { if err := _install_build(m, arg...); err != "" { web.ToastFailure(m, cli.BUILD) m.Echo(err) @@ -196,13 +188,13 @@ func init() { web.ToastSuccess(m, cli.BUILD) } }}, - cli.ORDER: {Name: "order link path", Help: "加载", Hand: func(m *ice.Message, arg ...string) { + cli.ORDER: {Name: "order link* path", Help: "加载", Hand: func(m *ice.Message, arg ...string) { _install_order(m, arg...) }}, - cli.SPAWN: {Name: "spawn link", Help: "新建", Hand: func(m *ice.Message, arg ...string) { + cli.SPAWN: {Name: "spawn link*", Help: "新建", Hand: func(m *ice.Message, arg ...string) { _install_spawn(m, arg...) }}, - cli.START: {Name: "start link cmd", Help: "启动", Hand: func(m *ice.Message, arg ...string) { + cli.START: {Name: "start link* cmd", Help: "启动", Hand: func(m *ice.Message, arg ...string) { _install_start(m, arg...) }}, cli.STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) { @@ -225,13 +217,12 @@ func init() { }}, }, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,name,path,link")), Hand: func(m *ice.Message, arg ...string) { switch len(arg) { - case 0: // 源码列表 + case 0: mdb.HashSelect(m, arg...) - - case 1: // 服务列表 + m.PushAction(cli.BUILD, cli.ORDER) + case 1: _install_service(m, arg...) - - default: // 目录列表 + default: m.Option(nfs.DIR_ROOT, path.Join(ice.USR_LOCAL_DAEMON, arg[1])) m.Cmdy(nfs.CAT, kit.Select(nfs.PWD, arg, 2)) } diff --git a/logs.go b/logs.go index 360c6275..b72b4873 100644 --- a/logs.go +++ b/logs.go @@ -105,7 +105,7 @@ func (m *Message) Warn(err Any, arg ...Any) bool { switch err := err.(type) { case error: if err == io.EOF { - return false + return true } arg = append(arg, ERR, err) case bool: