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

📄 stockquotes_.cpp

📁 一个补票分析程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
						 MB_ICONEXCLAMATION | MB_OK);
		}
		e->Delete();
	}
	DelSession();
	g_bUpdating = false;
	Unlock();
	return S_OK;
}

// Helper function to shutdown the updating process, terminates any pending
// updates.
//
void CStockQuotes::ShutdownUpdating()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())
	g_bStopUpdating = true;
	if (m_pINetSession)
		m_pINetSession->Close();

	TermNotifyThread();
	DelSession(false);
	g_bStopUpdating = false;
}

// Helper function to close and delete session.
//
void CStockQuotes::DelSession(bool bCloseFirst)
{
	if (bCloseFirst && m_pINetSession)
		m_pINetSession->Close();
	delete m_pINetSession;
	m_pINetSession = 0;
}

// Helper function to terminate notification thread.
// Waits for thread to end, otherwise we could get a memory leak when things
// shutdown.
//
void CStockQuotes::TermNotifyThread()
{
	if (m_pStockUpdateNotify)
	{
		m_pStockUpdateNotify->PostThreadMessage(WM_QUIT, 0, 0);
		::WaitForSingleObject(m_pStockUpdateNotify->m_hThread, 30000);
	}
}

// Write CString to stream.
//
//
void CStockQuotes::SaveString(COleStreamFile& strmFile, CString& s)
{
	int     size;
	LPTSTR  psz;
	size = s.GetLength();
	psz = s.LockBuffer();
	strmFile.Write(&size, sizeof(size));        // size of string.
	strmFile.Write(psz, size);                  // string.
	s.UnlockBuffer();
}

// Read CString from stream.
//
//
void CStockQuotes::LoadString(COleStreamFile& strmFile, CString& s)
{
	TCHAR           buf[128];       // more than enough for a stock symbol.
	int             strSize = 0;

	memset(buf, 0, sizeof(TCHAR)*128);
	strmFile.Read(&strSize, sizeof(strSize));   // size of string.
	strmFile.Read(buf, strSize);
	s = buf;
}


// debugging function.
// format:
// <symbol>:<price> <change>
void CStockQuotes::PrintStocks()
{
#if 0   // set to 1 to use.
	for (CStockListIter i = m_stockList.begin();
		 i != m_stockList.end(); i++)
	{
		CStock  s = *i;
		std::cout << (LPCTSTR)s.GetSymbol() << _T(":") << (LPCTSTR)s.GetCurrent() << _T(" ")
				  << (LPCTSTR)s.GetChange() << std::endl;
	}
#endif
}


///////////////////////////////////////////////////////////////////////////////
// CStockQuoteSource
//

// StripTags() rips through a buffer and removes HTML tags from it.
// The function uses a static variable to remember its state in case
// a HTML tag spans a buffer boundary.
//
void CStockQuoteSource::StripTags(LPTSTR pszBuffer)
{
	LPTSTR pszSource = pszBuffer;
	LPTSTR pszDest = pszBuffer;

	while (*pszSource != '\0')
	{
		if (m_bInTag)
		{
			if (*pszSource == '>')
				m_bInTag = FALSE;
			pszSource++;
		}
		else
		{
			if (*pszSource == '<')
				m_bInTag = TRUE;
			else
			{
				*pszDest = *pszSource;
				pszDest++;
			}
			pszSource++;
		}
	}
	*pszDest = '\0';
}


// Strips extra WS such that there are no 2 or more adjacent WS characters.
// Don't add space after the '/' character.
//
void CStockQuoteSource::StripExtraSpace(CString& s)
{
	CString temp;
	int     size = s.GetLength();

	for (int i = 0; i < size; i++)
	{
		int x = i;
		while (i < size && _istspace(s[i]))
			i++;
		if ((i - x > 0) &&
			(s[x-1] != _T('/') && s[x-1] != _T('+') && s[x-1] != _T('-')))
			temp += _T(' ');
		temp += s[i];
	}
	s = temp;
}


