windows-nt/Source/XPSP1/NT/enduser/windows.com/wuv3/wuv3is/template.cpp
2020-09-26 16:20:57 +08:00

574 lines
12 KiB
C++

//=======================================================================
//
// Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
//
// File: template.cpp
//
// Purpose: DHTML template support
//
// History: 4/3/99 YAsmi Created
//
//=======================================================================
#include "template.h"
// we are currently not using the templates feature
// the code for templates is wrapped in HTML_TEMPLATE define
#ifdef HTML_TEMPLATE
//
// CParseTemplate class
//
CParseTemplate::CParseTemplate(LPCSTR pszTemplate)
: m_pFrag(NULL),
m_cFragAlloc(0),
m_cFragUsed(0),
m_bInvalid(FALSE),
m_pszStrBuf(NULL),
m_cStrAlloc(0),
m_cStrUsed(0)
{
LPCSTR pszReplacementCodes = "012345";
LPCSTR pszConditionalCodes = "6789AB";
LPSTR pszNext;
FRAGMENT frag;
BOOL bInvalid = FALSE;
// copy the template in our buffer
m_pTemplateBuf = _strdup(pszTemplate);
//
// parse the template
//
pszNext = m_pTemplateBuf;
for (;;)
{
LPSTR p = strchr(pszNext, '^');
ZeroMemory(&frag, sizeof(frag));
if (p != NULL)
{
// delimiter found check to see if next character is a delimiter so we can escape it
if (*(p + 1) == '^')
{
// escape it
p++;
// insert a null to make the preceeding string a null terminated string
*p = '\0';
frag.FragType = FRAG_STR;
frag.pszStrVal = pszNext;
AddFrag(&frag);
}
else
{
//
// we have a non escape character following the delimiter
// add the preceeding string fragment and process the token fragment
//
// insert a null to make the preceeding string a null terminated string
*p = '\0';
frag.FragType = FRAG_STR;
frag.pszStrVal = pszNext;
AddFrag(&frag);
// we are at the begining of a token, skip to code
p++;
if (strchr(pszReplacementCodes, *p) != NULL)
{
// we have a replacement code
frag.FragType = FRAG_REPLACE;
frag.chCode = *p;
}
else if (strchr(pszConditionalCodes, *p) != NULL)
{
// we have a conditional code, read the paranthesis
frag.FragType = FRAG_CONDITION;
frag.chCode = *p;
frag.dwVal = 0;
frag.pszStrVal = NULL; // if not changed in the following code we have an error
// skip over code
p++;
if (*(p++) == '(')
{
// read numeric parameter between paranthesis
while (isdigit(*p))
{
frag.dwVal = frag.dwVal * 10 + (DWORD)(*(p++) - '0');
}
if (*(p++) == ')')
{
if (*(p++) == '^')
{
// we are looking at the begining of the replace value, skip to next delimiter
LPSTR p2 = p;
p = strchr(p2, '^');
if (p != NULL)
{
// we now have complete syntax of condition token
*p = '\0';
frag.pszStrVal = p2;
}
}
}
}
// if we did not set pszStrVal, then we have an invalid conditional token
if (frag.pszStrVal == NULL)
{
bInvalid = TRUE;
}
}
else
{
// the character following the delimter was not valid
bInvalid = TRUE;
}
// add the token faragment, we dont check for invalid before adding
// if invalid, everything is discard in the end anyway
AddFrag(&frag);
} // not escaped delimter
// now, we are looking at the end of the token, assign pszNext to process
// the next fragment
pszNext = ++p;
// exit the loop if we are at the end of the template or there was an error
if (bInvalid || (*p == '\0'))
{
break;
}
} // delimiter found
else
{
// delimiter not found, copy the rest of string as FRAG_STR
frag.FragType = FRAG_STR;
frag.pszStrVal = pszNext;
AddFrag(&frag);
// we are done, exit loop
break;
}
} // for loop
m_bInvalid = bInvalid;
}
CParseTemplate::~CParseTemplate()
{
free(m_pTemplateBuf);
if (m_pFrag != NULL)
free(m_pFrag);
if (m_pszStrBuf != NULL)
free(m_pszStrBuf);
}
void CParseTemplate::AddFrag(FRAGMENT* pfrag)
{
if ((m_cFragUsed + 1) > m_cFragAlloc)
{
// not enough entries allocated, allocate current count + a delta
FRAGMENT* pNew = (FRAGMENT*)malloc((m_cFragAlloc + FRAG_EXPAND) * sizeof(FRAGMENT));
if (m_pFrag != NULL)
{
memcpy(pNew, m_pFrag, m_cFragAlloc * sizeof(FRAGMENT));
free(m_pFrag);
}
m_pFrag = pNew;
m_cFragAlloc += FRAG_EXPAND;
}
// fill in the length field
if (pfrag->pszStrVal != NULL)
pfrag->dwStrLen = strlen(pfrag->pszStrVal);
memcpy(&m_pFrag[m_cFragUsed++], pfrag, sizeof(FRAGMENT));
}
void CParseTemplate::ClearStr()
{
if (m_pszStrBuf == NULL)
return;
*m_pszStrBuf = '\0';
m_cStrUsed = 0;
}
void CParseTemplate::AppendStr(LPCSTR pszStr, DWORD cLen)
{
if (cLen == 0)
{
return;
}
if ((m_cStrUsed + cLen + 1) > m_cStrAlloc)
{
// not enough memory allocated, allocate current + delta
LPSTR pNew = (LPSTR)malloc(m_cStrAlloc + STR_EXPAND);
if (m_pszStrBuf != NULL)
{
memcpy(pNew, m_pszStrBuf, m_cStrAlloc);
free(m_pszStrBuf);
}
else
{
*pNew = '\0';
m_cStrUsed = 0;
}
m_pszStrBuf = pNew;
m_cStrAlloc += STR_EXPAND;
}
// append the string
strcpy((m_pszStrBuf + m_cStrUsed), pszStr);
m_cStrUsed += cLen;
}
// ^0 PUID
// ^1 Title
// ^2 Description
// ^3 Size number in KB
// ^4 Formated download time (1 hr 2 min OR < 1 min)
// ^5 Line break
// ^6(n)^d^ Got read-this-page?
// n=0 -> if yes, insert DHTML d (@ in d replaced with URL)
// ^7(n)^d^ Can be uninstalled?
// n=0 -> if yes, insert DHTML d
// ^8(n)^d^ Is installed?
// n=0 -> if yes, insert DHTML d
// ^9(n)^d^ Is item currently selected (checked)?
// n=0 -> if yes, insert DHTML d
// ^A(n)^d^ Does section has items under it?
// n=0 -> if yes, insert DHTML d
// ^B(n)^d^ Is icon flag on?
// n=4 -> if 'new' flag is set, insert DHTML d
// n=8 -> if 'power' flag is set, insert DHTML d
// n=16 -> if 'registration' flag is set, insert DHTML d
// n=32 -> if 'cool' flag is set, insert DHTML d
// n=64 -> if 'patch' flag is set, insert DHTML d
BOOL CParseTemplate::MakeItemString(PINVENTORY_ITEM pItem)
{
FRAGMENT frag;
ClearStr();
if (m_bInvalid)
{
return FALSE;
}
for (int i = 0; i < m_cFragUsed; i++)
{
frag = m_pFrag[i];
if (frag.FragType == FRAG_STR)
{
//
// just a string, copy it as is
//
AppendStr(frag.pszStrVal, frag.dwStrLen);
}
else if (frag.FragType == FRAG_REPLACE)
{
//
// replacement token
//
switch (frag.chCode)
{
case '0':
// puid
BLOCK
{
PUID puid;
char szPuid[16];
pItem->GetFixedFieldInfo(WU_ITEM_PUID, (PVOID)&puid);
_itoa(puid, szPuid, 10);
AppendStr(szPuid, strlen(szPuid));
}
break;
case '1':
// title
BLOCK
{
PWU_VARIABLE_FIELD pvar;
if (pvar = pItem->pd->pv->Find(WU_DESCRIPTION_TITLE))
{
LPCSTR pszTitle = (LPCSTR)pvar->pData;
AppendStr(pszTitle, strlen(pszTitle));
}
}
break;
case '2':
// description
BLOCK
{
PWU_VARIABLE_FIELD pvar;
if (pvar = pItem->pd->pv->Find(WU_DESCRIPTION_DESCRIPTION))
{
LPCSTR pszDesc = (LPSTR)pvar->pData;
AppendStr(pszDesc, strlen(pszDesc));
}
}
break;
case '3':
// size
BLOCK
{
char szBuf[16];
_itoa(pItem->pd->size, szBuf, 10);
AppendStr(szBuf, strlen(szBuf));
}
break;
case '4':
// download time
BLOCK
{
DWORD dwSecsTotal = pItem->pd->downloadTime;
DWORD dwSecs = dwSecsTotal % 60;
DWORD dwMinutes = (dwSecsTotal % 3600) / 60;
DWORD dwHours = dwSecsTotal / 3600;
char szBuf[128];
int cBuf = 0;
if (dwHours == 0)
{
if (dwMinutes == 0)
cBuf = sprintf(szBuf, GetLocStr(IDS_PROG_TIME_SEC), dwSecs);
else
cBuf = sprintf(szBuf, GetLocStr(IDS_PROG_TIME_MIN), dwMinutes);
}
else
{
cBuf = sprintf(szBuf, GetLocStr(IDS_PROG_TIME_HRMIN), dwHours, dwMinutes);
}
AppendStr(szBuf, cBuf);
}
break;
case '5':
// line break
BLOCK
{
LPCSTR pszNL = "\r\n";
AppendStr(pszNL, strlen(pszNL));
}
break;
}
}
else if (frag.FragType == FRAG_CONDITION)
{
//
// conditional token
//
switch (frag.chCode)
{
case '6':
// read this first
BLOCK
{
PWU_VARIABLE_FIELD pvar;
if (pvar = pItem->pd->pv->Find(WU_DESCRIPTION_READTHIS_URL))
{
LPCSTR pszReadThisURL = (LPCSTR)pvar->pData;
// TODO: replace @ with the URL in a copy of pszStrVal
AppendStr(frag.pszStrVal, frag.dwStrLen);
}
}
break;
case '7':
// Can be uninstalled
BLOCK
{
BOOL bUninstall = FALSE;
if (pItem->recordType == WU_TYPE_CDM_RECORD)
{
bUninstall = TRUE;
}
else if (pItem->pd->pv->Find(WU_DESCRIPTION_UNINSTALL_KEY))
{
bUninstall = TRUE;
}
if (bUninstall)
{
AppendStr(frag.pszStrVal, frag.dwStrLen);
}
}
break;
case '8':
// Is installed
BLOCK
{
}
break;
case '9':
// currently selected
BLOCK
{
}
break;
case 'A':
// section has items
BLOCK
{
}
break;
case 'B':
// icon flags
BLOCK
{
}
break;
}
}
}
return TRUE;
}
HRESULT MakeCatalogHTML(
CCatalog* pCatalog,
long lFilters,
VARIANT* pvaVariant
)
{
LPCSTR pszItemTemp = GetTemplateStr(IDS_TEMPLATE_ITEM);
LPCSTR pszSecTemp = GetTemplateStr(IDS_TEMPLATE_SEC);
LPCSTR pszSubsecTemp = GetTemplateStr(IDS_TEMPLATE_SUBSEC);
LPCSTR pszSubsubsecTemp = GetTemplateStr(IDS_TEMPLATE_SUBSUBSEC);
VariantInit(pvaVariant);
if (pszItemTemp == NULL || pszSecTemp == NULL || pszSubsecTemp == NULL || pszSubsubsecTemp == NULL)
{
// all templates are not specified
return HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
}
//
// create template objects
//
CParseTemplate ItemTemp(pszItemTemp);
CParseTemplate SecTemp(pszSecTemp);
CParseTemplate SubsecTemp(pszSubsecTemp);
CParseTemplate SubsubsecTemp(pszSubsubsecTemp);
if (ItemTemp.Invalid() || SecTemp.Invalid() || SubsecTemp.Invalid() || SubsubsecTemp.Invalid())
{
// all templates are not valid
return HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
}
PINVENTORY_ITEM pItem;
LPSTR pszHTM;
int lenHTM = 0;
pszHTM = (char*)malloc(200 * 1024);
pszHTM[0] = '\0';
for (int i = 0; i < pCatalog->GetHeader()->totalItems; i++)
{
if (NULL == (pItem = pCatalog->GetItem(i)))
{
continue;
}
if (!FilterCatalogItem(pItem, lFilters))
continue;
if (!pItem->pd)
continue;
//
// based on item type select the correct template to create the string from
//
LPCSTR pszGenStr = NULL;
int cGenLen = 0;
if (pItem->recordType == WU_TYPE_SECTION_RECORD)
{
SecTemp.MakeItemString(pItem);
pszGenStr = SecTemp.GetString();
cGenLen = SecTemp.GetStringLen();
}
else if (pItem->recordType == WU_TYPE_SUBSECTION_RECORD)
{
SubsecTemp.MakeItemString(pItem);
pszGenStr = SubsecTemp.GetString();
cGenLen = SubsecTemp.GetStringLen();
}
else if (pItem->recordType == WU_TYPE_SUBSUBSECTION_RECORD)
{
SubsubsecTemp.MakeItemString(pItem);
pszGenStr = SubsubsecTemp.GetString();
cGenLen = SubsubsecTemp.GetStringLen();
}
else
{
ItemTemp.MakeItemString(pItem);
pszGenStr = ItemTemp.GetString();
cGenLen = ItemTemp.GetStringLen();
}
//
// append the generated to string to the main string
//
strcpy(pszHTM + lenHTM, pszGenStr);
lenHTM += cGenLen;
}
//
// return the string in buffer
//
V_VT(pvaVariant) = VT_BSTR;
pvaVariant->bstrVal = SysAllocString(T2OLE(pszHTM));
free(pszHTM);
return NOERROR;
}
#endif