package main import ( "fmt" "os" "regexp" "strings" ) // cmdShow decrypts an entry, or lists a directory (pass's implicit behaviour: // no name, or a name that is a directory, lists; otherwise show). func cmdShow(args []string) error { clip, line, rest := parseClip(args) name := "" if len(rest) > 0 { name = strings.Trim(rest[0], "/") } s, err := openStore() if err != nil { return err } if name == "" || s.isDir(name) { return printTree(s, name) } if !s.hasEntry(name) { return errf("Error: %s is not in the password store.", name) } v, err := newVault() if err != nil { return err } plain, err := decryptEntry(s, v, name) if err != nil { return err } if !clip { os.Stdout.Write(plain) if len(plain) == 0 || plain[len(plain)-1] != '\n' { fmt.Println() } return nil } lines := strings.Split(string(plain), "\n") if line-1 >= len(lines) { return errf("There is no password on line %d of %s.", line, name) } if err := copyClip(lines[line-1]); err != nil { return err } fmt.Fprintf(os.Stderr, "Copied %s to clipboard. Will clear in %d seconds.\n", name, clipTime()) return nil } // cmdFind lists entries whose path contains any of the given terms. func cmdFind(args []string) error { if len(args) == 0 { return &usageError{"Usage: passv find term..."} } s, err := openStore() if err != nil { return err } names, err := s.list("") if err != nil { return err } fmt.Println("Search Terms: " + strings.Join(args, ", ")) for _, n := range names { for _, t := range args { if strings.Contains(n, t) { fmt.Println(n) break } } } return nil } // cmdGrep decrypts every entry and prints lines matching the pattern. func cmdGrep(args []string) error { ignoreCase, args := popBool(args, "-i", "--ignore-case") if len(args) != 1 { return &usageError{"Usage: passv grep [-i] search-regexp"} } pattern := args[0] if ignoreCase { pattern = "(?i)" + pattern } re, err := regexp.Compile(pattern) if err != nil { return fmt.Errorf("invalid pattern: %w", err) } s, err := openStore() if err != nil { return err } v, err := newVault() if err != nil { return err } names, err := s.list("") if err != nil { return err } for _, n := range names { plain, err := decryptEntry(s, v, n) if err != nil { fmt.Fprintf(os.Stderr, "passv: skipping %s: %v\n", n, err) continue } var hits []string for _, ln := range strings.Split(string(plain), "\n") { if re.MatchString(ln) { hits = append(hits, ln) } } if len(hits) > 0 { fmt.Printf("%s:\n", n) for _, h := range hits { fmt.Println(h) } } } return nil }