// Do the download of the stock info.  Several types of exceptions may be
// thrown.  Just return 0 on an exception unless it is a CInternetException,
// then pass it on up.
//
bool CStockQuoteSource::DownloadStockInfo(CInternetSession& session, CStock& stock)
{
	CString             strURL;   // URL to connect to.
	DWORD               dwHttpRequestFlags =
		INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_NO_AUTO_REDIRECT;
	const TCHAR         szHeaders[] =
		_T("Accept: text/*\r\nUser-Agent: Stock Quotes\r\n");
	CHttpConnection*    pServer = NULL;
	CHttpFile*          pFile = NULL;
	bool                retval = true;

	m_bInTag = false;
	// construct URL to connect to.
	//
	strURL=GetURL();
	strURL+=stock.GetSymbol();

	CString         strServerName;
	CString         strObject;
	INTERNET_PORT   nPort;
	DWORD           dwServiceType;

	try
	{
		// Handle upto 5 redirections otherwise bail out
		for(int i = 0; i < 5; ++i)
		{
			if (!AfxParseURL((LPCTSTR)strURL, dwServiceType, strServerName, strObject, nPort) ||
				dwServiceType != INTERNET_SERVICE_HTTP)
			{
				throw 1;
			}

			if (g_bStopUpdating)
				throw 99;

			pServer = session.GetHttpConnection(strServerName, nPort);

			if (g_bStopUpdating)
				throw 99;

			pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET,
				strObject, NULL, 1, NULL, NULL, dwHttpRequestFlags);
			pFile->AddRequestHeaders(szHeaders);
			pFile->SendRequest();

			if (g_bStopUpdating)
				throw 99;

			DWORD dwRet;
			pFile->QueryInfoStatusCode(dwRet);

			// if access was denied exit out.

			if (dwRet == HTTP_STATUS_DENIED)
			{
				throw 1;
			}

			// were we redirected?
			// these response status codes come from WININET.H
			if (g_bStopUpdating)
				throw 99;

			if (dwRet == HTTP_STATUS_MOVED ||
				dwRet == HTTP_STATUS_REDIRECT ||
				dwRet == HTTP_STATUS_REDIRECT_METHOD)
			{
				CString strNewLocation;
				pFile->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, strNewLocation);

				int nPlace = strNewLocation.Find(_T("Location: "));
				if (nPlace == -1)
				{
					throw 2;
				}

				strNewLocation = strNewLocation.Mid(nPlace + 10);
				if(strNewLocation[0] == _T('/'))
				{
					strURL=_T("http://");
					strURL+=strServerName;
				}
				else
					strURL=_T("");

				nPlace = strNewLocation.Find(_T('\n'));
				if (nPlace > 0)
					strNewLocation = strNewLocation.Left(nPlace);

				// close up the redirected site

				pFile->Close();
				delete pFile;
				pServer->Close();
				delete pServer;
				
				strURL+=strNewLocation;
			}
			else
				break;
		}
		retval = SetStockInfo(pFile, stock);

		pFile->Close();
		pServer->Close();
	}
	catch(CInternetException* e)
	{
		if (pFile != NULL)
			delete pFile;
		if (pServer != NULL)
			delete pServer;

		retval = false;
		throw e;
	}
	catch(...)
	{
		retval = false;
	}

	if (pFile != NULL)
		delete pFile;
	if (pServer != NULL)
		delete pServer;

	return retval;
}

// Read data from net and attempt to find key words that identify where
// the stock info is.
//
bool CStockQuoteSource::SetStockInfoHelper(CHttpFile* pFile, CStock& stock, TCHAR* szCurText, TCHAR* szChangeText)
{
	CString cur;
	CString change;
	int     cnt = 0;

	TCHAR sz[1024];
	while (!g_bStopUpdating && pFile->ReadString(sz, 1023) && cnt != 2)
	{
		StripTags(sz);
		if (cnt == 0 && ParseStockInfo(sz, szCurText, cur))
		{
			stock.SetCurrent(cur);
			cnt++;
		}

		// assume change value comes after current.
		//
		if (cnt == 1 && ParseStockInfo(sz, szChangeText, change))
		{
			stock.SetChange(change);
			cnt++;
		}
	}
	return cnt == 2;
}

