1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2000 Yves Arrouye <yves@realnames.com>
4 SPDX-FileCopyrightText: 2000, 2010 Dawit Alemayehu <adawit at kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
9#include "kurifilter.h"
10#include "kurifilterdata_p.h"
11
12#include <KService>
13#include <kio/global.h>
14
15#include <KPluginFactory>
16#include <KPluginMetaData>
17
18#include <QHashIterator>
19#include <QHostAddress>
20#include <QHostInfo>
21#include <QIcon>
22
23#include "kurifilterplugin_p.h"
24
25QString KUriFilterDataPrivate::lookupIconNameFor(const QUrl &url, KUriFilterData::UriTypes type)
26{
27 QString iconName;
28
29 switch (type) {
30 case KUriFilterData::NetProtocol:
31 iconName = KIO::iconNameForUrl(url);
32 break;
33 case KUriFilterData::Executable: {
34 QString exeName = url.path();
35 exeName.remove(i: 0, len: exeName.lastIndexOf(c: QLatin1Char('/')) + 1); // strip path if given
36 KService::Ptr service = KService::serviceByDesktopName(name: exeName);
37 if (service && service->icon() != QLatin1String("unknown")) {
38 iconName = service->icon();
39 }
40 // Try to find an icon with the same name as the binary (useful for non-kde apps)
41 else if (!QIcon::fromTheme(name: exeName).isNull()) {
42 iconName = exeName;
43 } else {
44 // not found, use default
45 iconName = QStringLiteral("system-run");
46 }
47 break;
48 }
49 case KUriFilterData::Help: {
50 iconName = QStringLiteral("khelpcenter");
51 break;
52 }
53 case KUriFilterData::Shell: {
54 iconName = QStringLiteral("konsole");
55 break;
56 }
57 case KUriFilterData::Error:
58 case KUriFilterData::Blocked: {
59 iconName = QStringLiteral("error");
60 break;
61 }
62 default:
63 break;
64 }
65
66 return iconName;
67}
68
69class Q_DECL_HIDDEN KUriFilterSearchProvider::KUriFilterSearchProviderPrivate
70{
71public:
72 KUriFilterSearchProviderPrivate()
73 {
74 }
75 KUriFilterSearchProviderPrivate(const KUriFilterSearchProviderPrivate &other)
76 : desktopEntryName(other.desktopEntryName)
77 , iconName(other.iconName)
78 , name(other.name)
79 , keys(other.keys)
80 {
81 }
82
83 QString desktopEntryName;
84 QString iconName;
85 QString name;
86 QStringList keys;
87};
88
89KUriFilterSearchProvider::KUriFilterSearchProvider()
90 : d(new KUriFilterSearchProvider::KUriFilterSearchProviderPrivate)
91{
92}
93
94KUriFilterSearchProvider::KUriFilterSearchProvider(const KUriFilterSearchProvider &other)
95 : d(new KUriFilterSearchProvider::KUriFilterSearchProviderPrivate(*(other.d)))
96{
97}
98
99KUriFilterSearchProvider::~KUriFilterSearchProvider() = default;
100
101QString KUriFilterSearchProvider::desktopEntryName() const
102{
103 return d->desktopEntryName;
104}
105
106QString KUriFilterSearchProvider::iconName() const
107{
108 return d->iconName;
109}
110
111QString KUriFilterSearchProvider::name() const
112{
113 return d->name;
114}
115
116QStringList KUriFilterSearchProvider::keys() const
117{
118 return d->keys;
119}
120
121QString KUriFilterSearchProvider::defaultKey() const
122{
123 if (d->keys.isEmpty()) {
124 return QString();
125 }
126
127 return d->keys.first();
128}
129
130KUriFilterSearchProvider &KUriFilterSearchProvider::operator=(const KUriFilterSearchProvider &other)
131{
132 d->desktopEntryName = other.d->desktopEntryName;
133 d->iconName = other.d->iconName;
134 d->keys = other.d->keys;
135 d->name = other.d->name;
136 return *this;
137}
138
139void KUriFilterSearchProvider::setDesktopEntryName(const QString &desktopEntryName)
140{
141 d->desktopEntryName = desktopEntryName;
142}
143
144void KUriFilterSearchProvider::setIconName(const QString &iconName)
145{
146 d->iconName = iconName;
147}
148
149void KUriFilterSearchProvider::setName(const QString &name)
150{
151 d->name = name;
152}
153
154void KUriFilterSearchProvider::setKeys(const QStringList &keys)
155{
156 d->keys = keys;
157}
158
159KUriFilterData::KUriFilterData()
160 : d(new KUriFilterDataPrivate(QUrl(), QString()))
161{
162}
163
164KUriFilterData::KUriFilterData(const QUrl &url)
165 : d(new KUriFilterDataPrivate(url, url.toString()))
166{
167}
168
169KUriFilterData::KUriFilterData(const QString &url)
170 : d(new KUriFilterDataPrivate(QUrl::fromUserInput(userInput: url), url))
171{
172}
173
174KUriFilterData::KUriFilterData(const KUriFilterData &other)
175 : d(new KUriFilterDataPrivate(*other.d))
176{
177}
178
179KUriFilterData::~KUriFilterData() = default;
180
181QUrl KUriFilterData::uri() const
182{
183 return d->url;
184}
185
186QString KUriFilterData::errorMsg() const
187{
188 return d->errMsg;
189}
190
191KUriFilterData::UriTypes KUriFilterData::uriType() const
192{
193 return d->uriType;
194}
195
196QString KUriFilterData::absolutePath() const
197{
198 return d->absPath;
199}
200
201bool KUriFilterData::hasAbsolutePath() const
202{
203 return !d->absPath.isEmpty();
204}
205
206QString KUriFilterData::argsAndOptions() const
207{
208 return d->args;
209}
210
211bool KUriFilterData::hasArgsAndOptions() const
212{
213 return !d->args.isEmpty();
214}
215
216bool KUriFilterData::checkForExecutables() const
217{
218 return d->checkForExecs;
219}
220
221QString KUriFilterData::typedString() const
222{
223 return d->typedString;
224}
225
226QString KUriFilterData::searchTerm() const
227{
228 return d->searchTerm;
229}
230
231QChar KUriFilterData::searchTermSeparator() const
232{
233 return d->searchTermSeparator;
234}
235
236QString KUriFilterData::searchProvider() const
237{
238 return d->searchProvider;
239}
240
241QStringList KUriFilterData::preferredSearchProviders() const
242{
243 return d->searchProviderList;
244}
245
246KUriFilterSearchProvider KUriFilterData::queryForSearchProvider(const QString &provider) const
247{
248 const KUriFilterSearchProvider *searchProvider = d->searchProviderMap.value(key: provider);
249
250 if (searchProvider) {
251 return *(searchProvider);
252 }
253
254 return KUriFilterSearchProvider();
255}
256
257QString KUriFilterData::queryForPreferredSearchProvider(const QString &provider) const
258{
259 const KUriFilterSearchProvider *searchProvider = d->searchProviderMap.value(key: provider);
260 if (searchProvider) {
261 return (searchProvider->defaultKey() % searchTermSeparator() % searchTerm());
262 }
263 return QString();
264}
265
266QStringList KUriFilterData::allQueriesForSearchProvider(const QString &provider) const
267{
268 const KUriFilterSearchProvider *searchProvider = d->searchProviderMap.value(key: provider);
269 if (searchProvider) {
270 return searchProvider->keys();
271 }
272 return QStringList();
273}
274
275QString KUriFilterData::iconNameForPreferredSearchProvider(const QString &provider) const
276{
277 const KUriFilterSearchProvider *searchProvider = d->searchProviderMap.value(key: provider);
278 if (searchProvider) {
279 return searchProvider->iconName();
280 }
281 return QString();
282}
283
284QStringList KUriFilterData::alternateSearchProviders() const
285{
286 return d->alternateSearchProviders;
287}
288
289QString KUriFilterData::alternateDefaultSearchProvider() const
290{
291 return d->alternateDefaultSearchProvider;
292}
293
294QString KUriFilterData::defaultUrlScheme() const
295{
296 return d->defaultUrlScheme;
297}
298
299KUriFilterData::SearchFilterOptions KUriFilterData::searchFilteringOptions() const
300{
301 return d->searchFilterOptions;
302}
303
304QString KUriFilterData::iconName()
305{
306 auto foundProvider = d->searchProviderMap.constFind(key: searchProvider());
307 if (foundProvider != d->searchProviderMap.cend() && !foundProvider.value()->iconName().isEmpty()) {
308 return foundProvider.value()->iconName();
309 }
310
311 if (d->wasModified) {
312 d->iconName = KUriFilterDataPrivate::lookupIconNameFor(url: d->url, type: d->uriType);
313 d->wasModified = false;
314 }
315
316 return d->iconName;
317}
318
319void KUriFilterData::setData(const QUrl &url)
320{
321 d->setData(u: url, typedUrl: url.toString());
322}
323
324void KUriFilterData::setData(const QString &url)
325{
326 d->setData(u: QUrl(url), typedUrl: url);
327}
328
329bool KUriFilterData::setAbsolutePath(const QString &absPath)
330{
331 // Since a malformed URL could possibly be a relative
332 // URL we tag it as a possible local resource...
333 if ((d->url.scheme().isEmpty() || d->url.isLocalFile())) {
334 d->absPath = absPath;
335 return true;
336 }
337 return false;
338}
339
340void KUriFilterData::setCheckForExecutables(bool check)
341{
342 d->checkForExecs = check;
343}
344
345void KUriFilterData::setAlternateSearchProviders(const QStringList &providers)
346{
347 d->alternateSearchProviders = providers;
348}
349
350void KUriFilterData::setAlternateDefaultSearchProvider(const QString &provider)
351{
352 d->alternateDefaultSearchProvider = provider;
353}
354
355void KUriFilterData::setDefaultUrlScheme(const QString &scheme)
356{
357 d->defaultUrlScheme = scheme;
358}
359
360void KUriFilterData::setSearchFilteringOptions(SearchFilterOptions options)
361{
362 d->searchFilterOptions = options;
363}
364
365KUriFilterData &KUriFilterData::operator=(const QUrl &url)
366{
367 d->setData(u: url, typedUrl: url.toString());
368 return *this;
369}
370
371KUriFilterData &KUriFilterData::operator=(const QString &url)
372{
373 d->setData(u: QUrl(url), typedUrl: url);
374 return *this;
375}
376
377/******************************* KUriFilter ******************************/
378
379class KUriFilterPrivate
380{
381public:
382 KUriFilterPrivate()
383 {
384 }
385 ~KUriFilterPrivate()
386 {
387 qDeleteAll(c: pluginList);
388 pluginList.clear();
389 }
390 QList<KUriFilterPlugin *> pluginList;
391};
392
393class KUriFilterSingleton
394{
395public:
396 KUriFilter instance;
397};
398
399Q_GLOBAL_STATIC(KUriFilterSingleton, m_self)
400
401KUriFilter *KUriFilter::self()
402{
403 return &m_self()->instance;
404}
405
406KUriFilter::KUriFilter()
407 : d(new KUriFilterPrivate())
408{
409 QList<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("kf6/urifilters"));
410 const QString prefKey = QStringLiteral("X-KDE-InitialPreference");
411 // Sort the plugins by order of priority
412 std::sort(first: plugins.begin(), last: plugins.end(), comp: [prefKey](const KPluginMetaData &a, const KPluginMetaData &b) {
413 return a.value(key: prefKey, defaultValue: 0) > b.value(key: prefKey, defaultValue: 0);
414 });
415
416 for (const KPluginMetaData &pluginMetaData : std::as_const(t&: plugins)) {
417 if (auto plugin = KPluginFactory::instantiatePlugin<KUriFilterPlugin>(data: pluginMetaData).plugin) {
418 d->pluginList << plugin;
419 }
420 }
421}
422
423KUriFilter::~KUriFilter() = default;
424
425bool KUriFilter::filterUri(KUriFilterData &data, const QStringList &filters)
426{
427 bool filtered = false;
428
429 for (KUriFilterPlugin *plugin : std::as_const(t&: d->pluginList)) {
430 // If no specific filters were requested, iterate through all the plugins.
431 // Otherwise, only use available filters.
432 if (filters.isEmpty() || filters.contains(str: plugin->objectName())) {
433 if (plugin->filterUri(data)) {
434 filtered = true;
435 }
436 }
437 }
438
439 return filtered;
440}
441
442bool KUriFilter::filterUri(QUrl &uri, const QStringList &filters)
443{
444 KUriFilterData data(uri);
445 bool filtered = filterUri(data, filters);
446 if (filtered) {
447 uri = data.uri();
448 }
449 return filtered;
450}
451
452bool KUriFilter::filterUri(QString &uri, const QStringList &filters)
453{
454 KUriFilterData data(uri);
455 bool filtered = filterUri(data, filters);
456 if (filtered) {
457 uri = data.uri().toString();
458 }
459 return filtered;
460}
461
462QUrl KUriFilter::filteredUri(const QUrl &uri, const QStringList &filters)
463{
464 KUriFilterData data(uri);
465 filterUri(data, filters);
466 return data.uri();
467}
468
469QString KUriFilter::filteredUri(const QString &uri, const QStringList &filters)
470{
471 KUriFilterData data(uri);
472 filterUri(data, filters);
473 return data.uri().toString();
474}
475
476bool KUriFilter::filterSearchUri(KUriFilterData &data, SearchFilterTypes types)
477{
478 QStringList filters;
479
480 if (types & WebShortcutFilter) {
481 filters << QStringLiteral("kurisearchfilter");
482 }
483
484 if (types & NormalTextFilter) {
485 filters << QStringLiteral("kuriikwsfilter");
486 }
487
488 return filterUri(data, filters);
489}
490
491QStringList KUriFilter::pluginNames() const
492{
493 QStringList res;
494 res.reserve(asize: d->pluginList.size());
495 std::transform(first: d->pluginList.constBegin(), last: d->pluginList.constEnd(), result: std::back_inserter(x&: res), unary_op: [](const KUriFilterPlugin *plugin) {
496 return plugin->objectName();
497 });
498 return res;
499}
500

source code of kio/src/gui/kurifilter.cpp