Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

573 lines
12 KiB

  1. //=======================================================================
  2. //
  3. // Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
  4. //
  5. // File: template.cpp
  6. //
  7. // Purpose: DHTML template support
  8. //
  9. // History: 4/3/99 YAsmi Created
  10. //
  11. //=======================================================================
  12. #include "template.h"
  13. // we are currently not using the templates feature
  14. // the code for templates is wrapped in HTML_TEMPLATE define
  15. #ifdef HTML_TEMPLATE
  16. //
  17. // CParseTemplate class
  18. //
  19. CParseTemplate::CParseTemplate(LPCSTR pszTemplate)
  20. : m_pFrag(NULL),
  21. m_cFragAlloc(0),
  22. m_cFragUsed(0),
  23. m_bInvalid(FALSE),
  24. m_pszStrBuf(NULL),
  25. m_cStrAlloc(0),
  26. m_cStrUsed(0)
  27. {
  28. LPCSTR pszReplacementCodes = "012345";
  29. LPCSTR pszConditionalCodes = "6789AB";
  30. LPSTR pszNext;
  31. FRAGMENT frag;
  32. BOOL bInvalid = FALSE;
  33. // copy the template in our buffer
  34. m_pTemplateBuf = _strdup(pszTemplate);
  35. //
  36. // parse the template
  37. //
  38. pszNext = m_pTemplateBuf;
  39. for (;;)
  40. {
  41. LPSTR p = strchr(pszNext, '^');
  42. ZeroMemory(&frag, sizeof(frag));
  43. if (p != NULL)
  44. {
  45. // delimiter found check to see if next character is a delimiter so we can escape it
  46. if (*(p + 1) == '^')
  47. {
  48. // escape it
  49. p++;
  50. // insert a null to make the preceeding string a null terminated string
  51. *p = '\0';
  52. frag.FragType = FRAG_STR;
  53. frag.pszStrVal = pszNext;
  54. AddFrag(&frag);
  55. }
  56. else
  57. {
  58. //
  59. // we have a non escape character following the delimiter
  60. // add the preceeding string fragment and process the token fragment
  61. //
  62. // insert a null to make the preceeding string a null terminated string
  63. *p = '\0';
  64. frag.FragType = FRAG_STR;
  65. frag.pszStrVal = pszNext;
  66. AddFrag(&frag);
  67. // we are at the begining of a token, skip to code
  68. p++;
  69. if (strchr(pszReplacementCodes, *p) != NULL)
  70. {
  71. // we have a replacement code
  72. frag.FragType = FRAG_REPLACE;
  73. frag.chCode = *p;
  74. }
  75. else if (strchr(pszConditionalCodes, *p) != NULL)
  76. {
  77. // we have a conditional code, read the paranthesis
  78. frag.FragType = FRAG_CONDITION;
  79. frag.chCode = *p;
  80. frag.dwVal = 0;
  81. frag.pszStrVal = NULL; // if not changed in the following code we have an error
  82. // skip over code
  83. p++;
  84. if (*(p++) == '(')
  85. {
  86. // read numeric parameter between paranthesis
  87. while (isdigit(*p))
  88. {
  89. frag.dwVal = frag.dwVal * 10 + (DWORD)(*(p++) - '0');
  90. }
  91. if (*(p++) == ')')
  92. {
  93. if (*(p++) == '^')
  94. {
  95. // we are looking at the begining of the replace value, skip to next delimiter
  96. LPSTR p2 = p;
  97. p = strchr(p2, '^');
  98. if (p != NULL)
  99. {
  100. // we now have complete syntax of condition token
  101. *p = '\0';
  102. frag.pszStrVal = p2;
  103. }
  104. }
  105. }
  106. }
  107. // if we did not set pszStrVal, then we have an invalid conditional token
  108. if (frag.pszStrVal == NULL)
  109. {
  110. bInvalid = TRUE;
  111. }
  112. }
  113. else
  114. {
  115. // the character following the delimter was not valid
  116. bInvalid = TRUE;
  117. }
  118. // add the token faragment, we dont check for invalid before adding
  119. // if invalid, everything is discard in the end anyway
  120. AddFrag(&frag);
  121. } // not escaped delimter
  122. // now, we are looking at the end of the token, assign pszNext to process
  123. // the next fragment
  124. pszNext = ++p;
  125. // exit the loop if we are at the end of the template or there was an error
  126. if (bInvalid || (*p == '\0'))
  127. {
  128. break;
  129. }
  130. } // delimiter found
  131. else
  132. {
  133. // delimiter not found, copy the rest of string as FRAG_STR
  134. frag.FragType = FRAG_STR;
  135. frag.pszStrVal = pszNext;
  136. AddFrag(&frag);
  137. // we are done, exit loop
  138. break;
  139. }
  140. } // for loop
  141. m_bInvalid = bInvalid;
  142. }
  143. CParseTemplate::~CParseTemplate()
  144. {
  145. free(m_pTemplateBuf);
  146. if (m_pFrag != NULL)
  147. free(m_pFrag);
  148. if (m_pszStrBuf != NULL)
  149. free(m_pszStrBuf);
  150. }
  151. void CParseTemplate::AddFrag(FRAGMENT* pfrag)
  152. {
  153. if ((m_cFragUsed + 1) > m_cFragAlloc)
  154. {
  155. // not enough entries allocated, allocate current count + a delta
  156. FRAGMENT* pNew = (FRAGMENT*)malloc((m_cFragAlloc + FRAG_EXPAND) * sizeof(FRAGMENT));
  157. if (m_pFrag != NULL)
  158. {
  159. memcpy(pNew, m_pFrag, m_cFragAlloc * sizeof(FRAGMENT));
  160. free(m_pFrag);
  161. }
  162. m_pFrag = pNew;
  163. m_cFragAlloc += FRAG_EXPAND;
  164. }
  165. // fill in the length field
  166. if (pfrag->pszStrVal != NULL)
  167. pfrag->dwStrLen = strlen(pfrag->pszStrVal);
  168. memcpy(&m_pFrag[m_cFragUsed++], pfrag, sizeof(FRAGMENT));
  169. }
  170. void CParseTemplate::ClearStr()
  171. {
  172. if (m_pszStrBuf == NULL)
  173. return;
  174. *m_pszStrBuf = '\0';
  175. m_cStrUsed = 0;
  176. }
  177. void CParseTemplate::AppendStr(LPCSTR pszStr, DWORD cLen)
  178. {
  179. if (cLen == 0)
  180. {
  181. return;
  182. }
  183. if ((m_cStrUsed + cLen + 1) > m_cStrAlloc)
  184. {
  185. // not enough memory allocated, allocate current + delta
  186. LPSTR pNew = (LPSTR)malloc(m_cStrAlloc + STR_EXPAND);
  187. if (m_pszStrBuf != NULL)
  188. {
  189. memcpy(pNew, m_pszStrBuf, m_cStrAlloc);
  190. free(m_pszStrBuf);
  191. }
  192. else
  193. {
  194. *pNew = '\0';
  195. m_cStrUsed = 0;
  196. }
  197. m_pszStrBuf = pNew;
  198. m_cStrAlloc += STR_EXPAND;
  199. }
  200. // append the string
  201. strcpy((m_pszStrBuf + m_cStrUsed), pszStr);
  202. m_cStrUsed += cLen;
  203. }
  204. // ^0 PUID
  205. // ^1 Title
  206. // ^2 Description
  207. // ^3 Size number in KB
  208. // ^4 Formated download time (1 hr 2 min OR < 1 min)
  209. // ^5 Line break
  210. // ^6(n)^d^ Got read-this-page?
  211. // n=0 -> if yes, insert DHTML d (@ in d replaced with URL)
  212. // ^7(n)^d^ Can be uninstalled?
  213. // n=0 -> if yes, insert DHTML d
  214. // ^8(n)^d^ Is installed?
  215. // n=0 -> if yes, insert DHTML d
  216. // ^9(n)^d^ Is item currently selected (checked)?
  217. // n=0 -> if yes, insert DHTML d
  218. // ^A(n)^d^ Does section has items under it?
  219. // n=0 -> if yes, insert DHTML d
  220. // ^B(n)^d^ Is icon flag on?
  221. // n=4 -> if 'new' flag is set, insert DHTML d
  222. // n=8 -> if 'power' flag is set, insert DHTML d
  223. // n=16 -> if 'registration' flag is set, insert DHTML d
  224. // n=32 -> if 'cool' flag is set, insert DHTML d
  225. // n=64 -> if 'patch' flag is set, insert DHTML d
  226. BOOL CParseTemplate::MakeItemString(PINVENTORY_ITEM pItem)
  227. {
  228. FRAGMENT frag;
  229. ClearStr();
  230. if (m_bInvalid)
  231. {
  232. return FALSE;
  233. }
  234. for (int i = 0; i < m_cFragUsed; i++)
  235. {
  236. frag = m_pFrag[i];
  237. if (frag.FragType == FRAG_STR)
  238. {
  239. //
  240. // just a string, copy it as is
  241. //
  242. AppendStr(frag.pszStrVal, frag.dwStrLen);
  243. }
  244. else if (frag.FragType == FRAG_REPLACE)
  245. {
  246. //
  247. // replacement token
  248. //
  249. switch (frag.chCode)
  250. {
  251. case '0':
  252. // puid
  253. BLOCK
  254. {
  255. PUID puid;
  256. char szPuid[16];
  257. pItem->GetFixedFieldInfo(WU_ITEM_PUID, (PVOID)&puid);
  258. _itoa(puid, szPuid, 10);
  259. AppendStr(szPuid, strlen(szPuid));
  260. }
  261. break;
  262. case '1':
  263. // title
  264. BLOCK
  265. {
  266. PWU_VARIABLE_FIELD pvar;
  267. if (pvar = pItem->pd->pv->Find(WU_DESCRIPTION_TITLE))
  268. {
  269. LPCSTR pszTitle = (LPCSTR)pvar->pData;
  270. AppendStr(pszTitle, strlen(pszTitle));
  271. }
  272. }
  273. break;
  274. case '2':
  275. // description
  276. BLOCK
  277. {
  278. PWU_VARIABLE_FIELD pvar;
  279. if (pvar = pItem->pd->pv->Find(WU_DESCRIPTION_DESCRIPTION))
  280. {
  281. LPCSTR pszDesc = (LPSTR)pvar->pData;
  282. AppendStr(pszDesc, strlen(pszDesc));
  283. }
  284. }
  285. break;
  286. case '3':
  287. // size
  288. BLOCK
  289. {
  290. char szBuf[16];
  291. _itoa(pItem->pd->size, szBuf, 10);
  292. AppendStr(szBuf, strlen(szBuf));
  293. }
  294. break;
  295. case '4':
  296. // download time
  297. BLOCK
  298. {
  299. DWORD dwSecsTotal = pItem->pd->downloadTime;
  300. DWORD dwSecs = dwSecsTotal % 60;
  301. DWORD dwMinutes = (dwSecsTotal % 3600) / 60;
  302. DWORD dwHours = dwSecsTotal / 3600;
  303. char szBuf[128];
  304. int cBuf = 0;
  305. if (dwHours == 0)
  306. {
  307. if (dwMinutes == 0)
  308. cBuf = sprintf(szBuf, GetLocStr(IDS_PROG_TIME_SEC), dwSecs);
  309. else
  310. cBuf = sprintf(szBuf, GetLocStr(IDS_PROG_TIME_MIN), dwMinutes);
  311. }
  312. else
  313. {
  314. cBuf = sprintf(szBuf, GetLocStr(IDS_PROG_TIME_HRMIN), dwHours, dwMinutes);
  315. }
  316. AppendStr(szBuf, cBuf);
  317. }
  318. break;
  319. case '5':
  320. // line break
  321. BLOCK
  322. {
  323. LPCSTR pszNL = "\r\n";
  324. AppendStr(pszNL, strlen(pszNL));
  325. }
  326. break;
  327. }
  328. }
  329. else if (frag.FragType == FRAG_CONDITION)
  330. {
  331. //
  332. // conditional token
  333. //
  334. switch (frag.chCode)
  335. {
  336. case '6':
  337. // read this first
  338. BLOCK
  339. {
  340. PWU_VARIABLE_FIELD pvar;
  341. if (pvar = pItem->pd->pv->Find(WU_DESCRIPTION_READTHIS_URL))
  342. {
  343. LPCSTR pszReadThisURL = (LPCSTR)pvar->pData;
  344. // TODO: replace @ with the URL in a copy of pszStrVal
  345. AppendStr(frag.pszStrVal, frag.dwStrLen);
  346. }
  347. }
  348. break;
  349. case '7':
  350. // Can be uninstalled
  351. BLOCK
  352. {
  353. BOOL bUninstall = FALSE;
  354. if (pItem->recordType == WU_TYPE_CDM_RECORD)
  355. {
  356. bUninstall = TRUE;
  357. }
  358. else if (pItem->pd->pv->Find(WU_DESCRIPTION_UNINSTALL_KEY))
  359. {
  360. bUninstall = TRUE;
  361. }
  362. if (bUninstall)
  363. {
  364. AppendStr(frag.pszStrVal, frag.dwStrLen);
  365. }
  366. }
  367. break;
  368. case '8':
  369. // Is installed
  370. BLOCK
  371. {
  372. }
  373. break;
  374. case '9':
  375. // currently selected
  376. BLOCK
  377. {
  378. }
  379. break;
  380. case 'A':
  381. // section has items
  382. BLOCK
  383. {
  384. }
  385. break;
  386. case 'B':
  387. // icon flags
  388. BLOCK
  389. {
  390. }
  391. break;
  392. }
  393. }
  394. }
  395. return TRUE;
  396. }
  397. HRESULT MakeCatalogHTML(
  398. CCatalog* pCatalog,
  399. long lFilters,
  400. VARIANT* pvaVariant
  401. )
  402. {
  403. LPCSTR pszItemTemp = GetTemplateStr(IDS_TEMPLATE_ITEM);
  404. LPCSTR pszSecTemp = GetTemplateStr(IDS_TEMPLATE_SEC);
  405. LPCSTR pszSubsecTemp = GetTemplateStr(IDS_TEMPLATE_SUBSEC);
  406. LPCSTR pszSubsubsecTemp = GetTemplateStr(IDS_TEMPLATE_SUBSUBSEC);
  407. VariantInit(pvaVariant);
  408. if (pszItemTemp == NULL || pszSecTemp == NULL || pszSubsecTemp == NULL || pszSubsubsecTemp == NULL)
  409. {
  410. // all templates are not specified
  411. return HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
  412. }
  413. //
  414. // create template objects
  415. //
  416. CParseTemplate ItemTemp(pszItemTemp);
  417. CParseTemplate SecTemp(pszSecTemp);
  418. CParseTemplate SubsecTemp(pszSubsecTemp);
  419. CParseTemplate SubsubsecTemp(pszSubsubsecTemp);
  420. if (ItemTemp.Invalid() || SecTemp.Invalid() || SubsecTemp.Invalid() || SubsubsecTemp.Invalid())
  421. {
  422. // all templates are not valid
  423. return HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
  424. }
  425. PINVENTORY_ITEM pItem;
  426. LPSTR pszHTM;
  427. int lenHTM = 0;
  428. pszHTM = (char*)malloc(200 * 1024);
  429. pszHTM[0] = '\0';
  430. for (int i = 0; i < pCatalog->GetHeader()->totalItems; i++)
  431. {
  432. if (NULL == (pItem = pCatalog->GetItem(i)))
  433. {
  434. continue;
  435. }
  436. if (!FilterCatalogItem(pItem, lFilters))
  437. continue;
  438. if (!pItem->pd)
  439. continue;
  440. //
  441. // based on item type select the correct template to create the string from
  442. //
  443. LPCSTR pszGenStr = NULL;
  444. int cGenLen = 0;
  445. if (pItem->recordType == WU_TYPE_SECTION_RECORD)
  446. {
  447. SecTemp.MakeItemString(pItem);
  448. pszGenStr = SecTemp.GetString();
  449. cGenLen = SecTemp.GetStringLen();
  450. }
  451. else if (pItem->recordType == WU_TYPE_SUBSECTION_RECORD)
  452. {
  453. SubsecTemp.MakeItemString(pItem);
  454. pszGenStr = SubsecTemp.GetString();
  455. cGenLen = SubsecTemp.GetStringLen();
  456. }
  457. else if (pItem->recordType == WU_TYPE_SUBSUBSECTION_RECORD)
  458. {
  459. SubsubsecTemp.MakeItemString(pItem);
  460. pszGenStr = SubsubsecTemp.GetString();
  461. cGenLen = SubsubsecTemp.GetStringLen();
  462. }
  463. else
  464. {
  465. ItemTemp.MakeItemString(pItem);
  466. pszGenStr = ItemTemp.GetString();
  467. cGenLen = ItemTemp.GetStringLen();
  468. }
  469. //
  470. // append the generated to string to the main string
  471. //
  472. strcpy(pszHTM + lenHTM, pszGenStr);
  473. lenHTM += cGenLen;
  474. }
  475. //
  476. // return the string in buffer
  477. //
  478. V_VT(pvaVariant) = VT_BSTR;
  479. pvaVariant->bstrVal = SysAllocString(T2OLE(pszHTM));
  480. free(pszHTM);
  481. return NOERROR;
  482. }
  483. #endif