Leaked source code of windows server 2003
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.

239 lines
6.9 KiB

  1. //
  2. // MODULE: APGTSQRY.CPP
  3. //
  4. // PURPOSE: Implementation file for PTS Query Parser
  5. // Fully implements class CHttpQuery, parsing out NAME=VALUE pairs from HTTP query string
  6. //
  7. // PROJECT: Generic Troubleshooter DLL for Microsoft AnswerPoint
  8. //
  9. // COMPANY: Saltmine Creative, Inc. (206)-284-7511 [email protected]
  10. //
  11. // AUTHOR: Roman Mach
  12. //
  13. // ORIGINAL DATE: 8-2-96
  14. //
  15. // NOTES:
  16. // 1. Based on Print Troubleshooter DLL
  17. // 2. Caller is responsible to assure that all buffers passed in are large enough
  18. //
  19. // Version Date By Comments
  20. //--------------------------------------------------------------------
  21. // V0.1 - RM Original
  22. // V3.1 12/17/98 JM Major cleanup, add Push capablity
  23. //
  24. #pragma warning(disable:4786)
  25. #include "stdafx.h"
  26. #include "apgts.h"
  27. #include "apgtscls.h"
  28. //
  29. //
  30. CHttpQuery::CHttpQuery() :
  31. m_state(ST_GETDATA),
  32. m_nIndex(0)
  33. {
  34. }
  35. //
  36. //
  37. CHttpQuery::~CHttpQuery()
  38. {
  39. }
  40. //
  41. // INPUT *szInput - this is the URL-encoded query string in which we are searching
  42. // INPUT *pchName - must point to a buffer of size MAXBUF
  43. // OUTPUT *pchName - Typically NAME of a NAME=VALUE pair. Any URL-encoding stripped out.
  44. // Null-terminated. Leading and trailing blanks stripped.
  45. // INPUT *pchValue - must point to a buffer of size MAXBUF
  46. // OUTPUT *pchValue - Typically VALUE of a NAME=VALUE pair. Any URL-encoding stripped out.
  47. // Null-terminated. Leading and trailing blanks stripped.
  48. // RETURN - TRUE ==> more data to come
  49. BOOL CHttpQuery::GetFirst(LPCTSTR szInput, TCHAR *pchName, TCHAR *pchValue)
  50. {
  51. m_state = ST_GETDATA;
  52. m_strInput = szInput;
  53. m_nIndex = 0;
  54. BOOL status = LoopFind(pchName, pchValue);
  55. CleanStr(pchName);
  56. CleanStr(pchValue);
  57. return (status);
  58. }
  59. // Called after a call to CHttpQuery::GetFirst or to this fn has returned true
  60. // INPUT *pchName - must point to a buffer of size MAXBUF
  61. // OUTPUT *pchName - Typically NAME of a NAME=VALUE pair
  62. // Null-terminated. Leading and trailing blanks stripped.
  63. // INPUT *pchValue - must point to a buffer of size MAXBUF
  64. // OUTPUT *pchValue - Typically VALUE of a NAME=VALUE pair
  65. // Null-terminated. Leading and trailing blanks stripped.
  66. // RETURN - TRUE ==> more data to come
  67. BOOL CHttpQuery::GetNext(TCHAR *pchName, TCHAR *pchValue)
  68. {
  69. BOOL status = LoopFind(pchName, pchValue);
  70. CleanStr(pchName);
  71. CleanStr(pchValue);
  72. return (status);
  73. }
  74. // put new content on the front of the unparsed portion of the query string in which we are
  75. // searching.
  76. // Typically, szPushed should consist of 1 or more NAME=VALUE pairs, each terminated by an
  77. // ampersand ("&").
  78. void CHttpQuery::Push(LPCTSTR szPushed)
  79. {
  80. m_state = ST_GETDATA;
  81. m_strInput = CString(szPushed) + m_strInput.Mid(m_nIndex);
  82. m_nIndex = 0;
  83. }
  84. //
  85. // RETURN - TRUE ==> more data to come
  86. // INPUT *pchName - must point to a buffer of size MAXBUF
  87. // OUTPUT *pchName - Typically NAME of a NAME=VALUE pair. Any URL-encoding stripped out.
  88. // Null-terminated. May have leading and/or trailing blanks
  89. // INPUT *pchValue - must point to a buffer of size MAXBUF
  90. // OUTPUT *pchValue - Typically VALUE of a NAME=VALUE pair. Any URL-encoding stripped out.
  91. // Null-terminated. May have leading and/or trailing blanks
  92. BOOL CHttpQuery::LoopFind(TCHAR *pchName, TCHAR *pchValue)
  93. {
  94. *pchName = NULL;
  95. *pchValue = NULL;
  96. TCHAR ch;
  97. int val, oldval = 0;
  98. TCHAR temp[20]; // a way bigger buffer than we need
  99. TCHAR *pchPut; // initially points to pchName but can change to point to pchValue
  100. int nLength = m_strInput.GetLength();
  101. if (m_nIndex >= nLength)
  102. return (FALSE);
  103. pchPut = pchName;
  104. while (m_nIndex < nLength)
  105. {
  106. ch = m_strInput[m_nIndex++]; // You might think something related to _tcsinc()
  107. // would be called for to advance m_nIndex. You'd be wrong,
  108. // although the choice would be harmless.
  109. // URL-encoding keeps us within the ASCII character set, so no double-
  110. // byte issues should arise. Besides that, the strings passed in to the
  111. // command line of the troubleshooter controls are even further
  112. // constrained: for example, even in a Japanese-language topic, node
  113. // names will be ASCII.
  114. switch(m_state) {
  115. case ST_GETDATA:
  116. if (ch == _T('&'))
  117. // expect another NAME=VALUE pair
  118. return (TRUE);
  119. else if (ch == _T('=')) {
  120. // Got a name, expect a value
  121. pchPut = pchValue;
  122. break;
  123. }
  124. else if (ch == _T('%'))
  125. // expect to be followed by 2-digit hex
  126. m_state = ST_DECODEHEX1;
  127. else if (ch == _T('+'))
  128. // encoded blank
  129. AddBuffer(_T(' '),pchPut);
  130. else
  131. AddBuffer(ch,pchPut);
  132. break;
  133. case ST_DECODEHEX1:
  134. // first of 2 hex digits
  135. temp[0] = ch;
  136. m_state = ST_DECODEHEX2;
  137. break;
  138. case ST_DECODEHEX2:
  139. // second of 2 hex digits; parse it into a hex value & affix it to *pchPut
  140. temp[1] = ch;
  141. temp[2] = 0;
  142. _stscanf(temp,_T("%02X"),&val);
  143. // reinterpret CR, LF, or CRLF as '\n'
  144. if (val == 0x0A) {
  145. if (oldval != 0x0D)
  146. AddBuffer(_T('\n'),pchPut);
  147. }
  148. else if (val == 0x0D)
  149. AddBuffer(_T('\n'),pchPut);
  150. else
  151. AddBuffer( static_cast<TCHAR>(val), pchPut );
  152. oldval = val;
  153. m_state = ST_GETDATA;
  154. break;
  155. default:
  156. return (FALSE);
  157. }
  158. }
  159. return (TRUE);
  160. }
  161. //
  162. // append ch to *tostr, with a few subtleties: see comments in body of routine
  163. void CHttpQuery::AddBuffer( TCHAR ch, TCHAR *tostr)
  164. {
  165. if (ch == _T('\t'))
  166. // TAB -> 4 blanks
  167. PutStr(_T(" "),tostr);
  168. else if (ch == _T('\n'))
  169. // blank before newline
  170. PutStr(_T(" \n"),tostr);
  171. else if (ch == _T('<'))
  172. // html: must encrypt left angle bracket.
  173. PutStr(_T("&lt"),tostr);
  174. else if (ch == _T('>'))
  175. // html: must encrypt right angle bracket.
  176. PutStr(_T("&gt"),tostr);
  177. else if (ch > 0x7E || ch < 0x20)
  178. // refuse DEL, NUL, and control characters
  179. return;
  180. else {
  181. TCHAR temp[2];
  182. temp[0] = ch;
  183. temp[1] = _T('\0');
  184. PutStr(temp,tostr);
  185. }
  186. }
  187. // append string *addtostr to string *instr up to a maximum size of MAXBUF-1
  188. // INPUT/OUTPUT *instr
  189. // INPUT *addtostr
  190. // NOTE that this fails silently if total lengths exceed MAXBUF-1 chars
  191. void CHttpQuery::PutStr(LPCTSTR instr, TCHAR *addtostr)
  192. {
  193. if ((_tcslen(instr)+_tcslen(addtostr)) >= (MAXBUF-1)) {
  194. // can't add it to buff
  195. return;
  196. }
  197. _tcscat(addtostr,instr);
  198. }
  199. // Acts upon INPUT/OUTPUT *str - strip any leading control characters and spaces,
  200. // turn any other control characters and spaces into '\0's
  201. /* static */ void CHttpQuery::CleanStr(TCHAR *str)
  202. {
  203. TCHAR temp[MAXBUF], *ptr;
  204. int len;
  205. ptr = str;
  206. while (*ptr > _T('\0') && *ptr <= _T(' '))
  207. ptr = _tcsinc(ptr);
  208. _tcscpy(temp,ptr);
  209. if ((len = _tcslen(temp))!=0) {
  210. ptr = &temp[len-1];
  211. while (ptr > temp) {
  212. if (*ptr > _T('\0') && *ptr <= _T(' '))
  213. *ptr = _T('\0');
  214. else
  215. break;
  216. ptr = _tcsdec(temp, ptr);
  217. }
  218. }
  219. _tcscpy(str,temp);
  220. }