• Skip to content
  • Skip to link menu
KDE 4.7 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KDECore

ktoolinvocation_x11.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002     Copyright (c) 1997,1998 Matthias Kalle Dalheimer <kalle@kde.org>
00003     Copyright (c) 1999 Espen Sand <espen@kde.org>
00004     Copyright (c) 2000-2004 Frerich Raabe <raabe@kde.org>
00005     Copyright (c) 2003,2004 Oswald Buddenhagen <ossi@kde.org>
00006     Copyright (c) 2006 Thiago Macieira <thiago@kde.org>
00007     Copyright (C) 2008 Aaron Seigo <aseigo@kde.org>
00008 
00009     This library is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU Library General Public
00011     License as published by the Free Software Foundation; either
00012     version 2 of the License, or (at your option) any later version.
00013 
00014     This library is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017     Library General Public License for more details.
00018 
00019     You should have received a copy of the GNU Library General Public License
00020     along with this library; see the file COPYING.LIB.  If not, write to
00021     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00022     Boston, MA 02110-1301, USA.
00023 */
00024 
00025 #include <config.h>
00026 
00027 #include "ktoolinvocation.h"
00028 
00029 #include <kconfiggroup.h>
00030 #include <kmimetypetrader.h>
00031 
00032 #include "kcmdlineargs.h"
00033 #include "kconfig.h"
00034 #include "kcodecs.h"
00035 #include "kdebug.h"
00036 #include "kglobal.h"
00037 #include "kshell.h"
00038 #include "kmacroexpander.h"
00039 #include "klocale.h"
00040 #include "kstandarddirs.h"
00041 #include "kmessage.h"
00042 #include "kservice.h"
00043 
00044 #include <QtCore/QCoreApplication>
00045 #include <QtCore/QProcess>
00046 #include <QtCore/QHash>
00047 #include <QtCore/QDebug>
00048 #include <QtCore/QBool>
00049 #include <QtCore/QFile>
00050 #include <QtDBus/QtDBus>
00051 
00052 static QStringList splitEmailAddressList( const QString & aStr )
00053 {
00054     // This is a copy of KPIM::splitEmailAddrList().
00055     // Features:
00056     // - always ignores quoted characters
00057     // - ignores everything (including parentheses and commas)
00058     //   inside quoted strings
00059     // - supports nested comments
00060     // - ignores everything (including double quotes and commas)
00061     //   inside comments
00062 
00063     QStringList list;
00064 
00065     if (aStr.isEmpty())
00066         return list;
00067 
00068     QString addr;
00069     uint addrstart = 0;
00070     int commentlevel = 0;
00071     bool insidequote = false;
00072 
00073     for (int index=0; index<aStr.length(); index++) {
00074         // the following conversion to latin1 is o.k. because
00075         // we can safely ignore all non-latin1 characters
00076         switch (aStr[index].toLatin1()) {
00077         case '"' : // start or end of quoted string
00078             if (commentlevel == 0)
00079                 insidequote = !insidequote;
00080             break;
00081         case '(' : // start of comment
00082             if (!insidequote)
00083                 commentlevel++;
00084             break;
00085         case ')' : // end of comment
00086             if (!insidequote) {
00087                 if (commentlevel > 0)
00088                     commentlevel--;
00089                 else {
00090                     //kDebug() << "Error in address splitting: Unmatched ')'"
00091                     //          << endl;
00092                     return list;
00093                 }
00094             }
00095             break;
00096         case '\\' : // quoted character
00097             index++; // ignore the quoted character
00098             break;
00099         case ',' :
00100             if (!insidequote && (commentlevel == 0)) {
00101                 addr = aStr.mid(addrstart, index-addrstart);
00102                 if (!addr.isEmpty())
00103                     list += addr.simplified();
00104                 addrstart = index+1;
00105             }
00106             break;
00107         }
00108     }
00109     // append the last address to the list
00110     if (!insidequote && (commentlevel == 0)) {
00111         addr = aStr.mid(addrstart, aStr.length()-addrstart);
00112         if (!addr.isEmpty())
00113             list += addr.simplified();
00114     }
00115     //else
00116     //  kDebug() << "Error in address splitting: "
00117     //            << "Unexpected end of address list"
00118     //            << endl;
00119 
00120     return list;
00121 }
00122 
00123 #ifdef Q_WS_MAEMO_5
00124 // taken from QDesktopServices, which we cannot use here due to it being in QtGui
00125 inline static bool maemo5Launch(const QUrl &url)
00126 {
00127     typedef bool (*Ptr_hildon_uri_open)(const char *, void *, void **);
00128     static Ptr_hildon_uri_open hildon_uri_open = 0;
00129 
00130     if (!hildon_uri_open) {
00131         QLibrary lib(QLatin1String("libhildonmime"), 0, 0);
00132         hildon_uri_open = (Ptr_hildon_uri_open)lib.resolve("hildon_uri_open");
00133     }
00134     if (hildon_uri_open)
00135         return hildon_uri_open(url.toEncoded().constData(), 0, 0);
00136     return false;
00137 }
00138 #endif
00139 
00140 void KToolInvocation::invokeMailer(const QString &_to, const QString &_cc, const QString &_bcc,
00141                                    const QString &subject, const QString &body,
00142                                    const QString & /*messageFile TODO*/, const QStringList &attachURLs,
00143                                    const QByteArray& startup_id )
00144 {
00145     if (!isMainThreadActive())
00146         return;
00147 
00148     KConfig config(QString::fromLatin1("emaildefaults"));
00149     KConfigGroup defaultsGrp(&config, "Defaults");
00150 
00151     QString group = defaultsGrp.readEntry("Profile","Default");
00152 
00153     KConfigGroup profileGrp(&config, QString::fromLatin1("PROFILE_%1").arg(group) );
00154     QString command = profileGrp.readPathEntry("EmailClient", QString());
00155 
00156     QString to, cc, bcc;
00157     if (command.isEmpty() || command == QLatin1String("kmail")
00158         || command.endsWith(QLatin1String("/kmail")))
00159     {
00160         command = QLatin1String("kmail --composer -s %s -c %c -b %b --body %B --attach %A -- %t");
00161         if ( !_to.isEmpty() )
00162         {
00163             KUrl url;
00164             url.setProtocol(QLatin1String("mailto"));
00165             url.setPath(_to);
00166             to = QString::fromLatin1(url.toEncoded());
00167         }
00168         if ( !_cc.isEmpty() )
00169         {
00170             KUrl url;
00171             url.setProtocol(QLatin1String("mailto"));
00172             url.setPath(_cc);
00173             cc = QString::fromLatin1(url.toEncoded());
00174         }
00175         if ( !_bcc.isEmpty() )
00176         {
00177             KUrl url;
00178             url.setProtocol(QLatin1String("mailto"));
00179             url.setPath(_bcc);
00180             bcc = QString::fromLatin1(url.toEncoded());
00181         }
00182     } else {
00183         to = _to;
00184         cc = _cc;
00185         bcc = _bcc;
00186         if( !command.contains( QLatin1Char('%') ))
00187             command += QLatin1String(" %u");
00188     }
00189 
00190     if (profileGrp.readEntry("TerminalClient", false))
00191     {
00192         KConfigGroup confGroup( KGlobal::config(), "General" );
00193         QString preferredTerminal = confGroup.readPathEntry("TerminalApplication", QString::fromLatin1("konsole"));
00194         command = preferredTerminal + QString::fromLatin1(" -e ") + command;
00195     }
00196 
00197     QStringList cmdTokens = KShell::splitArgs(command);
00198     QString cmd = cmdTokens.takeFirst();
00199 
00200     KUrl url;
00201     //QStringList qry;
00202     if (!to.isEmpty())
00203     {
00204         QStringList tos = splitEmailAddressList( to );
00205         url.setPath( tos.first() );
00206         tos.erase( tos.begin() );
00207         for (QStringList::ConstIterator it = tos.constBegin(); it != tos.constEnd(); ++it)
00208             url.addQueryItem(QString::fromLatin1("to"), *it);
00209         //qry.append( "to=" + QLatin1String(KUrl::toPercentEncoding( *it ) ));
00210     }
00211     const QStringList ccs = splitEmailAddressList( cc );
00212     for (QStringList::ConstIterator it = ccs.constBegin(); it != ccs.constEnd(); ++it)
00213         url.addQueryItem(QString::fromLatin1("cc"), *it);
00214     //qry.append( "cc=" + QLatin1String(KUrl::toPercentEncoding( *it ) ));
00215     const QStringList bccs = splitEmailAddressList( bcc );
00216     for (QStringList::ConstIterator it = bccs.constBegin(); it != bccs.constEnd(); ++it)
00217         url.addQueryItem(QString::fromLatin1("bcc"), *it);
00218     //qry.append( "bcc=" + QLatin1String(KUrl::toPercentEncoding( *it ) ));
00219     for (QStringList::ConstIterator it = attachURLs.constBegin(); it != attachURLs.constEnd(); ++it)
00220         url.addQueryItem(QString::fromLatin1("attach"), *it);
00221     //qry.append( "attach=" + QLatin1String(KUrl::toPercentEncoding( *it ) ));
00222     if (!subject.isEmpty())
00223         url.addQueryItem(QString::fromLatin1("subject"), subject);
00224     //qry.append( "subject=" + QLatin1String(KUrl::toPercentEncoding( subject ) ));
00225     if (!body.isEmpty())
00226         url.addQueryItem(QString::fromLatin1("body"), body);
00227     //qry.append( "body=" + QLatin1String(KUrl::toPercentEncoding( body ) ));
00228     //url.setQuery( qry.join( "&" ) );
00229 
00230     if ( ! (to.isEmpty() && (!url.hasQuery())) )
00231         url.setProtocol(QString::fromLatin1("mailto"));
00232 
00233     QHash<QChar, QString> keyMap;
00234     keyMap.insert(QLatin1Char('t'), to);
00235     keyMap.insert(QLatin1Char('s'), subject);
00236     keyMap.insert(QLatin1Char('c'), cc);
00237     keyMap.insert(QLatin1Char('b'), bcc);
00238     keyMap.insert(QLatin1Char('B'), body);
00239     keyMap.insert(QLatin1Char('u'), url.url());
00240 
00241     QString attachlist = attachURLs.join(QString::fromLatin1(","));
00242     attachlist.prepend(QLatin1Char('\''));
00243     attachlist.append(QLatin1Char('\''));
00244     keyMap.insert(QLatin1Char('A'), attachlist);
00245 
00246     for (QStringList::Iterator it = cmdTokens.begin(); it != cmdTokens.end(); )
00247     {
00248         if (*it == QLatin1String("%A"))
00249         {
00250             if (it == cmdTokens.begin()) // better safe than sorry ...
00251                 continue;
00252             QStringList::ConstIterator urlit = attachURLs.begin();
00253             QStringList::ConstIterator urlend = attachURLs.end();
00254             if ( urlit != urlend )
00255             {
00256                 QStringList::Iterator previt = it;
00257                 --previt;
00258                 *it = *urlit;
00259                 ++it;
00260                 while ( ++urlit != urlend )
00261                 {
00262                     cmdTokens.insert( it, *previt );
00263                     cmdTokens.insert( it, *urlit );
00264                 }
00265             } else {
00266                 --it;
00267                 it = cmdTokens.erase( cmdTokens.erase( it ) );
00268             }
00269         } else {
00270             *it = KMacroExpander::expandMacros(*it, keyMap);
00271             ++it;
00272         }
00273     }
00274 
00275     QString error;
00276     // TODO this should check if cmd has a .desktop file, and use data from it, together
00277     // with sending more ASN data
00278     if (kdeinitExec(cmd, cmdTokens, &error, NULL, startup_id ))
00279     {
00280       KMessage::message(KMessage::Error,
00281                       i18n("Could not launch the mail client:\n\n%1", error),
00282                       i18n("Could not launch Mail Client"));
00283     }
00284 }
00285 
00286 void KToolInvocation::invokeBrowser( const QString &url, const QByteArray& startup_id )
00287 {
00288     if (!isMainThreadActive())
00289         return;
00290 
00291 #ifdef Q_WS_MAEMO_5
00292     if (maemo5Launch(url))
00293       return;
00294 #endif
00295     QStringList args;
00296     args << url;
00297     QString error;
00298 
00299     // This method should launch a webbrowser, preferably without doing a mimetype
00300     // check first, like KRun (i.e. kde-open) would do.
00301 
00302     // In a KDE session, honour BrowserApplication if set, otherwise use preferred app for text/html if any,
00303     // otherwise xdg-open, otherwise kde-open (which does a mimetype check first though).
00304 
00305     // Outside KDE, call xdg-open if present, otherwise fallback to the above logic.
00306 
00307     QString exe; // the binary we are going to launch.
00308 
00309     const QString xdg_open = KStandardDirs::findExe(QString::fromLatin1("xdg-open"));
00310     if (qgetenv("KDE_FULL_SESSION").isEmpty()) {
00311         exe = xdg_open;
00312     }
00313 
00314     if (exe.isEmpty()) {
00315         // We're in a KDE session (or there's no xdg-open installed)
00316         KConfigGroup config(KGlobal::config(), "General");
00317         const QString browserApp = config.readPathEntry("BrowserApplication", QString());
00318         if (!browserApp.isEmpty()) {
00319             exe = browserApp;
00320             if (exe.startsWith(QLatin1Char('!'))) {
00321                 exe = exe.mid(1); // Literal command
00322                 QStringList cmdTokens = KShell::splitArgs(exe);
00323                 exe = cmdTokens.takeFirst();
00324                 args = cmdTokens + args;
00325             } else {
00326                 // desktop file ID
00327                 KService::Ptr service = KService::serviceByStorageId(exe);
00328                 if (service) {
00329                     kDebug() << "Starting service" << service->entryPath();
00330                     if (startServiceByDesktopPath(service->entryPath(), args,
00331                             &error, 0, 0, startup_id)) {
00332                         KMessage::message(KMessage::Error,
00333                                           // TODO: i18n("Could not launch %1:\n\n%2", exe, error),
00334                                           i18n("Could not launch the browser:\n\n%1", error),
00335                                           i18n("Could not launch Browser"));
00336                     }
00337                     return;
00338                 }
00339             }
00340         } else {
00341             const KService::Ptr htmlApp = KMimeTypeTrader::self()->preferredService(QLatin1String("text/html"));
00342             if (htmlApp) {
00343                 // WORKAROUND: For bugs 264562 and 265474:
00344                 // In order to correctly handle non-HTML urls we change the service
00345                 // desktop file name to "kfmclient.desktop" whenever the above query
00346                 // returns "kfmclient_html.desktop".Otherwise, the hard coded mime-type
00347                 // "text/html" mime-type parameter in the kfmclient_html will cause all
00348                 // URLs to be treated as if they are HTML page.
00349                 QString entryPath = htmlApp->entryPath();
00350                 if (entryPath.endsWith(QLatin1String("kfmclient_html.desktop"))) {
00351                     entryPath.remove(entryPath.length()-13, 5);
00352                 }
00353                 QString error;
00354                 int pid = 0;
00355                 int err = startServiceByDesktopPath(entryPath, url, &error, 0, &pid, startup_id);
00356                 if (err != 0) {
00357                     KMessage::message(KMessage::Error,
00358                                       // TODO: i18n("Could not launch %1:\n\n%2", htmlApp->exec(), error),
00359                                       i18n("Could not launch the browser:\n\n%1", error),
00360                                       i18n("Could not launch Browser"));
00361                 } else { // success
00362                     return;
00363                 }
00364             } else {
00365                 exe = xdg_open;
00366             }
00367         }
00368     }
00369 
00370     if (exe.isEmpty()) {
00371         exe = QString::fromLatin1("kde-open"); // it's from kdebase-runtime, it has to be there.
00372     }
00373 
00374     kDebug(180) << "Using" << exe << "to open" << url;
00375     if (kdeinitExec(exe, args, &error, NULL, startup_id ))
00376     {
00377         KMessage::message(KMessage::Error,
00378                           // TODO: i18n("Could not launch %1:\n\n%2", exe, error),
00379                           i18n("Could not launch the browser:\n\n%1", error),
00380                           i18n("Could not launch Browser"));
00381     }
00382 }
00383 
00384 void KToolInvocation::invokeTerminal(const QString &command,
00385                                      const QString &workdir,
00386                                      const QByteArray &startup_id)
00387 {
00388     if (!isMainThreadActive()) {
00389         return;
00390     }
00391 
00392     KConfigGroup confGroup( KGlobal::config(), "General" );
00393     QString exec = confGroup.readPathEntry("TerminalApplication", QString::fromLatin1("konsole"));
00394 
00395     if (!command.isEmpty()) {
00396         if (exec == QLatin1String("konsole")) {
00397             exec += QString::fromLatin1(" --noclose");
00398         } else if (exec == QLatin1String("xterm")) {
00399             exec += QString::fromLatin1(" -hold");
00400         }
00401 
00402         exec += QString::fromLatin1(" -e ") + command;
00403     }
00404 
00405     QStringList cmdTokens = KShell::splitArgs(exec);
00406     QString cmd = cmdTokens.takeFirst();
00407 
00408     if (exec == QLatin1String("konsole") && !workdir.isEmpty()) {
00409         cmdTokens << QString::fromLatin1("--workdir");
00410         cmdTokens << workdir;
00411         // For other terminals like xterm, we'll simply change the working
00412         // directory before launching them, see below.
00413     }
00414 
00415     QString error;
00416     if (self()->startServiceInternal("kdeinit_exec_with_workdir",
00417                                     cmd, cmdTokens, &error, 0, NULL, startup_id, false, workdir)) {
00418       KMessage::message(KMessage::Error,
00419                       i18n("Could not launch the terminal client:\n\n%1", error),
00420                       i18n("Could not launch Terminal Client"));
00421     }
00422 }

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal