1/* poppler-pdf-converter.cc: qt interface to poppler
2 * Copyright (C) 2008, Pino Toscano <pino@kde.org>
3 * Copyright (C) 2008, 2009, 2020-2022, Albert Astals Cid <aacid@kde.org>
4 * Copyright (C) 2020, Thorsten Behrens <Thorsten.Behrens@CIB.de>
5 * Copyright (C) 2020, Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by Technische Universität Dresden
6 * Copyright (C) 2021, Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>.
7 * Copyright (C) 2021, Zachary Travis <ztravis@everlaw.com>
8 * Copyright (C) 2021, Georgiy Sgibnev <georgiy@sgibnev.com>. Work sponsored by lab50.net.
9 * Copyright (C) 2022, Martin <martinbts@gmx.net>
10 * Copyright (C) 2022, Felix Jung <fxjung@posteo.de>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2, or (at your option)
15 * any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
25 */
26
27#include "poppler-qt6.h"
28
29#include "poppler-annotation-helper.h"
30#include "poppler-annotation-private.h"
31#include "poppler-private.h"
32#include "poppler-converter-private.h"
33#include "poppler-qiodeviceoutstream-private.h"
34
35#include <QFile>
36#include <QUuid>
37
38#include "Array.h"
39#include "Form.h"
40#include <ErrorCodes.h>
41
42namespace Poppler {
43
44class PDFConverterPrivate : public BaseConverterPrivate
45{
46public:
47 PDFConverterPrivate();
48 ~PDFConverterPrivate() override;
49
50 PDFConverter::PDFOptions opts;
51};
52
53PDFConverterPrivate::PDFConverterPrivate() : BaseConverterPrivate() { }
54
55PDFConverterPrivate::~PDFConverterPrivate() = default;
56
57PDFConverter::PDFConverter(DocumentData *document) : BaseConverter(*new PDFConverterPrivate())
58{
59 Q_D(PDFConverter);
60 d->document = document;
61}
62
63PDFConverter::~PDFConverter() { }
64
65void PDFConverter::setPDFOptions(PDFConverter::PDFOptions options)
66{
67 Q_D(PDFConverter);
68 d->opts = options;
69}
70
71PDFConverter::PDFOptions PDFConverter::pdfOptions() const
72{
73 Q_D(const PDFConverter);
74 return d->opts;
75}
76
77bool PDFConverter::convert()
78{
79 Q_D(PDFConverter);
80 d->lastError = NoError;
81
82 if (d->document->locked) {
83 d->lastError = FileLockedError;
84 return false;
85 }
86
87 QIODevice *dev = d->openDevice();
88 if (!dev) {
89 d->lastError = OpenOutputError;
90 return false;
91 }
92
93 bool deleteFile = false;
94 if (QFile *file = qobject_cast<QFile *>(object: dev)) {
95 deleteFile = !file->exists();
96 }
97
98 int errorCode = errNone;
99 QIODeviceOutStream stream(dev);
100 if (d->opts & WithChanges) {
101 errorCode = d->document->doc->saveAs(outStr: &stream);
102 } else {
103 errorCode = d->document->doc->saveWithoutChangesAs(outStr: &stream);
104 }
105 d->closeDevice();
106 if (errorCode != errNone) {
107 if (deleteFile) {
108 qobject_cast<QFile *>(object: dev)->remove();
109 }
110 if (errorCode == errOpenFile) {
111 d->lastError = OpenOutputError;
112 } else {
113 d->lastError = NotSupportedInputFileError;
114 }
115 }
116
117 return (errorCode == errNone);
118}
119
120bool PDFConverter::sign(const NewSignatureData &data)
121{
122 Q_D(PDFConverter);
123 d->lastError = NoError;
124
125 if (d->document->locked) {
126 d->lastError = FileLockedError;
127 return false;
128 }
129
130 if (data.signatureText().isEmpty()) {
131 qWarning() << "No signature text given";
132 return false;
133 }
134
135 ::PDFDoc *doc = d->document->doc;
136 ::Page *destPage = doc->getPage(page: data.page() + 1);
137 std::unique_ptr<GooString> gSignatureText = std::unique_ptr<GooString>(QStringToUnicodeGooString(s: data.signatureText()));
138 std::unique_ptr<GooString> gSignatureLeftText = std::unique_ptr<GooString>(QStringToUnicodeGooString(s: data.signatureLeftText()));
139 const auto reason = std::unique_ptr<GooString>(data.reason().isEmpty() ? nullptr : QStringToUnicodeGooString(s: data.reason()));
140 const auto location = std::unique_ptr<GooString>(data.location().isEmpty() ? nullptr : QStringToUnicodeGooString(s: data.location()));
141 const auto ownerPwd = std::optional<GooString>(data.documentOwnerPassword().constData());
142 const auto userPwd = std::optional<GooString>(data.documentUserPassword().constData());
143 return doc->sign(saveFilename: d->outputFileName.toUtf8().constData(), certNickname: data.certNickname().toUtf8().constData(), password: data.password().toUtf8().constData(), partialFieldName: QStringToGooString(s: data.fieldPartialName()), page: data.page() + 1,
144 rect: boundaryToPdfRectangle(pdfPage: destPage, r: data.boundingRectangle(), flags: Annotation::FixedRotation), signatureText: *gSignatureText, signatureTextLeft: *gSignatureLeftText, fontSize: data.fontSize(), leftFontSize: data.leftFontSize(), fontColor: convertQColor(color: data.fontColor()), borderWidth: data.borderWidth(),
145 borderColor: convertQColor(color: data.borderColor()), backgroundColor: convertQColor(color: data.backgroundColor()), reason: reason.get(), location: location.get(), imagePath: data.imagePath().toStdString(), ownerPassword: ownerPwd, userPassword: userPwd);
146}
147
148struct PDFConverter::NewSignatureData::NewSignatureDataPrivate
149{
150 NewSignatureDataPrivate() = default;
151
152 QString certNickname;
153 QString password;
154 int page;
155 QRectF boundingRectangle;
156 QString signatureText;
157 QString signatureLeftText;
158 QString reason;
159 QString location;
160 double fontSize = 10.0;
161 double leftFontSize = 20.0;
162 QColor fontColor = Qt::red;
163 QColor borderColor = Qt::red;
164 double borderWidth = 1.5;
165 QColor backgroundColor = QColor(240, 240, 240);
166
167 QString partialName = QUuid::createUuid().toString();
168
169 QByteArray documentOwnerPassword;
170 QByteArray documentUserPassword;
171
172 QString imagePath;
173};
174
175PDFConverter::NewSignatureData::NewSignatureData() : d(new NewSignatureDataPrivate()) { }
176
177PDFConverter::NewSignatureData::~NewSignatureData()
178{
179 delete d;
180}
181
182QString PDFConverter::NewSignatureData::certNickname() const
183{
184 return d->certNickname;
185}
186
187void PDFConverter::NewSignatureData::setCertNickname(const QString &certNickname)
188{
189 d->certNickname = certNickname;
190}
191
192QString PDFConverter::NewSignatureData::password() const
193{
194 return d->password;
195}
196
197void PDFConverter::NewSignatureData::setPassword(const QString &password)
198{
199 d->password = password;
200}
201
202int PDFConverter::NewSignatureData::page() const
203{
204 return d->page;
205}
206
207void PDFConverter::NewSignatureData::setPage(int page)
208{
209 d->page = page;
210}
211
212QRectF PDFConverter::NewSignatureData::boundingRectangle() const
213{
214 return d->boundingRectangle;
215}
216
217void PDFConverter::NewSignatureData::setBoundingRectangle(const QRectF &rect)
218{
219 d->boundingRectangle = rect;
220}
221
222QString PDFConverter::NewSignatureData::signatureText() const
223{
224 return d->signatureText;
225}
226
227void PDFConverter::NewSignatureData::setSignatureText(const QString &text)
228{
229 d->signatureText = text;
230}
231
232QString PDFConverter::NewSignatureData::signatureLeftText() const
233{
234 return d->signatureLeftText;
235}
236
237void PDFConverter::NewSignatureData::setSignatureLeftText(const QString &text)
238{
239 d->signatureLeftText = text;
240}
241
242QString PDFConverter::NewSignatureData::reason() const
243{
244 return d->reason;
245}
246
247void PDFConverter::NewSignatureData::setReason(const QString &reason)
248{
249 d->reason = reason;
250}
251
252QString PDFConverter::NewSignatureData::location() const
253{
254 return d->location;
255}
256
257void PDFConverter::NewSignatureData::setLocation(const QString &location)
258{
259 d->location = location;
260}
261
262double PDFConverter::NewSignatureData::fontSize() const
263{
264 return d->fontSize;
265}
266
267void PDFConverter::NewSignatureData::setFontSize(double fontSize)
268{
269 d->fontSize = fontSize;
270}
271
272double PDFConverter::NewSignatureData::leftFontSize() const
273{
274 return d->leftFontSize;
275}
276
277void PDFConverter::NewSignatureData::setLeftFontSize(double fontSize)
278{
279 d->leftFontSize = fontSize;
280}
281
282QColor PDFConverter::NewSignatureData::fontColor() const
283{
284 return d->fontColor;
285}
286
287void PDFConverter::NewSignatureData::setFontColor(const QColor &color)
288{
289 d->fontColor = color;
290}
291
292QColor PDFConverter::NewSignatureData::borderColor() const
293{
294 return d->borderColor;
295}
296
297void PDFConverter::NewSignatureData::setBorderColor(const QColor &color)
298{
299 d->borderColor = color;
300}
301
302QColor PDFConverter::NewSignatureData::backgroundColor() const
303{
304 return d->backgroundColor;
305}
306
307double PDFConverter::NewSignatureData::borderWidth() const
308{
309 return d->borderWidth;
310}
311
312void PDFConverter::NewSignatureData::setBorderWidth(double width)
313{
314 d->borderWidth = width;
315}
316
317void PDFConverter::NewSignatureData::setBackgroundColor(const QColor &color)
318{
319 d->backgroundColor = color;
320}
321
322QString PDFConverter::NewSignatureData::fieldPartialName() const
323{
324 return d->partialName;
325}
326
327void PDFConverter::NewSignatureData::setFieldPartialName(const QString &name)
328{
329 d->partialName = name;
330}
331
332QByteArray PDFConverter::NewSignatureData::documentOwnerPassword() const
333{
334 return d->documentOwnerPassword;
335}
336
337void PDFConverter::NewSignatureData::setDocumentOwnerPassword(const QByteArray &password)
338{
339 d->documentOwnerPassword = password;
340}
341
342QByteArray PDFConverter::NewSignatureData::documentUserPassword() const
343{
344 return d->documentUserPassword;
345}
346
347void PDFConverter::NewSignatureData::setDocumentUserPassword(const QByteArray &password)
348{
349 d->documentUserPassword = password;
350}
351
352QString PDFConverter::NewSignatureData::imagePath() const
353{
354 return d->imagePath;
355}
356
357void PDFConverter::NewSignatureData::setImagePath(const QString &path)
358{
359 d->imagePath = path;
360}
361}
362

source code of poppler/qt6/src/poppler-pdf-converter.cc