From a6637b51c96c9422679a11974b9393d35b863068 Mon Sep 17 00:00:00 2001 From: sawka Date: Tue, 20 Sep 2022 17:37:49 -0700 Subject: [PATCH] getlinecmd and getlineidbyarg --- pkg/cmdrunner/cmdrunner.go | 7 ++-- pkg/scbase/scbase.go | 13 ++++++++ pkg/sstore/dbops.go | 67 ++++++++++++++++++++++++++++++++++---- pkg/sstore/sstore.go | 12 +++---- 4 files changed, 83 insertions(+), 16 deletions(-) diff --git a/pkg/cmdrunner/cmdrunner.go b/pkg/cmdrunner/cmdrunner.go index 2c2fd4bc..4a7056b6 100644 --- a/pkg/cmdrunner/cmdrunner.go +++ b/pkg/cmdrunner/cmdrunner.go @@ -19,6 +19,7 @@ import ( "github.com/scripthaus-dev/mshell/pkg/packet" "github.com/scripthaus-dev/mshell/pkg/shexec" "github.com/scripthaus-dev/sh2-server/pkg/remote" + "github.com/scripthaus-dev/sh2-server/pkg/scbase" "github.com/scripthaus-dev/sh2-server/pkg/scpacket" "github.com/scripthaus-dev/sh2-server/pkg/sstore" ) @@ -178,7 +179,7 @@ func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.U if err != nil { return nil, fmt.Errorf("/run error: %w", err) } - cmdId := uuid.New().String() + cmdId := scbase.GenSCUUID() cmdStr := firstArg(pk) runPacket := packet.MakeRunPacket() runPacket.ReqId = uuid.New().String() @@ -232,7 +233,7 @@ func addToHistory(ctx context.Context, pk *scpacket.FeCommandPacketType, history return err } hitem := &sstore.HistoryItemType{ - HistoryId: uuid.New().String(), + HistoryId: scbase.GenSCUUID(), Ts: time.Now().UnixMilli(), UserId: DefaultUserId, SessionId: ids.SessionId, @@ -512,7 +513,7 @@ func RemoteNewCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ss remoteOpts.Color = color } r := &sstore.RemoteType{ - RemoteId: uuid.New().String(), + RemoteId: scbase.GenSCUUID(), PhysicalId: "", RemoteType: sstore.RemoteTypeSsh, RemoteAlias: alias, diff --git a/pkg/scbase/scbase.go b/pkg/scbase/scbase.go index 094d7b38..1756bda2 100644 --- a/pkg/scbase/scbase.go +++ b/pkg/scbase/scbase.go @@ -6,8 +6,10 @@ import ( "io/fs" "os" "path" + "strconv" "sync" + "github.com/google/uuid" "github.com/scripthaus-dev/mshell/pkg/base" "golang.org/x/sys/unix" ) @@ -140,3 +142,14 @@ func (g ScFileNameGenerator) PtyOutFile(ck base.CommandKey) string { func (g ScFileNameGenerator) RunOutFile(ck base.CommandKey) string { return path.Join(g.ScHome, SessionsDirBaseName, ck.GetSessionId(), ck.GetCmdId()+".runout") } + +func GenSCUUID() string { + for { + rtn := uuid.New().String() + _, err := strconv.Atoi(rtn[0:8]) + if err == nil { // do not allow UUIDs where the initial 8 bytes parse to an integer + continue + } + return rtn + } +} diff --git a/pkg/sstore/dbops.go b/pkg/sstore/dbops.go index d19f7734..487d7073 100644 --- a/pkg/sstore/dbops.go +++ b/pkg/sstore/dbops.go @@ -4,10 +4,12 @@ import ( "context" "database/sql" "fmt" + "strconv" "strings" "github.com/google/uuid" "github.com/scripthaus-dev/mshell/pkg/packet" + "github.com/scripthaus-dev/sh2-server/pkg/scbase" ) const HistoryCols = "historyid, ts, userid, sessionid, screenid, windowid, lineid, cmdid, haderror, cmdstr, remoteownerid, remoteid, remotename, ismetacmd" @@ -371,7 +373,7 @@ func GetSessionByName(ctx context.Context, name string) (*SessionType, error) { // also creates default window, returns sessionId // if sessionName == "", it will be generated func InsertSessionWithName(ctx context.Context, sessionName string, activate bool) (UpdatePacket, error) { - newSessionId := uuid.New().String() + newSessionId := scbase.GenSCUUID() txErr := WithTx(ctx, func(tx *TxWrap) error { names := tx.SelectStrings(`SELECT name FROM session`) sessionName = fmtUniqueName(sessionName, "session-%d", len(names)+1, names) @@ -465,7 +467,7 @@ func InsertScreen(ctx context.Context, sessionId string, origScreenName string, maxScreenIdx := tx.GetInt(`SELECT COALESCE(max(screenidx), 0) FROM screen WHERE sessionid = ?`, sessionId) screenNames := tx.SelectStrings(`SELECT name FROM screen WHERE sessionid = ?`, sessionId) screenName := fmtUniqueName(origScreenName, "s%d", maxScreenIdx+1, screenNames) - newScreenId = uuid.New().String() + newScreenId = scbase.GenSCUUID() query = `INSERT INTO screen (sessionid, screenid, name, activewindowid, screenidx, screenopts, ownerid, sharemode) VALUES (?, ?, ?, ?, ?, ?, '', 'local')` tx.ExecWrap(query, sessionId, newScreenId, screenName, newWindowId, maxScreenIdx+1, ScreenOptsType{}) layout := LayoutType{Type: LayoutFull} @@ -513,7 +515,7 @@ func GetScreenById(ctx context.Context, sessionId string, screenId string) (*Scr func txCreateWindow(tx *TxWrap, sessionId string, curRemote RemotePtrType) string { w := &WindowType{ SessionId: sessionId, - WindowId: uuid.New().String(), + WindowId: scbase.GenSCUUID(), CurRemote: curRemote, NextLineNum: 1, WinOpts: WindowOptsType{}, @@ -527,6 +529,59 @@ func txCreateWindow(tx *TxWrap, sessionId string, curRemote RemotePtrType) strin return w.WindowId } +func FindLineIdByArg(ctx context.Context, sessionId string, windowId string, lineArg string) (string, error) { + var lineId string + txErr := WithTx(ctx, func(tx *TxWrap) error { + lineNum, err := strconv.Atoi(lineArg) + if err == nil { + // valid linenum + query := `SELECT lineid FROM line WHERE sessionid = ? AND windowid = ? AND linenum = ?` + lineId = tx.GetString(query, sessionId, windowId, lineNum) + } else if len(lineArg) == 8 { + // prefix id string match + query := `SELECT lineid FROM line WHERE sessionid = ? AND windowid = ? AND substr(lineid, 1, 8) = ?` + lineId = tx.GetString(query, sessionId, windowId, lineArg) + } else { + // id match + query := `SELECT * FROM line WHERE sessionid = ? AND windowid = ? AND lineid = ?` + lineId = tx.GetString(query, sessionId, windowId, lineArg) + } + return nil + }) + if txErr != nil { + return "", txErr + } + return lineId, nil +} + +func GetLineCmd(ctx context.Context, sessionId string, windowId string, lineId string) (*LineType, *CmdType, error) { + var lineRtn *LineType + var cmdRtn *CmdType + txErr := WithTx(ctx, func(tx *TxWrap) error { + query := `SELECT windowid FROM window WHERE sessionid = ? AND windowid = ?` + if !tx.Exists(query, sessionId, windowId) { + return fmt.Errorf("window not found") + } + var lineVal LineType + query = `SELECT * FROM line WHERE sessionid = ? AND windowid = ? AND lineid = ?` + found := tx.GetWrap(&lineVal, query, sessionId, windowId, lineId) + if !found { + return nil + } + lineRtn = &lineVal + if lineVal.CmdId != "" { + query = `SELECT * FROM cmd WHERE sessionid = ? AND cmdid = ?` + m := tx.GetMap(query, sessionId, lineVal.CmdId) + cmdRtn = CmdFromMap(m) + } + return nil + }) + if txErr != nil { + return nil, nil, txErr + } + return lineRtn, cmdRtn, nil +} + func InsertLine(ctx context.Context, line *LineType, cmd *CmdType) error { if line == nil { return fmt.Errorf("line cannot be nil") @@ -538,10 +593,8 @@ func InsertLine(ctx context.Context, line *LineType, cmd *CmdType) error { return fmt.Errorf("line should not hage linenum set") } return WithTx(ctx, func(tx *TxWrap) error { - var windowId string query := `SELECT windowid FROM window WHERE sessionid = ? AND windowid = ?` - hasWindow := tx.GetWrap(&windowId, query, line.SessionId, line.WindowId) - if !hasWindow { + if !tx.Exists(query, line.SessionId, line.WindowId) { return fmt.Errorf("window not found, cannot insert line[%s/%s]", line.SessionId, line.WindowId) } query = `SELECT nextlinenum FROM window WHERE sessionid = ? AND windowid = ?` @@ -744,7 +797,7 @@ func UpdateRemoteState(ctx context.Context, sessionId string, windowId string, r found := tx.GetWrap(&ri, query, sessionId, windowId, remotePtr.OwnerId, remotePtr.RemoteId, remotePtr.Name) if !found { ri = RemoteInstance{ - RIId: uuid.New().String(), + RIId: scbase.GenSCUUID(), Name: remotePtr.Name, SessionId: sessionId, WindowId: windowId, diff --git a/pkg/sstore/sstore.go b/pkg/sstore/sstore.go index 95ace511..5833c970 100644 --- a/pkg/sstore/sstore.go +++ b/pkg/sstore/sstore.go @@ -581,7 +581,7 @@ func makeNewLineCmd(sessionId string, windowId string, userId string, cmdId stri rtn.SessionId = sessionId rtn.WindowId = windowId rtn.UserId = userId - rtn.LineId = uuid.New().String() + rtn.LineId = scbase.GenSCUUID() rtn.Ts = time.Now().UnixMilli() rtn.LineLocal = true rtn.LineType = LineTypeCmd @@ -594,7 +594,7 @@ func makeNewLineText(sessionId string, windowId string, userId string, text stri rtn.SessionId = sessionId rtn.WindowId = windowId rtn.UserId = userId - rtn.LineId = uuid.New().String() + rtn.LineId = scbase.GenSCUUID() rtn.Ts = time.Now().UnixMilli() rtn.LineLocal = true rtn.LineType = LineTypeText @@ -642,7 +642,7 @@ func EnsureLocalRemote(ctx context.Context) error { } // create the local remote localRemote := &RemoteType{ - RemoteId: uuid.New().String(), + RemoteId: scbase.GenSCUUID(), PhysicalId: physicalId, RemoteType: RemoteTypeSsh, RemoteAlias: LocalRemoteAlias, @@ -670,7 +670,7 @@ func AddTest01Remote(ctx context.Context) error { return nil } testRemote := &RemoteType{ - RemoteId: uuid.New().String(), + RemoteId: scbase.GenSCUUID(), RemoteType: RemoteTypeSsh, RemoteAlias: "test01", RemoteCanonicalName: "ubuntu@test01.ec2", @@ -702,7 +702,7 @@ func AddTest02Remote(ctx context.Context) error { return nil } testRemote := &RemoteType{ - RemoteId: uuid.New().String(), + RemoteId: scbase.GenSCUUID(), RemoteType: RemoteTypeSsh, RemoteAlias: "test2", RemoteCanonicalName: "test2@test01.ec2", @@ -740,7 +740,7 @@ func EnsureDefaultSession(ctx context.Context) (*SessionType, error) { } func createClientData(tx *TxWrap) error { - userId := uuid.New().String() + userId := scbase.GenSCUUID() curve := elliptic.P384() pkey, err := ecdsa.GenerateKey(curve, rand.Reader) if err != nil {