Click here to Skip to main content
15,884,298 members
Articles / Web Development / IIS

Cookie Spy

Rate me:
Please Sign up or sign in to vote.
4.85/5 (17 votes)
10 Oct 2001 202.3K   5.2K   61  
Creating a CookieSpy explorer bar with ATL
/*
 Copyright (c) 2001
 Author: Konstantin Boukreev 
 E-mail: konstantin@mail.primorye.ru 

 Created: 16.02.2001 17:10:00
 Version: 1.0.0

*/
#include "stdafx.h"
#include "IeXtensions.h"
#include "CookieSpy.h"
#include "EditCookieDlg.h"

HRESULT CookieSpy::FinalConstruct()
{
	return CoCreateFreeThreadedMarshaler(GetControllingUnknown(), &m_pUnkMarshaler.p);
}

void CookieSpy::FinalRelease()
{
	m_pUnkMarshaler.Release();
}

/////////////////////////// 
// message handlers

LRESULT CookieSpy::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
	CAxWindow wnd(m_hWnd);
	HRESULT hr = wnd.CreateControl(IDR_HTML_MAIN);
	if (SUCCEEDED(hr))
	{
		CComQIPtr<IDispatch> spDisp(GetUnknown());
		hr = wnd.SetExternalDispatch(spDisp);
	}
//	if (SUCCEEDED(hr))
//		hr = wnd.QueryControl(IID_IWebBrowser2, (void**)&m_spBrowser);
	return SUCCEEDED(hr) ? 0 : -1;
}

///////////////////////////
// IObjectWithSite

STDMETHODIMP CookieSpy::SetSite(IUnknown *pUnkSite)
{
	HRESULT hr;
	hr = DeskBandImpl<CookieSpy>::SetSite(pUnkSite);

	if (SUCCEEDED(hr))
	{
		if (m_spUnkSite)
		{				
			CComQIPtr<IServiceProvider> spSP(m_spUnkSite);
			if(spSP)
			{
				spSP->QueryService(__uuidof(SHDocVw::IWebBrowserApp), __uuidof(SHDocVw::IWebBrowser2), (void**)&m_spWebBrowser);
				theDispEvent::DispEventAdvise(m_spWebBrowser);
			}
		}
		else
		{
			if (m_spWebBrowser)
			{
				theDispEvent::DispEventUnadvise(m_spWebBrowser);	
				m_spWebBrowser.Release();
			}
		}
	}
	return hr;
};

///////////////////////////
// ICookieSpy

STDMETHODIMP CookieSpy::put_Default(VARIANT* pVar)
{
	ATLTRACE(_T("CookieSpy::put_Default\n"));	

	if (!pVar) return E_POINTER;
	if (pVar->vt == VT_DISPATCH)
	{
		m_spElem = pVar->pdispVal; 

		CComPtr<MSHTML::IHTMLElement> spElem; 
		m_spElem->get_parentElement(&spElem);
		if (spElem)
		{
			CComQIPtr<MSHTML::IHTMLBodyElement> spBody(spElem);
			if (spBody)
			{
				TCHAR path[1024] = {0};
				GetModuleFileName(_Module.m_hInstResource, path, 1024);  			
				CComBSTR url(L"res://");
				url += path;
				url += L"/RT_JPEG/#201";		

				HRESULT hr;
				hr = spBody->put_background(url); 
			}
		}
	}
	return S_OK;
}

STDMETHODIMP CookieSpy::get_Default(VARIANT* pVar)
{
	ATLTRACE(_T("CookieSpy::get_Default\n"));

	if (!pVar) return E_POINTER;
	VariantClear(pVar);
	pVar->vt = VT_DISPATCH;
	return m_spElem->QueryInterface(&pVar->pdispVal);  	
}

STDMETHODIMP CookieSpy::Event(VARIANT* vHint, VARIANT* vEvent)
{
	USES_CONVERSION;

	vHint;	// didn't use so far

	if (!vEvent || 
		vEvent->vt != VT_DISPATCH ||
		!vEvent->pdispVal)
		return E_INVALIDARG;
	
	CComQIPtr<MSHTML::IHTMLEventObj> spEvent(vEvent->pdispVal);
	if (!spEvent) return E_INVALIDARG;
	
	CComPtr<MSHTML::IHTMLElement> spElem;
	spEvent->get_srcElement(&spElem);
	if (!spElem) return S_FALSE;
	
	#ifdef _DEBUG
	CComBSTR sType;
	spEvent->get_type(&sType);
	ATLASSERT(wcscmp(sType, L"click") == 0);
	#endif //_DEBUG

	CComBSTR sClass;
	spElem->get_className(&sClass);

	if (!sClass.Length() ||
		wcscmp(sClass, L"label"))
		return S_OK;
	
	CComBSTR  sID;
	spElem->get_id(&sID); 
	ATLASSERT(sID.Length());

	return OnClickLabel(sID);	
}

