|
|
//
// Microsoft Corporation - Copyright 1997
//
//
// RESPONSE.CPP - Contains possible responses
//
#include "pch.h"
// Globals
const char g_cszTableHeader[] = "%s \
<TABLE ID=%s BORDER=1> \ <TR> \ <TH WIDTH=40%%>Variable Name</TH> \ <TH WIDTH=60%%>Value</TH> \ </TR>";
const char g_cszTableEnd[] = "</TABLE>";
// List of known server variables
LPSTR g_lpServerVars[] = { "AUTH_TYPE", "CONTENT_LENGTH", "CONTENT_TYPE", "GATEWAY_INTERFACE", "LOGON_USER", "PATH_INFO", "PATH_TRANSLATED", "QUERY_STRING", "REMOTE_ADDR", "REMOTE_HOST", "REQUEST_METHOD", "SCRIPT_MAP", "SCRIPT_NAME", "SERVER_NAME", "SERVER_PORT", "SERVER_PORT_SECURE", "SERVER_SOFTWARE", "URL" };
#define FROMHEX( _v ) \
( ( _v >= 48 ) && ( _v <= 57 ) ? _v - 48 : \ ( ( _v >= 65 ) && ( _v <= 70 ) ? _v + 10 - 65 : 0 ) )
//
// What: UnCanonicalize
//
// Desc: Un-escapes strings
//
BOOL UnCanonicalize( LPSTR lpszStart, LPSTR lpszUnURL , LPDWORD lpdwSize ) { LPSTR lps = lpszStart; DWORD cb = 0;
while (( *lps ) && ( cb < *lpdwSize )) { if ( *lps == '%' ) { lps++; lpszUnURL[ cb ] = 16 * FROMHEX( *lps); lps++; lpszUnURL[ cb ] += FROMHEX( *lps); } else if ( *lps == '+' ) { lpszUnURL[ cb ] = 32; } else { lpszUnURL[ cb ] = *lps; } cb++; lps++; }
lpszUnURL[ cb ] = 0; // paranoid
*lpdwSize = cb;
return TRUE;
} // UnCanonicalize( )
//
// What: DumpFormDataFromPost
//
// Desc: Dumps the fields and values in a form from a POST.
//
BOOL DumpFormDataFromPost( LPECB lpEcb ) { BOOL fReturn = TRUE; DWORD dwSize;
static char szUnparsed[] = "The unparsed Form submit string is: <FONT FACE=\"Courier New\">"; static char szUnFont[] = "</FONT>";
TraceMsg( TF_FUNC | TF_RESPONSE, "DumpFormDataFromPost()" );
if ( fReturn ) { // header and the beginning of the table
CHAR szBuffer[ 512 ]; dwSize = wsprintf( szBuffer, g_cszTableHeader, "<H2>Form Data (METHOD=POST)</H2>", "TBLPOST" ); fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC ); }
if ( fReturn ) { int i = 0; LPSTR lpszStart = (LPSTR) lpEcb->lpbData; while (( fReturn ) && ( lpszStart )) { CHAR cTmpEnd; LPSTR lpszEquals = StrChr( lpszStart, '=' ); if ( !lpszEquals ) break; // no more data
LPSTR lpszEnd = StrChr( lpszEquals, '&' );
if ( lpszEnd ) { cTmpEnd = *lpszEnd; // save
*lpszEnd = 0; }
CHAR cTmp = *lpszEquals; // save
*lpszEquals = 0;
CHAR szBuffer[ 4096 ]; CHAR szUnURL[ 2048 ]; dwSize = sizeof( szUnURL ); fReturn = UnCanonicalize( lpszEquals + 1, szUnURL, &dwSize ); if ( fReturn ) { dwSize = wsprintf( szBuffer, "<TR ID=TR%u><TD ID=TD%u>%s</TD><TD ID=%s>%s</TD></TR>", i, i, lpszStart, lpszStart, szUnURL ); fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC ); }
*lpszEquals = cTmp; // restore
if ( lpszEnd ) { *lpszEnd = cTmpEnd; // restore
lpszEnd++; }
lpszStart = lpszEnd; i++; } }
// end of the table
if ( fReturn ) { dwSize = 1 + lstrlen( g_cszTableEnd ); fReturn = WriteClient( lpEcb->ConnID, (LPVOID) g_cszTableEnd, &dwSize, HSE_IO_ASYNC ); }
// display unparsed information
if ( fReturn ) { dwSize = 1 + lstrlen( szUnparsed ); fReturn = WriteClient( lpEcb->ConnID, szUnparsed, &dwSize, HSE_IO_ASYNC ); }
if ( fReturn ) { dwSize = 1 + lstrlen( (LPSTR) lpEcb->lpbData ); fReturn = WriteClient( lpEcb->ConnID, lpEcb->lpbData, &dwSize, HSE_IO_ASYNC ); }
// end FONT tag
if ( fReturn ) { dwSize = 1 + lstrlen( szUnFont ); fReturn = WriteClient( lpEcb->ConnID, szUnFont, &dwSize, HSE_IO_ASYNC ); }
TraceMsg( TF_FUNC | TF_RESPONSE, "DumpFormDataFromPost() Exit = %s", BOOLTOSTRING( fReturn ) ); return fReturn;
} // DumpFormDataFromPost( )
//
// What: DumpQueryStringDataFromGet
//
// Desc: Dumps the fields and values in a form from a GET.
//
BOOL DumpQueryStringDataFromGet( LPECB lpEcb ) { BOOL fReturn = TRUE; LPSTR lpszBuffer; DWORD dwSize;
static char szUnparsed[] = "The unparsed QueryString is: <FONT FACE=\"Courier New\">"; static char szUnFont[] = "</FONT>";
TraceMsg( TF_FUNC | TF_RESPONSE, "DumpQueryStringDataFromGet()" );
if ( fReturn ) fReturn = GetServerVarString( lpEcb, "QUERY_STRING", &lpszBuffer, NULL );
if ( fReturn ) { // header and the beginning of the table
CHAR szBuffer[ 512 ]; dwSize = wsprintf( szBuffer, g_cszTableHeader, "<H2>QueryString Data(METHOD=GET)</H2>", "TBLGET" ); fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC ); }
if ( fReturn ) { int i = 0; LPSTR lpszStart = lpszBuffer; while (( fReturn ) && ( lpszStart )) { CHAR cTmpEnd; LPSTR lpszEquals = StrChr( lpszStart, '=' ); LPSTR lpszEnd = StrChr( lpszEquals, '&' );
if ( lpszEnd ) { cTmpEnd = *lpszEnd; // save
*lpszEnd = 0; }
CHAR cTmp = *lpszEquals; // save
*lpszEquals = 0;
CHAR szBuffer[ 4096 ]; CHAR szUnURL[ 2048 ]; dwSize = sizeof( szUnURL ); fReturn = UnCanonicalize( lpszEquals + 1, szUnURL, &dwSize ); if ( fReturn ) { dwSize = wsprintf( szBuffer, "<TR ID=TR%u><TD ID=TD%u>%s</TD><TD ID=%s>%s</TD></TR>", i, i, lpszStart, lpszStart, szUnURL ); fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC ); }
*lpszEquals = cTmp; // restore
if ( lpszEnd ) { *lpszEnd = cTmpEnd; // restore
lpszEnd++; }
lpszStart = lpszEnd; i++; } }
// end the table
if ( fReturn ) { dwSize = 1 + lstrlen( g_cszTableEnd ); fReturn = WriteClient( lpEcb->ConnID, (LPVOID) g_cszTableEnd, &dwSize, HSE_IO_ASYNC ); }
// display unparsed information
if ( fReturn ) { dwSize = 1 + lstrlen( szUnparsed ); fReturn = WriteClient( lpEcb->ConnID, szUnparsed, &dwSize, HSE_IO_ASYNC ); }
if ( fReturn ) { dwSize = 1 + lstrlen( lpszBuffer ); fReturn = WriteClient( lpEcb->ConnID, lpszBuffer, &dwSize, HSE_IO_ASYNC ); }
// end font tag
if ( fReturn ) { dwSize = 1 + lstrlen( szUnFont ); fReturn = WriteClient( lpEcb->ConnID, szUnFont, &dwSize, HSE_IO_ASYNC ); }
// clean up
if ( lpszBuffer ) GlobalFree( lpszBuffer );
TraceMsg( TF_FUNC | TF_RESPONSE, "DumpQueryStringDataFromGet() Exit = %s", BOOLTOSTRING( fReturn ) ); return fReturn;
} // DumpQueryStringDataFromGet( )
//
// What: DumpServerVariables
//
// Desc: Dumps the current server variable settings from the result of
// a form submission.
//
BOOL DumpServerVariables( LPECB lpEcb ) { BOOL fReturn = TRUE; LPSTR lpszBuffer; DWORD dwSize; int i = 0; // counter
TraceMsg( TF_FUNC | TF_RESPONSE, "DumpServerVariables()" );
if ( fReturn ) { // header and the begging of the table
CHAR szBuffer[ 512 ]; dwSize = wsprintf( szBuffer, g_cszTableHeader, "<H2>Server Variables</H2>", "TBLSERVERVARS" ); fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC ); }
// try the known ones
for( ; ( fReturn ) && ( i < ARRAYOF( g_lpServerVars ) ); i++ ) { GetServerVarString( lpEcb, g_lpServerVars[ i ], &lpszBuffer, NULL );
if ( lpszBuffer ) { CHAR szBuffer[ 512 ]; dwSize = wsprintf( szBuffer, "<TR ID=TR%u><TD ID=TD%u>%s</TD><TD ID=%s>%s</TD></TR>", i, i, g_lpServerVars[ i ], g_lpServerVars[ i ], lpszBuffer ); fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC ); }
GlobalFree( lpszBuffer ); lpszBuffer = NULL; }
// try the HTTP_ALL from header that the server ignores
if ( fReturn ) fReturn = GetServerVarString( lpEcb, "ALL_HTTP", &lpszBuffer, NULL );
if (( fReturn ) && ( lpszBuffer )) { LPSTR lpszStart = lpszBuffer; while (( fReturn ) && ( lpszStart )) { char cTmpEnd;
LPSTR lpszColon = StrChr( lpszStart, ':' ); LPSTR lpszEnd = StrStr( lpszColon, "HTTP_" ); if ( lpszEnd ) { cTmpEnd = *lpszEnd; // save
*lpszEnd = 0; }
char cTmp = *lpszColon; // save
*lpszColon = 0;
CHAR szBuffer[ 4096 ]; dwSize = wsprintf( szBuffer, "<TR ID=TR%u><TD ID=TD%u>%s</TD><TD ID=%s>%s</TD></TR>", i, i, lpszStart, lpszStart, lpszColon + 1 ); fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
*lpszColon = cTmp; // restore
if ( lpszEnd ) *lpszEnd = cTmpEnd; // restore
lpszStart = lpszEnd; i++; } }
// end the table
if ( fReturn ) { dwSize = 1 + lstrlen( g_cszTableEnd ); fReturn = WriteClient( lpEcb->ConnID, (LPVOID) g_cszTableEnd, &dwSize, HSE_IO_ASYNC ); }
// clean up
GlobalFree( lpszBuffer ); lpszBuffer = NULL;
TraceMsg( TF_FUNC | TF_RESPONSE, "DumpServerVariables() Exit = %s", BOOLTOSTRING( fReturn ) ); return fReturn;
} // ( )
//
// What: DumpOutput
//
// Desc: Generate reponse body page after headers and the HTML header
// has been.
//
BOOL DumpOutput( QUERYMETHOD eMethod, LPECB lpEcb, LPSTR lpszOut, LPSTR lpszDebug ) { BOOL fReturn; DWORD dwSize; char szBuffer[ RESPONSE_BUF_SIZE ];
TraceMsg( TF_FUNC | TF_RESPONSE, "DumpOutput()" );
// Display form data
switch ( eMethod ) { case METHOD_POST: fReturn = DumpFormDataFromPost( lpEcb ); break;
case METHOD_GET: fReturn = DumpQueryStringDataFromGet( lpEcb ); break;
case METHOD_POSTTEXTPLAIN: case METHOD_POSTMULTIPART: if ( lpszOut ) { dwSize = 1 + lstrlen( lpszOut ); fReturn = WriteClient( lpEcb->ConnID, lpszOut, &dwSize, HSE_IO_ASYNC ); } break;
default: StrCpy( szBuffer, "<H2>???? (METHOD=UNKNOWN)</H2>" ); dwSize = 1 + lstrlen( szBuffer ); fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC ); }
// Dump the server variables
if ( fReturn ) fReturn = DumpServerVariables( lpEcb );
// Dump any debugging messages
if (( fReturn ) && ( lpszDebug )) { StrCpy( szBuffer, "<H2>Debugging Output</H2>" ); dwSize = 1 + lstrlen( szBuffer ); fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC );
if ( fReturn ) fReturn = OutputHTMLString( lpEcb, lpszDebug ); }
// Dump any server log entries
if (( fReturn ) && ( lpEcb->lpszLogData[ 0 ] )) { StrCpy( szBuffer, "<H2>Server Log Entry</H2>" ); dwSize = 1 + lstrlen( szBuffer ); fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC ); if ( fReturn ) { dwSize = 1 + lstrlen( lpEcb->lpszLogData ); fReturn = WriteClient( lpEcb->ConnID, lpEcb->lpszLogData, &dwSize, HSE_IO_ASYNC ); } }
TraceMsg( TF_FUNC | TF_RESPONSE, "DumpOutput() Exit = %s", BOOLTOSTRING( fReturn ) ); return fReturn;
} // DumpOutput( )
//
// What: SendSuccess
//
// Desc: Sends client an HTML response for a successful upload. Just a
// green screen with "SUCCESS!" in a big header.
//
// In: lpEcb is the EXTENDED_CONTROL_BLOCK that the server sent us.
//
BOOL SendSuccess( QUERYMETHOD eMethod, LPECB lpEcb, LPSTR lpszOut, LPSTR lpszDebug, LPBYTE lpbData, DWORD dwParsed, LPDUMPTABLE lpDT ) { BOOL fReturn = TRUE; // assume success
CHAR szBuffer[ RESPONSE_BUF_SIZE ]; DWORD dwSize; BOOL fDebug = FALSE;
TraceMsg( TF_FUNC | TF_RESPONSE, "SendSuccess( )" );
// Generate on the fly so
// fReturn = SendServerHeader( lpEcb );
if ( fReturn ) { StrCpy( szBuffer, "\
<HTML>\ <HEAD>\ <TITLE>Form Submission Reflector</TITLE>\ </HEAD>\ <BODY bgcolor=#00FF00>\ <FONT FACE=\"ARIAL,HELVETICA\" SIZE=2>\
Submission Result <INPUT TYPE=TEXT NAME=RESULT VALUE=\"SUCCESS!\">" ); dwSize = 1 + lstrlen( szBuffer ); fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC ); }
if ( fReturn ) fReturn = CheckForDebug( lpEcb, &fDebug );
if ( fReturn ) { if ( fDebug ) fReturn = DumpOutput( eMethod, lpEcb, lpszOut, lpszDebug ); else fReturn = DumpOutput( eMethod, lpEcb, lpszOut, NULL ); }
if (( fReturn ) && ( fDebug )) fReturn = HexDump( lpEcb, lpbData, dwParsed, lpDT );
if ( fReturn ) { StrCpy( szBuffer, "</BODY></HTML>" ); dwSize = 1 + lstrlen( szBuffer ); fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC ); }
TraceMsg( TF_FUNC | TF_RESPONSE, "SendSuccess( ) Exit = %s", BOOLTOSTRING( fReturn ) ); return fReturn; } // SendSuccess( )
//
// What: SendFailure
//
// Desc: Sends client an HTML response for a failed upload. Just a
// red screen with "FAILED!" in a big header.
//
// In: lpEcb is the EXTENDED_CONTROL_BLOCK that the server sent us.
//
BOOL SendFailure( QUERYMETHOD eMethod, LPECB lpEcb, LPSTR lpszOut, LPSTR lpszDebug, LPBYTE lpbData, DWORD dwParsed, LPDUMPTABLE lpDT ) { BOOL fReturn = TRUE; // assume success
CHAR szBuffer[ RESPONSE_BUF_SIZE ]; DWORD dwSize; BOOL fDebug = FALSE;
TraceMsg( TF_FUNC | TF_RESPONSE, "SendFailure( )" );
// fReturn = SendServerHeader( lpEcb );
if ( fReturn ) { StrCpy( szBuffer, "\
<HTML>\ <HEAD>\ <TITLE>Form Submission Reflector</TITLE>\ </HEAD>\ <BODY bgcolor=#FF0000>\ <FONT FACE=\"ARIAL,HELVETICA\" SIZE=2>\
Submission Result <INPUT TYPE=TEXT NAME=RESULT VALUE=\"FAILED!\">" ); dwSize = 1 + lstrlen( szBuffer ); fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC ); }
if ( fReturn ) fReturn = CheckForDebug( lpEcb, &fDebug );
if ( fReturn ) { if ( fDebug ) fReturn = DumpOutput( eMethod, lpEcb, lpszOut, lpszDebug ); else fReturn = DumpOutput( eMethod, lpEcb, lpszOut, NULL ); }
if (( fReturn ) && ( fDebug )) fReturn = HexDump( lpEcb, lpbData, dwParsed, lpDT );
if ( fReturn ) { StrCpy( szBuffer, "</BODY></HTML>" ); dwSize = 1 + lstrlen( szBuffer ); fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC ); }
TraceMsg( TF_FUNC | TF_RESPONSE, "SendFailure( ) Exit = %s", BOOLTOSTRING( fReturn ) ); return fReturn; } // SendSuccess( )
//
// What: SendRedirect
//
// Desc: Redirects to another URL.
//
// In: lpEcb is the EXTENDED_CONTROL_BLOCK that the server sent us.
//
BOOL SendRedirect( LPECB lpEcb, LPSTR lpszURL ) { BOOL fReturn = TRUE; // assume success
CHAR szBuffer[ RESPONSE_BUF_SIZE ]; DWORD dwSize = 1 + lstrlen( lpszURL ); DWORD dw;
TraceMsg( TF_FUNC | TF_RESPONSE, "SendRedirect( )" );
fReturn = ServerSupportFunction( lpEcb->ConnID, HSE_REQ_SEND_URL_REDIRECT_RESP, lpszURL, &dwSize, &dw );
TraceMsg( TF_FUNC | TF_RESPONSE, "SendRedirect( ) Exit = %s", BOOLTOSTRING( fReturn ) ); return fReturn; } // SendSuccess( )
//
// What: SendEcho
//
// Desc: Sends client an echo for everything that it sent to us.
//
// In: lpEcb is the EXTENDED_CONTROL_BLOCK
//
BOOL SendEcho( LPECB lpEcb ) { BOOL fReturn = TRUE; // assume success
CHAR szBuffer[ RESPONSE_BUF_SIZE ]; DWORD dwSize; LPVOID lpMoreData = NULL;
TraceMsg( TF_FUNC | TF_RESPONSE, "SendEcho( )" );
BOOL fDownloadComplete = (lpEcb->cbTotalBytes == lpEcb->cbAvailable );
TraceMsg( TF_RESPONSE, "Does cbTotalBytes(%u) == cbAvailable(%u)? %s", lpEcb->cbTotalBytes, lpEcb->cbAvailable, BOOLTOSTRING( fDownloadComplete ) );
if ( !fDownloadComplete ) { // Get the rest of the data
dwSize = lpEcb->cbTotalBytes - lpEcb->cbAvailable; lpMoreData = (LPVOID) GlobalAlloc( GPTR, dwSize ); fReturn = ReadData( lpEcb, lpMoreData, dwSize ); if ( !fReturn ) goto Cleanup; }
TraceMsg( TF_RESPONSE, "Total Bytes: %u\n%s", lpEcb->cbAvailable, lpEcb->lpbData );
// Server header info...
fReturn = SendServerHeader( lpEcb ); if ( !fReturn ) goto Cleanup;
// Create top part of response and send it
StrCpy( szBuffer, "<HTML><BODY bgcolor=#0000FF><PRE>" ); dwSize = 1 + lstrlen( szBuffer ); fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC ); if ( !fReturn ) goto Cleanup;
// and echo it back...
dwSize = lpEcb->cbAvailable; fReturn = WriteClient( lpEcb->ConnID, lpEcb->lpbData, &dwSize, HSE_IO_ASYNC ); if ( !fReturn ) goto Cleanup;
// and anything else that was sent...
if ( lpMoreData ) { dwSize = lpEcb->cbTotalBytes - lpEcb->cbAvailable; fReturn = WriteClient( lpEcb->ConnID, lpMoreData, &dwSize, HSE_IO_ASYNC ); if ( !fReturn ) goto Cleanup; }
// Create bottom part of response and send it
StrCpy( szBuffer, "</PRE></BODY></HTML>" ); dwSize = 1 + lstrlen( szBuffer ); fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC ); if ( !fReturn ) goto Cleanup;
Cleanup: if ( lpMoreData ) GlobalFree( lpMoreData );
TraceMsg( TF_FUNC | TF_RESPONSE, "SendEcho( ) Exit = %s", BOOLTOSTRING( fReturn ) ); return fReturn; } // SendEcho( )
//
// What: SendServerHeader
//
// Desc: This sends a complete HTTP server response header including the
// status, server version, message time, and MIME version. The ISAPI
// application should append other HTTP headers such as the content
// type and content length, followed by an extra "\r\n". This function
// only takes textual data, up to the first '\0' terminator
//
// In: lpEcb is the EXTENDED_CONTROL_BLOCK
//
BOOL SendServerHeader( LPECB lpEcb ) { BOOL fReturn; CHAR szBuffer[ RESPONSE_BUF_SIZE ]; DWORD dwSize, dwParam;
TraceMsg( TF_FUNC | TF_RESPONSE, "SendServerHeader( )" );
TraceMsg( TF_RESPONSE, "Sending Pre Header: %s", szBuffer );
dwSize = wsprintf( szBuffer, "200 OK" ); dwParam = 0; fReturn = ServerSupportFunction( lpEcb->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, szBuffer, &dwSize, &dwParam ); if ( !fReturn ) goto Cleanup;
TraceMsg( TF_RESPONSE, "Sending Post Header: %s", szBuffer );
dwSize = wsprintf( szBuffer, "Content-Type: text/html\r\n" );
fReturn = WriteClient( lpEcb->ConnID, szBuffer, &dwSize, HSE_IO_ASYNC ); if ( !fReturn ) goto Cleanup;
Cleanup: TraceMsg( TF_FUNC | TF_RESPONSE, "SendServerHeader( ) Exit = %s", BOOLTOSTRING( fReturn ) ); return fReturn;
} // SendServerHeader( )
//
// What: OutputHTMLString
//
// Desc: Outputs HTML to client. Simply changes '\n's to <BR>s.
//
// In: lpEcb is the EXTENDED_CONTROL_BLOCK
// lpszOut string to translate to HTML.
//
BOOL OutputHTMLString( LPECB lpEcb, LPSTR lpszOut ) { BOOL fReturn = TRUE; LPSTR lpstr; DWORD dwSize;
TraceMsg( TF_FUNC | TF_RESPONSE, "OutputHTMLString()" );
if( *lpszOut ) { lpstr = lpszOut; while (( *lpstr ) && ( fReturn)) { lpszOut = lpstr; lpstr++;
while (( *lpstr ) && ( *lpstr != '\n' )) lpstr++;
CHAR cTmp = *lpstr; // save
*lpstr = 0;
dwSize = 1 + lstrlen( lpszOut ); fReturn = WriteClient( lpEcb->ConnID, lpszOut, &dwSize, HSE_IO_ASYNC );
*lpstr = cTmp; // restore
if ( fReturn ) { dwSize = 4; fReturn = WriteClient( lpEcb->ConnID, "<BR>", &dwSize, HSE_IO_ASYNC ); } } }
TraceMsg( TF_FUNC | TF_RESPONSE, "OutputHTMLString() Exit = %s", BOOLTOSTRING( fReturn ) ); return fReturn; } // OutputHTMLString( )
//
// What: HexDump
//
// Desc: Dumps a HEX dump to the client using HTML. (16-byte rows)
//
// In: lpEcb is the EXTENDED_CONTROL_BLOCK
// lpbData is the data to be dumped
// dwLength is the length of the dump.
// lpDT is DUMPTABLE which contains information about what the
// parser found while parsing. The end of the DT is indicated
// by a NULL lpAddr.
//
// Return: Return a pointer to the formatted output buffer.
//
BOOL HexDump( LPECB lpEcb, LPBYTE lpbData, DWORD dwLength, LPDUMPTABLE lpDT ) { BOOL fReturn; DWORD cb = 0; // number of bytes processed
DWORD cbDT = 0; // number of DTs processed
DWORD cbComment = 0; // number of DT comments processed
LPBYTE lpb = lpbData; // current data byte to be processed
DWORD dwColor = 0x000000; // color to output text in
LPBYTE lpbStartLine = lpb; // keeps track of where this line begins
// for the string dump
BOOL fKeepGoing = TRUE; // exit flag
CHAR szBuffer[ 4096 ]; // output buffer
CHAR szString[ 512 ]; // "String Dump" output buffer
DWORD cbBuf, cbStr; // helper count bytes for buffers
// Output Dump Header
cbBuf = wsprintf( szBuffer, "\
<H2>Parser Commented Request Dump</H2>\ <FONT FACE=\"Courier\">\
<TABLE colpadding=2>\ <TR><TD>Offset</TD><TD>Hex Dump</TD><TD>String Dump</TD><TD>Comments</TD></TR>" );
fReturn = WriteClient( lpEcb->ConnID, szBuffer, &cbBuf, HSE_IO_ASYNC );
while (( fReturn ) && ( fKeepGoing )) { if ( cb == 0 ) { // beginning of every row....
if (( cbDT ) && ( ( lpDT[ cbDT ].lpAddr - lpb ) > 64 )) { // eliminates "big" body data (like binary files)
cbBuf = wsprintf( szBuffer, "<TR><TD>Skipping...</TD><TD>.</TD><TD>.</TD><TD>.</TD></TR>" );
// jump to one row before the next DT point
lpb = (LPBYTE) ( ( ( (DWORD) lpDT[ cbDT ].lpAddr / 16 ) - 1 ) * 16 ); } else { cbBuf = 0; }
// Output 0xXXXXXXXX (NNNNNN): and change the color
cbBuf += wsprintf( &szBuffer[ cbBuf ], "<TR><TD>0x%-8.8x (%-6.6u):</TD><TD><FONT COLOR=%-6.6x>", lpb - lpbData, lpb - lpbData, dwColor );
// starting color on "String Dump"
cbStr = wsprintf( szString, "<FONT COLOR=%-6.6x>", dwColor ); }
if ( lpb < lpbData + dwLength ) { // middle of every row...
// color change if needed
while (( lpDT[ cbDT ].lpAddr ) && ( lpb >= lpDT[ cbDT ].lpAddr )) { dwColor = lpDT[ cbDT ].dwColor; cbBuf += wsprintf( &szBuffer[ cbBuf ], "</FONT><FONT COLOR=%-6.6x>", dwColor );
cbStr += wsprintf( &szString[ cbStr ], "</FONT><FONT COLOR=%-6.6x>", dwColor );
cbDT++; }
// output hex number
cbBuf += wsprintf( &szBuffer[ cbBuf ], "%-2.2x ", *lpb );
// output "String Dump" character
cbStr += wsprintf( &szString[ cbStr ], "%c", ( ( *lpb < 32 || *lpb == 127 ) ? '.' : ( ( *lpb == 32 ) ? '_' : *lpb ) ) );
lpb++;
}
cb++; // always count even if there is no more data
if ( cb == 16 ) { // end of every row...
// terminate FONT tags and append "String Dump"
cbStr += wsprintf( &szString[ cbStr ], "</FONT>" ); cbBuf += wsprintf( &szBuffer[ cbBuf ], "</FONT></TD><TD>%s</TD>", szString );
// skip NULL comments
while (( lpDT[ cbComment ].lpAddr ) && ( !lpDT[ cbComment ].lpszComment )) cbComment++;
// don't allow comments to get ahead of the bits
if (( lpDT[ cbComment ].lpAddr ) && ( cbComment < cbDT )) { cbBuf += wsprintf( &szBuffer[ cbBuf ], "<TD><FONT COLOR=%-6.6x>%s</FONT></TD></TR>", lpDT[ cbComment ].dwColor, lpDT[ cbComment ].lpszComment ); cbComment++; } else { cbBuf += wsprintf( &szBuffer[ cbBuf ], "<TD><BR></TD></TR>" ); }
fReturn = WriteClient( lpEcb->ConnID, szBuffer, &cbBuf, HSE_IO_ASYNC );
cb = 0; lpbStartLine = lpb;
if ( lpb >= lpbData + dwLength ) fKeepGoing = FALSE; } }
// end the table
if ( fReturn ) { cbBuf = wsprintf( szBuffer, "</TABLE></FONT>" ); fReturn = WriteClient( lpEcb->ConnID, szBuffer, &cbBuf, HSE_IO_ASYNC ); }
return fReturn; } // HexDump( )
|