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.

944 lines
27 KiB

  1. //
  2. // Microsoft Corporation - Copyright 1997
  3. //
  4. //
  5. // RESPONSE.CPP - Contains possible responses
  6. //
  7. #include "pch.h"
  8. // Globals
  9. const char g_cszTableHeader[] = "%s \
  10. <TABLE ID=%s BORDER=1> \
  11. <TR> \
  12. <TH WIDTH=40%%>Variable Name</TH> \
  13. <TH WIDTH=60%%>Value</TH> \
  14. </TR>";
  15. const char g_cszTableEnd[] = "</TABLE>";
  16. // List of known server variables
  17. LPSTR g_lpServerVars[] = {
  18. "AUTH_TYPE",
  19. "CONTENT_LENGTH",
  20. "CONTENT_TYPE",
  21. "GATEWAY_INTERFACE",
  22. "LOGON_USER",
  23. "PATH_INFO",
  24. "PATH_TRANSLATED",
  25. "QUERY_STRING",
  26. "REMOTE_ADDR",
  27. "REMOTE_HOST",
  28. "REQUEST_METHOD",
  29. "SCRIPT_MAP",
  30. "SCRIPT_NAME",
  31. "SERVER_NAME",
  32. "SERVER_PORT",
  33. "SERVER_PORT_SECURE",
  34. "SERVER_SOFTWARE",
  35. "URL"
  36. };
  37. #define FROMHEX( _v ) \
  38. ( ( _v >= 48 ) && ( _v <= 57 ) ? _v - 48 : \
  39. ( ( _v >= 65 ) && ( _v <= 70 ) ? _v + 10 - 65 : 0 ) )
  40. //
  41. // What: UnCanonicalize
  42. //
  43. // Desc: Un-escapes strings
  44. //
  45. BOOL UnCanonicalize( LPSTR lpszStart, LPSTR lpszUnURL , LPDWORD lpdwSize )
  46. {
  47. LPSTR lps = lpszStart;
  48. DWORD cb = 0;
  49. while (( *lps ) && ( cb < *lpdwSize ))
  50. {
  51. if ( *lps == '%' )
  52. {
  53. lps++;
  54. lpszUnURL[ cb ] = 16 * FROMHEX( *lps);
  55. lps++;
  56. lpszUnURL[ cb ] += FROMHEX( *lps);
  57. }
  58. else if ( *lps == '+' )
  59. {
  60. lpszUnURL[ cb ] = 32;
  61. }
  62. else
  63. {
  64. lpszUnURL[ cb ] = *lps;
  65. }
  66. cb++;
  67. lps++;
  68. }
  69. lpszUnURL[ cb ] = 0; // paranoid
  70. *lpdwSize = cb;
  71. return TRUE;
  72. } // UnCanonicalize( )
  73. //
  74. // What: DumpFormDataFromPost
  75. //
  76. // Desc: Dumps the fields and values in a form from a POST.
  77. //
  78. BOOL DumpFormDataFromPost( LPECB lpEcb )
  79. {
  80. BOOL fReturn = TRUE;
  81. DWORD dwSize;
  82. static char szUnparsed[] = "The unparsed Form submit string is: <FONT FACE=\"Courier New\">";
  83. static char szUnFont[] = "</FONT>";
  84. TraceMsg( TF_FUNC | TF_RESPONSE, "DumpFormDataFromPost()" );
  85. if ( fReturn )
  86. { // header and the beginning of the table
  87. CHAR szBuffer[ 512 ];
  88. dwSize = wsprintf( szBuffer, g_cszTableHeader,
  89. "<H2>Form Data (METHOD=POST)</H2>", "TBLPOST" );
  90. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
  91. }
  92. if ( fReturn )
  93. {
  94. int i = 0;
  95. LPSTR lpszStart = (LPSTR) lpEcb->lpbData;
  96. while (( fReturn ) && ( lpszStart ))
  97. {
  98. CHAR cTmpEnd;
  99. LPSTR lpszEquals = StrChr( lpszStart, '=' );
  100. if ( !lpszEquals )
  101. break; // no more data
  102. LPSTR lpszEnd = StrChr( lpszEquals, '&' );
  103. if ( lpszEnd )
  104. {
  105. cTmpEnd = *lpszEnd; // save
  106. *lpszEnd = 0;
  107. }
  108. CHAR cTmp = *lpszEquals; // save
  109. *lpszEquals = 0;
  110. CHAR szBuffer[ 4096 ];
  111. CHAR szUnURL[ 2048 ];
  112. dwSize = sizeof( szUnURL );
  113. fReturn = UnCanonicalize( lpszEquals + 1, szUnURL, &dwSize );
  114. if ( fReturn )
  115. {
  116. dwSize = wsprintf( szBuffer,
  117. "<TR ID=TR%u><TD ID=TD%u>%s</TD><TD ID=%s>%s</TD></TR>",
  118. i, i, lpszStart, lpszStart, szUnURL );
  119. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
  120. }
  121. *lpszEquals = cTmp; // restore
  122. if ( lpszEnd )
  123. {
  124. *lpszEnd = cTmpEnd; // restore
  125. lpszEnd++;
  126. }
  127. lpszStart = lpszEnd;
  128. i++;
  129. }
  130. }
  131. // end of the table
  132. if ( fReturn )
  133. {
  134. dwSize = 1 + lstrlen( g_cszTableEnd );
  135. fReturn = WriteClient( lpEcb->ConnID, (LPVOID) g_cszTableEnd, &dwSize, HSE_IO_ASYNC );
  136. }
  137. // display unparsed information
  138. if ( fReturn )
  139. {
  140. dwSize = 1 + lstrlen( szUnparsed );
  141. fReturn = WriteClient( lpEcb->ConnID, szUnparsed, &dwSize, HSE_IO_ASYNC );
  142. }
  143. if ( fReturn )
  144. {
  145. dwSize = 1 + lstrlen( (LPSTR) lpEcb->lpbData );
  146. fReturn = WriteClient( lpEcb->ConnID, lpEcb->lpbData, &dwSize, HSE_IO_ASYNC );
  147. }
  148. // end FONT tag
  149. if ( fReturn )
  150. {
  151. dwSize = 1 + lstrlen( szUnFont );
  152. fReturn = WriteClient( lpEcb->ConnID, szUnFont, &dwSize, HSE_IO_ASYNC );
  153. }
  154. TraceMsg( TF_FUNC | TF_RESPONSE, "DumpFormDataFromPost() Exit = %s",
  155. BOOLTOSTRING( fReturn ) );
  156. return fReturn;
  157. } // DumpFormDataFromPost( )
  158. //
  159. // What: DumpQueryStringDataFromGet
  160. //
  161. // Desc: Dumps the fields and values in a form from a GET.
  162. //
  163. BOOL DumpQueryStringDataFromGet( LPECB lpEcb )
  164. {
  165. BOOL fReturn = TRUE;
  166. LPSTR lpszBuffer;
  167. DWORD dwSize;
  168. static char szUnparsed[] = "The unparsed QueryString is: <FONT FACE=\"Courier New\">";
  169. static char szUnFont[] = "</FONT>";
  170. TraceMsg( TF_FUNC | TF_RESPONSE, "DumpQueryStringDataFromGet()" );
  171. if ( fReturn )
  172. fReturn = GetServerVarString( lpEcb, "QUERY_STRING", &lpszBuffer, NULL );
  173. if ( fReturn )
  174. { // header and the beginning of the table
  175. CHAR szBuffer[ 512 ];
  176. dwSize = wsprintf( szBuffer, g_cszTableHeader,
  177. "<H2>QueryString Data(METHOD=GET)</H2>", "TBLGET" );
  178. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
  179. }
  180. if ( fReturn )
  181. {
  182. int i = 0;
  183. LPSTR lpszStart = lpszBuffer;
  184. while (( fReturn ) && ( lpszStart ))
  185. {
  186. CHAR cTmpEnd;
  187. LPSTR lpszEquals = StrChr( lpszStart, '=' );
  188. LPSTR lpszEnd = StrChr( lpszEquals, '&' );
  189. if ( lpszEnd )
  190. {
  191. cTmpEnd = *lpszEnd; // save
  192. *lpszEnd = 0;
  193. }
  194. CHAR cTmp = *lpszEquals; // save
  195. *lpszEquals = 0;
  196. CHAR szBuffer[ 4096 ];
  197. CHAR szUnURL[ 2048 ];
  198. dwSize = sizeof( szUnURL );
  199. fReturn = UnCanonicalize( lpszEquals + 1, szUnURL, &dwSize );
  200. if ( fReturn )
  201. {
  202. dwSize = wsprintf( szBuffer,
  203. "<TR ID=TR%u><TD ID=TD%u>%s</TD><TD ID=%s>%s</TD></TR>",
  204. i, i, lpszStart, lpszStart, szUnURL );
  205. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
  206. }
  207. *lpszEquals = cTmp; // restore
  208. if ( lpszEnd )
  209. {
  210. *lpszEnd = cTmpEnd; // restore
  211. lpszEnd++;
  212. }
  213. lpszStart = lpszEnd;
  214. i++;
  215. }
  216. }
  217. // end the table
  218. if ( fReturn )
  219. {
  220. dwSize = 1 + lstrlen( g_cszTableEnd );
  221. fReturn = WriteClient( lpEcb->ConnID, (LPVOID) g_cszTableEnd, &dwSize, HSE_IO_ASYNC );
  222. }
  223. // display unparsed information
  224. if ( fReturn )
  225. {
  226. dwSize = 1 + lstrlen( szUnparsed );
  227. fReturn = WriteClient( lpEcb->ConnID, szUnparsed, &dwSize, HSE_IO_ASYNC );
  228. }
  229. if ( fReturn )
  230. {
  231. dwSize = 1 + lstrlen( lpszBuffer );
  232. fReturn = WriteClient( lpEcb->ConnID, lpszBuffer, &dwSize, HSE_IO_ASYNC );
  233. }
  234. // end font tag
  235. if ( fReturn )
  236. {
  237. dwSize = 1 + lstrlen( szUnFont );
  238. fReturn = WriteClient( lpEcb->ConnID, szUnFont, &dwSize, HSE_IO_ASYNC );
  239. }
  240. // clean up
  241. if ( lpszBuffer )
  242. GlobalFree( lpszBuffer );
  243. TraceMsg( TF_FUNC | TF_RESPONSE, "DumpQueryStringDataFromGet() Exit = %s",
  244. BOOLTOSTRING( fReturn ) );
  245. return fReturn;
  246. } // DumpQueryStringDataFromGet( )
  247. //
  248. // What: DumpServerVariables
  249. //
  250. // Desc: Dumps the current server variable settings from the result of
  251. // a form submission.
  252. //
  253. BOOL DumpServerVariables( LPECB lpEcb )
  254. {
  255. BOOL fReturn = TRUE;
  256. LPSTR lpszBuffer;
  257. DWORD dwSize;
  258. int i = 0; // counter
  259. TraceMsg( TF_FUNC | TF_RESPONSE, "DumpServerVariables()" );
  260. if ( fReturn )
  261. { // header and the begging of the table
  262. CHAR szBuffer[ 512 ];
  263. dwSize = wsprintf( szBuffer, g_cszTableHeader,
  264. "<H2>Server Variables</H2>", "TBLSERVERVARS" );
  265. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
  266. }
  267. // try the known ones
  268. for( ; ( fReturn ) && ( i < ARRAYOF( g_lpServerVars ) ); i++ )
  269. {
  270. GetServerVarString( lpEcb, g_lpServerVars[ i ], &lpszBuffer, NULL );
  271. if ( lpszBuffer )
  272. {
  273. CHAR szBuffer[ 512 ];
  274. dwSize = wsprintf( szBuffer,
  275. "<TR ID=TR%u><TD ID=TD%u>%s</TD><TD ID=%s>%s</TD></TR>",
  276. i, i, g_lpServerVars[ i ], g_lpServerVars[ i ], lpszBuffer );
  277. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
  278. }
  279. GlobalFree( lpszBuffer );
  280. lpszBuffer = NULL;
  281. }
  282. // try the HTTP_ALL from header that the server ignores
  283. if ( fReturn )
  284. fReturn = GetServerVarString( lpEcb, "ALL_HTTP", &lpszBuffer, NULL );
  285. if (( fReturn ) && ( lpszBuffer ))
  286. {
  287. LPSTR lpszStart = lpszBuffer;
  288. while (( fReturn ) && ( lpszStart ))
  289. {
  290. char cTmpEnd;
  291. LPSTR lpszColon = StrChr( lpszStart, ':' );
  292. LPSTR lpszEnd = StrStr( lpszColon, "HTTP_" );
  293. if ( lpszEnd )
  294. {
  295. cTmpEnd = *lpszEnd; // save
  296. *lpszEnd = 0;
  297. }
  298. char cTmp = *lpszColon; // save
  299. *lpszColon = 0;
  300. CHAR szBuffer[ 4096 ];
  301. dwSize = wsprintf( szBuffer,
  302. "<TR ID=TR%u><TD ID=TD%u>%s</TD><TD ID=%s>%s</TD></TR>",
  303. i, i, lpszStart, lpszStart, lpszColon + 1 );
  304. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
  305. *lpszColon = cTmp; // restore
  306. if ( lpszEnd )
  307. *lpszEnd = cTmpEnd; // restore
  308. lpszStart = lpszEnd;
  309. i++;
  310. }
  311. }
  312. // end the table
  313. if ( fReturn )
  314. {
  315. dwSize = 1 + lstrlen( g_cszTableEnd );
  316. fReturn = WriteClient( lpEcb->ConnID, (LPVOID) g_cszTableEnd, &dwSize, HSE_IO_ASYNC );
  317. }
  318. // clean up
  319. GlobalFree( lpszBuffer );
  320. lpszBuffer = NULL;
  321. TraceMsg( TF_FUNC | TF_RESPONSE, "DumpServerVariables() Exit = %s",
  322. BOOLTOSTRING( fReturn ) );
  323. return fReturn;
  324. } // ( )
  325. //
  326. // What: DumpOutput
  327. //
  328. // Desc: Generate reponse body page after headers and the HTML header
  329. // has been.
  330. //
  331. BOOL DumpOutput(
  332. QUERYMETHOD eMethod,
  333. LPECB lpEcb,
  334. LPSTR lpszOut,
  335. LPSTR lpszDebug )
  336. {
  337. BOOL fReturn;
  338. DWORD dwSize;
  339. char szBuffer[ RESPONSE_BUF_SIZE ];
  340. TraceMsg( TF_FUNC | TF_RESPONSE, "DumpOutput()" );
  341. // Display form data
  342. switch ( eMethod )
  343. {
  344. case METHOD_POST:
  345. fReturn = DumpFormDataFromPost( lpEcb );
  346. break;
  347. case METHOD_GET:
  348. fReturn = DumpQueryStringDataFromGet( lpEcb );
  349. break;
  350. case METHOD_POSTTEXTPLAIN:
  351. case METHOD_POSTMULTIPART:
  352. if ( lpszOut )
  353. {
  354. dwSize = 1 + lstrlen( lpszOut );
  355. fReturn = WriteClient( lpEcb->ConnID, lpszOut, &dwSize, HSE_IO_ASYNC );
  356. }
  357. break;
  358. default:
  359. StrCpy( szBuffer, "<H2>???? (METHOD=UNKNOWN)</H2>" );
  360. dwSize = 1 + lstrlen( szBuffer );
  361. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
  362. }
  363. // Dump the server variables
  364. if ( fReturn )
  365. fReturn = DumpServerVariables( lpEcb );
  366. // Dump any debugging messages
  367. if (( fReturn ) && ( lpszDebug ))
  368. {
  369. StrCpy( szBuffer, "<H2>Debugging Output</H2>" );
  370. dwSize = 1 + lstrlen( szBuffer );
  371. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
  372. if ( fReturn )
  373. fReturn = OutputHTMLString( lpEcb, lpszDebug );
  374. }
  375. // Dump any server log entries
  376. if (( fReturn ) && ( lpEcb->lpszLogData[ 0 ] ))
  377. {
  378. StrCpy( szBuffer, "<H2>Server Log Entry</H2>" );
  379. dwSize = 1 + lstrlen( szBuffer );
  380. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
  381. if ( fReturn )
  382. {
  383. dwSize = 1 + lstrlen( lpEcb->lpszLogData );
  384. fReturn = WriteClient( lpEcb->ConnID, lpEcb->lpszLogData, &dwSize, HSE_IO_ASYNC );
  385. }
  386. }
  387. TraceMsg( TF_FUNC | TF_RESPONSE, "DumpOutput() Exit = %s",
  388. BOOLTOSTRING( fReturn ) );
  389. return fReturn;
  390. } // DumpOutput( )
  391. //
  392. // What: SendSuccess
  393. //
  394. // Desc: Sends client an HTML response for a successful upload. Just a
  395. // green screen with "SUCCESS!" in a big header.
  396. //
  397. // In: lpEcb is the EXTENDED_CONTROL_BLOCK that the server sent us.
  398. //
  399. BOOL SendSuccess(
  400. QUERYMETHOD eMethod,
  401. LPECB lpEcb,
  402. LPSTR lpszOut,
  403. LPSTR lpszDebug,
  404. LPBYTE lpbData,
  405. DWORD dwParsed,
  406. LPDUMPTABLE lpDT )
  407. {
  408. BOOL fReturn = TRUE; // assume success
  409. CHAR szBuffer[ RESPONSE_BUF_SIZE ];
  410. DWORD dwSize;
  411. BOOL fDebug = FALSE;
  412. TraceMsg( TF_FUNC | TF_RESPONSE, "SendSuccess( )" );
  413. // Generate on the fly so
  414. // fReturn = SendServerHeader( lpEcb );
  415. if ( fReturn )
  416. {
  417. StrCpy( szBuffer, "\
  418. <HTML>\
  419. <HEAD>\
  420. <TITLE>Form Submission Reflector</TITLE>\
  421. </HEAD>\
  422. <BODY bgcolor=#00FF00>\
  423. <FONT FACE=\"ARIAL,HELVETICA\" SIZE=2>\
  424. Submission Result <INPUT TYPE=TEXT NAME=RESULT VALUE=\"SUCCESS!\">" );
  425. dwSize = 1 + lstrlen( szBuffer );
  426. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
  427. }
  428. if ( fReturn )
  429. fReturn = CheckForDebug( lpEcb, &fDebug );
  430. if ( fReturn )
  431. {
  432. if ( fDebug )
  433. fReturn = DumpOutput( eMethod, lpEcb, lpszOut, lpszDebug );
  434. else
  435. fReturn = DumpOutput( eMethod, lpEcb, lpszOut, NULL );
  436. }
  437. if (( fReturn ) && ( fDebug ))
  438. fReturn = HexDump( lpEcb, lpbData, dwParsed, lpDT );
  439. if ( fReturn )
  440. {
  441. StrCpy( szBuffer, "</BODY></HTML>" );
  442. dwSize = 1 + lstrlen( szBuffer );
  443. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
  444. }
  445. TraceMsg( TF_FUNC | TF_RESPONSE, "SendSuccess( ) Exit = %s",
  446. BOOLTOSTRING( fReturn ) );
  447. return fReturn;
  448. } // SendSuccess( )
  449. //
  450. // What: SendFailure
  451. //
  452. // Desc: Sends client an HTML response for a failed upload. Just a
  453. // red screen with "FAILED!" in a big header.
  454. //
  455. // In: lpEcb is the EXTENDED_CONTROL_BLOCK that the server sent us.
  456. //
  457. BOOL SendFailure(
  458. QUERYMETHOD eMethod,
  459. LPECB lpEcb,
  460. LPSTR lpszOut,
  461. LPSTR lpszDebug,
  462. LPBYTE lpbData,
  463. DWORD dwParsed,
  464. LPDUMPTABLE lpDT )
  465. {
  466. BOOL fReturn = TRUE; // assume success
  467. CHAR szBuffer[ RESPONSE_BUF_SIZE ];
  468. DWORD dwSize;
  469. BOOL fDebug = FALSE;
  470. TraceMsg( TF_FUNC | TF_RESPONSE, "SendFailure( )" );
  471. // fReturn = SendServerHeader( lpEcb );
  472. if ( fReturn )
  473. {
  474. StrCpy( szBuffer, "\
  475. <HTML>\
  476. <HEAD>\
  477. <TITLE>Form Submission Reflector</TITLE>\
  478. </HEAD>\
  479. <BODY bgcolor=#FF0000>\
  480. <FONT FACE=\"ARIAL,HELVETICA\" SIZE=2>\
  481. Submission Result <INPUT TYPE=TEXT NAME=RESULT VALUE=\"FAILED!\">" );
  482. dwSize = 1 + lstrlen( szBuffer );
  483. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
  484. }
  485. if ( fReturn )
  486. fReturn = CheckForDebug( lpEcb, &fDebug );
  487. if ( fReturn )
  488. {
  489. if ( fDebug )
  490. fReturn = DumpOutput( eMethod, lpEcb, lpszOut, lpszDebug );
  491. else
  492. fReturn = DumpOutput( eMethod, lpEcb, lpszOut, NULL );
  493. }
  494. if (( fReturn ) && ( fDebug ))
  495. fReturn = HexDump( lpEcb, lpbData, dwParsed, lpDT );
  496. if ( fReturn )
  497. {
  498. StrCpy( szBuffer, "</BODY></HTML>" );
  499. dwSize = 1 + lstrlen( szBuffer );
  500. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
  501. }
  502. TraceMsg( TF_FUNC | TF_RESPONSE, "SendFailure( ) Exit = %s",
  503. BOOLTOSTRING( fReturn ) );
  504. return fReturn;
  505. } // SendSuccess( )
  506. //
  507. // What: SendRedirect
  508. //
  509. // Desc: Redirects to another URL.
  510. //
  511. // In: lpEcb is the EXTENDED_CONTROL_BLOCK that the server sent us.
  512. //
  513. BOOL SendRedirect( LPECB lpEcb, LPSTR lpszURL )
  514. {
  515. BOOL fReturn = TRUE; // assume success
  516. CHAR szBuffer[ RESPONSE_BUF_SIZE ];
  517. DWORD dwSize = 1 + lstrlen( lpszURL );
  518. DWORD dw;
  519. TraceMsg( TF_FUNC | TF_RESPONSE, "SendRedirect( )" );
  520. fReturn = ServerSupportFunction( lpEcb->ConnID, HSE_REQ_SEND_URL_REDIRECT_RESP,
  521. lpszURL, &dwSize, &dw );
  522. TraceMsg( TF_FUNC | TF_RESPONSE, "SendRedirect( ) Exit = %s",
  523. BOOLTOSTRING( fReturn ) );
  524. return fReturn;
  525. } // SendSuccess( )
  526. //
  527. // What: SendEcho
  528. //
  529. // Desc: Sends client an echo for everything that it sent to us.
  530. //
  531. // In: lpEcb is the EXTENDED_CONTROL_BLOCK
  532. //
  533. BOOL SendEcho( LPECB lpEcb )
  534. {
  535. BOOL fReturn = TRUE; // assume success
  536. CHAR szBuffer[ RESPONSE_BUF_SIZE ];
  537. DWORD dwSize;
  538. LPVOID lpMoreData = NULL;
  539. TraceMsg( TF_FUNC | TF_RESPONSE, "SendEcho( )" );
  540. BOOL fDownloadComplete = (lpEcb->cbTotalBytes == lpEcb->cbAvailable );
  541. TraceMsg( TF_RESPONSE, "Does cbTotalBytes(%u) == cbAvailable(%u)? %s",
  542. lpEcb->cbTotalBytes, lpEcb->cbAvailable,
  543. BOOLTOSTRING( fDownloadComplete ) );
  544. if ( !fDownloadComplete )
  545. { // Get the rest of the data
  546. dwSize = lpEcb->cbTotalBytes - lpEcb->cbAvailable;
  547. lpMoreData = (LPVOID) GlobalAlloc( GPTR, dwSize );
  548. fReturn = ReadData( lpEcb, lpMoreData, dwSize );
  549. if ( !fReturn )
  550. goto Cleanup;
  551. }
  552. TraceMsg( TF_RESPONSE, "Total Bytes: %u\n%s",
  553. lpEcb->cbAvailable, lpEcb->lpbData );
  554. // Server header info...
  555. fReturn = SendServerHeader( lpEcb );
  556. if ( !fReturn )
  557. goto Cleanup;
  558. // Create top part of response and send it
  559. StrCpy( szBuffer, "<HTML><BODY bgcolor=#0000FF><PRE>" );
  560. dwSize = 1 + lstrlen( szBuffer );
  561. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
  562. if ( !fReturn )
  563. goto Cleanup;
  564. // and echo it back...
  565. dwSize = lpEcb->cbAvailable;
  566. fReturn = WriteClient( lpEcb->ConnID, lpEcb->lpbData, &dwSize, HSE_IO_ASYNC );
  567. if ( !fReturn )
  568. goto Cleanup;
  569. // and anything else that was sent...
  570. if ( lpMoreData )
  571. {
  572. dwSize = lpEcb->cbTotalBytes - lpEcb->cbAvailable;
  573. fReturn = WriteClient( lpEcb->ConnID, lpMoreData, &dwSize, HSE_IO_ASYNC );
  574. if ( !fReturn )
  575. goto Cleanup;
  576. }
  577. // Create bottom part of response and send it
  578. StrCpy( szBuffer, "</PRE></BODY></HTML>" );
  579. dwSize = 1 + lstrlen( szBuffer );
  580. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
  581. if ( !fReturn )
  582. goto Cleanup;
  583. Cleanup:
  584. if ( lpMoreData )
  585. GlobalFree( lpMoreData );
  586. TraceMsg( TF_FUNC | TF_RESPONSE, "SendEcho( ) Exit = %s",
  587. BOOLTOSTRING( fReturn ) );
  588. return fReturn;
  589. } // SendEcho( )
  590. //
  591. // What: SendServerHeader
  592. //
  593. // Desc: This sends a complete HTTP server response header including the
  594. // status, server version, message time, and MIME version. The ISAPI
  595. // application should append other HTTP headers such as the content
  596. // type and content length, followed by an extra "\r\n". This function
  597. // only takes textual data, up to the first '\0' terminator
  598. //
  599. // In: lpEcb is the EXTENDED_CONTROL_BLOCK
  600. //
  601. BOOL SendServerHeader( LPECB lpEcb )
  602. {
  603. BOOL fReturn;
  604. CHAR szBuffer[ RESPONSE_BUF_SIZE ];
  605. DWORD dwSize, dwParam;
  606. TraceMsg( TF_FUNC | TF_RESPONSE, "SendServerHeader( )" );
  607. TraceMsg( TF_RESPONSE, "Sending Pre Header: %s", szBuffer );
  608. dwSize = wsprintf( szBuffer, "200 OK" );
  609. dwParam = 0;
  610. fReturn = ServerSupportFunction( lpEcb->ConnID, HSE_REQ_SEND_RESPONSE_HEADER,
  611. szBuffer, &dwSize, &dwParam );
  612. if ( !fReturn )
  613. goto Cleanup;
  614. TraceMsg( TF_RESPONSE, "Sending Post Header: %s", szBuffer );
  615. dwSize = wsprintf( szBuffer, "Content-Type: text/html\r\n" );
  616. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
  617. if ( !fReturn )
  618. goto Cleanup;
  619. Cleanup:
  620. TraceMsg( TF_FUNC | TF_RESPONSE, "SendServerHeader( ) Exit = %s",
  621. BOOLTOSTRING( fReturn ) );
  622. return fReturn;
  623. } // SendServerHeader( )
  624. //
  625. // What: OutputHTMLString
  626. //
  627. // Desc: Outputs HTML to client. Simply changes '\n's to <BR>s.
  628. //
  629. // In: lpEcb is the EXTENDED_CONTROL_BLOCK
  630. // lpszOut string to translate to HTML.
  631. //
  632. BOOL OutputHTMLString( LPECB lpEcb, LPSTR lpszOut )
  633. {
  634. BOOL fReturn = TRUE;
  635. LPSTR lpstr;
  636. DWORD dwSize;
  637. TraceMsg( TF_FUNC | TF_RESPONSE, "OutputHTMLString()" );
  638. if( *lpszOut )
  639. {
  640. lpstr = lpszOut;
  641. while (( *lpstr ) && ( fReturn))
  642. {
  643. lpszOut = lpstr;
  644. lpstr++;
  645. while (( *lpstr ) && ( *lpstr != '\n' ))
  646. lpstr++;
  647. CHAR cTmp = *lpstr; // save
  648. *lpstr = 0;
  649. dwSize = 1 + lstrlen( lpszOut );
  650. fReturn = WriteClient( lpEcb->ConnID, lpszOut, &dwSize, HSE_IO_ASYNC );
  651. *lpstr = cTmp; // restore
  652. if ( fReturn )
  653. {
  654. dwSize = 4;
  655. fReturn = WriteClient( lpEcb->ConnID, "<BR>", &dwSize, HSE_IO_ASYNC );
  656. }
  657. }
  658. }
  659. TraceMsg( TF_FUNC | TF_RESPONSE, "OutputHTMLString() Exit = %s",
  660. BOOLTOSTRING( fReturn ) );
  661. return fReturn;
  662. } // OutputHTMLString( )
  663. //
  664. // What: HexDump
  665. //
  666. // Desc: Dumps a HEX dump to the client using HTML. (16-byte rows)
  667. //
  668. // In: lpEcb is the EXTENDED_CONTROL_BLOCK
  669. // lpbData is the data to be dumped
  670. // dwLength is the length of the dump.
  671. // lpDT is DUMPTABLE which contains information about what the
  672. // parser found while parsing. The end of the DT is indicated
  673. // by a NULL lpAddr.
  674. //
  675. // Return: Return a pointer to the formatted output buffer.
  676. //
  677. BOOL HexDump(
  678. LPECB lpEcb,
  679. LPBYTE lpbData,
  680. DWORD dwLength,
  681. LPDUMPTABLE lpDT )
  682. {
  683. BOOL fReturn;
  684. DWORD cb = 0; // number of bytes processed
  685. DWORD cbDT = 0; // number of DTs processed
  686. DWORD cbComment = 0; // number of DT comments processed
  687. LPBYTE lpb = lpbData; // current data byte to be processed
  688. DWORD dwColor = 0x000000; // color to output text in
  689. LPBYTE lpbStartLine = lpb; // keeps track of where this line begins
  690. // for the string dump
  691. BOOL fKeepGoing = TRUE; // exit flag
  692. CHAR szBuffer[ 4096 ]; // output buffer
  693. CHAR szString[ 512 ]; // "String Dump" output buffer
  694. DWORD cbBuf, cbStr; // helper count bytes for buffers
  695. // Output Dump Header
  696. cbBuf = wsprintf( szBuffer, "\
  697. <H2>Parser Commented Request Dump</H2>\
  698. <FONT FACE=\"Courier\">\
  699. <TABLE colpadding=2>\
  700. <TR><TD>Offset</TD><TD>Hex Dump</TD><TD>String Dump</TD><TD>Comments</TD></TR>" );
  701. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &cbBuf, HSE_IO_ASYNC );
  702. while (( fReturn ) && ( fKeepGoing ))
  703. {
  704. if ( cb == 0 )
  705. { // beginning of every row....
  706. if (( cbDT )
  707. && ( ( lpDT[ cbDT ].lpAddr - lpb ) > 64 ))
  708. {
  709. // eliminates "big" body data (like binary files)
  710. cbBuf = wsprintf( szBuffer, "<TR><TD>Skipping...</TD><TD>.</TD><TD>.</TD><TD>.</TD></TR>" );
  711. // jump to one row before the next DT point
  712. lpb = (LPBYTE) ( ( ( (DWORD) lpDT[ cbDT ].lpAddr / 16 ) - 1 ) * 16 );
  713. }
  714. else
  715. {
  716. cbBuf = 0;
  717. }
  718. // Output 0xXXXXXXXX (NNNNNN): and change the color
  719. cbBuf += wsprintf( &szBuffer[ cbBuf ],
  720. "<TR><TD>0x%-8.8x (%-6.6u):</TD><TD><FONT COLOR=%-6.6x>",
  721. lpb - lpbData, lpb - lpbData, dwColor );
  722. // starting color on "String Dump"
  723. cbStr = wsprintf( szString, "<FONT COLOR=%-6.6x>", dwColor );
  724. }
  725. if ( lpb < lpbData + dwLength )
  726. { // middle of every row...
  727. // color change if needed
  728. while (( lpDT[ cbDT ].lpAddr )
  729. && ( lpb >= lpDT[ cbDT ].lpAddr ))
  730. {
  731. dwColor = lpDT[ cbDT ].dwColor;
  732. cbBuf += wsprintf( &szBuffer[ cbBuf ], "</FONT><FONT COLOR=%-6.6x>", dwColor );
  733. cbStr += wsprintf( &szString[ cbStr ], "</FONT><FONT COLOR=%-6.6x>", dwColor );
  734. cbDT++;
  735. }
  736. // output hex number
  737. cbBuf += wsprintf( &szBuffer[ cbBuf ], "%-2.2x ", *lpb );
  738. // output "String Dump" character
  739. cbStr += wsprintf( &szString[ cbStr ], "%c",
  740. ( ( *lpb < 32 || *lpb == 127 ) ? '.' : ( ( *lpb == 32 ) ? '_' : *lpb ) ) );
  741. lpb++;
  742. }
  743. cb++; // always count even if there is no more data
  744. if ( cb == 16 )
  745. { // end of every row...
  746. // terminate FONT tags and append "String Dump"
  747. cbStr += wsprintf( &szString[ cbStr ], "</FONT>" );
  748. cbBuf += wsprintf( &szBuffer[ cbBuf ], "</FONT></TD><TD>%s</TD>",
  749. szString );
  750. // skip NULL comments
  751. while (( lpDT[ cbComment ].lpAddr )
  752. && ( !lpDT[ cbComment ].lpszComment ))
  753. cbComment++;
  754. // don't allow comments to get ahead of the bits
  755. if (( lpDT[ cbComment ].lpAddr ) && ( cbComment < cbDT ))
  756. {
  757. cbBuf += wsprintf( &szBuffer[ cbBuf ],
  758. "<TD><FONT COLOR=%-6.6x>%s</FONT></TD></TR>",
  759. lpDT[ cbComment ].dwColor, lpDT[ cbComment ].lpszComment );
  760. cbComment++;
  761. }
  762. else
  763. {
  764. cbBuf += wsprintf( &szBuffer[ cbBuf ], "<TD><BR></TD></TR>" );
  765. }
  766. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &cbBuf, HSE_IO_ASYNC );
  767. cb = 0;
  768. lpbStartLine = lpb;
  769. if ( lpb >= lpbData + dwLength )
  770. fKeepGoing = FALSE;
  771. }
  772. }
  773. // end the table
  774. if ( fReturn )
  775. {
  776. cbBuf = wsprintf( szBuffer, "</TABLE></FONT>" );
  777. fReturn = WriteClient( lpEcb->ConnID, szBuffer, &cbBuf, HSE_IO_ASYNC );
  778. }
  779. return fReturn;
  780. } // HexDump( )