diff --git a/CMakeLists.txt b/CMakeLists.txt index 6887cc9..8972120 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,17 +1,34 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.0) project(kioslave) -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ) -# search packages used by KDE -find_package(KDE4 REQUIRED) -include(KDE4Defaults) -include(MacroLibrary) -include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES}) +set(QT_MIN_VERSION 5.5.0) +set(KF5_MIN_VERSION 5.27.0) -macro_optional_find_package(Perl 5.10) +find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE) -macro_log_feature(PERL_FOUND "Perl" "Perl Programming Language" "http://www.perl.org/" FALSE "5.10" "Required in order to use the perldoc KIOSlave.") +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) + +include(FeatureSummary) + +include(KDEInstallDirs) +include(KDECMakeSettings) +include(KDECompilerSettings NO_POLICY_SCOPE) + +find_package(Qt5 ${QT_MIN_VERSION} REQUIRED NO_MODULE + COMPONENTS + Core +) + +find_package(KF5 ${KF5_MIN_VERSION} REQUIRED + COMPONENTS + I18n + KIO +) + +find_package(Perl 5.10) if(PERL_FOUND) - macro_optional_add_subdirectory(perldoc) + add_subdirectory(perldoc) endif(PERL_FOUND) + +feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/perldoc/CMakeLists.txt b/perldoc/CMakeLists.txt index f5a4945..67f14ab 100644 --- a/perldoc/CMakeLists.txt +++ b/perldoc/CMakeLists.txt @@ -1,14 +1,19 @@ -PROJECT(kio_perldoc) +project(kio_perldoc) -SET(kio_perldoc_SRCS +add_definitions(-DTRANSLATION_DOMAIN=\"kio5_perldoc\") + +set(kio_perldoc_SRCS perldoc.cpp - ) +) -kde4_add_plugin(kio_perldoc ${kio_perldoc_SRCS}) +add_library(kio_perldoc MODULE ${kio_perldoc_SRCS}) -TARGET_LINK_LIBRARIES(kio_perldoc ${KDE4_KIO_LIBS}) +target_link_libraries(kio_perldoc + KF5::I18n + KF5::KIOCore +) -INSTALL(TARGETS kio_perldoc DESTINATION ${PLUGIN_INSTALL_DIR}) -INSTALL(PROGRAMS pod2html.pl DESTINATION ${DATA_INSTALL_DIR}/kio_perldoc) -INSTALL(FILES perldoc.protocol DESTINATION ${SERVICES_INSTALL_DIR}) +set_target_properties(kio_perldoc PROPERTIES OUTPUT_NAME "perldoc") +install(TARGETS kio_perldoc DESTINATION ${PLUGIN_INSTALL_DIR}/kf5/kio) +install(PROGRAMS pod2html.pl DESTINATION ${DATA_INSTALL_DIR}/kio_perldoc) diff --git a/perldoc/Messages.sh b/perldoc/Messages.sh index d7856ac..5c3c1f6 100755 --- a/perldoc/Messages.sh +++ b/perldoc/Messages.sh @@ -1,2 +1,2 @@ #! /usr/bin/env bash -$XGETTEXT *.cpp -o $podir/kio_perldoc.pot +$XGETTEXT *.cpp -o $podir/kio5_perldoc.pot diff --git a/perldoc/perldoc.cpp b/perldoc/perldoc.cpp index 770f24f..ca2f069 100644 --- a/perldoc/perldoc.cpp +++ b/perldoc/perldoc.cpp @@ -1,333 +1,219 @@ /* * perldoc.cpp * * Borrowed from KDevelop's perldoc ioslave, and improved. * Copyright 2007 Michael Pyne + * Copyright 2017 Luigi Toscano * * No copyright header was present in KDevelop's perldoc io slave source * code. However, source code revision history indicates it was written and * imported by Bernd Gehrmann . KDevelop is distributed * under the terms of the GNU General Public License v2. Therefore, so is * this software. * * All changes made by Michael Pyne are licensed under the terms of the GNU * GPL version 2 or (at your option) any later version. * * Uses the Pod::HtmlEasy Perl module by M. P. Graciliano and * Geoffrey Leach. It is distributed under the same terms as Perl. * See pod2html.pl for more information. */ #include "perldoc.h" -// Constants for ::stat() -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include + +#include +#include + +class KIOPluginForMetaData : public QObject +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.kde.kio.slave.perldoc" FILE "perldoc.json") +}; // Embed version info. Using const char[] instead of const char* const // places it in a read-only section. static const char #ifdef __GNUC__ /* force this into final object files */ __attribute__((__used__)) #endif -kio_perldoc_version[] = "kio_perldoc4 v0.9.1"; - -// Helper class to handle pipes. -class PipeManager -{ - public: - PipeManager(): m_fdRead(-1), m_fdWrite(-1) - { - int pipes[2] = { -1, -1 }; - - if(::pipe(pipes) == -1) - return; - - m_fdRead = pipes[0]; - m_fdWrite = pipes[1]; - } - - ~PipeManager() - { - closeReader(); - closeWriter(); - } - - void closeReader() - { - if(m_fdRead != -1) { - ::close(m_fdRead); - m_fdRead = -1; - } - } - - void closeWriter() - { - if(m_fdWrite != -1) { - ::close(m_fdWrite); - m_fdWrite = -1; - } - } - - int readerFd() const - { - return m_fdRead; - } - - int writerFd() const - { - return m_fdWrite; - } - - private: - int m_fdRead; - int m_fdWrite; -}; +kio_perldoc_version[] = "kio_perldoc v0.10.0"; PerldocProtocol::PerldocProtocol(const QByteArray &pool, const QByteArray &app) : KIO::SlaveBase("perldoc", pool, app) { - m_pod2htmlPath = KStandardDirs::locate("data", "kio_perldoc/pod2html.pl"); + m_pod2htmlPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kio_perldoc/pod2html.pl"); } PerldocProtocol::~PerldocProtocol() { } -void PerldocProtocol::get(const KUrl& url) +void PerldocProtocol::get(const QUrl &url) { QStringList l = url.path().split('/', QString::SkipEmptyParts); // Check for perldoc://foo if(!url.host().isEmpty()) { - KUrl newURL(url); + QUrl newURL(url); newURL.setPath(url.host() + url.path()); newURL.setHost(QString()); redirection(newURL); finished(); return; } mimeType("text/html"); if(l[0].isEmpty() || url.path() == "/") { QByteArray output = i18n("No page requested" "No page was requested. You can search for:
  • functions " "using perldoc:/functions/foo
  • \n\n" "
  • faq entries using perldoc:/faq/search_terms
  • " "
  • All other perldoc documents using the name of the document, like" "" "
