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.
 
 
 
 
 
 

788 lines
21 KiB

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name :
map_handler.cxx
Abstract:
Handle Map Files requests
Author:
Anil Ruia (AnilR) 9-Mar-2000
Environment:
Win32 - User Mode
Project:
ULW3.DLL
--*/
#include "precomp.hxx"
#include "staticfile.hxx"
#define MAXVERTS 160
const int MIN_INTEGER = 0x80000001;
void SkipLine(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex);
void SkipWhiteExceptNewLine(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex);
void SkipWhite(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex);
void SkipNonWhite(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex);
int GetNumber(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex);
BOOL PointInRect(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex,
const int x,
const int y,
DWORD &urlIndex);
BOOL PointInCircle(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex,
const int x,
const int y,
DWORD &urlIndex);
BOOL PointInPoly(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex,
const int x,
const int y,
DWORD &urlIndex);
double PointInPoint(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex,
const int x,
const int y,
DWORD &urlIndex);
DWORD GetDefaultUrl(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex);
HRESULT W3_STATIC_FILE_HANDLER::MapFileDoWork(
W3_CONTEXT *pW3Context,
W3_FILE_INFO *pOpenFile,
BOOL *pfHandled)
{
DBG_ASSERT(pW3Context != NULL);
DBG_ASSERT(pOpenFile != NULL);
DBG_ASSERT(pfHandled != NULL);
STACK_STRA(strTargetUrl, MAX_PATH);
STACK_STRU(strQueryString, MAX_PATH);
LPSTR pszFileContents = NULL;
BOOL fFileContentsAllocated = FALSE;
int x = 0;
int y = 0;
HRESULT hr = S_OK;
W3_REQUEST *pRequest = pW3Context->QueryRequest();
DBG_ASSERT(pRequest != NULL);
*pfHandled = FALSE;
DWORD cbFileSize;
ULARGE_INTEGER liFileSize;
pOpenFile->QuerySize(&liFileSize);
cbFileSize = liFileSize.LowPart;
if (pOpenFile->QueryFileBuffer() != NULL)
{
pszFileContents = (LPSTR)pOpenFile->QueryFileBuffer();
}
else
{
pszFileContents = new CHAR[cbFileSize];
if (pszFileContents == NULL)
{
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
goto Finished;
}
fFileContentsAllocated = TRUE;
DWORD cbRead;
OVERLAPPED ovl;
ZeroMemory(&ovl, sizeof ovl);
if (!ReadFile(pOpenFile->QueryFileHandle(),
pszFileContents,
cbFileSize,
&cbRead,
&ovl))
{
hr = HRESULT_FROM_WIN32(GetLastError());
switch (hr)
{
case HRESULT_FROM_WIN32(ERROR_IO_PENDING):
if (!GetOverlappedResult(pOpenFile->QueryFileHandle(),
&ovl,
&cbRead,
TRUE))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Finished;
}
break;
default:
goto Finished;
}
}
}
if (FAILED(hr = pW3Context->QueryRequest()->GetQueryString(&strQueryString)))
{
goto Finished;
}
strQueryString.Unescape();
swscanf(strQueryString.QueryStr(), L"%d, %d", &x, &y);
if (FAILED(hr = SearchMapFile(pszFileContents,
cbFileSize,
x, y, &strTargetUrl)))
{
goto Finished;
}
if (strTargetUrl.QueryCCH() == 0)
{
//
// No entry found
//
LPCSTR pszReferer;
if ((pszReferer = pRequest->GetHeader(HttpHeaderReferer)) != NULL)
{
//
// Redirect back to referrer
//
strTargetUrl.Copy(pszReferer);
}
else
{
*pfHandled = FALSE;
goto Finished;
}
}
*pfHandled = TRUE;
hr = pW3Context->SetupHttpRedirect(strTargetUrl,
FALSE,
HttpStatusRedirect);
Finished:
if (fFileContentsAllocated)
{
delete [] pszFileContents;
}
return hr;
}
HRESULT W3_STATIC_FILE_HANDLER::SearchMapFile(
IN LPCSTR pszFileContents,
IN const DWORD cbFileSize,
IN const int x,
IN const int y,
OUT STRA *pstrTarget)
{
DWORD fileIndex = 0;
DWORD urlIndex = 0;
BOOL fFound = FALSE;
double MinDistanceFromPoint = 1e64;
DWORD PointUrlIndex = 0;
DWORD DefaultUrlIndex = 0;
while ((fileIndex < cbFileSize) && !fFound)
{
switch (pszFileContents[fileIndex])
{
case '#':
//
// Comment, skip the line
//
break;
case 'r':
case 'R':
//
// Rectangle
//
if ((fileIndex < (cbFileSize - 4)) &&
!_strnicmp("rect", pszFileContents + fileIndex, 4))
{
fileIndex += 4;
fFound = PointInRect(pszFileContents, cbFileSize,
fileIndex,
x, y,
urlIndex);
}
break;
case 'c':
case 'C':
//
// Circle
//
if ((fileIndex < (cbFileSize - 4)) &&
!_strnicmp("circ", pszFileContents + fileIndex, 4))
{
fileIndex += 4;
fFound = PointInCircle(pszFileContents, cbFileSize,
fileIndex,
x, y,
urlIndex);
}
break;
case 'p':
case 'P':
//
// Polygon or point
//
if ((fileIndex < (cbFileSize - 4)) &&
!_strnicmp("poly", pszFileContents + fileIndex, 4))
{
fileIndex += 4;
fFound = PointInPoly(pszFileContents, cbFileSize,
fileIndex,
x, y,
urlIndex);
}
else if ((fileIndex < (cbFileSize - 5)) &&
!_strnicmp("point", pszFileContents + fileIndex, 5))
{
fileIndex += 5;
double distance = PointInPoint(pszFileContents, cbFileSize,
fileIndex,
x, y,
urlIndex);
if (distance < MinDistanceFromPoint)
{
MinDistanceFromPoint = distance;
PointUrlIndex = urlIndex;
}
}
break;
case 'd':
case 'D':
//
// default URL
//
if ((fileIndex < (cbFileSize - 3)) &&
!_strnicmp("def", pszFileContents + fileIndex, 3))
{
fileIndex += 3;
DefaultUrlIndex = GetDefaultUrl(pszFileContents,
cbFileSize,
fileIndex);
}
break;
} // switch
if (!fFound)
SkipLine(pszFileContents, cbFileSize, fileIndex);
} // while
//
// If we didn't find a mapping and a point or a default was specified,
// use that URL
//
if (!fFound)
{
if (PointUrlIndex != 0)
{
urlIndex = PointUrlIndex;
fFound = TRUE;
}
else if (DefaultUrlIndex != 0)
{
urlIndex = DefaultUrlIndex;
fFound = TRUE;
}
}
if (fFound)
{
//
// make urlIndex point to the start of the URL
//
SkipWhiteExceptNewLine(pszFileContents, cbFileSize, urlIndex);
//
// Determine the length of the URL and copy it out
//
DWORD endOfUrlIndex = urlIndex;
SkipNonWhite(pszFileContents, cbFileSize, endOfUrlIndex);
HRESULT hr;
if (FAILED(hr = pstrTarget->Copy(pszFileContents + urlIndex,
endOfUrlIndex - urlIndex)))
{
return hr;
}
//
// BUGBUG - Escape the URL
//
}
else
{
DBGPRINTF((DBG_CONTEXT, "No mapping found for %d, %d\n", x, y));
}
return S_OK;
}
void SkipLine(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex)
{
while ((fileIndex < cbFileSize) &&
(pszFileContents[fileIndex] != '\n'))
fileIndex++;
fileIndex++;
}
void SkipWhiteExceptNewLine(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex)
{
while ((fileIndex < cbFileSize) &&
((pszFileContents[fileIndex] == ' ') ||
(pszFileContents[fileIndex] == '\t') ||
(pszFileContents[fileIndex] == '(') ||
(pszFileContents[fileIndex] == ')')))
{
fileIndex++;
}
}
void SkipWhite(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex)
{
while ((fileIndex < cbFileSize) &&
((pszFileContents[fileIndex] == ' ') ||
(pszFileContents[fileIndex] == '\t') ||
(pszFileContents[fileIndex] == '\r') ||
(pszFileContents[fileIndex] == '\n') ||
(pszFileContents[fileIndex] == '(') ||
(pszFileContents[fileIndex] == ')')))
{
fileIndex++;
}
}
void SkipNonWhite(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex)
{
while ((fileIndex < cbFileSize) &&
(pszFileContents[fileIndex] != ' ') &&
(pszFileContents[fileIndex] != '\t') &&
(pszFileContents[fileIndex] != '\r') &&
(pszFileContents[fileIndex] != '\n'))
{
fileIndex++;
}
}
int GetNumber(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex)
{
int Value = MIN_INTEGER;
char ch;
bool fNegative = false;
//
// Make sure we don't get into the URL
//
while ((fileIndex < cbFileSize) &&
!isalnum(ch = pszFileContents[fileIndex]) &&
(ch != '-') && (ch != '/') &&
(ch != '\r') && (ch != '\n'))
{
fileIndex++;
}
//
// Read the number
//
if ((fileIndex < cbFileSize) &&
(pszFileContents[fileIndex] == '-'))
{
fNegative = true;
fileIndex++;
}
while ((fileIndex < cbFileSize) &&
isdigit(ch = pszFileContents[fileIndex]))
{
if (Value == MIN_INTEGER)
Value = 0;
Value = Value*10 + (ch - '0');
fileIndex++;
}
if (fNegative)
Value = -Value;
return Value;
}
BOOL PointInRect(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex,
const int x,
const int y,
DWORD &urlIndex)
{
BOOL fNCSA = FALSE;
BOOL fFound = FALSE;
SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
urlIndex = fileIndex; // NCSA case
SkipWhiteExceptNewLine(pszFileContents, cbFileSize, fileIndex);
char ch = pszFileContents[fileIndex];
if (((ch < '0') || (ch > '9')) &&
(ch != '-') && (ch != '('))
{
//
// NCSA format. Skip the URL
//
fNCSA = true;
SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
}
int x1 = GetNumber(pszFileContents, cbFileSize, fileIndex);
int y1 = GetNumber(pszFileContents, cbFileSize, fileIndex);
int x2 = GetNumber(pszFileContents, cbFileSize, fileIndex);
int y2 = GetNumber(pszFileContents, cbFileSize, fileIndex);
if ((x >= x1) && (x < x2) && (y >= y1) && (y < y2))
fFound = true;
if (!fNCSA)
{
urlIndex = fileIndex;
//
// Skip the URL
//
SkipWhiteExceptNewLine(pszFileContents, cbFileSize, fileIndex);
SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
}
return fFound;
}
BOOL PointInCircle(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex,
const int x,
const int y,
DWORD &urlIndex)
{
BOOL fNCSA = FALSE;
BOOL fFound = FALSE;
double r1, r2;
SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
urlIndex = fileIndex; // NCSA case
SkipWhiteExceptNewLine(pszFileContents, cbFileSize, fileIndex);
char ch = pszFileContents[fileIndex];
if (!isdigit(ch) && (ch != '-') && (ch != '('))
{
//
// NCSA format. Skip the URL
//
fNCSA = true;
SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
}
//
// Get the center and edge of the circle
//
double xCenter = GetNumber(pszFileContents, cbFileSize, fileIndex);
double yCenter = GetNumber(pszFileContents, cbFileSize, fileIndex);
double xEdge = GetNumber(pszFileContents, cbFileSize, fileIndex);
double yEdge = GetNumber(pszFileContents, cbFileSize, fileIndex);
//
// If we have the NCSA format, (xEdge, yEdge) is a point on the
// circumference. Otherwise xEdge specifies the radius
//
if (yEdge != (double)MIN_INTEGER)
{
r1 = (yCenter - yEdge) * (yCenter - yEdge) +
(xCenter - xEdge) * (xCenter - xEdge);
r2 = (yCenter - y) * (yCenter - y) +
(xCenter - x) * (xCenter - x);
if ( r2 <= r1 )
fFound = true;
}
//
// CERN format, third param is the radius
//
else if(xEdge >= 0)
{
double radius;
radius = xEdge;
if (( xCenter - x ) * ( xCenter - x) +
( yCenter - y ) * ( yCenter - y) <= ( radius * radius))
fFound = true;
}
// if invalid radius, just check if it is on center
else if ((xCenter == x) && (yCenter == y))
{
fFound = true;
}
if (!fNCSA)
{
urlIndex = fileIndex;
//
// Skip the URL
//
SkipWhiteExceptNewLine(pszFileContents, cbFileSize, fileIndex);
SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
}
return fFound;
}
const int X = 0;
const int Y = 1;
BOOL PointInPoly(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex,
const int x,
const int y,
DWORD &urlIndex)
{
//
// Algorithm used is from http://www.whisqu.se/per/docs/math27.htm
//
BOOL fNCSA = FALSE;
BOOL fFound = FALSE;
SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
urlIndex = fileIndex; // NCSA case
SkipWhiteExceptNewLine(pszFileContents, cbFileSize, fileIndex);
char ch = pszFileContents[fileIndex];
if (!isdigit(ch) && (ch != '-') && (ch != '('))
{
//
// NCSA format. Skip the URL
//
fNCSA = TRUE;
SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
}
//
// Build the array of points
//
double polygon[MAXVERTS][2];
int count = 0;
while ((fileIndex < cbFileSize) &&
(pszFileContents[fileIndex] != '\r') &&
(pszFileContents[fileIndex] != '\n'))
{
int polyX = GetNumber(pszFileContents, cbFileSize, fileIndex);
//
// Did we hit the end of the line (and go past the URL)?
//
if ( polyX != MIN_INTEGER)
{
polygon[count][X] = polyX;
polygon[count][Y] = GetNumber(pszFileContents, cbFileSize, fileIndex);
count++;
if (count >= MAXVERTS)
return FALSE;
}
else
break;
}
if (count > 1)
{
double tX = x;
double tY = y;
double prevX = polygon[count - 1][X];
double prevY = polygon[count - 1][Y];
double currX, currY;
int crossings = 0;
for (int i=0; i < count; i++)
{
double interpY;
currX = polygon[i][X];
currY = polygon[i][Y];
if (((prevX >= tX) && (currX < tX)) ||
((prevX < tX) && (currX >= tX)))
{
//
// Use linear interpolation to find the y coordinate of
// the line connecting (prevX, prevY) to (currX, currY)
// at the same x coordinate as the target point
//
interpY = prevY + ((currY - prevY)/(currX - prevX))* (tX - prevX);
if (interpY == tY)
{
fFound = true;
break;
}
else if (interpY > tY)
crossings++;
}
// To catch the left end of a line
else if (((prevX == tX) && (prevY == tY)) ||
((currX == tX) && (currY == tY)))
{
fFound = true;
break;
}
// To catch a vertical line
else if ((prevX == currX) && (prevX == tX))
if (((prevY >= tY) && ( currY <= tY)) ||
((prevY <= tY) && ( currY >= tY)))
{
fFound = true;
break;
}
prevX = currX;
prevY = currY;
}
if (!fFound)
{
//
// If # crossings is odd => In polygon
//
fFound = crossings & 0x1;
}
}
if (!fNCSA)
{
urlIndex = fileIndex;
//
// Skip the URL
//
SkipWhiteExceptNewLine(pszFileContents, cbFileSize, fileIndex);
SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
}
return fFound;
}
double PointInPoint(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex,
const int x,
const int y,
DWORD &urlIndex)
{
SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
urlIndex = fileIndex; // NCSA case
SkipWhiteExceptNewLine(pszFileContents, cbFileSize, fileIndex);
SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
double x1 = GetNumber(pszFileContents, cbFileSize, fileIndex);
double y1 = GetNumber(pszFileContents, cbFileSize, fileIndex);
return ((x1-x)*(x1-x)) + ((y1-y)*(y1-y));
}
DWORD GetDefaultUrl(LPCSTR pszFileContents,
const DWORD cbFileSize,
DWORD &fileIndex)
{
//
// Skip "default" (don't skip white space)
//
SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
DWORD defUrlIndex = fileIndex;
//
// Skip URL
//
SkipWhiteExceptNewLine(pszFileContents, cbFileSize, fileIndex);
SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
return defUrlIndex;
}