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

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name :
  4. map_handler.cxx
  5. Abstract:
  6. Handle Map Files requests
  7. Author:
  8. Anil Ruia (AnilR) 9-Mar-2000
  9. Environment:
  10. Win32 - User Mode
  11. Project:
  12. ULW3.DLL
  13. --*/
  14. #include "precomp.hxx"
  15. #include "staticfile.hxx"
  16. #define MAXVERTS 160
  17. const int MIN_INTEGER = 0x80000001;
  18. void SkipLine(LPCSTR pszFileContents,
  19. const DWORD cbFileSize,
  20. DWORD &fileIndex);
  21. void SkipWhiteExceptNewLine(LPCSTR pszFileContents,
  22. const DWORD cbFileSize,
  23. DWORD &fileIndex);
  24. void SkipWhite(LPCSTR pszFileContents,
  25. const DWORD cbFileSize,
  26. DWORD &fileIndex);
  27. void SkipNonWhite(LPCSTR pszFileContents,
  28. const DWORD cbFileSize,
  29. DWORD &fileIndex);
  30. int GetNumber(LPCSTR pszFileContents,
  31. const DWORD cbFileSize,
  32. DWORD &fileIndex);
  33. BOOL PointInRect(LPCSTR pszFileContents,
  34. const DWORD cbFileSize,
  35. DWORD &fileIndex,
  36. const int x,
  37. const int y,
  38. DWORD &urlIndex);
  39. BOOL PointInCircle(LPCSTR pszFileContents,
  40. const DWORD cbFileSize,
  41. DWORD &fileIndex,
  42. const int x,
  43. const int y,
  44. DWORD &urlIndex);
  45. BOOL PointInPoly(LPCSTR pszFileContents,
  46. const DWORD cbFileSize,
  47. DWORD &fileIndex,
  48. const int x,
  49. const int y,
  50. DWORD &urlIndex);
  51. double PointInPoint(LPCSTR pszFileContents,
  52. const DWORD cbFileSize,
  53. DWORD &fileIndex,
  54. const int x,
  55. const int y,
  56. DWORD &urlIndex);
  57. DWORD GetDefaultUrl(LPCSTR pszFileContents,
  58. const DWORD cbFileSize,
  59. DWORD &fileIndex);
  60. HRESULT W3_STATIC_FILE_HANDLER::MapFileDoWork(
  61. W3_CONTEXT *pW3Context,
  62. W3_FILE_INFO *pOpenFile,
  63. BOOL *pfHandled)
  64. {
  65. DBG_ASSERT(pW3Context != NULL);
  66. DBG_ASSERT(pOpenFile != NULL);
  67. DBG_ASSERT(pfHandled != NULL);
  68. STACK_STRA(strTargetUrl, MAX_PATH);
  69. STACK_STRU(strQueryString, MAX_PATH);
  70. LPSTR pszFileContents = NULL;
  71. BOOL fFileContentsAllocated = FALSE;
  72. int x = 0;
  73. int y = 0;
  74. HRESULT hr = S_OK;
  75. W3_REQUEST *pRequest = pW3Context->QueryRequest();
  76. DBG_ASSERT(pRequest != NULL);
  77. *pfHandled = FALSE;
  78. DWORD cbFileSize;
  79. ULARGE_INTEGER liFileSize;
  80. pOpenFile->QuerySize(&liFileSize);
  81. cbFileSize = liFileSize.LowPart;
  82. if (pOpenFile->QueryFileBuffer() != NULL)
  83. {
  84. pszFileContents = (LPSTR)pOpenFile->QueryFileBuffer();
  85. }
  86. else
  87. {
  88. pszFileContents = new CHAR[cbFileSize];
  89. if (pszFileContents == NULL)
  90. {
  91. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  92. goto Finished;
  93. }
  94. fFileContentsAllocated = TRUE;
  95. DWORD cbRead;
  96. OVERLAPPED ovl;
  97. ZeroMemory(&ovl, sizeof ovl);
  98. if (!ReadFile(pOpenFile->QueryFileHandle(),
  99. pszFileContents,
  100. cbFileSize,
  101. &cbRead,
  102. &ovl))
  103. {
  104. hr = HRESULT_FROM_WIN32(GetLastError());
  105. switch (hr)
  106. {
  107. case HRESULT_FROM_WIN32(ERROR_IO_PENDING):
  108. if (!GetOverlappedResult(pOpenFile->QueryFileHandle(),
  109. &ovl,
  110. &cbRead,
  111. TRUE))
  112. {
  113. hr = HRESULT_FROM_WIN32(GetLastError());
  114. goto Finished;
  115. }
  116. break;
  117. default:
  118. goto Finished;
  119. }
  120. }
  121. }
  122. if (FAILED(hr = pW3Context->QueryRequest()->GetQueryString(&strQueryString)))
  123. {
  124. goto Finished;
  125. }
  126. strQueryString.Unescape();
  127. swscanf(strQueryString.QueryStr(), L"%d, %d", &x, &y);
  128. if (FAILED(hr = SearchMapFile(pszFileContents,
  129. cbFileSize,
  130. x, y, &strTargetUrl)))
  131. {
  132. goto Finished;
  133. }
  134. if (strTargetUrl.QueryCCH() == 0)
  135. {
  136. //
  137. // No entry found
  138. //
  139. LPCSTR pszReferer;
  140. if ((pszReferer = pRequest->GetHeader(HttpHeaderReferer)) != NULL)
  141. {
  142. //
  143. // Redirect back to referrer
  144. //
  145. strTargetUrl.Copy(pszReferer);
  146. }
  147. else
  148. {
  149. *pfHandled = FALSE;
  150. goto Finished;
  151. }
  152. }
  153. *pfHandled = TRUE;
  154. hr = pW3Context->SetupHttpRedirect(strTargetUrl,
  155. FALSE,
  156. HttpStatusRedirect);
  157. Finished:
  158. if (fFileContentsAllocated)
  159. {
  160. delete [] pszFileContents;
  161. }
  162. return hr;
  163. }
  164. HRESULT W3_STATIC_FILE_HANDLER::SearchMapFile(
  165. IN LPCSTR pszFileContents,
  166. IN const DWORD cbFileSize,
  167. IN const int x,
  168. IN const int y,
  169. OUT STRA *pstrTarget)
  170. {
  171. DWORD fileIndex = 0;
  172. DWORD urlIndex = 0;
  173. BOOL fFound = FALSE;
  174. double MinDistanceFromPoint = 1e64;
  175. DWORD PointUrlIndex = 0;
  176. DWORD DefaultUrlIndex = 0;
  177. while ((fileIndex < cbFileSize) && !fFound)
  178. {
  179. switch (pszFileContents[fileIndex])
  180. {
  181. case '#':
  182. //
  183. // Comment, skip the line
  184. //
  185. break;
  186. case 'r':
  187. case 'R':
  188. //
  189. // Rectangle
  190. //
  191. if ((fileIndex < (cbFileSize - 4)) &&
  192. !_strnicmp("rect", pszFileContents + fileIndex, 4))
  193. {
  194. fileIndex += 4;
  195. fFound = PointInRect(pszFileContents, cbFileSize,
  196. fileIndex,
  197. x, y,
  198. urlIndex);
  199. }
  200. break;
  201. case 'c':
  202. case 'C':
  203. //
  204. // Circle
  205. //
  206. if ((fileIndex < (cbFileSize - 4)) &&
  207. !_strnicmp("circ", pszFileContents + fileIndex, 4))
  208. {
  209. fileIndex += 4;
  210. fFound = PointInCircle(pszFileContents, cbFileSize,
  211. fileIndex,
  212. x, y,
  213. urlIndex);
  214. }
  215. break;
  216. case 'p':
  217. case 'P':
  218. //
  219. // Polygon or point
  220. //
  221. if ((fileIndex < (cbFileSize - 4)) &&
  222. !_strnicmp("poly", pszFileContents + fileIndex, 4))
  223. {
  224. fileIndex += 4;
  225. fFound = PointInPoly(pszFileContents, cbFileSize,
  226. fileIndex,
  227. x, y,
  228. urlIndex);
  229. }
  230. else if ((fileIndex < (cbFileSize - 5)) &&
  231. !_strnicmp("point", pszFileContents + fileIndex, 5))
  232. {
  233. fileIndex += 5;
  234. double distance = PointInPoint(pszFileContents, cbFileSize,
  235. fileIndex,
  236. x, y,
  237. urlIndex);
  238. if (distance < MinDistanceFromPoint)
  239. {
  240. MinDistanceFromPoint = distance;
  241. PointUrlIndex = urlIndex;
  242. }
  243. }
  244. break;
  245. case 'd':
  246. case 'D':
  247. //
  248. // default URL
  249. //
  250. if ((fileIndex < (cbFileSize - 3)) &&
  251. !_strnicmp("def", pszFileContents + fileIndex, 3))
  252. {
  253. fileIndex += 3;
  254. DefaultUrlIndex = GetDefaultUrl(pszFileContents,
  255. cbFileSize,
  256. fileIndex);
  257. }
  258. break;
  259. } // switch
  260. if (!fFound)
  261. SkipLine(pszFileContents, cbFileSize, fileIndex);
  262. } // while
  263. //
  264. // If we didn't find a mapping and a point or a default was specified,
  265. // use that URL
  266. //
  267. if (!fFound)
  268. {
  269. if (PointUrlIndex != 0)
  270. {
  271. urlIndex = PointUrlIndex;
  272. fFound = TRUE;
  273. }
  274. else if (DefaultUrlIndex != 0)
  275. {
  276. urlIndex = DefaultUrlIndex;
  277. fFound = TRUE;
  278. }
  279. }
  280. if (fFound)
  281. {
  282. //
  283. // make urlIndex point to the start of the URL
  284. //
  285. SkipWhiteExceptNewLine(pszFileContents, cbFileSize, urlIndex);
  286. //
  287. // Determine the length of the URL and copy it out
  288. //
  289. DWORD endOfUrlIndex = urlIndex;
  290. SkipNonWhite(pszFileContents, cbFileSize, endOfUrlIndex);
  291. HRESULT hr;
  292. if (FAILED(hr = pstrTarget->Copy(pszFileContents + urlIndex,
  293. endOfUrlIndex - urlIndex)))
  294. {
  295. return hr;
  296. }
  297. //
  298. // BUGBUG - Escape the URL
  299. //
  300. }
  301. else
  302. {
  303. DBGPRINTF((DBG_CONTEXT, "No mapping found for %d, %d\n", x, y));
  304. }
  305. return S_OK;
  306. }
  307. void SkipLine(LPCSTR pszFileContents,
  308. const DWORD cbFileSize,
  309. DWORD &fileIndex)
  310. {
  311. while ((fileIndex < cbFileSize) &&
  312. (pszFileContents[fileIndex] != '\n'))
  313. fileIndex++;
  314. fileIndex++;
  315. }
  316. void SkipWhiteExceptNewLine(LPCSTR pszFileContents,
  317. const DWORD cbFileSize,
  318. DWORD &fileIndex)
  319. {
  320. while ((fileIndex < cbFileSize) &&
  321. ((pszFileContents[fileIndex] == ' ') ||
  322. (pszFileContents[fileIndex] == '\t') ||
  323. (pszFileContents[fileIndex] == '(') ||
  324. (pszFileContents[fileIndex] == ')')))
  325. {
  326. fileIndex++;
  327. }
  328. }
  329. void SkipWhite(LPCSTR pszFileContents,
  330. const DWORD cbFileSize,
  331. DWORD &fileIndex)
  332. {
  333. while ((fileIndex < cbFileSize) &&
  334. ((pszFileContents[fileIndex] == ' ') ||
  335. (pszFileContents[fileIndex] == '\t') ||
  336. (pszFileContents[fileIndex] == '\r') ||
  337. (pszFileContents[fileIndex] == '\n') ||
  338. (pszFileContents[fileIndex] == '(') ||
  339. (pszFileContents[fileIndex] == ')')))
  340. {
  341. fileIndex++;
  342. }
  343. }
  344. void SkipNonWhite(LPCSTR pszFileContents,
  345. const DWORD cbFileSize,
  346. DWORD &fileIndex)
  347. {
  348. while ((fileIndex < cbFileSize) &&
  349. (pszFileContents[fileIndex] != ' ') &&
  350. (pszFileContents[fileIndex] != '\t') &&
  351. (pszFileContents[fileIndex] != '\r') &&
  352. (pszFileContents[fileIndex] != '\n'))
  353. {
  354. fileIndex++;
  355. }
  356. }
  357. int GetNumber(LPCSTR pszFileContents,
  358. const DWORD cbFileSize,
  359. DWORD &fileIndex)
  360. {
  361. int Value = MIN_INTEGER;
  362. char ch;
  363. bool fNegative = false;
  364. //
  365. // Make sure we don't get into the URL
  366. //
  367. while ((fileIndex < cbFileSize) &&
  368. !isalnum(ch = pszFileContents[fileIndex]) &&
  369. (ch != '-') && (ch != '/') &&
  370. (ch != '\r') && (ch != '\n'))
  371. {
  372. fileIndex++;
  373. }
  374. //
  375. // Read the number
  376. //
  377. if ((fileIndex < cbFileSize) &&
  378. (pszFileContents[fileIndex] == '-'))
  379. {
  380. fNegative = true;
  381. fileIndex++;
  382. }
  383. while ((fileIndex < cbFileSize) &&
  384. isdigit(ch = pszFileContents[fileIndex]))
  385. {
  386. if (Value == MIN_INTEGER)
  387. Value = 0;
  388. Value = Value*10 + (ch - '0');
  389. fileIndex++;
  390. }
  391. if (fNegative)
  392. Value = -Value;
  393. return Value;
  394. }
  395. BOOL PointInRect(LPCSTR pszFileContents,
  396. const DWORD cbFileSize,
  397. DWORD &fileIndex,
  398. const int x,
  399. const int y,
  400. DWORD &urlIndex)
  401. {
  402. BOOL fNCSA = FALSE;
  403. BOOL fFound = FALSE;
  404. SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
  405. urlIndex = fileIndex; // NCSA case
  406. SkipWhiteExceptNewLine(pszFileContents, cbFileSize, fileIndex);
  407. char ch = pszFileContents[fileIndex];
  408. if (((ch < '0') || (ch > '9')) &&
  409. (ch != '-') && (ch != '('))
  410. {
  411. //
  412. // NCSA format. Skip the URL
  413. //
  414. fNCSA = true;
  415. SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
  416. }
  417. int x1 = GetNumber(pszFileContents, cbFileSize, fileIndex);
  418. int y1 = GetNumber(pszFileContents, cbFileSize, fileIndex);
  419. int x2 = GetNumber(pszFileContents, cbFileSize, fileIndex);
  420. int y2 = GetNumber(pszFileContents, cbFileSize, fileIndex);
  421. if ((x >= x1) && (x < x2) && (y >= y1) && (y < y2))
  422. fFound = true;
  423. if (!fNCSA)
  424. {
  425. urlIndex = fileIndex;
  426. //
  427. // Skip the URL
  428. //
  429. SkipWhiteExceptNewLine(pszFileContents, cbFileSize, fileIndex);
  430. SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
  431. }
  432. return fFound;
  433. }
  434. BOOL PointInCircle(LPCSTR pszFileContents,
  435. const DWORD cbFileSize,
  436. DWORD &fileIndex,
  437. const int x,
  438. const int y,
  439. DWORD &urlIndex)
  440. {
  441. BOOL fNCSA = FALSE;
  442. BOOL fFound = FALSE;
  443. double r1, r2;
  444. SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
  445. urlIndex = fileIndex; // NCSA case
  446. SkipWhiteExceptNewLine(pszFileContents, cbFileSize, fileIndex);
  447. char ch = pszFileContents[fileIndex];
  448. if (!isdigit(ch) && (ch != '-') && (ch != '('))
  449. {
  450. //
  451. // NCSA format. Skip the URL
  452. //
  453. fNCSA = true;
  454. SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
  455. }
  456. //
  457. // Get the center and edge of the circle
  458. //
  459. double xCenter = GetNumber(pszFileContents, cbFileSize, fileIndex);
  460. double yCenter = GetNumber(pszFileContents, cbFileSize, fileIndex);
  461. double xEdge = GetNumber(pszFileContents, cbFileSize, fileIndex);
  462. double yEdge = GetNumber(pszFileContents, cbFileSize, fileIndex);
  463. //
  464. // If we have the NCSA format, (xEdge, yEdge) is a point on the
  465. // circumference. Otherwise xEdge specifies the radius
  466. //
  467. if (yEdge != (double)MIN_INTEGER)
  468. {
  469. r1 = (yCenter - yEdge) * (yCenter - yEdge) +
  470. (xCenter - xEdge) * (xCenter - xEdge);
  471. r2 = (yCenter - y) * (yCenter - y) +
  472. (xCenter - x) * (xCenter - x);
  473. if ( r2 <= r1 )
  474. fFound = true;
  475. }
  476. //
  477. // CERN format, third param is the radius
  478. //
  479. else if(xEdge >= 0)
  480. {
  481. double radius;
  482. radius = xEdge;
  483. if (( xCenter - x ) * ( xCenter - x) +
  484. ( yCenter - y ) * ( yCenter - y) <= ( radius * radius))
  485. fFound = true;
  486. }
  487. // if invalid radius, just check if it is on center
  488. else if ((xCenter == x) && (yCenter == y))
  489. {
  490. fFound = true;
  491. }
  492. if (!fNCSA)
  493. {
  494. urlIndex = fileIndex;
  495. //
  496. // Skip the URL
  497. //
  498. SkipWhiteExceptNewLine(pszFileContents, cbFileSize, fileIndex);
  499. SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
  500. }
  501. return fFound;
  502. }
  503. const int X = 0;
  504. const int Y = 1;
  505. BOOL PointInPoly(LPCSTR pszFileContents,
  506. const DWORD cbFileSize,
  507. DWORD &fileIndex,
  508. const int x,
  509. const int y,
  510. DWORD &urlIndex)
  511. {
  512. //
  513. // Algorithm used is from http://www.whisqu.se/per/docs/math27.htm
  514. //
  515. BOOL fNCSA = FALSE;
  516. BOOL fFound = FALSE;
  517. SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
  518. urlIndex = fileIndex; // NCSA case
  519. SkipWhiteExceptNewLine(pszFileContents, cbFileSize, fileIndex);
  520. char ch = pszFileContents[fileIndex];
  521. if (!isdigit(ch) && (ch != '-') && (ch != '('))
  522. {
  523. //
  524. // NCSA format. Skip the URL
  525. //
  526. fNCSA = TRUE;
  527. SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
  528. }
  529. //
  530. // Build the array of points
  531. //
  532. double polygon[MAXVERTS][2];
  533. int count = 0;
  534. while ((fileIndex < cbFileSize) &&
  535. (pszFileContents[fileIndex] != '\r') &&
  536. (pszFileContents[fileIndex] != '\n'))
  537. {
  538. int polyX = GetNumber(pszFileContents, cbFileSize, fileIndex);
  539. //
  540. // Did we hit the end of the line (and go past the URL)?
  541. //
  542. if ( polyX != MIN_INTEGER)
  543. {
  544. polygon[count][X] = polyX;
  545. polygon[count][Y] = GetNumber(pszFileContents, cbFileSize, fileIndex);
  546. count++;
  547. if (count >= MAXVERTS)
  548. return FALSE;
  549. }
  550. else
  551. break;
  552. }
  553. if (count > 1)
  554. {
  555. double tX = x;
  556. double tY = y;
  557. double prevX = polygon[count - 1][X];
  558. double prevY = polygon[count - 1][Y];
  559. double currX, currY;
  560. int crossings = 0;
  561. for (int i=0; i < count; i++)
  562. {
  563. double interpY;
  564. currX = polygon[i][X];
  565. currY = polygon[i][Y];
  566. if (((prevX >= tX) && (currX < tX)) ||
  567. ((prevX < tX) && (currX >= tX)))
  568. {
  569. //
  570. // Use linear interpolation to find the y coordinate of
  571. // the line connecting (prevX, prevY) to (currX, currY)
  572. // at the same x coordinate as the target point
  573. //
  574. interpY = prevY + ((currY - prevY)/(currX - prevX))* (tX - prevX);
  575. if (interpY == tY)
  576. {
  577. fFound = true;
  578. break;
  579. }
  580. else if (interpY > tY)
  581. crossings++;
  582. }
  583. // To catch the left end of a line
  584. else if (((prevX == tX) && (prevY == tY)) ||
  585. ((currX == tX) && (currY == tY)))
  586. {
  587. fFound = true;
  588. break;
  589. }
  590. // To catch a vertical line
  591. else if ((prevX == currX) && (prevX == tX))
  592. if (((prevY >= tY) && ( currY <= tY)) ||
  593. ((prevY <= tY) && ( currY >= tY)))
  594. {
  595. fFound = true;
  596. break;
  597. }
  598. prevX = currX;
  599. prevY = currY;
  600. }
  601. if (!fFound)
  602. {
  603. //
  604. // If # crossings is odd => In polygon
  605. //
  606. fFound = crossings & 0x1;
  607. }
  608. }
  609. if (!fNCSA)
  610. {
  611. urlIndex = fileIndex;
  612. //
  613. // Skip the URL
  614. //
  615. SkipWhiteExceptNewLine(pszFileContents, cbFileSize, fileIndex);
  616. SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
  617. }
  618. return fFound;
  619. }
  620. double PointInPoint(LPCSTR pszFileContents,
  621. const DWORD cbFileSize,
  622. DWORD &fileIndex,
  623. const int x,
  624. const int y,
  625. DWORD &urlIndex)
  626. {
  627. SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
  628. urlIndex = fileIndex; // NCSA case
  629. SkipWhiteExceptNewLine(pszFileContents, cbFileSize, fileIndex);
  630. SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
  631. double x1 = GetNumber(pszFileContents, cbFileSize, fileIndex);
  632. double y1 = GetNumber(pszFileContents, cbFileSize, fileIndex);
  633. return ((x1-x)*(x1-x)) + ((y1-y)*(y1-y));
  634. }
  635. DWORD GetDefaultUrl(LPCSTR pszFileContents,
  636. const DWORD cbFileSize,
  637. DWORD &fileIndex)
  638. {
  639. //
  640. // Skip "default" (don't skip white space)
  641. //
  642. SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
  643. DWORD defUrlIndex = fileIndex;
  644. //
  645. // Skip URL
  646. //
  647. SkipWhiteExceptNewLine(pszFileContents, cbFileSize, fileIndex);
  648. SkipNonWhite(pszFileContents, cbFileSize, fileIndex);
  649. return defUrlIndex;
  650. }