File indexing completed on 2024-04-28 08:54:23
0001 /* 0002 This class handles the homes shares 0003 0004 SPDX-FileCopyrightText: 2006-2023 Alexander Reinholdt <alexander.reinholdt@kdemail.net> 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 // application specific includes 0009 #include "smb4khomesshareshandler.h" 0010 #include "smb4knotification.h" 0011 #include "smb4kprofilemanager.h" 0012 #include "smb4ksettings.h" 0013 #include "smb4kshare.h" 0014 0015 // Qt includes 0016 #include <QFile> 0017 #include <QXmlStreamReader> 0018 #include <QXmlStreamWriter> 0019 0020 // KDE includes 0021 #include <KLocalizedString> 0022 0023 class Smb4KHomesUsers 0024 { 0025 public: 0026 Smb4KHomesUsers(const SharePtr &share, const QStringList &users) 0027 { 0028 m_workgroupName = share->workgroupName(); 0029 m_url = share->url(); 0030 m_userList = users; 0031 } 0032 0033 Smb4KHomesUsers(const Smb4KHomesUsers &users) 0034 { 0035 m_workgroupName = users.workgroupName(); 0036 m_url = users.url(); 0037 m_userList = users.userList(); 0038 m_profile = users.profile(); 0039 } 0040 0041 Smb4KHomesUsers() 0042 { 0043 } 0044 0045 ~Smb4KHomesUsers() 0046 { 0047 } 0048 0049 QString workgroupName() const 0050 { 0051 return m_workgroupName; 0052 } 0053 0054 void setWorkgroupName(const QString &workgroupName) 0055 { 0056 m_workgroupName = workgroupName; 0057 } 0058 0059 QUrl url() const 0060 { 0061 return m_url; 0062 } 0063 0064 void setUrl(const QUrl &url) 0065 { 0066 m_url = url; 0067 } 0068 0069 QStringList userList() const 0070 { 0071 return m_userList; 0072 } 0073 0074 void setUserList(const QStringList &userList) 0075 { 0076 m_userList = userList; 0077 } 0078 0079 QString profile() const 0080 { 0081 return m_profile; 0082 } 0083 0084 void setProfile(const QString &profile) 0085 { 0086 m_profile = profile; 0087 } 0088 0089 private: 0090 QString m_workgroupName; 0091 QUrl m_url; 0092 QStringList m_userList; 0093 QString m_profile; 0094 }; 0095 0096 class Smb4KHomesSharesHandlerPrivate 0097 { 0098 public: 0099 QList<Smb4KHomesUsers *> homesUsers; 0100 }; 0101 0102 class Smb4KHomesSharesHandlerStatic 0103 { 0104 public: 0105 Smb4KHomesSharesHandler instance; 0106 }; 0107 0108 Q_GLOBAL_STATIC(Smb4KHomesSharesHandlerStatic, p); 0109 0110 Smb4KHomesSharesHandler::Smb4KHomesSharesHandler(QObject *parent) 0111 : QObject(parent) 0112 , d(new Smb4KHomesSharesHandlerPrivate) 0113 { 0114 // First we need the directory. 0115 QString path = dataLocation(); 0116 0117 QDir dir; 0118 0119 if (!dir.exists(path)) { 0120 dir.mkpath(path); 0121 } 0122 0123 readUserNames(); 0124 } 0125 0126 Smb4KHomesSharesHandler::~Smb4KHomesSharesHandler() 0127 { 0128 while (!d->homesUsers.isEmpty()) { 0129 delete d->homesUsers.takeFirst(); 0130 } 0131 } 0132 0133 Smb4KHomesSharesHandler *Smb4KHomesSharesHandler::self() 0134 { 0135 return &p->instance; 0136 } 0137 0138 QStringList Smb4KHomesSharesHandler::homesUsers(const SharePtr &share) 0139 { 0140 Q_ASSERT(share); 0141 0142 QStringList userList; 0143 0144 if (!d->homesUsers.isEmpty()) { 0145 for (const Smb4KHomesUsers *users : qAsConst(d->homesUsers)) { 0146 if (users->profile() == Smb4KSettings::activeProfile() 0147 && QString::compare(share->url().toString(QUrl::RemoveUserInfo | QUrl::RemovePort), 0148 users->url().toString(QUrl::RemoveUserInfo | QUrl::RemovePort)) 0149 == 0) { 0150 userList = users->userList(); 0151 break; 0152 } 0153 } 0154 } 0155 0156 return userList; 0157 } 0158 0159 void Smb4KHomesSharesHandler::addHomesUsers(const SharePtr &share, const QStringList &userList) 0160 { 0161 Q_ASSERT(share); 0162 0163 bool found = false; 0164 0165 if (!d->homesUsers.isEmpty()) { 0166 QMutableListIterator<Smb4KHomesUsers *> it(d->homesUsers); 0167 0168 while (it.hasNext()) { 0169 Smb4KHomesUsers *users = it.next(); 0170 0171 if (users->profile() == Smb4KSettings::activeProfile() 0172 && QString::compare(share->url().toString(QUrl::RemoveUserInfo | QUrl::RemovePort), 0173 users->url().toString(QUrl::RemoveUserInfo | QUrl::RemovePort)) 0174 == 0) { 0175 users->setUserList(userList); 0176 found = true; 0177 break; 0178 } 0179 } 0180 } 0181 0182 if (!found) { 0183 Smb4KHomesUsers *users = new Smb4KHomesUsers(share, userList); 0184 users->setProfile(Smb4KProfileManager::self()->activeProfile()); 0185 d->homesUsers << users; 0186 } 0187 0188 writeUserNames(); 0189 } 0190 0191 void Smb4KHomesSharesHandler::readUserNames() 0192 { 0193 // Locate the XML file. 0194 QFile xmlFile(dataLocation() + QDir::separator() + QStringLiteral("homes_shares.xml")); 0195 0196 if (xmlFile.open(QIODevice::ReadOnly | QIODevice::Text)) { 0197 QXmlStreamReader xmlReader(&xmlFile); 0198 0199 QString versionString; 0200 0201 while (!xmlReader.atEnd()) { 0202 xmlReader.readNext(); 0203 0204 if (xmlReader.isStartElement()) { 0205 if (xmlReader.name() == QStringLiteral("homes_shares") && xmlReader.attributes().value(QStringLiteral("version")) != QStringLiteral("1.0") 0206 && xmlReader.attributes().value(QStringLiteral("version")) != QStringLiteral("2.0")) { 0207 xmlReader.raiseError(i18n("The format of %1 is not supported.", xmlFile.fileName())); 0208 break; 0209 } else { 0210 // NOTE: Forbackward compatibility. Remove with version >> 4.0 0211 if (xmlReader.name() == QStringLiteral("homes_shares")) { 0212 versionString = xmlReader.attributes().value(QStringLiteral("version")).toString(); 0213 } 0214 0215 if (versionString == QStringLiteral("1.0")) { 0216 if (xmlReader.name() == QStringLiteral("homes")) { 0217 QString profile = xmlReader.attributes().value(QStringLiteral("profile")).toString(); 0218 0219 Smb4KHomesUsers *users = new Smb4KHomesUsers(); 0220 users->setProfile(profile); 0221 0222 QUrl url; 0223 url.setScheme(QStringLiteral("smb")); 0224 url.setPath(xmlReader.name().toString()); 0225 0226 while (!(xmlReader.isEndElement() && xmlReader.name() == QStringLiteral("homes"))) { 0227 xmlReader.readNext(); 0228 0229 if (xmlReader.isStartElement()) { 0230 if (xmlReader.name() == QStringLiteral("host")) { 0231 url.setHost(xmlReader.readElementText()); 0232 } else if (xmlReader.name() == QStringLiteral("workgroup")) { 0233 users->setWorkgroupName(xmlReader.readElementText()); 0234 } else if (xmlReader.name() == QStringLiteral("users")) { 0235 QStringList u; 0236 0237 while (!(xmlReader.isEndElement() && xmlReader.name() == QStringLiteral("users"))) { 0238 xmlReader.readNext(); 0239 0240 if (xmlReader.isStartElement() && xmlReader.name() == QStringLiteral("user")) { 0241 u << xmlReader.readElementText(); 0242 } 0243 } 0244 0245 users->setUserList(u); 0246 } 0247 } 0248 } 0249 0250 users->setUrl(url); 0251 0252 d->homesUsers << users; 0253 } 0254 } else if (versionString == QStringLiteral("2.0")) { 0255 if (xmlReader.name() == QStringLiteral("homes_share")) { 0256 QUrl url(xmlReader.attributes().value(QStringLiteral("url")).toString()); 0257 QString profile = xmlReader.attributes().value(QStringLiteral("profile")).toString(); 0258 0259 Smb4KHomesUsers *users = new Smb4KHomesUsers(); 0260 users->setProfile(profile); 0261 users->setUrl(url); 0262 0263 while (!(xmlReader.isEndElement() && xmlReader.name() == QStringLiteral("homes_share"))) { 0264 xmlReader.readNext(); 0265 0266 if (xmlReader.isStartElement()) { 0267 if (xmlReader.name() == QStringLiteral("workgroup")) { 0268 users->setWorkgroupName(xmlReader.readElementText()); 0269 } else if (xmlReader.name() == QStringLiteral("users")) { 0270 QStringList u; 0271 0272 while (!(xmlReader.isEndElement() && xmlReader.name() == QStringLiteral("users"))) { 0273 xmlReader.readNext(); 0274 0275 if (xmlReader.isStartElement() && xmlReader.name() == QStringLiteral("user")) { 0276 u << xmlReader.readElementText(); 0277 } 0278 } 0279 0280 users->setUserList(u); 0281 } 0282 } 0283 } 0284 0285 d->homesUsers << users; 0286 } 0287 } 0288 } 0289 } 0290 } 0291 0292 xmlFile.close(); 0293 0294 if (xmlReader.hasError()) { 0295 Smb4KNotification::readingFileFailed(xmlFile, xmlReader.errorString()); 0296 } 0297 } else { 0298 if (xmlFile.exists()) { 0299 Smb4KNotification::openingFileFailed(xmlFile); 0300 } 0301 } 0302 } 0303 0304 void Smb4KHomesSharesHandler::writeUserNames() 0305 { 0306 // FIXME: Use the workgroup at all? We really only need the URL. 0307 QFile xmlFile(dataLocation() + QDir::separator() + QStringLiteral("homes_shares.xml")); 0308 0309 if (!d->homesUsers.isEmpty()) { 0310 if (xmlFile.open(QIODevice::WriteOnly | QIODevice::Text)) { 0311 QXmlStreamWriter xmlWriter(&xmlFile); 0312 xmlWriter.setAutoFormatting(true); 0313 xmlWriter.writeStartDocument(); 0314 xmlWriter.writeStartElement(QStringLiteral("homes_shares")); 0315 xmlWriter.writeAttribute(QStringLiteral("version"), QStringLiteral("2.0")); 0316 0317 for (Smb4KHomesUsers *users : qAsConst(d->homesUsers)) { 0318 xmlWriter.writeStartElement(QStringLiteral("homes_share")); 0319 xmlWriter.writeAttribute(QStringLiteral("url"), users->url().toString(QUrl::RemoveUserInfo | QUrl::StripTrailingSlash)); 0320 xmlWriter.writeAttribute(QStringLiteral("profile"), users->profile()); 0321 xmlWriter.writeTextElement(QStringLiteral("workgroup"), users->workgroupName()); 0322 xmlWriter.writeStartElement(QStringLiteral("users")); 0323 0324 QStringList userList = users->userList(); 0325 0326 for (const QString &user : qAsConst(userList)) { 0327 xmlWriter.writeTextElement(QStringLiteral("user"), user); 0328 } 0329 0330 xmlWriter.writeEndElement(); 0331 xmlWriter.writeEndElement(); 0332 } 0333 0334 xmlWriter.writeEndDocument(); 0335 xmlFile.close(); 0336 } else { 0337 Smb4KNotification::openingFileFailed(xmlFile); 0338 } 0339 } else { 0340 xmlFile.remove(); 0341 } 0342 } 0343 0344 ///////////////////////////////////////////////////////////////////////////// 0345 // SLOT IMPLEMENTATIONS 0346 ///////////////////////////////////////////////////////////////////////////// 0347 0348 void Smb4KHomesSharesHandler::slotProfileRemoved(const QString &name) 0349 { 0350 QMutableListIterator<Smb4KHomesUsers *> it(d->homesUsers); 0351 0352 while (it.hasNext()) { 0353 Smb4KHomesUsers *user = it.next(); 0354 0355 if (name == user->profile()) { 0356 it.remove(); 0357 } 0358 } 0359 0360 writeUserNames(); 0361 } 0362 0363 void Smb4KHomesSharesHandler::slotProfileMigrated(const QString &oldName, const QString &newName) 0364 { 0365 for (int i = 0; i < d->homesUsers.size(); i++) { 0366 if (oldName == d->homesUsers.at(i)->profile()) { 0367 d->homesUsers[i]->setProfile(newName); 0368 } 0369 } 0370 0371 writeUserNames(); 0372 }