File indexing completed on 2024-04-21 14:56:20

0001 
0002 #include "../config-kdoctools.h"
0003 #include "docbookxslt.h"
0004 #include "docbookxslt_p.h"
0005 #include "loggingcategory.h"
0006 #include "meinproc_common.h"
0007 
0008 #include <QCoreApplication>
0009 #include <QDir>
0010 #include <QFile>
0011 #include <QFileInfo>
0012 #include <QList>
0013 #include <QStandardPaths>
0014 #include <QString>
0015 
0016 #include <QUrl>
0017 
0018 #include <libexslt/exslt.h>
0019 #include <libxml/HTMLtree.h>
0020 #include <libxml/debugXML.h>
0021 #include <libxml/parserInternals.h>
0022 #include <libxml/xmlIO.h>
0023 #include <libxml/xmlmemory.h>
0024 #include <libxml/xmlversion.h>
0025 #include <libxslt/transform.h>
0026 #include <libxslt/xsltInternals.h>
0027 #include <libxslt/xsltconfig.h>
0028 #include <libxslt/xsltutils.h>
0029 
0030 #include <QCommandLineOption>
0031 #include <QCommandLineParser>
0032 #include <qplatformdefs.h>
0033 #include <string.h>
0034 
0035 using namespace KDocTools;
0036 
0037 #ifndef _WIN32
0038 extern "C" int xmlLoadExtDtdDefaultValue;
0039 #endif
0040 
0041 #define DIE(x)                                                                                                                                                 \
0042     do {                                                                                                                                                       \
0043         qCCritical(KDocToolsLog) << "Error:" << x;                                                                                                             \
0044         exit(1);                                                                                                                                               \
0045     } while (0)
0046 
0047 int main(int argc, char **argv)
0048 {
0049     // xsltSetGenericDebugFunc(stderr, NULL);
0050 
0051     QCoreApplication app(argc, argv);
0052     app.setApplicationName(QStringLiteral("meinproc"));
0053     app.setApplicationVersion(QStringLiteral("5.0"));
0054 
0055     QCommandLineParser parser;
0056     parser.setApplicationDescription(QCoreApplication::translate("main", "KDE Translator for XML"));
0057     parser.addHelpOption();
0058     parser.addVersionOption();
0059     parser.addOption(
0060         QCommandLineOption(QStringList() << QStringLiteral("stylesheet"), QCoreApplication::translate("main", "Stylesheet to use"), QStringLiteral("xsl")));
0061     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("stdout"), QCoreApplication::translate("main", "Output whole document to stdout")));
0062     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("o") << QStringLiteral("output"),
0063                                         QCoreApplication::translate("main", "Output whole document to file"),
0064                                         QStringLiteral("file")));
0065     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("check"), QCoreApplication::translate("main", "Check the document for validity")));
0066     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("cache"),
0067                                         QCoreApplication::translate("main", "Create a cache file for the document"),
0068                                         QStringLiteral("file")));
0069     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("srcdir"),
0070                                         QCoreApplication::translate("main", "Set the srcdir, for kdoctools"),
0071                                         QStringLiteral("dir")));
0072     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("param"),
0073                                         QCoreApplication::translate("main", "Parameters to pass to the stylesheet"),
0074                                         QStringLiteral("key=value")));
0075     parser.addPositionalArgument(QStringLiteral("xml"), QCoreApplication::translate("main", "The file to transform"));
0076     parser.process(app);
0077 
0078     const QStringList filesToRead = parser.positionalArguments();
0079     if (filesToRead.count() != 1) {
0080         parser.showHelp();
0081         return (1);
0082     }
0083 
0084     exsltRegisterAll();
0085 
0086     // Need to set SRCDIR before calling setupStandardDirs
0087     QString srcdir;
0088     if (parser.isSet(QStringLiteral("srcdir"))) {
0089         srcdir = QDir(parser.value(QStringLiteral("srcdir"))).absolutePath();
0090     }
0091     setupStandardDirs(srcdir);
0092 
0093     LIBXML_TEST_VERSION
0094 
0095     const QString checkFilename(filesToRead.first());
0096     CheckFileResult ckr = checkFile(checkFilename);
0097     switch (ckr) {
0098     case CheckFileSuccess:
0099         break;
0100     case CheckFileDoesNotExist:
0101         DIE("File" << checkFilename << "does not exist.");
0102     case CheckFileIsNotFile:
0103         DIE(checkFilename << "is not a file.");
0104     case CheckFileIsNotReadable:
0105         DIE("File" << checkFilename << "is not readable.");
0106     }
0107 
0108     if (parser.isSet(QStringLiteral("check"))) {
0109         QStringList lst = getKDocToolsCatalogs();
0110         if (lst.isEmpty()) {
0111             DIE("Could not find kdoctools catalogs");
0112         }
0113         QByteArray catalogs = lst.join(" ").toLocal8Bit();
0114         QString exe;
0115 #if defined(XMLLINT)
0116         exe = QStringLiteral(XMLLINT);
0117 #endif
0118         if (!QFileInfo(exe).isExecutable()) {
0119             exe = QStandardPaths::findExecutable(QStringLiteral("xmllint"));
0120         }
0121 
0122         CheckResult cr = check(checkFilename, exe, catalogs);
0123         switch (cr) {
0124         case CheckSuccess:
0125             break;
0126         case CheckNoXmllint:
0127             DIE("Could not find xmllint");
0128         case CheckNoOut:
0129             DIE("`xmllint --noout` outputted text");
0130         }
0131     }
0132 
0133     QVector<const char *> params;
0134     {
0135         const QStringList paramList = parser.values(QStringLiteral("param"));
0136         for (const QString &tuple : paramList) {
0137             const int ch = tuple.indexOf(QLatin1Char('='));
0138             if (ch == -1) {
0139                 DIE("Key-Value tuple" << tuple << "lacks a '='!");
0140             }
0141             params.append(qstrdup(tuple.left(ch).toUtf8().constData()));
0142             params.append(qstrdup(tuple.mid(ch + 1).toUtf8().constData()));
0143         }
0144     }
0145     params.append(nullptr);
0146 
0147     QString tss = parser.value(QStringLiteral("stylesheet"));
0148     if (tss.isEmpty()) {
0149         tss = QStringLiteral("customization/kde-chunk.xsl");
0150     }
0151 
0152     QString tssPath = locateFileInDtdResource(tss);
0153     if (tssPath.isEmpty()) {
0154         DIE("Unable to find the stylesheet named" << tss << "in dtd resources");
0155     }
0156 #ifndef MEINPROC_NO_KARCHIVE
0157     const QString cache = parser.value(QStringLiteral("cache"));
0158 #else
0159     if (parser.isSet("cache")) {
0160         qCWarning(KDocToolsLog) << QCoreApplication::translate(
0161             "main",
0162             "The cache option is not available, please re-compile with KArchive support. See MEINPROC_NO_KARCHIVE in KDocTools");
0163     }
0164 #endif
0165     const bool usingStdOut = parser.isSet(QStringLiteral("stdout"));
0166     const bool usingOutput = parser.isSet(QStringLiteral("output"));
0167     const QString outputOption = parser.value(QStringLiteral("output"));
0168 
0169     QString output = transform(checkFilename, tssPath, params);
0170     if (output.isEmpty()) {
0171         DIE("Unable to parse" << checkFilename);
0172     }
0173 
0174 #ifndef MEINPROC_NO_KARCHIVE
0175     if (!cache.isEmpty()) {
0176         if (!saveToCache(output, cache)) {
0177             qCWarning(KDocToolsLog) << QCoreApplication::translate("main", "Could not write to cache file %1.").arg(cache);
0178         }
0179         goto end;
0180     }
0181 #endif
0182 
0183     doOutput(output, usingStdOut, usingOutput, outputOption, true /* replaceCharset */);
0184 #ifndef MEINPROC_NO_KARCHIVE
0185 end:
0186 #endif
0187     xmlCleanupParser();
0188     xmlMemoryDump();
0189     return (0);
0190 }