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.

1456 lines
40 KiB

  1. //
  2. // MODULE: APGTSHTIREAD.CPP
  3. //
  4. // PURPOSE: HTI template file reading classes
  5. //
  6. // COMPANY: Saltmine Creative, Inc. (206)-284-7511 [email protected]
  7. //
  8. // AUTHOR: Oleg Kalosha
  9. //
  10. // ORIGINAL DATE: 8-27-98
  11. //
  12. // NOTES:
  13. // 1. HTI is loosely modeled on a Microsoft format called HTX. It's a template for an
  14. // HTML file. Most of it is HTML, but certain pseudo-comments of the form
  15. // <!GTS whatever> are intended to be interpreted as conditionals, places to
  16. // insert text, etc.
  17. //
  18. // Variables are limited to the values
  19. // $ProblemAsk
  20. // $Recommendations
  21. // $States
  22. // $Questions
  23. // $Success (introduced 9/24/98)
  24. // $StartForm
  25. // See class CHTMLFragmentsTS for more details.
  26. // Commands are if/else/endif, forany/endfor, display
  27. // There is also a notion of a "resource", basically an include file.
  28. //
  29. // EXAMPLE 1
  30. // <!GTS forany $States >
  31. // <!GTS display $States >
  32. // <!GTS endfor>
  33. //
  34. // EXAMPLE 2
  35. // <!GTS if $ProblemAsk >
  36. // lots of HTML or nested calls to more GTS stuff could go here
  37. // <!GTS else >
  38. // lots of other HTML or nested calls to other GTS stuff could go here
  39. // <!GTS endif >
  40. //
  41. // each <!GTS...> command must fit on a single line.
  42. //
  43. // Version Date By Comments
  44. //--------------------------------------------------------------------
  45. // V3.0 08-04-98 OK
  46. //
  47. #pragma warning(disable:4786)
  48. #include "stdafx.h"
  49. #include "apgtshtiread.h"
  50. #include "event.h"
  51. #include "CharConv.h"
  52. #include "apgtsMFC.h"
  53. #ifdef LOCAL_TROUBLESHOOTER
  54. #include "htmlfraglocal.h"
  55. #endif
  56. namespace
  57. {
  58. CString k_strHTMLtag= _T("/HTML");
  59. }
  60. ///////////////////////////////////////////////////////////////////////////////////////////
  61. // CAPGTSHTIReader
  62. ///////////////////////////////////////////////////////////////////////////////////////////
  63. CAPGTSHTIReader::CAPGTSHTIReader(CPhysicalFileReader * pPhysicalFileReader, LPCTSTR szDefaultContents /* NULL */)
  64. : CTemplateReader(pPhysicalFileReader, szDefaultContents),
  65. m_pFragments(NULL)
  66. {
  67. }
  68. CAPGTSHTIReader::~CAPGTSHTIReader()
  69. {
  70. }
  71. void CAPGTSHTIReader::Parse()
  72. {
  73. #ifdef LOCAL_TROUBLESHOOTER
  74. // OVERVIEW: For the Local Troubleshooter, search for a <!GTS resource $Previous.script>
  75. // token in the stream. If one is not found, then insert one for backwards
  76. // compatibility.
  77. try
  78. {
  79. // Load the stream into a vector while searching for a "Previous.script" token and also
  80. // determining the position of the last closing HTML tag location in order to know where
  81. // to insert the generated_previous() function.
  82. CString str;
  83. vector<CString> str_arr;
  84. long indexLastHTML = -1;
  85. // Place the content of m_StreamData, line by line, into str_arr
  86. SetPos( m_StreamData, 0 );
  87. while (GetLine( m_StreamData, str ))
  88. {
  89. // Determine whether or not this line contains the "Previous.script" token.
  90. CString strCommand;
  91. if (GetCommand( str, strCommand))
  92. {
  93. // Check if the command is the right type.
  94. if (strCommand == COMMAND_RESOURCESTR)
  95. {
  96. CString strVariable;
  97. if (GetVariable( str, strVariable ))
  98. {
  99. // Check if the variable is the right type.
  100. if (strVariable == VAR_PREVIOUS_SCRIPT)
  101. {
  102. // We found what we were looking for.
  103. // Reset the stream position and exit function.
  104. SetPos( m_StreamData, 0 );
  105. return;
  106. }
  107. }
  108. }
  109. }
  110. // Add this line to the vector.
  111. str_arr.push_back( str );
  112. // Look for an HTML closing tag in this line.
  113. if (str.Find( k_strHTMLtag ) != -1)
  114. {
  115. // Mark the location of the last \HTML tag found.
  116. indexLastHTML= str_arr.size() - 1;
  117. }
  118. }
  119. // Rebuild the input stream from the vector and insert the "Previous.script" token
  120. // in the location determined above.
  121. vector<CString>::iterator iLastElement = str_arr.end();
  122. iLastElement--;
  123. m_StreamData.clear();
  124. CString strResult;
  125. long index = 0;
  126. for (vector<CString>::iterator i = str_arr.begin(); i < str_arr.end(); i++, index++)
  127. {
  128. if (index == indexLastHTML)
  129. {
  130. // Add the required token to the string.
  131. strResult+= COMMAND_STARTSTR;
  132. strResult+= _T(" ");
  133. strResult+= COMMAND_RESOURCESTR;
  134. strResult+= _T(" ");
  135. strResult+= COMMAND_STARTVARSTR;
  136. strResult+= VAR_PREVIOUS_SCRIPT;
  137. strResult+= COMMAND_ENDSTR;
  138. strResult+= _T("\r\n");
  139. }
  140. strResult += *i;
  141. if (i != iLastElement)
  142. strResult+= _T("\r\n");
  143. }
  144. m_StreamData.str( (LPCTSTR) strResult );
  145. SetPos( m_StreamData, 0 );
  146. }
  147. catch (exception& x)
  148. {
  149. CString str;
  150. // Note STL exception in event log.
  151. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  152. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  153. SrcLoc.GetSrcFileLineStr(),
  154. CCharConversion::ConvertACharToString(x.what(), str),
  155. _T(""),
  156. EV_GTS_STL_EXCEPTION );
  157. }
  158. #endif
  159. }
  160. // JSM V3.2 adapted from CreatePage()
  161. // builds list of all Network props in this HTI file which appear
  162. // in lines like <!GTI property "fooprop">
  163. //
  164. // called by apgtscontext to find network properties to pass to CHTMLFragmentsTS
  165. void CAPGTSHTIReader::ExtractNetProps(vector <CString> &arr_props)
  166. {
  167. LOCKOBJECT();
  168. try
  169. {
  170. arr_props.clear();
  171. // InitializeInterpreted populates m_arrInterpreted and
  172. // performs cookie substitutions. This is correct behavior,
  173. // because cookie substitution is supposed to happen
  174. // before !GTS processing, and it is conceivable
  175. // that a cookie's value could be "<!GTS property fooprop>"
  176. InitializeInterpreted();
  177. // we should not call Interpret(), which involves parsing <!GTS clauses
  178. for (vector<CString>::iterator i = m_arrInterpreted.begin(); i < m_arrInterpreted.end(); i++)
  179. {
  180. CString command;
  181. if (GetCommand(*i, command))
  182. {
  183. if (command == COMMAND_PROPERTY)
  184. {
  185. CString strProperty;
  186. if (GetVariable(*i,strProperty))
  187. arr_props.push_back(strProperty);
  188. }
  189. }
  190. }
  191. }
  192. catch (...)
  193. {
  194. // Catch any other exception thrown.
  195. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  196. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  197. SrcLoc.GetSrcFileLineStr(),
  198. _T(""), _T(""),
  199. EV_GTS_GEN_EXCEPTION );
  200. }
  201. UNLOCKOBJECT();
  202. }
  203. void CAPGTSHTIReader::CreatePage( const CHTMLFragments& fragments,
  204. CString& out,
  205. const map<CString,CString> & mapStrs,
  206. CString strHTTPcookies/*= _T("")*/ )
  207. {
  208. LOCKOBJECT();
  209. try
  210. {
  211. m_pFragments = &fragments;
  212. // V3.2 Cookie related enhancement.
  213. // Opted to use a member variable rather than modifying class interface by
  214. // adding a parameter to virtual void method InitializeInterpreted().
  215. m_strHTTPcookies= strHTTPcookies;
  216. m_mapCookies= mapStrs;
  217. InitializeInterpreted();
  218. Interpret();
  219. #ifdef __DEBUG_CUSTOM
  220. SetOutputToInterpreted();
  221. FlushOutputStreamToFile("..\\Files\\interpreted.hti");
  222. #endif
  223. ParseInterpreted();
  224. SetOutputToInterpreted();
  225. #ifdef __DEBUG_CUSTOM
  226. FlushOutputStreamToFile("..\\Files\\result.htm");
  227. #endif
  228. out = m_StreamOutput.rdbuf()->str().c_str();
  229. }
  230. catch (...)
  231. {
  232. // Catch any other exception thrown.
  233. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  234. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  235. SrcLoc.GetSrcFileLineStr(),
  236. _T(""), _T(""),
  237. EV_GTS_GEN_EXCEPTION );
  238. }
  239. UNLOCKOBJECT();
  240. }
  241. void CAPGTSHTIReader::InitializeInterpreted()
  242. {
  243. long savePos = 0;
  244. CString str;
  245. CString command;
  246. bool bOldFormat = true; // this is an old format (without $Success or $StartForm)
  247. bool bFoundFirstBlock= false;
  248. savePos = GetPos();
  249. bOldFormat = !Find(CString(COMMAND_STARTVARSTR)+VAR_SUCCESS) &&
  250. !Find(CString(COMMAND_STARTVARSTR)+VAR_STARTFORM);
  251. SetPos(0);
  252. m_arrInterpreted.clear();
  253. try
  254. {
  255. while (GetLine(str))
  256. {
  257. if (bOldFormat && (!bFoundFirstBlock) && (-1 != str.Find( COMMAND_STARTSTR )))
  258. {
  259. // Output the $StartForm block only if it is not a resource string command.
  260. CString strCommand;
  261. if ((GetCommand( str, strCommand )) && (strCommand != COMMAND_RESOURCESTR))
  262. {
  263. /*
  264. <!GTS if $StartForm>
  265. <!GTS display $StartForm>
  266. <!GTS endif>
  267. */
  268. ComposeCommand(COMMAND_IFSTR, VAR_STARTFORM, command);
  269. m_arrInterpreted.push_back(command);
  270. ComposeCommand(COMMAND_DISPLAYSTR, VAR_STARTFORM, command);
  271. m_arrInterpreted.push_back(command);
  272. ComposeCommand(COMMAND_ENDIFSTR, _T(""), command);
  273. m_arrInterpreted.push_back(command);
  274. bFoundFirstBlock = true;
  275. }
  276. }
  277. if (bOldFormat && (-1 != str.Find(_T("</FORM>"))))
  278. {
  279. /*
  280. <!GTS if $StartForm>
  281. */
  282. ComposeCommand(COMMAND_IFSTR, VAR_STARTFORM, command);
  283. m_arrInterpreted.push_back(command);
  284. m_arrInterpreted.push_back(str);
  285. /*
  286. <!GTS endif>
  287. */
  288. ComposeCommand(COMMAND_ENDIFSTR, _T(""), command);
  289. m_arrInterpreted.push_back(command);
  290. }
  291. else
  292. {
  293. // Check if we need to populate any cookie clauses.
  294. if (-1 != str.Find( COMMAND_COOKIE ))
  295. SubstituteCookieValues( str );
  296. m_arrInterpreted.push_back(str);
  297. }
  298. }
  299. }
  300. catch (exception& x)
  301. {
  302. CString str2;
  303. // Note STL exception in event log.
  304. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  305. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  306. SrcLoc.GetSrcFileLineStr(),
  307. CCharConversion::ConvertACharToString(x.what(), str2),
  308. _T(""),
  309. EV_GTS_STL_EXCEPTION );
  310. }
  311. SetPos(savePos);
  312. }
  313. void CAPGTSHTIReader::Interpret()
  314. {
  315. long curr_index = 0;
  316. long lLastIndex= -1; // Used to detect a HTI file with incomplete clauses.
  317. while(true)
  318. {
  319. vector<CString> clause_arr;
  320. // tries to extract clause from m_arrInterpreted starting with curr_index
  321. // and remove it from m_arrInterpreted
  322. if (ExtractClause(m_arrInterpreted,
  323. &curr_index, // in - out
  324. clause_arr))
  325. {
  326. // Reset the infinite loop detection counter.
  327. lLastIndex= -1;
  328. // Now curr_index is pointing to next element
  329. // of m_arrInterpreted (after removed clause)
  330. // OR OUTSIDE boundary of m_arrInterpreted.
  331. if (InterpretClause(clause_arr))
  332. {
  333. vector<CString>::iterator i = m_arrInterpreted.begin();
  334. { // create iterator that points to m_arrInterpreted[curr_index]
  335. // or is m_arrInterpreted.end()
  336. long tmp_index = curr_index;
  337. while(tmp_index--)
  338. i++;
  339. }
  340. try
  341. {
  342. // insert interpreted clause there
  343. for (vector<CString>::iterator j = clause_arr.begin(); j < clause_arr.end(); j++)
  344. {
  345. i = m_arrInterpreted.insert(i, *j); // inserts before "i"
  346. i++;
  347. curr_index++;
  348. }
  349. }
  350. catch (exception& x)
  351. {
  352. CString str;
  353. // Note STL exception in event log.
  354. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  355. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  356. SrcLoc.GetSrcFileLineStr(),
  357. CCharConversion::ConvertACharToString(x.what(), str),
  358. _T(""),
  359. EV_GTS_STL_EXCEPTION );
  360. }
  361. }
  362. }
  363. else
  364. {
  365. // If this condition is true, then we are in an infinite loop due to a bad HTI file.
  366. if (lLastIndex == curr_index)
  367. {
  368. // Log that this HTI file does not parse correctly.
  369. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  370. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  371. SrcLoc.GetSrcFileLineStr(),
  372. GetPathName(), _T(""),
  373. EV_GTS_BAD_HTI_FILE );
  374. break;
  375. }
  376. // Update the infinite loop detection counter.
  377. lLastIndex= curr_index;
  378. if (curr_index) {
  379. // we finished current pass of m_arrInterpreted, start new one
  380. curr_index = 0;
  381. continue;
  382. }
  383. else {
  384. // we can not extract clause though we start from beginning -
  385. // m_arrInterpreted is interpreted now
  386. break;
  387. }
  388. }
  389. }
  390. }
  391. // modified V3.2 JSM
  392. void CAPGTSHTIReader::ParseInterpreted()
  393. {
  394. for (vector<CString>::iterator i = m_arrInterpreted.begin(); i < m_arrInterpreted.end(); i++)
  395. {
  396. CString command;
  397. if (GetCommand(*i, command))
  398. {
  399. if (command == COMMAND_DISPLAYSTR ||
  400. command == COMMAND_RESOURCESTR ||
  401. command == COMMAND_INFORMATION
  402. )
  403. {
  404. CString variable;
  405. if (GetVariable(*i, variable))
  406. {
  407. CString substitution;
  408. FragmentIDVector arr_fragment;
  409. ParseVariable(variable, arr_fragment);
  410. substitution = const_cast<CHTMLFragments*>(m_pFragments)->GetText(arr_fragment, (command == COMMAND_RESOURCESTR) ? CHTMLFragments::eResource : CHTMLFragments::eNotOfInterest );
  411. SubstituteCommandBlockWith(substitution, *i);
  412. }
  413. else // obvious misbehaviour - "display" command should have variable
  414. SubstituteCommandBlockWith(_T(""), *i);
  415. }
  416. else if (command == COMMAND_VALUE)
  417. {
  418. CString variable;
  419. if (GetVariable(*i, variable))
  420. const_cast<CHTMLFragments*>(m_pFragments)->SetValue(variable);
  421. SubstituteCommandBlockWith(_T(""), *i);
  422. }
  423. // V3.2 JSM
  424. else if (command == COMMAND_PROPERTY)
  425. {
  426. CString strProperty;
  427. if (GetVariable(*i,strProperty))
  428. {
  429. CString substitution;
  430. substitution = const_cast<CHTMLFragments*>(m_pFragments)->GetNetProp(strProperty);
  431. SubstituteCommandBlockWith(substitution, *i);
  432. }
  433. else // obvious misbehaviour - "property" command should have variable
  434. SubstituteCommandBlockWith(_T(""), *i);
  435. } // end V3.2 JSM
  436. else // obvious misbehaviour - no other commands
  437. SubstituteCommandBlockWith(_T(""), *i);
  438. }
  439. }
  440. }
  441. void CAPGTSHTIReader::SetOutputToInterpreted()
  442. {
  443. vector<CString>::iterator j = m_arrInterpreted.end();
  444. // Decrement to point to last element.
  445. j--;
  446. m_StreamOutput.str(_T(""));
  447. for (vector<CString>::iterator i = m_arrInterpreted.begin(); i < m_arrInterpreted.end(); i++)
  448. {
  449. m_StreamOutput << (LPCTSTR)*i;
  450. if (i != j) // not last element
  451. m_StreamOutput << _T('\r') << _T('\n');
  452. }
  453. m_StreamOutput << ends;
  454. }
  455. // INPUT: arr_text (with clause)
  456. // IMPUT: *pstart_index - index in arr_text
  457. // OUTPUT: arr_text without clause
  458. // OUTPUT: *pstart_index points to element in arr_text next to where
  459. // clause used to be or outside arr_text
  460. // OUTPUT: arr_clause - extracted clause
  461. bool CAPGTSHTIReader::ExtractClause(vector<CString>& arr_text,
  462. long* pstart_index,
  463. vector<CString>& arr_clause)
  464. {
  465. if (*pstart_index > arr_text.size() - 1) // quite possible
  466. return false;
  467. for (long i = *pstart_index; i < arr_text.size(); i++)
  468. {
  469. CString str_command;
  470. if (GetCommand(arr_text[i], str_command))
  471. {
  472. if (str_command == COMMAND_FORANYSTR)
  473. {
  474. if (ExtractClause(arr_text,
  475. &i,
  476. arr_clause,
  477. COMMAND_FORANYSTR,
  478. COMMAND_ENDFORSTR))
  479. {
  480. *pstart_index = i;
  481. return true;
  482. }
  483. else
  484. {
  485. *pstart_index = i;
  486. return false;
  487. }
  488. }
  489. if (str_command == COMMAND_IFSTR)
  490. {
  491. if (ExtractClause(arr_text,
  492. &i,
  493. arr_clause,
  494. COMMAND_IFSTR,
  495. COMMAND_ENDIFSTR))
  496. {
  497. *pstart_index = i;
  498. return true;
  499. }
  500. else
  501. {
  502. *pstart_index = i;
  503. return false;
  504. }
  505. }
  506. }
  507. }
  508. return false;
  509. }
  510. bool CAPGTSHTIReader::ExtractClause(vector<CString>& arr_text,
  511. long* pstart_index,
  512. vector<CString>& arr_clause,
  513. const CString& str_start_command,
  514. const CString& str_end_command)
  515. {
  516. CString str_command;
  517. long start = *pstart_index, end = *pstart_index;
  518. long nest_level_counter = 1;
  519. while (++end < arr_text.size())
  520. {
  521. if (GetCommand(arr_text[end], str_command))
  522. {
  523. if (str_command == str_start_command)
  524. {
  525. nest_level_counter++;
  526. }
  527. if (str_command == str_end_command)
  528. {
  529. nest_level_counter--;
  530. if (!nest_level_counter)
  531. {
  532. vector<CString>::iterator start_it = arr_text.begin();
  533. vector<CString>::iterator end_it = arr_text.begin();
  534. arr_clause.clear();
  535. try
  536. {
  537. // copy clause to arr_clause
  538. for (long j = start; j <= end; j++)
  539. arr_clause.push_back(arr_text[j]);
  540. }
  541. catch (exception& x)
  542. {
  543. CString str;
  544. // Note STL exception in event log.
  545. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  546. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  547. SrcLoc.GetSrcFileLineStr(),
  548. CCharConversion::ConvertACharToString(x.what(), str),
  549. _T(""),
  550. EV_GTS_STL_EXCEPTION );
  551. }
  552. // make iterators correspond indexes
  553. while(start--)
  554. start_it++;
  555. while(end--)
  556. end_it++;
  557. // and, because we want to delete element pointed
  558. // at this moment by end_it:
  559. end_it++;
  560. // remove clause from arr_text
  561. arr_text.erase(start_it, end_it);
  562. return true;
  563. }
  564. }
  565. }
  566. }
  567. *pstart_index = --end;;
  568. return false;
  569. }
  570. bool CAPGTSHTIReader::InterpretClause(vector<CString>& arr_clause)
  571. {
  572. CString str_command;
  573. if (arr_clause.size() &&
  574. GetCommand(arr_clause[0], str_command))
  575. {
  576. if (str_command == COMMAND_FORANYSTR)
  577. return InterpretForanyClause(arr_clause);
  578. if (str_command == COMMAND_IFSTR)
  579. return InterpretIfClause(arr_clause);
  580. return false;
  581. }
  582. return false;
  583. }
  584. bool CAPGTSHTIReader::InterpretForanyClause(vector<CString>& arr_clause)
  585. {
  586. long count = 0;
  587. CString strVariable; // variable from 1-st line of arr_clause
  588. vector<CString> arrUnfolded;
  589. FragmentIDVector arrVariable; // array from strVariable
  590. if (arr_clause.size() < 2) // "forany" and "endfor" commands
  591. return false;
  592. if (!GetVariable(arr_clause[0], strVariable))
  593. return false;
  594. ParseVariable(strVariable, arrVariable);
  595. count = m_pFragments->GetCount(arrVariable);
  596. try
  597. {
  598. for (long i = 0; i < count; i++)
  599. {
  600. for (long j = 1; j < arr_clause.size() - 1; j++)
  601. {
  602. CString command, variable;
  603. if (GetCommand(arr_clause[j], command) &&
  604. GetVariable(arr_clause[j], variable))
  605. {
  606. if (command == COMMAND_FORANYSTR && variable == strVariable)
  607. {
  608. // if it is clause "forany" with the same variable,
  609. // there should be neither prefixing nor postfixing
  610. }
  611. else
  612. {
  613. CString line = arr_clause[j];
  614. if (variable == strVariable)
  615. {
  616. PostfixVariable(i, variable);
  617. }
  618. else
  619. {
  620. FragmentIDVector parents, children;
  621. CString strVariable_postfixed = strVariable;
  622. PostfixVariable(i, strVariable_postfixed);
  623. ParseVariable(strVariable_postfixed, parents);
  624. ParseVariable(variable, children);
  625. if (m_pFragments->IsValidSeqOfVars(parents, children))
  626. PrefixVariable(strVariable_postfixed, variable);
  627. }
  628. CString command_block;
  629. ComposeCommandBlock(command, variable, command_block);
  630. SubstituteCommandBlockWith(command_block, line);
  631. arrUnfolded.push_back(line);
  632. continue;
  633. }
  634. }
  635. arrUnfolded.push_back(arr_clause[j]);
  636. }
  637. }
  638. }
  639. catch (exception& x)
  640. {
  641. CString str;
  642. // Note STL exception in event log.
  643. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  644. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  645. SrcLoc.GetSrcFileLineStr(),
  646. CCharConversion::ConvertACharToString(x.what(), str),
  647. _T(""),
  648. EV_GTS_STL_EXCEPTION );
  649. }
  650. arr_clause = arrUnfolded;
  651. return true;
  652. }
  653. bool CAPGTSHTIReader::InterpretIfClause(vector<CString>& arr_clause)
  654. {
  655. CString strVariable; // variable from a line of arr_clause
  656. FragmentIDVector arrVariable;
  657. if (arr_clause.size() < 2) // "if" and "endif" commands
  658. return false;
  659. if (!GetVariable( arr_clause[ 0 ], strVariable ))
  660. return false;
  661. ParseVariable( strVariable, arrVariable );
  662. // Scan for "if", "elseif", "else", and "endif" commands
  663. vector<int> arrElseIfIndices;
  664. int elseIndex = -1; // index of "else" inside arr_clause
  665. int i = 0;
  666. int nDepthOfNesting;
  667. for (i= 1, nDepthOfNesting= 0; i < arr_clause.size() - 1; i++)
  668. {
  669. CString command;
  670. if (GetCommand(arr_clause[i], command))
  671. {
  672. if (command == COMMAND_IFSTR)
  673. {
  674. nDepthOfNesting++;
  675. }
  676. else if (command == COMMAND_ENDIFSTR)
  677. {
  678. nDepthOfNesting--;
  679. }
  680. else if (command == COMMAND_ELSEIFSTR)
  681. {
  682. // V3.2 - Check if this elseif clause is at the level we are looking for.
  683. if (nDepthOfNesting == 0)
  684. arrElseIfIndices.push_back( i );
  685. }
  686. else if (command == COMMAND_ELSESTR)
  687. {
  688. // Check if this else clause is at the level we are looking for.
  689. if (nDepthOfNesting == 0)
  690. {
  691. elseIndex = i;
  692. break;
  693. }
  694. }
  695. }
  696. }
  697. vector<CString> arrBody; // intermediate array
  698. try
  699. {
  700. CString strName; // name of strVariable associated through CHTMLFragments
  701. strName = const_cast<CHTMLFragments*>(m_pFragments)->GetText(arrVariable);
  702. if (strName.GetLength())
  703. {
  704. // Standard processing of what is inside if ... else (or endif)
  705. int nEndOfClause= (arrElseIfIndices.size()) ? arrElseIfIndices[ 0 ] : elseIndex;
  706. for (i = 1; i < (nEndOfClause == -1 ? arr_clause.size() - 1 : nEndOfClause); i++)
  707. arrBody.push_back(arr_clause[i]);
  708. }
  709. else
  710. {
  711. // Process any elseif or else clauses.
  712. bool bDoneProcessing= false;
  713. for (int nElseIf= 0; nElseIf < arrElseIfIndices.size(); nElseIf++)
  714. {
  715. if (!GetVariable( arr_clause[ arrElseIfIndices[ nElseIf ] ], strVariable ))
  716. return false;
  717. ParseVariable( strVariable, arrVariable );
  718. strName = const_cast<CHTMLFragments*>(m_pFragments)->GetText(arrVariable);
  719. if (strName.GetLength())
  720. {
  721. // Determine the ending point of this elseif clause and extract all clauses within.
  722. int nEndOfClause= ((nElseIf + 1) < arrElseIfIndices.size())
  723. ? arrElseIfIndices[ nElseIf + 1 ] : elseIndex;
  724. for (i= arrElseIfIndices[ nElseIf ] + 1; i < nEndOfClause; i++)
  725. arrBody.push_back( arr_clause[ i ] );
  726. bDoneProcessing= true;
  727. break;
  728. }
  729. }
  730. if ((!bDoneProcessing) && (elseIndex != -1))
  731. {
  732. // All of the clauses failed, output all clauses following the "else".
  733. for (i = elseIndex + 1; i < arr_clause.size() - 1; i++)
  734. arrBody.push_back(arr_clause[i]);
  735. }
  736. }
  737. }
  738. catch (exception& x)
  739. {
  740. CString str;
  741. // Note STL exception in event log.
  742. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  743. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  744. SrcLoc.GetSrcFileLineStr(),
  745. CCharConversion::ConvertACharToString(x.what(), str),
  746. _T(""),
  747. EV_GTS_STL_EXCEPTION );
  748. }
  749. arr_clause = arrBody;
  750. return true;
  751. }
  752. bool CAPGTSHTIReader::GetCommand(const CString& line, CString& command)
  753. {
  754. CString control_block;
  755. CString variable;
  756. if (GetControlBlockFromLine(line, control_block))
  757. if (GetCommandVariableFromControlBlock(control_block, command, variable))
  758. return true;
  759. return false;
  760. }
  761. bool CAPGTSHTIReader::ComposeCommand(const CString& oper, const CString& variable, CString& command)
  762. {
  763. command = _T("");
  764. LPCTSTR ws = _T(" ");
  765. command += COMMAND_STARTSTR;
  766. command += ws;
  767. command += oper;
  768. if (variable.GetLength()) {
  769. command += ws;
  770. command += COMMAND_STARTVARSTR;
  771. command += variable;
  772. }
  773. command += COMMAND_ENDSTR;
  774. return true;
  775. }
  776. bool CAPGTSHTIReader::GetVariable(const CString& line, CString& arg_variable)
  777. {
  778. CString control_block;
  779. CString command, variable;
  780. if (GetControlBlockFromLine(line, control_block))
  781. if (GetCommandVariableFromControlBlock(control_block, command, variable))
  782. if (variable.GetLength()) {
  783. arg_variable = variable;
  784. return true;
  785. }
  786. return false;
  787. }
  788. void CAPGTSHTIReader::ParseVariable(const CString& variable, FragmentIDVector& out)
  789. {
  790. vector<CString> arrStr;
  791. int start_index = 0;
  792. int end_index = -1;
  793. try
  794. {
  795. // arrStr contains strings between delimiter "_"
  796. while(-1 != (end_index = CString((LPCTSTR)variable + start_index).Find(DELIMITER_PREFIX)))
  797. {
  798. // end_index here is from "(LPCTSTR)variable + start_index" string
  799. // so we can use it as length (2nd argument) in CString::Mid function
  800. arrStr.push_back(((CString&)variable).Mid(start_index, end_index));
  801. start_index = start_index + end_index + _tcslen(DELIMITER_PREFIX);
  802. }
  803. // pull the "tail" - after last (if any) "_"
  804. arrStr.push_back(((CString&)variable).Right(variable.GetLength() - start_index));
  805. out.clear();
  806. for (vector<CString>::iterator i = arrStr.begin(); i < arrStr.end(); i++)
  807. {
  808. FragmentID fragmentID;
  809. int curr = (*i).Find(DELIMITER_POSTFIX);
  810. if (-1 != curr)
  811. {
  812. fragmentID.VarName = (*i).Left(curr);
  813. curr += _tcslen(DELIMITER_POSTFIX); // skip delimiter
  814. CString strIndex = (LPCTSTR)(*i) + curr;
  815. strIndex.TrimLeft();
  816. strIndex.TrimRight();
  817. if (strIndex == _T("0"))
  818. fragmentID.Index = 0;
  819. else
  820. fragmentID.Index = _ttol((LPCTSTR)strIndex) == 0
  821. ? fragmentID.Index // error occur
  822. : _ttol((LPCTSTR)strIndex);
  823. }
  824. else
  825. fragmentID.VarName = *i;
  826. out.push_back(fragmentID);
  827. }
  828. }
  829. catch (exception& x)
  830. {
  831. CString str;
  832. // Note STL exception in event log.
  833. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  834. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  835. SrcLoc.GetSrcFileLineStr(),
  836. CCharConversion::ConvertACharToString(x.what(), str),
  837. _T(""),
  838. EV_GTS_STL_EXCEPTION );
  839. }
  840. }
  841. void CAPGTSHTIReader::ComposeVariable(const FragmentIDVector& arr_fragment, CString& variable)
  842. {
  843. variable = _T("");
  844. for (FragmentIDVector::const_iterator i = arr_fragment.begin(); i < arr_fragment.end(); i++)
  845. {
  846. if (i != arr_fragment.begin())
  847. variable += DELIMITER_PREFIX;
  848. variable += (*i).VarName;
  849. if ((*i).Index != -1)
  850. {
  851. TCHAR buf[128] = {0};
  852. variable += DELIMITER_POSTFIX;
  853. _stprintf(buf, _T("%d"), (*i).Index);
  854. variable += buf;
  855. }
  856. }
  857. }
  858. bool CAPGTSHTIReader::SubstituteCommandBlockWith(const CString& str_substitution, CString& line)
  859. {
  860. int start_index = -1;
  861. int end_index = -1;
  862. if (-1 != (start_index = line.Find(COMMAND_STARTSTR)))
  863. {
  864. if (-1 != (end_index = CString((LPCTSTR)line + start_index).Find(COMMAND_ENDSTR)))
  865. {
  866. CString tmp;
  867. end_index += start_index;
  868. end_index += _tcslen(COMMAND_ENDSTR); // skip closing bracket
  869. tmp += line.Left(start_index);
  870. tmp += str_substitution;
  871. tmp += line.Right(line.GetLength() - end_index);
  872. line = tmp;
  873. return true;
  874. }
  875. }
  876. return false;
  877. }
  878. void CAPGTSHTIReader::ComposeCommandBlock(const CString& command, const CString& variable, CString& command_block)
  879. {
  880. command_block = COMMAND_STARTSTR;
  881. command_block += _T(" ");
  882. command_block += command;
  883. command_block += _T(" ");
  884. command_block += COMMAND_STARTVARSTR;
  885. command_block += variable;
  886. command_block += _T(" ");
  887. command_block += COMMAND_ENDSTR;
  888. }
  889. void CAPGTSHTIReader::PostfixVariable(const long postfix, CString& variable)
  890. {
  891. TCHAR buf[128] = {0};
  892. _stprintf(buf, _T("%ld"), postfix);
  893. variable += DELIMITER_POSTFIX;
  894. variable += buf;
  895. }
  896. void CAPGTSHTIReader::PrefixVariable(const CString& prefix, CString& variable)
  897. {
  898. CString tmp = variable;
  899. variable = prefix;
  900. variable += DELIMITER_PREFIX;
  901. variable += tmp;
  902. }
  903. // JSM V3.2 --
  904. // called by GetCommandVariableFromControlBlock to handle
  905. // decoding the variable part of commands like <!GTS property "fooprop">
  906. // finds the first string argument in strText, which is either:
  907. // any text beginning w/ anything other than '"', ending w/ whitespace or COMMAND_ENDSTR
  908. // all text between doublequote marks "...." where an escape char ('\') escapes the character following.
  909. //
  910. CString CAPGTSHTIReader::GetStringArg(const CString & strText)
  911. {
  912. CString strArg = strText;
  913. // look for quoted text:
  914. int iStartQuote = strArg.Find(COMMAND_DOUBLEQUOTE);
  915. if (iStartQuote != -1)
  916. {
  917. strArg = strArg.Mid(iStartQuote);
  918. return GetEscapedText(strArg);
  919. }
  920. // o/w, assume that we're dealing w/ ordinary text, which ends
  921. // with first whitespace or with COMMAND_ENDSTR
  922. strArg.TrimLeft();
  923. int iWhiteSpace(0), iEndCmd(0);
  924. for(;(iWhiteSpace < strArg.GetLength()) && !(_istspace(strArg[iWhiteSpace])); iWhiteSpace++);
  925. iEndCmd = strArg.Find(COMMAND_ENDSTR);
  926. strArg = strArg.Left(min(iEndCmd,iWhiteSpace));
  927. return strArg;
  928. }
  929. // JSM V3.2
  930. // Called by GetEscapedText
  931. // recursive function which does the work of removing escapes (backslashes)
  932. // also checks for non-escaped endquote, which terminates the process
  933. CString CAPGTSHTIReader::RemoveEscapesFrom(const CString &strIn)
  934. {
  935. int iNextESC = strIn.Find(COMMAND_ESCAPECHAR);
  936. int iNextQuote = strIn.Find(COMMAND_DOUBLEQUOTE);
  937. // (iNextQuote == -1) means a bad input, because the string
  938. // we're looking at must terminate with quote.
  939. // By default, however, we'll keep running to end of strIn.
  940. if (iNextQuote == -1)
  941. iNextQuote = strIn.GetLength();
  942. // no more escape chars
  943. if (iNextESC == -1 || (iNextESC > iNextQuote))
  944. return strIn.Left(iNextQuote);
  945. CString strEscapedChar;
  946. strEscapedChar = strIn.GetAt(iNextESC + _tcslen(COMMAND_ESCAPECHAR));
  947. return strIn.Left(iNextESC) +
  948. strEscapedChar +
  949. RemoveEscapesFrom(strIn.Mid(iNextESC + _tcslen(COMMAND_ESCAPECHAR) + 1));
  950. }
  951. // Converts a double-quoted string using backslash as an escape character to a correct CString
  952. CString CAPGTSHTIReader::GetEscapedText(const CString &strText)
  953. {
  954. CString strEscaped;
  955. // remove leading quote and anything preceding:
  956. int iLeadQuote = strText.Find(COMMAND_DOUBLEQUOTE);
  957. if (iLeadQuote != -1)
  958. {
  959. strEscaped = RemoveEscapesFrom(strText.Mid(iLeadQuote + _tcslen(COMMAND_DOUBLEQUOTE)));
  960. }
  961. return strEscaped;
  962. }
  963. // JSM V3.2 added ability to read string arguments into variable
  964. // e.g. <!GTS property "FOO">
  965. //
  966. bool CAPGTSHTIReader::GetCommandVariableFromControlBlock(const CString& control_block, CString& command, CString& variable)
  967. {
  968. int start_command_index = -1;
  969. int end_command_index = -1;
  970. int start_variable_index = -1;
  971. int end_variable_index = -1;
  972. variable.Empty();
  973. command.Empty();
  974. start_command_index = control_block.Find(COMMAND_STARTSTR);
  975. if (start_command_index == -1) // invalid control block
  976. return false;
  977. start_command_index += _tcslen(COMMAND_STARTSTR); // skip prefix
  978. // extract the variable block, which can look like:
  979. // ... $variable_name ...
  980. // ... "parameter_name\\\"" ... (text in quotes w/ backslash escape)
  981. // parameter_name (plain text)
  982. if (-1 != ( end_command_index = (control_block.Mid(start_command_index)).Find(COMMAND_STARTVARSTR) ) )
  983. {
  984. // Variable prefixed with '$...'
  985. end_command_index += start_command_index; // make end_command_index relative to start of control block
  986. start_variable_index = end_command_index + _tcslen(COMMAND_STARTVARSTR); // skip "$"
  987. end_variable_index = control_block.Find(COMMAND_ENDSTR);
  988. // validation of indexes
  989. if (-1 == min(start_command_index, end_command_index) ||
  990. start_command_index > end_command_index)
  991. return false;
  992. command = ((CString&)control_block).Mid(start_command_index, end_command_index - start_command_index);
  993. command.TrimLeft();
  994. command.TrimRight();
  995. if (start_variable_index > end_variable_index)
  996. return false;
  997. if (-1 != start_variable_index)
  998. {
  999. // extract variable from "..$varname>"
  1000. variable = ((CString&)control_block).Mid(start_variable_index, end_variable_index - start_variable_index);
  1001. variable.TrimLeft();
  1002. variable.TrimRight();
  1003. }
  1004. }
  1005. else
  1006. {
  1007. // Not prefixed with $.
  1008. // we don't know whether we're looking for a "\"quoted\"" or
  1009. // non-quoted string, or no variable at all. Also, we need
  1010. // to handle special cases like:
  1011. // <!GTS parameter ">">
  1012. // <!GTS endfor >
  1013. // etc.
  1014. command = ((CString&)control_block).Mid(start_command_index);
  1015. command.TrimLeft();
  1016. command.TrimRight();
  1017. // step through looking for whitespace at end of command:
  1018. int iWhiteSpace;
  1019. for(iWhiteSpace = 0;
  1020. (iWhiteSpace < command.GetLength()) && !(_istspace(command[iWhiteSpace]));
  1021. iWhiteSpace++);
  1022. if (iWhiteSpace != command.GetLength())
  1023. {
  1024. // found whitespace; the rest of the string may be a variable:
  1025. variable = GetStringArg(command.Mid(iWhiteSpace));
  1026. command = command.Left(iWhiteSpace); // truncate command where appropriate
  1027. }
  1028. else
  1029. {
  1030. // If there wasn't a variable after the command, we
  1031. // may still need to truncate to remove the COMMAND_ENDSTR:
  1032. end_command_index = command.Find(COMMAND_ENDSTR);
  1033. if (end_command_index != -1)
  1034. command = command.Left(end_command_index);
  1035. }
  1036. }
  1037. return true;
  1038. }
  1039. bool CAPGTSHTIReader::GetControlBlockFromLine(const CString& line, CString& control_block)
  1040. {
  1041. int start_index = -1;
  1042. int end_index = -1;
  1043. if (-1 == (start_index = line.Find(COMMAND_STARTSTR)))
  1044. return false;
  1045. if (-1 == (end_index = CString((LPCTSTR)line + start_index).Find(COMMAND_ENDSTR)))
  1046. return false;
  1047. end_index += _tcslen(COMMAND_ENDSTR); // points beyond closing bracket
  1048. end_index += start_index; // points in "line" string
  1049. control_block = ((CString&)line).Mid(start_index, end_index - start_index);
  1050. control_block.TrimLeft();
  1051. control_block.TrimRight();
  1052. return true;
  1053. }
  1054. bool CAPGTSHTIReader::HasHistoryTable()
  1055. {
  1056. bool bRet;
  1057. LOCKOBJECT();
  1058. CString indicator = CString(COMMAND_STARTVARSTR) + VAR_RECOMMENDATIONS;
  1059. bRet= Find( indicator );
  1060. UNLOCKOBJECT();
  1061. return( bRet );
  1062. }
  1063. #ifdef __DEBUG_CUSTOM
  1064. #include <io.h>
  1065. #include <fcntl.h>
  1066. #include <sys\\stat.h>
  1067. bool CAPGTSHTIReader::FlushOutputStreamToFile(const CString& file_name)
  1068. {
  1069. int hf = 0;
  1070. hf = _open(
  1071. file_name,
  1072. _O_CREAT | _O_TRUNC | /*_O_TEMPORARY |*/
  1073. _O_BINARY | _O_RDWR | _O_SEQUENTIAL ,
  1074. _S_IREAD | _S_IWRITE
  1075. );
  1076. if (hf != -1)
  1077. {
  1078. //tstringstream m_StreamOutput
  1079. basic_string<TCHAR> str = m_StreamOutput.rdbuf()->str();
  1080. long size = str.size();
  1081. LPCTSTR buf = str.c_str();
  1082. int ret = _write(hf, buf, size);
  1083. _close(hf);
  1084. if (-1 != ret)
  1085. return true;
  1086. }
  1087. return false;
  1088. }
  1089. #endif
  1090. // V3.2 - Enhancement to support cookies.
  1091. // This function handles the substituting of "<!Cookie" clauses with the either
  1092. // values from cookies, "_CK" values passed in via Get/Post, or the default value.
  1093. void CAPGTSHTIReader::SubstituteCookieValues( CString& strText )
  1094. {
  1095. CString strNewText;
  1096. const CString kstr_CommaChar= _T(",");
  1097. const CString kstr_DoubleQuote= _T("\"");
  1098. // Loop until we have processed all cookie clauses.
  1099. int nNumericCompareStart= strText.Find( kstrCond_NumericCompare );
  1100. int nCookieClauseStart= strText.Find( COMMAND_COOKIE );
  1101. while (CString::FIND_FAILED != nCookieClauseStart)
  1102. {
  1103. CString strCookieClause;
  1104. CString strCookieName, strCookieAttr, strCookieValue;
  1105. int nCookieClauseEnd, nScratchMarker;
  1106. // Add any text preceding the cookie clause to the return string.
  1107. strNewText+= strText.Left( nCookieClauseStart );
  1108. // Remove all preceding text.
  1109. strText= strText.Mid( nCookieClauseStart + _tcslen( COMMAND_COOKIE ) );
  1110. // Look for the ending clause.
  1111. nCookieClauseEnd= strText.Find( COMMAND_ENDSTR );
  1112. if (CString::FIND_FAILED == nCookieClauseEnd)
  1113. {
  1114. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  1115. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  1116. SrcLoc.GetSrcFileLineStr(),
  1117. COMMAND_ENDSTR, _T(""),
  1118. EV_GTS_COOKIE_COMPONENT_NOT_FOUND );
  1119. break;
  1120. }
  1121. // Pull out the current cookie clause and reset the working string.
  1122. strCookieClause= strText.Left( nCookieClauseEnd );
  1123. strText= strText.Mid( nCookieClauseEnd + 1 );
  1124. // Extract the cookie name.
  1125. nScratchMarker= strCookieClause.Find( kstr_CommaChar );
  1126. if (CString::FIND_FAILED == nScratchMarker)
  1127. {
  1128. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  1129. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  1130. SrcLoc.GetSrcFileLineStr(),
  1131. kstr_CommaChar, _T(""),
  1132. EV_GTS_COOKIE_COMPONENT_NOT_FOUND );
  1133. break;
  1134. }
  1135. strCookieName= strCookieClause.Left( nScratchMarker );
  1136. strCookieName.TrimLeft();
  1137. strCookieName.TrimRight();
  1138. // Extract the cookie setting.
  1139. strCookieClause= strCookieClause.Mid( nScratchMarker + 1 );
  1140. nScratchMarker= strCookieClause.Find( kstr_CommaChar );
  1141. if (CString::FIND_FAILED == nScratchMarker)
  1142. {
  1143. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  1144. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  1145. SrcLoc.GetSrcFileLineStr(),
  1146. kstr_CommaChar, _T(""),
  1147. EV_GTS_COOKIE_COMPONENT_NOT_FOUND );
  1148. break;
  1149. }
  1150. strCookieAttr= strCookieClause.Left( nScratchMarker );
  1151. strCookieAttr.TrimLeft();
  1152. strCookieAttr.TrimRight();
  1153. strCookieClause= strCookieClause.Mid( nScratchMarker + sizeof( TCHAR ) );
  1154. // Attempt to locate the appropriate attribute/value pair,
  1155. // first checking the command line CK_ values, and
  1156. // then checking the cookies passed in the HTTP header.
  1157. bool bCookieNotFound= true;
  1158. if (!m_mapCookies.empty())
  1159. {
  1160. // Search the command line CK_ values.
  1161. map<CString,CString>::const_iterator iterMap= m_mapCookies.find( strCookieAttr );
  1162. if (iterMap != m_mapCookies.end())
  1163. {
  1164. strCookieValue= iterMap->second;
  1165. bCookieNotFound= false;
  1166. }
  1167. }
  1168. if (bCookieNotFound)
  1169. {
  1170. if (!m_strHTTPcookies.IsEmpty())
  1171. {
  1172. // Attempt to locate the attribute in the HTTP header information.
  1173. if (LocateCookieValue( strCookieName, strCookieAttr, strCookieValue ))
  1174. bCookieNotFound= false;
  1175. }
  1176. }
  1177. if (bCookieNotFound)
  1178. {
  1179. // Extract the default value for this attribute, which should be surrounded
  1180. // by double quotes.
  1181. nScratchMarker= strCookieClause.Find( kstr_DoubleQuote );
  1182. if (CString::FIND_FAILED == nScratchMarker)
  1183. {
  1184. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  1185. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  1186. SrcLoc.GetSrcFileLineStr(),
  1187. kstr_DoubleQuote, _T(""),
  1188. EV_GTS_COOKIE_COMPONENT_NOT_FOUND );
  1189. break;
  1190. }
  1191. strCookieClause= strCookieClause.Mid( nScratchMarker + sizeof( TCHAR ) );
  1192. nScratchMarker= strCookieClause.Find( kstr_DoubleQuote );
  1193. if (CString::FIND_FAILED == nScratchMarker)
  1194. {
  1195. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  1196. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  1197. SrcLoc.GetSrcFileLineStr(),
  1198. kstr_DoubleQuote, _T(""),
  1199. EV_GTS_COOKIE_COMPONENT_NOT_FOUND );
  1200. break;
  1201. }
  1202. strCookieValue= strCookieClause.Left( nScratchMarker );
  1203. }
  1204. // Add the attribute value to the output string.
  1205. // >>> $MAINT - The determination of whether or not to output quotes should
  1206. // be improved. I currently have no suggestions. RAB-19990918.
  1207. if ((nNumericCompareStart == CString::FIND_FAILED) || (nNumericCompareStart > nCookieClauseStart))
  1208. strNewText+= _T("\"");
  1209. strNewText+= strCookieValue;
  1210. if ((nNumericCompareStart == CString::FIND_FAILED) || (nNumericCompareStart > nCookieClauseStart))
  1211. strNewText+= _T("\"");
  1212. // Look for another cookie clause.
  1213. nNumericCompareStart= strText.Find( kstrCond_NumericCompare );
  1214. nCookieClauseStart= strText.Find( COMMAND_COOKIE );
  1215. }
  1216. // Append any remaining text onto the end of the string.
  1217. // If a cookie clause did not contain an ending marker it will be appended as well.
  1218. strNewText+= strText;
  1219. // Reassign the return string.
  1220. strText= strNewText;
  1221. return;
  1222. }
  1223. // V3.2 - Enhancement to support cookies.
  1224. // This function searches the HTTP cookies for a given cookie name and attribute. If
  1225. // found, this function returns a value of true and the located cookie value.
  1226. bool CAPGTSHTIReader::LocateCookieValue( const CString& strCookieName,
  1227. const CString& strCookieAttr,
  1228. CString& strCookieValue )
  1229. {
  1230. bool bCookieFound= false;
  1231. CString strTmpCookieName= strCookieName + _T("=");
  1232. int nScratch;
  1233. // URL encode the cookie name to handle underscores.
  1234. APGTS_nmspace::CookieEncodeURL( strTmpCookieName );
  1235. nScratch= m_strHTTPcookies.Find( strTmpCookieName );
  1236. if (CString::FIND_FAILED != nScratch)
  1237. {
  1238. // Verify that we have not matched on a partial string for the cookie name.
  1239. if ((nScratch == 0) ||
  1240. (m_strHTTPcookies[ nScratch - 1 ] == _T(' ')) ||
  1241. (m_strHTTPcookies[ nScratch - 1 ] == _T(';')))
  1242. {
  1243. // We have found the cookie that we are looking for, now look for the attribute name.
  1244. CString strTmpCookieAttr= strCookieAttr + _T("=");
  1245. // URL encode the cookie name to handle underscores.
  1246. APGTS_nmspace::CookieEncodeURL( strTmpCookieAttr );
  1247. // Jump past the starting point and the original cookie name length.
  1248. CString strScratch = m_strHTTPcookies.Mid( nScratch + strCookieName.GetLength() );
  1249. nScratch= strScratch.Find( _T(";") );
  1250. if (CString::FIND_FAILED != nScratch)
  1251. {
  1252. // Truncate the string at the end of this particular cookie..
  1253. if (nScratch > 0)
  1254. strScratch= strScratch.Left( nScratch );
  1255. }
  1256. nScratch= strScratch.Find( strTmpCookieAttr );
  1257. if (CString::FIND_FAILED != nScratch)
  1258. {
  1259. if (nScratch > 0)
  1260. {
  1261. // Verify that we have not matched on a partial string for the cookie attribute.
  1262. if ((strScratch[ nScratch - 1 ] == _T('=')) ||
  1263. (strScratch[ nScratch - 1 ] == _T('&')))
  1264. {
  1265. strCookieValue= strScratch.Mid( nScratch + strTmpCookieAttr.GetLength() );
  1266. // Look for and remove any delimiters.
  1267. nScratch= strCookieValue.Find( _T("&") );
  1268. if (CString::FIND_FAILED != nScratch)
  1269. {
  1270. // Truncate the string.
  1271. if (nScratch > 0)
  1272. strCookieValue= strCookieValue.Left( nScratch );
  1273. }
  1274. nScratch= strCookieValue.Find( _T(";") );
  1275. if (CString::FIND_FAILED != nScratch)
  1276. {
  1277. // Truncate the string.
  1278. if (nScratch > 0)
  1279. strCookieValue= strCookieValue.Left( nScratch );
  1280. }
  1281. // Decode the cookie value.
  1282. if (!strCookieValue.IsEmpty())
  1283. APGTS_nmspace::CookieDecodeURL( strCookieValue );
  1284. bCookieFound= true;
  1285. }
  1286. }
  1287. }
  1288. }
  1289. }
  1290. return( bCookieFound );
  1291. }