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

KDECore

  • kdecore
  • kernel
ktoolinvocation_x11.cpp
Go to the documentation of this file.
1/* This file is part of the KDE libraries
2 Copyright (c) 1997,1998 Matthias Kalle Dalheimer <kalle@kde.org>
3 Copyright (c) 1999 Espen Sand <espen@kde.org>
4 Copyright (c) 2000-2004 Frerich Raabe <raabe@kde.org>
5 Copyright (c) 2003,2004 Oswald Buddenhagen <ossi@kde.org>
6 Copyright (c) 2006 Thiago Macieira <thiago@kde.org>
7 Copyright (C) 2008 Aaron Seigo <aseigo@kde.org>
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public
11 License as published by the Free Software Foundation; either
12 version 2 of the License, or (at your option) any later version.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
18
19 You should have received a copy of the GNU Library General Public License
20 along with this library; see the file COPYING.LIB. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA.
23*/
24
25#include <config.h>
26
27#include "ktoolinvocation.h"
28
29#include <kconfiggroup.h>
30#include <kmimetypetrader.h>
31
32#include "kcmdlineargs.h"
33#include "kconfig.h"
34#include "kcodecs.h"
35#include "kdebug.h"
36#include "kglobal.h"
37#include "kshell.h"
38#include "kmacroexpander.h"
39#include "klocale.h"
40#include "kstandarddirs.h"
41#include "kmessage.h"
42#include "kservice.h"
43
44#include <QtCore/QCoreApplication>
45#include <QtCore/QProcess>
46#include <QtCore/QHash>
47#include <QtCore/QDebug>
48#include <QtCore/QBool>
49#include <QtCore/QFile>
50#include <QtDBus/QtDBus>
51
52static QStringList splitEmailAddressList( const QString & aStr )
53{
54 // This is a copy of KPIM::splitEmailAddrList().
55 // Features:
56 // - always ignores quoted characters
57 // - ignores everything (including parentheses and commas)
58 // inside quoted strings
59 // - supports nested comments
60 // - ignores everything (including double quotes and commas)
61 // inside comments
62
63 QStringList list;
64
65 if (aStr.isEmpty())
66 return list;
67
68 QString addr;
69 uint addrstart = 0;
70 int commentlevel = 0;
71 bool insidequote = false;
72
73 for (int index=0; index<aStr.length(); index++) {
74 // the following conversion to latin1 is o.k. because
75 // we can safely ignore all non-latin1 characters
76 switch (aStr[index].toLatin1()) {
77 case '"' : // start or end of quoted string
78 if (commentlevel == 0)
79 insidequote = !insidequote;
80 break;
81 case '(' : // start of comment
82 if (!insidequote)
83 commentlevel++;
84 break;
85 case ')' : // end of comment
86 if (!insidequote) {
87 if (commentlevel > 0)
88 commentlevel--;
89 else {
90 //kDebug() << "Error in address splitting: Unmatched ')'"
91 // << endl;
92 return list;
93 }
94 }
95 break;
96 case '\\' : // quoted character
97 index++; // ignore the quoted character
98 break;
99 case ',' :
100 if (!insidequote && (commentlevel == 0)) {
101 addr = aStr.mid(addrstart, index-addrstart);
102 if (!addr.isEmpty())
103 list += addr.simplified();
104 addrstart = index+1;
105 }
106 break;
107 }
108 }
109 // append the last address to the list
110 if (!insidequote && (commentlevel == 0)) {
111 addr = aStr.mid(addrstart, aStr.length()-addrstart);
112 if (!addr.isEmpty())
113 list += addr.simplified();
114 }
115 //else
116 // kDebug() << "Error in address splitting: "
117 // << "Unexpected end of address list"
118 // << endl;
119
120 return list;
121}
122
123#ifdef Q_WS_MAEMO_5
124// taken from QDesktopServices, which we cannot use here due to it being in QtGui
125inline static bool maemo5Launch(const QUrl &url)
126{
127 typedef bool (*Ptr_hildon_uri_open)(const char *, void *, void **);
128 static Ptr_hildon_uri_open hildon_uri_open = 0;
129
130 if (!hildon_uri_open) {
131 QLibrary lib(QLatin1String("libhildonmime"), 0, 0);
132 hildon_uri_open = (Ptr_hildon_uri_open)lib.resolve("hildon_uri_open");
133 }
134 if (hildon_uri_open)
135 return hildon_uri_open(url.toEncoded().constData(), 0, 0);
136 return false;
137}
138#endif
139
140void KToolInvocation::invokeMailer(const QString &_to, const QString &_cc, const QString &_bcc,
141 const QString &subject, const QString &body,
142 const QString & /*messageFile TODO*/, const QStringList &attachURLs,
143 const QByteArray& startup_id )
144{
145 if (!isMainThreadActive())
146 return;
147
148 KConfig config(QString::fromLatin1("emaildefaults"));
149 KConfigGroup defaultsGrp(&config, "Defaults");
150
151 QString group = defaultsGrp.readEntry("Profile","Default");
152
153 KConfigGroup profileGrp(&config, QString::fromLatin1("PROFILE_%1").arg(group) );
154 QString command = profileGrp.readPathEntry("EmailClient", QString());
155
156 QString to, cc, bcc;
157 if (command.isEmpty() || command == QLatin1String("kmail")
158 || command.endsWith(QLatin1String("/kmail")))
159 {
160 command = QLatin1String("kmail --composer -s %s -c %c -b %b --body %B --attach %A -- %t");
161 if ( !_to.isEmpty() )
162 {
163 KUrl url;
164 url.setProtocol(QLatin1String("mailto"));
165 url.setPath(_to);
166 to = QString::fromLatin1(url.toEncoded());
167 }
168 if ( !_cc.isEmpty() )
169 {
170 KUrl url;
171 url.setProtocol(QLatin1String("mailto"));
172 url.setPath(_cc);
173 cc = QString::fromLatin1(url.toEncoded());
174 }
175 if ( !_bcc.isEmpty() )
176 {
177 KUrl url;
178 url.setProtocol(QLatin1String("mailto"));
179 url.setPath(_bcc);
180 bcc = QString::fromLatin1(url.toEncoded());
181 }
182 } else {
183 to = _to;
184 cc = _cc;
185 bcc = _bcc;
186 if( !command.contains( QLatin1Char('%') ))
187 command += QLatin1String(" %u");
188 }
189
190 if (profileGrp.readEntry("TerminalClient", false))
191 {
192 KConfigGroup confGroup( KGlobal::config(), "General" );
193 QString preferredTerminal = confGroup.readPathEntry("TerminalApplication", QString::fromLatin1("konsole"));
194 command = preferredTerminal + QString::fromLatin1(" -e ") + command;
195 }
196
197 QStringList cmdTokens = KShell::splitArgs(command);
198 QString cmd = cmdTokens.takeFirst();
199
200 KUrl url;
201 //QStringList qry;
202 if (!to.isEmpty())
203 {
204 QStringList tos = splitEmailAddressList( to );
205 url.setPath( tos.first() );
206 tos.erase( tos.begin() );
207 for (QStringList::ConstIterator it = tos.constBegin(); it != tos.constEnd(); ++it)
208 url.addQueryItem(QString::fromLatin1("to"), *it);
209 //qry.append( "to=" + QLatin1String(KUrl::toPercentEncoding( *it ) ));
210 }
211 const QStringList ccs = splitEmailAddressList( cc );
212 for (QStringList::ConstIterator it = ccs.constBegin(); it != ccs.constEnd(); ++it)
213 url.addQueryItem(QString::fromLatin1("cc"), *it);
214 //qry.append( "cc=" + QLatin1String(KUrl::toPercentEncoding( *it ) ));
215 const QStringList bccs = splitEmailAddressList( bcc );
216 for (QStringList::ConstIterator it = bccs.constBegin(); it != bccs.constEnd(); ++it)
217 url.addQueryItem(QString::fromLatin1("bcc"), *it);
218 //qry.append( "bcc=" + QLatin1String(KUrl::toPercentEncoding( *it ) ));
219 for (QStringList::ConstIterator it = attachURLs.constBegin(); it != attachURLs.constEnd(); ++it)
220 url.addQueryItem(QString::fromLatin1("attach"), *it);
221 //qry.append( "attach=" + QLatin1String(KUrl::toPercentEncoding( *it ) ));
222 if (!subject.isEmpty())
223 url.addQueryItem(QString::fromLatin1("subject"), subject);
224 //qry.append( "subject=" + QLatin1String(KUrl::toPercentEncoding( subject ) ));
225 if (!body.isEmpty())
226 url.addQueryItem(QString::fromLatin1("body"), body);
227 //qry.append( "body=" + QLatin1String(KUrl::toPercentEncoding( body ) ));
228 //url.setQuery( qry.join( "&" ) );
229
230 if ( ! (to.isEmpty() && (!url.hasQuery())) )
231 url.setProtocol(QString::fromLatin1("mailto"));
232
233 QHash<QChar, QString> keyMap;
234 keyMap.insert(QLatin1Char('t'), to);
235 keyMap.insert(QLatin1Char('s'), subject);
236 keyMap.insert(QLatin1Char('c'), cc);
237 keyMap.insert(QLatin1Char('b'), bcc);
238 keyMap.insert(QLatin1Char('B'), body);
239 keyMap.insert(QLatin1Char('u'), url.url());
240
241 QString attachlist = attachURLs.join(QString::fromLatin1(","));
242 attachlist.prepend(QLatin1Char('\''));
243 attachlist.append(QLatin1Char('\''));
244 keyMap.insert(QLatin1Char('A'), attachlist);
245
246 for (QStringList::Iterator it = cmdTokens.begin(); it != cmdTokens.end(); )
247 {
248 if (*it == QLatin1String("%A"))
249 {
250 if (it == cmdTokens.begin()) // better safe than sorry ...
251 continue;
252 QStringList::ConstIterator urlit = attachURLs.begin();
253 QStringList::ConstIterator urlend = attachURLs.end();
254 if ( urlit != urlend )
255 {
256 QStringList::Iterator previt = it;
257 --previt;
258 *it = *urlit;
259 ++it;
260 while ( ++urlit != urlend )
261 {
262 cmdTokens.insert( it, *previt );
263 cmdTokens.insert( it, *urlit );
264 }
265 } else {
266 --it;
267 it = cmdTokens.erase( cmdTokens.erase( it ) );
268 }
269 } else {
270 *it = KMacroExpander::expandMacros(*it, keyMap);
271 ++it;
272 }
273 }
274
275 QString error;
276 // TODO this should check if cmd has a .desktop file, and use data from it, together
277 // with sending more ASN data
278 if (kdeinitExec(cmd, cmdTokens, &error, NULL, startup_id ))
279 {
280 KMessage::message(KMessage::Error,
281 i18n("Could not launch the mail client:\n\n%1", error),
282 i18n("Could not launch Mail Client"));
283 }
284}
285
286void KToolInvocation::invokeBrowser( const QString &url, const QByteArray& startup_id )
287{
288 if (!isMainThreadActive())
289 return;
290
291#ifdef Q_WS_MAEMO_5
292 if (maemo5Launch(url))
293 return;
294#endif
295 QStringList args;
296 args << url;
297 QString error;
298
299 // This method should launch a webbrowser, preferably without doing a mimetype
300 // check first, like KRun (i.e. kde-open) would do.
301
302 // In a KDE session, honour BrowserApplication if set, otherwise use preferred app for text/html if any,
303 // otherwise xdg-open, otherwise kde-open (which does a mimetype check first though).
304
305 // Outside KDE, call xdg-open if present, otherwise fallback to the above logic.
306
307 QString exe; // the binary we are going to launch.
308
309 const QString xdg_open = KStandardDirs::findExe(QString::fromLatin1("xdg-open"));
310 if (qgetenv("KDE_FULL_SESSION").isEmpty()) {
311 exe = xdg_open;
312 }
313
314 if (exe.isEmpty()) {
315 // We're in a KDE session (or there's no xdg-open installed)
316 KConfigGroup config(KGlobal::config(), "General");
317 const QString browserApp = config.readPathEntry("BrowserApplication", QString());
318 if (!browserApp.isEmpty()) {
319 exe = browserApp;
320 if (exe.startsWith(QLatin1Char('!'))) {
321 exe = exe.mid(1); // Literal command
322 QStringList cmdTokens = KShell::splitArgs(exe);
323 exe = cmdTokens.takeFirst();
324 args = cmdTokens + args;
325 } else {
326 // desktop file ID
327 KService::Ptr service = KService::serviceByStorageId(exe);
328 if (service) {
329 kDebug() << "Starting service" << service->entryPath();
330 if (startServiceByDesktopPath(service->entryPath(), args,
331 &error, 0, 0, startup_id)) {
332 KMessage::message(KMessage::Error,
333 // TODO: i18n("Could not launch %1:\n\n%2", exe, error),
334 i18n("Could not launch the browser:\n\n%1", error),
335 i18n("Could not launch Browser"));
336 }
337 return;
338 }
339 }
340 } else {
341 const KService::Ptr htmlApp = KMimeTypeTrader::self()->preferredService(QLatin1String("text/html"));
342 if (htmlApp) {
343 // WORKAROUND: For bugs 264562 and 265474:
344 // In order to correctly handle non-HTML urls we change the service
345 // desktop file name to "kfmclient.desktop" whenever the above query
346 // returns "kfmclient_html.desktop".Otherwise, the hard coded mime-type
347 // "text/html" mime-type parameter in the kfmclient_html will cause all
348 // URLs to be treated as if they are HTML page.
349 QString entryPath = htmlApp->entryPath();
350 if (entryPath.endsWith(QLatin1String("kfmclient_html.desktop"))) {
351 entryPath.remove(entryPath.length()-13, 5);
352 }
353 QString error;
354 int pid = 0;
355 int err = startServiceByDesktopPath(entryPath, url, &error, 0, &pid, startup_id);
356 if (err != 0) {
357 KMessage::message(KMessage::Error,
358 // TODO: i18n("Could not launch %1:\n\n%2", htmlApp->exec(), error),
359 i18n("Could not launch the browser:\n\n%1", error),
360 i18n("Could not launch Browser"));
361 } else { // success
362 return;
363 }
364 } else {
365 exe = xdg_open;
366 }
367 }
368 }
369
370 if (exe.isEmpty()) {
371 exe = QString::fromLatin1("kde-open"); // it's from kdebase-runtime, it has to be there.
372 }
373
374 kDebug(180) << "Using" << exe << "to open" << url;
375 if (kdeinitExec(exe, args, &error, NULL, startup_id ))
376 {
377 KMessage::message(KMessage::Error,
378 // TODO: i18n("Could not launch %1:\n\n%2", exe, error),
379 i18n("Could not launch the browser:\n\n%1", error),
380 i18n("Could not launch Browser"));
381 }
382}
383
384void KToolInvocation::invokeTerminal(const QString &command,
385 const QString &workdir,
386 const QByteArray &startup_id)
387{
388 if (!isMainThreadActive()) {
389 return;
390 }
391
392 KConfigGroup confGroup( KGlobal::config(), "General" );
393 QString exec = confGroup.readPathEntry("TerminalApplication", QString::fromLatin1("konsole"));
394
395 if (!command.isEmpty()) {
396 if (exec == QLatin1String("konsole")) {
397 exec += QString::fromLatin1(" --noclose");
398 } else if (exec == QLatin1String("xterm")) {
399 exec += QString::fromLatin1(" -hold");
400 }
401
402 exec += QString::fromLatin1(" -e ") + command;
403 }
404
405 QStringList cmdTokens = KShell::splitArgs(exec);
406 QString cmd = cmdTokens.takeFirst();
407
408 if (exec == QLatin1String("konsole") && !workdir.isEmpty()) {
409 cmdTokens << QString::fromLatin1("--workdir");
410 cmdTokens << workdir;
411 // For other terminals like xterm, we'll simply change the working
412 // directory before launching them, see below.
413 }
414
415 if (!QProcess::startDetached(cmd, cmdTokens)) {
416 KMessage::message(KMessage::Error,
417 i18n("Could not launch the terminal client"),
418 i18n("Could not launch Terminal Client"));
419 }
420}
KConfigGroup
A class for one specific group in a KConfig object.
Definition: kconfiggroup.h:54
KConfig
The central class of the KDE configuration data system.
Definition: kconfig.h:71
KMimeTypeTrader::preferredService
KService::Ptr preferredService(const QString &mimeType, const QString &genericServiceType=QString::fromLatin1("Application"))
Returns the preferred service for mimeType and genericServiceType.
Definition: kmimetypetrader.cpp:157
KMimeTypeTrader::self
static KMimeTypeTrader * self()
This is a static pointer to the KMimeTypeTrader singleton.
Definition: kmimetypetrader.cpp:38
KService::serviceByStorageId
static Ptr serviceByStorageId(const QString &_storageId)
Find a service by its storage-id or desktop-file path.
Definition: kservice.cpp:638
KSharedPtr< KService >
KStandardDirs::findExe
static QString findExe(const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
Finds the executable in the system path.
Definition: kstandarddirs.cpp:1334
KSycocaEntry::entryPath
QString entryPath() const
Definition: ksycocaentry.cpp:104
KToolInvocation::invokeTerminal
static void invokeTerminal(const QString &command, const QString &workdir=QString(), const QByteArray &startup_id="")
Invokes the standard terminal application.
Definition: ktoolinvocation_win.cpp:82
KToolInvocation::kdeinitExec
static int kdeinitExec(const QString &name, const QStringList &args=QStringList(), QString *error=0, int *pid=0, const QByteArray &startup_id=QByteArray())
Starts a program via kdeinit.
Definition: ktoolinvocation.cpp:228
KToolInvocation::invokeMailer
static void invokeMailer(const QString &address, const QString &subject, const QByteArray &startup_id=QByteArray())
Convenience method; invokes the standard email application.
Definition: ktoolinvocation.cpp:319
KToolInvocation::invokeBrowser
static void invokeBrowser(const QString &url, const QByteArray &startup_id=QByteArray())
Invokes the user's preferred browser.
Definition: ktoolinvocation_win.cpp:37
KToolInvocation::startServiceByDesktopPath
static int startServiceByDesktopPath(const QString &_name, const QString &URL, QString *error=0, QString *serviceName=0, int *pid=0, const QByteArray &startup_id=QByteArray(), bool noWait=false)
Starts a service based on the desktop path of the service.
Definition: ktoolinvocation.cpp:174
KUrl
Represents and parses a URL.
Definition: kurl.h:112
KUrl::addQueryItem
void addQueryItem(const QString &_item, const QString &_value)
Add an additional query item.
Definition: kurl.cpp:1868
KUrl::url
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
Returns the URL as string, with all escape sequences intact, encoded in a given charset.
Definition: kurl.cpp:1035
KUrl::setProtocol
void setProtocol(const QString &proto)
Sets the protocol for the URL (i.e., file, http, etc.)
Definition: kurl.cpp:677
KUrl::setPath
void setPath(const QString &path)
Definition: kurl.cpp:1772
QHash
Definition: ksycocafactory.h:28
QLibrary
QStringList
QString
QUrl
bool
kDebug
#define kDebug
Definition: kdebug.h:316
pid
static pid_t pid
Definition: k3resolvermanager.cpp:249
kcmdlineargs.h
kcodecs.h
kconfig.h
kconfiggroup.h
kdebug.h
kglobal.h
klocale.h
i18n
QString i18n(const char *text)
Returns a localized version of a string.
Definition: klocalizedstring.h:630
kmacroexpander.h
kmessage.h
kmimetypetrader.h
kservice.h
kshell.h
kstandarddirs.h
ktoolinvocation.h
splitEmailAddressList
static QStringList splitEmailAddressList(const QString &aStr)
Definition: ktoolinvocation_x11.cpp:52
maemo5Launch
static bool maemo5Launch(const QUrl &url)
Definition: ktoolinvocation_x11.cpp:125
KGlobal::config
KSharedConfigPtr config()
Returns the general config object.
Definition: kglobal.cpp:139
KMacroExpander::expandMacros
QString expandMacros(const QString &ostr, const QHash< QChar, QString > &map, QChar c)
Perform safe macro expansion (substitution) on a string.
Definition: kmacroexpander.cpp:340
KMacroExpander::group
@ group
Definition: kmacroexpander_unix.cpp:34
KMessage::message
void message(KMessage::MessageType messageType, const QString &text, const QString &caption=QString())
Display a long message of a certain type.
Definition: kmessage.cpp:92
KMessage::Error
@ Error
Error message.
Definition: kmessage.h:57
KShell::splitArgs
QStringList splitArgs(const QString &cmd, Options flags=NoOptions, Errors *err=0)
Splits cmd according to system shell word splitting and quoting rules.
Definition: kshell_unix.cpp:70
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

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-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • 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
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal