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