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.
 
 
 
 
 
 

584 lines
11 KiB

/*
* H T M L M A P . C P P
*
* HTML .MAP file processing
*
* Copyright 1986-1997 Microsoft Corporation, All Rights Reserved
*/
#include "_davprs.h"
#include <htmlmap.h>
// .MAP file parsing ---------------------------------------------------------
//
// This code has been stolen from IIS and rewritten to work within the
// DAV/Caligula sources. The original code can be found in the IIS slm
// project at \\kernel\razzle3\slm\iis\svcs\w3\server\doget.cxx.
//
#define SQR(x) ((x) * (x))
#define MAXVERTS 160
#define X 0
#define Y 1
inline bool IsWhiteA (CHAR ch)
{
return ((ch) == '\t' || (ch) == ' ' || (ch) == '\r');
}
inline CHAR * SkipNonWhite( CHAR * pch )
{
while (*pch && !IsWhiteA(*pch))
pch++;
return pch;
}
inline CHAR * SkipWhite( CHAR * pch )
{
while (IsWhiteA(*pch) || (*pch == ')') || (*pch == '('))
pch++;
return pch;
}
int GetNumber( CHAR ** ppch )
{
CHAR * pch = *ppch;
INT n;
// Make sure we don't get into the URL
//
while ( *pch &&
!isdigit( *pch ) &&
!isalpha( *pch ) &&
*pch != '/' &&
*pch != '\r' &&
*pch != '\n' )
{
pch++;
}
if ( !isdigit( *pch ) )
return -1;
n = atoi( pch );
while ( isdigit( *pch ))
pch++;
*ppch = pch;
return n;
}
int pointinpoly(int point_x, int point_y, double pgon[MAXVERTS][2])
{
int i, numverts, inside_flag, xflag0;
int crossings;
double *p, *stop;
double tx, ty, y;
for (i = 0; pgon[i][X] != -1 && i < MAXVERTS; i++)
;
numverts = i;
crossings = 0;
tx = (double) point_x;
ty = (double) point_y;
y = pgon[numverts - 1][Y];
p = (double *) pgon + 1;
if ((y >= ty) != (*p >= ty))
{
if ((xflag0 = (pgon[numverts - 1][X] >= tx)) == (*(double *) pgon >= tx))
{
if (xflag0)
crossings++;
}
else
{
crossings += (pgon[numverts - 1][X] - (y - ty) *
(*(double *) pgon - pgon[numverts - 1][X]) /
(*p - y)) >= tx;
}
}
stop = pgon[numverts];
for (y = *p, p += 2; p < stop; y = *p, p += 2)
{
if (y >= ty)
{
while ((p < stop) && (*p >= ty))
p += 2;
if (p >= stop)
break;
if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx))
{
if (xflag0)
crossings++;
}
else
{
crossings += (*(p - 3) - (*(p - 2) - ty) *
(*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
}
}
else
{
while ((p < stop) && (*p < ty))
p += 2;
if (p >= stop)
break;
if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx))
{
if (xflag0)
crossings++;
}
else
{
crossings += (*(p - 3) - (*(p - 2) - ty) *
(*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
}
}
}
inside_flag = crossings & 0x01;
return (inside_flag);
}
BOOL
FSearchMapFile (LPCSTR pszMap,
INT x,
INT y,
BOOL * pfRedirect,
LPSTR pszRedirect,
UINT cchBuf)
{
BOOL fRet = FALSE;
CHAR * pch;
CHAR * pchDefault = NULL;
CHAR * pchPoint = NULL;
CHAR * pchStart;
UINT cchUrl;
UINT dis;
UINT bdis = static_cast<UINT>(-1);
BOOL fComment = FALSE;
BOOL fIsNCSA = FALSE;
LPSTR pURL; // valid only if fIsNCSA is TRUE
// We should now be ready to parse the map. Here is where the
// IIS code begins.
//
fRet = TRUE;
// Loop through the contents of the buffer and see what we've got
//
for (pch = const_cast<CHAR *>(pszMap); *pch; )
{
fIsNCSA = FALSE;
// note: _tolower doesn't check case (tolower does)
//
switch( ( *pch >= 'A' && *pch <= 'Z' ) ? _tolower( *pch ) : *pch )
{
case '#':
fComment = TRUE;
break;
case '\r':
case '\n':
fComment = FALSE;
break;
// Rectangle
//
case 'r':
case 'o':
// In the IIS code, "oval" and "rect" are treated the
// same. The code is commented with a BUGBUG comment.
//
if( !fComment &&
( !_strnicmp( "rect", pch, 4)
// BUGBUG handles oval as a rect, as they are using
// the same specification format. Should do better.
|| !_strnicmp( "oval", pch, 4 )) )
{
INT x1, y1, x2, y2;
pch = SkipNonWhite( pch );
pURL = pch;
pch = SkipWhite( pch );
if( !isdigit(*pch) && *pch!='(' )
{
fIsNCSA = TRUE;
pch = SkipNonWhite( pch );
}
x1 = GetNumber( &pch );
y1 = GetNumber( &pch );
x2 = GetNumber( &pch );
y2 = GetNumber( &pch );
if ( x >= x1 && x < x2 &&
y >= y1 && y < y2 )
{
if ( fIsNCSA )
pch = pURL;
goto Found;
}
// Skip the URL
//
if( !fIsNCSA )
{
pch = SkipWhite( pch );
pch = SkipNonWhite( pch );
}
continue;
}
break;
// Circle
//
case 'c':
if ( !fComment &&
!_strnicmp( "circ", pch, 4 ))
{
INT xCenter, yCenter, xEdge, yEdge;
INT r1, r2;
pch = SkipNonWhite( pch );
pURL = pch;
pch = SkipWhite( pch );
if ( !isdigit(*pch) && *pch!='(' )
{
fIsNCSA = TRUE;
pch = SkipNonWhite( pch );
}
// Get the center and edge of the circle
//
xCenter = GetNumber( &pch );
yCenter = GetNumber( &pch );
xEdge = GetNumber( &pch );
yEdge = GetNumber( &pch );
// If there's a yEdge, then we have the NCSA format, otherwise
// we have the CERN format, which specifies a radius
//
if ( yEdge != -1 )
{
r1 = ((yCenter - yEdge) * (yCenter - yEdge)) +
((xCenter - xEdge) * (xCenter - xEdge));
r2 = ((yCenter - y) * (yCenter - y)) +
((xCenter - x) * (xCenter - x));
if ( r2 <= r1 )
{
if ( fIsNCSA )
pch = pURL;
goto Found;
}
}
else
{
INT radius;
// CERN format, third param is the radius
//
radius = xEdge;
if ( SQR( xCenter - x ) + SQR( yCenter - y ) <=
SQR( radius ))
{
if ( fIsNCSA )
pch = pURL;
goto Found;
}
}
// Skip the URL
//
if ( !fIsNCSA )
{
pch = SkipWhite( pch );
pch = SkipNonWhite( pch );
}
continue;
}
break;
// Polygon
//
case 'p':
if ( !fComment &&
!_strnicmp( "poly", pch, 4 ))
{
double pgon[MAXVERTS][2];
DWORD i = 0;
BOOL fOverflow = FALSE;
pch = SkipNonWhite( pch );
pURL = pch;
pch = SkipWhite( pch );
if ( !isdigit(*pch) && *pch!='(' )
{
fIsNCSA = TRUE;
pch = SkipNonWhite( pch );
}
// Build the array of points
//
while ( *pch && *pch != '\r' && *pch != '\n' )
{
pgon[i][0] = GetNumber( &pch );
//
// Did we hit the end of the line (and go past the URL)?
//
if ( pgon[i][0] != -1 )
{
pgon[i][1] = GetNumber( &pch );
}
else
{
break;
}
if ( i < MAXVERTS-1 )
{
i++;
}
else
{
fOverflow = TRUE;
}
}
pgon[i][X] = -1;
if ( !fOverflow && pointinpoly( x, y, pgon ))
{
if ( fIsNCSA )
pch = pURL;
goto Found;
}
// Skip the URL
//
if ( !fIsNCSA )
{
pch = SkipWhite( pch );
pch = SkipNonWhite( pch );
}
continue;
}
else if ( !fComment &&
!_strnicmp( "point", pch, 5 ))
{
INT x1,y1;
pch = SkipNonWhite( pch );
pURL = pch;
pch = SkipWhite( pch );
pch = SkipNonWhite( pch );
x1 = GetNumber( &pch );
y1 = GetNumber( &pch );
x1 -= x;
y1 -= y;
dis = x1*x1 + y1*y1;
if ( dis < bdis )
{
pchPoint = pURL;
bdis = dis;
}
}
break;
// Default URL
//
case 'd':
if ( !fComment &&
!_strnicmp( "def", pch, 3 ) )
{
//
// Skip "default" (don't skip white space)
//
pch = SkipNonWhite( pch );
pchDefault = pch;
//
// Skip URL
//
pch = SkipWhite( pch );
pch = SkipNonWhite( pch );
continue;
}
break;
}
pch++;
pch = SkipWhite( pch );
}
// If we didn't find a mapping and a default was specified, use
// the default URL
//
if ( pchPoint )
{
pch = pchPoint;
goto Found;
}
if ( pchDefault )
{
pch = pchDefault;
goto Found;
}
DebugTrace ("Dav: no mapping found for (%d, %d)\n", x, y);
goto Exit;
Found:
// pch should point to the white space immediately before the URL
//
pch = SkipWhite( pch );
pchStart = pch;
pch = SkipNonWhite( pch );
// Determine the length of the URL and copy it out
//
cchUrl = static_cast<UINT>(pch - pchStart);
if ( cchUrl >= cchBuf )
return FALSE;
CopyMemory (pszRedirect, pchStart, cchUrl);
*(pszRedirect + cchUrl) = 0;
*pfRedirect = TRUE;
DebugTrace ("Dav: mapping for (%d, %d) is %hs\n", x, y, pszRedirect);
Exit:
return fRet;
}
BOOL
FIsMapProcessed (
LPCSTR lpszQueryString,
LPCSTR lpszUrlPrefix,
LPCSTR lpszServerName,
LPCSTR pszMap,
BOOL * pfRedirect,
LPSTR pszRedirect,
UINT cchBuf)
{
INT x = 0;
INT y = 0;
LPCSTR pch = lpszQueryString;
// Ensure the *pfRedirect is initialized
//
Assert( pfRedirect );
*pfRedirect = FALSE;
// If there is no query string, I don't think we want to process
// the file as if it were a .map request.
//
if ( pch == NULL )
return TRUE;
// Get the x and y cooridinates of the mouse click on the image
//
x = strtoul( pch, NULL, 10 );
// Move past x and any intervening delimiters
//
while ( isdigit( *pch ))
pch++;
while ( *pch && !isdigit( *pch ))
pch++;
y = strtoul( pch, NULL, 10 );
// Search the map file
//
if ( !FSearchMapFile( pszMap,
x,
y,
pfRedirect,
pszRedirect,
cchBuf))
{
DebugTrace ("Dav: FSearchMapFile() failed with %ld\n", GetLastError());
return FALSE;
}
// If no redirected URL was passed back, then we are done.
//
if ( !*pfRedirect )
{
// Returning true does not indicate success, it really
// just means that there were no processing errors
//
goto ret;
}
// If the found URL starts with a forward slash ("/foo/bar/doc.htm")
// and it doesn't contain a bookmark ('#') then the URL is local and
// we build a fully qualified URL to send back to the client. We assume
// it's a fully qualified URL ("http://foo/bar/doc.htm") and send the
// client a redirection notice to the mapped URL
//
if ( *pszRedirect == '/' )
{
CHAR rgch[MAX_PATH];
UINT cch;
UINT cchUri;
if ( strlen(lpszUrlPrefix) + strlen(lpszServerName) >= MAX_PATH)
return FALSE;
// Build up the full qualification to the url
//
strcpy (rgch, lpszUrlPrefix);
strcat (rgch, lpszServerName);
// See how much we need to shif the URL by
//
cch = static_cast<UINT>(strlen (rgch));
cchUri = static_cast<UINT>(strlen (pszRedirect));
// If they haven't passed us enough buffer to copy
// the redirect url, fail. Add one to the counts for the
// terminating NULL character
//
if (cchBuf < (cchUri + cch + 1))
return FALSE;
MoveMemory (pszRedirect + cch, pszRedirect, cchUri + 1);
CopyMemory (pszRedirect, rgch, cch);
}
ret:
return TRUE;
}