/
githubmirror
/
client
Обзор
Документация
Войти
/
githubmirror
/
client
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
go/libcmdline/cmdline.go
930 строк
23 KB
zoom-ua
enable linters: misspell, bodyclose (#28736)
23 дек 2025, 22:37
Не верифицирован
23 дек 2025, 22:37
7debd3d
Код
Авторство
О чём код?
// Copyright 2015 Keybase, Inc. All rights reserved. Use of // this source code is governed by the included BSD license. package libcmdline import ( "fmt" "io" "strings" "time" "github.com/keybase/cli" "github.com/keybase/client/go/libkb" ) type Command interface { libkb.Command ParseArgv(*cli.Context) error // A command-specific parse-args Run() error // Run in client mode } type ( ForkCmd int LogForward int ) const ( NormalFork ForkCmd = iota NoFork ForceFork ) const ( LogForwardNormal LogForward = iota LogForwardNone ) type CommandLine struct { app *cli.App ctx *cli.Context cmd Command name string // the name of the chosen command service bool // The server is a special command fork ForkCmd // If the command is to stop (then don't start the server) noStandalone bool // On if this command can't run in standalone mode logForward LogForward // What do to about log forwarding skipOutOfDateCheck bool // don't try to check for service being out of date skipAccountResetCheck bool // don't check if our account is scheduled for rest defaultCmd string } func (p CommandLine) IsService() bool { return p.service } func (p CommandLine) SkipOutOfDateCheck() bool { return p.skipOutOfDateCheck } func (p CommandLine) SkipAccountResetCheck() bool { return p.skipAccountResetCheck } func (p *CommandLine) SetService() { p.service = true } func (p CommandLine) GetForkCmd() ForkCmd { return p.fork } func (p *CommandLine) SetForkCmd(v ForkCmd) { p.fork = v } func (p *CommandLine) SetNoStandalone() { p.noStandalone = true } func (p CommandLine) IsNoStandalone() bool { return p.noStandalone } func (p *CommandLine) SetLogForward(f LogForward) { p.logForward = f } func (p *CommandLine) GetLogForward() LogForward { return p.logForward } func (p *CommandLine) SetSkipOutOfDateCheck() { p.skipOutOfDateCheck = true } func (p *CommandLine) SetSkipAccountResetCheck() { p.skipAccountResetCheck = true } func (p CommandLine) GetNoAutoFork() (bool, bool) { return p.GetBool("no-auto-fork", true) } func (p CommandLine) GetAutoFork() (bool, bool) { return p.GetBool("auto-fork", true) } func (p CommandLine) GetHome() string { return p.GetGString("home") } func (p CommandLine) GetMobileSharedHome() string { return p.GetGString("mobile-shared-home") } func (p CommandLine) GetServerURI() (string, error) { return p.GetGString("server"), nil } func (p CommandLine) GetConfigFilename() string { return p.GetGString("config-file") } func (p CommandLine) GetGUIConfigFilename() string { return p.GetGString("gui-config-file") } func (p CommandLine) GetUpdaterConfigFilename() string { return p.GetGString("updater-config-file") } func (p CommandLine) GetDeviceCloneStateFilename() string { return p.GetGString("device-clone-state-file") } func (p CommandLine) GetSessionFilename() string { return p.GetGString("session-file") } func (p CommandLine) GetDbFilename() string { return p.GetGString("db") } func (p CommandLine) GetChatDbFilename() string { return p.GetGString("chat-db") } func (p CommandLine) GetPvlKitFilename() string { return p.GetGString("pvl-kit") } func (p CommandLine) GetParamProofKitFilename() string { return p.GetGString("paramproof-kit") } func (p CommandLine) GetExternalURLKitFilename() string { return p.GetGString("externalurl-kit") } func (p CommandLine) GetProveBypass() (bool, bool) { return p.GetBool("prove-bypass", true) } func (p CommandLine) GetDebug() (bool, bool) { // --no-debug suppresses --debug. Note that although we don't define a // separate GetNoDebug() accessor, fork_server.go still looks for // --no-debug by name, to pass it along to an autoforked daemon. if noDebug, _ := p.GetBool("no-debug", true); noDebug { return false /* val */, true /* isSet */ } return p.GetBool("debug", true) } func (p CommandLine) GetDebugJourneycard() (bool, bool) { return p.GetBool("debug-journeycard", true) } func (p CommandLine) GetDisplayRawUntrustedOutput() (bool, bool) { return p.GetBool("display-raw-untrusted-output", true) } func (p CommandLine) GetVDebugSetting() string { return p.GetGString("vdebug") } func (p CommandLine) GetPGPFingerprint() *libkb.PGPFingerprint { return libkb.PGPFingerprintFromHexNoError(p.GetGString("fingerprint")) } func (p CommandLine) GetProxy() string { return p.GetGString("proxy") } func (p CommandLine) GetLogFile() string { return p.GetGString("log-file") } func (p CommandLine) GetEKLogFile() string { return p.GetGString("ek-log-file") } func (p CommandLine) GetPerfLogFile() string { return p.GetGString("perf-log-file") } func (p CommandLine) GetGUILogFile() string { return p.GetGString("gui-log-file") } func (p CommandLine) GetUseDefaultLogFile() (bool, bool) { return p.GetBool("use-default-log-file", true) } func (p CommandLine) GetUseRootConfigFile() (bool, bool) { return p.GetBool("use-root-config-file", true) } func (p CommandLine) GetLogPrefix() string { return p.GetGString("log-prefix") } func (p CommandLine) GetLogFormat() string { return p.GetGString("log-format") } func (p CommandLine) GetGpgHome() string { return p.GetGString("gpg-home") } func (p CommandLine) GetAPIDump() (bool, bool) { return p.GetBool("api-dump-unsafe", true) } func (p CommandLine) GetGregorSaveInterval() (time.Duration, bool) { ret, err := p.GetGDuration("push-save-interval") if err != nil { return 0, false } return ret, true } func (p CommandLine) GetGregorDisabled() (bool, bool) { return p.GetBool("push-disabled", true) } func (p CommandLine) GetSecretStorePrimingDisabled() (bool, bool) { // SecretStorePrimingDisabled is only for tests return false, false } func (p CommandLine) GetBGIdentifierDisabled() (bool, bool) { return p.GetBool("bg-identifier-disabled", true) } func (p CommandLine) GetGregorURI() string { return p.GetGString("push-server-uri") } func (p CommandLine) GetGregorPingInterval() (time.Duration, bool) { ret, err := p.GetGDuration("push-ping-interval") if err != nil { return 0, false } return ret, true } func (p CommandLine) GetGregorPingTimeout() (time.Duration, bool) { ret, err := p.GetGDuration("push-ping-timeout") if err != nil { return 0, false } return ret, true } func (p CommandLine) GetChatDelivererInterval() (time.Duration, bool) { ret, err := p.GetGDuration("chat-deliverer-interval") if err != nil { return 0, false } return ret, true } func (p CommandLine) GetRunMode() (libkb.RunMode, error) { return libkb.StringToRunMode(p.GetGString("run-mode")) } func (p CommandLine) GetFeatureFlags() (libkb.FeatureFlags, error) { return libkb.StringToFeatureFlags(p.GetGString("features")), nil } func (p CommandLine) GetPinentry() string { return p.GetGString("pinentry") } func (p CommandLine) GetAppType() libkb.AppType { return libkb.DesktopAppType } func (p CommandLine) IsMobileExtension() (bool, bool) { return false, false } func (p CommandLine) GetSlowGregorConn() (bool, bool) { return p.GetBool("slow-gregor-conn", true) } func (p CommandLine) GetReadDeletedSigChain() (bool, bool) { return p.GetBool("read-deleted-sigchain", true) } func (p CommandLine) GetGString(s string) string { return p.ctx.GlobalString(s) } func (p CommandLine) GetString(s string) string { return p.ctx.String(s) } func (p CommandLine) GetGInt(s string) int { return p.ctx.GlobalInt(s) } func (p CommandLine) GetGDuration(s string) (time.Duration, error) { return time.ParseDuration(p.GetGString(s)) } func (p CommandLine) GetGpg() string { return p.GetGString("gpg") } func (p CommandLine) GetSecretKeyringTemplate() string { return p.GetGString("secret-keyring") } func (p CommandLine) GetSocketFile() string { return p.GetGString("socket-file") } func (p CommandLine) GetPidFile() string { return p.GetGString("pid-file") } func (p CommandLine) GetScraperTimeout() (time.Duration, bool) { ret, err := p.GetGDuration("scraper-timeout") if err != nil { return 0, false } return ret, true } func (p CommandLine) GetAPITimeout() (time.Duration, bool) { ret, err := p.GetGDuration("api-timeout") if err != nil { return 0, false } return ret, true } func (p CommandLine) GetGpgOptions() []string { var ret []string s := p.GetGString("gpg-options") if len(s) > 0 { ret = strings.Fields(s) } return ret } func (p CommandLine) getKIDs(name string) []string { s := p.GetGString(name) if len(s) == 0 { return nil } return strings.Split(s, ":") } func (p CommandLine) GetMerkleKIDs() []string { return p.getKIDs("merkle-kids") } func (p CommandLine) GetCodeSigningKIDs() []string { return p.getKIDs("code-signing-kids") } func (p CommandLine) GetUserCacheMaxAge() (time.Duration, bool) { ret, err := p.GetGDuration("user-cache-maxage") if err != nil { return 0, false } return ret, true } func (p CommandLine) GetProofCacheSize() (int, bool) { ret := p.GetGInt("proof-cache-size") if ret != 0 { return ret, true } return 0, false } func (p CommandLine) GetLevelDBNumFiles() (int, bool) { ret := p.GetGInt("leveldb-num-files") if ret != 0 { return ret, true } return 0, false } func (p CommandLine) GetLevelDBWriteBufferMB() (int, bool) { ret := p.GetGInt("leveldb-write-buffer-mb") if ret != 0 { return ret, true } return 0, false } func (p CommandLine) GetChatInboxSourceLocalizeThreads() (int, bool) { ret := p.GetGInt("chat-inboxsource-localizethreads") if ret != 0 { return ret, true } return 0, false } func (p CommandLine) GetLinkCacheSize() (int, bool) { ret := p.GetGInt("link-cache-size") if ret != 0 { return ret, true } return 0, false } func (p CommandLine) GetUPAKCacheSize() (int, bool) { ret := p.GetGInt("upak-cache-size") if ret != 0 { return ret, true } return 0, false } func (p CommandLine) GetUIDMapFullNameCacheSize() (int, bool) { ret := p.GetGInt("uid-map-full-name-cache-size") if ret != 0 { return ret, true } return 0, false } func (p CommandLine) GetPayloadCacheSize() (int, bool) { ret := p.GetGInt("payload-cache-size") if ret != 0 { return ret, true } return 0, false } func (p CommandLine) GetLocalTrackMaxAge() (time.Duration, bool) { ret, err := p.GetGDuration("local-track-maxage") if err != nil { return 0, false } return ret, true } func (p CommandLine) GetStandalone() (bool, bool) { return p.GetBool("standalone", true) } func (p CommandLine) GetLocalRPCDebug() string { return p.GetGString("local-rpc-debug-unsafe") } func (p CommandLine) GetTimers() string { return p.GetGString("timers") } func (p CommandLine) GetTorMode() (ret libkb.TorMode, err error) { if s := p.GetGString("tor-mode"); s != "" { ret, err = libkb.StringToTorMode(s) } return ret, err } func (p CommandLine) GetTorHiddenAddress() string { return p.GetGString("tor-hidden-address") } func (p CommandLine) GetTorProxy() string { return p.GetGString("tor-proxy") } func (p CommandLine) GetProxyType() string { return p.GetGString("proxy-type") } func (p CommandLine) IsCertPinningEnabled() bool { r1, _ := p.GetBool("disable-cert-pinning", true) // Defaults to false since it is a boolean flag, so just invert it return !r1 } func (p CommandLine) GetMountDir() string { return p.GetGString("mountdir") } func (p CommandLine) GetMountDirDefault() string { return p.GetGString("mountdirdefault") } func (p CommandLine) GetRememberPassphrase(libkb.NormalizedUsername) (bool, bool) { return p.GetBool("remember-passphrase", true) } func (p CommandLine) GetAttachmentDisableMulti() (bool, bool) { return p.GetBool("attachment-disable-multi", true) } func (p CommandLine) GetDisableTeamAuditor() (bool, bool) { return p.GetBool("disable-team-auditor", true) } func (p CommandLine) GetDisableTeamBoxAuditor() (bool, bool) { return p.GetBool("disable-team-box-auditor", true) } func (p CommandLine) GetDisableEKBackgroundKeygen() (bool, bool) { return p.GetBool("disable-ek-background-keygen", true) } func (p CommandLine) GetDisableMerkleAuditor() (bool, bool) { return p.GetBool("disable-merkle-auditor", true) } func (p CommandLine) GetDisableSearchIndexer() (bool, bool) { return p.GetBool("disable-search-indexer", true) } func (p CommandLine) GetDisableBgConvLoader() (bool, bool) { return p.GetBool("disable-bg-conv-loader", true) } func (p CommandLine) GetEnableBotLiteMode() (bool, bool) { return p.GetBool("enable-bot-lite-mode", true) } func (p CommandLine) GetExtraNetLogging() (bool, bool) { return p.GetBool("extra-net-logging", true) } func (p CommandLine) GetForceLinuxKeyring() (bool, bool) { return p.GetBool("force-linux-keyring", true) } func (p CommandLine) GetForceSecretStoreFile() (bool, bool) { return false, false // not configurable via command line flags } func (p CommandLine) GetRuntimeStatsEnabled() (bool, bool) { return false, false } func (p CommandLine) GetAttachmentHTTPStartPort() (int, bool) { ret := p.GetGInt("attachment-httpsrv-port") if ret != 0 { return ret, true } return 0, false } func (p CommandLine) GetBool(s string, glbl bool) (bool, bool) { var v bool if glbl { v = p.ctx.GlobalBool(s) } else { v = p.ctx.Bool(s) } return v, v } type CmdBaseHelp struct { ctx *cli.Context } func (c *CmdBaseHelp) GetUsage() libkb.Usage { return libkb.Usage{} } func (c *CmdBaseHelp) ParseArgv(*cli.Context) error { return nil } type CmdGeneralHelp struct { CmdBaseHelp } func (c *CmdBaseHelp) RunClient() error { return c.Run() } func (c *CmdBaseHelp) Run() error { cli.ShowAppHelp(c.ctx) return nil } type CmdSpecificHelp struct { CmdBaseHelp name string } func (c CmdSpecificHelp) Run() error { cli.ShowCommandHelp(c.ctx, c.name) return nil } func NewCommandLine(addHelp bool, extraFlags []cli.Flag) *CommandLine { app := cli.NewApp() ret := &CommandLine{app: app, fork: NormalFork} ret.PopulateApp(addHelp, extraFlags) return ret } func (p *CommandLine) PopulateApp(addHelp bool, extraFlags []cli.Flag) { app := p.app app.Name = "keybase" app.EnableBashCompletion = true app.Version = libkb.VersionString() app.Usage = "Keybase command line client." app.Flags = []cli.Flag{ cli.BoolFlag{ Name: "api-dump-unsafe", Usage: "Dump API call internals (may leak secrets).", }, cli.StringFlag{ Name: "api-timeout", Usage: "set the HTTP timeout for API calls to the keybase API server", }, cli.StringFlag{ Name: "api-uri-path-prefix", Usage: "Specify an alternate API URI path prefix.", }, cli.StringFlag{ Name: "app-start-mode", Usage: "Specify 'service' to auto-start UI app, or anything else to disable", }, cli.BoolFlag{ Name: "bg-identifier-disabled", Usage: "supply to disable the BG identifier loop", }, cli.StringFlag{ Name: "chat-db", Usage: "Specify an alternate local Chat DB location.", }, cli.StringFlag{ Name: "code-signing-kids", Usage: "Set of code signing key IDs (colon-separated).", }, cli.StringFlag{ Name: "config-file, c", Usage: "Specify an (alternate) master config file.", }, cli.BoolFlag{ Name: "use-root-config-file", Usage: "Use the default root config on Linux only.", }, cli.StringFlag{ Name: "db", Usage: "Specify an alternate local DB location.", }, cli.BoolFlag{ Name: "debug, d", Usage: "Enable debugging mode.", }, cli.BoolFlag{ Name: "disable-cert-pinning", Usage: "Disable certificate pinning within the app. WARNING: This reduces the security of the app. Do not use " + "unless necessary! This should only be used if you are running keybase behind a proxy that does TLS interception.", }, cli.BoolFlag{ Name: "display-raw-untrusted-output", Usage: "Display output from users (messages, chats, ...) in the terminal without escaping terminal codes. WARNING: maliciously crafted unescaped outputs can overwrite anything you see on the terminal.", }, cli.StringFlag{ Name: "features", Usage: "specify experimental feature flags", }, cli.StringFlag{ Name: "gpg", Usage: "Path to GPG client (optional for exporting keys).", }, cli.StringFlag{ Name: "gpg-options", Usage: "Options to use when calling GPG.", }, cli.StringFlag{ Name: "home, H", Usage: "Specify an (alternate) home directory.", }, cli.IntFlag{ Name: "leveldb-num-files", Usage: "Specify the max number of files LevelDB may open", }, cli.StringFlag{ Name: "local-rpc-debug-unsafe", Usage: "Use to debug local RPC (may leak secrets).", }, cli.StringFlag{ Name: "log-file", Usage: "Specify a log file for the keybase service.", }, cli.StringFlag{ Name: "ek-log-file", Usage: "Specify a log file for the keybase ephemeral key log.", }, cli.StringFlag{ Name: "log-format", Usage: "Log format (default, plain, file, fancy).", }, cli.StringFlag{ Name: "log-prefix", Usage: "Specify a prefix for a unique log file name.", }, cli.StringFlag{ Name: "merkle-kids", Usage: "Set of admissible Merkle Tree fingerprints (colon-separated).", }, cli.BoolFlag{ Name: "no-debug", Usage: "Suppress debugging mode; takes precedence over --debug.", }, cli.StringFlag{ Name: "pgpdir, gpgdir", Usage: "Specify a PGP directory (default is ~/.gnupg).", }, cli.StringFlag{ Name: "pid-file", Usage: "Location of the keybased pid-file (to ensure only one running daemon).", }, cli.StringFlag{ Name: "pinentry", Usage: "Specify a path to find a pinentry program.", }, cli.IntFlag{ Name: "proof-cache-size", Usage: "Number of proof entries to cache.", }, cli.StringFlag{ Name: "proxy", Usage: "Specify a proxy to ship all Web requests over; Must be used with --proxy-type; Example: localhost:8080", }, cli.StringFlag{ Name: "proxy-type", Usage: fmt.Sprintf("set the proxy type; One of: %s", libkb.GetCommaSeparatedListOfProxyTypes()), }, cli.BoolFlag{ Name: "push-disabled", Usage: "Disable push server connection (which is on by default)", }, cli.IntFlag{ Name: "push-save-interval", Usage: "Set the interval between saves of the push cache (in seconds)", }, cli.StringFlag{ Name: "push-server-uri", Usage: "Specify a URI for contacting the Keybase push server", }, cli.StringFlag{ Name: "pvl-kit", Usage: "Specify an alternate local PVL kit file location.", }, cli.StringFlag{ Name: "paramproof-kit", Usage: "Specify an alternate local parameterized proof kit file location.", }, cli.BoolFlag{ Name: "prove-bypass", Usage: "Prove even disabled proof services", }, cli.BoolFlag{ Name: "remember-passphrase", Usage: "Remember keybase passphrase", }, cli.StringFlag{ Name: "run-mode", Usage: "Run mode (devel, staging, prod).", // These are defined in libkb/constants.go }, cli.StringFlag{ Name: "scraper-timeout", Usage: "set the HTTP timeout for external proof scrapers", }, cli.StringFlag{ Name: "secret-keyring", Usage: "Location of the Keybase secret-keyring (P3SKB-encoded).", }, cli.StringFlag{ Name: "server, s", Usage: "Specify server API.", }, cli.StringFlag{ Name: "session-file", Usage: "Specify an alternate session data file.", }, cli.BoolFlag{ Name: "slow-gregor-conn", Usage: "Slow responses from gregor for testing", }, cli.BoolFlag{ Name: "read-deleted-sigchain", Usage: "Allow admins to read deleted sigchains for debugging.", }, cli.StringFlag{ Name: "socket-file", Usage: "Location of the keybased socket-file.", }, cli.BoolFlag{ Name: "standalone", Usage: "Use the client without any daemon support.", }, cli.StringFlag{ Name: "timers", Usage: "Specify 'a' for API; 'r' for RPCs; and 'x' for eXternal API calls", }, cli.StringFlag{ Name: "tor-hidden-address", Usage: fmt.Sprintf("set TOR address of keybase server; defaults to %s", libkb.TorServerURI), }, cli.StringFlag{ Name: "tor-mode", Usage: "set TOR mode to be 'leaky', 'none', or 'strict'. 'none' by default. See 'help tor' for more details.", }, cli.StringFlag{ Name: "tor-proxy", Usage: fmt.Sprintf("set TOR proxy; when Tor mode is on; defaults to %s when TOR is enabled", libkb.TorProxy), }, cli.StringFlag{ Name: "updater-config-file", Usage: "Specify a path to the updater config file", }, cli.StringFlag{ Name: "gui-config-file", Usage: "Specify a path to the GUI config file", }, cli.BoolFlag{ Name: "use-default-log-file", Usage: "Log to the default log file in $XDG_CACHE_HOME, or ~/.cache if unset.", }, cli.IntFlag{ Name: "user-cache-size", Usage: "Number of User entries to cache.", }, cli.StringFlag{ Name: "vdebug", Usage: "Verbose debugging; takes a comma-joined list of levels and tags", }, cli.BoolFlag{ Name: "debug-journeycard", Usage: "Enable experimental journey cards", }, cli.BoolFlag{ Name: "disable-team-auditor", Usage: "Disable auditing of teams", }, cli.BoolFlag{ Name: "disable-team-box-auditor", Usage: "Disable box auditing of teams", }, cli.BoolFlag{ Name: "disable-merkle-auditor", Usage: "Disable background probabilistic merkle audit", }, cli.BoolFlag{ Name: "disable-search-indexer", Usage: "Disable chat search background indexer", }, cli.BoolFlag{ Name: "disable-bg-conv-loader", Usage: "Disable background conversation loading", }, cli.BoolFlag{ Name: "enable-bot-lite-mode", Usage: "Enable bot lite mode. Disables non-critical background services for bot performance.", }, cli.BoolFlag{ Name: "force-linux-keyring", Usage: "Require the use of the OS keyring (Gnome Keyring or KWallet) and fail if not available rather than falling back to file-based secret store.", }, cli.BoolFlag{ Name: "extra-net-logging", Usage: "Do additional debug logging during network requests.", }, } if extraFlags != nil { app.Flags = append(app.Flags, extraFlags...) } app.Commands = []cli.Command{} } func filter(cmds []cli.Command, fn func(cli.Command) bool) []cli.Command { var filter []cli.Command for _, cmd := range cmds { if fn(cmd) { filter = append(filter, cmd) } } return filter } func (p *CommandLine) AddCommands(cmds []cli.Command) { cmds = filter(cmds, func(c cli.Command) bool { return c.Name != "" }) p.app.Commands = append(p.app.Commands, cmds...) } func (p *CommandLine) SetDefaultCommand(name string, cmd Command) { p.defaultCmd = name p.app.Action = func(c *cli.Context) { p.cmd = cmd p.ctx = c p.name = name } } // Called back from inside our subcommands, when they're picked... func (p *CommandLine) ChooseCommand(cmd Command, name string, ctx *cli.Context) { p.cmd = cmd p.name = name p.ctx = ctx } func (p *CommandLine) Parse(args []string) (cmd Command, err error) { // This is suboptimal, but the default help action when there are // no args crashes. // (cli sets HelpPrinter to nil when p.app.Run(...) returns.) if len(args) == 1 && p.defaultCmd == "help" { args = append(args, p.defaultCmd) } // Actually pick a command err = p.app.Run(args) // Should not be populated cmd = p.cmd if err != nil || cmd == nil { return } // cli.HelpPrinter is nil here...anything that needs it will panic. // If we failed to parse arguments properly, switch to the help command if err = p.cmd.ParseArgv(p.ctx); err == nil { _, err = p.GetRunMode() } if err != nil { cmd = &CmdSpecificHelp{CmdBaseHelp{p.ctx}, p.name} } return } func (p *CommandLine) SetOutputWriter(w io.Writer) { p.app.Writer = w } // AddHelpTopics appends topics to the list of help topics for // this app. func (p *CommandLine) AddHelpTopics(topics []cli.HelpTopic) { p.app.HelpTopics = append(p.app.HelpTopics, topics...) }