// Using the szHeader member try to find the "key word" that identifies the
// stock info.  If found then read until we run into something other than
// a space, digit, +, -, or / characters.  If this algorithm does not
// work for your site, just override.
//
bool CStockQuoteSource::ParseStockInfo(TCHAR* szBuf, TCHAR* szHeader, CString& strResult)
{
	TCHAR*  temp = _tcsstr(szBuf, szHeader);

	if (temp)
	{
		temp += _tcslen(szHeader);

		// skip leading WS so the first character to be processed can be checked for
		// validity more accurately.
		while (*temp && _istspace(*temp)) temp++;
	}
	while(temp && *temp)
	{
		if (_istdigit(*temp) || _istspace(*temp) || *temp == '+' || *temp == '-' || *temp == '/' || *temp == '.')
			strResult += *temp;
		else
			break;
		temp++;
	}
	if (!strResult.IsEmpty())
	{
		strResult.TrimLeft();
		strResult.TrimRight();
		StripExtraSpace(strResult);
		return true;
	}
	return false;
}

// This helper function just checks to see if the given url ends with a '='.
// If is does then there is nothing else to do.  Otherwise append the given tail
// to the url.
//
//
//
void CStockQuoteSource::SetURLHelper(const CString& strURL,
									 const CString& strURLTail)
{
	m_strURL = strURL;
	if (strURL[strURL.GetLength()-1] != '=')
		m_strURL += strURLTail;
}

//////////////////////////////////////////////////////////////////////////////
// CSQSMSInvestor
//
bool CSQSMSInvestor::SetStockInfo(CHttpFile* pFile, CStock& stock)
{
	return SetStockInfoHelper(pFile, stock, _T("Last"), _T("Change"));
}

bool CSQSMSInvestor::ParseStockInfo(TCHAR* szBuf, TCHAR* szHeader, CString& strResult)
{
	TCHAR*  temp;
	if (!m_bFoundHeader)
	{
		temp = _tcsstr(szBuf, szHeader);
		if (temp)
		{
			temp += _tcslen(szHeader);
			m_bFoundHeader = true;
		}
	}
	else
		temp = szBuf;

	if (temp)
	{
		// skip leading WS so the first character to be processed can be checked for
		// validity more accurately.
		// also skip everything up to first $.
		bool    bNeg = false;
		while (*temp && !_istdigit(*temp) && *temp!= '.' && *temp !='-')
			++temp;

		if (*temp == '-')
				bNeg = true;

		if (*temp && bNeg)
		{
			++temp;
			strResult += _T("-");
		}

		while(temp && *temp)
		{

			if (_istdigit(*temp) || *temp == '.')
				strResult += *temp;
			else
				break;
			
			temp++;
		}

		if (!strResult.IsEmpty())
		{
			strResult.TrimLeft();
			strResult.TrimRight();
			StripExtraSpace(strResult);
			m_bFoundHeader = false;
			return true;
		}
	}
	return false;
}

//////////////////////////////////////////////////////////////////////////////
// ISAPI Dll Stock Source
//

bool CSQSISAPIDll::SetStockInfo(CHttpFile* pFile, CStock& stock)
{
	return SetStockInfoHelper(pFile, stock, _T("Current:"), _T("Change:"));
}

//////////////////////////////////////////////////////////////////////////////
// CSQSList
//
void CSQSList::Init()
{
	push_back(new CSQSMSInvestor);
	push_back(new CSQSISAPIDll);
}

CStockQuoteSource* CSQSList::GetMSInvestor()
{
	for (iterator i = begin(); i != end(); i++)
		if ((*i)->IsMSInvestor())
			return *i;
	return 0;
}

CStockQuoteSource* CSQSList::GetStockSourceISAPIDll()
{
	for (iterator i = begin(); i != end(); i++)
		if ((*i)->IsISAPIDll())
			return *i;
	return 0;
};


void CSQSList::Cleanup()
{
	for (iterator i = begin(); i != end(); i++)
		delete *i;
	clear();
}

⌨️ 快捷键说明

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