Re: Cookie processing in Fast CGI
"Martin Chapman" <[email protected]>
| Newsgroups | gmane.comp.web.fastcgi.devel |
|---|---|
| Message-ID | <9C951155AD144AFA88EE4B3E97E1EDF3@chapmanm64> |
Tom,
It's a little ugly because it's COM and if you convert it to FastCGI it
would be cool if you posted it back for the rest of us if you can. The
entire COM implementation is attached.
General Gist:
1. Get the cookie from the env vars. Should be called HTTP_COOKIE.
2. Use a method like the one below to parse the cookie value.
STDMETHODIMP CCookie::ParseValue(BSTR sCookie)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
_bstr_t bstrCookie(sCookie);
if (bstrCookie.length() == 0)
return E_INVALIDARG;
CString strCookie = (TCHAR*) bstrCookie;
LPCSTR pEnd = strCookie;
LPCSTR pStart = strCookie;
CString name, value;
while (*pEnd != '\0')
{
while (*pEnd && *pEnd != '=' && *pEnd != '&')
pEnd++;
if (*pEnd == '\0' || *pEnd == '&')
{
if (pEnd > pStart)
{
CopyToCString(value, pStart, pEnd);
}
put_Value(_bstr_t(value.GetBuffer()));
if (*pEnd == '&')
{
pEnd++;
pStart = pEnd;
continue;
}
return S_OK;
}
else if (*pEnd == '=' )
{
if (pEnd > pStart)
{
CopyToCString(name, pStart, pEnd);
}
else
{
pEnd++;
pStart = pEnd;
break;
}
pEnd++;
pStart = pEnd;
while (*pEnd && *pEnd != '&' && *pEnd != '=')
pEnd++;
if (pEnd > pStart)
CopyToCString(value, pStart, pEnd);
AddValue(_bstr_t(name.GetBuffer()),
_bstr_t(value.GetBuffer()));
if (*pEnd != '\0')
pEnd++;
pStart = pEnd;
}
}
return S_OK;
}
3. The following func parses a single cookie value and is used in the func
above.
STDMETHODIMP CCookie::ParseValue(BSTR sCookie)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
_bstr_t bstrCookie(sCookie);
if (bstrCookie.length() == 0)
return E_INVALIDARG;
CString strCookie = (TCHAR*) bstrCookie;
LPCSTR pEnd = strCookie;
LPCSTR pStart = strCookie;
CString name, value;
while (*pEnd != '\0')
{
while (*pEnd && *pEnd != '=' && *pEnd != '&')
pEnd++;
if (*pEnd == '\0' || *pEnd == '&')
{
if (pEnd > pStart)
{
CopyToCString(value, pStart, pEnd);
}
put_Value(_bstr_t(value.GetBuffer()));
if (*pEnd == '&')
{
pEnd++;
pStart = pEnd;
continue;
}
return S_OK;
}
else
if (*pEnd == '=' )
{
if (pEnd > pStart)
{
CopyToCString(name, pStart, pEnd);
}
else
{
pEnd++;
pStart = pEnd;
break;
}
pEnd++;
pStart = pEnd;
while (*pEnd && *pEnd != '&' && *pEnd != '=')
pEnd++;
if (pEnd > pStart)
CopyToCString(value, pStart, pEnd);
AddValue(_bstr_t(name.GetBuffer()),
_bstr_t(value.GetBuffer()));
if (*pEnd != '\0')
pEnd++;
pStart = pEnd;
}
}
return S_OK;
}
-----Original Message-----
From: fastcgi-developers-bounces+chapmanm=pixia.com-xGejAJT2w6xVgU18Zptdi0EOCMrvLtNR@public.gmane.org
[mailto:fastcgi-developers-bounces+chapmanm=pixia.com-xGejAJT2w6xVgU18Zptdi0EOCMrvLtNR@public.gmane.org]
On Behalf Of Tom Bowden
Sent: Wednesday, December 09, 2009 1:18 PM
To: FastCGI Developers
Subject: [FASTCGI] Cookie processing in Fast CGI
Is there a thread somewhere that talks about parsing cookies - or, is
this something that I have to treat like any other header parsing task.
Tom
_______________________________________________
FastCGI-developers mailing list
FastCGI-developers-xGejAJT2w6xVgU18Zptdi0EOCMrvLtNR@public.gmane.org
http://mailman.pins.net/mailman/listinfo.cgi/fastcgi-developers
_______________________________________________
FastCGI-developers mailing list
FastCGI-developers-xGejAJT2w6xVgU18Zptdi0EOCMrvLtNR@public.gmane.org
http://mailman.pins.net/mailman/listinfo.cgi/fastcgi-developers
CookieCollection.h
(text/plain, 2.1 KB)
// CookieCollection.h : Declaration of the CCookieCollection
#pragma once
#include "resource.h" // main symbols
#include "HttpServer.h"
#include "_ICookieCollectionEvents_CP.h"
#ifdef _WIN32_WCE
#error "Neutral-threaded COM objects are not supported on Windows CE."
#endif
// CCookieCollection
class ATL_NO_VTABLE CCookieCollection :
public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<CCookieCollection, &CLSID_CookieCollection>,
public ISupportErrorInfo,
public IConnectionPointContainerImpl<CCookieCollection>,
public CProxy_ICookieCollectionEvents<CCookieCollection>,
public IPersistStreamInitImpl<CCookieCollection>,
public ICookieCollection
{
public:
CCookieCollection();
virtual ~CCookieCollection(void);
DECLARE_REGISTRY_RESOURCEID(IDR_COOKIECOLLECTION)
BEGIN_COM_MAP(CCookieCollection)
COM_INTERFACE_ENTRY(ICookieCollection)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
COM_INTERFACE_ENTRY(IConnectionPointContainer)
COM_INTERFACE_ENTRY(IPersistStreamInit)
COM_INTERFACE_ENTRY(ICookieCollection)
END_COM_MAP()
BEGIN_CONNECTION_POINT_MAP(CCookieCollection)
CONNECTION_POINT_ENTRY(__uuidof(_ICookieCollectionEvents))
END_CONNECTION_POINT_MAP()
BEGIN_PROP_MAP(CCookieCollection)
END_PROP_MAP()
// ISupportsErrorInfo
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct();
void FinalRelease();
CCriticalSection m_CS;
vector< ICookie*>* m_pCookies;
public:
BOOL m_bRequiresSave;
// IPersistStorageInit Methods
STDMETHOD(Load)(LPSTREAM pStm);
STDMETHOD(Save)(LPSTREAM pStm, BOOL fClearDirty);
// ICookieCollection
STDMETHOD(Add)(ICookie* pCookie, LONG* pIndexOf);
STDMETHOD(GetByName)(BSTR sName, ICookie** ppCookie);
STDMETHOD(GetAt)(LONG nIndex, ICookie** ppCookie);
STDMETHOD(IndexOf)(ICookie* pCookie, LONG* pIndexOf);
STDMETHOD(RemoveByName)(BSTR sName);
STDMETHOD(RemoveAt)(LONG nIndex);
STDMETHOD(RemoveAll)(void);
STDMETHOD(get_Count)(LONG* pCount);
STDMETHOD(GetCookieString)(BSTR* pCookieString);
STDMETHOD(Clone)(ICookieCollection** ppCookieCollection);
};
OBJECT_ENTRY_AUTO(__uuidof(CookieCollection), CCookieCollection)
Cookie.cpp
(text/plain, 12.4 KB)
// Cookie.cpp : Implementation of CCookie
#include "stdafx.h"
#include "Cookie.h"
// CCookie
void SystemTimeToHttpDate(const SYSTEMTIME& st, CString &strTime)
{
static LPCSTR szDays[] = { "Sun", "Mon", "Tue",
"Wed", "Thu", "Fri", "Sat" };
static LPCSTR szMonth[] = { "Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug", "Sep",
"Oct", "Nov", "Dec" };
strTime.Format("%s, %02d-%s-%d %02d:%02d:%02d GMT",
szDays[st.wDayOfWeek], st.wDay, szMonth[st.wMonth-1], st.wYear,
st.wHour, st.wMinute, st.wSecond);
}
/**************************************************************************************************
* constructor/destructor
**************************************************************************************************/
CCookie::CCookie()
{
m_bRequiresSave = FALSE;
}
CCookie::~CCookie(void)
{
}
HRESULT CCookie::FinalConstruct()
{
return S_OK;
}
void CCookie::FinalRelease()
{
}
STDMETHODIMP CCookie::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_ICookie
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
/**************************************************************************************************
* IPersistStorageInit
**************************************************************************************************/
STDMETHODIMP CCookie::Load(LPSTREAM pStm)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = S_OK;
CSingleLock cs(&m_CS);
cs.Lock();
ULONG nBytesRead = 0;
CComBSTR sName;
hr = sName.ReadFromStream(pStm);
if (FAILED(hr)) return hr;
m_sName = sName.m_str != NULL ? sName : L"";
CComBSTR sValue;
hr = sValue.ReadFromStream(pStm);
if (FAILED(hr)) return hr;
m_sValue = sValue.m_str != NULL ? sValue : L"";
return S_OK;
}
STDMETHODIMP CCookie::Save(LPSTREAM pStm, BOOL fClearDirty)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = S_OK;
CSingleLock cs(&m_CS);
cs.Lock();
ULONG nBytesWritten = 0;
CComBSTR sName;
hr = sName.AppendBSTR(m_sName);
if (FAILED(hr)) return hr;
hr = sName.WriteToStream(pStm);
if (FAILED(hr)) return hr;
CComBSTR sValue;
hr = sValue.AppendBSTR(m_sValue);
if (FAILED(hr)) return hr;
hr = sValue.WriteToStream(pStm);
if (FAILED(hr)) return hr;
return S_OK;
}
/**************************************************************************************************
* ICookie
**************************************************************************************************/
STDMETHODIMP CCookie::get_Name(BSTR* pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
*pVal = m_sName.copy();
return S_OK;
}
STDMETHODIMP CCookie::put_Name(BSTR newVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
_bstr_t sName(newVal);
LPCSTR szName = (LPCSTR) sName;
if (szName && *szName)
{
m_sName = newVal;
return S_OK;
}
return E_FAIL;
}
STDMETHODIMP CCookie::get_Value(BSTR* pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
*pVal = m_sValue.copy();
return S_OK;
}
STDMETHODIMP CCookie::put_Value(BSTR newVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (m_Values.GetCount()) return S_OK;
m_sValue = newVal;
return S_OK;
}
STDMETHODIMP CCookie::get_Path(BSTR* pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString sPath;
m_Attributes.Lookup(_T("path"), sPath);
*pVal = sPath.AllocSysString();
return S_OK;
}
STDMETHODIMP CCookie::put_Path(BSTR newVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = SetVersion(1L);
if (FAILED(hr)) return hr;
return AddAttribute(_bstr_t(L"path"), newVal);
}
STDMETHODIMP CCookie::get_Domain(BSTR* pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString sDomain;
m_Attributes.Lookup(_T("domain"), sDomain);
*pVal = sDomain.AllocSysString();
return S_OK;
}
STDMETHODIMP CCookie::put_Domain(BSTR newVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = SetVersion(1L);
if (FAILED(hr)) return hr;
return AddAttribute(_bstr_t(L"domain"), newVal);
}
STDMETHODIMP CCookie::get_Expires(BSTR* pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString sExpires;
m_Attributes.Lookup(_T("expires"), sExpires);
*pVal = sExpires.AllocSysString();
return S_OK;
}
STDMETHODIMP CCookie::put_Expires(BSTR newVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return AddAttribute(_bstr_t(L"expires"), newVal);
}
STDMETHODIMP CCookie::get_Secure(VARIANT_BOOL* pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString sSecure;
if (m_Attributes.Lookup(_T("secure"), sSecure))
*pVal = VARIANT_TRUE;
else
*pVal = VARIANT_FALSE;
return S_OK;
}
STDMETHODIMP CCookie::put_Secure(VARIANT_BOOL newVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
LPCSTR szKey = _T("secure");
HRESULT hr = SetVersion(1L);
if (FAILED(hr)) return hr;
if (newVal == VARIANT_FALSE)
m_Attributes.RemoveKey(_T("secure"));
else
m_Attributes.SetAt(_T("secure"), _T(" "));
return S_OK;
}
STDMETHODIMP CCookie::IsEmpty(VARIANT_BOOL* pIsEmpty)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
*pIsEmpty = m_sName.length() == 0 ? VARIANT_TRUE : VARIANT_FALSE;
return S_OK;
}
STDMETHODIMP CCookie::AddValue(BSTR sName, BSTR sValue)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
_bstr_t bstrName(sName);
if (bstrName.length() == 0) return E_INVALIDARG;
m_Values.SetAt(bstrName, _bstr_t(sValue));
return S_OK;
}
STDMETHODIMP CCookie::ModifyValue(BSTR sName, BSTR sValue)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return AddValue(sName, sValue);
}
STDMETHODIMP CCookie::RemoveValue(BSTR sName)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
m_Values.RemoveKey(_bstr_t(sName));
return S_OK;
}
STDMETHODIMP CCookie::RemoveAllValues()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
m_Values.RemoveAll();
return S_OK;
}
STDMETHODIMP CCookie::AddAttribute(BSTR sName, BSTR sValue)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
_bstr_t bstrName(sName);
_bstr_t bstrValue(sValue);
LPCSTR szName = (LPCSTR) bstrName;
LPCSTR szValue = (LPCSTR) bstrValue;
if (!szName || !*szName || !szValue)
return E_INVALIDARG;
m_Attributes.SetAt(szName, szValue);
return S_OK;
}
STDMETHODIMP CCookie::ModifyAttribute(BSTR sName, BSTR sValue)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return AddAttribute(sName, sValue);
}
STDMETHODIMP CCookie::RemoveAttribute(BSTR sName)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
m_Attributes.RemoveKey(_bstr_t(sName));
return S_OK;
}
STDMETHODIMP CCookie::RemoveAllAttributes()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
m_Attributes.RemoveAll();
return S_OK;
}
STDMETHODIMP CCookie::SetComment(BSTR sComment)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = SetVersion(1L);
if (FAILED(hr)) return hr;
return AddAttribute(_bstr_t(L"comment"), sComment);
}
STDMETHODIMP CCookie::SetCommentUrl(BSTR sCommentUrl)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = SetVersion(1L);
if (FAILED(hr)) return hr;
return AddAttribute(_bstr_t(L"commenturl"), sCommentUrl);
}
STDMETHODIMP CCookie::SetDiscard(VARIANT_BOOL bDiscard)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = SetVersion(1L);
if (FAILED(hr)) return hr;
if (bDiscard == VARIANT_TRUE)
m_Attributes.RemoveKey(_T("Discard"));
else
m_Attributes.SetAt(_T("Discard"), _T(" "));
return S_OK;
}
STDMETHODIMP CCookie::SetMaxAge(LONG nMaxAge)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = SetVersion(1L);
if (FAILED(hr)) return hr;
TCHAR szBuffer[20] = _T("");
_itoa_s(nMaxAge, szBuffer, 20, 10);
return AddAttribute(_bstr_t(L"max-age"), _bstr_t(szBuffer));
}
STDMETHODIMP CCookie::SetPort(BSTR sPort)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = SetVersion(1L);
if (FAILED(hr)) return hr;
return AddAttribute(_bstr_t(L"port"), sPort);
}
STDMETHODIMP CCookie::SetVersion(LONG nVersion)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
TCHAR szBuffer[20] = _T("");
_itoa_s(nVersion, szBuffer, 20, 10);
return AddAttribute(_bstr_t(L"version"), _bstr_t(szBuffer));
}
STDMETHODIMP CCookie::Lookup(BSTR sName, BSTR* pValue)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
VARIANT_BOOL bIsEmpty = VARIANT_FALSE;
HRESULT hr = IsEmpty(&bIsEmpty);
if (bIsEmpty == VARIANT_TRUE) return S_OK;
if (m_sValue.length() > 0)
{
*pValue = m_sValue.copy();
return S_OK;
}
CString sValue;
if (m_Values.GetCount())
{
_bstr_t bstrName(sName);
if (m_Values.Lookup(CString((TCHAR*) sName), sValue))
{
*pValue = sValue.AllocSysString();
return S_OK;
}
}
return S_OK;
}
STDMETHODIMP CCookie::Empty()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
m_sName = L"";
m_sValue = L"";
m_Attributes.RemoveAll();
m_Values.RemoveAll();
return S_OK;
}
STDMETHODIMP CCookie::ParseValue(BSTR sCookie)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
_bstr_t bstrCookie(sCookie);
if (bstrCookie.length() == 0)
return E_INVALIDARG;
CString strCookie = (TCHAR*) bstrCookie;
LPCSTR pEnd = strCookie;
LPCSTR pStart = strCookie;
CString name, value;
while (*pEnd != '\0')
{
while (*pEnd && *pEnd != '=' && *pEnd != '&')
pEnd++;
if (*pEnd == '\0' || *pEnd == '&')
{
if (pEnd > pStart)
{
CopyToCString(value, pStart, pEnd);
}
put_Value(_bstr_t(value.GetBuffer()));
if (*pEnd == '&')
{
pEnd++;
pStart = pEnd;
continue;
}
return S_OK;
}
else
if (*pEnd == '=' )
{
if (pEnd > pStart)
{
CopyToCString(name, pStart, pEnd);
}
else
{
pEnd++;
pStart = pEnd;
break;
}
pEnd++;
pStart = pEnd;
while (*pEnd && *pEnd != '&' && *pEnd != '=')
pEnd++;
if (pEnd > pStart)
CopyToCString(value, pStart, pEnd);
AddValue(_bstr_t(name.GetBuffer()), _bstr_t(value.GetBuffer()));
if (*pEnd != '\0')
pEnd++;
pStart = pEnd;
}
}
return S_OK;
}
STDMETHODIMP CCookie::Render(BSTR* pCookie)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString strCookie;
CString name, value;
if (!m_sName.length())
return E_INVALIDARG;
try
{
strCookie = (TCHAR*) m_sName;
int nValSize = (int) m_Values.GetCount();
if (nValSize)
{
strCookie += _T("=");
POSITION pos = m_Values.GetStartPosition();
for (int i=0; pos; i++)
{
m_Values.GetNextAssoc(pos, name, value);
strCookie += name;
if (value.GetLength())
{
strCookie += '=';
strCookie += value;
}
if (i <= nValSize-2)
strCookie += '&';
}
}
else
{
strCookie += _T("=");
if (m_sValue.length())
strCookie += (TCHAR*) m_sValue;
}
CString strAttributes;
if (!RenderAttributes(strAttributes))
return FALSE;
if (strAttributes.GetLength() > 0)
{
strCookie += _T("; ");
strCookie += strAttributes;
}
_bstr_t bstrCookie = strCookie.GetBuffer();
*pCookie = bstrCookie.copy();
return S_OK;
}
catch(...) {}
return E_FAIL;
}
STDMETHODIMP CCookie::SetExpiresDate(DATE newVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
COleDateTime oleDateTimeExpires(newVal);
SYSTEMTIME sysTime;
oleDateTimeExpires.GetAsSystemTime(sysTime);
CString sTime;
SystemTimeToHttpDate(sysTime, sTime);
return put_Expires(_bstr_t(sTime.GetBuffer()));
}
STDMETHODIMP CCookie::IsDeleted(VARIANT_BOOL* pIsDeleted)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (m_sValue.length() > 0)
{
*pIsDeleted = VARIANT_FALSE;
return S_OK;
}
if (m_sValue.length() == 0 && m_Values.IsEmpty())
{
*pIsDeleted = VARIANT_TRUE;
return S_OK;
}
CString sName, sValue;
POSITION pos = m_Values.GetStartPosition();
while (pos != NULL)
{
m_Values.GetNextAssoc(pos, sName, sValue);
if (!sValue.IsEmpty())
{
*pIsDeleted = VARIANT_FALSE;
return S_OK;
}
}
*pIsDeleted = VARIANT_TRUE;
return S_OK;
}
STDMETHODIMP CCookie::Clone(ICookie** ppCookie)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CSingleLock cs(&m_CS);
cs.Lock();
CComPtr< ICookie> spCookie;
HRESULT hr = spCookie.CoCreateInstance(CLSID_Cookie);
if (FAILED(hr)) return hr;
hr = spCookie->put_Name(m_sName);
if (FAILED(hr)) return hr;
hr = spCookie->put_Value(m_sValue);
if (FAILED(hr)) return hr;
return spCookie->QueryInterface(ppCookie);
}
BOOL CCookie::RenderAttributes(CString& strAttributes)
{
strAttributes.Empty();
POSITION pos = m_Attributes.GetStartPosition();
CString key, val;
for (int i=0; pos; i++)
{
if (i)
strAttributes += _T(";");
m_Attributes.GetNextAssoc(pos, key, val);
strAttributes += key;
strAttributes += '=';
strAttributes += val;
}
return TRUE;
}
Cookie.h
(text/plain, 2.9 KB)
// Cookie.h : Declaration of the CCookie
#pragma once
#include "resource.h" // main symbols
#include "HttpServer.h"
#include "_ICookieEvents_CP.h"
#ifdef _WIN32_WCE
#error "Neutral-threaded COM objects are not supported on Windows CE."
#endif
// CCookie
class ATL_NO_VTABLE CCookie :
public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<CCookie, &CLSID_Cookie>,
public ISupportErrorInfo,
public IConnectionPointContainerImpl<CCookie>,
public CProxy_ICookieEvents<CCookie>,
public IPersistStreamInitImpl<CCookie>,
public ICookie
{
public:
CCookie();
virtual ~CCookie(void);
DECLARE_REGISTRY_RESOURCEID(IDR_COOKIE)
BEGIN_COM_MAP(CCookie)
COM_INTERFACE_ENTRY(ICookie)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
COM_INTERFACE_ENTRY(IConnectionPointContainer)
COM_INTERFACE_ENTRY(IPersistStreamInit)
COM_INTERFACE_ENTRY(ICookie)
END_COM_MAP()
BEGIN_CONNECTION_POINT_MAP(CCookie)
CONNECTION_POINT_ENTRY(__uuidof(_ICookieEvents))
END_CONNECTION_POINT_MAP()
BEGIN_PROP_MAP(CCookie)
END_PROP_MAP()
// ISupportsErrorInfo
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct();
void FinalRelease();
protected:
// member variables
_bstr_t m_sName;
_bstr_t m_sValue;
CMapStringToString m_Values;
CMapStringToString m_Attributes;
CCriticalSection m_CS;
BOOL RenderAttributes(CString& strAttributes);
public:
BOOL m_bRequiresSave;
// IPersistStorageInit Methods
STDMETHOD(Load)(LPSTREAM pStm);
STDMETHOD(Save)(LPSTREAM pStm, BOOL fClearDirty);
// ICookie
STDMETHOD(get_Name)(BSTR* pVal);
STDMETHOD(put_Name)(BSTR newVal);
STDMETHOD(get_Value)(BSTR* pVal);
STDMETHOD(put_Value)(BSTR newVal);
STDMETHOD(get_Path)(BSTR* pVal);
STDMETHOD(put_Path)(BSTR newVal);
STDMETHOD(get_Domain)(BSTR* pVal);
STDMETHOD(put_Domain)(BSTR newVal);
STDMETHOD(get_Expires)(BSTR* pVal);
STDMETHOD(put_Expires)(BSTR newVal);
STDMETHOD(get_Secure)(VARIANT_BOOL* pVal);
STDMETHOD(put_Secure)(VARIANT_BOOL newVal);
STDMETHOD(IsEmpty)(VARIANT_BOOL* pIsEmpty);
STDMETHOD(AddValue)(BSTR sName, BSTR sValue);
STDMETHOD(ModifyValue)(BSTR sName, BSTR sValue);
STDMETHOD(RemoveValue)(BSTR sName);
STDMETHOD(RemoveAllValues)();
STDMETHOD(AddAttribute)(BSTR sName, BSTR sValue);
STDMETHOD(ModifyAttribute)(BSTR sName, BSTR sValue);
STDMETHOD(RemoveAttribute)(BSTR sName);
STDMETHOD(RemoveAllAttributes)();
STDMETHOD(SetComment)(BSTR sComment);
STDMETHOD(SetCommentUrl)(BSTR sCommentUrl);
STDMETHOD(SetDiscard)(VARIANT_BOOL bDiscard);
STDMETHOD(SetMaxAge)(LONG nMaxAge);
STDMETHOD(SetPort)(BSTR sPort);
STDMETHOD(SetVersion)(LONG nVersion);
STDMETHOD(Lookup)(BSTR sName, BSTR* pValue);
STDMETHOD(Empty)();
STDMETHOD(ParseValue)(BSTR sCookie);
STDMETHOD(Render)(BSTR* pCookie);
STDMETHOD(SetExpiresDate)(DATE newVal);
STDMETHOD(IsDeleted)(VARIANT_BOOL* pIsDeleted);
STDMETHOD(Clone)(ICookie** ppCookie);
};
OBJECT_ENTRY_AUTO(__uuidof(Cookie), CCookie)
CookieCollection.cpp
(text/plain, 7.3 KB)
// CookieCollection.cpp : Implementation of CCookieCollection
#include "stdafx.h"
#include "CookieCollection.h"
// CCookieCollection
/**************************************************************************************************
* constructor/destructor
**************************************************************************************************/
CCookieCollection::CCookieCollection()
{
m_pCookies = new vector< ICookie*>();
m_bRequiresSave = TRUE;
}
CCookieCollection::~CCookieCollection(void)
{
RemoveAll();
if (m_pCookies)
delete m_pCookies;
}
HRESULT CCookieCollection::FinalConstruct()
{
return S_OK;
}
void CCookieCollection::FinalRelease()
{
}
STDMETHODIMP CCookieCollection::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_ICookieCollection
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
/**************************************************************************************************
* IPersistStorageInit
**************************************************************************************************/
STDMETHODIMP CCookieCollection::Load(LPSTREAM pStm)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = S_OK;
hr = RemoveAll();
if (FAILED(hr)) return hr;
CSingleLock cs(&m_CS);
cs.Lock();
ULONG nBytesRead = 0;
long nNumCookies = 0L;
hr = pStm->Read(&nNumCookies, sizeof(nNumCookies), &nBytesRead);
if (FAILED(hr)) return hr;
for (long i = 0; i < nNumCookies; i++)
{
CComPtr< ICookie> spCookie;
hr = spCookie.CoCreateInstance(CLSID_Cookie);
if (FAILED(hr)) return hr;
CComPtr< IPersistStreamInit> spPersistStreamInit;
hr = spCookie->QueryInterface(&spPersistStreamInit);
if (FAILED(hr)) return hr;
hr = spPersistStreamInit->Load(pStm);
if (FAILED(hr)) return hr;
long nID = 0L;
hr = Add(spCookie, &nID);
if (FAILED(hr)) return hr;
}
return S_OK;
}
STDMETHODIMP CCookieCollection::Save(LPSTREAM pStm, BOOL fClearDirty)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = S_OK;
CSingleLock cs(&m_CS);
cs.Lock();
ULONG nBytesWritten = 0;
long nNumCookies = (long) m_pCookies->size();
hr = pStm->Write(&nNumCookies, sizeof(nNumCookies), &nBytesWritten);
if (FAILED(hr)) return hr;
for (long i = 0; i < nNumCookies; i++)
{
CComPtr< ICookie> spCookie;
hr = m_pCookies->at(i)->QueryInterface(&spCookie);
if (FAILED(hr)) return hr;
CComPtr< IPersistStreamInit> spPersistStreamInit;
hr = spCookie->QueryInterface(&spPersistStreamInit);
if (FAILED(hr)) return hr;
hr = spPersistStreamInit->Save(pStm, fClearDirty);
if (FAILED(hr)) return hr;
}
return S_OK;
}
/**************************************************************************************************
* IIndexCollection
**************************************************************************************************/
STDMETHODIMP CCookieCollection::Add(ICookie* pCookie, LONG* pIndexOf)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (pCookie == NULL) return E_POINTER;
CSingleLock cs(&m_CS);
cs.Lock();
m_pCookies->push_back(pCookie);
pCookie->AddRef();
*pIndexOf = (LONG) m_pCookies->size();
return S_OK;
}
STDMETHODIMP CCookieCollection::GetByName(BSTR sName, ICookie** ppCookie)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CSingleLock cs(&m_CS);
cs.Lock();
_bstr_t bstrName(sName);
_bstr_t bstrCookieName;
HRESULT hr = S_OK;
ICookie* pCookie = NULL;
vector< ICookie*>::iterator it;
for (it = m_pCookies->begin(); it != m_pCookies->end(); it++)
{
hr = (*it)->get_Name(bstrCookieName.GetAddress());
if (FAILED(hr)) return hr;
if (bstrCookieName == bstrName)
{
return (*it)->QueryInterface(ppCookie);
}
}
return S_OK;
}
STDMETHODIMP CCookieCollection::GetAt(LONG nIndex, ICookie** ppCookie)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CSingleLock cs(&m_CS);
cs.Lock();
if (nIndex < 0 || nIndex >= (LONG) m_pCookies->size())
return AtlReportError(GetObjectCLSID(), _T("Index out of bounds."));
return m_pCookies->at(nIndex)->QueryInterface(ppCookie);
}
STDMETHODIMP CCookieCollection::IndexOf(ICookie* pCookie, LONG* pIndexOf)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (pCookie == NULL) return E_POINTER;
CSingleLock cs(&m_CS);
cs.Lock();
*pIndexOf = -1L;
if (!m_pCookies) return S_OK;
long nIndex = 0;
vector< ICookie*>::iterator it;
for (it = m_pCookies->begin(); it != m_pCookies->end(); it++, nIndex++)
{
if (pCookie == *it)
{
*pIndexOf = nIndex;
break;
}
}
return S_OK;
}
STDMETHODIMP CCookieCollection::RemoveByName(BSTR sName)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CSingleLock cs(&m_CS);
cs.Lock();
_bstr_t bstrName(sName);
_bstr_t bstrCookieName;
HRESULT hr = S_OK;
ICookie* pCookie = NULL;
vector< ICookie*>::iterator it;
for (it = m_pCookies->begin(); it != m_pCookies->end(); it++)
{
hr = (*it)->get_Name(bstrCookieName.GetAddress());
if (FAILED(hr)) return hr;
if (bstrCookieName == bstrName)
{
(*it)->Release();
m_pCookies->erase(it);
break;
}
}
return S_OK;
}
STDMETHODIMP CCookieCollection::RemoveAt(LONG nIndex)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CSingleLock cs(&m_CS);
cs.Lock();
if (nIndex < 0 || nIndex >= (LONG) m_pCookies->size())
return AtlReportError(GetObjectCLSID(), _T("Index out of bounds."));
vector< ICookie*>::iterator it = m_pCookies->begin() + nIndex;
m_pCookies->erase(it);
return S_OK;
}
STDMETHODIMP CCookieCollection::RemoveAll(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CSingleLock cs(&m_CS);
cs.Lock();
HRESULT hr = S_OK;
ICookie* pCookie = NULL;
vector< ICookie*>::iterator it;
for (it = m_pCookies->begin(); it != m_pCookies->end(); it++)
(*it)->Release();
m_pCookies->clear();
return S_OK;
}
STDMETHODIMP CCookieCollection::get_Count(LONG* pCount)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
*pCount = (LONG) m_pCookies->size();
return S_OK;
}
STDMETHODIMP CCookieCollection::GetCookieString(BSTR* pCookieString)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = S_OK;
_bstr_t sCookieString;
CString strKey;
vector< ICookie*>::iterator it;
for (it = m_pCookies->begin(); it != m_pCookies->end(); it++)
{
VARIANT_BOOL bIsDeleted = VARIANT_FALSE;
hr = (*it)->IsDeleted(&bIsDeleted);
if (FAILED(hr)) return hr;
if (bIsDeleted == VARIANT_TRUE)
{
hr = (*it)->SetMaxAge(0L);
if (FAILED(hr)) return hr;
}
_bstr_t sCookie;
hr = (*it)->Render(sCookie.GetAddress());
if (SUCCEEDED(hr))
{
sCookieString += L"Set-Cookie";
sCookieString += L": ";
sCookieString += sCookie;
sCookieString += L"\r\n";
}
}
*pCookieString = sCookieString.copy();
return S_OK;
}
STDMETHODIMP CCookieCollection::Clone(ICookieCollection** ppCookieCollection)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CSingleLock cs(&m_CS);
cs.Lock();
CComPtr< ICookieCollection> spCookieCollection;
HRESULT hr = spCookieCollection.CoCreateInstance(CLSID_CookieCollection);
if (FAILED(hr)) return hr;
LONG nID = 0L;
vector< ICookie*>::iterator it;
for (it = m_pCookies->begin(); it != m_pCookies->end(); it++)
{
CComPtr< ICookie> spCookie;
hr = (*it)->Clone(&spCookie);
if (FAILED(hr)) return hr;
hr = spCookieCollection->Add(spCookie, &nID);
if (FAILED(hr)) return hr;
}
return spCookieCollection->QueryInterface(ppCookieCollection);
}