1 #include <QtCore/QCoreApplication>
2 #include <QtCore/QDateTime>
3 #include <QtCore/QDebug>
4 
5 #include <iostream>
6 
7 #include <poppler-qt5.h>
8 #include <poppler-form.h>
9 
operator <<(std::ostream & out,Poppler::FormField::FormType type)10 static std::ostream &operator<<(std::ostream &out, Poppler::FormField::FormType type)
11 {
12     switch (type) {
13     case Poppler::FormField::FormButton:
14         out << "Button";
15         break;
16     case Poppler::FormField::FormText:
17         out << "Text";
18         break;
19     case Poppler::FormField::FormChoice:
20         out << "Choice";
21         break;
22     case Poppler::FormField::FormSignature:
23         out << "Signature";
24         break;
25     }
26     return out;
27 }
28 
operator <<(std::ostream & out,Poppler::FormFieldButton::ButtonType type)29 static std::ostream &operator<<(std::ostream &out, Poppler::FormFieldButton::ButtonType type)
30 {
31     switch (type) {
32     case Poppler::FormFieldButton::Push:
33         out << "Push";
34         break;
35     case Poppler::FormFieldButton::CheckBox:
36         out << "CheckBox";
37         break;
38     case Poppler::FormFieldButton::Radio:
39         out << "Radio";
40         break;
41     }
42     return out;
43 }
44 
operator <<(std::ostream & out,Poppler::FormFieldText::TextType type)45 static std::ostream &operator<<(std::ostream &out, Poppler::FormFieldText::TextType type)
46 {
47     switch (type) {
48     case Poppler::FormFieldText::Normal:
49         out << "Normal";
50         break;
51     case Poppler::FormFieldText::Multiline:
52         out << "Multiline";
53         break;
54     case Poppler::FormFieldText::FileSelect:
55         out << "FileSelect";
56         break;
57     }
58     return out;
59 }
60 
operator <<(std::ostream & out,Poppler::FormFieldChoice::ChoiceType type)61 static std::ostream &operator<<(std::ostream &out, Poppler::FormFieldChoice::ChoiceType type)
62 {
63     switch (type) {
64     case Poppler::FormFieldChoice::ComboBox:
65         out << "ComboBox";
66         break;
67     case Poppler::FormFieldChoice::ListBox:
68         out << "ListBox";
69         break;
70     }
71     return out;
72 }
73 
operator <<(std::ostream & out,Poppler::SignatureValidationInfo::SignatureStatus status)74 static std::ostream &operator<<(std::ostream &out, Poppler::SignatureValidationInfo::SignatureStatus status)
75 {
76     switch (status) {
77     case Poppler::SignatureValidationInfo::SignatureValid:
78         out << "Valid";
79         break;
80     case Poppler::SignatureValidationInfo::SignatureInvalid:
81         out << "Invalid";
82         break;
83     case Poppler::SignatureValidationInfo::SignatureDigestMismatch:
84         out << "DigestMismatch";
85         break;
86     case Poppler::SignatureValidationInfo::SignatureDecodingError:
87         out << "DecodingError";
88         break;
89     case Poppler::SignatureValidationInfo::SignatureGenericError:
90         out << "GenericError";
91         break;
92     case Poppler::SignatureValidationInfo::SignatureNotFound:
93         out << "NotFound";
94         break;
95     case Poppler::SignatureValidationInfo::SignatureNotVerified:
96         out << "NotVerifiedYet";
97         break;
98     }
99     return out;
100 }
101 
operator <<(std::ostream & out,Poppler::SignatureValidationInfo::CertificateStatus status)102 static std::ostream &operator<<(std::ostream &out, Poppler::SignatureValidationInfo::CertificateStatus status)
103 {
104     switch (status) {
105     case Poppler::SignatureValidationInfo::CertificateTrusted:
106         out << "Trusted";
107         break;
108     case Poppler::SignatureValidationInfo::CertificateUntrustedIssuer:
109         out << "UntrustedIssuer";
110         break;
111     case Poppler::SignatureValidationInfo::CertificateUnknownIssuer:
112         out << "UnknownIssuer";
113         break;
114     case Poppler::SignatureValidationInfo::CertificateRevoked:
115         out << "Revoked";
116         break;
117     case Poppler::SignatureValidationInfo::CertificateExpired:
118         out << "Expired";
119         break;
120     case Poppler::SignatureValidationInfo::CertificateGenericError:
121         out << "GenericError";
122         break;
123     case Poppler::SignatureValidationInfo::CertificateNotVerified:
124         out << "NotVerifiedYet";
125         break;
126     }
127     return out;
128 }
129 
operator <<(std::ostream & out,Qt::Alignment alignment)130 static std::ostream &operator<<(std::ostream &out, Qt::Alignment alignment)
131 {
132     switch (alignment) {
133     case Qt::AlignLeft:
134         out << "Left";
135         break;
136     case Qt::AlignRight:
137         out << "Right";
138         break;
139     case Qt::AlignHCenter:
140         out << "HCenter";
141         break;
142     case Qt::AlignJustify:
143         out << "Justify";
144         break;
145     case Qt::AlignTop:
146         out << "Top";
147         break;
148     case Qt::AlignBottom:
149         out << "Bottom";
150         break;
151     case Qt::AlignVCenter:
152         out << "VCenter";
153         break;
154     case Qt::AlignCenter:
155         out << "Center";
156         break;
157     case Qt::AlignAbsolute:
158         out << "Absolute";
159         break;
160     }
161     return out;
162 }
163 
operator <<(std::ostream & out,const QString & string)164 static std::ostream &operator<<(std::ostream &out, const QString &string)
165 {
166     out << string.toUtf8().constData();
167     return out;
168 }
169 
operator <<(std::ostream & out,const QRectF & rect)170 static std::ostream &operator<<(std::ostream &out, const QRectF &rect)
171 {
172     out << QStringLiteral("top: %1 left: %2 width: %3 height: %4").arg(rect.x()).arg(rect.y()).arg(rect.width()).arg(rect.height());
173     return out;
174 }
175 
176 template<typename T>
operator <<(std::ostream & out,const QList<T> & elems)177 std::ostream &operator<<(std::ostream &out, const QList<T> &elems)
178 {
179     bool isFirst = true;
180     for (int i = 0; i < elems.count(); ++i) {
181         if (!isFirst)
182             out << " ";
183         out << elems[i];
184         isFirst = false;
185     }
186     return out;
187 }
188 
main(int argc,char ** argv)189 int main(int argc, char **argv)
190 {
191     QCoreApplication a(argc, argv);
192 
193     if (!(argc == 2)) {
194         qWarning() << "usage: poppler-forms filename";
195         exit(1);
196     }
197 
198     Poppler::Document *doc = Poppler::Document::load(argv[1]);
199     if (!doc) {
200         qWarning() << "doc not loaded";
201         exit(1);
202     }
203 
204     std::cout << "Forms for file " << argv[1] << std::endl;
205     for (int i = 0; i < doc->numPages(); ++i) {
206         Poppler::Page *page = doc->page(i);
207         if (page) {
208             QList<Poppler::FormField *> forms = page->formFields();
209             std::cout << "\tPage " << i + 1 << std::endl;
210             foreach (const Poppler::FormField *form, forms) {
211                 std::cout << "\t\tForm" << std::endl;
212                 std::cout << "\t\t\tType: " << form->type() << std::endl;
213                 std::cout << "\t\t\tRect: " << form->rect() << std::endl;
214                 std::cout << "\t\t\tID: " << form->id() << std::endl;
215                 std::cout << "\t\t\tName: " << form->name() << std::endl;
216                 std::cout << "\t\t\tFullyQualifiedName: " << form->fullyQualifiedName() << std::endl;
217                 std::cout << "\t\t\tUIName: " << form->uiName() << std::endl;
218                 std::cout << "\t\t\tReadOnly: " << form->isReadOnly() << std::endl;
219                 std::cout << "\t\t\tVisible: " << form->isVisible() << std::endl;
220                 switch (form->type()) {
221                 case Poppler::FormField::FormButton: {
222                     const Poppler::FormFieldButton *buttonForm = static_cast<const Poppler::FormFieldButton *>(form);
223                     std::cout << "\t\t\tButtonType: " << buttonForm->buttonType() << std::endl;
224                     std::cout << "\t\t\tCaption: " << buttonForm->caption() << std::endl;
225                     std::cout << "\t\t\tState: " << buttonForm->state() << std::endl;
226                     std::cout << "\t\t\tSiblings: " << buttonForm->siblings() << std::endl;
227                 } break;
228 
229                 case Poppler::FormField::FormText: {
230                     const Poppler::FormFieldText *textForm = static_cast<const Poppler::FormFieldText *>(form);
231                     std::cout << "\t\t\tTextType: " << textForm->textType() << std::endl;
232                     std::cout << "\t\t\tText: " << textForm->text() << std::endl;
233                     std::cout << "\t\t\tIsPassword: " << textForm->isPassword() << std::endl;
234                     std::cout << "\t\t\tIsRichText: " << textForm->isRichText() << std::endl;
235                     std::cout << "\t\t\tMaximumLength: " << textForm->maximumLength() << std::endl;
236                     std::cout << "\t\t\tTextAlignment: " << textForm->textAlignment() << std::endl;
237                     std::cout << "\t\t\tCanBeSpellChecked: " << textForm->canBeSpellChecked() << std::endl;
238                 } break;
239 
240                 case Poppler::FormField::FormChoice: {
241                     const Poppler::FormFieldChoice *choiceForm = static_cast<const Poppler::FormFieldChoice *>(form);
242                     std::cout << "\t\t\tChoiceType: " << choiceForm->choiceType() << std::endl;
243                     std::cout << "\t\t\tChoices: " << choiceForm->choices() << std::endl;
244                     std::cout << "\t\t\tIsEditable: " << choiceForm->isEditable() << std::endl;
245                     std::cout << "\t\t\tIsMultiSelect: " << choiceForm->multiSelect() << std::endl;
246                     std::cout << "\t\t\tCurrentChoices: " << choiceForm->currentChoices() << std::endl;
247                     std::cout << "\t\t\tEditChoice: " << choiceForm->editChoice() << std::endl;
248                     std::cout << "\t\t\tTextAlignment: " << choiceForm->textAlignment() << std::endl;
249                     std::cout << "\t\t\tCanBeSpellChecked: " << choiceForm->canBeSpellChecked() << std::endl;
250                 } break;
251 
252                 case Poppler::FormField::FormSignature: {
253                     const Poppler::FormFieldSignature *signatureForm = static_cast<const Poppler::FormFieldSignature *>(form);
254                     const Poppler::SignatureValidationInfo svi = signatureForm->validate(Poppler::FormFieldSignature::ValidateVerifyCertificate);
255                     std::cout << "\t\t\tSignatureStatus: " << svi.signatureStatus() << std::endl;
256                     std::cout << "\t\t\tCertificateStatus: " << svi.certificateStatus() << std::endl;
257                     if (svi.signerName().isEmpty() == false)
258                         std::cout << "\t\t\tSignerName: " << svi.signerName() << std::endl;
259                     else
260                         std::cout << "\t\t\tSignerName: "
261                                   << "(null)" << std::endl;
262                     const QDateTime sviTime = QDateTime::fromSecsSinceEpoch(svi.signingTime(), Qt::UTC);
263                     std::cout << "\t\t\tSigningTime: " << sviTime.toString() << std::endl;
264                 } break;
265                 }
266             }
267             qDeleteAll(forms);
268             delete page;
269         }
270     }
271     delete doc;
272 }
273