From 1eb3850c42d58cb142ee8434d7e00bf93703f730 Mon Sep 17 00:00:00 2001 From: Dominik Schulz Date: Wed, 25 Sep 2024 13:07:37 +0200 Subject: [PATCH] feat: Add --qrbody flag to encode the entire body of a secret into a QR (#2946) This comes in handy when storing Wireguard configs in gopass as it allows to import the entire config on a mobile device easily. Signed-off-by: Dominik Schulz --- internal/action/commands.go | 4 ++++ internal/action/context.go | 16 ++++++++++++++++ internal/action/show.go | 13 +++++++++++++ 3 files changed, 33 insertions(+) diff --git a/internal/action/commands.go b/internal/action/commands.go index 9f86628e2c..e03f60a19c 100644 --- a/internal/action/commands.go +++ b/internal/action/commands.go @@ -32,6 +32,10 @@ func ShowFlags() []cli.Flag { Name: "qr", Usage: "Print the password as a QR Code", }, + &cli.BoolFlag{ + Name: "qrbody", + Usage: "Print the body as a QR Code", + }, &cli.BoolFlag{ Name: "unsafe", Aliases: []string{"u", "force", "f"}, diff --git a/internal/action/context.go b/internal/action/context.go index 8056c320cc..0c3667fb3f 100644 --- a/internal/action/context.go +++ b/internal/action/context.go @@ -13,6 +13,7 @@ const ( ctxKeyOnlyClip ctxKeyAlsoClip ctxKeyPrintChars + ctxKeyWithQRBody ) // WithClip returns a context with the value for clip (for copy to clipboard) @@ -151,3 +152,18 @@ func GetPrintChars(ctx context.Context) []int { return mv } + +// WithQRBody returns the context with the value of with QR body set. +func WithQRBody(ctx context.Context, qr bool) context.Context { + return context.WithValue(ctx, ctxKeyWithQRBody, qr) +} + +// IsQRBody returns the value of with QR body or the default (false). +func IsQRBody(ctx context.Context) bool { + bv, ok := ctx.Value(ctxKeyWithQRBody).(bool) + if !ok { + return false + } + + return bv +} diff --git a/internal/action/show.go b/internal/action/show.go index 34cabdf97c..c9c170a962 100644 --- a/internal/action/show.go +++ b/internal/action/show.go @@ -36,6 +36,9 @@ func showParseArgs(c *cli.Context) context.Context { if c.IsSet("qr") { ctx = WithPrintQR(ctx, c.Bool("qr")) } + if c.IsSet("qrbody") { + ctx = WithQRBody(ctx, c.Bool("qrbody")) + } if c.IsSet("password") { ctx = WithPasswordOnly(ctx, c.Bool("password")) @@ -197,6 +200,13 @@ func (s *Action) showHandleOutput(ctx context.Context, name string, sec gopass.S return exit.Error(exit.NotFound, store.ErrEmptySecret, store.ErrEmptySecret.Error()) } + if IsPrintQR(ctx) && IsQRBody(ctx) { + if err := s.showPrintQR(name, body); err != nil { + return err + } + + return nil + } if IsPrintQR(ctx) && pw != "" { if err := s.showPrintQR(name, pw); err != nil { return err @@ -245,6 +255,9 @@ func (s *Action) showGetContent(ctx context.Context, sec gopass.Secret) (string, // fallback for old MIME secrets. fullBody := strings.TrimPrefix(string(sec.Bytes()), secrets.Ident+"\n") + if IsQRBody(ctx) { + return pw, fullBody, nil + } // first line of the secret only. if IsPrintQR(ctx) || IsOnlyClip(ctx) { return pw, "", nil