///////////////////////////
// DWebBrowserEvents2

HRESULT __stdcall CookieSpy::BeforeNavigate2(IDispatch *pDisp, VARIANT *URL, VARIANT *Flags, VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers, VARIANT_BOOL *Cancel)
{
	Flags;
	TargetFrameName;
	PostData;
	Headers;
	Cancel;

	ATLTRACE(_T("CookieSpy::BeforeNavigate2\n"));

	UpdateCookies(pDisp, L"BeforeNavigate");
	return S_OK;
}

HRESULT __stdcall CookieSpy::DocumentComplete(IDispatch* pDisp, VARIANT* URL)
{	
	ATLTRACE(_T("CookieSpy::DocumentComplete\n"));	

	UpdateCookies(pDisp, L"DocumentComplete");
	return S_OK;
}

HRESULT __stdcall CookieSpy::NavigateComplete2(IDispatch* pDisp, VARIANT* URL)
{
	ATLTRACE(_T("CookieSpy::NavigateComplete2\n"));

	UpdateCookies(pDisp, L"NavigateComplete");
	return S_OK;
}

////////////////////////////////////
//

void CookieSpy::UpdateCookies(IDispatch* pDisp, const WCHAR* sEvent)
{
	CComQIPtr<SHDocVw::IWebBrowser2> spWB(pDisp);
	if (!spWB) return;
	
	CComPtr<IDispatch> spDocDisp;
	spWB->get_Document(&spDocDisp);
	m_spDoc = spDocDisp;

	if (m_spDoc)
	{			
		BSTR sCookie = 0;		
		m_spDoc->get_cookie(&sCookie);		
		RefreshCookieTable(sCookie, sEvent);
	}
}

void CookieSpy::RefreshCookieTable(BSTR sCookie, const WCHAR* sEvent)
{
	if (!m_spElem) return;
	if (!m_spWebBrowser) return;

	CComBSTR url, lname;

	m_spWebBrowser->get_LocationURL(&url);
	m_spWebBrowser->get_LocationName(&lname);
	
	bool bNewLocation;

	if (m_url == url.m_str)
	{
		bNewLocation = false;
	}
	else
	{
		bNewLocation = true;
		m_url = url;
		m_CookieEntries.Clear();
	}
	
	typedef std::basic_ostringstream<wchar_t> ostringstream;
	typedef std::basic_string<wchar_t> string;

	ostringstream os;

	// table's header
	os << L"<div class=\"status\" style=\"text-align:center\"><a href=\"" << url.m_str << L"\">" << lname.m_str << L"</a>";
	os << L"<span> - " << sEvent << L"<span></div>";
	os << L"<hr><table border=\"0\" cellpadding=\"1\" cellspacing=\"2\" width=\"100%%\" class=\"text\">";
	os << L"<tr><th><span class=\"label\" id=\"e84289f8-316e-4105-984f-28031bb5e26f\">+</span></th><th>name</th><th>value</th></tr>";
	
	// table's data
	if (SysStringLen(sCookie))
	{
		CookieEntry* pEntry = 0;
		wchar_t tokens[]	= L";=";
		wchar_t* token		= wcstok(sCookie, tokens);
		
		while (token)
		{			
			if (!pEntry)
			{					
				while(iswspace(*token)) token++;

				pEntry = m_CookieEntries.Find(token);
				if (pEntry) 
				{
					// update date
					pEntry->m_sName  = token;
					pEntry->m_nParam = 1;					
				}
				else
				{
					pEntry = m_CookieEntries.Add(token);
				}

				ATLASSERT(wcslen(token));
												
				os << L"<tr><td><span class=\"label\" id=\"" << token << L"\">x</span></td><td";
				if (!bNewLocation && !pEntry->m_nParam)
					os << L" style=\"color:red\"";
				os << L">" << token << L"</td>";
				
			}
			else
			{	
				ATLASSERT(wcslen(token));

				os << L"<td";
				if (!bNewLocation && (!pEntry->m_sValue || wcscmp(pEntry->m_sValue, token)))
					os << L" style=\"color:red\"";				
				os <<L">" << token << L"</td></tr>";

				pEntry->m_sValue = token;
				pEntry = 0;
			}
						
			token = wcstok(0, tokens);
		}
	}
		
	// table's end
	os << L"</table><hr>";
		
	m_cookies.Empty(); 
	m_cookies.Attach(sCookie);	
	m_CookieEntries.Reorganize();

	string s = os.str();

	BSTR bstr = SysAllocStringLen(s.c_str(), s.size());
	HRESULT hr = m_spElem->put_innerHTML(bstr);
	SysFreeString(bstr);
}

