diff --git a/firefox-kde/CMakeLists.txt b/firefox-kde/CMakeLists.txt new file mode 100644 index 0000000..a6d103b --- /dev/null +++ b/firefox-kde/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 2.8.12) + +project(kmozillahelper-frameworks) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +find_package(ECM 1.0.0 REQUIRED NO_MODULE) + +set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) + +include(KDEInstallDirs) +include(KDECMakeSettings) +include(FeatureSummary) + +find_package(KF5 REQUIRED COMPONENTS Notifications KIO I18n WindowSystem) +#find_package(KF5 REQUIRED COMPONENTS Notifications KIO) + +add_executable(kmozillahelper main.cpp) + +target_link_libraries(kmozillahelper KF5::I18n KF5::KIOWidgets KF5::Notifications KF5::WindowSystem) + +install(TARGETS kmozillahelper DESTINATION /usr/lib/mozilla/) +install(FILES kmozillahelper.notifyrc DESTINATION ${DATA_INSTALL_DIR}/kmozillahelper) diff --git a/firefox-kde/PKGBUILD b/firefox-kde/PKGBUILD index 31d5573..f360eed 100644 --- a/firefox-kde/PKGBUILD +++ b/firefox-kde/PKGBUILD @@ -1,26 +1,25 @@ pkgname=firefox-kde pkgver=42.0 -pkgrel=1 +pkgrel=2 pkgdesc="Standalone web browser from mozilla.org with OpenSUSE patch, integrate better with KDE" #_kmozillahelper_obsver=b88c72dfdc858f6209feb123227bd7df -_kmozillahelper_pkgname=kmozillahelper -_kmozillahelper_pkgver=0.6.4 +#_kmozillahelper_pkgname=kmozillahelper +#_kmozillahelper_pkgver=0.6.4 arch=('x86_64') license=('MPL' 'GPL' 'LGPL') url="https://www.mozilla.org/firefox/" depends=('gtk2' 'mozilla-common' 'libxt' 'startup-notification' 'mime-types' 'dbus-glib' 'alsa-lib' 'desktop-file-utils' 'hicolor-icon-theme' - 'libvpx' 'icu' 'libevent' 'nss>=3.18.1' 'hunspell' 'sqlite3>=3.8.9' - 'kdelibs') + 'libvpx' 'icu' 'libevent' 'nss>=3.19.4' 'hunspell' 'sqlite3>=3.8.9' + 'kio' 'knotifications' 'nspr>=4.10.10' 'libffi>=3.0.9') makedepends=('unzip' 'zip' 'diffutils' 'python2' 'yasm' 'mesa' 'imake' 'xorg-server-xvfb' 'libpulse' 'gst-plugins-base' 'inetutils' 'libpng>=1.6.16' - 'cmake' 'automoc4') + 'cmake' 'extra-cmake-modules') optdepends=('networkmanager: Location detection via available WiFi networks' 'gst-plugins-good: h.264 video' 'gst-libav: h.264 video' - 'firefox-i18n: for multilanguage support' - 'kdelibs: for KDE integration') + 'firefox-i18n: for multilanguage support') screenshot="http://img864.imageshack.us/img864/5116/firefoxm.png" provides=("firefox=${pkgver}" "kmozillahelper=${_kmozillahelper_pkgver}") conflicts=('firefox' 'kmozillahelper') @@ -47,7 +46,11 @@ source=("https://download-installer.cdn.mozilla.net/pub/firefox/releases/${pkgve 'vendor.js' 'kde.js' 'firefox-20.0.1-fixed-loading-icon.png' - "https://build.opensuse.org/source/openSUSE:Factory/mozilla-kde4-integration/${_kmozillahelper_pkgname}-${_kmozillahelper_pkgver}.tar.bz2" +# "https://build.opensuse.org/source/openSUSE:Factory/mozilla-kde4-integration/${_kmozillahelper_pkgname}-${_kmozillahelper_pkgver}.tar.bz2" + 'CMakeLists.txt' + 'kmozillahelper.notifyrc' + 'main.cpp' + 'main.h' 'firefox-install-dir.patch' 'rhbz-966424.patch' 'pgo-fix-missing-kdejs.patch' @@ -65,6 +68,13 @@ source=("https://download-installer.cdn.mozilla.net/pub/firefox/releases/${pkgve #'install-kde-js.patch' 'ddg-branding.patch' + + # GTK3 patchset +# 'firefox-build.patch' +# 'mozilla-1192243.patch' +# 'xulrunner-24.0-jemalloc-ppc.patch' +# 'xulrunner-24.0-s390-inlines.patch' + # Useless patchset #"$_patchurl/gecko-lockdown.patch" #"$_patchurl/mozilla-idldir.patch" @@ -82,7 +92,10 @@ sha1sums=('c207a73fbfde2683aca36417331441d007ceb765' 'ca77a08b296f8673828898d91b20cc6dd8742c2f' 'ce48f8e5065319e191a7389539ec663dc8a919d7' '0c3900ffe21bfc3d96b80ade334613bc7e76fe27' - '5543ea72a07fb6f3af19cfbb6d1683a5fddaa807' + '72c4cdc6dfadcd89715d642b76a37889e50ee0bd' + '9a3731a0a4caa15ffe3e06bc20ef97bd44c04ef4' + '43f630cf3f3df24174201ba8f0ec3f067ad32bcc' + 'e92c4d9b988ca52f5fdf72ae8d11e0112f9f1b54' 'a87a6eb5cb86f63e39249c60eb53594ce225dea0' 'ad1f05abf477dbc5f7e72c06e37c180459eeffd4' '6991d61be593b5ad109174ebc7d60763eb48125b' @@ -127,9 +140,15 @@ prepare() { msg "Firefox patchset" patch -Np1 -i "$srcdir/firefox-kde.patch" - msg '1' ; patch -Np1 -i "$srcdir/firefox-branded-icons.patch" - msg '1' ; patch -Np1 -i "$srcdir/ddg-branding.patch" - msg '1' ; patch -Np1 -i "$srcdir"/pgo-fix-missing-kdejs.patch + patch -Np1 -i "$srcdir/firefox-branded-icons.patch" + patch -Np1 -i "$srcdir/ddg-branding.patch" + patch -Np1 -i "$srcdir"/pgo-fix-missing-kdejs.patch + +# msg "GTK3 patchset" +# patch -p2 -i ../firefox-build.patch +# patch -p2 -i ../xulrunner-24.0-jemalloc-ppc.patch +# patch -p2 -i ../xulrunner-24.0-s390-inlines.patch +# patch -p1 -i ../mozilla-1192243.patch mkdir -vp "$srcdir/path" @@ -163,7 +182,7 @@ build_kmozillahelper() { mkdir -p kmozillahelper-build cd kmozillahelper-build - cmake -DCMAKE_INSTALL_PREFIX=`kde4-config --prefix` -DCMAKE_BUILD_TYPE=Release ../kmozillahelper + cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release .. make } diff --git a/firefox-kde/kmozillahelper.notifyrc b/firefox-kde/kmozillahelper.notifyrc new file mode 100644 index 0000000..e49b1f7 --- /dev/null +++ b/firefox-kde/kmozillahelper.notifyrc @@ -0,0 +1,102 @@ +[Global] +IconName=firefox +Comment=Firefox + +# this is borrowed from KGet +[Event/downloadfinished] +Name=Download Finished +Name[ar]=التنزيل انتهى +Name[ca]=Ha acabat la descàrrega +Name[cs]=Stahování ukončeno +Name[da]=Download afsluttet +Name[de]=Download abgeschlossen +Name[el]=Η μεταφορά ολοκληρώθηκε +Name[eo]=Elŝuto finis +Name[es]=Descarga finalizada +Name[et]=Allalaadimine lõpetatud +Name[eu]=Deskarga amaituta +Name[fi]=Haku valmistui +Name[fr]=Téléchargement terminé +Name[ga]=Críochnaíodh an tÍosluchtú +Name[gl]=Rematou unha transferencia +Name[hi]=डाउनलोड सम्पन्न +Name[hne]=डाउनलोड पूरा +Name[hu]=Egy letöltés befejeződött +Name[is]=Niðurhali lokið +Name[it]=Scaricamento completato +Name[ja]=ダウンロード完了 +Name[km]=បាន​បញ្ចប់​ការ​ទាញយក +Name[ko]=다운로드 완료됨 +Name[lt]=Atsiuntimas baigtas +Name[lv]=Lejupielāde pabeigta +Name[ml]=ഇറക്കിവെപ്പ്‍ അവസാനിച്ചു +Name[nb]=Nedlasting ferdig +Name[nds]=Daalladen afslaten +Name[nl]=Download voltooid +Name[nn]=Nedlastinga er ferdig +Name[pa]=ਡਾਊਨਲੋਡ ਮੁਕੰਮਲ ਹੋਇਆ +Name[pl]=Pobieranie zakończone +Name[pt]=Transferência Terminada +Name[pt_BR]=Download concluído +Name[ro]=Descărcare încheiată +Name[ru]=Загрузка завершена +Name[sl]=Konec prenosa +Name[sr]=Преузимање завршено +Name[sr@latin]=Preuzimanje završeno +Name[sv]=Nerladdning klar +Name[tr]=İndirme İşlemi Bitti +Name[uk]=Звантаження завершено +Name[x-test]=xxDownload Finishedxx +Name[zh_CN]=下载完成 +Name[zh_TW]=下載已完成 +Comment=Downloading finished +Comment[ar]=التنزيل انتهى +Comment[bn]=ডাউনলোড শেষ করল +Comment[br]=Echu eo an enkargañ +Comment[ca]=Ha acabat la descàrrega +Comment[cs]=Stahování bylo dokončeno +Comment[da]=Download afsluttet +Comment[de]=Herunterladen abgeschlossen +Comment[el]=Η λήψη του αρχείου ολοκληρώθηκε +Comment[eo]=Elŝuto finita +Comment[es]=Descarga finalizada +Comment[et]=Allalaadimine lõpetatud +Comment[eu]=Deskarga amaitu da +Comment[fi]=Tiedoston haku valmistui +Comment[fr]=Téléchargement terminé +Comment[ga]=Críochnaíodh an t-íosluchtú +Comment[gl]=Rematou unha transferencia +Comment[he]=ההורדה הסתיימה +Comment[hi]=डाउनलोडिंग सम्पन्न +Comment[hne]=डाउनलोडिंग पूरा +Comment[hu]=Egy letöltés befejeződött +Comment[is]=Niðurhali lokið +Comment[it]=Scaricamento completato +Comment[ja]=ダウンロードが完了しました +Comment[km]=បាន​បញ្ចប់​ការ​ទាញយក +Comment[ko]=다운로드 완료됨 +Comment[lt]=Atsiuntimas baigtas +Comment[lv]=Lejupielāde ir pabeigta +Comment[ml]=ഇറക്കിവെക്കല്‍ അവസാനിച്ചു +Comment[nb]=Nedlasting ferdig +Comment[nds]=Daalladen beendt +Comment[nl]=Het downloaden is voltooid +Comment[nn]=Nedlastinga er ferdig +Comment[pa]=ਡਾਊਨਲੋਡ ਮੁਕੰਮਲ ਹੋਇਆ +Comment[pl]=Pobieranie pliku zostało zakończone +Comment[pt]=A transferência terminou +Comment[pt_BR]=Download concluído +Comment[ro]=Descărcarea s-a încheiat +Comment[ru]=Загрузка завершена +Comment[sk]=Sťahovanie ukončené +Comment[sl]=Prenašanje se je zaključilo +Comment[sr]=Преузимање је завршено +Comment[sr@latin]=Preuzimanje je završeno +Comment[sv]=Nerladdning klar +Comment[tr]=Dosya indirme tamamlandı +Comment[uk]=Звантаження завершено +Comment[x-test]=xxDownloading finishedxx +Comment[zh_CN]=下载已完成 +Comment[zh_HK]=下載已完成 +Comment[zh_TW]=下載已完成 +Action=Popup diff --git a/firefox-kde/main.cpp b/firefox-kde/main.cpp new file mode 100644 index 0000000..dfb921f --- /dev/null +++ b/firefox-kde/main.cpp @@ -0,0 +1,692 @@ +/***************************************************************** + +Copyright (C) 2009 Lubos Lunak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#include "main.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define DEBUG_KDE + +#define HELPER_VERSION 6 +#define APP_HELPER_VERSION "0.6.4" + +int main( int argc, char* argv[] ) + { + QApplication app(argc, argv); + + KAboutData about( "kmozillahelper", i18n( "KMozillaHelper" ), APP_HELPER_VERSION ); + KAboutData::setApplicationData(about); + QApplication::setWindowIcon(QIcon::fromTheme(QLatin1String("firefox"))); // TODO: what about other mozilla apps? + + QCommandLineParser parser; + about.setupCommandLine(&parser); + + app.setQuitOnLastWindowClosed(false); + + Helper helper; + + return app.exec(); + } + +Helper::Helper() + : input( stdin ) + , output( stdout ) + , notifier( STDIN_FILENO, QSocketNotifier::Read ) + , arguments_read( false ) + { + connect( ¬ifier, SIGNAL( activated( int )), SLOT( readCommand())); + //setQuitOnLastWindowClosed( false ); + } + +void Helper::readCommand() + { + QString command = readLine(); + if( input.atEnd()) + { +#ifdef DEBUG_KDE + QTextStream( stderr ) << "EOF, existing." << endl; +#endif + QCoreApplication::exit(); + return; + } +#ifdef DEBUG_KDE + QTextStream( stderr ) << "COMMAND:" << command << endl; +#endif + bool status; + if( command == "CHECK" ) + status = handleCheck(); + else if( command == "GETPROXY" ) + status = handleGetProxy(); + else if( command == "HANDLEREXISTS" ) + status = handleHandlerExists(); + else if( command == "GETFROMEXTENSION" ) + status = handleGetFromExtension(); + else if( command == "GETFROMTYPE" ) + status = handleGetFromType(); + else if( command == "GETAPPDESCFORSCHEME" ) + status = handleGetAppDescForScheme(); + else if( command == "APPSDIALOG" ) + status = handleAppsDialog(); + else if( command == "GETOPENFILENAME" ) + status = handleGetOpenX( false ); + else if( command == "GETOPENURL" ) + status = handleGetOpenX( true ); + else if( command == "GETSAVEFILENAME" ) + status = handleGetSaveX( false ); + else if( command == "GETSAVEURL" ) + status = handleGetSaveX( true ); + else if( command == "GETDIRECTORYFILENAME" ) + status = handleGetDirectoryX( false ); + else if( command == "GETDIRECTORYURL" ) + status = handleGetDirectoryX( true ); + else if( command == "OPEN" ) + status = handleOpen(); + else if( command == "REVEAL" ) + status = handleReveal(); + else if( command == "RUN" ) + status = handleRun(); + else if( command == "GETDEFAULTFEEDREADER" ) + status = handleGetDefaultFeedReader(); + else if( command == "OPENMAIL" ) + status = handleOpenMail(); + else if( command == "OPENNEWS" ) + status = handleOpenNews(); + else if( command == "ISDEFAULTBROWSER" ) + status = handleIsDefaultBrowser(); + else if( command == "SETDEFAULTBROWSER" ) + status = handleSetDefaultBrowser(); + else if( command == "DOWNLOADFINISHED" ) + status = handleDownloadFinished(); + else + { + QTextStream( stderr ) << "Unknown command for KDE helper: " << command << endl; + status = false; + } + // status done as \1 (==ok) and \0 (==not ok), because otherwise this cannot happen + // in normal data (\ is escaped otherwise) + outputLine( status ? "\\1" : "\\0", false ); // do not escape + } + +bool Helper::handleCheck() + { + if( !readArguments( 1 )) + return false; + int version = getArgument().toInt(); // requested version + if( !allArgumentsUsed()) + return false; + if( version <= HELPER_VERSION ) // we must have the exact requested version + return true; + QTextStream( stderr ) << "KDE helper version too old." << endl; + return false; + } + +bool Helper::handleGetProxy() + { + if( !readArguments( 1 )) + return false; + QUrl url = QUrl::fromUserInput( getArgument()); + if( !allArgumentsUsed()) + return false; + QString proxy; + KProtocolManager::slaveProtocol( url, proxy ); + if( proxy.isEmpty() || proxy == "DIRECT" ) // TODO return DIRECT if empty? + { + outputLine( "DIRECT" ); + return true; + } + QUrl proxyurl = QUrl::fromUserInput( proxy ); + if( proxyurl.isValid()) + { // firefox wants this format + outputLine( "PROXY" " " + proxyurl.host() + ":" + QString::number( proxyurl.port())); + // TODO there is also "SOCKS " type + return true; + } + return false; + } + +bool Helper::handleHandlerExists() + { + if( !readArguments( 1 )) + return false; + QString protocol = getArgument(); + if( !allArgumentsUsed()) + return false; + return KProtocolInfo::isKnownProtocol( protocol ); + } + +bool Helper::handleGetFromExtension() + { + if( !readArguments( 1 )) + return false; + QString ext = getArgument(); + if( !allArgumentsUsed()) + return false; + if( !ext.isEmpty()) { + QList mimeList = QMimeDatabase().mimeTypesForFileName("foo." + ext); + for (const QMimeType &mime : mimeList) + if (mime.isValid() && writeMimeInfo(mime)) + return true; + return false; + } + return false; + } + +bool Helper::handleGetFromType() + { + if( !readArguments( 1 )) + return false; + QString type = getArgument(); + if( !allArgumentsUsed()) + return false; + QMimeType mime = QMimeDatabase().mimeTypeForName(type); + if (mime.isValid()) return writeMimeInfo(mime); + // firefox also asks for protocol handlers using getfromtype + QString app = getAppForProtocol( type ); + if( !app.isEmpty()) + { + outputLine( type ); + outputLine( type ); // TODO probably no way to find a good description + outputLine( app ); + return true; + } + return false; + } + +bool Helper::writeMimeInfo( QMimeType mime ) + { + KService::Ptr service = KMimeTypeTrader::self()->preferredService( mime.name()); + if( service ) + { + outputLine( mime.name()); + outputLine( mime.comment()); + outputLine( service->name()); + return true; + } + return false; + } + +bool Helper::handleGetAppDescForScheme() + { + if( !readArguments( 1 )) + return false; + QString scheme = getArgument(); + if( !allArgumentsUsed()) + return false; + QString app = getAppForProtocol( scheme ); + if( !app.isEmpty()) + { + outputLine( app ); + return true; + } + return false; + } + +bool Helper::handleAppsDialog() + { + if( !readArguments( 1 )) + return false; + QString title = getArgument(); + long wid = getArgumentParent(); + if( !allArgumentsUsed()) + return false; + KOpenWithDialog dialog( NULL ); + if( !title.isEmpty()) + dialog.setWindowTitle( title ); + dialog.hideNoCloseOnExit(); + dialog.hideRunInTerminal(); // TODO + if( wid != 0 ) + KWindowSystem::setMainWindow( &dialog, wid ); + if( dialog.exec()) + { + KService::Ptr service = dialog.service(); + QString command; + if( service ) + command = service->exec(); + else if( !dialog.text().isEmpty()) + command = dialog.text(); + else + return false; + command = command.split( " " ).first(); // only the actual command + command = QStandardPaths::findExecutable(command); + if( command.isEmpty()) + return false; + outputLine( QUrl::fromUserInput( command ).url()); + return true; + } + return false; + } + +bool Helper::handleGetOpenX( bool url ) + { + if( !readArguments( 4 )) + return false; + QString startDir = getArgument(); + QString filter = getArgument().replace("/", "\\/"); // TODO: not used + int selectFilter = getArgument().toInt(); + QString title = getArgument(); + bool multiple = isArgument( "MULTIPLE" ); + long wid = getArgumentParent(); + if( !allArgumentsUsed()) + return false; + + if (title.isEmpty()) + title = i18n("Open"); + + if (url) { + QList result; + if (multiple) + result = QFileDialog::getOpenFileUrls(nullptr, title, startDir); + else + result << QFileDialog::getOpenFileUrl(nullptr, title, startDir); + result.removeAll(QUrl()); + if (!result.isEmpty()) { + outputLine(QStringLiteral("0")); // filter is not implemented, so always 0 (All Files) + for (const QUrl &url : result) + outputLine(url.url()); + return true; + } + + } else { + QStringList result; + if (multiple) + result = QFileDialog::getOpenFileNames(nullptr, title, startDir); + else + result << QFileDialog::getOpenFileName(nullptr, title, startDir); + result.removeAll(QString()); + if (!result.isEmpty()) { + outputLine(QStringLiteral("0")); + for (const QString &str : result) + outputLine(str); + return true; + } + } + + return false; + } + +bool Helper::handleGetSaveX( bool url ) + { + if( !readArguments( 4 )) + return false; + QString startDir = getArgument(); + QString filter = getArgument().replace("/", "\\/"); // TODO: ignored + int selectFilter = getArgument().toInt(); + QString title = getArgument(); + long wid = getArgumentParent(); + if( !allArgumentsUsed()) + return false; + + if (title.isEmpty()) + title = i18n("Save As"); + + // TODO: confirm overwrite + if (url) { + QUrl result = QFileDialog::getSaveFileUrl(nullptr, title, startDir); + if (result.isValid()) { + outputLine(QStringLiteral("0")); + outputLine(result.url()); + return true; + } + } else { + QString result = QFileDialog::getSaveFileName(nullptr, title, startDir); + if (!result.isEmpty()) { + KRecentDocument::add(QUrl::fromLocalFile(result)); + outputLine(QStringLiteral("0")); + outputLine(result); + return true; + } + } + + return false; + } + +bool Helper::handleGetDirectoryX( bool url ) + { + if( !readArguments( 2 )) + return false; + QString startDir = getArgument(); + QString title = getArgument(); + long wid = getArgumentParent(); + if( !allArgumentsUsed()) + return false; + + if (url) { + QUrl result = QFileDialog::getExistingDirectoryUrl(nullptr, title, startDir); + if (result.isValid()) { + outputLine(result.url()); + return true; + } + } else { + QString result = QFileDialog::getExistingDirectory(nullptr, title, startDir); + if (!result.isEmpty()) { + outputLine(QUrl::fromLocalFile(result).url()); + return true; + } + } + + return false; + } + +bool Helper::handleOpen() + { + if( !readArguments( 1 )) + return false; + QUrl url = QUrl::fromUserInput(getArgument()); + QString mime; + if( isArgument( "MIMETYPE" )) + mime = getArgument(); + if( !allArgumentsUsed()) + return false; + //KApplication::updateUserTimestamp( 0 ); // TODO + // try to handle the case when the server has broken mimetypes and e.g. claims something is application/octet-stream + QMimeType mimeType = QMimeDatabase().mimeTypeForName(mime); + if (!mime.isEmpty() && mimeType.isValid() && KMimeTypeTrader::self()->preferredService(mimeType.name())) + return KRun::runUrl( url, mime, NULL ); // TODO parent + else + { + (void) new KRun( url, NULL ); // TODO parent + // QObject::connect( run, SIGNAL( finished()), &app, SLOT( openDone())); + // QObject::connect( run, SIGNAL( error()), &app, SLOT( openDone())); + return true; // TODO check for errors? + } + } + +bool Helper::handleReveal() + { + if( !readArguments( 1 )) + return false; + QString path = getArgument(); + if( !allArgumentsUsed()) + return false; + //KApplication::updateUserTimestamp( 0 ); // TODO + const KService::List apps = KMimeTypeTrader::self()->query("inode/directory", "Application"); + if (apps.size() != 0) + { + QString command = apps.at(0)->exec().split( " " ).first(); // only the actual command + if (command == "dolphin" || command == "konqueror") + { + command = QStandardPaths::findExecutable(command); + if( command.isEmpty()) + return false; + return KProcess::startDetached(command, QStringList() << "--select" << path); + } + } + QFileInfo info(path); + QString dir = info.dir().path(); + (void) new KRun( QUrl::fromLocalFile(dir), NULL ); // TODO parent + return true; // TODO check for errors? + } + +bool Helper::handleRun() + { + if( !readArguments( 2 )) + return false; + QString app = getArgument(); + QString arg = getArgument(); + if( !allArgumentsUsed()) + return false; + //KApplication::updateUserTimestamp( 0 ); // TODO + return KRun::runCommand( KShell::quoteArg( app ) + " " + KShell::quoteArg( arg ), NULL ); // TODO parent, ASN + } + +bool Helper::handleGetDefaultFeedReader() + { + if( !readArguments( 0 )) + return false; + // firefox wants the full path + QString reader = QStandardPaths::findExecutable("akregator"); // TODO there is no KDE setting for this + if( !reader.isEmpty()) + { + outputLine( reader ); + return true; + } + return false; + } + +bool Helper::handleOpenMail() + { + if( !readArguments( 0 )) + return false; + // this is based on ktoolinvocation_x11.cpp, there is no API for this + KConfig config( "emaildefaults" ); + QString groupname = KConfigGroup( &config, "Defaults" ).readEntry( "Profile", "Default" ); + KConfigGroup group( &config, QString( "PROFILE_%1" ).arg( groupname )); + QString command = group.readPathEntry( "EmailClient", QString()); + if( command.isEmpty()) + command = "kmail"; + if( group.readEntry( "TerminalClient", false )) + { + QString terminal = KConfigGroup( KSharedConfig::openConfig(), "General" ).readPathEntry( "TerminalApplication", "konsole" ); + command = terminal + " -e " + command; + } + KService::Ptr mail = KService::serviceByDesktopName( command.split( " " ).first()); + if( mail ) + { + //KApplication::updateUserTimestamp( 0 ); // TODO + return KRun::runService( *mail, QList(), NULL ); // TODO parent + } + return false; + } + +bool Helper::handleOpenNews() + { + if( !readArguments( 0 )) + return false; + KService::Ptr news = KService::serviceByDesktopName( "knode" ); // TODO there is no KDE setting for this + if( news ) + { + //KApplication::updateUserTimestamp( 0 ); // TODO + return KRun::runService( *news, QList(), NULL ); // TODO parent + } + return false; + } + +bool Helper::handleIsDefaultBrowser() + { + if( !readArguments( 0 )) + return false; + QString browser = KConfigGroup( KSharedConfig::openConfig( "kdeglobals" ), "General" ) + .readEntry( "BrowserApplication" ); + return browser == "MozillaFirefox" || browser == "MozillaFirefox.desktop" + || browser == "!firefox" || browser == "!/usr/bin/firefox" + || browser == "firefox" || browser == "firefox.desktop"; + } + +bool Helper::handleSetDefaultBrowser() + { + if( !readArguments( 1 )) + return false; + bool alltypes = ( getArgument() == "ALLTYPES" ); + if( !allArgumentsUsed()) + return false; + KConfigGroup( KSharedConfig::openConfig( "kdeglobals" ), "General" ) + .writeEntry( "BrowserApplication", "firefox" ); + if( alltypes ) + { + // TODO there is no API for this and it is a bit complex + } + return true; + } + +bool Helper::handleDownloadFinished() + { + if( !readArguments( 1 )) + return false; + QString download = getArgument(); + if( !allArgumentsUsed()) + return false; + // TODO cheat a bit due to i18n freeze - the strings are in the .notifyrc file, + // taken from KGet, but the notification itself needs the text too. + // So create it from there. + KConfig cfg( "kmozillahelper.notifyrc", KConfig::FullConfig, QStandardPaths::AppDataLocation ); + QString message = KConfigGroup( &cfg, "Event/downloadfinished" ).readEntry( "Comment" ); + KNotification::event( "downloadfinished", download + " : " + message ); + return true; + } + +#if 0 +static bool open_error = false; + +void Helper::openDone() + { + // like kde-open - wait 2 second to give error dialogs time to show up + QTimer::singleShot( 2000, this, SLOT( quit())); + if( static_cast< KRun* >( sender())->hasError()) + open_error = true; + } +#endif + +QString Helper::getAppForProtocol( const QString& protocol ) + { + if( KProtocolInfo::isHelperProtocol( protocol )) + { + QString exec = KProtocolInfo::exec( protocol ); + if( !exec.isEmpty()) + { + if( exec.contains( ' ' )) + exec = exec.split( ' ' ).first(); // first part of command + QString servicename; + if( KService::Ptr service = KService::serviceByDesktopName( exec )) + servicename = service->name(); + else + { + foreach( KService::Ptr service, KService::allServices()) + { + QString exec2 = service->exec(); + if( exec2.contains( ' ' )) + exec2 = exec2.split( ' ' ).first(); // first part of command + if( exec == exec2 ) + { + servicename = service->name(); + break; + } + } + if( servicename.isEmpty() && exec == "kmailservice" ) // kmailto is handled internally by kmailservice + servicename = i18n( "KDE" ); + } + return servicename; + } + } + return QString(); + } + +QString Helper::readLine() + { + QString line = input.readLine(); + line.replace( "\\n", "\n" ); + line.replace( "\\" "\\", "\\" ); + return line; + } + +void Helper::outputLine( QString line, bool escape ) + { + if( escape ) + { + line.replace( "\\", "\\" "\\" ); + line.replace( "\n", "\\n" ); + } + output << line << endl; +#ifdef DEBUG_KDE + QTextStream( stderr ) << "OUTPUT: " << line << endl; +#endif + } + +bool Helper::readArguments( int mincount ) + { + assert( arguments.isEmpty()); + for(;;) + { + QString line = readLine(); + if( input.atEnd()) + { + arguments.clear(); + return false; + } + if( line == "\\E" ) + { + arguments_read = true; + if( arguments.count() >= mincount ) + return true; + QTextStream( stderr ) << "Not enough arguments for KDE helper." << endl; + return false; + } + arguments.append( line ); + } + } + +QString Helper::getArgument() + { + assert( !arguments.isEmpty()); + return arguments.takeFirst(); + } + +bool Helper::isArgument( const QString& argument ) + { + if( !arguments.isEmpty() && arguments.first() == argument ) + { + arguments.removeFirst(); + return true; + } + return false; + } + +bool Helper::allArgumentsUsed() + { + assert( arguments_read ); + arguments_read = false; + if( arguments.isEmpty()) + return true; + QTextStream( stderr ) << "Unused arguments for KDE helper:" << arguments.join( " " ) << endl; + arguments.clear(); + return false; + } + +long Helper::getArgumentParent() + { + if( isArgument( "PARENT" )) + return getArgument().toLong(); + return 0; + } + +#include "main.h" diff --git a/firefox-kde/main.h b/firefox-kde/main.h new file mode 100644 index 0000000..126f19b --- /dev/null +++ b/firefox-kde/main.h @@ -0,0 +1,77 @@ +/***************************************************************** + +Copyright (C) 2009 Lubos Lunak + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef MAIN_H +#define MAIN_H + +#include +#include +#include + +class Helper + : public QObject + { + Q_OBJECT + public: + Helper(); + private: + bool handleCheck(); + bool handleGetProxy(); + bool handleHandlerExists(); + bool handleGetFromExtension(); + bool handleGetFromType(); + bool handleGetAppDescForScheme(); + bool handleAppsDialog(); + bool handleGetOpenX( bool url ); + bool handleGetSaveX( bool url ); + bool handleGetDirectoryX( bool url ); + bool handleOpen(); + bool handleReveal(); + bool handleRun(); + bool handleGetDefaultFeedReader(); + bool handleOpenMail(); + bool handleOpenNews(); + bool handleIsDefaultBrowser(); + bool handleSetDefaultBrowser(); + bool handleDownloadFinished(); + bool writeMimeInfo( QMimeType mime ); + QString getAppForProtocol( const QString& protocol ); + bool readArguments( int mincount ); + QString getArgument(); + bool isArgument( const QString& name ); // also discards the line with it + bool allArgumentsUsed(); + long getArgumentParent(); + void outputLine( QString line, bool escape = true ); + QString readLine(); + private slots: + void readCommand(); +// void openDone(); + private: + QTextStream input; + QTextStream output; + QSocketNotifier notifier; + QStringList arguments; + bool arguments_read; + }; + +#endif