📄 parseext.cpp
字号:
// We another line from nLines because the newline at the end of this
// current line will be counted on the call to GetLineNumber(pszRead, m_pIncludeInfo[i].m_pszStart)
// this avoids counting it twice.
nLines += m_pIncludeInfo[i].m_cLines - 2;
memcpy(pszWrite, pszIncFile, m_pIncludeInfo[i].m_dwFileSize);
pszWrite += m_pIncludeInfo[i].m_dwFileSize;
pszRead = m_pIncludeInfo[i].m_pszEnd;
}
// now copy the remaining data between last inc file and end of file.
memcpy(pszWrite, pszRead, m_pszFileData + m_cbFileData - pszRead);
MyFree(m_pszFileData);
m_pszFileData = pszNewFileData;
m_cbFileData += nNewChars;
DEBUGCHK(m_cbFileData > 0);
ret = TRUE;
done:
if (FALSE == ret)
ServerError(NULL,iErrLine);
MyFree(pszIncFile);
return ret;
}
// NOTE: assumes out buffer is MAX_PATH wchars
BOOL CASPState::GetVirtualIncludeFilePath(PSTR pszFileName, WCHAR wszNewFileName[])
{
CHAR szBuf[MAX_PATH+1];
DWORD dwLen = sizeof(szBuf);
// Calling function should error out before calling this function if
// the file name is too long.
if ((strlen(pszFileName)+1) >= sizeof(szBuf)) {
DEBUGCHK(0);
m_aspErr = IDS_E_NO_VIRTUAL_DIR;
return FALSE;
}
// puts the file into a new buffer, which is written in place
strcpy(szBuf, pszFileName);
// Use server support to change this buffer into physical path
if ( ! m_pACB->ServerSupportFunction(m_pACB->ConnID,
HSE_REQ_MAP_URL_TO_PATH,szBuf, &dwLen, NULL))
{
m_aspErr = IDS_E_NO_VIRTUAL_DIR;
return FALSE;
}
// Convert to Wide
MyA2W(szBuf,wszNewFileName, MAX_PATH+1);
return TRUE;
}
// NOTE: assumes out buffer is MAX_PATH wchars
BOOL CASPState::GetIncludeFilePath(PSTR pszFileName, WCHAR wszNewFileName[])
{
WCHAR *wsz = wszNewFileName;
WCHAR *wszEnd = wsz;
// We get the relative path (directory he parent ASP is in) by ripping out the very last "/" on the ASP path
wcscpy(wszNewFileName, m_pACB->wszFileName);
// Find the last "\" or "/" in the path and use that as base path to copy from.
for (wsz = wszNewFileName; *wsz; wsz++)
{
if (*wsz == '\\' || *wsz == '/')
wszEnd = wsz+1; // want to start copying one space past the \ or /
}
DEBUGCHK(wszEnd != wsz);
MyA2W(pszFileName, wszEnd, MAX_PATH-(wszEnd-wszNewFileName));
return TRUE;
}
// Scans text, looking for <%@
// NOTE: No support for ENABLESESSIONSTATE or TRANSACTION identifiers
// NOTE: Technically there can only be one Preproc directive per page, and
// it must come before any other <% directives. IIS checks for this, we don't,
// We use first <%@ directive on page, ignoring any others.
BOOL CASPState::ParseProcDirectives()
{
PSTR pszTrav = m_pszFileData; // walks across file
PSTR pszSubEnd = NULL; // end of directive
// Search for <%@. It's valid for there to be spaces between the <% and @
while ( pszTrav = MyStrStr(pszTrav,BEGIN_COMMAND))
{
pszTrav += sizeof(BEGIN_COMMAND) - 1;
svsutil_SkipWhiteSpace(pszTrav);
if ( *pszTrav == '@' )
{
if (NULL == (pszSubEnd = MyStrStr(pszTrav,END_COMMAND)))
{
m_aspErr = IDS_E_NO_SCRIPT_TERMINATOR;
ServerError(NULL,GetLineNumber(m_pszFileData, pszTrav));
return FALSE;
}
}
pszTrav++; // skip past '@'
svsutil_SkipWhiteSpace(pszTrav);
// This fcn made it's own ServerError call, so we don't do it again.
if ( ! ParseProcDirectiveLine(pszTrav, pszSubEnd))
return FALSE;
}
return TRUE;
}
// Handles the <%@ ... %> line
// There are four cases of var setting + spacing we must worry about,
// Var=VarName, Var= VarName, Var =VarName, Var = VarName
BOOL CASPState::ParseProcDirectiveLine(PSTR pszTrav, PSTR pszSubEnd)
{
DEBUG_CODE_INIT;
PSTR pszNext = NULL;
PSTR pszEnd = NULL;
CHAR szErr[256];
CHAR szVarName[128];
CHAR szVarValue[128];
PSTR pszDiv = NULL;
BOOL ret = FALSE;
szErr[0] = '\0';
// DebugBreak();
while (pszTrav < pszSubEnd)
{
// Look for "=" sign. If it's not there or if it's past the trailing %>
// then there's an error.
if(!(pszNext = pszEnd = strchr(pszTrav, '=')) ||
(pszNext > pszSubEnd) || ((pszEnd-pszTrav+1) >= sizeof(szVarName)))
{
m_aspErr = IDS_E_NO_ATTRIB;
strncpy(szErr,pszTrav,min(sizeof(szErr), pszSubEnd - pszTrav));
szErr[(min(sizeof(szErr), pszSubEnd - pszTrav)) - 1] = 0;
myleave(191);
}
// get var name
svsutil_SkipWhiteSpaceRev(pszEnd, pszTrav);
PREFAST_SUPPRESS(12008,"Check is always safe because pszEnd is calculated as a small addition past pszTrav");
Nstrcpy(szVarName, pszTrav, pszEnd-pszTrav);
// skip to var value
pszNext++; // skip past '='
svsutil_SkipWhiteSpace(pszNext);
if (*pszNext == '\"') // skip past at most one quote character.
pszNext++;
// case where there's no attribute set, ie <%LANGUAGE = %>
if (pszNext == pszSubEnd)
{
m_aspErr = IDS_E_NO_ATTRIB;
strcpy(szErr,szVarName);
myleave(191);
}
pszEnd = pszNext;
svsutil_SkipNonWhiteSpace(pszEnd);
// This handles case where there's no space between last variable and %>
if (pszEnd > pszSubEnd)
pszEnd = pszSubEnd;
if (*(pszEnd-1) == '\"') // swallow at most one quote character.
pszEnd--;
// get var value
if ((pszEnd <= pszNext) || ((pszEnd-pszNext+1) > sizeof(szVarValue)))
{
m_aspErr = IDS_E_NO_ATTRIB;
strcpy(szErr,szVarName);
myleave(194);
}
Nstrcpy(szVarValue, pszNext, pszEnd-pszNext);
// move the ptr up
pszTrav = pszEnd;
// Now that we have szVarName and szVarValue, figure out what they are
if (0 == strcmpi(szVarName, PREPROC_LANG))
{
if (0 == strcmpi(szVarValue,"VBSCRIPT"))
{
m_scriptLang = VBSCRIPT;
}
else if (0 == strcmpi(szVarValue,"JSCRIPT") ||
(0 == strcmpi(szVarValue,"JAVASCRIPT")))
{
m_scriptLang = JSCRIPT;
}
else
{
m_aspErr = IDS_E_BAD_SCRIPT_LANG;
strcpy(szErr, szVarValue);
myleave(193);
}
}
// Note: Even though the rest of the world usually refers to LCIDs in
// terms of their hex value, IIS reads them in as decimal values. So do
// we.
else if (0 == strcmpi(szVarName, PREPROC_LCID))
{
if ( 0 == sscanf(szVarValue, "%d", &m_lcid))
{
m_aspErr = IDS_E_NO_ATTRIB;
strcpy(szErr,szVarName);
myleave(194);
}
// make sure LCID is valid
if (FALSE == IsValidLocale(m_lcid, LCID_SUPPORTED))
{
m_aspErr = IDS_E_BAD_LCID;
strcpy(szErr,szVarValue);
myleave(199);
}
}
else if (0 == strcmpi(szVarName, PREPROC_CDPG))
{
CPINFO cp;
if ( 0 == sscanf(szVarValue, "%d", &m_lCodePage))
{
m_aspErr = IDS_E_NO_ATTRIB;
strcpy(szErr,szVarName);
myleave(195);
}
if (! GetCPInfo(m_lCodePage, &cp))
{
m_aspErr = IDS_E_BAD_CODEPAGE;
sprintf(szErr," %d",m_lCodePage);
myleave(198);
}
}
else
{
m_aspErr = IDS_E_UNKNOWN_ATTRIB;
strcpy(szErr,szVarName);
myleave(196);
}
if (*pszTrav == '\"') // skip past at most one quote character.
pszTrav++;
svsutil_SkipWhiteSpace(pszTrav);
}
ret = TRUE;
done:
if (FALSE == ret)
ServerError(szErr);
return ret;
}
// This fcn helps us resolve errors line numbers and file names if the
// script writer used #include files.
// iScriptErrLine is the line the error occured on according to IActiveScript
// ppszFileName points to the include file (if error occured there) or
// to NULL if the error occured in the main ASP page itself.
// piFileName is set to the actual line # the error occured on, in either the
// script or the include file.
void CASPState::GetIncErrorInfo(int iScriptErrLine,
int *piFileErrLine, PSTR *ppszFileName)
{
int i;
int iTotalIncLines = 0;
// If no inc files, then leave everything alone
if (NULL == m_pIncludeInfo)
{
*ppszFileName = NULL;
*piFileErrLine = iScriptErrLine;
return;
}
for (i = 0; i < MAX_INCLUDE_FILES; i++)
{
// We don't store # of inc files, rather we stop when 1st name is NULL
if (m_pIncludeInfo[i].m_pszFileName == NULL)
break;
// In this case error occured in script text before i(th) include file
if (iScriptErrLine < m_pIncludeInfo[i].m_iStartLine)
{
*ppszFileName = NULL;
*piFileErrLine = iScriptErrLine - iTotalIncLines;
return;
}
// In this case error occured in i(th) include file
if (iScriptErrLine < (m_pIncludeInfo[i].m_iStartLine + m_pIncludeInfo[i].m_cLines))
{
*ppszFileName = m_pIncludeInfo[i].m_pszFileName; // calling fnc shouldn't free this!
*piFileErrLine = iScriptErrLine - m_pIncludeInfo[i].m_iStartLine + 1;
return;
}
iTotalIncLines += m_pIncludeInfo[i].m_cLines - 1;
}
// If we broke out of the loop without finding a inc file, then the
// error occured after the last include file was included. Subtract
// off total # of lines include files took up.
*piFileErrLine = iScriptErrLine - iTotalIncLines;
return;
}
// Used to get the line number that a statement occured on.
int GetLineNumber(PSTR pszStart, PSTR pszEnd)
{
int nLines = 1;
PSTR pszTrav = pszStart;
while (pszTrav < pszEnd)
{
if ( *pszTrav == '\r')
nLines++;
pszTrav++;
}
return nLines;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -