From feef900250958e59a7a09eee60d732ef47a84b79 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Sun, 23 Jan 2022 19:36:31 +0100 Subject: [PATCH] Make sure helper apps we start are in path QProcess will happily start things in CWD which is not what we want --- core/document.cpp | 11 +++++- generators/dvi/dviFile.cpp | 51 ++++++++++++++++---------- generators/dvi/dviFile.h | 2 + generators/dvi/dviRenderer_prescan.cpp | 15 +++++--- generators/dvi/fontEncoding.cpp | 10 ++++- generators/dvi/fontMap.cpp | 8 +++- generators/dvi/fontpool.cpp | 9 ++++- generators/dvi/psgs.cpp | 18 ++++++++- 8 files changed, 92 insertions(+), 32 deletions(-) diff --git a/core/document.cpp b/core/document.cpp index 2048db9e6..ebcde758e 100644 --- a/core/document.cpp +++ b/core/document.cpp @@ -4202,11 +4202,18 @@ void Document::processSourceReference(const SourceReference *ref) const QString cmd = KMacroExpander::expandMacrosShellQuote(p, map); if (cmd.isEmpty()) return; - const QStringList args = KShell::splitArgs(cmd); + QStringList args = KShell::splitArgs(cmd); if (args.isEmpty()) return; - KProcess::startDetached(args); + const QString prog = args.takeFirst(); + // Make sure prog is in PATH and not just in the CWD + const QString progFullPath = QStandardPaths::findExecutable(prog); + if (progFullPath.isEmpty()) { + return; + } + + KProcess::startDetached(progFullPath, args); } const SourceReference *Document::dynamicSourceReference(int pageNr, double absX, double absY) diff --git a/generators/dvi/dviFile.cpp b/generators/dvi/dviFile.cpp index 7e3e6c8f8..1cd396247 100644 --- a/generators/dvi/dviFile.cpp +++ b/generators/dvi/dviFile.cpp @@ -43,6 +43,7 @@ #include #include +#include #include #include @@ -332,6 +333,28 @@ void dvifile::renumber() } } +void dvifile::pdf2psNotFound(const QString &PDFFilename, QString *converrorms) +{ + // Indicates that conversion failed, won't try again. + convertedFiles[PDFFilename].clear(); + if (converrorms != nullptr && !have_complainedAboutMissingPDF2PS) { + *converrorms = i18n( + "

The external program pdf2ps could not be started. As a result, " + "the PDF-file %1 could not be converted to PostScript. Some graphic elements in your " + "document will therefore not be displayed.

" + "

Possible reason: The program pdf2ps may not be installed " + "on your system, or cannot be found in the current search path.

" + "

What you can do: The program pdf2ps is normally " + "contained in distributions of the ghostscript PostScript interpreter system. If " + "ghostscript is not installed on your system, you could install it now. " + "If you are sure that ghostscript is installed, try to use pdf2ps " + "from the command line to check if it really works.

PATH: %2

", + PDFFilename, + QString::fromLocal8Bit(qgetenv("PATH"))); + have_complainedAboutMissingPDF2PS = true; + } +} + QString dvifile::convertPDFtoPS(const QString &PDFFilename, QString *converrorms) { // Check if the PDFFile is known @@ -341,6 +364,13 @@ QString dvifile::convertPDFtoPS(const QString &PDFFilename, QString *converrorms return it.value(); } + // Make sure pdf2ps is in PATH and not just in the CWD + static const QString fullPath = QStandardPaths::findExecutable(QStringLiteral("pdf2ps")); + if (!fullPath.isEmpty()) { + pdf2psNotFound(PDFFilename, converrorms); + return QString(); + } + // Get the name of a temporary file. // Must open the QTemporaryFile to access the name. QTemporaryFile tmpfile; @@ -351,27 +381,10 @@ QString dvifile::convertPDFtoPS(const QString &PDFFilename, QString *converrorms // Use pdf2ps to do the conversion QProcess pdf2ps; pdf2ps.setProcessChannelMode(QProcess::MergedChannels); - pdf2ps.start(QStringLiteral("pdf2ps"), QStringList() << PDFFilename << convertedFileName, QIODevice::ReadOnly | QIODevice::Text); + pdf2ps.start(fullPath, QStringList() << PDFFilename << convertedFileName, QIODevice::ReadOnly | QIODevice::Text); if (!pdf2ps.waitForStarted()) { - // Indicates that conversion failed, won't try again. - convertedFiles[PDFFilename].clear(); - if (converrorms != nullptr && !have_complainedAboutMissingPDF2PS) { - *converrorms = i18n( - "

The external program pdf2ps could not be started. As a result, " - "the PDF-file %1 could not be converted to PostScript. Some graphic elements in your " - "document will therefore not be displayed.

" - "

Possible reason: The program pdf2ps may not be installed " - "on your system, or cannot be found in the current search path.

" - "

What you can do: The program pdf2ps is normally " - "contained in distributions of the ghostscript PostScript interpreter system. If " - "ghostscript is not installed on your system, you could install it now. " - "If you are sure that ghostscript is installed, try to use pdf2ps " - "from the command line to check if it really works.

PATH: %2

", - PDFFilename, - QString::fromLocal8Bit(qgetenv("PATH"))); - have_complainedAboutMissingPDF2PS = true; - } + pdf2psNotFound(PDFFilename, converrorms); return QString(); } diff --git a/generators/dvi/dviFile.h b/generators/dvi/dviFile.h index 5721e2ba7..f3f096a6a 100644 --- a/generators/dvi/dviFile.h +++ b/generators/dvi/dviFile.h @@ -131,6 +131,8 @@ public: QString convertPDFtoPS(const QString &PDFFilename, QString *converrorms = nullptr); private: + void pdf2psNotFound(const QString &PDFFilename, QString *converrorms); + /** process_preamble reads the information in the preamble and stores it into global variables for later use. */ void process_preamble(); diff --git a/generators/dvi/dviRenderer_prescan.cpp b/generators/dvi/dviRenderer_prescan.cpp index 1ace3f501..fce823b09 100644 --- a/generators/dvi/dviRenderer_prescan.cpp +++ b/generators/dvi/dviRenderer_prescan.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include extern QPainter foreGroundPaint; @@ -278,11 +279,15 @@ void dviRenderer::prescan_ParsePSHeaderSpecial(const QString &cp) // to find it. if (!QFile::exists(_file)) { // Otherwise, use kpsewhich to find the eps file. - KProcess proc; - proc << QStringLiteral("kpsewhich") << cp; - proc.setOutputChannelMode(KProcess::SeparateChannels); - proc.execute(); - _file = QString::fromLocal8Bit(proc.readLine().trimmed()); + // Make sure kpsewhich is in PATH and not just in the CWD + static const QString fullPath = QStandardPaths::findExecutable(QStringLiteral("kpsewhich")); + if (!fullPath.isEmpty()) { + KProcess proc; + proc << fullPath << cp; + proc.setOutputChannelMode(KProcess::SeparateChannels); + proc.execute(); + _file = QString::fromLocal8Bit(proc.readLine().trimmed()); + } } if (QFile::exists(_file)) diff --git a/generators/dvi/fontEncoding.cpp b/generators/dvi/fontEncoding.cpp index df95aafdb..9dbfa46f7 100644 --- a/generators/dvi/fontEncoding.cpp +++ b/generators/dvi/fontEncoding.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include //#define DEBUG_FONTENC @@ -31,7 +32,14 @@ fontEncoding::fontEncoding(const QString &encName) QProcess kpsewhich; kpsewhich.setProcessChannelMode(QProcess::MergedChannels); - kpsewhich.start(QStringLiteral("kpsewhich"), QStringList() << encName, QIODevice::ReadOnly | QIODevice::Text); + // Make sure kpsewhich is in PATH and not just in the CWD + static const QString fullPath = QStandardPaths::findExecutable(QStringLiteral("kpsewhich")); + if (fullPath.isEmpty()) { + qCCritical(OkularDviDebug) << "fontEncoding::fontEncoding(...): kpsewhich is not in path." << endl; + return; + } + + kpsewhich.start(fullPath, QStringList() << encName, QIODevice::ReadOnly | QIODevice::Text); if (!kpsewhich.waitForStarted()) { qCCritical(OkularDviDebug) << "fontEncoding::fontEncoding(...): kpsewhich could not be started." << endl; diff --git a/generators/dvi/fontMap.cpp b/generators/dvi/fontMap.cpp index ef1acace9..e4a500d38 100644 --- a/generators/dvi/fontMap.cpp +++ b/generators/dvi/fontMap.cpp @@ -15,12 +15,16 @@ #include #include #include +#include #include //#define DEBUG_FONTMAP fontMap::fontMap() { + // Make sure kpsewhich is in PATH and not just in the CWD + static const QString kpsewhichFullPath = QStandardPaths::findExecutable(QStringLiteral("kpsewhich")); + // Read the map file of ps2pk which will provide us with a // dictionary "TeX Font names" <-> "Name of font files, Font Names // and Encodings" (example: the font "Times-Roman" is called @@ -35,7 +39,7 @@ fontMap::fontMap() // other way than to try both options one after another. We use the // teTeX 3.0 format first. QProcess kpsewhich; - kpsewhich.start(QStringLiteral("kpsewhich"), QStringList() << QStringLiteral("--format=map") << QStringLiteral("ps2pk.map"), QIODevice::ReadOnly | QIODevice::Text); + kpsewhich.start(kpsewhichFullPath, QStringList() << QStringLiteral("--format=map") << QStringLiteral("ps2pk.map"), QIODevice::ReadOnly | QIODevice::Text); if (!kpsewhich.waitForStarted()) { qCCritical(OkularDviDebug) << "fontMap::fontMap(): kpsewhich could not be started." << endl; @@ -49,7 +53,7 @@ fontMap::fontMap() if (map_fileName.isEmpty()) { // Map file not found? Then we try the teTeX < 3.0 way of finding // the file. - kpsewhich.start(QStringLiteral("kpsewhich"), QStringList() << QStringLiteral("--format=dvips config") << QStringLiteral("ps2pk.map"), QIODevice::ReadOnly | QIODevice::Text); + kpsewhich.start(kpsewhichFullPath, QStringList() << QStringLiteral("--format=dvips config") << QStringLiteral("ps2pk.map"), QIODevice::ReadOnly | QIODevice::Text); if (!kpsewhich.waitForStarted()) { qCCritical(OkularDviDebug) << "fontMap::fontMap(): kpsewhich could not be started." << endl; return; diff --git a/generators/dvi/fontpool.cpp b/generators/dvi/fontpool.cpp index da29de7e1..35232f136 100644 --- a/generators/dvi/fontpool.cpp +++ b/generators/dvi/fontpool.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -213,6 +214,12 @@ void fontPool::locateFonts() void fontPool::locateFonts(bool makePK, bool locateTFMonly, bool *virtualFontsFound) { + // Make sure kpsewhich is in PATH and not just in the CWD + static const QString kpsewhichFullPath = QStandardPaths::findExecutable(QStringLiteral("kpsewhich")); + if (kpsewhichFullPath.isEmpty()) { + return; + } + // Set up the kpsewhich process. If pass == 0, look for vf-fonts and // disable automatic font generation as vf-fonts can't be // generated. If pass == 0, enable font generation, if it was @@ -264,7 +271,7 @@ void fontPool::locateFonts(bool makePK, bool locateTFMonly, bool *virtualFontsFo const QString kpsewhich_exe = QStringLiteral("kpsewhich"); kpsewhichOutput += QStringLiteral("") + kpsewhich_exe + QLatin1Char(' ') + kpsewhich_args.join(QStringLiteral(" ")) + QStringLiteral(""); - kpsewhich_->start(kpsewhich_exe, kpsewhich_args, QIODevice::ReadOnly | QIODevice::Text); + kpsewhich_->start(kpsewhichFullPath, kpsewhich_args, QIODevice::ReadOnly | QIODevice::Text); if (!kpsewhich_->waitForStarted()) { QApplication::restoreOverrideCursor(); emit error(i18n("

