File indexing completed on 2024-05-05 05:44:46

0001 /*
0002  * perldoc.cpp
0003  *
0004  * Borrowed from KDevelop's perldoc ioslave, and improved.
0005  * Copyright 2007 Michael Pyne <michael.pyne@kdemail.net>
0006  * Copyright 2017 Luigi Toscano <luigi.toscano@tiscali.it>
0007  *
0008  * No copyright header was present in KDevelop's perldoc io slave source
0009  * code.  However, source code revision history indicates it was written and
0010  * imported by Bernd Gehrmann <bernd@mail.berlios.de>.  KDevelop is distributed
0011  * under the terms of the GNU General Public License v2.  Therefore, so is
0012  * this software.
0013  *
0014  * All changes made by Michael Pyne are licensed under the terms of the GNU
0015  * GPL version 2 or (at your option) any later version.
0016  *
0017  * Uses the Pod::HtmlEasy Perl module by M. P. Graciliano and
0018  * Geoffrey Leach.  It is distributed under the same terms as Perl.
0019  * See pod2html.pl for more information.
0020  */
0021 
0022 #include "perldoc.h"
0023 
0024 // KIO worker
0025 #include "version.h"
0026 // KF
0027 #include <KAboutData>
0028 #include <KLocalizedString>
0029 // Qt
0030 #include <QByteArray>
0031 #include <QCoreApplication>
0032 #include <QProcess>
0033 #include <QStandardPaths>
0034 #include <QStringList>
0035 #include <QUrl>
0036 
0037 class KIOPluginForMetaData : public QObject
0038 {
0039     Q_OBJECT
0040     Q_PLUGIN_METADATA(IID "org.kde.kio.worker.perldoc" FILE "perldoc.json")
0041 };
0042 
0043 PerldocProtocol::PerldocProtocol(const QByteArray &pool, const QByteArray &app)
0044     : KIO::WorkerBase("perldoc", pool, app)
0045 {
0046     m_pod2htmlPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kio_perldoc/pod2html.pl"));
0047     m_cssLocation = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kio_docfilter/kio_docfilter.css"));
0048 }
0049 
0050 PerldocProtocol::~PerldocProtocol()
0051 {
0052 }
0053 
0054 KIO::WorkerResult PerldocProtocol::get(const QUrl &url)
0055 {
0056     const QStringList l = url.path().split(QLatin1Char('/'), Qt::SkipEmptyParts);
0057 
0058     // Check for perldoc://foo
0059     if(!url.host().isEmpty()) {
0060         QUrl newURL(url);
0061 
0062         newURL.setPath(url.host() + url.path());
0063         newURL.setHost(QString());
0064 
0065         redirection(newURL);
0066         return KIO::WorkerResult::pass();
0067     }
0068 
0069     mimeType(QStringLiteral("text/html"));
0070 
0071     if(l[0].isEmpty() || url.path() == QLatin1String("/")) {
0072         QByteArray output = i18n("<html><head><title>No page requested</title>"
0073             "<body>No page was requested.  You can search for:<ul><li>functions "
0074             "using perldoc:/functions/foo</li>\n\n"
0075             "<li>faq entries using perldoc:/faq/search_terms</li>"
0076             "<li>All other perldoc documents using the name of the document, like"
0077             "<ul><li><a href='perldoc:/perlreftut'>perldoc:/perlreftut</a></li>"
0078             "<li>or <a href='perldoc:/Net::HTTP'>perldoc:/Net::HTTP</a></li></ul>"
0079             "</li></ul>\n\n</body></html>\n"
0080         ).toLocal8Bit();
0081 
0082         data(output);
0083         return KIO::WorkerResult::pass();
0084     }
0085 
0086     if(l[0] != QLatin1String("functions") && l[0] != QLatin1String("faq")) {
0087         // See if it exists first.
0088         if(!topicExists(l[0])) {
0089             // Failed
0090             QByteArray errstr =
0091                 i18n("<html><head><title>No documentation for %1</title><body>"
0092                 "Unable to find documentation for <b>%2</b></body></html>\n",
0093                 l[0], l[0]).toLocal8Bit();
0094 
0095             data(errstr);
0096             return KIO::WorkerResult::pass();
0097         }
0098     }
0099 
0100     QStringList pod2htmlArguments;
0101     if (l[0] == QLatin1String("functions")) {
0102         pod2htmlArguments = QStringList{QStringLiteral("-f"), l[1]};
0103     } else if (l[0] == QLatin1String("faq")) {
0104         pod2htmlArguments = QStringList{QStringLiteral("-q"), l[1]};
0105     } else if (!l[0].isEmpty()) {
0106         pod2htmlArguments = QStringList{l[0]};
0107     }
0108 
0109     QProcess pod2htmlProcess;
0110 
0111     QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
0112     env.insert(QStringLiteral("KIO_PERLDOC_VERSION"), QStringLiteral(KIO_PERLDOC_VERSION_STRING));
0113     env.insert(QStringLiteral("KIO_PERLDOC_CSSLOCATION"), m_cssLocation);
0114     pod2htmlProcess.setProcessEnvironment(env);
0115 
0116     pod2htmlProcess.start(m_pod2htmlPath, pod2htmlArguments);
0117     if (!pod2htmlProcess.waitForFinished()) {
0118         return failAndQuit();
0119     }
0120 
0121     if ((pod2htmlProcess.exitStatus() != QProcess::NormalExit) ||
0122         (pod2htmlProcess.exitCode() < 0)) {
0123         return KIO::WorkerResult::fail(KIO::ERR_CANNOT_LAUNCH_PROCESS, m_pod2htmlPath);
0124     }
0125 
0126     data(pod2htmlProcess.readAllStandardOutput());
0127     return KIO::WorkerResult::pass();
0128 }
0129 
0130 KIO::WorkerResult PerldocProtocol::failAndQuit()
0131 {
0132     data(errorMessage());
0133     return KIO::WorkerResult::pass();
0134 }
0135 
0136 QByteArray PerldocProtocol::errorMessage()
0137 {
0138     return QByteArray("<html><body bgcolor=\"#FFFFFF\">" +
0139            i18n("Error in perldoc").toLocal8Bit() +
0140            "</body></html>");
0141 }
0142 
0143 KIO::WorkerResult PerldocProtocol::stat(const QUrl &/*url*/)
0144 {
0145     KIO::UDSEntry uds_entry;
0146     uds_entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO);
0147 
0148     statEntry(uds_entry);
0149     return KIO::WorkerResult::pass();
0150 }
0151 
0152 KIO::WorkerResult PerldocProtocol::listDir(const QUrl &url)
0153 {
0154     return KIO::WorkerResult::fail( KIO::ERR_CANNOT_ENTER_DIRECTORY, url.path() );
0155 }
0156 
0157 bool PerldocProtocol::topicExists(const QString &topic)
0158 {
0159     // Run perldoc in query mode to see if the given manpage exists.
0160     QProcess perldocProcess;
0161     perldocProcess.start(QStringLiteral("perldoc"), QStringList{QStringLiteral("-l"), topic});
0162     if (!perldocProcess.waitForFinished()) {
0163         return false;
0164     }
0165 
0166     if ((perldocProcess.exitStatus() != QProcess::NormalExit) ||
0167         (perldocProcess.exitCode() < 0)) {
0168         return false;
0169     }
0170 
0171     return true;
0172 }
0173 
0174 extern "C" {
0175 
0176     int Q_DECL_EXPORT kdemain(int argc, char **argv)
0177     {
0178         QCoreApplication app(argc, argv);
0179 
0180         KAboutData aboutData(
0181             QStringLiteral("kio_perldoc"),
0182             i18n("perldoc KIO worker"),
0183             QStringLiteral(KIO_PERLDOC_VERSION_STRING),
0184             i18n("KIO worker to provide access to perldoc documentation"),
0185             KAboutLicense::GPL_V2,
0186             i18n("Copyright 2007, 2008 Michael Pyne"),
0187             i18n("Uses Pod::HtmlEasy by M. P. Graciliano and Geoffrey Leach")
0188         );
0189 
0190         aboutData.addAuthor(i18n("Michael Pyne"), i18n("Maintainer, port to KDE 4"),
0191             QStringLiteral("michael.pyne@kdemail.net"), QStringLiteral("http://purinchu.net/wp/"));
0192         aboutData.addAuthor(i18n("Bernd Gehrmann"), i18n("Initial implementation"));
0193         aboutData.addCredit(i18n("M. P. Graciliano"), i18n("Pod::HtmlEasy"));
0194         aboutData.addCredit(i18n("Geoffrey Leach"), i18n("Pod::HtmlEasy current maintainer"));
0195         aboutData.setTranslator(i18nc("NAME OF TRANSLATORS", "Your names"),
0196             i18nc("EMAIL OF TRANSLATORS", "Your emails"));
0197 
0198         app.setOrganizationDomain(QStringLiteral("kde.org"));
0199         app.setOrganizationName(QStringLiteral("KDE"));
0200 
0201         KAboutData::setApplicationData(aboutData);
0202 
0203         if (argc != 4) {
0204             fprintf(stderr, "Usage: kio_perldoc protocol domain-socket1 domain-socket2\n");
0205             exit(5);
0206         }
0207 
0208         PerldocProtocol worker(argv[2], argv[3]);
0209         worker.dispatchLoop();
0210 
0211         return 0;
0212     }
0213 }
0214 
0215 #include "perldoc.moc"
0216 
0217 // vim: set et sw=4 ts=8: