Files
Elydora-Go-SDK/cmd/elydora/plugins/shell_command.go
T
雷电芽衣 a7fc75bf6b chore(go): audit providers claudecode codex cursor gemini
Add managed_runtime.go (paths, config validation, identity, runtime file
changes, status checks) and shell_command.go (quoting, PowerShell
encoding, command parsing) and move the four providers onto them.

Claude-Session: https://claude.ai/code/session_01Agoc9bRVE9KL7mmWtey9Vq
2026-09-03 01:42:27 -04:00

199 lines
5.6 KiB
Go

package plugins
import (
"encoding/base64"
"encoding/binary"
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"unicode/utf16"
)
const (
posixApostrophe = `'"'"'`
powerShellExitSuffix = "; exit $LASTEXITCODE"
powerShellEncodedFlags = " -NoLogo -NoProfile -NonInteractive -EncodedCommand "
)
func resolveNodeRuntime() (string, error) {
nodePath, err := exec.LookPath("node")
if err != nil {
return "", fmt.Errorf("resolve Node.js runtime: %w", err)
}
absolute, err := filepath.Abs(nodePath)
if err != nil {
return "", fmt.Errorf("resolve Node.js runtime path: %w", err)
}
return absolute, nil
}
func resolveAbsoluteNodeRuntime(product string) (string, error) {
nodePath, err := resolveNodeRuntime()
if err != nil {
return "", err
}
if !filepath.IsAbs(nodePath) || !isNodeExecutable(nodePath) {
return "", fmt.Errorf("%s hooks require an absolute Node.js executable path", product)
}
return nodePath, nil
}
func isNodeExecutable(path string) bool {
name := filepath.Base(path)
return name == "node" || strings.EqualFold(name, "node.exe")
}
func quotePOSIXArgument(value string) string {
return "'" + strings.ReplaceAll(value, "'", posixApostrophe) + "'"
}
func quotePowerShellArgument(value string) string {
return "'" + strings.ReplaceAll(value, "'", "''") + "'"
}
func posixSource(runtimePath, scriptPath string) string {
return quotePOSIXArgument(runtimePath) + " " + quotePOSIXArgument(scriptPath)
}
func powerShellSource(runtimePath, scriptPath string) string {
return "& " + quotePowerShellArgument(runtimePath) + " " +
quotePowerShellArgument(scriptPath) + powerShellExitSuffix
}
func windowsPowerShellPath() string {
root := "C:\\Windows"
if runtime.GOOS == "windows" {
configured := os.Getenv("SystemRoot")
if filepath.IsAbs(configured) && !strings.ContainsAny(configured, "\"%\r\n") {
root = configured
}
}
return strings.TrimRight(root, `\/`) + `\System32\WindowsPowerShell\v1.0\powershell.exe`
}
func encodePowerShellSource(source string) string {
units := utf16.Encode([]rune(source))
raw := make([]byte, len(units)*2)
for index, value := range units {
binary.LittleEndian.PutUint16(raw[index*2:], value)
}
return base64.StdEncoding.EncodeToString(raw)
}
func decodePowerShellSource(encoded string) (string, bool) {
raw, err := base64.StdEncoding.DecodeString(encoded)
if err != nil || base64.StdEncoding.EncodeToString(raw) != encoded || len(raw)%2 != 0 {
return "", false
}
units := make([]uint16, len(raw)/2)
for index := range units {
units[index] = uint16(raw[index*2]) | uint16(raw[index*2+1])<<8
}
return string(utf16.Decode(units)), true
}
func encodedWindowsCommand(runtimePath, scriptPath string) string {
return `"` + windowsPowerShellPath() + `"` + powerShellEncodedFlags +
encodePowerShellSource(powerShellSource(runtimePath, scriptPath))
}
func readPOSIXArgument(command string, start int) (string, int, bool) {
if start >= len(command) || command[start] != '\'' {
return "", start, false
}
var value strings.Builder
for index := start + 1; index < len(command); {
if strings.HasPrefix(command[index:], posixApostrophe) {
value.WriteByte('\'')
index += len(posixApostrophe)
continue
}
if command[index] == '\'' {
return value.String(), index + 1, true
}
value.WriteByte(command[index])
index++
}
return "", start, false
}
func parsePOSIXCommand(command string) (string, string, bool) {
runtimePath, next, ok := readPOSIXArgument(command, 0)
if !ok || next >= len(command) || command[next] != ' ' {
return "", "", false
}
scriptPath, end, ok := readPOSIXArgument(command, next+1)
return runtimePath, scriptPath, ok && end == len(command)
}
func readPowerShellArgument(command string, start int) (string, int, bool) {
if start >= len(command) || command[start] != '\'' {
return "", start, false
}
var value strings.Builder
for index := start + 1; index < len(command); index++ {
if command[index] != '\'' {
value.WriteByte(command[index])
continue
}
if index+1 < len(command) && command[index+1] == '\'' {
value.WriteByte('\'')
index++
continue
}
return value.String(), index + 1, true
}
return "", start, false
}
func parsePowerShellSource(source string) (string, string, bool) {
if !strings.HasPrefix(source, "& ") {
return "", "", false
}
runtimePath, next, ok := readPowerShellArgument(source, 2)
if !ok || next >= len(source) || source[next] != ' ' {
return "", "", false
}
scriptPath, end, ok := readPowerShellArgument(source, next+1)
return runtimePath, scriptPath, ok && source[end:] == powerShellExitSuffix
}
func windowsPathBase(value string) string {
index := strings.LastIndexAny(value, `\/`)
return value[index+1:]
}
func isAbsoluteWindowsPath(value string) bool {
return len(value) >= 3 && ((value[0] >= 'A' && value[0] <= 'Z') ||
(value[0] >= 'a' && value[0] <= 'z')) && value[1] == ':' &&
(value[2] == '\\' || value[2] == '/') || strings.HasPrefix(value, `\\`)
}
func isPowerShellExecutable(value string) bool {
return isAbsoluteWindowsPath(value) &&
strings.EqualFold(windowsPathBase(value), "powershell.exe")
}
func parseEncodedWindowsCommand(command string) (string, string, bool) {
if !strings.HasPrefix(command, `"`) {
return "", "", false
}
closing := strings.IndexByte(command[1:], '"')
if closing < 0 {
return "", "", false
}
closing++
prefix := `"` + powerShellEncodedFlags
if !isPowerShellExecutable(command[1:closing]) || !strings.HasPrefix(command[closing:], prefix) {
return "", "", false
}
source, ok := decodePowerShellSource(command[closing+len(prefix):])
if !ok {
return "", "", false
}
return parsePowerShellSource(source)
}