📄 addfeeddlg.cpp.svn-base
字号:
/**
* AddFeedDlg.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/>.
*
*/
#include "StdAfx.h"
#include "prssr.h"
#include "AddFeedDlg.h"
#include "prssr.h"
#include "Config.h"
#include "misc.h"
#include "Errors.h"
#include "net/HttpConnection.h"
#include "net/Connection.h"
#include "net/Download.h"
#include "Site.h"
#include "Feed.h"
#include "xml/FeedFile.h"
#include "ProgressDlg.h"
#include "ChooseFeedsDlg.h"
#include "www/HTMLFile.h"
#include "www/AutoFeedHtmlFile.h"
#include "sync/NetworkSync.h"
#include "sync/GReaderSync.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
static CRITICAL_SECTION CSDownloader;
DWORD WINAPI AddThreadProc(LPVOID lpParameter) {
CAddFeedDlg *dlg = (CAddFeedDlg *) lpParameter;
return dlg->AddThread();
}
/////////////////////////////////////////////////////////////////////////////
// CAddProgressDlg dialog
class CAddProgressDlg : public CProgressDlg {
public:
CAddProgressDlg(CDownloader *downloader, CAddFeedDlg *parent);
virtual ~CAddProgressDlg();
protected:
UINT Timer;
UINT ProgressRefreshTimer;
EDownloadState State;
CDownloader *Downloader;
CAddFeedDlg *Parent;
int RangeHi, PosOffset;
//{{AFX_MSG(CAddProgressDlg)
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnDestroy();
//}}AFX_MSG
virtual BOOL OnInitDialog();
virtual void OnCancel();
DECLARE_MESSAGE_MAP()
friend class CAddFeedDlg;
};
CAddProgressDlg::CAddProgressDlg(CDownloader *downloader, CAddFeedDlg *parent) {
Downloader = downloader;
State = DOWNLOAD_STATE_NONE;
Timer = 1;
ProgressRefreshTimer = 2;
Parent = parent;
RangeHi = 160000;
PosOffset = 0;
}
CAddProgressDlg::~CAddProgressDlg() {
}
BEGIN_MESSAGE_MAP(CAddProgressDlg, CProgressDlg)
//{{AFX_MSG_MAP(CAddProgressDlg)
ON_WM_TIMER()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CAddProgressDlg::OnInitDialog() {
LOG0(3, "CAddProgressDlg::OnInitDialog()");
SetTimer(Timer, 500, NULL);
SetTimer(ProgressRefreshTimer, 700, NULL);
CProgressDlg::OnInitDialog();
SetRange(0, RangeHi);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CAddProgressDlg::OnDestroy() {
KillTimer(Timer);
KillTimer(ProgressRefreshTimer);
CProgressDlg::OnDestroy();
}
void CAddProgressDlg::OnTimer(UINT nIDEvent) {
if (nIDEvent == Timer) {
/* EDownloadState state = DOWNLOAD_STATE_NONE;
EnterCriticalSection(&CSDownloader);
if (Downloader != NULL)
state = Downloader->State;
LeaveCriticalSection(&CSDownloader);
if (State != state) {
State = state;
CString sText;
switch (state) {
case DOWNLOAD_STATE_CONNECTING: sText.LoadString(IDS_CONNECTING); break;
case DOWNLOAD_STATE_CONNECTED: sText.LoadString(IDS_CONNECTED); break;
case DOWNLOAD_STATE_SENDING_REQUEST: sText.LoadString(IDS_SENDING_REQUEST); break;
case DOWNLOAD_STATE_RECEIVING_RESPONSE: sText.LoadString(IDS_GETTING_RESPONSE); break;
case DOWNLOAD_STATE_DATA_TRANSFER: sText.LoadString(IDS_DATA_TRANSFER); break;
default: sText.LoadString(IDS_SEARCHING); break;
}
sText += _T("...");
m_ctlLabel.SetWindowText(sText);
}
*/
}
else if (nIDEvent == ProgressRefreshTimer) {
EnterCriticalSection(&CSDownloader);
if (Downloader != NULL) {
int newPos = PosOffset + (int) Downloader->GetDownloadedFileSize();
if (newPos > RangeHi) {
RangeHi *= 10;
SetRange(0, RangeHi);
}
SetPos(newPos);
}
LeaveCriticalSection(&CSDownloader);
}
CWnd::OnTimer(nIDEvent);
}
void CAddProgressDlg::OnCancel() {
LOG0(3, "CAddProgressDlg::OnCancel()");
KillTimer(ProgressRefreshTimer);
KillTimer(Timer);
EnterCriticalSection(&CSDownloader);
if (Downloader != NULL)
Downloader->Terminate();
LeaveCriticalSection(&CSDownloader);
CProgressDlg::OnCancel();
}
/////////////////////////////////////////////////////////////////////////////
// CAddFeedDlg dialog
CAddFeedDlg::CAddFeedDlg(CWnd *pParent/* = NULL*/)
: CCeDialog(InWideMode() ? CAddFeedDlg::IDD_WIDE : CAddFeedDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CAddFeedDlg)
//}}AFX_DATA_INIT
// m_strCaption.LoadString(IDS_NEW_SUBSCRIPTION);
m_nMenuID = IDR_ADD;
m_bCheckOnline = TRUE;
m_pProgress = NULL;
Downloader = NULL;
InitializeCriticalSection(&CSDownloader);
}
CAddFeedDlg::~CAddFeedDlg() {
DeleteCriticalSection(&CSDownloader);
}
void CAddFeedDlg::DoDataExchange(CDataExchange* pDX) {
LOG0(5, "CAddFeedDlg::DoDataExchange()");
CCeDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAddFeedDlg)
//}}AFX_DATA_MAP
DDX_Control(pDX, IDC_URL, m_ctlURL);
DDX_Text(pDX, IDC_URL, m_strURL);
DDV_NotEmpty(pDX, m_strURL, IDS_URL_CAN_NOT_BE_EMPTY);
if (pDX->m_bSaveAndValidate) {
if (m_strURL.Find(_T("://")) == -1)
m_strURL = CString(_T("http://")) + m_strURL;
DWORD srvType;
CString server, object;
INTERNET_PORT port;
if (!ParseURL(m_strURL, srvType, server, object, port)) {
Error(IDS_INVALID_URL);
pDX->Fail();
}
}
DDX_Control(pDX, IDC_CHECK_FEED_ONLINE, m_ctlCheckOnline);
DDX_Check(pDX, IDC_CHECK_FEED_ONLINE, m_bCheckOnline);
DDX_Control(pDX, IDC_NAME, m_ctlName);
DDX_Text(pDX, IDC_NAME, m_strName);
if (pDX->m_bSaveAndValidate) {
if (!m_bCheckOnline && m_strName.IsEmpty()) {
Error(IDS_NAME_CAN_NOT_BE_EMPTY);
pDX->Fail();
}
}
}
BEGIN_MESSAGE_MAP(CAddFeedDlg, CCeDialog)
//{{AFX_MSG_MAP(CAddFeedDlg)
ON_COMMAND(ID_ADD, OnAdd)
ON_COMMAND(ID_CLOSE, OnClose)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CAddFeedDlg message handlers
BOOL CAddFeedDlg::OnInitDialog() {
LOG0(3, "CAddFeedDlg::OnInitDialog()");
CCeDialog::OnInitDialog();
m_ctlURL.SetWindowText(_T("http://"));
// m_ctlURL.SetWindowText(_T("http://www.lamer.cz/"));
// m_ctlURL.SetWindowText(_T("http://192.168.2.1/garfield-gz.php"));
// m_ctlURL.SetWindowText(_T("http://www.kravicky.unas.cz/rss.xml"));
// m_ctlURL.SetWindowText(_T("http://isnoop.net/rss/theater.php?loc=79912&th=Cinemark+El+Paso&rss=1"));
m_ctlURL.PostMessage(EM_SETSEL, -1, 0);
UpdateControls();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CAddFeedDlg::OnAdd() {
LOG0(1, "CAddFeedDlg::OnAdd()");
if (UpdateData())
OnOK();
}
void CAddFeedDlg::OnClose() {
LOG0(1, "CAddFeedDlg::OnClose()");
EndDialog(IDOK);
}
void CAddFeedDlg::UpdateControls() {
}
void CAddFeedDlg::ResizeControls() {
LOG0(3, "CAddFeedDlg::ResizeControls()");
RelayoutDialog(AfxGetInstanceHandle(), GetSafeHwnd(), InWideMode() ?
MAKEINTRESOURCE(IDD_WIDE) :
MAKEINTRESOURCE(IDD));
}
void CAddFeedDlg::OnOK() {
LOG0(1, "CAddFeedDlg::OnOK()");
if (m_bCheckOnline) {
if (m_pProgress == NULL) {
EnterCriticalSection(&CSDownloader);
Downloader = new CDownloader();
LeaveCriticalSection(&CSDownloader);
m_pProgress = new CAddProgressDlg(Downloader, this);
m_pProgress->OpenDialog(IDS_DOWNLOADING_FEED, this);
CloseHandle(CreateThread(NULL, 0, AddThreadProc, this, 0, NULL));
}
else
m_pProgress->SetActiveWindow();
}
else
OnClose();
}
DWORD CAddFeedDlg::AddThread() {
LOG0(1, "CAddFeedDlg::AddThread() - start");
CString errorMsg;
CList<CHtmlFeed *, CHtmlFeed *> lFeeds;
lFeeds.AddTail(new CHtmlFeed(_T(""), m_strURL));
BOOL bOK = FALSE;
BOOL disconnect;
if (CheckConnection(Config.AutoConnect, disconnect)) {
DWORD type;
CString server, object;
INTERNET_PORT port;
ParseURL(m_strURL, type, server, object, port);
int t = 0;
while (lFeeds.GetCount() > 0 && !Downloader->IsTerminated()) {
CHtmlFeed *htmlFeedItem = lFeeds.RemoveHead();
// temp file name
CString sFileName;
LPTSTR fileName = sFileName.GetBufferSetLength(MAX_PATH + 1);
GetTempFileName(Config.CacheLocation, _T("rsr"), 0, fileName);
CFeedSync *sync = new CNetworkSync(Downloader);
// TODO: get the feed from greader if we use it
if (sync->DownloadFeed(htmlFeedItem->Url, fileName)) {
// prepare data structures
CSiteItem *item = new CSiteItem(NULL, CSiteItem::Site);
// process downloaded file
CFeedFile xml;
CFeed *feed = new CFeed;
if (xml.LoadFromFile(fileName) && xml.Parse(feed, item)) {
CFeedInfo *info = new CFeedInfo();
info->FileName = CFeedInfo::GenerateFileName(htmlFeedItem->Url);
info->XmlUrl = htmlFeedItem->Url;
// If the authentication was not required, SavePassword is FALSE
if (Downloader->GetSavePassword()) {
info->UserName = Downloader->GetUserName();
info->Password = Downloader->GetPassword();
}
item->Status = CSiteItem::Ok;
item->Name = feed->Title;
item->Feed = feed;
item->Info = info;
item->CheckFavIcon = FALSE;
CString sFeedFileName = GetCacheFile(FILE_TYPE_FEED, Config.CacheLocation, info->FileName);
item->Feed->Save(sFeedFileName);
// try to get favicon
CString sFaviconFileName = GetCacheFile(FILE_TYPE_FAVICON, Config.CacheLocation, info->FileName);
if (DownloadFavIcon(feed->HtmlUrl, sFaviconFileName)) {
// we've got a favicon
}
SiteItemsToAdd.AddTail(item);
bOK = TRUE;
}
else {
feed->Destroy();
delete feed;
delete item;
// do auto discovery only in first iteration
if (t == 0) {
CDiscoverFeedHtmlFile html;
if (html.LoadFromFile(fileName)) {
html.DetectEncoding(Downloader->GetCharset());
lFeeds.RemoveAll();
CList<CHtmlFeed *, CHtmlFeed *> feeds;
html.GetRSS(feeds);
// make all feed URLs absolute
POSITION pos = feeds.GetHeadPosition();
while (pos != NULL) {
CHtmlFeed *hf = feeds.GetNext(pos);
if (hf->Url.Left(7).CompareNoCase(_T("http://")) == 0 || hf->Url.Left(8).CompareNoCase(_T("https://")) == 0) {
// full URL -> do nothing
}
else if (hf->Url.GetAt(0) == '/') {
hf->Url.Format(_T("http://%s%s"), server, hf->Url);
}
else {
hf->Url.Format(_T("%s//%s"), m_strURL, hf->Url);
}
lFeeds.AddTail(hf);
}
if (feeds.GetCount() > 1) {
CChooseFeedsDlg dlg(AfxGetMainWnd());
while (!lFeeds.IsEmpty())
dlg.Feeds.AddTail(lFeeds.RemoveHead());
if (dlg.DoModal() == IDOK) {
lFeeds.RemoveAll();
while (!dlg.Feeds.IsEmpty())
lFeeds.AddTail(dlg.Feeds.RemoveHead());
}
}
}
}
}
m_pProgress->PosOffset = m_pProgress->m_ctlProgress.GetPos();
}
else {
errorMsg = Downloader->GetErrorMsg();
} // save http opbject
delete sync;
// remove temporary feed file
DeleteFile(fileName);
delete htmlFeedItem;
t++;
} // while
if (disconnect)
Connection.HangupConnection();
}
else {
// error: can not connect to the Internet
errorMsg.LoadString(IDS_NO_INTERNET_CONNECTION);
bOK = FALSE;
}
m_pProgress->SetPos(m_pProgress->RangeHi); // fill the progress bar
// free feeds that might left in lFeeds from auto-discovery (user might cancel the operation)
while (!lFeeds.IsEmpty())
delete lFeeds.RemoveHead();
// done
DWORD error = 0;
if (bOK) {
error = 0;
SendMessage(WM_COMMAND, ID_CLOSE);
}
else {
if (Downloader->IsTerminated())
error = 1; // terminated
else {
error = 2;
Error(IDS_FEED_NOT_ADDED, errorMsg);
m_pProgress->CloseDialog();
}
SiteItemsToAdd.RemoveAll();
}
m_pProgress = NULL;
EnterCriticalSection(&CSDownloader);
delete Downloader;
Downloader = NULL;
LeaveCriticalSection(&CSDownloader);
LOG0(1, "CAddFeedDlg::AddThread() - end");
return error;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -