summaryrefslogtreecommitdiffstats
path: root/fbreader/src/network
diff options
context:
space:
mode:
Diffstat (limited to 'fbreader/src/network')
-rw-r--r--fbreader/src/network/BookReference.cpp60
-rw-r--r--fbreader/src/network/BookReference.h87
-rw-r--r--fbreader/src/network/NetworkBookCollection.cpp71
-rw-r--r--fbreader/src/network/NetworkBookCollection.h60
-rw-r--r--fbreader/src/network/NetworkBookItem.cpp191
-rw-r--r--fbreader/src/network/NetworkCatalogItem.cpp91
-rw-r--r--fbreader/src/network/NetworkComparators.cpp120
-rw-r--r--fbreader/src/network/NetworkComparators.h57
-rw-r--r--fbreader/src/network/NetworkErrors.cpp70
-rw-r--r--fbreader/src/network/NetworkErrors.h60
-rw-r--r--fbreader/src/network/NetworkItem.cpp37
-rw-r--r--fbreader/src/network/NetworkItems.h202
-rw-r--r--fbreader/src/network/NetworkLink.cpp146
-rw-r--r--fbreader/src/network/NetworkLink.h109
-rw-r--r--fbreader/src/network/NetworkLinkCollection.cpp561
-rw-r--r--fbreader/src/network/NetworkLinkCollection.h101
-rw-r--r--fbreader/src/network/NetworkOperationData.cpp37
-rw-r--r--fbreader/src/network/NetworkOperationData.h45
-rw-r--r--fbreader/src/network/SearchResult.cpp36
-rw-r--r--fbreader/src/network/SearchResult.h49
-rw-r--r--fbreader/src/network/UserList.cpp85
-rw-r--r--fbreader/src/network/UserList.h44
-rw-r--r--fbreader/src/network/atom/ATOMConstructs.cpp339
-rw-r--r--fbreader/src/network/atom/ATOMConstructs.h135
-rw-r--r--fbreader/src/network/atom/ATOMContainers.cpp49
-rw-r--r--fbreader/src/network/atom/ATOMContainers.h142
-rw-r--r--fbreader/src/network/atom/ATOMMetadata.cpp202
-rw-r--r--fbreader/src/network/atom/ATOMMetadata.h221
-rw-r--r--fbreader/src/network/authentication/NetworkAuthenticationManager.cpp80
-rw-r--r--fbreader/src/network/authentication/NetworkAuthenticationManager.h88
-rw-r--r--fbreader/src/network/authentication/litres/LitResAuthenticationDataParser.cpp158
-rw-r--r--fbreader/src/network/authentication/litres/LitResAuthenticationDataParser.h107
-rw-r--r--fbreader/src/network/authentication/litres/LitResAuthenticationManager.cpp472
-rw-r--r--fbreader/src/network/authentication/litres/LitResAuthenticationManager.h93
-rw-r--r--fbreader/src/network/litres/LitResAuthorsItem.cpp111
-rw-r--r--fbreader/src/network/litres/LitResAuthorsItem.h51
-rw-r--r--fbreader/src/network/litres/LitResAuthorsParser.cpp185
-rw-r--r--fbreader/src/network/litres/LitResAuthorsParser.h83
-rw-r--r--fbreader/src/network/litres/LitResBookItem.cpp70
-rw-r--r--fbreader/src/network/litres/LitResBookItem.h53
-rw-r--r--fbreader/src/network/litres/LitResBooksFeedItem.cpp128
-rw-r--r--fbreader/src/network/litres/LitResBooksFeedItem.h60
-rw-r--r--fbreader/src/network/litres/LitResBooksFeedParser.cpp433
-rw-r--r--fbreader/src/network/litres/LitResBooksFeedParser.h89
-rw-r--r--fbreader/src/network/litres/LitResBookshelfItem.cpp111
-rw-r--r--fbreader/src/network/litres/LitResBookshelfItem.h51
-rw-r--r--fbreader/src/network/litres/LitResByGenresItem.cpp71
-rw-r--r--fbreader/src/network/litres/LitResByGenresItem.h47
-rw-r--r--fbreader/src/network/litres/LitResGenre.cpp206
-rw-r--r--fbreader/src/network/litres/LitResGenre.h66
-rw-r--r--fbreader/src/network/litres/LitResGenresParser.cpp81
-rw-r--r--fbreader/src/network/litres/LitResGenresParser.h56
-rw-r--r--fbreader/src/network/litres/LitResRecommendationsItem.cpp51
-rw-r--r--fbreader/src/network/litres/LitResRecommendationsItem.h40
-rw-r--r--fbreader/src/network/litres/LitResUtil.cpp178
-rw-r--r--fbreader/src/network/litres/LitResUtil.h54
-rw-r--r--fbreader/src/network/litres/SortedCatalogItem.cpp49
-rw-r--r--fbreader/src/network/litres/SortedCatalogItem.h100
-rw-r--r--fbreader/src/network/opds/NetworkOPDSFeedReader.cpp198
-rw-r--r--fbreader/src/network/opds/NetworkOPDSFeedReader.h60
-rw-r--r--fbreader/src/network/opds/OPDSBookItem.cpp310
-rw-r--r--fbreader/src/network/opds/OPDSBookItem.h88
-rw-r--r--fbreader/src/network/opds/OPDSCatalogItem.cpp81
-rw-r--r--fbreader/src/network/opds/OPDSCatalogItem.h51
-rw-r--r--fbreader/src/network/opds/OPDSFeedReader.h40
-rw-r--r--fbreader/src/network/opds/OPDSLink.cpp216
-rw-r--r--fbreader/src/network/opds/OPDSLink.h112
-rw-r--r--fbreader/src/network/opds/OPDSLink_AdvancedSearch.h72
-rw-r--r--fbreader/src/network/opds/OPDSLink_GenericFeedReader.cpp134
-rw-r--r--fbreader/src/network/opds/OPDSLink_GenericFeedReader.h61
-rw-r--r--fbreader/src/network/opds/OPDSLink_GenericXMLParser.cpp109
-rw-r--r--fbreader/src/network/opds/OPDSLink_GenericXMLParser.h35
-rw-r--r--fbreader/src/network/opds/OPDSMetadata.cpp89
-rw-r--r--fbreader/src/network/opds/OPDSMetadata.h139
-rw-r--r--fbreader/src/network/opds/OPDSXMLParser.cpp554
-rw-r--r--fbreader/src/network/opds/OPDSXMLParser.h79
-rw-r--r--fbreader/src/network/opds/OpenSearchXMLReader.cpp49
-rw-r--r--fbreader/src/network/opds/OpenSearchXMLReader.h42
-rw-r--r--fbreader/src/network/opds/URLRewritingRule.cpp77
-rw-r--r--fbreader/src/network/opds/URLRewritingRule.h50
-rw-r--r--fbreader/src/network/tree/NetworkAuthorTree.cpp53
-rw-r--r--fbreader/src/network/tree/NetworkBookTree.cpp262
-rw-r--r--fbreader/src/network/tree/NetworkCatalogRootTree.cpp265
-rw-r--r--fbreader/src/network/tree/NetworkCatalogTree.cpp292
-rw-r--r--fbreader/src/network/tree/NetworkCatalogUtil.cpp92
-rw-r--r--fbreader/src/network/tree/NetworkCatalogUtil.h45
-rw-r--r--fbreader/src/network/tree/NetworkLibrary.cpp101
-rw-r--r--fbreader/src/network/tree/NetworkLibrary.h57
-rw-r--r--fbreader/src/network/tree/NetworkSearcher.cpp179
-rw-r--r--fbreader/src/network/tree/NetworkSearcher.h59
-rw-r--r--fbreader/src/network/tree/NetworkSeriesTree.cpp72
-rw-r--r--fbreader/src/network/tree/NetworkTree.cpp31
-rw-r--r--fbreader/src/network/tree/NetworkTreeFactory.cpp123
-rw-r--r--fbreader/src/network/tree/NetworkTreeFactory.h42
-rw-r--r--fbreader/src/network/tree/NetworkTreeNodes.h275
-rw-r--r--fbreader/src/network/tree/RootTree.cpp42
-rw-r--r--fbreader/src/network/tree/SearchCatalogTree.cpp41
97 files changed, 11506 insertions, 0 deletions
diff --git a/fbreader/src/network/BookReference.cpp b/fbreader/src/network/BookReference.cpp
new file mode 100644
index 0000000..9740a65
--- /dev/null
+++ b/fbreader/src/network/BookReference.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 <ZLFile.h>
+
+#include "BookReference.h"
+#include "NetworkLinkCollection.h"
+
+BookReference::BookReference(const std::string &url, Format format, Type type) : URL(url), BookFormat(format), ReferenceType(type) {
+}
+
+const std::string &BookReference::cleanURL() const {
+ return URL;
+}
+
+std::string BuyBookReference::price(const std::string &price, const std::string &currency) {
+ if (currency.empty()) {
+ return price;
+ } else if (currency == "RUB") {
+ return price + " р.";
+ } else if (currency == "USD") {
+ return "$" + price;
+ }
+ return currency + " " + price;
+}
+
+BuyBookReference::BuyBookReference(const std::string &url, Format format, Type type, const std::string &price) : BookReference(url, format, type), Price(price) {
+}
+
+DecoratedBookReference::DecoratedBookReference(const BookReference &base, const std::string &url) : BookReference(url, base.BookFormat, base.ReferenceType), myCleanURL(base.cleanURL()) {
+}
+
+const std::string &DecoratedBookReference::cleanURL() const {
+ return myCleanURL;
+}
+
+std::string BookReference::localCopyFileName() const {
+ std::string fileName = NetworkLinkCollection::Instance().bookFileName(*this);
+ if (!fileName.empty() && ZLFile(fileName).exists()) {
+ return fileName;
+ }
+
+ return std::string();
+}
diff --git a/fbreader/src/network/BookReference.h b/fbreader/src/network/BookReference.h
new file mode 100644
index 0000000..7b7ef74
--- /dev/null
+++ b/fbreader/src/network/BookReference.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __BOOKREFERENCE_H__
+#define __BOOKREFERENCE_H__
+
+#include <string>
+
+class BookReference {
+
+public:
+ enum Type {
+ DOWNLOAD_FULL,
+ DOWNLOAD_FULL_CONDITIONAL,
+ DOWNLOAD_DEMO,
+ DOWNLOAD_FULL_OR_DEMO,
+ BUY,
+ BUY_IN_BROWSER,
+ UNKNOWN
+ };
+
+ enum Format {
+ NONE = 0,
+ MOBIPOCKET = 1,
+ FB2_ZIP = 2,
+ EPUB = 3,
+ };
+
+public:
+ BookReference(const std::string &url, Format format, Type type);
+
+public:
+ const std::string URL;
+ const Format BookFormat;
+ const Type ReferenceType;
+
+public:
+ virtual const std::string &cleanURL() const;
+
+ std::string localCopyFileName() const;
+
+private:
+ BookReference(const BookReference&);
+ const BookReference &operator = (const BookReference&);
+};
+
+class BuyBookReference : public BookReference {
+
+public:
+ BuyBookReference(const std::string &url, Format format, Type type, const std::string &price);
+
+public:
+ static std::string price(const std::string &price, const std::string &currency);
+
+public:
+ const std::string Price;
+};
+
+class DecoratedBookReference : public BookReference {
+
+public:
+ DecoratedBookReference(const BookReference &base, const std::string &url);
+
+private:
+ const std::string &cleanURL() const;
+
+private:
+ const std::string myCleanURL;
+};
+
+#endif /* __BOOKREFERENCE_H__ */
diff --git a/fbreader/src/network/NetworkBookCollection.cpp b/fbreader/src/network/NetworkBookCollection.cpp
new file mode 100644
index 0000000..155d702
--- /dev/null
+++ b/fbreader/src/network/NetworkBookCollection.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 <algorithm>
+
+#include <ZLResource.h>
+
+#include "NetworkBookCollection.h"
+
+
+NetworkBookCollection::NetworkBookCollection() {
+ myAuthorComparator = new NetworkAuthorComparator(myAuthorRates);
+}
+
+void NetworkBookCollection::clear() {
+ myBookList.clear();
+ myAuthorRates.clear();
+ myAuthorBooksMap.reset();
+}
+
+void NetworkBookCollection::addBook(shared_ptr<NetworkItem> bookPtr) {
+ if (bookPtr.isNull() || bookPtr->typeId() != NetworkBookItem::TYPE_ID) {
+ return;
+ }
+ myAuthorBooksMap.reset();
+
+ NetworkItem::List::iterator it = std::upper_bound(myBookList.begin(), myBookList.end(), bookPtr, NetworkBookItemComparator());
+ myBookList.insert(it, bookPtr);
+
+ NetworkBookItem &book = (NetworkBookItem &) *bookPtr;
+
+ for (std::vector<NetworkBookItem::AuthorData>::const_iterator jt = book.Authors.begin(); jt != book.Authors.end(); ++jt) {
+ const NetworkBookItem::AuthorData &author = *jt;
+ std::map<NetworkBookItem::AuthorData, unsigned int>::iterator kt = myAuthorRates.find(author);
+ if (kt == myAuthorRates.end()) {
+ myAuthorRates[author] = book.Index;
+ } else if (kt->second > book.Index) {
+ kt->second = book.Index;
+ }
+ }
+}
+
+const NetworkAuthorBooksMap &NetworkBookCollection::authorBooksMap() {
+ if (myAuthorBooksMap.isNull()) {
+ myAuthorBooksMap = new NetworkAuthorBooksMap(*myAuthorComparator);
+ NetworkAuthorBooksMap &bookMap = *myAuthorBooksMap;
+ for (NetworkItem::List::const_iterator it = myBookList.begin(); it != myBookList.end(); ++it) {
+ NetworkBookItem &book = (NetworkBookItem &) **it;
+ for (std::vector<NetworkBookItem::AuthorData>::const_iterator jt = book.Authors.begin(); jt != book.Authors.end(); ++jt) {
+ bookMap[*jt].push_back(*it);
+ }
+ }
+ }
+ return *myAuthorBooksMap;
+}
diff --git a/fbreader/src/network/NetworkBookCollection.h b/fbreader/src/network/NetworkBookCollection.h
new file mode 100644
index 0000000..730416e
--- /dev/null
+++ b/fbreader/src/network/NetworkBookCollection.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __NETWORKBOOKCOLLECTION_H__
+#define __NETWORKBOOKCOLLECTION_H__
+
+#include "NetworkItems.h"
+
+#include "NetworkComparators.h"
+
+
+typedef std::map<NetworkBookItem::AuthorData, NetworkItem::List, NetworkAuthorComparator> NetworkAuthorBooksMap;
+
+
+class NetworkBookCollection {
+
+public:
+ NetworkBookCollection();
+
+public:
+ void addBook(shared_ptr<NetworkItem> bookPtr);
+
+ const NetworkItem::List &books() const;
+ bool empty() const;
+
+ void clear();
+
+ const NetworkAuthorBooksMap &authorBooksMap();
+
+private:
+ NetworkItem::List myBookList;
+ std::map<NetworkBookItem::AuthorData, unsigned int> myAuthorRates;
+ shared_ptr<NetworkAuthorComparator> myAuthorComparator;
+ shared_ptr<NetworkAuthorBooksMap> myAuthorBooksMap;
+
+private: // disable copying
+ NetworkBookCollection(const NetworkBookCollection &);
+ const NetworkBookCollection &operator = (const NetworkBookCollection &);
+};
+
+inline const NetworkItem::List &NetworkBookCollection::books() const { return myBookList; }
+inline bool NetworkBookCollection::empty() const { return myBookList.empty(); }
+
+#endif /* __NETWORKBOOKCOLLECTION_H__ */
diff --git a/fbreader/src/network/NetworkBookItem.cpp b/fbreader/src/network/NetworkBookItem.cpp
new file mode 100644
index 0000000..5eeb101
--- /dev/null
+++ b/fbreader/src/network/NetworkBookItem.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 "NetworkItems.h"
+#include "NetworkLink.h"
+#include "authentication/NetworkAuthenticationManager.h"
+
+const ZLTypeId NetworkBookItem::TYPE_ID(NetworkItem::TYPE_ID);
+
+bool NetworkBookItem::AuthorData::operator < (const AuthorData &data) const {
+ const int sComp = SortKey.compare(data.SortKey);
+ return (sComp < 0) || (sComp == 0 && DisplayName < data.DisplayName);
+}
+
+bool NetworkBookItem::AuthorData::operator != (const NetworkBookItem::AuthorData &data) const {
+ return DisplayName != data.DisplayName || SortKey != data.SortKey;
+}
+
+bool NetworkBookItem::AuthorData::operator == (const NetworkBookItem::AuthorData &data) const {
+ return DisplayName == data.DisplayName && SortKey == data.SortKey;
+}
+
+NetworkBookItem::NetworkBookItem(
+ const NetworkLink &link,
+ const std::string &id,
+ unsigned int index,
+ const std::string &title,
+ const std::string &summary,
+ const std::string &language,
+ const std::string &date,
+ const std::vector<AuthorData> &authors,
+ const std::vector<std::string> &tags,
+ const std::string &seriesTitle,
+ unsigned int indexInSeries,
+ const UrlInfoCollection &urlByType,
+ const std::vector<shared_ptr<BookReference> > references
+) :
+ NetworkItem(link, title, summary, urlByType),
+ Index(index),
+ Id(id),
+ Language(language),
+ Date(date),
+ Authors(authors),
+ Tags(tags),
+ SeriesTitle(seriesTitle),
+ IndexInSeries(indexInSeries),
+ myReferences(references) {
+}
+
+NetworkBookItem::NetworkBookItem(const NetworkBookItem &book, unsigned int index) :
+ NetworkItem(book.Link, book.Title, book.Summary, book.URLByType),
+ Index(index),
+ Id(book.Id),
+ Language(book.Language),
+ Date(book.Date),
+ Authors(book.Authors),
+ Tags(book.Tags),
+ SeriesTitle(book.SeriesTitle),
+ IndexInSeries(book.IndexInSeries) {
+}
+
+const ZLTypeId &NetworkBookItem::typeId() const {
+ return TYPE_ID;
+}
+
+shared_ptr<BookReference> NetworkBookItem::reference(BookReference::Type type) const {
+ shared_ptr<BookReference> reference;
+ for (std::vector<shared_ptr<BookReference> >::const_iterator it = myReferences.begin(); it != myReferences.end(); ++it) {
+ if ((*it)->ReferenceType == type &&
+ (reference.isNull() || (*it)->BookFormat > reference->BookFormat)) {
+ reference = *it;
+ }
+ }
+
+ if (reference.isNull() && type == BookReference::DOWNLOAD_FULL) {
+ reference = this->reference(BookReference::DOWNLOAD_FULL_CONDITIONAL);
+ if (!reference.isNull()) {
+ shared_ptr<NetworkAuthenticationManager> authManager =
+ Link.authenticationManager();
+ if (authManager.isNull() || authManager->needPurchase(*this)) {
+ return 0;
+ }
+ reference = authManager->downloadReference(*this);
+ }
+ }
+
+ if (reference.isNull() &&
+ type == BookReference::DOWNLOAD_FULL &&
+ this->reference(BookReference::BUY).isNull() &&
+ this->reference(BookReference::BUY_IN_BROWSER).isNull()) {
+ reference = this->reference(BookReference::DOWNLOAD_FULL_OR_DEMO);
+ }
+
+ if (reference.isNull() &&
+ type == BookReference::DOWNLOAD_DEMO &&
+ (!this->reference(BookReference::BUY).isNull() ||
+ !this->reference(BookReference::BUY_IN_BROWSER).isNull())) {
+ reference = this->reference(BookReference::DOWNLOAD_FULL_OR_DEMO);
+ }
+
+ return reference;
+}
+
+std::string NetworkBookItem::localCopyFileName() const {
+ const bool hasBuyReference =
+ !this->reference(BookReference::BUY).isNull() ||
+ !this->reference(BookReference::BUY_IN_BROWSER).isNull();
+ shared_ptr<BookReference> reference;
+ std::string fileName;
+ for (std::vector<shared_ptr<BookReference> >::const_iterator it = myReferences.begin(); it != myReferences.end(); ++it) {
+ const BookReference::Type type = (*it)->ReferenceType;
+ if ((type == BookReference::DOWNLOAD_FULL ||
+ type == BookReference::DOWNLOAD_FULL_CONDITIONAL ||
+ (!hasBuyReference && type == BookReference::DOWNLOAD_FULL_OR_DEMO)) &&
+ (reference.isNull() || (*it)->BookFormat > reference->BookFormat)) {
+ std::string name = (*it)->localCopyFileName();
+ if (!name.empty()) {
+ reference = *it;
+ fileName = name;
+ }
+ }
+ }
+ return fileName;
+}
+
+void NetworkBookItem::removeLocalFiles() const {
+ const bool hasBuyReference =
+ !this->reference(BookReference::BUY).isNull() ||
+ !this->reference(BookReference::BUY_IN_BROWSER).isNull();
+ for (std::vector<shared_ptr<BookReference> >::const_iterator it = myReferences.begin(); it != myReferences.end(); ++it) {
+ const BookReference::Type type = (*it)->ReferenceType;
+ if (type == BookReference::DOWNLOAD_FULL ||
+ type == BookReference::DOWNLOAD_FULL_CONDITIONAL ||
+ (!hasBuyReference && type == BookReference::DOWNLOAD_FULL_OR_DEMO)) {
+ std::string fileName = (*it)->localCopyFileName();
+ if (!fileName.empty()) {
+ // TODO: remove a book from the library
+ // TODO: remove a record from the database
+ ZLFile(fileName).remove();
+ }
+ }
+ }
+}
+
+bool NetworkBookItem::isFullyLoaded() const {
+ return true;
+}
+
+void NetworkBookItem::loadFullInformation(shared_ptr<ZLNetworkRequest::Listener> listener) {
+ listener->finished();
+}
+
+std::vector<shared_ptr<NetworkItem> > NetworkBookItem::getRelatedCatalogsItems() const {
+ return std::vector<shared_ptr<NetworkItem> >();
+}
+
+void NetworkBookItem::updateReferences(const std::vector<shared_ptr<BookReference> > &references) {
+ //TODO implement using one UrlInfoCollection instead of vector of references and urlByType
+ for (std::size_t i = 0; i < references.size(); ++i) {
+ bool found = false;
+ const shared_ptr<BookReference> newRef = references.at(i);
+ for (std::size_t j = 0; j < myReferences.size(); ++j) {
+ shared_ptr<BookReference> ref = myReferences.at(j);
+ if (ref->ReferenceType == newRef->ReferenceType && ref->BookFormat == ref->BookFormat) {
+ //TODO maybe implement a supporting of new urls with same book format & reference type:
+ //ref->URL = newRef->URL;
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ myReferences.push_back(newRef);
+ }
+ }
+}
diff --git a/fbreader/src/network/NetworkCatalogItem.cpp b/fbreader/src/network/NetworkCatalogItem.cpp
new file mode 100644
index 0000000..58c739c
--- /dev/null
+++ b/fbreader/src/network/NetworkCatalogItem.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 "authentication/NetworkAuthenticationManager.h"
+#include "NetworkLink.h"
+
+#include "NetworkItems.h"
+
+const ZLTypeId NetworkCatalogItem::TYPE_ID(NetworkItem::TYPE_ID);
+
+NetworkCatalogItem::NetworkCatalogItem(
+ const NetworkLink &link,
+ const std::string &title,
+ const std::string &summary,
+ const UrlInfoCollection &urlByType,
+ AccessibilityType accessibility,
+ int flags
+) :
+ NetworkItem(link, title, summary, urlByType),
+ myAccessibility(accessibility),
+ myFlags(flags)
+ {
+}
+
+const ZLTypeId &NetworkCatalogItem::typeId() const {
+ return TYPE_ID;
+}
+
+void NetworkCatalogItem::onDisplayItem() {
+}
+
+bool NetworkCatalogItem::supportsResumeLoading() {
+ return false;
+}
+
+std::string NetworkCatalogItem::resumeLoading(NetworkItem::List &/*children*/, shared_ptr<ZLNetworkRequest::Listener> listener) {
+ listener->finished();
+ return std::string();
+}
+
+std::string NetworkCatalogItem::getCatalogUrl() {
+ return URLByType[URL_CATALOG];
+}
+
+int NetworkCatalogItem::getFlags() const {
+ return myFlags;
+}
+
+NetworkCatalogItem::AccessibilityType NetworkCatalogItem::getAccessibility() const {
+ return myAccessibility;
+}
+
+ZLBoolean3 NetworkCatalogItem::getVisibility() const {
+ shared_ptr<NetworkAuthenticationManager> mgr = Link.authenticationManager();
+ switch (myAccessibility) {
+ case ALWAYS:
+ return B3_TRUE;
+ case SIGNED_IN:
+ if (mgr.isNull()) {
+ return B3_FALSE;
+ }
+ return mgr->isAuthorised().Status == B3_TRUE ? B3_TRUE : B3_UNDEFINED;
+ case HAS_BOOKS:
+ if (mgr.isNull()) {
+ return B3_FALSE;
+ } else {
+ if (mgr->purchasedBooks().size() > 0) {
+ return B3_TRUE;
+ } else {
+ return B3_FALSE;
+ }
+ }
+ }
+ return B3_FALSE;
+}
diff --git a/fbreader/src/network/NetworkComparators.cpp b/fbreader/src/network/NetworkComparators.cpp
new file mode 100644
index 0000000..66a0de3
--- /dev/null
+++ b/fbreader/src/network/NetworkComparators.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 "NetworkComparators.h"
+
+bool NetworkBookItemComparator::operator () (const shared_ptr<NetworkItem> &bookPtr0, const shared_ptr<NetworkItem> &bookPtr1) const {
+ const bool book0isABook =
+ bookPtr0->isInstanceOf(NetworkBookItem::TYPE_ID);
+ const bool book1isABook =
+ bookPtr1->isInstanceOf(NetworkBookItem::TYPE_ID);
+
+ if (!book0isABook && !book1isABook) {
+ return bookPtr0->Title < bookPtr1->Title;
+ }
+ if (!book0isABook || !book1isABook) {
+ return !book0isABook;
+ }
+
+ const NetworkBookItem &book0 = (NetworkBookItem &) *bookPtr0;
+ const NetworkBookItem &book1 = (NetworkBookItem &) *bookPtr1;
+
+ const std::vector<NetworkBookItem::AuthorData> &authors0 = book0.Authors;
+ const std::vector<NetworkBookItem::AuthorData> &authors1 = book1.Authors;
+ if (authors0.empty() && !authors1.empty()) {
+ return true;
+ }
+ if (authors1.empty() && !authors0.empty()) {
+ return false;
+ }
+ if (!authors0.empty() && !authors1.empty()) {
+ if (authors0.front().SortKey != authors1.front().SortKey) {
+ return authors0.front().SortKey < authors1.front().SortKey;
+ }
+ }
+
+ /*if (book0.Index != book1.Index) {
+ return book0.Index < book1.Index;
+ }*/
+
+ const bool book0HasSeriesTitle = !book0.SeriesTitle.empty();
+ const bool book1HasSeriesTitle = !book1.SeriesTitle.empty();
+ if (book0HasSeriesTitle && book1HasSeriesTitle) {
+ const int comp = book0.SeriesTitle.compare(book1.SeriesTitle);
+ if (comp != 0) {
+ return comp < 0;
+ } else {
+ int diff = book0.IndexInSeries - book1.IndexInSeries;
+ if (diff != 0) {
+ return diff < 0;
+ }
+ }
+ return book0.Title < book1.Title;
+ }
+
+ const std::string &book0Key = book0HasSeriesTitle ? book0.SeriesTitle : book0.Title;
+ const std::string &book1Key = book1HasSeriesTitle ? book1.SeriesTitle : book1.Title;
+ const int comp = book0Key.compare(book1Key);
+ if (comp != 0) {
+ return comp < 0;
+ }
+ return book1HasSeriesTitle;
+}
+
+
+NetworkAuthorComparator::NetworkAuthorComparator(const std::map<NetworkBookItem::AuthorData, unsigned int> &rates) : myRates(rates) {
+}
+
+bool NetworkAuthorComparator::operator () (const NetworkBookItem::AuthorData &author0, const NetworkBookItem::AuthorData &author1) const {
+ std::map<NetworkBookItem::AuthorData, unsigned int>::const_iterator it1 = myRates.find(author0);
+ std::map<NetworkBookItem::AuthorData, unsigned int>::const_iterator it2 = myRates.find(author1);
+ if (it1 == myRates.end() && it2 == myRates.end()) {
+ return author0 < author1;
+ }
+ if (it1 == myRates.end()) {
+ return false;
+ }
+ if (it2 == myRates.end()) {
+ return true;
+ }
+ if (it1->second != it2->second) {
+ return it1->second < it2->second;
+ }
+ return author0 < author1;
+}
+
+bool NetworkBookItemByTitleComparator::operator ()(const shared_ptr<NetworkItem> &bookPtr0, const shared_ptr<NetworkItem> &bookPtr1) const {
+ return bookPtr0->Title < bookPtr1->Title;
+}
+
+bool NetworkBookItemBySeriesComparator::operator ()(const shared_ptr<NetworkItem> &bookPtr0, const shared_ptr<NetworkItem> &bookPtr1) const {
+ const NetworkBookItem &book0 = static_cast<const NetworkBookItem&>(*bookPtr0);
+ const NetworkBookItem &book1 = static_cast<const NetworkBookItem&>(*bookPtr1);
+ if (book0.SeriesTitle != book1.SeriesTitle) {
+ return book0.SeriesTitle < book1.SeriesTitle;
+ }
+ const int diff = book0.IndexInSeries - book1.IndexInSeries;
+ if (diff != 0) {
+ return diff < 0 ? true : false;
+ }
+ return book0.Title < book1.Title;
+}
+
+
+
diff --git a/fbreader/src/network/NetworkComparators.h b/fbreader/src/network/NetworkComparators.h
new file mode 100644
index 0000000..a872a3f
--- /dev/null
+++ b/fbreader/src/network/NetworkComparators.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __NETWORKCOMPARATORS_H__
+#define __NETWORKCOMPARATORS_H__
+
+
+#include <map>
+
+#include "NetworkItems.h"
+
+class NetworkBookItemComparator {
+
+public:
+ bool operator () (const shared_ptr<NetworkItem> &bookPtr0, const shared_ptr<NetworkItem> &bookPtr1) const;
+};
+
+class NetworkBookItemByTitleComparator {
+
+public:
+ bool operator () (const shared_ptr<NetworkItem> &bookPtr0, const shared_ptr<NetworkItem> &bookPtr1) const;
+};
+
+class NetworkBookItemBySeriesComparator {
+
+public:
+ bool operator () (const shared_ptr<NetworkItem> &bookPtr0, const shared_ptr<NetworkItem> &bookPtr1) const;
+};
+
+class NetworkAuthorComparator {
+
+public:
+ NetworkAuthorComparator(const std::map<NetworkBookItem::AuthorData, unsigned int> &rates);
+
+ bool operator () (const NetworkBookItem::AuthorData &author0, const NetworkBookItem::AuthorData &author1) const;
+
+private:
+ const std::map<NetworkBookItem::AuthorData, unsigned int> &myRates;
+};
+
+#endif /* __NETWORKCOMPARATORS_H__ */
diff --git a/fbreader/src/network/NetworkErrors.cpp b/fbreader/src/network/NetworkErrors.cpp
new file mode 100644
index 0000000..d20546f
--- /dev/null
+++ b/fbreader/src/network/NetworkErrors.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 <ZLResource.h>
+#include <ZLStringUtil.h>
+#include <ZLDialogManager.h>
+
+#include "NetworkErrors.h"
+
+const std::string NetworkErrors::ERROR_AUTHENTICATION_FAILED = "authenticationFailed";
+const std::string NetworkErrors::ERROR_INTERNAL = "internalError";
+const std::string NetworkErrors::ERROR_PURCHASE_NOT_ENOUGH_MONEY = "purchaseNotEnoughMoney";
+const std::string NetworkErrors::ERROR_PURCHASE_MISSING_BOOK = "purchaseMissingBook";
+const std::string NetworkErrors::ERROR_PURCHASE_ALREADY_PURCHASED = "purchaseAlreadyPurchased";
+const std::string NetworkErrors::ERROR_BOOK_NOT_PURCHASED = "bookNotPurchased";
+const std::string NetworkErrors::ERROR_DOWNLOAD_LIMIT_EXCEEDED = "downloadLimitExceeded";
+
+const std::string NetworkErrors::ERROR_LOGIN_ALREADY_TAKEN = "loginAlreadyTaken";
+const std::string NetworkErrors::ERROR_LOGIN_WAS_NOT_SPECIFIED = "loginNotSpecified";
+const std::string NetworkErrors::ERROR_PASSWORD_WAS_NOT_SPECIFIED = "passwordNotSpecified";
+const std::string NetworkErrors::ERROR_EMAIL_WAS_NOT_SPECIFIED = "emailNotSpecified";
+const std::string NetworkErrors::ERROR_INVALID_EMAIL = "invalidEMail";
+const std::string NetworkErrors::ERROR_TOO_MANY_REGISTRATIONS = "tooManyRegistrations";
+
+const std::string NetworkErrors::ERROR_NO_USER_EMAIL = "noUserEmail";
+
+const std::string NetworkErrors::ERROR_SOMETHING_WRONG = "somethingWrongMessage";
+const std::string NetworkErrors::ERROR_UNSUPPORTED_OPERATION = "unsupportedOperation";
+
+const std::string NetworkErrors::ERROR_CANT_DOWNLOAD_LIBRARIES_LIST = "librariesListDownloadingFailed";
+const std::string NetworkErrors::ERROR_TIMEOUT_EXPIRED = "operationTimedOutMessage";
+
+
+std::string NetworkErrors::errorMessage(const std::string &error) {
+ if (error.empty()) {
+ return "";
+ }
+
+ const ZLResource &errorResource = ZLResource::resource("dialog")["networkError"];
+ return errorResource[error].value();
+}
+
+std::string NetworkErrors::errorMessage(const std::string &error, const std::string &arg0) {
+ if (error.empty()) {
+ return "";
+ }
+ const ZLResource &errorResource = ZLResource::resource("dialog")["networkError"];
+ return ZLStringUtil::printf(errorResource[error].value(), arg0);
+}
+
+void NetworkErrors::showErrorMessage(const std::string &error) {
+ ZLDialogManager::Instance().errorBox(ZLResourceKey("networkError"), error);
+}
+
diff --git a/fbreader/src/network/NetworkErrors.h b/fbreader/src/network/NetworkErrors.h
new file mode 100644
index 0000000..d18d2f0
--- /dev/null
+++ b/fbreader/src/network/NetworkErrors.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __NETWORKERRORS_H__
+#define __NETWORKERRORS_H__
+
+#include <string>
+
+class NetworkErrors {
+
+private: // disable instantiation
+ NetworkErrors();
+
+public:
+ static const std::string ERROR_AUTHENTICATION_FAILED;
+ static const std::string ERROR_INTERNAL;
+ static const std::string ERROR_PURCHASE_NOT_ENOUGH_MONEY;
+ static const std::string ERROR_PURCHASE_MISSING_BOOK;
+ static const std::string ERROR_PURCHASE_ALREADY_PURCHASED;
+ static const std::string ERROR_BOOK_NOT_PURCHASED;
+ static const std::string ERROR_DOWNLOAD_LIMIT_EXCEEDED;
+
+ static const std::string ERROR_LOGIN_ALREADY_TAKEN;
+ static const std::string ERROR_LOGIN_WAS_NOT_SPECIFIED;
+ static const std::string ERROR_PASSWORD_WAS_NOT_SPECIFIED;
+ static const std::string ERROR_EMAIL_WAS_NOT_SPECIFIED;
+ static const std::string ERROR_INVALID_EMAIL;
+ static const std::string ERROR_TOO_MANY_REGISTRATIONS;
+
+ static const std::string ERROR_NO_USER_EMAIL;
+
+ static const std::string ERROR_SOMETHING_WRONG;
+ static const std::string ERROR_UNSUPPORTED_OPERATION;
+ static const std::string ERROR_CANT_DOWNLOAD_LIBRARIES_LIST;
+
+ static const std::string ERROR_TIMEOUT_EXPIRED;
+
+public:
+ static std::string errorMessage(const std::string &error);
+ static std::string errorMessage(const std::string &error, const std::string &arg0);
+ static void showErrorMessage(const std::string &error);
+};
+
+#endif /* __NETWORKERRORS_H__ */
diff --git a/fbreader/src/network/NetworkItem.cpp b/fbreader/src/network/NetworkItem.cpp
new file mode 100644
index 0000000..33e22c4
--- /dev/null
+++ b/fbreader/src/network/NetworkItem.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 "NetworkItems.h"
+
+const ZLTypeId NetworkItem::TYPE_ID(ZLObjectWithRTTI::TYPE_ID);
+
+NetworkItem::NetworkItem(
+ const NetworkLink &link,
+ const std::string &title,
+ const std::string &summary,
+ const UrlInfoCollection &urlByType
+) :
+ Link(link),
+ Title(title),
+ Summary(summary),
+ URLByType(urlByType) {
+}
+
+NetworkItem::~NetworkItem() {
+}
diff --git a/fbreader/src/network/NetworkItems.h b/fbreader/src/network/NetworkItems.h
new file mode 100644
index 0000000..169e5b7
--- /dev/null
+++ b/fbreader/src/network/NetworkItems.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __NETWORKITEMS_H__
+#define __NETWORKITEMS_H__
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include <shared_ptr.h>
+
+#include <ZLFile.h>
+#include <ZLTypeId.h>
+#include <ZLBoolean3.h>
+#include <ZLNetworkRequest.h>
+
+#include <ZLTreeNode.h>
+
+#include "BookReference.h"
+
+class NetworkAuthenticationManager;
+class NetworkLink;
+
+class NetworkItem : public ZLObjectWithRTTI {
+
+public:
+ typedef std::vector<shared_ptr<NetworkItem> > List;
+
+ enum URLType {
+ URL_NONE,
+ URL_CATALOG,
+ URL_HTML_PAGE,
+ URL_COVER,
+ URL_FULL_COVER,
+ URL_SINGLE_ENTRY
+ };
+
+ typedef std::map<URLType,std::string> UrlInfoCollection;
+
+protected:
+ static const ZLTypeId TYPE_ID;
+
+protected:
+ NetworkItem(
+ const NetworkLink &link,
+ const std::string &title,
+ const std::string &summary,
+ const UrlInfoCollection &urlByType
+ );
+
+public:
+ virtual ~NetworkItem();
+
+ virtual const ZLTypeId &typeId() const = 0;
+
+public:
+ const NetworkLink &Link;
+ const std::string Title;
+ /*const*/ std::string Summary;
+ /*const*/ UrlInfoCollection URLByType;
+
+private: // disable copying
+ NetworkItem(const NetworkItem &item);
+ const NetworkItem &operator = (const NetworkItem &);
+};
+
+class NetworkCatalogItem : public NetworkItem {
+
+public:
+ static const ZLTypeId TYPE_ID;
+
+ enum AccessibilityType {
+ ALWAYS,
+ SIGNED_IN,
+ HAS_BOOKS
+ };
+
+ enum CatalogFlags {
+ FLAG_NONE = 0,
+ FLAG_SHOW_AUTHOR = 1 << 0,
+ FLAG_GROUP_BY_AUTHOR = 1 << 1,
+ FLAG_GROUP_BY_SERIES = 1 << 2,
+ FLAG_GROUP_MORE_THAN_1_BOOK_BY_SERIES = 1 << 3,
+ FLAGS_DEFAULT =
+ FLAG_SHOW_AUTHOR |
+ FLAG_GROUP_MORE_THAN_1_BOOK_BY_SERIES,
+ FLAGS_GROUP =
+ FLAG_GROUP_BY_AUTHOR |
+ FLAG_GROUP_BY_SERIES |
+ FLAG_GROUP_MORE_THAN_1_BOOK_BY_SERIES,
+ };
+
+public:
+ NetworkCatalogItem(
+ const NetworkLink &link,
+ const std::string &title,
+ const std::string &summary,
+ const UrlInfoCollection &urlByType,
+ AccessibilityType accessibility = ALWAYS,
+ int flags = FLAGS_DEFAULT
+ );
+
+ const ZLTypeId &typeId() const;
+
+ // method is called each time the View Node is created for the Item.
+ virtual void onDisplayItem();
+ // returns error message
+ virtual std::string loadChildren(List &children, shared_ptr<ZLNetworkRequest::Listener> listener = 0) = 0;
+ virtual bool supportsResumeLoading();
+ virtual std::string resumeLoading(List &children, shared_ptr<ZLNetworkRequest::Listener> listener = 0);
+
+ int getFlags() const;
+ AccessibilityType getAccessibility() const;
+ ZLBoolean3 getVisibility() const;
+
+protected:
+ virtual std::string getCatalogUrl();
+
+private:
+ const AccessibilityType myAccessibility;
+ const int myFlags;
+};
+
+class NetworkBookItem : public NetworkItem {
+
+public:
+ struct AuthorData {
+ std::string DisplayName;
+ std::string SortKey;
+
+ bool operator < (const AuthorData &data) const;
+ bool operator != (const AuthorData &data) const;
+ bool operator == (const AuthorData &data) const;
+ };
+
+public:
+ static const ZLTypeId TYPE_ID;
+
+public:
+ NetworkBookItem(
+ const NetworkLink &link,
+ const std::string &id,
+ unsigned int index,
+ const std::string &title,
+ const std::string &summary,
+ const std::string &language,
+ const std::string &date,
+ const std::vector<AuthorData> &authors,
+ const std::vector<std::string> &tags,
+ const std::string &seriesTitle,
+ unsigned int indexInSeries,
+ const UrlInfoCollection &urlByType,
+ const std::vector<shared_ptr<BookReference> > references
+ );
+ NetworkBookItem(const NetworkBookItem &book, unsigned int index);
+
+ const ZLTypeId &typeId() const;
+
+public:
+ shared_ptr<BookReference> reference(BookReference::Type type) const;
+
+ std::string localCopyFileName() const;
+ void removeLocalFiles() const;
+
+ virtual bool isFullyLoaded() const;
+ virtual void loadFullInformation(shared_ptr<ZLNetworkRequest::Listener> listener);
+ virtual std::vector<shared_ptr<NetworkItem> > getRelatedCatalogsItems() const;
+
+ void updateReferences(const std::vector<shared_ptr<BookReference> > &references);
+
+public:
+ /*const*/ unsigned int Index;
+ const std::string Id;
+ const std::string Language;
+ const std::string Date;
+ const std::vector<AuthorData> Authors;
+ const std::vector<std::string> Tags;
+ const std::string SeriesTitle;
+ const int IndexInSeries;
+
+private:
+ std::vector<shared_ptr<BookReference> > myReferences;
+};
+
+#endif /* __NETWORKITEMS_H__ */
diff --git a/fbreader/src/network/NetworkLink.cpp b/fbreader/src/network/NetworkLink.cpp
new file mode 100644
index 0000000..218de23
--- /dev/null
+++ b/fbreader/src/network/NetworkLink.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2008-2012 Geometer Plus <[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 <ZLNetworkRequest.h>
+
+#include <ZLibrary.h>
+#include <ZLFile.h>
+#include <ZLStringUtil.h>
+
+#include "NetworkLink.h"
+#include "NetworkOperationData.h"
+
+const std::string NetworkLink::URL_MAIN = "main";
+const std::string NetworkLink::URL_SEARCH = "search";
+const std::string NetworkLink::URL_SIGN_IN = "signIn";
+const std::string NetworkLink::URL_SIGN_OUT = "signOut";
+const std::string NetworkLink::URL_SIGN_UP = "signUp";
+const std::string NetworkLink::URL_TOPUP = "topup";
+const std::string NetworkLink::URL_RECOVER_PASSWORD = "recoverPassword";
+
+NetworkLink::NetworkLink(
+ const std::string &siteName
+) :
+ mySiteName(ZLStringUtil::stringStartsWith(siteName, "www.") ? siteName.substr(std::string("www.").length()) : siteName),
+ myEnabled(true),
+ myUpdated(0) {
+}
+
+NetworkLink::~NetworkLink() {
+}
+
+std::string NetworkLink::url(const std::string &urlId) const {
+ std::map<std::string,std::string>::const_iterator it = myLinks.find(urlId);
+ return (it != myLinks.end()) ? it->second : std::string();
+}
+
+shared_ptr<ZLNetworkRequest> NetworkLink::resume(NetworkOperationData &result) const {
+ result.clear();
+ return 0;
+}
+
+void NetworkLink::setTitle(const std::string& title) {
+ myTitle = title;
+}
+void NetworkLink::setSummary(const std::string& summary) {
+ mySummary = summary;
+}
+
+void NetworkLink::setLanguage(const std::string &language) {
+ myLanguage = language;
+}
+
+void NetworkLink::setIcon(const std::string& icon) {
+ myIcon = icon;
+}
+
+void NetworkLink::setPredefinedId(const std::string& id) {
+ myPredefinedId = id;
+}
+
+void NetworkLink::setLinks(const std::map<std::string,std::string>& links) {
+ myLinks = links;
+}
+
+void NetworkLink::setUpdated(shared_ptr<ATOMUpdated> u) {
+ myUpdated = u;
+}
+
+std::string NetworkLink::getSiteName() const {
+ return mySiteName;
+}
+
+void NetworkLink::setEnabled(bool enabled) {
+ myEnabled = enabled;
+}
+
+std::string NetworkLink::getTitle() const {
+ return myTitle;
+}
+std::string NetworkLink::getSummary() const {
+ return mySummary;
+}
+
+std::string NetworkLink::getLanguage() const {
+ return myLanguage;
+}
+
+std::string NetworkLink::getPredefinedId() const {
+ return myPredefinedId;
+}
+
+const std::map<std::string,std::string>& NetworkLink::getLinks() const {
+ return myLinks;
+}
+
+shared_ptr<ATOMUpdated> NetworkLink::getUpdated() const {
+ return myUpdated;
+}
+
+bool NetworkLink::isPredefined() const {
+ return !myPredefinedId.empty();
+}
+
+std::string NetworkLink::getIcon() const {
+ return myIcon;
+}
+bool NetworkLink::isEnabled() const {
+ return myEnabled;
+}
+
+void NetworkLink::loadFrom(const NetworkLink & link) {
+ myTitle = link.myTitle;
+ myIcon = link.myIcon;
+ mySummary = link.mySummary;
+ myLanguage = link.myLanguage;
+ myLinks = link.myLinks;
+ myPredefinedId = link.myPredefinedId;
+ myUpdated = link.myUpdated;
+}
+
+void NetworkLink::loadLinksFrom(const NetworkLink & link) {
+ myIcon = link.myIcon;
+ myLinks = link.myLinks;
+ myUpdated = link.myUpdated;
+}
+
+void NetworkLink::loadSummaryFrom(const NetworkLink & link) {
+ myTitle = link.myTitle;
+ mySummary = link.mySummary;
+}
diff --git a/fbreader/src/network/NetworkLink.h b/fbreader/src/network/NetworkLink.h
new file mode 100644
index 0000000..e0260b0
--- /dev/null
+++ b/fbreader/src/network/NetworkLink.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2008-2012 Geometer Plus <[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.
+ */
+
+#ifndef __NETWORKLINK_H__
+#define __NETWORKLINK_H__
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include <shared_ptr.h>
+#include <ZLOptions.h>
+
+#include "NetworkItems.h"
+#include "atom/ATOMMetadata.h"
+
+class ZLNetworkRequest;
+
+class NetworkOperationData;
+class NetworkAuthenticationManager;
+
+class NetworkLink {
+
+public:
+ static const std::string URL_MAIN;
+ static const std::string URL_SEARCH;
+ static const std::string URL_SIGN_IN;
+ static const std::string URL_SIGN_OUT;
+ static const std::string URL_SIGN_UP;
+ static const std::string URL_TOPUP;
+ static const std::string URL_RECOVER_PASSWORD;
+
+protected:
+ NetworkLink(
+ const std::string &siteName
+ );
+
+public:
+ virtual ~NetworkLink();
+ std::string url(const std::string &urlId) const;
+
+ void setTitle(const std::string& title);
+ void setSummary(const std::string& summary);
+ void setLanguage(const std::string& language);
+ void setIcon(const std::string& icon);
+ void setLinks(const std::map<std::string,std::string>& links);
+ void setPredefinedId(const std::string& id);
+ void setEnabled(bool enabled);
+ void setUpdated(shared_ptr<ATOMUpdated> u);
+
+ std::string getSiteName() const;
+ std::string getTitle() const;
+ std::string getSummary() const;
+ std::string getLanguage() const;
+ std::string getIcon() const;
+ const std::map<std::string,std::string>& getLinks() const;
+ std::string getPredefinedId() const;
+ bool isEnabled() const;
+ shared_ptr<ATOMUpdated> getUpdated() const;
+
+ bool isPredefined() const;
+
+ void loadFrom(const NetworkLink & link);
+ void loadLinksFrom(const NetworkLink & link);
+ void loadSummaryFrom(const NetworkLink & link);
+
+public:
+ virtual shared_ptr<ZLNetworkRequest> simpleSearchData(NetworkOperationData &data, const std::string &pattern) const = 0;
+ virtual shared_ptr<ZLNetworkRequest> advancedSearchData(NetworkOperationData &data, const std::string &titleAndSeries, const std::string &author, const std::string &tag, const std::string &annotation) const = 0;
+ virtual shared_ptr<ZLNetworkRequest> resume(NetworkOperationData &data) const;
+
+ virtual shared_ptr<NetworkAuthenticationManager> authenticationManager() const = 0;
+ virtual shared_ptr<NetworkItem> libraryItem() const = 0;
+
+ virtual void rewriteUrl(std::string &url, bool isUrlExternal = false) const = 0;
+
+private:
+ const std::string mySiteName;
+ std::string myTitle;
+ std::string myIcon;
+ std::string mySummary;
+ std::string myLanguage;
+ std::map<std::string,std::string> myLinks;
+ std::string myPredefinedId;
+ bool myEnabled;
+ shared_ptr<ATOMUpdated> myUpdated;
+
+private: // disable copying
+ NetworkLink(const NetworkLink &);
+ const NetworkLink &operator = (const NetworkLink &);
+};
+
+#endif /* __NETWORKLINK_H__ */
diff --git a/fbreader/src/network/NetworkLinkCollection.cpp b/fbreader/src/network/NetworkLinkCollection.cpp
new file mode 100644
index 0000000..0b530b0
--- /dev/null
+++ b/fbreader/src/network/NetworkLinkCollection.cpp
@@ -0,0 +1,561 @@
+/*
+ * Copyright (C) 2008-2012 Geometer Plus <[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 <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);
+ }
+ }
+}
diff --git a/fbreader/src/network/NetworkLinkCollection.h b/fbreader/src/network/NetworkLinkCollection.h
new file mode 100644
index 0000000..080959d
--- /dev/null
+++ b/fbreader/src/network/NetworkLinkCollection.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __NETWORKLINKCOLLECTION_H__
+#define __NETWORKLINKCOLLECTION_H__
+
+#include <string>
+#include <vector>
+
+#include <shared_ptr.h>
+
+#include <ZLOptions.h>
+#include <ZLNetworkRequest.h>
+
+#include "NetworkItems.h"
+
+class NetworkLink;
+class NetworkBookCollection;
+class BookReference;
+
+class NetworkLinkCollection {
+
+public:
+ typedef std::vector<shared_ptr<NetworkLink> > LinkVector;
+
+private:
+ class Comparator;
+
+public:
+ static NetworkLinkCollection &Instance();
+
+private:
+ static NetworkLinkCollection *ourInstance;
+
+public:
+ ZLStringOption DirectoryOption;
+ ZLIntegerOption LastUpdateTimeOption;
+
+private:
+ NetworkLinkCollection();
+ ~NetworkLinkCollection();
+
+public:
+ void initialize();
+
+ std::string bookFileName(const BookReference &reference);
+
+ bool downloadBook(const BookReference &reference, std::string &fileName, shared_ptr<ZLNetworkRequest::Listener> listener);
+
+ shared_ptr<NetworkBookCollection> simpleSearch(const std::string &pattern);
+ shared_ptr<NetworkBookCollection> advancedSearch(const std::string &titleAndSeries, const std::string &author, const std::string &tag, const std::string &annotation);
+
+ LinkVector activeLinks() const;
+ std::size_t size() const;
+ std::size_t numberOfEnabledLinks() const;
+ NetworkLink &link(std::size_t index) const;
+
+ const std::string &errorMessage() const;
+
+ void rewriteUrl(std::string &url, bool externalUrl = false) const;
+
+ //void deleteLink(NetworkLink& link);
+ //void saveLink(NetworkLink& link, bool isAuto = false);
+
+private:
+ void synchronize();
+
+ std::string bookFileName(const std::string &url, BookReference::Format format, BookReference::Type type);
+
+ void updateLinks(std::string genericUrl);
+ shared_ptr<ZLFile> getGenericFile(std::string genericUrl);
+ void addOrUpdateLink(shared_ptr<NetworkLink> link);
+
+private:
+ LinkVector myLinks;
+ std::string myErrorMessage;
+ bool myIsInitialized;
+
+friend class NetworkLinksUpdater;
+friend class NetworkLinkCollectionSynchronizer;
+};
+
+inline const std::string &NetworkLinkCollection::errorMessage() const { return myErrorMessage; }
+
+#endif /* __NETWORKLINKCOLLECTION_H__ */
diff --git a/fbreader/src/network/NetworkOperationData.cpp b/fbreader/src/network/NetworkOperationData.cpp
new file mode 100644
index 0000000..6988071
--- /dev/null
+++ b/fbreader/src/network/NetworkOperationData.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 <ZLNetworkRequest.h>
+
+#include "NetworkLink.h"
+#include "NetworkOperationData.h"
+
+NetworkOperationData::NetworkOperationData(const NetworkLink &link) : Link(link) {
+}
+
+void NetworkOperationData::clear() {
+ Items.clear();
+ ResumeURI.clear();
+}
+
+shared_ptr<ZLNetworkRequest> NetworkOperationData::resume() {
+ shared_ptr<ZLNetworkRequest> request = Link.resume(*this);
+ clear();
+ return request;
+}
diff --git a/fbreader/src/network/NetworkOperationData.h b/fbreader/src/network/NetworkOperationData.h
new file mode 100644
index 0000000..4d4a46f
--- /dev/null
+++ b/fbreader/src/network/NetworkOperationData.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __NETWORKOPERATIONDATA_H__
+#define __NETWORKOPERATIONDATA_H__
+
+#include <shared_ptr.h>
+
+#include "NetworkItems.h"
+
+class ZLNetworkRequest;
+
+class NetworkLink;
+
+class NetworkOperationData {
+
+public:
+ NetworkOperationData(const NetworkLink &link);
+
+ void clear();
+ shared_ptr<ZLNetworkRequest> resume();
+
+public:
+ const NetworkLink &Link;
+ NetworkItem::List Items;
+ std::string ResumeURI;
+};
+
+#endif /* __NETWORKOPERATIONDATA_H__ */
diff --git a/fbreader/src/network/SearchResult.cpp b/fbreader/src/network/SearchResult.cpp
new file mode 100644
index 0000000..2b66326
--- /dev/null
+++ b/fbreader/src/network/SearchResult.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 "SearchResult.h"
+
+SearchResult SearchResult::ourLastSearchResult;
+
+
+SearchResult::SearchResult() {
+}
+
+const SearchResult &SearchResult::lastSearchResult() {
+ return ourLastSearchResult;
+}
+
+void SearchResult::setLastSearchResult(const std::string &summary, shared_ptr<NetworkBookCollection> bookCollection) {
+ ourLastSearchResult.mySummary = summary;
+ ourLastSearchResult.myBookCollection = bookCollection;
+}
+
diff --git a/fbreader/src/network/SearchResult.h b/fbreader/src/network/SearchResult.h
new file mode 100644
index 0000000..bd18b71
--- /dev/null
+++ b/fbreader/src/network/SearchResult.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __SEARCHRESULT_H__
+#define __SEARCHRESULT_H__
+
+#include "NetworkBookCollection.h"
+
+class SearchResult {
+
+private:
+ static SearchResult ourLastSearchResult;
+
+private:
+ SearchResult();
+
+public:
+ static const SearchResult &lastSearchResult();
+ static void setLastSearchResult(const std::string &summary, shared_ptr<NetworkBookCollection> bookCollection);
+
+public:
+ const std::string &summary() const;
+ shared_ptr<NetworkBookCollection> collection() const;
+
+private:
+ std::string mySummary;
+ shared_ptr<NetworkBookCollection> myBookCollection;
+};
+
+inline const std::string &SearchResult::summary() const { return mySummary; }
+inline shared_ptr<NetworkBookCollection> SearchResult::collection() const { return myBookCollection; }
+
+#endif /* __SEARCHRESULT_H__ */
diff --git a/fbreader/src/network/UserList.cpp b/fbreader/src/network/UserList.cpp
new file mode 100644
index 0000000..1712788
--- /dev/null
+++ b/fbreader/src/network/UserList.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 <algorithm>
+
+#include <ZLOptions.h>
+#include <ZLStringUtil.h>
+
+#include "UserList.h"
+
+
+static const unsigned int MAX_USER_NAMES = 10;
+
+static const std::string USER_LIST = "userList-";
+static const std::string USER = "user";
+
+UserList::UserList(const std::string &siteName) : myGroupName(USER_LIST + siteName) {
+ for (unsigned int i = 0; i < MAX_USER_NAMES; ++i) {
+ std::string userOptionName(USER);
+ ZLStringUtil::appendNumber(userOptionName, i);
+ std::string userName = ZLStringOption(ZLCategoryKey::NETWORK, myGroupName, userOptionName, "").value();
+ if (!userName.empty()) {
+ myUserNames.push_back(userName);
+ mySavedNames.insert(userName);
+ }
+ }
+ if (myUserNames.empty()) {
+ myUserNames.push_back(std::string());
+ }
+}
+
+UserList::~UserList() {
+ unsigned int i = 0;
+ for (std::size_t k = 0; k < myUserNames.size() && i < MAX_USER_NAMES; ++k) {
+ const std::string &name = myUserNames[k];
+ if (mySavedNames.find(name) != mySavedNames.end()) {
+ std::string userOptionName(USER);
+ ZLStringUtil::appendNumber(userOptionName, i++);
+ ZLStringOption userOption(ZLCategoryKey::NETWORK, myGroupName, userOptionName, "");
+ userOption.setValue(name);
+ }
+ }
+ while (i < MAX_USER_NAMES) {
+ std::string userOptionName(USER);
+ ZLStringUtil::appendNumber(userOptionName, i++);
+ ZLStringOption userOption(ZLCategoryKey::NETWORK, myGroupName, userOptionName, "");
+ userOption.setValue("");
+ }
+}
+
+const std::vector<std::string> &UserList::users() const {
+ return myUserNames;
+}
+
+void UserList::addUser(const std::string &user) {
+ std::vector<std::string>::iterator it;
+ while ((it = std::find(myUserNames.begin(), myUserNames.end(), user)) != myUserNames.end()) {
+ myUserNames.erase(it);
+ }
+ myUserNames.insert(myUserNames.begin(), user);
+}
+
+void UserList::saveUser(const std::string &user) {
+ std::vector<std::string>::iterator it = std::find(myUserNames.begin(), myUserNames.end(), user);
+ if (it == myUserNames.end()) {
+ myUserNames.insert(myUserNames.begin(), user);
+ }
+ mySavedNames.insert(user);
+}
diff --git a/fbreader/src/network/UserList.h b/fbreader/src/network/UserList.h
new file mode 100644
index 0000000..d1f298f
--- /dev/null
+++ b/fbreader/src/network/UserList.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __USERLIST_H__
+#define __USERLIST_H__
+
+#include <string>
+#include <vector>
+#include <set>
+
+
+class UserList {
+
+public:
+ UserList(const std::string &siteName);
+ ~UserList();
+
+ const std::vector<std::string> &users() const;
+ void addUser(const std::string &user);
+ void saveUser(const std::string &user);
+
+private:
+ std::string myGroupName;
+ std::vector<std::string> myUserNames;
+ std::set<std::string> mySavedNames;
+};
+
+#endif /* __USERLIST_H__ */
diff --git a/fbreader/src/network/atom/ATOMConstructs.cpp b/fbreader/src/network/atom/ATOMConstructs.cpp
new file mode 100644
index 0000000..9684825
--- /dev/null
+++ b/fbreader/src/network/atom/ATOMConstructs.cpp
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 "ATOMConstructs.h"
+
+#include <ZLStringUtil.h>
+
+#include <math.h>
+
+
+
+const std::string ATOMCommonAttributes::XML_BASE = "xml:base";
+const std::string ATOMCommonAttributes::XML_LANG = "xml:lang";
+
+
+ATOMCommonAttributes::ATOMCommonAttributes() {
+}
+
+ATOMCommonAttributes::~ATOMCommonAttributes() {
+}
+
+void ATOMCommonAttributes::readAttributes(const std::map<std::string, std::string> &attributes) {
+ readAttribute(XML_BASE, attributes);
+ readAttribute(XML_LANG, attributes);
+}
+
+void ATOMCommonAttributes::readAttribute(const std::string &name, const std::map<std::string, std::string> &attributes) {
+ std::map<std::string, std::string>::const_iterator it = attributes.find(name);
+ if (it != attributes.end()) {
+ myAttributes[name] = it->second;
+ }
+}
+
+void ATOMCommonAttributes::setUserData(const std::string &key, const std::string &value) {
+ myUserData[key] = value;
+}
+
+const std::string ATOMCommonAttributes::userData(const std::string &key) const {
+ std::map<std::string,std::string>::const_iterator it = myUserData.find(key);
+ return (it != myUserData.end()) ? it->second : std::string();
+}
+
+ATOMPersonConstruct::ATOMPersonConstruct() {
+}
+
+ATOMPersonConstruct::ATOMPersonConstruct(const std::string &name) : myName(name) {
+}
+
+
+ATOMDateConstruct::ATOMDateConstruct(int year) :
+ myYear(year), myMonth(0), myDay(0),
+ myHour(0), myMinutes(0), mySeconds(0), mySecondFraction(0), myTZHour(0), myTZMinutes(0) {
+}
+
+ATOMDateConstruct::ATOMDateConstruct(int year, int month, int day) :
+ myYear(year), myMonth(month), myDay(day),
+ myHour(0), myMinutes(0), mySeconds(0), mySecondFraction(0), myTZHour(0), myTZMinutes(0) {
+}
+
+ATOMDateConstruct::ATOMDateConstruct(int year, int month, int day, int hour, int minutes, int seconds) :
+ myYear(year), myMonth(month), myDay(day),
+ myHour(hour), myMinutes(minutes), mySeconds(seconds), mySecondFraction(0), myTZHour(0), myTZMinutes(0) {
+}
+
+ATOMDateConstruct::ATOMDateConstruct(int year, int month, int day, int hour, int minutes, int seconds, float sfract) :
+ myYear(year), myMonth(month), myDay(day),
+ myHour(hour), myMinutes(minutes), mySeconds(seconds), mySecondFraction(sfract), myTZHour(0), myTZMinutes(0) {
+}
+
+ATOMDateConstruct::ATOMDateConstruct(int year, int month, int day, int hour, int minutes, int seconds, float sfract, int tzhour, int tzminutes) :
+ myYear(year), myMonth(month), myDay(day),
+ myHour(hour), myMinutes(minutes), mySeconds(seconds), mySecondFraction(sfract), myTZHour(tzhour), myTZMinutes(tzminutes) {
+}
+
+bool ATOMDateConstruct::operator<(const ATOMDateConstruct &a) const {
+ if (myYear < a.myYear) return true;
+ if (myYear > a.myYear) return false;
+
+ if (myMonth < a.myMonth) return true;
+ if (myMonth > a.myMonth) return false;
+
+ if (myDay < a.myDay) return true;
+ if (myDay > a.myDay) return false;
+
+ if (myHour < a.myHour) return true;
+ if (myHour > a.myHour) return false;
+
+ if (myMinutes < a.myMinutes) return true;
+ if (myMinutes > a.myMinutes) return false;
+
+ if (mySeconds < a.mySeconds) return true;
+ if (mySeconds > a.mySeconds) return false;
+
+// if (mySecondFraction < a.mySecondFraction) return true;
+// if (mySecondFraction > a.mySecondFraction) return false;
+ return false;
+}
+
+bool ATOMDateConstruct::operator>(const ATOMDateConstruct &a) const {
+ if (myYear > a.myYear) return true;
+ if (myYear < a.myYear) return false;
+
+ if (myMonth > a.myMonth) return true;
+ if (myMonth < a.myMonth) return false;
+
+ if (myDay > a.myDay) return true;
+ if (myDay < a.myDay) return false;
+
+ if (myHour > a.myHour) return true;
+ if (myHour < a.myHour) return false;
+
+ if (myMinutes > a.myMinutes) return true;
+ if (myMinutes < a.myMinutes) return false;
+
+ if (mySeconds > a.mySeconds) return true;
+ if (mySeconds < a.mySeconds) return false;
+
+// if (mySecondFraction < a.mySecondFraction) return true;
+// if (mySecondFraction > a.mySecondFraction) return false;
+ return false;
+}
+
+void ATOMDateConstruct::makeStringLength(std::string &str, int len) {
+ const int lendiff = str.length() - len;
+ if (lendiff > 0) {
+ str = str.substr(lendiff);
+ } else {
+ str = std::string(-lendiff, '0') + str;
+ }
+}
+
+
+std::string ATOMDateConstruct::getDateTime(bool brief) const {
+ std::string timezone = "Z";
+ if (myTZMinutes != 0 || myTZHour != 0) {
+ int tzminnum = myTZMinutes;
+ int tzhournum = myTZHour;
+ char sign;
+ if (tzhournum == 0) {
+ sign = (tzminnum >= 0) ? '+' : '-';
+ } else {
+ sign = (tzhournum > 0) ? '+' : '-';
+ if (tzhournum > 0 && tzminnum < 0) {
+ --tzhournum;
+ tzminnum = 60 + tzminnum;
+ } else if (tzhournum < 0 && tzminnum > 0) {
+ ++tzhournum;
+ tzminnum = 60 - tzminnum;
+ }
+ }
+ std::string tzmin, tzhour;
+ ZLStringUtil::appendNumber(tzmin, tzminnum < 0 ? -tzminnum : tzminnum);
+ ZLStringUtil::appendNumber(tzhour, tzhournum < 0 ? -tzhournum : tzhournum);
+ makeStringLength(tzmin, 2);
+ makeStringLength(tzhour, 2);
+ timezone = sign + tzhour + ":" + tzmin;
+ }
+
+ std::string time;
+ if (mySecondFraction >= 0.01) {
+ std::string sfr;
+ unsigned int sfrnum = (unsigned int) floor(100 * mySecondFraction + 0.5);
+ ZLStringUtil::appendNumber(sfr, sfrnum);
+ makeStringLength(sfr, 2);
+ time = "." + sfr;
+ }
+ if (!brief || !time.empty() || mySeconds != 0) {
+ std::string sec;
+ ZLStringUtil::appendNumber(sec, mySeconds);
+ makeStringLength(sec, 2);
+ time = ":" + sec + time;
+ }
+ if (!brief || !time.empty() || myHour != 0 || myMinutes != 0 || timezone != "Z") {
+ std::string hour, min;
+ ZLStringUtil::appendNumber(hour, myHour);
+ ZLStringUtil::appendNumber(min, myMinutes);
+ makeStringLength(hour, 2);
+ makeStringLength(min, 2);
+ time = hour + ":" + min + time;
+ }
+
+ std::string date;
+ if (!brief || !time.empty() || myDay != 0) {
+ std::string day;
+ ZLStringUtil::appendNumber(day, myDay);
+ makeStringLength(day, 2);
+ date = "-" + day;
+ }
+ if (!brief || !date.empty() || myMonth != 0) {
+ std::string month;
+ ZLStringUtil::appendNumber(month, myMonth);
+ makeStringLength(month, 2);
+ date = "-" + month + date;
+ }
+
+ std::string year;
+ ZLStringUtil::appendNumber(year, myYear);
+ makeStringLength(year, 4);
+ date = year + date;
+
+ if (!brief || !time.empty()) {
+ date = date + "T" + time + timezone;
+ }
+ return date;
+}
+
+bool ATOMDateConstruct::parse(const std::string &str, ATOMDateConstruct &dateTime) {
+ dateTime.setYear(0);
+ dateTime.setMonth(0);
+ dateTime.setDay(0);
+ dateTime.setHour(0);
+ dateTime.setMinutes(0);
+ dateTime.setSeconds(0);
+ dateTime.setSecondFraction(0);
+ dateTime.setTZHour(0);
+ dateTime.setTZMinutes(0);
+ const int len = str.length();
+ if (len != 4 && len != 7 && len != 10 && len != 17 && len != 20 && len < 22) {
+ return false;
+ }
+ int num = 0, sign = 1;
+ float fnum = 0.0, fmult = 0.1;
+ int start, end, log;
+ char ch;
+ end = 4; start = 0; log = 0;
+ while (start < len) {
+ ch = str[start++];
+ if (!std::isdigit(ch)) {
+ return false;
+ }
+ num = 10 * num + ((int) (ch - '0'));
+ fnum += fmult * ((int) (ch - '0'));
+ fmult *= 0.1;
+ if (start == end) {
+ switch (log) {
+ case 0: dateTime.setYear(num); break;
+ case 1: dateTime.setMonth(num); break;
+ case 2: dateTime.setDay(num); break;
+ case 3: dateTime.setHour(num); break;
+ case 4: dateTime.setMinutes(num); break;
+ case 5: dateTime.setSeconds(num); break;
+ case 6: dateTime.setSecondFraction(fnum); break;
+ case 7: dateTime.setTZHour(sign * num); break;
+ case 8: dateTime.setTZMinutes(sign * num); break;
+ default: return false;
+ }
+ num = 0; fnum = 0.0; fmult = 0.1;
+ if (start == len) return true;
+ switch (log) {
+ case 0:
+ case 1:
+ if (str[start++] != '-') return false;
+ end = start + 2;
+ break;
+ case 2:
+ if (str[start++] != 'T') return false;
+ end = start + 2;
+ break;
+ case 3:
+ case 7:
+ if (str[start++] != ':') return false;
+ end = start + 2;
+ break;
+ case 4:
+ ch = str[start++];
+ if (ch == ':') {
+ end = start + 2;
+ } else if (ch == '+' || ch == '-') {
+ sign = (ch == '-') ? -1 : 1;
+ log += 2;
+ end = start + 2;
+ } else if (ch == 'Z') {
+ return true;
+ } else return false;
+ break;
+ case 5:
+ ch = str[start++];
+ if (ch == '.') {
+ end = start;
+ while (std::isdigit(str[++end])) /* NOP */;
+ } else if (ch == '+' || ch == '-') {
+ sign = (ch == '-') ? -1 : 1;
+ log += 1;
+ end = start + 2;
+ } else if (ch == 'Z') {
+ return true;
+ } else return false;
+ break;
+ case 6:
+ ch = str[start++];
+ if (ch == '+' || ch == '-') {
+ sign = (ch == '-') ? -1 : 1;
+ end = start + 2;
+ } else if (ch == 'Z') {
+ return true;
+ } else return false;
+ break;
+ //case 8:
+ default: return false;
+ }
+ ++log;
+ }
+ }
+ return false;
+}
+
+long ATOMDateConstruct::getLongSeconds_stupid() {
+ return ((((((myYear - 2000) * 12 + myMonth) * 31 + myDay) * 24 + myHour) * 60 + myMinutes) * 60 + mySeconds);
+}
+
+void ATOMDateConstruct::setLongSeconds_stupid(long t) {
+ myYear = t / (12*31*24*60*60) + 2000;
+ t = t % (12*31*24*60*60);
+ myMonth = t / (31*24*60*60);
+ t = t % (31*24*60*60);
+ myDay = t / (24*60*60);
+ t = t % (24*60*60);
+ myHour = t / (60*60);
+ t = t % (60*60);
+ myMinutes = t / (60);
+ t = t % (60);
+ mySeconds = t;
+}
diff --git a/fbreader/src/network/atom/ATOMConstructs.h b/fbreader/src/network/atom/ATOMConstructs.h
new file mode 100644
index 0000000..2497bd4
--- /dev/null
+++ b/fbreader/src/network/atom/ATOMConstructs.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __ATOMCONSTRUCTS_H__
+#define __ATOMCONSTRUCTS_H__
+
+#include <map>
+#include <string>
+
+
+class ATOMCommonAttributes {
+
+public:
+ static const std::string XML_BASE;
+ static const std::string XML_LANG;
+
+public:
+ ATOMCommonAttributes();
+ virtual ~ATOMCommonAttributes();
+
+public:
+ std::map<std::string, std::string> &attributes() { return myAttributes; }
+ const std::map<std::string, std::string> &attributes() const { return myAttributes; }
+
+ std::string &base() { return myAttributes[XML_BASE]; }
+ std::string &lang() { return myAttributes[XML_LANG]; }
+
+ virtual void readAttributes(const std::map<std::string, std::string> &attributes);
+
+ void setUserData(const std::string &key, const std::string &value);
+ const std::string userData(const std::string &key) const;
+
+protected:
+ void readAttribute(const std::string &name, const std::map<std::string, std::string> &attributes);
+
+private:
+ std::map<std::string, std::string> myAttributes;
+ std::map<std::string,std::string> myUserData;
+};
+
+
+class ATOMPersonConstruct : public ATOMCommonAttributes {
+
+public:
+ ATOMPersonConstruct();
+ ATOMPersonConstruct(const std::string &name);
+
+ const std::string &name() const { return myName; }
+ const std::string &uri() const { return myUri; }
+ const std::string &email() const { return myEmail; }
+
+ void setName(const std::string &name) { myName = name; }
+ void setUri(const std::string &uri) { myUri = uri; }
+ void setEmail(const std::string &email) { myEmail = email; }
+
+private:
+ std::string myName;
+ std::string myUri;
+ std::string myEmail;
+};
+
+
+class ATOMDateConstruct : public ATOMCommonAttributes {
+
+public:
+ static bool parse(const std::string &str, ATOMDateConstruct &dateTime);
+
+public:
+ ATOMDateConstruct(int year);
+ ATOMDateConstruct(int year, int month, int day);
+ ATOMDateConstruct(int year, int month, int day, int hour, int minutes, int seconds);
+ ATOMDateConstruct(int year, int month, int day, int hour, int minutes, int seconds, float sfract);
+ ATOMDateConstruct(int year, int month, int day, int hour, int minutes, int seconds, float sfract, int tzhour, int tzminutes);
+
+ bool operator <(const ATOMDateConstruct& a) const;
+ bool operator >(const ATOMDateConstruct& a) const;
+
+ std::string getDateTime(bool brief = false) const;
+
+ int year() const { return myYear; }
+ int month() const { return myMonth; }
+ int day() const { return myDay; }
+ int hour() const { return myHour; }
+ int minutes() const { return myMinutes; }
+ int seconds() const { return mySeconds; }
+ float secondFraction() const { return mySecondFraction; }
+ int timeZoneHour() const { return myTZHour; }
+ int timeZoneMinutes() const { return myTZMinutes; }
+
+ void setYear(int year) { myYear = year; }
+ void setMonth(int month) { myMonth = month; }
+ void setDay(int day) { myDay = day; }
+ void setHour(int hour) { myHour = hour; }
+ void setMinutes(int minutes) { myMinutes = minutes; }
+ void setSeconds(int seconds) { mySeconds = seconds; }
+ void setSecondFraction(float sfract) { mySecondFraction = sfract; }
+ void setTZHour(int tzhour) { myTZHour = tzhour; }
+ void setTZMinutes(int tzminutes) { myTZMinutes = tzminutes; }
+
+ long getLongSeconds_stupid();
+ void setLongSeconds_stupid(long t);
+
+private:
+ static void makeStringLength(std::string &str, int len);
+
+private:
+ int myYear;
+ int myMonth;
+ int myDay;
+ int myHour;
+ int myMinutes;
+ int mySeconds;
+ float mySecondFraction;
+ int myTZHour;
+ int myTZMinutes;
+};
+
+
+#endif /* __ATOMCONSTRUCTS_H__ */
diff --git a/fbreader/src/network/atom/ATOMContainers.cpp b/fbreader/src/network/atom/ATOMContainers.cpp
new file mode 100644
index 0000000..fb05c10
--- /dev/null
+++ b/fbreader/src/network/atom/ATOMContainers.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 "ATOMContainers.h"
+
+ATOMEntry::ATOMEntry() {
+}
+
+ATOMEntry::ATOMEntry(shared_ptr<ATOMId> id, const std::string &title, shared_ptr<ATOMUpdated> updated) :
+ myId(id), myTitle(title), myUpdated(updated) {
+}
+
+
+
+ATOMFeedMetadata::ATOMFeedMetadata() {
+}
+
+ATOMFeedMetadata::ATOMFeedMetadata(shared_ptr<ATOMId> id, const std::string &title, shared_ptr<ATOMUpdated> updated) :
+ myId(id), myTitle(title), myUpdated(updated) {
+}
+
+
+
+/*
+ATOMFeed::ATOMFeed() {
+}
+
+ATOMFeed::ATOMFeed(const ATOMId &id, const std::string &title, shared_ptr<ATOMUpdated> updated) :
+ ATOMFeedMatadata(id, title, updated) {
+}
+*/
+
+
diff --git a/fbreader/src/network/atom/ATOMContainers.h b/fbreader/src/network/atom/ATOMContainers.h
new file mode 100644
index 0000000..1fb3f92
--- /dev/null
+++ b/fbreader/src/network/atom/ATOMContainers.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __ATOMCONTAINTERS_H__
+#define __ATOMCONTAINTERS_H__
+
+#include <vector>
+
+#include <shared_ptr.h>
+
+#include "ATOMMetadata.h"
+
+
+
+class ATOMEntry : public ATOMCommonAttributes {
+
+public:
+ ATOMEntry();
+ ATOMEntry(shared_ptr<ATOMId> id, const std::string &title, shared_ptr<ATOMUpdated> updated);
+
+ std::vector<shared_ptr<ATOMAuthor> > &authors() { return myAuthors; }
+ std::vector<shared_ptr<ATOMCategory> > &categories() { return myCategories; }
+ std::vector<shared_ptr<ATOMContributor> > &contributors() { return myContributors; }
+ std::vector<shared_ptr<ATOMLink> > &links() { return myLinks; }
+
+ shared_ptr<ATOMPublished> published() { return myPublished; }
+ shared_ptr<ATOMIcon> icon() { return myIcon; }
+ const std::string &rights() { return myRights; }
+ const std::string &summary() { return mySummary; }
+ const std::string &title() { return myTitle; }
+ shared_ptr<ATOMUpdated> updated() { return myUpdated; }
+
+ void setPublished(shared_ptr<ATOMPublished> published) { myPublished = published; }
+ void setIcon(shared_ptr<ATOMIcon> icon) { myIcon = icon; }
+ void setRights(const std::string &rights) { myRights = rights; }
+ void setSummary(const std::string &summary) { mySummary = summary; }
+ void setTitle(const std::string &title) { myTitle = title; }
+ void setUpdated(shared_ptr<ATOMUpdated> updated) { myUpdated = updated; }
+
+ shared_ptr<ATOMId> id() { return myId; }
+ void setId(shared_ptr<ATOMId> id) { myId = id; }
+
+private:
+ shared_ptr<ATOMId> myId;
+
+ std::vector<shared_ptr<ATOMAuthor> > myAuthors;
+ std::vector<shared_ptr<ATOMCategory> > myCategories;
+ //shared_ptr<ATOMContent> myContent; TODO: implement ATOMContent
+ std::vector<shared_ptr<ATOMContributor> > myContributors;
+ std::vector<shared_ptr<ATOMLink> > myLinks;
+ shared_ptr<ATOMIcon> myIcon;
+ shared_ptr<ATOMPublished> myPublished;
+ std::string myRights; // TODO: implement ATOMTextConstruct
+ //shared_ptr<ATOMSource> mySource; // TODO: implement ATOMSource
+ std::string mySummary; // TODO: implement ATOMTextConstruct
+ std::string myTitle; // TODO: implement ATOMTextConstruct
+ shared_ptr<ATOMUpdated> myUpdated;
+};
+
+
+class ATOMFeedMetadata : public ATOMCommonAttributes {
+
+public:
+ ATOMFeedMetadata();
+ ATOMFeedMetadata(shared_ptr<ATOMId> id, const std::string &title, shared_ptr<ATOMUpdated> updated);
+
+ std::vector<shared_ptr<ATOMAuthor> > &authors() { return myAuthors; }
+ std::vector<shared_ptr<ATOMCategory> > &categories() { return myCategories; }
+ std::vector<shared_ptr<ATOMContributor> > &contributors() { return myContributors; }
+ std::vector<shared_ptr<ATOMLink> > &links() { return myLinks; }
+
+ shared_ptr<ATOMGenerator> generator() { return myGenerator; }
+ shared_ptr<ATOMIcon> icon() { return myIcon; }
+ shared_ptr<ATOMLogo> logo() { return myLogo; }
+ const std::string &rights() { return myRights; }
+ const std::string &subtitle() { return mySubtitle; }
+ const std::string &summary() { return mySummary; }
+ const std::string &title() { return myTitle; }
+ shared_ptr<ATOMUpdated> updated() { return myUpdated; }
+
+ void setGenerator(shared_ptr<ATOMGenerator> generator) { myGenerator = generator; }
+ void setIcon(shared_ptr<ATOMIcon> icon) { myIcon = icon; }
+ void setLogo(shared_ptr<ATOMLogo> logo) { myLogo = logo; }
+ void setRights(const std::string &rights) { myRights = rights; }
+ void setSubtitle(const std::string &subtitle) { mySubtitle = subtitle; }
+ void setSummary(const std::string &summary) { mySummary = summary; }
+ void setTitle(const std::string &title) { myTitle = title; }
+ void setUpdated(shared_ptr<ATOMUpdated> updated) { myUpdated = updated; }
+
+ shared_ptr<ATOMId> id() { return myId; }
+ void setId(shared_ptr<ATOMId> id) { myId = id; }
+
+private:
+ shared_ptr<ATOMId> myId;
+
+ std::vector<shared_ptr<ATOMAuthor> > myAuthors;
+ std::vector<shared_ptr<ATOMCategory> > myCategories;
+ std::vector<shared_ptr<ATOMContributor> > myContributors;
+ shared_ptr<ATOMGenerator> myGenerator;
+ shared_ptr<ATOMIcon> myIcon;
+ std::vector<shared_ptr<ATOMLink> > myLinks;
+ shared_ptr<ATOMLogo> myLogo;
+ std::string myRights; // TODO: implement ATOMTextConstruct
+ std::string mySubtitle; // TODO: implement ATOMTextConstruct
+ std::string mySummary; // TODO: implement ATOMTextConstruct
+ std::string myTitle; // TODO: implement ATOMTextConstruct
+ shared_ptr<ATOMUpdated> myUpdated;
+};
+
+
+/*
+class ATOMFeed : public ATOMFeedMetadata {
+
+public:
+ ATOMFeed();
+ ATOMFeed(const ATOMId &id, const std::string &title, shared_ptr<ATOMUpdated> updated);
+
+ std::vector<shared_ptr<ATOMEntry> > entries() { return myEntries; }
+
+private:
+ std::vector<shared_ptr<ATOMEntry> > myEntries;
+};
+*/
+
+
+#endif /* __ATOMCONTAINTERS_H__ */
diff --git a/fbreader/src/network/atom/ATOMMetadata.cpp b/fbreader/src/network/atom/ATOMMetadata.cpp
new file mode 100644
index 0000000..cb81e0e
--- /dev/null
+++ b/fbreader/src/network/atom/ATOMMetadata.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 "ATOMMetadata.h"
+
+
+const std::string ATOMConstants::TYPE_TEXT = "text";
+const std::string ATOMConstants::TYPE_HTML = "html";
+const std::string ATOMConstants::TYPE_XHTML = "xhtml";
+
+const std::string ATOMConstants::TYPE_DEFAULT = TYPE_TEXT;
+
+const std::string ATOMConstants::REL_ALTERNATE = "alternate";
+const std::string ATOMConstants::REL_RELATED = "related";
+const std::string ATOMConstants::REL_SELF = "self";
+const std::string ATOMConstants::REL_ENCLOSURE = "enclosure";
+const std::string ATOMConstants::REL_VIA = "via";
+
+
+
+const std::string ATOMCategory::TERM = "term";
+const std::string ATOMCategory::SCHEME = "scheme";
+const std::string ATOMCategory::LABEL = "label";
+
+const std::string ATOMGenerator::URI = "uri";
+const std::string ATOMGenerator::VERSION_ATT = "version";
+
+const std::string ATOMLink::HREF = "href";
+const std::string ATOMLink::REL = "rel";
+const std::string ATOMLink::TYPE = "type";
+const std::string ATOMLink::HREFLANG = "hreflang";
+const std::string ATOMLink::TITLE = "title";
+const std::string ATOMLink::LENGTH = "length";
+
+
+
+ATOMAuthor::ATOMAuthor() {
+}
+
+ATOMAuthor::ATOMAuthor(const std::string &name) : ATOMPersonConstruct(name) {
+}
+
+
+
+ATOMCategory::ATOMCategory() {
+}
+
+ATOMCategory::ATOMCategory(const std::string &termStr) {
+ term() = termStr;
+}
+
+void ATOMCategory::readAttributes(const std::map<std::string, std::string> &attributes) {
+ ATOMCommonAttributes::readAttributes(attributes);
+ readAttribute(TERM, attributes);
+ readAttribute(SCHEME, attributes);
+ readAttribute(LABEL, attributes);
+}
+
+
+
+ATOMContributor::ATOMContributor() {
+}
+
+ATOMContributor::ATOMContributor(const std::string &name) : ATOMPersonConstruct(name) {
+}
+
+
+
+ATOMGenerator::ATOMGenerator() {
+}
+
+ATOMGenerator::ATOMGenerator(const std::string &text) : myText(text) {
+}
+
+void ATOMGenerator::readAttributes(const std::map<std::string, std::string> &attributes) {
+ ATOMCommonAttributes::readAttributes(attributes);
+ readAttribute(URI, attributes);
+ readAttribute(VERSION_ATT, attributes);
+}
+
+
+
+ATOMIcon::ATOMIcon() {
+}
+
+ATOMIcon::ATOMIcon(const std::string &uri) : myUri(uri) {
+}
+
+
+
+ATOMId::ATOMId() {
+}
+
+ATOMId::ATOMId(const std::string &uri) : myUri(uri) {
+}
+
+
+
+ATOMLink::ATOMLink() {
+}
+
+ATOMLink::ATOMLink(const std::string &hrefStr) {
+ href() = hrefStr;
+}
+
+ATOMLink::ATOMLink(const std::string &hrefStr, const std::string &relStr) {
+ href() = hrefStr;
+ rel() = relStr;
+}
+
+ATOMLink::ATOMLink(const std::string &hrefStr, const std::string &relStr, const std::string &typeStr){
+ href() = hrefStr;
+ rel() = relStr;
+ type() = typeStr;
+}
+
+ATOMLink::ATOMLink(const std::string &hrefStr, const std::string &relStr, const std::string &typeStr, const std::string &titleStr) {
+ href() = hrefStr;
+ rel() = relStr;
+ type() = typeStr;
+ title() = titleStr;
+}
+
+void ATOMLink::readAttributes(const std::map<std::string, std::string> &attributes) {
+ ATOMCommonAttributes::readAttributes(attributes);
+ readAttribute(HREF, attributes);
+ readAttribute(REL, attributes);
+ readAttribute(TYPE, attributes);
+ readAttribute(HREFLANG, attributes);
+ readAttribute(TITLE, attributes);
+ readAttribute(LENGTH, attributes);
+}
+
+ATOMLogo::ATOMLogo() {
+}
+
+ATOMLogo::ATOMLogo(const std::string &uri) : myUri(uri) {
+}
+
+
+
+ATOMPublished::ATOMPublished() : ATOMDateConstruct(0) {
+}
+
+ATOMPublished::ATOMPublished(int year) : ATOMDateConstruct(year) {
+}
+
+ATOMPublished::ATOMPublished(int year, int month, int day) : ATOMDateConstruct(year, month, day) {
+}
+
+ATOMPublished::ATOMPublished(int year, int month, int day, int hour, int minutes, int seconds) :
+ ATOMDateConstruct(year, month, day, hour, minutes, seconds) {
+}
+
+ATOMPublished::ATOMPublished(int year, int month, int day, int hour, int minutes, int seconds, float sfract) :
+ ATOMDateConstruct(year, month, day, hour, minutes, seconds, sfract) {
+}
+
+ATOMPublished::ATOMPublished(int year, int month, int day, int hour, int minutes, int seconds, float sfract, int tzhour, int tzminutes) :
+ ATOMDateConstruct(year, month, day, hour, minutes, seconds, sfract, tzhour, tzminutes) {
+}
+
+
+
+ATOMUpdated::ATOMUpdated() : ATOMDateConstruct(0) {
+}
+
+ATOMUpdated::ATOMUpdated(int year) : ATOMDateConstruct(year) {
+}
+
+ATOMUpdated::ATOMUpdated(int year, int month, int day) : ATOMDateConstruct(year, month, day) {
+}
+
+ATOMUpdated::ATOMUpdated(int year, int month, int day, int hour, int minutes, int seconds) :
+ ATOMDateConstruct(year, month, day, hour, minutes, seconds) {
+}
+
+ATOMUpdated::ATOMUpdated(int year, int month, int day, int hour, int minutes, int seconds, float sfract) :
+ ATOMDateConstruct(year, month, day, hour, minutes, seconds, sfract) {
+}
+
+ATOMUpdated::ATOMUpdated(int year, int month, int day, int hour, int minutes, int seconds, float sfract, int tzhour, int tzminutes) :
+ ATOMDateConstruct(year, month, day, hour, minutes, seconds, sfract, tzhour, tzminutes) {
+}
+
+
diff --git a/fbreader/src/network/atom/ATOMMetadata.h b/fbreader/src/network/atom/ATOMMetadata.h
new file mode 100644
index 0000000..3fb7619
--- /dev/null
+++ b/fbreader/src/network/atom/ATOMMetadata.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __ATOMMETADATA_H__
+#define __ATOMMETADATA_H__
+
+#include "ATOMConstructs.h"
+
+
+class ATOMConstants {
+
+private:
+ ATOMConstants();
+
+public:
+ static const std::string TYPE_TEXT;
+ static const std::string TYPE_HTML;
+ static const std::string TYPE_XHTML;
+ static const std::string TYPE_DEFAULT;
+
+ static const std::string REL_ALTERNATE;
+ static const std::string REL_RELATED;
+ static const std::string REL_SELF;
+ static const std::string REL_ENCLOSURE;
+ static const std::string REL_VIA;
+};
+
+
+
+
+
+class ATOMAuthor : public ATOMPersonConstruct {
+
+public:
+ ATOMAuthor();
+ ATOMAuthor(const std::string &name);
+};
+
+
+
+class ATOMCategory : public ATOMCommonAttributes {
+
+public:
+ static const std::string TERM;
+ static const std::string SCHEME;
+ static const std::string LABEL;
+
+public:
+ ATOMCategory();
+ ATOMCategory(const std::string &termStr);
+
+public:
+ std::string &term() { return attributes()[TERM]; }
+ std::string &scheme() { return attributes()[SCHEME]; }
+ std::string &label() { return attributes()[LABEL]; }
+
+ void readAttributes(const std::map<std::string, std::string> &attributes);
+};
+
+
+
+class ATOMContributor : public ATOMPersonConstruct {
+
+public:
+ ATOMContributor();
+ ATOMContributor(const std::string &name);
+};
+
+
+
+class ATOMGenerator : public ATOMCommonAttributes {
+
+public:
+ static const std::string URI;
+ static const std::string VERSION_ATT;
+
+public:
+ ATOMGenerator();
+ ATOMGenerator(const std::string &text);
+
+public:
+ const std::string &text() const { return myText; }
+ void setText(const std::string &text) { myText = text; }
+
+ std::string &uri() { return attributes()[URI]; }
+ std::string &version() { return attributes()[VERSION_ATT]; }
+
+ void readAttributes(const std::map<std::string, std::string> &attributes);
+
+private:
+ std::string myText;
+};
+
+
+
+class ATOMIcon : public ATOMCommonAttributes {
+
+public:
+ ATOMIcon();
+ ATOMIcon(const std::string &uri);
+
+public:
+ const std::string &uri() const { return myUri; }
+ void setUri(const std::string &uri) { myUri = uri; }
+
+private:
+ std::string myUri;
+};
+
+
+
+class ATOMId : public ATOMCommonAttributes {
+
+public:
+ ATOMId();
+ ATOMId(const std::string &uri);
+
+ const ATOMId &operator = (const ATOMId &id);
+
+ bool operator == (const ATOMId &id) const;
+ bool operator != (const ATOMId &id) const;
+
+public:
+ const std::string &uri() const { return myUri; }
+ void setUri(const std::string &uri) { myUri = uri; }
+
+private:
+ std::string myUri;
+};
+
+inline const ATOMId &ATOMId::operator = (const ATOMId &id) { myUri = id.myUri; return *this; }
+inline bool ATOMId::operator == (const ATOMId &id) const { return myUri == id.myUri; }
+inline bool ATOMId::operator != (const ATOMId &id) const { return myUri != id.myUri; }
+
+
+
+class ATOMLink : public ATOMCommonAttributes {
+
+public:
+ static const std::string HREF;
+ static const std::string REL;
+ static const std::string TYPE;
+ static const std::string HREFLANG;
+ static const std::string TITLE;
+ static const std::string LENGTH;
+
+public:
+ ATOMLink();
+ ATOMLink(const std::string &hrefStr);
+ ATOMLink(const std::string &hrefStr, const std::string &relStr);
+ ATOMLink(const std::string &hrefStr, const std::string &relStr, const std::string &typeStr);
+ ATOMLink(const std::string &hrefStr, const std::string &relStr, const std::string &typeStr, const std::string &titleStr);
+
+public:
+ std::string &href() { return attributes()[HREF]; }
+ std::string &rel() { return attributes()[REL]; }
+ std::string &type() { return attributes()[TYPE]; }
+ std::string &hreflang() { return attributes()[HREFLANG]; }
+ std::string &title() { return attributes()[TITLE]; }
+ std::string &length() { return attributes()[LENGTH]; }
+
+ void readAttributes(const std::map<std::string, std::string> &attributes);
+};
+
+
+
+class ATOMLogo : public ATOMCommonAttributes {
+
+public:
+ ATOMLogo();
+ ATOMLogo(const std::string &uri);
+
+public:
+ const std::string &uri() const { return myUri; }
+ void setUri(const std::string &uri) { myUri = uri; }
+
+private:
+ std::string myUri;
+};
+
+
+class ATOMPublished : public ATOMDateConstruct {
+
+public:
+ ATOMPublished();
+ ATOMPublished(int year);
+ ATOMPublished(int year, int month, int day);
+ ATOMPublished(int year, int month, int day, int hour, int minutes, int seconds);
+ ATOMPublished(int year, int month, int day, int hour, int minutes, int seconds, float sfract);
+ ATOMPublished(int year, int month, int day, int hour, int minutes, int seconds, float sfract, int tzhour, int tzminutes);
+};
+
+class ATOMUpdated : public ATOMDateConstruct {
+
+public:
+ ATOMUpdated();
+ ATOMUpdated(int year);
+ ATOMUpdated(int year, int month, int day);
+ ATOMUpdated(int year, int month, int day, int hour, int minutes, int seconds);
+ ATOMUpdated(int year, int month, int day, int hour, int minutes, int seconds, float sfract);
+ ATOMUpdated(int year, int month, int day, int hour, int minutes, int seconds, float sfract, int tzhour, int tzminutes);
+};
+
+
+#endif /* ATOMMETADATA */
diff --git a/fbreader/src/network/authentication/NetworkAuthenticationManager.cpp b/fbreader/src/network/authentication/NetworkAuthenticationManager.cpp
new file mode 100644
index 0000000..137388f
--- /dev/null
+++ b/fbreader/src/network/authentication/NetworkAuthenticationManager.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 "NetworkAuthenticationManager.h"
+
+#include "../NetworkLink.h"
+#include "../NetworkErrors.h"
+
+NetworkAuthenticationManager::NetworkAuthenticationManager(const NetworkLink &link) :
+ Link(link),
+ UserNameOption(ZLCategoryKey::NETWORK, link.getSiteName(), "userName", ""),
+ SkipIPOption(ZLCategoryKey::NETWORK, link.getSiteName(), "skipIP", true) {
+}
+
+NetworkAuthenticationManager::~NetworkAuthenticationManager() {
+}
+
+bool NetworkAuthenticationManager::needsInitialization() {
+ return false;
+}
+
+std::string NetworkAuthenticationManager::initialize(shared_ptr<ZLNetworkRequest::Listener> listener) {
+ listener->finished();
+ return NetworkErrors::errorMessage(NetworkErrors::ERROR_UNSUPPORTED_OPERATION);
+}
+
+bool NetworkAuthenticationManager::needPurchase(const NetworkBookItem &) {
+ return true;
+}
+
+std::string NetworkAuthenticationManager::purchaseBook(const NetworkBookItem &, shared_ptr<ZLNetworkRequest::Listener> listener) {
+ std::string error = NetworkErrors::errorMessage(NetworkErrors::ERROR_UNSUPPORTED_OPERATION);
+ listener->finished(error);
+ return error;
+}
+
+
+std::string NetworkAuthenticationManager::topupAccountLink() {
+ return "";
+}
+
+std::string NetworkAuthenticationManager::currentAccount() {
+ return "";
+}
+
+bool NetworkAuthenticationManager::skipIPSupported() {
+ return false;
+}
+
+bool NetworkAuthenticationManager::registrationSupported() {
+ return false;
+}
+
+std::string NetworkAuthenticationManager::registerUser(const std::string &, const std::string &, const std::string &) {
+ return NetworkErrors::errorMessage(NetworkErrors::ERROR_UNSUPPORTED_OPERATION);
+}
+
+bool NetworkAuthenticationManager::passwordRecoverySupported() {
+ return false;
+}
+
+std::string NetworkAuthenticationManager::recoverPassword(const std::string &) {
+ return NetworkErrors::errorMessage(NetworkErrors::ERROR_UNSUPPORTED_OPERATION);
+}
diff --git a/fbreader/src/network/authentication/NetworkAuthenticationManager.h b/fbreader/src/network/authentication/NetworkAuthenticationManager.h
new file mode 100644
index 0000000..75ae9dd
--- /dev/null
+++ b/fbreader/src/network/authentication/NetworkAuthenticationManager.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __NETWORKAUTHENTICATIONMANAGER_H__
+#define __NETWORKAUTHENTICATIONMANAGER_H__
+
+#include <shared_ptr.h>
+#include <ZLOptions.h>
+#include <ZLBoolean3.h>
+
+#include "../NetworkItems.h"
+#include "../BookReference.h"
+
+class NetworkLink;
+
+class NetworkAuthenticationManager {
+
+public:
+ NetworkAuthenticationManager(const NetworkLink &link);
+ virtual ~NetworkAuthenticationManager();
+
+public:
+ const NetworkLink &Link;
+ ZLStringOption UserNameOption;
+ ZLBooleanOption SkipIPOption;
+
+public:
+ struct AuthenticationStatus {
+ const ZLBoolean3 Status;
+ const std::string Message;
+
+ AuthenticationStatus(bool status);
+ AuthenticationStatus(const std::string &msg);
+ };
+
+ virtual AuthenticationStatus isAuthorised(shared_ptr<ZLNetworkRequest::Listener> listener = 0) = 0;
+ virtual std::string authorise(const std::string &pwd, shared_ptr<ZLNetworkRequest::Listener> listener) = 0; // returns error message
+ virtual void logOut() = 0;
+
+ virtual bool skipIPSupported();
+
+ virtual shared_ptr<BookReference> downloadReference(const NetworkBookItem &book) = 0;
+
+public: // Account specific methods (can be called only if authorised!!!)
+ virtual const std::string &currentUserName() = 0;
+ virtual bool needsInitialization();
+ virtual std::string initialize(shared_ptr<ZLNetworkRequest::Listener> listener); // returns error message
+ virtual bool needPurchase(const NetworkBookItem &book); // returns true if link must be purchased before downloading
+ virtual std::string purchaseBook(const NetworkBookItem &, shared_ptr<ZLNetworkRequest::Listener> listener); // returns error message
+
+ virtual std::string topupAccountLink();
+ virtual std::string currentAccount();
+
+ virtual const NetworkItem::List &purchasedBooks() const = 0;
+
+public: // new User Registration
+ virtual bool registrationSupported();
+ virtual std::string registerUser(const std::string &login, const std::string &password, const std::string &email);
+
+public: // Password Recovery
+ virtual bool passwordRecoverySupported();
+ virtual std::string recoverPassword(const std::string &email);
+
+private: // disable copying
+ NetworkAuthenticationManager(const NetworkAuthenticationManager &);
+ const NetworkAuthenticationManager &operator = (const NetworkAuthenticationManager &);
+};
+
+inline NetworkAuthenticationManager::AuthenticationStatus::AuthenticationStatus(bool status) : Status(status ? B3_TRUE : B3_FALSE) {}
+inline NetworkAuthenticationManager::AuthenticationStatus::AuthenticationStatus(const std::string &msg) : Status(B3_UNDEFINED), Message(msg) {}
+
+#endif /* __NETWORKAUTHENTICATIONMANAGER_H__ */
diff --git a/fbreader/src/network/authentication/litres/LitResAuthenticationDataParser.cpp b/fbreader/src/network/authentication/litres/LitResAuthenticationDataParser.cpp
new file mode 100644
index 0000000..b1b6c69
--- /dev/null
+++ b/fbreader/src/network/authentication/litres/LitResAuthenticationDataParser.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 "LitResAuthenticationDataParser.h"
+
+
+static const std::string TAG_AUTHORIZATION_OK = "catalit-authorization-ok";
+static const std::string TAG_AUTHORIZATION_FAILED = "catalit-authorization-failed";
+
+static const std::string TAG_PURCHASE_OK = "catalit-purchase-ok";
+static const std::string TAG_PURCHASE_FAILED = "catalit-purchase-failed";
+
+static const std::string TAG_DOWNLOAD_FAILED = "catalit-download-failed";
+
+static const std::string TAG_REGISTRATION_FAILED = "catalit-registration-failed";
+
+static const std::string TAG_PASSWORD_RECOVERY_OK = "catalit-pass-recover-ok";
+static const std::string TAG_PASSWORD_RECOVERY_FAILED = "catalit-pass-recover-failed";
+
+LitResAuthenticationDataParser::LitResAuthenticationDataParser() {
+}
+
+void LitResAuthenticationDataParser::startElementHandler(const char *tag, const char **attributes) {
+ myAttributes.clear();
+ while (*attributes != 0) {
+ std::string name(*attributes++);
+ if (*attributes == 0) {
+ break;
+ }
+ std::string value(*attributes++);
+ myAttributes.insert(std::make_pair(name, value));
+ }
+ processTag(tag);
+}
+
+
+
+
+
+LitResLoginDataParser::LitResLoginDataParser(std::string &firstName, std::string &lastName, std::string &sid) :
+ myFirstName(firstName), myLastName(lastName), mySid(sid) {
+}
+
+void LitResLoginDataParser::processTag(const std::string &tag) {
+ if (TAG_AUTHORIZATION_FAILED == tag) {
+ setErrorCode(NetworkErrors::ERROR_AUTHENTICATION_FAILED);
+ } else if (TAG_AUTHORIZATION_OK == tag) {
+ myFirstName = attributes()["first-name"];
+ myLastName = attributes()["first-name"];
+ mySid = attributes()["sid"];
+ }
+}
+
+
+LitResPurchaseDataParser::LitResPurchaseDataParser(std::string &account, std::string &bookId) :
+ myAccount(account), myBookId(bookId) {
+}
+
+void LitResPurchaseDataParser::processTag(const std::string &tag) {
+ if (TAG_AUTHORIZATION_FAILED == tag) {
+ setErrorCode(NetworkErrors::ERROR_AUTHENTICATION_FAILED);
+ } else {
+ myAccount = attributes()["account"];
+ myBookId = attributes()["art"];
+ if (TAG_PURCHASE_OK == tag) {
+ // nop
+ } else if (TAG_PURCHASE_FAILED == tag) {
+ const std::string &error = attributes()["error"];
+ if ("1" == error) {
+ setErrorCode(NetworkErrors::ERROR_PURCHASE_NOT_ENOUGH_MONEY);
+ } else if ("2" == error) {
+ setErrorCode(NetworkErrors::ERROR_PURCHASE_MISSING_BOOK);
+ } else if ("3" == error) {
+ setErrorCode(NetworkErrors::ERROR_PURCHASE_ALREADY_PURCHASED);
+ } else {
+ setErrorCode(NetworkErrors::ERROR_INTERNAL);
+ }
+ }
+ }
+}
+
+
+/*LitResDownloadErrorDataParser::LitResDownloadErrorDataParser() {
+}
+
+void LitResDownloadErrorDataParser::processTag(const std::string &tag) {
+ if (TAG_AUTHORIZATION_FAILED == tag) {
+ setErrorCode(NetworkErrors::ERROR_AUTHENTICATION_FAILED);
+ } else {
+ if (TAG_DOWNLOAD_FAILED == tag) {
+ const std::string &error = attributes()["error"];
+ if ("1" == error) {
+ setErrorCode(NetworkErrors::ERROR_BOOK_NOT_PURCHASED);
+ } else if ("2" == error) {
+ setErrorCode(NetworkErrors::ERROR_DOWNLOAD_LIMIT_EXCEEDED);
+ } else {
+ setErrorCode(NetworkErrors::ERROR_INTERNAL);
+ }
+ }
+ }
+}*/
+
+
+LitResRegisterUserDataParser::LitResRegisterUserDataParser(std::string &sid) : mySid(sid) {
+}
+
+void LitResRegisterUserDataParser::processTag(const std::string &tag) {
+ if (TAG_REGISTRATION_FAILED == tag) {
+ const std::string &error = attributes()["error"];
+ if ("1" == error) {
+ setErrorCode(NetworkErrors::ERROR_LOGIN_ALREADY_TAKEN);
+ } else if ("2" == error) {
+ setErrorCode(NetworkErrors::ERROR_LOGIN_WAS_NOT_SPECIFIED);
+ } else if ("3" == error) {
+ setErrorCode(NetworkErrors::ERROR_PASSWORD_WAS_NOT_SPECIFIED);
+ } else if ("4" == error) {
+ setErrorCode(NetworkErrors::ERROR_INVALID_EMAIL);
+ } else if ("5" == error) {
+ setErrorCode(NetworkErrors::ERROR_TOO_MANY_REGISTRATIONS);
+ } else {
+ setErrorCode(NetworkErrors::ERROR_INTERNAL);
+ }
+ } else if (TAG_AUTHORIZATION_OK == tag) {
+ mySid = attributes()["sid"];
+ }
+}
+
+
+void LitResPasswordRecoveryDataParser::processTag(const std::string &tag) {
+ if (TAG_PASSWORD_RECOVERY_FAILED == tag) {
+ const std::string &error = attributes()["error"];
+ if ("1" == error) {
+ setErrorCode(NetworkErrors::ERROR_NO_USER_EMAIL);
+ } else if ("2" == error) {
+ setErrorCode(NetworkErrors::ERROR_EMAIL_WAS_NOT_SPECIFIED);
+ } else {
+ setErrorCode(NetworkErrors::ERROR_INTERNAL);
+ }
+ } else if (TAG_PASSWORD_RECOVERY_OK == tag) {
+ // NOP
+ }
+}
diff --git a/fbreader/src/network/authentication/litres/LitResAuthenticationDataParser.h b/fbreader/src/network/authentication/litres/LitResAuthenticationDataParser.h
new file mode 100644
index 0000000..60baa02
--- /dev/null
+++ b/fbreader/src/network/authentication/litres/LitResAuthenticationDataParser.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __LITRESAUTHENTICATIONDATAPARSER_H__
+#define __LITRESAUTHENTICATIONDATAPARSER_H__
+
+#include <ZLXMLReader.h>
+
+#include "../../NetworkErrors.h"
+
+
+class LitResAuthenticationDataParser : public ZLXMLReader {
+
+public:
+ LitResAuthenticationDataParser();
+
+private:
+ void startElementHandler(const char *tag, const char **attributes);
+
+protected:
+ void setErrorCode(const std::string &msg);
+ std::map<std::string, std::string> &attributes();
+
+ virtual void processTag(const std::string &tag) = 0;
+
+private:
+ std::map<std::string, std::string> myAttributes;
+};
+
+inline void LitResAuthenticationDataParser::setErrorCode(const std::string &msg) { setErrorMessage(NetworkErrors::errorMessage(msg)); }
+inline std::map<std::string, std::string> &LitResAuthenticationDataParser::attributes() { return myAttributes; }
+
+
+class LitResLoginDataParser : public LitResAuthenticationDataParser {
+
+public:
+ LitResLoginDataParser(std::string &firstName, std::string &lastName, std::string &sid);
+
+private:
+ void processTag(const std::string &tag);
+
+private:
+ std::string &myFirstName;
+ std::string &myLastName;
+ std::string &mySid;
+};
+
+
+class LitResPurchaseDataParser : public LitResAuthenticationDataParser {
+
+public:
+ LitResPurchaseDataParser(std::string &account, std::string &bookId);
+
+private:
+ void processTag(const std::string &tag);
+
+private:
+ std::string &myAccount;
+ std::string &myBookId;
+};
+
+
+/*class LitResDownloadErrorDataParser : public LitResAuthenticationDataParser {
+
+public:
+ LitResDownloadErrorDataParser();
+
+private:
+ void processTag(const std::string &tag);
+
+};*/
+
+class LitResRegisterUserDataParser : public LitResAuthenticationDataParser {
+
+public:
+ LitResRegisterUserDataParser(std::string &sid);
+
+private:
+ void processTag(const std::string &tag);
+
+private:
+ std::string &mySid;
+};
+
+class LitResPasswordRecoveryDataParser : public LitResAuthenticationDataParser {
+
+private:
+ void processTag(const std::string &tag);
+};
+
+#endif /* __LITRESAUTHENTICATIONDATAPARSER_H__ */
diff --git a/fbreader/src/network/authentication/litres/LitResAuthenticationManager.cpp b/fbreader/src/network/authentication/litres/LitResAuthenticationManager.cpp
new file mode 100644
index 0000000..e552b5c
--- /dev/null
+++ b/fbreader/src/network/authentication/litres/LitResAuthenticationManager.cpp
@@ -0,0 +1,472 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 <ZLNetworkUtil.h>
+#include <ZLNetworkManager.h>
+#include <ZLUserData.h>
+#include <ZLExecutionUtil.h>
+
+#include "../../tree/NetworkLibrary.h"
+
+#include "../../litres/LitResBooksFeedParser.h"
+#include "../../litres/LitResUtil.h"
+#include "LitResAuthenticationManager.h"
+#include "LitResAuthenticationDataParser.h"
+
+#include "../../NetworkErrors.h"
+#include "../../NetworkLink.h"
+#include "../../NetworkLinkCollection.h"
+
+LitResAuthenticationManager::LitResAuthenticationManager(const NetworkLink &link) :
+ NetworkAuthenticationManager(link),
+ mySidChecked(false),
+ mySidUserNameOption(ZLCategoryKey::NETWORK, link.getSiteName(), "sidUserName", ""),
+ mySidOption(ZLCategoryKey::NETWORK, link.getSiteName(), "sid", "")
+{
+}
+
+class LitResAuthorisationScope : public ZLUserData {
+public:
+ std::string firstName;
+ std::string lastName;
+ std::string newSid;
+ shared_ptr<ZLNetworkRequest::Listener> listener;
+};
+
+NetworkAuthenticationManager::AuthenticationStatus LitResAuthenticationManager::isAuthorised(shared_ptr<ZLNetworkRequest::Listener> listener) {
+ const bool useNetwork = !listener.isNull();
+ bool authState = !mySidUserNameOption.value().empty() && !mySidOption.value().empty();
+ if (mySidChecked || !useNetwork) {
+ if (!listener.isNull())
+ listener->finished(authState ? std::string() : "Not authorised");
+ return AuthenticationStatus(authState);
+ }
+
+ if (!authState) {
+ mySidChecked = true;
+ mySidUserNameOption.setValue("");
+ mySidOption.setValue("");
+ listener->finished("Not authorised");
+ return AuthenticationStatus(false);
+ }
+
+ LitResAuthorisationScope *scope = new LitResAuthorisationScope;
+ scope->listener = listener;
+ shared_ptr<ZLXMLReader> xmlReader = new LitResLoginDataParser(scope->firstName, scope->lastName, scope->newSid);
+
+ std::string url = Link.url(NetworkLink::URL_SIGN_IN);
+ ZLNetworkUtil::appendParameter(url, "sid", mySidOption.value());
+
+ shared_ptr<ZLNetworkRequest> networkData = ZLNetworkManager::Instance().createXMLParserRequest(url, xmlReader);
+ networkData->setListener(ZLExecutionUtil::createListener(scope, this, &LitResAuthenticationManager::onAuthorised));
+ ZLNetworkManager::Instance().performAsync(networkData);
+ return AuthenticationStatus(std::string());
+}
+
+std::string LitResAuthenticationManager::authorise(const std::string &pwd, shared_ptr<ZLNetworkRequest::Listener> listener) {
+ LitResAuthorisationScope *scope = new LitResAuthorisationScope;
+ scope->listener = listener;
+ shared_ptr<ZLXMLReader> xmlReader = new LitResLoginDataParser(scope->firstName, scope->lastName, scope->newSid);
+
+ std::string url = Link.url(NetworkLink::URL_SIGN_IN);
+ ZLNetworkUtil::appendParameter(url, "login", UserNameOption.value());
+ ZLNetworkUtil::appendParameter(url, "pwd", pwd);
+ ZLNetworkUtil::appendParameter(url, "skip_ip", "1");
+
+ shared_ptr<ZLNetworkRequest> networkData =
+ ZLNetworkManager::Instance().createXMLParserRequest(
+ url,
+ xmlReader
+ );
+
+ networkData->setListener(ZLExecutionUtil::createListener(scope, this, &LitResAuthenticationManager::onAuthorised));
+ return ZLNetworkManager::Instance().performAsync(networkData);
+}
+
+void LitResAuthenticationManager::onAuthorised(ZLUserDataHolder &data, const std::string &error) {
+ LitResAuthorisationScope &scope = static_cast<LitResAuthorisationScope&>(*data.getUserData("scope"));
+
+ if (error == NetworkErrors::errorMessage(NetworkErrors::ERROR_TIMEOUT_EXPIRED)) {
+ scope.listener->finished(error);
+ return;
+ }
+
+ mySidChecked = true;
+ if (!error.empty()) {
+ mySidUserNameOption.setValue("");
+ mySidOption.setValue("");
+ } else {
+ mySidOption.setValue(scope.newSid);
+ mySidUserNameOption.setValue(UserNameOption.value());
+ }
+
+ scope.listener->finished(error);
+}
+
+
+void LitResAuthenticationManager::logOut() {
+ mySidChecked = true;
+ mySidUserNameOption.setValue("");
+ mySidOption.setValue("");
+
+ myInitializedDataSid.clear();
+ myPurchasedBooksIds.clear();
+ myPurchasedBooksList.clear();
+ myAccount.clear();
+}
+
+const std::string &LitResAuthenticationManager::currentUserName() {
+ return mySidUserNameOption.value();
+}
+
+bool LitResAuthenticationManager::needPurchase(const NetworkBookItem &book) {
+ return myPurchasedBooksIds.count(book.Id) == 0;
+}
+
+class LitResPurchaseBookScope : public ZLUserData {
+public:
+ std::string account;
+ std::string bookId;
+ const NetworkBookItem *book;
+ shared_ptr<ZLNetworkRequest::Listener> listener;
+};
+
+std::string LitResAuthenticationManager::purchaseBook(const NetworkBookItem &book, shared_ptr<ZLNetworkRequest::Listener> listener) {
+ const std::string &sid = mySidOption.value();
+ std::string error;
+ if (sid.empty()) {
+ error = NetworkErrors::errorMessage(NetworkErrors::ERROR_AUTHENTICATION_FAILED);
+ listener->finished(error);
+ return error;
+ }
+
+ shared_ptr<BookReference> reference = book.reference(BookReference::BUY);
+ if (reference.isNull()) {
+ // TODO: add correct error message
+ error = "Oh, that's impossible";
+ listener->finished(error);
+ return error;
+ }
+ std::string query = reference->URL;
+ ZLNetworkUtil::appendParameter(query, "sid", sid);
+
+ LitResPurchaseBookScope *scope = new LitResPurchaseBookScope;
+ scope->book = &book;
+ scope->listener = listener;
+
+ shared_ptr<ZLXMLReader> xmlReader = new LitResPurchaseDataParser(scope->account, scope->bookId);
+ shared_ptr<ZLNetworkRequest> networkData = ZLNetworkManager::Instance().createXMLParserRequest(query, xmlReader);
+ networkData->setListener(ZLExecutionUtil::createListener(scope, this, &LitResAuthenticationManager::onBookPurchased));
+ return ZLNetworkManager::Instance().performAsync(networkData);
+}
+
+void LitResAuthenticationManager::onBookPurchased(ZLUserDataHolder &data, const std::string &error) {
+ LitResPurchaseBookScope &scope = static_cast<LitResPurchaseBookScope&>(*data.getUserData("scope"));
+ shared_ptr<ZLNetworkRequest::Listener> listener = scope.listener;
+ if (!scope.account.empty()) {
+ myAccount = BuyBookReference::price(scope.account, "RUB");
+ }
+ if (error == NetworkErrors::errorMessage(NetworkErrors::ERROR_AUTHENTICATION_FAILED)) {
+ mySidChecked = true;
+ mySidUserNameOption.setValue("");
+ mySidOption.setValue("");
+ }
+ const std::string alreadyPurchasedError = NetworkErrors::errorMessage(NetworkErrors::ERROR_PURCHASE_ALREADY_PURCHASED);
+ if (error != alreadyPurchasedError) {
+ if (!error.empty()) {
+ listener->finished(error);
+ return;
+ }
+ if (scope.bookId != scope.book->Id) {
+ listener->finished(NetworkErrors::errorMessage(NetworkErrors::ERROR_SOMETHING_WRONG, Link.getSiteName()));
+ return;
+ }
+ }
+ myPurchasedBooksIds.insert(scope.book->Id);
+ myPurchasedBooksList.push_back(new NetworkBookItem(*scope.book, 0));
+ listener->finished(error);
+}
+
+shared_ptr<BookReference> LitResAuthenticationManager::downloadReference(const NetworkBookItem &book) {
+ const std::string &sid = mySidOption.value();
+ if (sid.empty()) {
+ return 0;
+ }
+ shared_ptr<BookReference> reference =
+ book.reference(BookReference::DOWNLOAD_FULL_CONDITIONAL);
+ if (reference.isNull()) {
+ return 0;
+ }
+ std::string url = reference->URL;
+ ZLNetworkUtil::appendParameter(url, "sid", sid);
+ return new DecoratedBookReference(*reference, url);
+}
+
+void LitResAuthenticationManager::collectPurchasedBooks(NetworkItem::List &list) {
+ list.assign(myPurchasedBooksList.begin(), myPurchasedBooksList.end());
+}
+
+const std::set<std::string> &LitResAuthenticationManager::getPurchasedIds() const {
+ return myPurchasedBooksIds;
+}
+
+const NetworkItem::List &LitResAuthenticationManager::purchasedBooks() const {
+ return myPurchasedBooksList;
+}
+
+std::string LitResAuthenticationManager::topupAccountLink() {
+ const std::string &sid = mySidOption.value();
+ if (sid.empty()) {
+ return std::string();
+ }
+ std::string url = Link.url(NetworkLink::URL_TOPUP);
+ ZLNetworkUtil::appendParameter(url, "sid", sid);
+ return url;
+}
+
+std::string LitResAuthenticationManager::currentAccount() {
+ return myAccount;
+}
+
+bool LitResAuthenticationManager::needsInitialization() {
+ const std::string &sid = mySidOption.value();
+ if (sid.empty()) {
+ return false;
+ }
+ return sid != myInitializedDataSid;
+}
+
+class LitResInitializationScope : public ZLUserData {
+public:
+ std::string dummy;
+ std::string error;
+ shared_ptr<ZLNetworkRequest::Listener> listener;
+};
+
+std::string LitResAuthenticationManager::initialize(shared_ptr<ZLNetworkRequest::Listener> listener) {
+ const std::string &sid = mySidOption.value();
+ if (sid.empty()) {
+ listener->finished(NetworkErrors::errorMessage(NetworkErrors::ERROR_AUTHENTICATION_FAILED));
+ return NetworkErrors::errorMessage(NetworkErrors::ERROR_AUTHENTICATION_FAILED);
+ }
+ if (sid == myInitializedDataSid) {
+ listener->finished(std::string());
+ return std::string();
+ }
+
+ LitResInitializationScope *scope = new LitResInitializationScope;
+ scope->listener = listener;
+
+ shared_ptr<ZLNetworkRequest> request = loadPurchasedBooks(myPurchasedBooksIds, myPurchasedBooksList);
+ request->setListener(ZLExecutionUtil::createListener(scope, this, &LitResAuthenticationManager::onBooksLoaded));
+ return ZLNetworkManager::Instance().performAsync(request);
+}
+
+void LitResAuthenticationManager::onBooksLoaded(ZLUserDataHolder &data, const std::string &error) {
+ LitResInitializationScope &scope = static_cast<LitResInitializationScope&>(*data.getUserData("scope"));
+
+ if (error == NetworkErrors::errorMessage(NetworkErrors::ERROR_TIMEOUT_EXPIRED)) {
+ scope.listener->finished(error);
+ return;
+ }
+
+ scope.error = error;
+ shared_ptr<ZLNetworkRequest> request = loadAccount(scope.dummy);
+ request->setListener(ZLExecutionUtil::createListener(new ZLUserDataHolder(data), this, &LitResAuthenticationManager::onAccountReceived));
+ ZLNetworkManager::Instance().performAsync(request);
+}
+
+void LitResAuthenticationManager::onAccountReceived(ZLUserDataHolder &data, const std::string &error) {
+ LitResInitializationScope &scope = static_cast<LitResInitializationScope&>(*data.getUserData("scope"));
+
+ if (error == NetworkErrors::errorMessage(NetworkErrors::ERROR_TIMEOUT_EXPIRED)) {
+ scope.listener->finished(error);
+ return;
+ }
+
+ if (!error.empty() && !scope.error.empty()) {
+ scope.error.append("\n").append(error);
+ } else if (!error.empty()) {
+ scope.error = error;
+ }
+ if (!scope.error.empty()) {
+ myInitializedDataSid.clear();
+ loadPurchasedBooksOnError(myPurchasedBooksIds, myPurchasedBooksList);
+ loadAccountOnError();
+ scope.listener->finished(scope.error);
+ return;
+ }
+ myInitializedDataSid = mySidOption.value();
+ loadPurchasedBooksOnSuccess(myPurchasedBooksIds, myPurchasedBooksList);
+ loadAccountOnSuccess();
+ scope.listener->finished();
+}
+
+shared_ptr<ZLNetworkRequest> LitResAuthenticationManager::loadPurchasedBooks(std::set<std::string> &purchasedBooksIds, NetworkItem::List &purchasedBooksList) {
+ const std::string &sid = mySidOption.value();
+ purchasedBooksIds.clear();
+ purchasedBooksList.clear();
+
+ std::string query;
+ ZLNetworkUtil::appendParameter(query, "my", "1");
+ ZLNetworkUtil::appendParameter(query, "sid", sid);
+
+ return ZLNetworkManager::Instance().createXMLParserRequest(
+ LitResUtil::url(Link, "pages/catalit_browser/" + query),
+ new LitResBooksFeedParser(Link, purchasedBooksList)
+ );
+}
+
+void LitResAuthenticationManager::loadPurchasedBooksOnError(std::set<std::string> &purchasedBooksIds, NetworkItem::List &purchasedBooksList) {
+ purchasedBooksIds.clear();
+ purchasedBooksList.clear();
+}
+
+void LitResAuthenticationManager::loadPurchasedBooksOnSuccess(std::set<std::string> &purchasedBooksIds, NetworkItem::List &purchasedBooksList) {
+ for (NetworkItem::List::iterator it = purchasedBooksList.begin(); it != purchasedBooksList.end(); ++it) {
+ NetworkBookItem &book = (NetworkBookItem&)**it;
+ book.Index = 0;
+ purchasedBooksIds.insert(book.Id);
+ }
+
+ NetworkLibrary::Instance().invalidateVisibility();
+ NetworkLibrary::Instance().synchronize();
+ NetworkLibrary::Instance().refresh();
+}
+
+shared_ptr<ZLNetworkRequest> LitResAuthenticationManager::loadAccount(std::string &dummy1) {
+ const std::string &sid = mySidOption.value();
+
+ myAccount.clear();
+
+ std::string query;
+ ZLNetworkUtil::appendParameter(query, "sid", sid);
+ ZLNetworkUtil::appendParameter(query, "art", "0");
+
+ return ZLNetworkManager::Instance().createXMLParserRequest(
+ LitResUtil::url(Link, "pages/purchase_book/" + query),
+ new LitResPurchaseDataParser(myAccount, dummy1)
+ );
+}
+
+void LitResAuthenticationManager::loadAccountOnError() {
+ myAccount.clear();
+}
+
+void LitResAuthenticationManager::loadAccountOnSuccess() {
+ myAccount = BuyBookReference::price(myAccount, "RUB");
+}
+
+bool LitResAuthenticationManager::skipIPSupported() {
+ return true;
+}
+
+bool LitResAuthenticationManager::registrationSupported() {
+ return true;
+}
+
+std::string LitResAuthenticationManager::registerUser(const std::string &login, const std::string &password, const std::string &email) {
+ std::string newSid;
+ shared_ptr<ZLXMLReader> xmlReader = new LitResRegisterUserDataParser(newSid);
+
+ std::string url = Link.url(NetworkLink::URL_SIGN_UP);
+ ZLNetworkUtil::appendParameter(url, "new_login", login);
+ ZLNetworkUtil::appendParameter(url, "new_pwd1", password);
+ ZLNetworkUtil::appendParameter(url, "mail", email);
+
+ shared_ptr<ZLNetworkRequest> networkData =
+ ZLNetworkManager::Instance().createXMLParserRequest(
+ url, xmlReader
+ );
+ std::string error = ZLNetworkManager::Instance().perform(networkData);
+
+ mySidChecked = true;
+ if (!error.empty()) {
+ mySidUserNameOption.setValue("");
+ mySidOption.setValue("");
+ return error;
+ }
+ mySidOption.setValue(newSid);
+ mySidUserNameOption.setValue(login);
+ return "";
+}
+
+bool LitResAuthenticationManager::passwordRecoverySupported() {
+ return true;
+}
+
+std::string LitResAuthenticationManager::recoverPassword(const std::string &email) {
+ std::string url = Link.url(NetworkLink::URL_RECOVER_PASSWORD);
+ ZLNetworkUtil::appendParameter(url, "mail", email);
+
+ shared_ptr<ZLNetworkRequest> networkData =
+ ZLNetworkManager::Instance().createXMLParserRequest(
+ url, new LitResPasswordRecoveryDataParser()
+ );
+ return ZLNetworkManager::Instance().perform(networkData);
+}
+
+class LitResReloadPurchasedBooksScope : public ZLUserData {
+public:
+ std::set<std::string> purchasedBooksIds;
+ NetworkItem::List purchasedBooksList;
+ shared_ptr<ZLNetworkRequest::Listener> Listener;
+};
+
+std::string LitResAuthenticationManager::reloadPurchasedBooks(shared_ptr<ZLNetworkRequest::Listener> listener) {
+ const std::string &sid = mySidOption.value();
+ std::string error;
+ if (sid.empty()) {
+ error = NetworkErrors::errorMessage(NetworkErrors::ERROR_AUTHENTICATION_FAILED);
+ listener->finished(error);
+ return error;
+ }
+ if (sid != myInitializedDataSid) {
+ mySidChecked = true;
+ mySidUserNameOption.setValue("");
+ mySidOption.setValue("");
+ error = NetworkErrors::errorMessage(NetworkErrors::ERROR_AUTHENTICATION_FAILED);
+ listener->finished(error);
+ return error;
+ }
+
+ LitResReloadPurchasedBooksScope *scope = new LitResReloadPurchasedBooksScope;
+ shared_ptr<ZLNetworkRequest> networkData = loadPurchasedBooks(scope->purchasedBooksIds, scope->purchasedBooksList);
+ scope->Listener = listener;
+
+ networkData->setListener(ZLExecutionUtil::createListener(scope, this, &LitResAuthenticationManager::onBooksReloaded));
+ return ZLNetworkManager::Instance().performAsync(networkData);
+}
+
+void LitResAuthenticationManager::onBooksReloaded(ZLUserDataHolder &data, const std::string &error) {
+ LitResReloadPurchasedBooksScope &scope = static_cast<LitResReloadPurchasedBooksScope&>(*data.getUserData("scope"));
+ shared_ptr<ZLNetworkRequest::Listener> listener = scope.Listener;
+ if (!error.empty()) {
+ if (error == NetworkErrors::errorMessage(NetworkErrors::ERROR_AUTHENTICATION_FAILED)) {
+ logOut(); //should it logOut in this case?
+ }
+ listener->finished(error);
+ return;
+ }
+ loadPurchasedBooksOnSuccess(scope.purchasedBooksIds, scope.purchasedBooksList);
+ myPurchasedBooksIds = scope.purchasedBooksIds;
+ myPurchasedBooksList = scope.purchasedBooksList;
+ listener->finished(std::string());
+}
+
diff --git a/fbreader/src/network/authentication/litres/LitResAuthenticationManager.h b/fbreader/src/network/authentication/litres/LitResAuthenticationManager.h
new file mode 100644
index 0000000..6aefa6d
--- /dev/null
+++ b/fbreader/src/network/authentication/litres/LitResAuthenticationManager.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __LITRESAUTHENTICATIONMANAGER_H__
+#define __LITRESAUTHENTICATIONMANAGER_H__
+
+#include <set>
+
+#include <ZLNetworkRequest.h>
+#include <ZLUserData.h>
+
+#include "../NetworkAuthenticationManager.h"
+#include "../../NetworkItems.h"
+
+class LitResAuthenticationManager : public NetworkAuthenticationManager {
+
+public:
+ LitResAuthenticationManager(const NetworkLink &link);
+
+public:
+ AuthenticationStatus isAuthorised(shared_ptr<ZLNetworkRequest::Listener> listener = 0);
+ std::string authorise(const std::string &pwd, shared_ptr<ZLNetworkRequest::Listener> listener);
+ void logOut();
+ bool skipIPSupported();
+
+ const std::string &currentUserName();
+ bool needsInitialization();
+ std::string initialize(shared_ptr<ZLNetworkRequest::Listener> listener);
+ bool needPurchase(const NetworkBookItem &book);
+ std::string purchaseBook(const NetworkBookItem &, shared_ptr<ZLNetworkRequest::Listener> listener);
+ shared_ptr<BookReference> downloadReference(const NetworkBookItem &book);
+
+ std::string topupAccountLink();
+ std::string currentAccount();
+
+ std::string reloadPurchasedBooks(shared_ptr<ZLNetworkRequest::Listener> listener);
+ void collectPurchasedBooks(NetworkItem::List &list);
+ const std::set<std::string> &getPurchasedIds() const;
+ const NetworkItem::List &purchasedBooks() const;
+
+private:
+ void onAuthorised(ZLUserDataHolder &data, const std::string &error);
+ void onBookPurchased(ZLUserDataHolder &data, const std::string &error);
+ void onBooksLoaded(ZLUserDataHolder &data, const std::string &error);
+ void onAccountReceived(ZLUserDataHolder &data, const std::string &error);
+ void onBooksReloaded(ZLUserDataHolder &data, const std::string &error);
+
+private:
+ shared_ptr<ZLNetworkRequest> loadPurchasedBooks(std::set<std::string> &purchasedBooksIds, NetworkItem::List &purchasedBooksList);
+ void loadPurchasedBooksOnError(std::set<std::string> &purchasedBooksIds, NetworkItem::List &purchasedBooksList);
+ void loadPurchasedBooksOnSuccess(std::set<std::string> &purchasedBooksIds, NetworkItem::List &purchasedBooksList);
+
+ shared_ptr<ZLNetworkRequest> loadAccount(std::string &dummy1);
+ void loadAccountOnError();
+ void loadAccountOnSuccess();
+
+public: // new User Registration
+ bool registrationSupported();
+ std::string registerUser(const std::string &login, const std::string &password, const std::string &email);
+
+public: // Password Recovery
+ bool passwordRecoverySupported();
+ std::string recoverPassword(const std::string &email);
+
+private:
+ bool mySidChecked;
+
+ ZLStringOption mySidUserNameOption;
+ ZLStringOption mySidOption;
+
+ std::string myInitializedDataSid;
+ std::set<std::string> myPurchasedBooksIds;
+ NetworkItem::List myPurchasedBooksList;
+ std::string myAccount;
+};
+
+#endif /* __LITRESAUTHENTICATIONMANAGER_H__ */
diff --git a/fbreader/src/network/litres/LitResAuthorsItem.cpp b/fbreader/src/network/litres/LitResAuthorsItem.cpp
new file mode 100644
index 0000000..ece7438
--- /dev/null
+++ b/fbreader/src/network/litres/LitResAuthorsItem.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 <ZLNetworkManager.h>
+
+#include "../NetworkLink.h"
+#include "../NetworkComparators.h"
+#include "../NetworkErrors.h"
+#include "../NetworkItems.h"
+
+#include "LitResUtil.h"
+#include "LitResAuthorsParser.h"
+#include "LitResBooksFeedItem.h"
+
+#include "LitResAuthorsItem.h"
+
+LitResAuthorsItem::LitResAuthorsItem(
+ const NetworkLink &link,
+ const std::string &title,
+ const std::string &summary,
+ const UrlInfoCollection &urlByType,
+ AccessibilityType accessibility,
+ int flags
+) : NetworkCatalogItem(
+ link,
+ title,
+ summary,
+ urlByType,
+ accessibility,
+ flags
+) {
+}
+
+class LitResAuthorsItemRunnable : public ZLRunnable {
+public:
+ LitResAuthorsItemRunnable(LitResAuthorsItem *item, NetworkItem::List &children) : myItem(item), myChildren(children) { }
+ void run() {
+ myItem->fillChildrenWithAuthors(myChildren, myItem->myAuthorsList);
+ }
+private:
+ LitResAuthorsItem *myItem;
+ NetworkItem::List &myChildren;
+};
+
+std::string LitResAuthorsItem::loadChildren(NetworkItem::List &children, shared_ptr<ZLNetworkRequest::Listener> listener) {
+ //TODO maybe add sid parameter if possible
+ //(at LitRes API documentation it said that's adding sid _always_ is a good practice)
+
+ myAuthorsList.clear();
+ shared_ptr<ZLNetworkRequest> data = ZLNetworkManager::Instance().createXMLParserRequest(
+ getCatalogUrl(),
+ new LitResAuthorsParser(myAuthorsList),
+ new LitResAuthorsItemRunnable(this, children)
+ );
+ data->setListener(listener);
+ return ZLNetworkManager::Instance().performAsync(data);
+}
+
+void LitResAuthorsItem::fillChildrenWithAuthors(NetworkItem::List &children, const LitResAuthorsParser::AuthorsList &authors) {
+ for (std::size_t i = 0; i < authors.size(); ++i) {
+ const LitResAuthorsParser::LitresAuthorData &author = authors.at(i);
+
+ UrlInfoCollection urlByType = URLByType;
+ urlByType[NetworkItem::URL_CATALOG] = LitResUtil::generateBooksByAuthorUrl(author.Id);
+ //TODO add icon change for one author here
+ //urlByType[NetworkItem::URL_COVER] =
+ children.push_back(new LitResBooksFeedItem(
+ true,
+ Link,
+ author.DisplayName,
+ getSubtitle(author),
+ urlByType,
+ NetworkCatalogItem::ALWAYS,
+ NetworkCatalogItem::FLAG_GROUP_MORE_THAN_1_BOOK_BY_SERIES
+ ));
+ }
+}
+
+std::string LitResAuthorsItem::getSubtitle(const LitResAuthorsParser::LitresAuthorData &author) {
+ static const std::string SPACE = " ";
+ std::string subtitle = author.FirstName;
+ if (!author.MiddleName.empty()) {
+ if (!subtitle.empty()) {
+ subtitle += SPACE;
+ }
+ subtitle += author.MiddleName;
+ }
+ if (!author.LastName.empty()) {
+ if (!subtitle.empty()) {
+ subtitle += SPACE;
+ }
+ subtitle += author.LastName;
+ }
+ return subtitle;
+}
diff --git a/fbreader/src/network/litres/LitResAuthorsItem.h b/fbreader/src/network/litres/LitResAuthorsItem.h
new file mode 100644
index 0000000..31847f4
--- /dev/null
+++ b/fbreader/src/network/litres/LitResAuthorsItem.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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.
+ */
+
+#ifndef __LITRESAUTHORSITEM_H__
+#define __LITRESAUTHORSITEM_H__
+
+#include "../NetworkItems.h"
+
+#include "LitResAuthorsParser.h"
+
+class LitResAuthorsItem : public NetworkCatalogItem {
+
+public:
+ LitResAuthorsItem(
+ const NetworkLink &link,
+ const std::string &title,
+ const std::string &summary,
+ const UrlInfoCollection &urlByType,
+ AccessibilityType accessibility,
+ int flags = FLAGS_DEFAULT
+ );
+
+protected:
+ void fillChildrenWithAuthors(NetworkItem::List &children, const LitResAuthorsParser::AuthorsList &authors);
+ std::string loadChildren(NetworkItem::List &children, shared_ptr<ZLNetworkRequest::Listener> listener);
+
+ static std::string getSubtitle(const LitResAuthorsParser::LitresAuthorData &author);
+
+private:
+ LitResAuthorsParser::AuthorsList myAuthorsList;
+
+friend class LitResAuthorsItemRunnable;
+};
+
+#endif /* __LITRESAUTHORSITEM_H__ */
diff --git a/fbreader/src/network/litres/LitResAuthorsParser.cpp b/fbreader/src/network/litres/LitResAuthorsParser.cpp
new file mode 100644
index 0000000..453ffb5
--- /dev/null
+++ b/fbreader/src/network/litres/LitResAuthorsParser.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 <cstdlib>
+
+#include <ZLUnicodeUtil.h>
+
+#include "../NetworkLink.h"
+#include "LitResGenre.h"
+#include "LitResUtil.h"
+
+#include "LitResAuthorsParser.h"
+
+static const std::string TAG_CATALOG = "catalit-persons";
+static const std::string TAG_SUBJECT = "subject";
+static const std::string TAG_TITLE = "title";
+static const std::string TAG_MAIN = "main";
+static const std::string TAG_FIRST_NAME = "first-name";
+static const std::string TAG_MIDDLE_NAME = "middle-name";
+static const std::string TAG_LAST_NAME = "last-name";
+
+std::string LitResAuthorsParser::stringAttributeValue(const char **attributes, const char *name) {
+ if (attributes == 0) {
+ return std::string();
+ }
+ const char *value = attributeValue(attributes, name);
+ return value != 0 ? value : std::string();
+}
+
+LitResAuthorsParser::LitResAuthorsParser(AuthorsList &authors) : myAuthors(authors) {
+ myState = START;
+}
+
+
+void LitResAuthorsParser::startElementHandler(const char *tag, const char **attributes) {
+ processState(tag, false, attributes);
+ myState = getNextState(tag, false);
+ myBuffer.clear();
+}
+
+void LitResAuthorsParser::endElementHandler(const char *tag) {
+ processState(tag, true, 0);
+ myState = getNextState(tag, true);
+ myBuffer.clear();
+}
+
+void LitResAuthorsParser::characterDataHandler(const char *data, std::size_t len) {
+ myBuffer.append(data, len);
+}
+
+void LitResAuthorsParser::processState(const std::string &tag, bool closed, const char **attributes) {
+ switch(myState) {
+ case START:
+ break;
+ case CATALOG:
+ if (!closed && TAG_SUBJECT == tag) {
+ myAuthorId = stringAttributeValue(attributes, "id");
+ }
+ break;
+ case SUBJECT:
+ if (closed && TAG_SUBJECT == tag) {
+ LitresAuthorData litresAuthor;
+ litresAuthor.Id = myAuthorId;
+ litresAuthor.DisplayName = myAuthorDisplayName;
+ litresAuthor.FirstName = myAuthorFirstName;
+ litresAuthor.MiddleName = myAuthorMiddleName;
+ litresAuthor.LastName = myAuthorLastName;
+ litresAuthor.SortKey = ZLUnicodeUtil::toLower(myAuthorLastName);
+
+ myAuthors.push_back(litresAuthor);
+ myAuthorId.clear();
+ myAuthorDisplayName.clear();
+ myAuthorFirstName.clear();
+ myAuthorMiddleName.clear();
+ myAuthorLastName.clear();
+ }
+ break;
+ case TITLE:
+ break;
+ case MAIN:
+ if (closed && TAG_MAIN == tag) {
+ ZLUnicodeUtil::utf8Trim(myBuffer);
+ myAuthorDisplayName = myBuffer;
+ }
+ break;
+ case FIRST_NAME:
+ if (closed && TAG_FIRST_NAME == tag) {
+ ZLUnicodeUtil::utf8Trim(myBuffer);
+ myAuthorFirstName = myBuffer;
+ }
+ break;
+ case MIDDLE_NAME:
+ if (closed && TAG_MIDDLE_NAME == tag) {
+ ZLUnicodeUtil::utf8Trim(myBuffer);
+ myAuthorMiddleName = myBuffer;
+ }
+ break;
+ case LAST_NAME:
+ if (closed && TAG_LAST_NAME == tag) {
+ ZLUnicodeUtil::utf8Trim(myBuffer);
+ myAuthorLastName = myBuffer;
+ }
+ break;
+ }
+}
+
+LitResAuthorsParser::State LitResAuthorsParser::getNextState(const std::string &tag, bool closed) {
+ switch(myState) {
+ case START:
+ if (!closed && TAG_CATALOG == tag) {
+ return CATALOG;
+ }
+ break;
+ case CATALOG:
+ if (!closed) {
+ if (TAG_SUBJECT == tag) {
+ return SUBJECT;
+ }
+ } else {
+ if (TAG_CATALOG == tag) {
+ return START;
+ }
+ }
+ break;
+ case SUBJECT:
+ if (!closed) {
+ if (TAG_TITLE == tag) {
+ return TITLE;
+ }
+ } else {
+ if (TAG_SUBJECT == tag) {
+ return CATALOG;
+ }
+ }
+ break;
+ case TITLE:
+ if (!closed) {
+ if (TAG_MAIN == tag) {
+ return MAIN;
+ }
+ } else {
+ if (TAG_TITLE == tag) {
+ return FIRST_NAME;
+ }
+ }
+ break;
+ case MAIN:
+ if (closed && TAG_MAIN == tag) {
+ return TITLE;
+ }
+ break;
+ case FIRST_NAME:
+ if (closed && TAG_FIRST_NAME == tag) {
+ return MIDDLE_NAME;
+ }
+ break;
+ case MIDDLE_NAME:
+ if (closed && TAG_MIDDLE_NAME == tag) {
+ return LAST_NAME;
+ }
+ break;
+ case LAST_NAME:
+ if (closed && TAG_LAST_NAME == tag) {
+ return SUBJECT;
+ }
+ break;
+ }
+ return myState;
+}
diff --git a/fbreader/src/network/litres/LitResAuthorsParser.h b/fbreader/src/network/litres/LitResAuthorsParser.h
new file mode 100644
index 0000000..ead137d
--- /dev/null
+++ b/fbreader/src/network/litres/LitResAuthorsParser.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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.
+ */
+
+#ifndef __LITRESAUTHORSPARSER_H__
+#define __LITRESAUTHORSPARSER_H__
+
+#include <vector>
+#include <map>
+
+#include <ZLXMLReader.h>
+
+#include "../NetworkItems.h"
+
+class NetworkLink;
+struct LitResGenre;
+class NetworkAuthenticationManager;
+
+class LitResAuthorsParser : public ZLXMLReader {
+
+public:
+ struct LitresAuthorData {
+ std::string Id;
+ std::string DisplayName;
+ std::string FirstName;
+ std::string MiddleName;
+ std::string LastName;
+ std::string SortKey;
+
+ bool operator< (const LitresAuthorData &authorData) const;
+ };
+ typedef std::vector<LitresAuthorData> AuthorsList;
+
+public:
+ LitResAuthorsParser(AuthorsList &authors);
+
+private:
+ void startElementHandler(const char *tag, const char **attributes);
+ void endElementHandler(const char *tag);
+ void characterDataHandler(const char *text, std::size_t len);
+
+private:
+ enum State {
+ START, CATALOG, SUBJECT, TITLE, MAIN, FIRST_NAME, MIDDLE_NAME, LAST_NAME
+ };
+
+ std::string stringAttributeValue(const char **attributes, const char *name);
+ void processState(const std::string &tag, bool closed, const char **attributes);
+ State getNextState(const std::string &tag, bool closed);
+
+private:
+ AuthorsList &myAuthors;
+
+ std::string myBuffer;
+ State myState;
+
+ std::string myAuthorId;
+ std::string myAuthorDisplayName;
+ std::string myAuthorFirstName;
+ std::string myAuthorMiddleName;
+ std::string myAuthorLastName;
+};
+
+inline bool LitResAuthorsParser::LitresAuthorData::operator< (const LitresAuthorData &authorData) const {
+ return SortKey.compare(authorData.SortKey) < 0;
+}
+
+#endif /* __LITRESAUTHORSPARSER_H__ */
diff --git a/fbreader/src/network/litres/LitResBookItem.cpp b/fbreader/src/network/litres/LitResBookItem.cpp
new file mode 100644
index 0000000..cdc9306
--- /dev/null
+++ b/fbreader/src/network/litres/LitResBookItem.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 <ZLResource.h>
+#include <ZLStringUtil.h>
+
+#include "LitResBooksFeedItem.h"
+#include "LitResUtil.h"
+
+#include "LitResBookItem.h"
+
+LitResBookItem::LitResBookItem(
+ const NetworkLink &link,
+ const std::string &id,
+ unsigned int index,
+ const std::string &title,
+ const std::string &summary,
+ const std::string &language,
+ const std::string &date,
+ const std::vector<AuthorData> &authors,
+ const std::vector<std::string> &tags,
+ const std::string &seriesTitle,
+ unsigned int indexInSeries,
+ const UrlInfoCollection &urlByType,
+ const std::vector<shared_ptr<BookReference> > references,
+ const std::vector<std::string> authorIds
+) :
+ NetworkBookItem(link, id, index, title, summary, language, date, authors,
+ tags, seriesTitle, indexInSeries, urlByType, references),
+ myAuthorIds(authorIds)
+{
+
+}
+
+std::vector<shared_ptr<NetworkItem> > LitResBookItem::getRelatedCatalogsItems() const {
+ std::vector<shared_ptr<NetworkItem> > items;
+
+ UrlInfoCollection urlByType = URLByType;
+
+ urlByType[URL_CATALOG] = LitResUtil::generateAlsoReadUrl(Id);
+ items.push_back(new LitResBooksFeedItem(false, Link, resource("alsoRead").value(), std::string(), urlByType));
+
+ for (std::size_t i = 0; i < myAuthorIds.size(); ++i) {
+ urlByType[URL_CATALOG] = LitResUtil::generateBooksByAuthorUrl(myAuthorIds.at(i));
+ std::string title = ZLStringUtil::printf(resource("sameAuthor").value(), Authors.at(i).DisplayName);
+ items.push_back(new LitResBooksFeedItem(false, Link, title, std::string(), urlByType));
+ }
+
+ return items;
+}
+
+const ZLResource &LitResBookItem::resource(const std::string &resourceKey) const {
+ return ZLResource::resource("networkView")["bookNode"][resourceKey];
+}
diff --git a/fbreader/src/network/litres/LitResBookItem.h b/fbreader/src/network/litres/LitResBookItem.h
new file mode 100644
index 0000000..129b6a6
--- /dev/null
+++ b/fbreader/src/network/litres/LitResBookItem.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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.
+ */
+
+#ifndef __LITRESBOOKITEM_H__
+#define __LITRESBOOKITEM_H__
+
+#include "../NetworkItems.h"
+
+class LitResBookItem : public NetworkBookItem {
+public:
+ LitResBookItem(
+ const NetworkLink &link,
+ const std::string &id,
+ unsigned int index,
+ const std::string &title,
+ const std::string &summary,
+ const std::string &language,
+ const std::string &date,
+ const std::vector<AuthorData> &authors,
+ const std::vector<std::string> &tags,
+ const std::string &seriesTitle,
+ unsigned int indexInSeries,
+ const UrlInfoCollection &urlByType,
+ const std::vector<shared_ptr<BookReference> > references,
+ const std::vector<std::string> authorIds
+ );
+
+ std::vector<shared_ptr<NetworkItem> > getRelatedCatalogsItems() const;
+
+protected:
+ const ZLResource &resource(const std::string &resourceKey) const;
+
+private:
+ std::vector<std::string> myAuthorIds;
+};
+
+#endif /* __LITRESBOOKITEM_H__ */
diff --git a/fbreader/src/network/litres/LitResBooksFeedItem.cpp b/fbreader/src/network/litres/LitResBooksFeedItem.cpp
new file mode 100644
index 0000000..b597255
--- /dev/null
+++ b/fbreader/src/network/litres/LitResBooksFeedItem.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 <algorithm>
+
+#include <ZLNetworkManager.h>
+#include <ZLNetworkUtil.h>
+#include <ZLStringUtil.h>
+
+#include "../NetworkLink.h"
+#include "../NetworkComparators.h"
+#include "../NetworkErrors.h"
+#include "../NetworkItems.h"
+
+#include "LitResUtil.h"
+#include "LitResBooksFeedParser.h"
+
+#include "LitResBooksFeedItem.h"
+
+LitResBooksFeedItem::LitResBooksFeedItem(
+ bool shouldSort,
+ const NetworkLink &link,
+ const std::string &title,
+ const std::string &summary,
+ const UrlInfoCollection &urlByType,
+ AccessibilityType accessibility,
+ int flags
+) : NetworkCatalogItem(
+ link,
+ title,
+ summary,
+ urlByType,
+ accessibility,
+ flags
+), myShouldSort(shouldSort) {
+
+}
+
+void LitResBooksFeedItem::onDisplayItem() {
+}
+
+class LitResBooksFeedItemRunnable : public ZLNetworkRequest::Listener {
+public:
+ LitResBooksFeedItemRunnable(LitResBooksFeedItem &item, shared_ptr<ZLNetworkRequest> request, NetworkItem::List &children, shared_ptr<ZLNetworkRequest::Listener> listener) :
+ myItem(item), myChildren(children), myListener(listener) {
+ request->setListener(this);
+ ZLNetworkManager::Instance().performAsync(request);
+ }
+
+ void finished(const std::string &error) {
+ if (error.empty()) {
+ ++myItem.myLoadingState.CurrentPage;
+ if (myItem.myShouldSort) {
+ std::sort(myChildren.begin(), myChildren.end(), NetworkBookItemComparator());
+ }
+ }
+ myListener->finished(error);
+ }
+private:
+ LitResBooksFeedItem &myItem;
+ NetworkItem::List &myChildren;
+ shared_ptr<ZLNetworkRequest::Listener> myListener;
+};
+
+
+std::string LitResBooksFeedItem::loadChildren(NetworkItem::List &children, shared_ptr<ZLNetworkRequest::Listener> listener) {
+// //TODO maybe add sid parameter if possible
+// //(at LitRes API documentation it said that's adding sid _always_ is a good practice)
+
+ myLoadingState.CurrentPage = 0;
+ myLoadingState.AllPagesCount = 1;
+
+ shared_ptr<ZLNetworkRequest> request = getRequest(children);
+ new LitResBooksFeedItemRunnable(*this, request, children, listener);
+ return std::string();
+}
+
+bool LitResBooksFeedItem::supportsResumeLoading() {
+ return true;
+}
+
+std::string LitResBooksFeedItem::resumeLoading(NetworkItem::List &children, shared_ptr<ZLNetworkRequest::Listener> listener) {
+ shared_ptr<ZLNetworkRequest> request = getRequest(children);
+ if (request.isNull()) {
+ listener->finished();
+ return std::string();
+ }
+ new LitResBooksFeedItemRunnable(*this, request, children, listener);
+ return std::string();
+}
+
+shared_ptr<ZLNetworkRequest> LitResBooksFeedItem::getRequest(NetworkItem::List &children) {
+ if (myLoadingState.CurrentPage >= myLoadingState.AllPagesCount) {
+ return 0;
+ }
+ return ZLNetworkManager::Instance().createXMLParserRequest(
+ withLimitParameters(getCatalogUrl(), myLoadingState),
+ new LitResBooksFeedParser(Link, children, &myLoadingState)
+ );
+}
+
+std::string LitResBooksFeedItem::withLimitParameters(std::string query, const LoadingState &state) {
+ static const unsigned int ITEMS_PER_PAGE = 40;
+ unsigned int startItemNumber = (unsigned int)state.CurrentPage * ITEMS_PER_PAGE;
+ std::string params;
+ ZLStringUtil::appendNumber(params, startItemNumber);
+ params += ",";
+ ZLStringUtil::appendNumber(params, ITEMS_PER_PAGE);
+ ZLNetworkUtil::appendParameter(query, "limit", params);
+ return query;
+}
+
diff --git a/fbreader/src/network/litres/LitResBooksFeedItem.h b/fbreader/src/network/litres/LitResBooksFeedItem.h
new file mode 100644
index 0000000..8af7df2
--- /dev/null
+++ b/fbreader/src/network/litres/LitResBooksFeedItem.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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.
+ */
+
+#ifndef __LITRESBOOKFEEDITEM_H__
+#define __LITRESBOOKFEEDITEM_H__
+
+#include "../NetworkItems.h"
+
+class LitResBooksFeedItem : public NetworkCatalogItem {
+
+public:
+ struct LoadingState {
+ int CurrentPage;
+ int AllPagesCount;
+ } myLoadingState;
+
+public:
+ LitResBooksFeedItem(
+ bool shouldSort,
+ const NetworkLink &link,
+ const std::string &title,
+ const std::string &summary,
+ const UrlInfoCollection &urlByType,
+ AccessibilityType accessibility = ALWAYS,
+ int flags = FLAGS_DEFAULT
+ );
+
+private:
+ void onDisplayItem();
+ std::string loadChildren(NetworkItem::List &children, shared_ptr<ZLNetworkRequest::Listener> listener);
+ bool supportsResumeLoading();
+ std::string resumeLoading(NetworkItem::List &children, shared_ptr<ZLNetworkRequest::Listener> listener);
+
+private:
+ shared_ptr<ZLNetworkRequest> getRequest(NetworkItem::List &children);
+ static std::string withLimitParameters(std::string url, const LoadingState &state);
+
+private:
+ bool myShouldSort;
+
+friend class LitResBooksFeedItemRunnable;
+};
+
+#endif /* __LITRESBOOKFEEDITEM_H__ */
diff --git a/fbreader/src/network/litres/LitResBooksFeedParser.cpp b/fbreader/src/network/litres/LitResBooksFeedParser.cpp
new file mode 100644
index 0000000..970a8eb
--- /dev/null
+++ b/fbreader/src/network/litres/LitResBooksFeedParser.cpp
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 <cstdlib>
+
+#include <ZLStringUtil.h>
+#include <ZLUnicodeUtil.h>
+
+#include "LitResBooksFeedParser.h"
+#include "LitResBookItem.h"
+#include "LitResGenre.h"
+#include "LitResUtil.h"
+#include "../NetworkLink.h"
+
+static const std::string TAG_CATALOG = "catalit-fb2-books";
+static const std::string TAG_BOOK = "fb2-book";
+static const std::string TAG_TEXT_DESCRIPTION = "text_description";
+static const std::string TAG_HIDDEN = "hidden";
+static const std::string TAG_TITLE_INFO = "title-info";
+static const std::string TAG_GENRE = "genre";
+static const std::string TAG_AUTHOR = "author";
+static const std::string TAG_FIRST_NAME = "first-name";
+static const std::string TAG_MIDDLE_NAME = "middle-name";
+static const std::string TAG_LAST_NAME = "last-name";
+static const std::string TAG_AUTHOR_ID = "id";
+static const std::string TAG_BOOK_TITLE = "book-title";
+static const std::string TAG_ANNOTATION = "annotation";
+static const std::string TAG_DATE = "date";
+static const std::string TAG_SEQUENCE = "sequence";
+static const std::string TAG_LANGUAGE = "lang";
+
+std::string LitResBooksFeedParser::stringAttributeValue(const char **attributes, const char *name) {
+ if (attributes == 0) {
+ return std::string();
+ }
+ const char *value = attributeValue(attributes, name);
+ return value != 0 ? value : std::string();
+}
+
+LitResBooksFeedParser::LitResBooksFeedParser(const NetworkLink &link, NetworkItem::List &books, LitResBooksFeedItem::LoadingState *loadingState) :
+ myLink(link),
+ myBooks(books),
+ myIndex(0),
+ myLoadingState(loadingState) {
+ myState = START;
+}
+
+
+void LitResBooksFeedParser::startElementHandler(const char *tag, const char **attributes) {
+ processState(tag, false, attributes);
+ myState = getNextState(tag, false);
+ myBuffer.clear();
+}
+
+void LitResBooksFeedParser::endElementHandler(const char *tag) {
+ processState(tag, true, 0);
+ myState = getNextState(tag, true);
+ myBuffer.clear();
+}
+
+void LitResBooksFeedParser::characterDataHandler(const char *data, std::size_t len) {
+ myBuffer.append(data, len);
+}
+
+void LitResBooksFeedParser::processState(const std::string &tag, bool closed, const char **attributes) {
+ switch(myState) {
+ case START:
+ if (!closed && TAG_CATALOG == tag) {
+ if (myLoadingState) {
+ myLoadingState->AllPagesCount = ZLStringUtil::stringToInteger(stringAttributeValue(attributes, "pages"), 1);
+ }
+ }
+ break;
+ case CATALOG:
+ if (!closed && TAG_BOOK == tag) {
+ myBookId = stringAttributeValue(attributes, "hub_id");
+ myURLByType[NetworkItem::URL_COVER] =
+ stringAttributeValue(attributes, "cover_preview");
+ myURLByType[NetworkItem::URL_FULL_COVER] =
+ stringAttributeValue(attributes, "cover");
+
+ std::string url = stringAttributeValue(attributes, "url");
+ if (!url.empty()) {
+ myLink.rewriteUrl(url, true); // This code duplicates code in FBReader::openInBrowser and is not required
+ myURLByType[NetworkItem::URL_HTML_PAGE] = url;
+ }
+
+ //TODO check if buying book works right
+ std::string price = BuyBookReference::price(stringAttributeValue(attributes, "price"), "RUB");
+ myReferences.push_back(new BuyBookReference(
+ LitResUtil::generatePurchaseUrl(myLink, myBookId),
+ BookReference::FB2_ZIP,
+ BookReference::BUY,
+ price
+ ));
+
+ std::string hasTrial = stringAttributeValue(attributes, "has_trial");
+ if (!hasTrial.empty() && hasTrial != "0") {
+ myReferences.push_back(new BookReference(
+ LitResUtil::generateTrialUrl(myBookId),
+ BookReference::FB2_ZIP,
+ BookReference::DOWNLOAD_DEMO
+ ));
+ }
+
+ myReferences.push_back(new BookReference(
+ LitResUtil::generateDownloadUrl(myBookId),
+ BookReference::FB2_ZIP,
+ BookReference::DOWNLOAD_FULL_CONDITIONAL
+ ));
+ }
+ break;
+ case BOOK:
+ if (closed && TAG_BOOK == tag) {
+ myBooks.push_back(new LitResBookItem(
+ myLink,
+ myBookId,
+ myIndex++,
+ myTitle,
+ mySummary,
+ myLanguage,
+ myDate,
+ myAuthors,
+ myTags,
+ mySeriesTitle,
+ myIndexInSeries,
+ myURLByType,
+ myReferences,
+ myAuthorsIds
+ ));
+
+ myTitle.erase();
+ mySummary.erase();
+ myLanguage.erase();
+ myDate.erase();
+ mySeriesTitle.erase();
+ myIndexInSeries = 0;
+ myAuthors.clear();
+ myAuthorsIds.clear();
+ myTags.clear();
+ myURLByType.clear();
+ myReferences.clear();
+ }
+ break;
+ case BOOK_DESCRIPTION:
+ break;
+ case HIDDEN:
+ break;
+ case TITLE_INFO:
+ if (!closed) {
+ if (TAG_AUTHOR == tag) {
+ myAuthorFirstName.clear();
+ myAuthorMiddleName.clear();
+ myAuthorLastName.clear();
+ } else if (TAG_SEQUENCE == tag) {
+ mySeriesTitle = stringAttributeValue(attributes, "name");
+ if (!mySeriesTitle.empty()) {
+ const char *indexInSeries = attributeValue(attributes, "number");
+ myIndexInSeries = indexInSeries != 0 ? std::atoi(indexInSeries) : 0;
+ }
+ }
+ }
+ break;
+ case AUTHOR:
+ if (closed && TAG_AUTHOR == tag) {
+ NetworkBookItem::AuthorData data;
+ if (!myAuthorFirstName.empty()) {
+ data.DisplayName.append(myAuthorFirstName);
+ }
+ if (!myAuthorMiddleName.empty()) {
+ if (!data.DisplayName.empty()) {
+ data.DisplayName.append(" ");
+ }
+ data.DisplayName.append(myAuthorMiddleName);
+ }
+ if (!myAuthorLastName.empty()) {
+ if (!data.DisplayName.empty()) {
+ data.DisplayName.append(" ");
+ }
+ data.DisplayName.append(myAuthorLastName);
+ }
+ data.SortKey = myAuthorLastName;
+ myAuthors.push_back(data);
+ myAuthorsIds.push_back(myAuthorId);
+ }
+ break;
+ case FIRST_NAME:
+ if (closed && TAG_FIRST_NAME == tag) {
+ ZLUnicodeUtil::utf8Trim(myBuffer);
+ myAuthorFirstName = myBuffer;
+ }
+ break;
+ case MIDDLE_NAME:
+ if (closed && TAG_MIDDLE_NAME == tag) {
+ ZLUnicodeUtil::utf8Trim(myBuffer);
+ myAuthorMiddleName = myBuffer;
+ }
+ break;
+ case LAST_NAME:
+ if (closed && TAG_LAST_NAME == tag) {
+ ZLUnicodeUtil::utf8Trim(myBuffer);
+ myAuthorLastName = myBuffer;
+ }
+ break;
+ case AUTHOR_ID:
+ if (closed && TAG_AUTHOR_ID == tag) {
+ ZLUnicodeUtil::utf8Trim(myBuffer);
+ myAuthorId = myBuffer;
+ }
+ break;
+ case GENRE:
+ if (closed && TAG_GENRE == tag) {
+ ZLUnicodeUtil::utf8Trim(myBuffer);
+
+ const std::map<std::string,shared_ptr<LitResGenre> > &genresMap =
+ LitResGenreMap::Instance().genresMap();
+ const std::map<shared_ptr<LitResGenre>,std::string> &genresTitles =
+ LitResGenreMap::Instance().genresTitles();
+
+ std::map<std::string, shared_ptr<LitResGenre> >::const_iterator it = genresMap.find(myBuffer);
+ if (it != genresMap.end()) {
+ std::map<shared_ptr<LitResGenre>, std::string>::const_iterator jt = genresTitles.find(it->second);
+ if (jt != genresTitles.end()) {
+ myTags.push_back(jt->second);
+ }
+ }
+ }
+ break;
+ case BOOK_TITLE:
+ if (closed && TAG_BOOK_TITLE == tag) {
+ ZLUnicodeUtil::utf8Trim(myBuffer);
+ myTitle = myBuffer;
+ }
+ break;
+ case ANNOTATION:
+ if (!closed) {
+ ZLUnicodeUtil::utf8Trim(myBuffer);
+ if (!myBuffer.empty()) {
+ mySummary.append(myBuffer);
+ mySummary.append(" ");
+ }
+ } else {
+ ZLUnicodeUtil::utf8Trim(myBuffer);
+ mySummary.append(myBuffer);
+ int size = mySummary.size();
+ if (size > 0) {
+ if (TAG_ANNOTATION == tag) {
+ if (mySummary[size - 1] == '\n') {
+ mySummary.erase(size - 1);
+ }
+ } else if ("p" == tag) {
+ if (mySummary[size - 1] != '\n') {
+ mySummary.append("\n");
+ }
+ } else {
+ if (!myBuffer.empty() && mySummary[size - 1] != '\n') {
+ mySummary.append(" ");
+ }
+ }
+ }
+ }
+ break;
+ case DATE:
+ if (closed && TAG_DATE == tag) {
+ ZLUnicodeUtil::utf8Trim(myBuffer);
+ myDate = myBuffer;
+ }
+ break;
+ case LANGUAGE:
+ if (closed && TAG_LANGUAGE == tag) {
+ ZLUnicodeUtil::utf8Trim(myBuffer);
+ myLanguage = myBuffer;
+ }
+ break;
+ }
+}
+
+LitResBooksFeedParser::State LitResBooksFeedParser::getNextState(const std::string &tag, bool closed) {
+ switch(myState) {
+ case START:
+ if (!closed && TAG_CATALOG == tag) {
+ return CATALOG;
+ }
+ break;
+ case CATALOG:
+ if (!closed) {
+ if (TAG_BOOK == tag) {
+ return BOOK;
+ }
+ } else {
+ if (TAG_CATALOG == tag) {
+ return START;
+ }
+ }
+ break;
+ case BOOK:
+ if (!closed) {
+ if (TAG_TEXT_DESCRIPTION == tag) {
+ return BOOK_DESCRIPTION;
+ }
+ } else {
+ if (TAG_BOOK == tag) {
+ return CATALOG;
+ }
+ }
+ break;
+ case BOOK_DESCRIPTION:
+ if (!closed) {
+ if (TAG_HIDDEN == tag) {
+ return HIDDEN;
+ }
+ } else {
+ if (TAG_TEXT_DESCRIPTION == tag) {
+ return BOOK;
+ }
+ }
+ break;
+ case HIDDEN:
+ if (!closed) {
+ if (TAG_TITLE_INFO == tag) {
+ return TITLE_INFO;
+ }
+ } else {
+ if (TAG_HIDDEN == tag) {
+ return BOOK_DESCRIPTION;
+ }
+ }
+ break;
+ case TITLE_INFO:
+ if (!closed) {
+ if (TAG_GENRE == tag) {
+ return GENRE;
+ } else if (TAG_AUTHOR == tag) {
+ return AUTHOR;
+ } else if (TAG_BOOK_TITLE == tag) {
+ return BOOK_TITLE;
+ } else if (TAG_ANNOTATION == tag) {
+ return ANNOTATION;
+ } else if (TAG_DATE == tag) {
+ return DATE;
+ } else if (TAG_LANGUAGE == tag) {
+ return LANGUAGE;
+ } /*else if (TAG_SEQUENCE == tag) {
+ return SEQUENCE; // handled without state through attributes
+ }*/
+ } else {
+ if (TAG_TITLE_INFO == tag) {
+ return HIDDEN;
+ }
+ }
+ break;
+ case AUTHOR:
+ if (!closed) {
+ if (TAG_FIRST_NAME == tag) {
+ return FIRST_NAME;
+ } else if (TAG_MIDDLE_NAME == tag) {
+ return MIDDLE_NAME;
+ } else if (TAG_LAST_NAME == tag) {
+ return LAST_NAME;
+ } else if (TAG_AUTHOR_ID == tag) {
+ return AUTHOR_ID;
+ }
+ } else {
+ if (TAG_AUTHOR == tag) {
+ return TITLE_INFO;
+ }
+ }
+ break;
+ case FIRST_NAME:
+ if (closed && TAG_FIRST_NAME == tag) {
+ return AUTHOR;
+ }
+ break;
+ case MIDDLE_NAME:
+ if (closed && TAG_MIDDLE_NAME == tag) {
+ return AUTHOR;
+ }
+ break;
+ case LAST_NAME:
+ if (closed && TAG_LAST_NAME == tag) {
+ return AUTHOR;
+ }
+ break;
+ case AUTHOR_ID:
+ if (closed && TAG_AUTHOR_ID == tag) {
+ return AUTHOR;
+ }
+ break;
+ case GENRE:
+ if (closed && TAG_GENRE == tag) {
+ return TITLE_INFO;
+ }
+ break;
+ case BOOK_TITLE:
+ if (closed && TAG_BOOK_TITLE == tag) {
+ return TITLE_INFO;
+ }
+ break;
+ case ANNOTATION:
+ if (closed && TAG_ANNOTATION == tag) {
+ return TITLE_INFO;
+ }
+ break;
+ case DATE:
+ if (closed && TAG_DATE == tag) {
+ return TITLE_INFO;
+ }
+ break;
+ case LANGUAGE:
+ if (closed && TAG_LANGUAGE == tag) {
+ return TITLE_INFO;
+ }
+ break;
+ }
+ return myState;
+}
+
diff --git a/fbreader/src/network/litres/LitResBooksFeedParser.h b/fbreader/src/network/litres/LitResBooksFeedParser.h
new file mode 100644
index 0000000..6f9a6dc
--- /dev/null
+++ b/fbreader/src/network/litres/LitResBooksFeedParser.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __LITRESBOOKSFEEDPARSER_H__
+#define __LITRESBOOKSFEEDPARSER_H__
+
+#include <vector>
+#include <map>
+
+#include <ZLXMLReader.h>
+
+#include "../NetworkItems.h"
+
+#include "LitResBooksFeedItem.h"
+
+class NetworkLink;
+struct LitResGenre;
+class NetworkAuthenticationManager;
+
+class LitResBooksFeedParser : public ZLXMLReader {
+
+public:
+ LitResBooksFeedParser(const NetworkLink &link, NetworkItem::List &books, LitResBooksFeedItem::LoadingState *state = 0);
+
+private:
+ void startElementHandler(const char *tag, const char **attributes);
+ void endElementHandler(const char *tag);
+ void characterDataHandler(const char *text, std::size_t len);
+
+private:
+ enum State {
+ START, CATALOG, BOOK, BOOK_DESCRIPTION, HIDDEN, TITLE_INFO,
+ GENRE, AUTHOR, FIRST_NAME, MIDDLE_NAME, LAST_NAME, AUTHOR_ID, BOOK_TITLE,
+ ANNOTATION, DATE, LANGUAGE,
+ };
+
+ std::string stringAttributeValue(const char **attributes, const char *name);
+ void processState(const std::string &tag, bool closed, const char **attributes);
+ State getNextState(const std::string &tag, bool closed);
+
+private:
+ const NetworkLink &myLink;
+
+ NetworkItem::List &myBooks;
+ std::string myBuffer;
+
+ unsigned int myIndex;
+
+ State myState;
+
+ std::string myBookId;
+ std::string myTitle;
+ std::string mySummary;
+ std::string myLanguage;
+ std::string myDate;
+ std::string mySeriesTitle;
+ int myIndexInSeries;
+
+ std::string myAuthorFirstName;
+ std::string myAuthorMiddleName;
+ std::string myAuthorLastName;
+ std::string myAuthorId;
+ std::vector<NetworkBookItem::AuthorData> myAuthors;
+ std::vector<std::string> myAuthorsIds;
+
+ std::vector<std::string> myTags;
+ NetworkItem::UrlInfoCollection myURLByType;
+ std::vector<shared_ptr<BookReference> > myReferences;
+
+ LitResBooksFeedItem::LoadingState *myLoadingState;
+};
+
+#endif /* __LITRESBOOKSFEEDPARSER_H__ */
diff --git a/fbreader/src/network/litres/LitResBookshelfItem.cpp b/fbreader/src/network/litres/LitResBookshelfItem.cpp
new file mode 100644
index 0000000..be931fe
--- /dev/null
+++ b/fbreader/src/network/litres/LitResBookshelfItem.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 <algorithm>
+
+#include <ZLNetworkRequest.h>
+#include <ZLExecutionUtil.h>
+
+#include "LitResBookshelfItem.h"
+#include "../authentication/litres/LitResAuthenticationManager.h"
+
+#include "../NetworkLink.h"
+#include "../NetworkComparators.h"
+#include "../NetworkErrors.h"
+
+#include "SortedCatalogItem.h"
+
+LitResBookshelfItem::LitResBookshelfItem(
+ const NetworkLink &link,
+ const std::string &title,
+ const std::string &summary,
+ const UrlInfoCollection &urlByType,
+ AccessibilityType accessibility
+) : NetworkCatalogItem(
+ link,
+ title,
+ summary,
+ urlByType,
+ accessibility
+) {
+ myForceReload = false;
+}
+
+void LitResBookshelfItem::onDisplayItem() {
+ myForceReload = false;
+}
+
+class LitResBookshelfItemLoaderScope : public ZLUserData {
+public:
+ LitResBookshelfItemLoaderScope(NetworkItem::List &children) : Children(children) {}
+ NetworkItem::List &Children;
+ shared_ptr<ZLNetworkRequest::Listener> listener;
+};
+
+
+std::string LitResBookshelfItem::loadChildren(NetworkItem::List &children, shared_ptr<ZLNetworkRequest::Listener> listener) {
+ LitResAuthenticationManager &mgr = (LitResAuthenticationManager&)*Link.authenticationManager();
+ if (mgr.isAuthorised().Status == B3_FALSE) {
+ listener->finished(NetworkErrors::errorMessage(NetworkErrors::ERROR_AUTHENTICATION_FAILED));
+ return NetworkErrors::errorMessage(NetworkErrors::ERROR_AUTHENTICATION_FAILED);
+ }
+
+ LitResBookshelfItemLoaderScope *scope = new LitResBookshelfItemLoaderScope(children);
+ scope->listener = listener;
+
+ shared_ptr<ZLUserDataHolder> scopeData = new ZLUserDataHolder;
+ scopeData->addUserData("scope", scope);
+ if (myForceReload) {
+ mgr.reloadPurchasedBooks(ZLExecutionUtil::createListener(scopeData, this, &LitResBookshelfItem::onReloaded));
+ return std::string();
+ }
+ onReloaded(*scopeData, std::string());
+ return std::string();
+}
+
+void LitResBookshelfItem::onReloaded(ZLUserDataHolder &data, const std::string &error) {
+ LitResBookshelfItemLoaderScope &scope = static_cast<LitResBookshelfItemLoaderScope&>(*data.getUserData("scope"));
+ LitResAuthenticationManager &mgr = static_cast<LitResAuthenticationManager&>(*Link.authenticationManager());
+ myForceReload = true;
+ NetworkItem::List tmpChildren;
+ mgr.collectPurchasedBooks(tmpChildren);
+ std::sort(tmpChildren.begin(), tmpChildren.end(), NetworkBookItemComparator());
+
+
+ NetworkItem::List &children = scope.Children;
+
+ if (tmpChildren.size() <= 5) {
+ children.assign(tmpChildren.begin(), tmpChildren.end());
+ std::sort(children.begin(), children.end(), NetworkBookItemComparator());
+ } else {
+ children.push_back(SortedCatalogItem::create(*this, "byDate", tmpChildren, FLAG_SHOW_AUTHOR));
+ children.push_back(SortedCatalogItem::create(*this, "byAuthor", tmpChildren, FLAG_GROUP_BY_AUTHOR, NetworkBookItemComparator()));
+ children.push_back(SortedCatalogItem::create(*this, "byTitle", tmpChildren, FLAG_SHOW_AUTHOR, NetworkBookItemByTitleComparator()));
+ SortedCatalogItem* bySeries = SortedCatalogItem::create(*this, "bySeries", tmpChildren, FLAG_SHOW_AUTHOR | FLAG_GROUP_BY_SERIES,
+ NetworkBookItemBySeriesComparator(), SortedCatalogItem::BySeriesFilter());
+
+ if (!bySeries->isEmpty()) {
+ children.push_back(bySeries);
+ } else {
+ delete bySeries;
+ }
+ }
+
+ scope.listener->finished(error);
+}
diff --git a/fbreader/src/network/litres/LitResBookshelfItem.h b/fbreader/src/network/litres/LitResBookshelfItem.h
new file mode 100644
index 0000000..22ea8d9
--- /dev/null
+++ b/fbreader/src/network/litres/LitResBookshelfItem.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __LITRESBOOKSHELFITEM_H__
+#define __LITRESBOOKSHELFITEM_H__
+
+#include <ZLResource.h>
+#include <ZLExecutionUtil.h>
+
+#include "../NetworkComparators.h"
+#include "../NetworkItems.h"
+
+class NetworkLink;
+
+class LitResBookshelfItem : public NetworkCatalogItem {
+
+public:
+ LitResBookshelfItem(
+ const NetworkLink &link,
+ const std::string &title,
+ const std::string &summary,
+ const UrlInfoCollection &urlByType,
+ AccessibilityType accessibility = ALWAYS
+ );
+
+private:
+ void onDisplayItem();
+ std::string loadChildren(NetworkItem::List &children, shared_ptr<ZLNetworkRequest::Listener> listener);
+ void onReloaded(ZLUserDataHolder &data, const std::string &error);
+
+private:
+ bool myForceReload;
+};
+
+#endif /* __LITRESBOOKSHELFITEM_H__ */
diff --git a/fbreader/src/network/litres/LitResByGenresItem.cpp b/fbreader/src/network/litres/LitResByGenresItem.cpp
new file mode 100644
index 0000000..a9b6367
--- /dev/null
+++ b/fbreader/src/network/litres/LitResByGenresItem.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 <algorithm>
+
+#include <ZLNetworkManager.h>
+
+#include "../NetworkLink.h"
+#include "../NetworkComparators.h"
+#include "../NetworkErrors.h"
+#include "../NetworkItems.h"
+
+#include "LitResUtil.h"
+#include "LitResBooksFeedParser.h"
+#include "LitResBooksFeedItem.h"
+
+#include "LitResByGenresItem.h"
+
+static const std::string EMPTY_STRING = std::string();
+
+LitResByGenresItem::LitResByGenresItem(
+ const std::vector<shared_ptr<LitResGenre> > &genreTree,
+ const NetworkLink &link,
+ const std::string &title,
+ const std::string &summary,
+ const UrlInfoCollection &urlByType,
+ AccessibilityType accessibility,
+ int flags
+) : NetworkCatalogItem(
+ link,
+ title,
+ summary,
+ urlByType,
+ accessibility,
+ flags
+), myGenreTree(genreTree) {
+}
+
+std::string LitResByGenresItem::loadChildren(NetworkItem::List &children, shared_ptr<ZLNetworkRequest::Listener> listener) {
+ for (std::size_t i = 0; i < myGenreTree.size(); ++i) {
+ shared_ptr<LitResGenre> genre = myGenreTree.at(i);
+ if (genre->Children.empty()) {
+ UrlInfoCollection urlByType = URLByType;
+ urlByType[NetworkItem::URL_CATALOG] = LitResUtil::generateBooksByGenreUrl(genre->Id);
+ //TODO add icon change for one genre here
+ //urlByType[NetworkItem::URL_COVER] =
+ children.push_back(new LitResBooksFeedItem(true, Link, genre->Title, EMPTY_STRING, urlByType, ALWAYS));
+ } else {
+ children.push_back(new LitResByGenresItem(genre->Children, Link, genre->Title, EMPTY_STRING, URLByType, ALWAYS, FLAG_NONE));
+ }
+ }
+ listener->finished();
+ return std::string();
+}
+
diff --git a/fbreader/src/network/litres/LitResByGenresItem.h b/fbreader/src/network/litres/LitResByGenresItem.h
new file mode 100644
index 0000000..3af0e23
--- /dev/null
+++ b/fbreader/src/network/litres/LitResByGenresItem.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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.
+ */
+
+#ifndef __LITRESBYGENRESITEM_H__
+#define __LITRESBYGENRESITEM_H__
+
+#include "../NetworkItems.h"
+
+#include "LitResGenre.h"
+
+class LitResByGenresItem : public NetworkCatalogItem {
+
+public:
+ LitResByGenresItem(
+ const std::vector<shared_ptr<LitResGenre> > &genreTree,
+ const NetworkLink &link,
+ const std::string &title,
+ const std::string &summary,
+ const UrlInfoCollection &urlByType,
+ AccessibilityType accessibility,
+ int flags
+ );
+
+private:
+ std::string loadChildren(NetworkItem::List &children, shared_ptr<ZLNetworkRequest::Listener> listener);
+
+private:
+ const std::vector<shared_ptr<LitResGenre> > &myGenreTree;
+};
+
+#endif /* __LITRESBYGENRESITEM_H__ */
diff --git a/fbreader/src/network/litres/LitResGenre.cpp b/fbreader/src/network/litres/LitResGenre.cpp
new file mode 100644
index 0000000..a541948
--- /dev/null
+++ b/fbreader/src/network/litres/LitResGenre.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 <cstdlib>
+
+#include <ZLStringUtil.h>
+#include <ZLUnicodeUtil.h>
+#include <ZLNetworkManager.h>
+
+#include <ZLibrary.h>
+#include <ZLDir.h>
+#include <ZLFile.h>
+#include <ZLTime.h>
+
+#include "LitResGenresParser.h"
+#include "LitResGenre.h"
+#include "LitResUtil.h"
+
+static const std::string GENRES_CACHE_PREFIX = "litres_genres_";
+static const std::string GENRES_CACHE_SUFFIX = ".xml";
+
+LitResGenre::LitResGenre() {
+}
+
+LitResGenre::LitResGenre(const std::string &id, const std::string &title) : Id(id), Title(title) {
+}
+
+LitResGenreMap *LitResGenreMap::ourInstance = 0;
+
+const LitResGenreMap &LitResGenreMap::Instance() {
+ if (ourInstance == 0) {
+ ourInstance = new LitResGenreMap();
+ }
+ return *ourInstance;
+}
+
+LitResGenreMap::LitResGenreMap() : myInitialized(false) {
+}
+
+void LitResGenreMap::validateGenres() const {
+ if (!myInitialized) {
+ if (loadGenres()) {
+ buildGenresTitles(myGenresTree);
+ myInitialized = true;
+ }
+ }
+}
+
+const std::map<std::string, shared_ptr<LitResGenre> > &LitResGenreMap::genresMap() const {
+ validateGenres();
+ return myGenresMap;
+}
+
+const std::vector<shared_ptr<LitResGenre> > &LitResGenreMap::genresTree() const {
+ validateGenres();
+ return myGenresTree;
+}
+
+const std::map<shared_ptr<LitResGenre>, std::string> &LitResGenreMap::genresTitles() const {
+ validateGenres();
+ return myGenresTitles;
+}
+
+void LitResGenreMap::fillGenreIds(const std::string &tag, std::vector<std::string> &ids) const {
+ std::vector<std::string> words;
+ int index = 0;
+
+ const std::map<shared_ptr<LitResGenre>, std::string> map = genresTitles();
+
+ do {
+ int index2 = tag.find(' ', index);
+ std::string word = tag.substr(index, index2 - index);
+ ZLUnicodeUtil::utf8Trim(word);
+ if (!word.empty()) {
+ words.push_back(ZLUnicodeUtil::toLower(word));
+ }
+ index = index2 + 1;
+ } while (index != 0);
+
+ for (std::map<shared_ptr<LitResGenre>, std::string>::const_iterator it = map.begin(); it != map.end(); ++it) {
+ const LitResGenre &genre = *it->first;
+ std::string title = ZLUnicodeUtil::toLower(it->second);
+ bool containsAll = true;
+ for (std::vector<std::string>::const_iterator jt = words.begin(); jt != words.end(); ++jt) {
+ if (title.find(*jt) == std::string::npos) {
+ containsAll = false;
+ break;
+ }
+ }
+ if (containsAll) {
+ ids.push_back(genre.Id);
+ }
+ }
+}
+
+bool LitResGenreMap::loadGenres() const {
+ static const std::string directoryPath = ZLNetworkManager::CacheDirectory();
+ static shared_ptr<ZLDir> dir = ZLFile(directoryPath).directory(true);
+
+ const std::string url = LitResUtil::url("pages/catalit_genres/");
+
+ myGenresTree.clear();
+ myGenresMap.clear();
+ myGenresTitles.clear();
+
+ if (dir.isNull()) {
+ shared_ptr<ZLNetworkRequest> networkData = ZLNetworkManager::Instance().createXMLParserRequest(
+ url,
+ new LitResGenresParser(myGenresTree, myGenresMap)
+ );
+ const std::string error = ZLNetworkManager::Instance().perform(networkData);
+ if (!error.empty()) {
+ myGenresTree.clear();
+ myGenresMap.clear();
+ myGenresTitles.clear();
+ return false;
+ }
+ return true;
+ }
+
+ std::string cacheName;
+ bool cacheValid = false;
+
+ std::vector<std::string> files;
+ dir->collectFiles(files, false);
+ for (std::vector<std::string>::const_iterator it = files.begin(); it != files.end(); ++it) {
+ const std::string &name = *it;
+ if (ZLStringUtil::stringStartsWith(name, GENRES_CACHE_PREFIX)) {
+ cacheName = name;
+ }
+ }
+ files.clear();
+
+ ZLTime now;
+
+ if (!cacheName.empty()) {
+ std::string cacheDate = cacheName.substr(GENRES_CACHE_PREFIX.size(), 8);
+ int cacheYear = std::atoi(cacheDate.substr(0, 4).c_str());
+ int cacheMonth = std::atoi(cacheDate.substr(4, 2).c_str());
+ int cacheDay = std::atoi(cacheDate.substr(6, 2).c_str());
+ int daysDiff = (now.year() - cacheYear) * 365 + (now.month() - cacheMonth) * 31 + (now.dayOfMonth() - cacheDay);
+ if (daysDiff < 30) {
+ cacheValid = true;
+ }
+ cacheName = dir->itemPath(cacheName);
+ }
+
+ if (!cacheValid) {
+ std::string yearStr, monthStr, dayStr;
+ ZLStringUtil::appendNumber(yearStr, now.year());
+ ZLStringUtil::appendNumber(monthStr, now.month());
+ ZLStringUtil::appendNumber(dayStr, now.dayOfMonth());
+ while (monthStr.size() < 2) {
+ monthStr = "0" + monthStr;
+ }
+ while (dayStr.size() < 2) {
+ dayStr = "0" + dayStr;
+ }
+
+ const std::string fileName = dir->path() + ZLibrary::FileNameDelimiter +
+ GENRES_CACHE_PREFIX + yearStr + monthStr + dayStr + GENRES_CACHE_SUFFIX;
+
+ const std::string error = ZLNetworkManager::Instance().downloadFile(url, fileName);
+ if (!error.empty()) {
+ ZLFile(fileName).remove();
+ } else {
+ ZLFile(cacheName).remove();
+ cacheName = fileName;
+ }
+ }
+
+ if (cacheName.empty()) {
+ return false;
+ }
+
+ shared_ptr<ZLXMLReader> parser = new LitResGenresParser(myGenresTree, myGenresMap);
+ return parser->readDocument(ZLFile(cacheName));
+}
+
+void LitResGenreMap::buildGenresTitles(const std::vector<shared_ptr<LitResGenre> > &genres, const std::string &titlePrefix) const {
+ for (std::vector<shared_ptr<LitResGenre> >::const_iterator it = genres.begin(); it != genres.end(); ++it) {
+ shared_ptr<LitResGenre> genre = *it;
+ std::string title = titlePrefix.empty() ? (genre->Title) : (titlePrefix + "/" + genre->Title);
+ if (genre->Id.empty()) {
+ buildGenresTitles(genre->Children, title);
+ } else {
+ myGenresTitles[genre] = title;
+ }
+ }
+}
diff --git a/fbreader/src/network/litres/LitResGenre.h b/fbreader/src/network/litres/LitResGenre.h
new file mode 100644
index 0000000..4b2bd3b
--- /dev/null
+++ b/fbreader/src/network/litres/LitResGenre.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __LITRESGENRE_H__
+#define __LITRESGENRE_H__
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include <shared_ptr.h>
+
+struct LitResGenre {
+ std::string Id;
+ std::string Title;
+ std::vector<shared_ptr<LitResGenre> > Children;
+
+ LitResGenre();
+ LitResGenre(const std::string &id, const std::string &title);
+};
+
+class LitResGenreMap {
+
+public:
+ static const LitResGenreMap &Instance();
+
+private:
+ static LitResGenreMap *ourInstance;
+
+private:
+ LitResGenreMap();
+
+public:
+ const std::map<std::string, shared_ptr<LitResGenre> > &genresMap() const;
+ const std::vector<shared_ptr<LitResGenre> > &genresTree() const;
+ const std::map<shared_ptr<LitResGenre>, std::string> &genresTitles() const;
+ void fillGenreIds(const std::string &tag, std::vector<std::string> &ids) const;
+
+private:
+ void validateGenres() const;
+ bool loadGenres() const;
+ void buildGenresTitles(const std::vector<shared_ptr<LitResGenre> > &genres, const std::string &titlePrefix = "") const;
+
+ mutable std::vector<shared_ptr<LitResGenre> > myGenresTree;
+ mutable std::map<std::string, shared_ptr<LitResGenre> > myGenresMap;
+ mutable std::map<shared_ptr<LitResGenre>, std::string> myGenresTitles;
+ mutable bool myInitialized;
+};
+
+#endif /* __LITRESGENRE_H__ */
diff --git a/fbreader/src/network/litres/LitResGenresParser.cpp b/fbreader/src/network/litres/LitResGenresParser.cpp
new file mode 100644
index 0000000..9ed3f2d
--- /dev/null
+++ b/fbreader/src/network/litres/LitResGenresParser.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 <ZLStringUtil.h>
+
+#include "LitResGenresParser.h"
+
+#include "LitResGenre.h"
+
+static const std::string TAG_GENRE = "genre";
+
+
+LitResGenresParser::LitResGenresParser(std::vector<shared_ptr<LitResGenre> > &genresTree, std::map<std::string, shared_ptr<LitResGenre> > &genresMap) :
+ myGenresTree(genresTree),
+ myGenresMap(genresMap),
+ myDontPopStack(false) {
+}
+
+void LitResGenresParser::saveGenre(shared_ptr<LitResGenre> genre, const std::string &token) {
+ if (myStack.empty()) {
+ myGenresTree.push_back(genre);
+ } else {
+ myStack.back()->Children.push_back(genre);
+ }
+ if (genre->Id.empty()) {
+ myStack.push_back(genre);
+ } else {
+ myDontPopStack = true;
+ if (!token.empty()) {
+ myGenresMap[token] = genre;
+ }
+ }
+}
+
+void LitResGenresParser::startElementHandler(const char *tag, const char **attributes) {
+ if (TAG_GENRE == tag) {
+ const char *id = attributeValue(attributes, "id");
+ const char *title = attributeValue(attributes, "title");
+ const char *token = attributeValue(attributes, "token");
+ std::string strId, strTitle, strToken;
+ if (id != 0) {
+ strId = id;
+ }
+ if (title != 0) {
+ strTitle = title;
+ }
+ if (token != 0) {
+ strToken = token;
+ }
+ saveGenre(new LitResGenre(strId, strTitle), strToken);
+ }
+}
+
+void LitResGenresParser::endElementHandler(const char *tag) {
+ if (TAG_GENRE == tag) {
+ if (!myDontPopStack) {
+ myStack.pop_back();
+ }
+ myDontPopStack = false;
+ }
+}
+
+void LitResGenresParser::characterDataHandler(const char *, std::size_t) {
+}
+
diff --git a/fbreader/src/network/litres/LitResGenresParser.h b/fbreader/src/network/litres/LitResGenresParser.h
new file mode 100644
index 0000000..424d37b
--- /dev/null
+++ b/fbreader/src/network/litres/LitResGenresParser.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __LITRESGENRESPARSER_H__
+#define __LITRESGENRESPARSER_H__
+
+
+#include <map>
+#include <vector>
+#include <string>
+
+#include <ZLXMLReader.h>
+
+struct LitResGenre;
+
+class LitResGenresParser : public ZLXMLReader {
+
+public:
+ LitResGenresParser(std::vector<shared_ptr<LitResGenre> > &genresTree, std::map<std::string, shared_ptr<LitResGenre> > &genresMap);
+
+private:
+ void startElementHandler(const char *tag, const char **attributes);
+ void endElementHandler(const char *tag);
+ void characterDataHandler(const char *text, std::size_t len);
+
+ void saveGenre(shared_ptr<LitResGenre> genre, const std::string &token);
+
+ const std::string &titlePrefix();
+
+private:
+ std::vector<shared_ptr<LitResGenre> > &myGenresTree;
+ std::map<std::string, shared_ptr<LitResGenre> > &myGenresMap;
+ std::vector<shared_ptr<LitResGenre> > myStack;
+ bool myDontPopStack;
+
+ std::vector<std::string> myTitleStack;
+ std::string myTitlePrefix;
+};
+
+#endif /* __LITRESGENRESPARSER_H__ */
diff --git a/fbreader/src/network/litres/LitResRecommendationsItem.cpp b/fbreader/src/network/litres/LitResRecommendationsItem.cpp
new file mode 100644
index 0000000..54d7cd7
--- /dev/null
+++ b/fbreader/src/network/litres/LitResRecommendationsItem.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 <ZLStringUtil.h>
+#include <ZLNetworkUtil.h>
+
+#include "../NetworkLink.h"
+#include "../authentication/litres/LitResAuthenticationManager.h"
+
+#include "LitResRecommendationsItem.h"
+
+LitResRecommendationsItem::LitResRecommendationsItem(
+ const OPDSLink &link,
+ const std::string &title,
+ const std::string &summary,
+ const UrlInfoCollection &urlByType,
+ AccessibilityType accessibility
+) : OPDSCatalogItem(
+ link,
+ title,
+ summary,
+ urlByType,
+ accessibility
+) { }
+
+std::string LitResRecommendationsItem::getCatalogUrl() {
+ LitResAuthenticationManager &mgr = (LitResAuthenticationManager&)*Link.authenticationManager();
+ std::string catalogUrl = OPDSCatalogItem::getCatalogUrl();
+ if (mgr.isAuthorised().Status == B3_FALSE) {
+ return catalogUrl;
+ }
+ std::string query = ZLStringUtil::join(mgr.getPurchasedIds(), ",");
+ ZLNetworkUtil::appendParameter(catalogUrl, "ids", query);
+ return catalogUrl;
+}
diff --git a/fbreader/src/network/litres/LitResRecommendationsItem.h b/fbreader/src/network/litres/LitResRecommendationsItem.h
new file mode 100644
index 0000000..ba27623
--- /dev/null
+++ b/fbreader/src/network/litres/LitResRecommendationsItem.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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.
+ */
+
+#ifndef __LITRESRECOMMENDATIONSITEM_H__
+#define __LITRESRECOMMENDATIONSITEM_H__
+
+#include "../opds/OPDSCatalogItem.h"
+
+class LitResRecommendationsItem : public OPDSCatalogItem {
+
+public:
+ LitResRecommendationsItem(
+ const OPDSLink &link,
+ const std::string &title,
+ const std::string &summary,
+ const UrlInfoCollection &urlByType,
+ AccessibilityType accessibility = ALWAYS
+ );
+
+private:
+ std::string getCatalogUrl();
+};
+
+#endif /* __LITRESRECOMMENDATIONSITEM_H__ */
diff --git a/fbreader/src/network/litres/LitResUtil.cpp b/fbreader/src/network/litres/LitResUtil.cpp
new file mode 100644
index 0000000..992b7d9
--- /dev/null
+++ b/fbreader/src/network/litres/LitResUtil.cpp
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 <ZLNetworkUtil.h>
+#include <ZLStringUtil.h>
+
+#include "../NetworkLink.h"
+#include "../opds/OPDSMetadata.h"
+
+#include "LitResBookshelfItem.h"
+#include "LitResBooksFeedItem.h"
+#include "LitResRecommendationsItem.h"
+#include "LitResByGenresItem.h"
+#include "LitResAuthorsItem.h"
+
+#include "LitResUtil.h"
+
+
+static std::string LITRES_API_URL = "://robot.litres.ru/";
+
+std::string LitResUtil::url(const std::string &path) {
+ std::string url = LITRES_API_URL + path;
+ if (ZLNetworkUtil::hasParameter(url, "sid") ||
+ ZLNetworkUtil::hasParameter(url, "pwd")) {
+ url = "https" + url;
+ } else {
+ url = "http" + url;
+ }
+ return url;
+}
+
+std::string LitResUtil::url(const NetworkLink &link, const std::string &path) {
+ std::string urlString = url(path);
+ link.rewriteUrl(urlString);
+ return urlString;
+}
+
+std::string LitResUtil::url(bool secure, const std::string &path) {
+ std::string url = LITRES_API_URL + path;
+ if (secure) {
+ url = "https" + url;
+ } else {
+ url = "http" + url;
+ }
+ return url;
+}
+
+std::string LitResUtil::url(const NetworkLink &link, bool secure, const std::string &path) {
+ std::string urlString = url(secure, path);
+ link.rewriteUrl(urlString, true);
+ return urlString;
+}
+
+std::string LitResUtil::generateTrialUrl(std::string bookId) {
+ std::size_t len = bookId.length();
+ if (len < 8) {
+ bookId = std::string(8 - len, '0') + bookId;
+ }
+ std::string query = "static/trials/%s/%s/%s/%s.fb2.zip";
+ query = ZLStringUtil::printf(query, bookId.substr(0,2));
+ query = ZLStringUtil::printf(query, bookId.substr(2,2));
+ query = ZLStringUtil::printf(query, bookId.substr(4,2));
+ query = ZLStringUtil::printf(query, bookId);
+ return url(false, query);
+}
+
+std::string LitResUtil::generatePurchaseUrl(const NetworkLink &link, const std::string &bookId) {
+ std::string query;
+ ZLNetworkUtil::appendParameter(query, "art", bookId);
+ return url(link, true, "pages/purchase_book/" + query);
+}
+
+std::string LitResUtil::generateDownloadUrl(const std::string &bookId) {
+ std::string query;
+ ZLNetworkUtil::appendParameter(query, "art", bookId);
+ return url(true, "pages/catalit_download_book/" + query);
+}
+
+std::string LitResUtil::generateAlsoReadUrl(const std::string &bookId) {
+ std::string query;
+ ZLNetworkUtil::appendParameter(query, "rating", "with");
+ ZLNetworkUtil::appendParameter(query, "art", bookId);
+ return url(false, "pages/catalit_browser/" + query);
+}
+
+std::string LitResUtil::generateBooksByGenreUrl(const std::string &genreId) {
+ std::string query;
+ ZLNetworkUtil::appendParameter(query, "checkpoint", "2000-01-01");
+ ZLNetworkUtil::appendParameter(query, "genre", genreId);
+ return url(false, "pages/catalit_browser/" + query);
+}
+
+std::string LitResUtil::generateBooksByAuthorUrl(const std::string &authorId) {
+ std::string query;
+ ZLNetworkUtil::appendParameter(query, "checkpoint", "2000-01-01");
+ ZLNetworkUtil::appendParameter(query, "person", authorId);
+ return url(false, "pages/catalit_browser/" + query);
+}
+
+shared_ptr<NetworkItem> LitResUtil::createLitResNode(shared_ptr<ZLMimeType> type, std::string rel, const NetworkLink &link, std::string title,
+ std::string annotation, std::map<NetworkItem::URLType,std::string> urlMap, bool dependsOnAccount) {
+ static const std::string TYPE = "type";
+ static const std::string NO = "no";
+
+ std::string litresType = type->getParameter(TYPE);
+
+ if (rel == OPDSConstants::REL_BOOKSHELF) {
+ return new LitResBookshelfItem(
+ link,
+ title,
+ annotation,
+ urlMap,
+ NetworkCatalogItem::SIGNED_IN
+ );
+ } else if (rel == OPDSConstants::REL_RECOMMENDATIONS) {
+ return new LitResRecommendationsItem(
+ (OPDSLink&)link,
+ title,
+ annotation,
+ urlMap,
+ NetworkCatalogItem::HAS_BOOKS
+ );
+ } else if (litresType == ZLMimeType::APPLICATION_LITRES_XML_BOOKS->getParameter(TYPE)) {
+ int flags = NetworkCatalogItem::FLAGS_DEFAULT;
+ if (type->getParameter("groupSeries") == NO) {
+ flags &= ~NetworkCatalogItem::FLAG_GROUP_MORE_THAN_1_BOOK_BY_SERIES;
+ }
+ if (type->getParameter("showAuthor") == "false") {
+ flags &= ~NetworkCatalogItem::FLAG_SHOW_AUTHOR;
+ }
+ bool sort = type->getParameter("sort") != NO;
+ return new LitResBooksFeedItem(
+ sort,
+ link,
+ title,
+ annotation,
+ urlMap,
+ dependsOnAccount ? NetworkCatalogItem::SIGNED_IN : NetworkCatalogItem::ALWAYS,
+ flags
+ );
+ } else if (litresType == ZLMimeType::APPLICATION_LITRES_XML_GENRES->getParameter(TYPE)) {
+ return new LitResByGenresItem(
+ LitResGenreMap::Instance().genresTree(),
+ link,
+ title,
+ annotation,
+ urlMap,
+ NetworkCatalogItem::ALWAYS,
+ NetworkCatalogItem::FLAG_SHOW_AUTHOR
+ );
+ } else if (litresType == ZLMimeType::APPLICATION_LITRES_XML_AUTHORS->getParameter(TYPE)) {
+ return new LitResAuthorsItem(
+ link,
+ title,
+ annotation,
+ urlMap,
+ NetworkCatalogItem::ALWAYS
+ );
+ } else {
+ return 0;
+ }
+}
diff --git a/fbreader/src/network/litres/LitResUtil.h b/fbreader/src/network/litres/LitResUtil.h
new file mode 100644
index 0000000..fd23a08
--- /dev/null
+++ b/fbreader/src/network/litres/LitResUtil.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __LITRESUTIL_H__
+#define __LITRESUTIL_H__
+
+#include <string>
+
+#include "../NetworkItems.h"
+
+class NetworkLink;
+
+class LitResUtil {
+
+public:
+ static std::string url(const std::string &path);
+ static std::string url(const NetworkLink &link, const std::string &path);
+ static std::string url(const NetworkLink &link, bool secure, const std::string &path);
+ static std::string url(bool secure, const std::string &path);
+
+ static std::string generateTrialUrl(std::string bookId);
+ static std::string generatePurchaseUrl(const NetworkLink &link, const std::string &bookId);
+ static std::string generateDownloadUrl(const std::string &bookId);
+ static std::string generateAlsoReadUrl(const std::string &bookId);
+ static std::string generateBooksByGenreUrl(const std::string &genreId);
+ static std::string generateBooksByAuthorUrl(const std::string &authorId);
+
+public:
+ static shared_ptr<NetworkItem> createLitResNode(shared_ptr<ZLMimeType> type, std::string rel,
+ const NetworkLink &link, std::string title,
+ std::string annotation, std::map<NetworkItem::URLType,std::string> urlMap,
+ bool dependsOnAccount);
+
+private:
+ LitResUtil();
+};
+
+#endif /* __LITRESUTIL_H__ */
diff --git a/fbreader/src/network/litres/SortedCatalogItem.cpp b/fbreader/src/network/litres/SortedCatalogItem.cpp
new file mode 100644
index 0000000..79d7f49
--- /dev/null
+++ b/fbreader/src/network/litres/SortedCatalogItem.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 "SortedCatalogItem.h"
+
+bool SortedCatalogItem::BookItemFilter::accepts(NetworkItem* item) const {
+ return zlobject_cast<NetworkBookItem*>(item) != 0;
+}
+
+bool SortedCatalogItem::BySeriesFilter::accepts(NetworkItem* item) const {
+ NetworkBookItem* bookItem = zlobject_cast<NetworkBookItem*>(item);
+ return bookItem != 0 && !bookItem->SeriesTitle.empty();
+}
+
+SortedCatalogItem::SortedCatalogItem(const NetworkCatalogItem &parent, const ZLResource &resource,
+ const NetworkItem::List &children, int flags)
+ : NetworkCatalogItem(parent.Link, resource.value(), resource["summary"].value(), parent.URLByType, ALWAYS, flags) {
+ myChildren = children;
+}
+
+std::string SortedCatalogItem::loadChildren(NetworkItem::List &children, shared_ptr<ZLNetworkRequest::Listener> listener) {
+ children.assign(myChildren.begin(), myChildren.end());
+ listener->finished();
+ return std::string();
+}
+
+bool SortedCatalogItem::isEmpty() const {
+ return myChildren.empty();
+}
+
+const ZLResource &SortedCatalogItem::resource(const std::string &resourceKey) {
+ return ZLResource::resource("networkView")[resourceKey];
+}
diff --git a/fbreader/src/network/litres/SortedCatalogItem.h b/fbreader/src/network/litres/SortedCatalogItem.h
new file mode 100644
index 0000000..e4f2744
--- /dev/null
+++ b/fbreader/src/network/litres/SortedCatalogItem.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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.
+ */
+
+#ifndef __SORTEDCATALOGITEM_H__
+#define __SORTEDCATALOGITEM_H__
+
+#include <algorithm>
+
+#include <ZLResource.h>
+
+#include "../NetworkComparators.h"
+#include "../NetworkItems.h"
+
+class SortedCatalogItem : public NetworkCatalogItem {
+
+public:
+ class BookItemFilter {
+ public:
+ bool accepts(NetworkItem* item) const;
+ };
+
+ class BySeriesFilter {
+ public:
+ bool accepts(NetworkItem* item) const;
+ };
+
+ //TODO maybe refactor (using templates is too complex for this simple case
+ //(templates were used because in C++ virtual methods can't be called from constructor)
+ template <class T, class F>
+ static SortedCatalogItem* create(const NetworkCatalogItem &parent, const std::string &resourceKey,
+ const NetworkItem::List &children, int flags, T comparator, F filter);
+ template <class T>
+ static SortedCatalogItem* create(const NetworkCatalogItem &parent, const std::string &resourceKey,
+ const NetworkItem::List &children, int flags, T comparator);
+ static SortedCatalogItem* create(const NetworkCatalogItem &parent, const std::string &resourceKey,
+ const NetworkItem::List &children, int flags);
+
+public:
+ SortedCatalogItem(const NetworkCatalogItem &parent, const ZLResource &resource, const NetworkItem::List &children, int flags);
+
+public:
+ std::string loadChildren(NetworkItem::List &children, shared_ptr<ZLNetworkRequest::Listener> listener);
+ bool isEmpty() const;
+ //TODO following method should be in class NetworkLibrary or smth like that
+ static const ZLResource &resource(const std::string &resourceKey);
+
+protected:
+ NetworkItem::List myChildren;
+};
+
+template <class T, class F>
+SortedCatalogItem* SortedCatalogItem::create(const NetworkCatalogItem &parent, const std::string &resourceKey,
+ const NetworkItem::List &children, int flags, T comparator, F filter) {
+ NetworkItem::List tmpChildren;
+ for (std::size_t i = 0; i < children.size(); ++i) {
+ shared_ptr<NetworkItem> child = children.at(i);
+ if (filter.accepts(&(*child))) {
+ tmpChildren.push_back(child);
+ }
+ }
+ std::sort(tmpChildren.begin(), tmpChildren.end(), comparator);
+ return new SortedCatalogItem(parent, resource(resourceKey), tmpChildren, flags);
+}
+
+template <class T>
+SortedCatalogItem* SortedCatalogItem::create(const NetworkCatalogItem &parent, const std::string &resourceKey,
+ const NetworkItem::List &children, int flags, T comparator) {
+ return create(parent, resourceKey, children, flags, comparator, BookItemFilter());
+}
+
+inline SortedCatalogItem* SortedCatalogItem::create(const NetworkCatalogItem &parent, const std::string &resourceKey,
+ const NetworkItem::List &children, int flags) {
+ BookItemFilter filter;
+ NetworkItem::List tmpChildren;
+ for (std::size_t i = 0; i < children.size(); ++i) {
+ shared_ptr<NetworkItem> child = children.at(i);
+ if (filter.accepts(&(*child))) {
+ tmpChildren.push_back(child);
+ }
+ }
+ return new SortedCatalogItem(parent, resource(resourceKey), tmpChildren, flags);
+}
+
+#endif /* __SORTEDCATALOGITEM_H__ */
diff --git a/fbreader/src/network/opds/NetworkOPDSFeedReader.cpp b/fbreader/src/network/opds/NetworkOPDSFeedReader.cpp
new file mode 100644
index 0000000..3c1ad0a
--- /dev/null
+++ b/fbreader/src/network/opds/NetworkOPDSFeedReader.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 <algorithm>
+
+#include <ZLStringUtil.h>
+#include <ZLUnicodeUtil.h>
+#include <ZLNetworkUtil.h>
+#include <ZLMimeType.h>
+
+#include "NetworkOPDSFeedReader.h"
+#include "OPDSCatalogItem.h"
+#include "OPDSXMLParser.h"
+
+#include "../NetworkOperationData.h"
+#include "../NetworkItems.h"
+#include "../BookReference.h"
+#include "OPDSBookItem.h"
+
+#include "../litres/LitResUtil.h"
+
+
+NetworkOPDSFeedReader::NetworkOPDSFeedReader(
+ const OPDSLink &link,
+ const std::string &baseURL,
+ NetworkOperationData &result
+) :
+ myLink(link),
+ myBaseURL(baseURL),
+ myData(result),
+ myIndex(0),
+ myOpenSearchStartIndex(0) {
+}
+
+void NetworkOPDSFeedReader::processFeedStart() {
+}
+
+void NetworkOPDSFeedReader::processFeedMetadata(shared_ptr<OPDSFeedMetadata> feed) {
+ for (std::size_t i = 0; i < feed->links().size(); ++i) {
+ ATOMLink &link = *(feed->links()[i]);
+ const std::string &href = ZLNetworkUtil::url(myBaseURL, link.href());
+ shared_ptr<ZLMimeType> type = ZLMimeType::get(link.type());
+ const std::string &rel = myLink.relation(link.rel(), link.type());
+ if (type->weakEquals(*ZLMimeType::APPLICATION_ATOM_XML)) {
+ if (rel == "self") {
+ } else if (rel == "next") {
+ myData.ResumeURI = href;
+ }
+ }
+ }
+ myOpenSearchStartIndex = feed->getOpensearchStartIndex() - 1;
+}
+
+
+void NetworkOPDSFeedReader::processFeedEnd() {
+ for (std::size_t i = 0; i < myData.Items.size(); ++i) {
+ NetworkItem &item = *myData.Items[i];
+ if (!item.isInstanceOf(NetworkBookItem::TYPE_ID)) {
+ continue;
+ }
+ NetworkBookItem &book = (NetworkBookItem&) item;
+ book.Index += myOpenSearchStartIndex;
+ }
+}
+
+void NetworkOPDSFeedReader::processFeedEntry(shared_ptr<OPDSEntry> entry) {
+ if (entry.isNull()) {
+ return;
+ }
+
+ std::map<std::string,OPDSLink::FeedCondition>::const_iterator it = myLink.myFeedConditions.find(entry->id()->uri());
+ if (it != myLink.myFeedConditions.end() && it->second == OPDSLink::CONDITION_NEVER) {
+ return;
+ }
+ OPDSEntry &e = *entry;
+ bool hasBookLink = false;
+ for (std::size_t i = 0; i < e.links().size(); ++i) {
+ ATOMLink &link = *(e.links()[i]);
+ const std::string &type = link.type();
+ const std::string &rel = myLink.relation(link.rel(), type);
+ if (rel == OPDSConstants::REL_ACQUISITION ||
+ rel == OPDSConstants::REL_ACQUISITION_OPEN ||
+ rel == OPDSConstants::REL_ACQUISITION_SAMPLE ||
+ rel == OPDSConstants::REL_ACQUISITION_BUY ||
+ rel == OPDSConstants::REL_ACQUISITION_CONDITIONAL ||
+ rel == OPDSConstants::REL_ACQUISITION_SAMPLE_OR_FULL ||
+ (rel.empty() && OPDSBookItem::formatByZLMimeType(type) != BookReference::NONE)) {
+ hasBookLink = true;
+ break;
+ }
+ }
+
+ shared_ptr<NetworkItem> item;
+ if (hasBookLink) {
+ item = new OPDSBookItem(myLink, e, myBaseURL, myIndex++);
+ } else {
+ item = readCatalogItem(e);
+ }
+ if (!item.isNull()) {
+ myData.Items.push_back(item);
+ }
+}
+
+shared_ptr<NetworkItem> NetworkOPDSFeedReader::readCatalogItem(OPDSEntry &entry) {
+ std::string coverURL;
+ std::string url;
+ bool urlIsAlternate = false;
+ std::string htmlURL;
+ std::string litresRel;
+ shared_ptr<ZLMimeType> litresMimeType;
+ int catalogFlags = NetworkCatalogItem::FLAGS_DEFAULT;
+ for (std::size_t i = 0; i < entry.links().size(); ++i) {
+ ATOMLink &link = *(entry.links()[i]);
+ const std::string &href = ZLNetworkUtil::url(myBaseURL, link.href());
+ shared_ptr<ZLMimeType> type = ZLMimeType::get(link.type());
+ const std::string &rel = myLink.relation(link.rel(), link.type());
+ if (ZLMimeType::isImage(type)) {
+ if (rel == OPDSConstants::REL_THUMBNAIL || rel == OPDSConstants::REL_IMAGE_THUMBNAIL) {
+ coverURL = href;
+ } else if (coverURL.empty() && (rel == OPDSConstants::REL_COVER || ZLStringUtil::stringStartsWith(rel, OPDSConstants::REL_IMAGE_PREFIX))) {
+ coverURL = href;
+ }
+ } else if (type->weakEquals(*ZLMimeType::APPLICATION_ATOM_XML)) {
+ if (rel == ATOMConstants::REL_ALTERNATE) {
+ if (url.empty()) {
+ url = href;
+ urlIsAlternate = true;
+ }
+ } else {
+ url = href;
+ urlIsAlternate = false;
+ if (rel == OPDSConstants::REL_CATALOG_AUTHOR) {
+ catalogFlags &= !NetworkCatalogItem::FLAG_SHOW_AUTHOR;
+ }
+ }
+ } else if (type->weakEquals(*ZLMimeType::TEXT_HTML)) {
+ if (rel == OPDSConstants::REL_ACQUISITION ||
+ rel == ATOMConstants::REL_ALTERNATE ||
+ rel.empty()) {
+ htmlURL = href;
+ }
+ } else if (type->weakEquals(*ZLMimeType::APPLICATION_LITRES_XML)) {
+ url = href;
+ litresRel = rel;
+ litresMimeType = type;
+ }
+ }
+
+ if (url.empty() && htmlURL.empty()) {
+ return 0;
+ }
+
+ if (!url.empty() && !urlIsAlternate) {
+ htmlURL.erase();
+ }
+
+ std::map<std::string,OPDSLink::FeedCondition>::const_iterator it =
+ myLink.myFeedConditions.find(entry.id()->uri());
+ bool dependsOnAccount =
+ it != myLink.myFeedConditions.end() &&
+ it->second == OPDSLink::CONDITION_SIGNED_IN;
+
+ std::string annotation = entry.summary();
+ annotation.erase(std::remove(annotation.begin(), annotation.end(), 0x09), annotation.end());
+ annotation.erase(std::remove(annotation.begin(), annotation.end(), 0x0A), annotation.end());
+ NetworkItem::UrlInfoCollection urlMap;
+ urlMap[NetworkItem::URL_COVER] = coverURL;
+ urlMap[NetworkItem::URL_CATALOG] = url;
+ urlMap[NetworkItem::URL_HTML_PAGE] = htmlURL;
+
+ if (!litresMimeType.isNull()) {
+ return LitResUtil::createLitResNode(litresMimeType, litresRel, myData.Link, entry.title(), annotation, urlMap, dependsOnAccount);
+ }
+ return new OPDSCatalogItem(
+ (OPDSLink&)myData.Link,
+ entry.title(),
+ annotation,
+ urlMap,
+ dependsOnAccount ? NetworkCatalogItem::SIGNED_IN : NetworkCatalogItem::ALWAYS,
+ catalogFlags
+ );
+}
diff --git a/fbreader/src/network/opds/NetworkOPDSFeedReader.h b/fbreader/src/network/opds/NetworkOPDSFeedReader.h
new file mode 100644
index 0000000..f51b1bf
--- /dev/null
+++ b/fbreader/src/network/opds/NetworkOPDSFeedReader.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __NETWORKOPDSFEEDREADER_H__
+#define __NETWORKOPDSFEEDREADER_H__
+
+#include <map>
+#include <string>
+
+#include "OPDSFeedReader.h"
+#include "OPDSLink.h"
+
+class NetworkOperationData;
+
+class NetworkItem;
+
+class NetworkOPDSFeedReader : public OPDSFeedReader {
+
+public:
+ NetworkOPDSFeedReader(
+ const OPDSLink &link,
+ const std::string &baseURL,
+ NetworkOperationData &result
+ );
+
+public:
+ void processFeedEntry(shared_ptr<OPDSEntry> entry);
+ void processFeedStart();
+ void processFeedMetadata(shared_ptr<OPDSFeedMetadata> feed);
+ void processFeedEnd();
+
+private:
+ shared_ptr<NetworkItem> readCatalogItem(OPDSEntry &entry);
+
+private:
+ const OPDSLink &myLink;
+ const std::string myBaseURL;
+ NetworkOperationData &myData;
+ unsigned int myIndex;
+ unsigned int myOpenSearchStartIndex;
+};
+
+
+#endif /* __NETWORKOPDSFEEDREADER_H__ */
diff --git a/fbreader/src/network/opds/OPDSBookItem.cpp b/fbreader/src/network/opds/OPDSBookItem.cpp
new file mode 100644
index 0000000..6899afa
--- /dev/null
+++ b/fbreader/src/network/opds/OPDSBookItem.cpp
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 <ZLNetworkManager.h>
+#include <ZLNetworkUtil.h>
+#include <ZLUnicodeUtil.h>
+#include <ZLStringUtil.h>
+
+#include "../NetworkLink.h"
+#include "OPDSXMLParser.h"
+
+#include "OPDSBookItem.h"
+#include "OPDSCatalogItem.h"
+
+#include "../tree/NetworkTreeFactory.h"
+
+OPDSBookItem::OPDSBookItem(const OPDSLink &link, OPDSEntry &entry, std::string baseUrl, unsigned int index) :
+ NetworkBookItem(
+ link,
+ entry.id()->uri(),
+ index,
+ entry.title(),
+ getAnnotation(entry),
+ entry.dcLanguage(),
+ getDate(entry),
+ getAuthors(entry),
+ getTags(entry),
+ entry.seriesTitle(),
+ entry.seriesIndex(),
+ getUrls(link, entry, baseUrl),
+ getReferences(link, entry, baseUrl)
+ ) {
+ myRelatedInfos = getRelatedUrls(link, entry, baseUrl);
+ myInformationIsFull = false;
+}
+
+bool OPDSBookItem::isFullyLoaded() const {
+ return myInformationIsFull || URLByType.find(URL_SINGLE_ENTRY) == URLByType.end();
+}
+
+class OPDSBookItemFullInfoLoader : public ZLNetworkRequest::Listener {
+public:
+ OPDSBookItemFullInfoLoader(OPDSBookItem &item, shared_ptr<ZLNetworkRequest> request, shared_ptr<ZLNetworkRequest::Listener> listener) :
+ myItem(item), myListener(listener) {
+ request->setListener(this);
+ ZLNetworkManager::Instance().performAsync(request);
+ }
+
+ void finished(const std::string &error) {
+ if (error.empty()) {
+ myItem.myInformationIsFull = true;
+ }
+ myListener->finished(error);
+ }
+private:
+ OPDSBookItem &myItem;
+ shared_ptr<ZLNetworkRequest::Listener> myListener;
+};
+
+void OPDSBookItem::loadFullInformation(shared_ptr<ZLNetworkRequest::Listener> listener) {
+ if (myInformationIsFull) {
+ listener->finished();
+ return;
+ }
+
+ if (URLByType.find(URL_SINGLE_ENTRY) == URLByType.end()) {
+ myInformationIsFull = true;
+ listener->finished();
+ return;
+ }
+
+ std::string url = URLByType[URL_SINGLE_ENTRY];
+ shared_ptr<ZLNetworkRequest> request = ZLNetworkManager::Instance().createXMLParserRequest(
+ url, new OPDSXMLParser(new FullEntryReader(*this, (const OPDSLink&)Link, url), true)
+ );
+
+ new OPDSBookItemFullInfoLoader(*this, request, listener);
+}
+
+std::vector<shared_ptr<NetworkItem> > OPDSBookItem::getRelatedCatalogsItems() const {
+ std::vector<shared_ptr<NetworkItem> > items;
+ for (std::size_t i = 0; i < myRelatedInfos.size(); ++i) {
+ shared_ptr<RelatedUrlInfo> urlInfo = myRelatedInfos.at(i);
+ if (!urlInfo->MimeType->weakEquals(*ZLMimeType::APPLICATION_ATOM_XML)) {
+ continue;
+ //TODO implement items for loading link in browser
+ }
+ UrlInfoCollection urlByType = URLByType;
+ urlByType[URL_CATALOG] = urlInfo->Url;
+ OPDSCatalogItem *item = new OPDSCatalogItem(static_cast<const OPDSLink&>(Link), urlInfo->Title, std::string(), urlByType);
+ items.push_back(item);
+ }
+ return items;
+}
+
+std::string OPDSBookItem::getAnnotation(OPDSEntry &entry) {
+ //TODO implement ATOMContent support (and return content)
+ return entry.summary();
+}
+
+std::string OPDSBookItem::getDate(OPDSEntry &entry) {
+ std::string date;
+ if (!entry.dcIssued().isNull()) {
+ date = entry.dcIssued()->getDateTime(true);
+ }
+ return date;
+}
+
+std::vector<NetworkBookItem::AuthorData> OPDSBookItem::getAuthors(OPDSEntry &entry) {
+ std::vector<NetworkBookItem::AuthorData> authors;
+ for (std::size_t i = 0; i < entry.authors().size(); ++i) {
+ ATOMAuthor &author = *(entry.authors()[i]);
+ NetworkBookItem::AuthorData authorData;
+ std::string name = author.name();
+ std::string lowerCased = ZLUnicodeUtil::toLower(name);
+ static const std::string authorPrefix = "author:";
+ std::size_t index = lowerCased.find(authorPrefix);
+ if (index != std::string::npos) {
+ name = name.substr(index + authorPrefix.size());
+ } else {
+ static const std::string authorsPrefix = "authors:";
+ index = lowerCased.find(authorsPrefix);
+ if (index != std::string::npos) {
+ name = name.substr(index + authorsPrefix.size());
+ }
+ }
+ index = name.find(',');
+ if (index != std::string::npos) {
+ std::string before = name.substr(0, index);
+ std::string after = name.substr(index + 1);
+ ZLUnicodeUtil::utf8Trim(before);
+ ZLUnicodeUtil::utf8Trim(after);
+ authorData.SortKey = before;
+ authorData.DisplayName = after + ' ' + before;
+ } else {
+ ZLUnicodeUtil::utf8Trim(name);
+ index = name.rfind(' ');
+ authorData.SortKey = name.substr(index + 1);
+ authorData.DisplayName = name;
+ }
+ authors.push_back(authorData);
+ }
+ return authors;
+}
+
+std::vector<std::string> OPDSBookItem::getTags(OPDSEntry &entry) {
+ std::vector<std::string> tags;
+ for (std::size_t i = 0; i < entry.categories().size(); ++i) {
+ ATOMCategory &category = *(entry.categories()[i]);
+ tags.push_back(category.label());
+ }
+ return tags;
+}
+
+NetworkItem::UrlInfoCollection OPDSBookItem::getUrls(const OPDSLink &networkLink, OPDSEntry &entry, std::string baseUrl) {
+ //TODO split urls and references in UrlInfoCollection, like it's implemented in FBReaderJ
+ NetworkItem::UrlInfoCollection urlMap;
+ for (std::size_t i = 0; i < entry.links().size(); ++i) {
+ ATOMLink &link = *(entry.links()[i]);
+ const std::string href = ZLNetworkUtil::url(baseUrl, link.href());
+ shared_ptr<ZLMimeType> type = ZLMimeType::get(link.type());
+ const std::string &rel = networkLink.relation(link.rel(), link.type());
+ if (ZLStringUtil::stringStartsWith(rel, OPDSConstants::REL_IMAGE_PREFIX) || rel == OPDSConstants::REL_COVER) {
+ if (urlMap[NetworkItem::URL_COVER].empty() && ZLMimeType::isImage(type)) {
+ urlMap[NetworkItem::URL_COVER] = href;
+ }
+ } else if (rel == OPDSConstants::REL_THUMBNAIL || rel == OPDSConstants::REL_IMAGE_THUMBNAIL) {
+ if (ZLMimeType::isImage(type)) {
+ urlMap[NetworkItem::URL_COVER] = href;
+ }
+ } else if (type->weakEquals(*ZLMimeType::APPLICATION_ATOM_XML) &&
+ rel == ATOMConstants::REL_ALTERNATE &&
+ type->getParameter("type") == "entry") {
+ urlMap[NetworkItem::URL_SINGLE_ENTRY] = href;
+ }
+ }
+ return urlMap;
+}
+
+OPDSBookItem::RelatedUrlsList OPDSBookItem::getRelatedUrls(const OPDSLink &networkLink, OPDSEntry &entry, std::string baseUrl) {
+ OPDSBookItem::RelatedUrlsList relatedUrlList;
+ for (std::size_t i = 0; i < entry.links().size(); ++i) {
+ ATOMLink &link = *(entry.links()[i]);
+ const std::string href = ZLNetworkUtil::url(baseUrl, link.href());
+ shared_ptr<ZLMimeType> type = ZLMimeType::get(link.type());
+ const std::string &rel = networkLink.relation(link.rel(), link.type());
+ if (rel == ATOMConstants::REL_RELATED) {
+ relatedUrlList.push_back(new RelatedUrlInfo(link.title(), type, href));
+ }
+ }
+ return relatedUrlList;
+}
+
+std::vector<shared_ptr<BookReference> > OPDSBookItem::getReferences(const OPDSLink &networkLink, OPDSEntry &entry, std::string baseUrl) {
+ //TODO split urls and references in UrlInfoCollection, like it's implemented in FBReaderJ
+ std::vector<shared_ptr<BookReference> > references;
+ for (std::size_t i = 0; i < entry.links().size(); ++i) {
+ ATOMLink &link = *(entry.links()[i]);
+ const std::string href = ZLNetworkUtil::url(baseUrl, link.href());
+ shared_ptr<ZLMimeType> type = ZLMimeType::get(link.type());
+ const std::string &rel = networkLink.relation(link.rel(), link.type());
+ const BookReference::Type referenceType = typeByRelation(rel);
+ if (referenceType == BookReference::BUY) {
+ std::string price = BuyBookReference::price(
+ link.userData(OPDSXMLParser::KEY_PRICE),
+ link.userData(OPDSXMLParser::KEY_CURRENCY)
+ );
+ if (price.empty()) {
+ price = BuyBookReference::price(
+ entry.userData(OPDSXMLParser::KEY_PRICE),
+ entry.userData(OPDSXMLParser::KEY_CURRENCY)
+ );
+ }
+ if (type == ZLMimeType::TEXT_HTML) {
+ references.push_back(new BuyBookReference(
+ href, BookReference::NONE, BookReference::BUY_IN_BROWSER, price
+ ));
+ } else {
+ BookReference::Format format = formatByZLMimeType(link.userData(OPDSXMLParser::KEY_FORMAT));
+ if (format != BookReference::NONE) {
+ references.push_back(new BuyBookReference(
+ href, format, BookReference::BUY, price
+ ));
+ }
+ }
+ } else if (referenceType != BookReference::UNKNOWN) {
+ BookReference::Format format = formatByZLMimeType(link.type());
+ if (format != BookReference::NONE) {
+ references.push_back(new BookReference(href, format, referenceType));
+ }
+ }
+ }
+ return references;
+}
+
+BookReference::Format OPDSBookItem::formatByZLMimeType(const std::string &mimeType) {
+ shared_ptr<ZLMimeType> type = ZLMimeType::get(mimeType);
+ if (type == ZLMimeType::APPLICATION_FB2_ZIP) {
+ return BookReference::FB2_ZIP;
+ } else if (type == ZLMimeType::APPLICATION_EPUB_ZIP) {
+ return BookReference::EPUB;
+ } else if (type == ZLMimeType::APPLICATION_MOBIPOCKET_EBOOK) {
+ return BookReference::MOBIPOCKET;
+ }
+ return BookReference::NONE;
+}
+
+BookReference::Type OPDSBookItem::typeByRelation(const std::string &rel) {
+ if (rel == OPDSConstants::REL_ACQUISITION || rel == OPDSConstants::REL_ACQUISITION_OPEN || rel.empty()) {
+ return BookReference::DOWNLOAD_FULL;
+ } else if (rel == OPDSConstants::REL_ACQUISITION_SAMPLE) {
+ return BookReference::DOWNLOAD_DEMO;
+ } else if (rel == OPDSConstants::REL_ACQUISITION_CONDITIONAL) {
+ return BookReference::DOWNLOAD_FULL_CONDITIONAL;
+ } else if (rel == OPDSConstants::REL_ACQUISITION_SAMPLE_OR_FULL) {
+ return BookReference::DOWNLOAD_FULL_OR_DEMO;
+ } else if (rel == OPDSConstants::REL_ACQUISITION_BUY) {
+ return BookReference::BUY;
+ } else {
+ return BookReference::UNKNOWN;
+ }
+}
+
+OPDSBookItem::FullEntryReader::FullEntryReader(OPDSBookItem &item, const OPDSLink &link, std::string url) :
+ myItem(item), myLink(link), myUrl(url) {
+}
+
+void OPDSBookItem::FullEntryReader::processFeedEntry(shared_ptr<OPDSEntry> entry) {
+ NetworkItem::UrlInfoCollection urlMap = OPDSBookItem::getUrls(myLink, *entry, myUrl);
+ std::vector<shared_ptr<BookReference> > references = OPDSBookItem::getReferences(myLink, *entry, myUrl);
+ for (NetworkItem::UrlInfoCollection::iterator it = urlMap.begin(); it != urlMap.end(); ++it) {
+ myItem.URLByType[(*it).first] = (*it).second;
+ }
+ myItem.updateReferences(references);
+ std::string summary = OPDSBookItem::getAnnotation(*entry);
+ if (!summary.empty()) {
+ myItem.Summary = summary;
+ }
+ myItem.myRelatedInfos = OPDSBookItem::getRelatedUrls(myLink, *entry, myUrl);
+}
+
+void OPDSBookItem::FullEntryReader::processFeedStart() {
+}
+
+void OPDSBookItem::FullEntryReader::processFeedMetadata(shared_ptr<OPDSFeedMetadata> /*feed*/) {
+}
+
+void OPDSBookItem::FullEntryReader::processFeedEnd() {
+}
+
+OPDSBookItem::RelatedUrlInfo::RelatedUrlInfo(const std::string &title, shared_ptr<ZLMimeType> mimeType, const std::string url) :
+ Title(title), MimeType(mimeType), Url(url) { }
+
+
diff --git a/fbreader/src/network/opds/OPDSBookItem.h b/fbreader/src/network/opds/OPDSBookItem.h
new file mode 100644
index 0000000..8b3ddbd
--- /dev/null
+++ b/fbreader/src/network/opds/OPDSBookItem.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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.
+ */
+
+#ifndef __OPDSBOOKITEM_H__
+#define __OPDSBOOKITEM_H__
+
+#include "OPDSLink.h"
+#include "OPDSMetadata.h"
+#include "OPDSFeedReader.h"
+
+class OPDSBookItem : public NetworkBookItem {
+
+public:
+ OPDSBookItem(const OPDSLink &networkLink, OPDSEntry &entry, std::string baseUrl, unsigned int index);
+
+public:
+ bool isFullyLoaded() const;
+ void loadFullInformation(shared_ptr<ZLNetworkRequest::Listener> listener);
+ std::vector<shared_ptr<NetworkItem> > getRelatedCatalogsItems() const;
+
+public:
+ static BookReference::Format formatByZLMimeType(const std::string &mimeType);
+ static BookReference::Type typeByRelation(const std::string &rel);
+
+protected:
+ static std::string getAnnotation(OPDSEntry &entry);
+ static std::string getDate(OPDSEntry &entry);
+ static std::vector<AuthorData> getAuthors(OPDSEntry &entry);
+ static std::vector<std::string> getTags(OPDSEntry &entry);
+ static UrlInfoCollection getUrls(const OPDSLink &networkLink, OPDSEntry &entry, std::string baseUrl);
+ //TODO implement one UrlInfoCollection to not duplicate similar methods
+ static std::vector<shared_ptr<BookReference> > getReferences(const OPDSLink &networkLink, OPDSEntry &entry, std::string baseUrl);
+
+private:
+ class FullEntryReader : public OPDSFeedReader {
+
+ public:
+ FullEntryReader(OPDSBookItem &item, const OPDSLink &link, std::string url);
+
+ public:
+ void processFeedEntry(shared_ptr<OPDSEntry> entry);
+ void processFeedStart();
+ void processFeedMetadata(shared_ptr<OPDSFeedMetadata> feed);
+ void processFeedEnd();
+
+ private:
+ OPDSBookItem &myItem;
+ const OPDSLink &myLink;
+ std::string myUrl;
+ };
+
+ class RelatedUrlInfo {
+ public:
+ RelatedUrlInfo(const std::string& title, shared_ptr<ZLMimeType> mimeType, const std::string url);
+
+ std::string Title;
+ shared_ptr<ZLMimeType> MimeType;
+ std::string Url;
+ };
+
+ typedef std::vector<shared_ptr<RelatedUrlInfo> > RelatedUrlsList;
+ RelatedUrlsList myRelatedInfos;
+protected:
+ static RelatedUrlsList getRelatedUrls(const OPDSLink &networkLink, OPDSEntry &entry, std::string baseUrl);
+private:
+ bool myInformationIsFull;
+
+friend class OPDSBookItemFullInfoLoader;
+
+};
+
+#endif /* __OPDSBOOKITEM_H__ */
diff --git a/fbreader/src/network/opds/OPDSCatalogItem.cpp b/fbreader/src/network/opds/OPDSCatalogItem.cpp
new file mode 100644
index 0000000..853bc4c
--- /dev/null
+++ b/fbreader/src/network/opds/OPDSCatalogItem.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 <ZLNetworkRequest.h>
+#include <ZLNetworkManager.h>
+
+#include "OPDSCatalogItem.h"
+#include "OPDSLink.h"
+#include "OPDSXMLParser.h"
+#include "NetworkOPDSFeedReader.h"
+
+#include "../NetworkOperationData.h"
+
+OPDSCatalogItem::OPDSCatalogItem(
+ const OPDSLink &link,
+ const std::string &title,
+ const std::string &summary,
+ const UrlInfoCollection &urlByType,
+ AccessibilityType accessibility,
+ int flags
+ ) : NetworkCatalogItem(link, title, summary, urlByType, accessibility, flags), myLoadingState(Link) {
+}
+
+class OPDSCatalogItemRunnable : public ZLNetworkRequest::Listener {
+public:
+ OPDSCatalogItemRunnable(shared_ptr<ZLNetworkRequest> request, NetworkItem::List &children, NetworkOperationData &data, shared_ptr<ZLNetworkRequest::Listener> listener) :
+ myChildren(children), myLoadingData(data), myListener(listener) {
+ request->setListener(this);
+ ZLNetworkManager::Instance().performAsync(request);
+ }
+ void finished(const std::string &error) {
+ myChildren.insert(myChildren.end(), myLoadingData.Items.begin(), myLoadingData.Items.end());
+ myListener->finished(error);
+ }
+ void setUIStatus(bool enabled) {
+ myListener->setUIStatus(enabled); //to hide refreshing while authentication dialog
+ }
+
+private:
+ NetworkItem::List &myChildren;
+ NetworkOperationData &myLoadingData;
+ shared_ptr<ZLNetworkRequest::Listener> myListener;
+};
+
+
+std::string OPDSCatalogItem::loadChildren(NetworkItem::List &children, shared_ptr<ZLNetworkRequest::Listener> listener) {
+ myLoadingState.clear();
+ shared_ptr<ZLNetworkRequest> request = ((OPDSLink&)Link).createNetworkRequest(getCatalogUrl(), myLoadingState);
+ new OPDSCatalogItemRunnable(request, children, myLoadingState, listener);
+ return std::string();
+}
+
+bool OPDSCatalogItem::supportsResumeLoading() {
+ return true;
+}
+
+std::string OPDSCatalogItem::resumeLoading(NetworkItem::List &children, shared_ptr<ZLNetworkRequest::Listener> listener) {
+ shared_ptr<ZLNetworkRequest> request = myLoadingState.resume();
+ if (request.isNull()) {
+ listener->finished();
+ return std::string();
+ }
+ new OPDSCatalogItemRunnable(request, children, myLoadingState, listener);
+ return std::string();
+}
diff --git a/fbreader/src/network/opds/OPDSCatalogItem.h b/fbreader/src/network/opds/OPDSCatalogItem.h
new file mode 100644
index 0000000..e2bc787
--- /dev/null
+++ b/fbreader/src/network/opds/OPDSCatalogItem.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __OPDSCATALOGITEM_H__
+#define __OPDSCATALOGITEM_H__
+
+#include <ZLExecutionUtil.h>
+
+#include "../NetworkItems.h"
+#include "../NetworkOperationData.h"
+
+class OPDSLink;
+
+class OPDSCatalogItem : public NetworkCatalogItem {
+
+public:
+ OPDSCatalogItem(
+ const OPDSLink &link,
+ const std::string &title,
+ const std::string &summary,
+ const UrlInfoCollection &urlByType,
+ AccessibilityType accessibility = ALWAYS,
+ int flags = FLAGS_DEFAULT
+ );
+
+public:
+ std::string loadChildren(NetworkItem::List &children, shared_ptr<ZLNetworkRequest::Listener> listener = 0);
+ bool supportsResumeLoading();
+ std::string resumeLoading(List &children, shared_ptr<ZLNetworkRequest::Listener> listener = 0);
+
+private:
+ NetworkOperationData myLoadingState;
+};
+
+#endif /* __OPDSCATALOGITEM_H__ */
diff --git a/fbreader/src/network/opds/OPDSFeedReader.h b/fbreader/src/network/opds/OPDSFeedReader.h
new file mode 100644
index 0000000..a842f41
--- /dev/null
+++ b/fbreader/src/network/opds/OPDSFeedReader.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __OPDSFEEDREADER_H__
+#define __OPDSFEEDREADER_H__
+
+#include "OPDSMetadata.h"
+
+
+class OPDSFeedReader {
+
+public:
+ OPDSFeedReader() {}
+ virtual ~OPDSFeedReader() {}
+
+public:
+ virtual void processFeedEntry(shared_ptr<OPDSEntry> entry) = 0;
+ virtual void processFeedStart() = 0;
+ virtual void processFeedMetadata(shared_ptr<OPDSFeedMetadata> feed) = 0;
+ virtual void processFeedEnd() = 0;
+};
+
+
+#endif /* __OPDSFEEDREADER_H__ */
diff --git a/fbreader/src/network/opds/OPDSLink.cpp b/fbreader/src/network/opds/OPDSLink.cpp
new file mode 100644
index 0000000..f682b7d
--- /dev/null
+++ b/fbreader/src/network/opds/OPDSLink.cpp
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 <algorithm>
+
+#include <ZLStringUtil.h>
+#include <ZLUnicodeUtil.h>
+#include <ZLNetworkUtil.h>
+#include <ZLNetworkManager.h>
+
+#include "OPDSLink.h"
+#include "OPDSLink_AdvancedSearch.h"
+#include "OPDSCatalogItem.h"
+#include "OPDSXMLParser.h"
+#include "NetworkOPDSFeedReader.h"
+
+#include "../NetworkOperationData.h"
+#include "../authentication/NetworkAuthenticationManager.h"
+#include "../authentication/litres/LitResAuthenticationManager.h"
+
+#include "URLRewritingRule.h"
+
+OPDSLink::AdvancedSearch::AdvancedSearch(
+ const std::string &type,
+ const std::string &titleParameter,
+ const std::string &authorParameter,
+ const std::string &tagParameter,
+ const std::string &annotationParameter
+) : myType(type), myTitleParameter(titleParameter), myAuthorParameter(authorParameter), myTagParameter(tagParameter), myAnnotationParameter(annotationParameter) {
+}
+
+void OPDSLink::AdvancedSearch::addSubQuery(std::string &query, const std::string &name, const std::string &value) const {
+ if (value.empty()) {
+ return;
+ }
+
+ if (myType == "separateWords") {
+ std::size_t start = 0, end;
+ do {
+ end = value.find(' ', start);
+ std::string ss = value.substr(start, end - start);
+ ZLUnicodeUtil::utf8Trim(ss);
+ if (!ss.empty()) {
+ if (!query.empty()) {
+ query.append("+");
+ }
+ query.append(name + ':');
+ query.append(ZLNetworkUtil::htmlEncode(ss));
+ }
+ start = end + 1;
+ } while (end != std::string::npos);
+ } else if (myType == "quoted") {
+ std::string encodedValue = value;
+ ZLUnicodeUtil::utf8Trim(encodedValue);
+
+ if (encodedValue.empty()) {
+ return;
+ }
+ encodedValue = '"' + encodedValue + '"';
+ std::replace(encodedValue.begin(), encodedValue.end(), ' ', '+');
+
+ if (!query.empty()) {
+ query += '+';
+ }
+ query += name + ':' + ZLNetworkUtil::htmlEncode(encodedValue);
+ }
+}
+
+std::string OPDSLink::AdvancedSearch::query(
+ const std::string &titleOrSeries,
+ const std::string &author,
+ const std::string &tag,
+ const std::string &annotation
+) const {
+ std::string query;
+ addSubQuery(query, myTitleParameter, titleOrSeries);
+ addSubQuery(query, myAuthorParameter, author);
+ addSubQuery(query, myTagParameter, tag);
+ addSubQuery(query, myAnnotationParameter, annotation);
+ return query;
+}
+
+//shared_ptr<NetworkLink> OPDSLink::read(const ZLFile &file) {
+// Reader reader;
+// reader.readDocument(file);
+// return reader.link();
+//}
+
+shared_ptr<ZLNetworkRequest> OPDSLink::createNetworkRequest(const std::string &url, NetworkOperationData &result) const {
+ if (url.empty()) {
+ return 0;
+ }
+ std::string modifiedUrl(url);
+ rewriteUrl(modifiedUrl);
+ return ZLNetworkManager::Instance().createXMLParserRequest(modifiedUrl, new OPDSXMLParser(new NetworkOPDSFeedReader(*this, url, result)) );
+}
+
+OPDSLink::OPDSLink(
+ const std::string &siteName
+) : NetworkLink(siteName) {
+}
+
+OPDSLink::~OPDSLink() {
+}
+
+shared_ptr<NetworkItem> OPDSLink::libraryItem() const {
+ NetworkItem::UrlInfoCollection urlMap;
+ urlMap[NetworkItem::URL_COVER] = getIcon();
+ urlMap[NetworkItem::URL_CATALOG] = url(URL_MAIN);
+ return new OPDSCatalogItem(*this, getTitle(), getSummary(), urlMap);
+}
+
+const std::string OPDSLink::searchURL(const std::string &query) const {
+ return ZLStringUtil::printf(url(URL_SEARCH), query);
+}
+
+shared_ptr<ZLNetworkRequest> OPDSLink::simpleSearchData(NetworkOperationData &result, const std::string &pattern) const {
+ return createNetworkRequest(
+ searchURL(ZLNetworkUtil::htmlEncode(pattern)),
+ result
+ );
+}
+
+shared_ptr<ZLNetworkRequest> OPDSLink::advancedSearchData(
+ NetworkOperationData &result,
+ const std::string &titleAndSeries,
+ const std::string &author,
+ const std::string &tag,
+ const std::string &annotation
+) const {
+ if (myAdvancedSearch.isNull()) {
+ return 0;
+ }
+ std::string query = myAdvancedSearch->query(
+ titleAndSeries, author, tag, annotation
+ );
+ return query.empty() ? 0 : createNetworkRequest(searchURL(query), result);
+}
+
+shared_ptr<ZLNetworkRequest> OPDSLink::resume(NetworkOperationData &data) const {
+ const std::string url = data.ResumeURI;
+ return createNetworkRequest(url, data);
+}
+
+shared_ptr<NetworkAuthenticationManager> OPDSLink::authenticationManager() const {
+ return myAuthenticationManager;
+}
+
+void OPDSLink::setUrlRewritingRules(std::vector<shared_ptr<URLRewritingRule> > rules) {
+ myUrlRewritingRules = rules;
+}
+
+void OPDSLink::setAuthenticationManager(shared_ptr<NetworkAuthenticationManager> manager) {
+ myAuthenticationManager = manager;
+}
+
+void OPDSLink::setAdvancedSearch(shared_ptr<OPDSLink::AdvancedSearch> advancedSearch) {
+ myAdvancedSearch = advancedSearch;
+}
+
+void OPDSLink::setRelationAliases(std::map<RelationAlias, std::string> relationAliases) {
+ myRelationAliases = relationAliases;
+}
+
+void OPDSLink::rewriteUrl(std::string &url, bool isUrlExternal) const {
+ URLRewritingRule::RuleApply apply = isUrlExternal ? URLRewritingRule::EXTERNAL : URLRewritingRule::INTERNAL;
+ for (std::vector<shared_ptr<URLRewritingRule> >::const_iterator it = myUrlRewritingRules.begin(); it != myUrlRewritingRules.end(); ++it) {
+ const URLRewritingRule &rule = **it;
+ if (rule.whereToApply() == apply) {
+ url = rule.apply(url);
+ }
+ }
+}
+
+OPDSLink::RelationAlias::RelationAlias(const std::string &alias, const std::string &type) : Alias(alias), Type(type) {
+}
+
+bool OPDSLink::RelationAlias::operator < (const RelationAlias &alias) const {
+ int cmp = Alias.compare(alias.Alias);
+ if (cmp != 0) {
+ return cmp < 0;
+ }
+ return Type < alias.Type;
+}
+
+const std::string &OPDSLink::relation(const std::string &rel, const std::string &type) const {
+ RelationAlias alias(rel, type);
+ std::map<RelationAlias,std::string>::const_iterator it = myRelationAliases.find(alias);
+ if (it != myRelationAliases.end()) {
+ return it->second;
+ }
+ if (!type.empty()) {
+ alias.Type.erase();
+ it = myRelationAliases.find(alias);
+ if (it != myRelationAliases.end()) {
+ return it->second;
+ }
+ }
+ return rel;
+}
diff --git a/fbreader/src/network/opds/OPDSLink.h b/fbreader/src/network/opds/OPDSLink.h
new file mode 100644
index 0000000..d6fd87e
--- /dev/null
+++ b/fbreader/src/network/opds/OPDSLink.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __OPDSLINK_H__
+#define __OPDSLINK_H__
+
+#include <map>
+#include <vector>
+#include <string>
+
+#include "../NetworkLink.h"
+
+class ZLFile;
+
+class NetworkAuthenticationManager;
+struct URLRewritingRule;
+
+class OPDSLink : public NetworkLink {
+
+public:
+ enum FeedCondition {
+ CONDITION_NEVER,
+ CONDITION_SIGNED_IN,
+ };
+
+private:
+ class AdvancedSearch;
+
+public:
+ class GenericReader;
+ class FeedReader;
+ class GenericFeedReader;
+ class GenericXMLParser;
+
+ OPDSLink(
+ const std::string &siteName
+ );
+
+public:
+ ~OPDSLink();
+
+private:
+ struct RelationAlias;
+
+public:
+ void setUrlRewritingRules(std::vector<shared_ptr<URLRewritingRule> > rules);
+ void setAuthenticationManager(shared_ptr<NetworkAuthenticationManager> manager);
+ void setAdvancedSearch(shared_ptr<OPDSLink::AdvancedSearch> advancedSearch);
+ void setRelationAliases(std::map<RelationAlias, std::string> relationAliases);
+
+private:
+ const std::string searchURL(const std::string &pattern) const;
+
+ shared_ptr<ZLNetworkRequest> createNetworkRequest(const std::string &url, NetworkOperationData &result) const;
+
+ shared_ptr<ZLNetworkRequest> simpleSearchData(
+ NetworkOperationData &result,
+ const std::string &pattern) const;
+ shared_ptr<ZLNetworkRequest> advancedSearchData(
+ NetworkOperationData &result,
+ const std::string &titleAndSeries,
+ const std::string &author,
+ const std::string &tag,
+ const std::string &annotation) const;
+ shared_ptr<ZLNetworkRequest> resume(NetworkOperationData &result) const;
+
+ shared_ptr<NetworkItem> libraryItem() const;
+ shared_ptr<NetworkAuthenticationManager> authenticationManager() const;
+
+ void rewriteUrl(std::string &url, bool isUrlExternal = false) const;
+
+ const std::string &relation(const std::string &rel, const std::string &type) const;
+
+private:
+ shared_ptr<AdvancedSearch> myAdvancedSearch;
+
+ struct RelationAlias {
+ std::string Alias;
+ std::string Type;
+
+ RelationAlias(const std::string &alias, const std::string &type);
+ bool operator < (const RelationAlias &other) const;
+ };
+ std::map<RelationAlias, std::string> myRelationAliases;
+
+ std::map<std::string,FeedCondition> myFeedConditions;
+ std::vector<shared_ptr<URLRewritingRule> > myUrlRewritingRules;
+
+ shared_ptr<NetworkAuthenticationManager> myAuthenticationManager;
+
+friend class NetworkOPDSFeedReader;
+friend class OPDSCatalogItem;
+friend class OPDSBookItem;
+};
+
+#endif /* __OPDSLINK_H__ */
diff --git a/fbreader/src/network/opds/OPDSLink_AdvancedSearch.h b/fbreader/src/network/opds/OPDSLink_AdvancedSearch.h
new file mode 100644
index 0000000..76519c9
--- /dev/null
+++ b/fbreader/src/network/opds/OPDSLink_AdvancedSearch.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __OPDSLINK_ADVANCEDSEARCH_H__
+#define __OPDSLINK_ADVANCEDSEARCH_H__
+
+#include <string>
+/*
+#include <algorithm>
+
+#include <ZLStringUtil.h>
+#include <ZLNetworkUtil.h>
+#include <ZLNetworkManager.h>
+
+#include "OPDSLink.h"
+#include "OPDSLinkReader.h"
+#include "OPDSCatalogItem.h"
+#include "OPDSXMLParser.h"
+#include "NetworkOPDSFeedReader.h"
+
+#include "../NetworkOperationData.h"
+#include "../authentication/NetworkAuthenticationManager.h"
+
+#include "URLRewritingRule.h"
+*/
+
+class OPDSLink::AdvancedSearch {
+
+public:
+ AdvancedSearch(
+ const std::string &type,
+ const std::string &titleParameter,
+ const std::string &authorParameter,
+ const std::string &tagParameter,
+ const std::string &annotationParameter
+ );
+
+ std::string query(
+ const std::string &titleOrSeries,
+ const std::string &author,
+ const std::string &tag,
+ const std::string &annotation
+ ) const;
+
+private:
+ void addSubQuery(std::string &query, const std::string &name, const std::string &value) const;
+
+private:
+ const std::string myType;
+ const std::string myTitleParameter;
+ const std::string myAuthorParameter;
+ const std::string myTagParameter;
+ const std::string myAnnotationParameter;
+};
+
+#endif /* __OPDSLINK_ADVANCEDSEARCH_H__ */
diff --git a/fbreader/src/network/opds/OPDSLink_GenericFeedReader.cpp b/fbreader/src/network/opds/OPDSLink_GenericFeedReader.cpp
new file mode 100644
index 0000000..5389f2d
--- /dev/null
+++ b/fbreader/src/network/opds/OPDSLink_GenericFeedReader.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2008-2012 Geometer Plus <[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 <ZLNetworkUtil.h>
+#include <ZLStringUtil.h>
+#include <ZLMimeType.h>
+#include <ZLNetworkRequest.h>
+#include <ZLNetworkManager.h>
+
+#include "../authentication/litres/LitResAuthenticationManager.h"
+
+#include "OPDSLink_GenericFeedReader.h"
+#include "OpenSearchXMLReader.h"
+
+OPDSLink::GenericFeedReader::GenericFeedReader(
+ std::vector<shared_ptr<NetworkLink> >& links
+) :
+ myLinks(links) {
+}
+
+void OPDSLink::GenericFeedReader::processFeedStart() {
+}
+
+void OPDSLink::GenericFeedReader::processFeedMetadata(shared_ptr<OPDSFeedMetadata>) {
+
+}
+
+
+void OPDSLink::GenericFeedReader::processFeedEnd() {
+}
+
+void OPDSLink::GenericFeedReader::processFeedEntry(shared_ptr<OPDSEntry> entry) {
+ std::map<std::string,std::string> links;
+ std::string iconURL;
+ for (std::size_t i = 0; i < entry->links().size(); ++i) {
+ ATOMLink &link = *(entry->links()[i]);
+ const std::string &href = link.href();
+ const std::string &rel = link.rel();
+ shared_ptr<ZLMimeType> type = ZLMimeType::get(link.type());
+ if (rel == NetworkLink::URL_SEARCH) {
+ links[rel] = OpenSearchXMLReader::convertOpenSearchURL(href);
+ } else if (rel == "") {
+ links[NetworkLink::URL_MAIN] = href;
+ } else if (rel == OPDSConstants::REL_LINK_SIGN_IN) {
+ links[NetworkLink::URL_SIGN_IN] = href;
+ } else if (rel == OPDSConstants::REL_LINK_SIGN_OUT) {
+ links[NetworkLink::URL_SIGN_OUT] = href;
+ } else if (rel == OPDSConstants::REL_LINK_SIGN_UP) {
+ links[NetworkLink::URL_SIGN_UP] = href;
+ } else if (rel == OPDSConstants::REL_LINK_TOPUP) {
+ links[NetworkLink::URL_TOPUP] = href;
+ } else if (rel == OPDSConstants::REL_LINK_RECOVER_PASSWORD) {
+ links[NetworkLink::URL_RECOVER_PASSWORD] = href;
+ } else if (rel == OPDSConstants::REL_THUMBNAIL || rel == OPDSConstants::REL_IMAGE_THUMBNAIL) {
+ if (ZLMimeType::isImage(type)) {
+ iconURL = href;
+ }
+ } else if (iconURL.empty() && (rel == OPDSConstants::REL_COVER || ZLStringUtil::stringStartsWith(rel, OPDSConstants::REL_IMAGE_PREFIX))) {
+ if (ZLMimeType::isImage(type)) {
+ iconURL = href;
+ }
+ } else {
+ links[rel] = href;
+ }
+ }
+ if (entry->title().empty() || links[NetworkLink::URL_MAIN].empty()) {
+ return;
+ }
+ if (entry->id() == 0) {
+ return;
+ }
+ std::string id = entry->id()->uri();
+ std::string summary = entry->summary();
+ std::string language = entry->dcLanguage();
+
+ shared_ptr<NetworkLink> link = new OPDSLink(id.substr(25)); //why just 25 symbols?
+ link->setTitle(entry->title());
+ link->setSummary(summary);
+ link->setLanguage(language);
+ link->setIcon(iconURL);
+ link->setLinks(links);
+ link->setPredefinedId(id);
+ link->setUpdated(entry->updated());
+
+ OPDSLink &opdsLink = static_cast<OPDSLink&>(*link);
+ opdsLink.setUrlRewritingRules(myUrlRewritingRules);
+ if (!myAdvancedSearch.isNull()) {
+ opdsLink.setAdvancedSearch(myAdvancedSearch);
+ }
+ opdsLink.setRelationAliases(myRelationAliases);
+ if (myAuthenticationType == "litres") {
+ opdsLink.setAuthenticationManager(new LitResAuthenticationManager(*link));
+ }
+ myLinks.push_back(link);
+}
+
+void OPDSLink::GenericFeedReader::clear() {
+ myAuthenticationType.clear();
+ myUrlRewritingRules.clear();
+ myAdvancedSearch.reset();
+ myRelationAliases.clear();
+}
+
+void OPDSLink::GenericFeedReader::setAdvancedSearch(shared_ptr<OPDSLink::AdvancedSearch> advancedSearch) {
+ myAdvancedSearch = advancedSearch;
+}
+
+void OPDSLink::GenericFeedReader::setAuthenticationType(std::string type) {
+ myAuthenticationType = type;
+}
+
+void OPDSLink::GenericFeedReader::addUrlRewritingRule(shared_ptr<URLRewritingRule> rewritingRule) {
+ myUrlRewritingRules.push_back(rewritingRule);
+}
+
+void OPDSLink::GenericFeedReader::addRelationAlias(const OPDSLink::RelationAlias& alias, std::string name) {
+ myRelationAliases[alias] = name;
+}
diff --git a/fbreader/src/network/opds/OPDSLink_GenericFeedReader.h b/fbreader/src/network/opds/OPDSLink_GenericFeedReader.h
new file mode 100644
index 0000000..15ffe38
--- /dev/null
+++ b/fbreader/src/network/opds/OPDSLink_GenericFeedReader.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2008-2012 Geometer Plus <[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.
+ */
+
+#ifndef __OPDSLINK_GENERICFEEDREADER_H__
+#define __OPDSLINK_GENERICFEEDREADER_H__
+
+#include <map>
+#include <string>
+
+#include "URLRewritingRule.h"
+#include "OPDSFeedReader.h"
+#include "OPDSLink.h"
+#include "OPDSLink_AdvancedSearch.h"
+
+class OPDSLink::GenericFeedReader : public OPDSFeedReader {
+
+public:
+ GenericFeedReader(
+ std::vector<shared_ptr<NetworkLink> >& links
+ );
+
+public:
+ void processFeedEntry(shared_ptr<OPDSEntry> entry);
+ void processFeedStart();
+ void processFeedMetadata(shared_ptr<OPDSFeedMetadata> feed);
+ void processFeedEnd();
+
+public:
+ void clear();
+ void setAdvancedSearch(shared_ptr<OPDSLink::AdvancedSearch> advancedSearch);
+ void setAuthenticationType(std::string type);
+ void addUrlRewritingRule(shared_ptr<URLRewritingRule> rewritingRule);
+ void addRelationAlias(const OPDSLink::RelationAlias&, std::string name);
+
+private:
+ std::vector<shared_ptr<NetworkLink> >& myLinks;
+
+private:
+ std::string myAuthenticationType;
+ std::vector<shared_ptr<URLRewritingRule> > myUrlRewritingRules;
+ shared_ptr<OPDSLink::AdvancedSearch> myAdvancedSearch;
+ std::map<OPDSLink::RelationAlias,std::string> myRelationAliases;
+};
+
+#endif /* __OPDSLINK_GENERICFEEDREADER_H__ */
diff --git a/fbreader/src/network/opds/OPDSLink_GenericXMLParser.cpp b/fbreader/src/network/opds/OPDSLink_GenericXMLParser.cpp
new file mode 100644
index 0000000..ef67116
--- /dev/null
+++ b/fbreader/src/network/opds/OPDSLink_GenericXMLParser.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2008-2012 Geometer Plus <[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 <ZLXMLNamespace.h>
+
+#include "OPDSLink_GenericXMLParser.h"
+#include "URLRewritingRule.h"
+#include "OPDSLink_AdvancedSearch.h"
+
+static const std::string TAG_ENTRY = "entry";
+static const std::string FBREADER_ADVANCED_SEARCH = "advancedSearch";
+static const std::string FBREADER_AUTHENTICATION = "authentication";
+static const std::string FBREADER_REWRITING_RULE = "urlRewritingRule";
+static const std::string FBREADER_RELATION_ALIAS = "relationAlias";
+static const std::string FBREADER_EXTRA = "extra";
+
+OPDSLink::GenericXMLParser::GenericXMLParser(shared_ptr<OPDSFeedReader> feedReader) :
+ OPDSXMLParser(feedReader) {
+}
+
+OPDSLink::GenericFeedReader &OPDSLink::GenericXMLParser::getFeedReader() const {
+ return static_cast<OPDSLink::GenericFeedReader&>(*myFeedReader);
+}
+
+void OPDSLink::GenericXMLParser::startElementHandler(const char *tag, const char **attributes) {
+ switch (myState) {
+ case FEED:
+ if (testTag(ZLXMLNamespace::Atom, TAG_ENTRY, tag)) {
+ getFeedReader().clear();
+ }
+ break;
+ case F_ENTRY:
+ if (testTag(ZLXMLNamespace::FBReaderCatalogMetadata, FBREADER_ADVANCED_SEARCH, tag)) {
+ const char *style = attributeValue(attributes, "style");
+ const char *author = attributeValue(attributes, "author");
+ const char *titleOrSeries = attributeValue(attributes, "titleOrSeries");
+ const char *tag = attributeValue(attributes, "tag");
+ const char *annotation = attributeValue(attributes, "annotation");
+ if (style != 0 && author != 0 && titleOrSeries != 0 && tag != 0 && annotation != 0) {
+ getFeedReader().setAdvancedSearch(new OPDSLink::AdvancedSearch(style, titleOrSeries, author, tag, annotation));
+ }
+ return;
+ } else if (testTag(ZLXMLNamespace::FBReaderCatalogMetadata, FBREADER_AUTHENTICATION, tag)) {
+ const char *type = attributeValue(attributes, "type");
+ if (type != 0) {
+ getFeedReader().setAuthenticationType(type);
+ }
+ return;
+ } else if (testTag(ZLXMLNamespace::FBReaderCatalogMetadata, FBREADER_RELATION_ALIAS, tag)) {
+ const char *name = attributeValue(attributes, "name");
+ const char *type = attributeValue(attributes, "type");
+ const char *alias = attributeValue(attributes, "alias");
+ if (name != 0 && alias != 0) {
+ getFeedReader().addRelationAlias(OPDSLink::RelationAlias(alias, (type != 0) ? type : std::string()), name);
+ }
+ } else if (testTag(ZLXMLNamespace::FBReaderCatalogMetadata, FBREADER_REWRITING_RULE, tag)) {
+
+ getFeedReader().addUrlRewritingRule(new URLRewritingRule(getAttributesMap(attributes)));
+
+// const char *type = attributeValue(attributes, "type");
+// const char *apply = attributeValue(attributes, "apply");
+// const char *name = attributeValue(attributes, "name");
+// const char *value = attributeValue(attributes, "value");
+
+// //TODO add rewrite type of 'rewriting rules'
+// URLRewritingRule::RuleApply ruleApply = URLRewritingRule::ALWAYS;
+// if (apply != 0) {
+// const std::string applyStr = apply;
+// if (applyStr == "external") {
+// ruleApply = URLRewritingRule::EXTERNAL;
+// } else if (applyStr == "internal") {
+// ruleApply = URLRewritingRule::INTERNAL;
+// } else if (applyStr != "always") {
+// type = 0;
+// }
+// }
+
+// if (type != 0 && name != 0 && value != 0) {
+// std::string typeStr = type;
+// if (typeStr == "addUrlParameter") {
+// getFeedReader().addUrlRewritingRule(new URLRewritingRule(URLRewritingRule::ADD_URL_PARAMETER, ruleApply, name, value));
+// }
+// }
+
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ OPDSXMLParser::startElementHandler(tag, attributes);
+}
+
diff --git a/fbreader/src/network/opds/OPDSLink_GenericXMLParser.h b/fbreader/src/network/opds/OPDSLink_GenericXMLParser.h
new file mode 100644
index 0000000..9bdf9d6
--- /dev/null
+++ b/fbreader/src/network/opds/OPDSLink_GenericXMLParser.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2008-2012 Geometer Plus <[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.
+ */
+
+#ifndef __OPDSLINK_GENERICXMLPARSER_H__
+#define __OPDSLINK_GENERICXMLPARSER_H__
+
+#include "OPDSXMLParser.h"
+#include "OPDSLink_GenericFeedReader.h"
+
+class OPDSLink::GenericXMLParser : public OPDSXMLParser {
+public:
+ GenericXMLParser(shared_ptr<OPDSFeedReader> feedReader);
+
+protected:
+ void startElementHandler(const char *tag, const char **attributes);
+ OPDSLink::GenericFeedReader &getFeedReader() const;
+};
+
+#endif /* __OPDSLINK_GENERICXMLPARSER_H__ */
diff --git a/fbreader/src/network/opds/OPDSMetadata.cpp b/fbreader/src/network/opds/OPDSMetadata.cpp
new file mode 100644
index 0000000..6595e05
--- /dev/null
+++ b/fbreader/src/network/opds/OPDSMetadata.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 "OPDSMetadata.h"
+
+// Feed level
+const std::string OPDSConstants::REL_BOOKSHELF = "http://data.fbreader.org/rel/bookshelf";
+const std::string OPDSConstants::REL_RECOMMENDATIONS = "http://data.fbreader.org/rel/recommendations";
+
+//const std::string OPDSConstants::REL_SUBSCRIPTIONS = "http://opds-spec.org/subscriptions";
+
+const std::string OPDSConstants::REL_CATALOG_AUTHOR = "http://data.fbreader.org/catalog/author";
+const std::string OPDSConstants::REL_ACQUISITION = "http://opds-spec.org/acquisition";
+const std::string OPDSConstants::REL_ACQUISITION_OPEN = "http://opds-spec.org/acquisition/open-access";
+const std::string OPDSConstants::REL_ACQUISITION_BUY = "http://opds-spec.org/acquisition/buy";
+//const std::string OPDSConstants::REL_ACQUISITION_BORROW = "http://opds-spec.org/acquisition/borrow";
+//const std::string OPDSConstants::REL_ACQUISITION_SUBSCRIBE = "http://opds-spec.org/acquisition/subscribe";
+const std::string OPDSConstants::REL_ACQUISITION_SAMPLE = "http://opds-spec.org/acquisition/sample";
+const std::string OPDSConstants::REL_ACQUISITION_CONDITIONAL = "http://data.fbreader.org/acquisition/conditional";
+const std::string OPDSConstants::REL_ACQUISITION_SAMPLE_OR_FULL = "http://data.fbreader.org/acquisition/sampleOrFull";
+
+// Entry level / other
+const std::string OPDSConstants::REL_IMAGE_PREFIX = "http://opds-spec.org/image";
+//const std::string OPDSConstants::REL_IMAGE = "http://opds-spec.org/image";
+const std::string OPDSConstants::REL_IMAGE_THUMBNAIL = "http://opds-spec.org/image/thumbnail";
+// FIXME: This relations have been removed from OPDS-1.0 standard. Use RelationAlias instead???
+const std::string OPDSConstants::REL_COVER = "http://opds-spec.org/cover";
+const std::string OPDSConstants::REL_THUMBNAIL = "http://opds-spec.org/thumbnail";
+
+// Entry level / OPDS Link Relations
+const std::string OPDSConstants::REL_LINK_SIGN_IN = "http://data.fbreader.org/catalog/sign-in";
+const std::string OPDSConstants::REL_LINK_SIGN_OUT = "http://data.fbreader.org/catalog/sign-out";
+const std::string OPDSConstants::REL_LINK_SIGN_UP = "http://data.fbreader.org/catalog/sign-up";
+const std::string OPDSConstants::REL_LINK_TOPUP = "http://data.fbreader.org/catalog/refill-account";
+const std::string OPDSConstants::REL_LINK_RECOVER_PASSWORD = "http://data.fbreader.org/catalog/recover-password";
+
+DCDate::DCDate() :
+ ATOMDateConstruct(0) {
+}
+
+DCDate::DCDate(int year) :
+ ATOMDateConstruct(year) {
+}
+
+DCDate::DCDate(int year, int month, int day) :
+ ATOMDateConstruct(year, month, day) {
+}
+
+DCDate::DCDate(int year, int month, int day, int hour, int minutes, int seconds) :
+ ATOMDateConstruct(year, month, day, hour, minutes, seconds) {
+}
+
+DCDate::DCDate(int year, int month, int day, int hour, int minutes, int seconds, float sfract) :
+ ATOMDateConstruct(year, month, day, hour, minutes, seconds, sfract) {
+}
+
+DCDate::DCDate(int year, int month, int day, int hour, int minutes, int seconds, float sfract, int tzhour, int tzminutes) :
+ ATOMDateConstruct(year, month, day, hour, minutes, seconds, sfract, tzhour, tzminutes) {
+}
+
+OPDSEntry::OPDSEntry() {
+}
+
+OPDSEntry::OPDSEntry(shared_ptr<ATOMId> id, const std::string &title, shared_ptr<ATOMUpdated> updated) :
+ ATOMEntry(id, title, updated) {
+}
+
+OPDSFeedMetadata::OPDSFeedMetadata() : myOpensearchTotalResults(0), myOpensearchItemsPerPage(0), myOpensearchStartIndex(1) {
+}
+
+OPDSFeedMetadata::OPDSFeedMetadata(shared_ptr<ATOMId> id, const std::string &title, shared_ptr<ATOMUpdated> updated) :
+ ATOMFeedMetadata(id, title, updated), myOpensearchTotalResults(0), myOpensearchItemsPerPage(0), myOpensearchStartIndex(1) {
+}
diff --git a/fbreader/src/network/opds/OPDSMetadata.h b/fbreader/src/network/opds/OPDSMetadata.h
new file mode 100644
index 0000000..51554dd
--- /dev/null
+++ b/fbreader/src/network/opds/OPDSMetadata.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __OPDSMETADATA_H__
+#define __OPDSMETADATA_H__
+
+#include <map>
+
+#include "../atom/ATOMContainers.h"
+
+
+class OPDSConstants {
+
+private:
+ OPDSConstants();
+
+public:
+
+ //TODO get other relations from FBReaderJ
+
+ // Feed level
+ static const std::string REL_BOOKSHELF;
+ static const std::string REL_RECOMMENDATIONS;
+
+ //static const std::string REL_SUBSCRIPTIONS;
+
+ // Entry level / catalog types
+ static const std::string REL_CATALOG_AUTHOR;
+
+ // Entry level / acquisition links
+ static const std::string REL_ACQUISITION;
+ static const std::string REL_ACQUISITION_OPEN;
+ static const std::string REL_ACQUISITION_BUY;
+// static const std::string REL_ACQUISITION_BORROW;
+// static const std::string REL_ACQUISITION_SUBSCRIBE;
+ static const std::string REL_ACQUISITION_SAMPLE;
+ static const std::string REL_ACQUISITION_CONDITIONAL;
+ static const std::string REL_ACQUISITION_SAMPLE_OR_FULL;
+
+ // Entry level / other
+ static const std::string REL_IMAGE_PREFIX;
+ //static const std::string REL_IMAGE;
+ static const std::string REL_IMAGE_THUMBNAIL;
+ static const std::string REL_COVER;
+ static const std::string REL_THUMBNAIL;
+
+ // Entry level / OPDS Link Relations
+ static const std::string REL_LINK_SIGN_IN;
+ static const std::string REL_LINK_SIGN_OUT;
+ static const std::string REL_LINK_SIGN_UP;
+ static const std::string REL_LINK_TOPUP;
+ static const std::string REL_LINK_RECOVER_PASSWORD;
+};
+
+
+class DCDate : public ATOMDateConstruct {
+
+public:
+ DCDate();
+ DCDate(int year);
+ DCDate(int year, int month, int day);
+ DCDate(int year, int month, int day, int hour, int minutes, int seconds);
+ DCDate(int year, int month, int day, int hour, int minutes, int seconds, float sfract);
+ DCDate(int year, int month, int day, int hour, int minutes, int seconds, float sfract, int tzhour, int tzminutes);
+};
+
+class OPDSEntry : public ATOMEntry {
+
+public:
+ OPDSEntry();
+ OPDSEntry(shared_ptr<ATOMId> id, const std::string &title, shared_ptr<ATOMUpdated> updated);
+
+ const std::string &dcLanguage() const { return myDCLanguage; }
+ const std::string &dcPublisher() const { return myDCPublisher; }
+ shared_ptr<DCDate> dcIssued() { return myDCIssued; }
+ const std::string &seriesTitle() const { return mySeriesTitle; }
+ int seriesIndex() const { return mySeriesIndex; }
+
+ void setDCLanguage(const std::string &language) { myDCLanguage = language; }
+ void setDCPublisher(const std::string &publisher) { myDCPublisher = publisher; }
+ void setDCIssued(shared_ptr<DCDate> issued) { myDCIssued = issued; }
+ void setSeriesTitle(const std::string &seriesTitle) { mySeriesTitle = seriesTitle; }
+ void setSeriesIndex(int seriesIndex) { mySeriesIndex = seriesIndex; }
+
+private:
+ std::string myDCLanguage;
+ std::string myDCPublisher;
+ shared_ptr<DCDate> myDCIssued;
+
+ std::string mySeriesTitle;
+ int mySeriesIndex;
+};
+
+
+
+class OPDSFeedMetadata : public ATOMFeedMetadata {
+
+public:
+ OPDSFeedMetadata();
+ OPDSFeedMetadata(shared_ptr<ATOMId> id, const std::string &title, shared_ptr<ATOMUpdated> updated);
+
+ unsigned long getOpensearchTotalResults() const;
+ unsigned long getOpensearchItemsPerPage() const;
+ unsigned long getOpensearchStartIndex() const;
+
+ void setOpensearchTotalResults(unsigned long number);
+ void setOpensearchItemsPerPage(unsigned long number);
+ void setOpensearchStartIndex(unsigned long number);
+
+private:
+ unsigned long myOpensearchTotalResults;
+ unsigned long myOpensearchItemsPerPage;
+ unsigned long myOpensearchStartIndex;
+};
+
+inline unsigned long OPDSFeedMetadata::getOpensearchTotalResults() const { return myOpensearchTotalResults; }
+inline unsigned long OPDSFeedMetadata::getOpensearchItemsPerPage() const { return myOpensearchItemsPerPage; }
+inline unsigned long OPDSFeedMetadata::getOpensearchStartIndex() const { return myOpensearchStartIndex; }
+inline void OPDSFeedMetadata::setOpensearchTotalResults(unsigned long number) { myOpensearchTotalResults = number; }
+inline void OPDSFeedMetadata::setOpensearchItemsPerPage(unsigned long number) { myOpensearchItemsPerPage = number; }
+inline void OPDSFeedMetadata::setOpensearchStartIndex(unsigned long number) { myOpensearchStartIndex = number; }
+
+#endif /* __OPDSMETADATA_H__ */
diff --git a/fbreader/src/network/opds/OPDSXMLParser.cpp b/fbreader/src/network/opds/OPDSXMLParser.cpp
new file mode 100644
index 0000000..a1a1dd9
--- /dev/null
+++ b/fbreader/src/network/opds/OPDSXMLParser.cpp
@@ -0,0 +1,554 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 <cstdlib>
+
+#include <ZLUnicodeUtil.h>
+#include <ZLXMLNamespace.h>
+
+#include "OPDSXMLParser.h"
+
+static const std::string TAG_FEED = "feed";
+static const std::string TAG_ENTRY = "entry";
+static const std::string TAG_AUTHOR = "author";
+static const std::string TAG_NAME = "name";
+static const std::string TAG_URI = "uri";
+static const std::string TAG_EMAIL = "email";
+static const std::string TAG_ID = "id";
+static const std::string TAG_CATEGORY = "category";
+static const std::string TAG_LINK = "link";
+static const std::string TAG_PUBLISHED = "published";
+static const std::string TAG_SUMMARY = "summary";
+static const std::string TAG_CONTENT = "content";
+static const std::string TAG_SUBTITLE = "subtitle";
+static const std::string TAG_TITLE = "title";
+static const std::string TAG_UPDATED = "updated";
+static const std::string TAG_PRICE = "price";
+static const std::string TAG_ICON = "icon";
+
+static const std::string TAG_HACK_SPAN = "span";
+
+static const std::string DC_TAG_LANGUAGE = "language";
+static const std::string DC_TAG_ISSUED = "issued";
+static const std::string DC_TAG_PUBLISHER = "publisher";
+static const std::string DC_TAG_FORMAT = "format";
+
+static const std::string CALIBRE_TAG_SERIES = "series";
+static const std::string CALIBRE_TAG_SERIES_INDEX = "series_index";
+
+static const std::string OPENSEARCH_TAG_TOTALRESULTS = "totalResults";
+static const std::string OPENSEARCH_TAG_ITEMSPERPAGE = "itemsPerPage";
+static const std::string OPENSEARCH_TAG_STARTINDEX = "startIndex";
+
+const std::string OPDSXMLParser::KEY_PRICE = "price";
+const std::string OPDSXMLParser::KEY_CURRENCY = "currency";
+const std::string OPDSXMLParser::KEY_FORMAT = "format";
+
+static const std::string TAG_SEARCH_DESCRIPTION = "fbreader:advancedSearch";
+static const std::string TAG_AUTHENTICATION = "fbreader:authentication";
+static const std::string TAG_URL_REWRITING_RULES = "fbreader:urlRewritingRule";
+static const std::string TAG_RELATION_ALIASES = "fbreader:relationAlias";
+
+OPDSXMLParser::OPDSXMLParser(shared_ptr<OPDSFeedReader> feedReader, bool readEntryNotFeed) : myFeedReader(feedReader) {
+ myState = readEntryNotFeed ? FEED : START;
+}
+
+bool OPDSXMLParser::processNamespaces() const {
+ return true;
+}
+
+void OPDSXMLParser::startElementHandler(const char *tag, const char **attributes) {
+ std::map<std::string,std::string> attributeMap = getAttributesMap(attributes);
+ switch (myState) {
+ case START:
+ if (testTag(ZLXMLNamespace::Atom, TAG_FEED, tag)) {
+ myFeedReader->processFeedStart();
+ myFeed = new OPDSFeedMetadata();
+ myFeed->readAttributes(attributeMap);
+ myState = FEED;
+ }
+ break;
+ case FEED:
+ if (testTag(ZLXMLNamespace::Atom, TAG_AUTHOR, tag)) {
+ myAuthor = new ATOMAuthor();
+ myAuthor->readAttributes(attributeMap);
+ myState = F_AUTHOR;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_ID, tag)) {
+ myId = new ATOMId();
+ myId->readAttributes(attributeMap);
+ myState = F_ID;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_ICON, tag)) {
+ myIcon = new ATOMIcon();
+ myIcon->readAttributes(attributeMap);
+ myState = F_ICON;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_LINK, tag)) {
+ myLink = new ATOMLink();
+ myLink->readAttributes(attributeMap);
+ myState = F_LINK;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_CATEGORY, tag)) {
+ myCategory = new ATOMCategory();
+ myCategory->readAttributes(attributeMap);
+ myState = F_CATEGORY;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_TITLE, tag)) {
+ //myTitle = new ATOMTitle(); // TODO:implement ATOMTextConstruct & ATOMTitle
+ //myTitle->readAttributes(attributeMap);
+ myState = F_TITLE;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_SUBTITLE, tag)) {
+ myState = F_SUBTITLE;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_SUMMARY, tag)) {
+ myState = F_SUMMARY;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_UPDATED, tag)) {
+ myUpdated = new ATOMUpdated();
+ myUpdated->readAttributes(attributeMap);
+ myState = F_UPDATED;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_ENTRY, tag)) {
+ myEntry = new OPDSEntry();
+ myEntry->readAttributes(attributeMap);
+ mySummaryTagFound = false;
+ myState = F_ENTRY;
+ } else if (testTag(ZLXMLNamespace::OpenSearch, OPENSEARCH_TAG_TOTALRESULTS, tag)) {
+ myState = OPENSEARCH_TOTALRESULTS;
+ } else if (testTag(ZLXMLNamespace::OpenSearch, OPENSEARCH_TAG_ITEMSPERPAGE, tag)) {
+ myState = OPENSEARCH_ITEMSPERPAGE;
+ } else if (testTag(ZLXMLNamespace::OpenSearch, OPENSEARCH_TAG_STARTINDEX, tag)) {
+ myState = OPENSEARCH_STARTINDEX;
+ }
+ break;
+ case F_ENTRY:
+ if (testTag(ZLXMLNamespace::Atom, TAG_AUTHOR, tag)) {
+ myAuthor = new ATOMAuthor();
+ myAuthor->readAttributes(attributeMap);
+ myState = FE_AUTHOR;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_ID, tag)) {
+ myId = new ATOMId();
+ myId->readAttributes(attributeMap);
+ myState = FE_ID;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_CATEGORY, tag)) {
+ myCategory = new ATOMCategory();
+ myCategory->readAttributes(attributeMap);
+ myState = FE_CATEGORY;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_ICON, tag)) {
+ myIcon = new ATOMIcon();
+ myIcon->readAttributes(attributeMap);
+ myState = FE_ICON;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_LINK, tag)) {
+ myLink = new ATOMLink();
+ myLink->readAttributes(attributeMap);
+ myState = FE_LINK;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_PUBLISHED, tag)) {
+ myPublished = new ATOMPublished();
+ myPublished->readAttributes(attributeMap);
+ myState = FE_PUBLISHED;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_SUMMARY, tag)) {
+ //mySummary = new ATOMSummary(); // TODO:implement ATOMTextConstruct & ATOMSummary
+ //mySummary->readAttributes(attributeMap);
+ myState = FE_SUMMARY;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_CONTENT, tag)) {
+ // ???
+ myState = FE_CONTENT;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_SUBTITLE, tag)) {
+ // ???
+ myState = FE_SUBTITLE;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_TITLE, tag)) {
+ //myTitle = new ATOMTitle(); // TODO:implement ATOMTextConstruct & ATOMTitle
+ //myTitle->readAttributes(attributeMap);
+ myState = FE_TITLE;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_UPDATED, tag)) {
+ myUpdated = new ATOMUpdated();
+ myUpdated->readAttributes(attributeMap);
+ myState = FE_UPDATED;
+ } else if (testTag(ZLXMLNamespace::DublinCoreTerms, DC_TAG_LANGUAGE, tag)) {
+ myState = FE_DC_LANGUAGE;
+ } else if (testTag(ZLXMLNamespace::DublinCoreTerms, DC_TAG_ISSUED, tag)) {
+ myState = FE_DC_ISSUED;
+ } else if (testTag(ZLXMLNamespace::DublinCoreTerms, DC_TAG_PUBLISHER, tag)) {
+ myState = FE_DC_PUBLISHER;
+ } else if (testTag(ZLXMLNamespace::CalibreMetadata, CALIBRE_TAG_SERIES, tag)) {
+ myState = FE_CALIBRE_SERIES;
+ } else if (testTag(ZLXMLNamespace::CalibreMetadata, CALIBRE_TAG_SERIES_INDEX, tag)) {
+ myState = FE_CALIBRE_SERIES_INDEX;
+ }
+ break;
+ case F_AUTHOR:
+ if (testTag(ZLXMLNamespace::Atom, TAG_NAME, tag)) {
+ myState = FA_NAME;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_URI, tag)) {
+ myState = FA_URI;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_EMAIL, tag)) {
+ myState = FA_EMAIL;
+ }
+ break;
+ case FE_TITLE:
+ // TODO: remove this temporary code
+ // DON'T clear myBuffer
+ return;
+ case FE_LINK:
+ if (testTag(ZLXMLNamespace::Opds, TAG_PRICE, tag)) {
+ myLink->setUserData(KEY_CURRENCY, attributeMap["currencycode"]);
+ myState = FEL_PRICE;
+ } if (testTag(ZLXMLNamespace::DublinCoreTerms, DC_TAG_FORMAT, tag)) {
+ myState = FEL_FORMAT;
+ }
+ break;
+ case FE_AUTHOR:
+ if (testTag(ZLXMLNamespace::Atom, TAG_NAME, tag)) {
+ myState = FEA_NAME;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_URI, tag)) {
+ myState = FEA_URI;
+ } else if (testTag(ZLXMLNamespace::Atom, TAG_EMAIL, tag)) {
+ myState = FEA_EMAIL;
+ }
+ break;
+ case FE_CONTENT:
+ if (TAG_HACK_SPAN == tag || attributeMap["class"] == "price") {
+ myState = FEC_HACK_SPAN;
+ }
+ break;
+ default:
+ break;
+ }
+
+ myBuffer.clear();
+}
+
+void OPDSXMLParser::endElementHandler(const char *tag) {
+ ZLUnicodeUtil::utf8Trim(myBuffer);
+
+ switch (myState) {
+ case START:
+ break;
+ case FEED:
+ if (testTag(ZLXMLNamespace::Atom, TAG_FEED, tag)) {
+ myFeedReader->processFeedMetadata(myFeed);
+ myFeed.reset();
+ myFeedReader->processFeedEnd();
+ myState = START;
+ }
+ break;
+ case F_ENTRY:
+ if (testTag(ZLXMLNamespace::Atom, TAG_ENTRY, tag)) {
+ myFeedReader->processFeedEntry(myEntry);
+ myEntry.reset();
+ myState = FEED;
+ }
+ break;
+ case F_ID:
+ if (testTag(ZLXMLNamespace::Atom, TAG_ID, tag)) {
+ // FIXME:uri can be lost:buffer will be truncated, if there are extension tags inside the <id> tag
+ myId->setUri(myBuffer);
+ if (!myFeed.isNull()) {
+ myFeed->setId(myId);
+ }
+ myId.reset();
+ myState = FEED;
+ }
+ break;
+ case F_ICON:
+ if (testTag(ZLXMLNamespace::Atom, TAG_ICON, tag)) {
+ myIcon->setUri(myBuffer);
+ if (!myFeed.isNull()) {
+ myFeed->setIcon(myIcon);
+ }
+ myIcon.reset();
+ myState = FEED;
+ }
+ break;
+ case F_LINK:
+ if (testTag(ZLXMLNamespace::Atom, TAG_LINK, tag)) {
+ if (!myFeed.isNull()) {
+ myFeed->links().push_back(myLink);
+ }
+ myLink.reset();
+ myState = FEED;
+ }
+ break;
+ case F_CATEGORY:
+ if (testTag(ZLXMLNamespace::Atom, TAG_CATEGORY, tag)) {
+ if (!myFeed.isNull()) {
+ myFeed->categories().push_back(myCategory);
+ }
+ myCategory.reset();
+ myState = FEED;
+ }
+ break;
+ case F_TITLE:
+ if (testTag(ZLXMLNamespace::Atom, TAG_TITLE, tag)) {
+ // FIXME:title can be lost:buffer will be truncated, if there are extension tags inside the <title> tag
+ // TODO:implement ATOMTextConstruct & ATOMTitle
+ if (!myFeed.isNull()) {
+ myFeed->setTitle(myBuffer);
+ }
+ myState = FEED;
+ }
+ break;
+ case F_SUBTITLE:
+ if (testTag(ZLXMLNamespace::Atom, TAG_SUBTITLE, tag)) {
+ if (!myFeed.isNull()) {
+ myFeed->setSubtitle(myBuffer);
+ }
+ myState = FEED;
+ }
+ break;
+ case F_SUMMARY:
+ if (testTag(ZLXMLNamespace::Atom, TAG_SUMMARY, tag)) {
+ if (!myFeed.isNull()) {
+ myFeed->setSummary(myBuffer);
+ }
+ myState = FEED;
+ }
+ break;
+ case F_UPDATED:
+ if (testTag(ZLXMLNamespace::Atom, TAG_UPDATED, tag)) {
+ // FIXME:uri can be lost:buffer will be truncated, if there are extension tags inside the <id> tag
+ ATOMDateConstruct::parse(myBuffer, *myUpdated);
+ if (!myFeed.isNull()) {
+ myFeed->setUpdated(myUpdated);
+ }
+ myUpdated.reset();
+ myState = FEED;
+ }
+ break;
+ case F_AUTHOR:
+ if (testTag(ZLXMLNamespace::Atom, TAG_AUTHOR, tag)) {
+ if (!myFeed.isNull()) {
+ myFeed->authors().push_back(myAuthor);
+ }
+ myAuthor.reset();
+ myState = FEED;
+ }
+ break;
+ case FA_NAME:
+ if (testTag(ZLXMLNamespace::Atom, TAG_NAME, tag)) {
+ myAuthor->setName(myBuffer);
+ myState = F_AUTHOR;
+ }
+ break;
+ case FEA_NAME:
+ if (testTag(ZLXMLNamespace::Atom, TAG_NAME, tag)) {
+ myAuthor->setName(myBuffer);
+ myState = FE_AUTHOR;
+ }
+ break;
+ case FEL_PRICE:
+ if (testTag(ZLXMLNamespace::Opds, TAG_PRICE, tag)) {
+ myLink->setUserData(KEY_PRICE, myBuffer);
+ myState = FE_LINK;
+ }
+ break;
+ case FEL_FORMAT:
+ if (testTag(ZLXMLNamespace::DublinCoreTerms, DC_TAG_FORMAT, tag)) {
+ myLink->setUserData(KEY_FORMAT, myBuffer);
+ myState = FE_LINK;
+ }
+ break;
+ case FA_URI:
+ if (testTag(ZLXMLNamespace::Atom, TAG_URI, tag)) {
+ myAuthor->setUri(myBuffer);
+ myState = F_AUTHOR;
+ }
+ break;
+ case FEA_URI:
+ if (testTag(ZLXMLNamespace::Atom, TAG_URI, tag)) {
+ myAuthor->setUri(myBuffer);
+ myState = FE_AUTHOR;
+ }
+ break;
+ case FA_EMAIL:
+ if (testTag(ZLXMLNamespace::Atom, TAG_EMAIL, tag)) {
+ myAuthor->setEmail(myBuffer);
+ myState = F_AUTHOR;
+ }
+ break;
+ case FEA_EMAIL:
+ if (testTag(ZLXMLNamespace::Atom, TAG_EMAIL, tag)) {
+ myAuthor->setEmail(myBuffer);
+ myState = FE_AUTHOR;
+ }
+ break;
+ case FE_AUTHOR:
+ if (testTag(ZLXMLNamespace::Atom, TAG_AUTHOR, tag)) {
+ myEntry->authors().push_back(myAuthor);
+ myAuthor.reset();
+ myState = F_ENTRY;
+ }
+ break;
+ case FE_ICON:
+ if (testTag(ZLXMLNamespace::Atom, TAG_ICON, tag)) {
+ myIcon->setUri(myBuffer);
+ if (!myEntry.isNull()) {
+ myEntry->setIcon(myIcon);
+ }
+ myIcon.reset();
+ myState = F_ENTRY;
+ }
+ break;
+ case FE_ID:
+ if (testTag(ZLXMLNamespace::Atom, TAG_ID, tag)) {
+ // FIXME:uri can be lost:buffer will be truncated, if there are extension tags inside the <id> tag
+ myId->setUri(myBuffer);
+ myEntry->setId(myId);
+ myId.reset();
+ myState = F_ENTRY;
+ }
+ break;
+ case FE_CATEGORY:
+ if (testTag(ZLXMLNamespace::Atom, TAG_CATEGORY, tag)) {
+ myEntry->categories().push_back(myCategory);
+ myCategory.reset();
+ myState = F_ENTRY;
+ }
+ break;
+ case FE_LINK:
+ if (testTag(ZLXMLNamespace::Atom, TAG_LINK, tag)) {
+ myEntry->links().push_back(myLink);
+ myLink.reset();
+ myState = F_ENTRY;
+ }
+ break;
+ case FE_PUBLISHED:
+ if (testTag(ZLXMLNamespace::Atom, TAG_PUBLISHED, tag)) {
+ // FIXME:uri can be lost:buffer will be truncated, if there are extension tags inside the <id> tag
+ ATOMDateConstruct::parse(myBuffer, *myPublished);
+ myEntry->setPublished(myPublished);
+ myPublished.reset();
+ myState = F_ENTRY;
+ }
+ break;
+ case FE_SUMMARY:
+ if (testTag(ZLXMLNamespace::Atom, TAG_SUMMARY, tag)) {
+ // FIXME:summary can be lost:buffer will be truncated, if there are extension tags inside the <summary> tag
+ // TODO:implement ATOMTextConstruct & ATOMSummary
+ myEntry->setSummary(myBuffer);
+ mySummaryTagFound = true;
+ myState = F_ENTRY;
+ }
+ break;
+ case FE_CONTENT:
+ if (testTag(ZLXMLNamespace::Atom, TAG_CONTENT, tag)) {
+ // TODO:check this accurately
+ if (!mySummaryTagFound) {
+ myEntry->setSummary(myBuffer);
+ }
+ myState = F_ENTRY;
+ }
+ break;
+ case FEC_HACK_SPAN:
+ myEntry->setUserData(KEY_PRICE, myBuffer);
+ myState = FE_CONTENT;
+ break;
+ case FE_SUBTITLE:
+ if (testTag(ZLXMLNamespace::Atom, TAG_SUBTITLE, tag)) {
+ // TODO:check this accurately
+ if (!mySummaryTagFound) {
+ myEntry->setSummary(myBuffer);
+ }
+ myState = F_ENTRY;
+ }
+ break;
+ case FE_TITLE:
+ if (testTag(ZLXMLNamespace::Atom, TAG_TITLE, tag)) {
+ // FIXME:title can be lost:buffer will be truncated, if there are extension tags inside the <title> tag
+ // TODO:implement ATOMTextConstruct & ATOMTitle
+ myEntry->setTitle(myBuffer);
+ myState = F_ENTRY;
+ } else {
+ // TODO: remove this temporary code
+ // DON'T clear myBuffer
+ return;
+ }
+ break;
+ case FE_UPDATED:
+ if (testTag(ZLXMLNamespace::Atom, TAG_UPDATED, tag)) {
+ // FIXME:uri can be lost:buffer will be truncated, if there are extension tags inside the <id> tag
+ ATOMDateConstruct::parse(myBuffer, *myUpdated);
+ myEntry->setUpdated(myUpdated);
+ myUpdated.reset();
+ myState = F_ENTRY;
+ }
+ break;
+ case FE_DC_LANGUAGE:
+ if (testTag(ZLXMLNamespace::DublinCoreTerms, DC_TAG_LANGUAGE, tag)) {
+ // FIXME:language can be lost:buffer will be truncated, if there are extension tags inside the <dc:language> tag
+ myEntry->setDCLanguage(myBuffer);
+ myState = F_ENTRY;
+ }
+ break;
+ case FE_DC_ISSUED:
+ if (testTag(ZLXMLNamespace::DublinCoreTerms, DC_TAG_ISSUED, tag)) {
+ // FIXME:issued can be lost:buffer will be truncated, if there are extension tags inside the <dc:issued> tag
+ DCDate *issued = new DCDate();
+ ATOMDateConstruct::parse(myBuffer, *issued);
+ myEntry->setDCIssued(issued);
+ myState = F_ENTRY;
+ }
+ break;
+ case FE_DC_PUBLISHER:
+ if (testTag(ZLXMLNamespace::DublinCoreTerms, DC_TAG_PUBLISHER, tag)) {
+ // FIXME:publisher can be lost:buffer will be truncated, if there are extension tags inside the <dc:publisher> tag
+ myEntry->setDCPublisher(myBuffer);
+ myState = F_ENTRY;
+ }
+ break;
+ case FE_CALIBRE_SERIES:
+ if (testTag(ZLXMLNamespace::CalibreMetadata, CALIBRE_TAG_SERIES, tag)) {
+ myEntry->setSeriesTitle(myBuffer);
+ myState = F_ENTRY;
+ }
+ break;
+ case FE_CALIBRE_SERIES_INDEX:
+ if (testTag(ZLXMLNamespace::CalibreMetadata, CALIBRE_TAG_SERIES_INDEX, tag)) {
+ myEntry->setSeriesIndex(std::atoi(myBuffer.c_str()));
+ myState = F_ENTRY;
+ }
+ break;
+ case OPENSEARCH_TOTALRESULTS:
+ if (testTag(ZLXMLNamespace::OpenSearch, OPENSEARCH_TAG_TOTALRESULTS, tag)) {
+ int number = std::atoi(myBuffer.c_str());
+ if (!myFeed.isNull()) {
+ myFeed->setOpensearchTotalResults(number);
+ }
+ myState = FEED;
+ }
+ break;
+ case OPENSEARCH_ITEMSPERPAGE:
+ if (testTag(ZLXMLNamespace::OpenSearch, OPENSEARCH_TAG_ITEMSPERPAGE, tag)) {
+ int number = std::atoi(myBuffer.c_str());
+ if (!myFeed.isNull()) {
+ myFeed->setOpensearchItemsPerPage(number);
+ }
+ myState = FEED;
+ }
+ break;
+ case OPENSEARCH_STARTINDEX:
+ if (testTag(ZLXMLNamespace::OpenSearch, OPENSEARCH_TAG_STARTINDEX, tag)) {
+ int number = std::atoi(myBuffer.c_str());
+ if (!myFeed.isNull()) {
+ myFeed->setOpensearchStartIndex(number);
+ }
+ myState = FEED;
+ }
+ break;
+ }
+
+ myBuffer.clear();
+}
+
+void OPDSXMLParser::characterDataHandler(const char *data, std::size_t len) {
+ myBuffer.append(data, len);
+}
diff --git a/fbreader/src/network/opds/OPDSXMLParser.h b/fbreader/src/network/opds/OPDSXMLParser.h
new file mode 100644
index 0000000..82f0124
--- /dev/null
+++ b/fbreader/src/network/opds/OPDSXMLParser.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __OPDSXMLPARSER_H__
+#define __OPDSXMLPARSER_H__
+
+#include <ZLXMLReader.h>
+
+#include "OPDSMetadata.h"
+#include "OPDSFeedReader.h"
+
+
+class OPDSXMLParser : public ZLXMLReader {
+
+public:
+ static const std::string KEY_PRICE;
+ static const std::string KEY_CURRENCY;
+ static const std::string KEY_FORMAT;
+
+public:
+ OPDSXMLParser(shared_ptr<OPDSFeedReader> feedReader, bool readEntryNotFeed = false);
+
+protected:
+ void startElementHandler(const char *tag, const char **attributes);
+ void endElementHandler(const char *tag);
+ void characterDataHandler(const char *text, std::size_t len);
+ bool processNamespaces() const;
+
+protected:
+ enum State {
+ START,
+ FEED, F_ENTRY, F_ID, F_LINK, F_CATEGORY, F_TITLE, F_UPDATED, F_AUTHOR, F_SUBTITLE, F_ICON, F_SUMMARY,
+ FA_NAME, FA_URI, FA_EMAIL,
+ FE_AUTHOR, FE_ID, FE_CATEGORY, FE_LINK, FE_PUBLISHED, FE_SUMMARY, FE_CONTENT, FE_SUBTITLE, FE_TITLE, FE_ICON, FE_UPDATED, FE_DC_LANGUAGE, FE_DC_ISSUED, FE_DC_PUBLISHER, FE_CALIBRE_SERIES, FE_CALIBRE_SERIES_INDEX,
+ FEL_PRICE, FEL_FORMAT,
+ FEA_NAME, FEA_URI, FEA_EMAIL,
+ OPENSEARCH_TOTALRESULTS, OPENSEARCH_ITEMSPERPAGE, OPENSEARCH_STARTINDEX,
+ FEC_HACK_SPAN,
+ };
+
+protected:
+ shared_ptr<OPDSFeedReader> myFeedReader;
+ State myState;
+
+private:
+ std::string myBuffer;
+ shared_ptr<OPDSFeedMetadata> myFeed;
+ shared_ptr<OPDSEntry> myEntry;
+
+ shared_ptr<ATOMAuthor> myAuthor;
+ shared_ptr<ATOMId> myId;
+ shared_ptr<ATOMIcon> myIcon;
+ shared_ptr<ATOMLink> myLink;
+ shared_ptr<ATOMCategory> myCategory;
+ shared_ptr<ATOMUpdated> myUpdated;
+ shared_ptr<ATOMPublished> myPublished;
+
+ //shared_ptr<ATOMTitle> myTitle; // TODO: implement ATOMTextConstruct & ATOMTitle
+ //shared_ptr<ATOMSummary> mySummary; // TODO: implement ATOMTextConstruct & ATOMSummary
+ bool mySummaryTagFound;
+};
+
+#endif /* __OPDSXMLPARSER_H__ */
diff --git a/fbreader/src/network/opds/OpenSearchXMLReader.cpp b/fbreader/src/network/opds/OpenSearchXMLReader.cpp
new file mode 100644
index 0000000..686d8c1
--- /dev/null
+++ b/fbreader/src/network/opds/OpenSearchXMLReader.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2008-2012 Geometer Plus <[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 "OpenSearchXMLReader.h"
+#include <ZLMimeType.h>
+
+static const std::string TAG_URL = "Url";
+
+std::string OpenSearchXMLReader::convertOpenSearchURL(const std::string& raws) { //TODO
+ std::size_t pos = raws.find('{');
+ return raws.substr(0, pos) + "%s";
+}
+
+void OpenSearchXMLReader::startElementHandler(const char *tag, const char **attributes) {
+ if (TAG_URL == tag) {
+ const char *type = attributeValue(attributes, "type");
+ if (ZLMimeType::get(type)->weakEquals(*ZLMimeType::APPLICATION_ATOM_XML)) {
+ const char *templ = attributeValue(attributes, "template");
+ if (templ != 0) {
+ myTemplateURL = convertOpenSearchURL(templ);
+ }
+ }
+ }
+}
+
+void OpenSearchXMLReader::endElementHandler(const char *tag) {
+ (void)tag;
+}
+
+void OpenSearchXMLReader::characterDataHandler(const char *text, std::size_t len) {
+ (void)text;
+ (void)len;
+}
diff --git a/fbreader/src/network/opds/OpenSearchXMLReader.h b/fbreader/src/network/opds/OpenSearchXMLReader.h
new file mode 100644
index 0000000..2b53f19
--- /dev/null
+++ b/fbreader/src/network/opds/OpenSearchXMLReader.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008-2012 Geometer Plus <[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.
+ */
+
+#ifndef __OPENSEARCHXMLREADER_H__
+#define __OPENSEARCHXMLREADER_H__
+
+#include <string>
+#include <ZLXMLReader.h>
+
+class OpenSearchXMLReader : public ZLXMLReader {
+
+public:
+ OpenSearchXMLReader() {}
+ std::string templateURL() {return myTemplateURL;}
+
+ static std::string convertOpenSearchURL(const std::string& raws);
+
+private:
+ void startElementHandler(const char *tag, const char **attributes);
+ void endElementHandler(const char *tag);
+ void characterDataHandler(const char *text, std::size_t len);
+ std::string myTemplateURL;
+
+};
+
+#endif /* __OPENSEARCHXMLREADER_H__ */
diff --git a/fbreader/src/network/opds/URLRewritingRule.cpp b/fbreader/src/network/opds/URLRewritingRule.cpp
new file mode 100644
index 0000000..8cea851
--- /dev/null
+++ b/fbreader/src/network/opds/URLRewritingRule.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2010-2012 Geometer Plus <[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 <ZLNetworkUtil.h>
+
+#include "URLRewritingRule.h"
+
+URLRewritingRule::URLRewritingRule(const std::map<std::string,std::string> &map) : myType(UNKNOWN), myApply(ALWAYS) {
+ for (std::map<std::string, std::string>::const_iterator it = map.begin(); it != map.end(); ++it) {
+ std::string key = (*it).first;
+ std::string value = (*it).second;
+
+ if (key == "type") {
+ if (value == "addUrlParameter") {
+ myType = ADD_URL_PARAMETER;
+ } else if (value == "rewrite") {
+ myType = REWRITE;
+ }
+ } else if (key == "apply") {
+ if (value == "internal") {
+ myApply = INTERNAL;
+ } else if (value == "external") {
+ myApply = EXTERNAL;
+ }
+ } else {
+ myParameters.insert(std::make_pair(key, value));
+ }
+
+ }
+}
+
+std::string URLRewritingRule::apply(const std::string &url) const {
+ std::string appliedUrl = url;
+ switch (myType) {
+ case ADD_URL_PARAMETER:
+ {
+ std::string name, value;
+ std::map<std::string, std::string>::const_iterator it;
+ it = myParameters.find("name");
+ if (it != myParameters.end()) {
+ name = (*it).second;
+ }
+ it = myParameters.find("value");
+ if (it != myParameters.end()) {
+ value = (*it).second;
+ }
+ if (name.empty() || value.empty()) {
+ break;
+ }
+ ZLNetworkUtil::appendParameter(appliedUrl, name, value);
+ }
+ case REWRITE: //TODO implement (regular expressions should be used here)
+ default:
+ break;
+ }
+ return appliedUrl;
+}
+
+URLRewritingRule::RuleApply URLRewritingRule::whereToApply() const {
+ return myApply;
+}
diff --git a/fbreader/src/network/opds/URLRewritingRule.h b/fbreader/src/network/opds/URLRewritingRule.h
new file mode 100644
index 0000000..1251139
--- /dev/null
+++ b/fbreader/src/network/opds/URLRewritingRule.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010-2012 Geometer Plus <[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.
+ */
+
+#ifndef __URLREWRITINGRULE_H__
+#define __URLREWRITINGRULE_H__
+
+#include <string>
+#include <map>
+
+class URLRewritingRule {
+
+public:
+ enum RuleType {
+ ADD_URL_PARAMETER,
+ REWRITE,
+ UNKNOWN,
+ };
+
+ enum RuleApply {
+ ALWAYS, EXTERNAL, INTERNAL
+ };
+
+ URLRewritingRule(const std::map<std::string,std::string> &attributesMap);
+ std::string apply(const std::string &url) const;
+ RuleApply whereToApply() const;
+
+private:
+ RuleType myType;
+ RuleApply myApply;
+ std::map<std::string, std::string> myParameters;
+};
+
+
+#endif /* __URLREWRITINGRULE_H__ */
diff --git a/fbreader/src/network/tree/NetworkAuthorTree.cpp b/fbreader/src/network/tree/NetworkAuthorTree.cpp
new file mode 100644
index 0000000..8106838
--- /dev/null
+++ b/fbreader/src/network/tree/NetworkAuthorTree.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 <ZLResource.h>
+#include <ZLImage.h>
+
+#include "NetworkTreeNodes.h"
+
+const ZLTypeId NetworkAuthorTree::TYPE_ID(NetworkTree::TYPE_ID);
+
+const ZLTypeId &NetworkAuthorTree::typeId() const {
+ return TYPE_ID;
+}
+
+const ZLResource &NetworkAuthorTree::resource() const {
+ return ZLResource::resource("networkView")["authorNode"];
+}
+
+NetworkAuthorTree::NetworkAuthorTree(NetworkTree *parent, const NetworkBookItem::AuthorData &author) : NetworkTree(parent), myAuthor(author) {
+ init();
+}
+
+void NetworkAuthorTree::init() {
+ //registerExpandTreeAction();
+}
+
+std::string NetworkAuthorTree::title() const {
+ return myAuthor.DisplayName;
+}
+
+shared_ptr<const ZLImage> NetworkAuthorTree::image() const {
+ return defaultCoverImage("booktree-author.png");
+}
+
+const NetworkBookItem::AuthorData &NetworkAuthorTree::author() {
+ return myAuthor;
+}
diff --git a/fbreader/src/network/tree/NetworkBookTree.cpp b/fbreader/src/network/tree/NetworkBookTree.cpp
new file mode 100644
index 0000000..c59d247
--- /dev/null
+++ b/fbreader/src/network/tree/NetworkBookTree.cpp
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 <ZLResource.h>
+#include <ZLImage.h>
+#include <ZLExecutionUtil.h>
+#include <ZLNetworkManager.h>
+
+#include "NetworkTreeNodes.h"
+#include "NetworkTreeFactory.h"
+#include "NetworkLibrary.h"
+#include "NetworkCatalogUtil.h"
+
+#include "../../networkActions/NetworkActions.h"
+
+const ZLTypeId NetworkBookTree::TYPE_ID(ZLTreePageNode::TYPE_ID);
+
+const ZLTypeId &NetworkBookTree::typeId() const {
+ return TYPE_ID;
+}
+
+const ZLResource &NetworkBookTree::resource() const {
+ return ZLResource::resource("networkView")["bookNode"];
+}
+
+NetworkBookTree::NetworkBookTree(NetworkTree *parent, shared_ptr<NetworkItem> book, SummaryType summaryType) : ZLTreePageNode(parent), myBook(book), mySummaryType(summaryType) {
+ init();
+}
+
+//TODO we don't need a actions wrappers since we don't use old network library
+class NetworkTreeBookReadAction : public NetworkBookReadAction {
+public:
+ NetworkTreeBookReadAction(const NetworkBookTree &tree, const NetworkBookItem &book, bool demo) : NetworkBookReadAction(book, demo), myTree(tree) {}
+ void run() {
+ NetworkBookReadAction::run();
+ myTree.close();
+ }
+
+private:
+ const NetworkBookTree &myTree;
+};
+
+static std::vector<shared_ptr<ZLTreeAction> > getBookActions(NetworkBookTree &tree) {
+ std::vector<shared_ptr<ZLTreeAction> > actions;
+ const NetworkBookItem &book = tree.book();
+ if (!book.reference(BookReference::DOWNLOAD_FULL).isNull() ||
+ !book.reference(BookReference::DOWNLOAD_FULL_CONDITIONAL).isNull()) {
+ actions.push_back(new NetworkTreeBookReadAction(tree, book, false));
+ actions.push_back(new NetworkBookDownloadAction(tree, book, false));
+ actions.push_back(new NetworkBookDeleteAction(book));
+ }
+ if (!book.reference(BookReference::DOWNLOAD_DEMO).isNull()) {
+ actions.push_back(new NetworkTreeBookReadAction(tree, book, true));
+ actions.push_back(new NetworkBookDownloadAction(tree, book, true, tree.resource()["demo"].value()));
+ }
+ if (!book.reference(BookReference::BUY).isNull()) {
+ actions.push_back(new NetworkBookBuyDirectlyAction(tree, book));
+ } else if (!book.reference(BookReference::BUY_IN_BROWSER).isNull()) {
+ actions.push_back(new NetworkBookBuyInBrowserAction(book));
+ }
+ return actions;
+}
+
+void NetworkBookTree::init() {
+ std::vector<shared_ptr<ZLTreeAction> > actions = getBookActions(*this);
+ for (std::size_t i = 0; i < actions.size(); ++i) {
+ registerAction(actions.at(i));
+ }
+}
+
+std::string NetworkBookTree::title() const {
+ return myBook->Title;
+}
+
+std::string NetworkBookTree::subtitle() const {
+ int count = 0;
+ std::string authorsString;
+ const std::vector<NetworkBookItem::AuthorData> authors = book().Authors;
+ for (std::vector<NetworkBookItem::AuthorData>::const_iterator it = authors.begin(); it != authors.end(); ++it) {
+ if (!authorsString.empty()) {
+ authorsString += ", ";
+ }
+ authorsString += it->DisplayName;
+ ++count;
+ }
+ if (mySummaryType == NONE && count == 1) {
+ return std::string();
+ }
+ return authorsString;
+}
+
+shared_ptr<ZLTreePageInfo> NetworkBookTree::getPageInfo() /*const*/ {
+ if (myPageInfo.isNull()) {
+ myPageInfo = new BookItemWrapper(*this, myBook);
+ }
+ return myPageInfo;
+}
+
+
+shared_ptr<const ZLImage> NetworkBookTree::image() const {
+ if (myImage.isNull()) {
+ myImage = NetworkCatalogUtil::getAndDownloadImageByUrl(myBook->URLByType[NetworkItem::URL_COVER], this);
+ }
+ return (!myImage.isNull() && myImage->good()) ? myImage : FBTree::defaultCoverImage("booktree-book.png");
+}
+
+shared_ptr<const ZLImage> NetworkBookTree::fullImage() const {
+ if (myBook->URLByType.find(NetworkItem::URL_FULL_COVER) == myBook->URLByType.end()) {
+ return 0;
+ }
+ shared_ptr<const ZLImage> fullImage = NetworkCatalogUtil::getImageByUrl(myBook->URLByType[NetworkItem::URL_FULL_COVER]);
+ return !fullImage.isNull() ? fullImage : 0;
+}
+
+const NetworkBookItem &NetworkBookTree::book() const {
+ return (const NetworkBookItem&)*myBook;
+}
+
+
+NetworkBookTree::BookItemWrapper::BookItemWrapper(NetworkBookTree &tree, shared_ptr<NetworkItem> bookItem) :
+ myTree(tree), myBookItem(bookItem), myIsInitialized(false) {
+}
+
+bool NetworkBookTree::BookItemWrapper::isPageInfoLoaded() {
+ return myIsInitialized;
+}
+
+class BookItemWrapperScope : public ZLUserData {
+public:
+ shared_ptr<ZLNetworkRequest::Listener> listener;
+};
+
+void NetworkBookTree::BookItemWrapper::loadAll(shared_ptr<ZLNetworkRequest::Listener> listener) {
+ if (myIsInitialized) {
+ listener->finished();
+ return;
+ }
+
+ NetworkBookItem &bookItem = book();
+
+ BookItemWrapperScope *scope = new BookItemWrapperScope;
+ scope->listener = listener;
+ shared_ptr<ZLUserDataHolder> scopeData = new ZLUserDataHolder;
+ scopeData->addUserData("scope", scope);
+
+ if (bookItem.isFullyLoaded()) {
+ onInformationLoaded(*scopeData, std::string());
+ return;
+ }
+ bookItem.loadFullInformation(ZLExecutionUtil::createListener(scopeData, this, &NetworkBookTree::BookItemWrapper::onInformationLoaded));
+}
+
+void NetworkBookTree::BookItemWrapper::onInformationLoaded(ZLUserDataHolder &data, const std::string &error){
+ shared_ptr<const ZLImage> cover = image();
+ if (!cover.isNull()) {
+ shared_ptr<ZLNetworkRequest> request = cover->synchronizationData();
+ if (!request.isNull()) {
+ request->setListener(ZLExecutionUtil::createListener(new ZLUserDataHolder(data), this, &NetworkBookTree::BookItemWrapper::onCoverLoaded));
+ ZLNetworkManager::Instance().performAsync(request);
+ return;
+ }
+ }
+ onCoverLoaded(data, error); //if image is loaded already
+}
+
+void NetworkBookTree::BookItemWrapper::onCoverLoaded(ZLUserDataHolder &data, const std::string &error) {
+ BookItemWrapperScope &scope = static_cast<BookItemWrapperScope&>(*data.getUserData("scope"));
+ if (error.empty()) {
+ myIsInitialized = true;
+ }
+ scope.listener->finished(error);
+}
+
+std::string NetworkBookTree::BookItemWrapper::title() const {
+ return book().Title;
+}
+
+std::vector<std::string> NetworkBookTree::BookItemWrapper::authors() const {
+ const NetworkBookItem &bookItem = book();
+ std::vector<std::string> authors;
+ for (std::size_t i = 0; i < bookItem.Authors.size(); ++i) {
+ authors.push_back(bookItem.Authors.at(i).DisplayName);
+ }
+ return authors;
+}
+
+std::vector<std::string> NetworkBookTree::BookItemWrapper::tags() const {
+ return book().Tags;
+}
+
+std::string NetworkBookTree::BookItemWrapper::summary() const {
+ return book().Summary;
+}
+
+shared_ptr<const ZLImage> NetworkBookTree::BookItemWrapper::image() const {
+ shared_ptr<const ZLImage> fullImage = myTree.fullImage();
+ if (!fullImage.isNull()) {
+ return fullImage;
+ }
+ return myTree.image();
+}
+
+const std::vector<shared_ptr<ZLTreeAction> > &NetworkBookTree::BookItemWrapper::actions() const {
+ return myTree.actions();
+}
+
+std::string NetworkBookTree::BookItemWrapper::actionText(const shared_ptr<ZLTreeAction> &action) const {
+ return myTree.actionText(action);
+}
+
+class RelatedAction : public ZLTreeAction {
+public:
+ RelatedAction(shared_ptr<NetworkItem> item) : myTitle(item->Title) {
+ myNode = new NetworkCatalogTree(&NetworkLibrary::Instance().getFakeCatalogTree(), item);
+ //myNode = NetworkTreeFactory::createNetworkTree(0, item);
+ }
+ ZLResourceKey key() const { return ZLResourceKey(""); }
+ std::string text(const ZLResource &/*resource*/) const {
+ return myTitle;
+ }
+ void run() {
+ if (NetworkCatalogTree *tree = zlobject_cast<NetworkCatalogTree*>(&*myNode)){
+ tree->expand();
+ }
+ }
+
+private:
+ shared_ptr<ZLTreeTitledNode> myNode;
+ std::string myTitle;
+};
+
+const std::vector<shared_ptr<ZLTreeAction> > NetworkBookTree::BookItemWrapper::relatedActions() const {
+ if (!myRelatedActions.empty()) {
+ return myRelatedActions;
+ }
+ std::vector<shared_ptr<NetworkItem> > catalogItems = static_cast<NetworkBookItem&>(*myBookItem).getRelatedCatalogsItems();
+ for (std::size_t i = 0; i < catalogItems.size(); ++i) {
+ shared_ptr<NetworkItem> item = catalogItems.at(i);
+ myRelatedActions.push_back(new RelatedAction(item));
+ }
+ return myRelatedActions;
+}
+
+NetworkBookItem &NetworkBookTree::BookItemWrapper::book() const {
+ return (NetworkBookItem&)*myBookItem;
+}
diff --git a/fbreader/src/network/tree/NetworkCatalogRootTree.cpp b/fbreader/src/network/tree/NetworkCatalogRootTree.cpp
new file mode 100644
index 0000000..50a78f5
--- /dev/null
+++ b/fbreader/src/network/tree/NetworkCatalogRootTree.cpp
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 <ZLStringUtil.h>
+#include <ZLExecutionUtil.h>
+
+#include "../../fbreader/FBReader.h"
+
+#include "../authentication/NetworkAuthenticationManager.h"
+#include "../../networkActions/NetworkOperationRunnable.h"
+#include "../../networkActions/AuthenticationDialogManager.h"
+#include "../../networkActions/PasswordRecoveryDialog.h"
+#include "../../networkActions/RegisterUserDialog.h"
+
+#include "NetworkLibrary.h"
+
+#include "NetworkTreeNodes.h"
+
+class NetworkTreeCatalogAuthAction : public ZLTreeAction {
+
+protected:
+ NetworkTreeCatalogAuthAction(NetworkAuthenticationManager &mgr, bool forLoggedUsers);
+
+protected:
+ bool makesSense() const;
+
+protected:
+ NetworkAuthenticationManager &myManager;
+
+private:
+ const bool myForLoggedUsers;
+};
+
+class NetworkCatalogRootTree::LoginAction : public NetworkTreeCatalogAuthAction {
+
+public:
+ LoginAction(NetworkAuthenticationManager &mgr, ZLTreeNode *node);
+ void run();
+ ZLResourceKey key() const;
+
+private:
+ void onAuthorised(const std::string &error);
+
+private:
+ ZLTreeNode *myNode;
+
+friend class LoginActionListener;
+};
+
+class NetworkCatalogRootTree::LogoutAction : public NetworkTreeCatalogAuthAction {
+
+public:
+ LogoutAction(NetworkAuthenticationManager &mgr);
+ void run();
+ ZLResourceKey key() const;
+ std::string text(const ZLResource &resource) const;
+};
+
+class NetworkCatalogRootTree::TopupAccountAction : public NetworkTreeCatalogAuthAction {
+
+public:
+ TopupAccountAction(NetworkAuthenticationManager &mgr);
+
+private:
+ void run();
+ ZLResourceKey key() const;
+ std::string text(const ZLResource &resource) const;
+ bool makesSense() const;
+};
+
+class NetworkCatalogRootTree::PasswordRecoveryAction : public NetworkTreeCatalogAuthAction {
+
+public:
+ PasswordRecoveryAction(NetworkAuthenticationManager &mgr);
+ void run();
+ ZLResourceKey key() const;
+};
+
+class NetworkCatalogRootTree::RegisterUserAction : public NetworkTreeCatalogAuthAction {
+
+public:
+ RegisterUserAction(NetworkAuthenticationManager &mgr);
+ void run();
+ ZLResourceKey key() const;
+};
+
+const ZLTypeId NetworkCatalogRootTree::TYPE_ID(NetworkCatalogTree::TYPE_ID);
+
+const ZLTypeId &NetworkCatalogRootTree::typeId() const {
+ return TYPE_ID;
+}
+
+NetworkCatalogRootTree::NetworkCatalogRootTree(RootTree *parent, NetworkLink &link, std::size_t position) :
+ NetworkCatalogTree(parent, link.libraryItem(), position), myLink(link) {
+ init(); //at old version, init is called when node should be painted (and if initialized yet)
+}
+
+void NetworkCatalogRootTree::init() {
+ shared_ptr<NetworkAuthenticationManager> mgr = myLink.authenticationManager();
+ //registerAction(new ExpandCatalogAction(*this));
+ //registerAction(new ReloadAction(*this));
+ if (!mgr.isNull()) {
+ registerAction(new LoginAction(*mgr, this));
+ registerAction(new LogoutAction(*mgr));
+ registerAction(new TopupAccountAction(*mgr));
+
+ if (mgr->registrationSupported()) {
+ registerAction(new RegisterUserAction(*mgr));
+ }
+ if (mgr->passwordRecoverySupported()) {
+ registerAction(new PasswordRecoveryAction(*mgr));
+ }
+ }
+}
+
+const ZLResource &NetworkCatalogRootTree::resource() const {
+ return ZLResource::resource("networkView")["libraryItemRootNode"];
+}
+
+NetworkTreeCatalogAuthAction::NetworkTreeCatalogAuthAction(NetworkAuthenticationManager &mgr, bool forLoggedUsers) : myManager(mgr), myForLoggedUsers(forLoggedUsers) {
+}
+
+bool NetworkTreeCatalogAuthAction::makesSense() const {
+ return (myManager.isAuthorised().Status == B3_FALSE) != myForLoggedUsers;
+}
+
+NetworkCatalogRootTree::LoginAction::LoginAction(NetworkAuthenticationManager &mgr, ZLTreeNode *node) :
+ NetworkTreeCatalogAuthAction(mgr, false), myNode(node) {
+}
+
+ZLResourceKey NetworkCatalogRootTree::LoginAction::key() const {
+ return ZLResourceKey("login");
+}
+
+class LoginActionListener : public ZLNetworkRequest::Listener {
+public:
+ LoginActionListener(NetworkCatalogRootTree::LoginAction &action) : myAction(action) {}
+
+ virtual void finished(const std::string &error) {
+ myAction.onAuthorised(error);
+ }
+
+ virtual void setUIStatus(bool enabled) {
+ if (enabled) {
+ myAction.myNode->notifyDownloadStarted();
+ } else {
+ myAction.myNode->notifyDownloadStopped();
+ }
+ }
+
+private:
+ NetworkCatalogRootTree::LoginAction &myAction;
+};
+
+void NetworkCatalogRootTree::LoginAction::run() {
+ if (!NetworkOperationRunnable::tryConnect()) {
+ return;
+ }
+ AuthenticationDialogManager::authAndInitAsync(
+ myManager,
+ new LoginActionListener(*this)
+ );
+}
+
+void NetworkCatalogRootTree::LoginAction::onAuthorised(const std::string &/*error*/) {
+ myNode->notifyDownloadStopped();
+ NetworkLibrary::Instance().invalidateVisibility();
+ NetworkLibrary::Instance().synchronize();
+ NetworkLibrary::Instance().refresh();
+}
+
+NetworkCatalogRootTree::LogoutAction::LogoutAction(NetworkAuthenticationManager &mgr) : NetworkTreeCatalogAuthAction(mgr, true) {
+}
+
+ZLResourceKey NetworkCatalogRootTree::LogoutAction::key() const {
+ return ZLResourceKey("logout");
+}
+
+std::string NetworkCatalogRootTree::LogoutAction::text(const ZLResource &resource) const {
+ const std::string text = ZLTreeAction::text(resource);
+ return ZLStringUtil::printf(text, myManager.currentUserName());
+}
+
+void NetworkCatalogRootTree::LogoutAction::run() {
+ myManager.logOut();
+ NetworkLibrary::Instance().invalidateVisibility();
+ NetworkLibrary::Instance().synchronize();
+ NetworkLibrary::Instance().refresh();
+}
+
+
+NetworkCatalogRootTree::TopupAccountAction::TopupAccountAction(NetworkAuthenticationManager &mgr) : NetworkTreeCatalogAuthAction(mgr, true) {
+}
+
+ZLResourceKey NetworkCatalogRootTree::TopupAccountAction::key() const {
+ return !myManager.currentAccount().empty() ? ZLResourceKey("topupAccount") : ZLResourceKey("topupAccountUndefined");
+}
+
+std::string NetworkCatalogRootTree::TopupAccountAction::text(const ZLResource &resource) const {
+ const std::string text = ZLTreeAction::text(resource);
+ std::string account = myManager.currentAccount();
+ if (!account.empty() && !myManager.topupAccountLink().empty()) {
+ return ZLStringUtil::printf(text, account);
+ }
+ return text;
+}
+
+void NetworkCatalogRootTree::TopupAccountAction::run() {
+ FBReader::Instance().openLinkInBrowser(myManager.topupAccountLink());
+ NetworkLibrary::Instance().refresh();
+}
+
+bool NetworkCatalogRootTree::TopupAccountAction::makesSense() const {
+ return NetworkTreeCatalogAuthAction::makesSense();
+}
+
+NetworkCatalogRootTree::PasswordRecoveryAction::PasswordRecoveryAction(NetworkAuthenticationManager &mgr) : NetworkTreeCatalogAuthAction(mgr, false) {
+}
+
+ZLResourceKey NetworkCatalogRootTree::PasswordRecoveryAction::key() const {
+ return ZLResourceKey("passwordRecovery");
+}
+
+void NetworkCatalogRootTree::PasswordRecoveryAction::run() {
+ if (!NetworkOperationRunnable::tryConnect()) {
+ return;
+ }
+
+ PasswordRecoveryDialog::run(myManager);
+ FBReader::Instance().refreshWindow();
+ NetworkLibrary::Instance().refresh();
+}
+
+NetworkCatalogRootTree::RegisterUserAction::RegisterUserAction(NetworkAuthenticationManager &mgr) : NetworkTreeCatalogAuthAction(mgr, false) {
+}
+
+ZLResourceKey NetworkCatalogRootTree::RegisterUserAction::key() const {
+ return ZLResourceKey("register");
+}
+
+void NetworkCatalogRootTree::RegisterUserAction::run() {
+ if (!NetworkOperationRunnable::tryConnect()) {
+ return;
+ }
+
+ RegisterUserDialog::run(myManager);
+ FBReader::Instance().refreshWindow();
+ NetworkLibrary::Instance().refresh();
+}
diff --git a/fbreader/src/network/tree/NetworkCatalogTree.cpp b/fbreader/src/network/tree/NetworkCatalogTree.cpp
new file mode 100644
index 0000000..6b6bf6e
--- /dev/null
+++ b/fbreader/src/network/tree/NetworkCatalogTree.cpp
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 <algorithm>
+
+#include <ZLDialogManager.h>
+
+#include "../authentication/NetworkAuthenticationManager.h"
+#include "NetworkCatalogUtil.h"
+#include "../../networkActions/NetworkOperationRunnable.h"
+#include "../NetworkErrors.h"
+#include "NetworkTreeFactory.h"
+#include "../../networkActions/AuthenticationDialogManager.h"
+#include "NetworkTreeNodes.h"
+
+const ZLTypeId NetworkCatalogTree::TYPE_ID(NetworkTree::TYPE_ID);
+
+const ZLTypeId &NetworkCatalogTree::typeId() const {
+ return TYPE_ID;
+}
+
+NetworkCatalogTree::NetworkCatalogTree(RootTree *parent, shared_ptr<NetworkItem> item, std::size_t position) :
+ NetworkTree(parent, position), myItem(item) {
+}
+
+NetworkCatalogTree::NetworkCatalogTree(NetworkCatalogTree *parent, shared_ptr<NetworkItem> item, std::size_t position) :
+ NetworkTree(parent, position), myItem(item) {
+ init();
+}
+
+void NetworkCatalogTree::init() {
+// if (!item().URLByType[NetworkItem::URL_CATALOG].empty()) {
+// registerAction(new ExpandCatalogAction(*this));
+// }
+// const std::string htmlUrl =
+// item().URLByType[NetworkItem::URL_HTML_PAGE];
+// if (!htmlUrl.empty()) {
+// registerAction(new OpenInBrowserAction(htmlUrl));
+// }
+ //registerAction(new ReloadAction(*this));
+}
+
+std::string NetworkCatalogTree::title() const {
+ return myItem->Title;
+}
+
+std::string NetworkCatalogTree::subtitle() const {
+ return ((const NetworkCatalogItem&)*myItem).Summary;
+}
+
+
+shared_ptr<const ZLImage> NetworkCatalogTree::image() const {
+ const std::string &url = myItem->URLByType[NetworkItem::URL_COVER];
+ if (url.empty()) {
+ if (ZLTreeTitledNode* node = zlobject_cast<ZLTreeTitledNode*>(parent())) {
+ return node->image();
+ }
+ }
+ if (myImage.isNull()) {
+ myImage = NetworkCatalogUtil::getAndDownloadImageByUrl(url, this);
+ }
+ return (!myImage.isNull() && myImage->good()) ? myImage : FBTree::defaultCoverImage("booktree-catalog.png");
+}
+
+class AsyncLoadSubCatalogRunnable : public ZLNetworkRequest::Listener {
+
+public:
+ AsyncLoadSubCatalogRunnable(NetworkCatalogTree *tree, bool resumeMode) :
+ myTree(tree), myResumeMode(resumeMode) {
+ myTree->notifyDownloadStarted();
+ if (myResumeMode) {
+ myTree->item().resumeLoading(myChildrens, this);
+ } else {
+ myTree->item().loadChildren(myChildrens, this);
+ }
+ }
+
+ void finished(const std::string &error) {
+ myTree->notifyDownloadStopped();
+ myTree->onChildrenReceived(myChildrens, error);
+ }
+
+ void setUIStatus(bool enabled) {
+ if (enabled) {
+ myTree->notifyDownloadStarted();
+ } else {
+ myTree->notifyDownloadStopped();
+ }
+ }
+
+private:
+ NetworkCatalogTree *myTree;
+ NetworkItem::List myChildrens;
+ bool myResumeMode;
+};
+
+//class NetworkCatalogTreeAuthScope : public ZLUserData {
+//public:
+// shared_ptr<ZLNetworkRequest::Listener> listener;
+//};
+
+class NetworkCatalogTreeAuthListener : public ZLNetworkRequest::Listener {
+public:
+ NetworkCatalogTreeAuthListener(NetworkCatalogTree *tree) : myTree(tree) {
+ }
+
+ void finished(const std::string &error) {
+ myTree->onAuthCheck(error);
+ }
+
+ void setUIStatus(bool enabled) {
+ if (enabled) {
+ myTree->notifyDownloadStarted();
+ } else {
+ myTree->notifyDownloadStopped();
+ }
+ }
+
+private:
+ NetworkCatalogTree *myTree;
+};
+
+void NetworkCatalogTree::requestChildren(shared_ptr<ZLNetworkRequest::Listener> listener) {
+ myListeners.push_back(listener);
+ if (myListeners.size() > 1) {
+ return;
+ }
+
+ const NetworkLink &link = item().Link;
+ shared_ptr<NetworkAuthenticationManager> manager = link.authenticationManager();
+
+ if (item().getVisibility() == B3_UNDEFINED && !manager.isNull()) {
+ AuthenticationDialogManager::authAndInitAsync(*manager, new NetworkCatalogTreeAuthListener(this));
+ return;
+ }
+
+ if (!manager.isNull() && manager->isAuthorised(0).Status == B3_TRUE) {
+ AuthenticationDialogManager::athoriseIfCan(*manager, new NetworkCatalogTreeAuthListener(this));
+ return;
+ }
+ onAuthCheck(std::string());
+}
+
+void NetworkCatalogTree::onAuthCheck(const std::string &error) {
+ if (!error.empty()) {
+ notifyListeners(error);
+ return;
+ }
+
+ if (!myChildrenItems.empty()) {
+ notifyDownloadStopped();
+ notifyListeners(std::string()); //TODO maybe not be silent about auth error here
+ return;
+ }
+ new AsyncLoadSubCatalogRunnable(this, false);
+
+}
+
+void NetworkCatalogTree::requestMoreChildren(shared_ptr<ZLNetworkRequest::Listener> listener) {
+ //TODO does double requesting is processed correct?
+ if (!item().supportsResumeLoading()) {
+ listener->finished();
+ return;
+ }
+ myListeners.push_back(listener);
+ if (myListeners.size() == 1) {
+ new AsyncLoadSubCatalogRunnable(this, true);
+ }
+}
+
+void NetworkCatalogTree::onChildrenReceived(NetworkItem::List &childrens, const std::string &error) {
+ if (!error.empty()) {
+ //special case for authenticationFailed after 'cancel' button pressed in AuthDialog?
+ //TODO maybe it'll be work wrong at some cases? maybe we should have another error this case?
+ if (error != NetworkErrors::errorMessage(NetworkErrors::ERROR_AUTHENTICATION_FAILED)) {
+ NetworkErrors::showErrorMessage(error);
+ }
+ notifyListeners(error);
+ return;
+ }
+
+ myChildrenItems.insert(myChildrenItems.end(), childrens.begin(), childrens.end());
+
+ if (myChildrenItems.empty()) {
+ ZLDialogManager::Instance().informationBox(ZLResourceKey("emptyCatalogBox"));
+ notifyListeners(error);
+ return;
+ }
+
+ bool hasSubcatalogs = false;
+ for (NetworkItem::List::iterator it = myChildrenItems.begin(); it != myChildrenItems.end(); ++it) {
+ if ((*it)->typeId() == NetworkCatalogItem::TYPE_ID) {
+ hasSubcatalogs = true;
+ break;
+ }
+ }
+
+ //TODO rewrite this method
+ if (hasSubcatalogs) {
+ for (NetworkItem::List::iterator it = childrens.begin(); it != childrens.end(); ++it) {
+ NetworkTreeFactory::createNetworkTree(this, *it);
+ }
+ } else {
+ NetworkTreeFactory::fillAuthorTree(this, childrens);
+ }
+ notifyListeners(error);
+
+ this->updated();
+}
+
+void NetworkCatalogTree::notifyListeners(const std::string &error) {
+ for (std::size_t i = 0; i < myListeners.size(); ++i) {
+ if (!myListeners.at(i).isNull())
+ myListeners.at(i)->finished(error);
+ }
+ myListeners.clear();
+}
+
+NetworkCatalogItem &NetworkCatalogTree::item() {
+ return (NetworkCatalogItem&)*myItem;
+}
+
+void NetworkCatalogTree::updateVisibility() {
+ //adding to remove list and clearing all existed nodes
+ List toRemove;
+ NetworkItem::List itemsWithNodes; //used in loop for creating new nodes (for these items new nodes won't be created)
+ for (size_t i = 0; i < children().size(); ++i) {
+ ZLTreeNode* tree = children().at(i);
+ if (!tree->isInstanceOf(NetworkCatalogTree::TYPE_ID)) {
+ continue;
+ }
+ NetworkCatalogTree *child = (NetworkCatalogTree*)tree;
+ itemsWithNodes.push_back(child->myItem);
+ switch (child->item().getVisibility()) {
+ case B3_TRUE:
+ child->updateVisibility();
+ break;
+ case B3_FALSE:
+ toRemove.push_back(child);
+ break;
+ case B3_UNDEFINED:
+ child->clearCatalog();
+ break;
+ }
+ }
+
+ //creating new nodes (if necessary)
+ for (size_t i = 0; i < myChildrenItems.size(); ++i) {
+ shared_ptr<NetworkItem> item = myChildrenItems.at(i);
+ if (!item->isInstanceOf(NetworkCatalogItem::TYPE_ID)) {
+ continue;
+ }
+ if (std::find(itemsWithNodes.begin(), itemsWithNodes.end(), item) != itemsWithNodes.end()) {
+ continue;
+ }
+ NetworkCatalogItem *catalogItem = (NetworkCatalogItem*)(&*item);
+ if (catalogItem->getVisibility() != B3_FALSE) {
+ NetworkTreeFactory::createNetworkTree(this, item, i);
+ }
+ }
+
+ for (size_t i = 0; i < toRemove.size(); ++i) {
+ ZLTreeNode* tree = toRemove.at(i);
+ remove(tree);
+ }
+
+}
+
+void NetworkCatalogTree::clearCatalog() {
+ myChildrenItems.clear();
+ clear();
+}
+
+const ZLResource &NetworkCatalogTree::resource() const {
+ return ZLResource::resource("networkView")["libraryItemNode"];
+}
diff --git a/fbreader/src/network/tree/NetworkCatalogUtil.cpp b/fbreader/src/network/tree/NetworkCatalogUtil.cpp
new file mode 100644
index 0000000..953bf67
--- /dev/null
+++ b/fbreader/src/network/tree/NetworkCatalogUtil.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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 <ZLStringUtil.h>
+#include <ZLNetworkManager.h>
+
+#include <ZLBase64EncodedImage.h>
+#include <ZLNetworkImage.h>
+
+#include "NetworkCatalogUtil.h"
+
+#include "../NetworkLinkCollection.h"
+
+shared_ptr<const ZLImage> NetworkCatalogUtil::getImageByNetworkUrl(const std::string &url, const std::string &prefix) {
+ if (!ZLStringUtil::stringStartsWith(url, prefix)) {
+ return 0;
+ }
+
+ return new ZLNetworkImage(ZLMimeType::IMAGE_AUTO, url);
+}
+
+shared_ptr<const ZLImage> NetworkCatalogUtil::getImageByDataUrl(const std::string &url) {
+ if (!ZLStringUtil::stringStartsWith(url, "data:")) {
+ return 0;
+ }
+
+ std::size_t index = url.find(',');
+ if (index == std::string::npos) {
+ return 0;
+ }
+
+ ZLBase64EncodedImage *image = new ZLBase64EncodedImage(ZLMimeType::IMAGE_AUTO);
+ image->addData(url, index + 1, std::string::npos);
+ return image;
+}
+
+shared_ptr<const ZLImage> NetworkCatalogUtil::getImageByUrl(const std::string &url) {
+ shared_ptr<const ZLImage> image;
+
+ image = getImageByNetworkUrl(url, "http://");
+ if (!image.isNull()) {
+ return image;
+ }
+
+ image = getImageByNetworkUrl(url, "https://");
+ if (!image.isNull()) {
+ return image;
+ }
+
+ return getImageByDataUrl(url);
+}
+
+class NetworkImageDownloadListener : public ZLNetworkRequest::Listener {
+public:
+ NetworkImageDownloadListener(ZLTreeNode *node) : myNode(node) {}
+ void finished(const std::string &error) {
+ if (error.empty()) {
+ myNode->updated();
+ }
+ }
+private:
+ ZLTreeNode *myNode;
+};
+
+shared_ptr<const ZLImage> NetworkCatalogUtil::getAndDownloadImageByUrl(const std::string &url, const ZLTreeNode *node) {
+ shared_ptr<const ZLImage> image = getImageByUrl(url);
+
+ if (!image.isNull()) {
+ shared_ptr<ZLNetworkRequest> downloadRequest = image->synchronizationData();
+ if (!downloadRequest.isNull()) {
+ downloadRequest->setListener(new NetworkImageDownloadListener(const_cast<ZLTreeNode*>(node)));
+ ZLNetworkManager::Instance().performAsync(downloadRequest);
+ }
+ }
+ return image;
+}
diff --git a/fbreader/src/network/tree/NetworkCatalogUtil.h b/fbreader/src/network/tree/NetworkCatalogUtil.h
new file mode 100644
index 0000000..0196896
--- /dev/null
+++ b/fbreader/src/network/tree/NetworkCatalogUtil.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[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.
+ */
+
+#ifndef __NETWORKCATALOGUTIL_H__
+#define __NETWORKCATALOGUTIL_H__
+
+#include <string>
+
+#include <shared_ptr.h>
+
+#include <ZLTreeNode.h>
+
+class ZLImage;
+
+class NetworkCatalogUtil {
+
+public:
+ static shared_ptr<const ZLImage> getImageByUrl(const std::string &url);
+ static shared_ptr<const ZLImage> getAndDownloadImageByUrl(const std::string &url, const ZLTreeNode *node);
+
+private:
+ static shared_ptr<const ZLImage> getImageByNetworkUrl(const std::string &url, const std::string &prefix);
+ static shared_ptr<const ZLImage> getImageByDataUrl(const std::string &url);
+
+private:
+ NetworkCatalogUtil();
+};
+
+#endif /* __NETWORKCATALOGUTIL_H__ */
diff --git a/fbreader/src/network/tree/NetworkLibrary.cpp b/fbreader/src/network/tree/NetworkLibrary.cpp
new file mode 100644
index 0000000..118abd0
--- /dev/null
+++ b/fbreader/src/network/tree/NetworkLibrary.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 <ZLDialogManager.h>
+
+#include "../NetworkLinkCollection.h"
+
+//#include "NetworkNodesFactory.h"
+
+#include "../NetworkItems.h"
+#include "../NetworkLinkCollection.h"
+#include "../NetworkLink.h"
+#include "../SearchResult.h"
+#include "../authentication/NetworkAuthenticationManager.h"
+#include "../../networkActions/NetworkOperationRunnable.h"
+#include "NetworkSearcher.h"
+#include "NetworkTreeNodes.h"
+
+#include "NetworkLibrary.h"
+
+NetworkLibrary *NetworkLibrary::ourInstance = 0;
+
+NetworkLibrary &NetworkLibrary::Instance() {
+ if (ourInstance == 0) {
+ ourInstance = new NetworkLibrary();
+ }
+ return *ourInstance;
+}
+
+NetworkLibrary::NetworkLibrary() {
+ //TODO maybe it should be created in showDialog method?
+ myDialog = ZLDialogManager::Instance().createTreeDialog(ZLResource::resource("networkView"));
+ myRootTree.setDialog(myDialog);
+ myFakeRootTree.setDialog(myDialog);
+ myUpdateVisibility = false;
+ myChildrenAreInvalid = true;
+}
+
+void NetworkLibrary::showDialog() {
+ synchronize();
+ myDialog->run(&myRootTree);
+ myDialog->setSearcher(new NetworkSearcher);
+}
+
+void NetworkLibrary::refresh() {
+ myDialog->onRefresh();
+}
+
+void NetworkLibrary::makeUpToDate() {
+ //TODO rewrite this method
+ NetworkLinkCollection::Instance().initialize();
+ NetworkLinkCollection &collection = NetworkLinkCollection::Instance();
+ for (std::size_t i = 0; i < collection.size(); ++i) {
+ NetworkLink &link = collection.link(i);
+ new NetworkCatalogRootTree(&myRootTree, link, i);
+ }
+}
+
+void NetworkLibrary::updateVisibility() {
+ for (size_t i = 0; i < myRootTree.children().size(); ++i) {
+ ZLTreeNode* tree = myRootTree.children().at(i);
+ if (NetworkCatalogTree* catalogTree = zlobject_cast<NetworkCatalogTree*>(tree)) {
+ catalogTree->updateVisibility();
+ }
+ }
+}
+
+RootTree &NetworkLibrary::getFakeCatalogTree() {
+ return myFakeRootTree;
+}
+
+void NetworkLibrary::synchronize() {
+ if (myChildrenAreInvalid) {
+ myChildrenAreInvalid = false;
+ makeUpToDate();
+ }
+ if (myUpdateVisibility) {
+ myUpdateVisibility = false;
+ updateVisibility();
+ }
+}
+
+void NetworkLibrary::invalidateVisibility() {
+ myUpdateVisibility = true;
+}
diff --git a/fbreader/src/network/tree/NetworkLibrary.h b/fbreader/src/network/tree/NetworkLibrary.h
new file mode 100644
index 0000000..026cbbd
--- /dev/null
+++ b/fbreader/src/network/tree/NetworkLibrary.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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.
+ */
+
+#ifndef __NETWORKLIBRARY_H__
+#define __NETWORKLIBRARY_H__
+
+#include <ZLTreeDialog.h>
+
+#include "NetworkTreeNodes.h"
+
+class NetworkLibrary {
+
+public:
+ static NetworkLibrary &Instance();
+
+private:
+ static NetworkLibrary *ourInstance;
+
+public:
+ void showDialog();
+ void refresh();
+ RootTree &getFakeCatalogTree();
+
+ void synchronize();
+ void invalidateVisibility();
+
+private:
+ NetworkLibrary();
+ void makeUpToDate();
+
+ void updateVisibility();
+
+private:
+ shared_ptr<ZLTreeDialog> myDialog;
+ RootTree myRootTree;
+ RootTree myFakeRootTree;
+ bool myUpdateVisibility;
+ bool myChildrenAreInvalid;
+};
+
+#endif /* __NETWORKLIBRARY_H__ */
diff --git a/fbreader/src/network/tree/NetworkSearcher.cpp b/fbreader/src/network/tree/NetworkSearcher.cpp
new file mode 100644
index 0000000..10d318e
--- /dev/null
+++ b/fbreader/src/network/tree/NetworkSearcher.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 <ZLNetworkManager.h>
+#include <ZLDialogManager.h>
+#include <ZLTimeManager.h>
+
+#include "../authentication/NetworkAuthenticationManager.h"
+#include "../../networkActions/NetworkOperationRunnable.h"
+#include "../NetworkLinkCollection.h"
+#include "../NetworkLink.h"
+#include "../NetworkOperationData.h"
+#include "../NetworkErrors.h"
+#include "NetworkTreeNodes.h"
+#include "NetworkLibrary.h"
+#include "NetworkSearcher.h"
+
+//TODO rewrite code to not to use fake network link
+
+NetworkSearcher::NetworkSearcher() { }
+
+void NetworkSearcher::simpleSearch(const std::string &pattern) {
+ //TODO maybe move code for simple search from NetworkLinkCollection to here
+ NetworkCatalogTree *tree = new SearchCatalogTree(&NetworkLibrary::Instance().getFakeCatalogTree(), new AllCatalogsSearchItem(myFakeLink, pattern));
+ tree->expand();
+}
+
+AllCatalogsSearchItem::AllCatalogsSearchItem(const NetworkLink &link, const std::string &pattern) :
+ NetworkCatalogItem(link, std::string(), std::string(), UrlInfoCollection()),
+ myPattern(pattern) {
+}
+
+class AllCatalogsSearchItemListener : public ZLNetworkRequest::Listener {
+public:
+ AllCatalogsSearchItemListener(AllCatalogsSearchItem &item,
+ NetworkItem::List &children,
+ shared_ptr<ZLNetworkRequest::Listener> listener,
+ ZLNetworkRequest::Vector requestList,
+ std::vector<shared_ptr<NetworkOperationData> > dataList) :
+ myItem(item),
+ myChildren(children),
+ myListener(listener),
+ myDataList(dataList),
+ myHolder(this) {
+ myItemFound = false;
+ myCollection = new NetworkBookCollection;
+ myCounter = 0;
+ performRequests(requestList);
+ }
+
+ void performRequests(ZLNetworkRequest::Vector requestList) {
+ for (std::size_t i = 0; i < requestList.size(); ++i) {
+ shared_ptr<ZLNetworkRequest> request = requestList.at(i);
+ request->setListener(myHolder);
+ ++myCounter;
+ ZLNetworkManager::Instance().performAsync(request);
+ }
+ }
+
+ void finished(const std::string &error) {
+ --myCounter;
+
+ ZLNetworkRequest::Vector requestList;
+
+ for (std::size_t i = 0; i < myDataList.size(); ++i) {
+ shared_ptr<NetworkOperationData> data = myDataList.at(i);
+ for (std::size_t j = 0; j < data->Items.size(); ++j) {
+ myCollection->addBook(data->Items.at(j));
+ }
+
+ if (!data->Items.empty()) {
+ shared_ptr<ZLNetworkRequest> request = data->resume();
+ if (!request.isNull()) {
+ request->setListener(myHolder);
+ requestList.push_back(request);
+ }
+ }
+ }
+
+
+ if (!myCollection->books().empty()) {
+ myItem.onChildrenLoaded(myChildren, myCollection, myListener);
+ myChildren.clear();
+ myCollection->clear();
+ }
+
+ if (!requestList.empty()) {
+ performRequests(requestList);
+ }
+
+ if (myCounter == 0) {
+ ZLTimeManager::deleteLater(myHolder);
+ myHolder.reset(); //destroy itself
+ }
+ }
+
+private:
+ AllCatalogsSearchItem &myItem;
+ NetworkItem::List &myChildren;
+ shared_ptr<ZLNetworkRequest::Listener> myListener;
+ shared_ptr<NetworkBookCollection> myCollection; //TODO maybe remove this class using
+
+ bool myItemFound;
+
+ std::vector<shared_ptr<NetworkOperationData> > myDataList;
+ int myCounter;
+// std::string myErrorMessage;
+ shared_ptr<ZLNetworkRequest::Listener> myHolder; //for keeping this instance alive
+};
+
+std::string AllCatalogsSearchItem::loadChildren(NetworkItem::List &children, shared_ptr<ZLNetworkRequest::Listener> listener) {
+ ZLNetworkRequest::Vector requestList;
+ std::vector<shared_ptr<NetworkOperationData> > dataList;
+
+ const NetworkLinkCollection::LinkVector &links = NetworkLinkCollection::Instance().activeLinks();
+ for (std::size_t i = 0; i < links.size(); ++i) {
+ const NetworkLink &link = *links.at(i);
+ shared_ptr<NetworkOperationData> data = new NetworkOperationData(link);
+
+ shared_ptr<ZLNetworkRequest> request = link.simpleSearchData(*data, myPattern);
+ if (!request.isNull()) {
+ dataList.push_back(data);
+ requestList.push_back(request);
+ }
+ }
+
+ new AllCatalogsSearchItemListener(*this, children, listener, requestList, dataList);
+
+ return std::string();
+}
+
+void AllCatalogsSearchItem::onChildrenLoaded(NetworkItem::List &children, shared_ptr<NetworkBookCollection> collection, shared_ptr<ZLNetworkRequest::Listener> listener) {
+ if (!collection.isNull()) {
+ const NetworkItem::List &books = collection->books();
+ children.assign(books.begin(), books.end());
+ }
+ listener->finished();
+}
+
+FakeNetworkLink::FakeNetworkLink() : NetworkLink("") { }
+
+shared_ptr<ZLNetworkRequest> FakeNetworkLink::simpleSearchData(NetworkOperationData &/*data*/, const std::string &/*pattern*/) const {
+ return 0;
+}
+
+shared_ptr<ZLNetworkRequest> FakeNetworkLink::advancedSearchData(NetworkOperationData &/*data*/, const std::string &/*titleAndSeries*/, const std::string &/*author*/, const std::string &/*tag*/, const std::string &/*annotation*/) const {
+ return 0;
+}
+
+shared_ptr<ZLNetworkRequest> FakeNetworkLink::resume(NetworkOperationData &/*data*/) const {
+ return 0;
+}
+
+shared_ptr<NetworkAuthenticationManager> FakeNetworkLink::authenticationManager() const {
+ return 0;
+}
+
+shared_ptr<NetworkItem> FakeNetworkLink::libraryItem() const {
+ return 0;
+}
+
+void FakeNetworkLink::rewriteUrl(std::string &/*url*/, bool /*isUrlExternal*/) const {
+}
diff --git a/fbreader/src/network/tree/NetworkSearcher.h b/fbreader/src/network/tree/NetworkSearcher.h
new file mode 100644
index 0000000..08ebc35
--- /dev/null
+++ b/fbreader/src/network/tree/NetworkSearcher.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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.
+ */
+
+#ifndef __NETWORKSEARCHER_H__
+#define __NETWORKSEARCHER_H__
+
+#include <ZLTreeSearcher.h>
+
+#include "../NetworkBookCollection.h"
+#include "../NetworkItems.h"
+
+//TODO rewrite code to not to use fake network link
+class FakeNetworkLink : public NetworkLink {
+public:
+ FakeNetworkLink();
+ shared_ptr<ZLNetworkRequest> simpleSearchData(NetworkOperationData &data, const std::string &pattern) const;
+ shared_ptr<ZLNetworkRequest> advancedSearchData(NetworkOperationData &data, const std::string &titleAndSeries, const std::string &author, const std::string &tag, const std::string &annotation) const;
+ shared_ptr<ZLNetworkRequest> resume(NetworkOperationData &data) const;
+ shared_ptr<NetworkAuthenticationManager> authenticationManager() const;
+ shared_ptr<NetworkItem> libraryItem() const;
+ void rewriteUrl(std::string &url, bool isUrlExternal = false) const;
+};
+
+class NetworkSearcher : public ZLTreeSearcher {
+public:
+ NetworkSearcher();
+ void simpleSearch(const std::string &pattern);
+private:
+ const FakeNetworkLink myFakeLink;
+};
+
+class AllCatalogsSearchItem : public NetworkCatalogItem {
+
+public:
+ AllCatalogsSearchItem(const NetworkLink &link, const std::string &pattern);
+ std::string loadChildren(List &children, shared_ptr<ZLNetworkRequest::Listener> listener);
+ void onChildrenLoaded(List &children, shared_ptr<NetworkBookCollection> collection, shared_ptr<ZLNetworkRequest::Listener> listener);
+
+private:
+ std::string myPattern;
+};
+
+#endif /* __NETWORKSEARCHER_H__ */
diff --git a/fbreader/src/network/tree/NetworkSeriesTree.cpp b/fbreader/src/network/tree/NetworkSeriesTree.cpp
new file mode 100644
index 0000000..4456ade
--- /dev/null
+++ b/fbreader/src/network/tree/NetworkSeriesTree.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 <set>
+#include <algorithm>
+
+#include <ZLResource.h>
+#include <ZLImage.h>
+#include <ZLStringUtil.h>
+
+#include "NetworkCatalogUtil.h"
+#include "NetworkTreeNodes.h"
+
+const ZLTypeId NetworkSeriesTree::TYPE_ID(NetworkTree::TYPE_ID);
+
+const ZLTypeId &NetworkSeriesTree::typeId() const {
+ return TYPE_ID;
+}
+
+const ZLResource &NetworkSeriesTree::resource() const {
+ return ZLResource::resource("networkView")["seriesNode"];
+}
+
+NetworkSeriesTree::NetworkSeriesTree(NetworkTree *parent, const std::string &seriesTitle) :
+ NetworkTree(parent), mySeriesTitle(seriesTitle) {
+ init();
+}
+
+void NetworkSeriesTree::init() {
+ //registerExpandTreeAction();
+}
+
+std::string NetworkSeriesTree::title() const {
+ return mySeriesTitle;
+}
+
+std::string NetworkSeriesTree::subtitle() const {
+ return ZLStringUtil::printf(resource()["booksCount"].value((int)children().size()), (unsigned int)children().size());
+}
+
+static const size_t MAX_BATCH_SIZE = 6;
+
+shared_ptr<const ZLImage> NetworkSeriesTree::image() const {
+ if (myImages.empty()) {
+ for (size_t i = 0; i < std::min(children().size(), MAX_BATCH_SIZE); ++i) {
+ NetworkBookTree *bookTree = zlobject_cast<NetworkBookTree*>(children().at(i));
+ if (!bookTree) {
+ continue;
+ }
+ NetworkItem::UrlInfoCollection urlByType = bookTree->book().URLByType;
+ std::string url = urlByType[NetworkItem::URL_COVER];
+ myImages.push_back(NetworkCatalogUtil::getAndDownloadImageByUrl(url, this));
+ }
+ }
+ return ZLImageManager::Instance().makeBatchImage(myImages, FBTree::defaultCoverImage("booktree-book.png"));
+}
diff --git a/fbreader/src/network/tree/NetworkTree.cpp b/fbreader/src/network/tree/NetworkTree.cpp
new file mode 100644
index 0000000..ac7b39a
--- /dev/null
+++ b/fbreader/src/network/tree/NetworkTree.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 "NetworkTreeNodes.h"
+
+const ZLTypeId NetworkTree::TYPE_ID(FBTree::TYPE_ID);
+
+const ZLTypeId &NetworkTree::typeId() const {
+ return TYPE_ID;
+}
+
+
+NetworkTree::NetworkTree(RootTree *parent, std::size_t position) : FBTree(parent, position) { }
+
+NetworkTree::NetworkTree(NetworkTree *parent, std::size_t position) : FBTree(parent, position) { }
diff --git a/fbreader/src/network/tree/NetworkTreeFactory.cpp b/fbreader/src/network/tree/NetworkTreeFactory.cpp
new file mode 100644
index 0000000..0868034
--- /dev/null
+++ b/fbreader/src/network/tree/NetworkTreeFactory.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 "NetworkTreeFactory.h"
+
+#include "NetworkTreeNodes.h"
+
+#include "../NetworkBookCollection.h"
+
+NetworkTreeFactory::NetworkTreeFactory() {
+}
+
+ZLTreeTitledNode *NetworkTreeFactory::createNetworkTree(NetworkCatalogTree *parent, shared_ptr<NetworkItem> item, std::size_t position) {
+ if (item->isInstanceOf(NetworkCatalogItem::TYPE_ID)) {
+ NetworkCatalogItem *catalogItem = (NetworkCatalogItem*)(&*item);
+ if (catalogItem->getVisibility() == B3_FALSE) {
+ return 0;
+ }
+ NetworkCatalogTree *ptr = new NetworkCatalogTree(parent, item, position);
+ ptr->item().onDisplayItem();
+ return ptr;
+ } else if (item->isInstanceOf(NetworkBookItem::TYPE_ID)) {
+ return new NetworkBookTree(parent, item, NetworkBookTree::AUTHORS);
+ }
+ return 0;
+}
+
+void NetworkTreeFactory::fillAuthorTree(NetworkTree *parent, const NetworkItem::List &books) {
+ NetworkSeriesTree *seriesTree = 0;
+ NetworkAuthorTree *authorTree = 0;
+
+ int flags = NetworkCatalogItem::FLAGS_DEFAULT;
+ if (NetworkCatalogTree* catalogTree = zlobject_cast<NetworkCatalogTree*>(parent)) {
+ flags = catalogTree->item().getFlags();
+ }
+ NetworkBookTree::SummaryType booksSummaryType = NetworkBookTree::AUTHORS;
+ if ((parent->isInstanceOf(NetworkCatalogTree::TYPE_ID) &&
+ (flags & NetworkCatalogItem::FLAG_SHOW_AUTHOR) == 0) ||
+ parent->isInstanceOf(NetworkAuthorTree::TYPE_ID)) {
+ booksSummaryType = NetworkBookTree::NONE;
+ }
+
+ for (NetworkItem::List::const_iterator it = books.begin(); it != books.end(); ++it) {
+ if (!(*it)->isInstanceOf(NetworkBookItem::TYPE_ID)) {
+ continue;
+ }
+ const NetworkBookItem &book = (const NetworkBookItem &) **it;
+
+ //TODO split this method on smaller parts
+ switch (flags & NetworkCatalogItem::FLAGS_GROUP) {
+ case NetworkCatalogItem::FLAG_GROUP_BY_SERIES:
+ if (book.SeriesTitle.empty()) {
+ new NetworkBookTree(parent, *it, booksSummaryType);
+ } else {
+ if (seriesTree == 0 || seriesTree->title() != book.SeriesTitle) {
+ seriesTree = new NetworkSeriesTree(parent, book.SeriesTitle);
+ }
+ new NetworkBookTree(seriesTree, *it, booksSummaryType);
+ }
+ break;
+ case NetworkCatalogItem::FLAG_GROUP_MORE_THAN_1_BOOK_BY_SERIES:
+ {
+ std::string seriesTitle = book.SeriesTitle;
+ if (!seriesTitle.empty() && (seriesTree == 0 || seriesTree->title() != seriesTitle)) {
+ NetworkItem::List::const_iterator jt = it + 1;
+ while (jt != books.end() && !(*jt)->isInstanceOf(NetworkBookItem::TYPE_ID)) {
+ ++jt;
+ }
+ if (jt == books.end()) {
+ seriesTitle.clear();
+ } else {
+ const NetworkBookItem &next = (const NetworkBookItem&)**jt;
+ if (next.SeriesTitle != seriesTitle) {
+ seriesTitle.clear();
+ }
+ }
+ }
+ if (seriesTitle.empty()) {
+ seriesTree = 0;
+ new NetworkBookTree(parent, *it, booksSummaryType);
+ } else {
+ if (seriesTree == 0 || seriesTree->title() != seriesTitle) {
+ seriesTree = new NetworkSeriesTree(parent, seriesTitle);
+ }
+ new NetworkBookTree(seriesTree, *it, booksSummaryType);
+ }
+ }
+ break;
+ case NetworkCatalogItem::FLAG_GROUP_BY_AUTHOR:
+ if (book.Authors.empty()) {
+ new NetworkBookTree(parent, *it, booksSummaryType);
+ } else {
+ const NetworkBookItem::AuthorData &author = book.Authors.front();
+ if (authorTree == 0 || authorTree->author() != author) {
+ authorTree = new NetworkAuthorTree(parent, author);
+ }
+ new NetworkBookTree(authorTree, *it, booksSummaryType);
+ }
+ break;
+ default:
+ new NetworkBookTree(parent, *it, booksSummaryType);
+ break;
+ }
+
+
+ }
+}
diff --git a/fbreader/src/network/tree/NetworkTreeFactory.h b/fbreader/src/network/tree/NetworkTreeFactory.h
new file mode 100644
index 0000000..b53213e
--- /dev/null
+++ b/fbreader/src/network/tree/NetworkTreeFactory.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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.
+ */
+
+#ifndef __NETWORKTREEFACTORY_H__
+#define __NETWORKTREEFACTORY_H__
+
+#include "../NetworkItems.h"
+
+class NetworkBookCollection;
+class FBTree;
+class NetworkCatalogTree;
+class NetworkTree;
+class ZLTreeTitledNode;
+
+
+class NetworkTreeFactory {
+
+private:
+ NetworkTreeFactory();
+
+public:
+ static ZLTreeTitledNode *createNetworkTree(NetworkCatalogTree *parent, shared_ptr<NetworkItem> item, std::size_t position = (std::size_t)-1);
+ static void fillAuthorTree(NetworkTree *parent, const NetworkItem::List &books);
+};
+
+#endif /* __NETWORKTREEFACTORY_H__ */
diff --git a/fbreader/src/network/tree/NetworkTreeNodes.h b/fbreader/src/network/tree/NetworkTreeNodes.h
new file mode 100644
index 0000000..fcc76f6
--- /dev/null
+++ b/fbreader/src/network/tree/NetworkTreeNodes.h
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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.
+ */
+
+#ifndef __NETWORKTREENODES_H__
+#define __NETWORKTREENODES_H__
+
+#include <ZLResource.h>
+#include <ZLExecutionUtil.h>
+
+#include <ZLTreeNode.h>
+#include <ZLTreeDialog.h>
+#include <ZLTreePageNode.h>
+
+#include "../NetworkLink.h"
+#include "../../tree/FBTree.h"
+
+//maybe RootTree should be nested class for NetworkLibrary?
+class RootTree : public ZLTreeNode {
+
+public:
+ static const ZLTypeId TYPE_ID;
+
+private:
+ const ZLTypeId &typeId() const;
+
+public:
+ RootTree();
+ void setDialog(shared_ptr<ZLTreeDialog> dialog);
+
+
+protected:
+ ZLTreeListener *listener() const;
+
+private:
+ shared_ptr<ZLTreeDialog> myListener;
+};
+
+class NetworkTree : public FBTree {
+
+public:
+ static const ZLTypeId TYPE_ID;
+
+private:
+ const ZLTypeId &typeId() const;
+
+public:
+ NetworkTree(RootTree *parent, std::size_t position);
+ NetworkTree(NetworkTree *parent, std::size_t position = (std::size_t)-1);
+};
+
+class NetworkCatalogTree : public NetworkTree {
+
+public:
+ static const ZLTypeId TYPE_ID;
+
+private:
+ const ZLTypeId &typeId() const;
+
+public:
+ NetworkCatalogTree(RootTree *parent, shared_ptr<NetworkItem> item, std::size_t position = (std::size_t)-1);
+ NetworkCatalogTree(NetworkCatalogTree *parent, shared_ptr<NetworkItem> item, std::size_t position = (std::size_t)-1);
+
+ std::string title() const;
+ std::string subtitle() const;
+ shared_ptr<const ZLImage> image() const;
+
+ void requestChildren(shared_ptr<ZLNetworkRequest::Listener> listener);
+ void requestMoreChildren(shared_ptr<ZLNetworkRequest::Listener> listener);
+ virtual void onChildrenReceived(NetworkItem::List &childrens, const std::string &error);
+
+ NetworkCatalogItem &item();
+
+ void updateVisibility();
+ void clearCatalog();
+
+private:
+ void init();
+ void notifyListeners(const std::string &error);
+
+private:
+ void onAuthCheck(const std::string &error);
+
+private:
+ const ZLResource &resource() const;
+
+private:
+ shared_ptr<NetworkItem> myItem;
+ NetworkItem::List myChildrenItems;
+
+ std::vector<shared_ptr<ZLNetworkRequest::Listener> > myListeners;
+ mutable shared_ptr<const ZLImage> myImage;
+
+friend class NetworkTreeFactory;
+friend class NetworkCatalogTreeAuthListener;
+};
+
+class NetworkCatalogRootTree : public NetworkCatalogTree {
+
+public:
+ static const ZLTypeId TYPE_ID;
+
+private:
+ const ZLTypeId &typeId() const;
+
+public:
+ class LoginAction;
+ class LogoutAction;
+ class TopupAccountAction;
+ class PasswordRecoveryAction;
+ class RegisterUserAction;
+
+public:
+ NetworkCatalogRootTree(RootTree *parent, NetworkLink &link, std::size_t position);
+ void init();
+
+private:
+ const ZLResource &resource() const;
+
+private:
+ NetworkLink &myLink;
+};
+
+class SearchCatalogTree : public NetworkCatalogTree {
+
+public:
+ static const ZLTypeId TYPE_ID;
+
+private:
+ const ZLTypeId &typeId() const;
+
+public:
+ SearchCatalogTree(RootTree *parent, shared_ptr<NetworkItem> item, std::size_t position = (std::size_t)-1);
+
+ void requestChildren(shared_ptr<ZLNetworkRequest::Listener> listener);
+ void onChildrenReceived(NetworkItem::List &childrens, const std::string &error);
+};
+
+class NetworkAuthorTree : public NetworkTree {
+
+public:
+ static const ZLTypeId TYPE_ID;
+
+private:
+ const ZLTypeId &typeId() const;
+
+protected:
+ NetworkAuthorTree(NetworkTree *parent, const NetworkBookItem::AuthorData &author);
+
+friend class NetworkTreeFactory;
+
+public:
+ const NetworkBookItem::AuthorData &author();
+
+private:
+ void init();
+ const ZLResource &resource() const;
+ shared_ptr<const ZLImage> image() const;
+ std::string title() const;
+
+private:
+ NetworkBookItem::AuthorData myAuthor;
+};
+
+class NetworkSeriesTree : public NetworkTree {
+
+public:
+ static const ZLTypeId TYPE_ID;
+
+private:
+ const ZLTypeId &typeId() const;
+
+protected:
+ NetworkSeriesTree(NetworkTree *parent, const std::string &seriesTitle);
+
+friend class NetworkTreeFactory;
+
+private:
+ void init();
+ const ZLResource &resource() const;
+ shared_ptr<const ZLImage> image() const;
+ std::string title() const;
+ std::string subtitle() const;
+
+private:
+ std::string mySeriesTitle;
+ mutable std::vector<shared_ptr<const ZLImage> > myImages;
+};
+
+class NetworkBookTree : public ZLTreePageNode {
+
+public:
+ static const ZLTypeId TYPE_ID;
+
+private:
+ const ZLTypeId &typeId() const;
+
+public:
+ enum SummaryType { AUTHORS, NONE };
+
+private:
+ NetworkBookTree(NetworkTree *parent, shared_ptr<NetworkItem> book, SummaryType summaryType);
+ void init();
+
+friend class NetworkTreeFactory;
+
+public:
+ const NetworkBookItem &book() const;
+
+public:
+ const ZLResource &resource() const;
+ shared_ptr<const ZLImage> image() const;
+ shared_ptr<const ZLImage> fullImage() const;
+ std::string title() const;
+ std::string subtitle() const;
+
+ shared_ptr<ZLTreePageInfo> getPageInfo();
+
+private:
+ class BookItemWrapper : public ZLTreePageInfo {
+
+ public:
+ BookItemWrapper(NetworkBookTree &tree, shared_ptr<NetworkItem> bookItem);
+
+ bool isPageInfoLoaded();
+ void loadAll(shared_ptr<ZLNetworkRequest::Listener> listener);
+ void onInformationLoaded(ZLUserDataHolder &data, const std::string &error);
+ void onCoverLoaded(ZLUserDataHolder &data, const std::string &error);
+
+ public:
+ std::string title() const;
+ std::vector<std::string> authors() const;
+ std::vector<std::string> tags() const;
+ std::string summary() const;
+ shared_ptr<const ZLImage> image() const;
+
+ //TODO maybe store actions in other place?
+ const std::vector<shared_ptr<ZLTreeAction> > &actions() const;
+ std::string actionText(const shared_ptr<ZLTreeAction> &action) const;
+ const std::vector<shared_ptr<ZLTreeAction> > relatedActions() const;
+
+ private:
+ NetworkBookItem &book() const;
+
+ private:
+ NetworkBookTree &myTree;
+ shared_ptr<NetworkItem> myBookItem;
+ mutable bool myIsInitialized;
+
+ mutable std::vector<shared_ptr<ZLTreeAction> > myRelatedActions;
+ };
+
+private:
+ shared_ptr<NetworkItem> myBook;
+ SummaryType mySummaryType;
+ mutable shared_ptr<const ZLImage> myImage;
+ shared_ptr<ZLTreePageInfo> myPageInfo;
+};
+
+#endif /* __NETWORKTREENODES_H__ */
diff --git a/fbreader/src/network/tree/RootTree.cpp b/fbreader/src/network/tree/RootTree.cpp
new file mode 100644
index 0000000..8aad8a5
--- /dev/null
+++ b/fbreader/src/network/tree/RootTree.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 "NetworkTreeNodes.h"
+
+const ZLTypeId RootTree::TYPE_ID(ZLTreeNode::TYPE_ID);
+
+const ZLTypeId &RootTree::typeId() const {
+ return TYPE_ID;
+}
+
+
+RootTree::RootTree() {
+
+}
+
+void RootTree::setDialog(shared_ptr<ZLTreeDialog> dialog) {
+ myListener = dialog;
+}
+
+ZLTreeListener *RootTree::listener() const {
+ if (myListener.isNull()) {
+ return 0;
+ }
+ return &(*myListener);
+}
diff --git a/fbreader/src/network/tree/SearchCatalogTree.cpp b/fbreader/src/network/tree/SearchCatalogTree.cpp
new file mode 100644
index 0000000..62ee967
--- /dev/null
+++ b/fbreader/src/network/tree/SearchCatalogTree.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <[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 "NetworkTreeNodes.h"
+
+const ZLTypeId SearchCatalogTree::TYPE_ID(NetworkCatalogTree::TYPE_ID);
+
+const ZLTypeId &SearchCatalogTree::typeId() const {
+ return TYPE_ID;
+}
+
+SearchCatalogTree::SearchCatalogTree(RootTree *parent, shared_ptr<NetworkItem> item, std::size_t position) :
+ NetworkCatalogTree(parent, item, position) {
+ //TODO maybe remove this class
+}
+
+void SearchCatalogTree::requestChildren(shared_ptr<ZLNetworkRequest::Listener> listener) {
+ notifySearchStarted();
+ NetworkCatalogTree::requestChildren(listener);
+}
+
+void SearchCatalogTree::onChildrenReceived(NetworkItem::List &childrens, const std::string &error) {
+ notifySearchStopped();
+ NetworkCatalogTree::onChildrenReceived(childrens, error);
+}