diff --git a/cmd/verysimple/cli.go b/cmd/verysimple/cli.go index f82ac40..0fd8fab 100644 --- a/cmd/verysimple/cli.go +++ b/cmd/verysimple/cli.go @@ -63,7 +63,7 @@ func init() { cliCmdList = append(cliCmdList, &CliCmd{ "【生成分享链接】<-当前的配置", func() { - sc := mainM.GetStandardConfFromCurrentState() + sc := mainM.DumpStandardConf() interactively_generate_share(&sc) }, }, &CliCmd{ diff --git a/cmd/verysimple/cli_generateConfigs.go b/cmd/verysimple/cli_generateConfigs.go index eeb931c..a231743 100644 --- a/cmd/verysimple/cli_generateConfigs.go +++ b/cmd/verysimple/cli_generateConfigs.go @@ -17,7 +17,7 @@ import ( ) func interactively_exportVsConf() { - vc := mainM.GetVSConfFromCurrentState() + vc := mainM.DumpVSConf() bs, e := utils.GetPurgedTomlBytes(vc) if e != nil { @@ -89,6 +89,15 @@ func interactively_generate_share(conf *proxy.StandardConf) { }, }, + { + Name: "v2rayN分享链接 (vmess://base64)", + f: func() { + for _, v := range conf.Dial { + url := configAdapter.ToV2rayN(v) + fmt.Println(url) + } + }, + }, { Name: "xray分享链接标准提案 (#716)", f: func() { @@ -107,15 +116,7 @@ func interactively_generate_share(conf *proxy.StandardConf) { } }, }, - { - Name: "v2rayN分享链接 (vmess://base64)", - f: func() { - for _, v := range conf.Dial { - url := configAdapter.ToV2rayN(v) - fmt.Println(url) - } - }, - }, + { Name: "Quantumult X (圈叉的配置的 [server_local] 部分)", f: func() { @@ -160,6 +161,7 @@ func interactively_generateConf(confClient, confServer *proxy.StandardConf) { Items: []string{ "socks5", "http", + "socks5http", }, } i2, result, err := select2.Run() @@ -171,7 +173,7 @@ func interactively_generateConf(confClient, confServer *proxy.StandardConf) { fmt.Printf("你选择了 %s\n", result) - if i2 < 2 { + if i2 < 3 { confClient.Listen = append(confClient.Listen, &proxy.ListenConf{}) } else { utils.PrintStr("Prompt failed, werid input") diff --git a/cmd/verysimple/gui.go b/cmd/verysimple/gui.go index 5f3f096..1d9dd68 100644 --- a/cmd/verysimple/gui.go +++ b/cmd/verysimple/gui.go @@ -278,7 +278,7 @@ func makeBasicControlsPage() ui.Control { return } - vc := mainM.GetVSConfFromCurrentState() + vc := mainM.DumpVSConf() bs, e := utils.GetPurgedTomlBytes(vc) if e != nil { diff --git a/machine/apiServer.go b/machine/apiServer.go index 444757b..00e8933 100644 --- a/machine/apiServer.go +++ b/machine/apiServer.go @@ -7,6 +7,7 @@ import ( "flag" "log" "net/http" + "os" "strconv" "strings" "time" @@ -238,11 +239,11 @@ func (m *M) runApiServer() { return } if isDial { - dc := m.getDialConfFromCurrentState(ind) + dc := m.dumpDialConf(ind) url := proxy.ToStandardUrl(&dc.CommonConf, dc, nil) w.Write([]byte(url)) } else { - lc := m.getListenConfFromCurrentState(ind) + lc := m.dumpListenConf(ind) url := proxy.ToStandardUrl(&lc.CommonConf, nil, lc) w.Write([]byte(url)) } @@ -251,6 +252,53 @@ func (m *M) runApiServer() { }) + //保存所有配置到标准配置文件. 如果是GET, 直接将文件打印给客户, 如果是POST, 接收name参数并导出到文件 + ser.addServerHandle(mux, "dump", func(w http.ResponseWriter, r *http.Request) { + q := r.URL.Query() + + fn := q.Get("name") + if fn == "" && r.Method == "POST" { + if ce := utils.CanLogWarn("api server got dump request but no file name given"); ce != nil { + ce.Write() + } + return + } + vc := m.DumpVSConf() + + bs, e := utils.GetPurgedTomlBytes(vc) + if e != nil { + if ce := utils.CanLogErr("api server: 转换格式错误"); ce != nil { + ce.Write(zap.Error(e)) + } + w.WriteHeader(500) + w.Write([]byte("failed")) + + return + } + + if r.Method == "GET" { + w.Write(bs) + } else { + e = os.WriteFile(fn, bs, 0666) + + if e != nil { + if ce := utils.CanLogErr("写入文件错误"); ce != nil { + ce.Write(zap.Error(e)) + } + w.WriteHeader(500) + w.Write([]byte("failed")) + + return + } + + if ce := utils.CanLogInfo("导出成功"); ce != nil { + ce.Write(zap.String("filename", fn)) + } + w.Write([]byte("ok")) + } + + }) + tlsConf := &tls.Config{} if m.PlainHttp { diff --git a/machine/load.go b/machine/load.go index 89fbdcd..d94a31c 100644 --- a/machine/load.go +++ b/machine/load.go @@ -168,35 +168,37 @@ func (m *M) loadUrlClient(urlConf proxy.UrlConf) (result int, client proxy.Clien return } -func (m *M) GetVSConfFromCurrentState() (vc VSConf) { - vc.StandardConf = m.GetStandardConfFromCurrentState() +// 从当前内存中的配置 导出 VSConf +func (m *M) DumpVSConf() (vc VSConf) { + vc.StandardConf = m.DumpStandardConf() vc.ApiServerConf = &m.ApiServerConf vc.AppConf = &m.AppConf return } -func (m *M) GetStandardConfFromCurrentState() (sc proxy.StandardConf) { +// 从当前内存中的配置 导出 proxy.StandardConf +func (m *M) DumpStandardConf() (sc proxy.StandardConf) { for i := range m.allClients { - sc.Dial = append(sc.Dial, m.getDialConfFromCurrentState(i)) + sc.Dial = append(sc.Dial, m.dumpDialConf(i)) } for i := range m.allServers { - sc.Listen = append(sc.Listen, m.getListenConfFromCurrentState(i)) + sc.Listen = append(sc.Listen, m.dumpListenConf(i)) } return } -func (m *M) getDialConfFromCurrentState(i int) (dc *proxy.DialConf) { +func (m *M) dumpDialConf(i int) (dc *proxy.DialConf) { c := m.allClients[i] dc = c.GetBase().DialConf return } -func (m *M) getListenConfFromCurrentState(i int) (lc *proxy.ListenConf) { +func (m *M) dumpListenConf(i int) (lc *proxy.ListenConf) { c := m.allServers[i] lc = c.GetBase().ListenConf