<div dir="ltr">Hi,<div><br></div><div>is this really that common a use case? Supporting this will add a dependency on qrencode to pass.</div><div><br></div><div>In what way is this better than doing "pass foo/bar | qrencode"?</div>
<div><br></div><div>Cheers,</div><div>Jonas</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Jun 20, 2014 at 2:23 AM, Patrick Burroughs (Celti) <span dir="ltr"><<a href="mailto:celticmadman@gmail.com" target="_blank">celticmadman@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This patch adds support for displaying passwords as QR codes for easy transfer<br>
to any device that can read them, rendered in the terminal with ANSI escape<br>
sequences via qrencode.<br>
<br>
---<br>
man/pass.1 | 10 ++++++++--<br>
src/password-store.sh | 37 ++++++++++++++++++++++++-------------<br>
2 files changed, 32 insertions(+), 15 deletions(-)<br>
<br>
diff --git a/man/pass.1 b/man/pass.1<br>
index 8ac8ecf..4d44f8a 100644<br>
--- a/man/pass.1<br>
+++ b/man/pass.1<br>
@@ -86,12 +86,15 @@ List names of passwords inside the tree that match \fIpass-names\fP by using the<br>
.BR tree (1)<br>
program. This command is alternatively named \fBsearch\fP.<br>
.TP<br>
-\fBshow\fP [ \fI--clip\fP, \fI-c\fP ] \fIpass-name\fP<br>
+\fBshow\fP [ \fI--clip\fP, \fI-c\fP | \fI--qr\fP, \fI-q\fP ] \fIpass-name\fP<br>
Decrypt and print a password named \fIpass-name\fP. If \fI--clip\fP or \fI-c\fP<br>
is specified, do not print the password but instead copy the first line to the<br>
clipboard using<br>
.BR xclip (1)<br>
and then restore the clipboard after 45 (or \fIPASSWORD_STORE_CLIP_TIME\fP) seconds.<br>
+If \fI--qr\fP or \fI-q\fP is specified, do not print the password but instead display the first line as a QR code<br>
+encoded using<br>
+.BR qrencode (1).<br>
.TP<br>
\fBinsert\fP [ \fI--echo\fP, \fI-e\fP | \fI--multiline\fP, \fI-m\fP ] [ \fI--force\fP, \fI-f\fP ] \fIpass-name\fP<br>
Insert a new password into the password store called \fIpass-name\fP. This will<br>
@@ -110,7 +113,7 @@ ensure that temporary files are created in \fI/dev/shm\fP in order to avoid writ<br>
difficult-to-erase disk sectors. If \fI/dev/shm\fP is not accessible, fallback to<br>
the ordinary \fITMPDIR\fP location, and print a warning.<br>
.TP<br>
-\fBgenerate\fP [ \fI--no-symbols\fP, \fI-n\fP ] [ \fI--clip\fP, \fI-c\fP ] [ \fI--in-place\fP, \fI-i\fP | \fI--force\fP, \fI-f\fP ] \fIpass-name pass-length\fP<br>
+\fBgenerate\fP [ \fI--no-symbols\fP, \fI-n\fP ] [ \fI--clip\fP, \fI-c\fP | \fI--qr\fP, \fI-q\fP ] [ \fI--in-place\fP, \fI-i\fP | \fI--force\fP, \fI-f\fP ] \fIpass-name pass-length\fP<br>
Generate a new password using<br>
.BR pwgen (1)<br>
of length \fIpass-length\fP and insert into \fIpass-name\fP. If \fI--no-symbols\fP or \fI-n\fP<br>
@@ -119,6 +122,9 @@ If \fI--clip\fP or \fI-c\fP is specified, do not print the password but instead<br>
it to the clipboard using<br>
.BR xclip (1)<br>
and then restore the clipboard after 45 (or \fIPASSWORD_STORE_CLIP_TIME\fP) seconds.<br>
+If \fI--qr\fP or \fI-q\fP is specified, do not print the password but instead display the first line as a QR code<br>
+encoded using<br>
+.BR qrencode (1).<br>
Prompt before overwriting an existing password,<br>
unless \fI--force\fP or \fI-f\fP is specified. If \fI--in-place\fP or \fI-i\fP is<br>
specified, do not interactively prompt, and only replace the first line of the password<br>
diff --git a/src/password-store.sh b/src/password-store.sh<br>
index e68384b..75b451b 100755<br>
--- a/src/password-store.sh<br>
+++ b/src/password-store.sh<br>
@@ -126,7 +126,10 @@ check_sneaky_paths() {<br>
[[ $path =~ /\.\.$ || $path =~ ^\.\./ || $path =~ /\.\./ || $path =~ ^\.\.$ ]] && die "Error: You've attempted to pass a sneaky path to pass. Go home."<br>
done<br>
}<br>
-<br>
+qr_encode() {<br>
+ echo "Displaying $2 as QR code."<br>
+ echo -n "$1" | qrencode --8bit --type=ANSI<br>
+}<br>
#<br>
# END helper functions<br>
#<br>
@@ -222,8 +225,8 @@ cmd_usage() {<br>
List passwords.<br>
$PROGRAM find pass-names...<br>
List passwords that match pass-names.<br>
- $PROGRAM [show] [--clip,-c] pass-name<br>
- Show existing password and optionally put it on the clipboard.<br>
+ $PROGRAM [show] [--clip,-c | --qr,-q] pass-name<br>
+ Show existing password and optionally put it on the clipboard or display it as a QR code.<br>
If put on the clipboard, it will be cleared in $CLIP_TIME seconds.<br>
$PROGRAM grep search-string<br>
Search for password files containing search-string when decrypted.<br>
@@ -233,9 +236,9 @@ cmd_usage() {<br>
overwriting existing password unless forced.<br>
$PROGRAM edit pass-name<br>
Insert a new password or edit an existing password using ${EDITOR:-vi}.<br>
- $PROGRAM generate [--no-symbols,-n] [--clip,-c] [--in-place,-i | --force,-f] pass-name pass-length<br>
+ $PROGRAM generate [--no-symbols,-n] [--clip,-c | --qr,-q] [--in-place,-i | --force,-f] pass-name pass-length<br>
Generate a new password of pass-length with optionally no symbols.<br>
- Optionally put it on the clipboard and clear board after 45 seconds.<br>
+ Optionally put it on the clipboard and clear board after $CLIP_TIME seconds, or display it as a QR code.<br>
Prompt before overwriting existing password unless forced.<br>
Optionally replace only the first line of an existing file with a new password.<br>
$PROGRAM rm [--recursive,-r] [--force,-f] pass-name<br>
@@ -294,27 +297,32 @@ cmd_init() {<br>
}<br>
<br>
cmd_show() {<br>
- local opts clip=0<br>
- opts="$($GETOPT -o c -l clip -n "$PROGRAM" -- "$@")"<br>
+ local opts clip=0 qr=0<br>
+ opts="$($GETOPT -o cq -l clip,qr -n "$PROGRAM" -- "$@")"<br>
local err=$?<br>
eval set -- "$opts"<br>
while true; do case $1 in<br>
-c|--clip) clip=1; shift ;;<br>
+ -q|--qr) qr=1; shift ;;<br>
--) shift; break ;;<br>
esac done<br>
<br>
- [[ $err -ne 0 ]] && die "Usage: $PROGRAM $COMMAND [--clip,-c] [pass-name]"<br>
+ [[ $err -ne 0 ]] && die "Usage: $PROGRAM $COMMAND [--clip,-c | --qr,-q] [pass-name]"<br>
<br>
local path="$1"<br>
local passfile="$PREFIX/$path.gpg"<br>
check_sneaky_paths "$path"<br>
if [[ -f $passfile ]]; then<br>
- if [[ $clip -eq 0 ]]; then<br>
+ if [[ $clip -eq 0 && $qr -eq 0 ]]; then<br>
exec $GPG -d "${GPG_OPTS[@]}" "$passfile"<br>
else<br>
local pass="$($GPG -d "${GPG_OPTS[@]}" "$passfile" | head -n 1)"<br>
[[ -n $pass ]] || exit 1<br>
- clip "$pass" "$path"<br>
+ if [[ $clip -eq 1 ]]; then<br>
+ clip "$pass" "$path"<br>
+ elif [[ $qr -eq 1 ]]; then<br>
+ qr_encode "$pass" "$path"<br>
+ fi<br>
fi<br>
elif [[ -d $PREFIX/$path ]]; then<br>
if [[ -z $path ]]; then<br>
@@ -435,12 +443,13 @@ cmd_edit() {<br>
<br>
cmd_generate() {<br>
local opts clip=0 force=0 symbols="-y" inplace=0<br>
- opts="$($GETOPT -o ncif -l no-symbols,clip,in-place,force -n "$PROGRAM" -- "$@")"<br>
+ opts="$($GETOPT -o ncqif -l no-symbols,clip,qr,in-place,force -n "$PROGRAM" -- "$@")"<br>
local err=$?<br>
eval set -- "$opts"<br>
while true; do case $1 in<br>
-n|--no-symbols) symbols=""; shift ;;<br>
-c|--clip) clip=1; shift ;;<br>
+ -q|--qr) qr=1; shift ;;<br>
-f|--force) force=1; shift ;;<br>
-i|--in-place) inplace=1; shift ;;<br>
--) shift; break ;;<br>
@@ -474,10 +483,12 @@ cmd_generate() {<br>
[[ $inplace -eq 1 ]] && verb="Replace"<br>
git_add_file "$passfile" "$verb generated password for ${path}."<br>
<br>
- if [[ $clip -eq 0 ]]; then<br>
+ if [[ $clip -eq 0 && $qr -eq 0 ]]; then<br>
printf "\e[1m\e[37mThe generated password for \e[4m%s\e[24m is:\e[0m\n\e[1m\e[93m%s\e[0m\n" "$path" "$pass"<br>
- else<br>
+ elif [[ $clip -eq 1 ]]; then<br>
clip "$pass" "$path"<br>
+ elif [[ $qr -eq 1 ]]; then<br>
+ qr_encode "$pass" "$path"<br>
fi<br>
}<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
2.0.0<br>
<br>
_______________________________________________<br>
Password-Store mailing list<br>
<a href="mailto:Password-Store@lists.zx2c4.com">Password-Store@lists.zx2c4.com</a><br>
<a href="http://lists.zx2c4.com/mailman/listinfo/password-store" target="_blank">http://lists.zx2c4.com/mailman/listinfo/password-store</a><br>
</font></span></blockquote></div><br></div>