File indexing completed on 2025-01-12 03:39:38
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2000 Yves Arrouye <yves@realnames.com> 0004 SPDX-FileCopyrightText: 2000, 2010 Dawit Alemayehu <adawit at kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #include "kurifilter.h" 0010 #include "kurifilterdata_p.h" 0011 0012 #include "hostinfo.h" 0013 0014 #include <KService> 0015 #include <kio/global.h> 0016 0017 #include <KPluginFactory> 0018 #include <KPluginMetaData> 0019 0020 #include <QHashIterator> 0021 #include <QHostAddress> 0022 #include <QHostInfo> 0023 #include <QIcon> 0024 0025 #include "kurifilterplugin_p.h" 0026 0027 QString KUriFilterDataPrivate::lookupIconNameFor(const QUrl &url, KUriFilterData::UriTypes type) 0028 { 0029 QString iconName; 0030 0031 switch (type) { 0032 case KUriFilterData::NetProtocol: 0033 iconName = KIO::iconNameForUrl(url); 0034 break; 0035 case KUriFilterData::Executable: { 0036 QString exeName = url.path(); 0037 exeName.remove(0, exeName.lastIndexOf(QLatin1Char('/')) + 1); // strip path if given 0038 KService::Ptr service = KService::serviceByDesktopName(exeName); 0039 if (service && service->icon() != QLatin1String("unknown")) { 0040 iconName = service->icon(); 0041 } 0042 // Try to find an icon with the same name as the binary (useful for non-kde apps) 0043 else if (!QIcon::fromTheme(exeName).isNull()) { 0044 iconName = exeName; 0045 } else { 0046 // not found, use default 0047 iconName = QStringLiteral("system-run"); 0048 } 0049 break; 0050 } 0051 case KUriFilterData::Help: { 0052 iconName = QStringLiteral("khelpcenter"); 0053 break; 0054 } 0055 case KUriFilterData::Shell: { 0056 iconName = QStringLiteral("konsole"); 0057 break; 0058 } 0059 case KUriFilterData::Error: 0060 case KUriFilterData::Blocked: { 0061 iconName = QStringLiteral("error"); 0062 break; 0063 } 0064 default: 0065 break; 0066 } 0067 0068 return iconName; 0069 } 0070 0071 class Q_DECL_HIDDEN KUriFilterSearchProvider::KUriFilterSearchProviderPrivate 0072 { 0073 public: 0074 KUriFilterSearchProviderPrivate() 0075 { 0076 } 0077 KUriFilterSearchProviderPrivate(const KUriFilterSearchProviderPrivate &other) 0078 : desktopEntryName(other.desktopEntryName) 0079 , iconName(other.iconName) 0080 , name(other.name) 0081 , keys(other.keys) 0082 { 0083 } 0084 0085 QString desktopEntryName; 0086 QString iconName; 0087 QString name; 0088 QStringList keys; 0089 }; 0090 0091 KUriFilterSearchProvider::KUriFilterSearchProvider() 0092 : d(new KUriFilterSearchProvider::KUriFilterSearchProviderPrivate) 0093 { 0094 } 0095 0096 KUriFilterSearchProvider::KUriFilterSearchProvider(const KUriFilterSearchProvider &other) 0097 : d(new KUriFilterSearchProvider::KUriFilterSearchProviderPrivate(*(other.d))) 0098 { 0099 } 0100 0101 KUriFilterSearchProvider::~KUriFilterSearchProvider() = default; 0102 0103 QString KUriFilterSearchProvider::desktopEntryName() const 0104 { 0105 return d->desktopEntryName; 0106 } 0107 0108 QString KUriFilterSearchProvider::iconName() const 0109 { 0110 return d->iconName; 0111 } 0112 0113 QString KUriFilterSearchProvider::name() const 0114 { 0115 return d->name; 0116 } 0117 0118 QStringList KUriFilterSearchProvider::keys() const 0119 { 0120 return d->keys; 0121 } 0122 0123 QString KUriFilterSearchProvider::defaultKey() const 0124 { 0125 if (d->keys.isEmpty()) { 0126 return QString(); 0127 } 0128 0129 return d->keys.first(); 0130 } 0131 0132 KUriFilterSearchProvider &KUriFilterSearchProvider::operator=(const KUriFilterSearchProvider &other) 0133 { 0134 d->desktopEntryName = other.d->desktopEntryName; 0135 d->iconName = other.d->iconName; 0136 d->keys = other.d->keys; 0137 d->name = other.d->name; 0138 return *this; 0139 } 0140 0141 void KUriFilterSearchProvider::setDesktopEntryName(const QString &desktopEntryName) 0142 { 0143 d->desktopEntryName = desktopEntryName; 0144 } 0145 0146 void KUriFilterSearchProvider::setIconName(const QString &iconName) 0147 { 0148 d->iconName = iconName; 0149 } 0150 0151 void KUriFilterSearchProvider::setName(const QString &name) 0152 { 0153 d->name = name; 0154 } 0155 0156 void KUriFilterSearchProvider::setKeys(const QStringList &keys) 0157 { 0158 d->keys = keys; 0159 } 0160 0161 KUriFilterData::KUriFilterData() 0162 : d(new KUriFilterDataPrivate(QUrl(), QString())) 0163 { 0164 } 0165 0166 KUriFilterData::KUriFilterData(const QUrl &url) 0167 : d(new KUriFilterDataPrivate(url, url.toString())) 0168 { 0169 } 0170 0171 KUriFilterData::KUriFilterData(const QString &url) 0172 : d(new KUriFilterDataPrivate(QUrl::fromUserInput(url), url)) 0173 { 0174 } 0175 0176 KUriFilterData::KUriFilterData(const KUriFilterData &other) 0177 : d(new KUriFilterDataPrivate(*other.d)) 0178 { 0179 } 0180 0181 KUriFilterData::~KUriFilterData() = default; 0182 0183 QUrl KUriFilterData::uri() const 0184 { 0185 return d->url; 0186 } 0187 0188 QString KUriFilterData::errorMsg() const 0189 { 0190 return d->errMsg; 0191 } 0192 0193 KUriFilterData::UriTypes KUriFilterData::uriType() const 0194 { 0195 return d->uriType; 0196 } 0197 0198 QString KUriFilterData::absolutePath() const 0199 { 0200 return d->absPath; 0201 } 0202 0203 bool KUriFilterData::hasAbsolutePath() const 0204 { 0205 return !d->absPath.isEmpty(); 0206 } 0207 0208 QString KUriFilterData::argsAndOptions() const 0209 { 0210 return d->args; 0211 } 0212 0213 bool KUriFilterData::hasArgsAndOptions() const 0214 { 0215 return !d->args.isEmpty(); 0216 } 0217 0218 bool KUriFilterData::checkForExecutables() const 0219 { 0220 return d->checkForExecs; 0221 } 0222 0223 QString KUriFilterData::typedString() const 0224 { 0225 return d->typedString; 0226 } 0227 0228 QString KUriFilterData::searchTerm() const 0229 { 0230 return d->searchTerm; 0231 } 0232 0233 QChar KUriFilterData::searchTermSeparator() const 0234 { 0235 return d->searchTermSeparator; 0236 } 0237 0238 QString KUriFilterData::searchProvider() const 0239 { 0240 return d->searchProvider; 0241 } 0242 0243 QStringList KUriFilterData::preferredSearchProviders() const 0244 { 0245 return d->searchProviderList; 0246 } 0247 0248 KUriFilterSearchProvider KUriFilterData::queryForSearchProvider(const QString &provider) const 0249 { 0250 const KUriFilterSearchProvider *searchProvider = d->searchProviderMap.value(provider); 0251 0252 if (searchProvider) { 0253 return *(searchProvider); 0254 } 0255 0256 return KUriFilterSearchProvider(); 0257 } 0258 0259 QString KUriFilterData::queryForPreferredSearchProvider(const QString &provider) const 0260 { 0261 const KUriFilterSearchProvider *searchProvider = d->searchProviderMap.value(provider); 0262 if (searchProvider) { 0263 return (searchProvider->defaultKey() % searchTermSeparator() % searchTerm()); 0264 } 0265 return QString(); 0266 } 0267 0268 QStringList KUriFilterData::allQueriesForSearchProvider(const QString &provider) const 0269 { 0270 const KUriFilterSearchProvider *searchProvider = d->searchProviderMap.value(provider); 0271 if (searchProvider) { 0272 return searchProvider->keys(); 0273 } 0274 return QStringList(); 0275 } 0276 0277 QString KUriFilterData::iconNameForPreferredSearchProvider(const QString &provider) const 0278 { 0279 const KUriFilterSearchProvider *searchProvider = d->searchProviderMap.value(provider); 0280 if (searchProvider) { 0281 return searchProvider->iconName(); 0282 } 0283 return QString(); 0284 } 0285 0286 QStringList KUriFilterData::alternateSearchProviders() const 0287 { 0288 return d->alternateSearchProviders; 0289 } 0290 0291 QString KUriFilterData::alternateDefaultSearchProvider() const 0292 { 0293 return d->alternateDefaultSearchProvider; 0294 } 0295 0296 QString KUriFilterData::defaultUrlScheme() const 0297 { 0298 return d->defaultUrlScheme; 0299 } 0300 0301 KUriFilterData::SearchFilterOptions KUriFilterData::searchFilteringOptions() const 0302 { 0303 return d->searchFilterOptions; 0304 } 0305 0306 QString KUriFilterData::iconName() 0307 { 0308 if (d->wasModified) { 0309 d->iconName = KUriFilterDataPrivate::lookupIconNameFor(d->url, d->uriType); 0310 d->wasModified = false; 0311 } 0312 0313 return d->iconName; 0314 } 0315 0316 void KUriFilterData::setData(const QUrl &url) 0317 { 0318 d->setData(url, url.toString()); 0319 } 0320 0321 void KUriFilterData::setData(const QString &url) 0322 { 0323 d->setData(QUrl(url), url); 0324 } 0325 0326 bool KUriFilterData::setAbsolutePath(const QString &absPath) 0327 { 0328 // Since a malformed URL could possibly be a relative 0329 // URL we tag it as a possible local resource... 0330 if ((d->url.scheme().isEmpty() || d->url.isLocalFile())) { 0331 d->absPath = absPath; 0332 return true; 0333 } 0334 return false; 0335 } 0336 0337 void KUriFilterData::setCheckForExecutables(bool check) 0338 { 0339 d->checkForExecs = check; 0340 } 0341 0342 void KUriFilterData::setAlternateSearchProviders(const QStringList &providers) 0343 { 0344 d->alternateSearchProviders = providers; 0345 } 0346 0347 void KUriFilterData::setAlternateDefaultSearchProvider(const QString &provider) 0348 { 0349 d->alternateDefaultSearchProvider = provider; 0350 } 0351 0352 void KUriFilterData::setDefaultUrlScheme(const QString &scheme) 0353 { 0354 d->defaultUrlScheme = scheme; 0355 } 0356 0357 void KUriFilterData::setSearchFilteringOptions(SearchFilterOptions options) 0358 { 0359 d->searchFilterOptions = options; 0360 } 0361 0362 KUriFilterData &KUriFilterData::operator=(const QUrl &url) 0363 { 0364 d->setData(url, url.toString()); 0365 return *this; 0366 } 0367 0368 KUriFilterData &KUriFilterData::operator=(const QString &url) 0369 { 0370 d->setData(QUrl(url), url); 0371 return *this; 0372 } 0373 0374 /******************************* KUriFilter ******************************/ 0375 0376 class KUriFilterPrivate 0377 { 0378 public: 0379 KUriFilterPrivate() 0380 { 0381 } 0382 ~KUriFilterPrivate() 0383 { 0384 qDeleteAll(pluginList); 0385 pluginList.clear(); 0386 } 0387 QList<KUriFilterPlugin *> pluginList; 0388 }; 0389 0390 class KUriFilterSingleton 0391 { 0392 public: 0393 KUriFilter instance; 0394 }; 0395 0396 Q_GLOBAL_STATIC(KUriFilterSingleton, m_self) 0397 0398 KUriFilter *KUriFilter::self() 0399 { 0400 return &m_self()->instance; 0401 } 0402 0403 KUriFilter::KUriFilter() 0404 : d(new KUriFilterPrivate()) 0405 { 0406 QList<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("kf6/urifilters")); 0407 const QString prefKey = QStringLiteral("X-KDE-InitialPreference"); 0408 // Sort the plugins by order of priority 0409 std::sort(plugins.begin(), plugins.end(), [prefKey](const KPluginMetaData &a, const KPluginMetaData &b) { 0410 return a.value(prefKey, 0) > b.value(prefKey, 0); 0411 }); 0412 0413 for (const KPluginMetaData &pluginMetaData : std::as_const(plugins)) { 0414 if (auto plugin = KPluginFactory::instantiatePlugin<KUriFilterPlugin>(pluginMetaData).plugin) { 0415 d->pluginList << plugin; 0416 } 0417 } 0418 } 0419 0420 KUriFilter::~KUriFilter() = default; 0421 0422 bool KUriFilter::filterUri(KUriFilterData &data, const QStringList &filters) 0423 { 0424 bool filtered = false; 0425 0426 for (KUriFilterPlugin *plugin : std::as_const(d->pluginList)) { 0427 // If no specific filters were requested, iterate through all the plugins. 0428 // Otherwise, only use available filters. 0429 if (filters.isEmpty() || filters.contains(plugin->objectName())) { 0430 if (plugin->filterUri(data)) { 0431 filtered = true; 0432 } 0433 } 0434 } 0435 0436 return filtered; 0437 } 0438 0439 bool KUriFilter::filterUri(QUrl &uri, const QStringList &filters) 0440 { 0441 KUriFilterData data(uri); 0442 bool filtered = filterUri(data, filters); 0443 if (filtered) { 0444 uri = data.uri(); 0445 } 0446 return filtered; 0447 } 0448 0449 bool KUriFilter::filterUri(QString &uri, const QStringList &filters) 0450 { 0451 KUriFilterData data(uri); 0452 bool filtered = filterUri(data, filters); 0453 if (filtered) { 0454 uri = data.uri().toString(); 0455 } 0456 return filtered; 0457 } 0458 0459 QUrl KUriFilter::filteredUri(const QUrl &uri, const QStringList &filters) 0460 { 0461 KUriFilterData data(uri); 0462 filterUri(data, filters); 0463 return data.uri(); 0464 } 0465 0466 QString KUriFilter::filteredUri(const QString &uri, const QStringList &filters) 0467 { 0468 KUriFilterData data(uri); 0469 filterUri(data, filters); 0470 return data.uri().toString(); 0471 } 0472 0473 bool KUriFilter::filterSearchUri(KUriFilterData &data, SearchFilterTypes types) 0474 { 0475 QStringList filters; 0476 0477 if (types & WebShortcutFilter) { 0478 filters << QStringLiteral("kurisearchfilter"); 0479 } 0480 0481 if (types & NormalTextFilter) { 0482 filters << QStringLiteral("kuriikwsfilter"); 0483 } 0484 0485 return filterUri(data, filters); 0486 } 0487 0488 QStringList KUriFilter::pluginNames() const 0489 { 0490 QStringList res; 0491 res.reserve(d->pluginList.size()); 0492 std::transform(d->pluginList.constBegin(), d->pluginList.constEnd(), std::back_inserter(res), [](const KUriFilterPlugin *plugin) { 0493 return plugin->objectName(); 0494 }); 0495 return res; 0496 }