Compare commits

...

2 commits

5 changed files with 274 additions and 33 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
yad

View file

@ -1,18 +1,24 @@
# qPDF Decode
Shell scripts for easier decrypting PDF files with a password using
[QPDF](https://qpdf.sourceforge.io/).
[<img align="right" width="96" alt="Application icon depicting a white unlocked padlock on a red sheet of paper"
title="Link to qPDF Decode main repo"
src="img/qpdf-decode-gui.svg">](https://git.disroot.org/daltux/qpdf-decode)
Permanent decryption of a single PDF file using a password.
Main repository: <https://git.disroot.org/daltux/qpdf-decode>
## Dependencies
- **[QPDF](https://qpdf.sourceforge.io/)** (tested on version 11.6.3)
- **[QPDF](https://qpdf.sourceforge.io/)** tool
- versions tested: 11.6.3, 8.0.2
- A POSIX-compliant Shell (`/bin/sh`)
- tested on [Debian GNU/Linux](https://debian.org) and Ubuntu with:
- [`dash`](https://manpages.debian.org/testing/dash/dash.1.en.html) 0.5.12, 0.5.8
- [`posh`](https://manpages.debian.org/testing/posh/posh.1.en.html) 0.14.1
- [`posh`](https://manpages.debian.org/testing/posh/posh.1.en.html) 0.14.1, 0.13.1
- [`busybox sh`](http://www.busybox.net) 1.36.1
- For the graphic user interface:
- For the graphic user interface (`qpdf-decode-gui`):
- [YAD](https://github.com/v1cont/yad)
- tested on 0.40.0 from Debian, Xfce 4.18, GTK+ 3.24.38
- tested on 0.38.2 from Ubuntu 18.04

36
img/qpdf-decode-gui.svg Normal file
View file

@ -0,0 +1,36 @@
<svg version="1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<title>qpdf-decode-gui.svg</title>
<path d="m28 5v10c0 1.1046 0.89543 2 2 2h10z" opacity=".2"/>
<path d="m10 5c-1.108 0-2 0.892-2 2v36c0 1.108 0.892 2 2 2h28c1.108 0 2-0.892 2-2v-26l-11-1-1-11z" opacity=".2"/>
<path d="m10 4c-1.108 0-2 0.892-2 2v36c0 1.108 0.892 2 2 2h28c1.108 0 2-0.892 2-2v-26l-11-1-1-11z" fill="#c03630"/>
<path d="m10 4c-1.108 0-2 0.892-2 2v1c0-1.108 0.892-2 2-2h18l11 11h1l-12-12z" fill="#fff" opacity=".1"/>
<path d="m28 4v10c0 1.1046 0.89543 2 2 2h10z" fill="#f36961"/>
<g transform="matrix(.65949 0 0 .65949 .21066 -4.9356)">
<path d="m22.78 17.18c-0.46126 0-0.89261 0.22577-0.99696 0.59841-0.38752 1.4286 0.0462 3.6379 0.76956 6.3906l-0.21821 0.53294c-0.55387 1.3501-1.2462 2.6947-1.855 3.8879-2.5135 4.918-4.4689 7.5715-5.7727 7.7574l-5e-3 -0.054c-0.0283-0.61346 1.1038-2.1951 2.6382-3.4526 0.16005-0.12944 0.84304-0.79021 0.84304-0.79021s-0.92191 0.48667-1.129 0.61218c-1.9228 1.1477-2.8796 2.2976-3.0356 3.0609-0.0463 0.22672-0.0166 0.5057 0.18375 0.62024l0.4916 0.24694c1.3384 0.66995 2.9841-1.0916 5.172-4.9262 2.2264-0.73036 5.0043-1.418 7.5335-1.7906 2.264 1.2936 4.861 1.9095 5.8588 1.6436 0.18987-0.0502 0.3896-0.19924 0.4916-0.33652 0.08-0.12631 0.19183-0.63172 0.19183-0.63172s-0.18773 0.25547-0.3423 0.33078c-0.63152 0.29811-2.6253-0.19924-4.6712-1.2002 1.769-0.18828 3.2427-0.19554 4.0303 0.0562 1.0003 0.3193 1.0011 0.64659 0.98778 0.71326 0.0135-0.0549 0.0583-0.27418 0.0528-0.36753-0.0227-0.24006-0.0967-0.45443-0.27795-0.63172-0.37027-0.36479-1.2845-0.54862-2.5303-0.56509-0.939-0.0102-2.065 0.072-3.2872 0.24694-0.56012-0.32164-1.1512-0.67522-1.6195-1.113-1.1877-1.1093-2.1832-2.6494-2.8014-4.376 0.0422-0.16553 0.0826-0.32727 0.11944-0.49045 0.17183-0.77271 0.29517-3.3274 0.29517-3.3274s-0.48934 1.9192-0.56622 2.2087c-0.0494 0.18357-0.11086 0.3795-0.18147 0.58347-0.375-1.3179-0.56509-2.5952-0.56509-3.564 0-0.27379 0.0235-0.80656 0.10105-1.2278 0.0378-0.30045 0.1466-0.45647 0.2596-0.53179 0.22357 0.0542 0.47383 0.39708 0.73509 0.97054 0.22435 0.4958 0.21017 1.07 0.21017 1.4254 0 0 0.24061-0.87999 0.18492-1.4001-0.0339-0.31223-0.33096-1.1155-0.96248-1.1061h-0.0517l-0.28139-3e-3zm0.21478 7.9791c0.65351 1.314 1.5548 2.5619 2.7371 3.5629 0.26357 0.22279 0.544 0.43475 0.83269 0.634-2.1471 0.39931-4.4021 0.96102-6.4975 1.8389 0.37891-0.67309 0.78861-1.4064 1.2083-2.1972 0.81274-1.5368 1.3052-2.7222 1.7194-3.8385z" opacity=".2"/>
<path d="m22.78 16.18c-0.46126 0-0.89261 0.22577-0.99696 0.59841-0.38752 1.4286 0.0462 3.6379 0.76956 6.3906l-0.21821 0.53294c-0.55387 1.3501-1.2462 2.6947-1.855 3.8879-2.5135 4.918-4.4689 7.5715-5.7727 7.7574l-5e-3 -0.054c-0.0283-0.61346 1.1038-2.1951 2.6382-3.4526 0.16005-0.12944 0.84304-0.79021 0.84304-0.79021s-0.92191 0.48667-1.129 0.61218c-1.9228 1.1477-2.8796 2.2976-3.0356 3.0609-0.0463 0.22672-0.0166 0.5057 0.18375 0.62024l0.4916 0.24694c1.3384 0.66995 2.9841-1.0916 5.172-4.9262 2.2264-0.73036 5.0043-1.418 7.5335-1.7906 2.264 1.2936 4.861 1.9095 5.8588 1.6436 0.18987-0.0502 0.3896-0.19924 0.4916-0.33652 0.08-0.12631 0.19183-0.63172 0.19183-0.63172s-0.18773 0.25547-0.3423 0.33078c-0.63152 0.29811-2.6253-0.19924-4.6712-1.2002 1.769-0.18828 3.2427-0.19554 4.0303 0.0562 1.0003 0.3193 1.0011 0.64659 0.98778 0.71326 0.0135-0.0549 0.0583-0.27418 0.0528-0.36753-0.0227-0.24006-0.0967-0.45443-0.27795-0.63172-0.37027-0.36479-1.2845-0.54862-2.5303-0.56509-0.939-0.0102-2.065 0.072-3.2872 0.24694-0.56012-0.32164-1.1512-0.67522-1.6195-1.113-1.1877-1.1093-2.1832-2.6494-2.8014-4.376 0.0422-0.16553 0.0826-0.32727 0.11944-0.49045 0.17183-0.77271 0.29517-3.3274 0.29517-3.3274s-0.48934 1.9192-0.56622 2.2087c-0.0494 0.18357-0.11086 0.3795-0.18147 0.58347-0.375-1.3179-0.56509-2.5952-0.56509-3.564 0-0.27379 0.0235-0.80656 0.10105-1.2278 0.0378-0.30045 0.1466-0.45647 0.2596-0.53179 0.22357 0.0542 0.47383 0.39708 0.73509 0.97054 0.22435 0.4958 0.21017 1.07 0.21017 1.4254 0 0 0.24061-0.87999 0.18492-1.4001-0.0339-0.31223-0.33096-1.1155-0.96248-1.1061h-0.0517l-0.28139-3e-3zm0.21478 7.9791c0.65351 1.314 1.5548 2.5619 2.7371 3.5629 0.26357 0.22279 0.544 0.43475 0.83269 0.634-2.1471 0.39931-4.4021 0.96102-6.4975 1.8389 0.37891-0.67309 0.78861-1.4064 1.2083-2.1972 0.81274-1.5368 1.3052-2.7222 1.7194-3.8385z" fill="#782121"/>
</g>
<g transform="matrix(1.1218 0 0 1.1218 18.22 20.903)">
<path d="m5.1527-3.2032c-3.2718 0-5.7795 1.525-6.1142 5.276h2.6741c0.35145-1.9561 1.8942-2.638 3.4401-2.638 1.7587 0 3.5174 0.87934 3.5174 3.5174v2.638h-10.846c-0.81192 0-1.465 0.65907-1.465 1.4942v9.3086c0 0.83512 0.65307 1.5079 1.465 1.5079h14.657c0.81192 0 1.465-0.67281 1.465-1.5079v-9.3086c0-0.83512-0.65307-1.4942-1.465-1.4942h-1.173v-2.638c0-4.3967-2.638-6.1554-6.1554-6.1554z" fill="#fff" stroke-width="1.7587"/>
</g>
<metadata>
<rdf:RDF>
<cc:Work rdf:about="">
<dc:title>qpdf-decode-gui.svg</dc:title>
<dc:date>2023-12-03</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>Daltux</dc:title>
</cc:Agent>
</dc:creator>
<dc:description>Icon for qpdf-decode-gui, mixing of application-pdf.svg and emblem-unlocked.svg from Papirus project (GPLv3) - https://git.io/papirus-icon-theme</dc:description>
<dc:contributor>
<cc:Agent>
<dc:title>See Papirus AUTHORS file</dc:title>
</cc:Agent>
</dc:contributor>
<dc:source>papirus-icon-theme</dc:source>
<cc:license rdf:resource="https://www.gnu.org/licenses/gpl-3.0.en.html"/>
</cc:Work>
</rdf:RDF>
</metadata>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

View file

@ -1,15 +1,6 @@
#!/bin/sh
# qpdf-decode: a script for calling qpdf with a password to decrypt a pdf.
# If the operation succeeds, the output will be a default new file adding a
# suffix "_decrypted" to the source file name. Be careful: if the output file
# already exists, it will be overwritten without warning!
#
# Parameters:
# 1st. PASSWORD
# 2nd. file to be decrypted
# 3rd. (optional) file to save (default: the same name concatenating _decrypted)
#
# qpdf-decode: permanent decryption of a PDF file with its password
# Copyright © 2023 Daltux <https://daltux.net/>
#
# This program is free software: you can redistribute it and/or modify
@ -24,31 +15,49 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
app_title=qpdf-decode
app_version=0.2.0
###
# This script calls qpdf with a password in order to decrypt a single PDF.
# If the operation succeeds, the output will be a default new file adding a
# suffix "_decrypted" to the source file name. Be careful: if the output file
# already exists, it will be overwritten without warning!
#
# Parameters:
# 1st. PASSWORD
# 2nd. file to be decrypted
# 3rd. (optional) file to save (default: the same name concatenating _decrypted)
app_title='qpdf-decode'
app_version='0.2.0'
app_description='permanent decryption of a PDF file with its password'
out_suffix="_decrypted"
about() {
echo "$app_title: decrypts a pdf"
echo "$app_title: $app_description"
echo "Version $app_version"
echo
echo "Copyright (C) 2023 Daltux <https://daltux.net>"
echo "This program comes with ABSOLUTELY NO WARRANTY;"
echo "This is Free Software, and you are welcome to redistribute it under certain conditions. For details, see the GNU General Public License, version 3 or later."
echo 'Copyright (C) 2023 Daltux <https://daltux.net>'
echo
echo "Usage:"
echo " $0 <password> <file to decode> [optional: file to save (default *_decrypted)]"
echo 'This program comes with ABSOLUTELY NO WARRANTY;'
echo 'This is Free Software, and you are welcome to redistribute it under'
echo 'certain conditions. For details, see the GNU General Public License,'
echo 'version 3 or later: <https://gnu.org/licenses/gpl.html>'
echo
echo "Be careful: if the output file already exists, it will be overwritten without warning!"
echo 'Usage:'
echo " $0 <password> <input file> [output file]"
echo
echo "Exit codes meaning:"
echo " 0: no errors or warnings"
echo " 1: unable to invoke qpdf"
echo " 2: qpdf error"
echo " 3: qpdf warning"
echo " 4: missing password for decryption"
echo " 5: missing reference to file"
echo "The default output file is the same as input with suffix \"$out_suffix\""
echo
echo 'Be careful: if the output file already exists, it will be overwritten'
echo 'without warning!'
echo
echo 'Exit codes meaning:'
echo ' 0: no errors or warnings'
echo ' 1: unable to invoke qpdf'
echo ' 2: qpdf error'
echo ' 3: qpdf warning'
echo ' 4: missing password for decryption'
echo ' 5: missing reference to file'
}
# strFind <string> <substring to find>
@ -79,7 +88,7 @@ if [ -z "$infile" ] ; then
exit 5
fi
outfile=${infile}_decrypted
outfile=${infile}${out_suffix}
outfile=${3:-$outfile}
if command -v qpdf > /dev/null 2>&1 ; then

189
qpdf-decode-gui Executable file
View file

@ -0,0 +1,189 @@
#!/bin/sh
# qpdf-decode-gui: a script using yad as graphic user interface for calling
# qpdf with a password to decrypt a pdf. If the operation succeeds, the output
# will be a default new file adding a suffix "_decrypted" to the source file
# name. Be careful: if the output file already exists, it will be overwritten
# without warning!
#
# Copyright © 2023 Daltux <https://daltux.net/>
#
# 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/>.
#
# Dependencies:
# 0: qpdf-decode in $PATH or the same directory of this file
# 1: qpdf
# 2: yad
app_title='qPDF Decode'
app_version='0.2.0'
app_icon='application-pdf'
qpdfd_name='qpdf-decode'
qpdfd="$qpdfd_name"
if [ -n "$1" ] && ([ "$1" = '-h' ] || [ "${@#*"--help"}" != "$@" ]) ; then
echo "$app_title (GUI) $app_version"
echo
echo "Copyright (C) 2023 Daltux <https://daltux.net>"
echo "This program comes with ABSOLUTELY NO WARRANTY;"
echo "This is Free Software, and you are welcome to redistribute it under certain conditions. For details, see the GNU General Public License, version 3 or later."
echo
echo "Usage:"
echo " $0 [optional: file to decode]"
exit
fi
cmdExists() {
command -v "$1" > /dev/null 2>&1
return $?
}
yadExists() {
if [ -z $yadExists ] ; then
cmdExists yad
yadExists=$?
fi
return $yadExists
}
myad() {
yad --center --borders=10 --image-on-top --buttons-layout=edge \
--title="$app_title" --window-icon="$app_icon" "$@"
}
errorDlg() {
local errorMsg="$@"
echo "$app_title ERROR: $errorMsg" >&2
if yadExists ; then
myad --close-on-unfocus \
--image="dialog-error" \
--escape-ok \
--text="$errorMsg" \
--button=gtk-close:30 \
--timeout=10 \
--timeoutindicator=top
elif cmdExists notify-send ; then
notify-send --icon=error "$app_title ERROR" "$errorMsg"
fi
}
if ! cmdExists "$qpdfd" ; then
qpdfd_path=$(realpath "$0")
qpdfd=$(dirname "$qpdf_path")/"$qpdfd"
fi
if ! [ -x "$qpdfd" ] ; then
errorDlg "Cannot find or run:\n<b>$qpdfd</b>"
exit 30
fi
if ! yadExists ; then
errorDlg "Cannot find or run:\n<b>yad</b>"
exit 31
fi
if [ -n "$1" ] ; then
infile=$1
else
infile=$(myad --title="$app_title" \
--window-icon="$app_icon" \
--text="Select the <b>source</b> PDF file:" \
--file --on-top)
fi
if [ -z "$infile" ] ; then
errorDlg "No input file provided."
exit 50
elif ! [ -e "$infile" ] ; then
errorDlg "Input file not found:\n\n<tt>$infile</tt>"
exit 51
fi
if cmdExists mimetype ; then
mimecmd='mimetype'
mimecmd_opts='-b'
elif cmdExists file ; then
mimecmd='file'
mimecmd_opts='-ib'
elif cmdExists xdg-mime ; then
mimecmd='xdg-mime'
mimecmd_opts='query filetype'
fi
pdfmime='application/pdf'
xpdfmime='application/x-pdf'
if [ -n "$mimecmd" ] && ! "$mimecmd" "$mimecmd_opts" "$infile" | grep -Fqs -e "$pdfmime" -e "$xpdfmime" ; then
errorDlg "Media Type different than\n\"<tt>$pdfmime</tt>\" or \"<tt>$xpdfmime</tt>\":\n\n<tt>$infile</tt>"
exit 52
fi
inpath=$(dirname "$infile")
outfile=$(myad \
--text="Select the <b>output</b> PDF file:" \
--on-top --file --save --add-preview --mime-filter="$pdfmime" --mime-filter="$xpdfmime" \
--confirm-overwrite="Output file already exists. Do you want to overwrite it?")
pass=$(myad \
--image="dialog-password" \
--text="Enter passphrase for file\n<tt><b>$infile</b></tt>:" \
--entry --hide-text --entry-label="Passphrase")
if [ -z $pass ] ; then
errorDlg "Missing passphrase for decryption."
exit 40
fi
#myad --form \
# --text "Password for decrypting $infile" \
# --image Frutas.jpg \
# --field "Escolha uma fruta:CB" 'Pera!Uva!Maçã!Manga' \
# --field Outra "" \
# --field "Qtas vc come?:NUM" '1!1..10!1' \
# --field "Arquivo:FL" \
# --field "Como e chupo o caroço:CHK"
#outfile=${infile}_decrypted
#outfile=${3:-$outfile}
qpdfd_output=$( "$qpdfd" "$pass" "$infile" "$outfile" 2>&1 )
qpdfd_exit=$?
case $qpdfd_exit in
0)
[ -n "$qpdfd_output" ] && echo "$qpdfd_output"
myad --text="Operation succeeded.\n\n<tt>$qpdfd_output</tt>" \
--button="gtk-ok:0" \
--image="dialog-information"
;;
1)
errorDlg "Unable to run qpdf."
;;
2|3)
errorDlg "QPDF error or warning:\n\n<tt>$qpdfd_output</tt>"
;;
4)
errorDlg "Missing passphrase for decryption."
;;
5)
errorDlg "Missing reference to source PDF file."
;;
*)
errorDlg "Unspecified output:\n\n<tt>$qpdfd_output</tt>"
;;
esac
exit $qpdfd_exit