bool CookieSpy::GetCookieDataFromCookieFolder(WCHAR* sCookie, WCHAR* sValue, BSTR* psUrl, SYSTEMTIME& ExpireDate)
{	
	USES_CONVERSION;

	CComPtr<MSHTML::IHTMLLocation> spLoc;
	m_spDoc->get_location(&spLoc);
	if (!spLoc) return false;
						
	CComBSTR sHostName;
	spLoc->get_hostname(&sHostName); 
	if (!sHostName.Length()) return false;
	
	WCHAR* sHost = 0;

	sHost = wcschr(sHostName, L'.');
	if (!sHost) return false;	
	
	WCHAR* p = wcsrchr(sHost, L'.');
	if (!p) return false;	
		
	*p = 0;	
	sHost++;
	if (!wcslen(sHost)) return false;

	TCHAR sUser[UNLEN + 1];
	DWORD dwSize = UNLEN + 1;
	if (!GetUserName(sUser, &dwSize))
		return false;

	TCHAR szPath[MAX_PATH] = {0};

	/*
	PFNSHGETFOLDERPATH pfnSHGetFolderPath = 0;
	HMODULE hMod = LoadLibrary(_T("shfolder.dll"));
	#ifdef _UNICODE
	pfnSHGetFolderPath = (PFNSHGETFOLDERPATHW)GetProcAddress(hMod, "SHGetFolderPathW");	
	#else
	pfnSHGetFolderPath = (PFNSHGETFOLDERPATHA)GetProcAddress(hMod, "SHGetFolderPathA");	
	#endif
	
	HRESULT hr = pfnSHGetFolderPath(0, CSIDL_COOKIES, 0, 0, szPath);
	FreeLibrary(hMod);
	if (FAILED(hr))	return false;
	*/

	if (!SHGetSpecialFolderPath(0, szPath, CSIDL_COOKIES, FALSE))
		return false;
	
	PathAddBackslash(szPath);
	
	TCHAR sSearch[MAX_PATH];
	wsprintf(sSearch, _T("%s%s@%s????.txt"), szPath, sUser, W2T(sHost));

	HANDLE f;
	WIN32_FIND_DATA fd;

	f = FindFirstFile(sSearch, &fd);	
	if (f == INVALID_HANDLE_VALUE)
		return false;

	bool r = false;

	do 
	{		
		TCHAR cookieFile[MAX_PATH];
		lstrcpy(cookieFile, szPath);		
		lstrcat(cookieFile, fd.cFileName);

		r = GetCookieDataFromCookieFile(cookieFile, sCookie, sValue, psUrl, ExpireDate);
		if (r) break;
		
	} while(FindNextFile(f, &fd));

	FindClose(f);

	return r;
}

