summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErich E. Hoover <erich.e.hoover@gmail.com>2024-02-08 11:07:24 -0700
committerAlbert Astals Cid <aacid@kde.org>2024-02-18 17:45:13 +0000
commita7f1652ebdb78a4757565a91b62294ad7333ec75 (patch)
tree543fcde1d305d878061e61361a5ac75cfa90538b
parent53b98e8d3c7783b4340e6006e7641fa6b0ffe3ec (diff)
pdfsig: Sign form signature fields with an appearance
-rw-r--r--utils/CMakeLists.txt7
-rw-r--r--utils/pdfsig.13
-rw-r--r--utils/pdfsig.cc33
-rw-r--r--utils/po/CMakeLists.txt26
-rw-r--r--utils/po/pdfsig.pot26
5 files changed, 94 insertions, 1 deletions
diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt
index d9795eb9..8fb7a509 100644
--- a/utils/CMakeLists.txt
+++ b/utils/CMakeLists.txt
@@ -1,3 +1,4 @@
+include(FindGettext)
set(common_srcs
parseargs.cc
@@ -93,6 +94,12 @@ target_link_libraries(pdfinfo ${common_libs})
install(TARGETS pdfinfo DESTINATION bin)
install(FILES pdfinfo.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
+if (GETTEXT_FOUND AND ENABLE_SIGNATURES)
+ add_definitions(-DHAVE_GETTEXT)
+ add_definitions(-DCMAKE_INSTALL_LOCALEDIR="${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LOCALEDIR}")
+ add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/po")
+endif ()
+
if (ENABLE_SIGNATURES)
# pdfsig
set(pdfsig_SOURCES ${common_srcs}
diff --git a/utils/pdfsig.1 b/utils/pdfsig.1
index 30364684..93bb5ea5 100644
--- a/utils/pdfsig.1
+++ b/utils/pdfsig.1
@@ -46,6 +46,9 @@ Do not validate the certificate.
.B \-no-ocsp
Do not perform online OCSP certificate revocation check (local Certificate Revocation Lists (CRL) are still used).
.TP
+.B \-no-appearance
+Do not add appearance information when signing existing fields (signer name and date).
+.TP
.B \-aia
Enable the use of Authority Information Access (AIA) extension to fetch missing certificates to build the certificate chain.
.TP
diff --git a/utils/pdfsig.cc b/utils/pdfsig.cc
index ecf43e9a..d9079611 100644
--- a/utils/pdfsig.cc
+++ b/utils/pdfsig.cc
@@ -38,6 +38,7 @@
#include "Page.h"
#include "PDFDoc.h"
#include "PDFDocFactory.h"
+#include "DateInfo.h"
#include "Error.h"
#include "GlobalParams.h"
#ifdef ENABLE_NSS3
@@ -52,6 +53,14 @@
# include <libgen.h>
#endif
+#ifdef HAVE_GETTEXT
+# include <libintl.h>
+# include <clocale>
+# define _(STRING) gettext(STRING)
+#else
+# define _(STRING) STRING
+#endif
+
static const char *getReadableSigState(SignatureValidationStatus sig_vs)
{
switch (sig_vs) {
@@ -139,6 +148,7 @@ static bool printHelp = false;
static bool printCryptoSignBackends = false;
static bool dontVerifyCert = false;
static bool noOCSPRevocationCheck = false;
+static bool noAppearance = false;
static bool dumpSignatures = false;
static bool etsiCAdESdetached = false;
static char backendString[256] = "";
@@ -156,6 +166,7 @@ static const ArgDesc argDesc[] = { { "-nssdir", argGooString, &nssDir, 0, "path
{ "-nss-pwd", argGooString, &nssPassword, 0, "password to access the NSS database (if any)" },
{ "-nocert", argFlag, &dontVerifyCert, 0, "don't perform certificate validation" },
{ "-no-ocsp", argFlag, &noOCSPRevocationCheck, 0, "don't perform online OCSP certificate revocation check" },
+ { "-no-appearance", argFlag, &noAppearance, 0, "don't add appearance information when signing existing fields" },
{ "-aia", argFlag, &useAIACertFetch, 0, "use Authority Information Access (AIA) extension for certificate fetching" },
{ "-dump", argFlag, &dumpSignatures, 0, "dump all signatures into current directory" },
{ "-add-signature", argFlag, &addNewSignature, 0, "adds a new signature to the document" },
@@ -512,8 +523,28 @@ int main(int argc, char *argv[])
printf("Unexpected number of widgets for the signature: %d\n", ffs->getNumWidgets());
return 2;
}
+#ifdef HAVE_GETTEXT
+ if (!noAppearance) {
+ setlocale(LC_ALL, "");
+ bindtextdomain("pdfsig", CMAKE_INSTALL_LOCALEDIR);
+ textdomain("pdfsig");
+ }
+#endif
FormWidgetSignature *fws = static_cast<FormWidgetSignature *>(ffs->getWidget(0));
- const bool success = fws->signDocument(std::string { argv[2] }, std::string { certNickname }, std::string { password }, rs.get());
+ auto backend = CryptoSign::Factory::createActive();
+ auto sigHandler = backend->createSigningHandler(certNickname, HashAlgorithm::Sha256);
+ std::unique_ptr<X509CertificateInfo> certInfo = sigHandler->getCertificateInfo();
+ if (!certInfo) {
+ fprintf(stderr, "signDocument: error getting signature info\n");
+ return 2;
+ }
+ const std::string signerName = certInfo->getSubjectInfo().commonName;
+ const std::string timestamp = timeToStringWithFormat(nullptr, "%Y.%m.%d %H:%M:%S %z");
+ const AnnotColor blackColor(0, 0, 0);
+ const std::string signatureText(GooString::format(_("Digitally signed by {0:s}"), signerName.c_str())->toStr() + "\n" + GooString::format(_("Date: {0:s}"), timestamp.c_str())->toStr());
+ const auto gSignatureText = std::make_unique<GooString>((signatureText.empty() || noAppearance) ? "" : utf8ToUtf16WithBom(signatureText));
+ const auto gSignatureLeftText = std::make_unique<GooString>((signerName.empty() || noAppearance) ? "" : utf8ToUtf16WithBom(signerName));
+ const bool success = fws->signDocumentWithAppearance(argv[2], std::string { certNickname }, std::string { password }, rs.get(), nullptr, {}, {}, *gSignatureText, *gSignatureLeftText, 0, 0, std::make_unique<AnnotColor>(blackColor));
return success ? 0 : 3;
}
diff --git a/utils/po/CMakeLists.txt b/utils/po/CMakeLists.txt
new file mode 100644
index 00000000..d9fca3c5
--- /dev/null
+++ b/utils/po/CMakeLists.txt
@@ -0,0 +1,26 @@
+file(GLOB _files "${CMAKE_CURRENT_SOURCE_DIR}/*")
+foreach (_dir ${_files})
+ if (IS_DIRECTORY "${_dir}")
+ add_subdirectory("${_dir}")
+ get_filename_component(_lang ${_dir} NAME)
+ list(APPEND _langs ${_lang})
+ endif ()
+endforeach()
+
+
+macro(UPDATE_POT_FILE input)
+ set(_potFile "${input}.pot")
+ foreach(_lang ${_langs})
+ set(_poFile "${CMAKE_CURRENT_SOURCE_DIR}/${_lang}/${input}.po")
+ list(APPEND _commands
+ COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} --quiet --update --backup=none -s ${_poFile} "${CMAKE_CURRENT_SOURCE_DIR}/${_potFile}")
+ endforeach()
+ add_custom_target(update_pot_${input}
+ ALL
+ COMMAND xgettext --keyword=_ --language=c++ --package-name=pdfsig --output-dir=po --output=${_potFile} ${input}.cc
+ ${_commands}
+ DEPENDS ../${input}.cc
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/..)
+endmacro()
+
+UPDATE_POT_FILE(pdfsig)
diff --git a/utils/po/pdfsig.pot b/utils/po/pdfsig.pot
new file mode 100644
index 00000000..83095113
--- /dev/null
+++ b/utils/po/pdfsig.pot
@@ -0,0 +1,26 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the pdfsig package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: pdfsig\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2024-02-12 14:44-0700\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: pdfsig.cc:544
+msgid "Digitally signed by {0:s}"
+msgstr ""
+
+#: pdfsig.cc:544
+msgid "Date: {0:s}"
+msgstr ""