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.

830 lines
22 KiB

  1. //
  2. // MODULE: HTMLFrag.cpp
  3. //
  4. // PURPOSE: implementation of the CHTMLFragmentsTS class, which is how CInfer packages
  5. // up fragments of HTML to be rendered in accord with a template
  6. //
  7. // PROJECT: Generic Troubleshooter DLL for Microsoft AnswerPoint
  8. //
  9. // COMPANY: Saltmine Creative, Inc. (206)-284-7511 [email protected]
  10. //
  11. // AUTHOR: Joe Mabel
  12. //
  13. // ORIGINAL DATE: 8-27-1998
  14. //
  15. // NOTES:
  16. //
  17. // Version Date By Comments
  18. //--------------------------------------------------------------------
  19. // V3.0 7-20-98 JM Original
  20. //
  21. //////////////////////////////////////////////////////////////////////
  22. #pragma warning(disable:4786)
  23. #include "stdafx.h"
  24. #include <algorithm>
  25. #include "HTMLFrag.h"
  26. #include "event.h"
  27. #include "baseexception.h"
  28. #include "CharConv.h"
  29. #include "fileread.h"
  30. #ifdef LOCAL_TROUBLESHOOTER
  31. #include "CHMFileReader.h"
  32. #endif
  33. // V3.2 Additions.
  34. namespace
  35. {
  36. const CString kstrCond_StringCompare= _T("StringCompare");
  37. const CString kstrCond_OperatorGT= _T(".GT.");
  38. const CString kstrCond_OperatorGE= _T(".GE.");
  39. const CString kstrCond_OperatorEQ= _T(".EQ.");
  40. const CString kstrCond_OperatorNE= _T(".NE.");
  41. const CString kstrCond_OperatorLE= _T(".LE.");
  42. const CString kstrCond_OperatorLT= _T(".LT.");
  43. const CString kstrCond_OperatorSubstring= _T(".SubstringOf.");
  44. }
  45. //////////////////////////////////////////////////////////////////////
  46. // CHTMLValue implementation
  47. //////////////////////////////////////////////////////////////////////
  48. bool CHTMLValue::SetValue(const CString& value)
  49. {
  50. CString strOldValue = m_strValValue;
  51. m_strValValue = value;
  52. m_strValValue.TrimLeft();
  53. m_strValValue.TrimRight();
  54. if (IsValid())
  55. return true;
  56. m_strValValue = strOldValue;
  57. return false;
  58. }
  59. bool CHTMLValue::IsNumeric()
  60. {
  61. for (int i = 0; i < m_strValValue.GetLength(); i++)
  62. if(!_ismbcdigit(m_strValValue[i]))
  63. return false;
  64. return true;
  65. }
  66. bool CHTMLValue::IsString()
  67. {
  68. // string should be wrapped by quots
  69. if (m_strValValue.GetLength() >= 2 &&
  70. m_strValValue[0] == _T('"') &&
  71. m_strValValue[m_strValValue.GetLength()-1] == _T('"')
  72. )
  73. return true;
  74. return false;
  75. }
  76. bool CHTMLValue::IsBoolean()
  77. {
  78. return 0 == _tcsicmp(_T("true"), m_strValValue) ||
  79. 0 == _tcsicmp(_T("false"), m_strValValue);
  80. }
  81. bool CHTMLValue::GetNumeric(long& out)
  82. {
  83. if (IsNumeric())
  84. {
  85. out = _ttol(m_strValValue);
  86. return true;
  87. }
  88. return false;
  89. }
  90. bool CHTMLValue::GetString(CString& out)
  91. {
  92. if (IsString())
  93. {
  94. out = m_strValValue.Mid(1, m_strValValue.GetLength()-2);
  95. return true;
  96. }
  97. return false;
  98. }
  99. bool CHTMLValue::GetBoolean(bool& out)
  100. {
  101. if (IsBoolean())
  102. {
  103. out = (0 == _tcsicmp(_T("true"), m_strValValue)) ? true : false;
  104. return true;
  105. }
  106. return false;
  107. }
  108. bool CHTMLValue::operator == (const CHTMLValue& sib)
  109. {
  110. return 0 == _tcsicmp(m_strValName, sib.m_strValName); // case insensitive
  111. }
  112. //////////////////////////////////////////////////////////////////////
  113. // CHTMLFragments implementation
  114. //////////////////////////////////////////////////////////////////////
  115. bool CHTMLFragments::SetValue(const CString& str)
  116. {
  117. int index = str.Find(_T('='));
  118. if (index == -1)
  119. return false;
  120. CString name = str.Left(index);
  121. name.TrimLeft();
  122. name.TrimRight();
  123. CString value= str.Right(str.GetLength() - index - 1);
  124. value.TrimLeft();
  125. value.TrimRight();
  126. CHTMLValue HTMLValue(name, value);
  127. HTMLValueVector::iterator found = find(m_HTMLValueVector.begin(), m_HTMLValueVector.end(), HTMLValue);
  128. if (found != m_HTMLValueVector.end())
  129. *found = HTMLValue;
  130. else
  131. m_HTMLValueVector.push_back(HTMLValue);
  132. return true;
  133. }
  134. CHTMLValue* CHTMLFragments::GetValue(const CString& value_name)
  135. {
  136. HTMLValueVector::iterator found = find(m_HTMLValueVector.begin(), m_HTMLValueVector.end(), CHTMLValue(value_name));
  137. if (found != m_HTMLValueVector.end())
  138. return found;
  139. return NULL;
  140. }
  141. //////////////////////////////////////////////////////////////////////
  142. // CHTMLFragmentsTS implementation
  143. //////////////////////////////////////////////////////////////////////
  144. CHTMLFragmentsTS::CHTMLFragmentsTS( const CString & strScriptPath, bool bIncludesHistoryTable ) :
  145. m_bIncludesHistoryTable(bIncludesHistoryTable),
  146. m_bIncludesHiddenHistory(!bIncludesHistoryTable),
  147. m_bSuccess(false),
  148. m_strYes(_T("Yes")),
  149. m_strScriptPath(strScriptPath)
  150. {
  151. }
  152. CHTMLFragmentsTS::~CHTMLFragmentsTS()
  153. {
  154. }
  155. // Obviously, a very ad hoc implementation
  156. int CHTMLFragmentsTS::GetCount(const FragmentIDVector & fidvec) const
  157. {
  158. if (fidvec.empty())
  159. return 0;
  160. if (fidvec.back().Index != -1)
  161. return 0;
  162. const CString & strVariable = fidvec[0].VarName; // ref of convenience
  163. if (fidvec.size() == 1)
  164. {
  165. if (strVariable == VAR_PROBLEM_ASK)
  166. return 1;
  167. if (strVariable == VAR_RECOMMENDATIONS)
  168. return m_vstrVisitedNodes.size();
  169. if (strVariable == VAR_QUESTIONS)
  170. return 1;
  171. if (strVariable == VAR_SUCCESS)
  172. return m_bSuccess ? 1 : 0;
  173. if (strVariable == VAR_STARTFORM)
  174. return 1;
  175. return 0;
  176. }
  177. if (fidvec.size() == 2
  178. && strVariable == VAR_RECOMMENDATIONS
  179. && fidvec[0].Index >= 0
  180. && fidvec[0].Index < m_vvstrStatesOfVisitedNodes.size()
  181. && fidvec[1].VarName == VAR_STATES)
  182. {
  183. return m_vvstrStatesOfVisitedNodes[fidvec[0].Index].size();
  184. }
  185. return 0;
  186. }
  187. // this function was removed from const to achieve further flexibility:
  188. // we might need to take some active steps in it, as for informational
  189. // statement we might modify current node text. Oleg. 01.05.99
  190. CString CHTMLFragmentsTS::GetText( const FragmentIDVector & fidvec, const FragCommand fragCmd )
  191. {
  192. if (fidvec.empty())
  193. return m_strNil;
  194. const CString & strVariable0 = fidvec[0].VarName; // ref of convenience
  195. int i0 = fidvec[0].Index;
  196. if (fidvec.size() == 1)
  197. {
  198. if (strVariable0 == VAR_PROBLEM_ASK)
  199. return m_strProblem;
  200. if (strVariable0 == VAR_RECOMMENDATIONS
  201. && i0 >= 0
  202. && i0 < m_vstrVisitedNodes.size() )
  203. {
  204. return m_vstrVisitedNodes[i0];
  205. }
  206. if (strVariable0 == VAR_QUESTIONS)
  207. return m_strCurrentNode;
  208. if (strVariable0 == VAR_SUCCESS)
  209. return m_bSuccess ? m_strYes : m_strNil;
  210. if (strVariable0 == VAR_STARTFORM)
  211. return m_strStartForm;
  212. if (fragCmd == eResource)
  213. {
  214. // Load a server side include file.
  215. CString strScriptContent;
  216. CString strFullPath = m_strScriptPath + strVariable0;
  217. CFileReader fileReader( CPhysicalFileReader::makeReader( strFullPath ) );
  218. if (fileReader.Read())
  219. {
  220. fileReader.GetContent(strScriptContent);
  221. return strScriptContent;
  222. }
  223. }
  224. // Check for new conditionals added in V3.2.
  225. CString strTemp= strVariable0.Left( kstrCond_NumericCompare.GetLength() );
  226. if (strTemp == kstrCond_NumericCompare)
  227. {
  228. // Evaluate the numeric expression.
  229. if (NumericConditionEvaluatesToTrue( strVariable0.Mid( kstrCond_NumericCompare.GetLength() )))
  230. return( m_strYes );
  231. return( m_strNil );
  232. }
  233. strTemp= strVariable0.Left( kstrCond_StringCompare.GetLength() );
  234. if (strTemp == kstrCond_StringCompare)
  235. {
  236. // Evaluate the string expression.
  237. if (StringConditionEvaluatesToTrue( strVariable0.Mid( kstrCond_StringCompare.GetLength() )))
  238. return( m_strYes );
  239. return( m_strNil );
  240. }
  241. return m_strNil;
  242. }
  243. const CString & strVariable1 = fidvec[1].VarName; // ref of convenience
  244. int i1 = fidvec[1].Index;
  245. if (fidvec.size() == 2
  246. && strVariable0 == VAR_RECOMMENDATIONS
  247. && i0 >= 0
  248. && i0 < m_vvstrStatesOfVisitedNodes.size()
  249. && strVariable1 == VAR_STATES
  250. && i1 >= 0
  251. && i1 < m_vvstrStatesOfVisitedNodes[i0].size() )
  252. return (m_vvstrStatesOfVisitedNodes[i0][i1]);
  253. // V3.2
  254. // The specification for the v3.2 cookies called for permitting underscores
  255. // in cookie names. The HTI reader already used underscores to delimit
  256. // variables. The code below detects a comparision operation that has been
  257. // broken up due to the presence of underscores and reassembles it.
  258. // RAB-19991019.
  259. {
  260. // Check for new conditionals added in V3.2.
  261. int nOpType= 0;
  262. CString strTemp= strVariable0.Left( kstrCond_NumericCompare.GetLength() );
  263. if (strTemp == kstrCond_NumericCompare)
  264. nOpType= 1;
  265. else
  266. {
  267. strTemp= strVariable0.Left( kstrCond_StringCompare.GetLength() );
  268. if (strTemp == kstrCond_StringCompare)
  269. nOpType= 2;
  270. }
  271. if (nOpType)
  272. {
  273. // Reassemble the comparison operation.
  274. CString strCompareOp= fidvec[0].VarName;
  275. for (int nItem= 1; nItem < fidvec.size(); nItem++)
  276. {
  277. strCompareOp+= _T("_"); // Reinsert the delimiter that was removed during the parse.
  278. strCompareOp+= fidvec[ nItem ].VarName;
  279. }
  280. if (nOpType == 1)
  281. {
  282. // Evaluate the numeric expression.
  283. if (NumericConditionEvaluatesToTrue( strCompareOp.Mid( kstrCond_NumericCompare.GetLength() )))
  284. return( m_strYes );
  285. }
  286. else
  287. {
  288. // Evaluate the string expression.
  289. if (StringConditionEvaluatesToTrue( strCompareOp.Mid( kstrCond_StringCompare.GetLength() )))
  290. return( m_strYes );
  291. }
  292. return( m_strNil );
  293. }
  294. }
  295. return m_strNil;
  296. }
  297. bool CHTMLFragmentsTS::IsValidSeqOfVars(const FragmentIDVector & arrParents, const FragmentIDVector & arrChildren) const
  298. {
  299. // we allow only one level of nesting
  300. // that means in "forany" of $Recommendations we can have "forany" array of $States
  301. if (arrParents.size() == 1 && arrChildren.size() == 1)
  302. if (arrParents[0].VarName == VAR_RECOMMENDATIONS && arrChildren[0].VarName == VAR_STATES)
  303. return true;
  304. return false;
  305. }
  306. void CHTMLFragmentsTS::SetStartForm(const CString & str)
  307. {
  308. m_strStartForm = str;
  309. }
  310. void CHTMLFragmentsTS::SetProblemText(const CString & str)
  311. {
  312. if (m_bIncludesHistoryTable)
  313. m_strProblem = str;
  314. }
  315. void CHTMLFragmentsTS::SetCurrentNodeText(const CString & str)
  316. {
  317. m_strCurrentNodeSimple = str;
  318. RebuildCurrentNodeText();
  319. }
  320. void CHTMLFragmentsTS::SetHiddenHistoryText(const CString & str)
  321. {
  322. if (m_bIncludesHiddenHistory)
  323. {
  324. m_strHiddenHistory = str;
  325. RebuildCurrentNodeText();
  326. }
  327. }
  328. // need only be called for bSuccess == true (false is default) but written more generally.
  329. void CHTMLFragmentsTS::SetSuccessBool(bool bSuccess)
  330. {
  331. m_bSuccess = bSuccess;
  332. }
  333. CString CHTMLFragmentsTS::GetCurrentNodeText()
  334. {
  335. return m_strCurrentNodeSimple;
  336. }
  337. // must be called in order nodes were visited. Do not call for problem node.
  338. // return index of added node
  339. int CHTMLFragmentsTS::PushBackVisitedNodeText(const CString & str)
  340. {
  341. if (m_bIncludesHistoryTable)
  342. {
  343. try
  344. {
  345. m_vstrVisitedNodes.push_back(str);
  346. }
  347. catch (exception& x)
  348. {
  349. CString str;
  350. // Note STL exception in event log.
  351. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  352. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  353. SrcLoc.GetSrcFileLineStr(),
  354. CCharConversion::ConvertACharToString(x.what(), str),
  355. _T(""),
  356. EV_GTS_STL_EXCEPTION );
  357. }
  358. return m_vstrVisitedNodes.size() - 1;
  359. }
  360. return -1;
  361. }
  362. // For each given iVisitedNode, must be called in order of state number,
  363. // with ST_UNKNOWN last
  364. // return index of added state
  365. int CHTMLFragmentsTS::PushBackStateText(UINT iVisitedNode, const CString & str)
  366. {
  367. if (m_bIncludesHistoryTable)
  368. {
  369. try
  370. {
  371. // Check if we need to add one or more elements to the vector of nodes.
  372. if (m_vvstrStatesOfVisitedNodes.size() <= iVisitedNode)
  373. {
  374. // Check if we need to add more than one element to the vector of nodes.
  375. if (m_vvstrStatesOfVisitedNodes.size() < iVisitedNode)
  376. {
  377. // We need to add more than one element to the vector of nodes.
  378. // This condition should not be occurring, so log it.
  379. CString tmpStrCurCnt, tmpStrReqCnt;
  380. tmpStrCurCnt.Format( _T("%d"), m_vvstrStatesOfVisitedNodes.size() );
  381. tmpStrReqCnt.Format( _T("%d"), iVisitedNode );
  382. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  383. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  384. SrcLoc.GetSrcFileLineStr(),
  385. tmpStrCurCnt, tmpStrReqCnt,
  386. EV_GTS_NODE_COUNT_DISCREPANCY );
  387. // Add to the vector of nodes until we have placed a total of
  388. // iVisitedNode elements into the vector. We are inserting empty
  389. // states as the first element of the vector of states for a node.
  390. vector<CString> vecDummy;
  391. vecDummy.push_back( _T("") );
  392. do
  393. {
  394. m_vvstrStatesOfVisitedNodes.push_back( vecDummy );
  395. }
  396. while (m_vvstrStatesOfVisitedNodes.size() < iVisitedNode);
  397. }
  398. // Add this state string as the first element of the vector of states for a node.
  399. vector<CString> tmpVector;
  400. tmpVector.push_back( str );
  401. m_vvstrStatesOfVisitedNodes.push_back( tmpVector );
  402. }
  403. else
  404. {
  405. // Add this state string to the vector of states for a node.
  406. m_vvstrStatesOfVisitedNodes[iVisitedNode].push_back(str);
  407. }
  408. }
  409. catch (exception& x)
  410. {
  411. CString str;
  412. // Note STL exception in event log.
  413. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  414. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  415. SrcLoc.GetSrcFileLineStr(),
  416. CCharConversion::ConvertACharToString(x.what(), str),
  417. _T(""),
  418. EV_GTS_STL_EXCEPTION );
  419. }
  420. return m_vvstrStatesOfVisitedNodes[iVisitedNode].size() - 1;
  421. }
  422. return -1;
  423. }
  424. // call this function to find out if there is any need for a history table.
  425. // If not, calling class can save the effort of constructing one:
  426. // SetProblemText(), AppendVisitedNodeText(), AppendStateText()
  427. // becomes no-ops, so no need to construct strings and call them
  428. bool CHTMLFragmentsTS::IncludesHistoryTable() const
  429. {
  430. return m_bIncludesHistoryTable;
  431. }
  432. // call this function to find out if there is any need for "hidden history"
  433. // If not, calling class can save the effort of constructing one:
  434. // SetHiddenHistoryText() becomes a no-op, so no need to construct a string and call it
  435. bool CHTMLFragmentsTS::IncludesHiddenHistory() const
  436. {
  437. return m_bIncludesHiddenHistory;
  438. }
  439. void CHTMLFragmentsTS::RebuildCurrentNodeText()
  440. {
  441. m_strCurrentNode = m_strHiddenHistory;
  442. m_strCurrentNode += m_strCurrentNodeSimple;
  443. }
  444. // Function which parses and evaluates a numeric condition.
  445. bool CHTMLFragmentsTS::NumericConditionEvaluatesToTrue( const CString & str )
  446. {
  447. bool bRetVal= false;
  448. CString strScratch= RemoveOuterParenthesis( str );
  449. if (strScratch.GetLength())
  450. {
  451. long lLeftOperand, lRightOperand;
  452. // Check for all supported operators.
  453. if (RetNumericOperands( strScratch, kstrCond_OperatorGT, lLeftOperand, lRightOperand ))
  454. {
  455. // .GT. case.
  456. bRetVal= (lLeftOperand > lRightOperand) ? true : false;
  457. }
  458. else if (RetNumericOperands( strScratch, kstrCond_OperatorGE, lLeftOperand, lRightOperand ))
  459. {
  460. // .GE. case.
  461. bRetVal= (lLeftOperand >= lRightOperand) ? true : false;
  462. }
  463. else if (RetNumericOperands( strScratch, kstrCond_OperatorEQ, lLeftOperand, lRightOperand ))
  464. {
  465. // .EQ. case.
  466. bRetVal= (lLeftOperand == lRightOperand) ? true : false;
  467. }
  468. else if (RetNumericOperands( strScratch, kstrCond_OperatorNE, lLeftOperand, lRightOperand ))
  469. {
  470. // .NE. case.
  471. bRetVal= (lLeftOperand != lRightOperand) ? true : false;
  472. }
  473. else if (RetNumericOperands( strScratch, kstrCond_OperatorLE, lLeftOperand, lRightOperand ))
  474. {
  475. // .LE. case.
  476. bRetVal= (lLeftOperand <= lRightOperand) ? true : false;
  477. }
  478. else if (RetNumericOperands( strScratch, kstrCond_OperatorLT, lLeftOperand, lRightOperand ))
  479. {
  480. // .LT. case.
  481. bRetVal= (lLeftOperand < lRightOperand) ? true : false;
  482. }
  483. }
  484. return( bRetVal );
  485. }
  486. // Function which parses and evaluates a string condition.
  487. bool CHTMLFragmentsTS::StringConditionEvaluatesToTrue( const CString & str )
  488. {
  489. bool bRetVal= false;
  490. CString strScratch= RemoveOuterParenthesis( str );
  491. if (strScratch.GetLength())
  492. {
  493. CString strLeftOperand, strRightOperand;
  494. // Check for all supported operators.
  495. if (RetStringOperands( strScratch, kstrCond_OperatorEQ, strLeftOperand, strRightOperand ))
  496. {
  497. if ((strLeftOperand.GetLength() == strRightOperand.GetLength()) &&
  498. (_tcsicmp( strLeftOperand, strRightOperand ) == 0))
  499. bRetVal= true;
  500. }
  501. else if (RetStringOperands( strScratch, kstrCond_OperatorNE, strLeftOperand, strRightOperand ))
  502. {
  503. if ((strLeftOperand.GetLength() != strRightOperand.GetLength()) ||
  504. (_tcsicmp( strLeftOperand, strRightOperand ) != 0))
  505. bRetVal= true;
  506. }
  507. else if (RetStringOperands( strScratch, kstrCond_OperatorSubstring, strLeftOperand, strRightOperand ))
  508. {
  509. int nLeftLen= strLeftOperand.GetLength();
  510. int nRightLen= strRightOperand.GetLength();
  511. if ((nLeftLen) && (nRightLen) && (nLeftLen <= nRightLen))
  512. {
  513. strLeftOperand.MakeLower();
  514. strRightOperand.MakeLower();
  515. if (_tcsstr( strRightOperand, strLeftOperand ) != NULL)
  516. bRetVal= true;
  517. }
  518. }
  519. }
  520. return( bRetVal );
  521. }
  522. // Function to peel off the outer parenthesis of a condition.
  523. CString CHTMLFragmentsTS::RemoveOuterParenthesis( const CString & str )
  524. {
  525. CString strRet;
  526. int nOrigLength= str.GetLength();
  527. if (nOrigLength > 2)
  528. {
  529. TCHAR cFirstChar= str.GetAt( 0 );
  530. TCHAR cLastChar= str.GetAt( nOrigLength - 1 );
  531. if ((cFirstChar == _T('(')) && (cLastChar == _T(')')))
  532. strRet= str.Mid( 1, nOrigLength - 2 );
  533. }
  534. return( strRet );
  535. }
  536. // Breaks out the numeric operands from a string.
  537. bool CHTMLFragmentsTS::RetNumericOperands( const CString & str, const CString & strOperator,
  538. long &lLeftOperand, long &lRightOperand )
  539. {
  540. bool bRetVal= false;
  541. int nOffset= str.Find( strOperator );
  542. if (nOffset != -1)
  543. {
  544. CString strScratch= str.Left( nOffset - 1 );
  545. strScratch.TrimRight();
  546. strScratch.TrimLeft();
  547. if (strScratch.GetLength())
  548. {
  549. lLeftOperand= atol( strScratch );
  550. strScratch= str.Mid( nOffset + strOperator.GetLength() );
  551. strScratch.TrimRight();
  552. strScratch.TrimLeft();
  553. if (strScratch.GetLength())
  554. {
  555. lRightOperand= atol( strScratch );
  556. bRetVal= true;
  557. }
  558. }
  559. }
  560. return( bRetVal );
  561. }
  562. // Breaks out the string operands from a string.
  563. bool CHTMLFragmentsTS::RetStringOperands( const CString & str, const CString & strOperator,
  564. CString & strLeftOperand, CString & strRightOperand )
  565. {
  566. bool bRetVal= false;
  567. int nOffset= str.Find( strOperator );
  568. if (nOffset != -1)
  569. {
  570. strLeftOperand= str.Left( nOffset - 1 );
  571. if (CleanStringOperand( strLeftOperand ))
  572. {
  573. strRightOperand= str.Mid( nOffset + strOperator.GetLength() );
  574. strRightOperand.TrimRight();
  575. strRightOperand.TrimLeft();
  576. if (CleanStringOperand( strRightOperand ))
  577. bRetVal= true;
  578. }
  579. }
  580. return( bRetVal );
  581. }
  582. // Trims an operand string and replaces embedded characters.
  583. int CHTMLFragmentsTS::CleanStringOperand( CString& strOperand )
  584. {
  585. int nRetLength= 0;
  586. if (!strOperand.IsEmpty())
  587. {
  588. strOperand.TrimRight();
  589. strOperand.TrimLeft();
  590. nRetLength= strOperand.GetLength();
  591. if (nRetLength > 2)
  592. {
  593. if ((strOperand[ 0 ] == _T('\"')) && (strOperand[ nRetLength - 1 ] == _T('\"')))
  594. {
  595. // V3.2 Remove the surrounding double quotes.
  596. nRetLength-= 2;
  597. strOperand= strOperand.Mid( 1, nRetLength );
  598. }
  599. // V3.2 Replace embedded quotes or backslashes within the string.
  600. for (int nOp= 0; nOp < 2; nOp++)
  601. {
  602. // Set the search and replacement strings.
  603. CString strSearch, strReplace;
  604. if (nOp)
  605. {
  606. // Replace backslashes.
  607. strSearch= _T("\\\\");
  608. strReplace= _T("\\");
  609. }
  610. else
  611. {
  612. // Replace double quotes.
  613. strSearch= _T("\\\"");
  614. strReplace= _T("\"");
  615. }
  616. // Search and replace.
  617. int nStart= 0, nEnd;
  618. while (CString::FIND_FAILED != (nStart= strOperand.Find( strSearch, nStart )))
  619. {
  620. nEnd= nStart + strSearch.GetLength();
  621. strOperand= strOperand.Left( nStart ) + strReplace + strOperand.Mid( nEnd );
  622. nStart+= strReplace.GetLength(); // Move search past the character that was just replaced.
  623. }
  624. }
  625. }
  626. }
  627. return( nRetLength );
  628. }
  629. // JSM V3.2
  630. // called by HTIReader in parsing stage to convert network property name, given
  631. // in <$GTS property "propname">, to network property (value).
  632. //
  633. CString CHTMLFragmentsTS::GetNetProp(const CString & strNetPropName)
  634. {
  635. map<CString,CString>::iterator it = m_mapstrNetProps.find(strNetPropName);
  636. if (it == m_mapstrNetProps.end())
  637. return _T("\0"); // not found
  638. else
  639. return (*it).second;
  640. }
  641. // JSM V3.2
  642. // add a name to the internal list (map) of Net props which are needed
  643. // by this Fragments object
  644. //
  645. // CAPGTSHTIReader finds the names of the network properties and passes
  646. // them in via AddNetPropName, but it doesn't know how to get the values.
  647. // CInfer will later get the network property names from Fragments object, call the BNTS
  648. // to find out the network property values, and supply the values to Fragments
  649. //
  650. //
  651. void CHTMLFragmentsTS::AddNetPropName(const CString & strNetPropName)
  652. {
  653. // don't insert a NULL key!!!
  654. if (!strNetPropName.IsEmpty())
  655. m_mapstrNetProps[strNetPropName];
  656. }
  657. // JSM V3.2
  658. // SetNetProp()
  659. //
  660. // For a Network Property Name in our internal map, set the
  661. // corresponding network property (ie, fill in the map value
  662. // for that key.) Called by CInfer, which is the object that knows how
  663. // to talk to the BNTS.
  664. //
  665. // returns TRUE if success
  666. // FALSE if we've given a NetPropName which is not in the internal map
  667. //
  668. BOOL CHTMLFragmentsTS::SetNetProp(CString strNetPropName, CString strNetProp)
  669. {
  670. map<CString,CString>::iterator it;
  671. if ((it= m_mapstrNetProps.find(strNetPropName)) == m_mapstrNetProps.end())
  672. return false;
  673. m_mapstrNetProps[strNetPropName] = strNetProp;
  674. return true;
  675. }
  676. // JSM V3.2
  677. // IterateNetProp()
  678. // Called to iterate through the network properties in our internal
  679. // map during the setting process (see above.)
  680. //
  681. // Sets strNameIterator to the name of the next net prop in the map.
  682. //
  683. // calling w/ an empty (NULL) key starts the iteration.
  684. // calling w/ a name that's not in the map returns false.
  685. // calling w/ any other name returns true, unless at end of iteration
  686. //
  687. // strNameIterator is not valid if this function returns false.
  688. //
  689. BOOL CHTMLFragmentsTS::IterateNetProp(CString & strNameIterator)
  690. {
  691. map<CString,CString>::iterator it;
  692. if (strNameIterator.IsEmpty())
  693. {
  694. // request to start iteration, if possible
  695. if (m_mapstrNetProps.empty())
  696. return false; // we're at end already
  697. it = m_mapstrNetProps.begin();
  698. }
  699. else if ((it= m_mapstrNetProps.find(strNameIterator)) != m_mapstrNetProps.end())
  700. {
  701. // iterate:
  702. if (++it == m_mapstrNetProps.end())
  703. return false; // arrived at end
  704. }
  705. else
  706. {
  707. // invalid key
  708. return false;
  709. }
  710. strNameIterator = (*it).first;
  711. return true;
  712. }
  713. // V3.2 enhancement for the Start Over button.
  714. void CHTMLFragmentsTS::SetStartOverLink( const CString & str )
  715. {
  716. m_strStartOverLink = str;
  717. }
  718. // V3.2 enhancement for the Start Over button.
  719. CString CHTMLFragmentsTS::GetStartOverLink()
  720. {
  721. return m_strStartOverLink;
  722. }