📄 dict.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "aspmain.h"
const BOOL c_fUseCollections = TRUE;
const char cszDomain[] = "; domain=";
const char cszPath[] = "; path=";
const char cszPathDefault[] = "; path=/";
const char cszExpires[] = "; expires";
int DBCSEncodeLen(const char *szSrc);
CRequestDictionary * CreateCRequestDictionary(DICT_TYPE dt, CASPState *pASPState, PSTR pszData)
{
CRequestDictionary *pDict = NULL;
if (FAILED (CoCreateInstance(CLSID_RequestDictionary,NULL,CLSCTX_INPROC_SERVER,IID_IRequestDictionary,(void**) &pDict)))
return NULL;
pDict->m_dictType = dt;
pDict->m_pASPState = pASPState;
pDict->m_pszRawData = pszData;
if (pszData)
pDict->ParseInput();
return pDict;
}
CRequestDictionary::CRequestDictionary()
: CPtrMapper(0)
{
// m_cRef = 0;
m_pszRawData = NULL;
}
// We inherit from CPtrMapper class, which handles the deallocation of the list
CRequestDictionary::~CRequestDictionary()
{
// MyFree(m_pszRawData); // don't free this, because we never made a copy of
// the data in the first place.
}
// CRequestDictionary::get_Item
// This is called when accessing a collection object (Request.QueryString/Form/Cookies),
// Response.Cookies.
// If there is no argument, for example <% var = Request.Cookies %>, then
// varKey is of type VT_ERROR. Like IIS, we return the raw, unformatted string
// in this case, except for Response.Cookies, which doesn't support being accessed
// raw.
// If the argument is an integer, the i(th) element is returned. This is
// only valid for Form and QueryString objects. (ie Request.Form(1) )
// The element is a CRequestStrList, not the string itself, because subindexing
// is possible and we need an object to handle this. (ie Request.Form(1)(2) would
// get the 2nd element of the 1st var declared in the Post input)
// If the argument is a string, the string is looked up in the table that was
// created on CookieParse or PostParse. Again a CRequestStrList class element
// is returned.
// If no string exists, or if there is no data in the VT_ERROR case, then
// we return a CRequestStrList that is specified as an empty string. We have
// only one such object per request. The reason we return this object rather
// than an VT_EMPTY variant is that we still need to support methods such
// as Request.Form("No-Data").Count. Without an object, the value is the string "",
// it needs to be the integer 0.
STDMETHODIMP CRequestDictionary::get_Item(VARIANT varKey, VARIANT* pvarReturn)
{
DEBUG_CODE_INIT;
HRESULT ret = DISP_E_EXCEPTION;
VariantInit(pvarReturn);
VARIANT *pvarKey = &varKey;
BSTR bstr = NULL;
int iIndex;
CRequestStrList *pStrList = NULL;
DWORD vt;
// For Request.Cookies we convert from ANSI, otherwise change from DBCS.
// This is like ASP on IIS.
LONG lCodePage = (m_dictType == REQUEST_COOKIE_TYPE) ? CP_ACP : m_pASPState->m_lCodePage;
// Use VariantResolveDispatch which will:
//
// * Copy BYREF variants for us using VariantCopyInd
// * handle E_OUTOFMEMORY for us
// * get the default value from an IDispatch, which seems
// like an appropriate conversion.
//
VARIANT varKeyCopy;
VariantInit(&varKeyCopy);
vt = V_VT(pvarKey);
if ((vt != VT_BSTR) && (vt != VT_I2) && (vt != VT_I4))
{
if (FAILED(VariantResolveDispatch(&varKeyCopy, &varKey)))
{
ASP_ERR(IDS_E_PARSER);
myleave(811);
}
pvarKey = &varKeyCopy;
}
vt = V_VT(pvarKey);
switch (vt)
{
case VT_I1: case VT_I2: case VT_I8:
case VT_UI1: case VT_UI2: case VT_UI4: case VT_UI8:
case VT_R4: case VT_R8:
// Coerce all integral types to VT_I4
if (FAILED(VariantChangeTypeEx(pvarKey, pvarKey, lCodePage, 0, VT_I4)))
{
ASP_ERR(IDS_E_UNKNOWN);
myleave(811);
}
vt = VT_I4;
}
// directly accessing object, no arguments.
// This is only valid for Request objects. It gives the user
// the original, unformatted/unparsed string from the client.
if ( VT_ERROR == vt)
{
// This would be made on <% var = Response.Cookies %> (or Request.ServerVariables), no raw dumping. Like IIS.
if ( RESPONSE_COOKIE_TYPE == m_dictType || SERVER_VARIABLE_TYPE == m_dictType )
{
ASP_ERR(IDS_E_EXPECTED_STRING);
myleave(802);
}
if (m_pszRawData)
{
if ( FAILED( SysAllocStringFromSz(m_pszRawData, 0, &bstr, lCodePage)))
{
ASP_ERR(IDS_E_NOMEM);
myleave(803);
}
V_VT(pvarReturn) = VT_BSTR;
V_BSTR(pvarReturn) = bstr;
}
else // no data of requested type, ie Request.Form but not POST data sent
{
// Point it at the empty string object, only one of these per ASP session
V_VT(pvarReturn) = VT_DISPATCH;
m_pASPState->m_pEmptyString->QueryInterface(IID_IRequestStrList, (void **) (&V_DISPATCH(pvarReturn)));
}
}
else if (VT_I4 == vt) //lookup based on index
{
// Can't index cookies or server variables based on an integer
if ( RESPONSE_COOKIE_TYPE == m_dictType ||
REQUEST_COOKIE_TYPE == m_dictType ||
SERVER_VARIABLE_TYPE == m_dictType )
{
ASP_ERR(IDS_E_EXPECTED_STRING);
myleave(804);
}
iIndex = V_I4(pvarKey);
if (iIndex <= 0 ||
iIndex > m_nEntries)
{
ASP_ERR(IDS_E_BAD_INDEX);
myleave(804);
}
pStrList = (CRequestStrList *) (m_pMapInfo[iIndex - 1].pbData);
pStrList->QueryInterface(IID_IRequestStrList, (void **) (&V_DISPATCH(pvarReturn)));
V_VT(pvarReturn) = VT_DISPATCH;
} // VT_I4
else if (VT_BSTR == vt) // Lookup based on string.
{
if (SERVER_VARIABLE_TYPE == m_dictType)
{
GetServerVariables(V_BSTR(pvarKey),pvarReturn);
}
else if (Lookup( V_BSTR(pvarKey), (void **) &pStrList))
{
pStrList->QueryInterface(IID_IRequestStrList, (void **) (&V_DISPATCH(pvarReturn)));
V_VT(pvarReturn) = VT_DISPATCH;
}
else
{
m_pASPState->m_pEmptyString->QueryInterface(IID_IRequestStrList, (void **) (&V_DISPATCH(pvarReturn)));
V_VT(pvarReturn) = VT_DISPATCH;
}
} // VT_BSTR
// vt not an integer or string. We follow IIS's lead as far as what error to report.
else
{
ASP_ERR(IDS_E_EXPECTED_STRING);
myleave(806);
}
ret = S_OK;
done:
DEBUGMSG_ERR(ZONE_ERROR,(L"ASP: CRequestDictionary::get_Item failed, err = %d, GLE=%X\r\n",
err,GetLastError()));
VariantClear(&varKeyCopy);
return ret;
}
// put_Item. Used for assigning values to Cookie response data.
// This will be called on cases
// Response.Cookies = "Value"
// Response.Cookies("index") = "Value"
// It will NOT be called on Response.Cookies("index1")("index2") = "value",
// instead this will be a CRequestDictionary::get_Item with "index1", then
// a CRequestStrList::put_Item with "index2", and "value" through object created
STDMETHODIMP CRequestDictionary::put_Item(VARIANT varKey, BSTR bstrValue)
{
DEBUG_CODE_INIT;
VARIANT *pvarKey = &varKey;
HRESULT ret = DISP_E_EXCEPTION;
int iIndex =0;
WCHAR *wszValue = NULL;
WCHAR *wszName = NULL;
CRequestStrList *pStrList = NULL;
DWORD vt;
VARIANT varKeyCopy;
VariantInit(&varKeyCopy);
vt = V_VT(pvarKey);
if (NULL == bstrValue)
myretleave(S_OK,809);
if (m_dictType != RESPONSE_COOKIE_TYPE)
{
ASP_ERR(IDS_E_READ_ONLY);
myleave(810);
}
if (TRUE == m_pASPState->m_fSentHeaders)
{
ASP_ERR(IDS_E_SENT_HEADERS);
myleave(808);
}
// Use VariantResolveDispatch which will:
//
// * Copy BYREF variants for us using VariantCopyInd
// * handle E_OUTOFMEMORY for us
// * get the default value from an IDispatch, which seems
// like an appropriate conversion.
//
if ((vt != VT_BSTR) && (vt != VT_I2) && (vt != VT_I4))
{
if (FAILED(VariantResolveDispatch(&varKeyCopy, &varKey)))
{
ASP_ERR(IDS_E_PARSER);
myleave(811);
}
pvarKey = &varKeyCopy;
}
vt = V_VT(pvarKey);
// this would correspond to Response.Cookies = "Value", or Response.Cookies(5) = "value",
// No support in IIS or in CE ASP.
if (vt != VT_BSTR)
{
ASP_ERR(IDS_E_EXPECTED_STRING);
myleave(812);
}
if (NULL == (wszValue = MySzDupW(bstrValue)))
{
ASP_ERR(IDS_E_NOMEM);
myleave(817);
}
if ( Lookup( V_BSTR(pvarKey), (void**) &pStrList))
{
if (FALSE == pStrList->AddStringToArray(wszValue))
{
ASP_ERR(IDS_E_NOMEM);
myleave(815);
}
// Do NOT add reference here, we're just overwriting it!
}
else // new element
{
if (NULL == (wszName = MySzDupW( V_BSTR(pvarKey))))
{
ASP_ERR(IDS_E_NOMEM);
myleave(818);
}
pStrList = CreateCRequestStrList(m_pASPState,wszValue,m_dictType);
if ( NULL == pStrList || FALSE == Set(wszName, (void *) pStrList))
{
MyFree(wszName);
ASP_ERR(IDS_E_NOMEM);
myleave(816);
}
}
ret = S_OK;
done:
DEBUGMSG_ERR(ZONE_ERROR,(L"ASP: CRequestDictionary::put_Item failed, err = %d, GLE=%X\r\n",
err, GetLastError()));
if (FAILED(ret))
MyFree(wszValue);
VariantClear(&varKeyCopy);
return ret;
}
STDMETHODIMP CRequestDictionary::get_Count(int* cStrRet)
{
if (SERVER_VARIABLE_TYPE == m_dictType)
return E_NOTIMPL;
*cStrRet = m_nEntries;
return S_OK;
}
// Note: WinCE does not support enumeration through collection objects in ASP, unlike IIS.
STDMETHODIMP CRequestDictionary::get_Key(VARIANT VarKey, VARIANT* pvar)
{
ASP_ERR(IDS_E_NOT_IMPL);
return E_NOTIMPL;
}
STDMETHODIMP CRequestDictionary::get__NewEnum(IUnknown** ppEnumReturn)
{
ASP_ERR(IDS_E_NOT_IMPL);
return E_NOTIMPL;
}
// CRequest::ParseInput()
// This takes the raw data receieved from the POST, query string, or incoming cookies
// and breaks it into individual items that can be more easily indexed.
BOOL CRequestDictionary::ParseInput()
{
DEBUG_CODE_INIT;
PSTR pszName = NULL;
PSTR pszValue = NULL;
CRequestStrList *pStrList = NULL;
PSTR pszTrav = NULL;
PSTR pszTempRawData = NULL;
WCHAR *wszName = NULL; // Don't free at end of function
WCHAR *wszValue = NULL; // Don't free at end of function
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -