1 /* poppler-pdf-converter.cc: qt interface to poppler
2 * Copyright (C) 2008, Pino Toscano <pino@kde.org>
3 * Copyright (C) 2008, 2009, 2020, 2021, 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 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
23 */
24
25 #include "poppler-qt6.h"
26
27 #include "poppler-annotation-helper.h"
28 #include "poppler-annotation-private.h"
29 #include "poppler-private.h"
30 #include "poppler-converter-private.h"
31 #include "poppler-qiodeviceoutstream-private.h"
32
33 #include <QFile>
34 #include <QUuid>
35
36 #include "Array.h"
37 #include "Form.h"
38 #include <ErrorCodes.h>
39
40 namespace Poppler {
41
42 class PDFConverterPrivate : public BaseConverterPrivate
43 {
44 public:
45 PDFConverterPrivate();
46 ~PDFConverterPrivate() override;
47
48 PDFConverter::PDFOptions opts;
49 };
50
PDFConverterPrivate()51 PDFConverterPrivate::PDFConverterPrivate() : BaseConverterPrivate() { }
52
53 PDFConverterPrivate::~PDFConverterPrivate() = default;
54
PDFConverter(DocumentData * document)55 PDFConverter::PDFConverter(DocumentData *document) : BaseConverter(*new PDFConverterPrivate())
56 {
57 Q_D(PDFConverter);
58 d->document = document;
59 }
60
~PDFConverter()61 PDFConverter::~PDFConverter() { }
62
setPDFOptions(PDFConverter::PDFOptions options)63 void PDFConverter::setPDFOptions(PDFConverter::PDFOptions options)
64 {
65 Q_D(PDFConverter);
66 d->opts = options;
67 }
68
pdfOptions() const69 PDFConverter::PDFOptions PDFConverter::pdfOptions() const
70 {
71 Q_D(const PDFConverter);
72 return d->opts;
73 }
74
convert()75 bool PDFConverter::convert()
76 {
77 Q_D(PDFConverter);
78 d->lastError = NoError;
79
80 if (d->document->locked) {
81 d->lastError = FileLockedError;
82 return false;
83 }
84
85 QIODevice *dev = d->openDevice();
86 if (!dev) {
87 d->lastError = OpenOutputError;
88 return false;
89 }
90
91 bool deleteFile = false;
92 if (QFile *file = qobject_cast<QFile *>(dev))
93 deleteFile = !file->exists();
94
95 int errorCode = errNone;
96 QIODeviceOutStream stream(dev);
97 if (d->opts & WithChanges) {
98 errorCode = d->document->doc->saveAs(&stream);
99 } else {
100 errorCode = d->document->doc->saveWithoutChangesAs(&stream);
101 }
102 d->closeDevice();
103 if (errorCode != errNone) {
104 if (deleteFile) {
105 qobject_cast<QFile *>(dev)->remove();
106 }
107 if (errorCode == errOpenFile)
108 d->lastError = OpenOutputError;
109 else
110 d->lastError = NotSupportedInputFileError;
111 }
112
113 return (errorCode == errNone);
114 }
115
sign(const NewSignatureData & data)116 bool PDFConverter::sign(const NewSignatureData &data)
117 {
118 Q_D(PDFConverter);
119 d->lastError = NoError;
120
121 if (d->document->locked) {
122 d->lastError = FileLockedError;
123 return false;
124 }
125
126 if (data.signatureText().isEmpty()) {
127 qWarning() << "No signature text given";
128 return false;
129 }
130
131 ::PDFDoc *doc = d->document->doc;
132 ::Page *destPage = doc->getPage(data.page() + 1);
133 std::unique_ptr<GooString> gSignatureText = std::unique_ptr<GooString>(QStringToUnicodeGooString(data.signatureText()));
134 std::unique_ptr<GooString> gSignatureLeftText = std::unique_ptr<GooString>(QStringToUnicodeGooString(data.signatureLeftText()));
135 const auto reason = std::unique_ptr<GooString>(data.reason().isEmpty() ? nullptr : QStringToUnicodeGooString(data.reason()));
136 const auto location = std::unique_ptr<GooString>(data.location().isEmpty() ? nullptr : QStringToUnicodeGooString(data.location()));
137 return doc->sign(d->outputFileName.toUtf8().constData(), data.certNickname().toUtf8().constData(), data.password().toUtf8().constData(), QStringToGooString(data.fieldPartialName()), data.page() + 1,
138 boundaryToPdfRectangle(destPage, data.boundingRectangle(), Annotation::FixedRotation), *gSignatureText, *gSignatureLeftText, data.fontSize(), convertQColor(data.fontColor()), data.borderWidth(),
139 convertQColor(data.borderColor()), convertQColor(data.backgroundColor()), reason.get(), location.get());
140 }
141
142 struct PDFConverter::NewSignatureData::NewSignatureDataPrivate
143 {
144 NewSignatureDataPrivate() = default;
145
146 QString certNickname;
147 QString password;
148 int page;
149 QRectF boundingRectangle;
150 QString signatureText;
151 QString signatureLeftText;
152 QString reason;
153 QString location;
154 double fontSize = 10.0;
155 double leftFontSize = 20.0;
156 QColor fontColor = Qt::red;
157 QColor borderColor = Qt::red;
158 double borderWidth = 1.5;
159 QColor backgroundColor = QColor(240, 240, 240);
160
161 QString partialName = QUuid::createUuid().toString();
162 };
163
NewSignatureData()164 PDFConverter::NewSignatureData::NewSignatureData() : d(new NewSignatureDataPrivate()) { }
165
~NewSignatureData()166 PDFConverter::NewSignatureData::~NewSignatureData()
167 {
168 delete d;
169 }
170
certNickname() const171 QString PDFConverter::NewSignatureData::certNickname() const
172 {
173 return d->certNickname;
174 }
175
setCertNickname(const QString & certNickname)176 void PDFConverter::NewSignatureData::setCertNickname(const QString &certNickname)
177 {
178 d->certNickname = certNickname;
179 }
180
password() const181 QString PDFConverter::NewSignatureData::password() const
182 {
183 return d->password;
184 }
185
setPassword(const QString & password)186 void PDFConverter::NewSignatureData::setPassword(const QString &password)
187 {
188 d->password = password;
189 }
190
page() const191 int PDFConverter::NewSignatureData::page() const
192 {
193 return d->page;
194 }
195
setPage(int page)196 void PDFConverter::NewSignatureData::setPage(int page)
197 {
198 d->page = page;
199 }
200
boundingRectangle() const201 QRectF PDFConverter::NewSignatureData::boundingRectangle() const
202 {
203 return d->boundingRectangle;
204 }
205
setBoundingRectangle(const QRectF & rect)206 void PDFConverter::NewSignatureData::setBoundingRectangle(const QRectF &rect)
207 {
208 d->boundingRectangle = rect;
209 }
210
signatureText() const211 QString PDFConverter::NewSignatureData::signatureText() const
212 {
213 return d->signatureText;
214 }
215
setSignatureText(const QString & text)216 void PDFConverter::NewSignatureData::setSignatureText(const QString &text)
217 {
218 d->signatureText = text;
219 }
220
signatureLeftText() const221 QString PDFConverter::NewSignatureData::signatureLeftText() const
222 {
223 return d->signatureLeftText;
224 }
225
setSignatureLeftText(const QString & text)226 void PDFConverter::NewSignatureData::setSignatureLeftText(const QString &text)
227 {
228 d->signatureLeftText = text;
229 }
230
reason() const231 QString PDFConverter::NewSignatureData::reason() const
232 {
233 return d->reason;
234 }
235
setReason(const QString & reason)236 void PDFConverter::NewSignatureData::setReason(const QString &reason)
237 {
238 d->reason = reason;
239 }
240
location() const241 QString PDFConverter::NewSignatureData::location() const
242 {
243 return d->location;
244 }
245
setLocation(const QString & location)246 void PDFConverter::NewSignatureData::setLocation(const QString &location)
247 {
248 d->location = location;
249 }
250
fontSize() const251 double PDFConverter::NewSignatureData::fontSize() const
252 {
253 return d->fontSize;
254 }
255
setFontSize(double fontSize)256 void PDFConverter::NewSignatureData::setFontSize(double fontSize)
257 {
258 d->fontSize = fontSize;
259 }
260
leftFontSize() const261 double PDFConverter::NewSignatureData::leftFontSize() const
262 {
263 return d->leftFontSize;
264 }
265
setLeftFontSize(double fontSize)266 void PDFConverter::NewSignatureData::setLeftFontSize(double fontSize)
267 {
268 d->leftFontSize = fontSize;
269 }
270
fontColor() const271 QColor PDFConverter::NewSignatureData::fontColor() const
272 {
273 return d->fontColor;
274 }
275
setFontColor(const QColor & color)276 void PDFConverter::NewSignatureData::setFontColor(const QColor &color)
277 {
278 d->fontColor = color;
279 }
280
borderColor() const281 QColor PDFConverter::NewSignatureData::borderColor() const
282 {
283 return d->borderColor;
284 }
285
setBorderColor(const QColor & color)286 void PDFConverter::NewSignatureData::setBorderColor(const QColor &color)
287 {
288 d->borderColor = color;
289 }
290
backgroundColor() const291 QColor PDFConverter::NewSignatureData::backgroundColor() const
292 {
293 return d->backgroundColor;
294 }
295
borderWidth() const296 double PDFConverter::NewSignatureData::borderWidth() const
297 {
298 return d->borderWidth;
299 }
300
setBorderWidth(double width)301 void PDFConverter::NewSignatureData::setBorderWidth(double width)
302 {
303 d->borderWidth = width;
304 }
305
setBackgroundColor(const QColor & color)306 void PDFConverter::NewSignatureData::setBackgroundColor(const QColor &color)
307 {
308 d->backgroundColor = color;
309 }
310
fieldPartialName() const311 QString PDFConverter::NewSignatureData::fieldPartialName() const
312 {
313 return d->partialName;
314 }
315
setFieldPartialName(const QString & name)316 void PDFConverter::NewSignatureData::setFieldPartialName(const QString &name)
317 {
318 d->partialName = name;
319 }
320 }
321