📄 feedfile.cpp.svn-base
字号:
sDescription = value;
else if (name.Compare(_T("content:encoded")) == 0)
sContent = value;
else if (name.Compare(_T("dc:creator")) == 0 || name.Compare(_T("author")) == 0) {
item->Author = value;
}
#endif
else if (name.Compare(_T("link")) == 0)
item->Link = value;
else if (name.Compare(_T("pubDate")) == 0 || name.Compare(_T("date")) == 0 || name.Compare(_T("dc:date")) == 0) {
SYSTEMTIME st = { 0 };
if (ConvertToSytemTime(value, &st))
item->PubDate = st;
}
#if defined PRSSR_APP
// enclosure tag has no data in
if (name.Compare(_T("enclosure")) == 0) {
CEnclosureItem *enclosure = new CEnclosureItem;
if (RSSFillEnclosure(childNode, enclosure)) {
item->Enclosures.AddTail(enclosure);
}
else {
delete enclosure;
}
}
#endif
}
#if defined PRSSR_APP
if (!sContent.IsEmpty())
item->Description = SanitizeHtml(sContent, BaseUrl);
else
item->Description = SanitizeHtml(sDescription, BaseUrl);
#endif
#if defined PRSSR_APP
// create date for proper sorting
if (item->PubDate.wYear == 0)
GetSystemTime(&item->PubDate);
item->Date = item->PubDate;
Sleep(1); // ensure that items in a feed will differ at least by 1 ms
#endif
if (item->Hash.IsEmpty())
item->ComputeHash();
return TRUE;
}
//
// RDF specific methods
//
BOOL CFeedFile::RDFFill(CFeed *feed, CSiteItem *si) {
LOG0(5, "CFeedFile::RDFFill()");
BOOL ret = FALSE;
CList<CFeedItem *, CFeedItem *> feedList;
POSITION pos = RootNode->GetFirstChildPos();
while (pos != NULL) {
CXmlNode *child = RootNode->GetNextChild(pos);
CString tagName = child->GetName();
if (tagName.Compare(_T("channel")) == 0) {
ret = RSSFillInfo(child, feed);
}
else if (tagName.Compare(_T("item")) == 0) {
CFeedItem *item = new CFeedItem(si);
if (RSSFillItem(child, item))
feedList.AddTail(item);
else
delete item;
}
}
// copy from temp list to feed
feed->SetSize(feedList.GetCount());
int idx = 0;
while (!feedList.IsEmpty())
feed->SetAt(idx++, feedList.RemoveHead());
return ret;
}
//
// RSS specific methods
//
BOOL CFeedFile::RSSFill(CFeed *feed, CSiteItem *si) {
LOG0(5, "CFeedFile::RSSFill()");
BOOL ret = FALSE;
POSITION pos;
// root tag is <rss>
pos = RootNode->GetFirstAttrPos();
while (pos != NULL) {
CXmlAttr *attr = RootNode->GetNextAttr(pos);
if (attr->GetName().CompareNoCase(_T("xml:base")) == 0) {
BaseUrl = attr->GetValue();
}
}
// get channel tag
pos = RootNode->GetFirstChildPos();
if (pos != NULL) {
CXmlNode *channel = RootNode->GetNextChild(pos);
CString tagName = channel->GetName();
if (tagName.Compare(_T("channel")) == 0) {
ret = RSSFillInfo(channel, feed);
// item list
CList<CFeedItem *, CFeedItem *> feedList;
POSITION posItem = channel->GetFirstChildPos();
while (posItem != NULL) {
CXmlNode *child = channel->GetNextChild(posItem);
CString tagName = child->GetName();
if (tagName.Compare(_T("item")) == 0) {
CFeedItem *item = new CFeedItem(si);
if (RSSFillItem(child, item))
feedList.AddTail(item);
else
delete item;
}
}
// copy from temp list to feed
feed->SetSize(feedList.GetCount());
int idx = 0;
while (!feedList.IsEmpty())
feed->SetAt(idx++, feedList.RemoveHead());
}
}
return ret;
}
#if defined PRSSR_APP
static EEnclosureType GetEnclosureType(const CString &type) {
int nPos = type.Find('/');
if (nPos != -1) {
CString sType = type.Left(nPos);
if (sType.CompareNoCase(_T("video")) == 0) return ENCLOSURE_TYPE_VIDEO;
else if (sType.CompareNoCase(_T("audio")) == 0) return ENCLOSURE_TYPE_AUDIO;
else if (sType.CompareNoCase(_T("image")) == 0) return ENCLOSURE_TYPE_IMAGE;
else return ENCLOSURE_TYPE_UNKNOWN;
}
else return ENCLOSURE_TYPE_UNKNOWN;
}
BOOL CFeedFile::RSSFillEnclosure(CXmlNode *xmlElem, CEnclosureItem *enclosure) {
LOG0(5, "CFeedFile::RSSFillEnclosure()");
BOOL ret = FALSE;
CString url, type;
long length = 0;
POSITION pos = xmlElem->GetFirstAttrPos();
while (pos != NULL) {
CXmlAttr *attr = xmlElem->GetNextAttr(pos);
CString attrName = attr->GetName();
if (attrName.Compare(_T("url")) == 0)
url = attr->GetValue();
else if (attrName.Compare(_T("length")) == 0)
swscanf(attr->GetValue(), _T("%ld"), &length);
else if (attrName.Compare(_T("type")) == 0)
type = attr->GetValue();
}
// set read values
if (!url.IsEmpty() && !type.IsEmpty()) {
enclosure->URL = url;
if (length < 0) length = 0;
enclosure->Length = length;
enclosure->Type = GetEnclosureType(type);
ret = TRUE;
}
return ret;
}
#endif
//
// Atom specific methods
//
BOOL CFeedFile::AtomFill(CFeed *feed, CSiteItem *si) {
LOG0(5, "CFeedFile::AtomFill()");
BOOL ret = AtomFillInfo(RootNode, feed);
// item list
CList<CFeedItem *, CFeedItem *> feedList;
POSITION posItem = RootNode->GetFirstChildPos();
while (posItem != NULL) {
CXmlNode *child = RootNode->GetNextChild(posItem);
CString tagName = child->GetName();
if (tagName.Compare(_T("entry")) == 0) {
CFeedItem *item = new CFeedItem(si);
if (AtomFillItem(child, item))
feedList.AddTail(item);
else
delete item;
}
}
// copy from temp list to feed
feed->SetSize(feedList.GetCount());
int idx = 0;
while (!feedList.IsEmpty())
feed->SetAt(idx++, feedList.RemoveHead());
return ret;
}
BOOL CFeedFile::AtomFillInfo(CXmlNode *xmlElem, CFeed *feed) {
LOG0(5, "CFeedFile::AtomFillInfo()");
BOOL ret = FALSE;
POSITION pos = xmlElem->GetFirstChildPos();
while (pos != NULL) {
CXmlNode *child = xmlElem->GetNextChild(pos);
CString name = child->GetName();
if (name.Compare(_T("title")) == 0) {
feed->Title = child->GetValue();
ret = TRUE;
}
#if defined PRSSR_APP
else if (name.Compare(_T("copyright")) == 0)
feed->Copyright = child->GetValue();
else if (name.Compare(_T("tagline")) == 0 || name.Compare(_T("subtitle")) == 0)
feed->Description = child->GetValue();
else if (name.Compare(_T("link")) == 0) {
CString rel, type, href;
POSITION posAttr = child->GetFirstAttrPos();
while (posAttr != NULL) {
CXmlAttr *attr = child->GetNextAttr(posAttr);
CString attrName = attr->GetName();
if (attrName.Compare(_T("rel")) == 0)
rel = attr->GetValue();
else if (attrName.Compare(_T("type")) == 0)
type = attr->GetValue();
else if (attrName.Compare(_T("href")) == 0)
href = attr->GetValue();
}
// href value of tag with attribute type="text/html" and rel="alternate" (0.3) or rel empty)
if ((rel.Compare(_T("alternate")) == 0 || rel.IsEmpty()) &&
type.Compare(_T("text/html")) == 0)
feed->HtmlUrl = href;
}
#endif
}
return ret;
}
#ifdef PRSSR_APP
BOOL CFeedFile::AtomFillPerson(CXmlNode *xmlItem, CString &name) {
LOG0(5, "CFeedFile::AtomFillPerson()");
POSITION pos = xmlItem->GetFirstChildPos();
while (pos != NULL) {
CXmlNode *child = xmlItem->GetNextChild(pos);
CString tag = child->GetName();
if (tag.Compare(_T("name")) == 0)
name = child->GetValue();
}
return TRUE;
}
#endif
BOOL CFeedFile::AtomFillItem(CXmlNode *xmlItem, CFeedItem *item) {
LOG0(5, "CFeedFile::AtomFillItem()");
SYSTEMTIME issued = { 0 };
SYSTEMTIME created = { 0 };
SYSTEMTIME modified = { 0 };
SYSTEMTIME updated = { 0 };
SYSTEMTIME published = { 0 };
CString summary, content;
CString itemId;
DWORD flagsMask = 0;
DWORD flags = 0;
POSITION pos = xmlItem->GetFirstChildPos();
while (pos != NULL) {
CXmlNode *child = xmlItem->GetNextChild(pos);
CString name = child->GetName();
if (name.Compare(_T("title")) == 0) {
CString value = child->GetValue();
value.Remove('\r');
value.Remove('\n');
item->Title = StripHtmlTags(value);
}
#if defined PRSSR_APP
else if (wcscmp(name, _T("content")) == 0) {
content = child->GetXML();
}
else if (wcscmp(name, _T("summary")) == 0) {
summary = child->GetXML();
}
else if (wcscmp(name, _T("author")) == 0) {
BOOL knownAuthor = TRUE;
POSITION posAttr = child->GetFirstAttrPos();
while (posAttr != NULL) {
CXmlAttr *attr = child->GetNextAttr(posAttr);
CString attrName = attr->GetName();
CString attrVal = attr->GetValue();
// GoogleReader specific
if (attrName.Compare(_T("gr:unknown-author")) == 0 && attrVal.CompareNoCase(_T("true")) == 0)
knownAuthor = FALSE;
}
if (knownAuthor)
AtomFillPerson(child, item->Author);
}
// GoogleReader specific
else if (wcscmp(name, _T("category")) == 0) {
CString term, label;
POSITION posAttr = child->GetFirstAttrPos();
while (posAttr != NULL) {
CXmlAttr *attr = child->GetNextAttr(posAttr);
CString attrName = attr->GetName();
if (attrName.Compare(_T("term")) == 0) term = attr->GetValue();
else if (attrName.Compare(_T("label")) == 0) label = attr->GetValue();
}
if (term.Right(11).Compare(_T("kept-unread")) == 0 && label.Compare(_T("kept-unread")) == 0) { flagsMask |= MESSAGE_READ_STATE; flags |= MESSAGE_UNREAD; }
else if (term.Right(4).Compare(_T("read")) == 0 && label.Compare(_T("read")) == 0) { flagsMask |= MESSAGE_READ_STATE; flags &= ~MESSAGE_READ_STATE; }
else if (term.Right(7).Compare(_T("starred")) == 0 && label.Compare(_T("starred")) == 0) { flagsMask |= MESSAGE_FLAG; flags |= MESSAGE_FLAG; }
}
// GoogleReader specific
else if (wcscmp(name, _T("id")) == 0) {
itemId = child->GetValue();
}
#endif
else if (wcscmp(name, _T("link")) == 0) {
CString rel, type, href;
long length;
POSITION posAttr = child->GetFirstAttrPos();
while (posAttr != NULL) {
CXmlAttr *attr = child->GetNextAttr(posAttr);
CString attrName = attr->GetName();
if (attrName.Compare(_T("rel")) == 0)
rel = attr->GetValue();
else if (attrName.Compare(_T("type")) == 0)
type = attr->GetValue();
else if (attrName.Compare(_T("href")) == 0)
href = attr->GetValue();
else if (attrName.Compare(_T("length")) == 0)
swscanf(attr->GetValue(), _T("%ld"), &length);
}
// href value of tag with attributes rel="alternate" and type="text/html"
if (rel.Compare(_T("alternate")) == 0 && type.Compare(_T("text/html")) == 0)
item->Link = href;
else if (rel.Compare(_T("enclosure")) == 0) {
if (!href.IsEmpty() && !type.IsEmpty()) {
CEnclosureItem *enclosure = new CEnclosureItem;
enclosure->URL = href;
if (length < 0) length = 0;
enclosure->Length = length;
enclosure->Type = GetEnclosureType(type);
item->Enclosures.AddTail(enclosure);
}
}
}
else if (name.Compare(_T("issued")) == 0)
ConvertToSytemTime(child->GetValue(), &issued);
else if (name.Compare(_T("updated")) == 0)
ConvertToSytemTime(child->GetValue(), &updated);
else if (name.Compare(_T("modified")) == 0)
ConvertToSytemTime(child->GetValue(), &modified);
else if (name.Compare(_T("created")) == 0)
ConvertToSytemTime(child->GetValue(), &created);
else if (name.Compare(_T("published")) == 0)
ConvertToSytemTime(child->GetValue(), &published);
}
if (issued.wYear != 0)
item->PubDate = issued;
else if (updated.wYear != 0)
item->PubDate = updated;
else if (modified.wYear != 0)
item->PubDate = modified;
else if (published.wYear != 0)
item->PubDate = updated;
else if (created.wYear != 0)
item->PubDate = created;
#if defined PRSSR_APP
// GoogleReader specific
if (flagsMask != 0)
item->SetFlags(flags, flagsMask);
if (itemId.IsEmpty())
item->ComputeHash();
else
item->Hash = itemId;
// create date for proper sorting
if (item->PubDate.wYear == 0)
GetSystemTime(&item->PubDate);
item->Date = item->PubDate;
Sleep(1);
#endif
#if defined PRSSR_APP
// if <content> is empty, then use <summary>
if (!content.IsEmpty())
item->Description = SanitizeHtml(content, BaseUrl);
else
item->Description = SanitizeHtml(summary, BaseUrl);
#endif
return TRUE;
}
#if defined PRSSR_APP
static CString SanitizeHtml(const CString &html, const CString &baseUrl) {
// sanitize HTML
CLocalHtmlFile file(baseUrl);
CString s;
s.Format(_T("<div>%s</div>"), html); // libsgml workaround
file.LoadFromMemory(s);
file.Filter();
file.RewriteRelativeUrls();
return file.ToString();
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -