home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 July & August / Pcwk78a98.iso / Internet / Omnihttp / OH20A8.EXE / data1.cab / CGI / Cgi-Bin / IMAGEMAP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  19.8 KB  |  772 lines

  1. /*===================================================================
  2. <M> Module name - imagemap.c
  3. <A> Abstract - CGI program for parsing image map requests 
  4. <C> Copyright (C) 1996 MicroPlot Systems Co., Stephen F. Bean
  5. <C> Released for FREE distribution 11/07/96
  6. <B> Bibliography
  7. <B> Many of the definitions for this code came from an excellent book
  8. <B> entitled: "HTML Sourcebook", by Ian S. Graham, 2nd Edition
  9. <B> ISBN: 0-471-14242-5, 1996, John Wiley & Sons
  10. <D> October 25, 1996
  11. <I> Interface - none
  12. <V> Version 1.00.00 11/07/96 Stephen F. Bean (published on Internet)
  13. <R> Revision Record
  14. <R> 1.
  15. ;==================================================================*/
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <malloc.h>
  20. #include <math.h>
  21. #include <direct.h>
  22. //
  23. // local string tables
  24. //
  25. char    *ServerErrors[] = {    "Bad Path Error",
  26.                             "Map File Not Found",
  27.                             "Insufficient Arguments",
  28.                             "Bad Arguments"};
  29. //
  30. // object types recognized
  31. //
  32. char    *ObjectTypes[]    = {    "rect",
  33.                             "circ",
  34.                             "poly",
  35.                             "poin",
  36.                             "defa"};
  37. //
  38. // local structure defs
  39. // one of these structures is created for each line in the
  40. // map file.
  41. //
  42. typedef struct {
  43.                 int        MapRecordNumber;
  44.                 int        MapObjectType;
  45.                 int        MapXMin;
  46.                 int        MapXMax;
  47.                 int        MapYMin;
  48.                 int        MapYMax;
  49.                 char    MapObjectUrl[100];
  50.                 int        NumMapPoints;
  51.                 void    *MapRecordPoints;
  52.                 void    *NextMapRecord;
  53.                 } MapRecord;
  54. //
  55. // sub structure for x,y data points
  56. // the first one is pointed to by MapRecordPoints
  57. //
  58. typedef struct {
  59.                 int        MapX;
  60.                 int        MapY;
  61.                 void    *NextPoint;
  62.                 } MapPoint;
  63. //
  64. // global variables
  65. //
  66. MapRecord    *FirstMapRecord    = NULL;
  67. MapRecord    *CurrMapRecord    = NULL;
  68. MapRecord    *TempMapRecord    = NULL;
  69. MapPoint    *FirstPoint    = NULL;
  70. MapPoint    *CurrPoint    = NULL;
  71. MapPoint    *TempPoint    = NULL;
  72. //
  73. // local function prototypes
  74. //
  75.     void    main(int argc, char **argv);
  76.     void    ParseMapString(char *MapString);
  77.     void    ServerError(int ErrorNumber);
  78.     int     CompareRectangle(int Xval, int Yval);
  79.     int     CompareCircle(int Xval, int Yval);
  80.     int     ComparePolygon(int Xval, int Yval);
  81.     int        ComparePoint(int Xval, int Yval);
  82.     int        IsLetter(char Value);
  83.     int        IsNumber(char Value);
  84.     int        IsSeparator(char Value);
  85.     int        IsUrl(char Value);
  86. /*===================================================================
  87. <M> Module name - main
  88. <A> Abstract - main module CGI program for parsing image map requests 
  89. <C> Copyright (C) 1996 MicroPlot Systems Co., Stephen F. Bean
  90. <D> October 25, 1996
  91. <I> Interface - void main(int argc, char **argv);
  92. <R> Revision Record
  93. <R> 1.
  94. ;==================================================================*/
  95. void main(int argc, char **argv)
  96.     {
  97.     FILE    *CgiMap;
  98.     int        idx;
  99.     int        FoundRecord;
  100.     char    *MapFileString;
  101.     char    OutString[100];
  102.     char    MapFileName[100];
  103.     char    *MapPtr;
  104.     char    DefaultUrl[100];
  105.     int     Xcoord;
  106.     int        Ycoord;
  107.     int        ServerPort;
  108.     //
  109.     // check that there are enough passed parms
  110.     // in the command line
  111.     // passed x & y are in second argument as "x,y"
  112.     //
  113.     if(argc >= 2)
  114.         {
  115.         //
  116.         // extract x & y from passed values
  117.         //
  118.         strcpy(OutString, argv[1]);
  119.         MapPtr = strstr(OutString, ",");
  120.         if (MapPtr != NULL)
  121.             {
  122.             *MapPtr = '\0';
  123.             MapPtr++;
  124.             Xcoord = atoi(OutString);
  125.             Ycoord = atoi(MapPtr);
  126.             //
  127.             // get server port number for later
  128.             //
  129.             strcpy(OutString, getenv("SERVER_PORT"));
  130.             ServerPort = atoi(OutString);
  131.             //
  132.             // construct file name for map resource
  133.             //
  134.             DefaultUrl[0] = '\0';
  135.             MapFileString = (char *)calloc(257, sizeof(char));
  136.             _getcwd(MapFileName, 100);
  137.             //
  138.             // patch for default location of OmniHTTPd server
  139.             // user files
  140.             //
  141.             strcpy(OutString, getenv("SERVER_SOFTWARE"));
  142.             if (strstr(OutString, "OmniHTTPd") != NULL)
  143.                 {
  144.                 strcat(MapFileName, "\\htdocs");
  145.                 }
  146.             strcat(MapFileName, getenv("PATH_INFO"));
  147.                idx = 0;
  148.             //
  149.             // since this is DOS, change / to \
  150.             //
  151.                while ((unsigned)idx < strlen(MapFileName))
  152.                   {
  153.                    if (MapFileName[idx] == '/')
  154.                        {
  155.                        MapFileName[idx] = '\\';
  156.                        }
  157.                    idx++;    
  158.                   }
  159.             //
  160.             // open map file and parse it line by line
  161.             // create a structure for each map line
  162.             // a map file has the following syntax:
  163.             // <object type> <URL> <x,y pairs>
  164.             // where object type can be: rectangle, circle, polygon, point, default
  165.             // URL - depends upon the HTTP server but usually is a relative URL to a HTML file
  166.             // x,y pairs separated by spaces or commas
  167.             //
  168.             if ((CgiMap = fopen(MapFileName, "r")) != NULL)
  169.                 {
  170.                 while (fgets(MapFileString, 255, CgiMap) != NULL)
  171.                     {
  172.                      ParseMapString(MapFileString);
  173.                     }
  174.                 fclose(CgiMap);
  175.                 //
  176.                 // look through parsed map records to see if
  177.                 // current position maps to a URL
  178.                 //
  179.                 FoundRecord = 0;
  180.                 CurrMapRecord = FirstMapRecord;
  181.                 while (CurrMapRecord != NULL)
  182.                     {
  183.                     switch(CurrMapRecord->MapObjectType)
  184.                         {
  185.                         case 0: // rectangle
  186.                             if (CompareRectangle(Xcoord, Ycoord) != 0)
  187.                                 {
  188.                                   FoundRecord = 1;
  189.                                 TempMapRecord = CurrMapRecord;
  190.                                 }
  191.                             break;                  
  192.                         case 1: // circle
  193.                             if (CompareCircle(Xcoord, Ycoord) != 0)
  194.                                 {
  195.                                   FoundRecord = 1;
  196.                                 TempMapRecord = CurrMapRecord;
  197.                                 }
  198.                             break;                  
  199.                         case 2: // polygon
  200.                             if (ComparePolygon(Xcoord, Ycoord) != 0)
  201.                                 {
  202.                                   FoundRecord = 1;
  203.                                 TempMapRecord = CurrMapRecord;
  204.                                 }
  205.                             break;
  206.                         case 3: // point
  207.                             if (ComparePoint(Xcoord, Ycoord) != 0)
  208.                                 {
  209.                                 FoundRecord = 1;
  210.                                 TempMapRecord = CurrMapRecord;
  211.                                 }
  212.                             break;
  213.                         case 4:
  214.                             strcpy(DefaultUrl, CurrMapRecord->MapObjectUrl);
  215.                             break;
  216.                         default: // bad object type
  217.                             break;                      
  218.                         }
  219.                        CurrMapRecord = CurrMapRecord->NextMapRecord;
  220.                     }
  221.                 //
  222.                 // construct a complete url
  223.                 // get chars up to first '.' in server name
  224.                 // this may not be right but I had to do it to make it work on my system
  225.                 // I am running Microsoft NT & Win 95 network using TCP/IP and NetBEUI and
  226.                 // EMWACS reports my server machine whose name is "fileserver" as
  227.                 // fileserver.MICROPLOT ?? MicroPlot is the workgroup name on my network
  228.                 // but EMWACS appends it to the host name.
  229.                 //
  230.                 strcpy(OutString, getenv("SERVER_NAME"));
  231.                 if ((MapPtr = strstr(OutString, ".")) != NULL)
  232.                     {
  233.                     *MapPtr = '\0';
  234.                     }
  235.                 strcpy(MapFileString, "http://");
  236.                 strcat(MapFileString, OutString);
  237.                 if (ServerPort != 80)
  238.                     {
  239.                     sprintf(OutString, ":%d", ServerPort);
  240.                     strcat(MapFileString, OutString);
  241.                     }
  242.                 //
  243.                 // get user and directory portion of path
  244.                 //
  245.                 strcpy(OutString, getenv("PATH_INFO"));
  246.                 idx = strlen(OutString) -1;
  247.                 while ((OutString[idx] != '/') && (idx >= 0))
  248.                   {
  249.                   idx--;
  250.                   }
  251.                 OutString[idx] = '\0';
  252.                 strcat(MapFileString, OutString);
  253.                 //
  254.                 // return value to http server
  255.                 // using a Location: directive
  256.                 // send map object url if found
  257.                 //
  258.                 if (FoundRecord != 0)    
  259.                     {
  260.                     //
  261.                     // need to construct complete url
  262.                     //
  263.                     if (strstr(TempMapRecord->MapObjectUrl, ":") == NULL)
  264.                         {
  265.                         printf("Location: %s/%s\n\n",MapFileString, TempMapRecord->MapObjectUrl);
  266.                         }
  267.                     //
  268.                     // url is complete with http://...
  269.                     //
  270.                     else
  271.                         {
  272.                         printf("Location: %s\n\n",TempMapRecord->MapObjectUrl);              
  273.                         }
  274.                     }
  275.                 //
  276.                 // send default url if not found
  277.                 //
  278.                 else
  279.                     {
  280.                       if (DefaultUrl[0] == '\0')
  281.                         {
  282.                         printf("Content-TYPE:  text/html\n\n");
  283.                         printf("<HEAD><TITLE>MicroPlot IsMap Server</TITLE></HEAD><BODY>No Default URL in Map</BODY><BR>\n");
  284.                         }
  285.                     else
  286.                         {
  287.                         if (strstr(DefaultUrl, ":") == NULL)
  288.                             {
  289.                             printf("Location: %s/%s\n\n",MapFileString, DefaultUrl);              
  290.                             }
  291.                         else
  292.                             {
  293.                             printf("Location: %s\n\n",DefaultUrl);              
  294.                             }
  295.                         }
  296.                     }
  297.                 }
  298.             else
  299.                 {
  300.                 ServerError(1);
  301.                 }
  302.             }
  303.         else
  304.             {
  305.             ServerError(3);
  306.             }
  307.         }
  308.     //
  309.     // clean up before exiting
  310.     //
  311.     free(MapFileString);
  312.     CurrMapRecord = FirstMapRecord;
  313.     while (CurrMapRecord != NULL)
  314.         {
  315.         TempMapRecord = CurrMapRecord->NextMapRecord;
  316.         CurrPoint = CurrMapRecord->MapRecordPoints;
  317.         while (CurrPoint != NULL)
  318.             {
  319.             TempPoint = CurrPoint->NextPoint;
  320.             free(CurrPoint);
  321.             CurrPoint = TempPoint;
  322.             }
  323.         free(CurrMapRecord);
  324.         CurrMapRecord = TempMapRecord;
  325.         }
  326.     }
  327. /*===================================================================
  328. <M> Module name - ParseMapString
  329. <A> Abstract - take string data from map file and put in structures
  330. <C> Copyright (C) 1996 MicroPlot Systems Co., Stephen F. Bean
  331. <D> October 25, 1996
  332. <I> Interface - void ParseMapString(char *MapString);
  333. <R> Revision Record
  334. <R> 1.
  335. ;==================================================================*/
  336. void ParseMapString(char *MapString)
  337.     {
  338.     int        idx;
  339.     int        ObjType;
  340.     int        LeftPtr;
  341.     int        RightPtr;
  342.     int        NewX;
  343.     int        NewY;
  344.     int        ParseState;
  345.     int        MapPoints;
  346.  
  347.     idx = 0;
  348.     MapPoints = 0;
  349.     FirstPoint = NULL;
  350.     CurrPoint = NULL;
  351.     //
  352.     // passed line has to include at least an object definition and URL
  353.     // # is interpreted as a comment line (this may be an extension)
  354.     //
  355.     if (((RightPtr = strlen(MapString)) < 10) || (MapString[0] == '#'))
  356.         {
  357.         return;
  358.         }
  359.     //
  360.     // create new map object structure
  361.     //
  362.     if ((TempMapRecord = (MapRecord *)calloc(sizeof(MapRecord), sizeof(char))) == NULL)
  363.         {
  364.         return;
  365.         }
  366.     //
  367.     // set up linked list pointers and min/max values
  368.     //
  369.     TempMapRecord->NextMapRecord = NULL;
  370.     TempMapRecord->MapRecordPoints = NULL;
  371.     TempMapRecord->MapXMin = 9999;
  372.     TempMapRecord->MapXMax = 0;
  373.     TempMapRecord->MapYMin = 9999;
  374.     TempMapRecord->MapYMax = 0;
  375.     if (FirstMapRecord == NULL)
  376.         {
  377.         FirstMapRecord = TempMapRecord;
  378.         TempMapRecord->MapRecordNumber = 0;        
  379.         }
  380.     else
  381.         {
  382.         CurrMapRecord->NextMapRecord = TempMapRecord;
  383.         TempMapRecord->MapRecordNumber = CurrMapRecord->MapRecordNumber + 1;
  384.         }
  385.     CurrMapRecord = TempMapRecord;
  386.     CurrMapRecord->MapObjectType = -1;
  387.     //
  388.     // state machine
  389.     // extracts object type, URL, and x,y from string
  390.     // until end of string is found.
  391.     //
  392.     ParseState = 0;
  393.     while (idx < RightPtr)
  394.         {
  395.         switch(ParseState)
  396.             {
  397.             //
  398.             // get object type string
  399.             // filter out leading spaces & tabs
  400.             //
  401.             case 0:
  402.                 if (IsLetter(MapString[idx]) != 0)
  403.                     {
  404.                     LeftPtr = idx; // set at first alphabetic
  405.                     ParseState++;
  406.                     }
  407.                 else
  408.                     {
  409.                     idx++;
  410.                     }
  411.                 break;
  412.             //
  413.             // get map object type string - mark end of string
  414.             // allowed are: rect(angle), circ(le), poly(gon), poin(t), defa(ult)
  415.             //
  416.             case 1:
  417.                 if (IsLetter(MapString[idx]) == 0) 
  418.                     {
  419.                     MapString[idx] = '\0';
  420.                     ParseState++;
  421.                     }
  422.                 else
  423.                     {
  424.                     idx++;
  425.                     }
  426.                 break;
  427.             //
  428.             // look up valid object types and
  429.             // save object type in structure
  430.             //
  431.             case 2:
  432.                 ObjType = 0;
  433.                 for (ObjType = 0; ObjType < 5; ObjType++)
  434.                     {
  435.                     if (strnicmp(&MapString[LeftPtr], ObjectTypes[ObjType],4) == 0)
  436.                         {
  437.                         CurrMapRecord->MapObjectType = ObjType;
  438.                         break;
  439.                         }
  440.                     }
  441.                 if (CurrMapRecord->MapObjectType >= 0)
  442.                     {
  443.                     ParseState++;
  444.                     }
  445.                 else
  446.                     {
  447.                     idx = RightPtr; // done - error
  448.                     }
  449.                 break;
  450.             //
  451.             // get URL, skip over white space
  452.             //
  453.             case 3:
  454.                 if (IsUrl(MapString[idx]) == 0)
  455.                     {
  456.                     idx++;
  457.                     }
  458.                 else
  459.                     {
  460.                     LeftPtr = idx;
  461.                     ParseState++;
  462.                     }
  463.                 break;
  464.             //
  465.             // find end of URL
  466.             //
  467.             case 4:
  468.                 if (IsUrl(MapString[idx]) != 0)
  469.                     {
  470.                     idx++;
  471.                     }
  472.                 else
  473.                     {
  474.                     MapString[idx] = '\0';
  475.                     strcpy(CurrMapRecord->MapObjectUrl, &MapString[LeftPtr]);
  476.                     ParseState++;
  477.                     }
  478.                 break;
  479.             //
  480.             // skip over white spaces
  481.             //
  482.             case 5: 
  483.                 NewX = -1;
  484.                 NewY = -1;
  485.                 if (IsNumber(MapString[idx]) == 0)
  486.                     {
  487.                     idx++;
  488.                     }
  489.                 else
  490.                     {
  491.                     LeftPtr = idx;
  492.                     ParseState++;
  493.                     }
  494.                 break;
  495.             //
  496.             // get x
  497.             //
  498.             case 6: 
  499.                 if (IsNumber(MapString[idx]) != 0)
  500.                     {
  501.                     idx++;
  502.                     }
  503.                 else
  504.                     {
  505.                     MapString[idx] = '\0';
  506.                     ParseState++;
  507.                     }
  508.                 break;
  509.             //
  510.             // save newx
  511.             //
  512.             case 7: 
  513.                 NewX = atoi(&MapString[LeftPtr]);
  514.                 if (NewX < CurrMapRecord->MapXMin)
  515.                     {
  516.                       CurrMapRecord->MapXMin = NewX;
  517.                     }
  518.                 if (NewX > CurrMapRecord->MapXMax)
  519.                     {
  520.                       CurrMapRecord->MapXMax = NewX;
  521.                     }
  522.                 ParseState++;
  523.                 break;
  524.             //
  525.             // skip over white space
  526.             //
  527.             case 8: 
  528.                 if (IsNumber(MapString[idx]) == 0)
  529.                     {
  530.                     idx++;
  531.                     }
  532.                 else
  533.                     {
  534.                     LeftPtr = idx;
  535.                     ParseState++;
  536.                     }
  537.                 break;
  538.             case 9: // get new y
  539.                 if (IsNumber(MapString[idx]) != 0)
  540.                     {
  541.                     idx++;
  542.                     }
  543.                 else
  544.                     {
  545.                     MapString[idx] = '\0';
  546.                     ParseState++;
  547.                     }
  548.                 break;
  549.             //
  550.             // save new y
  551.             //
  552.             case 10: 
  553.                 NewY = atoi(&MapString[LeftPtr]);
  554.                 if (NewY < CurrMapRecord->MapYMin)
  555.                     {
  556.                       CurrMapRecord->MapYMin = NewY;
  557.                     }
  558.                 if (NewY > CurrMapRecord->MapYMax)
  559.                     {
  560.                       CurrMapRecord->MapYMax = NewY;
  561.                     }
  562.                 ParseState++;
  563.                 break;
  564.             //
  565.             // create new point record to save x & y
  566.             // x,y points are stored in a second linked list
  567.             // the head of the x,y linked list is stored in
  568.             // MapRecordPoints in each map structure
  569.             //
  570.             case 11: 
  571.                 if ((TempPoint = (MapPoint *)malloc(sizeof(MapPoint))) == NULL)
  572.                     {
  573.                     return;
  574.                     }
  575.                 TempPoint->NextPoint = NULL;
  576.                 if (FirstPoint == NULL)
  577.                     {
  578.                     FirstPoint = TempPoint;
  579.                     CurrMapRecord->MapRecordPoints = TempPoint;
  580.                     }
  581.                 else
  582.                     {
  583.                     CurrPoint->NextPoint = TempPoint;
  584.                     }
  585.                 CurrPoint = TempPoint;
  586.                 CurrPoint->MapX = NewX;
  587.                 CurrPoint->MapY = NewY;
  588.                 MapPoints++;
  589.                 ParseState = 5; // get more x,y
  590.                 break;
  591.             }
  592.         }
  593.     CurrMapRecord->NumMapPoints = MapPoints;
  594.     }
  595. /*===================================================================
  596. <M> Module name - CompareRectangle
  597. <A> Abstract - compare passed x,y with current map record
  598. <C> Copyright (C) 1996 MicroPlot Systems Co., Stephen F. Bean
  599. <D> October 27, 1996
  600. <I> Interface - int CompareRectangle(int Xval, int Yval);
  601. <R> Revision Record
  602. <R> 1.
  603. ;==================================================================*/
  604. int CompareRectangle(int Xval, int Yval)
  605.     {
  606.       if ((Xval < CurrMapRecord->MapXMin) ||
  607.         (Xval > CurrMapRecord->MapXMax) ||
  608.         (Yval < CurrMapRecord->MapYMin) ||
  609.         (Yval > CurrMapRecord->MapYMax))
  610.           {
  611.           return(0);
  612.           }
  613.     else
  614.         {
  615.         return(1);
  616.         }
  617.     }
  618. /*===================================================================
  619. <M> Module name - CompareCircle
  620. <A> Abstract - compare passed x,y with current map record
  621. <C> Copyright (C) 1996 MicroPlot Systems Co., Stephen F. Bean
  622. <D> October 27, 1996
  623. <I> Interface - int CompareCircle(int Xval, int Yval);
  624. <R> Revision Record
  625. <R> 1.
  626. ;==================================================================*/
  627. int CompareCircle(int Xval, int Yval)
  628.     {
  629.     int    Xp, Yp;
  630.     int Xc, Yc;
  631.     double    dist, radius;
  632.     //
  633.     // the 2 x,y points passed are (1) the center of the circle and (2) a point on the
  634.     // circle. I compute the radius of the circle and the distance between the center
  635.     // of the circle and the passed point.
  636.     //
  637.     if (CurrMapRecord->NumMapPoints == 2)
  638.         {
  639.         CurrPoint = CurrMapRecord->MapRecordPoints;
  640.         Xc = CurrPoint->MapX;
  641.         Yc = CurrPoint->MapY;
  642.         CurrPoint = CurrPoint->NextPoint;
  643.         Xp = CurrPoint->MapX;
  644.         Yp = CurrPoint->MapY;
  645.         radius = sqrt((double)((Xc - Xp) * (Xc - Xp)) + (double)((Yc - Yp) * (Yc - Yp)));
  646.         dist   = sqrt((double)((Xc - Xval) * (Xc - Xval)) + (double)((Yc - Yval) * (Yc - Yval)));
  647.         if (dist <= radius)
  648.             {
  649.             return(1);
  650.             }
  651.         }
  652.     return(0);
  653.     }
  654. /*===================================================================
  655. <M> Module name - ComparePolygon
  656. <A> Abstract - compare passed x,y with current map record
  657. <A>     I wimped out - only test is the trivially rejected points
  658. <A>     outside the bounding box
  659. <C> Copyright (C) 1996 MicroPlot Systems Co., Stephen F. Bean
  660. <D> October 27, 1996
  661. <I> Interface - int ComparePolygon(int Xval, int Yval);
  662. <R> Revision Record
  663. <R> 1.
  664. ;==================================================================*/
  665. int ComparePolygon(int Xval, int Yval)
  666.     {
  667.       if ((Xval < CurrMapRecord->MapXMin) ||
  668.         (Xval > CurrMapRecord->MapXMax) ||
  669.         (Yval < CurrMapRecord->MapYMin) ||
  670.         (Yval > CurrMapRecord->MapYMax))
  671.           {
  672.           return(0);
  673.           }
  674.     else
  675.         {
  676.         return(1);
  677.         }
  678.     }
  679. /*===================================================================
  680. <M> Module name - ComparePoint
  681. <A> Abstract - compare passed x,y with current map record
  682. <C> Copyright (C) 1996 MicroPlot Systems Co., Stephen F. Bean
  683. <D> October 27, 1996
  684. <I> Interface - int ComparePoint(int Xval, int Yval);
  685. <R> Revision Record
  686. <R> 1.
  687. ;==================================================================*/
  688. int ComparePoint(int Xval, int Yval)
  689.     {
  690.     CurrPoint = CurrMapRecord->MapRecordPoints;
  691.     if ((CurrPoint->MapX == Xval) && (CurrPoint->MapY == Yval))
  692.         {
  693.         return(1);
  694.         }
  695.     return(0);
  696.     }
  697. /*===================================================================
  698. <M> Module name - ServerError
  699. <A> Abstract - report error to HTTP server
  700. <C> Copyright (C) 1996 MicroPlot Systems Co., Stephen F. Bean
  701. <D> October 25, 1996
  702. <I> Interface - void ServerError(int ErrorNumber);
  703. <R> Revision Record
  704. <R> 1.
  705. ;==================================================================*/
  706. void ServerError(int ErrorNumber)
  707.     {
  708.     printf("Content-TYPE: text/html\n\n");
  709.     printf("<TITLE>MicroPlot IsMap Server Error</TITLE>"); 
  710.     printf("<H1>MicroPlot IsMap Server Error</H1>"); 
  711.     printf("Error is: %s<BR>",ServerErrors[ErrorNumber]);
  712.     }
  713. /*===================================================================
  714. <M> Module name - IsNumber, IsLetter, IsSeparator
  715. <A> Abstract - filters for character types
  716. <C> Copyright (C) 1996 MicroPlot Systems Co., Stephen F. Bean
  717. <D> October 25, 1996
  718. <I> Interface - short IsLetter(char Value);
  719. <I> Interface - short IsNumber(char Value);
  720. <I> Interface - short IsSeparator(char Value);
  721. <R> Revision Record
  722. <R> 1.
  723. ;==================================================================*/
  724. int IsLetter(char Value)
  725.     {
  726.     if (((Value >= 'A') && (Value <= 'Z')) || ((Value >= 'a') && (Value <= 'z')))
  727.         {
  728.         return(1);
  729.         }
  730.     return(0);
  731.     }
  732.  
  733. int IsNumber(char Value)
  734.     {
  735.     if ((Value >= '0') && (Value <= '9'))
  736.         {
  737.         return(1);
  738.         }
  739.     return(0);
  740.     }
  741.  
  742. int IsSeparator(char Value)
  743.     {
  744.     if ((Value == ' ') || (Value == ',') || (Value == '\t'))
  745.         {
  746.         return(1);
  747.         }
  748.     return(0);
  749.     }
  750.  
  751. int IsUrl(char Value)
  752.     {
  753.     if (((Value >= 0) && (Value <= 0x1f)) ||
  754.         (Value == 0x09) || // tab
  755.         (Value == 0x22) || // double quote
  756.         (Value == '>')  ||
  757.         (Value == '<')  ||
  758.         (Value == ' ')  ||
  759.         (Value == '[')  ||
  760.         (Value == ']')  ||
  761.         (Value == '\\') ||
  762.         (Value == '^')  ||
  763.         (Value == '`')  ||
  764.         (Value == '{')  ||
  765.         (Value == '}')  ||
  766.         (Value == '|')  ||
  767.         (Value == '~'))
  768.             {
  769.             return(0);
  770.             }
  771.     return(1);
  772.     }