1/*
2 SPDX-FileCopyrightText: 2018 Stefan BrĂ¼ns <stefan.bruens@rwth-aachen.de>
3
4 SPDX-License-Identifier: LGPL-2.1-or-later
5*/
6
7
8#include "postscriptdscextractor.h"
9#include "kfilemetadata_debug.h"
10
11#include <QFile>
12#include <QTimeZone>
13
14namespace KFileMetaData
15{
16
17DscExtractor::DscExtractor(QObject* parent)
18 : ExtractorPlugin(parent)
19{
20
21}
22
23QStringList DscExtractor::mimetypes() const
24{
25 QStringList list;
26 list << QStringLiteral("application/postscript")
27 << QStringLiteral("image/x-eps");
28
29 return list;
30}
31
32void DscExtractor::extract(ExtractionResult* result)
33{
34 QFile file(result->inputUrl());
35 if (!file.open(flags: QIODevice::ReadOnly)) {
36 qCWarning(KFILEMETADATA_LOG) << "Document is not a valid file";
37 return;
38 }
39
40 // A little bit heuristic - assume EPS files are images, PS complete documents
41 if (result->inputMimetype() == QLatin1String("application/postscript")) {
42 result->addType(type: Type::Document);
43 } else {
44 result->addType(type: Type::Image);
45 }
46
47 if (!(result->inputFlags() & ExtractionResult::ExtractMetaData)) {
48 return;
49 }
50 // Try to find some DSC (PostScript Language Document Structuring Conventions) conforming data
51 QTextStream stream(&file);
52 QString line;
53
54 while (stream.readLineInto(line: &line)) {
55 if (!line.startsWith(s: QLatin1String("%%"))) {
56 continue;
57 }
58
59 if (const auto tag = QLatin1String("%%Pages:"); line.startsWith(s: tag)) {
60 bool ok = false;
61 int pages = QStringView(line).mid(pos: tag.size()).toInt(ok: &ok, base: 10);
62 if (ok) {
63 result->add(property: Property::PageCount, value: pages);
64 }
65
66 } else if (const auto tag = QLatin1String("%%Title:"); line.startsWith(s: tag)) {
67 QStringView title = QStringView(line).mid(pos: tag.size()).trimmed();
68 if (title.startsWith(c: QLatin1Char('(')) && title.endsWith(c: QLatin1Char(')'))) {
69 title = title.mid(pos: 1, n: title.size() - 2);
70 }
71 if (!title.isEmpty()) {
72 result->add(property: Property::Title, value: title.toString());
73 }
74
75 } else if (const auto tag = QLatin1String("%%CreationDate:"); line.startsWith(s: tag)) {
76 // "Neither the date nor time need be in any standard format."
77 QStringView date = QStringView(line).mid(pos: tag.size()).trimmed();
78 if (date.startsWith(c: QLatin1Char('(')) && date.endsWith(c: QLatin1Char(')'))) {
79 date = date.mid(pos: 1, n: date.size() - 2);
80 date = date.trimmed();
81 }
82 if (date.startsWith(s: QLatin1String("D:")) && date.size() >= 23) {
83 // Standard PDF date format, ASN.1 like - (D:YYYYMMDDHHmmSSOHH'mm')
84 auto dt = QDateTime::fromString(string: date.mid(pos: 2, n: 14).toString(), format: QLatin1String("yyyyMMddhhmmss"));
85 auto offset = QTime::fromString(string: date.mid(pos: 17, n: 5).toString(), format: QLatin1String("hh'\\''mm"));
86 if (date.at(n: 16) == QLatin1Char('+')) {
87 dt.setTimeZone(toZone: QTimeZone::fromSecondsAheadOfUtc(offset: QTime(0, 0).secsTo(t: offset)));
88 } else {
89 dt.setTimeZone(toZone: QTimeZone::fromSecondsAheadOfUtc(offset: -1 * QTime(0, 0).secsTo(t: offset)));
90 }
91 result->add(property: Property::CreationDate, value: dt);
92 } else {
93 auto dt = QDateTime::fromString(string: date.toString());
94 if (dt.isValid()) {
95 result->add(property: Property::CreationDate, value: dt);
96 }
97 }
98
99 } else if (line.startsWith(s: QLatin1String("%%EndComments"))) {
100 break;
101 }
102 }
103}
104
105} // namespace KFileMetaData
106
107#include "moc_postscriptdscextractor.cpp"
108

source code of kfilemetadata/src/extractors/postscriptdscextractor.cpp