summaryrefslogtreecommitdiffstats
path: root/fbreader/src/network/NetworkLinkCollection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'fbreader/src/network/NetworkLinkCollection.cpp')
-rw-r--r--fbreader/src/network/NetworkLinkCollection.cpp561
1 files changed, 0 insertions, 561 deletions
diff --git a/fbreader/src/network/NetworkLinkCollection.cpp b/fbreader/src/network/NetworkLinkCollection.cpp
deleted file mode 100644
index 0b530b0..0000000
--- a/fbreader/src/network/NetworkLinkCollection.cpp
+++ /dev/null
@@ -1,561 +0,0 @@
-/*
- * Copyright (C) 2008-2012 Geometer Plus <contact@geometerplus.com>
- *
- * 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 <cctype>
-#include <algorithm>
-
-#include <ZLFile.h>
-#include <ZLDir.h>
-#include <ZLStringUtil.h>
-#include <ZLUnicodeUtil.h>
-#include <ZLResource.h>
-#include <ZLNetworkManager.h>
-#include <ZLTimeManager.h>
-#include <ZLNetworkUtil.h>
-#include <ZLibrary.h>
-#include <ZLDialogManager.h>
-#include <ZLInputStream.h>
-#include <ZLOutputStream.h>
-#include "../fbreader/FBReader.h"
-#include "../networkActions/NetworkOperationRunnable.h"
-
-#include "NetworkLinkCollection.h"
-
-#include "../options/FBCategoryKey.h"
-
-#include "../database/networkdb/NetworkDB.h"
-
-#include "NetworkOperationData.h"
-#include "NetworkBookCollection.h"
-#include "BookReference.h"
-#include "NetworkErrors.h"
-
-#include "opds/OPDSLink.h"
-#include "opds/OPDSLink_GenericXMLParser.h"
-#include "opds/OPDSLink_GenericFeedReader.h"
-#include "opds/OPDSXMLParser.h"
-
-#include "opds/URLRewritingRule.h"
-
-NetworkLinkCollection *NetworkLinkCollection::ourInstance = 0;
-
-NetworkLinkCollection &NetworkLinkCollection::Instance() {
- if (ourInstance == 0) {
- ourInstance = new NetworkLinkCollection();
- }
- return *ourInstance;
-}
-
-class NetworkLinkCollection::Comparator {
-
-public:
- bool operator() (
- const shared_ptr<NetworkLink> &first,
- const shared_ptr<NetworkLink> &second
- ) const;
-
-private:
- std::string removeLeadingNonAscii(const std::string &title) const;
-};
-
-std::string NetworkLinkCollection::Comparator::removeLeadingNonAscii(const std::string &title) const {
- std::string str = title;
- std::string::iterator it = str.begin();
- for (; it != str.end(); ++it) {
- if ((*it & 0x80) == 0 && std::isalnum(*it)) {
- break;
- }
- }
- if (it != str.end()) {
- str.erase(str.begin(), it);
- }
- return str;
-}
-
-bool NetworkLinkCollection::Comparator::operator() (
- const shared_ptr<NetworkLink> &first,
- const shared_ptr<NetworkLink> &second
-) const {
- return
- removeLeadingNonAscii(first->getSiteName()) <
- removeLeadingNonAscii(second->getSiteName());
-}
-
-//void NetworkLinkCollection::deleteLink(NetworkLink& link) {
-// BooksDB::Instance().deleteNetworkLink(link.SiteName);
-// for (std::vector<shared_ptr<NetworkLink> >::iterator it = myLinks.begin(); it != myLinks.end(); ++it) {
-// if (&(**it) == &link) {
-// myLinks.erase(it);
-// break;
-// }
-// }
-// FBReader::Instance().refreshWindow();
-//}
-
-//void NetworkLinkCollection::saveLink(NetworkLink& link, bool isAuto) {
-// saveLinkWithoutRefreshing(link, isAuto);
-// FBReader::Instance().refreshWindow();
-//}
-
-void NetworkLinkCollection::addOrUpdateLink(shared_ptr<NetworkLink> link) {
- bool found = false;
- bool updated = false;
-
- for (std::size_t i = 0; i < myLinks.size(); ++i) {
- shared_ptr<NetworkLink> curLink = myLinks.at(i);
- if (curLink->getPredefinedId() == link->getPredefinedId()) {
- //if (*(link->getUpdated()) > *(curLink->getUpdated())) {
- myLinks.at(i) = link;
- updated = true;
- //TODO implement custom links saving
- found = true;
- break;
- }
- }
-
- if (!found) {
- myLinks.push_back(link);
- std::sort(myLinks.begin(), myLinks.end(), Comparator());
- updated = true;
- }
- if (updated) {
- NetworkDB::Instance().saveNetworkLink(link);
- //FBReader::Instance().sendRefresh();
- }
-}
-
-
-
-static const std::string LOADING_NETWORK_LIBRARY_LIST = "loadingNetworkLibraryList";
-
-class NetworkDownloadListRunnable : public NetworkOperationRunnable {
-public:
- NetworkDownloadListRunnable(ZLFile &tmpFile, const std::string &genericUrl) :
- NetworkOperationRunnable(LOADING_NETWORK_LIBRARY_LIST),
- myTmpFile(tmpFile),
- myGenericUrl(genericUrl) {
- }
-
-private:
- void run() {
- shared_ptr<ZLNetworkRequest> loadingRequest = ZLNetworkManager::Instance().createDownloadRequest(myGenericUrl, myTmpFile.physicalFilePath());
- myErrorMessage = ZLNetworkManager::Instance().perform(loadingRequest);
- }
-
-private:
- ZLFile &myTmpFile;
- std::string myGenericUrl;
-};
-
-
-class NetworkLinksUpdater : public ZLRunnable {
-
-public:
- NetworkLinksUpdater(NetworkLinkCollection &networkLinkCollection, shared_ptr<ZLFile> genericFile) :
- myNetworkLinkCollection(networkLinkCollection), myGenericFile(genericFile) { }
-
-private:
- void run() {
- std::vector<shared_ptr<NetworkLink> > links;
- shared_ptr<OPDSFeedReader> feedReader = new OPDSLink::GenericFeedReader(links);
- shared_ptr<ZLXMLReader> parser = new OPDSLink::GenericXMLParser(feedReader);
- parser->readDocument(*myGenericFile);
-
- for (std::vector<shared_ptr<NetworkLink> >::iterator it = links.begin(); it != links.end(); ++it) {
- myNetworkLinkCollection.addOrUpdateLink(*it);
- }
- }
-
-private:
- NetworkLinkCollection &myNetworkLinkCollection;
- shared_ptr<ZLFile> myGenericFile;
-};
-
-
-NetworkLinkCollection::NetworkLinkCollection() :
- DirectoryOption(ZLCategoryKey::NETWORK, "Options", "DownloadDirectory", ""),
- LastUpdateTimeOption(ZLCategoryKey::NETWORK, "Update", "LastUpdateTime", -1),
- myIsInitialized(false) {
-}
-
-class NetworkLinkCollectionSynchronizer : public DBRunnable {
-public:
- NetworkLinkCollectionSynchronizer(NetworkLinkCollection &collection) : myCollection(collection) {}
- bool run() {
- myCollection.synchronize();
- return true;
- }
-private:
- NetworkLinkCollection &myCollection;
-};
-
-void NetworkLinkCollection::initialize() {
- if (myIsInitialized) {
- return;
- }
- NetworkLinkCollectionSynchronizer runnable(*this);
- NetworkDB::Instance().executeAsTransaction(runnable);
-}
-
-void NetworkLinkCollection::synchronize() {
- NetworkDB::Instance().loadNetworkLinks(myLinks);
- std::sort(myLinks.begin(), myLinks.end(), Comparator());
- updateLinks("http://data.fbreader.org/catalogs/generic-1.9.xml");
-}
-
-void NetworkLinkCollection::updateLinks(std::string genericUrl) {
- shared_ptr<ZLFile> genericFile = getGenericFile(genericUrl);
- if (genericFile.isNull()) {
- NetworkErrors::showErrorMessage(NetworkErrors::errorMessage(NetworkErrors::ERROR_CANT_DOWNLOAD_LIBRARIES_LIST));
- return;
- }
-
- NetworkLinksUpdater updater(*this, genericFile);
- ZLDialogManager::Instance().wait(ZLResourceKey(LOADING_NETWORK_LIBRARY_LIST), updater);
- myIsInitialized = true;
-}
-
-shared_ptr<ZLFile> NetworkLinkCollection::getGenericFile(std::string genericUrl) {
- const std::string FILE_NAME = "fbreader_catalogs-" + genericUrl.substr(genericUrl.find_last_of('/') + 1);
- ZLFile genericFileDir(ZLNetworkManager::CacheDirectory());
- genericFileDir.directory(true);
- shared_ptr<ZLFile> genericFile = new ZLFile(ZLNetworkManager::CacheDirectory() + ZLibrary::FileNameDelimiter + FILE_NAME);
-
- long diff = LastUpdateTimeOption.value() == -1 ? -1 : ZLTime().millisecondsFrom(ZLTime(LastUpdateTimeOption.value(), 0));
-
- if (genericFile->exists() && diff != -1 && diff < 7 * 24 * 60 * 60 * 1000) { //1 week
- return genericFile;
- }
-
- ZLFile tmpFile(ZLNetworkManager::CacheDirectory() + ZLibrary::FileNameDelimiter + "tmp" + FILE_NAME);
- NetworkDownloadListRunnable runnable(tmpFile, genericUrl);
- runnable.executeWithUI();
- if (runnable.hasErrors()) {
- if (!genericFile->exists()) { //loading list from saved file even if obsolete
- return 0;
- } else {
- return genericFile;
- }
- }
-
- shared_ptr<ZLOutputStream> outputStream = genericFile->outputStream(true);
- shared_ptr<ZLInputStream> inputStream = tmpFile.inputStream();
- if (!outputStream->open() || !inputStream->open()) {
- tmpFile.remove();
- return 0;
- }
- char buffer[2048];
- std::size_t readed = 0;
- do {
- readed = inputStream->read(buffer, 2048);
- outputStream->write(buffer, readed);
- } while (readed > 0);
-
- LastUpdateTimeOption.setValue(ZLTime().inSeconds());
- return genericFile;
-}
-
-NetworkLinkCollection::~NetworkLinkCollection() {
-}
-
-static std::string normalize(const std::string &url) {
- static const std::string PREFIX0 = "http://feedbooks.com/";
- static const std::string PREFIX1 = "http://www.feedbooks.com/";
- static const std::string STANZA_PREFIX = "http://feedbooks.com/book/stanza/";
-
- std::string nURL = url;
- if (ZLStringUtil::stringStartsWith(nURL, PREFIX1)) {
- nURL = PREFIX0 + nURL.substr(PREFIX1.length());
- }
- if (ZLStringUtil::stringStartsWith(nURL, STANZA_PREFIX)) {
- nURL = PREFIX0 + "book/" + nURL.substr(STANZA_PREFIX.length()) + ".epub";
- }
- return nURL;
-}
-
-std::string NetworkLinkCollection::bookFileName(const BookReference &reference) {
- myErrorMessage.clear();
- return bookFileName(::normalize(reference.cleanURL()), reference.BookFormat, reference.ReferenceType);
-}
-
-static bool parseUrl(const std::string &url, std::string &hostAndPath, std::string &query) {
- std::size_t hostBegin = url.find("://");
- if (hostBegin == std::string::npos) {
- return false;
- }
- hostBegin += 3;
- if (!url.compare(hostBegin, 4, "www.")) {
- hostBegin += 4;
- }
- std::size_t pathEnd = url.find('?', hostBegin);
- hostAndPath = url.substr(hostBegin, pathEnd - hostBegin);
- if (pathEnd != std::string::npos) {
- query = url.substr(pathEnd + 1);
- }
- return true;
-}
-
-std::string NetworkLinkCollection::bookFileName(const std::string &url, BookReference::Format format, BookReference::Type type) {
- static const std::string escapeChars = "<>:\"|?*\\";
-
- std::string path;
- std::string query;
- if (!::parseUrl(url, path, query)) {
- return std::string();
- }
-
- std::string fileName = DirectoryOption.value();
- if (!ZLStringUtil::stringEndsWith(fileName, ZLibrary::FileNameDelimiter)) {
- fileName += ZLibrary::FileNameDelimiter;
- }
- if (type == BookReference::DOWNLOAD_DEMO) {
- fileName += "Demos" + ZLibrary::FileNameDelimiter;
- }
-
- for (std::size_t i = 0; i < path.size(); ++i) {
- char ch = path[i];
- if (escapeChars.find(ch) != std::string::npos) {
- path[i] = '_';
- }
- if (ch == '/') {
- path[i] = ZLibrary::FileNameDelimiter[0];
- }
- }
-
- const std::size_t nameIndex = path.find_last_of(ZLibrary::FileNameDelimiter);
- if (nameIndex + 1 == path.length()) {
- path.resize(path.length() - 1); //removing ending / if exists
- }
-
- std::string ext;
- switch (format) {
- case BookReference::EPUB:
- ext = ".epub";
- break;
- case BookReference::MOBIPOCKET:
- ext = ".mobi";
- break;
- case BookReference::FB2_ZIP:
- ext = ".fb2.zip";
- break;
- case BookReference::NONE:
- break;
- }
- if (ext.empty()) {
- std::size_t tmp = path.find('.', nameIndex); // using not find_last_of to preserve extensions like `.fb2.zip`
- if (tmp == std::string::npos) {
- return std::string();
- }
- ext = path.substr(tmp);
- path.resize(tmp);
- } else if (ZLStringUtil::stringEndsWith(path, ext)) {
- path.resize(path.size() - ext.size());
- }
-
- if (!query.empty()) {
- std::size_t index = 0;
- while (index < query.size()) {
- std::size_t j = query.find('&', index);
- if (j == std::string::npos) {
- j = query.size();
- }
- std::string param = query.substr(index, j);
- if (!ZLStringUtil::stringStartsWith(param, "username=")
- && !ZLStringUtil::stringStartsWith(param, "password=")
- && !ZLStringUtil::stringEndsWith(param, "=")) {
- std::size_t k = path.size();
- path.append("_").append(param);
- while (k < path.size()) {
- char ch = path[k];
- if (escapeChars.find(ch) != std::string::npos || ch == '/') {
- path[k] = '_';
- }
- ++k;
- }
- }
- index = j + 1;
- }
- }
- fileName.append(path);
- fileName.append(ext);
- return fileName;
-}
-
-
-bool NetworkLinkCollection::downloadBook(const BookReference &reference, std::string &fileName, shared_ptr<ZLNetworkRequest::Listener> listener) {
- std::string nURL = ::normalize(reference.URL);
- rewriteUrl(nURL);
- const std::string nNetworkBookId = ::normalize(reference.cleanURL());
- const ZLResource &errorResource = ZLResource::resource("dialog")["networkError"];
- myErrorMessage.clear();
-
- if (nURL.empty() || nNetworkBookId.empty()) {
- myErrorMessage = errorResource["unknownErrorMessage"].value();
- return false;
- }
- fileName = bookFileName(nNetworkBookId, reference.BookFormat, reference.ReferenceType);
-
- //creating directory if not existed
- const std::size_t directoryIndex = fileName.find_last_of(ZLibrary::FileNameDelimiter);
- ZLFile(fileName.substr(0, directoryIndex)).directory(true);
-
- if (ZLFile(fileName).exists()) {
- return true;
- }
- if (fileName.empty()) {
- if (myErrorMessage.empty()) {
- myErrorMessage = errorResource["unknownErrorMessage"].value();
- }
- return false;
- }
- if (ZLFile(fileName).exists()) {
- ZLFile(fileName).remove();
- }
- ZLNetworkManager::Instance().downloadFile(nURL, fileName, listener);
- return true;
-}
-
-shared_ptr<NetworkBookCollection> NetworkLinkCollection::simpleSearch(const std::string &pattern) {
- ZLNetworkRequest::Vector dataList;
- std::vector<shared_ptr<NetworkOperationData> > opDataVector;
- shared_ptr<NetworkBookCollection> result;
-
- myErrorMessage.clear();
-
- for (std::vector<shared_ptr<NetworkLink> >::const_iterator it = myLinks.begin(); it != myLinks.end(); ++it) {
- NetworkLink &link = **it;
- if (link.isEnabled()) {
- shared_ptr<NetworkOperationData> opData = new NetworkOperationData(link);
- opDataVector.push_back(opData);
- shared_ptr<ZLNetworkRequest> data = link.simpleSearchData(*opData, pattern);
- if (!data.isNull()) {
- dataList.push_back(data);
- }
- }
- }
-
- while (myErrorMessage.empty() && !dataList.empty()) {
- myErrorMessage = ZLNetworkManager::Instance().perform(dataList);
-
- for (std::vector<shared_ptr<NetworkOperationData> >::const_iterator jt = opDataVector.begin(); jt != opDataVector.end(); ++jt) {
- NetworkOperationData &opData = **jt;
- if (!opData.Items.empty() && result.isNull()) {
- result = new NetworkBookCollection();
- }
- for (NetworkItem::List::const_iterator kt = opData.Items.begin(); kt != opData.Items.end(); ++kt) {
- result->addBook(*kt);
- }
- }
-
- dataList.clear();
-
- for (std::vector<shared_ptr<NetworkOperationData> >::const_iterator jt = opDataVector.begin(); jt != opDataVector.end(); ++jt) {
- shared_ptr<ZLNetworkRequest> data = (*jt)->resume();
- if (!data.isNull()) {
- dataList.push_back(data);
- }
- }
- }
-
- return result;
-}
-
-shared_ptr<NetworkBookCollection> NetworkLinkCollection::advancedSearch(const std::string &titleAndSeries, const std::string &author, const std::string &tag, const std::string &annotation) {
- ZLNetworkRequest::Vector dataList;
- std::vector<shared_ptr<NetworkOperationData> > opDataVector;
- shared_ptr<NetworkBookCollection> result;
-
- myErrorMessage.clear();
-
- for (std::vector<shared_ptr<NetworkLink> >::const_iterator it = myLinks.begin(); it != myLinks.end(); ++it) {
- NetworkLink &link = **it;
- if (link.isEnabled()) {
- shared_ptr<NetworkOperationData> opData = new NetworkOperationData(link);
- opDataVector.push_back(opData);
- shared_ptr<ZLNetworkRequest> data = link.advancedSearchData(*opData, titleAndSeries, author, tag, annotation);
- if (!data.isNull()) {
- dataList.push_back(data);
- }
- }
- }
-
- while (myErrorMessage.empty() && !dataList.empty()) {
- myErrorMessage = ZLNetworkManager::Instance().perform(dataList);
-
- for (std::vector<shared_ptr<NetworkOperationData> >::const_iterator jt = opDataVector.begin(); jt != opDataVector.end(); ++jt) {
- NetworkOperationData &opData = **jt;
- if (!opData.Items.empty() && result.isNull()) {
- result = new NetworkBookCollection();
- }
- for (NetworkItem::List::const_iterator kt = opData.Items.begin(); kt != opData.Items.end(); ++kt) {
- result->addBook(*kt);
- }
- }
-
- dataList.clear();
-
- for (std::vector<shared_ptr<NetworkOperationData> >::const_iterator jt = opDataVector.begin(); jt != opDataVector.end(); ++jt) {
- shared_ptr<ZLNetworkRequest> data = (*jt)->resume();
- if (!data.isNull()) {
- dataList.push_back(data);
- }
- }
- }
-
- return result;
-}
-
-NetworkLinkCollection::LinkVector NetworkLinkCollection::activeLinks() const {
- LinkVector filteredList;
- for (std::size_t i = 0; i < myLinks.size(); ++i) {
- shared_ptr<NetworkLink> link = myLinks.at(i);
- if (link->isEnabled()) {
- filteredList.push_back(link);
- }
- }
- return filteredList;
-}
-
-std::size_t NetworkLinkCollection::size() const {
- return myLinks.size();
-}
-
-NetworkLink &NetworkLinkCollection::link(std::size_t index) const {
- return *myLinks[index];
-}
-
-std::size_t NetworkLinkCollection::numberOfEnabledLinks() const {
- std::size_t count = 0;
- for (std::vector<shared_ptr<NetworkLink> >::const_iterator it = myLinks.begin(); it != myLinks.end(); ++it) {
- if ((*it)->isEnabled()) {
- ++count;
- }
- }
- return count;
-}
-
-void NetworkLinkCollection::rewriteUrl(std::string &url, bool externalUrl) const {
- const std::string host =
- ZLUnicodeUtil::toLower(ZLNetworkUtil::hostFromUrl(url));
- for (std::vector<shared_ptr<NetworkLink> >::const_iterator it = myLinks.begin(); it != myLinks.end(); ++it) {
- if (host.find((*it)->getSiteName()) != std::string::npos) {
- (*it)->rewriteUrl(url, externalUrl);
- }
- }
-}