diff --git a/Makefile b/Makefile index a503d711..2427adc2 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ install: @go get github.com/nsf/termbox-go @go get github.com/skip2/go-qrcode @go get github.com/gomarkdown/markdown + @go get github.com/PuerkitoBio/goquery go install $(BENCH) @date # bench web.code.counter nmake 1 @@ -20,6 +21,10 @@ install_all: install run: etc/bootstrap.sh +shy: + cp -r src/ ~/shycontext/ + cp -r usr/template/ ~/shycontext/usr/ + cp -r usr/librarys/ ~/shycontext/usr/ tar: [ -e tar ] || mkdir tar diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go index 88cebbc4..1dcf289d 100644 --- a/src/contexts/cli/cli.go +++ b/src/contexts/cli/cli.go @@ -227,6 +227,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", msg := m for k, v := range m.Confv("cmd_script").(map[string]interface{}) { if strings.HasSuffix(detail[0], "."+k) { + detail[0] = m.Sess("nfs").Cmd("path", detail[0]).Result(0) detail = append([]string{v.(string)}, detail...) msg = m.Spawn(cli.target) break @@ -573,7 +574,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } m.Echo(m.Cap(arg[1])) }}, - "echo": &ctx.Command{Name: "echo arg...", Help: "输出表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "expr": &ctx.Command{Name: "expr arg...", Help: "输出表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { m.Echo("%s", strings.Join(arg[1:], "")) }}, "return": &ctx.Command{Name: "return result...", Help: "结束脚本, result: 返回值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { diff --git a/src/contexts/cli/cli_windows.go b/src/contexts/cli/cli_windows.go new file mode 100644 index 00000000..dfa0c1c8 --- /dev/null +++ b/src/contexts/cli/cli_windows.go @@ -0,0 +1,8 @@ +package cli + +import ( + "contexts/ctx" +) + +func sysinfo(m *ctx.Message, c *ctx.Context, key string, arg ...string) { +} diff --git a/src/contexts/ctx/ctx.go b/src/contexts/ctx/ctx.go index 0107cb65..fbf10562 100644 --- a/src/contexts/ctx/ctx.go +++ b/src/contexts/ctx/ctx.go @@ -2279,9 +2279,10 @@ var CGI = template.FuncMap{ var Pulse = &Message{code: 0, time: time.Now(), source: Index, target: Index, Meta: map[string][]string{}} var Index = &Context{Name: "ctx", Help: "模块中心", Caches: map[string]*Cache{ - "nserver": &Cache{Name: "nserver", Value: "0", Help: "服务数量"}, - "ncontext": &Cache{Name: "ncontext", Value: "0", Help: "模块数量"}, - "nmessage": &Cache{Name: "nmessage", Value: "0", Help: "消息数量"}, + "begin_time": &Cache{Name: "begin_time", Value: "", Help: "启动时间"}, + "nserver": &Cache{Name: "nserver", Value: "0", Help: "服务数量"}, + "ncontext": &Cache{Name: "ncontext", Value: "0", Help: "模块数量"}, + "nmessage": &Cache{Name: "nmessage", Value: "0", Help: "消息数量"}, }, Configs: map[string]*Config{ "chain": &Config{Name: "chain", Value: map[string]interface{}{}, Help: "调试模式,on:打印,off:不打印)"}, @@ -2323,16 +2324,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", m.Echo("^_^ Welcome to context world ^_^\n") m.Echo("Version: 1.0 A New Language, A New Framework\n") - m.Echo("More: github.com/shylinux/context/README.md\n") - m.Color(31, " c\n") - m.Color(31, " sh").Color(33, " go\n") - m.Color(31, " vi").Color(32, " php").Color(32, " js\n") - m.Echo(" ARM Linux HTTP\n") - m.Color(31, "Context ").Color(32, "Message\n") - m.Color(32, "ctx ").Color(33, "cli ").Color(31, "aaa ").Color(33, "web\n") - m.Color(32, "lex ").Color(33, "yac ").Color(31, "log ").Color(33, "gdb\n") - m.Color(32, "tcp ").Color(33, "nfs ").Color(31, "ssh ").Color(33, "mdb\n") - m.Color(31, "script ").Color(32, "template\n") + m.Echo("More: https://github.com/shylinux/context\n") return } @@ -3089,16 +3081,19 @@ var Index = &Context{Name: "ctx", Help: "模块中心", switch val := value.(type) { case map[string]interface{}: - for k, v := range val { - m.Add("append", k, v) + if true { + for k, v := range val { + m.Add("append", k, v) + } + sort.Strings(m.Meta["append"]) + m.Table() + } else { + for k, v := range val { + m.Add("append", "key", k) + m.Add("append", "value", v) + } + m.Sort("key", "str").Table() } - sort.Strings(m.Meta["append"]) - m.Table() - // for k, v := range val { - // m.Add("append", "key", k) - // m.Add("append", "value", v) - // } - // m.Sort("key", "str").Table() case map[string]string: for k, v := range val { m.Add("append", k, v) @@ -3115,7 +3110,15 @@ var Index = &Context{Name: "ctx", Help: "模块中心", switch value := v.(type) { case map[string]interface{}: for k, v := range value { - m.Add("append", k, v) + switch val := v.(type) { + case string: + m.Add("append", k, val) + case float64: + m.Add("append", k, int(val)) + default: + b, _ := json.Marshal(val) + m.Add("append", k, string(b)) + } } sort.Strings(m.Meta["append"]) case map[string]string: @@ -3185,10 +3188,13 @@ var Index = &Context{Name: "ctx", Help: "模块中心", for k, v := range val { m.Add("append", "key", k) switch value := v.(type) { + case string: + m.Add("append", "value", value) case float64: m.Add("append", "value", fmt.Sprintf("%d", int(value))) default: - m.Add("append", "value", fmt.Sprintf("%v", value)) + b, _ := json.Marshal(value) + m.Add("append", "value", fmt.Sprintf("%v", string(b))) } } m.Sort("key", "str").Table() @@ -3204,15 +3210,25 @@ var Index = &Context{Name: "ctx", Help: "模块中心", case map[string]interface{}: for k, v := range value { switch value := v.(type) { + case string: + m.Add("append", k, value) case float64: m.Add("append", k, fmt.Sprintf("%d", int(value))) default: - m.Add("append", k, fmt.Sprintf("%v", value)) + b, _ := json.Marshal(value) + m.Add("append", k, fmt.Sprintf("%v", string(b))) } } + case string: + m.Add("append", "index", i) + m.Add("append", "value", value) + case float64: + m.Add("append", "index", i) + m.Add("append", "value", fmt.Sprintf("%v", int(value))) default: m.Add("append", "index", i) - m.Add("append", "value", fmt.Sprintf("%v", v)) + b, _ := json.Marshal(value) + m.Add("append", "value", fmt.Sprintf("%v", string(b))) } } m.Table() @@ -3222,45 +3238,61 @@ var Index = &Context{Name: "ctx", Help: "模块中心", m.Add("append", "value", v) } m.Table() + case string: + m.Echo("%s", val) case float64: m.Echo("%d", int(val)) case nil: m.Echo("") default: - m.Echo("%v", val) + b, _ := json.Marshal(val) + m.Echo("%s", string(b)) } }}, "select": &Command{Name: "select key value field", - Form: map[string]int{"parse": 2, "group": 1, "order": 2, "limit": 1, "offset": 1, "fields": 1, "format": 2, "trans_map": 3, "vertical": 0}, + Form: map[string]int{"parse": 2, "group": 1, "order": 2, "limit": 1, "offset": 1, "fields": 1, "format": 2, "trans_map": 3, "vertical": 0, "hide": 1}, Help: "选取数据", Hand: func(m *Message, c *Context, key string, arg ...string) { msg := m.Spawn() m.Set("result") - // 筛选与解析 + // 解析 nrow := len(m.Meta[m.Meta["append"][0]]) + for i := 0; i < nrow; i++ { + for j := 0; j < len(m.Meta["parse"]); j += 2 { + var value interface{} + e := json.Unmarshal([]byte(m.Meta[m.Meta["parse"][j]][i]), &value) + if m.Meta["parse"][j+1] != "" { + value = Chain(m, value, m.Meta["parse"][j+1]) + } + m.Log("fuck", "info %v %v %v %v %T", e, m.Meta["parse"][j], m.Meta["parse"][j+1], value, value) + + switch val := value.(type) { + case map[string]interface{}: + for k, v := range val { + m.Add("append", k, v) + } + case float64: + m.Add("append", m.Meta["parse"][j+1], fmt.Sprintf("%d", int(val))) + case nil: + m.Add("append", m.Meta["parse"][j+1], "") + default: + m.Add("append", m.Meta["parse"][j+1], fmt.Sprintf("%v", val)) + } + } + } + + // 筛选 + hides := map[string]bool{} + for _, k := range m.Meta["hide"] { + hides[k] = true + } for i := 0; i < nrow; i++ { if len(arg) == 0 || strings.Contains(m.Meta[arg[0]][i], arg[1]) { for _, k := range m.Meta["append"] { - if m.Has("parse") && m.Option("parse") == k { - var value interface{} - json.Unmarshal([]byte(m.Meta[k][i]), &value) - if m.Meta["parse"][1] != "" { - value = Chain(m, value, m.Meta["parse"][1]) - } - - switch val := value.(type) { - case map[string]interface{}: - for k, v := range val { - msg.Add("append", k, v) - } - case nil: - msg.Add("append", m.Meta["parse"][1], "") - default: - msg.Add("append", m.Meta["parse"][1], fmt.Sprintf("%v", val)) - } - } else { - msg.Add("append", k, m.Meta[k][i]) + if hides[k] { + continue } + msg.Add("append", k, m.Meta[k][i]) } } } @@ -3452,6 +3484,7 @@ func Start() { for k, c := range Index.contexts { Pulse.Sess(k, c) } + Pulse.Cap("begin_time", time.Now().Format(Pulse.Conf("time_format"))) args := os.Args[1:] if len(args) > 0 { diff --git a/src/contexts/mdb/mdb.go b/src/contexts/mdb/mdb.go index b084d556..9769e3e7 100644 --- a/src/contexts/mdb/mdb.go +++ b/src/contexts/mdb/mdb.go @@ -195,7 +195,7 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", }}, "show": &ctx.Command{Name: "show table fields...", Help: "查询数据库, table: 表名, fields: 字段, where: 查询条件, group: 聚合字段, order: 排序字段", - Form: map[string]int{"eq": 2, "where": 1, "group": 1, "desc": 0, "order": 1, "limit": 1, "offset": 1, "other": -1, + Form: map[string]int{"like": 2, "eq": 2, "where": 1, "group": 1, "desc": 0, "order": 1, "limit": 1, "offset": 1, "other": -1, "extra_field": 2, "extra_fields": 1, "extra_format": 1, "trans_field": 1, "trans_map": 2}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if _, ok := m.Target().Server.(*MDB); m.Assert(ok) { @@ -234,6 +234,19 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", } } + begin := []string{} + for i := 0; i < len(m.Meta["begin"]); i += 2 { + begin = append(begin, fmt.Sprintf(" %s like '%s%%' ", m.Meta["begin"][i], m.Meta["begin"][i+1])) + } + + if len(begin) > 0 { + if m.Options("where") { + m.Option("where", m.Option("where")+" and "+strings.Join(begin, "and")) + } else { + m.Option("where", strings.Join(begin, "and")) + } + } + where := m.Confx("where", m.Option("where"), "where %s") group := m.Confx("group", m.Option("group"), "group by %s") order := m.Confx("order", m.Option("order"), "order by %s") diff --git a/src/contexts/web/web.go b/src/contexts/web/web.go index 67a1ff19..8aa67fd5 100644 --- a/src/contexts/web/web.go +++ b/src/contexts/web/web.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "github.com/PuerkitoBio/goquery" + "github.com/go-cas/cas" "html/template" "io" "io/ioutil" @@ -109,6 +110,28 @@ func (web *WEB) HandleCmd(m *ctx.Message, key string, cmd *ctx.Command) { } for k, v := range r.Form { msg.Add("option", k, v) + if k == "ticket" { + m.Log("info", "hide ticket %v %v %v %v", k, v, r.URL, r.Header.Get("index_path")) + uri, _ := r.URL.Parse(r.Header.Get("index_path")) + http.Redirect(w, r, uri.Path, http.StatusTemporaryRedirect) + return + } + } + + if msg.Confs("cas_url") { + if !cas.IsAuthenticated(r) && !msg.Confs("skip_cas") { + r.URL.Path = r.Header.Get("index_path") + cas.RedirectToLogin(w, r) + return + } + + msg.Option("username", cas.Username(r)) + msg.Option("password", cas.Username(r)) + for k, v := range cas.Attributes(r) { + for _, val := range v { + msg.Add("option", k, val) + } + } } msg.Log("cmd", "%s [] %v", key, msg.Meta["option"]) @@ -157,8 +180,10 @@ func (web *WEB) ServeHTTP(w http.ResponseWriter, r *http.Request) { r.Header.Set("index_module", m.Cap("module")) if index { + r.Header.Set("index_path", r.URL.String()) m.Log("info", "").Log("info", "%v %s %s", r.RemoteAddr, r.Method, r.URL) } + if index && m.Confs("logheaders") { for k, v := range r.Header { m.Log("info", "%s: %v", k, v) @@ -189,6 +214,7 @@ func (web *WEB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server return s } func (web *WEB) Begin(m *ctx.Message, arg ...string) ctx.Server { + web.Configs["skip_cas"] = &ctx.Config{Name: "skip_cas", Value: "false", Help: "默认路由"} web.Configs["root_index"] = &ctx.Config{Name: "root_index", Value: "/render", Help: "默认路由"} web.Configs["logheaders"] = &ctx.Config{Name: "logheaders(yes/no)", Value: "no", Help: "日志输出报文头"} web.Configs["template_sub"] = &ctx.Config{Name: "template_sub", Value: web.Context.Name, Help: "模板文件"} @@ -247,7 +273,17 @@ func (web *WEB) Start(m *ctx.Message, arg ...string) bool { web.Caches["protocol"] = &ctx.Cache{Name: "protocol", Value: m.Confx("protocol", arg, 2), Help: "服务协议"} web.Caches["address"] = &ctx.Cache{Name: "address", Value: m.Confx("address", arg, 1), Help: "服务地址"} m.Log("info", "%d %s://%s", m.Capi("nserve", 1), m.Cap("protocol"), m.Cap("stream", m.Cap("address"))) - web.Server = &http.Server{Addr: m.Cap("address"), Handler: web} + + var handler http.Handler + if cas_url, e := url.Parse(m.Conf("cas_url")); e == nil && m.Confs("cas_url") { + m.Log("info", "cas url: %s", m.Conf("cas_url")) + client := cas.NewClient(&cas.Options{URL: cas_url}) + handler = client.Handle(web) + } else { + handler = web + } + + web.Server = &http.Server{Addr: m.Cap("address"), Handler: handler} if m.Caps("master", true); m.Cap("protocol") == "https" { web.Caches["cert"] = &ctx.Cache{Name: "cert", Value: m.Confx("cert", arg, 3), Help: "服务证书"} @@ -274,6 +310,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", "nroute": &ctx.Cache{Name: "nroute", Value: "0", Help: "路由数量"}, }, Configs: map[string]*ctx.Config{ + "login_lark": &ctx.Config{Name: "login_lark", Value: "false", Help: "缓存大小"}, "login_right": &ctx.Config{Name: "login_right", Value: "1", Help: "缓存大小"}, "log_uri": &ctx.Config{Name: "log_uri", Value: "false", Help: "缓存大小"}, "multipart_bsize": &ctx.Config{Name: "multipart_bsize", Value: "102400", Help: "缓存大小"}, @@ -286,6 +323,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", "cert": &ctx.Config{Name: "cert", Value: "etc/cert.pem", Help: "路由数量"}, "key": &ctx.Config{Name: "key", Value: "etc/key.pem", Help: "路由数量"}, + "cas_url": &ctx.Config{Name: "cas_url", Value: "", Help: "模板路径"}, "library_dir": &ctx.Config{Name: "library_dir", Value: "usr/librarys", Help: "模板路径"}, "template_dir": &ctx.Config{Name: "template_dir", Value: "usr/template", Help: "模板路径"}, "template_debug": &ctx.Config{Name: "template_debug", Value: "true", Help: "模板调试"}, @@ -402,8 +440,10 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", if m.Confs("log_uri") { m.Echo("%s: %s\n", req.Method, req.URL) } - for k, v := range req.Header { - m.Log("info", "%s: %s", k, v) + if m.Confs("logheaders") { + for k, v := range req.Header { + m.Log("info", "%s: %s", k, v) + } } if web.Client == nil { @@ -414,8 +454,10 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", return } m.Assert(e) - for k, v := range res.Header { - m.Log("info", "%s: %v", k, v) + if m.Confs("logheaders") { + for k, v := range res.Header { + m.Log("info", "%s: %v", k, v) + } } for _, v := range res.Cookies() { @@ -424,8 +466,22 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", } var result interface{} - ct := res.Header.Get("Content-Type") + defer func() { + m.Target().Configs[m.Confx("body_response")] = &ctx.Config{Value: result} + m.Log("info", "cache %s", m.Confx("body_response")) + }() + if m.Has("save") { + p := path.Join(m.Sess("nfs").Cmd("pwd").Result(0), m.Option("save")) + f, e := os.Create(p) + m.Assert(e) + io.Copy(f, res.Body) + defer f.Close() + m.Log("info", "save file %s", p) + return + } + + ct := res.Header.Get("Content-Type") switch { case strings.HasPrefix(ct, "application/json"): json.NewDecoder(res.Body).Decode(&result) @@ -433,10 +489,11 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", msg := m.Spawn() msg.Put("option", "response", result) msg.Cmd("trans", "response", m.Option("parse")) - m.Copy(msg, "append") - m.Copy(msg, "result") + m.Copy(msg, "append").Copy(msg, "result") return } + b, _ := json.Marshal(result) + result = string(b) case strings.HasPrefix(ct, "text/html"): html, e := goquery.NewDocumentFromReader(res.Body) m.Assert(e) @@ -485,7 +542,6 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", } } - m.Target().Configs[m.Confx("body_response")] = &ctx.Config{Value: result} m.Echo("%v", result) } }}, @@ -493,6 +549,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", Form: map[string]int{"file": 2, "content_type": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { msg := m.Spawn() + parse := "_" if m.Has("file") { file, e := os.Open(m.Meta["file"][1]) m.Assert(e) @@ -505,6 +562,10 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", m.Assert(e) for i := 1; i < len(arg)-1; i += 2 { + if arg[i] == "parse" { + parse = arg[i+1] + continue + } value := arg[i+1] if len(arg[i+1]) > 1 { switch arg[i+1][0] { @@ -525,6 +586,10 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", } else if m.Option("content_type") == "json" { data := map[string]interface{}{} for i := 1; i < len(arg)-1; i += 2 { + if arg[i] == "parse" { + parse = arg[i+1] + continue + } switch arg[i+1] { case "false": data[arg[i]] = false @@ -538,8 +603,11 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", } } } + b, e := json.Marshal(data) m.Assert(e) + m.Log("info", "json %v", string(b)) + msg.Optionv("body", bytes.NewReader(b)) msg.Option("content_type", "application/json") arg = arg[:1] @@ -559,6 +627,11 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", } else { msg.Option("content_type", "application/x-www-form-urlencoded") } + + if parse != "_" { + arg = append(arg, "parse") + arg = append(arg, parse) + } msg.Cmd("get", "method", "POST", arg) m.Copy(msg, "result").Copy(msg, "append") }}, @@ -769,7 +842,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", defer o.Close() io.Copy(o, f) - m.Log("upload", "file(%d): %s", h.Size, p) + m.Log("upload", "file: %s", p) m.Append("redirect", m.Option("referer")) }}, "/download/": &ctx.Command{Name: "/download/", Help: "上传文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { @@ -782,11 +855,6 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", accept_json := strings.HasPrefix(m.Option("accept"), "application/json") list := []interface{}{} - // tmpl, e := web.Template.Clone() - // m.Assert(e) - // tmpl.Funcs(ctx.CGI) - // - tmpl := web.Template if m.Confs("template_debug") { tmpl = template.New("render").Funcs(ctx.CGI) @@ -828,6 +896,12 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", right = m.Sess("aaa").Cmd("right", "void", "check", group).Results(0) } + if !right { + if lark := m.Find("web.lark"); lark != nil && m.Confs("login_lark") { + right = ctx.Right(lark.Cmd("auth", m.Option("username"), "check", m.Option("cmd")).Result(0)) + } + } + m.Log("info", "group: %v, name: %v, right: %v", group, order, right) for count := 0; count == 0; group, order, right = "login", "", true { for _, v := range m.Confv("componet", group).([]interface{}) { @@ -934,7 +1008,6 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", } }}, "/proxy/": &ctx.Command{Name: "/proxy/", Help: "服务代理", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - m.Log("fuck", "what %v", key) msg := m.Spawn().Cmd("get", strings.TrimPrefix(key, "/proxy/"), arg) m.Copy(msg, "append").Copy(msg, "result") }}, diff --git a/src/contexts/yac/yac.go b/src/contexts/yac/yac.go index baa93bea..6b14c613 100644 --- a/src/contexts/yac/yac.go +++ b/src/contexts/yac/yac.go @@ -359,7 +359,7 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", m.Cmd("train", "stm", "label", "label", "exp") m.Cmd("train", "stm", "goto", "goto", "exp", "opt{", "exp", "}", "exp") - m.Cmd("train", "stm", "echo", "echo", "rep{", "exp", "}") + m.Cmd("train", "stm", "expr", "expr", "rep{", "exp", "}") m.Cmd("train", "stm", "return", "return", "rep{", "exp", "}") m.Cmd("train", "word", "word", "mul{", "~", "!", "=", "\\?\\?", "\\?", "<", ">$", ">@", ">", "\\|", "%", "exe", "str", "[a-zA-Z0-9_/\\-.:]+", "}")