summaryrefslogtreecommitdiffstats
path: root/kftpgrabber/src/kftpbookmarks.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kftpgrabber/src/kftpbookmarks.cpp')
-rw-r--r--kftpgrabber/src/kftpbookmarks.cpp948
1 files changed, 948 insertions, 0 deletions
diff --git a/kftpgrabber/src/kftpbookmarks.cpp b/kftpgrabber/src/kftpbookmarks.cpp
new file mode 100644
index 0000000..0211ac6
--- /dev/null
+++ b/kftpgrabber/src/kftpbookmarks.cpp
@@ -0,0 +1,948 @@
+/*
+ * This file is part of the KFTPGrabber project
+ *
+ * Copyright (C) 2003-2004 by the KFTPGrabber developers
+ * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
+ * NON-INFRINGEMENT. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+
+#include "kftpbookmarks.h"
+#include "kftpbookmarkaction.h"
+#include "kftpqueue.h"
+#include "kftpapi.h"
+#include "kftpwalletconnection.h"
+#include "misc.h"
+#include "desencryptor.h"
+#include "browser/view.h"
+#include "kftpsession.h"
+#include "bookmarks/listview.h"
+
+#include "misc/config.h"
+#include "engine/thread.h"
+#include "engine/ftpsocket.h"
+
+#include <qfile.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kpassdlg.h>
+#include <kmessagebox.h>
+#include <kdeversion.h>
+#include <kapplication.h>
+#include <kio/passdlg.h>
+#include <kstaticdeleter.h>
+
+/* KSSL includes */
+#include <ksslpkcs12.h>
+
+using namespace KFTPGrabberBase;
+
+namespace KFTPBookmarks {
+
+Site::Site(QDomNode node)
+ : m_element(node.toElement())
+{
+ // generate id if it is not present!
+ if (m_element.tagName() == "category") {
+ m_type = ST_CATEGORY;
+
+ if (getAttribute("id").isEmpty())
+ setAttribute("id", QString("cat-%1").arg(KApplication::randomString(7)));
+ } else if (m_element.tagName() == "server") {
+ m_type = ST_SITE;
+
+ if (getAttribute("id").isEmpty())
+ setAttribute("id", QString("site-%1").arg(KApplication::randomString(7)));
+ }
+
+ // Set the id
+ m_id = getAttribute("id");
+}
+
+Site::~Site()
+{
+}
+
+Site *Site::duplicate()
+{
+ Site *site = new Site(m_element.cloneNode());
+ site->setAttribute("name", i18n("Copy of") + " " + getAttribute("name"));
+
+ // Assign a new id
+ site->setAttribute("id", QString("site-%1").arg(KApplication::randomString(7)));
+ site->m_id = site->getAttribute("id");
+
+ m_element.parentNode().appendChild(site->m_element);
+
+ return site;
+}
+
+void Site::reparentSite(Site *site)
+{
+ // Move site's parent
+ m_element.appendChild(site->m_element);
+}
+
+Site *Site::addSite(QDomNode node)
+{
+ if (node.isNull()) {
+ // If there was no node specified, create a new one
+ node = m_element.ownerDocument().createElement("server");
+ }
+
+ Site *site = new Site(node);
+ m_element.appendChild(site->m_element);
+
+ return site;
+}
+
+void Site::addCategory(const QString &name)
+{
+ QDomElement cat = m_element.ownerDocument().createElement("category");
+
+ // Assign a new id and name
+ cat.setAttribute("id", QString("cat-%1").arg(KApplication::randomString(7)));
+ cat.setAttribute("name", name);
+
+ m_element.appendChild(cat);
+}
+
+KURL Site::getUrl()
+{
+ KURL url;
+
+ url.setProtocol(getProperty("protocol"));
+ url.setHost(getProperty("host"));
+ url.setPort(getIntProperty("port"));
+ url.setUser(getProperty("username"));
+ url.setPass(getProperty("password"));
+
+ return url;
+}
+
+Site *Site::getParentSite()
+{
+ // Get parent's site id, then search for it
+ QDomElement parent = m_element.parentNode().toElement();
+
+ if (parent.isNull())
+ return NULL;
+ else
+ return KFTPBookmarks::Manager::self()->findCategory(parent.attribute("id"));
+}
+
+QString Site::getProperty(const QString &name)
+{
+ QDomNodeList nodes = m_element.elementsByTagName(name);
+
+ if (nodes.length() > 0) {
+ QString property = nodes.item(0).toElement().text();
+ property.stripWhiteSpace();
+
+ // Automagicly decode passwords from BASE64
+ if (name.contains("pass") == 1)
+ property = decodePassword(property);
+
+ return property;
+ } else {
+ return QString::null;
+ }
+}
+
+int Site::getIntProperty(const QString &name)
+{
+ return getProperty(name).toInt();
+}
+
+void Site::setProperty(const QString &name, const QString &value)
+{
+ // First delete the old property if it exists
+ QDomNodeList nodes = m_element.elementsByTagName(name);
+
+ if (nodes.length() > 0)
+ m_element.removeChild(nodes.item(0));
+
+ // Now add a new one
+ QDomElement property = m_element.ownerDocument().createElement(name);
+ m_element.appendChild(property);
+
+ QDomText text = m_element.ownerDocument().createTextNode(value);
+ property.appendChild(text);
+}
+
+void Site::setProperty(const QString &name, int value)
+{
+ setProperty(name, QString::number(value));
+}
+
+void Site::setAttribute(const QString &name, const QString &value)
+{
+ m_element.setAttribute(name, value);
+}
+
+QString Site::getAttribute(const QString &name)
+{
+ return m_element.attribute(name);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+Manager *Manager::m_self = 0;
+static KStaticDeleter<Manager> staticBookmarkManagerDeleter;
+
+Manager *Manager::self()
+{
+ if (!m_self) {
+ staticBookmarkManagerDeleter.setObject(m_self, new Manager());
+ }
+
+ return m_self;
+}
+
+Manager::Manager()
+ : QObject()
+{
+ // Init the cache
+ m_siteCache.setAutoDelete(true);
+
+ // Init the DOM document
+ m_document = QDomDocument("KFTPGrabber");
+}
+
+Manager::Manager(const Manager &bookmarks)
+ : QObject()
+{
+ // Init the cache
+ m_siteCache.setAutoDelete(true);
+
+ // Init the DOM document
+ m_document = QDomDocument("KFTPGrabber");
+
+ // Copy the bookmarks
+ QDomNode tmp = m_document.importNode(bookmarks.m_document.documentElement(), true);
+ m_document.appendChild(tmp);
+}
+
+Manager::~Manager()
+{
+ if (m_self == this)
+ staticBookmarkManagerDeleter.setObject(m_self, 0, false);
+}
+
+void Manager::setBookmarks(KFTPBookmarks::Manager *bookmarks)
+{
+ // Init the DOM document
+ m_document = QDomDocument("KFTPGrabber");
+
+ QDomNode tmp = m_document.importNode(bookmarks->m_document.documentElement(), true);
+ m_document.appendChild(tmp);
+
+ // Clear the cache
+ m_siteCache.clear();
+
+ emit update();
+}
+
+void Manager::importSites(QDomNode node)
+{
+ QDomNode import = m_document.importNode(node, true);
+ m_document.documentElement().appendChild(import);
+
+ // Run sanity checks to generate missing ids
+ Manager::validate();
+}
+
+void Manager::load(const QString &filename)
+{
+ m_filename = filename;
+
+ QFile file(filename);
+ if (!file.open(IO_ReadOnly)) {
+ // Create a new empty XML
+ m_document.setContent(QString("<sites version=\"%1\"></sites>").arg(KFTP_BOOKMARKS_VERSION));
+
+ return;
+ }
+
+ // Check if the file is encrpyted
+ QCString content(file.readAll());
+
+ if (KFTPCore::Config::encryptBookmarks()) {
+ // File is encrypted
+pwd_entry:
+ int saveToWallet = 1;
+
+ QCString p_pass(KFTPAPI::getInstance()->walletConnection()->getPassword("bookmarkDecryptPwd").ascii());
+ if (QString(p_pass).isNull()) {
+ // Ask the user for a password
+ int ret = KPasswordDialog::getPassword(p_pass, i18n("This bookmark file is encrypted. Please enter key for decryption."), &saveToWallet);
+
+ if (ret != KPasswordDialog::Accepted) {
+ // User pressed cancel
+ p_pass = "";
+ }
+ }
+
+ // Try to decrypt
+ DESEncryptor des;
+ des.setKey(p_pass);
+ des.decrypt(content);
+
+ if (des.output().left(6) != "<sites" && des.output().left(9) != "<!DOCTYPE") {
+ // Clear any saved passwords
+ KFTPAPI::getInstance()->walletConnection()->setPassword("bookmarkDecryptPwd", QString::null);
+
+ if (KMessageBox::warningContinueCancel(
+ KFTPAPI::getInstance()->mainWindow(),
+ i18n("<qt>Bookmark file decryption has failed with provided key. Do you want to <b>overwrite</b> bookmarks with an empty file ?<br><br><font color=\"red\"><b>Warning:</b> If you overwrite, all current bookmarks will be lost.</font></qt>"),
+ i18n("Decryption Failed"),
+ KGuiItem(i18n("&Overwrite Bookmarks"))
+ ) != KMessageBox::Continue)
+ {
+ // Request the password again
+ goto pwd_entry;
+ }
+
+ // Create new empty XML
+ m_document.setContent(QString("<sites version=\"%1\"></sites>").arg(KFTP_BOOKMARKS_VERSION));
+
+ file.close();
+ return;
+ }
+
+ // Save the password for later encryption
+ m_decryptKey = p_pass;
+ content = des.output().ascii();
+
+ if (saveToWallet) {
+ // Save the password to KWallet
+ KFTPAPI::getInstance()->walletConnection()->setPassword("bookmarkDecryptPwd", p_pass);
+ }
+ }
+
+ m_document.setContent(QString::fromLocal8Bit(content));
+ file.close();
+
+ // Check for XML document version updates
+ versionUpdate();
+
+ // Document validation
+ Manager::validate();
+
+ // We have just loaded the bookmarks, so update all the menus
+ emit update();
+}
+
+void Manager::save()
+{
+ // Save the new XML file
+ if (m_filename.isEmpty()) {
+ qDebug("WARNING: No open XML file, will NOT save.");
+ return;
+ }
+
+ QFile file(m_filename);
+ if (!file.open(IO_WriteOnly)) {
+ qDebug("WARNING: Unable to open xml for writing!");
+ return;
+ }
+
+ // Should we encrypt the data ?
+ QString content = m_document.toString();
+ if (KFTPCore::Config::encryptBookmarks()) {
+ DESEncryptor des;
+
+ if (m_decryptKey.isEmpty()) {
+ // Ask the user for the password
+ KPasswordDialog::getPassword(m_decryptKey, i18n("Enter key for bookmark file encryption."));
+ }
+
+ des.setKey(m_decryptKey);
+ des.encrypt(content);
+
+ content = des.output();
+ }
+
+ // Write the XML data to the stream
+ QTextStream fileStream(&file);
+ fileStream << content;
+ file.flush();
+ file.close();
+}
+
+void Manager::validate(QDomNode node)
+{
+ if (node.isNull())
+ node = m_document.documentElement();
+
+ QDomNode n = node.firstChild();
+
+ while (!n.isNull()) {
+ if (n.toElement().tagName() == "category") {
+ if (!n.toElement().hasAttribute("id"))
+ n.toElement().setAttribute("id", QString("cat-%1").arg(KApplication::randomString(7)));
+
+ Manager::validate(n);
+ } else if (n.toElement().tagName() == "server") {
+ if (!n.toElement().hasAttribute("id"))
+ n.toElement().setAttribute("id", QString("site-%1").arg(KApplication::randomString(7)));
+ }
+
+ n = n.nextSibling();
+ }
+}
+
+void Manager::versionUpdate()
+{
+ int version = m_document.documentElement().attribute("version").toInt();
+
+ if (version < KFTP_BOOKMARKS_VERSION) {
+ // Conversion from an old bookmark file
+ qDebug("Detected an old (version %d, new version %d) bookmarks file. Starting conversion process...", version, KFTP_BOOKMARKS_VERSION);
+
+ // NOTE: There are no breaks here, since every update method updates to a specific
+ // version. So in order to convert to the most current from the oldest version, all
+ // methods need to be called!
+ switch (version) {
+ case 0:
+ case 1: versionFrom1Update();
+ }
+
+ // Fix the version
+ m_document.documentElement().setAttribute("version", KFTP_BOOKMARKS_VERSION);
+ }
+}
+
+void Manager::versionFrom1Update(QDomNode parent)
+{
+ // The original format had no site ids, so we have to generate them. Also the old
+ // format used something wierd called "options", we have to convert them as well.
+ // The username/password fields now have differend names.
+
+ if (parent.isNull())
+ parent = m_document.documentElement();
+
+ QDomNode n = parent.firstChild();
+
+ while (!n.isNull()) {
+ if (n.toElement().tagName() == "category") {
+ // Update the category id and all children
+ n.toElement().setAttribute("id", QString("cat-%1").arg(KApplication::randomString(7)));
+
+ versionFrom1Update(n);
+ } else if (n.toElement().tagName() == "server") {
+ // Update the server id
+ n.toElement().setAttribute("id", QString("site-%1").arg(KApplication::randomString(7)));
+
+ // Convert the "options"
+ QDomNodeList nodes = n.toElement().elementsByTagName("option");
+
+ if (nodes.length() > 0) {
+ for (unsigned int i = 0; i < nodes.count(); i++) {
+ QDomNode node = nodes.item(i);
+
+ // Add a new standard property
+ QDomElement property = m_document.createElement(node.toElement().attribute("name"));
+ n.appendChild(property);
+
+ QDomText text = m_document.createTextNode(node.toElement().attribute("value"));
+ property.appendChild(text);
+
+ // And remove the option :>
+ node.parentNode().removeChild(node);
+ i--;
+ }
+ }
+
+ // Rename the username/password fields
+ nodes = n.toElement().elementsByTagName("downuser");
+ if (nodes.length() > 0) {
+ for (unsigned int i = 0; i < nodes.count(); i++) {
+ QDomNode node = nodes.item(i);
+ node.toElement().setTagName("username");
+ }
+ }
+
+ nodes = n.toElement().elementsByTagName("downpass");
+ if (nodes.length() > 0) {
+ for (unsigned int i = 0; i < nodes.count(); i++) {
+ QDomNode node = nodes.item(i);
+ node.toElement().setTagName("password");
+ }
+ }
+ }
+
+ n = n.nextSibling();
+ }
+}
+
+Site *Manager::findSite(const KURL &url)
+{
+ // Find the node, then see if it is already present in the cache
+ QDomNode siteElement = findSiteElementByUrl(url);
+
+ if (!siteElement.isNull()) {
+ // Try to get a cached version
+ Site *site = m_siteCache.find(siteElement.toElement().attribute("id"));
+
+ if (!site) {
+ site = new Site(siteElement);
+ m_siteCache.insert(siteElement.toElement().attribute("id"), site);
+ }
+
+ return site;
+ } else {
+ return NULL;
+ }
+}
+
+Site *Manager::findSite(const QString &id)
+{
+ if (id.isNull())
+ return NULL;
+
+ // Try the cache first
+ Site *site = m_siteCache.find(id);
+
+ if (!site) {
+ // The site was not found, search in the DOM tree and add it to the
+ // cache if found.
+ QDomNode siteElement = findSiteElementById(id);
+
+ if (siteElement.isNull()) {
+ qDebug("WARNING: Unable to find site with id '%s'!", id.ascii());
+
+ return NULL;
+ }
+
+ site = new Site(siteElement);
+ m_siteCache.insert(id, site);
+ }
+
+ return site;
+}
+
+QDomNode Manager::findSiteElementByUrl(const KURL &url, QDomNode parent)
+{
+ if (parent.isNull())
+ parent = m_document.documentElement();
+
+ QDomNode n = parent.firstChild();
+
+ while (!n.isNull()) {
+ if (n.toElement().tagName() == "category") {
+ // Check the category
+ QDomNode site = findSiteElementByUrl(url, n);
+
+ if (!site.isNull())
+ return site;
+ } else if (n.toElement().tagName() == "server") {
+ // Check if the server matches
+ Site *tmp = new Site(n);
+
+ if (tmp->getProperty("host") == url.host() &&
+ tmp->getIntProperty("port") == url.port() &&
+ tmp->getProperty("username") == url.user() &&
+ tmp->getProperty("password") == url.pass())
+ {
+ delete tmp;
+ return n;
+ }
+
+ delete tmp;
+ }
+
+ n = n.nextSibling();
+ }
+
+ return QDomNode();
+}
+
+QDomNode Manager::findSiteElementById(const QString &id, QDomNode parent)
+{
+ if (parent.isNull())
+ parent = m_document.documentElement();
+
+ QDomNode n = parent.firstChild();
+
+ while (!n.isNull()) {
+ if (n.toElement().tagName() == "category") {
+ // Check the category
+ QDomNode site = findSiteElementById(id, n);
+
+ if (!site.isNull())
+ return site;
+ } else if (n.toElement().tagName() == "server") {
+ // Check if the server matches
+ if (n.toElement().attribute("id") == id)
+ return n;
+ }
+
+ n = n.nextSibling();
+ }
+
+ return QDomNode();
+}
+
+QDomNode Manager::findCategoryElementById(const QString &id, QDomNode parent)
+{
+ if (id == "root")
+ return m_document.documentElement();
+
+ if (parent.isNull())
+ parent = m_document.documentElement();
+
+ QDomNode n = parent.firstChild();
+
+ while (!n.isNull()) {
+ if (n.toElement().tagName() == "category") {
+ if (n.toElement().attribute("id") == id)
+ return n;
+
+ // Check the category
+ QDomNode site = findCategoryElementById(id, n);
+
+ if (!site.isNull())
+ return site;
+ }
+
+ n = n.nextSibling();
+ }
+
+ return QDomNode();
+}
+
+Site *Manager::findCategory(const QString &id)
+{
+ // Try the cache first
+ Site *site = m_siteCache.find(id);
+
+ if (!site) {
+ // The site was not found, search in the DOM tree and add it to the
+ // cache if found.
+ QDomNode siteElement = findCategoryElementById(id);
+
+ if (siteElement.isNull()) {
+ qDebug("WARNING: Unable to find category with id '%s'!", id.ascii());
+
+ return NULL;
+ }
+
+ site = new Site(siteElement);
+ m_siteCache.insert(id, site);
+ }
+
+ return site;
+}
+
+Site *Manager::addSite(Site *category, QDomNode node)
+{
+ if (category)
+ return category->addSite(node);
+
+ return NULL;
+}
+
+void Manager::delSite(Site *site)
+{
+ // Remove the node from the DOM tree
+ site->m_element.parentNode().removeChild(site->m_element);
+
+ // Remove the site from cache and it will be automaticly deleted
+ m_siteCache.remove(site->id());
+
+ emit update();
+}
+
+void Manager::setupClient(Site *site, KFTPEngine::Thread *client)
+{
+ if (site) {
+ // First activate the correct socket and reset the old flags
+ client->selectSocketForProtocol(KURL(QString("%1://test/").arg(site->getProperty("protocol"))));
+ client->socket()->initConfig();
+
+ int retryTime = site->getIntProperty("retrytime");
+ int retryCnt = site->getIntProperty("retrycount");
+
+ if (retryTime != 0) {
+ client->socket()->setConfig("retry", 1);
+ client->socket()->setConfig("max_retries", retryCnt);
+ client->socket()->setConfig("retry_delay", retryTime);
+ } else {
+ client->socket()->setConfig("retry", 0);
+ }
+
+ client->socket()->setConfig("keepalive.enabled", site->getIntProperty("doKeepalive"));
+ client->socket()->setConfig("keepalive.timeout", site->getIntProperty("keepaliveTimeout"));
+
+ client->socket()->setConfig("ssl.use_tls", site->getIntProperty("use_tls"));
+ client->socket()->setConfig("ssl.use_implicit", site->getIntProperty("use_implicit"));
+ client->socket()->setConfig("ssl.prot_mode", site->getProperty("tls_data_mode"));
+ client->socket()->setConfig("feat.pasv", site->getIntProperty("disablePASV") == 1 ? 0 : 1);
+ client->socket()->setConfig("feat.epsv", site->getIntProperty("disableEPSV") == 1 ? 0 : 1);
+ client->socket()->setConfig("pasv.use_site_ip", site->getIntProperty("pasvSiteIp"));
+ client->socket()->setConfig("active.no_force_ip", site->getIntProperty("disableForceIp"));
+ client->socket()->setConfig("stat_listings", site->getIntProperty("statListings"));
+ client->socket()->setConfig("encoding", site->getProperty("encoding"));
+
+ // Should we use a X509 certificate ?
+ if (site->getIntProperty("use_cert") && site->getProperty("protocol") == "ftp") {
+ // Ask the user for the decryption password
+ QCString certPass;
+ KPasswordDialog::getPassword(certPass, i18n("Please provide your X509 certificate decryption password."));
+
+ static_cast<KFTPEngine::FtpSocket*>(client->socket())->setSslClientCertificate(KSSLPKCS12::loadCertFile(site->getProperty("tls_cert_path"), certPass));
+ }
+ } else {
+ // Just reset the client, since we don't know the config
+ client->socket()->initConfig();
+ }
+}
+
+void Manager::guiPopulateBookmarksTree(KFTPWidgets::Bookmarks::ListView *tree, QDomNode parent, KFTPWidgets::Bookmarks::ListViewItem *item)
+{
+ if (parent.isNull()) {
+ // Clear the tree and set the parent
+ tree->clear();
+ parent = m_document.documentElement();
+ }
+
+ QDomNode n = parent.firstChild();
+
+ while (!n.isNull()) {
+ if (n.toElement().tagName() == "category") {
+ // Add a submenu
+ KFTPWidgets::Bookmarks::ListViewItem *cat;
+ Site *site = findCategory(n.toElement().attribute("id"));
+
+ if (!item)
+ cat = new KFTPWidgets::Bookmarks::ListViewItem(tree, site->getAttribute("name"));
+ else
+ cat = new KFTPWidgets::Bookmarks::ListViewItem(item, site->getAttribute("name"));
+
+ cat->setType(0);
+ cat->setSite(site);
+
+ cat->setPixmap(0, loadSmallPixmap("bookmark_folder"));
+ guiPopulateBookmarksTree(tree, n, cat);
+ } else if (n.toElement().tagName() == "server") {
+ KFTPWidgets::Bookmarks::ListViewItem *serv;
+ Site *site = findSite(n.toElement().attribute("id"));
+
+ if (!item)
+ serv = new KFTPWidgets::Bookmarks::ListViewItem(tree, site->getAttribute("name"));
+ else
+ serv = new KFTPWidgets::Bookmarks::ListViewItem(item, site->getAttribute("name"));
+
+ serv->setType(1);
+ serv->setSite(site);
+
+ serv->setPixmap(0, loadSmallPixmap("ftp"));
+ }
+
+ n = n.nextSibling();
+ }
+}
+
+void Manager::guiPopulateBookmarksMenu(KActionMenu *parentMenu, QDomNode parentNode, bool base, QObject *data)
+{
+ if (parentNode.isNull())
+ parentNode = m_document.documentElement();
+
+ QDomNode n = parentNode.firstChild();
+ KActionMenu *menu = 0L;
+ KFTPBookmarkAction *action = 0L;
+
+ while (!n.isNull()) {
+ QString name = n.toElement().attribute("name");
+
+ if (n.toElement().tagName() == "category") {
+ menu = new KActionMenu(name, "bookmark_folder", parentMenu);
+ parentMenu->insert(menu, base ? 5 : 0);
+
+ // Fill the menu
+ guiPopulateBookmarksMenu(menu, n, false, data);
+ } else if (n.toElement().tagName() == "server") {
+ action = new KFTPBookmarkAction(name, "ftp", KShortcut(), this, SLOT(slotBookmarkExecuted()), KFTPAPI::getInstance()->mainWindow()->actionCollection());
+ action->setSiteId(n.toElement().attribute("id"));
+ action->setData(data);
+
+ parentMenu->insert(action);
+ }
+
+ n = n.nextSibling();
+ }
+}
+
+void Manager::guiPopulateZeroconfMenu(KActionMenu *parentMenu)
+{
+ // Clear the menu
+ parentMenu->popupMenu()->clear();
+
+#if KDE_IS_VERSION(3,4,0)
+ // Populate
+ QValueList<DNSSD::RemoteService::Ptr> list = KFTPAPI::getInstance()->zeroConfInterface()->getServiceList();
+
+ if (!list.empty()) {
+ QValueList<DNSSD::RemoteService::Ptr>::iterator end(list.end());
+
+ for (QValueList<DNSSD::RemoteService::Ptr>::iterator i(list.begin()); i != end; ++i) {
+ KFTPZeroconfAction *newService = new KFTPZeroconfAction((*i)->serviceName(), "lan", KShortcut(), this, SLOT(slotZeroconfExecuted()), KFTPAPI::getInstance()->mainWindow()->actionCollection());
+ newService->setSite(*i);
+
+ parentMenu->insert(newService);
+ }
+ } else {
+ KAction *disabledAction = new KAction(i18n("<No Services Published>"));
+ disabledAction->setEnabled(false);
+ parentMenu->insert(disabledAction);
+ }
+#else
+ KAction *disabledAction = new KAction(i18n("<DNSSD Not Available>"));
+ disabledAction->setEnabled(false);
+ parentMenu->insert(disabledAction);
+#endif
+}
+
+void Manager::guiPopulateWalletMenu(KActionMenu *parentMenu)
+{
+ // Clear the menu
+ parentMenu->popupMenu()->clear();
+
+ // Populate
+ QValueList<KURL> list = KFTPAPI::getInstance()->walletConnection()->getSiteList();
+
+ if (!list.empty()) {
+ QValueList<KURL>::iterator end(list.end());
+
+ for (QValueList<KURL>::iterator i(list.begin()); i != end; ++i) {
+ QString desc;
+
+ if ((*i).port() != 21)
+ desc = QString("%1@%2:%3").arg((*i).user()).arg((*i).host()).arg((*i).port());
+ else
+ desc = QString("%1@%2").arg((*i).user()).arg((*i).host());
+
+ KFTPWalletAction *newSite = new KFTPWalletAction(desc, "ftp", KShortcut(), this, SLOT(slotWalletExecuted()), KFTPAPI::getInstance()->mainWindow()->actionCollection());
+ newSite->setSite(*i);
+
+ parentMenu->insert(newSite);
+ }
+ } else {
+ KAction *disabledAction = new KAction(i18n("<No Sites In KWallet>"));
+ disabledAction->setEnabled(false);
+ parentMenu->insert(disabledAction);
+ }
+}
+
+void Manager::slotBookmarkExecuted()
+{
+ // Get the sender
+ KFTPBookmarkAction *action = (KFTPBookmarkAction*) QObject::sender();
+ Site *site = findSite(action->siteId());
+
+ // Get the node data from bookmarks
+ KURL siteUrl = site->getUrl();
+
+ // Handle empty usernames and passwords for non-anonymous sites
+ if (!siteUrl.hasUser() || !siteUrl.hasPass() && siteUrl.user() != "anonymous") {
+ KIO::PasswordDialog *dlg = new KIO::PasswordDialog(i18n("Please provide your username and password for connecting to this site."), siteUrl.user(), true);
+ dlg->addCommentLine(i18n("Site:"), QString("%1:%2").arg(siteUrl.host()).arg(siteUrl.port()));
+
+ if (dlg->exec() == KDialogBase::Accepted) {
+ siteUrl.setUser(dlg->username());
+ siteUrl.setPass(dlg->password());
+
+ if (dlg->keepPassword()) {
+ // Save password to the bookmarked site
+ site->setProperty("username", dlg->username());
+ site->setProperty("password", encodePassword(dlg->password()));
+ }
+
+ delete dlg;
+ } else {
+ // Abort connection attempt
+ delete dlg;
+ return;
+ }
+ }
+
+ if (action->data()) {
+ // A specific session was passed on to us
+ KFTPSession::Session *session = static_cast<KFTPSession::Session*>(action->data());
+
+ // Set the correct client for connection
+ KFTPEngine::Thread *client = session->getClient();
+
+ // Now, connect to the server
+ if (client->socket()->isConnected()) {
+ if (KFTPCore::Config::confirmDisconnects() && KMessageBox::warningYesNo(0, i18n("Do you want to drop current connection?")) == KMessageBox::No)
+ return;
+ }
+
+ client->socket()->setCurrentUrl(siteUrl);
+
+ // Set the session's site and connect
+ session->setSite(site);
+ session->reconnect(siteUrl);
+ } else {
+ // Just spawn a new session
+ KFTPSession::Session *session = KFTPSession::Manager::self()->spawnRemoteSession(KFTPSession::IgnoreSide, siteUrl, site);
+ KFTPSession::Manager::self()->setActive(session);
+ }
+}
+
+void Manager::slotWalletExecuted()
+{
+ // Get the sender
+ KFTPWalletAction *action = (KFTPWalletAction*) QObject::sender();
+ KURL siteUrl = action->getSite();
+
+ // Just spawn a new session
+ KFTPSession::Manager::self()->spawnRemoteSession(KFTPSession::IgnoreSide, siteUrl);
+}
+
+void Manager::slotZeroconfExecuted()
+{
+#if KDE_IS_VERSION(3,4,0)
+ // Get the sender
+ KFTPZeroconfAction *action = (KFTPZeroconfAction*) QObject::sender();
+ DNSSD::RemoteService::Ptr service = action->getSite();
+
+ KFTPAPI::getInstance()->mainWindow()->slotQuickConnect(service->serviceName(), service->hostName(), service->port());
+#endif
+}
+
+}
+
+
+#include "kftpbookmarks.moc"