File indexing completed on 2024-05-19 03:56:45

0001 /*
0002     SPDX-FileCopyrightText: 2018 Stefan BrĂ¼ns <stefan.bruens@rwth-aachen.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-or-later
0005 */
0006 
0007 
0008 #include "postscriptdscextractor.h"
0009 #include "kfilemetadata_debug.h"
0010 
0011 #include <QFile>
0012 #include <QTimeZone>
0013 
0014 namespace KFileMetaData
0015 {
0016 
0017 DscExtractor::DscExtractor(QObject* parent)
0018     : ExtractorPlugin(parent)
0019 {
0020 
0021 }
0022 
0023 QStringList DscExtractor::mimetypes() const
0024 {
0025     QStringList list;
0026     list << QStringLiteral("application/postscript")
0027          << QStringLiteral("image/x-eps");
0028 
0029     return list;
0030 }
0031 
0032 void DscExtractor::extract(ExtractionResult* result)
0033 {
0034     QFile file(result->inputUrl());
0035     if (!file.open(QIODevice::ReadOnly)) {
0036         qCWarning(KFILEMETADATA_LOG) << "Document is not a valid file";
0037         return;
0038     }
0039 
0040     // A little bit heuristic - assume EPS files are images, PS complete documents
0041     if (result->inputMimetype() == QLatin1String("application/postscript")) {
0042         result->addType(Type::Document);
0043     } else {
0044         result->addType(Type::Image);
0045     }
0046 
0047     if (!(result->inputFlags() & ExtractionResult::ExtractMetaData)) {
0048         return;
0049     }
0050     // Try to find some DSC (PostScript Language Document Structuring Conventions) conforming data
0051     QTextStream stream(&file);
0052     QString line;
0053 
0054     while (stream.readLineInto(&line)) {
0055         if (!line.startsWith(QLatin1String("%%"))) {
0056             continue;
0057         }
0058 
0059         if (const auto tag = QLatin1String("%%Pages:"); line.startsWith(tag)) {
0060             bool ok = false;
0061             int pages = QStringView(line).mid(tag.size()).toInt(&ok, 10);
0062             if (ok) {
0063                 result->add(Property::PageCount, pages);
0064             }
0065 
0066         } else if (const auto tag = QLatin1String("%%Title:"); line.startsWith(tag)) {
0067             QStringView title = QStringView(line).mid(tag.size()).trimmed();
0068             if (title.startsWith(QLatin1Char('(')) && title.endsWith(QLatin1Char(')'))) {
0069                 title = title.mid(1, title.size() - 2);
0070             }
0071             if (!title.isEmpty()) {
0072                 result->add(Property::Title, title.toString());
0073             }
0074 
0075         } else if (const auto tag = QLatin1String("%%CreationDate:"); line.startsWith(tag)) {
0076             // "Neither the date nor time need be in any standard format."
0077             QStringView date = QStringView(line).mid(tag.size()).trimmed();
0078             if (date.startsWith(QLatin1Char('(')) && date.endsWith(QLatin1Char(')'))) {
0079                 date = date.mid(1, date.size() - 2);
0080                 date = date.trimmed();
0081             }
0082             if (date.startsWith(QLatin1String("D:")) && date.size() >= 23) {
0083                 // Standard PDF date format, ASN.1 like - (D:YYYYMMDDHHmmSSOHH'mm')
0084                 auto dt = QDateTime::fromString(date.mid(2, 14).toString(), QLatin1String("yyyyMMddhhmmss"));
0085                 auto offset = QTime::fromString(date.mid(17, 5).toString(), QLatin1String("hh'\\''mm"));
0086                 if (date.at(16) == QLatin1Char('+')) {
0087                     dt.setTimeZone(QTimeZone::fromSecondsAheadOfUtc(QTime(0, 0).secsTo(offset)));
0088                 } else {
0089                     dt.setTimeZone(QTimeZone::fromSecondsAheadOfUtc(-1 * QTime(0, 0).secsTo(offset)));
0090                 }
0091                 result->add(Property::CreationDate, dt);
0092             } else {
0093                 auto dt = QDateTime::fromString(date.toString());
0094                 if (dt.isValid()) {
0095                     result->add(Property::CreationDate, dt);
0096                 }
0097             }
0098 
0099         } else if (line.startsWith(QLatin1String("%%EndComments"))) {
0100             break;
0101         }
0102     }
0103 }
0104 
0105 } // namespace KFileMetaData
0106 
0107 #include "moc_postscriptdscextractor.cpp"