bool CookieSpy::GetCookieDataFromCookieFile(TCHAR* sFile, WCHAR* sCookie, WCHAR* sValue, BSTR* psUrl, SYSTEMTIME& ExpireDate)
{
	USES_CONVERSION;

	HANDLE hFile = CreateFile(sFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	if (INVALID_HANDLE_VALUE == hFile)return false;

	DWORD cbSize = GetFileSize(hFile, 0);

	if (-1 == cbSize)
	{
		CloseHandle(hFile);
		return false;
	}
	
	char* pData = (char*)_alloca(cbSize);
	ReadFile(hFile, pData, cbSize, &cbSize, 0);
	CloseHandle(hFile);
	
	char* tokenUrl = 0;
	char* tokenLowDate = 0;
	char* tokenHighDate = 0;	
	bool r = false;
	int i = 0;

	char* CookieName  = W2A(sCookie);
	char* CookieValue = W2A(sValue);

	char tokens[] = "\n";	
	char* token = strtok(pData, tokens);

	while (token)
	{	
		switch(i)
		{
			case 0: //cookie name
				r = strcmp(token, CookieName) == 0;
				break;
			case 1: // cookie value
				if (r) r = strcmp(token, CookieValue) == 0;
				break;
			case 2: // cookie path
				if (r) tokenUrl = token;
				break;
			case 3: // secure ?
				break;
			case 4: // expire date
				if (r) tokenLowDate = token;
				break;
			case 5: // expire date
				if (r) tokenHighDate = token;
				break;
			case 6: // creation date ?
				break;
			case 7: // creation date ?	
				break;
			case 8: // * <- end of cookie record
				if (*token != '*') return false;				
				break;			
		}

		if (i == 8) 
		{
			if (r) break;
			i = 0;
		}
		else
		{
			i++;
		}

		token = strtok(0, tokens);
	}

	if (r)
	{
		FILETIME ft;
		ft.dwLowDateTime  = atol(tokenLowDate);
		ft.dwHighDateTime = atol(tokenHighDate);		
		FileTimeToSystemTime(&ft, &ExpireDate);

		char ValidUrl[MAX_PATH] = "http://";
		strcat(ValidUrl, tokenUrl);

		*psUrl = SysAllocString(A2W(ValidUrl));
	}

	return r;
}

HRESULT CookieSpy::OnClickLabel(WCHAR* sID)
{			
	CookieEntry* pEntry = 0;
	TCHAR* sTitle		= _T("");
	TCHAR* sHelp		= _T("");
	WCHAR* sValue		= L"";	
	bool r				= false;
	bool bSession		= false;

	CComBSTR sUrl;

	SYSTEMTIME st;
	GetSystemTime(&st);

	if (wcscmp(sID, L"e84289f8-316e-4105-984f-28031bb5e26f"))
	{
		pEntry = m_CookieEntries.Find(sID);

		if (pEntry)
		{
			sTitle = _T("Edit Cookie");

			sValue = pEntry->m_sValue;						
			r = GetCookieDataFromCookieFolder(sID, pEntry->m_sValue, &sUrl, st);
			if (!r)
			{
				bSession = true;
			//	sHelp = _T("");
			}			
		}
		else
		{
			MessageBox(_T("Error, Cannot find the cookie"), _T("Cookie Spy"), MB_ICONWARNING);
			return E_FAIL;
		}
	}
	else
	{
		sTitle = _T("Add new Cookie");
		sID = L"";
		st.wYear++;
	}
	
	if (!sUrl.Length())
	{		
		sUrl = m_url;
	}

	EditCookieDlg dlg(sUrl, sID, sValue, st, bSession, sTitle, sHelp);
	if (IDOK == dlg.DoModal())
	{
		CComBSTR& sCookie = dlg.m_sCookie;

		sCookie += L"=";
		sCookie += dlg.m_sValue;
		sCookie += L";";

		if (!dlg.m_bSession)
		{
			SYSTEMTIME& st = dlg.m_st; 

			static wchar_t* Days[]  = {L"Sun", L"Mon", L"Tue", L"Wed", L"Thu", L"Fri", L"Sat"};
			static wchar_t* Months[] = {L"Jan", L"Feb", L"Mar", L"Apr", L"May", L"Jun", L"Jul", L"Aug", L"Sen", L"Oct", L"Nov", L"Dec"};

			wchar_t expires[100];
			_snwprintf(expires, 100,
				L" expires=%s, %u %s %u %02u:%02u:%02u GMT", 
				Days[st.wDayOfWeek], 
				st.wDay, 
				Months[st.wMonth - 1],
				st.wYear,
				st.wHour,
				st.wMinute,
				st.wSecond);

			sCookie += expires;
		}

		BOOL r = InternetSetCookieW(dlg.m_sUrl, 0, sCookie);

		if (!r)
		{
			MessageBox(_T("Error, Cannot set the cookie"), _T("Cookie Spy"), MB_ICONWARNING);
		}
	}

	return S_OK;
}

////////////////////////////////////////////
// CookieSpy::CookieEntries

CookieSpy::CookieEntry* CookieSpy::CookieEntries::Add(WCHAR* sName)
{
	push_back(CookieEntry(sName));
	return &back();
}

CookieSpy::CookieEntry* CookieSpy::CookieEntries::Find(WCHAR* sName)
{
	ATLASSERT(sName && wcslen(sName));

	LONG l = wcslen(sName);
	
	for (iterator x = begin(); x != end(); x++)
	{
		ATLASSERT((*x).m_sName && wcslen((*x).m_sName));
	
		if ((*x).m_nHint == l &&
			wcscmp((*x).m_sName, sName) == 0)
		{
			return &(*x);
		}
	}
		
	return 0;
}

void CookieSpy::CookieEntries::Reorganize()
{
	iterator x = begin();

	while (x != end())
	{
		if ((*x).m_nParam == 0xffffffff)
		{
			iterator _x = x++;
			erase(_x);
			continue;
		}
		
		(*x).m_nParam = 0xffffffff;
		 x++;
	}
}

void CookieSpy::CookieEntries::Clear()
{
	clear();
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Russian Federation Russian Federation
I am freelance programmer. About 3 years of experience in C++ and I would rather use ATL, STL, WTL but not MFC Smile | :) . Main backgrounds are Win32 API, COM and Networking. Now I am interested about AI (Neural Network, Fuzzy Logic and GA). Currently based in Vladivostok, Russia.

Comments and Discussions