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.

711 lines
18 KiB

  1. //
  2. // MODULE: APGTSBESREAD.CPP
  3. //
  4. // PURPOSE: 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-12-98
  11. //
  12. // NOTES:
  13. // 1. URLEncodeString() and DecodeInputString() come with only minor changes from Roman's
  14. // old approach to BES.
  15. //
  16. // 2. Typical BES file content might be:
  17. // <FORM METHOD=POST ACTION="/scripts/samples/search/query.idq">
  18. // <INPUT TYPE=HIDDEN NAME="CiMaxRecordsPerPage" VALUE="10">
  19. // <INPUT TYPE=HIDDEN NAME="CiScope" VALUE="/">
  20. // <INPUT TYPE=HIDDEN NAME="TemplateName" VALUE="query">
  21. // <INPUT TYPE=HIDDEN NAME="HTMLQueryForm" VALUE="/samples/search/query.htm">
  22. // Enter items to search for
  23. // <INPUT TYPE=TEXT NAME="CiRestriction" VALUE="print OR &quot;network print&quot;">
  24. // <INPUT TYPE=SUBMIT VALUE="Search">
  25. // </FORM>
  26. //
  27. // There are some tight restrictions because of a rather naive parse:
  28. // FORM, ACTION, TYPE, NAME, VALUE must be capitalized
  29. // No white space allowed in any of
  30. // <FORM
  31. // ACTION="
  32. // <INPUT
  33. // TYPE=
  34. // TYPE=TEXT
  35. // NAME=
  36. // VALUE=
  37. // "> (value for TYPE=TEXT)
  38. // At least one character (typically CR) is mandatory between each use of <INPUT ...>
  39. // Each <INPUT ...> must include attribute TYPE=
  40. // For each <INPUT ...> NAME=, VALUE= are optional, but if present attributes must be
  41. // in order TYPE=, NAME=, VALUE=
  42. // There should be exactly one TYPE=TEXT input, and it should come after all the
  43. // HIDDENs and before the SUBMIT.
  44. //
  45. // 3. Back End Search (BES) is used only for the service node or for the fail node.
  46. // The fail node is the unique, implicit node in a belief network which we reach when
  47. // there are no more recommendations and no explicit skips. The service node is the
  48. // unique, implicit node which we reach when there are no more recommendations and at least
  49. // one explicit skip.
  50. // The service node and fail node are not explicitly implemented as nodes. Instead,
  51. // they are implicitly constructed from either support text or the content of the BES file.
  52. // (The latter supersedes the former.)
  53. //
  54. // 4. We call BuildURLEncodedForm() more often than is absolutely necessary. It really
  55. // could be called only "on demand" in GetURLEncodedForm(). Since this is all in-memory
  56. // stuff, it's pretty cheap to make the extra calls, and it should make debugging easier.
  57. //
  58. // Version Date By Comments
  59. //--------------------------------------------------------------------
  60. // V3.0 08-04-98 OK
  61. // V3.0 08-31-98 JM support both returning a raw & an URL encoded form
  62. //
  63. #include "stdafx.h"
  64. #include "apgtsbesread.h"
  65. #include "CharConv.h"
  66. #include <algorithm>
  67. #include "event.h"
  68. ////////////////////////////////////////////////////////////////////////////////////
  69. // CAPGTSBESReaderException
  70. ////////////////////////////////////////////////////////////////////////////////////
  71. CAPGTSBESReaderException::CAPGTSBESReaderException(
  72. CFileReader* reader,
  73. eAPGTSBESErr err,
  74. LPCSTR source_file,
  75. int line)
  76. : CFileReaderException(reader, eErrParse, source_file, line),
  77. m_eAPGTSBESErr(err)
  78. {
  79. }
  80. ////////////////////////////////////////////////////////////////////////////////////
  81. // CBESPair
  82. ////////////////////////////////////////////////////////////////////////////////////
  83. // concatenate strings to produce new BESStr. Place " AND " between each
  84. // pair of strings.
  85. // If resulting string is to be URL-encoded, then, on input, content of strings in vector
  86. // must each be URL-encoded. In practice, we don't URL-encode this, we URL-encode the
  87. // output of GetBESStr() instead.
  88. CBESPair& CBESPair::operator << (const vector<CString>& in)
  89. {
  90. BESStr = _T(""); // clear
  91. for (vector<CString>::const_iterator i = in.begin(); i < in.end(); i++)
  92. {
  93. vector<CString>::iterator current = (vector<CString>::iterator)i;
  94. BESStr += _T("(");
  95. BESStr += *i;
  96. BESStr += _T(")");
  97. if (++current != in.end())
  98. BESStr += _T(" AND ");
  99. }
  100. return *this;
  101. }
  102. ////////////////////////////////////////////////////////////////////////////////////
  103. // CAPGTSBESReader
  104. ////////////////////////////////////////////////////////////////////////////////////
  105. /*static*/ LPCTSTR CAPGTSBESReader::FORM = _T("FORM");
  106. /*static*/ LPCTSTR CAPGTSBESReader::METHOD = _T("METHOD");
  107. /*static*/ LPCTSTR CAPGTSBESReader::ACTION = _T("ACTION");
  108. /*static*/ LPCTSTR CAPGTSBESReader::INPUT = _T("INPUT");
  109. /*static*/ LPCTSTR CAPGTSBESReader::TYPE = _T("TYPE");
  110. /*static*/ LPCTSTR CAPGTSBESReader::NAME = _T("NAME");
  111. /*static*/ LPCTSTR CAPGTSBESReader::VALUE = _T("VALUE");
  112. /*static*/ LPCTSTR CAPGTSBESReader::HIDDEN = _T("HIDDEN");
  113. /*static*/ LPCTSTR CAPGTSBESReader::TEXT = _T("TEXT");
  114. CAPGTSBESReader::CAPGTSBESReader(CPhysicalFileReader * pPhysicalFileReader, LPCTSTR szDefaultContents /* = NULL */)
  115. : CTextFileReader(pPhysicalFileReader, szDefaultContents)
  116. {
  117. }
  118. CAPGTSBESReader::~CAPGTSBESReader()
  119. {
  120. }
  121. void CAPGTSBESReader::GenerateBES(
  122. const vector<CString> & arrstrIn,
  123. CString & strEncoded,
  124. CString & strRaw)
  125. {
  126. LOCKOBJECT();
  127. ClearSearchString();
  128. for (vector<CString>::const_iterator i = arrstrIn.begin(); i < arrstrIn.end(); i++)
  129. operator << (*i);
  130. GetURLEncodedForm(strEncoded);
  131. GetRawForm(strRaw);
  132. UNLOCKOBJECT();
  133. }
  134. // string "in" will be ANDed onto the list of strings to search.
  135. CAPGTSBESReader& CAPGTSBESReader::operator << (const CString& in)
  136. {
  137. LOCKOBJECT();
  138. try
  139. {
  140. m_arrBESStr.push_back( in );
  141. m_SearchText << m_arrBESStr;
  142. BuildURLEncodedForm();
  143. }
  144. catch (exception& x)
  145. {
  146. CString str;
  147. // Note STL exception in event log.
  148. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  149. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  150. SrcLoc.GetSrcFileLineStr(),
  151. CCharConversion::ConvertACharToString(x.what(), str),
  152. _T(""),
  153. EV_GTS_STL_EXCEPTION );
  154. }
  155. UNLOCKOBJECT();
  156. return *this;
  157. }
  158. // string "in" will be removed from the list of strings to search.
  159. // This is provided for class completeness, not for any current need. (JM 8/98)
  160. CAPGTSBESReader& CAPGTSBESReader::operator >> (const CString& in)
  161. {
  162. LOCKOBJECT();
  163. vector<CString>::iterator i = find( m_arrBESStr.begin(), m_arrBESStr.end(), in );
  164. if (i != m_arrBESStr.end())
  165. {
  166. m_arrBESStr.erase(i);
  167. m_SearchText << m_arrBESStr;
  168. BuildURLEncodedForm();
  169. }
  170. UNLOCKOBJECT();
  171. return *this;
  172. }
  173. // Typically, you will want to call this to clear the search string before you start
  174. // appending new strings to it.
  175. CAPGTSBESReader& CAPGTSBESReader::ClearSearchString()
  176. {
  177. LOCKOBJECT();
  178. m_arrBESStr.clear();
  179. m_SearchText << m_arrBESStr;
  180. BuildURLEncodedForm();
  181. UNLOCKOBJECT();
  182. return *this;
  183. }
  184. void CAPGTSBESReader::GetURLEncodedForm(CString& out)
  185. {
  186. LOCKOBJECT();
  187. out = m_strURLEncodedForm;
  188. UNLOCKOBJECT();
  189. }
  190. void CAPGTSBESReader::GetRawForm(CString& str)
  191. {
  192. vector<CString>::iterator i = NULL;
  193. LOCKOBJECT();
  194. str.Empty();
  195. vector<CString>::iterator itBES = m_arrRawForm.begin() + m_iBES;
  196. for (i = m_arrRawForm.begin(); i < itBES; i++)
  197. {
  198. if ((i + 1) < itBES)
  199. str += *i;
  200. else
  201. {
  202. // Remove the default BES VALUE off the raw string.
  203. TCHAR *valuestr = _T("VALUE=\"");
  204. int nFoundLoc;
  205. nFoundLoc= (*i).Find( valuestr );
  206. if (nFoundLoc == -1)
  207. str += *i;
  208. else
  209. str += (*i).Left( nFoundLoc + _tcslen( valuestr ) );
  210. }
  211. }
  212. str += m_SearchText.GetBESStr();
  213. for (i = itBES; i < m_arrRawForm.end(); i++)
  214. str += *i;
  215. UNLOCKOBJECT();
  216. }
  217. void CAPGTSBESReader::Parse()
  218. {
  219. CString str, tmp, strSav;
  220. long save_pos = 0;
  221. LOCKOBJECT();
  222. save_pos = GetPos();
  223. SetPos(0);
  224. m_iBES = 0;
  225. vector<CString>::iterator itBES = NULL;
  226. try
  227. {
  228. // pump file content into array of lines
  229. m_arrRawForm.clear();
  230. while (GetLine(str))
  231. {
  232. m_arrRawForm.push_back(str);
  233. }
  234. m_arrURLEncodedForm.clear();
  235. // parse string-by-string
  236. for (vector<CString>::iterator i = m_arrRawForm.begin(); i < m_arrRawForm.end(); i++)
  237. {
  238. if (IsMethodString(*i))
  239. {
  240. if (ParseMethodString(*i, tmp))
  241. {
  242. m_arrURLEncodedForm.push_back(tmp);
  243. continue;
  244. }
  245. }
  246. else if (IsBESString(*i))
  247. {
  248. if (ParseBESString(*i, m_SearchText)) // modifies m_SearchText.Name
  249. {
  250. // do not include BES string into m_arrURLEncodedForm,
  251. // include it in m_SearchText instead (although typically, we
  252. // will throw it away unused).
  253. m_SearchText << m_arrBESStr;
  254. itBES = i+1;
  255. int loc = i->Find(_T("\">"));
  256. strSav = i->Mid(loc);
  257. *i = i->Left(loc);
  258. continue;
  259. }
  260. }
  261. else if (IsTypeString(*i))
  262. {
  263. if (ParseTypeString(*i, tmp))
  264. {
  265. m_arrURLEncodedForm.push_back(tmp);
  266. continue;
  267. }
  268. }
  269. // else can not be parsed, leave m_arrURLEncodedForm alone.
  270. }
  271. BuildURLEncodedForm();
  272. }
  273. catch (CAPGTSBESReaderException&)
  274. {
  275. // Log BES file parsing error and rethrow exception.
  276. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  277. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  278. SrcLoc.GetSrcFileLineStr(),
  279. _T(""), _T(""), EV_GTS_ERROR_BES_PARSE );
  280. throw;
  281. }
  282. catch (exception& x)
  283. {
  284. CString str;
  285. // Note STL exception in event log and rethrow exception.
  286. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  287. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  288. SrcLoc.GetSrcFileLineStr(),
  289. CCharConversion::ConvertACharToString(x.what(), str),
  290. _T(""),
  291. EV_GTS_STL_EXCEPTION );
  292. throw;
  293. }
  294. if (itBES)
  295. {
  296. m_iBES = itBES - m_arrRawForm.begin();
  297. try
  298. {
  299. m_arrRawForm.insert(itBES, strSav);
  300. }
  301. catch (exception& x)
  302. {
  303. CString str2;
  304. // Note STL exception in event log.
  305. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  306. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  307. SrcLoc.GetSrcFileLineStr(),
  308. CCharConversion::ConvertACharToString(x.what(), str2),
  309. _T(""),
  310. EV_GTS_STL_EXCEPTION );
  311. }
  312. }
  313. SetPos(save_pos);
  314. UNLOCKOBJECT();
  315. }
  316. void CAPGTSBESReader::BuildURLEncodedForm()
  317. {
  318. CString strTemp;
  319. vector<CString>::const_iterator i = m_arrURLEncodedForm.begin();
  320. LOCKOBJECT();
  321. m_strURLEncodedForm = _T(*i); // URL of web app itself
  322. m_strURLEncodedForm += _T("?");
  323. i++;
  324. // form output string without BES string
  325. for (; i < m_arrURLEncodedForm.end(); i++)
  326. {
  327. m_strURLEncodedForm += *i; // name/value pair
  328. m_strURLEncodedForm += _T("&");
  329. }
  330. // append BES string
  331. URLEncodeString(m_SearchText.Name, strTemp);
  332. m_strURLEncodedForm += strTemp;
  333. m_strURLEncodedForm += _T("=");
  334. URLEncodeString(m_SearchText.GetBESStr(), strTemp);
  335. m_strURLEncodedForm += strTemp;
  336. m_strURLEncodedForm += _T(" HTTP/1.0");
  337. UNLOCKOBJECT();
  338. }
  339. // Determine whether or not a string constitutes a "Method" string. Method strings need
  340. // to contain a FORM, METHOD, and ACTION string. Here is an example Method string.
  341. // <FORM METHOD=POST ACTION="/scripts/samples/search/query.idq">
  342. bool CAPGTSBESReader::IsMethodString(const CString& str) const
  343. {
  344. if (-1 == str.Find(FORM) ||
  345. -1 == str.Find(METHOD) ||
  346. -1 == str.Find(ACTION))
  347. {
  348. // All required elements were not found.
  349. return false;
  350. }
  351. return true;
  352. }
  353. // Determine whether or not a string constitutes a "Type" string. Type strings need
  354. // to contain a INPUT, TYPE, NAME, and VALUE string. Here is an example Type string.
  355. // <INPUT TYPE=HIDDEN NAME="TemplateName" VALUE="query">
  356. bool CAPGTSBESReader::IsTypeString(const CString& str) const
  357. {
  358. if (-1 == str.Find(INPUT) ||
  359. -1 == str.Find(TYPE) ||
  360. -1 == str.Find(NAME) ||
  361. -1 == str.Find(VALUE))
  362. {
  363. // All required elements were not found.
  364. return false;
  365. }
  366. return true;
  367. }
  368. // Determine whether or not a string constitutes a "BES" string. BES strings need
  369. // to contain all of the elements of a "Type" string as well as a TEXT tag.
  370. // The following is an example BES string.
  371. // Enter items to search for <INPUT TYPE=TEXT NAME="CiRestriction" VALUE="print OR &quot;network print&quot;">
  372. bool CAPGTSBESReader::IsBESString(const CString& str) const
  373. {
  374. if (!IsTypeString(str) || -1 == str.Find(TEXT))
  375. {
  376. // All required elements were not found.
  377. return false;
  378. }
  379. return true;
  380. }
  381. bool CAPGTSBESReader::ParseMethodString(const CString& in, CString& out)
  382. {
  383. long index = -1;
  384. LPTSTR str = (LPTSTR)(LPCTSTR)in, start =NULL, end =NULL;
  385. if (-1 != (index = in.Find(ACTION)))
  386. {
  387. start = (LPTSTR)(LPCTSTR)in + index;
  388. while (*start && *start != _T('"'))
  389. start++;
  390. if (*start)
  391. {
  392. end = ++start;
  393. while (*end && *end != _T('"'))
  394. end++;
  395. if (*end)
  396. {
  397. try
  398. {
  399. TCHAR* path = new TCHAR[end - start + 1];
  400. _tcsncpy(path, start, end - start);
  401. path[end - start] = 0;
  402. out= path;
  403. delete [] path;
  404. return true;
  405. }
  406. catch (bad_alloc&)
  407. {
  408. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  409. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  410. SrcLoc.GetSrcFileLineStr(),
  411. _T(""), _T(""), EV_GTS_CANT_ALLOC );
  412. return( false );
  413. }
  414. }
  415. }
  416. }
  417. return false;
  418. }
  419. bool CAPGTSBESReader::ParseTypeString(const CString& in, CString& out)
  420. {
  421. CString type, name, value;
  422. CString name_encoded, value_encoded;
  423. if (DecodeInputString(this, in, type, name, value))
  424. {
  425. URLEncodeString(name, name_encoded);
  426. URLEncodeString(value, value_encoded);
  427. out = _T("");
  428. out += name_encoded;
  429. out += _T("=");
  430. out += value_encoded;
  431. return true;
  432. }
  433. return false;
  434. }
  435. bool CAPGTSBESReader::ParseBESString(const CString& in, CBESPair& out)
  436. {
  437. CString type, name, value;
  438. CString name_encoded, value_encoded;
  439. if (DecodeInputString(this, in, type, name, value))
  440. {
  441. URLEncodeString(name, name_encoded);
  442. URLEncodeString(value, value_encoded);
  443. out.Name = name_encoded;
  444. // Note: We do not care about the value_encoded string as it is no longer
  445. // used as all of the search parameters come from nodes visited. RAB-981028.
  446. return true;
  447. }
  448. return false;
  449. }
  450. // URL-encoding in the narrow sense.
  451. // INPUT in - normal text
  452. // OUTPUT out - equivalent URL-encoded string
  453. /*static*/ void CAPGTSBESReader::URLEncodeString(const CString& in, CString& out)
  454. {
  455. TCHAR tostr[2048];
  456. TCHAR *ptr = (LPTSTR)(LPCTSTR)in;
  457. TCHAR buf[5], *str;
  458. TCHAR EncodeByte;
  459. str = ptr;
  460. _tcscpy(tostr, _T(""));
  461. while (*str) {
  462. if (!_istalnum(*str) || *str < 0) {
  463. if (*str == _T(' '))
  464. _tcscat(tostr, _T("+"));
  465. else {
  466. if (!_istleadbyte(*str)) {
  467. EncodeByte = *str;
  468. _stprintf(buf, _T("%%%02X"), (unsigned char) EncodeByte);
  469. _tcscat(tostr, buf);
  470. }
  471. else {
  472. EncodeByte = *str;
  473. _stprintf(buf, _T("%%%02X"), (unsigned char) EncodeByte);
  474. _tcscat(tostr, buf);
  475. EncodeByte = *(str + 1);
  476. _stprintf(buf, _T("%%%02X"), (unsigned char) EncodeByte);
  477. _tcscat(tostr, buf);
  478. }
  479. }
  480. }
  481. else {
  482. _tcsncpy(buf, str, 2);
  483. if (_istleadbyte(*str))
  484. buf[2] = NULL;
  485. else
  486. buf[1] = NULL;
  487. _tcscat(tostr, buf);
  488. }
  489. str = _tcsinc(str);
  490. }
  491. out = tostr;
  492. return;
  493. }
  494. // Parse a line from BES file
  495. // <INPUT TYPE=HIDDEN NAME="CiMaxRecordsPerPage" VALUE="10">
  496. // See note at head of this .cpp file for detailed requirements on these lines
  497. //
  498. // If const_str is a null string, returns success with type, name, value all null strings
  499. // Otherwise, if successful, this function sets type, name, value to the content
  500. // of those respective attributes, if present (e.g "HIDDEN", "CiMaxRecordsPerPage", "10").
  501. // All of these physically point into the (altered) string originally passed in *str
  502. //
  503. // Returns true on success. All failures throw exceptions.
  504. //
  505. /*static*/ bool CAPGTSBESReader::DecodeInputString(
  506. CFileReader* reader,
  507. const CString& const_str,
  508. CString& type,
  509. CString& name,
  510. CString& value
  511. )
  512. {
  513. CString temp_str = const_str;
  514. TCHAR* str = (LPTSTR)(LPCTSTR)temp_str;
  515. TCHAR* ptrtype = NULL;
  516. TCHAR* ptrname = NULL;
  517. TCHAR* ptrvalue = NULL;
  518. TCHAR *typestr = _T("TYPE=");
  519. TCHAR *namestr = _T("NAME=");
  520. TCHAR *valuestr = _T("VALUE=");
  521. TCHAR *ptr, *ptrstart;
  522. int typelen = _tcslen(typestr);
  523. int namelen = _tcslen(namestr);
  524. int valuelen = _tcslen(valuestr);
  525. ptr = str;
  526. ptrtype = str;
  527. ptrname = str;
  528. ptrvalue = str;
  529. if (*ptr == _T('\0'))
  530. goto SUCCESS;
  531. *ptr = _T('\0');
  532. ptr = _tcsinc(ptr);
  533. // must have TYPE
  534. if ((ptrstart = _tcsstr(ptr, typestr))==NULL)
  535. throw CAPGTSBESReaderException(
  536. reader,
  537. CAPGTSBESReaderException::eEV_GTS_ERROR_BES_MISS_TYPE_TAG,
  538. __FILE__,
  539. __LINE__);
  540. ptrstart = _tcsninc(ptrstart, typelen);
  541. if (*ptrstart == _T('"'))
  542. // Deal with optional quotation marks
  543. ptrstart = _tcsinc(ptrstart);
  544. if ((ptr = _tcschr(ptrstart, _T(' ')))==NULL)
  545. if ((ptr = _tcschr(ptrstart, _T('>')))==NULL)
  546. throw CAPGTSBESReaderException(
  547. reader,
  548. CAPGTSBESReaderException::eEV_GTS_ERROR_BES_MISS_CT_TAG,
  549. __FILE__,
  550. __LINE__);
  551. if (ptrstart != ptr)
  552. ptr = _tcsdec(ptrstart, ptr);
  553. if (*ptr != _T('"'))
  554. ptr = _tcsinc(ptr);
  555. *ptr = _T('\0');
  556. ptr = _tcsinc(ptr);
  557. ptrtype = ptrstart;
  558. // NAME must come next if present
  559. if ((ptrstart = _tcsstr(ptr, namestr))==NULL)
  560. goto SUCCESS;
  561. ptrstart = _tcsninc(ptrstart, namelen);
  562. if (*ptrstart == _T('"'))
  563. ptrstart = _tcsinc(ptrstart);
  564. if ((ptr = _tcschr(ptrstart, _T('"')))==NULL)
  565. if ((ptr = _tcschr(ptrstart, _T(' ')))==NULL)
  566. if ((ptr = _tcschr(ptrstart, _T('>')))==NULL)
  567. throw CAPGTSBESReaderException(
  568. reader,
  569. CAPGTSBESReaderException::eEV_GTS_ERROR_BES_MISS_CN_TAG,
  570. __FILE__,
  571. __LINE__);
  572. if (ptrstart != ptr)
  573. ptr = _tcsdec(ptrstart, ptr);
  574. if (*ptr != _T('"'))
  575. ptr = _tcsinc(ptr);
  576. *ptr = _T('\0');
  577. ptr = _tcsinc(ptr);
  578. ptrname = ptrstart;
  579. // VALUE must come next if present
  580. if ((ptrstart = _tcsstr(ptr, valuestr))==NULL)
  581. goto SUCCESS;
  582. ptrstart = _tcsninc(ptrstart, valuelen);
  583. if (*ptrstart == _T('"'))
  584. ptrstart = _tcsinc(ptrstart);
  585. if ((ptr = _tcschr(ptrstart, _T('"')))==NULL)
  586. if ((ptr = _tcschr(ptrstart, _T(' ')))==NULL)
  587. if ((ptr = _tcschr(ptrstart, _T('>')))==NULL)
  588. throw CAPGTSBESReaderException(
  589. reader,
  590. CAPGTSBESReaderException::eEV_GTS_ERROR_BES_MISS_CV_TAG,
  591. __FILE__,
  592. __LINE__);
  593. if (ptrstart != ptr)
  594. ptr = _tcsdec(ptrstart, ptr);
  595. if (*ptr != _T('"'))
  596. ptr = _tcsinc(ptr);
  597. *ptr = _T('\0');
  598. ptr = _tcsinc(ptr);
  599. ptrvalue = ptrstart;
  600. SUCCESS:
  601. type = ptrtype;
  602. name = ptrname;
  603. value = ptrvalue;
  604. return true;
  605. }