mirror of
https://github.com/BishopFox/sliver.git
synced 2026-11-08 01:38:17 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba3ec022bb | ||
|
|
394ba431b2 | ||
|
|
cda6aeaee6 | ||
|
|
187f9e99ac | ||
|
|
1f6abf9be3 | ||
|
|
25a22054b7 | ||
|
|
64c5460545 | ||
|
|
76fb9dfc93 | ||
|
|
ccd3ed2250 | ||
|
|
fb5c6c0c88 | ||
|
|
11878069f6 | ||
|
|
3db3930091 | ||
|
|
9e6412c911 | ||
|
|
ade96fa281 | ||
|
|
3035d75882 | ||
|
|
4ed95375e0 | ||
|
|
9ee10c5321 | ||
|
|
3cc7be8a9f | ||
|
|
d411d2400c | ||
|
|
e31cafa81d | ||
|
|
80677e652b | ||
|
|
88abea26a7 | ||
|
|
120d537044 | ||
|
|
59781d4328 | ||
|
|
f117995aa1 | ||
|
|
e4793cf616 | ||
|
|
b68f4bffd3 | ||
|
|
22fea029ec | ||
|
|
b1db1ab614 | ||
|
|
40b99e860f | ||
|
|
56d143b018 | ||
|
|
327f7c6826 | ||
|
|
eb9506510e | ||
|
|
9c5aa26af9 | ||
|
|
f2b78748de | ||
|
|
891bb49f1a | ||
|
|
82d1728360 | ||
|
|
01b6a3c657 | ||
|
|
312f133f1e | ||
|
|
a141e1f689 | ||
|
|
a9a16aaa39 | ||
|
|
2c944db7ed | ||
|
|
b93f939ec5 | ||
|
|
ba07826d83 | ||
|
|
09fb3e0095 | ||
|
|
be9c34e1ef | ||
|
|
d5945898b3 | ||
|
|
7d8457d494 | ||
|
|
330ceea52f | ||
|
|
afe4fb04a3 | ||
|
|
e89a04f747 | ||
|
|
e8aae22d50 | ||
|
|
003f882be5 | ||
|
|
bb2a56d469 | ||
|
|
bb36fb6850 | ||
|
|
dd31ae253c | ||
|
|
307b1998a1 | ||
|
|
381e131438 | ||
|
|
c9898b9854 | ||
|
|
9dd5dd9c93 | ||
|
|
01f2d0c9de | ||
|
|
fd1b873f75 | ||
|
|
bb51a9f1a6 | ||
|
|
f1d4a51e73 | ||
|
|
d003f5a4ac | ||
|
|
36277b9d46 | ||
|
|
c90988aba5 | ||
|
|
a6dca18cdc | ||
|
|
dd48b4b71d | ||
|
|
91e6ea5e05 | ||
|
|
3a8201c202 | ||
|
|
2ea605e915 |
No files matched your search
@@ -0,0 +1,16 @@
|
||||
# Basic set up for three package managers
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
|
||||
# Maintain dependencies for GitHub Actions
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
# Maintain dependencies for go
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
@@ -15,9 +15,9 @@ jobs:
|
||||
steps:
|
||||
|
||||
- name: Go 1.18
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.18.5'
|
||||
go-version: '1.18.6'
|
||||
|
||||
- name: OS Packages
|
||||
run: |
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
mingw-w64 binutils-mingw-w64 g++-mingw-w64 gcc-multilib
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Git Fetch Tags
|
||||
run: git fetch --prune --unshallow --tags -f
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
run: export PATH=/home/runner/go/bin/:$PATH && make linux
|
||||
|
||||
- name: Linux Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: linux
|
||||
path: ./sliver-*
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
export PATH=/home/runner/go/bin/:$PATH && make windows
|
||||
|
||||
- name: Windows Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: windows
|
||||
path: ./sliver-*
|
||||
@@ -66,15 +66,15 @@ jobs:
|
||||
steps:
|
||||
|
||||
- name: Go 1.18
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.18.5'
|
||||
go-version: '1.18.6'
|
||||
|
||||
- name: Mingw
|
||||
run: brew install mingw-w64
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Git Fetch Tags
|
||||
run: git fetch --prune --unshallow --tags -f
|
||||
@@ -93,7 +93,7 @@ jobs:
|
||||
run: make macos-arm64
|
||||
|
||||
- name: MacOS Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: macos
|
||||
path: ./sliver-*
|
||||
@@ -110,7 +110,7 @@ jobs:
|
||||
steps:
|
||||
|
||||
- run: mkdir -p ./builds
|
||||
- uses: actions/download-artifact@v2
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
path: ./builds
|
||||
|
||||
|
||||
@@ -18,12 +18,12 @@ jobs:
|
||||
steps:
|
||||
# Setup go environment
|
||||
- name: Go 1.18
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: "1.18.5"
|
||||
go-version: "1.18.6"
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# Must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head of the pull request.
|
||||
@@ -55,14 +55,14 @@ jobs:
|
||||
&& make install
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Go Assets
|
||||
run: ./go-assets.sh
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
config-file: ./.github/codeql/codeql-config.yml
|
||||
languages: go
|
||||
@@ -72,6 +72,6 @@ jobs:
|
||||
make
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
uses: github/codeql-action/analyze@v2
|
||||
env:
|
||||
VERSION: ${{github.sha}}
|
||||
@@ -21,9 +21,9 @@ jobs:
|
||||
steps:
|
||||
|
||||
- name: Go 1.18
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.18.5'
|
||||
go-version: '1.18.6'
|
||||
|
||||
- name: OS Packages
|
||||
run: |
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
mingw-w64 binutils-mingw-w64 g++-mingw-w64 gcc-multilib
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Git Fetch Tags
|
||||
run: git fetch --prune --unshallow --tags -f
|
||||
@@ -56,15 +56,15 @@ jobs:
|
||||
steps:
|
||||
|
||||
- name: Go 1.18
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.18.5'
|
||||
go-version: '1.18.6'
|
||||
|
||||
- name: Mingw
|
||||
run: brew install mingw-w64
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Git Fetch Tags
|
||||
run: git fetch --prune --unshallow --tags -f
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.18.5
|
||||
FROM golang:1.18.6
|
||||
|
||||
#
|
||||
# IMPORTANT: This Dockerfile is used for testing, I do not recommend deploying
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
GO ?= go
|
||||
ARTIFACT_SUFFIX ?=
|
||||
ENV =
|
||||
TAGS = -tags osusergo,netgo,cgosqlite,sqlite_omit_load_extension
|
||||
TAGS ?= -tags osusergo,netgo,cgosqlite,sqlite_omit_load_extension
|
||||
|
||||
|
||||
#
|
||||
|
||||
@@ -717,6 +717,28 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
},
|
||||
HelpGroup: consts.GenericHelpGroup,
|
||||
})
|
||||
tasksCmd.AddCommand(&grumble.Command{
|
||||
Name: consts.CancelStr,
|
||||
Help: "Cancel a pending beacon task",
|
||||
LongHelp: help.GetHelpFor([]string{consts.TasksStr, consts.CancelStr}),
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.Bool("O", "overflow", false, "overflow terminal width (display truncated rows)")
|
||||
f.Int("S", "skip-pages", 0, "skip the first n page(s)")
|
||||
f.String("f", "filter", "", "filter based on task type (case-insensitive prefix matching)")
|
||||
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
},
|
||||
Args: func(a *grumble.Args) {
|
||||
a.String("id", "beacon task ID", grumble.Default(""))
|
||||
},
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
con.Println()
|
||||
tasks.TasksCancelCmd(ctx, con)
|
||||
con.Println()
|
||||
return nil
|
||||
},
|
||||
HelpGroup: consts.GenericHelpGroup,
|
||||
})
|
||||
con.App.AddCommand(tasksCmd)
|
||||
|
||||
// [ Use ] --------------------------------------------------------------
|
||||
|
||||
@@ -90,7 +90,7 @@ func ExecuteAssemblyCmd(ctx *grumble.Context, con *console.SliverConsoleClient)
|
||||
ClassName: ctx.Flags.String("class"),
|
||||
AppDomain: ctx.Flags.String("app-domain"),
|
||||
ProcessArgs: processArgs,
|
||||
PPid: uint32(ctx.Flags.Int("ppid")),
|
||||
PPid: uint32(ctx.Flags.Uint("ppid")),
|
||||
Runtime: runtime,
|
||||
EtwBypass: etwBypass,
|
||||
AmsiBypass: amsiBypass,
|
||||
|
||||
@@ -50,6 +50,8 @@ func SideloadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
con.PrintErrorf("%s", err.Error())
|
||||
return
|
||||
}
|
||||
processArgsStr := ctx.Flags.String("process-arguments")
|
||||
processArgs := strings.Split(processArgsStr, " ")
|
||||
isDLL := (filepath.Ext(binPath) == ".dll")
|
||||
ctrl := make(chan bool)
|
||||
con.SpinUntil(fmt.Sprintf("Sideloading %s ...", binPath), ctrl)
|
||||
@@ -62,6 +64,8 @@ func SideloadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
Kill: !ctx.Flags.Bool("keep-alive"),
|
||||
IsDLL: isDLL,
|
||||
IsUnicode: ctx.Flags.Bool("unicode"),
|
||||
PPid: uint32(ctx.Flags.Uint("ppid")),
|
||||
ProcessArgs: processArgs,
|
||||
})
|
||||
ctrl <- true
|
||||
<-ctrl
|
||||
|
||||
@@ -477,6 +477,7 @@ func ParseHTTPc2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
uri.Path = strings.TrimSuffix(uri.Path, "/")
|
||||
if uri.Scheme != "http" && uri.Scheme != "https" {
|
||||
return nil, fmt.Errorf("invalid http(s) scheme: %s", uri.Scheme)
|
||||
}
|
||||
|
||||
@@ -39,6 +39,11 @@ var (
|
||||
// Process Name -> [Color, Stylized Name]
|
||||
"ccSvcHst.exe": {console.Red, "Symantec Endpoint Protection"}, // Symantec Endpoint Protection (SEP)
|
||||
"cb.exe": {console.Red, "Carbon Black"}, // Carbon Black
|
||||
"RepMgr.exe": {console.Red, "Carbon Black Cloud Sensor"}, // Carbon Black Cloud Sensor
|
||||
"RepUtils.exe": {console.Red, "Carbon Black Cloud Sensor"}, // Carbon Black Cloud Sensor
|
||||
"RepUx.exe": {console.Red, "Carbon Black Cloud Sensor"}, // Carbon Black Cloud Sensor
|
||||
"RepWSC.exe": {console.Red, "Carbon Black Cloud Sensor"}, // Carbon Black Cloud Sensor
|
||||
"scanhost.exe": {console.Red, "Carbon Black Cloud Sensor"}, // Carbon Black Cloud Sensor
|
||||
"MsMpEng.exe": {console.Red, "Windows Defender"}, // Windows Defender
|
||||
"smartscreen.exe": {console.Red, "Windows Smart Screen"}, // Windows Defender Smart Screen
|
||||
"CSFalconService.exe": {console.Red, "CrowdStrike"}, // Crowdstrike Falcon Service
|
||||
@@ -46,12 +51,28 @@ var (
|
||||
"bdservicehost.exe": {console.Red, "Bitdefender"}, // Bitdefender (Total Security)
|
||||
"bdagent.exe": {console.Red, "Bitdefender"}, // Bitdefender (Total Security)
|
||||
"bdredline.exe": {console.Red, "Bitdefender"}, // Bitdefender Redline Update Service (Source https://community.bitdefender.com/en/discussion/82135/bdredline-exe-bitdefender-total-security-2020)
|
||||
"Deep Security Manager.exe": {console.Red, "Trend Micro"}, // TM Deep Security Manager
|
||||
"coreServiceShell.exe": {console.Red, "Trend Micro"}, // TM Anti-malware scan process
|
||||
"ds_monitor.exe": {console.Red, "Trend Micro"}, // TM Deep Security Monitor
|
||||
"Notifier.exe": {console.Red, "Trend Micro"}, // TM Deep Security Notifier's process
|
||||
"dsa.exe": {console.Red, "Trend Micro"}, // TM Agent's main process
|
||||
"ds_nuagent.exe": {console.Red, "Trend Micro"}, // TM Advanced TLS traffic inspection
|
||||
"coreFrameworkHost.exe": {console.Red, "Trend Micro"}, // TM Anti-malware scan process
|
||||
"SentinelServiceHost.exe": {console.Red, "SentinelOne"}, // Sentinel One
|
||||
"SentinelStaticEngine.exe": {console.Red, "SentinelOne"}, // Sentinel One
|
||||
"SentinelStaticEngineScanner.exe": {console.Red, "SentinelOne"}, // Sentinel One
|
||||
"SentinelAgent.exe": {console.Red, "SentinelOne"}, // Sentinel One
|
||||
"SentinelAgentWorker.exe": {console.Red, "SentinelOne"}, // Sentinel One
|
||||
"SentinelHelperService.exe": {console.Red, "SentinelOne"}, // Sentinel One
|
||||
"SentinelBrowserNativeHost.exe": {console.Red, "SentinelOne"}, // Sentinel One
|
||||
"SentinelUI.exe": {console.Red, "SentinelOne"}, // Sentinel One
|
||||
"Sysmon.exe": {console.Red, "Sysmon"}, // Sysmon
|
||||
"Sysmon64.exe": {console.Red, "Sysmon64"}, // Sysmon64
|
||||
"CylanceSvc.exe": {console.Red, "Cylance"}, // Cylance
|
||||
"CylanceUI.exe": {console.Red, "Cylance"}, // Cylance
|
||||
"TaniumClient.exe": {console.Red, "Tanium"}, // Tanium
|
||||
"TaniumCX.exe": {console.Red, "Tanium"}, // Tanium
|
||||
"TaniumDetectEngine.exe": {console.Red, "Tanium"}, // Tanium
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -157,6 +157,8 @@ func emojiState(state string) string {
|
||||
return "⏳"
|
||||
case "failed":
|
||||
return "❌"
|
||||
case "canceled":
|
||||
return "🚫"
|
||||
default:
|
||||
return "❓"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
|
||||
// TasksCancelCmd - Cancel a beacon task before it's sent to the implant
|
||||
func TasksCancelCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
beacon := con.ActiveTarget.GetBeaconInteractive()
|
||||
if beacon == nil {
|
||||
return
|
||||
}
|
||||
|
||||
idArg := ctx.Args.String("id")
|
||||
var task *clientpb.BeaconTask
|
||||
var err error
|
||||
if idArg == "" {
|
||||
beaconTasks, err := con.Rpc.GetBeaconTasks(context.Background(), &clientpb.Beacon{ID: beacon.ID})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
tasks := []*clientpb.BeaconTask{}
|
||||
for _, task := range beaconTasks.Tasks {
|
||||
if task.State == "pending" {
|
||||
tasks = append(tasks, task)
|
||||
}
|
||||
}
|
||||
if len(tasks) == 0 {
|
||||
con.PrintErrorf("No pending tasks for beacon\n")
|
||||
return
|
||||
}
|
||||
|
||||
task, err = SelectBeaconTask(tasks)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
con.Printf(console.UpN+console.Clearln, 1)
|
||||
} else {
|
||||
task, err = con.Rpc.GetBeaconTaskContent(context.Background(), &clientpb.BeaconTask{ID: idArg})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if task != nil {
|
||||
task, err := con.Rpc.CancelBeaconTask(context.Background(), task)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Task %s canceled\n", task.ID)
|
||||
}
|
||||
}
|
||||
@@ -97,6 +97,8 @@ func prettyState(state string) string {
|
||||
return console.Bold + console.Orange + state + console.Normal
|
||||
case "completed":
|
||||
return console.Bold + console.Green + state + console.Normal
|
||||
case "canceled":
|
||||
return console.Bold + console.Gray + state + console.Normal
|
||||
default:
|
||||
return state
|
||||
}
|
||||
|
||||
@@ -104,6 +104,7 @@ const (
|
||||
ReconfigStr = "reconfig"
|
||||
PruneStr = "prune"
|
||||
TasksStr = "tasks"
|
||||
CancelStr = "cancel"
|
||||
GenerateStr = "generate"
|
||||
RegenerateStr = "regenerate"
|
||||
CompilerInfoStr = "info"
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ set -e
|
||||
|
||||
# Creates the static go asset archives
|
||||
|
||||
GO_VER="1.18.5"
|
||||
GO_VER="1.18.6"
|
||||
GARBLE_VER="1.18.0"
|
||||
SGN_VER="0.0.3"
|
||||
|
||||
|
||||
@@ -5,21 +5,22 @@ go 1.18
|
||||
replace github.com/desertbit/grumble v1.1.1 => github.com/moloch--/grumble v1.1.6
|
||||
|
||||
require (
|
||||
github.com/AlecAivazis/survey/v2 v2.2.2
|
||||
github.com/AlecAivazis/survey/v2 v2.3.6
|
||||
github.com/Binject/binjection v0.0.0-20200705191933-da1a50d7013d
|
||||
github.com/Binject/debug v0.0.0-20210312092933-6277045c2fdf
|
||||
github.com/Binject/go-donut v0.0.0-20210701074227-67a31e2d883e
|
||||
github.com/Binject/universal v0.0.0-20210304094126-daefaa886313
|
||||
github.com/Ne0nd0g/go-clr v1.0.2
|
||||
github.com/alecthomas/chroma v0.8.1
|
||||
github.com/cheggaaa/pb/v3 v3.0.5
|
||||
github.com/alecthomas/chroma v0.10.0
|
||||
github.com/cheggaaa/pb/v3 v3.1.0
|
||||
github.com/chromedp/cdproto v0.0.0-20220827030233-358ed4af73cf
|
||||
github.com/chromedp/chromedp v0.8.5
|
||||
github.com/desertbit/columnize v2.1.0+incompatible
|
||||
github.com/desertbit/go-shlex v0.1.1
|
||||
github.com/desertbit/grumble v1.1.1
|
||||
github.com/fatih/color v1.12.0
|
||||
github.com/gofrs/uuid v3.3.0+incompatible
|
||||
github.com/desertbit/readline v1.5.1
|
||||
github.com/fatih/color v1.13.0
|
||||
github.com/gofrs/uuid v4.3.0+incompatible
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2
|
||||
@@ -27,16 +28,16 @@ require (
|
||||
github.com/kbinani/screenshot v0.0.0-20191211154542-3a185f1ce18f
|
||||
github.com/lesnuages/go-winio v0.4.19
|
||||
github.com/lesnuages/snitch v0.6.0
|
||||
github.com/mattn/go-sqlite3 v1.14.12
|
||||
github.com/miekg/dns v1.1.35
|
||||
github.com/mattn/go-sqlite3 v1.14.15
|
||||
github.com/miekg/dns v1.1.50
|
||||
github.com/moloch--/memmod v0.0.0-20211120144554-8b37cc654945
|
||||
github.com/pquerna/otp v1.3.0
|
||||
github.com/shirou/gopsutil/v3 v3.21.10
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/spf13/cobra v1.1.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/spf13/cobra v1.5.0
|
||||
github.com/stretchr/testify v1.8.0
|
||||
github.com/things-go/go-socks5 v0.0.3-0.20210722055343-24af464efe43
|
||||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
|
||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f
|
||||
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
|
||||
@@ -46,10 +47,10 @@ require (
|
||||
google.golang.org/grpc v1.42.0-dev.0.20211020220737-f00baa6c3c84
|
||||
google.golang.org/protobuf v1.27.1
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.8
|
||||
gorm.io/driver/mysql v1.0.3
|
||||
gorm.io/driver/postgres v1.0.5
|
||||
gorm.io/driver/sqlite v1.1.3
|
||||
gorm.io/gorm v1.21.14
|
||||
gorm.io/driver/mysql v1.3.6
|
||||
gorm.io/driver/postgres v1.3.9
|
||||
gorm.io/driver/sqlite v1.3.6
|
||||
gorm.io/gorm v1.23.8
|
||||
gvisor.dev/gvisor v0.0.0-20211020211948-f76a604701b6
|
||||
modernc.org/sqlite v1.16.0
|
||||
)
|
||||
@@ -65,15 +66,13 @@ require (
|
||||
github.com/awgh/rawreader v0.0.0-20200626064944-56820a9c6da4 // indirect
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||
github.com/chromedp/sysutil v1.0.0 // indirect
|
||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/demisto/goxforce v0.0.0-20160322194047-db8357535b1d // indirect
|
||||
github.com/desertbit/closer/v3 v3.1.2 // indirect
|
||||
github.com/desertbit/readline v1.5.1 // indirect
|
||||
github.com/dlclark/regexp2 v1.2.0 // indirect
|
||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-sql-driver/mysql v1.5.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.6.0 // indirect
|
||||
github.com/gobwas/httphead v0.1.0 // indirect
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/gobwas/ws v1.1.0 // indirect
|
||||
@@ -83,28 +82,28 @@ require (
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
|
||||
github.com/jackc/pgconn v1.7.0 // indirect
|
||||
github.com/jackc/pgconn v1.13.0 // indirect
|
||||
github.com/jackc/pgio v1.0.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgproto3/v2 v2.0.5 // indirect
|
||||
github.com/jackc/pgproto3/v2 v2.3.1 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
|
||||
github.com/jackc/pgtype v1.5.0 // indirect
|
||||
github.com/jackc/pgx/v4 v4.9.0 // indirect
|
||||
github.com/jackc/pgtype v1.12.0 // indirect
|
||||
github.com/jackc/pgx/v4 v4.17.2 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.2 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.8 // indirect
|
||||
github.com/mattn/go-isatty v0.0.13 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/mattn/go-colorable v0.1.9 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.12 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||
github.com/sergi/go-diff v1.1.0 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/thedevsaddam/gojsonq/v2 v2.5.2 // indirect
|
||||
golang.org/x/mod v0.5.1 // indirect
|
||||
@@ -115,7 +114,7 @@ require (
|
||||
google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f // indirect
|
||||
google.golang.org/grpc/examples v0.0.0-20210910232509-03268c8ed29e // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
lukechampine.com/uint128 v1.1.1 // indirect
|
||||
modernc.org/cc/v3 v3.35.24 // indirect
|
||||
modernc.org/ccgo/v3 v3.15.18 // indirect
|
||||
|
||||
@@ -27,7 +27,6 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
@@ -39,8 +38,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/AlecAivazis/survey/v2 v2.0.5/go.mod h1:WYBhg6f0y/fNYUuesWQc0PKbJcEliGcYHB9sNT3Bg74=
|
||||
github.com/AlecAivazis/survey/v2 v2.2.2 h1:1I4qBrNsHQE+91tQCqVlfrKe9DEL65949d1oKZWVELY=
|
||||
github.com/AlecAivazis/survey/v2 v2.2.2/go.mod h1:9FJRdMdDm8rnT+zHVbvQT2RTSTLq0Ttd6q3Vl2fahjk=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.6 h1:NvTuVHISgTHEHeBFqt6BHOe4Ny/NwGZr7w+F8S9ziyw=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.6/go.mod h1:4AuI9b7RjAR+G7v9+C4YSlX/YL3K3cWNXgWXOhllqvI=
|
||||
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
@@ -75,6 +74,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/BurntSushi/xgb v0.0.0-20201008132610-5f9e7b3c49cd h1:u7K2oMFMd8APDV3fM1j2rO3U/XJf1g1qC3DDTKou8iM=
|
||||
github.com/BurntSushi/xgb v0.0.0-20201008132610-5f9e7b3c49cd/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
|
||||
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
|
||||
@@ -88,8 +89,9 @@ github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb0
|
||||
github.com/Ne0nd0g/go-clr v1.0.2 h1:jVD7iJyXaS3KhPiKetUnUAuLxgDlNSvYmPfMFK8E3VY=
|
||||
github.com/Ne0nd0g/go-clr v1.0.2/go.mod h1:TKYSQ/5xT25EvBUttAlUrzpR8yHuI0qTRK495I5xG/I=
|
||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
|
||||
github.com/Netflix/go-expect v0.0.0-20190729225929-0e00d9168667 h1:l2RCK7mjLhjfZRIcCXTVHI34l67IRtKASBjusViLzQ0=
|
||||
github.com/Netflix/go-expect v0.0.0-20190729225929-0e00d9168667/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
|
||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
|
||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
@@ -105,25 +107,15 @@ github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdc
|
||||
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
|
||||
github.com/akamensky/argparse v1.2.1/go.mod h1:S5kwC7IuDcEr5VeXtGPRVZ5o/FdhcMlQz4IZQuw64xA=
|
||||
github.com/akamensky/argparse v1.3.0/go.mod h1:S5kwC7IuDcEr5VeXtGPRVZ5o/FdhcMlQz4IZQuw64xA=
|
||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
|
||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
|
||||
github.com/alecthomas/chroma v0.8.1 h1:ym20sbvyC6RXz45u4qDglcgr8E313oPROshcuCHqiEE=
|
||||
github.com/alecthomas/chroma v0.8.1/go.mod h1:sko8vR34/90zvl5QdcUdvzL3J8NKjAUx9va9jPuFNoM=
|
||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo=
|
||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
|
||||
github.com/alecthomas/kong v0.2.4/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE=
|
||||
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY=
|
||||
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
||||
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
|
||||
github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/awgh/cppgo v0.0.0-20210224085512-3d24bca8edc0 h1:JjwxKkxzcBk4k8147g0eBQRCIy0UN1Be8AAv6RaIj4Q=
|
||||
github.com/awgh/cppgo v0.0.0-20210224085512-3d24bca8edc0/go.mod h1:IbERvuyb387Hppp8hX0SQTFt/mkej8+OhuS8L0nC2CI=
|
||||
@@ -136,7 +128,6 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||
@@ -152,8 +143,8 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
|
||||
github.com/cheggaaa/pb/v3 v3.0.5 h1:lmZOti7CraK9RSjzExsY53+WWfub9Qv13B5m4ptEoPE=
|
||||
github.com/cheggaaa/pb/v3 v3.0.5/go.mod h1:X1L61/+36nz9bjIsrDU52qHKOQukUQe2Ge+YvGuquCw=
|
||||
github.com/cheggaaa/pb/v3 v3.1.0 h1:3uouEsl32RL7gTiQsuaXD4Bzbfl5tGztXGUvXbs4O04=
|
||||
github.com/cheggaaa/pb/v3 v3.1.0/go.mod h1:YjrevcBqadFDaGQKRdmZxTY42pXEqda48Ea3lt0K/BE=
|
||||
github.com/chromedp/cdproto v0.0.0-20220827030233-358ed4af73cf h1:e0oJZmGJidTRZ0FvWXNhdj9OaOMN30Yf+T3K2Tf3L+s=
|
||||
github.com/chromedp/cdproto v0.0.0-20220827030233-358ed4af73cf/go.mod h1:5Y4sD/eXpwrChIuxhSr/G20n9CdbCmoerOHnuAf0Zr0=
|
||||
github.com/chromedp/chromedp v0.8.5 h1:HAVg54yQFcn7sg5reVjXtoI1eQaFxhjAjflHACicUFw=
|
||||
@@ -213,7 +204,6 @@ github.com/containernetworking/plugins v0.8.7/go.mod h1:R7lXeZaBzpfqapcAbHRW8/CY
|
||||
github.com/containers/ocicrypt v1.0.3/go.mod h1:CUBa+8MRNL/VkpxYIpaMtgn1WgXGyvPQj8jcy0EVG6g=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
|
||||
github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
|
||||
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
||||
@@ -229,15 +219,15 @@ github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfc
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7 h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
|
||||
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
||||
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
|
||||
github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
|
||||
github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
|
||||
github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I=
|
||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
|
||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
|
||||
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
@@ -255,8 +245,8 @@ github.com/desertbit/readline v1.5.1 h1:/wOIZkWYl1s+IvJm/5bOknfUgs6MhS9svRNZpFM5
|
||||
github.com/desertbit/readline v1.5.1/go.mod h1:pHQgTsCFs9Cpfh5mlSUFi9Xa5kkL4d8L1Jo4UVWzPw0=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk=
|
||||
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v1.4.2-0.20191028175130-9e7d5ac5ea55/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
@@ -288,8 +278,8 @@ github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
|
||||
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
@@ -309,8 +299,10 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
|
||||
github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
@@ -327,8 +319,8 @@ github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsd
|
||||
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
|
||||
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
@@ -341,9 +333,9 @@ github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblf
|
||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84=
|
||||
github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gofrs/uuid v4.3.0+incompatible h1:CaSVZxm5B+7o45rtab4jC2G37WGYX1zQfuU2i6DSvnc=
|
||||
github.com/gofrs/uuid v4.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
|
||||
github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
@@ -452,34 +444,20 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
|
||||
github.com/hinshun/vt10x v0.0.0-20180809195222-d55458df857c h1:kp3AxgXgDOmIJFR7bIwqFhwJ2qWar8tEQSE5XXhCfVk=
|
||||
github.com/hinshun/vt10x v0.0.0-20180809195222-d55458df857c/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
@@ -489,7 +467,6 @@ github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
|
||||
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
|
||||
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
|
||||
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
|
||||
@@ -497,57 +474,58 @@ github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgO
|
||||
github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA=
|
||||
github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE=
|
||||
github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s=
|
||||
github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk=
|
||||
github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI=
|
||||
github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI=
|
||||
github.com/jackc/pgconn v1.7.0 h1:pwjzcYyfmz/HQOQlENvG1OcDqauTGaqlVahq934F0/U=
|
||||
github.com/jackc/pgconn v1.7.0/go.mod h1:sF/lPpNEMEOp+IYhyQGdAvrG20gWf6A1tKlr0v7JMeA=
|
||||
github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o=
|
||||
github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY=
|
||||
github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
|
||||
github.com/jackc/pgconn v1.12.1/go.mod h1:ZkhRC59Llhrq3oSfrikvwQ5NaxYExr6twkdkMLaKono=
|
||||
github.com/jackc/pgconn v1.13.0 h1:3L1XMNV2Zvca/8BYhzcRFS70Lr0WlDg16Di6SFGAbys=
|
||||
github.com/jackc/pgconn v1.13.0/go.mod h1:AnowpAqO4CMIIJNZl2VJp+KrkAZciAkhEl0W0JIobpI=
|
||||
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
|
||||
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
|
||||
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye4717ITLaNwV9mWbJx0dLCpcRzdA=
|
||||
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
|
||||
github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c=
|
||||
github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc=
|
||||
github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A=
|
||||
github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.0.5 h1:NUbEWPmCQZbMmYlTjVoNPhc0CfnYyz2bfUAh6A5ZVJM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.5/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
|
||||
github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.3.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y4Y=
|
||||
github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
|
||||
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
|
||||
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
|
||||
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
|
||||
github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0=
|
||||
github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po=
|
||||
github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ=
|
||||
github.com/jackc/pgtype v1.5.0 h1:jzBqRk2HFG2CV4AIwgCI2PwTgm6UUoCAK2ofHHRirtc=
|
||||
github.com/jackc/pgtype v1.5.0/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig=
|
||||
github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM=
|
||||
github.com/jackc/pgtype v1.11.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w=
|
||||
github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
|
||||
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
|
||||
github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA=
|
||||
github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o=
|
||||
github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg=
|
||||
github.com/jackc/pgx/v4 v4.9.0 h1:6STjDqppM2ROy5p1wNDcsC7zJTjSHeuCsguZmXyzx7c=
|
||||
github.com/jackc/pgx/v4 v4.9.0/go.mod h1:MNGWmViCgqbZck9ujOOBN63gK9XVGILXWCvKLGKmnms=
|
||||
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
|
||||
github.com/jackc/pgx/v4 v4.16.1/go.mod h1:SIhx0D5hoADaiXZVyv+3gSm3LCIIINTVO0PficsvWGQ=
|
||||
github.com/jackc/pgx/v4 v4.17.2 h1:0Ut0rpeKwvIVbMQ1KbMBU4h6wxehBI535LK6Flheh8E=
|
||||
github.com/jackc/pgx/v4 v4.17.2/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw=
|
||||
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.2/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jedib0t/go-pretty/v6 v6.2.4 h1:wdaj2KHD2W+mz8JgJ/Q6L/T5dB7kyqEFI16eLq7GEmk=
|
||||
github.com/jedib0t/go-pretty/v6 v6.2.4/go.mod h1:+nE9fyyHGil+PuISTCrp7avEdo6bqoMwqZnuiK2r2a0=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI=
|
||||
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
@@ -581,12 +559,10 @@ github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.4-0.20190131011033-7dc38fb350b1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI=
|
||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo=
|
||||
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
|
||||
github.com/lesnuages/go-winio v0.4.19 h1:lFDu1mnhg5em+8zTHO4ChSD11J56xkyE8m3N8IrVmbA=
|
||||
github.com/lesnuages/go-winio v0.4.19/go.mod h1:rm7jf4kBcldxMeljR7c7XY1qVCBc+8z3PtSgkrT9Clk=
|
||||
github.com/lesnuages/snitch v0.6.0 h1:vOao32MdYDHYDcTAq2CKszDh6Dn8Bv1Gmgc8uVh193U=
|
||||
@@ -594,14 +570,13 @@ github.com/lesnuages/snitch v0.6.0/go.mod h1:RfXlAVJYL7gUoZ9VMMon4LqrPiAjC8x62Nt
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
|
||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
|
||||
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc=
|
||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
@@ -616,26 +591,26 @@ github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcncea
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
|
||||
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.12 h1:Y41i/hVW3Pgwr8gV+J23B9YEY0zxjptBuCWEaxmAOow=
|
||||
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
||||
github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
|
||||
github.com/mattn/go-sqlite3 v1.14.12 h1:TJ1bhYJPV44phC+IMu1u2K/i5RriLTPe+yc68XDJ1Z0=
|
||||
github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
|
||||
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/mdlayher/genetlink v1.2.0/go.mod h1:ra5LDov2KrUCZJiAtEvXXZBxGMInICMXIwshlJ+qRxQ=
|
||||
@@ -643,19 +618,12 @@ github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWC
|
||||
github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/miekg/dns v1.1.35 h1:oTfOaDH+mZkdcgdIjH6yBajRGtIwcwcaR+rt23ZSrJs=
|
||||
github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
||||
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
|
||||
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||
@@ -710,8 +678,6 @@ github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mo
|
||||
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw=
|
||||
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
@@ -724,7 +690,6 @@ github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6J
|
||||
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
||||
github.com/pquerna/otp v1.3.0 h1:oJV/SkzR33anKXwQU3Of42rL4wbrffP4uvUf1SvS5Xs=
|
||||
github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||
@@ -757,6 +722,9 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
@@ -764,30 +732,25 @@ github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/shirou/gopsutil/v3 v3.21.10 h1:flTg1DrnV/UVrBqjLgVgDJzx6lf+91rC64/dBHmO2IA=
|
||||
github.com/shirou/gopsutil/v3 v3.21.10/go.mod h1:t75NhzCZ/dYyPQjyQmrAYP6c8+LCdFANeBMdLPCNnew=
|
||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
||||
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc h1:jUIKcSPO9MoMJBbEoyE/RJoE8vz7Mb8AjvifMMwSyvY=
|
||||
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
@@ -795,8 +758,8 @@ github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTd
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
|
||||
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
|
||||
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
|
||||
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
@@ -804,11 +767,11 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
@@ -816,9 +779,10 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
|
||||
github.com/thedevsaddam/gojsonq/v2 v2.5.2 h1:CoMVaYyKFsVj6TjU6APqAhAvC07hTI6IQen8PHzHYY0=
|
||||
@@ -848,7 +812,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
||||
@@ -868,17 +831,19 @@ go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
@@ -888,17 +853,20 @@ golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
|
||||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
|
||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -943,7 +911,6 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -961,7 +928,6 @@ golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@@ -986,8 +952,8 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211111083644-e5c967477495/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
@@ -1021,11 +987,9 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1048,7 +1012,6 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -1071,7 +1034,6 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -1103,24 +1065,24 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 h1:UiNENfZ8gDvpiWw7IpOMQ27spWmThO1RwwdQVbJahJM=
|
||||
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -1164,15 +1126,14 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
@@ -1201,6 +1162,7 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.9 h1:j9KsMiaP1c3B0OTQGth0/k+miLGTgLsAFUCrF2vLcF8=
|
||||
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -1350,7 +1312,6 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
@@ -1363,19 +1324,20 @@ gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
|
||||
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/mysql v1.0.3 h1:+JKBYPfn1tygR1/of/Fh2T8iwuVwzt+PEJmKaXzMQXg=
|
||||
gorm.io/driver/mysql v1.0.3/go.mod h1:twGxftLBlFgNVNakL7F+P/x9oYqoymG3YYT8cAfI9oI=
|
||||
gorm.io/driver/postgres v1.0.5 h1:raX6ezL/ciUmaYTvOq48jq1GE95aMC0CmxQYbxQ4Ufw=
|
||||
gorm.io/driver/postgres v1.0.5/go.mod h1:qrD92UurYzNctBMVCJ8C3VQEjffEuphycXtxOudXNCA=
|
||||
gorm.io/driver/sqlite v1.1.3 h1:BYfdVuZB5He/u9dt4qDpZqiqDJ6KhPqs5QUqsr/Eeuc=
|
||||
gorm.io/driver/sqlite v1.1.3/go.mod h1:AKDgRWk8lcSQSw+9kxCJnX/yySj8G3rdwYlU57cB45c=
|
||||
gorm.io/gorm v1.20.1/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||
gorm.io/gorm v1.20.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||
gorm.io/gorm v1.21.14 h1:NAR9A/3SoyiPVHouW/rlpMUZvuQZ6Z6UYGz+2tosSQo=
|
||||
gorm.io/gorm v1.21.14/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/mysql v1.3.6 h1:BhX1Y/RyALb+T9bZ3t07wLnPZBukt+IRkMn8UZSNbGM=
|
||||
gorm.io/driver/mysql v1.3.6/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c=
|
||||
gorm.io/driver/postgres v1.3.9 h1:lWGiVt5CijhQAg0PWB7Od1RNcBw/jS4d2cAScBcSDXg=
|
||||
gorm.io/driver/postgres v1.3.9/go.mod h1:qw/FeqjxmYqW5dBcYNBsnhQULIApQdk7YuuDPktVi1U=
|
||||
gorm.io/driver/sqlite v1.3.6 h1:Fi8xNYCUplOqWiPa3/GuCeowRNBRGTf62DEmhMDHeQQ=
|
||||
gorm.io/driver/sqlite v1.3.6/go.mod h1:Sg1/pvnKtbQ7jLXxfZa+jSHvoX8hoZA8cn4xllOMTgE=
|
||||
gorm.io/gorm v1.23.4/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
|
||||
gorm.io/gorm v1.23.7/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
|
||||
gorm.io/gorm v1.23.8 h1:h8sGJ+biDgBA1AD1Ha9gFCx7h8npU7AsLdlkX0n2TpE=
|
||||
gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||
|
||||
@@ -372,6 +372,9 @@ func prepareDownload(path string, filter string, recurse bool) ([]byte, bool, in
|
||||
to download a single file
|
||||
*/
|
||||
fileInfo, err := os.Stat(path + filter)
|
||||
if err != nil {
|
||||
return nil, false, 0, 1, err
|
||||
}
|
||||
if err == nil && !fileInfo.IsDir() {
|
||||
// Then this is a single file
|
||||
rawData, err := os.ReadFile(path + filter)
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
package service
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2022 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
@@ -67,14 +67,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
InstanceID string
|
||||
|
||||
c2Servers = []string{
|
||||
// {{range $index, $value := .Config.C2}}
|
||||
"{{$value}}", // {{$index}}
|
||||
// {{end}}
|
||||
}
|
||||
|
||||
InstanceID string
|
||||
connectionErrors = 0
|
||||
)
|
||||
|
||||
@@ -202,7 +195,7 @@ func beaconStartup() {
|
||||
defer func() {
|
||||
abort <- struct{}{}
|
||||
}()
|
||||
beacons := transports.StartBeaconLoop(c2Servers, abort)
|
||||
beacons := transports.StartBeaconLoop(abort)
|
||||
for beacon := range beacons {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Next beacon = %v", beacon)
|
||||
@@ -234,7 +227,7 @@ func sessionStartup() {
|
||||
defer func() {
|
||||
abort <- struct{}{}
|
||||
}()
|
||||
connections := transports.StartConnectionLoop(c2Servers, abort)
|
||||
connections := transports.StartConnectionLoop(abort)
|
||||
for connection := range connections {
|
||||
if connection != nil {
|
||||
err := sessionMainLoop(connection)
|
||||
@@ -480,9 +473,7 @@ func openSessionHandler(data []byte) {
|
||||
log.Printf("[beacon] failed to parse open session msg: %s", err)
|
||||
// {{end}}
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[beacon] open session -> %v", openSession.C2S)
|
||||
// {{end}}
|
||||
|
||||
if openSession.Delay != 0 {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[beacon] delay %s", time.Duration(openSession.Delay))
|
||||
@@ -492,7 +483,7 @@ func openSessionHandler(data []byte) {
|
||||
|
||||
go func() {
|
||||
abort := make(chan struct{})
|
||||
connections := transports.StartConnectionLoop(openSession.C2S, abort)
|
||||
connections := transports.StartConnectionLoop(abort)
|
||||
defer func() { abort <- struct{}{} }()
|
||||
connectionAttempts := 0
|
||||
for connection := range connections {
|
||||
|
||||
@@ -1,12 +1,31 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package spoof
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2022 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/windows"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
|
||||
@@ -113,7 +113,7 @@ func (b *Beacon) Duration() time.Duration {
|
||||
}
|
||||
|
||||
// StartBeaconLoop - Starts the beacon loop generator
|
||||
func StartBeaconLoop(c2s []string, abort <-chan struct{}) <-chan *Beacon {
|
||||
func StartBeaconLoop(abort <-chan struct{}) <-chan *Beacon {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Starting beacon loop ...")
|
||||
// {{end}}
|
||||
@@ -122,7 +122,7 @@ func StartBeaconLoop(c2s []string, abort <-chan struct{}) <-chan *Beacon {
|
||||
nextBeacon := make(chan *Beacon)
|
||||
|
||||
innerAbort := make(chan struct{})
|
||||
c2Generator := C2Generator(c2s, innerAbort)
|
||||
c2Generator := C2Generator(innerAbort)
|
||||
|
||||
go func() {
|
||||
defer close(nextBeacon)
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
package transports
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2022 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"sync"
|
||||
@@ -14,7 +32,7 @@ type Connection struct {
|
||||
ctrl chan struct{}
|
||||
cleanup func()
|
||||
once *sync.Once
|
||||
tunnels *map[uint64]*Tunnel
|
||||
tunnels map[uint64]*Tunnel
|
||||
mutex *sync.RWMutex
|
||||
|
||||
uri *url.URL
|
||||
@@ -53,7 +71,7 @@ func (c *Connection) Cleanup() {
|
||||
func (c *Connection) Tunnel(ID uint64) *Tunnel {
|
||||
c.mutex.RLock()
|
||||
defer c.mutex.RUnlock()
|
||||
return (*c.tunnels)[ID]
|
||||
return c.tunnels[ID]
|
||||
}
|
||||
|
||||
// AddTunnel - Add tunnel to mapping
|
||||
@@ -61,7 +79,7 @@ func (c *Connection) AddTunnel(tun *Tunnel) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
(*c.tunnels)[tun.ID] = tun
|
||||
c.tunnels[tun.ID] = tun
|
||||
}
|
||||
|
||||
// RemoveTunnel - Add tunnel to mapping
|
||||
@@ -69,17 +87,17 @@ func (c *Connection) RemoveTunnel(ID uint64) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
delete(*c.tunnels, ID)
|
||||
delete(c.tunnels, ID)
|
||||
}
|
||||
|
||||
func (c *Connection) removeAndCloseAllTunnels() {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
for id, tunnel := range *c.tunnels {
|
||||
for id, tunnel := range c.tunnels {
|
||||
tunnel.Close()
|
||||
|
||||
delete(*c.tunnels, id)
|
||||
delete(c.tunnels, id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ type Start func() error
|
||||
type Stop func() error
|
||||
|
||||
// StartConnectionLoop - Starts the main connection loop
|
||||
func StartConnectionLoop(c2s []string, abort <-chan struct{}) <-chan *Connection {
|
||||
func StartConnectionLoop(abort <-chan struct{}) <-chan *Connection {
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Starting interactive session connection loop ...")
|
||||
@@ -88,7 +88,7 @@ func StartConnectionLoop(c2s []string, abort <-chan struct{}) <-chan *Connection
|
||||
|
||||
nextConnection := make(chan *Connection)
|
||||
innerAbort := make(chan struct{})
|
||||
c2Generator := C2Generator(c2s, innerAbort)
|
||||
c2Generator := C2Generator(innerAbort)
|
||||
|
||||
go func() {
|
||||
var connection *Connection
|
||||
@@ -204,7 +204,7 @@ func mtlsConnect(uri *url.URL) (*Connection, error) {
|
||||
Send: send,
|
||||
Recv: recv,
|
||||
ctrl: ctrl,
|
||||
tunnels: &map[uint64]*Tunnel{},
|
||||
tunnels: map[uint64]*Tunnel{},
|
||||
mutex: &sync.RWMutex{},
|
||||
once: &sync.Once{},
|
||||
IsOpen: false,
|
||||
@@ -306,7 +306,7 @@ func wgConnect(uri *url.URL) (*Connection, error) {
|
||||
Send: send,
|
||||
Recv: recv,
|
||||
ctrl: ctrl,
|
||||
tunnels: &map[uint64]*Tunnel{},
|
||||
tunnels: map[uint64]*Tunnel{},
|
||||
mutex: &sync.RWMutex{},
|
||||
once: &sync.Once{},
|
||||
uri: uri,
|
||||
@@ -414,7 +414,7 @@ func httpConnect(uri *url.URL) (*Connection, error) {
|
||||
Send: send,
|
||||
Recv: recv,
|
||||
ctrl: ctrl,
|
||||
tunnels: &map[uint64]*Tunnel{},
|
||||
tunnels: map[uint64]*Tunnel{},
|
||||
mutex: &sync.RWMutex{},
|
||||
once: &sync.Once{},
|
||||
uri: uri,
|
||||
@@ -535,7 +535,7 @@ func dnsConnect(uri *url.URL) (*Connection, error) {
|
||||
Send: send,
|
||||
Recv: recv,
|
||||
ctrl: ctrl,
|
||||
tunnels: &map[uint64]*Tunnel{},
|
||||
tunnels: map[uint64]*Tunnel{},
|
||||
mutex: &sync.RWMutex{},
|
||||
once: &sync.Once{},
|
||||
IsOpen: true,
|
||||
@@ -644,7 +644,7 @@ func tcpPivotConnect(uri *url.URL) (*Connection, error) {
|
||||
Send: send,
|
||||
Recv: recv,
|
||||
ctrl: ctrl,
|
||||
tunnels: &map[uint64]*Tunnel{},
|
||||
tunnels: map[uint64]*Tunnel{},
|
||||
mutex: &sync.RWMutex{},
|
||||
once: &sync.Once{},
|
||||
IsOpen: true,
|
||||
|
||||
@@ -36,10 +36,18 @@ const (
|
||||
)
|
||||
|
||||
// C2Generator - Creates a stream of C2 URLs based on a connection strategy
|
||||
func C2Generator(c2Servers []string, abort <-chan struct{}) <-chan *url.URL {
|
||||
func C2Generator(abort <-chan struct{}) <-chan *url.URL {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Starting c2 url generator ({{.Config.ConnectionStrategy}}) ...")
|
||||
// {{end}}
|
||||
|
||||
c2Servers := []func() string{}
|
||||
// {{range $index, $value := .Config.C2}}
|
||||
c2Servers = append(c2Servers, func() string {
|
||||
return "{{$value}}" // {{$index}}
|
||||
})
|
||||
// {{end}} - range
|
||||
|
||||
generator := make(chan *url.URL)
|
||||
go func() {
|
||||
defer close(generator)
|
||||
@@ -48,16 +56,16 @@ func C2Generator(c2Servers []string, abort <-chan struct{}) <-chan *url.URL {
|
||||
var next string
|
||||
switch "{{.Config.ConnectionStrategy}}" {
|
||||
case strategyRandom: // Random
|
||||
next = c2Servers[insecureRand.Intn(len(c2Servers))]
|
||||
next = c2Servers[insecureRand.Intn(len(c2Servers))]()
|
||||
case strategyRandomDomain: // Random Domain
|
||||
// Select the next sequential C2 then use it's protocol to make a random
|
||||
// selection from all C2s that share it's protocol.
|
||||
next = c2Servers[insecureRand.Intn(len(c2Servers))]
|
||||
next = c2Servers[insecureRand.Intn(len(c2Servers))]()
|
||||
next = randomCCDomain(c2Servers, next)
|
||||
case strategySequential: // Sequential
|
||||
next = c2Servers[c2Counter%uint(len(c2Servers))]
|
||||
next = c2Servers[c2Counter%uint(len(c2Servers))]()
|
||||
default:
|
||||
next = c2Servers[c2Counter%uint(len(c2Servers))]
|
||||
next = c2Servers[c2Counter%uint(len(c2Servers))]()
|
||||
}
|
||||
c2Counter++
|
||||
if ^uint(0) < c2Counter {
|
||||
@@ -90,15 +98,15 @@ func C2Generator(c2Servers []string, abort <-chan struct{}) <-chan *url.URL {
|
||||
}
|
||||
|
||||
// randomCCDomain - Random selection within a protocol
|
||||
func randomCCDomain(ccServers []string, next string) string {
|
||||
func randomCCDomain(ccServers []func() string, next string) string {
|
||||
uri, err := url.Parse(next)
|
||||
if err != nil {
|
||||
return next
|
||||
}
|
||||
pool := []string{}
|
||||
pool := []func() string{}
|
||||
protocol := uri.Scheme
|
||||
for _, cc := range ccServers {
|
||||
uri, err := url.Parse(cc)
|
||||
uri, err := url.Parse(cc())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
@@ -106,7 +114,7 @@ func randomCCDomain(ccServers []string, next string) string {
|
||||
pool = append(pool, cc)
|
||||
}
|
||||
}
|
||||
return pool[insecureRand.Intn(len(pool))]
|
||||
return pool[insecureRand.Intn(len(pool))]()
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -46,7 +46,7 @@ func namedPipeConnect(uri *url.URL) (*Connection, error) {
|
||||
Send: send,
|
||||
Recv: recv,
|
||||
ctrl: ctrl,
|
||||
tunnels: &map[uint64]*Tunnel{},
|
||||
tunnels: map[uint64]*Tunnel{},
|
||||
mutex: &sync.RWMutex{},
|
||||
once: &sync.Once{},
|
||||
IsOpen: true,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.21.5
|
||||
// source: clientpb/client.proto
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.21.5
|
||||
// source: commonpb/common.proto
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.21.5
|
||||
// source: dnspb/dns.proto
|
||||
|
||||
|
||||
+245
-239
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.21.5
|
||||
// source: rpcpb/services.proto
|
||||
|
||||
@@ -31,7 +31,7 @@ var file_rpcpb_services_proto_rawDesc = []byte{
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2f, 0x73,
|
||||
0x6c, 0x69, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x63, 0x6c, 0x69,
|
||||
0x65, 0x6e, 0x74, 0x70, 0x62, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x32, 0xa6, 0x38, 0x0a, 0x09, 0x53, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x52, 0x50, 0x43,
|
||||
0x74, 0x6f, 0x32, 0xe6, 0x38, 0x0a, 0x09, 0x53, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x52, 0x50, 0x43,
|
||||
0x12, 0x30, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x0f,
|
||||
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a,
|
||||
0x11, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69,
|
||||
@@ -68,6 +68,10 @@ var file_rpcpb_services_proto_rawDesc = []byte{
|
||||
0x6f, 0x6e, 0x54, 0x61, 0x73, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x2e,
|
||||
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x54,
|
||||
0x61, 0x73, 0x6b, 0x1a, 0x14, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x2e, 0x42,
|
||||
0x65, 0x61, 0x63, 0x6f, 0x6e, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x3e, 0x0a, 0x10, 0x43, 0x61, 0x6e,
|
||||
0x63, 0x65, 0x6c, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x14, 0x2e,
|
||||
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x54,
|
||||
0x61, 0x73, 0x6b, 0x1a, 0x14, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x2e, 0x42,
|
||||
0x65, 0x61, 0x63, 0x6f, 0x6e, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x33, 0x0a, 0x0c, 0x4d, 0x6f, 0x6e,
|
||||
0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
||||
0x6f, 0x6e, 0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
@@ -673,243 +677,245 @@ var file_rpcpb_services_proto_depIdxs = []int32{
|
||||
4, // 8: rpcpb.SliverRPC.RmBeacon:input_type -> clientpb.Beacon
|
||||
4, // 9: rpcpb.SliverRPC.GetBeaconTasks:input_type -> clientpb.Beacon
|
||||
5, // 10: rpcpb.SliverRPC.GetBeaconTaskContent:input_type -> clientpb.BeaconTask
|
||||
0, // 11: rpcpb.SliverRPC.MonitorStart:input_type -> commonpb.Empty
|
||||
0, // 12: rpcpb.SliverRPC.MonitorStop:input_type -> commonpb.Empty
|
||||
0, // 13: rpcpb.SliverRPC.GetJobs:input_type -> commonpb.Empty
|
||||
6, // 14: rpcpb.SliverRPC.KillJob:input_type -> clientpb.KillJobReq
|
||||
7, // 15: rpcpb.SliverRPC.StartMTLSListener:input_type -> clientpb.MTLSListenerReq
|
||||
8, // 16: rpcpb.SliverRPC.StartWGListener:input_type -> clientpb.WGListenerReq
|
||||
9, // 17: rpcpb.SliverRPC.StartDNSListener:input_type -> clientpb.DNSListenerReq
|
||||
10, // 18: rpcpb.SliverRPC.StartHTTPSListener:input_type -> clientpb.HTTPListenerReq
|
||||
10, // 19: rpcpb.SliverRPC.StartHTTPListener:input_type -> clientpb.HTTPListenerReq
|
||||
11, // 20: rpcpb.SliverRPC.StartTCPStagerListener:input_type -> clientpb.StagerListenerReq
|
||||
11, // 21: rpcpb.SliverRPC.StartHTTPStagerListener:input_type -> clientpb.StagerListenerReq
|
||||
12, // 22: rpcpb.SliverRPC.LootAdd:input_type -> clientpb.Loot
|
||||
12, // 23: rpcpb.SliverRPC.LootRm:input_type -> clientpb.Loot
|
||||
12, // 24: rpcpb.SliverRPC.LootUpdate:input_type -> clientpb.Loot
|
||||
12, // 25: rpcpb.SliverRPC.LootContent:input_type -> clientpb.Loot
|
||||
0, // 26: rpcpb.SliverRPC.LootAll:input_type -> commonpb.Empty
|
||||
12, // 27: rpcpb.SliverRPC.LootAllOf:input_type -> clientpb.Loot
|
||||
0, // 28: rpcpb.SliverRPC.Hosts:input_type -> commonpb.Empty
|
||||
13, // 29: rpcpb.SliverRPC.Host:input_type -> clientpb.Host
|
||||
13, // 30: rpcpb.SliverRPC.HostRm:input_type -> clientpb.Host
|
||||
14, // 31: rpcpb.SliverRPC.HostIOCRm:input_type -> clientpb.IOC
|
||||
15, // 32: rpcpb.SliverRPC.Generate:input_type -> clientpb.GenerateReq
|
||||
16, // 33: rpcpb.SliverRPC.Regenerate:input_type -> clientpb.RegenerateReq
|
||||
0, // 34: rpcpb.SliverRPC.ImplantBuilds:input_type -> commonpb.Empty
|
||||
17, // 35: rpcpb.SliverRPC.DeleteImplantBuild:input_type -> clientpb.DeleteReq
|
||||
0, // 36: rpcpb.SliverRPC.Canaries:input_type -> commonpb.Empty
|
||||
0, // 37: rpcpb.SliverRPC.GenerateWGClientConfig:input_type -> commonpb.Empty
|
||||
0, // 38: rpcpb.SliverRPC.GenerateUniqueIP:input_type -> commonpb.Empty
|
||||
0, // 39: rpcpb.SliverRPC.ImplantProfiles:input_type -> commonpb.Empty
|
||||
17, // 40: rpcpb.SliverRPC.DeleteImplantProfile:input_type -> clientpb.DeleteReq
|
||||
18, // 41: rpcpb.SliverRPC.SaveImplantProfile:input_type -> clientpb.ImplantProfile
|
||||
19, // 42: rpcpb.SliverRPC.MsfStage:input_type -> clientpb.MsfStagerReq
|
||||
20, // 43: rpcpb.SliverRPC.ShellcodeRDI:input_type -> clientpb.ShellcodeRDIReq
|
||||
0, // 44: rpcpb.SliverRPC.GetCompiler:input_type -> commonpb.Empty
|
||||
21, // 45: rpcpb.SliverRPC.ShellcodeEncoder:input_type -> clientpb.ShellcodeEncodeReq
|
||||
0, // 46: rpcpb.SliverRPC.ShellcodeEncoderMap:input_type -> commonpb.Empty
|
||||
0, // 47: rpcpb.SliverRPC.Websites:input_type -> commonpb.Empty
|
||||
22, // 48: rpcpb.SliverRPC.Website:input_type -> clientpb.Website
|
||||
22, // 49: rpcpb.SliverRPC.WebsiteRemove:input_type -> clientpb.Website
|
||||
23, // 50: rpcpb.SliverRPC.WebsiteAddContent:input_type -> clientpb.WebsiteAddContent
|
||||
23, // 51: rpcpb.SliverRPC.WebsiteUpdateContent:input_type -> clientpb.WebsiteAddContent
|
||||
24, // 52: rpcpb.SliverRPC.WebsiteRemoveContent:input_type -> clientpb.WebsiteRemoveContent
|
||||
25, // 53: rpcpb.SliverRPC.Ping:input_type -> sliverpb.Ping
|
||||
26, // 54: rpcpb.SliverRPC.Ps:input_type -> sliverpb.PsReq
|
||||
27, // 55: rpcpb.SliverRPC.Terminate:input_type -> sliverpb.TerminateReq
|
||||
28, // 56: rpcpb.SliverRPC.Ifconfig:input_type -> sliverpb.IfconfigReq
|
||||
29, // 57: rpcpb.SliverRPC.Netstat:input_type -> sliverpb.NetstatReq
|
||||
30, // 58: rpcpb.SliverRPC.Ls:input_type -> sliverpb.LsReq
|
||||
31, // 59: rpcpb.SliverRPC.Cd:input_type -> sliverpb.CdReq
|
||||
32, // 60: rpcpb.SliverRPC.Pwd:input_type -> sliverpb.PwdReq
|
||||
33, // 61: rpcpb.SliverRPC.Mv:input_type -> sliverpb.MvReq
|
||||
34, // 62: rpcpb.SliverRPC.Rm:input_type -> sliverpb.RmReq
|
||||
35, // 63: rpcpb.SliverRPC.Mkdir:input_type -> sliverpb.MkdirReq
|
||||
36, // 64: rpcpb.SliverRPC.Download:input_type -> sliverpb.DownloadReq
|
||||
37, // 65: rpcpb.SliverRPC.Upload:input_type -> sliverpb.UploadReq
|
||||
38, // 66: rpcpb.SliverRPC.ProcessDump:input_type -> sliverpb.ProcessDumpReq
|
||||
39, // 67: rpcpb.SliverRPC.RunAs:input_type -> sliverpb.RunAsReq
|
||||
40, // 68: rpcpb.SliverRPC.Impersonate:input_type -> sliverpb.ImpersonateReq
|
||||
41, // 69: rpcpb.SliverRPC.RevToSelf:input_type -> sliverpb.RevToSelfReq
|
||||
42, // 70: rpcpb.SliverRPC.GetSystem:input_type -> clientpb.GetSystemReq
|
||||
43, // 71: rpcpb.SliverRPC.Task:input_type -> sliverpb.TaskReq
|
||||
44, // 72: rpcpb.SliverRPC.Msf:input_type -> clientpb.MSFReq
|
||||
45, // 73: rpcpb.SliverRPC.MsfRemote:input_type -> clientpb.MSFRemoteReq
|
||||
46, // 74: rpcpb.SliverRPC.ExecuteAssembly:input_type -> sliverpb.ExecuteAssemblyReq
|
||||
47, // 75: rpcpb.SliverRPC.Migrate:input_type -> clientpb.MigrateReq
|
||||
48, // 76: rpcpb.SliverRPC.Execute:input_type -> sliverpb.ExecuteReq
|
||||
49, // 77: rpcpb.SliverRPC.ExecuteWindows:input_type -> sliverpb.ExecuteWindowsReq
|
||||
50, // 78: rpcpb.SliverRPC.Sideload:input_type -> sliverpb.SideloadReq
|
||||
51, // 79: rpcpb.SliverRPC.SpawnDll:input_type -> sliverpb.InvokeSpawnDllReq
|
||||
52, // 80: rpcpb.SliverRPC.Screenshot:input_type -> sliverpb.ScreenshotReq
|
||||
53, // 81: rpcpb.SliverRPC.CurrentTokenOwner:input_type -> sliverpb.CurrentTokenOwnerReq
|
||||
54, // 82: rpcpb.SliverRPC.PivotStartListener:input_type -> sliverpb.PivotStartListenerReq
|
||||
55, // 83: rpcpb.SliverRPC.PivotStopListener:input_type -> sliverpb.PivotStopListenerReq
|
||||
56, // 84: rpcpb.SliverRPC.PivotSessionListeners:input_type -> sliverpb.PivotListenersReq
|
||||
0, // 85: rpcpb.SliverRPC.PivotGraph:input_type -> commonpb.Empty
|
||||
57, // 86: rpcpb.SliverRPC.StartService:input_type -> sliverpb.StartServiceReq
|
||||
58, // 87: rpcpb.SliverRPC.StopService:input_type -> sliverpb.StopServiceReq
|
||||
59, // 88: rpcpb.SliverRPC.RemoveService:input_type -> sliverpb.RemoveServiceReq
|
||||
60, // 89: rpcpb.SliverRPC.MakeToken:input_type -> sliverpb.MakeTokenReq
|
||||
61, // 90: rpcpb.SliverRPC.GetEnv:input_type -> sliverpb.EnvReq
|
||||
62, // 91: rpcpb.SliverRPC.SetEnv:input_type -> sliverpb.SetEnvReq
|
||||
63, // 92: rpcpb.SliverRPC.UnsetEnv:input_type -> sliverpb.UnsetEnvReq
|
||||
64, // 93: rpcpb.SliverRPC.Backdoor:input_type -> sliverpb.BackdoorReq
|
||||
65, // 94: rpcpb.SliverRPC.RegistryRead:input_type -> sliverpb.RegistryReadReq
|
||||
66, // 95: rpcpb.SliverRPC.RegistryWrite:input_type -> sliverpb.RegistryWriteReq
|
||||
67, // 96: rpcpb.SliverRPC.RegistryCreateKey:input_type -> sliverpb.RegistryCreateKeyReq
|
||||
68, // 97: rpcpb.SliverRPC.RegistryDeleteKey:input_type -> sliverpb.RegistryDeleteKeyReq
|
||||
69, // 98: rpcpb.SliverRPC.RegistryListSubKeys:input_type -> sliverpb.RegistrySubKeyListReq
|
||||
70, // 99: rpcpb.SliverRPC.RegistryListValues:input_type -> sliverpb.RegistryListValuesReq
|
||||
71, // 100: rpcpb.SliverRPC.RunSSHCommand:input_type -> sliverpb.SSHCommandReq
|
||||
72, // 101: rpcpb.SliverRPC.HijackDLL:input_type -> clientpb.DllHijackReq
|
||||
73, // 102: rpcpb.SliverRPC.GetPrivs:input_type -> sliverpb.GetPrivsReq
|
||||
74, // 103: rpcpb.SliverRPC.OpenSession:input_type -> sliverpb.OpenSession
|
||||
75, // 104: rpcpb.SliverRPC.CloseSession:input_type -> sliverpb.CloseSession
|
||||
76, // 105: rpcpb.SliverRPC.RegisterExtension:input_type -> sliverpb.RegisterExtensionReq
|
||||
77, // 106: rpcpb.SliverRPC.CallExtension:input_type -> sliverpb.CallExtensionReq
|
||||
78, // 107: rpcpb.SliverRPC.ListExtensions:input_type -> sliverpb.ListExtensionsReq
|
||||
79, // 108: rpcpb.SliverRPC.WGStartPortForward:input_type -> sliverpb.WGPortForwardStartReq
|
||||
80, // 109: rpcpb.SliverRPC.WGStopPortForward:input_type -> sliverpb.WGPortForwardStopReq
|
||||
81, // 110: rpcpb.SliverRPC.WGStartSocks:input_type -> sliverpb.WGSocksStartReq
|
||||
82, // 111: rpcpb.SliverRPC.WGStopSocks:input_type -> sliverpb.WGSocksStopReq
|
||||
83, // 112: rpcpb.SliverRPC.WGListForwarders:input_type -> sliverpb.WGTCPForwardersReq
|
||||
84, // 113: rpcpb.SliverRPC.WGListSocksServers:input_type -> sliverpb.WGSocksServersReq
|
||||
85, // 114: rpcpb.SliverRPC.Shell:input_type -> sliverpb.ShellReq
|
||||
86, // 115: rpcpb.SliverRPC.Portfwd:input_type -> sliverpb.PortfwdReq
|
||||
87, // 116: rpcpb.SliverRPC.CreateSocks:input_type -> sliverpb.Socks
|
||||
87, // 117: rpcpb.SliverRPC.CloseSocks:input_type -> sliverpb.Socks
|
||||
88, // 118: rpcpb.SliverRPC.SocksProxy:input_type -> sliverpb.SocksData
|
||||
89, // 119: rpcpb.SliverRPC.CreateTunnel:input_type -> sliverpb.Tunnel
|
||||
89, // 120: rpcpb.SliverRPC.CloseTunnel:input_type -> sliverpb.Tunnel
|
||||
90, // 121: rpcpb.SliverRPC.TunnelData:input_type -> sliverpb.TunnelData
|
||||
0, // 122: rpcpb.SliverRPC.Events:input_type -> commonpb.Empty
|
||||
91, // 123: rpcpb.SliverRPC.GetVersion:output_type -> clientpb.Version
|
||||
92, // 124: rpcpb.SliverRPC.GetOperators:output_type -> clientpb.Operators
|
||||
0, // 125: rpcpb.SliverRPC.Kill:output_type -> commonpb.Empty
|
||||
93, // 126: rpcpb.SliverRPC.Reconfigure:output_type -> sliverpb.Reconfigure
|
||||
0, // 127: rpcpb.SliverRPC.Rename:output_type -> commonpb.Empty
|
||||
94, // 128: rpcpb.SliverRPC.GetSessions:output_type -> clientpb.Sessions
|
||||
95, // 129: rpcpb.SliverRPC.GetBeacons:output_type -> clientpb.Beacons
|
||||
4, // 130: rpcpb.SliverRPC.GetBeacon:output_type -> clientpb.Beacon
|
||||
0, // 131: rpcpb.SliverRPC.RmBeacon:output_type -> commonpb.Empty
|
||||
96, // 132: rpcpb.SliverRPC.GetBeaconTasks:output_type -> clientpb.BeaconTasks
|
||||
5, // 133: rpcpb.SliverRPC.GetBeaconTaskContent:output_type -> clientpb.BeaconTask
|
||||
97, // 134: rpcpb.SliverRPC.MonitorStart:output_type -> commonpb.Response
|
||||
0, // 135: rpcpb.SliverRPC.MonitorStop:output_type -> commonpb.Empty
|
||||
98, // 136: rpcpb.SliverRPC.GetJobs:output_type -> clientpb.Jobs
|
||||
99, // 137: rpcpb.SliverRPC.KillJob:output_type -> clientpb.KillJob
|
||||
100, // 138: rpcpb.SliverRPC.StartMTLSListener:output_type -> clientpb.MTLSListener
|
||||
101, // 139: rpcpb.SliverRPC.StartWGListener:output_type -> clientpb.WGListener
|
||||
102, // 140: rpcpb.SliverRPC.StartDNSListener:output_type -> clientpb.DNSListener
|
||||
103, // 141: rpcpb.SliverRPC.StartHTTPSListener:output_type -> clientpb.HTTPListener
|
||||
103, // 142: rpcpb.SliverRPC.StartHTTPListener:output_type -> clientpb.HTTPListener
|
||||
104, // 143: rpcpb.SliverRPC.StartTCPStagerListener:output_type -> clientpb.StagerListener
|
||||
104, // 144: rpcpb.SliverRPC.StartHTTPStagerListener:output_type -> clientpb.StagerListener
|
||||
12, // 145: rpcpb.SliverRPC.LootAdd:output_type -> clientpb.Loot
|
||||
0, // 146: rpcpb.SliverRPC.LootRm:output_type -> commonpb.Empty
|
||||
12, // 147: rpcpb.SliverRPC.LootUpdate:output_type -> clientpb.Loot
|
||||
12, // 148: rpcpb.SliverRPC.LootContent:output_type -> clientpb.Loot
|
||||
105, // 149: rpcpb.SliverRPC.LootAll:output_type -> clientpb.AllLoot
|
||||
105, // 150: rpcpb.SliverRPC.LootAllOf:output_type -> clientpb.AllLoot
|
||||
106, // 151: rpcpb.SliverRPC.Hosts:output_type -> clientpb.AllHosts
|
||||
13, // 152: rpcpb.SliverRPC.Host:output_type -> clientpb.Host
|
||||
0, // 153: rpcpb.SliverRPC.HostRm:output_type -> commonpb.Empty
|
||||
0, // 154: rpcpb.SliverRPC.HostIOCRm:output_type -> commonpb.Empty
|
||||
107, // 155: rpcpb.SliverRPC.Generate:output_type -> clientpb.Generate
|
||||
107, // 156: rpcpb.SliverRPC.Regenerate:output_type -> clientpb.Generate
|
||||
108, // 157: rpcpb.SliverRPC.ImplantBuilds:output_type -> clientpb.ImplantBuilds
|
||||
0, // 158: rpcpb.SliverRPC.DeleteImplantBuild:output_type -> commonpb.Empty
|
||||
109, // 159: rpcpb.SliverRPC.Canaries:output_type -> clientpb.Canaries
|
||||
110, // 160: rpcpb.SliverRPC.GenerateWGClientConfig:output_type -> clientpb.WGClientConfig
|
||||
111, // 161: rpcpb.SliverRPC.GenerateUniqueIP:output_type -> clientpb.UniqueWGIP
|
||||
112, // 162: rpcpb.SliverRPC.ImplantProfiles:output_type -> clientpb.ImplantProfiles
|
||||
0, // 163: rpcpb.SliverRPC.DeleteImplantProfile:output_type -> commonpb.Empty
|
||||
18, // 164: rpcpb.SliverRPC.SaveImplantProfile:output_type -> clientpb.ImplantProfile
|
||||
113, // 165: rpcpb.SliverRPC.MsfStage:output_type -> clientpb.MsfStager
|
||||
114, // 166: rpcpb.SliverRPC.ShellcodeRDI:output_type -> clientpb.ShellcodeRDI
|
||||
115, // 167: rpcpb.SliverRPC.GetCompiler:output_type -> clientpb.Compiler
|
||||
116, // 168: rpcpb.SliverRPC.ShellcodeEncoder:output_type -> clientpb.ShellcodeEncode
|
||||
117, // 169: rpcpb.SliverRPC.ShellcodeEncoderMap:output_type -> clientpb.ShellcodeEncoderMap
|
||||
118, // 170: rpcpb.SliverRPC.Websites:output_type -> clientpb.Websites
|
||||
22, // 171: rpcpb.SliverRPC.Website:output_type -> clientpb.Website
|
||||
0, // 172: rpcpb.SliverRPC.WebsiteRemove:output_type -> commonpb.Empty
|
||||
22, // 173: rpcpb.SliverRPC.WebsiteAddContent:output_type -> clientpb.Website
|
||||
22, // 174: rpcpb.SliverRPC.WebsiteUpdateContent:output_type -> clientpb.Website
|
||||
22, // 175: rpcpb.SliverRPC.WebsiteRemoveContent:output_type -> clientpb.Website
|
||||
25, // 176: rpcpb.SliverRPC.Ping:output_type -> sliverpb.Ping
|
||||
119, // 177: rpcpb.SliverRPC.Ps:output_type -> sliverpb.Ps
|
||||
120, // 178: rpcpb.SliverRPC.Terminate:output_type -> sliverpb.Terminate
|
||||
121, // 179: rpcpb.SliverRPC.Ifconfig:output_type -> sliverpb.Ifconfig
|
||||
122, // 180: rpcpb.SliverRPC.Netstat:output_type -> sliverpb.Netstat
|
||||
123, // 181: rpcpb.SliverRPC.Ls:output_type -> sliverpb.Ls
|
||||
124, // 182: rpcpb.SliverRPC.Cd:output_type -> sliverpb.Pwd
|
||||
124, // 183: rpcpb.SliverRPC.Pwd:output_type -> sliverpb.Pwd
|
||||
125, // 184: rpcpb.SliverRPC.Mv:output_type -> sliverpb.Mv
|
||||
126, // 185: rpcpb.SliverRPC.Rm:output_type -> sliverpb.Rm
|
||||
127, // 186: rpcpb.SliverRPC.Mkdir:output_type -> sliverpb.Mkdir
|
||||
128, // 187: rpcpb.SliverRPC.Download:output_type -> sliverpb.Download
|
||||
129, // 188: rpcpb.SliverRPC.Upload:output_type -> sliverpb.Upload
|
||||
130, // 189: rpcpb.SliverRPC.ProcessDump:output_type -> sliverpb.ProcessDump
|
||||
131, // 190: rpcpb.SliverRPC.RunAs:output_type -> sliverpb.RunAs
|
||||
132, // 191: rpcpb.SliverRPC.Impersonate:output_type -> sliverpb.Impersonate
|
||||
133, // 192: rpcpb.SliverRPC.RevToSelf:output_type -> sliverpb.RevToSelf
|
||||
134, // 193: rpcpb.SliverRPC.GetSystem:output_type -> sliverpb.GetSystem
|
||||
135, // 194: rpcpb.SliverRPC.Task:output_type -> sliverpb.Task
|
||||
135, // 195: rpcpb.SliverRPC.Msf:output_type -> sliverpb.Task
|
||||
135, // 196: rpcpb.SliverRPC.MsfRemote:output_type -> sliverpb.Task
|
||||
136, // 197: rpcpb.SliverRPC.ExecuteAssembly:output_type -> sliverpb.ExecuteAssembly
|
||||
137, // 198: rpcpb.SliverRPC.Migrate:output_type -> sliverpb.Migrate
|
||||
138, // 199: rpcpb.SliverRPC.Execute:output_type -> sliverpb.Execute
|
||||
138, // 200: rpcpb.SliverRPC.ExecuteWindows:output_type -> sliverpb.Execute
|
||||
139, // 201: rpcpb.SliverRPC.Sideload:output_type -> sliverpb.Sideload
|
||||
140, // 202: rpcpb.SliverRPC.SpawnDll:output_type -> sliverpb.SpawnDll
|
||||
141, // 203: rpcpb.SliverRPC.Screenshot:output_type -> sliverpb.Screenshot
|
||||
142, // 204: rpcpb.SliverRPC.CurrentTokenOwner:output_type -> sliverpb.CurrentTokenOwner
|
||||
143, // 205: rpcpb.SliverRPC.PivotStartListener:output_type -> sliverpb.PivotListener
|
||||
0, // 206: rpcpb.SliverRPC.PivotStopListener:output_type -> commonpb.Empty
|
||||
144, // 207: rpcpb.SliverRPC.PivotSessionListeners:output_type -> sliverpb.PivotListeners
|
||||
145, // 208: rpcpb.SliverRPC.PivotGraph:output_type -> clientpb.PivotGraph
|
||||
146, // 209: rpcpb.SliverRPC.StartService:output_type -> sliverpb.ServiceInfo
|
||||
146, // 210: rpcpb.SliverRPC.StopService:output_type -> sliverpb.ServiceInfo
|
||||
146, // 211: rpcpb.SliverRPC.RemoveService:output_type -> sliverpb.ServiceInfo
|
||||
147, // 212: rpcpb.SliverRPC.MakeToken:output_type -> sliverpb.MakeToken
|
||||
148, // 213: rpcpb.SliverRPC.GetEnv:output_type -> sliverpb.EnvInfo
|
||||
149, // 214: rpcpb.SliverRPC.SetEnv:output_type -> sliverpb.SetEnv
|
||||
150, // 215: rpcpb.SliverRPC.UnsetEnv:output_type -> sliverpb.UnsetEnv
|
||||
151, // 216: rpcpb.SliverRPC.Backdoor:output_type -> sliverpb.Backdoor
|
||||
152, // 217: rpcpb.SliverRPC.RegistryRead:output_type -> sliverpb.RegistryRead
|
||||
153, // 218: rpcpb.SliverRPC.RegistryWrite:output_type -> sliverpb.RegistryWrite
|
||||
154, // 219: rpcpb.SliverRPC.RegistryCreateKey:output_type -> sliverpb.RegistryCreateKey
|
||||
155, // 220: rpcpb.SliverRPC.RegistryDeleteKey:output_type -> sliverpb.RegistryDeleteKey
|
||||
156, // 221: rpcpb.SliverRPC.RegistryListSubKeys:output_type -> sliverpb.RegistrySubKeyList
|
||||
157, // 222: rpcpb.SliverRPC.RegistryListValues:output_type -> sliverpb.RegistryValuesList
|
||||
158, // 223: rpcpb.SliverRPC.RunSSHCommand:output_type -> sliverpb.SSHCommand
|
||||
159, // 224: rpcpb.SliverRPC.HijackDLL:output_type -> clientpb.DllHijack
|
||||
160, // 225: rpcpb.SliverRPC.GetPrivs:output_type -> sliverpb.GetPrivs
|
||||
74, // 226: rpcpb.SliverRPC.OpenSession:output_type -> sliverpb.OpenSession
|
||||
0, // 227: rpcpb.SliverRPC.CloseSession:output_type -> commonpb.Empty
|
||||
161, // 228: rpcpb.SliverRPC.RegisterExtension:output_type -> sliverpb.RegisterExtension
|
||||
162, // 229: rpcpb.SliverRPC.CallExtension:output_type -> sliverpb.CallExtension
|
||||
163, // 230: rpcpb.SliverRPC.ListExtensions:output_type -> sliverpb.ListExtensions
|
||||
164, // 231: rpcpb.SliverRPC.WGStartPortForward:output_type -> sliverpb.WGPortForward
|
||||
164, // 232: rpcpb.SliverRPC.WGStopPortForward:output_type -> sliverpb.WGPortForward
|
||||
165, // 233: rpcpb.SliverRPC.WGStartSocks:output_type -> sliverpb.WGSocks
|
||||
165, // 234: rpcpb.SliverRPC.WGStopSocks:output_type -> sliverpb.WGSocks
|
||||
166, // 235: rpcpb.SliverRPC.WGListForwarders:output_type -> sliverpb.WGTCPForwarders
|
||||
167, // 236: rpcpb.SliverRPC.WGListSocksServers:output_type -> sliverpb.WGSocksServers
|
||||
168, // 237: rpcpb.SliverRPC.Shell:output_type -> sliverpb.Shell
|
||||
169, // 238: rpcpb.SliverRPC.Portfwd:output_type -> sliverpb.Portfwd
|
||||
87, // 239: rpcpb.SliverRPC.CreateSocks:output_type -> sliverpb.Socks
|
||||
0, // 240: rpcpb.SliverRPC.CloseSocks:output_type -> commonpb.Empty
|
||||
88, // 241: rpcpb.SliverRPC.SocksProxy:output_type -> sliverpb.SocksData
|
||||
89, // 242: rpcpb.SliverRPC.CreateTunnel:output_type -> sliverpb.Tunnel
|
||||
0, // 243: rpcpb.SliverRPC.CloseTunnel:output_type -> commonpb.Empty
|
||||
90, // 244: rpcpb.SliverRPC.TunnelData:output_type -> sliverpb.TunnelData
|
||||
170, // 245: rpcpb.SliverRPC.Events:output_type -> clientpb.Event
|
||||
123, // [123:246] is the sub-list for method output_type
|
||||
0, // [0:123] is the sub-list for method input_type
|
||||
5, // 11: rpcpb.SliverRPC.CancelBeaconTask:input_type -> clientpb.BeaconTask
|
||||
0, // 12: rpcpb.SliverRPC.MonitorStart:input_type -> commonpb.Empty
|
||||
0, // 13: rpcpb.SliverRPC.MonitorStop:input_type -> commonpb.Empty
|
||||
0, // 14: rpcpb.SliverRPC.GetJobs:input_type -> commonpb.Empty
|
||||
6, // 15: rpcpb.SliverRPC.KillJob:input_type -> clientpb.KillJobReq
|
||||
7, // 16: rpcpb.SliverRPC.StartMTLSListener:input_type -> clientpb.MTLSListenerReq
|
||||
8, // 17: rpcpb.SliverRPC.StartWGListener:input_type -> clientpb.WGListenerReq
|
||||
9, // 18: rpcpb.SliverRPC.StartDNSListener:input_type -> clientpb.DNSListenerReq
|
||||
10, // 19: rpcpb.SliverRPC.StartHTTPSListener:input_type -> clientpb.HTTPListenerReq
|
||||
10, // 20: rpcpb.SliverRPC.StartHTTPListener:input_type -> clientpb.HTTPListenerReq
|
||||
11, // 21: rpcpb.SliverRPC.StartTCPStagerListener:input_type -> clientpb.StagerListenerReq
|
||||
11, // 22: rpcpb.SliverRPC.StartHTTPStagerListener:input_type -> clientpb.StagerListenerReq
|
||||
12, // 23: rpcpb.SliverRPC.LootAdd:input_type -> clientpb.Loot
|
||||
12, // 24: rpcpb.SliverRPC.LootRm:input_type -> clientpb.Loot
|
||||
12, // 25: rpcpb.SliverRPC.LootUpdate:input_type -> clientpb.Loot
|
||||
12, // 26: rpcpb.SliverRPC.LootContent:input_type -> clientpb.Loot
|
||||
0, // 27: rpcpb.SliverRPC.LootAll:input_type -> commonpb.Empty
|
||||
12, // 28: rpcpb.SliverRPC.LootAllOf:input_type -> clientpb.Loot
|
||||
0, // 29: rpcpb.SliverRPC.Hosts:input_type -> commonpb.Empty
|
||||
13, // 30: rpcpb.SliverRPC.Host:input_type -> clientpb.Host
|
||||
13, // 31: rpcpb.SliverRPC.HostRm:input_type -> clientpb.Host
|
||||
14, // 32: rpcpb.SliverRPC.HostIOCRm:input_type -> clientpb.IOC
|
||||
15, // 33: rpcpb.SliverRPC.Generate:input_type -> clientpb.GenerateReq
|
||||
16, // 34: rpcpb.SliverRPC.Regenerate:input_type -> clientpb.RegenerateReq
|
||||
0, // 35: rpcpb.SliverRPC.ImplantBuilds:input_type -> commonpb.Empty
|
||||
17, // 36: rpcpb.SliverRPC.DeleteImplantBuild:input_type -> clientpb.DeleteReq
|
||||
0, // 37: rpcpb.SliverRPC.Canaries:input_type -> commonpb.Empty
|
||||
0, // 38: rpcpb.SliverRPC.GenerateWGClientConfig:input_type -> commonpb.Empty
|
||||
0, // 39: rpcpb.SliverRPC.GenerateUniqueIP:input_type -> commonpb.Empty
|
||||
0, // 40: rpcpb.SliverRPC.ImplantProfiles:input_type -> commonpb.Empty
|
||||
17, // 41: rpcpb.SliverRPC.DeleteImplantProfile:input_type -> clientpb.DeleteReq
|
||||
18, // 42: rpcpb.SliverRPC.SaveImplantProfile:input_type -> clientpb.ImplantProfile
|
||||
19, // 43: rpcpb.SliverRPC.MsfStage:input_type -> clientpb.MsfStagerReq
|
||||
20, // 44: rpcpb.SliverRPC.ShellcodeRDI:input_type -> clientpb.ShellcodeRDIReq
|
||||
0, // 45: rpcpb.SliverRPC.GetCompiler:input_type -> commonpb.Empty
|
||||
21, // 46: rpcpb.SliverRPC.ShellcodeEncoder:input_type -> clientpb.ShellcodeEncodeReq
|
||||
0, // 47: rpcpb.SliverRPC.ShellcodeEncoderMap:input_type -> commonpb.Empty
|
||||
0, // 48: rpcpb.SliverRPC.Websites:input_type -> commonpb.Empty
|
||||
22, // 49: rpcpb.SliverRPC.Website:input_type -> clientpb.Website
|
||||
22, // 50: rpcpb.SliverRPC.WebsiteRemove:input_type -> clientpb.Website
|
||||
23, // 51: rpcpb.SliverRPC.WebsiteAddContent:input_type -> clientpb.WebsiteAddContent
|
||||
23, // 52: rpcpb.SliverRPC.WebsiteUpdateContent:input_type -> clientpb.WebsiteAddContent
|
||||
24, // 53: rpcpb.SliverRPC.WebsiteRemoveContent:input_type -> clientpb.WebsiteRemoveContent
|
||||
25, // 54: rpcpb.SliverRPC.Ping:input_type -> sliverpb.Ping
|
||||
26, // 55: rpcpb.SliverRPC.Ps:input_type -> sliverpb.PsReq
|
||||
27, // 56: rpcpb.SliverRPC.Terminate:input_type -> sliverpb.TerminateReq
|
||||
28, // 57: rpcpb.SliverRPC.Ifconfig:input_type -> sliverpb.IfconfigReq
|
||||
29, // 58: rpcpb.SliverRPC.Netstat:input_type -> sliverpb.NetstatReq
|
||||
30, // 59: rpcpb.SliverRPC.Ls:input_type -> sliverpb.LsReq
|
||||
31, // 60: rpcpb.SliverRPC.Cd:input_type -> sliverpb.CdReq
|
||||
32, // 61: rpcpb.SliverRPC.Pwd:input_type -> sliverpb.PwdReq
|
||||
33, // 62: rpcpb.SliverRPC.Mv:input_type -> sliverpb.MvReq
|
||||
34, // 63: rpcpb.SliverRPC.Rm:input_type -> sliverpb.RmReq
|
||||
35, // 64: rpcpb.SliverRPC.Mkdir:input_type -> sliverpb.MkdirReq
|
||||
36, // 65: rpcpb.SliverRPC.Download:input_type -> sliverpb.DownloadReq
|
||||
37, // 66: rpcpb.SliverRPC.Upload:input_type -> sliverpb.UploadReq
|
||||
38, // 67: rpcpb.SliverRPC.ProcessDump:input_type -> sliverpb.ProcessDumpReq
|
||||
39, // 68: rpcpb.SliverRPC.RunAs:input_type -> sliverpb.RunAsReq
|
||||
40, // 69: rpcpb.SliverRPC.Impersonate:input_type -> sliverpb.ImpersonateReq
|
||||
41, // 70: rpcpb.SliverRPC.RevToSelf:input_type -> sliverpb.RevToSelfReq
|
||||
42, // 71: rpcpb.SliverRPC.GetSystem:input_type -> clientpb.GetSystemReq
|
||||
43, // 72: rpcpb.SliverRPC.Task:input_type -> sliverpb.TaskReq
|
||||
44, // 73: rpcpb.SliverRPC.Msf:input_type -> clientpb.MSFReq
|
||||
45, // 74: rpcpb.SliverRPC.MsfRemote:input_type -> clientpb.MSFRemoteReq
|
||||
46, // 75: rpcpb.SliverRPC.ExecuteAssembly:input_type -> sliverpb.ExecuteAssemblyReq
|
||||
47, // 76: rpcpb.SliverRPC.Migrate:input_type -> clientpb.MigrateReq
|
||||
48, // 77: rpcpb.SliverRPC.Execute:input_type -> sliverpb.ExecuteReq
|
||||
49, // 78: rpcpb.SliverRPC.ExecuteWindows:input_type -> sliverpb.ExecuteWindowsReq
|
||||
50, // 79: rpcpb.SliverRPC.Sideload:input_type -> sliverpb.SideloadReq
|
||||
51, // 80: rpcpb.SliverRPC.SpawnDll:input_type -> sliverpb.InvokeSpawnDllReq
|
||||
52, // 81: rpcpb.SliverRPC.Screenshot:input_type -> sliverpb.ScreenshotReq
|
||||
53, // 82: rpcpb.SliverRPC.CurrentTokenOwner:input_type -> sliverpb.CurrentTokenOwnerReq
|
||||
54, // 83: rpcpb.SliverRPC.PivotStartListener:input_type -> sliverpb.PivotStartListenerReq
|
||||
55, // 84: rpcpb.SliverRPC.PivotStopListener:input_type -> sliverpb.PivotStopListenerReq
|
||||
56, // 85: rpcpb.SliverRPC.PivotSessionListeners:input_type -> sliverpb.PivotListenersReq
|
||||
0, // 86: rpcpb.SliverRPC.PivotGraph:input_type -> commonpb.Empty
|
||||
57, // 87: rpcpb.SliverRPC.StartService:input_type -> sliverpb.StartServiceReq
|
||||
58, // 88: rpcpb.SliverRPC.StopService:input_type -> sliverpb.StopServiceReq
|
||||
59, // 89: rpcpb.SliverRPC.RemoveService:input_type -> sliverpb.RemoveServiceReq
|
||||
60, // 90: rpcpb.SliverRPC.MakeToken:input_type -> sliverpb.MakeTokenReq
|
||||
61, // 91: rpcpb.SliverRPC.GetEnv:input_type -> sliverpb.EnvReq
|
||||
62, // 92: rpcpb.SliverRPC.SetEnv:input_type -> sliverpb.SetEnvReq
|
||||
63, // 93: rpcpb.SliverRPC.UnsetEnv:input_type -> sliverpb.UnsetEnvReq
|
||||
64, // 94: rpcpb.SliverRPC.Backdoor:input_type -> sliverpb.BackdoorReq
|
||||
65, // 95: rpcpb.SliverRPC.RegistryRead:input_type -> sliverpb.RegistryReadReq
|
||||
66, // 96: rpcpb.SliverRPC.RegistryWrite:input_type -> sliverpb.RegistryWriteReq
|
||||
67, // 97: rpcpb.SliverRPC.RegistryCreateKey:input_type -> sliverpb.RegistryCreateKeyReq
|
||||
68, // 98: rpcpb.SliverRPC.RegistryDeleteKey:input_type -> sliverpb.RegistryDeleteKeyReq
|
||||
69, // 99: rpcpb.SliverRPC.RegistryListSubKeys:input_type -> sliverpb.RegistrySubKeyListReq
|
||||
70, // 100: rpcpb.SliverRPC.RegistryListValues:input_type -> sliverpb.RegistryListValuesReq
|
||||
71, // 101: rpcpb.SliverRPC.RunSSHCommand:input_type -> sliverpb.SSHCommandReq
|
||||
72, // 102: rpcpb.SliverRPC.HijackDLL:input_type -> clientpb.DllHijackReq
|
||||
73, // 103: rpcpb.SliverRPC.GetPrivs:input_type -> sliverpb.GetPrivsReq
|
||||
74, // 104: rpcpb.SliverRPC.OpenSession:input_type -> sliverpb.OpenSession
|
||||
75, // 105: rpcpb.SliverRPC.CloseSession:input_type -> sliverpb.CloseSession
|
||||
76, // 106: rpcpb.SliverRPC.RegisterExtension:input_type -> sliverpb.RegisterExtensionReq
|
||||
77, // 107: rpcpb.SliverRPC.CallExtension:input_type -> sliverpb.CallExtensionReq
|
||||
78, // 108: rpcpb.SliverRPC.ListExtensions:input_type -> sliverpb.ListExtensionsReq
|
||||
79, // 109: rpcpb.SliverRPC.WGStartPortForward:input_type -> sliverpb.WGPortForwardStartReq
|
||||
80, // 110: rpcpb.SliverRPC.WGStopPortForward:input_type -> sliverpb.WGPortForwardStopReq
|
||||
81, // 111: rpcpb.SliverRPC.WGStartSocks:input_type -> sliverpb.WGSocksStartReq
|
||||
82, // 112: rpcpb.SliverRPC.WGStopSocks:input_type -> sliverpb.WGSocksStopReq
|
||||
83, // 113: rpcpb.SliverRPC.WGListForwarders:input_type -> sliverpb.WGTCPForwardersReq
|
||||
84, // 114: rpcpb.SliverRPC.WGListSocksServers:input_type -> sliverpb.WGSocksServersReq
|
||||
85, // 115: rpcpb.SliverRPC.Shell:input_type -> sliverpb.ShellReq
|
||||
86, // 116: rpcpb.SliverRPC.Portfwd:input_type -> sliverpb.PortfwdReq
|
||||
87, // 117: rpcpb.SliverRPC.CreateSocks:input_type -> sliverpb.Socks
|
||||
87, // 118: rpcpb.SliverRPC.CloseSocks:input_type -> sliverpb.Socks
|
||||
88, // 119: rpcpb.SliverRPC.SocksProxy:input_type -> sliverpb.SocksData
|
||||
89, // 120: rpcpb.SliverRPC.CreateTunnel:input_type -> sliverpb.Tunnel
|
||||
89, // 121: rpcpb.SliverRPC.CloseTunnel:input_type -> sliverpb.Tunnel
|
||||
90, // 122: rpcpb.SliverRPC.TunnelData:input_type -> sliverpb.TunnelData
|
||||
0, // 123: rpcpb.SliverRPC.Events:input_type -> commonpb.Empty
|
||||
91, // 124: rpcpb.SliverRPC.GetVersion:output_type -> clientpb.Version
|
||||
92, // 125: rpcpb.SliverRPC.GetOperators:output_type -> clientpb.Operators
|
||||
0, // 126: rpcpb.SliverRPC.Kill:output_type -> commonpb.Empty
|
||||
93, // 127: rpcpb.SliverRPC.Reconfigure:output_type -> sliverpb.Reconfigure
|
||||
0, // 128: rpcpb.SliverRPC.Rename:output_type -> commonpb.Empty
|
||||
94, // 129: rpcpb.SliverRPC.GetSessions:output_type -> clientpb.Sessions
|
||||
95, // 130: rpcpb.SliverRPC.GetBeacons:output_type -> clientpb.Beacons
|
||||
4, // 131: rpcpb.SliverRPC.GetBeacon:output_type -> clientpb.Beacon
|
||||
0, // 132: rpcpb.SliverRPC.RmBeacon:output_type -> commonpb.Empty
|
||||
96, // 133: rpcpb.SliverRPC.GetBeaconTasks:output_type -> clientpb.BeaconTasks
|
||||
5, // 134: rpcpb.SliverRPC.GetBeaconTaskContent:output_type -> clientpb.BeaconTask
|
||||
5, // 135: rpcpb.SliverRPC.CancelBeaconTask:output_type -> clientpb.BeaconTask
|
||||
97, // 136: rpcpb.SliverRPC.MonitorStart:output_type -> commonpb.Response
|
||||
0, // 137: rpcpb.SliverRPC.MonitorStop:output_type -> commonpb.Empty
|
||||
98, // 138: rpcpb.SliverRPC.GetJobs:output_type -> clientpb.Jobs
|
||||
99, // 139: rpcpb.SliverRPC.KillJob:output_type -> clientpb.KillJob
|
||||
100, // 140: rpcpb.SliverRPC.StartMTLSListener:output_type -> clientpb.MTLSListener
|
||||
101, // 141: rpcpb.SliverRPC.StartWGListener:output_type -> clientpb.WGListener
|
||||
102, // 142: rpcpb.SliverRPC.StartDNSListener:output_type -> clientpb.DNSListener
|
||||
103, // 143: rpcpb.SliverRPC.StartHTTPSListener:output_type -> clientpb.HTTPListener
|
||||
103, // 144: rpcpb.SliverRPC.StartHTTPListener:output_type -> clientpb.HTTPListener
|
||||
104, // 145: rpcpb.SliverRPC.StartTCPStagerListener:output_type -> clientpb.StagerListener
|
||||
104, // 146: rpcpb.SliverRPC.StartHTTPStagerListener:output_type -> clientpb.StagerListener
|
||||
12, // 147: rpcpb.SliverRPC.LootAdd:output_type -> clientpb.Loot
|
||||
0, // 148: rpcpb.SliverRPC.LootRm:output_type -> commonpb.Empty
|
||||
12, // 149: rpcpb.SliverRPC.LootUpdate:output_type -> clientpb.Loot
|
||||
12, // 150: rpcpb.SliverRPC.LootContent:output_type -> clientpb.Loot
|
||||
105, // 151: rpcpb.SliverRPC.LootAll:output_type -> clientpb.AllLoot
|
||||
105, // 152: rpcpb.SliverRPC.LootAllOf:output_type -> clientpb.AllLoot
|
||||
106, // 153: rpcpb.SliverRPC.Hosts:output_type -> clientpb.AllHosts
|
||||
13, // 154: rpcpb.SliverRPC.Host:output_type -> clientpb.Host
|
||||
0, // 155: rpcpb.SliverRPC.HostRm:output_type -> commonpb.Empty
|
||||
0, // 156: rpcpb.SliverRPC.HostIOCRm:output_type -> commonpb.Empty
|
||||
107, // 157: rpcpb.SliverRPC.Generate:output_type -> clientpb.Generate
|
||||
107, // 158: rpcpb.SliverRPC.Regenerate:output_type -> clientpb.Generate
|
||||
108, // 159: rpcpb.SliverRPC.ImplantBuilds:output_type -> clientpb.ImplantBuilds
|
||||
0, // 160: rpcpb.SliverRPC.DeleteImplantBuild:output_type -> commonpb.Empty
|
||||
109, // 161: rpcpb.SliverRPC.Canaries:output_type -> clientpb.Canaries
|
||||
110, // 162: rpcpb.SliverRPC.GenerateWGClientConfig:output_type -> clientpb.WGClientConfig
|
||||
111, // 163: rpcpb.SliverRPC.GenerateUniqueIP:output_type -> clientpb.UniqueWGIP
|
||||
112, // 164: rpcpb.SliverRPC.ImplantProfiles:output_type -> clientpb.ImplantProfiles
|
||||
0, // 165: rpcpb.SliverRPC.DeleteImplantProfile:output_type -> commonpb.Empty
|
||||
18, // 166: rpcpb.SliverRPC.SaveImplantProfile:output_type -> clientpb.ImplantProfile
|
||||
113, // 167: rpcpb.SliverRPC.MsfStage:output_type -> clientpb.MsfStager
|
||||
114, // 168: rpcpb.SliverRPC.ShellcodeRDI:output_type -> clientpb.ShellcodeRDI
|
||||
115, // 169: rpcpb.SliverRPC.GetCompiler:output_type -> clientpb.Compiler
|
||||
116, // 170: rpcpb.SliverRPC.ShellcodeEncoder:output_type -> clientpb.ShellcodeEncode
|
||||
117, // 171: rpcpb.SliverRPC.ShellcodeEncoderMap:output_type -> clientpb.ShellcodeEncoderMap
|
||||
118, // 172: rpcpb.SliverRPC.Websites:output_type -> clientpb.Websites
|
||||
22, // 173: rpcpb.SliverRPC.Website:output_type -> clientpb.Website
|
||||
0, // 174: rpcpb.SliverRPC.WebsiteRemove:output_type -> commonpb.Empty
|
||||
22, // 175: rpcpb.SliverRPC.WebsiteAddContent:output_type -> clientpb.Website
|
||||
22, // 176: rpcpb.SliverRPC.WebsiteUpdateContent:output_type -> clientpb.Website
|
||||
22, // 177: rpcpb.SliverRPC.WebsiteRemoveContent:output_type -> clientpb.Website
|
||||
25, // 178: rpcpb.SliverRPC.Ping:output_type -> sliverpb.Ping
|
||||
119, // 179: rpcpb.SliverRPC.Ps:output_type -> sliverpb.Ps
|
||||
120, // 180: rpcpb.SliverRPC.Terminate:output_type -> sliverpb.Terminate
|
||||
121, // 181: rpcpb.SliverRPC.Ifconfig:output_type -> sliverpb.Ifconfig
|
||||
122, // 182: rpcpb.SliverRPC.Netstat:output_type -> sliverpb.Netstat
|
||||
123, // 183: rpcpb.SliverRPC.Ls:output_type -> sliverpb.Ls
|
||||
124, // 184: rpcpb.SliverRPC.Cd:output_type -> sliverpb.Pwd
|
||||
124, // 185: rpcpb.SliverRPC.Pwd:output_type -> sliverpb.Pwd
|
||||
125, // 186: rpcpb.SliverRPC.Mv:output_type -> sliverpb.Mv
|
||||
126, // 187: rpcpb.SliverRPC.Rm:output_type -> sliverpb.Rm
|
||||
127, // 188: rpcpb.SliverRPC.Mkdir:output_type -> sliverpb.Mkdir
|
||||
128, // 189: rpcpb.SliverRPC.Download:output_type -> sliverpb.Download
|
||||
129, // 190: rpcpb.SliverRPC.Upload:output_type -> sliverpb.Upload
|
||||
130, // 191: rpcpb.SliverRPC.ProcessDump:output_type -> sliverpb.ProcessDump
|
||||
131, // 192: rpcpb.SliverRPC.RunAs:output_type -> sliverpb.RunAs
|
||||
132, // 193: rpcpb.SliverRPC.Impersonate:output_type -> sliverpb.Impersonate
|
||||
133, // 194: rpcpb.SliverRPC.RevToSelf:output_type -> sliverpb.RevToSelf
|
||||
134, // 195: rpcpb.SliverRPC.GetSystem:output_type -> sliverpb.GetSystem
|
||||
135, // 196: rpcpb.SliverRPC.Task:output_type -> sliverpb.Task
|
||||
135, // 197: rpcpb.SliverRPC.Msf:output_type -> sliverpb.Task
|
||||
135, // 198: rpcpb.SliverRPC.MsfRemote:output_type -> sliverpb.Task
|
||||
136, // 199: rpcpb.SliverRPC.ExecuteAssembly:output_type -> sliverpb.ExecuteAssembly
|
||||
137, // 200: rpcpb.SliverRPC.Migrate:output_type -> sliverpb.Migrate
|
||||
138, // 201: rpcpb.SliverRPC.Execute:output_type -> sliverpb.Execute
|
||||
138, // 202: rpcpb.SliverRPC.ExecuteWindows:output_type -> sliverpb.Execute
|
||||
139, // 203: rpcpb.SliverRPC.Sideload:output_type -> sliverpb.Sideload
|
||||
140, // 204: rpcpb.SliverRPC.SpawnDll:output_type -> sliverpb.SpawnDll
|
||||
141, // 205: rpcpb.SliverRPC.Screenshot:output_type -> sliverpb.Screenshot
|
||||
142, // 206: rpcpb.SliverRPC.CurrentTokenOwner:output_type -> sliverpb.CurrentTokenOwner
|
||||
143, // 207: rpcpb.SliverRPC.PivotStartListener:output_type -> sliverpb.PivotListener
|
||||
0, // 208: rpcpb.SliverRPC.PivotStopListener:output_type -> commonpb.Empty
|
||||
144, // 209: rpcpb.SliverRPC.PivotSessionListeners:output_type -> sliverpb.PivotListeners
|
||||
145, // 210: rpcpb.SliverRPC.PivotGraph:output_type -> clientpb.PivotGraph
|
||||
146, // 211: rpcpb.SliverRPC.StartService:output_type -> sliverpb.ServiceInfo
|
||||
146, // 212: rpcpb.SliverRPC.StopService:output_type -> sliverpb.ServiceInfo
|
||||
146, // 213: rpcpb.SliverRPC.RemoveService:output_type -> sliverpb.ServiceInfo
|
||||
147, // 214: rpcpb.SliverRPC.MakeToken:output_type -> sliverpb.MakeToken
|
||||
148, // 215: rpcpb.SliverRPC.GetEnv:output_type -> sliverpb.EnvInfo
|
||||
149, // 216: rpcpb.SliverRPC.SetEnv:output_type -> sliverpb.SetEnv
|
||||
150, // 217: rpcpb.SliverRPC.UnsetEnv:output_type -> sliverpb.UnsetEnv
|
||||
151, // 218: rpcpb.SliverRPC.Backdoor:output_type -> sliverpb.Backdoor
|
||||
152, // 219: rpcpb.SliverRPC.RegistryRead:output_type -> sliverpb.RegistryRead
|
||||
153, // 220: rpcpb.SliverRPC.RegistryWrite:output_type -> sliverpb.RegistryWrite
|
||||
154, // 221: rpcpb.SliverRPC.RegistryCreateKey:output_type -> sliverpb.RegistryCreateKey
|
||||
155, // 222: rpcpb.SliverRPC.RegistryDeleteKey:output_type -> sliverpb.RegistryDeleteKey
|
||||
156, // 223: rpcpb.SliverRPC.RegistryListSubKeys:output_type -> sliverpb.RegistrySubKeyList
|
||||
157, // 224: rpcpb.SliverRPC.RegistryListValues:output_type -> sliverpb.RegistryValuesList
|
||||
158, // 225: rpcpb.SliverRPC.RunSSHCommand:output_type -> sliverpb.SSHCommand
|
||||
159, // 226: rpcpb.SliverRPC.HijackDLL:output_type -> clientpb.DllHijack
|
||||
160, // 227: rpcpb.SliverRPC.GetPrivs:output_type -> sliverpb.GetPrivs
|
||||
74, // 228: rpcpb.SliverRPC.OpenSession:output_type -> sliverpb.OpenSession
|
||||
0, // 229: rpcpb.SliverRPC.CloseSession:output_type -> commonpb.Empty
|
||||
161, // 230: rpcpb.SliverRPC.RegisterExtension:output_type -> sliverpb.RegisterExtension
|
||||
162, // 231: rpcpb.SliverRPC.CallExtension:output_type -> sliverpb.CallExtension
|
||||
163, // 232: rpcpb.SliverRPC.ListExtensions:output_type -> sliverpb.ListExtensions
|
||||
164, // 233: rpcpb.SliverRPC.WGStartPortForward:output_type -> sliverpb.WGPortForward
|
||||
164, // 234: rpcpb.SliverRPC.WGStopPortForward:output_type -> sliverpb.WGPortForward
|
||||
165, // 235: rpcpb.SliverRPC.WGStartSocks:output_type -> sliverpb.WGSocks
|
||||
165, // 236: rpcpb.SliverRPC.WGStopSocks:output_type -> sliverpb.WGSocks
|
||||
166, // 237: rpcpb.SliverRPC.WGListForwarders:output_type -> sliverpb.WGTCPForwarders
|
||||
167, // 238: rpcpb.SliverRPC.WGListSocksServers:output_type -> sliverpb.WGSocksServers
|
||||
168, // 239: rpcpb.SliverRPC.Shell:output_type -> sliverpb.Shell
|
||||
169, // 240: rpcpb.SliverRPC.Portfwd:output_type -> sliverpb.Portfwd
|
||||
87, // 241: rpcpb.SliverRPC.CreateSocks:output_type -> sliverpb.Socks
|
||||
0, // 242: rpcpb.SliverRPC.CloseSocks:output_type -> commonpb.Empty
|
||||
88, // 243: rpcpb.SliverRPC.SocksProxy:output_type -> sliverpb.SocksData
|
||||
89, // 244: rpcpb.SliverRPC.CreateTunnel:output_type -> sliverpb.Tunnel
|
||||
0, // 245: rpcpb.SliverRPC.CloseTunnel:output_type -> commonpb.Empty
|
||||
90, // 246: rpcpb.SliverRPC.TunnelData:output_type -> sliverpb.TunnelData
|
||||
170, // 247: rpcpb.SliverRPC.Events:output_type -> clientpb.Event
|
||||
124, // [124:248] is the sub-list for method output_type
|
||||
0, // [0:124] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
|
||||
@@ -29,6 +29,7 @@ service SliverRPC {
|
||||
rpc RmBeacon(clientpb.Beacon) returns (commonpb.Empty);
|
||||
rpc GetBeaconTasks(clientpb.Beacon) returns (clientpb.BeaconTasks);
|
||||
rpc GetBeaconTaskContent(clientpb.BeaconTask) returns (clientpb.BeaconTask);
|
||||
rpc CancelBeaconTask(clientpb.BeaconTask) returns (clientpb.BeaconTask);
|
||||
|
||||
// ***Threat monitoring ***
|
||||
rpc MonitorStart(commonpb.Empty) returns (commonpb.Response);
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc v3.21.5
|
||||
// source: rpcpb/services.proto
|
||||
|
||||
package rpcpb
|
||||
|
||||
@@ -41,6 +37,7 @@ type SliverRPCClient interface {
|
||||
RmBeacon(ctx context.Context, in *clientpb.Beacon, opts ...grpc.CallOption) (*commonpb.Empty, error)
|
||||
GetBeaconTasks(ctx context.Context, in *clientpb.Beacon, opts ...grpc.CallOption) (*clientpb.BeaconTasks, error)
|
||||
GetBeaconTaskContent(ctx context.Context, in *clientpb.BeaconTask, opts ...grpc.CallOption) (*clientpb.BeaconTask, error)
|
||||
CancelBeaconTask(ctx context.Context, in *clientpb.BeaconTask, opts ...grpc.CallOption) (*clientpb.BeaconTask, error)
|
||||
// ***Threat monitoring ***
|
||||
MonitorStart(ctx context.Context, in *commonpb.Empty, opts ...grpc.CallOption) (*commonpb.Response, error)
|
||||
MonitorStop(ctx context.Context, in *commonpb.Empty, opts ...grpc.CallOption) (*commonpb.Empty, error)
|
||||
@@ -279,6 +276,15 @@ func (c *sliverRPCClient) GetBeaconTaskContent(ctx context.Context, in *clientpb
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) CancelBeaconTask(ctx context.Context, in *clientpb.BeaconTask, opts ...grpc.CallOption) (*clientpb.BeaconTask, error) {
|
||||
out := new(clientpb.BeaconTask)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/CancelBeaconTask", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) MonitorStart(ctx context.Context, in *commonpb.Empty, opts ...grpc.CallOption) (*commonpb.Response, error) {
|
||||
out := new(commonpb.Response)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/MonitorStart", in, out, opts...)
|
||||
@@ -1374,6 +1380,7 @@ type SliverRPCServer interface {
|
||||
RmBeacon(context.Context, *clientpb.Beacon) (*commonpb.Empty, error)
|
||||
GetBeaconTasks(context.Context, *clientpb.Beacon) (*clientpb.BeaconTasks, error)
|
||||
GetBeaconTaskContent(context.Context, *clientpb.BeaconTask) (*clientpb.BeaconTask, error)
|
||||
CancelBeaconTask(context.Context, *clientpb.BeaconTask) (*clientpb.BeaconTask, error)
|
||||
// ***Threat monitoring ***
|
||||
MonitorStart(context.Context, *commonpb.Empty) (*commonpb.Response, error)
|
||||
MonitorStop(context.Context, *commonpb.Empty) (*commonpb.Empty, error)
|
||||
@@ -1543,6 +1550,9 @@ func (UnimplementedSliverRPCServer) GetBeaconTasks(context.Context, *clientpb.Be
|
||||
func (UnimplementedSliverRPCServer) GetBeaconTaskContent(context.Context, *clientpb.BeaconTask) (*clientpb.BeaconTask, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetBeaconTaskContent not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) CancelBeaconTask(context.Context, *clientpb.BeaconTask) (*clientpb.BeaconTask, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CancelBeaconTask not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) MonitorStart(context.Context, *commonpb.Empty) (*commonpb.Response, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method MonitorStart not implemented")
|
||||
}
|
||||
@@ -2090,6 +2100,24 @@ func _SliverRPC_GetBeaconTaskContent_Handler(srv interface{}, ctx context.Contex
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_CancelBeaconTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(clientpb.BeaconTask)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).CancelBeaconTask(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/CancelBeaconTask",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).CancelBeaconTask(ctx, req.(*clientpb.BeaconTask))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_MonitorStart_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(commonpb.Empty)
|
||||
if err := dec(in); err != nil {
|
||||
@@ -4176,6 +4204,10 @@ var SliverRPC_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "GetBeaconTaskContent",
|
||||
Handler: _SliverRPC_GetBeaconTaskContent_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "CancelBeaconTask",
|
||||
Handler: _SliverRPC_CancelBeaconTask_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "MonitorStart",
|
||||
Handler: _SliverRPC_MonitorStart_Handler,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.21.5
|
||||
// source: sliverpb/sliver.proto
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ package certs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/bishopfox/sliver/server/log"
|
||||
"golang.org/x/crypto/acme/autocert"
|
||||
@@ -37,7 +37,7 @@ var (
|
||||
|
||||
// GetACMEDir - Dir to store ACME certs
|
||||
func GetACMEDir() string {
|
||||
acmePath := path.Join(getCertDir(), ACMEDirName)
|
||||
acmePath := filepath.Join(getCertDir(), ACMEDirName)
|
||||
if _, err := os.Stat(acmePath); os.IsNotExist(err) {
|
||||
acmeLog.Infof("[mkdir] %s", acmePath)
|
||||
os.MkdirAll(acmePath, 0700)
|
||||
|
||||
+8
-8
@@ -25,7 +25,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/bishopfox/sliver/server/assets"
|
||||
)
|
||||
@@ -44,7 +44,7 @@ func SetupCAs() {
|
||||
|
||||
func getCertDir() string {
|
||||
rootDir := assets.GetRootAppDir()
|
||||
certDir := path.Join(rootDir, "certs")
|
||||
certDir := filepath.Join(rootDir, "certs")
|
||||
if _, err := os.Stat(certDir); os.IsNotExist(err) {
|
||||
err := os.MkdirAll(certDir, 0700)
|
||||
if err != nil {
|
||||
@@ -57,7 +57,7 @@ func getCertDir() string {
|
||||
// GenerateCertificateAuthority - Creates a new CA cert for a given type
|
||||
func GenerateCertificateAuthority(caType string, commonName string) (*x509.Certificate, *ecdsa.PrivateKey) {
|
||||
storageDir := getCertDir()
|
||||
certFilePath := path.Join(storageDir, fmt.Sprintf("%s-ca-cert.pem", caType))
|
||||
certFilePath := filepath.Join(storageDir, fmt.Sprintf("%s-ca-cert.pem", caType))
|
||||
if _, err := os.Stat(certFilePath); os.IsNotExist(err) {
|
||||
certsLog.Infof("Generating certificate authority for '%s'", caType)
|
||||
cert, key := GenerateECCCertificate(caType, commonName, true, false)
|
||||
@@ -104,9 +104,9 @@ func GetCertificateAuthority(caType string) (*x509.Certificate, *ecdsa.PrivateKe
|
||||
|
||||
// GetCertificateAuthorityPEM - Get PEM encoded CA cert/key
|
||||
func GetCertificateAuthorityPEM(caType string) ([]byte, []byte, error) {
|
||||
caType = path.Base(caType)
|
||||
caCertPath := path.Join(getCertDir(), fmt.Sprintf("%s-ca-cert.pem", caType))
|
||||
caKeyPath := path.Join(getCertDir(), fmt.Sprintf("%s-ca-key.pem", caType))
|
||||
caType = filepath.Base(caType)
|
||||
caCertPath := filepath.Join(getCertDir(), fmt.Sprintf("%s-ca-cert.pem", caType))
|
||||
caKeyPath := filepath.Join(getCertDir(), fmt.Sprintf("%s-ca-key.pem", caType))
|
||||
|
||||
certPEM, err := ioutil.ReadFile(caCertPath)
|
||||
if err != nil {
|
||||
@@ -134,8 +134,8 @@ func SaveCertificateAuthority(caType string, cert []byte, key []byte) {
|
||||
|
||||
// CAs get written to the filesystem since we control the names and makes them
|
||||
// easier to move around/backup
|
||||
certFilePath := path.Join(storageDir, fmt.Sprintf("%s-ca-cert.pem", caType))
|
||||
keyFilePath := path.Join(storageDir, fmt.Sprintf("%s-ca-key.pem", caType))
|
||||
certFilePath := filepath.Join(storageDir, fmt.Sprintf("%s-ca-cert.pem", caType))
|
||||
keyFilePath := filepath.Join(storageDir, fmt.Sprintf("%s-ca-key.pem", caType))
|
||||
|
||||
err := ioutil.WriteFile(certFilePath, cert, 0600)
|
||||
if err != nil {
|
||||
|
||||
+23
-10
@@ -31,6 +31,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
insecureRand "math/rand"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
@@ -40,12 +41,6 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// RSAKeySize - Default size of RSA keys in bits
|
||||
RSAKeySize = 2048 // This is plenty 4096 is overkill
|
||||
|
||||
// Certs are valid for ~3 Years, minus up to 1 year from Now()
|
||||
validFor = 3 * (365 * 24 * time.Hour)
|
||||
|
||||
// ECCKey - Namespace for ECC keys
|
||||
ECCKey = "ecc"
|
||||
|
||||
@@ -148,7 +143,9 @@ func GenerateECCCertificate(caType string, commonName string, isCA bool, isClien
|
||||
var err error
|
||||
|
||||
// Generate private key
|
||||
privateKey, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
|
||||
curves := []elliptic.Curve{elliptic.P521(), elliptic.P384(), elliptic.P256()}
|
||||
curve := curves[randomInt(len(curves))]
|
||||
privateKey, err = ecdsa.GenerateKey(curve, rand.Reader)
|
||||
if err != nil {
|
||||
certsLog.Fatalf("Failed to generate private key: %s", err)
|
||||
}
|
||||
@@ -158,7 +155,7 @@ func GenerateECCCertificate(caType string, commonName string, isCA bool, isClien
|
||||
return generateCertificate(caType, subject, isCA, isClient, privateKey)
|
||||
}
|
||||
|
||||
// GenerateRSACertificate - Generates a 2048 bit RSA Certificate
|
||||
// GenerateRSACertificate - Generates an RSA Certificate
|
||||
func GenerateRSACertificate(caType string, commonName string, isCA bool, isClient bool) ([]byte, []byte) {
|
||||
|
||||
certsLog.Debugf("Generating TLS certificate (RSA) for '%s' ...", commonName)
|
||||
@@ -167,7 +164,7 @@ func GenerateRSACertificate(caType string, commonName string, isCA bool, isClien
|
||||
var err error
|
||||
|
||||
// Generate private key
|
||||
privateKey, err = rsa.GenerateKey(rand.Reader, RSAKeySize)
|
||||
privateKey, err = rsa.GenerateKey(rand.Reader, rsaKeySize())
|
||||
if err != nil {
|
||||
certsLog.Fatalf("Failed to generate private key %s", err)
|
||||
}
|
||||
@@ -183,7 +180,7 @@ func generateCertificate(caType string, subject pkix.Name, isCA bool, isClient b
|
||||
notBefore := time.Now()
|
||||
days := randomInt(365) * -1 // Within -1 year
|
||||
notBefore = notBefore.AddDate(0, 0, days)
|
||||
notAfter := notBefore.Add(validFor)
|
||||
notAfter := notBefore.Add(randomValidFor())
|
||||
certsLog.Debugf("Valid from %v to %v", notBefore, notAfter)
|
||||
|
||||
// Serial number
|
||||
@@ -297,3 +294,19 @@ func randomInt(max int) int {
|
||||
i := binary.LittleEndian.Uint32(buf)
|
||||
return int(i) % max
|
||||
}
|
||||
|
||||
func randomValidFor() time.Duration {
|
||||
validFor := 3 * (365 * 24 * time.Hour)
|
||||
switch insecureRand.Intn(2) {
|
||||
case 0:
|
||||
validFor = 2 * (365 * 24 * time.Hour)
|
||||
case 1:
|
||||
validFor = 3 * (365 * 24 * time.Hour)
|
||||
}
|
||||
return validFor
|
||||
}
|
||||
|
||||
func rsaKeySize() int {
|
||||
rsaKeySizes := []int{4096, 2048}
|
||||
return rsaKeySizes[randomInt(len(rsaKeySizes))]
|
||||
}
|
||||
@@ -37,7 +37,7 @@ func HTTPSGenerateRSACertificate(host string) ([]byte, []byte, error) {
|
||||
var err error
|
||||
|
||||
// Generate private key
|
||||
privateKey, err = rsa.GenerateKey(rand.Reader, RSAKeySize)
|
||||
privateKey, err = rsa.GenerateKey(rand.Reader, rsaKeySize())
|
||||
if err != nil {
|
||||
certsLog.Fatalf("Failed to generate private key %s", err)
|
||||
return nil, nil, err
|
||||
|
||||
@@ -66,7 +66,6 @@ func OperatorServerGenerateCertificate(hostname string) ([]byte, []byte, error)
|
||||
|
||||
// OperatorClientListCertificates - Get all client certificates
|
||||
func OperatorClientListCertificates() []*x509.Certificate {
|
||||
|
||||
operatorCerts := []*models.Certificate{}
|
||||
dbSession := db.Session()
|
||||
result := dbSession.Where(&models.Certificate{CAType: OperatorCA}).Find(&operatorCerts)
|
||||
|
||||
+325
-86
@@ -16,6 +16,11 @@ package certs
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Use JARM if you want to fingerprint, don't rely on the subject, its sloppy.
|
||||
|
||||
*/
|
||||
|
||||
import (
|
||||
@@ -23,101 +28,314 @@ import (
|
||||
"fmt"
|
||||
insecureRand "math/rand"
|
||||
"strings"
|
||||
|
||||
"github.com/bishopfox/sliver/server/codenames"
|
||||
)
|
||||
|
||||
var (
|
||||
// State -> Localities -> Street Addresses
|
||||
states = map[string]map[string][]string{
|
||||
"": {
|
||||
"": {""},
|
||||
// Finally found a good use for Github Co-Pilot!
|
||||
// Country -> State -> Localities -> Street Addresses
|
||||
subjects = map[string]map[string]map[string][]string{
|
||||
"US": {
|
||||
"": {
|
||||
"": {
|
||||
"",
|
||||
},
|
||||
},
|
||||
"Arizona": {
|
||||
"Phoenix": {""},
|
||||
"Mesa": {""},
|
||||
"Scottsdale": {""},
|
||||
"Chandler": {""},
|
||||
},
|
||||
"California": {
|
||||
"San Francisco": {"", "", "Golden Gate"},
|
||||
"Oakland": {""},
|
||||
"Berkeley": {""},
|
||||
"Palo Alto": {""},
|
||||
"Los Angeles": {""},
|
||||
"San Diego": {""},
|
||||
"San Jose": {""},
|
||||
"Sunnyvale": {""},
|
||||
"Santa Clara": {""},
|
||||
"Mountain View": {""},
|
||||
"San Mateo": {""},
|
||||
"Redwood City": {""},
|
||||
"Menlo Park": {""},
|
||||
"San Bruno": {""},
|
||||
"San Carlos": {""},
|
||||
"San Leandro": {""},
|
||||
"San Rafael": {""},
|
||||
"San Ramon": {""},
|
||||
"Santa Monica": {""},
|
||||
"Santa Rosa": {""},
|
||||
"South San Francisco": {
|
||||
"",
|
||||
},
|
||||
},
|
||||
"Colorado": {
|
||||
"Denver": {""},
|
||||
"Boulder": {""},
|
||||
"Aurora": {""},
|
||||
"Fort Collins": {""},
|
||||
},
|
||||
"Connecticut": {
|
||||
"New Haven": {""},
|
||||
"Bridgeport": {""},
|
||||
"Stamford": {""},
|
||||
"Norwalk": {""},
|
||||
},
|
||||
"Washington": {
|
||||
"Seattle": {""},
|
||||
"Tacoma": {""},
|
||||
"Olympia": {""},
|
||||
"Spokane": {""},
|
||||
},
|
||||
"Florida": {
|
||||
"Miami": {""},
|
||||
"Orlando": {""},
|
||||
"Tampa": {""},
|
||||
"Jacksonville": {""},
|
||||
},
|
||||
"Illinois": {
|
||||
"Chicago": {""},
|
||||
"Aurora": {""},
|
||||
"Naperville": {""},
|
||||
"Peoria": {""},
|
||||
},
|
||||
"Indiana": {
|
||||
"Indianapolis": {""},
|
||||
"Fort Wayne": {""},
|
||||
"Evansville": {""},
|
||||
"South Bend": {""},
|
||||
},
|
||||
"Massachusetts": {
|
||||
"Boston": {""},
|
||||
"Worcester": {
|
||||
"",
|
||||
"Polytechnic Institute",
|
||||
},
|
||||
"Springfield": {""},
|
||||
"Lowell": {""},
|
||||
},
|
||||
"Michigan": {
|
||||
"Detroit": {""},
|
||||
"Grand Rapids": {
|
||||
"",
|
||||
"State University",
|
||||
},
|
||||
"Warren": {""},
|
||||
"Sterling Heights": {
|
||||
"",
|
||||
"Community College",
|
||||
},
|
||||
},
|
||||
"Minnesota": {
|
||||
"Minneapolis": {""},
|
||||
"Saint Paul": {""},
|
||||
"Bloomington": {""},
|
||||
"Plymouth": {""},
|
||||
},
|
||||
"New Jersey": {
|
||||
"Newark": {""},
|
||||
"Jersey City": {
|
||||
"",
|
||||
"Institute of Technology",
|
||||
},
|
||||
"Paterson": {""},
|
||||
"Elizabeth": {
|
||||
"",
|
||||
"Princeton",
|
||||
},
|
||||
},
|
||||
"New York": {
|
||||
"New York": {""},
|
||||
"Buffalo": {""},
|
||||
"Rochester": {
|
||||
"",
|
||||
"University",
|
||||
},
|
||||
"Yonkers": {""},
|
||||
},
|
||||
"North Carolina": {
|
||||
"Charlotte": {""},
|
||||
"Raleigh": {""},
|
||||
"Greensboro": {
|
||||
"",
|
||||
"University",
|
||||
},
|
||||
"Winston-Salem": {""},
|
||||
},
|
||||
"Ohio": {
|
||||
"Columbus": {""},
|
||||
"Cleveland": {
|
||||
"",
|
||||
"State University",
|
||||
},
|
||||
"Cincinnati": {""},
|
||||
"Toledo": {""},
|
||||
},
|
||||
},
|
||||
"Arizona": {
|
||||
"Phoenix": {""},
|
||||
"Mesa": {""},
|
||||
"Scottsdale": {""},
|
||||
"Chandler": {""},
|
||||
"CA": {
|
||||
"": {
|
||||
"": {
|
||||
"",
|
||||
},
|
||||
},
|
||||
"Alberta": {
|
||||
"Calgary": {""},
|
||||
"Edmonton": {
|
||||
"",
|
||||
"University",
|
||||
},
|
||||
"Red Deer": {""},
|
||||
"Fort McMurray": {
|
||||
"",
|
||||
"University",
|
||||
},
|
||||
},
|
||||
"British Columbia": {
|
||||
"Vancouver": {""},
|
||||
"Victoria": {""},
|
||||
"Kelowna": {""},
|
||||
"Richmond": {""},
|
||||
},
|
||||
"Manitoba": {
|
||||
"Winnipeg": {""},
|
||||
"Brandon": {""},
|
||||
"Thompson": {""},
|
||||
"Portage la Prairie": {
|
||||
"",
|
||||
"University",
|
||||
},
|
||||
},
|
||||
"New Brunswick": {
|
||||
"Fredericton": {""},
|
||||
"Moncton": {""},
|
||||
"Saint John": {""},
|
||||
"Dieppe": {""},
|
||||
},
|
||||
"Newfoundland and Labrador": {
|
||||
"St. John's": {""},
|
||||
"Mount Pearl": {
|
||||
"",
|
||||
"College",
|
||||
},
|
||||
"Conception Bay South": {""},
|
||||
"Paradise": {
|
||||
"",
|
||||
"College",
|
||||
},
|
||||
},
|
||||
},
|
||||
"California": {
|
||||
"San Francisco": {"", "Golden Gate Bridge"},
|
||||
"Oakland": {""},
|
||||
"Berkeley": {""},
|
||||
"Palo Alto": {""},
|
||||
"Los Angeles": {""},
|
||||
"San Diego": {""},
|
||||
"San Jose": {""},
|
||||
},
|
||||
"Colorado": {
|
||||
"Denver": {""},
|
||||
"Boulder": {""},
|
||||
"Aurora": {""},
|
||||
"Fort Collins": {""},
|
||||
},
|
||||
"Connecticut": {
|
||||
"New Haven": {""},
|
||||
"Bridgeport": {""},
|
||||
"Stamford": {""},
|
||||
"Norwalk": {""},
|
||||
},
|
||||
"Washington": {
|
||||
"Seattle": {""},
|
||||
"Tacoma": {""},
|
||||
"Olympia": {""},
|
||||
"Spokane": {""},
|
||||
},
|
||||
"Florida": {
|
||||
"Miami": {""},
|
||||
"Orlando": {""},
|
||||
"Tampa": {""},
|
||||
"Jacksonville": {""},
|
||||
},
|
||||
"Illinois": {
|
||||
"Chicago": {""},
|
||||
"Aurora": {""},
|
||||
"Naperville": {""},
|
||||
"Peoria": {""},
|
||||
"JP": {
|
||||
"": {
|
||||
"": {
|
||||
"",
|
||||
},
|
||||
},
|
||||
"Aichi": {
|
||||
"Nagoya": {""},
|
||||
"Kasugai": {
|
||||
"",
|
||||
"University",
|
||||
},
|
||||
"Okazaki": {""},
|
||||
"Handa": {""},
|
||||
},
|
||||
"Chiba": {
|
||||
"Chiba": {""},
|
||||
"Kashiwa": {
|
||||
"",
|
||||
"University",
|
||||
},
|
||||
"Funabashi": {""},
|
||||
"Kimitsu": {""},
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func randomSubject(commonName string) *pkix.Name {
|
||||
province, locale, street := randomProvinceLocalityStreetAddress()
|
||||
country, province, locale, street := randomProvinceLocalityStreetAddress()
|
||||
return &pkix.Name{
|
||||
Organization: randomOrganization(),
|
||||
Country: []string{"US"},
|
||||
Country: country,
|
||||
Province: province,
|
||||
Locality: locale,
|
||||
StreetAddress: street,
|
||||
PostalCode: randomPostalCode(),
|
||||
PostalCode: randomPostalCode(country),
|
||||
CommonName: commonName,
|
||||
}
|
||||
}
|
||||
|
||||
func randomPostalCode() []string {
|
||||
switch insecureRand.Intn(1) {
|
||||
case 0:
|
||||
return []string{fmt.Sprintf("%d", insecureRand.Intn(8000)+1000)}
|
||||
default:
|
||||
func randomPostalCode(country []string) []string {
|
||||
// 1 in `n` will include a postal code
|
||||
// From my cursory view of a few TLS certs it seems uncommon to include this
|
||||
// in the distinguished name so right now it's set to 1/5
|
||||
const postalProbability = 5
|
||||
|
||||
if len(country) == 0 {
|
||||
return []string{}
|
||||
}
|
||||
switch country[0] {
|
||||
|
||||
case "US":
|
||||
// American postal codes are 5 digits
|
||||
switch insecureRand.Intn(postalProbability) {
|
||||
case 0:
|
||||
return []string{fmt.Sprintf("%05d", insecureRand.Intn(90000)+1000)}
|
||||
default:
|
||||
return []string{}
|
||||
}
|
||||
|
||||
case "CA":
|
||||
// Canadian postal codes are weird and include letter/number combo's
|
||||
letters := "ABHLMNKGJPRSTVYX"
|
||||
switch insecureRand.Intn(postalProbability) {
|
||||
case 0:
|
||||
letter1 := string(letters[insecureRand.Intn(len(letters))])
|
||||
letter2 := string(letters[insecureRand.Intn(len(letters))])
|
||||
if insecureRand.Intn(2) == 0 {
|
||||
letter1 = strings.ToLower(letter1)
|
||||
letter2 = strings.ToLower(letter2)
|
||||
}
|
||||
return []string{
|
||||
fmt.Sprintf("%s%d%s", letter1, insecureRand.Intn(9), letter2),
|
||||
}
|
||||
default:
|
||||
return []string{}
|
||||
}
|
||||
}
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func randomProvinceLocalityStreetAddress() ([]string, []string, []string) {
|
||||
state := randomState()
|
||||
locality := randomLocality(state)
|
||||
streetAddress := randomStreetAddress(state, locality)
|
||||
return []string{state}, []string{locality}, []string{streetAddress}
|
||||
func randomProvinceLocalityStreetAddress() ([]string, []string, []string, []string) {
|
||||
country := randomCountry()
|
||||
state := randomState(country)
|
||||
locality := randomLocality(country, state)
|
||||
streetAddress := randomStreetAddress(country, state, locality)
|
||||
return []string{country}, []string{state}, []string{locality}, []string{streetAddress}
|
||||
}
|
||||
|
||||
func randomState() string {
|
||||
keys := make([]string, 0, len(states))
|
||||
for k := range states {
|
||||
func randomCountry() string {
|
||||
keys := make([]string, 0, len(subjects))
|
||||
for k := range subjects {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
return keys[insecureRand.Intn(len(keys))]
|
||||
}
|
||||
|
||||
func randomLocality(state string) string {
|
||||
locales := states[state]
|
||||
func randomState(country string) string {
|
||||
keys := make([]string, 0, len(subjects[country]))
|
||||
for k := range subjects[country] {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
return keys[insecureRand.Intn(len(keys))]
|
||||
}
|
||||
|
||||
func randomLocality(country string, state string) string {
|
||||
locales := subjects[country][state]
|
||||
keys := make([]string, 0, len(locales))
|
||||
for k := range locales {
|
||||
keys = append(keys, k)
|
||||
@@ -125,44 +343,65 @@ func randomLocality(state string) string {
|
||||
return keys[insecureRand.Intn(len(keys))]
|
||||
}
|
||||
|
||||
func randomStreetAddress(state string, locality string) string {
|
||||
addresses := states[state][locality]
|
||||
func randomStreetAddress(country string, state string, locality string) string {
|
||||
addresses := subjects[country][state][locality]
|
||||
return addresses[insecureRand.Intn(len(addresses))]
|
||||
}
|
||||
|
||||
var (
|
||||
orgNames = []string{
|
||||
"",
|
||||
"ACME",
|
||||
"Partners",
|
||||
"Tech",
|
||||
"Cloud",
|
||||
"Synergy",
|
||||
"Test",
|
||||
"Debug",
|
||||
}
|
||||
orgSuffixes = []string{
|
||||
"",
|
||||
"",
|
||||
"co",
|
||||
"llc",
|
||||
"inc",
|
||||
"corp",
|
||||
"ltd",
|
||||
"plc",
|
||||
"inc.",
|
||||
"corp.",
|
||||
"ltd.",
|
||||
"plc.",
|
||||
"co.",
|
||||
"llc.",
|
||||
"incorporated",
|
||||
"limited",
|
||||
"corporation",
|
||||
"company",
|
||||
"incorporated",
|
||||
"limited",
|
||||
"corporation",
|
||||
"company",
|
||||
}
|
||||
)
|
||||
|
||||
func randomOrganization() []string {
|
||||
name := orgNames[insecureRand.Intn(len(orgNames))]
|
||||
adjective, _ := codenames.RandomAdjective()
|
||||
noun, _ := codenames.RandomNoun()
|
||||
suffix := orgSuffixes[insecureRand.Intn(len(orgSuffixes))]
|
||||
switch insecureRand.Intn(4) {
|
||||
case 0:
|
||||
return []string{strings.TrimSpace(strings.ToLower(name + " " + suffix))}
|
||||
case 1:
|
||||
return []string{strings.TrimSpace(strings.ToUpper(name + " " + suffix))}
|
||||
case 2:
|
||||
return []string{strings.TrimSpace(strings.Title(fmt.Sprintf("%s %s", name, suffix)))}
|
||||
|
||||
var orgName string
|
||||
switch insecureRand.Intn(8) {
|
||||
case 0:
|
||||
orgName = strings.TrimSpace(fmt.Sprintf("%s %s, %s", adjective, noun, suffix))
|
||||
case 1:
|
||||
orgName = strings.TrimSpace(strings.ToLower(fmt.Sprintf("%s %s, %s", adjective, noun, suffix)))
|
||||
case 2:
|
||||
orgName = strings.TrimSpace(fmt.Sprintf("%s, %s", noun, suffix))
|
||||
case 3:
|
||||
orgName = strings.TrimSpace(strings.Title(fmt.Sprintf("%s %s, %s", adjective, noun, suffix)))
|
||||
case 4:
|
||||
orgName = strings.TrimSpace(strings.Title(fmt.Sprintf("%s %s", adjective, noun)))
|
||||
case 5:
|
||||
orgName = strings.TrimSpace(strings.ToLower(fmt.Sprintf("%s %s", adjective, noun)))
|
||||
case 6:
|
||||
orgName = strings.TrimSpace(strings.Title(fmt.Sprintf("%s", noun)))
|
||||
case 7:
|
||||
noun2, _ := codenames.RandomNoun()
|
||||
orgName = strings.TrimSpace(strings.ToLower(fmt.Sprintf("%s-%s", noun, noun2)))
|
||||
default:
|
||||
return []string{}
|
||||
orgName = ""
|
||||
}
|
||||
|
||||
return []string{orgName}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package generate
|
||||
package codenames
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
"fmt"
|
||||
insecureRand "math/rand"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/bishopfox/sliver/server/assets"
|
||||
@@ -39,11 +39,11 @@ var (
|
||||
})
|
||||
)
|
||||
|
||||
// readlines - Read lines of a text file into a slice
|
||||
func readlines(fpath string) ([]string, error) {
|
||||
file, err := os.Open(fpath)
|
||||
// readLines - Read lines of a text file into a slice
|
||||
func readLines(txtFilePath string) ([]string, error) {
|
||||
file, err := os.Open(txtFilePath)
|
||||
if err != nil {
|
||||
codenameLog.Errorf("Error opening %s: %v", fpath, err)
|
||||
codenameLog.Errorf("Error opening %s: %v", txtFilePath, err)
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
@@ -63,37 +63,37 @@ func readlines(fpath string) ([]string, error) {
|
||||
}
|
||||
|
||||
// getRandomWord - Get a random word from a file, not cryptographically secure
|
||||
func getRandomWord(fpath string) (string, error) {
|
||||
func getRandomWord(txtFilePath string) (string, error) {
|
||||
appDir := assets.GetRootAppDir()
|
||||
words, err := readlines(path.Join(appDir, fpath))
|
||||
words, err := readLines(filepath.Join(appDir, txtFilePath))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wordsLen := len(words)
|
||||
if wordsLen == 0 {
|
||||
return "", fmt.Errorf("no words found in %s", fpath)
|
||||
return "", fmt.Errorf("no words found in %s", txtFilePath)
|
||||
}
|
||||
word := words[insecureRand.Intn(wordsLen-1)]
|
||||
return strings.TrimSpace(word), nil
|
||||
}
|
||||
|
||||
// getRandomAdjective - Get a random noun, not cryptographically secure
|
||||
func getRandomAdjective() (string, error) {
|
||||
// RandomAdjective - Get a random noun, not cryptographically secure
|
||||
func RandomAdjective() (string, error) {
|
||||
return getRandomWord("adjectives.txt")
|
||||
}
|
||||
|
||||
// getRandomNoun - Get a random noun, not cryptographically secure
|
||||
func getRandomNoun() (string, error) {
|
||||
// RandomNoun - Get a random noun, not cryptographically secure
|
||||
func RandomNoun() (string, error) {
|
||||
return getRandomWord("nouns.txt")
|
||||
}
|
||||
|
||||
// GetCodename - Returns a randomly generated 'codename'
|
||||
func GetCodename() (string, error) {
|
||||
adjective, err := getRandomAdjective()
|
||||
adjective, err := RandomAdjective()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
noun, err := getRandomNoun()
|
||||
noun, err := RandomNoun()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -35,7 +35,8 @@ import (
|
||||
|
||||
const (
|
||||
httpC2ConfigFileName = "http-c2.json"
|
||||
chromeBaseVer = 97
|
||||
DefaultChromeBaseVer = 100
|
||||
DefaultMacOSVer = "10_15_7"
|
||||
)
|
||||
|
||||
// HTTPC2Config - Parent config file struct for implant/server
|
||||
@@ -69,7 +70,7 @@ func (h *HTTPC2Config) generateChromeUserAgent(goos string, goarch string) strin
|
||||
case "arm64":
|
||||
fallthrough // https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/core/frame/navigator_id.cc;l=76
|
||||
case "amd64":
|
||||
return fmt.Sprintf("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Safari/537.36", h.ChromeVer())
|
||||
return fmt.Sprintf("Mozilla/5.0 (Macintosh; Intel Mac OS X %s) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Safari/537.36", h.MacOSVer(), h.ChromeVer())
|
||||
}
|
||||
|
||||
}
|
||||
@@ -83,7 +84,19 @@ func (h *HTTPC2Config) generateChromeUserAgent(goos string, goarch string) strin
|
||||
|
||||
// ChromeVer - Generate a random Chrome user-agent
|
||||
func (h *HTTPC2Config) ChromeVer() string {
|
||||
return fmt.Sprintf("%d.0.%d.%d", chromeBaseVer+insecureRand.Intn(3), 1000+insecureRand.Intn(8999), insecureRand.Intn(999))
|
||||
chromeVer := h.ImplantConfig.ChromeBaseVersion
|
||||
if chromeVer == 0 {
|
||||
chromeVer = DefaultChromeBaseVer
|
||||
}
|
||||
return fmt.Sprintf("%d.0.%d.%d", chromeVer+insecureRand.Intn(3), 1000+insecureRand.Intn(8999), insecureRand.Intn(999))
|
||||
}
|
||||
|
||||
func (h *HTTPC2Config) MacOSVer() string {
|
||||
macosVer := h.ImplantConfig.MacOSVersion
|
||||
if macosVer == "" {
|
||||
macosVer = DefaultMacOSVer
|
||||
}
|
||||
return macosVer
|
||||
}
|
||||
|
||||
// RandomImplantConfig - Randomly generate a config
|
||||
@@ -126,7 +139,9 @@ type NameValueProbability struct {
|
||||
// .png = stop
|
||||
// .woff = sliver shellcode
|
||||
type HTTPC2ImplantConfig struct {
|
||||
UserAgent string `json:"user_agent"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
ChromeBaseVersion int `json:"chrome_base_version"`
|
||||
MacOSVersion string `json:"macos_version"`
|
||||
|
||||
URLParameters []NameValueProbability `json:"url_parameters"`
|
||||
Headers []NameValueProbability `json:"headers"`
|
||||
@@ -222,11 +237,13 @@ var (
|
||||
},
|
||||
},
|
||||
ImplantConfig: &HTTPC2ImplantConfig{
|
||||
UserAgent: "", // Blank string is rendered as randomized platform user-agent
|
||||
MaxFiles: 8,
|
||||
MinFiles: 2,
|
||||
MaxPaths: 8,
|
||||
MinPaths: 2,
|
||||
UserAgent: "", // Blank string is rendered as randomized platform user-agent
|
||||
ChromeBaseVersion: DefaultChromeBaseVer,
|
||||
MacOSVersion: DefaultMacOSVer,
|
||||
MaxFiles: 8,
|
||||
MinFiles: 2,
|
||||
MaxPaths: 8,
|
||||
MinPaths: 2,
|
||||
|
||||
StagerFileExt: ".woff",
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// TunSocksTunnels - Interating with duplex SocksTunnels
|
||||
// TunSocksTunnels - Interacting with duplex SocksTunnels
|
||||
SocksTunnels = tcpTunnel{
|
||||
tunnels: map[uint64]*TcpTunnel{},
|
||||
mutex: &sync.Mutex{},
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// Tunnels - Interating with duplex tunnels
|
||||
// Tunnels - Interacting with duplex tunnels
|
||||
Tunnels = tunnels{
|
||||
tunnels: map[uint64]*Tunnel{},
|
||||
mutex: &sync.Mutex{},
|
||||
@@ -125,10 +125,10 @@ func (t *tunnels) Create(sessionID string) *Tunnel {
|
||||
// will close it once there is no data for at least delayBeforeClose delay since last message
|
||||
// This is _necessary_ since we processing messages asynchronously
|
||||
// and if tunnelCloseHandler routine will fire before tunnelDataHandler routine we will lose some data
|
||||
// (this is what happends for socks and portfwd)
|
||||
// (this is what happens for socks and portfwd)
|
||||
// There is no another way around it, if we want to stick to async processing as we do now.
|
||||
// All additional changes requires changes on implants(like sequencing for close messages),
|
||||
// and as there is a goal to keep compatability we don't do that at the moment.
|
||||
// and as there is a goal to keep compatibility we don't do that at the moment.
|
||||
// So there is trade off - more stability or more speed. Or rewriting implant logic.
|
||||
// At the moment, i see it affects only `shell` command and locking it for 10 seconds on exit. Not a big deal.
|
||||
func (t *tunnels) ScheduleClose(tunnelID uint64) {
|
||||
@@ -153,7 +153,7 @@ func (t *tunnels) ScheduleClose(tunnelID uint64) {
|
||||
}
|
||||
|
||||
// Close - closing tunnel
|
||||
// It's prefered to use ScheduleClose function if you don't 100% sure there is no more data to receive
|
||||
// It's preferred to use ScheduleClose function if you don't 100% sure there is no more data to receive
|
||||
func (t *tunnels) Close(tunnelID uint64) error {
|
||||
t.mutex.Lock()
|
||||
defer t.mutex.Unlock()
|
||||
|
||||
@@ -112,6 +112,7 @@ const (
|
||||
PENDING = "pending"
|
||||
SENT = "sent"
|
||||
COMPLETED = "completed"
|
||||
CANCELED = "canceled"
|
||||
)
|
||||
|
||||
type BeaconTask struct {
|
||||
|
||||
@@ -111,7 +111,7 @@ func tunnelDataHandler(implantConn *core.ImplantConnection, data []byte) *sliver
|
||||
tunnelData := &sliverpb.TunnelData{}
|
||||
proto.Unmarshal(data, tunnelData)
|
||||
|
||||
sessionHandlerLog.Debugf("[DATA] Sequence on tunel %d, %d, data: %s", tunnelData.TunnelID, tunnelData.Sequence, tunnelData.Data)
|
||||
sessionHandlerLog.Debugf("[DATA] Sequence on tunnel %d, %d, data: %s", tunnelData.TunnelID, tunnelData.Sequence, tunnelData.Data)
|
||||
|
||||
tunnel := core.Tunnels.Get(tunnelData.TunnelID)
|
||||
if tunnel != nil {
|
||||
@@ -137,7 +137,7 @@ func tunnelCloseHandler(implantConn *core.ImplantConnection, data []byte) *slive
|
||||
|
||||
tunnelData := &sliverpb.TunnelData{}
|
||||
proto.Unmarshal(data, tunnelData)
|
||||
sessionHandlerLog.Debugf("[CLOSE] Sequence on tunel %d, %d, data: %s", tunnelData.TunnelID, tunnelData.Sequence, tunnelData.Data)
|
||||
sessionHandlerLog.Debugf("[CLOSE] Sequence on tunnel %d, %d, data: %s", tunnelData.TunnelID, tunnelData.Sequence, tunnelData.Data)
|
||||
if !tunnelData.Closed {
|
||||
return nil
|
||||
}
|
||||
@@ -181,10 +181,10 @@ func socksDataHandler(implantConn *core.ImplantConnection, data []byte) *sliverp
|
||||
// return nil
|
||||
//}
|
||||
sessionHandlerLog.Debugf("socksDataHandler:", len(socksData.Data), socksData.Data)
|
||||
SocksTunne := core.SocksTunnels.Get(socksData.TunnelID)
|
||||
if SocksTunne != nil {
|
||||
if session.ID == SocksTunne.SessionID {
|
||||
SocksTunne.FromImplant <- socksData
|
||||
socksTunnel := core.SocksTunnels.Get(socksData.TunnelID)
|
||||
if socksTunnel != nil {
|
||||
if session.ID == socksTunnel.SessionID {
|
||||
socksTunnel.FromImplant <- socksData
|
||||
} else {
|
||||
sessionHandlerLog.Warnf("Warning: Session %s attempted to send data on tunnel it did not own", session.ID)
|
||||
}
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ package log
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -34,7 +34,7 @@ var (
|
||||
func newAuditLogger() *logrus.Logger {
|
||||
auditLogger := logrus.New()
|
||||
auditLogger.Formatter = &logrus.JSONFormatter{}
|
||||
jsonFilePath := path.Join(GetLogDir(), "audit.json")
|
||||
jsonFilePath := filepath.Join(GetLogDir(), "audit.json")
|
||||
jsonFile, err := os.OpenFile(jsonFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to open log file %v", err))
|
||||
|
||||
@@ -19,6 +19,9 @@ package rpc
|
||||
*/
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/bishopfox/sliver/server/db/models"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
@@ -41,4 +44,6 @@ var (
|
||||
|
||||
// ErrInvalidName - Invalid name
|
||||
ErrInvalidName = status.Error(codes.InvalidArgument, "Invalid session name, alphanumerics and _-. only")
|
||||
|
||||
ErrInvalidBeaconTaskCancelState = status.Error(codes.InvalidArgument, fmt.Sprintf("Invalid task state, must be '%s' to cancel", models.PENDING))
|
||||
)
|
||||
@@ -107,3 +107,27 @@ func (rpc *Server) GetBeaconTaskContent(ctx context.Context, req *clientpb.Beaco
|
||||
}
|
||||
return task.ToProtobuf(true), nil
|
||||
}
|
||||
|
||||
// CancelBeaconTask - Cancel a beacon task
|
||||
func (rpc *Server) CancelBeaconTask(ctx context.Context, req *clientpb.BeaconTask) (*clientpb.BeaconTask, error) {
|
||||
task, err := db.BeaconTaskByID(req.ID)
|
||||
if err != nil {
|
||||
return nil, ErrInvalidBeaconTaskID
|
||||
}
|
||||
if task.State == models.PENDING {
|
||||
task.State = models.CANCELED
|
||||
err = db.Session().Save(task).Error
|
||||
if err != nil {
|
||||
beaconRpcLog.Errorf("Database error: %s", err)
|
||||
return nil, ErrDatabaseFailure
|
||||
}
|
||||
} else {
|
||||
// No real point to cancel the task if it's already been sent
|
||||
return task.ToProtobuf(false), ErrInvalidBeaconTaskCancelState
|
||||
}
|
||||
task, err = db.BeaconTaskByID(req.ID)
|
||||
if err != nil {
|
||||
return nil, ErrInvalidBeaconTaskID
|
||||
}
|
||||
return task.ToProtobuf(false), nil
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
consts "github.com/bishopfox/sliver/client/constants"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/server/codenames"
|
||||
"github.com/bishopfox/sliver/server/core"
|
||||
"github.com/bishopfox/sliver/server/db"
|
||||
"github.com/bishopfox/sliver/server/generate"
|
||||
@@ -46,7 +47,7 @@ func (rpc *Server) Generate(ctx context.Context, req *clientpb.GenerateReq) (*cl
|
||||
var err error
|
||||
name, config := generate.ImplantConfigFromProtobuf(req.Config)
|
||||
if name == "" {
|
||||
name, err = generate.GetCodename()
|
||||
name, err = codenames.GetCodename()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import (
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/server/codenames"
|
||||
"github.com/bishopfox/sliver/server/core"
|
||||
"github.com/bishopfox/sliver/server/generate"
|
||||
"github.com/bishopfox/sliver/util/encoders"
|
||||
@@ -107,7 +108,7 @@ func (rpc *Server) HijackDLL(ctx context.Context, req *clientpb.DllHijackReq) (*
|
||||
|
||||
name, config := generate.ImplantConfigFromProtobuf(p.Config)
|
||||
if name == "" {
|
||||
name, err = generate.GetCodename()
|
||||
name, err = codenames.GetCodename()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// Kill - Kill the implant proccess
|
||||
// Kill - Kill the implant process
|
||||
func (rpc *Server) Kill(ctx context.Context, kill *sliverpb.KillReq) (*commonpb.Empty, error) {
|
||||
var (
|
||||
beacon *models.Beacon
|
||||
@@ -55,7 +55,9 @@ func (rpc *Server) killSession(kill *sliverpb.KillReq, session *core.Session) (*
|
||||
return nil, err
|
||||
}
|
||||
timeout := time.Duration(kill.Request.GetTimeout())
|
||||
session.Request(sliverpb.MsgNumber(kill), timeout, data)
|
||||
// Do not block waiting for the msg send, the implant connection may already be dead
|
||||
go session.Request(sliverpb.MsgNumber(kill), timeout, data)
|
||||
core.Sessions.Remove(session.ID)
|
||||
return &commonpb.Empty{}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -29,9 +29,9 @@ import (
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/server/codenames"
|
||||
"github.com/bishopfox/sliver/server/core"
|
||||
"github.com/bishopfox/sliver/server/db"
|
||||
"github.com/bishopfox/sliver/server/generate"
|
||||
"github.com/bishopfox/sliver/server/log"
|
||||
"github.com/bishopfox/sliver/server/msf"
|
||||
)
|
||||
@@ -197,7 +197,7 @@ func (rpc *Server) MsfStage(ctx context.Context, req *clientpb.MsfStagerReq) (*c
|
||||
return MSFStage, err
|
||||
}
|
||||
MSFStage.File.Data = stage
|
||||
name, err := generate.GetCodename()
|
||||
name, err := codenames.GetCodename()
|
||||
if err != nil {
|
||||
return MSFStage, err
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/server/codenames"
|
||||
"github.com/bishopfox/sliver/server/core"
|
||||
"github.com/bishopfox/sliver/server/generate"
|
||||
|
||||
@@ -85,7 +86,7 @@ func (rpc *Server) GetSystem(ctx context.Context, req *clientpb.GetSystemReq) (*
|
||||
if err != nil {
|
||||
name, config := generate.ImplantConfigFromProtobuf(req.Config)
|
||||
if name == "" {
|
||||
name, err = generate.GetCodename()
|
||||
name, err = codenames.GetCodename()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/server/codenames"
|
||||
"github.com/bishopfox/sliver/server/core"
|
||||
"github.com/bishopfox/sliver/server/db"
|
||||
"github.com/bishopfox/sliver/server/db/models"
|
||||
@@ -66,7 +67,7 @@ func (rpc *Server) Migrate(ctx context.Context, req *clientpb.MigrateReq) (*sliv
|
||||
if err != nil {
|
||||
name, config := generate.ImplantConfigFromProtobuf(req.Config)
|
||||
if name == "" {
|
||||
name, err = generate.GetCodename()
|
||||
name, err = codenames.GetCodename()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
package sgn
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2022 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
|
||||
@@ -23,10 +23,11 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/server/configs"
|
||||
"github.com/bishopfox/sliver/server/core"
|
||||
"github.com/bishopfox/sliver/server/db"
|
||||
"github.com/bishopfox/sliver/server/log"
|
||||
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
|
||||
@@ -41,6 +42,8 @@ import (
|
||||
|
||||
var (
|
||||
serverConfig = configs.GetServerConfig()
|
||||
|
||||
middlewareLog = log.NamedLogger("transport", "middleware")
|
||||
)
|
||||
|
||||
// initMiddleware - Initialize middleware logger
|
||||
@@ -126,9 +129,6 @@ func tokenAuthFunc(ctx context.Context) (context.Context, error) {
|
||||
mtlsLog.Debugf("Valid user token for %s", operator.Name)
|
||||
tokenCache.Store(token, operator.Name)
|
||||
|
||||
// grpc_ctxtags.Extract(ctx).Set("auth.sub", userClaimFromToken(tokenInfo))
|
||||
// WARNING: in production define your own type to avoid context collisions
|
||||
|
||||
newCtx = context.WithValue(newCtx, "operator", operator.Name)
|
||||
return newCtx, nil
|
||||
}
|
||||
@@ -186,26 +186,84 @@ func codeToLevel(code codes.Code) logrus.Level {
|
||||
type auditUnaryLogMsg struct {
|
||||
Request string `json:"request"`
|
||||
Method string `json:"method"`
|
||||
Session string `json:"session,omitempty"`
|
||||
Beacon string `json:"beacon,omitempty"`
|
||||
}
|
||||
|
||||
func auditLogUnaryServerInterceptor() grpc.UnaryServerInterceptor {
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (_ interface{}, err error) {
|
||||
var request string
|
||||
rawRequest, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
log.AuditLogger.Errorf("Failed to serialize %s", err)
|
||||
request = fmt.Sprintf("%v", req)
|
||||
} else {
|
||||
request = string(rawRequest)
|
||||
middlewareLog.Errorf("Failed to serialize %s", err)
|
||||
return
|
||||
}
|
||||
middlewareLog.Debugf("Raw request: %s", string(rawRequest))
|
||||
session, beacon, err := getActiveTarget(rawRequest)
|
||||
if err != nil {
|
||||
middlewareLog.Errorf("Middleware failed to insert details: %s", err)
|
||||
}
|
||||
|
||||
msg, _ := json.Marshal(&auditUnaryLogMsg{
|
||||
Request: request,
|
||||
// Construct Log Message
|
||||
msg := &auditUnaryLogMsg{
|
||||
Request: string(rawRequest),
|
||||
Method: info.FullMethod,
|
||||
})
|
||||
log.AuditLogger.Info(string(msg))
|
||||
}
|
||||
if session != nil {
|
||||
sessionJSON, _ := json.Marshal(session)
|
||||
msg.Session = string(sessionJSON)
|
||||
}
|
||||
if beacon != nil {
|
||||
beaconJSON, _ := json.Marshal(beacon)
|
||||
msg.Beacon = string(beaconJSON)
|
||||
}
|
||||
|
||||
msgData, _ := json.Marshal(msg)
|
||||
log.AuditLogger.Info(string(msgData))
|
||||
|
||||
resp, err := handler(ctx, req)
|
||||
return resp, err
|
||||
}
|
||||
}
|
||||
|
||||
func getActiveTarget(rawRequest []byte) (*clientpb.Session, *clientpb.Beacon, error) {
|
||||
|
||||
var activeBeacon *clientpb.Beacon
|
||||
var activeSession *clientpb.Session
|
||||
|
||||
var request map[string]interface{}
|
||||
err := json.Unmarshal(rawRequest, &request)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// RPC is not a session/beacon request
|
||||
if _, ok := request["Request"]; !ok {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
rpcRequest := request["Request"].(map[string]interface{})
|
||||
|
||||
middlewareLog.Debugf("RPC Request: %v", rpcRequest)
|
||||
|
||||
if rawBeaconID, ok := rpcRequest["BeaconID"]; ok {
|
||||
beaconID := rawBeaconID.(string)
|
||||
middlewareLog.Debugf("Found Beacon ID: %s", beaconID)
|
||||
beacon, err := db.BeaconByID(beaconID)
|
||||
if err != nil {
|
||||
middlewareLog.Errorf("Failed to get beacon %s: %s", beaconID, err)
|
||||
} else if beacon != nil {
|
||||
activeBeacon = beacon.ToProtobuf()
|
||||
}
|
||||
}
|
||||
|
||||
if rawSessionID, ok := rpcRequest["SessionID"]; ok {
|
||||
sessionID := rawSessionID.(string)
|
||||
middlewareLog.Debugf("Found Session ID: %s", sessionID)
|
||||
session := core.Sessions.Get(sessionID)
|
||||
if session != nil {
|
||||
activeSession = session.ToProtobuf()
|
||||
}
|
||||
}
|
||||
|
||||
return activeSession, activeBeacon, nil
|
||||
}
|
||||
@@ -21,6 +21,7 @@ package website
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -72,9 +73,14 @@ func GetContent(websiteName string, path string) (string, []byte, error) {
|
||||
|
||||
dbSession := db.Session()
|
||||
content := models.WebContent{}
|
||||
// Use path without any query parameters
|
||||
u, err := url.Parse(path)
|
||||
if err != nil {
|
||||
return "", []byte{}, err
|
||||
}
|
||||
result := dbSession.Where(&models.WebContent{
|
||||
WebsiteID: website.ID,
|
||||
Path: path,
|
||||
Path: u.Path,
|
||||
}).First(&content)
|
||||
if result.Error != nil {
|
||||
return "", []byte{}, result.Error
|
||||
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.12
|
||||
|
||||
os:
|
||||
- linux
|
||||
- linux-ppc64le
|
||||
- osx
|
||||
- windows
|
||||
|
||||
go_import_path: github.com/AlecAivazis/survey/v2
|
||||
|
||||
before_install:
|
||||
- go get github.com/alecaivazis/run
|
||||
|
||||
install:
|
||||
- run install-deps
|
||||
|
||||
script:
|
||||
- run tests
|
||||
# - run autoplay-tests
|
||||
+9
-31
@@ -4,48 +4,26 @@
|
||||
|
||||
The following is a set of guidelines to follow when contributing to this package. These are not hard rules, please use common sense and feel free to propose changes to this document in a pull request.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Code of Conduct](#code-of-conduct)
|
||||
1. [Getting Help](#getting-help)
|
||||
1. [Filing a Bug Report](#how-to-file-a-bug-report)
|
||||
1. [Suggesting an API change](#suggesting-an-api-change)
|
||||
1. [Submitting a Contribution](#submitting-a-contribution)
|
||||
1. [Writing and Running Tests](#writing-and-running-tests)
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project and its contibutors are expected to uphold the [Go Community Code of Conduct](https://golang.org/conduct). By participating, you are expected to follow these guidelines.
|
||||
|
||||
## Getting help
|
||||
|
||||
Feel free to [open up an issue](https://github.com/AlecAivazis/survey/v2/issues/new) on GitHub when asking a question so others will be able to find it. Please remember to tag the issue with the `Question` label so the maintainers can get to your question as soon as possible. If the question is urgent, feel free to reach out to `@AlecAivazis` directly in the gophers slack channel.
|
||||
|
||||
## How to file a bug report
|
||||
|
||||
Bugs are tracked using the Github Issue tracker. When filing a bug, please remember to label the issue as a `Bug` and answer/provide the following:
|
||||
|
||||
1. What operating system and terminal are you using?
|
||||
1. An example that showcases the bug.
|
||||
1. What did you expect to see?
|
||||
1. What did you see instead?
|
||||
|
||||
## Suggesting an API change
|
||||
|
||||
If you have an idea, I'm more than happy to discuss it. Please open an issue and we can work through it. In order to maintain some sense of stability, additions to the top-level API are taken just as seriously as changes that break it. Adding stuff is much easier than removing it.
|
||||
* [Open an issue](https://github.com/AlecAivazis/survey/issues/new/choose)
|
||||
* Reach out to `@AlecAivazis` or `@mislav` in the Gophers slack (please use only when urgent)
|
||||
|
||||
## Submitting a contribution
|
||||
|
||||
In order to maintain stability, most features get fully integrated in more than one PR. This allows for more opportunity to think through each API change without amassing large amounts of tech debt and API changes at once. If your feature can be broken into separate chunks, it will be able to be reviewed much quicker. For example, if the PR that implemented the `Validate` field was submitted in a PR separately from one that included `survey.Required`, it would be able to get merge without having to decide how many different `Validators` we want to provide as part of `survey`'s API.
|
||||
|
||||
When submitting a contribution,
|
||||
|
||||
- Provide a description of the feature or change
|
||||
- Reference the ticket addressed by the PR if there is one
|
||||
- Following community standards, add comments for all exported members so that all necessary information is available on godocs
|
||||
- Remember to update the project README.md with changes to the high-level API
|
||||
- Include both positive and negative unit tests (when applicable)
|
||||
- Contributions with visual ramifications or interaction changes should be accompanied with the appropriate `go-expect` tests. For more information on writing these tests, see [Writing and Running Tests](#writing-and-running-tests)
|
||||
- Try to make a series of smaller changes instead of one large change
|
||||
- Provide a description of each change that you are proposing
|
||||
- Reference the issue addressed by your pull request (if there is one)
|
||||
- Document all new exported Go APIs
|
||||
- Update the project's README when applicable
|
||||
- Include unit tests if possible
|
||||
- Contributions with visual ramifications or interaction changes should be accompanied with an integration test—see below for details.
|
||||
|
||||
## Writing and running tests
|
||||
|
||||
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/Netflix/go-expect"
|
||||
packages = ["."]
|
||||
revision = "c93bf25de8e869da25cf26bcd2932b36141f61ae"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/davecgh/go-spew"
|
||||
packages = ["spew"]
|
||||
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hinshun/vt10x"
|
||||
packages = ["."]
|
||||
revision = "1954e646417484a2a687ea344edade2c2b6523c8"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/kballard/go-shellquote"
|
||||
packages = ["."]
|
||||
revision = "95032a82bc518f77982ea72343cc1ade730072f0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/kr/pty"
|
||||
packages = ["."]
|
||||
revision = "282ce0e5322c82529687d609ee670fac7c7d917c"
|
||||
version = "v1.1.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-colorable"
|
||||
packages = ["."]
|
||||
revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072"
|
||||
version = "v0.0.9"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-isatty"
|
||||
packages = ["."]
|
||||
revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39"
|
||||
version = "v0.0.3"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mgutz/ansi"
|
||||
packages = ["."]
|
||||
revision = "9520e82c474b0a04dd04f8a40959027271bab992"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pmezard/go-difflib"
|
||||
packages = ["difflib"]
|
||||
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/stretchr/testify"
|
||||
packages = [
|
||||
"assert",
|
||||
"require"
|
||||
]
|
||||
revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
|
||||
version = "v1.2.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix"]
|
||||
revision = "9527bec2660bd847c050fda93a0f0c6dee0800bb"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "371508ebad4798adc38a118f858b5c17a65b58594203548f9feb74cb781dd907"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
#
|
||||
# [prune]
|
||||
# non-go = false
|
||||
# go-tests = true
|
||||
# unused-packages = true
|
||||
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/Netflix/go-expect"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/hinshun/vt10x"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/mattn/go-isatty"
|
||||
version = "0.0.3"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/mgutz/ansi"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/stretchr/testify"
|
||||
version = "1.2.1"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/kballard/go-shellquote"
|
||||
+81
-43
@@ -1,9 +1,8 @@
|
||||
# Survey
|
||||
|
||||
[](https://travis-ci.org/AlecAivazis/survey)
|
||||
[](https://pkg.go.dev/github.com/AlecAivazis/survey/v2)
|
||||
|
||||
A library for building interactive prompts.
|
||||
A library for building interactive and accessible prompts on terminals supporting ANSI escape sequences.
|
||||
|
||||
<img width="550" src="https://thumbs.gfycat.com/VillainousGraciousKouprey-size_restricted.gif"/>
|
||||
|
||||
@@ -56,39 +55,12 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Examples](#examples)
|
||||
1. [Running the Prompts](#running-the-prompts)
|
||||
1. [Prompts](#prompts)
|
||||
1. [Input](#input)
|
||||
1. [Suggestion Options](#suggestion-options)
|
||||
1. [Multiline](#multiline)
|
||||
1. [Password](#password)
|
||||
1. [Confirm](#confirm)
|
||||
1. [Select](#select)
|
||||
1. [MultiSelect](#multiselect)
|
||||
1. [Editor](#editor)
|
||||
1. [Filtering Options](#filtering-options)
|
||||
1. [Validation](#validation)
|
||||
1. [Built-in Validators](#built-in-validators)
|
||||
1. [Help Text](#help-text)
|
||||
1. [Changing the input rune](#changing-the-input-rune)
|
||||
1. [Changing the Icons ](#changing-the-icons)
|
||||
1. [Custom Types](#custom-types)
|
||||
1. [Testing](#testing)
|
||||
1. [FAQ](#faq)
|
||||
|
||||
## Examples
|
||||
|
||||
Examples can be found in the `examples/` directory. Run them
|
||||
to see basic behavior:
|
||||
|
||||
```bash
|
||||
go get github.com/AlecAivazis/survey/v2
|
||||
|
||||
cd $GOPATH/src/github.com/AlecAivazis/survey
|
||||
|
||||
go run examples/simple.go
|
||||
go run examples/validation.go
|
||||
```
|
||||
@@ -221,6 +193,28 @@ prompt := &survey.MultiSelect{..., PageSize: 10}
|
||||
survey.AskOne(prompt, &days, survey.WithPageSize(10))
|
||||
```
|
||||
|
||||
#### Select options description
|
||||
|
||||
The optional description text can be used to add extra information to each option listed in the select prompt:
|
||||
|
||||
```golang
|
||||
color := ""
|
||||
prompt := &survey.Select{
|
||||
Message: "Choose a color:",
|
||||
Options: []string{"red", "blue", "green"},
|
||||
Description: func(value string, index int) string {
|
||||
if value == "red" {
|
||||
return "My favorite color"
|
||||
}
|
||||
return ""
|
||||
},
|
||||
}
|
||||
survey.AskOne(prompt, &color)
|
||||
|
||||
// Assuming that the user chose "red - My favorite color":
|
||||
fmt.Println(color) //=> "red"
|
||||
```
|
||||
|
||||
### MultiSelect
|
||||
|
||||

|
||||
@@ -295,7 +289,7 @@ survey.AskOne(prompt, &color, survey.WithFilter(myFilter))
|
||||
|
||||
## Keeping the filter active
|
||||
|
||||
By default the filter will disappear if the user selects one of the filtered elements. Once the user selects one element the filter setting is gone.
|
||||
By default the filter will disappear if the user selects one of the filtered elements. Once the user selects one element the filter setting is gone.
|
||||
|
||||
However the user can prevent this from happening and keep the filter active for multiple selections in a e.g. MultiSelect:
|
||||
|
||||
@@ -342,11 +336,13 @@ survey.AskOne(prompt, &color, survey.WithValidator(survey.Required))
|
||||
`survey` comes prepackaged with a few validators to fit common situations. Currently these
|
||||
validators include:
|
||||
|
||||
| name | valid types | description | notes |
|
||||
| ------------ | ----------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------- |
|
||||
| Required | any | Rejects zero values of the response type | Boolean values pass straight through since the zero value (false) is a valid response |
|
||||
| MinLength(n) | string | Enforces that a response is at least the given length | |
|
||||
| MaxLength(n) | string | Enforces that a response is no longer than the given length | |
|
||||
| name | valid types | description | notes |
|
||||
| ------------ | -------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
|
||||
| Required | any | Rejects zero values of the response type | Boolean values pass straight through since the zero value (false) is a valid response |
|
||||
| MinLength(n) | string | Enforces that a response is at least the given length | |
|
||||
| MaxLength(n) | string | Enforces that a response is no longer than the given length | |
|
||||
| MaxItems(n) | []OptionAnswer | Enforces that a response has no more selections of the indicated | |
|
||||
| MinItems(n) | []OptionAnswer | Enforces that a response has no less selections of the indicated | |
|
||||
|
||||
## Help Text
|
||||
|
||||
@@ -361,6 +357,39 @@ All of the prompts have a `Help` field which can be defined to provide more info
|
||||
}
|
||||
```
|
||||
|
||||
## Removing the "Select All" and "Select None" options
|
||||
|
||||
By default, users can select all of the multi-select options using the right arrow key. To prevent users from being able to do this (and remove the `<right> to all` message from the prompt), use the option `WithRemoveSelectAll`:
|
||||
|
||||
```golang
|
||||
import (
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
)
|
||||
|
||||
number := ""
|
||||
prompt := &survey.Input{
|
||||
Message: "This question has the select all option removed",
|
||||
}
|
||||
|
||||
survey.AskOne(prompt, &number, survey.WithRemoveSelectAll())
|
||||
```
|
||||
|
||||
Also by default, users can use the left arrow key to unselect all of the options. To prevent users from being able to do this (and remove the `<left> to none` message from the prompt), use the option `WithRemoveSelectNone`:
|
||||
|
||||
```golang
|
||||
import (
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
)
|
||||
|
||||
number := ""
|
||||
prompt := &survey.Input{
|
||||
Message: "This question has the select all option removed",
|
||||
}
|
||||
|
||||
survey.AskOne(prompt, &number, survey.WithRemoveSelectNone())
|
||||
```
|
||||
|
||||
|
||||
### Changing the input rune
|
||||
|
||||
In some situations, `?` is a perfectly valid response. To handle this, you can change the rune that survey
|
||||
@@ -456,17 +485,26 @@ For some examples, you can see any of the tests in this repo.
|
||||
|
||||
## FAQ
|
||||
|
||||
### Why isn't sending a SIGINT (aka. CTRL-C) signal working?
|
||||
### What kinds of IO are supported by `survey`?
|
||||
|
||||
When you send an interrupt signal to the process, it only interrupts the current prompt instead of the entire process. This manifests in a `github.com/AlecAivazis/survey/v2/terminal.InterruptErr` being returned from `Ask` and `AskOne`. If you want to stop the process, handle the returned error in your code:
|
||||
survey aims to support most terminal emulators; it expects support for ANSI escape sequences.
|
||||
This means that reading from piped stdin or writing to piped stdout is **not supported**,
|
||||
and likely to break your application in these situations. See [#337](https://github.com/AlecAivazis/survey/pull/337#issue-581351617)
|
||||
|
||||
### Why isn't Ctrl-C working?
|
||||
|
||||
Ordinarily, when you type Ctrl-C, the terminal recognizes this as the QUIT button and delivers a SIGINT signal to the process, which terminates it.
|
||||
However, Survey temporarily configures the terminal to deliver control codes as ordinary input bytes.
|
||||
When Survey reads a ^C byte (ASCII \x03, "end of text"), it interrupts the current survey and returns a
|
||||
`github.com/AlecAivazis/survey/v2/terminal.InterruptErr` from `Ask` or `AskOne`.
|
||||
If you want to stop the process, handle the returned error in your code:
|
||||
|
||||
```go
|
||||
err := survey.AskOne(prompt, &myVar)
|
||||
if err == terminal.InterruptErr {
|
||||
fmt.Println("interrupted")
|
||||
|
||||
os.Exit(0)
|
||||
} else if err != nil {
|
||||
panic(err)
|
||||
if err != nil {
|
||||
if err == terminal.InterruptErr {
|
||||
log.Fatal("interrupted")
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
task "install-deps" {
|
||||
description = "Install all of package dependencies"
|
||||
pipeline = [
|
||||
"go get {{.files}}",
|
||||
]
|
||||
}
|
||||
|
||||
task "tests" {
|
||||
description = "Run the test suite"
|
||||
command = "go test {{.files}}"
|
||||
environment {
|
||||
GOFLAGS = "-mod=vendor"
|
||||
}
|
||||
}
|
||||
|
||||
variables {
|
||||
files = "$(go list -v ./... | grep -iEv \"tests|examples\")"
|
||||
}
|
||||
|
||||
+4
-4
@@ -49,8 +49,10 @@ func yesNo(t bool) string {
|
||||
func (c *Confirm) getBool(showHelp bool, config *PromptConfig) (bool, error) {
|
||||
cursor := c.NewCursor()
|
||||
rr := c.NewRuneReader()
|
||||
rr.SetTermMode()
|
||||
defer rr.RestoreTermMode()
|
||||
_ = rr.SetTermMode()
|
||||
defer func() {
|
||||
_ = rr.RestoreTermMode()
|
||||
}()
|
||||
|
||||
// start waiting for input
|
||||
for {
|
||||
@@ -107,8 +109,6 @@ func (c *Confirm) getBool(showHelp bool, config *PromptConfig) (bool, error) {
|
||||
}
|
||||
return answer, nil
|
||||
}
|
||||
// should not get here
|
||||
return c.Default, nil
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+3
-3
@@ -29,7 +29,7 @@ var TemplateFuncsNoColor = map[string]interface{}{
|
||||
//for colored output. The second string does not contain escape codes
|
||||
//and can be used by the renderer for layout purposes.
|
||||
func RunTemplate(tmpl string, data interface{}) (string, string, error) {
|
||||
tPair, err := getTemplatePair(tmpl)
|
||||
tPair, err := GetTemplatePair(tmpl)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
@@ -52,12 +52,12 @@ var (
|
||||
memoMutex = &sync.RWMutex{}
|
||||
)
|
||||
|
||||
//getTemplatePair returns a pair of compiled templates where the
|
||||
//GetTemplatePair returns a pair of compiled templates where the
|
||||
//first template is generated for user-facing output and the
|
||||
//second is generated for use by the renderer. The second
|
||||
//template does not contain any color escape codes, whereas
|
||||
//the first template may or may not depending on DisableColor.
|
||||
func getTemplatePair(tmpl string) ([2]*template.Template, error) {
|
||||
func GetTemplatePair(tmpl string) ([2]*template.Template, error) {
|
||||
memoMutex.RLock()
|
||||
if t, ok := memoizedGetTemplate[tmpl]; ok {
|
||||
memoMutex.RUnlock()
|
||||
|
||||
+37
-19
@@ -24,6 +24,11 @@ type OptionAnswer struct {
|
||||
Index int
|
||||
}
|
||||
|
||||
type reflectField struct {
|
||||
value reflect.Value
|
||||
fieldType reflect.StructField
|
||||
}
|
||||
|
||||
func OptionAnswerList(incoming []string) []OptionAnswer {
|
||||
list := []OptionAnswer{}
|
||||
for i, opt := range incoming {
|
||||
@@ -63,13 +68,12 @@ func WriteAnswer(t interface{}, name string, v interface{}) (err error) {
|
||||
}
|
||||
|
||||
// get the name of the field that matches the string we were given
|
||||
fieldIndex, err := findFieldIndex(elem, name)
|
||||
field, _, err := findField(elem, name)
|
||||
// if something went wrong
|
||||
if err != nil {
|
||||
// bubble up
|
||||
return err
|
||||
}
|
||||
field := elem.Field(fieldIndex)
|
||||
// handle references to the Settable interface aswell
|
||||
if s, ok := field.Interface().(Settable); ok {
|
||||
// use the interface method
|
||||
@@ -156,37 +160,49 @@ func IsFieldNotMatch(err error) (string, bool) {
|
||||
|
||||
// BUG(AlecAivazis): the current implementation might cause weird conflicts if there are
|
||||
// two fields with same name that only differ by casing.
|
||||
func findFieldIndex(s reflect.Value, name string) (int, error) {
|
||||
// the type of the value
|
||||
sType := s.Type()
|
||||
func findField(s reflect.Value, name string) (reflect.Value, reflect.StructField, error) {
|
||||
|
||||
fields := flattenFields(s)
|
||||
|
||||
// first look for matching tags so we can overwrite matching field names
|
||||
for i := 0; i < sType.NumField(); i++ {
|
||||
// the field we are current scanning
|
||||
field := sType.Field(i)
|
||||
|
||||
for _, f := range fields {
|
||||
// the value of the survey tag
|
||||
tag := field.Tag.Get(tagName)
|
||||
tag := f.fieldType.Tag.Get(tagName)
|
||||
// if the tag matches the name we are looking for
|
||||
if tag != "" && tag == name {
|
||||
// then we found our index
|
||||
return i, nil
|
||||
return f.value, f.fieldType, nil
|
||||
}
|
||||
}
|
||||
|
||||
// then look for matching names
|
||||
for i := 0; i < sType.NumField(); i++ {
|
||||
// the field we are current scanning
|
||||
field := sType.Field(i)
|
||||
|
||||
for _, f := range fields {
|
||||
// if the name of the field matches what we're looking for
|
||||
if strings.ToLower(field.Name) == strings.ToLower(name) {
|
||||
return i, nil
|
||||
if strings.EqualFold(f.fieldType.Name, name) {
|
||||
return f.value, f.fieldType, nil
|
||||
}
|
||||
}
|
||||
|
||||
// we didn't find the field
|
||||
return -1, errFieldNotMatch{name}
|
||||
return reflect.Value{}, reflect.StructField{}, errFieldNotMatch{name}
|
||||
}
|
||||
|
||||
func flattenFields(s reflect.Value) []reflectField {
|
||||
sType := s.Type()
|
||||
numField := sType.NumField()
|
||||
fields := make([]reflectField, 0, numField)
|
||||
for i := 0; i < numField; i++ {
|
||||
fieldType := sType.Field(i)
|
||||
field := s.Field(i)
|
||||
|
||||
if field.Kind() == reflect.Struct && fieldType.Anonymous {
|
||||
// field is a promoted structure
|
||||
fields = append(fields, flattenFields(field)...)
|
||||
continue
|
||||
}
|
||||
fields = append(fields, reflectField{field, fieldType})
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
// isList returns true if the element is something we can Len()
|
||||
@@ -343,7 +359,9 @@ func copy(t reflect.Value, v reflect.Value) (err error) {
|
||||
// otherwise it could be an array
|
||||
case reflect.Array:
|
||||
// set the index to the appropriate value
|
||||
copy(t.Slice(i, i+1).Index(0), v.Index(i))
|
||||
if err := copy(t.Slice(i, i+1).Index(0), v.Index(i)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
+7
-3
@@ -101,8 +101,10 @@ func (e *Editor) prompt(initialValue string, config *PromptConfig) (interface{},
|
||||
|
||||
// start reading runes from the standard in
|
||||
rr := e.NewRuneReader()
|
||||
rr.SetTermMode()
|
||||
defer rr.RestoreTermMode()
|
||||
_ = rr.SetTermMode()
|
||||
defer func() {
|
||||
_ = rr.RestoreTermMode()
|
||||
}()
|
||||
|
||||
cursor := e.NewCursor()
|
||||
cursor.Hide()
|
||||
@@ -147,7 +149,9 @@ func (e *Editor) prompt(initialValue string, config *PromptConfig) (interface{},
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer os.Remove(f.Name())
|
||||
defer func() {
|
||||
_ = os.Remove(f.Name())
|
||||
}()
|
||||
|
||||
// write utf8 BOM header
|
||||
// The reason why we do this is because notepad.exe on Windows determines the
|
||||
|
||||
+104
-80
@@ -1,6 +1,8 @@
|
||||
package survey
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2/core"
|
||||
"github.com/AlecAivazis/survey/v2/terminal"
|
||||
)
|
||||
@@ -19,8 +21,8 @@ type Input struct {
|
||||
Default string
|
||||
Help string
|
||||
Suggest func(toComplete string) []string
|
||||
typedAnswer string
|
||||
answer string
|
||||
typedAnswer string
|
||||
options []core.OptionAnswer
|
||||
selectedIndex int
|
||||
showingHelp bool
|
||||
@@ -58,85 +60,90 @@ var InputQuestionTemplate = `
|
||||
{{- if and .Suggest }}{{color "cyan"}}{{ print .Config.SuggestInput }} for suggestions{{end -}}
|
||||
]{{color "reset"}} {{end}}
|
||||
{{- if .Default}}{{color "white"}}({{.Default}}) {{color "reset"}}{{end}}
|
||||
{{- .Answer -}}
|
||||
{{- end}}`
|
||||
|
||||
func (i *Input) OnChange(key rune, config *PromptConfig) (bool, error) {
|
||||
if key == terminal.KeyEnter || key == '\n' {
|
||||
if i.answer != config.HelpInput || i.Help == "" {
|
||||
// we're done
|
||||
return true, nil
|
||||
} else {
|
||||
i.answer = ""
|
||||
i.showingHelp = true
|
||||
}
|
||||
} else if key == terminal.KeyDeleteWord || key == terminal.KeyDeleteLine {
|
||||
i.answer = ""
|
||||
} else if key == terminal.KeyEscape && i.Suggest != nil {
|
||||
if len(i.options) > 0 {
|
||||
func (i *Input) onRune(config *PromptConfig) terminal.OnRuneFn {
|
||||
return terminal.OnRuneFn(func(key rune, line []rune) ([]rune, bool, error) {
|
||||
if i.options != nil && (key == terminal.KeyEnter || key == '\n') {
|
||||
return []rune(i.answer), true, nil
|
||||
} else if i.options != nil && key == terminal.KeyEscape {
|
||||
i.answer = i.typedAnswer
|
||||
}
|
||||
i.options = nil
|
||||
} else if key == terminal.KeyArrowUp && len(i.options) > 0 {
|
||||
if i.selectedIndex == 0 {
|
||||
i.selectedIndex = len(i.options) - 1
|
||||
} else {
|
||||
i.selectedIndex--
|
||||
}
|
||||
i.answer = i.options[i.selectedIndex].Value
|
||||
} else if (key == terminal.KeyArrowDown || key == terminal.KeyTab) && len(i.options) > 0 {
|
||||
if i.selectedIndex == len(i.options)-1 {
|
||||
i.options = nil
|
||||
} else if key == terminal.KeyArrowUp && len(i.options) > 0 {
|
||||
if i.selectedIndex == 0 {
|
||||
i.selectedIndex = len(i.options) - 1
|
||||
} else {
|
||||
i.selectedIndex--
|
||||
}
|
||||
i.answer = i.options[i.selectedIndex].Value
|
||||
} else if (key == terminal.KeyArrowDown || key == terminal.KeyTab) && len(i.options) > 0 {
|
||||
if i.selectedIndex == len(i.options)-1 {
|
||||
i.selectedIndex = 0
|
||||
} else {
|
||||
i.selectedIndex++
|
||||
}
|
||||
i.answer = i.options[i.selectedIndex].Value
|
||||
} else if key == terminal.KeyTab && i.Suggest != nil {
|
||||
i.answer = string(line)
|
||||
i.typedAnswer = i.answer
|
||||
options := i.Suggest(i.answer)
|
||||
i.selectedIndex = 0
|
||||
} else {
|
||||
i.selectedIndex++
|
||||
}
|
||||
i.answer = i.options[i.selectedIndex].Value
|
||||
} else if key == terminal.KeyTab && i.Suggest != nil {
|
||||
options := i.Suggest(i.answer)
|
||||
i.selectedIndex = 0
|
||||
i.typedAnswer = i.answer
|
||||
if len(options) > 0 {
|
||||
if len(options) == 0 {
|
||||
return line, false, nil
|
||||
}
|
||||
|
||||
i.answer = options[0]
|
||||
if len(options) == 1 {
|
||||
i.typedAnswer = i.answer
|
||||
i.options = nil
|
||||
} else {
|
||||
i.options = core.OptionAnswerList(options)
|
||||
}
|
||||
}
|
||||
} else if key == terminal.KeyDelete || key == terminal.KeyBackspace {
|
||||
if i.answer != "" {
|
||||
i.answer = i.answer[0 : len(i.answer)-1]
|
||||
}
|
||||
} else if key >= terminal.KeySpace {
|
||||
i.answer += string(key)
|
||||
i.typedAnswer = i.answer
|
||||
i.options = nil
|
||||
}
|
||||
} else {
|
||||
if i.options == nil {
|
||||
return line, false, nil
|
||||
}
|
||||
|
||||
pageSize := config.PageSize
|
||||
opts, idx := paginate(pageSize, i.options, i.selectedIndex)
|
||||
err := i.Render(
|
||||
InputQuestionTemplate,
|
||||
InputTemplateData{
|
||||
Input: *i,
|
||||
Answer: i.answer,
|
||||
ShowHelp: i.showingHelp,
|
||||
SelectedIndex: idx,
|
||||
PageEntries: opts,
|
||||
Config: config,
|
||||
},
|
||||
)
|
||||
if key >= terminal.KeySpace {
|
||||
i.answer += string(key)
|
||||
}
|
||||
i.typedAnswer = i.answer
|
||||
|
||||
return err != nil, err
|
||||
i.options = nil
|
||||
}
|
||||
|
||||
pageSize := config.PageSize
|
||||
opts, idx := paginate(pageSize, i.options, i.selectedIndex)
|
||||
err := i.Render(
|
||||
InputQuestionTemplate,
|
||||
InputTemplateData{
|
||||
Input: *i,
|
||||
Answer: i.answer,
|
||||
ShowHelp: i.showingHelp,
|
||||
SelectedIndex: idx,
|
||||
PageEntries: opts,
|
||||
Config: config,
|
||||
},
|
||||
)
|
||||
|
||||
if err == nil {
|
||||
err = readLineAgain
|
||||
}
|
||||
|
||||
return []rune(i.typedAnswer), true, err
|
||||
})
|
||||
}
|
||||
|
||||
var readLineAgain = errors.New("read line again")
|
||||
|
||||
func (i *Input) Prompt(config *PromptConfig) (interface{}, error) {
|
||||
// render the template
|
||||
err := i.Render(
|
||||
InputQuestionTemplate,
|
||||
InputTemplateData{
|
||||
Input: *i,
|
||||
Config: config,
|
||||
Input: *i,
|
||||
Config: config,
|
||||
ShowHelp: i.showingHelp,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
@@ -145,34 +152,44 @@ func (i *Input) Prompt(config *PromptConfig) (interface{}, error) {
|
||||
|
||||
// start reading runes from the standard in
|
||||
rr := i.NewRuneReader()
|
||||
rr.SetTermMode()
|
||||
defer rr.RestoreTermMode()
|
||||
|
||||
_ = rr.SetTermMode()
|
||||
defer func() {
|
||||
_ = rr.RestoreTermMode()
|
||||
}()
|
||||
cursor := i.NewCursor()
|
||||
cursor.Hide() // hide the cursor
|
||||
defer cursor.Show() // show the cursor when we're done
|
||||
if !config.ShowCursor {
|
||||
cursor.Hide() // hide the cursor
|
||||
defer cursor.Show() // show the cursor when we're done
|
||||
}
|
||||
|
||||
var line []rune
|
||||
|
||||
// start waiting for input
|
||||
for {
|
||||
r, _, err := rr.ReadRune()
|
||||
if err != nil {
|
||||
return "", err
|
||||
if i.options != nil {
|
||||
line = []rune{}
|
||||
}
|
||||
if r == terminal.KeyInterrupt {
|
||||
return "", terminal.InterruptErr
|
||||
}
|
||||
if r == terminal.KeyEndTransmission {
|
||||
break
|
||||
|
||||
line, err = rr.ReadLineWithDefault(0, line, i.onRune(config))
|
||||
if err == readLineAgain {
|
||||
continue
|
||||
}
|
||||
|
||||
b, err := i.OnChange(r, config)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if b {
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
i.answer = string(line)
|
||||
// readline print an empty line, go up before we render the follow up
|
||||
cursor.Up(1)
|
||||
|
||||
// if we ran into the help string
|
||||
if i.answer == config.HelpInput && i.Help != "" {
|
||||
// show the help and prompt again
|
||||
i.showingHelp = true
|
||||
return i.Prompt(config)
|
||||
}
|
||||
|
||||
// if the line is empty
|
||||
@@ -190,13 +207,20 @@ func (i *Input) Prompt(config *PromptConfig) (interface{}, error) {
|
||||
}
|
||||
|
||||
func (i *Input) Cleanup(config *PromptConfig, val interface{}) error {
|
||||
// use the default answer when cleaning up the prompt if necessary
|
||||
ans := i.answer
|
||||
if ans == "" && i.Default != "" {
|
||||
ans = i.Default
|
||||
}
|
||||
|
||||
// render the cleanup
|
||||
return i.Render(
|
||||
InputQuestionTemplate,
|
||||
InputTemplateData{
|
||||
Input: *i,
|
||||
ShowAnswer: true,
|
||||
Config: config,
|
||||
Answer: i.answer,
|
||||
Answer: ans,
|
||||
},
|
||||
)
|
||||
}
|
||||
+5
-3
@@ -50,8 +50,10 @@ func (i *Multiline) Prompt(config *PromptConfig) (interface{}, error) {
|
||||
|
||||
// start reading runes from the standard in
|
||||
rr := i.NewRuneReader()
|
||||
rr.SetTermMode()
|
||||
defer rr.RestoreTermMode()
|
||||
_ = rr.SetTermMode()
|
||||
defer func() {
|
||||
_ = rr.RestoreTermMode()
|
||||
}()
|
||||
|
||||
cursor := i.NewCursor()
|
||||
|
||||
@@ -60,7 +62,7 @@ func (i *Multiline) Prompt(config *PromptConfig) (interface{}, error) {
|
||||
emptyOnce := false
|
||||
// get the next line
|
||||
for {
|
||||
line := []rune{}
|
||||
var line []rune
|
||||
line, err = rr.ReadLine(0)
|
||||
if err != nil {
|
||||
return string(line), err
|
||||
|
||||
+55
-34
@@ -45,21 +45,36 @@ type MultiSelectTemplateData struct {
|
||||
ShowHelp bool
|
||||
PageEntries []core.OptionAnswer
|
||||
Config *PromptConfig
|
||||
|
||||
// These fields are used when rendering an individual option
|
||||
CurrentOpt core.OptionAnswer
|
||||
CurrentIndex int
|
||||
}
|
||||
|
||||
// IterateOption sets CurrentOpt and CurrentIndex appropriately so a multiselect option can be rendered individually
|
||||
func (m MultiSelectTemplateData) IterateOption(ix int, opt core.OptionAnswer) interface{} {
|
||||
copy := m
|
||||
copy.CurrentIndex = ix
|
||||
copy.CurrentOpt = opt
|
||||
return copy
|
||||
}
|
||||
|
||||
var MultiSelectQuestionTemplate = `
|
||||
{{- define "option"}}
|
||||
{{- if eq .SelectedIndex .CurrentIndex }}{{color .Config.Icons.SelectFocus.Format }}{{ .Config.Icons.SelectFocus.Text }}{{color "reset"}}{{else}} {{end}}
|
||||
{{- if index .Checked .CurrentOpt.Index }}{{color .Config.Icons.MarkedOption.Format }} {{ .Config.Icons.MarkedOption.Text }} {{else}}{{color .Config.Icons.UnmarkedOption.Format }} {{ .Config.Icons.UnmarkedOption.Text }} {{end}}
|
||||
{{- color "reset"}}
|
||||
{{- " "}}{{- .CurrentOpt.Value}}
|
||||
{{end}}
|
||||
{{- if .ShowHelp }}{{- color .Config.Icons.Help.Format }}{{ .Config.Icons.Help.Text }} {{ .Help }}{{color "reset"}}{{"\n"}}{{end}}
|
||||
{{- color .Config.Icons.Question.Format }}{{ .Config.Icons.Question.Text }} {{color "reset"}}
|
||||
{{- color "default+hb"}}{{ .Message }}{{ .FilterMessage }}{{color "reset"}}
|
||||
{{- if .ShowAnswer}}{{color "cyan"}} {{.Answer}}{{color "reset"}}{{"\n"}}
|
||||
{{- else }}
|
||||
{{- " "}}{{- color "cyan"}}[Use arrows to move, space to select, <right> to all, <left> to none, type to filter{{- if and .Help (not .ShowHelp)}}, {{ .Config.HelpInput }} for more help{{end}}]{{color "reset"}}
|
||||
{{- " "}}{{- color "cyan"}}[Use arrows to move, space to select,{{- if not .Config.RemoveSelectAll }} <right> to all,{{end}}{{- if not .Config.RemoveSelectNone }} <left> to none,{{end}} type to filter{{- if and .Help (not .ShowHelp)}}, {{ .Config.HelpInput }} for more help{{end}}]{{color "reset"}}
|
||||
{{- "\n"}}
|
||||
{{- range $ix, $option := .PageEntries}}
|
||||
{{- if eq $ix $.SelectedIndex }}{{color $.Config.Icons.SelectFocus.Format }}{{ $.Config.Icons.SelectFocus.Text }}{{color "reset"}}{{else}} {{end}}
|
||||
{{- if index $.Checked $option.Index }}{{color $.Config.Icons.MarkedOption.Format }} {{ $.Config.Icons.MarkedOption.Text }} {{else}}{{color $.Config.Icons.UnmarkedOption.Format }} {{ $.Config.Icons.UnmarkedOption.Text }} {{end}}
|
||||
{{- color "reset"}}
|
||||
{{- " "}}{{$option.Value}}{{"\n"}}
|
||||
{{- template "option" $.IterateOption $ix $option}}
|
||||
{{- end}}
|
||||
{{- end}}`
|
||||
|
||||
@@ -113,19 +128,20 @@ func (m *MultiSelect) OnChange(key rune, config *PromptConfig) {
|
||||
m.filter = ""
|
||||
} else if key == terminal.KeyDelete || key == terminal.KeyBackspace {
|
||||
if m.filter != "" {
|
||||
m.filter = m.filter[0 : len(m.filter)-1]
|
||||
runeFilter := []rune(m.filter)
|
||||
m.filter = string(runeFilter[0 : len(runeFilter)-1])
|
||||
}
|
||||
} else if key >= terminal.KeySpace {
|
||||
m.filter += string(key)
|
||||
m.VimMode = false
|
||||
} else if key == terminal.KeyArrowRight {
|
||||
} else if !config.RemoveSelectAll && key == terminal.KeyArrowRight {
|
||||
for _, v := range options {
|
||||
m.checked[v.Index] = true
|
||||
}
|
||||
if !config.KeepFilter {
|
||||
m.filter = ""
|
||||
}
|
||||
} else if key == terminal.KeyArrowLeft {
|
||||
} else if !config.RemoveSelectNone && key == terminal.KeyArrowLeft {
|
||||
for _, v := range options {
|
||||
m.checked[v.Index] = false
|
||||
}
|
||||
@@ -158,18 +174,17 @@ func (m *MultiSelect) OnChange(key rune, config *PromptConfig) {
|
||||
// and we have modified the filter then we should move the page back!
|
||||
opts, idx := paginate(pageSize, options, m.selectedIndex)
|
||||
|
||||
tmplData := MultiSelectTemplateData{
|
||||
MultiSelect: *m,
|
||||
SelectedIndex: idx,
|
||||
Checked: m.checked,
|
||||
ShowHelp: m.showingHelp,
|
||||
PageEntries: opts,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
// render the options
|
||||
m.Render(
|
||||
MultiSelectQuestionTemplate,
|
||||
MultiSelectTemplateData{
|
||||
MultiSelect: *m,
|
||||
SelectedIndex: idx,
|
||||
Checked: m.checked,
|
||||
ShowHelp: m.showingHelp,
|
||||
PageEntries: opts,
|
||||
Config: config,
|
||||
},
|
||||
)
|
||||
_ = m.RenderWithCursorOffset(MultiSelectQuestionTemplate, tmplData, opts, idx)
|
||||
}
|
||||
|
||||
func (m *MultiSelect) filterOptions(config *PromptConfig) []core.OptionAnswer {
|
||||
@@ -249,31 +264,37 @@ func (m *MultiSelect) Prompt(config *PromptConfig) (interface{}, error) {
|
||||
opts, idx := paginate(pageSize, core.OptionAnswerList(m.Options), m.selectedIndex)
|
||||
|
||||
cursor := m.NewCursor()
|
||||
cursor.Hide() // hide the cursor
|
||||
defer cursor.Show() // show the cursor when we're done
|
||||
cursor.Save() // for proper cursor placement during selection
|
||||
cursor.Hide() // hide the cursor
|
||||
defer cursor.Show() // show the cursor when we're done
|
||||
defer cursor.Restore() // clear any accessibility offsetting on exit
|
||||
|
||||
tmplData := MultiSelectTemplateData{
|
||||
MultiSelect: *m,
|
||||
SelectedIndex: idx,
|
||||
Checked: m.checked,
|
||||
PageEntries: opts,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
// ask the question
|
||||
err := m.Render(
|
||||
MultiSelectQuestionTemplate,
|
||||
MultiSelectTemplateData{
|
||||
MultiSelect: *m,
|
||||
SelectedIndex: idx,
|
||||
Checked: m.checked,
|
||||
PageEntries: opts,
|
||||
Config: config,
|
||||
},
|
||||
)
|
||||
err := m.RenderWithCursorOffset(MultiSelectQuestionTemplate, tmplData, opts, idx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
rr := m.NewRuneReader()
|
||||
rr.SetTermMode()
|
||||
defer rr.RestoreTermMode()
|
||||
_ = rr.SetTermMode()
|
||||
defer func() {
|
||||
_ = rr.RestoreTermMode()
|
||||
}()
|
||||
|
||||
// start waiting for input
|
||||
for {
|
||||
r, _, _ := rr.ReadRune()
|
||||
r, _, err := rr.ReadRune()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if r == '\r' || r == '\n' {
|
||||
break
|
||||
}
|
||||
|
||||
+9
-4
@@ -44,14 +44,19 @@ func (p *Password) Prompt(config *PromptConfig) (interface{}, error) {
|
||||
Config: config,
|
||||
},
|
||||
)
|
||||
fmt.Fprint(terminal.NewAnsiStdout(p.Stdio().Out), userOut)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if _, err := fmt.Fprint(terminal.NewAnsiStdout(p.Stdio().Out), userOut); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
rr := p.NewRuneReader()
|
||||
rr.SetTermMode()
|
||||
defer rr.RestoreTermMode()
|
||||
_ = rr.SetTermMode()
|
||||
defer func() {
|
||||
_ = rr.RestoreTermMode()
|
||||
}()
|
||||
|
||||
// no help msg? Just return any response
|
||||
if p.Help == "" {
|
||||
@@ -61,7 +66,7 @@ func (p *Password) Prompt(config *PromptConfig) (interface{}, error) {
|
||||
|
||||
cursor := p.NewCursor()
|
||||
|
||||
line := []rune{}
|
||||
var line []rune
|
||||
// process answers looking for help prompt answer
|
||||
for {
|
||||
line, err = rr.ReadLine('*')
|
||||
|
||||
+49
-10
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"github.com/AlecAivazis/survey/v2/core"
|
||||
"github.com/AlecAivazis/survey/v2/terminal"
|
||||
goterm "golang.org/x/crypto/ssh/terminal"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
type Renderer struct {
|
||||
@@ -61,7 +61,9 @@ func (r *Renderer) Error(config *PromptConfig, invalid error) error {
|
||||
}
|
||||
|
||||
// send the message to the user
|
||||
fmt.Fprint(terminal.NewAnsiStdout(r.stdio.Out), userOut)
|
||||
if _, err := fmt.Fprint(terminal.NewAnsiStdout(r.stdio.Out), userOut); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// add the printed text to the rendered error buffer so we can cleanup later
|
||||
r.appendRenderedError(layoutOut)
|
||||
@@ -69,6 +71,14 @@ func (r *Renderer) Error(config *PromptConfig, invalid error) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Renderer) OffsetCursor(offset int) {
|
||||
cursor := r.NewCursor()
|
||||
for offset > 0 {
|
||||
cursor.PreviousLine(1)
|
||||
offset--
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Renderer) Render(tmpl string, data interface{}) error {
|
||||
// cleanup the currently rendered text
|
||||
lineCount := r.countLines(r.renderedText)
|
||||
@@ -82,7 +92,9 @@ func (r *Renderer) Render(tmpl string, data interface{}) error {
|
||||
}
|
||||
|
||||
// print the summary
|
||||
fmt.Fprint(terminal.NewAnsiStdout(r.stdio.Out), userOut)
|
||||
if _, err := fmt.Fprint(terminal.NewAnsiStdout(r.stdio.Out), userOut); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// add the printed text to the rendered text buffer so we can cleanup later
|
||||
r.AppendRenderedText(layoutOut)
|
||||
@@ -91,6 +103,21 @@ func (r *Renderer) Render(tmpl string, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Renderer) RenderWithCursorOffset(tmpl string, data IterableOpts, opts []core.OptionAnswer, idx int) error {
|
||||
cursor := r.NewCursor()
|
||||
cursor.Restore() // clear any accessibility offsetting
|
||||
|
||||
if err := r.Render(tmpl, data); err != nil {
|
||||
return err
|
||||
}
|
||||
cursor.Save()
|
||||
|
||||
offset := computeCursorOffset(MultiSelectQuestionTemplate, data, opts, idx, r.termWidthSafe())
|
||||
r.OffsetCursor(offset)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// appendRenderedError appends text to the renderer's error buffer
|
||||
// which is used to track what has been printed. It is not exported
|
||||
// as errors should only be displayed via Error(config, error).
|
||||
@@ -119,26 +146,31 @@ func (r *Renderer) resetPrompt(lines int) {
|
||||
|
||||
func (r *Renderer) termWidth() (int, error) {
|
||||
fd := int(r.stdio.Out.Fd())
|
||||
termWidth, _, err := goterm.GetSize(fd)
|
||||
termWidth, _, err := term.GetSize(fd)
|
||||
return termWidth, err
|
||||
}
|
||||
|
||||
// countLines will return the count of `\n` with the addition of any
|
||||
// lines that have wrapped due to narrow terminal width
|
||||
func (r *Renderer) countLines(buf bytes.Buffer) int {
|
||||
func (r *Renderer) termWidthSafe() int {
|
||||
w, err := r.termWidth()
|
||||
if err != nil || w == 0 {
|
||||
// if we got an error due to terminal.GetSize not being supported
|
||||
// on current platform then just assume a very wide terminal
|
||||
w = 10000
|
||||
}
|
||||
return w
|
||||
}
|
||||
|
||||
// countLines will return the count of `\n` with the addition of any
|
||||
// lines that have wrapped due to narrow terminal width
|
||||
func (r *Renderer) countLines(buf bytes.Buffer) int {
|
||||
w := r.termWidthSafe()
|
||||
|
||||
bufBytes := buf.Bytes()
|
||||
|
||||
count := 0
|
||||
curr := 0
|
||||
delim := -1
|
||||
for curr < len(bufBytes) {
|
||||
var delim int
|
||||
// read until the next newline or the end of the string
|
||||
relDelim := bytes.IndexRune(bufBytes[curr:], '\n')
|
||||
if relDelim != -1 {
|
||||
@@ -148,8 +180,15 @@ func (r *Renderer) countLines(buf bytes.Buffer) int {
|
||||
delim = len(bufBytes) // no new line found, read rest of text
|
||||
}
|
||||
|
||||
// account for word wrapping
|
||||
count += int(utf8.RuneCount(bufBytes[curr:delim]) / w)
|
||||
if lineWidth := utf8.RuneCount(bufBytes[curr:delim]); lineWidth > w {
|
||||
// account for word wrapping
|
||||
count += lineWidth / w
|
||||
if (lineWidth % w) == 0 {
|
||||
// content whose width is exactly a multiplier of available width should not
|
||||
// count as having wrapped on the last line
|
||||
count -= 1
|
||||
}
|
||||
}
|
||||
curr = delim + 1
|
||||
}
|
||||
|
||||
|
||||
+67
-34
@@ -28,6 +28,7 @@ type Select struct {
|
||||
VimMode bool
|
||||
FilterMessage string
|
||||
Filter func(filter string, value string, index int) bool
|
||||
Description func(value string, index int) string
|
||||
filter string
|
||||
selectedIndex int
|
||||
useDefault bool
|
||||
@@ -42,10 +43,35 @@ type SelectTemplateData struct {
|
||||
Answer string
|
||||
ShowAnswer bool
|
||||
ShowHelp bool
|
||||
Description func(value string, index int) string
|
||||
Config *PromptConfig
|
||||
|
||||
// These fields are used when rendering an individual option
|
||||
CurrentOpt core.OptionAnswer
|
||||
CurrentIndex int
|
||||
}
|
||||
|
||||
// IterateOption sets CurrentOpt and CurrentIndex appropriately so a select option can be rendered individually
|
||||
func (s SelectTemplateData) IterateOption(ix int, opt core.OptionAnswer) interface{} {
|
||||
copy := s
|
||||
copy.CurrentIndex = ix
|
||||
copy.CurrentOpt = opt
|
||||
return copy
|
||||
}
|
||||
|
||||
func (s SelectTemplateData) GetDescription(opt core.OptionAnswer) string {
|
||||
if s.Description == nil {
|
||||
return ""
|
||||
}
|
||||
return s.Description(opt.Value, opt.Index)
|
||||
}
|
||||
|
||||
var SelectQuestionTemplate = `
|
||||
{{- define "option"}}
|
||||
{{- if eq .SelectedIndex .CurrentIndex }}{{color .Config.Icons.SelectFocus.Format }}{{ .Config.Icons.SelectFocus.Text }} {{else}}{{color "default"}} {{end}}
|
||||
{{- .CurrentOpt.Value}}{{ if ne ($.GetDescription .CurrentOpt) "" }} - {{color "cyan"}}{{ $.GetDescription .CurrentOpt }}{{end}}
|
||||
{{- color "reset"}}
|
||||
{{end}}
|
||||
{{- if .ShowHelp }}{{- color .Config.Icons.Help.Format }}{{ .Config.Icons.Help.Text }} {{ .Help }}{{color "reset"}}{{"\n"}}{{end}}
|
||||
{{- color .Config.Icons.Question.Format }}{{ .Config.Icons.Question.Text }} {{color "reset"}}
|
||||
{{- color "default+hb"}}{{ .Message }}{{ .FilterMessage }}{{color "reset"}}
|
||||
@@ -53,10 +79,8 @@ var SelectQuestionTemplate = `
|
||||
{{- else}}
|
||||
{{- " "}}{{- color "cyan"}}[Use arrows to move, type to filter{{- if and .Help (not .ShowHelp)}}, {{ .Config.HelpInput }} for more help{{end}}]{{color "reset"}}
|
||||
{{- "\n"}}
|
||||
{{- range $ix, $choice := .PageEntries}}
|
||||
{{- if eq $ix $.SelectedIndex }}{{color $.Config.Icons.SelectFocus.Format }}{{ $.Config.Icons.SelectFocus.Text }} {{else}}{{color "default"}} {{end}}
|
||||
{{- $choice.Value}}
|
||||
{{- color "reset"}}{{"\n"}}
|
||||
{{- range $ix, $option := .PageEntries}}
|
||||
{{- template "option" $.IterateOption $ix $option}}
|
||||
{{- end}}
|
||||
{{- end}}`
|
||||
|
||||
@@ -114,8 +138,9 @@ func (s *Select) OnChange(key rune, config *PromptConfig) bool {
|
||||
} else if key == terminal.KeyDelete || key == terminal.KeyBackspace {
|
||||
// if there is content in the filter to delete
|
||||
if s.filter != "" {
|
||||
runeFilter := []rune(s.filter)
|
||||
// subtract a line from the current filter
|
||||
s.filter = s.filter[0 : len(s.filter)-1]
|
||||
s.filter = string(runeFilter[0 : len(runeFilter)-1])
|
||||
// we removed the last value in the filter
|
||||
}
|
||||
} else if key >= terminal.KeySpace {
|
||||
@@ -151,17 +176,17 @@ func (s *Select) OnChange(key rune, config *PromptConfig) bool {
|
||||
// and we have modified the filter then we should move the page back!
|
||||
opts, idx := paginate(pageSize, options, s.selectedIndex)
|
||||
|
||||
tmplData := SelectTemplateData{
|
||||
Select: *s,
|
||||
SelectedIndex: idx,
|
||||
ShowHelp: s.showingHelp,
|
||||
Description: s.Description,
|
||||
PageEntries: opts,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
// render the options
|
||||
s.Render(
|
||||
SelectQuestionTemplate,
|
||||
SelectTemplateData{
|
||||
Select: *s,
|
||||
SelectedIndex: idx,
|
||||
ShowHelp: s.showingHelp,
|
||||
PageEntries: opts,
|
||||
Config: config,
|
||||
},
|
||||
)
|
||||
_ = s.RenderWithCursorOffset(SelectQuestionTemplate, tmplData, opts, idx)
|
||||
|
||||
// keep prompting
|
||||
return false
|
||||
@@ -233,16 +258,23 @@ func (s *Select) Prompt(config *PromptConfig) (interface{}, error) {
|
||||
// figure out the options and index to render
|
||||
opts, idx := paginate(pageSize, core.OptionAnswerList(s.Options), sel)
|
||||
|
||||
cursor := s.NewCursor()
|
||||
cursor.Save() // for proper cursor placement during selection
|
||||
cursor.Hide() // hide the cursor
|
||||
defer cursor.Show() // show the cursor when we're done
|
||||
defer cursor.Restore() // clear any accessibility offsetting on exit
|
||||
|
||||
tmplData := SelectTemplateData{
|
||||
Select: *s,
|
||||
SelectedIndex: idx,
|
||||
Description: s.Description,
|
||||
ShowHelp: s.showingHelp,
|
||||
PageEntries: opts,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
// ask the question
|
||||
err := s.Render(
|
||||
SelectQuestionTemplate,
|
||||
SelectTemplateData{
|
||||
Select: *s,
|
||||
PageEntries: opts,
|
||||
SelectedIndex: idx,
|
||||
Config: config,
|
||||
},
|
||||
)
|
||||
err := s.RenderWithCursorOffset(SelectQuestionTemplate, tmplData, opts, idx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -251,12 +283,10 @@ func (s *Select) Prompt(config *PromptConfig) (interface{}, error) {
|
||||
s.useDefault = true
|
||||
|
||||
rr := s.NewRuneReader()
|
||||
rr.SetTermMode()
|
||||
defer rr.RestoreTermMode()
|
||||
|
||||
cursor := s.NewCursor()
|
||||
cursor.Hide() // hide the cursor
|
||||
defer cursor.Show() // show the cursor when we're done
|
||||
_ = rr.SetTermMode()
|
||||
defer func() {
|
||||
_ = rr.RestoreTermMode()
|
||||
}()
|
||||
|
||||
// start waiting for input
|
||||
for {
|
||||
@@ -316,13 +346,16 @@ func (s *Select) Prompt(config *PromptConfig) (interface{}, error) {
|
||||
}
|
||||
|
||||
func (s *Select) Cleanup(config *PromptConfig, val interface{}) error {
|
||||
cursor := s.NewCursor()
|
||||
cursor.Restore()
|
||||
return s.Render(
|
||||
SelectQuestionTemplate,
|
||||
SelectTemplateData{
|
||||
Select: *s,
|
||||
Answer: val.(core.OptionAnswer).Value,
|
||||
ShowAnswer: true,
|
||||
Config: config,
|
||||
Select: *s,
|
||||
Answer: val.(core.OptionAnswer).Value,
|
||||
ShowAnswer: true,
|
||||
Description: s.Description,
|
||||
Config: config,
|
||||
},
|
||||
)
|
||||
}
|
||||
+115
-53
@@ -1,10 +1,12 @@
|
||||
package survey
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2/core"
|
||||
"github.com/AlecAivazis/survey/v2/terminal"
|
||||
@@ -54,7 +56,10 @@ func defaultAskOptions() *AskOptions {
|
||||
// include this option if it matches
|
||||
return strings.Contains(strings.ToLower(value), filter)
|
||||
},
|
||||
KeepFilter: false,
|
||||
KeepFilter: false,
|
||||
ShowCursor: false,
|
||||
RemoveSelectAll: false,
|
||||
RemoveSelectNone: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -108,12 +113,15 @@ type Question struct {
|
||||
|
||||
// PromptConfig holds the global configuration for a prompt
|
||||
type PromptConfig struct {
|
||||
PageSize int
|
||||
Icons IconSet
|
||||
HelpInput string
|
||||
SuggestInput string
|
||||
Filter func(filter string, option string, index int) bool
|
||||
KeepFilter bool
|
||||
PageSize int
|
||||
Icons IconSet
|
||||
HelpInput string
|
||||
SuggestInput string
|
||||
Filter func(filter string, option string, index int) bool
|
||||
KeepFilter bool
|
||||
ShowCursor bool
|
||||
RemoveSelectAll bool
|
||||
RemoveSelectNone bool
|
||||
}
|
||||
|
||||
// Prompt is the primary interface for the objects that can take user input
|
||||
@@ -171,6 +179,22 @@ func WithKeepFilter(KeepFilter bool) AskOpt {
|
||||
}
|
||||
}
|
||||
|
||||
// WithRemoveSelectAll remove the select all option in Multiselect
|
||||
func WithRemoveSelectAll() AskOpt {
|
||||
return func(options *AskOptions) error {
|
||||
options.PromptConfig.RemoveSelectAll = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithRemoveSelectNone remove the select none/unselect all in Multiselect
|
||||
func WithRemoveSelectNone() AskOpt {
|
||||
return func(options *AskOptions) error {
|
||||
options.PromptConfig.RemoveSelectNone = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithValidator specifies a validator to use while prompting the user
|
||||
func WithValidator(v Validator) AskOpt {
|
||||
return func(options *AskOptions) error {
|
||||
@@ -219,6 +243,17 @@ func WithIcons(setIcons func(*IconSet)) AskOpt {
|
||||
}
|
||||
}
|
||||
|
||||
// WithShowCursor sets the show cursor behavior when prompting the user
|
||||
func WithShowCursor(ShowCursor bool) AskOpt {
|
||||
return func(options *AskOptions) error {
|
||||
// set the page size
|
||||
options.PromptConfig.ShowCursor = ShowCursor
|
||||
|
||||
// nothing went wrong
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
AskOne performs the prompt for a single prompt and asks for validation if required.
|
||||
Response types should be something that can be casted from the response type designated
|
||||
@@ -282,6 +317,20 @@ func Ask(qs []*Question, response interface{}, opts ...AskOpt) error {
|
||||
return errors.New("cannot call Ask() with a nil reference to record the answers")
|
||||
}
|
||||
|
||||
validate := func(q *Question, val interface{}) error {
|
||||
if q.Validate != nil {
|
||||
if err := q.Validate(val); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, v := range options.Validators {
|
||||
if err := v(val); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// go over every question
|
||||
for _, q := range qs {
|
||||
// If Prompt implements controllable stdio, pass in specified stdio.
|
||||
@@ -289,46 +338,28 @@ func Ask(qs []*Question, response interface{}, opts ...AskOpt) error {
|
||||
p.WithStdio(options.Stdio)
|
||||
}
|
||||
|
||||
// grab the user input and save it
|
||||
ans, err := q.Prompt.Prompt(&options.PromptConfig)
|
||||
// if there was a problem
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// build up a list of validators that we have to apply to this question
|
||||
validators := []Validator{}
|
||||
|
||||
// make sure to include the question specific one
|
||||
if q.Validate != nil {
|
||||
validators = append(validators, q.Validate)
|
||||
}
|
||||
// add any "global" validators
|
||||
for _, validator := range options.Validators {
|
||||
validators = append(validators, validator)
|
||||
}
|
||||
|
||||
// apply every validator to thte response
|
||||
for _, validator := range validators {
|
||||
// wait for a valid response
|
||||
for invalid := validator(ans); invalid != nil; invalid = validator(ans) {
|
||||
err := q.Prompt.Error(&options.PromptConfig, invalid)
|
||||
// if there was a problem
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// ask for more input
|
||||
if promptAgainer, ok := q.Prompt.(PromptAgainer); ok {
|
||||
ans, err = promptAgainer.PromptAgain(&options.PromptConfig, ans, invalid)
|
||||
} else {
|
||||
ans, err = q.Prompt.Prompt(&options.PromptConfig)
|
||||
}
|
||||
// if there was a problem
|
||||
if err != nil {
|
||||
var ans interface{}
|
||||
var validationErr error
|
||||
// prompt and validation loop
|
||||
for {
|
||||
if validationErr != nil {
|
||||
if err := q.Prompt.Error(&options.PromptConfig, validationErr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
var err error
|
||||
if promptAgainer, ok := q.Prompt.(PromptAgainer); ok && validationErr != nil {
|
||||
ans, err = promptAgainer.PromptAgain(&options.PromptConfig, ans, validationErr)
|
||||
} else {
|
||||
ans, err = q.Prompt.Prompt(&options.PromptConfig)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
validationErr = validate(q, ans)
|
||||
if validationErr == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if q.Transform != nil {
|
||||
@@ -341,21 +372,14 @@ func Ask(qs []*Question, response interface{}, opts ...AskOpt) error {
|
||||
}
|
||||
|
||||
// tell the prompt to cleanup with the validated value
|
||||
q.Prompt.Cleanup(&options.PromptConfig, ans)
|
||||
|
||||
// if something went wrong
|
||||
if err != nil {
|
||||
// stop listening
|
||||
if err := q.Prompt.Cleanup(&options.PromptConfig, ans); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// add it to the map
|
||||
err = core.WriteAnswer(response, q.Name, ans)
|
||||
// if something went wrong
|
||||
if err != nil {
|
||||
if err := core.WriteAnswer(response, q.Name, ans); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// return the response
|
||||
@@ -398,3 +422,41 @@ func paginate(pageSize int, choices []core.OptionAnswer, sel int) ([]core.Option
|
||||
// return the subset we care about and the index
|
||||
return choices[start:end], cursor
|
||||
}
|
||||
|
||||
type IterableOpts interface {
|
||||
IterateOption(int, core.OptionAnswer) interface{}
|
||||
}
|
||||
|
||||
func computeCursorOffset(tmpl string, data IterableOpts, opts []core.OptionAnswer, idx, tWidth int) int {
|
||||
tmpls, err := core.GetTemplatePair(tmpl)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
t := tmpls[0]
|
||||
|
||||
renderOpt := func(ix int, opt core.OptionAnswer) string {
|
||||
var buf bytes.Buffer
|
||||
_ = t.ExecuteTemplate(&buf, "option", data.IterateOption(ix, opt))
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
offset := len(opts) - idx
|
||||
|
||||
for i, o := range opts {
|
||||
if i < idx {
|
||||
continue
|
||||
}
|
||||
renderedOpt := renderOpt(i, o)
|
||||
valWidth := utf8.RuneCount([]byte(renderedOpt))
|
||||
if valWidth > tWidth {
|
||||
splitCount := valWidth / tWidth
|
||||
if valWidth%tWidth == 0 {
|
||||
splitCount -= 1
|
||||
}
|
||||
offset += splitCount
|
||||
}
|
||||
}
|
||||
|
||||
return offset
|
||||
}
|
||||
+54
-35
@@ -1,3 +1,4 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package terminal
|
||||
@@ -21,79 +22,99 @@ type Cursor struct {
|
||||
}
|
||||
|
||||
// Up moves the cursor n cells to up.
|
||||
func (c *Cursor) Up(n int) {
|
||||
fmt.Fprintf(c.Out, "\x1b[%dA", n)
|
||||
func (c *Cursor) Up(n int) error {
|
||||
_, err := fmt.Fprintf(c.Out, "\x1b[%dA", n)
|
||||
return err
|
||||
}
|
||||
|
||||
// Down moves the cursor n cells to down.
|
||||
func (c *Cursor) Down(n int) {
|
||||
fmt.Fprintf(c.Out, "\x1b[%dB", n)
|
||||
func (c *Cursor) Down(n int) error {
|
||||
_, err := fmt.Fprintf(c.Out, "\x1b[%dB", n)
|
||||
return err
|
||||
}
|
||||
|
||||
// Forward moves the cursor n cells to right.
|
||||
func (c *Cursor) Forward(n int) {
|
||||
fmt.Fprintf(c.Out, "\x1b[%dC", n)
|
||||
func (c *Cursor) Forward(n int) error {
|
||||
_, err := fmt.Fprintf(c.Out, "\x1b[%dC", n)
|
||||
return err
|
||||
}
|
||||
|
||||
// Back moves the cursor n cells to left.
|
||||
func (c *Cursor) Back(n int) {
|
||||
fmt.Fprintf(c.Out, "\x1b[%dD", n)
|
||||
func (c *Cursor) Back(n int) error {
|
||||
_, err := fmt.Fprintf(c.Out, "\x1b[%dD", n)
|
||||
return err
|
||||
}
|
||||
|
||||
// NextLine moves cursor to beginning of the line n lines down.
|
||||
func (c *Cursor) NextLine(n int) {
|
||||
fmt.Fprintf(c.Out, "\x1b[%dE", n)
|
||||
func (c *Cursor) NextLine(n int) error {
|
||||
if err := c.Down(1); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.HorizontalAbsolute(0)
|
||||
}
|
||||
|
||||
// PreviousLine moves cursor to beginning of the line n lines up.
|
||||
func (c *Cursor) PreviousLine(n int) {
|
||||
fmt.Fprintf(c.Out, "\x1b[%dF", n)
|
||||
func (c *Cursor) PreviousLine(n int) error {
|
||||
if err := c.Up(1); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.HorizontalAbsolute(0)
|
||||
}
|
||||
|
||||
// HorizontalAbsolute moves cursor horizontally to x.
|
||||
func (c *Cursor) HorizontalAbsolute(x int) {
|
||||
fmt.Fprintf(c.Out, "\x1b[%dG", x)
|
||||
func (c *Cursor) HorizontalAbsolute(x int) error {
|
||||
_, err := fmt.Fprintf(c.Out, "\x1b[%dG", x)
|
||||
return err
|
||||
}
|
||||
|
||||
// Show shows the cursor.
|
||||
func (c *Cursor) Show() {
|
||||
fmt.Fprint(c.Out, "\x1b[?25h")
|
||||
func (c *Cursor) Show() error {
|
||||
_, err := fmt.Fprint(c.Out, "\x1b[?25h")
|
||||
return err
|
||||
}
|
||||
|
||||
// Hide hide the cursor.
|
||||
func (c *Cursor) Hide() {
|
||||
fmt.Fprint(c.Out, "\x1b[?25l")
|
||||
func (c *Cursor) Hide() error {
|
||||
_, err := fmt.Fprint(c.Out, "\x1b[?25l")
|
||||
return err
|
||||
}
|
||||
|
||||
// Move moves the cursor to a specific x,y location.
|
||||
func (c *Cursor) Move(x int, y int) {
|
||||
fmt.Fprintf(c.Out, "\x1b[%d;%df", x, y)
|
||||
// move moves the cursor to a specific x,y location.
|
||||
func (c *Cursor) move(x int, y int) error {
|
||||
_, err := fmt.Fprintf(c.Out, "\x1b[%d;%df", x, y)
|
||||
return err
|
||||
}
|
||||
|
||||
// Save saves the current position
|
||||
func (c *Cursor) Save() {
|
||||
fmt.Fprint(c.Out, "\x1b7")
|
||||
func (c *Cursor) Save() error {
|
||||
_, err := fmt.Fprint(c.Out, "\x1b7")
|
||||
return err
|
||||
}
|
||||
|
||||
// Restore restores the saved position of the cursor
|
||||
func (c *Cursor) Restore() {
|
||||
fmt.Fprint(c.Out, "\x1b8")
|
||||
func (c *Cursor) Restore() error {
|
||||
_, err := fmt.Fprint(c.Out, "\x1b8")
|
||||
return err
|
||||
}
|
||||
|
||||
// for comparability purposes between windows
|
||||
// in unix we need to print out a new line on some terminals
|
||||
func (c *Cursor) MoveNextLine(cur *Coord, terminalSize *Coord) {
|
||||
func (c *Cursor) MoveNextLine(cur *Coord, terminalSize *Coord) error {
|
||||
if cur.Y == terminalSize.Y {
|
||||
fmt.Fprintln(c.Out)
|
||||
if _, err := fmt.Fprintln(c.Out); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
c.NextLine(1)
|
||||
return c.NextLine(1)
|
||||
}
|
||||
|
||||
// Location returns the current location of the cursor in the terminal
|
||||
func (c *Cursor) Location(buf *bytes.Buffer) (*Coord, error) {
|
||||
// ANSI escape sequence for DSR - Device Status Report
|
||||
// https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences
|
||||
fmt.Fprint(c.Out, "\x1b[6n")
|
||||
if _, err := fmt.Fprint(c.Out, "\x1b[6n"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// There may be input in Stdin prior to CursorLocation so make sure we don't
|
||||
// drop those bytes.
|
||||
@@ -167,11 +188,14 @@ func (c *Cursor) Size(buf *bytes.Buffer) (*Coord, error) {
|
||||
|
||||
// hide the cursor (so it doesn't blink when getting the size of the terminal)
|
||||
c.Hide()
|
||||
defer c.Show()
|
||||
|
||||
// save the current location of the cursor
|
||||
c.Save()
|
||||
defer c.Restore()
|
||||
|
||||
// move the cursor to the very bottom of the terminal
|
||||
c.Move(999, 999)
|
||||
c.move(999, 999)
|
||||
|
||||
// ask for the current location
|
||||
bottom, err := c.Location(buf)
|
||||
@@ -179,11 +203,6 @@ func (c *Cursor) Size(buf *bytes.Buffer) (*Coord, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// move back where we began
|
||||
c.Restore()
|
||||
|
||||
// show the cursor
|
||||
c.Show()
|
||||
// since the bottom was calculated in the lower right corner, it
|
||||
// is the dimensions we are looking for
|
||||
return bottom, nil
|
||||
|
||||
+62
-36
@@ -16,31 +16,37 @@ type Cursor struct {
|
||||
Out FileWriter
|
||||
}
|
||||
|
||||
func (c *Cursor) Up(n int) {
|
||||
c.cursorMove(0, n)
|
||||
func (c *Cursor) Up(n int) error {
|
||||
return c.cursorMove(0, n)
|
||||
}
|
||||
|
||||
func (c *Cursor) Down(n int) {
|
||||
c.cursorMove(0, -1*n)
|
||||
func (c *Cursor) Down(n int) error {
|
||||
return c.cursorMove(0, -1*n)
|
||||
}
|
||||
|
||||
func (c *Cursor) Forward(n int) {
|
||||
c.cursorMove(n, 0)
|
||||
func (c *Cursor) Forward(n int) error {
|
||||
return c.cursorMove(n, 0)
|
||||
}
|
||||
|
||||
func (c *Cursor) Back(n int) {
|
||||
c.cursorMove(-1*n, 0)
|
||||
func (c *Cursor) Back(n int) error {
|
||||
return c.cursorMove(-1*n, 0)
|
||||
}
|
||||
|
||||
// save the cursor location
|
||||
func (c *Cursor) Save() {
|
||||
cursorLoc, _ = c.Location(nil)
|
||||
func (c *Cursor) Save() error {
|
||||
loc, err := c.Location(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cursorLoc = *loc
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Cursor) Restore() {
|
||||
func (c *Cursor) Restore() error {
|
||||
handle := syscall.Handle(c.Out.Fd())
|
||||
// restore it to the original position
|
||||
procSetConsoleCursorPosition.Call(uintptr(handle), uintptr(*(*int32)(unsafe.Pointer(&cursorLoc))))
|
||||
_, _, err := procSetConsoleCursorPosition.Call(uintptr(handle), uintptr(*(*int32)(unsafe.Pointer(&cursorLoc))))
|
||||
return normalizeError(err)
|
||||
}
|
||||
|
||||
func (cur Coord) CursorIsAtLineEnd(size *Coord) bool {
|
||||
@@ -51,40 +57,49 @@ func (cur Coord) CursorIsAtLineBegin() bool {
|
||||
return cur.X == 0
|
||||
}
|
||||
|
||||
func (c *Cursor) cursorMove(x int, y int) {
|
||||
func (c *Cursor) cursorMove(x int, y int) error {
|
||||
handle := syscall.Handle(c.Out.Fd())
|
||||
|
||||
var csbi consoleScreenBufferInfo
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
if _, _, err := procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))); normalizeError(err) != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var cursor Coord
|
||||
cursor.X = csbi.cursorPosition.X + Short(x)
|
||||
cursor.Y = csbi.cursorPosition.Y + Short(y)
|
||||
|
||||
procSetConsoleCursorPosition.Call(uintptr(handle), uintptr(*(*int32)(unsafe.Pointer(&cursor))))
|
||||
_, _, err := procSetConsoleCursorPosition.Call(uintptr(handle), uintptr(*(*int32)(unsafe.Pointer(&cursor))))
|
||||
return normalizeError(err)
|
||||
}
|
||||
|
||||
func (c *Cursor) NextLine(n int) {
|
||||
c.Up(n)
|
||||
c.HorizontalAbsolute(0)
|
||||
func (c *Cursor) NextLine(n int) error {
|
||||
if err := c.Up(n); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.HorizontalAbsolute(0)
|
||||
}
|
||||
|
||||
func (c *Cursor) PreviousLine(n int) {
|
||||
c.Down(n)
|
||||
c.HorizontalAbsolute(0)
|
||||
func (c *Cursor) PreviousLine(n int) error {
|
||||
if err := c.Down(n); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.HorizontalAbsolute(0)
|
||||
}
|
||||
|
||||
// for comparability purposes between windows
|
||||
// in windows we don't have to print out a new line
|
||||
func (c *Cursor) MoveNextLine(cur Coord, terminalSize *Coord) {
|
||||
c.NextLine(1)
|
||||
func (c *Cursor) MoveNextLine(cur *Coord, terminalSize *Coord) error {
|
||||
return c.NextLine(1)
|
||||
}
|
||||
|
||||
func (c *Cursor) HorizontalAbsolute(x int) {
|
||||
func (c *Cursor) HorizontalAbsolute(x int) error {
|
||||
handle := syscall.Handle(c.Out.Fd())
|
||||
|
||||
var csbi consoleScreenBufferInfo
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
if _, _, err := procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))); normalizeError(err) != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var cursor Coord
|
||||
cursor.X = Short(x)
|
||||
@@ -94,43 +109,54 @@ func (c *Cursor) HorizontalAbsolute(x int) {
|
||||
cursor.X = csbi.size.X
|
||||
}
|
||||
|
||||
procSetConsoleCursorPosition.Call(uintptr(handle), uintptr(*(*int32)(unsafe.Pointer(&cursor))))
|
||||
_, _, err := procSetConsoleCursorPosition.Call(uintptr(handle), uintptr(*(*int32)(unsafe.Pointer(&cursor))))
|
||||
return normalizeError(err)
|
||||
}
|
||||
|
||||
func (c *Cursor) Show() {
|
||||
func (c *Cursor) Show() error {
|
||||
handle := syscall.Handle(c.Out.Fd())
|
||||
|
||||
var cci consoleCursorInfo
|
||||
procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&cci)))
|
||||
if _, _, err := procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&cci))); normalizeError(err) != nil {
|
||||
return err
|
||||
}
|
||||
cci.visible = 1
|
||||
|
||||
procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&cci)))
|
||||
_, _, err := procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&cci)))
|
||||
return normalizeError(err)
|
||||
}
|
||||
|
||||
func (c *Cursor) Hide() {
|
||||
func (c *Cursor) Hide() error {
|
||||
handle := syscall.Handle(c.Out.Fd())
|
||||
|
||||
var cci consoleCursorInfo
|
||||
procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&cci)))
|
||||
if _, _, err := procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&cci))); normalizeError(err) != nil {
|
||||
return err
|
||||
}
|
||||
cci.visible = 0
|
||||
|
||||
procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&cci)))
|
||||
_, _, err := procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&cci)))
|
||||
return normalizeError(err)
|
||||
}
|
||||
|
||||
func (c *Cursor) Location(buf *bytes.Buffer) (Coord, error) {
|
||||
func (c *Cursor) Location(buf *bytes.Buffer) (*Coord, error) {
|
||||
handle := syscall.Handle(c.Out.Fd())
|
||||
|
||||
var csbi consoleScreenBufferInfo
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
if _, _, err := procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))); normalizeError(err) != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return csbi.cursorPosition, nil
|
||||
return &csbi.cursorPosition, nil
|
||||
}
|
||||
|
||||
func (c *Cursor) Size(buf *bytes.Buffer) (*Coord, error) {
|
||||
handle := syscall.Handle(c.Out.Fd())
|
||||
|
||||
var csbi consoleScreenBufferInfo
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
if _, _, err := procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))); normalizeError(err) != nil {
|
||||
return nil, err
|
||||
}
|
||||
// windows' coordinate system begins at (0, 0)
|
||||
csbi.size.X--
|
||||
csbi.size.Y--
|
||||
|
||||
+3
-2
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func EraseLine(out FileWriter, mode EraseLineMode) {
|
||||
fmt.Fprintf(out, "\x1b[%dK", mode)
|
||||
func EraseLine(out FileWriter, mode EraseLineMode) error {
|
||||
_, err := fmt.Fprintf(out, "\x1b[%dK", mode)
|
||||
return err
|
||||
}
|
||||
+7
-3
@@ -5,11 +5,13 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func EraseLine(out FileWriter, mode EraseLineMode) {
|
||||
func EraseLine(out FileWriter, mode EraseLineMode) error {
|
||||
handle := syscall.Handle(out.Fd())
|
||||
|
||||
var csbi consoleScreenBufferInfo
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
if _, _, err := procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))); normalizeError(err) != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var w uint32
|
||||
var x Short
|
||||
@@ -23,5 +25,7 @@ func EraseLine(out FileWriter, mode EraseLineMode) {
|
||||
cursor.X = 0
|
||||
x = csbi.size.X
|
||||
}
|
||||
procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(x), uintptr(*(*int32)(unsafe.Pointer(&cursor))), uintptr(unsafe.Pointer(&w)))
|
||||
|
||||
_, _, err := procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(x), uintptr(*(*int32)(unsafe.Pointer(&cursor))), uintptr(unsafe.Pointer(&w)))
|
||||
return normalizeError(err)
|
||||
}
|
||||
+60
-34
@@ -12,18 +12,6 @@ import (
|
||||
"github.com/mattn/go-isatty"
|
||||
)
|
||||
|
||||
var (
|
||||
cursorFunctions = map[rune]func(c *Cursor) func(int){
|
||||
'A': func(c *Cursor) func(int) { return c.Up },
|
||||
'B': func(c *Cursor) func(int) { return c.Down },
|
||||
'C': func(c *Cursor) func(int) { return c.Forward },
|
||||
'D': func(c *Cursor) func(int) { return c.Back },
|
||||
'E': func(c *Cursor) func(int) { return c.NextLine },
|
||||
'F': func(c *Cursor) func(int) { return c.PreviousLine },
|
||||
'G': func(c *Cursor) func(int) { return c.HorizontalAbsolute },
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
foregroundBlue = 0x1
|
||||
foregroundGreen = 0x2
|
||||
@@ -67,9 +55,14 @@ func (w *Writer) Write(data []byte) (n int, err error) {
|
||||
r := bytes.NewReader(data)
|
||||
|
||||
for {
|
||||
ch, size, err := r.ReadRune()
|
||||
var ch rune
|
||||
var size int
|
||||
ch, size, err = r.ReadRune()
|
||||
if err != nil {
|
||||
break
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
n += size
|
||||
|
||||
@@ -78,22 +71,29 @@ func (w *Writer) Write(data []byte) (n int, err error) {
|
||||
size, err = w.handleEscape(r)
|
||||
n += size
|
||||
if err != nil {
|
||||
break
|
||||
return
|
||||
}
|
||||
default:
|
||||
fmt.Fprint(w.out, string(ch))
|
||||
_, err = fmt.Fprint(w.out, string(ch))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (w *Writer) handleEscape(r *bytes.Reader) (n int, err error) {
|
||||
buf := make([]byte, 0, 10)
|
||||
buf = append(buf, "\x1b"...)
|
||||
|
||||
var ch rune
|
||||
var size int
|
||||
// Check '[' continues after \x1b
|
||||
ch, size, err := r.ReadRune()
|
||||
ch, size, err = r.ReadRune()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
fmt.Fprint(w.out, string(buf))
|
||||
return
|
||||
}
|
||||
@@ -109,6 +109,9 @@ func (w *Writer) handleEscape(r *bytes.Reader) (n int, err error) {
|
||||
for {
|
||||
ch, size, err = r.ReadRune()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
fmt.Fprint(w.out, string(buf))
|
||||
return
|
||||
}
|
||||
@@ -120,47 +123,62 @@ func (w *Writer) handleEscape(r *bytes.Reader) (n int, err error) {
|
||||
argBuf = append(argBuf, string(ch)...)
|
||||
}
|
||||
|
||||
w.applyEscapeCode(buf, string(argBuf), code)
|
||||
err = w.applyEscapeCode(buf, string(argBuf), code)
|
||||
return
|
||||
}
|
||||
|
||||
func (w *Writer) applyEscapeCode(buf []byte, arg string, code rune) {
|
||||
func (w *Writer) applyEscapeCode(buf []byte, arg string, code rune) error {
|
||||
c := &Cursor{Out: w.out}
|
||||
|
||||
switch arg + string(code) {
|
||||
case "?25h":
|
||||
c.Show()
|
||||
return
|
||||
return c.Show()
|
||||
case "?25l":
|
||||
c.Hide()
|
||||
return
|
||||
return c.Hide()
|
||||
}
|
||||
|
||||
if f, ok := cursorFunctions[code]; ok {
|
||||
if code >= 'A' && code <= 'G' {
|
||||
if n, err := strconv.Atoi(arg); err == nil {
|
||||
f(c)(n)
|
||||
return
|
||||
switch code {
|
||||
case 'A':
|
||||
return c.Up(n)
|
||||
case 'B':
|
||||
return c.Down(n)
|
||||
case 'C':
|
||||
return c.Forward(n)
|
||||
case 'D':
|
||||
return c.Back(n)
|
||||
case 'E':
|
||||
return c.NextLine(n)
|
||||
case 'F':
|
||||
return c.PreviousLine(n)
|
||||
case 'G':
|
||||
return c.HorizontalAbsolute(n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch code {
|
||||
case 'm':
|
||||
w.applySelectGraphicRendition(arg)
|
||||
return w.applySelectGraphicRendition(arg)
|
||||
default:
|
||||
buf = append(buf, string(code)...)
|
||||
fmt.Fprint(w.out, string(buf))
|
||||
_, err := fmt.Fprint(w.out, string(buf))
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Original implementation: https://github.com/mattn/go-colorable
|
||||
func (w *Writer) applySelectGraphicRendition(arg string) {
|
||||
func (w *Writer) applySelectGraphicRendition(arg string) error {
|
||||
if arg == "" {
|
||||
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(w.orgAttr))
|
||||
return
|
||||
_, _, err := procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(w.orgAttr))
|
||||
return normalizeError(err)
|
||||
}
|
||||
|
||||
var csbi consoleScreenBufferInfo
|
||||
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
||||
if _, _, err := procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))); normalizeError(err) != nil {
|
||||
return err
|
||||
}
|
||||
attr := csbi.attributes
|
||||
|
||||
for _, param := range strings.Split(arg, ";") {
|
||||
@@ -223,5 +241,13 @@ func (w *Writer) applySelectGraphicRendition(arg string) {
|
||||
}
|
||||
}
|
||||
|
||||
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(attr))
|
||||
_, _, err := procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(attr))
|
||||
return normalizeError(err)
|
||||
}
|
||||
|
||||
func normalizeError(err error) error {
|
||||
if syserr, ok := err.(syscall.Errno); ok && syserr == 0 {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
+88
-32
@@ -8,9 +8,8 @@ import (
|
||||
)
|
||||
|
||||
type RuneReader struct {
|
||||
stdio Stdio
|
||||
cursor *Cursor
|
||||
state runeReaderState
|
||||
stdio Stdio
|
||||
state runeReaderState
|
||||
}
|
||||
|
||||
func NewRuneReader(stdio Stdio) *RuneReader {
|
||||
@@ -20,18 +19,25 @@ func NewRuneReader(stdio Stdio) *RuneReader {
|
||||
}
|
||||
}
|
||||
|
||||
func (rr *RuneReader) printChar(char rune, mask rune) {
|
||||
func (rr *RuneReader) printChar(char rune, mask rune) error {
|
||||
// if we don't need to mask the input
|
||||
if mask == 0 {
|
||||
// just print the character the user pressed
|
||||
fmt.Fprintf(rr.stdio.Out, "%c", char)
|
||||
} else {
|
||||
// otherwise print the mask we were given
|
||||
fmt.Fprintf(rr.stdio.Out, "%c", mask)
|
||||
_, err := fmt.Fprintf(rr.stdio.Out, "%c", char)
|
||||
return err
|
||||
}
|
||||
// otherwise print the mask we were given
|
||||
_, err := fmt.Fprintf(rr.stdio.Out, "%c", mask)
|
||||
return err
|
||||
}
|
||||
|
||||
func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
||||
type OnRuneFn func(rune, []rune) ([]rune, bool, error)
|
||||
|
||||
func (rr *RuneReader) ReadLine(mask rune, onRunes ...OnRuneFn) ([]rune, error) {
|
||||
return rr.ReadLineWithDefault(mask, []rune{}, onRunes...)
|
||||
}
|
||||
|
||||
func (rr *RuneReader) ReadLineWithDefault(mask rune, d []rune, onRunes ...OnRuneFn) ([]rune, error) {
|
||||
line := []rune{}
|
||||
// we only care about horizontal displacements from the origin so start counting at 0
|
||||
index := 0
|
||||
@@ -41,19 +47,58 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
||||
Out: rr.stdio.Out,
|
||||
}
|
||||
|
||||
onRune := func(r rune, line []rune) ([]rune, bool, error) {
|
||||
return line, false, nil
|
||||
}
|
||||
|
||||
// if the user pressed a key the caller was interested in capturing
|
||||
if len(onRunes) > 0 {
|
||||
onRune = onRunes[0]
|
||||
}
|
||||
|
||||
// we get the terminal width and height (if resized after this point the property might become invalid)
|
||||
terminalSize, _ := cursor.Size(rr.Buffer())
|
||||
// we set the current location of the cursor once
|
||||
cursorCurrent, _ := cursor.Location(rr.Buffer())
|
||||
|
||||
increment := func() {
|
||||
if cursorCurrent.CursorIsAtLineEnd(terminalSize) {
|
||||
cursorCurrent.X = COORDINATE_SYSTEM_BEGIN
|
||||
cursorCurrent.Y++
|
||||
} else {
|
||||
cursorCurrent.X++
|
||||
}
|
||||
}
|
||||
decrement := func() {
|
||||
if cursorCurrent.CursorIsAtLineBegin() {
|
||||
cursorCurrent.X = terminalSize.X
|
||||
cursorCurrent.Y--
|
||||
} else {
|
||||
cursorCurrent.X--
|
||||
}
|
||||
}
|
||||
|
||||
if len(d) > 0 {
|
||||
index = len(d)
|
||||
if _, err := fmt.Fprint(rr.stdio.Out, string(d)); err != nil {
|
||||
return d, err
|
||||
}
|
||||
line = d
|
||||
for range d {
|
||||
increment()
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
// wait for some input
|
||||
r, _, err := rr.ReadRune()
|
||||
if err != nil {
|
||||
return line, err
|
||||
}
|
||||
// increment cursor location
|
||||
cursorCurrent.X++
|
||||
|
||||
if l, stop, err := onRune(r, line); stop || err != nil {
|
||||
return l, err
|
||||
}
|
||||
|
||||
// if the user pressed enter or some other newline/termination like ctrl+d
|
||||
if r == '\r' || r == '\n' || r == KeyEndTransmission {
|
||||
@@ -63,13 +108,10 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
||||
EraseLine(rr.stdio.Out, ERASE_LINE_END)
|
||||
cursor.PreviousLine(1)
|
||||
cursor.Forward(int(terminalSize.X))
|
||||
cursorCurrent.X = terminalSize.X
|
||||
cursorCurrent.Y--
|
||||
|
||||
} else {
|
||||
cursor.Back(1)
|
||||
cursorCurrent.X--
|
||||
}
|
||||
decrement()
|
||||
index--
|
||||
}
|
||||
// move the cursor the a new line
|
||||
@@ -81,7 +123,9 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
||||
// if the user interrupts (ie with ctrl+c)
|
||||
if r == KeyInterrupt {
|
||||
// go to the beginning of the next line
|
||||
fmt.Fprint(rr.stdio.Out, "\r\n")
|
||||
if _, err := fmt.Fprint(rr.stdio.Out, "\r\n"); err != nil {
|
||||
return line, err
|
||||
}
|
||||
|
||||
// we're done processing the input, and treat interrupt like an error
|
||||
return line, InterruptErr
|
||||
@@ -128,8 +172,9 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
||||
//Erase symbols which are left over from older print
|
||||
EraseLine(rr.stdio.Out, ERASE_LINE_END)
|
||||
// print characters to the new line appropriately
|
||||
rr.printChar(char, mask)
|
||||
|
||||
if err := rr.printChar(char, mask); err != nil {
|
||||
return line, err
|
||||
}
|
||||
}
|
||||
// erase what's left over from last print
|
||||
if cursorCurrent.Y < terminalSize.Y {
|
||||
@@ -148,9 +193,10 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
||||
|
||||
// decrement the index
|
||||
index--
|
||||
decrement()
|
||||
} else {
|
||||
// otherwise the user pressed backspace while at the beginning of the line
|
||||
soundBell(rr.stdio.Out)
|
||||
_ = soundBell(rr.stdio.Out)
|
||||
}
|
||||
|
||||
// we're done processing this key
|
||||
@@ -170,11 +216,12 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
||||
}
|
||||
//decrement the index
|
||||
index--
|
||||
decrement()
|
||||
|
||||
} else {
|
||||
// otherwise we are at the beginning of where we started reading lines
|
||||
// sound the bell
|
||||
soundBell(rr.stdio.Out)
|
||||
_ = soundBell(rr.stdio.Out)
|
||||
}
|
||||
|
||||
// we're done processing this key press
|
||||
@@ -192,11 +239,12 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
||||
cursor.Forward(runeWidth(line[index]))
|
||||
}
|
||||
index++
|
||||
increment()
|
||||
|
||||
} else {
|
||||
// otherwise we are at the end of the word and can't go past
|
||||
// sound the bell
|
||||
soundBell(rr.stdio.Out)
|
||||
_ = soundBell(rr.stdio.Out)
|
||||
}
|
||||
|
||||
// we're done processing this key press
|
||||
@@ -208,12 +256,11 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
||||
if cursorCurrent.CursorIsAtLineBegin() {
|
||||
cursor.PreviousLine(1)
|
||||
cursor.Forward(int(terminalSize.X))
|
||||
cursorCurrent.X = terminalSize.X
|
||||
cursorCurrent.Y--
|
||||
|
||||
cursorCurrent.X = terminalSize.X
|
||||
} else {
|
||||
cursor.Back(runeWidth(line[index-1]))
|
||||
cursorCurrent.X--
|
||||
cursorCurrent.X -= Short(runeWidth(line[index-1]))
|
||||
}
|
||||
index--
|
||||
}
|
||||
@@ -223,12 +270,11 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
||||
for index != len(line) {
|
||||
if cursorCurrent.CursorIsAtLineEnd(terminalSize) {
|
||||
cursor.NextLine(1)
|
||||
cursorCurrent.X = COORDINATE_SYSTEM_BEGIN
|
||||
cursorCurrent.Y++
|
||||
|
||||
cursorCurrent.X = COORDINATE_SYSTEM_BEGIN
|
||||
} else {
|
||||
cursor.Forward(runeWidth(line[index]))
|
||||
cursorCurrent.X++
|
||||
cursorCurrent.X += Short(runeWidth(line[index]))
|
||||
}
|
||||
index++
|
||||
}
|
||||
@@ -247,7 +293,9 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
||||
for _, char := range line[index:] {
|
||||
EraseLine(rr.stdio.Out, ERASE_LINE_END)
|
||||
// print out the character
|
||||
rr.printChar(char, mask)
|
||||
if err := rr.printChar(char, mask); err != nil {
|
||||
return line, err
|
||||
}
|
||||
}
|
||||
// erase what's left on last line
|
||||
if cursorCurrent.Y < terminalSize.Y {
|
||||
@@ -277,8 +325,11 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
||||
line = append(line, r)
|
||||
// save the location of the cursor
|
||||
index++
|
||||
increment()
|
||||
// print out the character
|
||||
rr.printChar(r, mask)
|
||||
if err := rr.printChar(r, mask); err != nil {
|
||||
return line, err
|
||||
}
|
||||
} else {
|
||||
// we are in the middle of the word so we need to insert the character the user pressed
|
||||
line = append(line[:index], append([]rune{r}, line[index:]...)...)
|
||||
@@ -292,13 +343,17 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
||||
for _, char := range line[index:] {
|
||||
EraseLine(rr.stdio.Out, ERASE_LINE_END)
|
||||
// print out the character
|
||||
rr.printChar(char, mask)
|
||||
cursorCurrent.X++
|
||||
if err := rr.printChar(char, mask); err != nil {
|
||||
return line, err
|
||||
}
|
||||
increment()
|
||||
}
|
||||
// if we are at the last line, we want to visually insert a new line and append to it.
|
||||
if cursorCurrent.CursorIsAtLineEnd(terminalSize) && cursorCurrent.Y == terminalSize.Y {
|
||||
// add a new line to the terminal
|
||||
fmt.Fprintln(rr.stdio.Out)
|
||||
if _, err := fmt.Fprintln(rr.stdio.Out); err != nil {
|
||||
return line, err
|
||||
}
|
||||
// restore the position of the cursor horizontally
|
||||
cursor.Restore()
|
||||
// restore the position of the cursor vertically
|
||||
@@ -316,6 +371,7 @@ func (rr *RuneReader) ReadLine(mask rune) ([]rune, error) {
|
||||
}
|
||||
// increment the index
|
||||
index++
|
||||
increment()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+61
-41
@@ -16,6 +16,11 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
normalKeypad = '['
|
||||
applicationKeypad = 'O'
|
||||
)
|
||||
|
||||
type runeReaderState struct {
|
||||
term syscall.Termios
|
||||
reader *bufio.Reader
|
||||
@@ -45,6 +50,11 @@ func (rr *RuneReader) SetTermMode() error {
|
||||
|
||||
newState := rr.state.term
|
||||
newState.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG
|
||||
// Because we are clearing canonical mode, we need to ensure VMIN & VTIME are
|
||||
// set to the values we expect. This combination puts things in standard
|
||||
// "blocking read" mode (see termios(3)).
|
||||
newState.Cc[syscall.VMIN] = 1
|
||||
newState.Cc[syscall.VTIME] = 0
|
||||
|
||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(rr.stdio.In.Fd()), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
|
||||
return err
|
||||
@@ -60,52 +70,62 @@ func (rr *RuneReader) RestoreTermMode() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadRune Parse escape sequences such as ESC [ A for arrow keys.
|
||||
// See https://vt100.net/docs/vt102-ug/appendixc.html
|
||||
func (rr *RuneReader) ReadRune() (rune, int, error) {
|
||||
r, size, err := rr.state.reader.ReadRune()
|
||||
if err != nil {
|
||||
return r, size, err
|
||||
}
|
||||
|
||||
// parse ^[ sequences to look for arrow keys
|
||||
if r == '\033' {
|
||||
if rr.state.reader.Buffered() == 0 {
|
||||
// no more characters so must be `Esc` key
|
||||
return KeyEscape, 1, nil
|
||||
}
|
||||
r, size, err = rr.state.reader.ReadRune()
|
||||
if err != nil {
|
||||
return r, size, err
|
||||
}
|
||||
if r != '[' {
|
||||
return r, size, fmt.Errorf("Unexpected Escape Sequence: %q", []rune{'\033', r})
|
||||
}
|
||||
r, size, err = rr.state.reader.ReadRune()
|
||||
if err != nil {
|
||||
return r, size, err
|
||||
}
|
||||
switch r {
|
||||
case 'D':
|
||||
return KeyArrowLeft, 1, nil
|
||||
case 'C':
|
||||
return KeyArrowRight, 1, nil
|
||||
case 'A':
|
||||
return KeyArrowUp, 1, nil
|
||||
case 'B':
|
||||
return KeyArrowDown, 1, nil
|
||||
case 'H': // Home button
|
||||
return SpecialKeyHome, 1, nil
|
||||
case 'F': // End button
|
||||
return SpecialKeyEnd, 1, nil
|
||||
case '3': // Delete Button
|
||||
// discard the following '~' key from buffer
|
||||
rr.state.reader.Discard(1)
|
||||
return SpecialKeyDelete, 1, nil
|
||||
default:
|
||||
// discard the following '~' key from buffer
|
||||
rr.state.reader.Discard(1)
|
||||
return IgnoreKey, 1, nil
|
||||
}
|
||||
return r, size, fmt.Errorf("Unknown Escape Sequence: %q", []rune{'\033', '[', r})
|
||||
if r != KeyEscape {
|
||||
return r, size, err
|
||||
}
|
||||
return r, size, err
|
||||
|
||||
if rr.state.reader.Buffered() == 0 {
|
||||
// no more characters so must be `Esc` key
|
||||
return KeyEscape, 1, nil
|
||||
}
|
||||
|
||||
r, size, err = rr.state.reader.ReadRune()
|
||||
if err != nil {
|
||||
return r, size, err
|
||||
}
|
||||
|
||||
// ESC O ... or ESC [ ...?
|
||||
if r != normalKeypad && r != applicationKeypad {
|
||||
return r, size, fmt.Errorf("unexpected escape sequence from terminal: %q", []rune{KeyEscape, r})
|
||||
}
|
||||
|
||||
keypad := r
|
||||
|
||||
r, size, err = rr.state.reader.ReadRune()
|
||||
if err != nil {
|
||||
return r, size, err
|
||||
}
|
||||
|
||||
switch r {
|
||||
case 'A': // ESC [ A or ESC O A
|
||||
return KeyArrowUp, 1, nil
|
||||
case 'B': // ESC [ B or ESC O B
|
||||
return KeyArrowDown, 1, nil
|
||||
case 'C': // ESC [ C or ESC O C
|
||||
return KeyArrowRight, 1, nil
|
||||
case 'D': // ESC [ D or ESC O D
|
||||
return KeyArrowLeft, 1, nil
|
||||
case 'F': // ESC [ F or ESC O F
|
||||
return SpecialKeyEnd, 1, nil
|
||||
case 'H': // ESC [ H or ESC O H
|
||||
return SpecialKeyHome, 1, nil
|
||||
case '3': // ESC [ 3
|
||||
if keypad == normalKeypad {
|
||||
// discard the following '~' key from buffer
|
||||
_, _ = rr.state.reader.Discard(1)
|
||||
return SpecialKeyDelete, 1, nil
|
||||
}
|
||||
}
|
||||
|
||||
// discard the following '~' key from buffer
|
||||
_, _ = rr.state.reader.Discard(1)
|
||||
return IgnoreKey, 1, nil
|
||||
}
|
||||
+3
-2
@@ -26,6 +26,7 @@ const (
|
||||
KeyTab = '\t'
|
||||
)
|
||||
|
||||
func soundBell(out io.Writer) {
|
||||
fmt.Fprint(out, "\a")
|
||||
func soundBell(out io.Writer) error {
|
||||
_, err := fmt.Fprint(out, "\a")
|
||||
return err
|
||||
}
|
||||
+7
-4
@@ -18,18 +18,21 @@ func TransformString(f func(s string) string) Transformer {
|
||||
return func(ans interface{}) interface{} {
|
||||
// if the answer value passed in is the zero value of the appropriate type
|
||||
if isZero(reflect.ValueOf(ans)) {
|
||||
// skip this `Transformer` by returning a nil value.
|
||||
// skip this `Transformer` by returning a zero value of string.
|
||||
// The original answer will be not affected,
|
||||
// see survey.go#L125.
|
||||
return nil
|
||||
// A zero value of string should be returned to be handled by
|
||||
// next Transformer in a composed Tranformer,
|
||||
// see tranform.go#L75
|
||||
return ""
|
||||
}
|
||||
|
||||
// "ans" is never nil here, so we don't have to check that
|
||||
// see survey.go#L97 for more.
|
||||
// see survey.go#L338 for more.
|
||||
// Make sure that the the answer's value was a typeof string.
|
||||
s, ok := ans.(string)
|
||||
if !ok {
|
||||
return nil
|
||||
return ""
|
||||
}
|
||||
|
||||
return f(s)
|
||||
|
||||
+40
@@ -4,6 +4,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2/core"
|
||||
)
|
||||
|
||||
// Required does not allow an empty value
|
||||
@@ -58,6 +60,44 @@ func MinLength(length int) Validator {
|
||||
}
|
||||
}
|
||||
|
||||
// MaxItems requires that the list is no longer than the specified value
|
||||
func MaxItems(numberItems int) Validator {
|
||||
// return a validator that checks the length of the list
|
||||
return func(val interface{}) error {
|
||||
if list, ok := val.([]core.OptionAnswer); ok {
|
||||
// if the list is longer than the given value
|
||||
if len(list) > numberItems {
|
||||
// yell loudly
|
||||
return fmt.Errorf("value is too long. Max items is %v", numberItems)
|
||||
}
|
||||
} else {
|
||||
// otherwise we cannot convert the value into a list of answer and cannot enforce length
|
||||
return fmt.Errorf("cannot impose the length on something other than a list of answers")
|
||||
}
|
||||
// the input is fine
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// MinItems requires that the list is longer or equal in length to the specified value
|
||||
func MinItems(numberItems int) Validator {
|
||||
// return a validator that checks the length of the list
|
||||
return func(val interface{}) error {
|
||||
if list, ok := val.([]core.OptionAnswer); ok {
|
||||
// if the list is shorter than the given value
|
||||
if len(list) < numberItems {
|
||||
// yell loudly
|
||||
return fmt.Errorf("value is too short. Min items is %v", numberItems)
|
||||
}
|
||||
} else {
|
||||
// otherwise we cannot convert the value into a list of answer and cannot enforce length
|
||||
return fmt.Errorf("cannot impose the length on something other than a list of answers")
|
||||
}
|
||||
// the input is fine
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ComposeValidators is a variadic function used to create one validator from many.
|
||||
func ComposeValidators(validators ...Validator) Validator {
|
||||
// return a validator that calls each one sequentially
|
||||
|
||||
+16
@@ -25,6 +25,17 @@ linters:
|
||||
- testpackage
|
||||
- godot
|
||||
- nestif
|
||||
- paralleltest
|
||||
- nlreturn
|
||||
- cyclop
|
||||
- exhaustivestruct
|
||||
- gci
|
||||
- gofumpt
|
||||
- errorlint
|
||||
- exhaustive
|
||||
- ifshort
|
||||
- wrapcheck
|
||||
- stylecheck
|
||||
|
||||
linters-settings:
|
||||
govet:
|
||||
@@ -36,6 +47,11 @@ linters-settings:
|
||||
goconst:
|
||||
min-len: 8
|
||||
min-occurrences: 3
|
||||
forbidigo:
|
||||
forbid:
|
||||
- (Must)?NewLexer
|
||||
exclude_godoc_examples: false
|
||||
|
||||
|
||||
issues:
|
||||
max-per-linter: 0
|
||||
|
||||
+5
-1
@@ -6,17 +6,21 @@ release:
|
||||
brews:
|
||||
-
|
||||
install: bin.install "chroma"
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
builds:
|
||||
- goos:
|
||||
- linux
|
||||
- darwin
|
||||
- windows
|
||||
goarch:
|
||||
- arm64
|
||||
- amd64
|
||||
- "386"
|
||||
goarm:
|
||||
- "6"
|
||||
main: ./cmd/chroma/main.go
|
||||
dir: ./cmd/chroma
|
||||
main: .
|
||||
ldflags: -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}
|
||||
binary: chroma
|
||||
archives:
|
||||
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
sudo: false
|
||||
language: go
|
||||
go:
|
||||
- "1.13.x"
|
||||
script:
|
||||
- go test -v ./...
|
||||
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s v1.26.0
|
||||
- ./bin/golangci-lint run
|
||||
- git clean -fdx .
|
||||
after_success:
|
||||
curl -sL https://git.io/goreleaser | bash && goreleaser
|
||||
|
||||
+3
-3
@@ -1,5 +1,7 @@
|
||||
.PHONY: chromad upload all
|
||||
|
||||
VERSION ?= $(shell git describe --tags --dirty --always)
|
||||
|
||||
all: README.md tokentype_string.go
|
||||
|
||||
README.md: lexers/*/*.go
|
||||
@@ -9,10 +11,8 @@ tokentype_string.go: types.go
|
||||
go generate
|
||||
|
||||
chromad:
|
||||
(cd ./cmd/chromad && go get github.com/GeertJohan/go.rice/rice@master && go install github.com/GeertJohan/go.rice/rice)
|
||||
rm -f chromad
|
||||
(export CGOENABLED=0 GOOS=linux ; cd ./cmd/chromad && go build -o ../../chromad .)
|
||||
rice append -i ./cmd/chromad --exec=./chromad
|
||||
(export CGOENABLED=0 GOOS=linux GOARCH=amd64; cd ./cmd/chromad && go build -ldflags="-X 'main.version=$(VERSION)'" -o ../../chromad .)
|
||||
|
||||
upload: chromad
|
||||
scp chromad [email protected]: && \
|
||||
|
||||
+39
-21
@@ -1,4 +1,5 @@
|
||||
# Chroma — A general purpose syntax highlighter in pure Go [](https://godoc.org/github.com/alecthomas/chroma) [](https://travis-ci.org/alecthomas/chroma) [](https://gitter.im/alecthomas/Lobby)
|
||||
# Chroma — A general purpose syntax highlighter in pure Go
|
||||
[](https://godoc.org/github.com/alecthomas/chroma) [](https://github.com/alecthomas/chroma/actions/workflows/ci.yml) [](https://invite.slack.golangbridge.org/)
|
||||
|
||||
> **NOTE:** As Chroma has just been released, its API is still in flux. That said, the high-level interface should not change significantly.
|
||||
|
||||
@@ -36,29 +37,30 @@ translators for Pygments lexers and styles.
|
||||
Prefix | Language
|
||||
:----: | --------
|
||||
A | ABAP, ABNF, ActionScript, ActionScript 3, Ada, Angular2, ANTLR, ApacheConf, APL, AppleScript, Arduino, Awk
|
||||
B | Ballerina, Base Makefile, Bash, Batchfile, BlitzBasic, BNF, Brainfuck
|
||||
C | C, C#, C++, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Crystal, CSS, Cython
|
||||
D | D, Dart, Diff, Django/Jinja, Docker, DTD
|
||||
B | Ballerina, Base Makefile, Bash, Batchfile, BibTeX, Bicep, BlitzBasic, BNF, Brainfuck
|
||||
C | C, C#, C++, Caddyfile, Caddyfile Directives, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Crystal, CSS, Cython
|
||||
D | D, Dart, Diff, Django/Jinja, Docker, DTD, Dylan
|
||||
E | EBNF, Elixir, Elm, EmacsLisp, Erlang
|
||||
F | Factor, Fish, Forth, Fortran, FSharp
|
||||
G | GAS, GDScript, Genshi, Genshi HTML, Genshi Text, GLSL, Gnuplot, Go, Go HTML Template, Go Text Template, GraphQL, Groovy
|
||||
H | Handlebars, Haskell, Haxe, HCL, Hexdump, HTML, HTTP, Hy
|
||||
I | Idris, INI, Io
|
||||
G | GAS, GDScript, Genshi, Genshi HTML, Genshi Text, Gherkin, GLSL, Gnuplot, Go, Go HTML Template, Go Text Template, GraphQL, Groff, Groovy
|
||||
H | Handlebars, Haskell, Haxe, HCL, Hexdump, HLB, HTML, HTTP, Hy
|
||||
I | Idris, Igor, INI, Io
|
||||
J | J, Java, JavaScript, JSON, Julia, Jungle
|
||||
K | Kotlin
|
||||
L | Lighttpd configuration file, LLVM, Lua
|
||||
M | Mako, markdown, Mason, Mathematica, Matlab, MiniZinc, MLIR, Modula-2, MonkeyC, MorrowindScript, Myghty, MySQL
|
||||
N | NASM, Newspeak, Nginx configuration file, Nim, Nix
|
||||
O | Objective-C, OCaml, Octave, OpenSCAD, Org Mode
|
||||
P | PacmanConf, Perl, PHP, Pig, PkgConfig, PL/pgSQL, plaintext, PostgreSQL SQL dialect, PostScript, POVRay, PowerShell, Prolog, Protocol Buffer, Puppet, Python, Python 3
|
||||
O | Objective-C, OCaml, Octave, OnesEnterprise, OpenEdge ABL, OpenSCAD, Org Mode
|
||||
P | PacmanConf, Perl, PHP, PHTML, Pig, PkgConfig, PL/pgSQL, plaintext, Pony, PostgreSQL SQL dialect, PostScript, POVRay, PowerShell, Prolog, PromQL, Protocol Buffer, Puppet, Python 2, Python
|
||||
Q | QBasic
|
||||
R | R, Racket, Ragel, react, reg, reStructuredText, Rexx, Ruby, Rust
|
||||
S | Sass, Scala, Scheme, Scilab, SCSS, Smalltalk, Smarty, SML, Snobol, Solidity, SPARQL, SQL, SquidConf, Swift, SYSTEMD, systemverilog
|
||||
R | R, Racket, Ragel, Raku, react, ReasonML, reg, reStructuredText, Rexx, Ruby, Rust
|
||||
S | SAS, Sass, Scala, Scheme, Scilab, SCSS, Smalltalk, Smarty, Snobol, Solidity, SPARQL, SQL, SquidConf, Standard ML, Stylus, Svelte, Swift, SYSTEMD, systemverilog
|
||||
T | TableGen, TASM, Tcl, Tcsh, Termcap, Terminfo, Terraform, TeX, Thrift, TOML, TradingView, Transact-SQL, Turing, Turtle, Twig, TypeScript, TypoScript, TypoScriptCssData, TypoScriptHtmlData
|
||||
V | VB.net, verilog, VHDL, VimL, vue
|
||||
W | WDTE
|
||||
X | XML, Xorg
|
||||
Y | YAML
|
||||
Y | YAML, YANG
|
||||
Z | Zig
|
||||
|
||||
|
||||
_I will attempt to keep this section up to date, but an authoritative list can be
|
||||
@@ -183,7 +185,7 @@ following constructor options:
|
||||
- `ClassPrefix(prefix)` - prefix each generated CSS class.
|
||||
- `TabWidth(width)` - Set the rendered tab width, in characters.
|
||||
- `WithLineNumbers()` - Render line numbers (style with `LineNumbers`).
|
||||
- `LinkableLineNumbers()` - Make the line numbers linkable.
|
||||
- `LinkableLineNumbers()` - Make the line numbers linkable and be a link to themselves.
|
||||
- `HighlightLines(ranges)` - Highlight lines in these ranges (style with `LineHighlight`).
|
||||
- `LineNumbersInTable()` - Use a table for formatting line numbers and code, rather than spans.
|
||||
|
||||
@@ -209,13 +211,13 @@ using the included Python 3 script `pygments2chroma.py`. I use something like
|
||||
the following:
|
||||
|
||||
```sh
|
||||
python3 ~/Projects/chroma/_tools/pygments2chroma.py \
|
||||
python3 _tools/pygments2chroma.py \
|
||||
pygments.lexers.jvm.KotlinLexer \
|
||||
> ~/Projects/chroma/lexers/kotlin.go \
|
||||
&& gofmt -s -w ~/Projects/chroma/lexers/*.go
|
||||
> lexers/k/kotlin.go \
|
||||
&& gofmt -s -w lexers/k/kotlin.go
|
||||
```
|
||||
|
||||
See notes in [pygments-lexers.go](https://github.com/alecthomas/chroma/blob/master/pygments-lexers.txt)
|
||||
See notes in [pygments-lexers.txt](https://github.com/alecthomas/chroma/blob/master/pygments-lexers.txt)
|
||||
for a list of lexers, and notes on some of the issues importing them.
|
||||
|
||||
<a id="markdown-formatters" name="formatters"></a>
|
||||
@@ -248,18 +250,34 @@ For a quick overview of the available styles and how they look, check out the [C
|
||||
<a id="markdown-command-line-interface" name="command-line-interface"></a>
|
||||
## Command-line interface
|
||||
|
||||
A command-line interface to Chroma is included. It can be installed with:
|
||||
A command-line interface to Chroma is included.
|
||||
|
||||
```sh
|
||||
go get -u github.com/alecthomas/chroma/cmd/chroma
|
||||
Binaries are available to install from [the releases page](https://github.com/alecthomas/chroma/releases).
|
||||
|
||||
The CLI can be used as a preprocessor to colorise output of `less(1)`,
|
||||
see documentation for the `LESSOPEN` environment variable.
|
||||
|
||||
The `--fail` flag can be used to suppress output and return with exit status
|
||||
1 to facilitate falling back to some other preprocessor in case chroma
|
||||
does not resolve a specific lexer to use for the given file. For example:
|
||||
|
||||
```shell
|
||||
export LESSOPEN='| p() { chroma --fail "$1" || cat "$1"; }; p "%s"'
|
||||
```
|
||||
|
||||
Replace `cat` with your favourite fallback preprocessor.
|
||||
|
||||
When invoked as `.lessfilter`, the `--fail` flag is automatically turned
|
||||
on under the hood for easy integration with [lesspipe shipping with
|
||||
Debian and derivatives](https://manpages.debian.org/lesspipe#USER_DEFINED_FILTERS);
|
||||
for that setup the `chroma` executable can be just symlinked to `~/.lessfilter`.
|
||||
|
||||
<a id="markdown-whats-missing-compared-to-pygments" name="whats-missing-compared-to-pygments"></a>
|
||||
## What's missing compared to Pygments?
|
||||
|
||||
- Quite a few lexers, for various reasons (pull-requests welcome):
|
||||
- Pygments lexers for complex languages often include custom code to
|
||||
handle certain aspects, such as Perl6's ability to nest code inside
|
||||
handle certain aspects, such as Raku's ability to nest code inside
|
||||
regular expressions. These require time and effort to convert.
|
||||
- I mostly only converted languages I had heard of, to reduce the porting cost.
|
||||
- Some more esoteric features of Pygments are omitted for simplicity.
|
||||
|
||||
+74
-17
@@ -46,6 +46,13 @@ func WithPreWrapper(wrapper PreWrapper) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WrapLongLines wraps long lines.
|
||||
func WrapLongLines(b bool) Option {
|
||||
return func(f *Formatter) {
|
||||
f.wrapLongLines = b
|
||||
}
|
||||
}
|
||||
|
||||
// WithLineNumbers formats output with line numbers.
|
||||
func WithLineNumbers(b bool) Option {
|
||||
return func(f *Formatter) {
|
||||
@@ -131,10 +138,18 @@ var (
|
||||
}
|
||||
defaultPreWrapper = preWrapper{
|
||||
start: func(code bool, styleAttr string) string {
|
||||
return fmt.Sprintf("<pre%s>", styleAttr)
|
||||
if code {
|
||||
return fmt.Sprintf(`<pre tabindex="0"%s><code>`, styleAttr)
|
||||
}
|
||||
|
||||
return fmt.Sprintf(`<pre tabindex="0"%s>`, styleAttr)
|
||||
},
|
||||
end: func(code bool) string {
|
||||
return "</pre>"
|
||||
if code {
|
||||
return `</code></pre>`
|
||||
}
|
||||
|
||||
return `</pre>`
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -147,6 +162,7 @@ type Formatter struct {
|
||||
allClasses bool
|
||||
preWrapper PreWrapper
|
||||
tabWidth int
|
||||
wrapLongLines bool
|
||||
lineNumbers bool
|
||||
lineNumbersInTable bool
|
||||
linkableLineNumbers bool
|
||||
@@ -197,10 +213,10 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
|
||||
|
||||
if wrapInTable {
|
||||
// List line numbers in its own <td>
|
||||
fmt.Fprintf(w, "<div%s>\n", f.styleAttr(css, chroma.Background))
|
||||
fmt.Fprintf(w, "<div%s>\n", f.styleAttr(css, chroma.PreWrapper))
|
||||
fmt.Fprintf(w, "<table%s><tr>", f.styleAttr(css, chroma.LineTable))
|
||||
fmt.Fprintf(w, "<td%s>\n", f.styleAttr(css, chroma.LineTableTD))
|
||||
fmt.Fprintf(w, f.preWrapper.Start(false, f.styleAttr(css, chroma.Background)))
|
||||
fmt.Fprintf(w, f.preWrapper.Start(false, f.styleAttr(css, chroma.PreWrapper)))
|
||||
for index := range lines {
|
||||
line := f.baseLineNumber + index
|
||||
highlight, next := f.shouldHighlight(highlightIndex, line)
|
||||
@@ -211,7 +227,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
|
||||
fmt.Fprintf(w, "<span%s>", f.styleAttr(css, chroma.LineHighlight))
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "<span%s%s>%*d\n</span>", f.styleAttr(css, chroma.LineNumbersTable), f.lineIDAttribute(line), lineDigits, line)
|
||||
fmt.Fprintf(w, "<span%s%s>%s\n</span>", f.styleAttr(css, chroma.LineNumbersTable), f.lineIDAttribute(line), f.lineTitleWithLinkIfNeeded(lineDigits, line))
|
||||
|
||||
if highlight {
|
||||
fmt.Fprintf(w, "</span>")
|
||||
@@ -222,7 +238,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
|
||||
fmt.Fprintf(w, "<td%s>\n", f.styleAttr(css, chroma.LineTableTD, "width:100%"))
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, f.preWrapper.Start(true, f.styleAttr(css, chroma.Background)))
|
||||
fmt.Fprintf(w, f.preWrapper.Start(true, f.styleAttr(css, chroma.PreWrapper)))
|
||||
|
||||
highlightIndex = 0
|
||||
for index, tokens := range lines {
|
||||
@@ -232,14 +248,28 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
|
||||
if next {
|
||||
highlightIndex++
|
||||
}
|
||||
|
||||
// Start of Line
|
||||
fmt.Fprint(w, `<span`)
|
||||
if highlight {
|
||||
fmt.Fprintf(w, "<span%s>", f.styleAttr(css, chroma.LineHighlight))
|
||||
// Line + LineHighlight
|
||||
if f.Classes {
|
||||
fmt.Fprintf(w, ` class="%s %s"`, f.class(chroma.Line), f.class(chroma.LineHighlight))
|
||||
} else {
|
||||
fmt.Fprintf(w, ` style="%s %s"`, css[chroma.Line], css[chroma.LineHighlight])
|
||||
}
|
||||
fmt.Fprint(w, `>`)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s>", f.styleAttr(css, chroma.Line))
|
||||
}
|
||||
|
||||
// Line number
|
||||
if f.lineNumbers && !wrapInTable {
|
||||
fmt.Fprintf(w, "<span%s%s>%*d</span>", f.styleAttr(css, chroma.LineNumbers), f.lineIDAttribute(line), lineDigits, line)
|
||||
fmt.Fprintf(w, "<span%s%s>%s</span>", f.styleAttr(css, chroma.LineNumbers), f.lineIDAttribute(line), f.lineTitleWithLinkIfNeeded(lineDigits, line))
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, `<span%s>`, f.styleAttr(css, chroma.CodeLine))
|
||||
|
||||
for _, token := range tokens {
|
||||
html := html.EscapeString(token.String())
|
||||
attr := f.styleAttr(css, token.Type)
|
||||
@@ -248,9 +278,10 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
|
||||
}
|
||||
fmt.Fprint(w, html)
|
||||
}
|
||||
if highlight {
|
||||
fmt.Fprintf(w, "</span>")
|
||||
}
|
||||
|
||||
fmt.Fprint(w, `</span>`) // End of CodeLine
|
||||
|
||||
fmt.Fprint(w, `</span>`) // End of Line
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, f.preWrapper.End(true))
|
||||
@@ -272,7 +303,19 @@ func (f *Formatter) lineIDAttribute(line int) string {
|
||||
if !f.linkableLineNumbers {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf(" id=\"%s%d\"", f.lineNumbersIDPrefix, line)
|
||||
return fmt.Sprintf(" id=\"%s\"", f.lineID(line))
|
||||
}
|
||||
|
||||
func (f *Formatter) lineTitleWithLinkIfNeeded(lineDigits, line int) string {
|
||||
title := fmt.Sprintf("%*d", lineDigits, line)
|
||||
if !f.linkableLineNumbers {
|
||||
return title
|
||||
}
|
||||
return fmt.Sprintf("<a style=\"outline: none; text-decoration:none; color:inherit\" href=\"#%s\">%s</a>", f.lineID(line), title)
|
||||
}
|
||||
|
||||
func (f *Formatter) lineID(line int) string {
|
||||
return fmt.Sprintf("%s%d", f.lineNumbersIDPrefix, line)
|
||||
}
|
||||
|
||||
func (f *Formatter) shouldHighlight(highlightIndex, line int) (bool, bool) {
|
||||
@@ -339,7 +382,11 @@ func (f *Formatter) tabWidthStyle() string {
|
||||
func (f *Formatter) WriteCSS(w io.Writer, style *chroma.Style) error {
|
||||
css := f.styleToCSS(style)
|
||||
// Special-case background as it is mapped to the outer ".chroma" class.
|
||||
if _, err := fmt.Fprintf(w, "/* %s */ .%schroma { %s }\n", chroma.Background, f.prefix, css[chroma.Background]); err != nil {
|
||||
if _, err := fmt.Fprintf(w, "/* %s */ .%sbg { %s }\n", chroma.Background, f.prefix, css[chroma.Background]); err != nil {
|
||||
return err
|
||||
}
|
||||
// Special-case PreWrapper as it is the ".chroma" class.
|
||||
if _, err := fmt.Fprintf(w, "/* %s */ .%schroma { %s }\n", chroma.PreWrapper, f.prefix, css[chroma.PreWrapper]); err != nil {
|
||||
return err
|
||||
}
|
||||
// Special-case code column of table to expand width.
|
||||
@@ -363,7 +410,8 @@ func (f *Formatter) WriteCSS(w io.Writer, style *chroma.Style) error {
|
||||
sort.Ints(tts)
|
||||
for _, ti := range tts {
|
||||
tt := chroma.TokenType(ti)
|
||||
if tt == chroma.Background {
|
||||
switch tt {
|
||||
case chroma.Background, chroma.PreWrapper:
|
||||
continue
|
||||
}
|
||||
class := f.class(tt)
|
||||
@@ -393,12 +441,21 @@ func (f *Formatter) styleToCSS(style *chroma.Style) map[chroma.TokenType]string
|
||||
classes[t] = StyleEntryToCSS(entry)
|
||||
}
|
||||
classes[chroma.Background] += f.tabWidthStyle()
|
||||
lineNumbersStyle := "margin-right: 0.4em; padding: 0 0.4em 0 0.4em;"
|
||||
classes[chroma.PreWrapper] += classes[chroma.Background] + `;`
|
||||
// Make PreWrapper a grid to show highlight style with full width.
|
||||
if len(f.highlightRanges) > 0 {
|
||||
classes[chroma.PreWrapper] += `display: grid;`
|
||||
}
|
||||
// Make PreWrapper wrap long lines.
|
||||
if f.wrapLongLines {
|
||||
classes[chroma.PreWrapper] += `white-space: pre-wrap; word-break: break-word;`
|
||||
}
|
||||
lineNumbersStyle := `white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;`
|
||||
// All rules begin with default rules followed by user provided rules
|
||||
classes[chroma.Line] = `display: flex;` + classes[chroma.Line]
|
||||
classes[chroma.LineNumbers] = lineNumbersStyle + classes[chroma.LineNumbers]
|
||||
classes[chroma.LineNumbersTable] = lineNumbersStyle + classes[chroma.LineNumbersTable]
|
||||
classes[chroma.LineHighlight] = "display: block; width: 100%;" + classes[chroma.LineHighlight]
|
||||
classes[chroma.LineTable] = "border-spacing: 0; padding: 0; margin: 0; border: 0; width: auto; overflow: auto; display: block;" + classes[chroma.LineTable]
|
||||
classes[chroma.LineTable] = "border-spacing: 0; padding: 0; margin: 0; border: 0;" + classes[chroma.LineTable]
|
||||
classes[chroma.LineTableTD] = "vertical-align: top; padding: 0; margin: 0; border: 0;" + classes[chroma.LineTableTD]
|
||||
return classes
|
||||
}
|
||||
|
||||
+2
-2
@@ -120,7 +120,7 @@ func maxLineWidth(lines [][]chroma.Token) int {
|
||||
for _, tokens := range lines {
|
||||
length := 0
|
||||
for _, token := range tokens {
|
||||
length += len(strings.Replace(token.String(), ` `, " ", -1))
|
||||
length += len(strings.ReplaceAll(token.String(), ` `, " "))
|
||||
}
|
||||
if length > maxWidth {
|
||||
maxWidth = length
|
||||
@@ -136,7 +136,7 @@ func (f *Formatter) writeTokenBackgrounds(w io.Writer, lines [][]chroma.Token, s
|
||||
for index, tokens := range lines {
|
||||
lineLength := 0
|
||||
for _, token := range tokens {
|
||||
length := len(strings.Replace(token.String(), ` `, " ", -1))
|
||||
length := len(strings.ReplaceAll(token.String(), ` `, " "))
|
||||
tokenBackground := style.Get(token.Type).Background
|
||||
if tokenBackground.IsSet() && tokenBackground != style.Get(chroma.Background).Background {
|
||||
fmt.Fprintf(w, "<rect id=\"%s\" x=\"%dch\" y=\"%fem\" width=\"%dch\" height=\"1.2em\" fill=\"%s\" />\n", escapeString(token.String()), lineLength, 1.2*float64(index)+0.25, length, style.Get(token.Type).Background.String())
|
||||
|
||||
+27
-5
@@ -17,6 +17,20 @@ var c = chroma.MustParseColour
|
||||
|
||||
var ttyTables = map[int]*ttyTable{
|
||||
8: {
|
||||
foreground: map[chroma.Colour]string{
|
||||
c("#000000"): "\033[30m", c("#7f0000"): "\033[31m", c("#007f00"): "\033[32m", c("#7f7fe0"): "\033[33m",
|
||||
c("#00007f"): "\033[34m", c("#7f007f"): "\033[35m", c("#007f7f"): "\033[36m", c("#e5e5e5"): "\033[37m",
|
||||
c("#555555"): "\033[1m\033[30m", c("#ff0000"): "\033[1m\033[31m", c("#00ff00"): "\033[1m\033[32m", c("#ffff00"): "\033[1m\033[33m",
|
||||
c("#0000ff"): "\033[1m\033[34m", c("#ff00ff"): "\033[1m\033[35m", c("#00ffff"): "\033[1m\033[36m", c("#ffffff"): "\033[1m\033[37m",
|
||||
},
|
||||
background: map[chroma.Colour]string{
|
||||
c("#000000"): "\033[40m", c("#7f0000"): "\033[41m", c("#007f00"): "\033[42m", c("#7f7fe0"): "\033[43m",
|
||||
c("#00007f"): "\033[44m", c("#7f007f"): "\033[45m", c("#007f7f"): "\033[46m", c("#e5e5e5"): "\033[47m",
|
||||
c("#555555"): "\033[1m\033[40m", c("#ff0000"): "\033[1m\033[41m", c("#00ff00"): "\033[1m\033[42m", c("#ffff00"): "\033[1m\033[43m",
|
||||
c("#0000ff"): "\033[1m\033[44m", c("#ff00ff"): "\033[1m\033[45m", c("#00ffff"): "\033[1m\033[46m", c("#ffffff"): "\033[1m\033[47m",
|
||||
},
|
||||
},
|
||||
16: {
|
||||
foreground: map[chroma.Colour]string{
|
||||
c("#000000"): "\033[30m", c("#7f0000"): "\033[31m", c("#007f00"): "\033[32m", c("#7f7fe0"): "\033[33m",
|
||||
c("#00007f"): "\033[34m", c("#7f007f"): "\033[35m", c("#007f7f"): "\033[36m", c("#e5e5e5"): "\033[37m",
|
||||
@@ -227,15 +241,11 @@ type indexedTTYFormatter struct {
|
||||
func (c *indexedTTYFormatter) Format(w io.Writer, style *chroma.Style, it chroma.Iterator) (err error) {
|
||||
theme := styleToEscapeSequence(c.table, style)
|
||||
for token := it(); token != chroma.EOF; token = it() {
|
||||
// TODO: Cache token lookups?
|
||||
clr, ok := theme[token.Type]
|
||||
if !ok {
|
||||
clr, ok = theme[token.Type.SubCategory()]
|
||||
if !ok {
|
||||
clr = theme[token.Type.Category()]
|
||||
// if !ok {
|
||||
// clr = theme[chroma.InheritStyle]
|
||||
// }
|
||||
}
|
||||
}
|
||||
if clr != "" {
|
||||
@@ -249,10 +259,22 @@ func (c *indexedTTYFormatter) Format(w io.Writer, style *chroma.Style, it chroma
|
||||
return nil
|
||||
}
|
||||
|
||||
// TTY is an 8-colour terminal formatter.
|
||||
//
|
||||
// The Lab colour space is used to map RGB values to the most appropriate index colour.
|
||||
var TTY = Register("terminal", &indexedTTYFormatter{ttyTables[8]})
|
||||
|
||||
// TTY8 is an 8-colour terminal formatter.
|
||||
//
|
||||
// The Lab colour space is used to map RGB values to the most appropriate index colour.
|
||||
var TTY8 = Register("terminal", &indexedTTYFormatter{ttyTables[8]})
|
||||
var TTY8 = Register("terminal8", &indexedTTYFormatter{ttyTables[8]})
|
||||
|
||||
// TTY16 is a 16-colour terminal formatter.
|
||||
//
|
||||
// It uses \033[3xm for normal colours and \033[90Xm for bright colours.
|
||||
//
|
||||
// The Lab colour space is used to map RGB values to the most appropriate index colour.
|
||||
var TTY16 = Register("terminal16", &indexedTTYFormatter{ttyTables[16]})
|
||||
|
||||
// TTY256 is a 256-colour terminal formatter.
|
||||
//
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import "strings"
|
||||
|
||||
// An Iterator across tokens.
|
||||
//
|
||||
// nil will be returned at the end of the Token stream.
|
||||
// EOF will be returned at the end of the Token stream.
|
||||
//
|
||||
// If an error occurs within an Iterator, it may propagate this in a panic. Formatters should recover.
|
||||
type Iterator func() Token
|
||||
|
||||
+6
-3
@@ -2,6 +2,7 @@ package chroma
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -98,9 +99,11 @@ type Lexer interface {
|
||||
// Lexers is a slice of lexers sortable by name.
|
||||
type Lexers []Lexer
|
||||
|
||||
func (l Lexers) Len() int { return len(l) }
|
||||
func (l Lexers) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
|
||||
func (l Lexers) Less(i, j int) bool { return l[i].Config().Name < l[j].Config().Name }
|
||||
func (l Lexers) Len() int { return len(l) }
|
||||
func (l Lexers) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
|
||||
func (l Lexers) Less(i, j int) bool {
|
||||
return strings.ToLower(l[i].Config().Name) < strings.ToLower(l[j].Config().Name)
|
||||
}
|
||||
|
||||
// PrioritisedLexers is a slice of lexers sortable by priority.
|
||||
type PrioritisedLexers []Lexer
|
||||
|
||||
+3
@@ -3,6 +3,9 @@
|
||||
The tests in this directory feed a known input `testdata/<name>.actual` into the parser for `<name>` and check
|
||||
that its output matches `<name>.exported`.
|
||||
|
||||
It is also possible to perform several tests on a same parser `<name>`, by placing know inputs `*.actual` into a
|
||||
directory `testdata/<name>/`.
|
||||
|
||||
## Running the tests
|
||||
|
||||
Run the tests as normal:
|
||||
|
||||
+8
-4
@@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
// ABAP lexer.
|
||||
var Abap = internal.Register(MustNewLexer(
|
||||
var Abap = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "ABAP",
|
||||
Aliases: []string{"abap"},
|
||||
@@ -14,7 +14,11 @@ var Abap = internal.Register(MustNewLexer(
|
||||
MimeTypes: []string{"text/x-abap"},
|
||||
CaseInsensitive: true,
|
||||
},
|
||||
Rules{
|
||||
abapRules,
|
||||
))
|
||||
|
||||
func abapRules() Rules {
|
||||
return Rules{
|
||||
"common": {
|
||||
{`\s+`, Text, nil},
|
||||
{`^\*.*$`, CommentSingle, nil},
|
||||
@@ -52,5 +56,5 @@ var Abap = internal.Register(MustNewLexer(
|
||||
{`[/;:()\[\],.]`, Punctuation, nil},
|
||||
{`(!)(\w+)`, ByGroups(Operator, Name), nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
+8
-4
@@ -6,14 +6,18 @@ import (
|
||||
)
|
||||
|
||||
// Abnf lexer.
|
||||
var Abnf = internal.Register(MustNewLexer(
|
||||
var Abnf = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "ABNF",
|
||||
Aliases: []string{"abnf"},
|
||||
Filenames: []string{"*.abnf"},
|
||||
MimeTypes: []string{"text/x-abnf"},
|
||||
},
|
||||
Rules{
|
||||
abnfRules,
|
||||
))
|
||||
|
||||
func abnfRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`;.*$`, CommentSingle, nil},
|
||||
{`(%[si])?"[^"]*"`, Literal, nil},
|
||||
@@ -34,5 +38,5 @@ var Abnf = internal.Register(MustNewLexer(
|
||||
{`\s+`, Text, nil},
|
||||
{`.`, Text, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
+8
-4
@@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
// Actionscript lexer.
|
||||
var Actionscript = internal.Register(MustNewLexer(
|
||||
var Actionscript = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "ActionScript",
|
||||
Aliases: []string{"as", "actionscript"},
|
||||
@@ -15,7 +15,11 @@ var Actionscript = internal.Register(MustNewLexer(
|
||||
NotMultiline: true,
|
||||
DotAll: true,
|
||||
},
|
||||
Rules{
|
||||
actionscriptRules,
|
||||
))
|
||||
|
||||
func actionscriptRules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\s+`, Text, nil},
|
||||
{`//.*?\n`, CommentSingle, nil},
|
||||
@@ -35,5 +39,5 @@ var Actionscript = internal.Register(MustNewLexer(
|
||||
{`"(\\\\|\\"|[^"])*"`, LiteralStringDouble, nil},
|
||||
{`'(\\\\|\\'|[^'])*'`, LiteralStringSingle, nil},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
+8
-4
@@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
// Actionscript 3 lexer.
|
||||
var Actionscript3 = internal.Register(MustNewLexer(
|
||||
var Actionscript3 = internal.Register(MustNewLazyLexer(
|
||||
&Config{
|
||||
Name: "ActionScript 3",
|
||||
Aliases: []string{"as3", "actionscript3"},
|
||||
@@ -14,7 +14,11 @@ var Actionscript3 = internal.Register(MustNewLexer(
|
||||
MimeTypes: []string{"application/x-actionscript3", "text/x-actionscript3", "text/actionscript3"},
|
||||
DotAll: true,
|
||||
},
|
||||
Rules{
|
||||
actionscript3Rules,
|
||||
))
|
||||
|
||||
func actionscript3Rules() Rules {
|
||||
return Rules{
|
||||
"root": {
|
||||
{`\s+`, Text, nil},
|
||||
{`(function\s+)([$a-zA-Z_]\w*)(\s*)(\()`, ByGroups(KeywordDeclaration, NameFunction, Text, Operator), Push("funcparams")},
|
||||
@@ -52,5 +56,5 @@ var Actionscript3 = internal.Register(MustNewLexer(
|
||||
{`,`, Operator, Pop(1)},
|
||||
Default(Pop(1)),
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
Loaded 100 of 709 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user