Some Feed and Entry refacotring
This commit is contained in:
parent
08d5a73f89
commit
d596cef76a
1
Makefile
1
Makefile
|
@ -37,7 +37,6 @@ SRCS = \
|
||||||
src/Feed.cpp, \
|
src/Feed.cpp, \
|
||||||
src/FeedController.cpp \
|
src/FeedController.cpp \
|
||||||
src/FeedsView.cpp, \
|
src/FeedsView.cpp, \
|
||||||
src/Invocation.cpp \
|
|
||||||
src/MainWindow.cpp, \
|
src/MainWindow.cpp, \
|
||||||
src/Mimetypes.cpp, \
|
src/Mimetypes.cpp, \
|
||||||
src/ProtocolListener.cpp, \
|
src/ProtocolListener.cpp, \
|
||||||
|
|
|
@ -82,7 +82,8 @@ void
|
||||||
App::ArgvReceived(int32 argc, char** argv)
|
App::ArgvReceived(int32 argc, char** argv)
|
||||||
{
|
{
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
Feed* newFeed = new Feed(argv[i]);
|
if (BUrl(argv[i]).IsValid()) {
|
||||||
|
Feed* newFeed = new Feed(BUrl(argv[i]));
|
||||||
|
|
||||||
BMessage* enqueue = new BMessage(kEnqueueFeed);
|
BMessage* enqueue = new BMessage(kEnqueueFeed);
|
||||||
enqueue->AddData("feeds", B_RAW_TYPE, (void*)newFeed, sizeof(Feed));
|
enqueue->AddData("feeds", B_RAW_TYPE, (void*)newFeed, sizeof(Feed));
|
||||||
|
@ -90,6 +91,7 @@ App::ArgvReceived(int32 argc, char** argv)
|
||||||
MessageReceived(enqueue);
|
MessageReceived(enqueue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* configPath = "/boot/home/config/settings/Pogger/";
|
const char* configPath = "/boot/home/config/settings/Pogger/";
|
||||||
|
|
|
@ -16,11 +16,8 @@
|
||||||
AtomFeed::AtomFeed()
|
AtomFeed::AtomFeed()
|
||||||
{
|
{
|
||||||
title = BString("Untitled Feed");
|
title = BString("Untitled Feed");
|
||||||
description = BString("");
|
|
||||||
homeUrl = BString("");
|
|
||||||
xmlUrl = BString("");
|
xmlUrl = BString("");
|
||||||
cachePath = BString("");
|
cachePath = BString("");
|
||||||
outputDir = ((App*)be_app)->cfg->outDir;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,9 +42,9 @@ AtomFeed::Parse ()
|
||||||
RootParse(xfeed);
|
RootParse(xfeed);
|
||||||
ParseEntries(xfeed);
|
ParseEntries(xfeed);
|
||||||
|
|
||||||
BFile* feedFile = new BFile(GetCachePath().String(), B_READ_WRITE);
|
BFile* feedFile = new BFile(cachePath, B_READ_WRITE);
|
||||||
time_t tt_lastDate = lastDate.Time_t();
|
time_t tt_date = date.Time_t();
|
||||||
feedFile->WriteAttr("LastDate", B_TIME_TYPE, 0, &tt_lastDate,
|
feedFile->WriteAttr("LastDate", B_TIME_TYPE, 0, &tt_date,
|
||||||
sizeof(time_t));
|
sizeof(time_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +60,6 @@ AtomFeed::RootParse(tinyxml2::XMLElement* xfeed)
|
||||||
bool set = false;
|
bool set = false;
|
||||||
|
|
||||||
SetTitle(xfeed->FirstChildElement("title"));
|
SetTitle(xfeed->FirstChildElement("title"));
|
||||||
SetDesc( xfeed->FirstChildElement("description"));
|
|
||||||
|
|
||||||
set = SetDate(xfeed->FirstChildElement("updated"));
|
set = SetDate(xfeed->FirstChildElement("updated"));
|
||||||
if (!set)
|
if (!set)
|
||||||
|
@ -73,14 +69,8 @@ AtomFeed::RootParse(tinyxml2::XMLElement* xfeed)
|
||||||
if (!set && xentry)
|
if (!set && xentry)
|
||||||
set = SetDate(xentry->FirstChildElement("published"));
|
set = SetDate(xentry->FirstChildElement("published"));
|
||||||
|
|
||||||
set = SetHomeUrl(xlink->Attribute("href"));
|
printf("Channel '%s' at '%s':\n", title.String(),
|
||||||
if (!set && xauthor)
|
xmlUrl.UrlString().String());
|
||||||
set = SetHomeUrl(xauthor->FirstChildElement("uri"));
|
|
||||||
if (!set && xauthlink)
|
|
||||||
set = SetHomeUrl(xauthlink->Attribute("href"));
|
|
||||||
|
|
||||||
if (((App*)be_app)->cfg->verbose)
|
|
||||||
printf("Channel '%s' at '%s':\n", title.String(), homeUrl.String());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,7 +78,7 @@ void
|
||||||
AtomFeed::EntryParse(tinyxml2::XMLElement* xentry)
|
AtomFeed::EntryParse(tinyxml2::XMLElement* xentry)
|
||||||
{
|
{
|
||||||
Entry* newEntry = (Entry*)malloc(sizeof(Entry));
|
Entry* newEntry = (Entry*)malloc(sizeof(Entry));
|
||||||
newEntry = new Entry(outputDir);
|
newEntry = new Entry();
|
||||||
|
|
||||||
tinyxml2::XMLElement* xcontent = xentry->FirstChildElement("content");
|
tinyxml2::XMLElement* xcontent = xentry->FirstChildElement("content");
|
||||||
tinyxml2::XMLElement* xmedia = xentry->FirstChildElement("media:group");
|
tinyxml2::XMLElement* xmedia = xentry->FirstChildElement("media:group");
|
||||||
|
@ -109,8 +99,8 @@ AtomFeed::EntryParse(tinyxml2::XMLElement* xentry)
|
||||||
if (!set)
|
if (!set)
|
||||||
set = newEntry->SetDate(xentry->FirstChildElement("published"));
|
set = newEntry->SetDate(xentry->FirstChildElement("published"));
|
||||||
|
|
||||||
if (lastDate == NULL || lastDate < newEntry->date)
|
if (date == NULL || date < newEntry->GetDate())
|
||||||
lastDate = newEntry->date;
|
SetDate(newEntry->GetDate());
|
||||||
|
|
||||||
if (xcontent) {
|
if (xcontent) {
|
||||||
xcontent->Accept(&xprinter);
|
xcontent->Accept(&xprinter);
|
||||||
|
@ -131,7 +121,6 @@ AtomFeed::ParseEntries(tinyxml2::XMLElement* xfeed)
|
||||||
int entryCount = xmlCountSiblings(xentry, "entry");
|
int entryCount = xmlCountSiblings(xentry, "entry");
|
||||||
entries = BList(entryCount);
|
entries = BList(entryCount);
|
||||||
|
|
||||||
if (((App*)be_app)->cfg->verbose)
|
|
||||||
printf("\t-%i entries-\n", entryCount);
|
printf("\t-%i entries-\n", entryCount);
|
||||||
|
|
||||||
while (xentry) {
|
while (xentry) {
|
||||||
|
|
|
@ -14,25 +14,23 @@
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
|
||||||
|
|
||||||
Entry::Entry(BString outputPath)
|
Entry::Entry()
|
||||||
{
|
{
|
||||||
title = BString("");
|
title = BString("");
|
||||||
description = BString("");
|
description = BString("");
|
||||||
feedTitle = BString("");
|
feedTitle = BString("");
|
||||||
postUrl = BString("");
|
postUrl = BString("");
|
||||||
content = BString("");
|
content = BString("");
|
||||||
outputDir = outputPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Entry::Filetize(bool onlyIfNew = false)
|
Entry::Filetize(BDirectory outDir)
|
||||||
{
|
{
|
||||||
BDirectory* dir = new BDirectory(outputDir);
|
|
||||||
BFile* file = new BFile(title.String(), B_READ_WRITE);
|
BFile* file = new BFile(title.String(), B_READ_WRITE);
|
||||||
time_t tt_date = date.Time_t();
|
time_t tt_date = date.Time_t();
|
||||||
|
|
||||||
dir->CreateFile(title.String(), file);
|
outDir.CreateFile(title.String(), file);
|
||||||
|
|
||||||
BString betype = BString("text/x-feed-entry");
|
BString betype = BString("text/x-feed-entry");
|
||||||
file->WriteAttr("BEOS:TYPE", B_MIME_STRING_TYPE, 0, betype.String(),
|
file->WriteAttr("BEOS:TYPE", B_MIME_STRING_TYPE, 0, betype.String(),
|
||||||
|
@ -57,7 +55,8 @@ Entry::Filetize(bool onlyIfNew = false)
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Entry::SetTitle(const char* titleStr) {
|
Entry::SetTitle(const char* titleStr)
|
||||||
|
{
|
||||||
if (titleStr != NULL)
|
if (titleStr != NULL)
|
||||||
title = BString(titleStr);
|
title = BString(titleStr);
|
||||||
else return false;
|
else return false;
|
||||||
|
@ -66,7 +65,8 @@ Entry::SetTitle(const char* titleStr) {
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Entry::SetTitle(tinyxml2::XMLElement* elem) {
|
Entry::SetTitle(tinyxml2::XMLElement* elem)
|
||||||
|
{
|
||||||
if (elem != NULL)
|
if (elem != NULL)
|
||||||
return SetTitle(elem->GetText());
|
return SetTitle(elem->GetText());
|
||||||
return false;
|
return false;
|
||||||
|
@ -74,7 +74,8 @@ Entry::SetTitle(tinyxml2::XMLElement* elem) {
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Entry::SetDesc(const char* descStr) {
|
Entry::SetDesc(const char* descStr)
|
||||||
|
{
|
||||||
if (descStr != NULL)
|
if (descStr != NULL)
|
||||||
description = BString(descStr);
|
description = BString(descStr);
|
||||||
else return false;
|
else return false;
|
||||||
|
@ -83,7 +84,8 @@ Entry::SetDesc(const char* descStr) {
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Entry::SetDesc(tinyxml2::XMLElement* elem) {
|
Entry::SetDesc(tinyxml2::XMLElement* elem)
|
||||||
|
{
|
||||||
if (elem != NULL)
|
if (elem != NULL)
|
||||||
return SetDesc(elem->GetText());
|
return SetDesc(elem->GetText());
|
||||||
return false;
|
return false;
|
||||||
|
@ -91,7 +93,8 @@ Entry::SetDesc(tinyxml2::XMLElement* elem) {
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Entry::SetFeedTitle(BString titleStr) {
|
Entry::SetFeedTitle(BString titleStr)
|
||||||
|
{
|
||||||
if (titleStr != NULL)
|
if (titleStr != NULL)
|
||||||
feedTitle = titleStr;
|
feedTitle = titleStr;
|
||||||
else return false;
|
else return false;
|
||||||
|
@ -119,7 +122,8 @@ Entry::SetContent(tinyxml2::XMLElement* elem)
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Entry::SetPostUrl(const char* urlStr) {
|
Entry::SetPostUrl(const char* urlStr)
|
||||||
|
{
|
||||||
if (urlStr != NULL)
|
if (urlStr != NULL)
|
||||||
postUrl = BString(urlStr);
|
postUrl = BString(urlStr);
|
||||||
else return false;
|
else return false;
|
||||||
|
@ -128,7 +132,8 @@ Entry::SetPostUrl(const char* urlStr) {
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Entry::SetPostUrl(tinyxml2::XMLElement* elem) {
|
Entry::SetPostUrl(tinyxml2::XMLElement* elem)
|
||||||
|
{
|
||||||
if (elem != NULL)
|
if (elem != NULL)
|
||||||
return SetPostUrl(elem->GetText());
|
return SetPostUrl(elem->GetText());
|
||||||
return false;
|
return false;
|
||||||
|
@ -136,7 +141,8 @@ Entry::SetPostUrl(tinyxml2::XMLElement* elem) {
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Entry::SetDate(const char* dateStr) {
|
Entry::SetDate(const char* dateStr)
|
||||||
|
{
|
||||||
if (dateStr == NULL)
|
if (dateStr == NULL)
|
||||||
return false;
|
return false;
|
||||||
BDateTime newDate = feedDateToBDate(dateStr);
|
BDateTime newDate = feedDateToBDate(dateStr);
|
||||||
|
@ -148,10 +154,18 @@ Entry::SetDate(const char* dateStr) {
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Entry::SetDate(tinyxml2::XMLElement* elem) {
|
Entry::SetDate(tinyxml2::XMLElement* elem)
|
||||||
|
{
|
||||||
if (elem != NULL)
|
if (elem != NULL)
|
||||||
return SetDate(elem->GetText());
|
return SetDate(elem->GetText());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BDateTime
|
||||||
|
Entry::GetDate()
|
||||||
|
{
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,9 @@
|
||||||
class Entry {
|
class Entry {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Entry(BString);
|
Entry();
|
||||||
|
|
||||||
bool Filetize(bool);
|
bool Filetize(BDirectory outDir);
|
||||||
|
|
||||||
bool SetTitle(const char*);
|
bool SetTitle(const char*);
|
||||||
bool SetTitle(tinyxml2::XMLElement*);
|
bool SetTitle(tinyxml2::XMLElement*);
|
||||||
|
@ -34,6 +34,7 @@ public:
|
||||||
bool SetPostUrl(tinyxml2::XMLElement*);
|
bool SetPostUrl(tinyxml2::XMLElement*);
|
||||||
bool SetDate(const char*);
|
bool SetDate(const char*);
|
||||||
bool SetDate(tinyxml2::XMLElement*);
|
bool SetDate(tinyxml2::XMLElement*);
|
||||||
|
BDateTime GetDate();
|
||||||
|
|
||||||
BString title;
|
BString title;
|
||||||
BString description;
|
BString description;
|
||||||
|
@ -41,7 +42,6 @@ public:
|
||||||
BDateTime date;
|
BDateTime date;
|
||||||
BString postUrl;
|
BString postUrl;
|
||||||
BString content;
|
BString content;
|
||||||
BString outputDir;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
242
src/Feed.cpp
242
src/Feed.cpp
|
@ -13,106 +13,77 @@
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
|
||||||
|
|
||||||
Feed::Feed(BString path)
|
Feed::Feed(BUrl xml, BString path)
|
||||||
|
: Feed()
|
||||||
{
|
{
|
||||||
title = BString("Untitled Feed");
|
xmlUrl = xml;
|
||||||
description = BString("Nondescript, N/A.");
|
cachePath = path;
|
||||||
homeUrl = BString("");
|
}
|
||||||
xmlUrl = BString("");
|
|
||||||
updated = true;
|
|
||||||
fetched = false;
|
Feed::Feed(BUrl xml)
|
||||||
inputPath = path;
|
: Feed()
|
||||||
SetCachePath(path);
|
{
|
||||||
|
xmlUrl = xml;
|
||||||
|
BString cache("/boot/home/config/cache/Pogger/");
|
||||||
|
cache.Append(urlToFilename(xmlUrl));
|
||||||
|
SetCachePath(cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Feed::Feed(Feed* feed)
|
Feed::Feed(Feed* feed)
|
||||||
: Feed()
|
: Feed()
|
||||||
{
|
{
|
||||||
SetCachePath(feed->GetCachePath());
|
SetTitle(feed->GetTitle());
|
||||||
|
SetXmlUrl(feed->GetXmlUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Feed::Feed()
|
Feed::Feed()
|
||||||
|
:
|
||||||
|
title(BString("Untitled Feed"))
|
||||||
{
|
{
|
||||||
title = BString("");
|
lastDate = BDateTime::CurrentDateTime(B_LOCAL_TIME);
|
||||||
description = BString("");
|
|
||||||
homeUrl = BString("");
|
|
||||||
xmlUrl = BString("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Feed::Parse()
|
Feed::Parse()
|
||||||
{
|
{
|
||||||
BFile* feedFile = new BFile(GetCachePath().String(), B_READ_ONLY);
|
BFile feedFile = BFile(cachePath, B_READ_ONLY);
|
||||||
BDateTime attrLastDate = BDateTime();
|
|
||||||
time_t tt_lastDate = 0;
|
time_t tt_lastDate = 0;
|
||||||
|
|
||||||
feedFile->ReadAttr("LastDate", B_TIME_TYPE, 0, &tt_lastDate,
|
feedFile.ReadAttr("LastDate", B_TIME_TYPE, 0, &tt_lastDate, sizeof(time_t));
|
||||||
sizeof(time_t));
|
|
||||||
|
|
||||||
if (tt_lastDate > 0 && ((App*)be_app)->cfg->updateFeeds == true) {
|
if (tt_lastDate > 0)
|
||||||
attrLastDate.SetTime_t(tt_lastDate);
|
lastDate.SetTime_t(tt_lastDate);
|
||||||
minDate = attrLastDate;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Download a remote feed's XML to the cache path.
|
// Download a remote feed's XML to the cache path.
|
||||||
BString
|
BString
|
||||||
Feed::FetchRemoteFeed()
|
Feed::Fetch()
|
||||||
{
|
{
|
||||||
BUrl givenUrl = BUrl(inputPath);
|
BFile cacheFile = BFile(cachePath, B_READ_WRITE | B_CREATE_FILE);
|
||||||
time_t tt_lastDate = 0;
|
|
||||||
BDateTime* lastDate = new BDateTime();
|
|
||||||
BString newHash;
|
|
||||||
BString oldHash;
|
|
||||||
|
|
||||||
BFile* cacheFile = new BFile(GetCachePath(), B_READ_WRITE | B_CREATE_FILE);
|
cacheFile.ReadAttrString("LastHash", &lastHash);
|
||||||
|
|
||||||
// cacheFile->ReadAttr("LastHash", B_STRING_TYPE, 0, oldHash, 41);
|
fetch(xmlUrl, &cacheFile, &hash, 30);
|
||||||
cacheFile->ReadAttrString("LastHash", &oldHash);
|
cacheFile.WriteAttrString("LastHash", &hash);
|
||||||
|
|
||||||
if (((App*)be_app)->cfg->verbose)
|
if (hash == lastHash)
|
||||||
printf("Saving %s...\n", inputPath.String());
|
|
||||||
|
|
||||||
fetch(BUrl(inputPath), cacheFile, &newHash, 30);
|
|
||||||
cacheFile->WriteAttrString("LastHash", &newHash);
|
|
||||||
// cacheFile->WriteAttr("LastHash", B_STRING_TYPE, 0,
|
|
||||||
// newHash.String(), newHash.CountChars());
|
|
||||||
|
|
||||||
if (newHash == oldHash)
|
|
||||||
updated = false;
|
updated = false;
|
||||||
|
|
||||||
fetched = true;
|
fetched = true;
|
||||||
return GetCachePath();
|
return cachePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// return whether or not the feed's given URI/path is remote.
|
|
||||||
bool
|
|
||||||
Feed::IsRemote ()
|
|
||||||
{
|
|
||||||
return isRemotePath(inputPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// return whether or not the feed seems to have been updated
|
|
||||||
bool
|
|
||||||
Feed::IsUpdated ()
|
|
||||||
{
|
|
||||||
return updated;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// return whether or not feed is RSS
|
|
||||||
bool
|
bool
|
||||||
Feed::IsRss()
|
Feed::IsRss()
|
||||||
{
|
{
|
||||||
EnsureCached();
|
|
||||||
tinyxml2::XMLDocument xml;
|
tinyxml2::XMLDocument xml;
|
||||||
xml.LoadFile(GetCachePath().String());
|
xml.LoadFile(cachePath.String());
|
||||||
|
|
||||||
if (xml.FirstChildElement("rss"))
|
if (xml.FirstChildElement("rss"))
|
||||||
return true;
|
return true;
|
||||||
|
@ -120,12 +91,11 @@ Feed::IsRss ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// return whether or not feed is Atom
|
|
||||||
bool
|
bool
|
||||||
Feed::IsAtom()
|
Feed::IsAtom()
|
||||||
{
|
{
|
||||||
tinyxml2::XMLDocument xml;
|
tinyxml2::XMLDocument xml;
|
||||||
xml.LoadFile(GetCachePath().String());
|
xml.LoadFile(cachePath.String());
|
||||||
|
|
||||||
if (xml.FirstChildElement("feed"))
|
if (xml.FirstChildElement("feed"))
|
||||||
return true;
|
return true;
|
||||||
|
@ -133,49 +103,10 @@ Feed::IsAtom ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ensure the feed XML is available at the cache path.
|
bool
|
||||||
// if necessary, download it.
|
Feed::IsUpdated()
|
||||||
void
|
|
||||||
Feed::EnsureCached ()
|
|
||||||
{
|
{
|
||||||
if (IsRemote() && fetched == false)
|
return lastHash != hash;
|
||||||
FetchRemoteFeed();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Return the 'cachePath' (location of XML file locally)
|
|
||||||
BString
|
|
||||||
Feed::GetCachePath ()
|
|
||||||
{
|
|
||||||
if (cachePath == NULL)
|
|
||||||
SetCachePath(inputPath);
|
|
||||||
return cachePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Select a 'cachePath' (location of XML file locally)
|
|
||||||
// For remote files, a cache file is created in ~/config/cache/Pogger/ by default
|
|
||||||
// For local files, the same local file is used.
|
|
||||||
BString
|
|
||||||
Feed::SetCachePath (BString givenPath)
|
|
||||||
{
|
|
||||||
BUrl givenUrl = BUrl(givenPath);
|
|
||||||
BString protocol = givenUrl.Protocol().String();
|
|
||||||
|
|
||||||
if (protocol == NULL && givenUrl.UrlString() != NULL) {
|
|
||||||
cachePath = givenPath;
|
|
||||||
return givenPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
BString splitName = givenUrl.Host();
|
|
||||||
splitName.Append(givenUrl.Path());
|
|
||||||
splitName.ReplaceAll("/", "_");
|
|
||||||
|
|
||||||
BString filename = ((App*)be_app)->cfg->cacheDir;
|
|
||||||
filename.Append(splitName);
|
|
||||||
|
|
||||||
cachePath = filename;
|
|
||||||
return filename;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -192,17 +123,11 @@ Feed::xmlCountSiblings (tinyxml2::XMLElement* xsibling, const char* sibling_name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Add the given entry to the feed, if appropriate
|
|
||||||
bool
|
bool
|
||||||
Feed::AddEntry (Entry* newEntry)
|
Feed::AddEntry (Entry* newEntry)
|
||||||
{
|
{
|
||||||
Config* cfg = ((App*)be_app)->cfg;
|
Config* cfg = ((App*)be_app)->cfg;
|
||||||
if (!withinDateRange(cfg->minDate, newEntry->date, cfg->maxDate) ||
|
|
||||||
!withinDateRange(minDate, newEntry->date, maxDate))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (cfg->verbose == true)
|
|
||||||
printf("\t%s\n", newEntry->title.String());
|
|
||||||
entries.AddItem(newEntry);
|
entries.AddItem(newEntry);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -215,6 +140,20 @@ Feed::GetEntries()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BList
|
||||||
|
Feed::GetNewEntries()
|
||||||
|
{
|
||||||
|
BList newEntries;
|
||||||
|
for (int i = 0; i < entries.CountItems(); i++) {
|
||||||
|
Entry* entry = ((Entry*)entries.ItemAt(i));
|
||||||
|
if (entry->GetDate() > lastDate)
|
||||||
|
newEntries.AddItem(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Feed::SetTitle(const char* titleStr)
|
Feed::SetTitle(const char* titleStr)
|
||||||
{
|
{
|
||||||
|
@ -242,75 +181,52 @@ Feed::GetTitle()
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Feed::SetDesc(const char* descStr)
|
Feed::SetXmlUrl(BUrl newUrl)
|
||||||
{
|
{
|
||||||
if (descStr != NULL)
|
xmlUrl = newUrl;
|
||||||
description = BString(descStr);
|
|
||||||
else return false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
BUrl
|
||||||
Feed::SetDesc(tinyxml2::XMLElement* elem)
|
|
||||||
{
|
|
||||||
if (elem != NULL)
|
|
||||||
return SetDesc(elem->GetText());
|
|
||||||
else return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BString
|
|
||||||
Feed::GetDesc()
|
|
||||||
{
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// set a feed's «home URL»
|
|
||||||
bool
|
|
||||||
Feed::SetHomeUrl(const char* homepageStr)
|
|
||||||
{
|
|
||||||
if (homepageStr != NULL)
|
|
||||||
homeUrl = BString(homepageStr);
|
|
||||||
else return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Feed::SetHomeUrl(tinyxml2::XMLElement* elem)
|
|
||||||
{
|
|
||||||
if (elem != NULL)
|
|
||||||
return SetHomeUrl(elem->GetText());
|
|
||||||
else return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BString
|
|
||||||
Feed::GetHomeUrl()
|
|
||||||
{
|
|
||||||
return homeUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BString
|
|
||||||
Feed::GetXmlUrl()
|
Feed::GetXmlUrl()
|
||||||
{
|
{
|
||||||
return xmlUrl;
|
return xmlUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// set the update time for a feed
|
bool
|
||||||
|
Feed::SetCachePath(BString path)
|
||||||
|
{
|
||||||
|
cachePath = path;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
Feed::GetCachePath()
|
||||||
|
{
|
||||||
|
return cachePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Set the latest date given by feed (from entry or from root)
|
||||||
|
bool
|
||||||
|
Feed::SetDate(BDateTime newDate)
|
||||||
|
{
|
||||||
|
if (newDate == NULL)
|
||||||
|
return false;
|
||||||
|
date = newDate;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Feed::SetDate(const char* dateCStr)
|
Feed::SetDate(const char* dateCStr)
|
||||||
{
|
{
|
||||||
if (dateCStr == NULL)
|
if (dateCStr == NULL)
|
||||||
return false;
|
return false;
|
||||||
BDateTime newDate = feedDateToBDate(dateCStr);
|
SetDate(feedDateToBDate(dateCStr));
|
||||||
if (newDate == NULL)
|
|
||||||
return false;
|
|
||||||
date = newDate;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
50
src/Feed.h
50
src/Feed.h
|
@ -19,53 +19,49 @@ class BUrl;
|
||||||
|
|
||||||
class Feed {
|
class Feed {
|
||||||
public:
|
public:
|
||||||
Feed(BString);
|
Feed(BUrl);
|
||||||
|
Feed(BUrl, BString);
|
||||||
Feed(Feed*);
|
Feed(Feed*);
|
||||||
Feed();
|
Feed();
|
||||||
|
|
||||||
virtual void Parse();
|
virtual void Parse();
|
||||||
|
|
||||||
bool IsRemote();
|
BList GetEntries();
|
||||||
bool IsUpdated();
|
BList GetNewEntries();
|
||||||
|
|
||||||
|
BString Fetch();
|
||||||
|
|
||||||
bool IsRss();
|
bool IsRss();
|
||||||
bool IsAtom();
|
bool IsAtom();
|
||||||
|
bool IsUpdated();
|
||||||
|
|
||||||
BString FetchRemoteFeed();
|
|
||||||
|
|
||||||
bool AddEntry(Entry*);
|
|
||||||
BList GetEntries();
|
|
||||||
bool SetTitle(const char*);
|
|
||||||
bool SetTitle(tinyxml2::XMLElement*);
|
|
||||||
BString GetTitle();
|
BString GetTitle();
|
||||||
bool SetDesc(const char*);
|
BUrl GetXmlUrl();
|
||||||
bool SetDesc(tinyxml2::XMLElement*);
|
|
||||||
BString GetDesc();
|
|
||||||
bool SetHomeUrl(const char*);
|
|
||||||
bool SetHomeUrl(tinyxml2::XMLElement*);
|
|
||||||
BString GetHomeUrl();
|
|
||||||
BString GetXmlUrl();
|
|
||||||
bool SetDate(const char*);
|
|
||||||
bool SetDate(tinyxml2::XMLElement*);
|
|
||||||
BDateTime GetDate();
|
BDateTime GetDate();
|
||||||
|
|
||||||
BString SetCachePath(BString);
|
|
||||||
BString GetCachePath();
|
BString GetCachePath();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void EnsureCached();
|
bool SetTitle(const char*);
|
||||||
|
bool SetTitle(tinyxml2::XMLElement*);
|
||||||
|
bool SetDate(BDateTime);
|
||||||
|
bool SetDate(const char*);
|
||||||
|
bool SetDate(tinyxml2::XMLElement*);
|
||||||
|
bool SetXmlUrl(BUrl newUrl);
|
||||||
|
bool SetCachePath(BString path);
|
||||||
|
|
||||||
|
bool AddEntry(Entry*);
|
||||||
|
|
||||||
int xmlCountSiblings(tinyxml2::XMLElement*, const char*);
|
int xmlCountSiblings(tinyxml2::XMLElement*, const char*);
|
||||||
|
|
||||||
BString title;
|
BString title;
|
||||||
BString description;
|
|
||||||
BDateTime date;
|
BDateTime date;
|
||||||
BDateTime lastDate;
|
BDateTime lastDate;
|
||||||
BDateTime minDate;
|
BUrl xmlUrl;
|
||||||
BDateTime maxDate;
|
|
||||||
BString homeUrl;
|
|
||||||
BString inputPath;
|
|
||||||
BString xmlUrl;
|
|
||||||
BString cachePath;
|
BString cachePath;
|
||||||
BString outputDir;
|
BString hash;
|
||||||
|
BString lastHash;
|
||||||
|
|
||||||
BList entries;
|
BList entries;
|
||||||
bool fetched;
|
bool fetched;
|
||||||
bool updated;
|
bool updated;
|
||||||
|
|
|
@ -89,7 +89,7 @@ FeedController::_DownloadLoop(void* ignored)
|
||||||
|
|
||||||
while (receive_data(&sender, (void*)feedBuffer, sizeof(Feed)) != 0) {
|
while (receive_data(&sender, (void*)feedBuffer, sizeof(Feed)) != 0) {
|
||||||
printf( "%s\n\n", feedBuffer->GetCachePath().String());
|
printf( "%s\n\n", feedBuffer->GetCachePath().String());
|
||||||
feedBuffer->FetchRemoteFeed();
|
feedBuffer->Fetch();
|
||||||
|
|
||||||
BMessage* downloaded = new BMessage(kDownloadComplete);
|
BMessage* downloaded = new BMessage(kDownloadComplete);
|
||||||
downloaded->AddData("feeds", B_RAW_TYPE, feedBuffer, sizeof(Feed));
|
downloaded->AddData("feeds", B_RAW_TYPE, feedBuffer, sizeof(Feed));
|
||||||
|
@ -110,24 +110,26 @@ FeedController::_ParseLoop(void* ignored)
|
||||||
|
|
||||||
while (receive_data(&sender, (void*)feedBuffer, sizeof(Feed)) != 0) {
|
while (receive_data(&sender, (void*)feedBuffer, sizeof(Feed)) != 0) {
|
||||||
BList entries;
|
BList entries;
|
||||||
|
BDirectory outDir = BDirectory(((App*)be_app)->cfg->outDir);
|
||||||
|
|
||||||
if (feedBuffer->IsAtom()) {
|
if (feedBuffer->IsAtom()) {
|
||||||
AtomFeed* feed = (AtomFeed*)malloc(sizeof(AtomFeed));
|
AtomFeed* feed = (AtomFeed*)malloc(sizeof(AtomFeed));
|
||||||
feed = new AtomFeed(feedBuffer);
|
feed = new AtomFeed(feedBuffer);
|
||||||
feed->Parse();
|
feed->Parse();
|
||||||
entries = feed->GetEntries();
|
entries = feed->GetNewEntries();
|
||||||
delete(feed);
|
delete(feed);
|
||||||
}
|
}
|
||||||
if (feedBuffer->IsRss()) {
|
else if (feedBuffer->IsRss()) {
|
||||||
RssFeed* feed = (RssFeed*)malloc(sizeof(RssFeed));
|
RssFeed* feed = (RssFeed*)malloc(sizeof(RssFeed));
|
||||||
feed = new RssFeed(feedBuffer);
|
feed = new RssFeed(feedBuffer);
|
||||||
feed->Parse();
|
feed->Parse();
|
||||||
entries = feed->GetEntries();
|
entries = feed->GetNewEntries();
|
||||||
delete(feed);
|
delete(feed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (feedBuffer->IsAtom() || feedBuffer->IsRss())
|
||||||
for (int i = 0; i < entries.CountItems(); i++)
|
for (int i = 0; i < entries.CountItems(); i++)
|
||||||
((Entry*)entries.ItemAt(i))->Filetize(true);
|
((Entry*)entries.ItemAt(i))->Filetize(outDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete (feedBuffer);
|
delete (feedBuffer);
|
||||||
|
|
|
@ -14,15 +14,15 @@
|
||||||
RssFeed::RssFeed()
|
RssFeed::RssFeed()
|
||||||
{
|
{
|
||||||
title = BString("Untitled Feed");
|
title = BString("Untitled Feed");
|
||||||
description = BString("");
|
|
||||||
homeUrl = BString("");
|
|
||||||
xmlUrl = BString("");
|
xmlUrl = BString("");
|
||||||
outputDir = ((App*)be_app)->cfg->outDir;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RssFeed::RssFeed(Feed* feed) : RssFeed::RssFeed()
|
RssFeed::RssFeed(Feed* feed)
|
||||||
{ SetCachePath(feed->GetCachePath()); }
|
: RssFeed::RssFeed()
|
||||||
|
{
|
||||||
|
SetCachePath(feed->GetCachePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -39,9 +39,9 @@ RssFeed::Parse()
|
||||||
RootParse(xchan);
|
RootParse(xchan);
|
||||||
ParseEntries(xchan);
|
ParseEntries(xchan);
|
||||||
|
|
||||||
time_t tt_lastDate = lastDate.Time_t();
|
time_t tt_date = date.Time_t();
|
||||||
BFile* feedFile = new BFile(GetCachePath().String(), B_READ_ONLY);
|
BFile* feedFile = new BFile(cachePath, B_READ_ONLY);
|
||||||
feedFile->WriteAttr("LastDate", B_TIME_TYPE, 0, &tt_lastDate, sizeof(time_t));
|
feedFile->WriteAttr("LastDate", B_TIME_TYPE, 0, &tt_date, sizeof(time_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,12 +49,10 @@ void
|
||||||
RssFeed::RootParse(tinyxml2::XMLElement* xchan)
|
RssFeed::RootParse(tinyxml2::XMLElement* xchan)
|
||||||
{
|
{
|
||||||
SetTitle(xchan->FirstChildElement("title"));
|
SetTitle(xchan->FirstChildElement("title"));
|
||||||
SetDesc(xchan->FirstChildElement("description"));
|
|
||||||
SetHomeUrl(xchan->FirstChildElement("link"));
|
|
||||||
SetDate(xchan->FirstChildElement("lastBuildDate"));
|
SetDate(xchan->FirstChildElement("lastBuildDate"));
|
||||||
|
|
||||||
if (((App*)be_app)->cfg->verbose)
|
printf("Channel '%s' at '%s':\n", title.String(),
|
||||||
printf("Channel '%s' at '%s':\n", title.String(), homeUrl.String());
|
xmlUrl.UrlString().String());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,7 +60,7 @@ void
|
||||||
RssFeed::EntryParse(tinyxml2::XMLElement* xitem)
|
RssFeed::EntryParse(tinyxml2::XMLElement* xitem)
|
||||||
{
|
{
|
||||||
Entry* newEntry = (Entry*)malloc(sizeof(Entry));
|
Entry* newEntry = (Entry*)malloc(sizeof(Entry));
|
||||||
newEntry = new Entry(outputDir);
|
newEntry = new Entry();
|
||||||
|
|
||||||
newEntry->SetTitle(xitem->FirstChildElement("title"));
|
newEntry->SetTitle(xitem->FirstChildElement("title"));
|
||||||
newEntry->SetDesc(xitem->FirstChildElement("description"));
|
newEntry->SetDesc(xitem->FirstChildElement("description"));
|
||||||
|
@ -71,8 +69,8 @@ RssFeed::EntryParse(tinyxml2::XMLElement* xitem)
|
||||||
newEntry->SetContent(xitem->FirstChildElement("content:encoded"));
|
newEntry->SetContent(xitem->FirstChildElement("content:encoded"));
|
||||||
newEntry->SetFeedTitle(title);
|
newEntry->SetFeedTitle(title);
|
||||||
|
|
||||||
if (lastDate == NULL || lastDate < newEntry->date)
|
if (date == NULL || date < newEntry->GetDate())
|
||||||
lastDate = newEntry->date;
|
date = newEntry->date;
|
||||||
|
|
||||||
AddEntry(newEntry);
|
AddEntry(newEntry);
|
||||||
}
|
}
|
||||||
|
@ -88,7 +86,6 @@ RssFeed::ParseEntries(tinyxml2::XMLElement* xchan)
|
||||||
int entryCount = xmlCountSiblings(xitem, "item");
|
int entryCount = xmlCountSiblings(xitem, "item");
|
||||||
entries = BList(entryCount);
|
entries = BList(entryCount);
|
||||||
|
|
||||||
if (((App*)be_app)->cfg->verbose)
|
|
||||||
printf("\t-%i entries-\n", entryCount);
|
printf("\t-%i entries-\n", entryCount);
|
||||||
|
|
||||||
while (xitem) {
|
while (xitem) {
|
||||||
|
|
21
src/Util.cpp
21
src/Util.cpp
|
@ -84,7 +84,8 @@ withinDateRange(BDateTime minDate, BDateTime nowDate, BDateTime maxDate)
|
||||||
|
|
||||||
// return whether or not the given path is remote
|
// return whether or not the given path is remote
|
||||||
bool
|
bool
|
||||||
isRemotePath(BString path) {
|
isRemotePath(BString path)
|
||||||
|
{
|
||||||
BUrl givenUrl = BUrl(path);
|
BUrl givenUrl = BUrl(path);
|
||||||
BString protocol = givenUrl.Protocol().String();
|
BString protocol = givenUrl.Protocol().String();
|
||||||
|
|
||||||
|
@ -95,6 +96,24 @@ isRemotePath(BString path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
urlToFilename(BUrl url)
|
||||||
|
{
|
||||||
|
BString protocol = url.Protocol().String();
|
||||||
|
|
||||||
|
if (protocol == NULL && url.UrlString() != NULL) {
|
||||||
|
return BString("");
|
||||||
|
}
|
||||||
|
|
||||||
|
BString filename = url.Host();
|
||||||
|
filename.Append(url.Path());
|
||||||
|
filename.ReplaceAll("/", "_");
|
||||||
|
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
fetch(BUrl url, BDataIO* reply, BString* hash, int timeout)
|
fetch(BUrl url, BDataIO* reply, BString* hash, int timeout)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,6 +23,8 @@ bool withinDateRange(BDateTime, BDateTime, BDateTime);
|
||||||
|
|
||||||
bool isRemotePath(BString);
|
bool isRemotePath(BString);
|
||||||
|
|
||||||
|
BString urlToFilename(BUrl url);
|
||||||
|
|
||||||
int32 fetch(BUrl url, BDataIO* reply, BString* hash, int timeout);
|
int32 fetch(BUrl url, BDataIO* reply, BString* hash, int timeout);
|
||||||
|
|
||||||
|
|
||||||
|
|
Ŝarĝante…
Reference in New Issue