File indexing completed on 2025-04-20 12:24:45
0001 // -*- c++ -*- 0002 /* 0003 This file is part of the KDE libraries 0004 SPDX-FileCopyrightText: 2001 Waldo Bastian <bastian@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-only 0007 */ 0008 0009 #include "workerconfig.h" 0010 0011 #include <QHash> 0012 #include <QThreadStorage> 0013 0014 #include <KConfig> 0015 #include <KSharedConfig> 0016 #include <kprotocolinfo.h> 0017 #include <kprotocolmanager.h> 0018 0019 using namespace KIO; 0020 0021 namespace KIO 0022 { 0023 class WorkerConfigProtocol 0024 { 0025 public: 0026 WorkerConfigProtocol() = default; 0027 ~WorkerConfigProtocol() 0028 { 0029 delete configFile; 0030 } 0031 0032 WorkerConfigProtocol(const WorkerConfigProtocol &) = delete; 0033 WorkerConfigProtocol &operator=(const WorkerConfigProtocol &) = delete; 0034 0035 public: 0036 MetaData global; 0037 QHash<QString, MetaData> host; 0038 KConfig *configFile; 0039 }; 0040 0041 static void readConfig(KConfig *config, const QString &group, MetaData *metaData) 0042 { 0043 *metaData += config->entryMap(group); 0044 } 0045 0046 class WorkerConfigPrivate 0047 { 0048 public: 0049 void readGlobalConfig(); 0050 WorkerConfigProtocol *readProtocolConfig(const QString &_protocol); 0051 WorkerConfigProtocol *findProtocolConfig(const QString &_protocol); 0052 void readConfigProtocolHost(const QString &_protocol, WorkerConfigProtocol *scp, const QString &host); 0053 0054 public: 0055 MetaData global; 0056 QHash<QString, WorkerConfigProtocol *> protocol; 0057 }; 0058 0059 void WorkerConfigPrivate::readGlobalConfig() 0060 { 0061 global.clear(); 0062 // Read stuff... 0063 readConfig(KSharedConfig::openConfig().data(), QStringLiteral("Socks"), &global); // Socks settings. 0064 global += KProtocolManager::entryMap(QStringLiteral("<default>")); 0065 } 0066 0067 WorkerConfigProtocol *WorkerConfigPrivate::readProtocolConfig(const QString &_protocol) 0068 { 0069 WorkerConfigProtocol *scp = protocol.value(_protocol, nullptr); 0070 if (!scp) { 0071 QString filename = KProtocolInfo::config(_protocol); 0072 scp = new WorkerConfigProtocol; 0073 scp->configFile = new KConfig(filename, KConfig::NoGlobals); 0074 protocol.insert(_protocol, scp); 0075 } 0076 // Read global stuff... 0077 readConfig(scp->configFile, QStringLiteral("<default>"), &(scp->global)); 0078 return scp; 0079 } 0080 0081 WorkerConfigProtocol *WorkerConfigPrivate::findProtocolConfig(const QString &_protocol) 0082 { 0083 WorkerConfigProtocol *scp = protocol.value(_protocol, nullptr); 0084 if (!scp) { 0085 scp = readProtocolConfig(_protocol); 0086 } 0087 return scp; 0088 } 0089 0090 void WorkerConfigPrivate::readConfigProtocolHost(const QString &, WorkerConfigProtocol *scp, const QString &host) 0091 { 0092 MetaData metaData; 0093 scp->host.insert(host, metaData); 0094 0095 // Read stuff 0096 // Break host into domains 0097 QString domain = host; 0098 0099 if (!domain.contains(QLatin1Char('.'))) { 0100 // Host without domain. 0101 if (scp->configFile->hasGroup("<local>")) { 0102 readConfig(scp->configFile, QStringLiteral("<local>"), &metaData); 0103 scp->host.insert(host, metaData); 0104 } 0105 } 0106 0107 int pos = 0; 0108 do { 0109 pos = host.lastIndexOf(QLatin1Char('.'), pos - 1); 0110 0111 if (pos < 0) { 0112 domain = host; 0113 } else { 0114 domain = host.mid(pos + 1); 0115 } 0116 0117 if (scp->configFile->hasGroup(domain)) { 0118 readConfig(scp->configFile, domain.toLower(), &metaData); 0119 scp->host.insert(host, metaData); 0120 } 0121 } while (pos > 0); 0122 } 0123 0124 class WorkerConfigSingleton 0125 { 0126 public: 0127 WorkerConfig instance; 0128 }; 0129 0130 template<typename T> 0131 T *perThreadGlobalStatic() 0132 { 0133 static QThreadStorage<T *> s_storage; 0134 if (!s_storage.hasLocalData()) { 0135 s_storage.setLocalData(new T); 0136 } 0137 return s_storage.localData(); 0138 } 0139 // Q_GLOBAL_STATIC(WorkerConfigSingleton, _self) 0140 // TODO: export symbol here, or make compile unit local by "static"? 0141 WorkerConfigSingleton *_workerConfigSelf() 0142 { 0143 return perThreadGlobalStatic<WorkerConfigSingleton>(); 0144 } 0145 0146 WorkerConfig *WorkerConfig::self() 0147 { 0148 return &_workerConfigSelf()->instance; 0149 } 0150 0151 WorkerConfig::WorkerConfig() 0152 : d(new WorkerConfigPrivate) 0153 { 0154 d->readGlobalConfig(); 0155 } 0156 0157 WorkerConfig::~WorkerConfig() 0158 { 0159 qDeleteAll(d->protocol); 0160 } 0161 0162 void WorkerConfig::setConfigData(const QString &protocol, const QString &host, const QString &key, const QString &value) 0163 { 0164 MetaData config; 0165 config.insert(key, value); 0166 setConfigData(protocol, host, config); 0167 } 0168 0169 void WorkerConfig::setConfigData(const QString &protocol, const QString &host, const MetaData &config) 0170 { 0171 if (protocol.isEmpty()) { 0172 d->global += config; 0173 } else { 0174 WorkerConfigProtocol *scp = d->findProtocolConfig(protocol); 0175 if (host.isEmpty()) { 0176 scp->global += config; 0177 } else { 0178 if (!scp->host.contains(host)) { 0179 d->readConfigProtocolHost(protocol, scp, host); 0180 } 0181 0182 MetaData hostConfig = scp->host.value(host); 0183 hostConfig += config; 0184 scp->host.insert(host, hostConfig); 0185 } 0186 } 0187 } 0188 0189 MetaData WorkerConfig::configData(const QString &protocol, const QString &host) 0190 { 0191 MetaData config = d->global; 0192 WorkerConfigProtocol *scp = d->findProtocolConfig(protocol); 0193 config += scp->global; 0194 if (host.isEmpty()) { 0195 return config; 0196 } 0197 0198 if (!scp->host.contains(host)) { 0199 d->readConfigProtocolHost(protocol, scp, host); 0200 Q_EMIT configNeeded(protocol, host); 0201 } 0202 MetaData hostConfig = scp->host.value(host); 0203 config += hostConfig; 0204 0205 return config; 0206 } 0207 0208 QString WorkerConfig::configData(const QString &protocol, const QString &host, const QString &key) 0209 { 0210 return configData(protocol, host).value(key); 0211 } 0212 0213 void WorkerConfig::reset() 0214 { 0215 qDeleteAll(d->protocol); 0216 d->protocol.clear(); 0217 d->readGlobalConfig(); 0218 } 0219 0220 } 0221 0222 #include "moc_workerconfig.cpp"