diff options
Diffstat (limited to 'klinkstatus/src/engine/searchmanager.cpp')
-rw-r--r-- | klinkstatus/src/engine/searchmanager.cpp | 916 |
1 files changed, 916 insertions, 0 deletions
diff --git a/klinkstatus/src/engine/searchmanager.cpp b/klinkstatus/src/engine/searchmanager.cpp new file mode 100644 index 00000000..81562a7a --- /dev/null +++ b/klinkstatus/src/engine/searchmanager.cpp @@ -0,0 +1,916 @@ +/*************************************************************************** + * Copyright (C) 2004 by Paulo Moura Guedes * + * [email protected] * + * * + * 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 WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include <kapplication.h> +#include <kdebug.h> +#include <klocale.h> +#include <khtml_part.h> +#include <kprotocolmanager.h> + +#include <qstring.h> +#include <qvaluevector.h> +#include <qdom.h> + +#include <iostream> +#include <unistd.h> + +#include "searchmanager.h" +#include "../parser/mstring.h" +#include "../cfg/klsconfig.h" + + +SearchManager::SearchManager(int max_simultaneous_connections, int time_out, + QObject *parent, const char *name) + : QObject(parent, name), + max_simultaneous_connections_(max_simultaneous_connections), has_document_root_(false), + depth_(-1), current_depth_(0), external_domain_depth_(0), + current_node_(0), current_index_(0), links_being_checked_(0), + finished_connections_(max_simultaneous_connections_), + maximum_current_connections_(-1), general_domain_(false), + checked_general_domain_(false), time_out_(time_out), current_connections_(0), + send_identification_(true), canceled_(false), searching_(false), checked_links_(0), ignored_links_(0), + check_parent_dirs_(true), check_external_links_(true), check_regular_expressions_(false), + number_of_level_links_(0), number_of_links_to_check_(0) +{ + root_.setIsRoot(true); + + if (KLSConfig::userAgent().isEmpty()) { + KLSConfig::setUserAgent(KProtocolManager::defaultUserAgent()); + } + user_agent_ = KLSConfig::userAgent(); +} + +void SearchManager::reset() +{ + kdDebug(23100) << "SearchManager::reset()" << endl; + + //Q_ASSERT(not links_being_checked_); + + root_.reset(); + cleanItems(); + depth_ = -1; + current_depth_ = 0; + current_node_ = 0; + current_index_ = 0; + finished_connections_ = max_simultaneous_connections_; + domain_ = ""; + maximum_current_connections_ = -1; + general_domain_ = false; + checked_general_domain_ = false; + check_regular_expressions_ = false; + current_connections_ = 0; + canceled_ = false; + searching_ = false; + checked_links_ = 0; + if(KLSConfig::userAgent().isEmpty()) { + KLSConfig::setUserAgent(KProtocolManager::defaultUserAgent()); + } + user_agent_ = KLSConfig::userAgent(); + + removeHtmlParts(); +} + +SearchManager::~SearchManager() +{ + reset(); +} + +void SearchManager::cleanItems() +{ + for(uint i = 0; i != search_results_.size(); ++i) + { + for(uint j = 0; j != search_results_[i].size() ; ++j) + { + for(uint l = 0; l != (search_results_[i])[j].size(); ++l) + { + if(((search_results_[i])[j])[l] != 0) + { + delete ((search_results_[i])[j])[l]; + ((search_results_[i])[j])[l] = 0; + } + else + kdDebug(23100) << "LinkStatus NULL!!" << endl; + } + search_results_[i][j].clear(); + } + search_results_[i].clear(); + } + search_results_.clear(); + kdDebug(23100) << endl; +} + +void SearchManager::startSearch(KURL const& root, SearchMode const& modo) +{ + canceled_ = false; + + //time_.restart(); + time_.start(); + + Q_ASSERT(root.isValid()); + //Q_ASSERT(root.protocol() == "http" || root.protocol() == "https"); + + if(root.hasHost() && (domain_.isNull() || domain_.isEmpty())) + { + setDomain(root.host() + root.directory()); + kdDebug(23100) << "Domain: " << domain_ << endl; + } + root_.setIsRoot(true); + root_.setDepth(0); + root_.setOriginalUrl(root.prettyURL()); + root_.setAbsoluteUrl(root); + root_.setOnlyCheckHeader(false); + root_.setRootUrl(root); + + search_mode_ = modo; + if(modo == depth) + Q_ASSERT(depth_ != -1); + else if(modo == domain) + Q_ASSERT(depth_ == -1); + else + Q_ASSERT(depth_ != -1); + + searching_ = true; + + //Q_ASSERT(domain_ != QString::null); + checkRoot(); +} + +void SearchManager::resume() +{ + searching_ = true; + canceled_ = false; + continueSearch(); +} + +void SearchManager::finnish() +{ + searching_ = false; + while(links_being_checked_) + { + kdDebug(23100) << "links_being_checked_: " << links_being_checked_ << endl; + sleep(1); + } + emit signalSearchFinished(); +} + +void SearchManager::pause() +{ + searching_ = false; + while(links_being_checked_) + { + kdDebug(23100) << "links_being_checked_: " << links_being_checked_ << endl; + sleep(1); + } + emit signalSearchPaused(); +} + +void SearchManager::cancelSearch() +{ + canceled_ = true; +} + +void SearchManager::checkRoot() +{ + LinkChecker* checker = new LinkChecker(&root_, time_out_, this, "link_checker"); + checker->setSearchManager(this); + + connect(checker, SIGNAL(transactionFinished(const LinkStatus *, LinkChecker *)), + this, SLOT(slotRootChecked(const LinkStatus *, LinkChecker *))); + /* + connect(checker, SIGNAL(jobFinnished(LinkChecker *)), + this, SLOT(slotLinkCheckerFinnished(LinkChecker *))); + */ + checker->check(); +} + +void SearchManager::slotRootChecked(const LinkStatus * link, LinkChecker * checker) +{ + kdDebug(23100) << "SearchManager::slotRootChecked:" << endl; + kdDebug(23100) << link->absoluteUrl().url() << " -> " << + LinkStatus::lastRedirection(&root_)->absoluteUrl().url() << endl; + + Q_ASSERT(checked_links_ == 0); + Q_ASSERT(search_results_.size() == 0); + + ++checked_links_; + //kdDebug(23100) << "++checked_links_: SearchManager::slotRootChecked" << endl; + emit signalRootChecked(link, checker); + + if(search_mode_ != depth || depth_ > 0) + { + current_depth_ = 1; + + vector<LinkStatus*> no = children(LinkStatus::lastRedirection(&root_)); + + emit signalLinksToCheckTotalSteps(no.size()); + + vector< vector<LinkStatus*> > nivel; + nivel.push_back(no); + + search_results_.push_back(nivel); + + if(search_results_.size() != 1) + { + kdDebug(23100) << "search_results_.size() != 1:" << endl; + kdDebug(23100) << "size: " << search_results_.size() << endl; + } + Q_ASSERT(search_results_.size() == 1); + + if(no.size() > 0) + { + startSearch(); + } + else + { + kdDebug(23100) << "SearchManager::slotRootChecked#1" << endl; + finnish(); + } + } + + else + { + Q_ASSERT(search_results_.size() == 0); + kdDebug(23100) << "SearchManager::slotRootChecked#2" << endl; + finnish(); + } + + delete checker; + checker = 0; +} + +vector<LinkStatus*> SearchManager::children(LinkStatus* link) +{ + vector<LinkStatus*> children; + + if(!link || link->absoluteUrl().hasRef()) + return children; + + vector<Node*> const& nodes = link->childrenNodes(); + + int count = 0; + for(uint i = 0; i != nodes.size(); ++i) + { + ++count; + + Node* node = nodes[i]; + KURL url; + if(node->url().isEmpty()) + url = ""; + else + url = Url::normalizeUrl(node->url(), *link, documentRoot().path()); + + if( (node->isLink() && + checkable(url, *link) && + !Url::existUrl(url, children) && + !node->url().isEmpty()) + || + node->malformed() ) + { + LinkStatus* ls = new LinkStatus(node, link); + ls->setAbsoluteUrl(url); + + if(localDomain(ls->absoluteUrl())) + ls->setExternalDomainDepth(-1); + else + ls->setExternalDomainDepth(link->externalDomainDepth() + 1); + + //ls->setIsLocalRestrict(localDomain(url)); + ls->setIsLocalRestrict(ls->local()); // @todo clean this nonsense + + if(!validUrl(url)) { + ls->setMalformed(true); + ls->setErrorOccurred(true); + } + + ls->setOnlyCheckHeader(onlyCheckHeader(ls)); + + if(link->externalDomainDepth() > external_domain_depth_) + { + kdDebug(23100) << "link->externalDomainDepth() > external_domain_depth_: " + << link->externalDomainDepth() << endl; + kdDebug(23100) << "link: " << endl << link->toString() << endl; + kdDebug(23100) << "child: " << endl << ls->toString() << endl; + } + Q_ASSERT(link->externalDomainDepth() <= external_domain_depth_); + + children.push_back(ls); + } + if(count == 50) + { + kapp->processEvents(); + count = 0; + } + } + + return children; +} + +bool SearchManager::existUrl(KURL const& url, KURL const& url_parent) const +{ + if(url.prettyURL().isEmpty() || root_.originalUrl() == url.prettyURL()) + return true; + + for(uint i = 0; i != search_results_.size(); ++i) + for(uint j = 0; j != search_results_[i].size(); ++j) + for(uint l = 0; l != (search_results_[i])[j].size(); ++l) + { + LinkStatus* tmp = search_results_[i][j][l]; + Q_ASSERT(tmp); + if(tmp->absoluteUrl() == url) + { // URL exists + QValueVector<KURL> referrers(tmp->referrers()); + + // Add new referrer + for(uint i = 0; i != referrers.size(); ++i) + { + if(referrers[i] == url_parent) + return true; + } + tmp->addReferrer(url_parent); + + return true; + } + } + + return false; +} + +LinkStatus const* SearchManager::linkStatus(QString const& s_url) const +{ + Q_ASSERT(!s_url.isEmpty()); + + if(root_.absoluteUrl().url() == s_url) + return &root_; + + int count = 0; + for(uint i = 0; i != search_results_.size(); ++i) + for(uint j = 0; j != search_results_[i].size(); ++j) + for(uint l = 0; l != (search_results_[i])[j].size(); ++l) + { + ++count; + + LinkStatus* ls = search_results_[i][j][l]; + Q_ASSERT(ls); + if(ls->absoluteUrl().url() == s_url && ls->checked()) + return ls; + + if(count == 50) + { + count = 0; + kapp->processEvents(); + } + + } + + return 0; +} + + +void SearchManager::startSearch() +{ + Q_ASSERT(current_depth_ == 1); + Q_ASSERT(search_results_[current_depth_ - 1].size() == 1); + Q_ASSERT(current_node_ == 0); + + if( (int)current_depth_ <= depth_ || search_mode_ != depth ) + checkVectorLinks(nodeToAnalize()); + else + { + kdDebug(23100) << "Search Finished! (SearchManager::comecaPesquisa)" << endl; + finnish(); + } +} + +void SearchManager::continueSearch() +{ + Q_ASSERT(!links_being_checked_); + + vector<LinkStatus*> const& no = nodeToAnalize(); + + if((uint)current_index_ < no.size()) + checkVectorLinks(no); + + else + { + current_index_ = 0; + kdDebug(23100) << "Next node_____________________\n\n"; + ++current_node_; + if( (uint)current_node_ < (search_results_[current_depth_ - 1]).size() ) + checkVectorLinks(nodeToAnalize()); + else + { + kdDebug(23100) << "Next Level_____________________________________________________________________________________\n\n\n"; + if(search_mode_ == SearchManager::domain || + current_depth_ < depth_) + { + current_node_ = 0; + ++current_depth_; + + addLevel(); + + if( (uint)current_depth_ == search_results_.size() ) + checkVectorLinks(nodeToAnalize()); + else + { + kdDebug(23100) << "Search Finished! (SearchManager::continueSearch#1)" << endl; + finnish(); + } + } + else + { + kdDebug(23100) << "Search Finished! (SearchManager::continueSearch#2)" << endl; + finnish(); + } + } + } +} + +vector<LinkStatus*> const& SearchManager::nodeToAnalize() const +{ + Q_ASSERT( (uint)current_depth_ == search_results_.size() ); + Q_ASSERT( (uint)current_node_ < (search_results_[current_depth_ - 1]).size() ); + + return (search_results_[current_depth_ - 1])[current_node_]; +} + +void SearchManager::checkVectorLinks(vector<LinkStatus*> const& links) +{ + checkLinksSimultaneously(chooseLinks(links)); +} + +vector<LinkStatus*> SearchManager::chooseLinks(vector<LinkStatus*> const& links) +{ + vector<LinkStatus*> escolha; + for(int i = 0; i != max_simultaneous_connections_; ++i) + { + if((uint)current_index_ < links.size()) + escolha.push_back(links[current_index_++]); + } + return escolha; +} + +void SearchManager::checkLinksSimultaneously(vector<LinkStatus*> const& links) +{ + Q_ASSERT(finished_connections_ <= max_simultaneous_connections_); + finished_connections_ = 0; + links_being_checked_ = 0; + maximum_current_connections_ = -1; + + if(links.size() < (uint)max_simultaneous_connections_) + maximum_current_connections_ = links.size(); + else + maximum_current_connections_ = max_simultaneous_connections_; + + for(uint i = 0; i != links.size(); ++i) + { + LinkStatus* ls(links[i]); + Q_ASSERT(ls); + + QString protocol = ls->absoluteUrl().protocol(); + + ++links_being_checked_; + Q_ASSERT(links_being_checked_ <= max_simultaneous_connections_); + + if(ls->malformed()) + { + Q_ASSERT(ls->errorOccurred()); + Q_ASSERT(ls->status() == LinkStatus::MALFORMED); + + ls->setChecked(true); + slotLinkChecked(ls, 0); + } + + else if(ls->absoluteUrl().prettyURL().contains("javascript:", false)) + { + ++ignored_links_; + ls->setIgnored(true); + ls->setErrorOccurred(true); + ls->setError(i18n( "Javascript not supported" )); + ls->setStatus(LinkStatus::NOT_SUPPORTED); + ls->setChecked(true); + slotLinkChecked(ls, 0); + } + /* + else if(!(protocol == "http" || protocol == "https")) + { + ++ignored_links_; + ls->setIgnored(true); + ls->setErrorOccurred(true); + ls->setError(i18n("Protocol %1 not supported").arg(protocol)); + ls->setStatus(LinkStatus::MALFORMED); + ls->setChecked(true); + slotLinkChecked(ls, 0); + } + */ + else + { + LinkChecker* checker = new LinkChecker(ls, time_out_, this, "link_checker"); + checker->setSearchManager(this); + + connect(checker, SIGNAL(transactionFinished(const LinkStatus *, LinkChecker *)), + this, SLOT(slotLinkChecked(const LinkStatus *, LinkChecker *))); + /* + connect(checker, SIGNAL(jobFinnished(LinkChecker *)), + this, SLOT(slotLinkCheckerFinnished(LinkChecker *))); + */ + checker->check(); + } + } +} + +void SearchManager::slotLinkChecked(const LinkStatus * link, LinkChecker * checker) +{ + kdDebug(23100) << "SearchManager::slotLinkChecked:" << endl; +// kdDebug(23100) << link->absoluteUrl().url() << " -> " << +// LinkStatus::lastRedirection((const_cast<LinkStatus*> (link)))->absoluteUrl().url() << endl; + + Q_ASSERT(link); + emit signalLinkChecked(link, checker); + ++checked_links_; + ++finished_connections_; + --links_being_checked_; + + if(links_being_checked_ < 0) + kdDebug(23100) << link->toString() << endl; + Q_ASSERT(links_being_checked_ >= 0); + + if(canceled_ && searching_ && !links_being_checked_) + { + pause(); + } + + else if(!canceled_ && finished_connections_ == maximumCurrentConnections() ) + { + continueSearch(); + return; + } + /* + delete checker; + checker = 0; + */ +} + +void SearchManager::addLevel() +{ + search_results_.push_back(vector< vector <LinkStatus*> >()); + vector< vector <LinkStatus*> >& ultimo_nivel(search_results_[search_results_.size() - 2]); + + number_of_level_links_ = 0; + number_of_links_to_check_ = 0; + uint end = ultimo_nivel.size(); + + for(uint i = 0; i != end; ++i) // nodes + { + uint end_sub1 = ultimo_nivel[i].size(); + for(uint j = 0; j != end_sub1; ++j) // links + ++number_of_level_links_; + } + + if(number_of_level_links_) + emit signalAddingLevelTotalSteps(number_of_level_links_); + + for(uint i = 0; i != end; ++i) // nodes + { + uint end_sub1 = ultimo_nivel[i].size(); + for(uint j = 0; j != end_sub1; ++j) // links + { + vector <LinkStatus*> f(children( LinkStatus::lastRedirection(((ultimo_nivel[i])[j])) )); + if(f.size() != 0) + { + search_results_[search_results_.size() - 1].push_back(f); + number_of_links_to_check_ += f.size(); + } + + emit signalAddingLevelProgress(); +// kapp->processEvents(); + } + } + if( (search_results_[search_results_.size() - 1]).size() == 0 ) + search_results_.pop_back(); + else + emit signalLinksToCheckTotalSteps(number_of_links_to_check_); +} + +bool SearchManager::checkable(KURL const& url, LinkStatus const& link_parent) const +{ + if(existUrl(url, link_parent.absoluteUrl())) + return false; + + if(!checkableByDomain(url, link_parent)) + return false; + + if(!check_parent_dirs_) + { + if(Url::parentDir(root_.absoluteUrl(), url)) + return false; + } + if(!check_external_links_) + { + if(Url::externalLink(root_.absoluteUrl(), url)) + return false; + } + if(check_regular_expressions_) + { + Q_ASSERT(!reg_exp_.isEmpty()); + + if(reg_exp_.search(url.url()) != -1) + return false; + } + + //kdDebug(23100) << "url " << url.url() << " is checkable!" << endl; + return true; +} + +bool SearchManager::checkableByDomain(KURL const& url, LinkStatus const& link_parent) const +{ + bool result = false; + if(localDomain(url)) + result = true; + else if( (link_parent.externalDomainDepth() + 1) < external_domain_depth_ ) + result = true; + else + result = false; + /* + if(!result) + kdDebug(23100) << "\n\nURL " << url.url() << " is not checkable by domain\n\n" << endl; + */ + return result; +} +/* +bool SearchManager::localDomain(KURL const& url) const + { + KURL url_root = root_.absoluteUrl(); + + if(url_root.protocol() != url.protocol()) + return false; + + if(url_root.hasHost()) + { + if(generalDomain()) + { + return equalHost(domain_, url.host()); + } + else + { + vector<QString> referencia = tokenizeWordsSeparatedBy(domain_, QChar('/')); + vector<QString> a_comparar = tokenizeWordsSeparatedBy(url.host() + url.directory(), QChar('/')); + + if(a_comparar.size() < referencia.size()) + return false; + else + { + for(uint i = 0; i != referencia.size(); ++i) + { + if(i == 0) + { // host, deal with specific function + if(!equalHost(referencia[i], a_comparar[i], !check_parent_dirs_)) + return false; + } + else if(referencia[i] != a_comparar[i]) + return false; + } + } + return true; + } + } + else if(checkParentDirs()) + return true; + else + return url_root.isParentOf(url); + } +*/ + +/** + The same as SearchManager::localDomain(), but only for http or https. + http://linkstatus.paradigma.co.pt != http://paradigma.co.pt +*/ +/* +bool SearchManager::isLocalRestrict(KURL const& url) const + { + Q_ASSERT(url.protocol() == "http" || url.protocol() == "https"); + + KURL url_root = root_.absoluteUrl(); + + if(url_root.protocol() != url.protocol()) + return false; + + if(url_root.hasHost()) + { + vector<QString> referencia = tokenizeWordsSeparatedBy(domain_, QChar('/')); + vector<QString> a_comparar = tokenizeWordsSeparatedBy(url.host() + url.directory(), QChar('/')); + + if(a_comparar.size() < referencia.size()) + return false; + else + { + for(uint i = 0; i != referencia.size(); ++i) + { + if(i == 0) + { // host, deal with specific function + if(!equalHost(referencia[i], a_comparar[i], true)) + return false; + } + else if(referencia[i] != a_comparar[i]) + return false; + } + } + return true; + } + else + return false; + } +*/ +bool SearchManager::generalDomain() const +{ + if(checked_general_domain_) + return general_domain_; + + else + { + Q_ASSERT(!domain_.isEmpty()); + + if(!check_parent_dirs_) + return false; + + int barra = domain_.find('/'); + if(barra != -1 && (uint)barra != domain_.length() - 1) + { + kdDebug(23100) << "Domain nao vago" << endl; + return false; + } + else + { + vector<QString> palavras = tokenizeWordsSeparatedByDots(domain_); + Q_ASSERT(palavras.size() >= 1); // host might be localhost + + QString primeira_palavra = palavras[0]; + if(primeira_palavra == "www") + { + Q_ASSERT(palavras.size() >= 3); + kdDebug(23100) << "Domain vago" << endl; + return true; + } + else if(palavras.size() == 2) + { + kdDebug(23100) << "Domain vago" << endl; + return true; + } + else + { + kdDebug(23100) << "Domain nao vago" << endl; + return false; + } + } + } +} + +bool SearchManager::onlyCheckHeader(LinkStatus* ls) const +{ + if(search_mode_ == depth) + return current_depth_ == depth_; + + else if(search_mode_ == domain) + return !ls->local() && + ls->externalDomainDepth() == external_domain_depth_ - 1; + + else + return + current_depth_ == depth_ || + (!ls->local() && + ls->externalDomainDepth() == external_domain_depth_ - 1); +} + +void SearchManager::slotSearchFinished() +{} + +void SearchManager::slotLinkCheckerFinnished(LinkChecker * checker) +{ + kdDebug(23100) << "deleting linkchecker" << endl; + + Q_ASSERT(checker); + //Q_ASSERT(checker->linkStatus()->checked()); + + delete checker; + checker = 0; +} + +KHTMLPart* SearchManager::htmlPart(QString const& key_url) const +{ + if(!html_parts_.contains(key_url)) + return 0; + + return html_parts_[key_url]; +} + +void SearchManager::addHtmlPart(QString const& key_url, KHTMLPart* html_part) +{ + Q_ASSERT(!key_url.isEmpty()); + Q_ASSERT(html_part); + + // FIXME configurable + if(html_parts_.count() > 150) + removeHtmlParts(); + + html_parts_.insert(key_url, html_part); +} + +void SearchManager::removeHtmlParts() +{ + KHTMLPartMap::Iterator it; + for(it = html_parts_.begin(); it != html_parts_.end(); ++it) + { + delete it.data(); + it.data() = 0; + } + + html_parts_.clear(); +} + +void SearchManager::save(QDomElement& element) const +{ + // <url> + QDomElement child_element = element.ownerDocument().createElement("url"); + child_element.appendChild(element.ownerDocument().createTextNode(root_.absoluteUrl().prettyURL())); + element.appendChild(child_element); + + // <recursively> + bool recursively = searchMode() == domain || depth_ > 0; + child_element = element.ownerDocument().createElement("recursively"); + child_element.appendChild(element.ownerDocument().createTextNode(recursively ? "true" : "false")); + element.appendChild(child_element); + + // <depth> + child_element = element.ownerDocument().createElement("depth"); + child_element.appendChild(element.ownerDocument(). + createTextNode(searchMode() == domain ? QString("Unlimited") : QString::number(depth_))); + element.appendChild(child_element); + + // <check_parent_folders> + child_element = element.ownerDocument().createElement("check_parent_folders"); + child_element.appendChild(element.ownerDocument(). + createTextNode(checkParentDirs() ? "true" : "false")); + element.appendChild(child_element); + + // <check_external_links> + child_element = element.ownerDocument().createElement("check_external_links"); + child_element.appendChild(element.ownerDocument(). + createTextNode(checkExternalLinks() ? "true" : "false")); + element.appendChild(child_element); + + // <check_regular_expression> + child_element = element.ownerDocument().createElement("check_regular_expression"); + child_element.setAttribute("check", checkRegularExpressions() ? "true" : "false"); + if(checkRegularExpressions()) + child_element.appendChild(element.ownerDocument(). + createTextNode(reg_exp_.pattern())); + element.appendChild(child_element); + + child_element = element.ownerDocument().createElement("link_list"); + element.appendChild(child_element); + + for(uint i = 0; i != search_results_.size(); ++i) + { + for(uint j = 0; j != search_results_[i].size() ; ++j) + { + for(uint l = 0; l != (search_results_[i])[j].size(); ++l) + { + LinkStatus* ls = ((search_results_[i])[j])[l]; + if(ls->checked()) + ls->save(child_element); + } + } + } +} + +QString SearchManager::toXML() const +{ + QDomDocument doc; + doc.appendChild(doc.createProcessingInstruction( "xml", + "version=\"1.0\" encoding=\"UTF-8\"")); + + QDomElement root = doc.createElement("klinkstatus"); + doc.appendChild(root); + + save(root); + + return doc.toString(4); +} + +#include "searchmanager.moc" |