File indexing completed on 2024-04-28 07:43:53
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 1999 Torben Weis <weis@kde.org> 0004 SPDX-FileCopyrightText: 2003 Waldo Bastian <bastian@kde.org> 0005 SPDX-FileCopyrightText: 2012 David Faure <faure@kde.org> 0006 SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org> 0007 0008 SPDX-License-Identifier: LGPL-2.0-only 0009 */ 0010 0011 #include "kprotocolinfo.h" 0012 #include "kprotocolinfo_p.h" 0013 #include "kprotocolinfofactory_p.h" 0014 0015 #include "kiocoredebug.h" 0016 0017 #include <KApplicationTrader> 0018 #include <KConfig> 0019 #include <KConfigGroup> 0020 #include <KJsonUtils> 0021 #include <KPluginMetaData> 0022 #include <KSharedConfig> 0023 #include <QUrl> 0024 0025 KProtocolInfoPrivate::KProtocolInfoPrivate(const QString &name, const QString &exec, const QJsonObject &json) 0026 : m_name(name) 0027 , m_exec(exec) 0028 { 0029 // source has fallback true if not set 0030 m_isSourceProtocol = json.value(QStringLiteral("source")).toBool(true); 0031 // true if not set for backwards compatibility 0032 m_supportsPermissions = json.value(QStringLiteral("permissions")).toBool(true); 0033 0034 // other bools are fine with default false by toBool 0035 m_isHelperProtocol = json.value(QStringLiteral("helper")).toBool(); 0036 m_supportsReading = json.value(QStringLiteral("reading")).toBool(); 0037 m_supportsWriting = json.value(QStringLiteral("writing")).toBool(); 0038 m_supportsMakeDir = json.value(QStringLiteral("makedir")).toBool(); 0039 m_supportsDeleting = json.value(QStringLiteral("deleting")).toBool(); 0040 m_supportsLinking = json.value(QStringLiteral("linking")).toBool(); 0041 m_supportsMoving = json.value(QStringLiteral("moving")).toBool(); 0042 m_supportsOpening = json.value(QStringLiteral("opening")).toBool(); 0043 m_supportsTruncating = json.value(QStringLiteral("truncating")).toBool(); 0044 m_canCopyFromFile = json.value(QStringLiteral("copyFromFile")).toBool(); 0045 m_canCopyToFile = json.value(QStringLiteral("copyToFile")).toBool(); 0046 m_canRenameFromFile = json.value(QStringLiteral("renameFromFile")).toBool(); 0047 m_canRenameToFile = json.value(QStringLiteral("renameToFile")).toBool(); 0048 m_canDeleteRecursive = json.value(QStringLiteral("deleteRecursive")).toBool(); 0049 0050 // default is "FromURL" 0051 const QString fnu = json.value(QStringLiteral("fileNameUsedForCopying")).toString(); 0052 m_fileNameUsedForCopying = KProtocolInfo::FromUrl; 0053 if (fnu == QLatin1String("Name")) { 0054 m_fileNameUsedForCopying = KProtocolInfo::Name; 0055 } else if (fnu == QLatin1String("DisplayName")) { 0056 m_fileNameUsedForCopying = KProtocolInfo::DisplayName; 0057 } 0058 0059 m_listing = json.value(QStringLiteral("listing")).toVariant().toStringList(); 0060 // Many .protocol files say "Listing=false" when they really mean "Listing=" (i.e. unsupported) 0061 if (m_listing.count() == 1 && m_listing.first() == QLatin1String("false")) { 0062 m_listing.clear(); 0063 } 0064 m_supportsListing = (m_listing.count() > 0); 0065 0066 m_defaultMimetype = json.value(QStringLiteral("defaultMimetype")).toString(); 0067 0068 // determineMimetypeFromExtension has fallback true if not set 0069 m_determineMimetypeFromExtension = json.value(QStringLiteral("determineMimetypeFromExtension")).toBool(true); 0070 0071 m_archiveMimeTypes = json.value(QStringLiteral("archiveMimetype")).toVariant().toStringList(); 0072 0073 m_icon = json.value(QStringLiteral("Icon")).toString(); 0074 0075 // config has fallback to name if not set 0076 m_config = json.value(QStringLiteral("config")).toString(m_name); 0077 0078 // max workers has fallback to 1 if not set 0079 m_maxWorkers = json.value(QStringLiteral("maxInstances")).toInt(1); 0080 0081 m_maxWorkersPerHost = json.value(QStringLiteral("maxInstancesPerHost")).toInt(); 0082 0083 QString tmp = json.value(QStringLiteral("input")).toString(); 0084 if (tmp == QLatin1String("filesystem")) { 0085 m_inputType = KProtocolInfo::T_FILESYSTEM; 0086 } else if (tmp == QLatin1String("stream")) { 0087 m_inputType = KProtocolInfo::T_STREAM; 0088 } else { 0089 m_inputType = KProtocolInfo::T_NONE; 0090 } 0091 0092 tmp = json.value(QStringLiteral("output")).toString(); 0093 if (tmp == QLatin1String("filesystem")) { 0094 m_outputType = KProtocolInfo::T_FILESYSTEM; 0095 } else if (tmp == QLatin1String("stream")) { 0096 m_outputType = KProtocolInfo::T_STREAM; 0097 } else { 0098 m_outputType = KProtocolInfo::T_NONE; 0099 } 0100 0101 m_docPath = json.value(QStringLiteral("X-DocPath")).toString(); 0102 if (m_docPath.isEmpty()) { 0103 m_docPath = json.value(QStringLiteral("DocPath")).toString(); 0104 } 0105 0106 m_protClass = json.value(QStringLiteral("Class")).toString().toLower(); 0107 if (!m_protClass.startsWith(QLatin1Char(':'))) { 0108 m_protClass.prepend(QLatin1Char(':')); 0109 } 0110 0111 // ExtraNames is a translated value, use the KCoreAddons helper to read it 0112 const QStringList extraNames = KJsonUtils::readTranslatedValue(json, QStringLiteral("ExtraNames")).toVariant().toStringList(); 0113 const QStringList extraTypes = json.value(QStringLiteral("ExtraTypes")).toVariant().toStringList(); 0114 if (extraNames.size() == extraTypes.size()) { 0115 auto func = [](const QString &name, const QString &type) { 0116 const int metaType = QMetaType::fromName(type.toLatin1().constData()).id(); 0117 // currently QMetaType::Type and ExtraField::Type use the same subset of values, so we can just cast. 0118 return KProtocolInfo::ExtraField(name, static_cast<KProtocolInfo::ExtraField::Type>(metaType)); 0119 }; 0120 0121 std::transform(extraNames.cbegin(), extraNames.cend(), extraTypes.cbegin(), std::back_inserter(m_extraFields), func); 0122 } else { 0123 qCWarning(KIO_CORE) << "Malformed JSON protocol file for protocol:" << name 0124 << ", number of the ExtraNames fields should match the number of ExtraTypes fields"; 0125 } 0126 0127 // fallback based on class 0128 m_showPreviews = json.value(QStringLiteral("ShowPreviews")).toBool(m_protClass == QLatin1String(":local")); 0129 0130 m_capabilities = json.value(QStringLiteral("Capabilities")).toVariant().toStringList(); 0131 0132 m_proxyProtocol = json.value(QStringLiteral("ProxiedBy")).toString(); 0133 } 0134 0135 // 0136 // Static functions: 0137 // 0138 0139 QStringList KProtocolInfo::protocols() 0140 { 0141 return KProtocolInfoFactory::self()->protocols(); 0142 } 0143 0144 bool KProtocolInfo::isFilterProtocol(const QString &_protocol) 0145 { 0146 // We call the findProtocol directly (not via KProtocolManager) to bypass any proxy settings. 0147 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol); 0148 if (!prot) { 0149 return false; 0150 } 0151 0152 return !prot->m_isSourceProtocol; 0153 } 0154 0155 QString KProtocolInfo::icon(const QString &_protocol) 0156 { 0157 // We call the findProtocol directly (not via KProtocolManager) to bypass any proxy settings. 0158 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol); 0159 if (!prot) { 0160 if (auto service = KApplicationTrader::preferredService(QLatin1String("x-scheme-handler/") + _protocol)) { 0161 return service->icon(); 0162 } else { 0163 return QString(); 0164 } 0165 } 0166 0167 return prot->m_icon; 0168 } 0169 0170 QString KProtocolInfo::config(const QString &_protocol) 0171 { 0172 // We call the findProtocol directly (not via KProtocolManager) to bypass any proxy settings. 0173 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol); 0174 if (!prot) { 0175 return QString(); 0176 } 0177 0178 return QStringLiteral("kio_%1rc").arg(prot->m_config); 0179 } 0180 0181 int KProtocolInfo::maxWorkers(const QString &_protocol) 0182 { 0183 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol); 0184 if (!prot) { 0185 return 1; 0186 } 0187 0188 return prot->m_maxWorkers; 0189 } 0190 0191 int KProtocolInfo::maxWorkersPerHost(const QString &_protocol) 0192 { 0193 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol); 0194 if (!prot) { 0195 return 0; 0196 } 0197 0198 return prot->m_maxWorkersPerHost; 0199 } 0200 0201 bool KProtocolInfo::determineMimetypeFromExtension(const QString &_protocol) 0202 { 0203 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol); 0204 if (!prot) { 0205 return true; 0206 } 0207 0208 return prot->m_determineMimetypeFromExtension; 0209 } 0210 0211 QString KProtocolInfo::exec(const QString &protocol) 0212 { 0213 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(protocol); 0214 if (!prot) { 0215 return QString(); 0216 } 0217 return prot->m_exec; 0218 } 0219 0220 KProtocolInfo::ExtraFieldList KProtocolInfo::extraFields(const QUrl &url) 0221 { 0222 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(url.scheme()); 0223 if (!prot) { 0224 return ExtraFieldList(); 0225 } 0226 0227 return prot->m_extraFields; 0228 } 0229 0230 QString KProtocolInfo::defaultMimetype(const QString &_protocol) 0231 { 0232 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol); 0233 if (!prot) { 0234 return QString(); 0235 } 0236 0237 return prot->m_defaultMimetype; 0238 } 0239 0240 QString KProtocolInfo::docPath(const QString &_protocol) 0241 { 0242 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol); 0243 if (!prot) { 0244 return QString(); 0245 } 0246 0247 return prot->m_docPath; 0248 } 0249 0250 QString KProtocolInfo::protocolClass(const QString &_protocol) 0251 { 0252 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol); 0253 if (!prot) { 0254 return QString(); 0255 } 0256 0257 return prot->m_protClass; 0258 } 0259 0260 bool KProtocolInfo::showFilePreview(const QString &_protocol) 0261 { 0262 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol); 0263 const bool defaultSetting = prot ? prot->m_showPreviews : false; 0264 0265 KConfigGroup group(KSharedConfig::openConfig(), QStringLiteral("PreviewSettings")); 0266 return group.readEntry(_protocol, defaultSetting); 0267 } 0268 0269 QStringList KProtocolInfo::capabilities(const QString &_protocol) 0270 { 0271 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol); 0272 if (!prot) { 0273 return QStringList(); 0274 } 0275 0276 return prot->m_capabilities; 0277 } 0278 0279 QStringList KProtocolInfo::archiveMimetypes(const QString &protocol) 0280 { 0281 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(protocol); 0282 if (!prot) { 0283 return QStringList(); 0284 } 0285 0286 return prot->m_archiveMimeTypes; 0287 } 0288 0289 QString KProtocolInfo::proxiedBy(const QString &_protocol) 0290 { 0291 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol); 0292 if (!prot) { 0293 return QString(); 0294 } 0295 0296 return prot->m_proxyProtocol; 0297 } 0298 0299 bool KProtocolInfo::isFilterProtocol(const QUrl &url) 0300 { 0301 return isFilterProtocol(url.scheme()); 0302 } 0303 0304 bool KProtocolInfo::isHelperProtocol(const QUrl &url) 0305 { 0306 return isHelperProtocol(url.scheme()); 0307 } 0308 0309 bool KProtocolInfo::isHelperProtocol(const QString &protocol) 0310 { 0311 // We call the findProtocol directly (not via KProtocolManager) to bypass any proxy settings. 0312 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(protocol); 0313 if (prot) { 0314 return prot->m_isHelperProtocol; 0315 } 0316 return false; 0317 } 0318 0319 bool KProtocolInfo::isKnownProtocol(const QUrl &url) 0320 { 0321 return isKnownProtocol(url.scheme()); 0322 } 0323 0324 bool KProtocolInfo::isKnownProtocol(const QString &protocol, bool updateCacheIfNotfound) 0325 { 0326 // We call the findProtocol (const QString&) to bypass any proxy settings. 0327 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(protocol, updateCacheIfNotfound); 0328 return prot; 0329 }