mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-08-18 19:08:35 -04:00
FeedReader:
- Added error handling to xml functions - Added xslt transformation - Added retransform of existing messages - Redesigned preview dialog - Enabled embed images for forum feeds - Changed config format, switching back to an older version results in a loss of all data of the FeedReader Added new base class RSPlainTextEdit with placeholder text. New library libxslt needed git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@6081 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
919fb3f62d
commit
ef49000b9a
28 changed files with 1549 additions and 849 deletions
|
@ -88,8 +88,10 @@ static void feedToInfo(const RsFeedReaderFeed *feed, FeedInfo &info)
|
|||
info.errorState = feed->errorState;
|
||||
info.errorString = feed->errorString;
|
||||
|
||||
info.transformationType = feed->transformationType;
|
||||
info.xpathsToUse = feed->xpathsToUse.ids;
|
||||
info.xpathsToRemove = feed->xpathsToRemove.ids;
|
||||
info.xslt = feed->xslt;
|
||||
|
||||
info.flag.folder = (feed->flag & RS_FEED_FLAG_FOLDER);
|
||||
info.flag.infoFromFeed = (feed->flag & RS_FEED_FLAG_INFO_FROM_FEED);
|
||||
|
@ -144,8 +146,10 @@ static void infoToFeed(const FeedInfo &info, RsFeedReaderFeed *feed, bool add)
|
|||
feed->forumId = info.forumId;
|
||||
}
|
||||
|
||||
feed->transformationType = info.transformationType;
|
||||
feed->xpathsToUse.ids = info.xpathsToUse;
|
||||
feed->xpathsToRemove.ids = info.xpathsToRemove;
|
||||
feed->xslt = info.xslt;
|
||||
|
||||
// feed->preview = info.flag.preview;
|
||||
|
||||
|
@ -200,6 +204,7 @@ static void feedMsgToInfo(const RsFeedReaderMsg *msg, FeedMsgInfo &info)
|
|||
info.link = msg->link;
|
||||
info.author = msg->author;
|
||||
info.description = msg->description;
|
||||
info.descriptionTransformed = msg->descriptionTransformed;
|
||||
info.pubDate = msg->pubDate;
|
||||
|
||||
info.flag.isnew = (msg->flag & RS_FEEDMSG_FLAG_NEW);
|
||||
|
@ -491,6 +496,7 @@ RsFeedAddResult p3FeedReader::setFeed(const std::string &feedId, const FeedInfo
|
|||
forumId = fi->forumId;
|
||||
librs::util::ConvertUtf8ToUtf16(fi->name, forumInfo.forumName);
|
||||
librs::util::ConvertUtf8ToUtf16(fi->description, forumInfo.forumDesc);
|
||||
forumInfo.forumName.insert(0, FEEDREADER_FORUM_PREFIX);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -759,8 +765,11 @@ bool p3FeedReader::removeMsg(const std::string &feedId, const std::string &msgId
|
|||
return false;
|
||||
}
|
||||
|
||||
msgIt->second->flag |= RS_FEEDMSG_FLAG_DELETED | RS_FEEDMSG_FLAG_READ;
|
||||
msgIt->second->flag &= ~RS_FEEDMSG_FLAG_NEW;
|
||||
RsFeedReaderMsg *mi = msgIt->second;
|
||||
mi->flag |= RS_FEEDMSG_FLAG_DELETED | RS_FEEDMSG_FLAG_READ;
|
||||
mi->flag &= ~RS_FEEDMSG_FLAG_NEW;
|
||||
mi->description.clear();
|
||||
mi->descriptionTransformed.clear();
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
|
@ -805,8 +814,11 @@ bool p3FeedReader::removeMsgs(const std::string &feedId, const std::list<std::st
|
|||
continue;
|
||||
}
|
||||
|
||||
msgIt->second->flag |= RS_FEEDMSG_FLAG_DELETED | RS_FEEDMSG_FLAG_READ;
|
||||
msgIt->second->flag &= ~RS_FEEDMSG_FLAG_NEW;
|
||||
RsFeedReaderMsg *mi = msgIt->second;
|
||||
mi->flag |= RS_FEEDMSG_FLAG_DELETED | RS_FEEDMSG_FLAG_READ;
|
||||
mi->flag &= ~RS_FEEDMSG_FLAG_NEW;
|
||||
mi->description.clear();
|
||||
mi->descriptionTransformed.clear();
|
||||
|
||||
removedMsgs.push_back(*idIt);
|
||||
}
|
||||
|
@ -1121,11 +1133,74 @@ bool p3FeedReader::setMessageRead(const std::string &feedId, const std::string &
|
|||
return true;
|
||||
}
|
||||
|
||||
bool p3FeedReader::retransformMsg(const std::string &feedId, const std::string &msgId)
|
||||
{
|
||||
bool msgChanged = false;
|
||||
bool feedChanged = false;
|
||||
|
||||
{
|
||||
RsStackMutex stack(mFeedReaderMtx); /******* LOCK STACK MUTEX *********/
|
||||
|
||||
std::map<std::string, RsFeedReaderFeed*>::iterator feedIt = mFeeds.find(feedId);
|
||||
if (feedIt == mFeeds.end()) {
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReader::setMessageRead - feed " << feedId << " not found" << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
RsFeedReaderFeed *fi = feedIt->second;
|
||||
|
||||
std::map<std::string, RsFeedReaderMsg*>::iterator msgIt;
|
||||
msgIt = fi->msgs.find(msgId);
|
||||
if (msgIt == fi->msgs.end()) {
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReader::setMessageRead - msg " << msgId << " not found" << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
RsFeedReaderMsg *mi = msgIt->second;
|
||||
|
||||
std::string errorString;
|
||||
std::string descriptionTransformed = mi->descriptionTransformed;
|
||||
if (p3FeedReaderThread::processTransformation(*fi, mi, errorString) == RS_FEED_ERRORSTATE_OK) {
|
||||
if (mi->descriptionTransformed != descriptionTransformed) {
|
||||
msgChanged = true;
|
||||
}
|
||||
} else {
|
||||
if (!errorString.empty()) {
|
||||
fi->errorString = errorString;
|
||||
feedChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (feedChanged || msgChanged) {
|
||||
IndicateConfigChanged();
|
||||
if (mNotify) {
|
||||
if (feedChanged) {
|
||||
mNotify->notifyFeedChanged(feedId, NOTIFY_TYPE_MOD);
|
||||
}
|
||||
if (msgChanged) {
|
||||
mNotify->notifyMsgChanged(feedId, msgId, NOTIFY_TYPE_MOD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RsFeedReaderErrorState p3FeedReader::processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, std::string &description, std::string &errorString)
|
||||
{
|
||||
return p3FeedReaderThread::processXPath(xpathsToUse, xpathsToRemove, description, errorString);
|
||||
}
|
||||
|
||||
RsFeedReaderErrorState p3FeedReader::processXslt(const std::string &xslt, std::string &description, std::string &errorString)
|
||||
{
|
||||
return p3FeedReaderThread::processXslt(xslt, description, errorString);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/****************************** p3Service **********************************/
|
||||
/***************************************************************************/
|
||||
|
@ -1776,7 +1851,8 @@ void p3FeedReader::onProcessSuccess_addMsgs(const std::string &feedId, std::list
|
|||
if (forum) {
|
||||
miNew->flag = RS_FEEDMSG_FLAG_DELETED;
|
||||
forumMsgs.push_back(*miNew);
|
||||
// miNew->description.clear();
|
||||
miNew->description.clear();
|
||||
miNew->descriptionTransformed.clear();
|
||||
} else {
|
||||
miNew->flag = RS_FEEDMSG_FLAG_NEW;
|
||||
addedMsgs.push_back(miNew->msgId);
|
||||
|
@ -1816,7 +1892,7 @@ void p3FeedReader::onProcessSuccess_addMsgs(const std::string &feedId, std::list
|
|||
forumMsgInfo.forumId = forumId;
|
||||
librs::util::ConvertUtf8ToUtf16(mi.title, forumMsgInfo.title);
|
||||
|
||||
std::string description = mi.description;
|
||||
std::string description = mi.descriptionTransformed.empty() ? mi.description : mi.descriptionTransformed;
|
||||
/* add link */
|
||||
if (!mi.link.empty()) {
|
||||
description += "<br><a href=\"" + mi.link + "\">" + mi.link + "</a>";
|
||||
|
|
|
@ -62,8 +62,10 @@ public:
|
|||
virtual bool getFeedMsgIdList(const std::string &feedId, std::list<std::string> &msgIds);
|
||||
virtual bool processFeed(const std::string &feedId);
|
||||
virtual bool setMessageRead(const std::string &feedId, const std::string &msgId, bool read);
|
||||
virtual bool retransformMsg(const std::string &feedId, const std::string &msgId);
|
||||
|
||||
virtual RsFeedReaderErrorState processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, std::string &description, std::string &errorString);
|
||||
virtual RsFeedReaderErrorState processXslt(const std::string &xslt, std::string &description, std::string &errorString);
|
||||
|
||||
/****************** p3Service STUFF ******************/
|
||||
virtual int tick();
|
||||
|
|
|
@ -117,6 +117,10 @@ void p3FeedReaderThread::run()
|
|||
delete (*it1);
|
||||
}
|
||||
} else {
|
||||
result = processTransformation(feed, mi, errorString);
|
||||
if (result != RS_FEED_ERRORSTATE_OK) {
|
||||
break;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
@ -258,14 +262,14 @@ static bool getFavicon(CURLWrapper &CURL, const std::string &url, std::string &i
|
|||
return result;
|
||||
}
|
||||
|
||||
RsFeedReaderErrorState p3FeedReaderThread::download(const RsFeedReaderFeed &feed, std::string &content, std::string &icon, std::string &error)
|
||||
RsFeedReaderErrorState p3FeedReaderThread::download(const RsFeedReaderFeed &feed, std::string &content, std::string &icon, std::string &errorString)
|
||||
{
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::download - feed " << feed.feedId << " (" << feed.name << ")" << std::endl;
|
||||
#endif
|
||||
|
||||
content.clear();
|
||||
error.clear();
|
||||
errorString.clear();
|
||||
|
||||
RsFeedReaderErrorState result;
|
||||
|
||||
|
@ -291,7 +295,7 @@ RsFeedReaderErrorState p3FeedReaderThread::download(const RsFeedReaderFeed &feed
|
|||
result = RS_FEED_ERRORSTATE_OK;
|
||||
} else {
|
||||
result = RS_FEED_ERRORSTATE_DOWNLOAD_UNKNOWN_CONTENT_TYPE;
|
||||
error = contentType;
|
||||
errorString = contentType;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -300,17 +304,17 @@ RsFeedReaderErrorState p3FeedReaderThread::download(const RsFeedReaderFeed &feed
|
|||
break;
|
||||
default:
|
||||
result = RS_FEED_ERRORSTATE_DOWNLOAD_UNKOWN_RESPONSE_CODE;
|
||||
rs_sprintf(error, "%ld", responseCode);
|
||||
rs_sprintf(errorString, "%ld", responseCode);
|
||||
}
|
||||
|
||||
getFavicon(CURL, feed.url, icon);
|
||||
} else {
|
||||
result = RS_FEED_ERRORSTATE_DOWNLOAD_ERROR;
|
||||
error = curl_easy_strerror(code);
|
||||
errorString = curl_easy_strerror(code);
|
||||
}
|
||||
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::download - feed " << feed.feedId << " (" << feed.name << "), result " << result << ", error = " << error << std::endl;
|
||||
std::cerr << "p3FeedReaderThread::download - feed " << feed.feedId << " (" << feed.name << "), result " << result << ", error = " << errorString << std::endl;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
|
@ -805,7 +809,7 @@ static time_t parseISO8601Date(const std::string &pubDate)
|
|||
return result;
|
||||
}
|
||||
|
||||
RsFeedReaderErrorState p3FeedReaderThread::process(const RsFeedReaderFeed &feed, std::list<RsFeedReaderMsg*> &entries, std::string &error)
|
||||
RsFeedReaderErrorState p3FeedReaderThread::process(const RsFeedReaderFeed &feed, std::list<RsFeedReaderMsg*> &entries, std::string &errorString)
|
||||
{
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::process - feed " << feed.feedId << " (" << feed.name << ")" << std::endl;
|
||||
|
@ -826,7 +830,7 @@ RsFeedReaderErrorState p3FeedReaderThread::process(const RsFeedReaderFeed &feed,
|
|||
feedFormat = FORMAT_ATOM;
|
||||
} else {
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_UNKNOWN_FORMAT;
|
||||
error = "Only RSS, RDF or ATOM supported";
|
||||
errorString = "Only RSS, RDF or ATOM supported";
|
||||
}
|
||||
|
||||
if (result == RS_FEED_ERRORSTATE_OK) {
|
||||
|
@ -962,19 +966,23 @@ RsFeedReaderErrorState p3FeedReaderThread::process(const RsFeedReaderFeed &feed,
|
|||
}
|
||||
} else {
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_UNKNOWN_FORMAT;
|
||||
error = "Channel not found";
|
||||
errorString = "Channel not found";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_UNKNOWN_FORMAT;
|
||||
error = "Can't read document";
|
||||
errorString = "Can't read document";
|
||||
}
|
||||
} else {
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR;
|
||||
errorString = xml.lastError();
|
||||
}
|
||||
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::process - feed " << feed.feedId << " (" << feed.name << "), result " << result << ", error = " << error << std::endl;
|
||||
std::cerr << "p3FeedReaderThread::process - feed " << feed.feedId << " (" << feed.name << "), result " << result << ", error = " << errorString << std::endl;
|
||||
if (result == RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR) {
|
||||
std::cerr << " Error: " << errorString << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
|
@ -1059,7 +1067,7 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
|
|||
}
|
||||
|
||||
/* check if string contains xml chars (very simple test) */
|
||||
if (msg->description.find('<') == std::string::npos) {
|
||||
if (msg->description.find('<') == std::string::npos && feed.transformationType == RS_FEED_TRANSFORMATION_TYPE_NONE) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1164,10 +1172,6 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
|
|||
}
|
||||
nodesToDelete.clear();
|
||||
|
||||
if (isRunning() && !feed.preview) {
|
||||
result = processXPath(feed.xpathsToUse.ids, feed.xpathsToRemove.ids, html, errorString);
|
||||
}
|
||||
|
||||
if (isRunning() && result == RS_FEED_ERRORSTATE_OK) {
|
||||
unsigned int xpathCount;
|
||||
unsigned int xpathIndex;
|
||||
|
@ -1241,8 +1245,10 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
|
|||
if (result == RS_FEED_ERRORSTATE_OK) {
|
||||
if (isRunning()) {
|
||||
if (!html.saveHTML(msg->description)) {
|
||||
errorString = html.lastError();
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot dump html" << std::endl;
|
||||
std::cerr << " Error: " << errorString << std::endl;
|
||||
#endif
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR;
|
||||
}
|
||||
|
@ -1255,8 +1261,10 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
|
|||
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
||||
}
|
||||
} else {
|
||||
errorString = html.lastError();
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processHTML - feed " << feed.feedId << " (" << feed.name << ") cannot read html" << std::endl;
|
||||
std::cerr << " Error: " << errorString << std::endl;
|
||||
#endif
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
||||
}
|
||||
|
@ -1265,6 +1273,30 @@ RsFeedReaderErrorState p3FeedReaderThread::processMsg(const RsFeedReaderFeed &fe
|
|||
return result;
|
||||
}
|
||||
|
||||
RsFeedReaderErrorState p3FeedReaderThread::processTransformation(const RsFeedReaderFeed &feed, RsFeedReaderMsg *msg, std::string &errorString)
|
||||
{
|
||||
RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK;
|
||||
|
||||
switch (feed.transformationType) {
|
||||
case RS_FEED_TRANSFORMATION_TYPE_NONE:
|
||||
break;
|
||||
case RS_FEED_TRANSFORMATION_TYPE_XPATH:
|
||||
msg->descriptionTransformed = msg->description;
|
||||
result = processXPath(feed.xpathsToUse.ids, feed.xpathsToRemove.ids, msg->descriptionTransformed, errorString);
|
||||
break;
|
||||
case RS_FEED_TRANSFORMATION_TYPE_XSLT:
|
||||
msg->descriptionTransformed = msg->description;
|
||||
result = processXslt(feed.xslt, msg->descriptionTransformed, errorString);
|
||||
break;
|
||||
}
|
||||
|
||||
if (msg->descriptionTransformed == msg->description) {
|
||||
msg->descriptionTransformed.clear();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
RsFeedReaderErrorState p3FeedReaderThread::processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, HTMLWrapper &html, std::string &errorString)
|
||||
{
|
||||
long todo_fill_errorString;
|
||||
|
@ -1376,8 +1408,6 @@ RsFeedReaderErrorState p3FeedReaderThread::processXPath(const std::list<std::str
|
|||
|
||||
RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK;
|
||||
|
||||
long todo_fill_errorString;
|
||||
|
||||
/* process description */
|
||||
long todo; // encoding
|
||||
HTMLWrapper html;
|
||||
|
@ -1388,8 +1418,10 @@ RsFeedReaderErrorState p3FeedReaderThread::processXPath(const std::list<std::str
|
|||
|
||||
if (result == RS_FEED_ERRORSTATE_OK) {
|
||||
if (!html.saveHTML(description)) {
|
||||
errorString = html.lastError();
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processXPath - cannot dump html" << std::endl;
|
||||
std::cerr << " Error: " << errorString << std::endl;
|
||||
#endif
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR;
|
||||
}
|
||||
|
@ -1398,11 +1430,131 @@ RsFeedReaderErrorState p3FeedReaderThread::processXPath(const std::list<std::str
|
|||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processXPath - no root element" << std::endl;
|
||||
#endif
|
||||
errorString = "No root element found";
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
||||
}
|
||||
} else {
|
||||
errorString = html.lastError();
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processXPath - cannot read html" << std::endl;
|
||||
std::cerr << " Error: " << errorString << std::endl;
|
||||
#endif
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
RsFeedReaderErrorState p3FeedReaderThread::processXslt(const std::string &xslt, HTMLWrapper &html, std::string &errorString)
|
||||
{
|
||||
XMLWrapper style;
|
||||
if (!style.readXML(xslt.c_str())) {
|
||||
errorString = style.lastError();
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processXslt - error loading style" << std::endl;
|
||||
std::cerr << " Error: " << errorString << std::endl;
|
||||
#endif
|
||||
return RS_FEED_ERRORSTATE_PROCESS_XSLT_FORMAT_ERROR;
|
||||
}
|
||||
|
||||
XMLWrapper xmlResult;
|
||||
if (!html.transform(style, xmlResult)) {
|
||||
errorString = html.lastError();
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processXslt - error transform" << std::endl;
|
||||
std::cerr << " Error: " << errorString << std::endl;
|
||||
#endif
|
||||
return RS_FEED_ERRORSTATE_PROCESS_XSLT_TRANSFORM_ERROR;
|
||||
}
|
||||
|
||||
RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK;
|
||||
|
||||
xmlNodePtr root = xmlResult.getRootElement();
|
||||
if (root) {
|
||||
if (xmlResult.nodeName(root) == "html") {
|
||||
if (root->children && xmlResult.nodeName(root->children) == "body") {
|
||||
root = root->children->children;
|
||||
}
|
||||
}
|
||||
HTMLWrapper htmlNew;
|
||||
if (htmlNew.createHTML()) {
|
||||
xmlNodePtr body = htmlNew.getBody();
|
||||
if (body) {
|
||||
/* copy result nodes */
|
||||
xmlNodePtr node;
|
||||
for (node = root; node; node = node->next) {
|
||||
xmlNodePtr newNode = xmlCopyNode(node, 1);
|
||||
if (newNode) {
|
||||
if (!xmlAddChild(body, newNode)) {
|
||||
xmlFreeNode(newNode);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR;
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processXslt - node copy error" << std::endl;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
||||
}
|
||||
} else {
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
||||
}
|
||||
|
||||
if (result == RS_FEED_ERRORSTATE_OK) {
|
||||
html = htmlNew;
|
||||
}
|
||||
} else {
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processXslt - no result" << std::endl;
|
||||
#endif
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_XSLT_NO_RESULT;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
RsFeedReaderErrorState p3FeedReaderThread::processXslt(const std::string &xslt, std::string &description, std::string &errorString)
|
||||
{
|
||||
if (xslt.empty()) {
|
||||
return RS_FEED_ERRORSTATE_OK;
|
||||
}
|
||||
|
||||
RsFeedReaderErrorState result = RS_FEED_ERRORSTATE_OK;
|
||||
|
||||
/* process description */
|
||||
long todo; // encoding
|
||||
HTMLWrapper html;
|
||||
if (html.readHTML(description.c_str(), "")) {
|
||||
xmlNodePtr root = html.getRootElement();
|
||||
if (root) {
|
||||
result = processXslt(xslt, html, errorString);
|
||||
|
||||
if (result == RS_FEED_ERRORSTATE_OK) {
|
||||
if (!html.saveHTML(description)) {
|
||||
errorString = html.lastError();
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processXslt - cannot dump html" << std::endl;
|
||||
std::cerr << " Error: " << errorString << std::endl;
|
||||
#endif
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processXslt - no root element" << std::endl;
|
||||
#endif
|
||||
errorString = "No root element found";
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
||||
}
|
||||
} else {
|
||||
errorString = html.lastError();
|
||||
#ifdef FEEDREADER_DEBUG
|
||||
std::cerr << "p3FeedReaderThread::processXslt - cannot read html" << std::endl;
|
||||
std::cerr << " Error: " << errorString << std::endl;
|
||||
#endif
|
||||
result = RS_FEED_ERRORSTATE_PROCESS_HTML_ERROR;
|
||||
}
|
||||
|
|
|
@ -51,11 +51,15 @@ public:
|
|||
static RsFeedReaderErrorState processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, std::string &description, std::string &errorString);
|
||||
static RsFeedReaderErrorState processXPath(const std::list<std::string> &xpathsToUse, const std::list<std::string> &xpathsToRemove, HTMLWrapper &html, std::string &errorString);
|
||||
|
||||
static RsFeedReaderErrorState processXslt(const std::string &xslt, std::string &description, std::string &errorString);
|
||||
static RsFeedReaderErrorState processXslt(const std::string &xslt, HTMLWrapper &html, std::string &errorString);
|
||||
|
||||
static RsFeedReaderErrorState processTransformation(const RsFeedReaderFeed &feed, RsFeedReaderMsg *msg, std::string &errorString);
|
||||
private:
|
||||
virtual void run();
|
||||
|
||||
RsFeedReaderErrorState download(const RsFeedReaderFeed &feed, std::string &content, std::string &icon, std::string &error);
|
||||
RsFeedReaderErrorState process(const RsFeedReaderFeed &feed, std::list<RsFeedReaderMsg*> &entries, std::string &error);
|
||||
RsFeedReaderErrorState download(const RsFeedReaderFeed &feed, std::string &content, std::string &icon, std::string &errorString);
|
||||
RsFeedReaderErrorState process(const RsFeedReaderFeed &feed, std::list<RsFeedReaderMsg*> &entries, std::string &errorString);
|
||||
|
||||
std::string getProxyForFeed(const RsFeedReaderFeed &feed);
|
||||
RsFeedReaderErrorState processMsg(const RsFeedReaderFeed &feed, RsFeedReaderMsg *msg, std::string &errorString);
|
||||
|
|
|
@ -51,8 +51,10 @@ void RsFeedReaderFeed::clear()
|
|||
icon.clear();
|
||||
errorState = RS_FEED_ERRORSTATE_OK;
|
||||
errorString.clear();
|
||||
transformationType = RS_FEED_TRANSFORMATION_TYPE_NONE;
|
||||
xpathsToUse.ids.clear();
|
||||
xpathsToRemove.ids.clear();
|
||||
xslt.clear();
|
||||
|
||||
preview = false;
|
||||
workstate = WAITING;
|
||||
|
@ -85,8 +87,10 @@ uint32_t RsFeedReaderSerialiser::sizeFeed(RsFeedReaderFeed *item)
|
|||
s += GetTlvStringSize(item->forumId);
|
||||
s += sizeof(uint32_t); /* errorstate */
|
||||
s += GetTlvStringSize(item->errorString);
|
||||
s += sizeof(uint32_t); /* transformationType */
|
||||
s += item->xpathsToUse.TlvSize();
|
||||
s += item->xpathsToRemove.TlvSize();
|
||||
s += GetTlvStringSize(item->xslt);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -110,7 +114,7 @@ bool RsFeedReaderSerialiser::serialiseFeed(RsFeedReaderFeed *item, void *data, u
|
|||
offset += 8;
|
||||
|
||||
/* add values */
|
||||
ok &= setRawUInt16(data, tlvsize, &offset, 0); /* version */
|
||||
ok &= setRawUInt16(data, tlvsize, &offset, 1); /* version */
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GENID, item->feedId);
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->parentId);
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_LINK, item->url);
|
||||
|
@ -128,8 +132,10 @@ bool RsFeedReaderSerialiser::serialiseFeed(RsFeedReaderFeed *item, void *data, u
|
|||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->forumId);
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, item->errorState);
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->errorString);
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, item->transformationType);
|
||||
ok &= item->xpathsToUse.SetTlv(data, tlvsize, &offset);
|
||||
ok &= item->xpathsToRemove.SetTlv(data, tlvsize, &offset);
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->xslt);
|
||||
|
||||
if (offset != tlvsize)
|
||||
{
|
||||
|
@ -192,9 +198,28 @@ RsFeedReaderFeed *RsFeedReaderSerialiser::deserialiseFeed(void *data, uint32_t *
|
|||
ok &= getRawUInt32(data, rssize, &offset, &errorState);
|
||||
item->errorState = (RsFeedReaderErrorState) errorState;
|
||||
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->errorString);
|
||||
if (version >= 1) {
|
||||
uint32_t value = RS_FEED_TRANSFORMATION_TYPE_NONE;
|
||||
ok &= getRawUInt32(data, rssize, &offset, &value);
|
||||
if (ok)
|
||||
{
|
||||
item->transformationType = (RsFeedTransformationType) value;
|
||||
}
|
||||
}
|
||||
ok &= item->xpathsToUse.GetTlv(data, rssize, &offset);
|
||||
ok &= item->xpathsToRemove.GetTlv(data, rssize, &offset);
|
||||
if (version >= 1) {
|
||||
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->xslt);
|
||||
}
|
||||
|
||||
if (version == 0)
|
||||
{
|
||||
if (!item->xpathsToUse.ids.empty() || !item->xpathsToRemove.ids.empty())
|
||||
{
|
||||
/* set transformation type */
|
||||
item->transformationType = RS_FEED_TRANSFORMATION_TYPE_XPATH;
|
||||
}
|
||||
}
|
||||
if (offset != rssize)
|
||||
{
|
||||
/* error */
|
||||
|
@ -226,6 +251,7 @@ void RsFeedReaderMsg::clear()
|
|||
link.clear();
|
||||
author.clear();
|
||||
description.clear();
|
||||
descriptionTransformed.clear();
|
||||
pubDate = 0;
|
||||
flag = 0;
|
||||
}
|
||||
|
@ -245,6 +271,7 @@ uint32_t RsFeedReaderSerialiser::sizeMsg(RsFeedReaderMsg *item)
|
|||
s += GetTlvStringSize(item->link);
|
||||
s += GetTlvStringSize(item->author);
|
||||
s += GetTlvStringSize(item->description);
|
||||
s += GetTlvStringSize(item->descriptionTransformed);
|
||||
s += sizeof(time_t); /* pubDate */
|
||||
s += sizeof(uint32_t); /* flag */
|
||||
|
||||
|
@ -270,13 +297,14 @@ bool RsFeedReaderSerialiser::serialiseMsg(RsFeedReaderMsg *item, void *data, uin
|
|||
offset += 8;
|
||||
|
||||
/* add values */
|
||||
ok &= setRawUInt16(data, tlvsize, &offset, 0); /* version */
|
||||
ok &= setRawUInt16(data, tlvsize, &offset, 1); /* version */
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GENID, item->msgId);
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->feedId);
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_NAME, item->title);
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_LINK, item->link);
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->author);
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_COMMENT, item->description);
|
||||
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_COMMENT, item->descriptionTransformed);
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, item->pubDate);
|
||||
ok &= setRawUInt32(data, tlvsize, &offset, item->flag);
|
||||
|
||||
|
@ -328,6 +356,9 @@ RsFeedReaderMsg *RsFeedReaderSerialiser::deserialiseMsg(void *data, uint32_t *pk
|
|||
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_LINK, item->link);
|
||||
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->author);
|
||||
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_COMMENT, item->description);
|
||||
if (version >= 1) {
|
||||
ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_COMMENT, item->descriptionTransformed);
|
||||
}
|
||||
ok &= getRawUInt32(data, rssize, &offset, (uint32_t*) &(item->pubDate));
|
||||
ok &= getRawUInt32(data, rssize, &offset, &(item->flag));
|
||||
|
||||
|
|
|
@ -65,26 +65,28 @@ public:
|
|||
virtual void clear();
|
||||
virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
|
||||
|
||||
std::string feedId;
|
||||
std::string parentId;
|
||||
std::string name;
|
||||
std::string url;
|
||||
std::string user;
|
||||
std::string password;
|
||||
std::string proxyAddress;
|
||||
uint16_t proxyPort;
|
||||
uint32_t updateInterval;
|
||||
time_t lastUpdate;
|
||||
uint32_t flag; // RS_FEED_FLAG_...
|
||||
std::string forumId;
|
||||
uint32_t storageTime;
|
||||
std::string description;
|
||||
std::string icon;
|
||||
RsFeedReaderErrorState errorState;
|
||||
std::string errorString;
|
||||
std::string feedId;
|
||||
std::string parentId;
|
||||
std::string name;
|
||||
std::string url;
|
||||
std::string user;
|
||||
std::string password;
|
||||
std::string proxyAddress;
|
||||
uint16_t proxyPort;
|
||||
uint32_t updateInterval;
|
||||
time_t lastUpdate;
|
||||
uint32_t flag; // RS_FEED_FLAG_...
|
||||
std::string forumId;
|
||||
uint32_t storageTime;
|
||||
std::string description;
|
||||
std::string icon;
|
||||
RsFeedReaderErrorState errorState;
|
||||
std::string errorString;
|
||||
|
||||
RsTlvStringSet xpathsToUse;
|
||||
RsTlvStringSet xpathsToRemove;
|
||||
RsFeedTransformationType transformationType;
|
||||
RsTlvStringSet xpathsToUse;
|
||||
RsTlvStringSet xpathsToRemove;
|
||||
std::string xslt;
|
||||
|
||||
/* Not Serialised */
|
||||
bool preview;
|
||||
|
@ -113,6 +115,7 @@ public:
|
|||
std::string link;
|
||||
std::string author;
|
||||
std::string description;
|
||||
std::string descriptionTransformed;
|
||||
time_t pubDate;
|
||||
uint32_t flag; // RS_FEEDMSG_FLAG_...
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue