|
|
//=======================================================================
//
// 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
|