File indexing completed on 2024-04-21 15:42:43
0001 /*************************************************************************** 0002 This class handles the bookmarks. 0003 ------------------- 0004 begin : Fr Jan 9 2004 0005 copyright : (C) 2004-2019 by Alexander Reinholdt 0006 email : alexander.reinholdt@kdemail.net 0007 ***************************************************************************/ 0008 0009 /*************************************************************************** 0010 * This program is free software; you can redistribute it and/or modify * 0011 * it under the terms of the GNU General Public License as published by * 0012 * the Free Software Foundation; either version 2 of the License, or * 0013 * (at your option) any later version. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, but * 0016 * WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 0018 * General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program; if not, write to the * 0022 * Free Software Foundation, Inc., 51 Franklin Street, Suite 500, Boston,* 0023 * MA 02110-1335, USA * 0024 ***************************************************************************/ 0025 0026 #ifdef HAVE_CONFIG_H 0027 #include <config.h> 0028 #endif 0029 0030 // application specific includes 0031 #include "smb4kbookmarkhandler.h" 0032 #include "smb4kbookmarkhandler_p.h" 0033 #include "smb4khomesshareshandler.h" 0034 #include "smb4kglobal.h" 0035 #include "smb4kbookmark.h" 0036 #include "smb4khost.h" 0037 #include "smb4kshare.h" 0038 #include "smb4ksettings.h" 0039 #include "smb4knotification.h" 0040 #include "smb4kprofilemanager.h" 0041 0042 // Qt includes 0043 #include <QDir> 0044 #include <QFile> 0045 #include <QTextCodec> 0046 #include <QTextStream> 0047 #include <QXmlStreamWriter> 0048 #include <QXmlStreamReader> 0049 #include <QPointer> 0050 #include <QMutableListIterator> 0051 #include <QApplication> 0052 0053 // KDE includes 0054 #define TRANSLATION_DOMAIN "smb4k-core" 0055 #include <KI18n/KLocalizedString> 0056 0057 0058 using namespace Smb4KGlobal; 0059 0060 0061 Q_GLOBAL_STATIC(Smb4KBookmarkHandlerStatic, p); 0062 0063 0064 0065 Smb4KBookmarkHandler::Smb4KBookmarkHandler(QObject *parent) 0066 : QObject(parent), d(new Smb4KBookmarkHandlerPrivate) 0067 { 0068 // 0069 // First we need the directory. 0070 // 0071 QString path = dataLocation(); 0072 0073 QDir dir; 0074 0075 if (!dir.exists(path)) 0076 { 0077 dir.mkpath(path); 0078 } 0079 0080 // 0081 // Read the list of bookmarks 0082 // 0083 readBookmarkList(); 0084 0085 // 0086 // Init the bookmark editor 0087 // 0088 d->editor = 0; 0089 } 0090 0091 0092 Smb4KBookmarkHandler::~Smb4KBookmarkHandler() 0093 { 0094 while (!d->bookmarks.isEmpty()) 0095 { 0096 d->bookmarks.takeFirst().clear(); 0097 } 0098 } 0099 0100 0101 Smb4KBookmarkHandler *Smb4KBookmarkHandler::self() 0102 { 0103 return &p->instance; 0104 } 0105 0106 0107 void Smb4KBookmarkHandler::addBookmark(const SharePtr &share) 0108 { 0109 if (share) 0110 { 0111 QList<SharePtr> shares; 0112 shares << share; 0113 addBookmarks(shares); 0114 } 0115 } 0116 0117 0118 void Smb4KBookmarkHandler::addBookmarks(const QList<SharePtr> &list) 0119 { 0120 // 0121 // Prepare the list of bookmarks that should be added 0122 // 0123 QList<BookmarkPtr> newBookmarks; 0124 0125 for (const SharePtr &share : list) 0126 { 0127 // 0128 // Printer shares cannot be bookmarked 0129 // 0130 if (share->isPrinter()) 0131 { 0132 Smb4KNotification::cannotBookmarkPrinter(share); 0133 continue; 0134 } 0135 0136 // 0137 // Process homes shares 0138 // 0139 if (share->isHomesShare() && !Smb4KHomesSharesHandler::self()->specifyUser(share, true)) 0140 { 0141 continue; 0142 } 0143 0144 // 0145 // Check if the share has already been bookmarked and skip it if it 0146 // already exists 0147 // 0148 BookmarkPtr knownBookmark = findBookmarkByUrl(share->isHomesShare() ? share->homeUrl() : share->url()); 0149 0150 if (knownBookmark) 0151 { 0152 Smb4KNotification::bookmarkExists(knownBookmark.data()); 0153 continue; 0154 } 0155 0156 BookmarkPtr bookmark = BookmarkPtr(new Smb4KBookmark(share.data())); 0157 bookmark->setProfile(Smb4KProfileManager::self()->activeProfile()); 0158 newBookmarks << bookmark; 0159 } 0160 0161 // 0162 // Show the bookmark dialog, if necessary 0163 // 0164 if (!newBookmarks.isEmpty()) 0165 { 0166 QPointer<Smb4KBookmarkDialog> dlg = new Smb4KBookmarkDialog(newBookmarks, groupsList(), QApplication::activeWindow()); 0167 0168 if (dlg->exec() == QDialog::Accepted) 0169 { 0170 // The bookmark dialog uses an internal list of bookmarks, 0171 // so use that one instead of the temporary list created 0172 // above. 0173 addBookmarks(dlg->bookmarks(), false); 0174 } 0175 0176 delete dlg; 0177 } 0178 0179 // 0180 // Clear the temporary list of bookmarks 0181 // 0182 while (!newBookmarks.isEmpty()) 0183 { 0184 newBookmarks.takeFirst().clear(); 0185 } 0186 } 0187 0188 0189 void Smb4KBookmarkHandler::addBookmarks(const QList<BookmarkPtr> &list, bool replace) 0190 { 0191 // 0192 // Process the incoming list. 0193 // In case the internal list should be replaced, clear the internal 0194 // list first. 0195 // 0196 if (replace) 0197 { 0198 QMutableListIterator<BookmarkPtr> it(d->bookmarks); 0199 0200 while (it.hasNext()) 0201 { 0202 BookmarkPtr bookmark = it.next(); 0203 0204 if (Smb4KSettings::useProfiles() && bookmark->profile() != Smb4KProfileManager::self()->activeProfile()) 0205 { 0206 continue; 0207 } 0208 0209 it.remove(); 0210 } 0211 } 0212 0213 // 0214 // Copy all bookmarks that are not in the list 0215 // 0216 for (const BookmarkPtr &bookmark : list) 0217 { 0218 // 0219 // Check if the bookmark label is already in use 0220 // 0221 if (!bookmark->label().isEmpty() && findBookmarkByLabel(bookmark->label())) 0222 { 0223 Smb4KNotification::bookmarkLabelInUse(bookmark.data()); 0224 bookmark->setLabel(QString("%1 (1)").arg(bookmark->label())); 0225 } 0226 0227 // 0228 // Check if we have to add the bookmark 0229 // 0230 BookmarkPtr existingBookmark = findBookmarkByUrl(bookmark->url()); 0231 0232 if (!existingBookmark) 0233 { 0234 d->bookmarks << bookmark; 0235 } 0236 else 0237 { 0238 // We do not need to update the bookmark, because we are 0239 // operating on a shared pointer. 0240 } 0241 } 0242 0243 // 0244 // Save the bookmark list and emit the updated() signal 0245 // 0246 writeBookmarkList(); 0247 emit updated(); 0248 } 0249 0250 0251 void Smb4KBookmarkHandler::removeBookmark(const BookmarkPtr &bookmark) 0252 { 0253 if (bookmark) 0254 { 0255 for (int i = 0; i < d->bookmarks.size(); ++i) 0256 { 0257 if ((!Smb4KSettings::useProfiles() || Smb4KSettings::activeProfile() == d->bookmarks.at(i)->profile()) && 0258 QString::compare(d->bookmarks.at(i)->url().toString(QUrl::RemoveUserInfo|QUrl::RemovePort), 0259 bookmark->url().toString(QUrl::RemoveUserInfo|QUrl::RemovePort), 0260 Qt::CaseInsensitive) == 0 && 0261 QString::compare(bookmark->groupName(), d->bookmarks.at(i)->groupName(), Qt::CaseInsensitive) == 0) 0262 { 0263 d->bookmarks.takeAt(i).clear(); 0264 break; 0265 } 0266 } 0267 0268 // Write the list to the bookmarks file. 0269 writeBookmarkList(); 0270 emit updated(); 0271 } 0272 } 0273 0274 0275 void Smb4KBookmarkHandler::removeGroup(const QString& name) 0276 { 0277 QMutableListIterator<BookmarkPtr> it(d->bookmarks); 0278 0279 while (it.hasNext()) 0280 { 0281 const BookmarkPtr &b = it.next(); 0282 0283 if ((!Smb4KSettings::useProfiles() || Smb4KSettings::activeProfile() == b->profile()) || 0284 QString::compare(b->groupName(), name, Qt::CaseInsensitive) == 0) 0285 { 0286 it.remove(); 0287 } 0288 } 0289 0290 // Write the list to the bookmarks file. 0291 writeBookmarkList(); 0292 emit updated(); 0293 } 0294 0295 0296 void Smb4KBookmarkHandler::writeBookmarkList() 0297 { 0298 QFile xmlFile(dataLocation()+QDir::separator()+"bookmarks.xml"); 0299 0300 if (!d->bookmarks.isEmpty()) 0301 { 0302 if (xmlFile.open(QIODevice::WriteOnly|QIODevice::Text)) 0303 { 0304 QXmlStreamWriter xmlWriter(&xmlFile); 0305 xmlWriter.setAutoFormatting(true); 0306 xmlWriter.writeStartDocument(); 0307 xmlWriter.writeStartElement("bookmarks"); 0308 xmlWriter.writeAttribute("version", "2.0"); 0309 0310 for (const BookmarkPtr &bookmark : d->bookmarks) 0311 { 0312 if (!bookmark->url().isValid()) 0313 { 0314 Smb4KNotification::invalidURLPassed(); 0315 continue; 0316 } 0317 0318 xmlWriter.writeStartElement("bookmark"); 0319 xmlWriter.writeAttribute("profile", bookmark->profile()); 0320 xmlWriter.writeAttribute("group", bookmark->groupName()); 0321 0322 xmlWriter.writeTextElement("workgroup", bookmark->workgroupName()); 0323 xmlWriter.writeTextElement("url", bookmark->url().toString(QUrl::RemoveUserInfo|QUrl::RemovePort)); 0324 xmlWriter.writeTextElement("login", bookmark->login()); 0325 xmlWriter.writeTextElement("ip", bookmark->hostIpAddress()); 0326 xmlWriter.writeTextElement("label", bookmark->label()); 0327 0328 xmlWriter.writeEndElement(); 0329 } 0330 0331 xmlWriter.writeEndDocument(); 0332 0333 xmlFile.close(); 0334 } 0335 else 0336 { 0337 Smb4KNotification::openingFileFailed(xmlFile); 0338 } 0339 } 0340 else 0341 { 0342 xmlFile.remove(); 0343 } 0344 } 0345 0346 0347 void Smb4KBookmarkHandler::readBookmarkList() 0348 { 0349 // 0350 // Clear the list of bookmarks 0351 // 0352 while (!d->bookmarks.isEmpty()) 0353 { 0354 d->bookmarks.takeFirst().clear(); 0355 } 0356 0357 // 0358 // Locate the XML file and read the bookmarks 0359 // 0360 QFile xmlFile(dataLocation()+QDir::separator()+"bookmarks.xml"); 0361 0362 if (xmlFile.open(QIODevice::ReadOnly | QIODevice::Text)) 0363 { 0364 QXmlStreamReader xmlReader(&xmlFile); 0365 0366 while (!xmlReader.atEnd()) 0367 { 0368 xmlReader.readNext(); 0369 0370 if (xmlReader.isStartElement()) 0371 { 0372 if (xmlReader.name() == "bookmarks" && 0373 (xmlReader.attributes().value("version") != "1.1" && xmlReader.attributes().value("version") != "2.0")) 0374 { 0375 xmlReader.raiseError(i18n("The format of %1 is not supported.", xmlFile.fileName())); 0376 break; 0377 } 0378 else 0379 { 0380 if (xmlReader.name() == "bookmark") 0381 { 0382 QString profile = xmlReader.attributes().value("profile").toString(); 0383 0384 BookmarkPtr bookmark = BookmarkPtr(new Smb4KBookmark()); 0385 bookmark->setProfile(profile); 0386 bookmark->setGroupName(xmlReader.attributes().value("group").toString()); 0387 0388 while (!(xmlReader.isEndElement() && xmlReader.name() == "bookmark")) 0389 { 0390 xmlReader.readNext(); 0391 0392 if (xmlReader.isStartElement()) 0393 { 0394 if (xmlReader.name() == "workgroup") 0395 { 0396 bookmark->setWorkgroupName(xmlReader.readElementText()); 0397 } 0398 else if (xmlReader.name() == "unc") 0399 { 0400 bookmark->setUrl(xmlReader.readElementText()); 0401 } 0402 else if (xmlReader.name() == "url") 0403 { 0404 bookmark->setUrl(QUrl(xmlReader.readElementText())); 0405 } 0406 else if (xmlReader.name() == "login") 0407 { 0408 bookmark->setLogin(xmlReader.readElementText()); 0409 } 0410 else if (xmlReader.name() == "ip") 0411 { 0412 bookmark->setHostIpAddress(xmlReader.readElementText()); 0413 } 0414 else if (xmlReader.name() == "label") 0415 { 0416 bookmark->setLabel(xmlReader.readElementText()); 0417 } 0418 0419 continue; 0420 } 0421 else 0422 { 0423 continue; 0424 } 0425 } 0426 0427 d->bookmarks << bookmark; 0428 } 0429 else 0430 { 0431 continue; 0432 } 0433 } 0434 } 0435 else 0436 { 0437 continue; 0438 } 0439 } 0440 0441 xmlFile.close(); 0442 0443 if (xmlReader.hasError()) 0444 { 0445 Smb4KNotification::readingFileFailed(xmlFile, xmlReader.errorString()); 0446 } 0447 } 0448 else 0449 { 0450 if (xmlFile.exists()) 0451 { 0452 Smb4KNotification::openingFileFailed(xmlFile); 0453 } 0454 } 0455 0456 emit updated(); 0457 } 0458 0459 0460 BookmarkPtr Smb4KBookmarkHandler::findBookmarkByUrl(const QUrl &url) 0461 { 0462 // Update the bookmarks: 0463 update(); 0464 0465 // Find the bookmark: 0466 BookmarkPtr bookmark; 0467 0468 if (!url.isEmpty() && url.isValid() && !bookmarksList().isEmpty()) 0469 { 0470 for (const BookmarkPtr &b : bookmarksList()) 0471 { 0472 if (QString::compare(b->url().toString(QUrl::RemoveUserInfo|QUrl::RemovePort), 0473 url.toString(QUrl::RemoveUserInfo|QUrl::RemovePort), 0474 Qt::CaseInsensitive) == 0) 0475 { 0476 bookmark = b; 0477 break; 0478 } 0479 } 0480 } 0481 0482 return bookmark; 0483 } 0484 0485 0486 BookmarkPtr Smb4KBookmarkHandler::findBookmarkByLabel(const QString &label) 0487 { 0488 // Update the bookmarks: 0489 update(); 0490 0491 // Find the bookmark: 0492 BookmarkPtr bookmark; 0493 0494 for (const BookmarkPtr &b : bookmarksList()) 0495 { 0496 if (QString::compare(b->label().toUpper(), label.toUpper()) == 0) 0497 { 0498 bookmark = b; 0499 break; 0500 } 0501 else 0502 { 0503 continue; 0504 } 0505 } 0506 0507 return bookmark; 0508 } 0509 0510 0511 QList<BookmarkPtr> Smb4KBookmarkHandler::bookmarksList() const 0512 { 0513 // Update the bookmarks: 0514 update(); 0515 0516 // Get this list of the bookmarks 0517 if (Smb4KSettings::useProfiles()) 0518 { 0519 QList<BookmarkPtr> bookmarks; 0520 0521 for (const BookmarkPtr &b : d->bookmarks) 0522 { 0523 if (b->profile() == Smb4KSettings::activeProfile()) 0524 { 0525 bookmarks << b; 0526 } 0527 } 0528 0529 return bookmarks; 0530 } 0531 0532 // Return the list of bookmarks: 0533 return d->bookmarks; 0534 } 0535 0536 0537 QList<BookmarkPtr> Smb4KBookmarkHandler::bookmarksList(const QString &group) const 0538 { 0539 // Update bookmarks 0540 update(); 0541 0542 // Get the list of bookmarks organized in the given group 0543 QList<BookmarkPtr> bookmarks; 0544 0545 for (const BookmarkPtr &bookmark : bookmarksList()) 0546 { 0547 if (QString::compare(group, bookmark->groupName(), Qt::CaseInsensitive) == 0) 0548 { 0549 bookmarks << bookmark; 0550 } 0551 } 0552 0553 return bookmarks; 0554 } 0555 0556 0557 QStringList Smb4KBookmarkHandler::groupsList() const 0558 { 0559 QStringList groups; 0560 0561 for (const BookmarkPtr &b : bookmarksList()) 0562 { 0563 if (!groups.contains(b->groupName())) 0564 { 0565 groups << b->groupName(); 0566 } 0567 } 0568 0569 return groups; 0570 } 0571 0572 0573 void Smb4KBookmarkHandler::resetBookmarks() 0574 { 0575 readBookmarkList(); 0576 } 0577 0578 0579 bool Smb4KBookmarkHandler::isBookmarked(const SharePtr& share) 0580 { 0581 if (findBookmarkByUrl(share->url())) 0582 { 0583 return true; 0584 } 0585 0586 return false; 0587 } 0588 0589 0590 void Smb4KBookmarkHandler::editBookmarks() 0591 { 0592 // 0593 // Only allow one instance of the bookmark editor 0594 // 0595 if (!d->editor) 0596 { 0597 d->editor = new Smb4KBookmarkEditor(bookmarksList(), QApplication::activeWindow()); 0598 } 0599 else 0600 { 0601 d->editor->raise(); 0602 } 0603 0604 if (d->editor->exec() == QDialog::Accepted) 0605 { 0606 addBookmarks(d->editor->editedBookmarks(), true); 0607 } 0608 else 0609 { 0610 resetBookmarks(); 0611 } 0612 0613 // 0614 // Delete the editor after use 0615 // 0616 delete d->editor; 0617 d->editor = 0; 0618 } 0619 0620 0621 void Smb4KBookmarkHandler::update() const 0622 { 0623 // Get new IP addresses. 0624 for (const BookmarkPtr &bookmark : d->bookmarks) 0625 { 0626 HostPtr host = findHost(bookmark->hostName(), bookmark->workgroupName()); 0627 0628 if (host) 0629 { 0630 if (host->hasIpAddress() && bookmark->hostIpAddress() != host->ipAddress()) 0631 { 0632 bookmark->setHostIpAddress(host->ipAddress()); 0633 } 0634 } 0635 } 0636 } 0637 0638 0639 void Smb4KBookmarkHandler::migrateProfile(const QString& from, const QString& to) 0640 { 0641 // Replace the old profile name with the new one. 0642 for (const BookmarkPtr &bookmark : d->bookmarks) 0643 { 0644 if (QString::compare(bookmark->profile(), from, Qt::CaseSensitive) == 0) 0645 { 0646 bookmark->setProfile(to); 0647 } 0648 } 0649 0650 // Write the new list to the file. 0651 writeBookmarkList(); 0652 } 0653 0654 0655 void Smb4KBookmarkHandler::removeProfile(const QString& name) 0656 { 0657 QMutableListIterator<BookmarkPtr> it(d->bookmarks); 0658 0659 while (it.hasNext()) 0660 { 0661 const BookmarkPtr &bookmark = it.next(); 0662 0663 if (QString::compare(bookmark->profile(), name, Qt::CaseSensitive) == 0) 0664 { 0665 it.remove(); 0666 } 0667 } 0668 0669 // Write the new list to the file. 0670 writeBookmarkList(); 0671 } 0672