There were problems running kpsewhich. As a result, " diff --git a/generators/dvi/psgs.cpp b/generators/dvi/psgs.cpp index 2fa9e0d93..d496b2e8d 100644 --- a/generators/dvi/psgs.cpp +++ b/generators/dvi/psgs.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -157,6 +158,13 @@ void ghostscript_interface::gs_generate_graphics_file(const quint16 page, const return; } + // Make sure gs is in PATH and not just in the CWD + static const QString gsFullPath = QStandardPaths::findExecutable(QStringLiteral("gs")); + if (gsFullPath.isEmpty()) { + qCCritical(OkularDviDebug) << "gs is not in path" << endl; + return; + } + pageInfo *info = pageList.value(page); // Generate a PNG-file @@ -216,7 +224,7 @@ void ghostscript_interface::gs_generate_graphics_file(const quint16 page, const KProcess proc; proc.setOutputChannelMode(KProcess::SeparateChannels); QStringList argus; - argus << QStringLiteral("gs"); + argus << gsFullPath; argus << QStringLiteral("-dSAFER") << QStringLiteral("-dPARANOIDSAFER") << QStringLiteral("-dDELAYSAFER") << QStringLiteral("-dNOPAUSE") << QStringLiteral("-dBATCH"); argus << QStringLiteral("-sDEVICE=%1").arg(*gsDevice); argus << QStringLiteral("-sOutputFile=%1").arg(filename); @@ -328,8 +336,14 @@ QString ghostscript_interface::locateEPSfile(const QString &filename, const QUrl } // Otherwise, use kpsewhich to find the eps file. + // Make sure kpsewhich is in PATH and not just in the CWD + static const QString fullPath = QStandardPaths::findExecutable(QStringLiteral("kpsewhich")); + if (fullPath.isEmpty()) { + return {}; + } + KProcess proc; - proc << QStringLiteral("kpsewhich") << filename; + proc << fullPath << filename; proc.execute(); return QString::fromLocal8Bit(proc.readLine().trimmed()); }