\n\n\n" ).toLocal8Bit(); data(output); finished(); return; } if(l[0] != "functions" && l[0] != "faq") { // See if it exists first. if(!topicExists(l[0])) { // Failed QByteArray errstr = i18n("No documentation for %1" "Unable to find documentation for %2\n", l[0], l[0]).toLocal8Bit(); data(errstr); finished(); return; } } - // Uses pipe(2) to implement some basic IPC - PipeManager pipes; - - // Start the helper process and simply dump its output to data(). - pid_t childPid = ::fork(); + QStringList pod2htmlArguments; + if (l[0] == "functions") { + pod2htmlArguments << "-f" << l[1]; + } else if (l[0] == "faq") { + pod2htmlArguments << "-q" << l[1]; + } else if (!l[0].isEmpty()) { + pod2htmlArguments << l[0]; + } - if(childPid < 0) { + QProcess pod2htmlProcess; + pod2htmlProcess.start(m_pod2htmlPath, pod2htmlArguments); + if (!pod2htmlProcess.waitForFinished()) { failAndQuit(); return; } - if(childPid == 0) { - // Child, run the helper. We have no need for the input pipe - pipes.closeReader(); - - // Make the output pipe also be STDOUT. - ::close(STDOUT_FILENO); - if(::dup2(pipes.writerFd(), STDOUT_FILENO) < 0) - ::exit(1); - - // Close pipes.writerFd(), which is now stdout. stdout still refers - // to the pipe's write end, and we only want one reference to it. - pipes.closeWriter(); - - // When using toLocal8Bit.data(), there must be a QByteArray object that survives long - // enough for the call to complete. - QByteArray executablePath = m_pod2htmlPath.toLocal8Bit(); - - // For execl(3), the first two arguments are for the path to the - // program, and the program name respectively. Normally they should be - // the same. - if (l[0] == "functions") { - QByteArray podName = l[1].toLocal8Bit(); - ::execl(executablePath.data(), executablePath.data(), "-f", podName.data(), (char*) NULL); - } - else if (l[0] == "faq") { - QByteArray podName = l[1].toLocal8Bit(); - ::execl(executablePath.data(), executablePath.data(), "-q", podName.data(), (char*) NULL); - } - else if (!l[0].isEmpty()) { - QByteArray podName = l[0].toLocal8Bit(); - ::execl(executablePath.data(), executablePath.data(), podName.data(), (char*) NULL); - } - - ::exit(1); // Shouldn't make it here. + if ((pod2htmlProcess.exitStatus() != QProcess::NormalExit) || + (pod2htmlProcess.exitCode() < 0)) { + error(KIO::ERR_CANNOT_LAUNCH_PROCESS, m_pod2htmlPath); } - else { - // Parent. We will read from the pipe, have no need for write end. - pipes.closeWriter(); - - char buffer[1024]; - ssize_t bufSize = -1; - - // We use QByteArray::fromRawData instead of just reading into a QByteArray - // buffer in case bufSize is less than buffer.size(). In that case we would - // have to resize, and then resize back to the required buffer size after the - // call to data, which I don't feel like doing. - bufSize = ::read(pipes.readerFd(), buffer, sizeof buffer); - while(bufSize > 0) { - data(QByteArray::fromRawData(buffer, bufSize)); - - if(wasKilled()) // someone killed us! - return; - - bufSize = ::read(pipes.readerFd(), buffer, bufSize); - } - - if(bufSize < 0) - failAndQuit(); // Don't return on purpose, cleanup happens either way - - int status = 0; - ::waitpid(childPid, &status, 0); - - if(WIFEXITED(status) && WEXITSTATUS(status) != 0) - error(KIO::ERR_CANNOT_LAUNCH_PROCESS, m_pod2htmlPath); - finished(); - } + data(pod2htmlProcess.readAllStandardOutput()); + finished(); } void PerldocProtocol::failAndQuit() { data(errorMessage()); finished(); } QByteArray PerldocProtocol::errorMessage() { return QByteArray("" + i18n("Error in perldoc").toLocal8Bit() + ""); } -void PerldocProtocol::stat(const KUrl &/*url*/) +void PerldocProtocol::stat(const QUrl &/*url*/) { KIO::UDSEntry uds_entry; uds_entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO); statEntry(uds_entry); finished(); } -void PerldocProtocol::listDir(const KUrl &url) +void PerldocProtocol::listDir(const QUrl &url) { error( KIO::ERR_CANNOT_ENTER_DIRECTORY, url.path() ); } bool PerldocProtocol::topicExists(const QString &topic) { // Run perldoc in query mode to see if the given manpage exists. - pid_t childPid = fork(); - - if(childPid < 0) { - data(QByteArray(i18n("Failed to fork").toLocal8Bit())); - return false; // Failed to fork - } - - if(childPid == 0) { - // Child - QByteArray topicData = topic.toLocal8Bit(); - if(execlp("perldoc", "perldoc", "-l", topicData.data(), (char *) NULL) < 0) - ::exit(errno); + QProcess perldocProcess; + perldocProcess.start(QStringLiteral("perldoc"), QStringList() << "-l" << topic); + if (!perldocProcess.waitForFinished()) { + return false; } - else { - int status = 0; - ::waitpid(childPid, &status, 0); - if(WIFEXITED(status) && WEXITSTATUS(status) == 0) - return true; + if ((perldocProcess.exitStatus() != QProcess::NormalExit) || + (perldocProcess.exitCode() < 0)) { + return false; } - return false; + return true; } extern "C" { - int KDE_EXPORT kdemain(int argc, char **argv) + int Q_DECL_EXPORT kdemain(int argc, char **argv) { + QCoreApplication app(argc, argv); + KAboutData aboutData( - "kio_perldoc", - "kio_perldoc", - ki18n("perldoc KIOSlave"), - "0.9.1", - ki18n("KIOSlave to provide access to perldoc documentation"), - KAboutData::License_GPL_V2, - ki18n("Copyright 2007, 2008 Michael Pyne"), - ki18n("Uses Pod::HtmlEasy by M. P. Graciliano and Geoffrey Leach") + QStringLiteral("kio_perldoc"), + i18n("perldoc KIOSlave"), + QStringLiteral("0.9.1"), + i18n("KIOSlave to provide access to perldoc documentation"), + KAboutLicense::GPL_V2, + i18n("Copyright 2007, 2008 Michael Pyne"), + i18n("Uses Pod::HtmlEasy by M. P. Graciliano and Geoffrey Leach") ); - aboutData.addAuthor(ki18n("Michael Pyne"), ki18n("Maintainer, port to KDE 4"), + aboutData.addAuthor(i18n("Michael Pyne"), i18n("Maintainer, port to KDE 4"), "michael.pyne@kdemail.net", "http://purinchu.net/wp/"); - aboutData.addAuthor(ki18n("Bernd Gehrmann"), ki18n("Initial implementation")); - aboutData.addCredit(ki18n("M. P. Graciliano"), ki18n("Pod::HtmlEasy")); - aboutData.addCredit(ki18n("Geoffrey Leach"), ki18n("Pod::HtmlEasy current maintainer")); - aboutData.setTranslator(ki18nc("NAME OF TRANSLATORS", "Your names"), - ki18nc("EMAIL OF TRANSLATORS", "Your emails")); + aboutData.addAuthor(i18n("Bernd Gehrmann"), i18n("Initial implementation")); + aboutData.addCredit(i18n("M. P. Graciliano"), i18n("Pod::HtmlEasy")); + aboutData.addCredit(i18n("Geoffrey Leach"), i18n("Pod::HtmlEasy current maintainer")); + aboutData.setTranslator(i18nc("NAME OF TRANSLATORS", "Your names"), + i18nc("EMAIL OF TRANSLATORS", "Your emails")); + + app.setOrganizationDomain(QStringLiteral("kde.org")); + app.setOrganizationName(QStringLiteral("KDE")); - KComponentData componentData(aboutData); + KAboutData::setApplicationData(aboutData); if (argc != 4) { fprintf(stderr, "Usage: kio_perldoc protocol domain-socket1 domain-socket2\n"); exit(5); } PerldocProtocol slave(argv[2], argv[3]); slave.dispatchLoop(); return 0; } } +#include "perldoc.moc" + // vim: set et sw=4 ts=8: diff --git a/perldoc/perldoc.h b/perldoc/perldoc.h index b59e28e..a00e999 100644 --- a/perldoc/perldoc.h +++ b/perldoc/perldoc.h @@ -1,47 +1,47 @@ #ifndef KIO_PERLDOC_H_ #define KIO_PERLDOC_H_ /* * perldoc.h * * Borrowed from KDevelop's perldoc ioslave, and improved. * Copyright 2007 Michael Pyne * * No copyright header was present in KDevelop's perldoc io slave source * code. However, source code revision history indicates it was written and * imported by Bernd Gehrmann . KDevelop is distributed * under the terms of the GNU General Public License v2. Therefore, so is * this software. * * All changes made by Michael Pyne are licensed under the terms of the GNU * GPL version 2 or (at your option) any later version. * * Uses the Pod::HtmlEasy Perl module by M. P. Graciliano and * Geoffrey Leach. It is distributed under the same terms as Perl. * See pod2html.pl for more information. */ #include class PerldocProtocol : public KIO::SlaveBase { public: PerldocProtocol(const QByteArray &pool, const QByteArray &app); virtual ~PerldocProtocol(); - virtual void get(const KUrl& url); - virtual void stat(const KUrl& url); - virtual void listDir(const KUrl& url); + virtual void get(const QUrl &url); + virtual void stat(const QUrl &url); + virtual void listDir(const QUrl &url); bool topicExists(const QString &topic); protected: QByteArray errorMessage(); void failAndQuit(); QString m_pod2htmlPath; }; #endif // vim: set et sw=4 ts=8: diff --git a/perldoc/perldoc.json b/perldoc/perldoc.json new file mode 100644 index 0000000..06ea61c --- /dev/null +++ b/perldoc/perldoc.json @@ -0,0 +1,18 @@ +{ + "KDE-KIO-Protocols": { + "perldoc": { + "Class": ":internet", + "Icon": "application-x-perl", + "defaultMimetype": "text/html", + "determineMimetypeFromExtension": false, + "exec": "kf5/kio/perldoc", + "input": "none", + "listing": [ + "Name" + ], + "output": "filesystem", + "protocol": "perldoc", + "reading": true + } + } +} diff --git a/perldoc/perldoc.protocol b/perldoc/perldoc.protocol deleted file mode 100644 index 561434c..0000000 --- a/perldoc/perldoc.protocol +++ /dev/null @@ -1,11 +0,0 @@ -[Protocol] -exec=kio_perldoc -protocol=perldoc -input=none -output=filesystem -defaultMimetype=text/html -Class=:local -reading=true -listing=Name -determineMimetypeFromExtension=false -Icon=application-x-perl