⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 feedfile.cpp.svn-base

📁 wince c++ 下 开发的 rss 阅读器源代码
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
/**
 *  FeedFile.cpp
 *
 *  Copyright (C) 2008  David Andrs <pda@jasnapaka.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#ifdef PRSSR_APP
	#include "../StdAfx.h"
	#include "../prssr.h"
#endif

#if defined PRSSR_TODAY
	#include "..\prssrtoday\StdAfx.h"
#endif

#include "FeedFile.h"
#include "../../share/helpers.h"
#include "../../share/date.h"
#include "../Feed.h"
#include "../www/LocalHtmlFile.h"

#ifdef MYDEBUG
#undef THIS_FILE
static TCHAR THIS_FILE[] = _T(__FILE__);
#include "../debug/crtdbg.h"
#define new MYDEBUG_NEW
#endif

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


BOOL DcDateToSytemTime(LPCTSTR strTime, SYSTEMTIME *time) {
	LOG0(5, "DcDateToSytemTime()");

	SYSTEMTIME st = { 0 };

	TCHAR sign;
	double second = 0;
	int year, month, day, hour = 0, minute = 0, tzhour = 0, tzmin = 0;
	if (swscanf(strTime, _T("%d-%d-%dT%d:%d:%lf%c%d:%d"),
		&year, &month, &day, &hour, &minute, &second, &sign, &tzhour, &tzmin) < 6)
		return FALSE;

	st.wYear = year;
	st.wMonth = month;
	st.wDay = day;
	st.wHour = hour;
	st.wMinute = minute;
	st.wSecond = (int) second;

	if (sign == '+')
		*time = TimeToGMT(&st, -tzhour, tzmin);
	else
		*time = TimeToGMT(&st, tzhour, tzmin);

	return TRUE;
}

BOOL DateToSystemTime(LPCTSTR strTime, SYSTEMTIME *time) {
	LOG0(5, "DateToSytemTime()");

	SYSTEMTIME st = { 0 };

	int day, month, year;
	int hour = 0, minute = 0, second = 0;
	int tzhour = 0, tzmin = 0;

	// try format: yyyy-mm-dd hh:mm:ss (violates RSS standard)
	if (swscanf(strTime, _T("%d-%d-%d %d:%d:%d"), &year, &month, &day, &hour, &minute, &second) < 6)
		return FALSE;

	st.wDay = day;
	st.wMonth = month;
	st.wYear = year;
	st.wHour = hour;
	st.wMinute = minute;
	st.wSecond = second;

	// use default time zone
	TIME_ZONE_INFORMATION tzi;
	GetTimeZoneInformation(&tzi);
	tzhour = -(tzi.Bias / 60);
	tzmin = -(tzi.Bias % 60);

	*time = TimeToGMT(&st, tzhour, tzmin);

	return TRUE;
}

BOOL DateRfc822ToSystemTime(LPCTSTR strTime, SYSTEMTIME *time) {
	LOG0(5, "DateRfc822ToSystemTime()");

	SYSTEMTIME st = { 0 };
	TCHAR buffer[1024] = { 0 };
	lstrcpy(buffer, strTime);

	int day, year;
	int hour = 0, minute = 0, second = 0;
	int tzhour = 0, tzmin = 0;


	TCHAR seps[] = _T(" ");
	TCHAR *token = NULL;

	token = wcstok(buffer, seps);
	if (token == NULL) return FALSE;
	if (wcschr(token, ',') != NULL)
		token = wcstok(NULL, seps);

	// day
	if (swscanf(token, _T("%d"), &day) != 1) return FALSE;
	st.wDay = day;

	// month
	token = wcstok(NULL, seps);
	if (token == NULL) return FALSE;

	if (_wcsnicmp(token, _T("Jan"), 3) == 0) st.wMonth = 1;
	else if (_wcsnicmp(token, _T("Feb"), 3) == 0) st.wMonth = 2;
	else if (_wcsnicmp(token, _T("Mar"), 3) == 0) st.wMonth = 3;
	else if (_wcsnicmp(token, _T("Apr"), 3) == 0) st.wMonth = 4;
	else if (_wcsnicmp(token, _T("May"), 3) == 0) st.wMonth = 5;
	else if (_wcsnicmp(token, _T("Jun"), 3) == 0) st.wMonth = 6;
	else if (_wcsnicmp(token, _T("Jul"), 3) == 0) st.wMonth = 7;
	else if (_wcsnicmp(token, _T("Aug"), 3) == 0) st.wMonth = 8;
	else if (_wcsnicmp(token, _T("Sep"), 3) == 0) st.wMonth = 9;
	else if (_wcsnicmp(token, _T("Oct"), 3) == 0) st.wMonth = 10;
	else if (_wcsnicmp(token, _T("Nov"), 3) == 0) st.wMonth = 11;
	else if (_wcsnicmp(token, _T("Dec"), 3) == 0) st.wMonth = 12;
	else return FALSE;

	// year
	token = wcstok(NULL, seps);
	if (token == NULL) return FALSE;

	if (swscanf(token, _T("%d"), &year) != 1) return FALSE;
	if (wcslen(token) == 4) {
		st.wYear = year;
	}
	else {
		// Note: ugly, but simple
		st.wYear = 2000 + year;
	}

	// time
	token = wcstok(NULL, seps);
	if (token == NULL) {
		// HACK: no time specified (violates RSS specification)
		st.wHour = 0;
		st.wMinute = 0;
		st.wSecond = 0;

		// make time zone correction
		TIME_ZONE_INFORMATION tzi;
		GetTimeZoneInformation(&tzi);
		tzhour = -(tzi.Bias / 60);
		tzmin = -(tzi.Bias % 60);
	}
	else {
		swscanf(token, _T("%d:%d:%d"), &hour, &minute, &second);
		st.wHour = hour;
		st.wMinute = minute;
		st.wSecond = second;

		// convert to time zone
		token = wcstok(NULL, seps);
		if (token != NULL) {
			TCHAR sign;
			int tzh = 0, tzm = 0;
			if (swscanf(token, _T("%c%02d%02d"), &sign, &tzh, &tzm) == 3) {
				if (sign == '+') {
					tzhour = tzh;
					tzmin = tzm;
				}
				else {
					tzhour = -tzh;
					tzmin = -tzm;
				}
			}
			// textual representation of time zone
			else if (wcscmp(token, _T("GMT")) == 0) {
				tzhour = 0; tzmin = 0;
			}
			else if (wcscmp(token, _T("UT")) == 0) {
				tzhour = 0; tzmin = 0;
			}
			else if (wcscmp(token, _T("EST")) == 0) {
				tzhour = -5; tzmin = 00;
			}
			else if (wcscmp(token, _T("EDT")) == 0) {
				tzhour = -4; tzmin = 00;
			}
			else if (wcscmp(token, _T("CST")) == 0) {
				tzhour = -6; tzmin = 00;
			}
			else if (wcscmp(token, _T("CDT")) == 0) {
				tzhour = -5; tzmin = 00;
			}
			else if (wcscmp(token, _T("MST")) == 0) {
				tzhour = -7; tzmin = 00;
			}
			else if (wcscmp(token, _T("MDT")) == 0) {
				tzhour = -6; tzmin = 00;
			}
			else if (wcscmp(token, _T("PST")) == 0) {
				tzhour = -8; tzmin = 00;
			}
			else if (wcscmp(token, _T("PDT")) == 0) {
				tzhour = -7; tzmin = 00;
			}
			else {
				// use default time zone
				TIME_ZONE_INFORMATION tzi;
				GetTimeZoneInformation(&tzi);
				tzhour = -(tzi.Bias / 60);
				tzmin = -(tzi.Bias % 60);
			}
		}
		else {
			// use default time zone
			TIME_ZONE_INFORMATION tzi;
			GetTimeZoneInformation(&tzi);
			tzhour = -(tzi.Bias / 60);
			tzmin = -(tzi.Bias % 60);
		}
	}

	*time = TimeToGMT(&st, tzhour, tzmin);

	return TRUE;
}

BOOL ConvertToSytemTime(LPCTSTR strTime, SYSTEMTIME *time) {
	LOG1(5, "ConvertToSytemTime('%S')", strTime);

	if (DcDateToSytemTime(strTime, time))
		return TRUE;

	if (DateToSystemTime(strTime, time))
		return TRUE;

	if (DateRfc822ToSystemTime(strTime, time))
		return TRUE;

	return FALSE;
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CFeedFile::CFeedFile() {
}

CFeedFile::~CFeedFile() {
}

CFeedFile::EType CFeedFile::GetType() {
	LOG0(5, "CFeedFile::GetType()");

	CFeedFile::EType type = Unknown;

	CString tagName = RootNode->GetName();
	if (tagName.Compare(_T("rss")) == 0)
		type = RSS;
	else if (tagName.Compare(_T("rdf:RDF")) == 0)
//	else if (tagName.Compare(_T("rdf")) == 0)
		type = RDF;
	else if (tagName.Compare(_T("feed")) == 0)
		type = Atom;

	return type;
}

CString CFeedFile::GetVersion() {
	LOG0(5, "CFeedFile::GetVersion()");

	CString version = _T("???");

	CString tagName = RootNode->GetName();
	if (tagName.Compare(_T("rss")) == 0) {
		POSITION pos = RootNode->GetFirstAttrPos();
		while (pos != NULL) {
			CXmlAttr *attr = RootNode->GetNextAttr(pos);
			if (attr->GetName().CompareNoCase(_T("version")) == 0) {
				version = attr->GetValue();
			}
		}
	}
	else if (tagName.Compare(_T("rdf:RDF")) == 0)
		version = _T("1.0");
	else if (tagName.Compare(_T("feed")) == 0) {
		POSITION pos = RootNode->GetFirstAttrPos();
		while (pos != NULL) {
			CXmlAttr *attr = RootNode->GetNextAttr(pos);
			if (attr->GetName().CompareNoCase(_T("version")) == 0) {
				version = attr->GetValue();
			}
		}
	}

	return version;
}


BOOL CFeedFile::IsValid() {
	BOOL ret = TRUE;

	return GetType() != Unknown;
}

BOOL CFeedFile::Parse(CFeed *feed, CSiteItem *si) {
	LOG0(5, "CFeedFile::Parse()");

	BOOL ret = FALSE;
	EType type = GetType();

	switch (type) {
		case RSS:
			ret = RSSFill(feed, si);
			break;

		case RDF:
			ret = RDFFill(feed, si);
			break;

		case Atom:
			ret = AtomFill(feed, si);
			break;

		default:
			return FALSE;
	} // switch

#if defined PRSSR_APP
	// fill milisecond field (crucial for proper sorting)
	for (int i = feed->GetItemCount() - 1; i >= 0; i--) {
		CFeedItem *item = feed->GetItem(i);
		item->Date.wMilliseconds = (WORD) (GetTickCount() & 0xFFFF);
		Sleep(1);
	}
#endif


#if defined PRSSR_APP
	CString version = GetVersion();
	// set format
	CString strFormat;
	switch (type) {
		case RSS: strFormat.Format(IDS_FEED_FMT, _T("RSS"), version); break;
		case RDF: strFormat.Format(IDS_FEED_FMT, _T("RDF"), version); break;
		case Atom: strFormat.Format(IDS_FEED_FMT, _T("Atom"), version); break;
	} // switch
	feed->Format = strFormat;
#endif

	return TRUE;
}

BOOL CFeedFile::RSSFillInfo(CXmlNode *parent, CFeed *feed) {
	LOG0(5, "CFeedFile::RSSFillInfo()");

	BOOL ret = FALSE;

	CString updatePeriod;
	int updateFrequency = -1;
	int ttl = -1;

	POSITION pos = parent->GetFirstChildPos();
	while (pos != NULL) {
		CXmlNode *child = parent->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("description")) == 0)
			feed->Description = child->GetValue();
		else if (name.Compare(_T("link")) == 0) {
			feed->HtmlUrl = child->GetValue();
			if (BaseUrl.IsEmpty()) BaseUrl = child->GetValue();
		}
		else if (name.Compare(_T("language")) == 0 || name.Compare(_T("dc:language")) == 0)
			feed->Language = child->GetValue();
		else if (name.Compare(_T("copyright")) == 0 || name.Compare(_T("dc:rights")) == 0)
			feed->Copyright = child->GetValue();
#endif
#if defined PRSSR_APP
		else if (name.Right(13).Compare(_T(":updatePeriod")) == 0) {
			updatePeriod = child->GetValue();
		}
		else if (name.Right(16).Compare(_T(":updateFrequency")) == 0) {
			swscanf(child->GetValue(), _T("%d"), &updateFrequency);
		}
		else if (name.Compare(_T("ttl")) == 0) {
			swscanf(child->GetValue(), _T("%d"), &ttl);
		}
#endif
	}

#if defined PRSSR_APP
	if (ttl != -1) {
		feed->UpdateInterval = ttl;
	}
	else {
		int mins = 0;
		if (updatePeriod.CompareNoCase(_T("hourly")) == 0)
			mins = 60;
		else if (updatePeriod.CompareNoCase(_T("daily")) == 0)
			mins = 1440;
		else if (updatePeriod.CompareNoCase(_T("weekly")) == 0)
			mins = 10080;
		else if (updatePeriod.CompareNoCase(_T("monthly")) == 0)
			mins = 44640;
		else if (updatePeriod.CompareNoCase(_T("yearly")) == 0)
			mins = 525600;

		feed->UpdateInterval = mins / updateFrequency;
	}
#endif

	return ret;
}

BOOL CFeedFile::RSSFillItem(CXmlNode *xmlItem, CFeedItem *item) {
	LOG0(5, "CFeedFile::RSSFillItem()");

#if defined PRSSR_APP
	CString sDescription, sContent;
#endif

	POSITION pos = xmlItem->GetFirstChildPos();
	while (pos != NULL) {
		CXmlNode *childNode = xmlItem->GetNextChild(pos);

		CString name = childNode->GetName();
		CString value = childNode->GetXML();
		if (name.Compare(_T("title")) == 0) {
			value.Remove('\r');
			value.Remove('\n');
			item->Title = StripHtmlTags(value);
		}
		else if (wcscmp(name, _T("guid")) == 0) {
			item->Hash = value;
		}
#if defined PRSSR_APP
		else if (name.Compare(_T("description")) == 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -