source: trunk/mapserver/mapservutil.c

Last change on this file was 13171, checked in by sdlime, 12 years ago

Added classgroup parameter support to the CGI (in msCGILoadMap()). (#4207)

  • Property svn:keywords set to Author Date Id Revision
File size: 72.3 KB
Line 
1/******************************************************************************
2 * $id$
3 *
4 * Project: MapServer
5 * Purpose: MapServer CGI utility functions.
6 * Author: Steve Lime and the MapServer team.
7 *
8 ******************************************************************************
9 * Copyright (c) 1996-2005 Regents of the University of Minnesota.
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies of this Software or works derived from this Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 * DEALINGS IN THE SOFTWARE.
28 ****************************************************************************/
29
30
31#include "mapserver.h"
32#include "mapserv.h"
33#include "maptime.h"
34#include <sys/stat.h>
35
36/*
37** Enumerated types, keep the query modes in sequence and at the end of the enumeration (mode enumeration is in maptemplate.h).
38*/
39static int numModes = 21;
40static char *modeStrings[21] = {"BROWSE","ZOOMIN","ZOOMOUT","MAP","LEGEND","LEGENDICON","REFERENCE","SCALEBAR","COORDINATE",
41 "QUERY","NQUERY","ITEMQUERY","ITEMNQUERY",
42 "FEATUREQUERY","FEATURENQUERY","ITEMFEATUREQUERY","ITEMFEATURENQUERY",
43 "INDEXQUERY","TILE","OWS", "WFS"};
44
45
46
47int msCGIWriteLog(mapservObj *mapserv, int show_error)
48{
49 FILE *stream;
50 int i;
51 time_t t;
52 char szPath[MS_MAXPATHLEN];
53
54 if(!mapserv) return(MS_SUCCESS);
55 if(!mapserv->map) return(MS_SUCCESS);
56 if(!mapserv->map->web.log) return(MS_SUCCESS);
57
58 if((stream = fopen(msBuildPath(szPath, mapserv->map->mappath,
59 mapserv->map->web.log),"a")) == NULL) {
60 msSetError(MS_IOERR, mapserv->map->web.log, "msCGIWriteLog()");
61 return(MS_FAILURE);
62 }
63
64 t = time(NULL);
65 fprintf(stream,"%s,",msStringChop(ctime(&t)));
66 fprintf(stream,"%d,",(int)getpid());
67
68 if(getenv("REMOTE_ADDR") != NULL)
69 fprintf(stream,"%s,",getenv("REMOTE_ADDR"));
70 else
71 fprintf(stream,"NULL,");
72
73 fprintf(stream,"%s,",mapserv->map->name);
74 fprintf(stream,"%d,",mapserv->Mode);
75
76 fprintf(stream,"%f %f %f %f,", mapserv->map->extent.minx, mapserv->map->extent.miny, mapserv->map->extent.maxx, mapserv->map->extent.maxy);
77
78 fprintf(stream,"%f %f,", mapserv->mappnt.x, mapserv->mappnt.y);
79
80 for(i=0;i<mapserv->NumLayers;i++)
81 fprintf(stream, "%s ", mapserv->Layers[i]);
82 fprintf(stream,",");
83
84 if(show_error == MS_TRUE)
85 msWriteError(stream);
86 else
87 fprintf(stream, "normal execution");
88
89 fprintf(stream,"\n");
90
91 fclose(stream);
92 return(MS_SUCCESS);
93}
94
95void msCGIWriteError(mapservObj *mapserv)
96{
97 errorObj *ms_error = msGetErrorObj();
98
99 if(!ms_error || ms_error->code == MS_NOERR || ms_error->isreported) {
100 /* either we have no error, or it was already reported by other means */
101 return;
102 }
103
104 msCGIWriteLog(mapserv,MS_TRUE);
105
106 if(!mapserv || !mapserv->map) {
107 msIO_setHeader("Content-type","text/html");
108 msIO_sendHeaders();
109 msIO_printf("<HTML>\n");
110 msIO_printf("<HEAD><TITLE>MapServer Message</TITLE></HEAD>\n");
111 msIO_printf("<!-- %s -->\n", msGetVersion());
112 msIO_printf("<BODY BGCOLOR=\"#FFFFFF\">\n");
113 msWriteErrorXML(stdout);
114 msIO_printf("</BODY></HTML>");
115 return;
116 }
117
118 if((ms_error->code == MS_NOTFOUND) && (mapserv->map->web.empty)) {
119 /* msRedirect(mapserv->map->web.empty); */
120 if(msReturnURL(mapserv, mapserv->map->web.empty, BROWSE) != MS_SUCCESS) {
121 msIO_setHeader("Content-type","text/html");
122 msIO_sendHeaders();
123 msIO_printf("<HTML>\n");
124 msIO_printf("<HEAD><TITLE>MapServer Message</TITLE></HEAD>\n");
125 msIO_printf("<!-- %s -->\n", msGetVersion());
126 msIO_printf("<BODY BGCOLOR=\"#FFFFFF\">\n");
127 msWriteErrorXML(stdout);
128 msIO_printf("</BODY></HTML>");
129 }
130 } else {
131 if(mapserv->map->web.error) {
132 /* msRedirect(mapserv->map->web.error); */
133 if(msReturnURL(mapserv, mapserv->map->web.error, BROWSE) != MS_SUCCESS) {
134 msIO_setHeader("Content-type","text/html");
135 msIO_sendHeaders();
136 msIO_printf("<HTML>\n");
137 msIO_printf("<HEAD><TITLE>MapServer Message</TITLE></HEAD>\n");
138 msIO_printf("<!-- %s -->\n", msGetVersion());
139 msIO_printf("<BODY BGCOLOR=\"#FFFFFF\">\n");
140 msWriteErrorXML(stdout);
141 msIO_printf("</BODY></HTML>");
142 }
143 } else {
144 msIO_setHeader("Content-type","text/html");
145 msIO_sendHeaders();
146 msIO_printf("<HTML>\n");
147 msIO_printf("<HEAD><TITLE>MapServer Message</TITLE></HEAD>\n");
148 msIO_printf("<!-- %s -->\n", msGetVersion());
149 msIO_printf("<BODY BGCOLOR=\"#FFFFFF\">\n");
150 msWriteErrorXML(stdout);
151 msIO_printf("</BODY></HTML>");
152 }
153 }
154}
155
156/*
157** Converts a string (e.g. form parameter) to a double, first checking the format against
158** a regular expression. returns an error if the format test fails.
159*/
160
161#define GET_NUMERIC(string,dbl) do { \
162 dbl = strtod((string), &strtoderr);\
163 if (*strtoderr) {\
164 msSetError(MS_TYPEERR, NULL, "GET_NUMERIC()");\
165 return MS_FAILURE;\
166 }\
167} while (0)
168
169static void setClassGroup(layerObj *layer, char *classgroup) {
170 int i;
171
172 if(!layer || !classgroup) return;
173
174 for(i=0; i<layer->numclasses; i++) {
175 if(layer->class[i]->group && strcmp(layer->class[i]->group, classgroup) == 0) {
176 msFree(layer->classgroup);
177 layer->classgroup = msStrdup(classgroup);
178 return; /* bail */
179 }
180 }
181}
182
183/*
184** Extract Map File name from params and load it.
185** Returns map object or NULL on error.
186*/
187mapObj *msCGILoadMap(mapservObj *mapserv)
188{
189 int i, j;
190 mapObj *map = NULL;
191 static mapObj *preloadedmap = NULL;
192 static time_t preloadedmap_mtime;
193 static char *ms_mapfile = NULL;
194 struct stat mapfile_stat;
195
196 /* check if we should use and/or create a pre-parsed mapfile */
197 ms_mapfile = getenv("MS_MAPFILE");
198 if(preloadedmap || ms_mapfile) {
199 if(preloadedmap) {
200 /* we already have a preloaded mapfile, check if the mapfile itself hasn't changed */
201 stat(ms_mapfile,&mapfile_stat);
202 if(mapfile_stat.st_mtime > preloadedmap_mtime) {
203 /* the mapfile has been updated on disk, discard the cached mapObj */
204 msFreeMap(preloadedmap);
205 preloadedmap = NULL;
206 msDebug("reloading mapfile %s as it has been changed on disk",ms_mapfile);
207 }
208 }
209 if(!preloadedmap) {
210 /* either the mapfile has never been loaded, or it has been destroyed because it was outdated */
211 preloadedmap = msLoadMap(ms_mapfile,NULL);
212 if(!preloadedmap) return NULL;
213 stat(ms_mapfile,&mapfile_stat);
214 preloadedmap_mtime = mapfile_stat.st_mtime;
215 }
216 map = msNewMapObj();
217 msCopyMap(map,preloadedmap);
218 } else {
219 for(i=0;i<mapserv->request->NumParams;i++) /* find the mapfile parameter first */
220 if(strcasecmp(mapserv->request->ParamNames[i], "map") == 0) break;
221
222 if(i == mapserv->request->NumParams) {
223 msSetError(MS_WEBERR, "CGI variable \"map\" is not set.", "msCGILoadMap()"); /* no default, outta here */
224 return NULL;
225 } else {
226 if(getenv(mapserv->request->ParamValues[i])) /* an environment variable references the actual file to use */
227 map = msLoadMap(getenv(mapserv->request->ParamValues[i]), NULL);
228 else {
229 /* by here we know the request isn't for something in an environment variable */
230 if(getenv("MS_MAP_NO_PATH")) {
231 msSetError(MS_WEBERR, "Mapfile not found in environment variables and this server is not configured for full paths.", "msCGILoadMap()");
232 return NULL;
233 }
234
235 if(getenv("MS_MAP_PATTERN") && msEvalRegex(getenv("MS_MAP_PATTERN"), mapserv->request->ParamValues[i]) != MS_TRUE) {
236 msSetError(MS_WEBERR, "Parameter 'map' value fails to validate.", "msCGILoadMap()");
237 return NULL;
238 }
239
240 /* ok to try to load now */
241 map = msLoadMap(mapserv->request->ParamValues[i], NULL);
242 }
243 }
244 }
245
246 if(!map) return NULL;
247
248 if(!msLookupHashTable(&(map->web.validation), "immutable")) {
249 /* check for any %variable% substitutions here, also do any map_ changes, we do this here so WMS/WFS */
250 /* services can take advantage of these "vendor specific" extensions */
251 for(i=0;i<mapserv->request->NumParams;i++) {
252 /*
253 ** a few CGI variables should be skipped altogether
254 **
255 ** qstring: there is separate per layer validation for attribute queries and the substitution checks
256 ** below conflict with that so we avoid it here
257 */
258 if(strncasecmp(mapserv->request->ParamNames[i],"qstring",7) == 0) continue;
259
260 /* check to see if there are any additions to the mapfile */
261 if(strncasecmp(mapserv->request->ParamNames[i],"map_",4) == 0 || strncasecmp(mapserv->request->ParamNames[i],"map.",4) == 0) {
262 if(msUpdateMapFromURL(map, mapserv->request->ParamNames[i], mapserv->request->ParamValues[i]) != MS_SUCCESS) {
263 msFreeMap(map);
264 return NULL;
265 }
266 continue;
267 }
268
269 if(strncasecmp(mapserv->request->ParamNames[i],"classgroup",10) == 0) { /* #4207 */
270 for(j=0; j<map->numlayers; j++) {
271 setClassGroup(GET_LAYER(map, j), mapserv->request->ParamValues[i]);
272 }
273 continue;
274 }
275 }
276
277 msApplySubstitutions(map, mapserv->request->ParamNames, mapserv->request->ParamValues, mapserv->request->NumParams);
278 msApplyDefaultSubstitutions(map);
279
280 /* check to see if a ogc map context is passed as argument. if there */
281 /* is one load it */
282
283 for(i=0;i<mapserv->request->NumParams;i++) {
284 if(strcasecmp(mapserv->request->ParamNames[i],"context") == 0) {
285 if(mapserv->request->ParamValues[i] && strlen(mapserv->request->ParamValues[i]) > 0) {
286 if(strncasecmp(mapserv->request->ParamValues[i],"http",4) == 0) {
287 if(msGetConfigOption(map, "CGI_CONTEXT_URL"))
288 msLoadMapContextURL(map, mapserv->request->ParamValues[i], MS_FALSE);
289 } else
290 msLoadMapContext(map, mapserv->request->ParamValues[i], MS_FALSE);
291 }
292 }
293 }
294 }
295
296 /*
297 * RFC-42 HTTP Cookie Forwarding
298 * Here we set the http_cookie_data metadata to handle the
299 * HTTP Cookie Forwarding. The content of this metadata is the cookie
300 * content. In the future, this metadata will probably be replaced
301 * by an object that is part of the mapObject that would contain
302 * information on the application status (such as cookie).
303 */
304 if( mapserv->request->httpcookiedata != NULL )
305 {
306 msInsertHashTable( &(map->web.metadata), "http_cookie_data",
307 mapserv->request->httpcookiedata );
308 }
309
310 return map;
311}
312
313
314/*
315** Set operation mode. First look in MS_MODE env. var. as a
316** default value that can be overridden by the mode=... CGI param.
317** Returns silently, leaving mapserv->Mode unchanged if mode param not set.
318*/
319int msCGISetMode(mapservObj *mapserv)
320{
321 const char *mode = NULL;
322 int i, j;
323
324
325 mode = getenv("MS_MODE");
326 for( i=0; i<mapserv->request->NumParams; i++ )
327 {
328 if(strcasecmp(mapserv->request->ParamNames[i], "mode") == 0)
329 {
330 mode = mapserv->request->ParamValues[i];
331 break;
332 }
333 }
334
335 if (mode) {
336 for(j=0; j<numModes; j++) {
337 if(strcasecmp(mode, modeStrings[j]) == 0) {
338 mapserv->Mode = j;
339 break;
340 }
341 }
342
343 if(j == numModes) {
344 msSetError(MS_WEBERR, "Invalid mode.", "msCGISetMode()");
345 return MS_FAILURE;
346 }
347 }
348
349 return MS_SUCCESS;
350}
351
352
353
354
355/*
356** Process CGI parameters.
357*/
358int msCGILoadForm(mapservObj *mapserv)
359{
360 int i,n;
361 char **tokens=NULL;
362 int rosa_type=0;
363 double tmpval;
364 char *strtoderr;
365
366 for(i=0;i<mapserv->request->NumParams;i++) { /* now process the rest of the form variables */
367 if(strlen(mapserv->request->ParamValues[i]) == 0)
368 continue;
369
370
371 if(strcasecmp(mapserv->request->ParamNames[i],"icon") == 0) {
372 mapserv->icon = msStrdup(mapserv->request->ParamValues[i]);
373 continue;
374 }
375
376 if(strcasecmp(mapserv->request->ParamNames[i],"queryfile") == 0) {
377 mapserv->QueryFile = msStrdup(mapserv->request->ParamValues[i]);
378 continue;
379 }
380
381 if(strcasecmp(mapserv->request->ParamNames[i],"savequery") == 0) {
382 mapserv->savequery = MS_TRUE;
383 continue;
384 }
385
386 /* Insecure as implemented, need to save someplace non accessible by everyone in the universe
387 if(strcasecmp(mapserv->request->ParamNames[i],"savemap") == 0) {
388 mapserv->savemap = MS_TRUE;
389 continue;
390 }
391 */
392
393 if(strcasecmp(mapserv->request->ParamNames[i],"zoom") == 0) {
394 GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->Zoom);
395 if((mapserv->Zoom > MAXZOOM) || (mapserv->Zoom < MINZOOM)) {
396 msSetError(MS_WEBERR, "Zoom value out of range.", "msCGILoadForm()");
397 return MS_FAILURE;
398 }
399 continue;
400 }
401
402 if(strcasecmp(mapserv->request->ParamNames[i],"zoomdir") == 0) {
403 GET_NUMERIC(mapserv->request->ParamValues[i],tmpval);
404 mapserv->ZoomDirection = (int)tmpval;
405 if((mapserv->ZoomDirection != -1) && (mapserv->ZoomDirection != 1) && (mapserv->ZoomDirection != 0)) {
406 msSetError(MS_WEBERR, "Zoom direction must be 1, 0 or -1.", "msCGILoadForm()");
407 return MS_FAILURE;
408 }
409 continue;
410 }
411
412 if(strcasecmp(mapserv->request->ParamNames[i],"zoomsize") == 0) { /* absolute zoom magnitude */
413 GET_NUMERIC(mapserv->request->ParamValues[i],tmpval);
414 mapserv->ZoomSize = (int)tmpval;
415 if((mapserv->ZoomSize > MAXZOOM) || (mapserv->ZoomSize < 1)) {
416 msSetError(MS_WEBERR, "Invalid zoom size.", "msCGILoadForm()");
417 return MS_FAILURE;
418 }
419 continue;
420 }
421
422 if(strcasecmp(mapserv->request->ParamNames[i],"imgext") == 0) { /* extent of an existing image in a web application */
423 tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n);
424
425 if(!tokens) {
426 msSetError(MS_MEMERR, NULL, "msCGILoadForm()");
427 return MS_FAILURE;
428 }
429
430 if(n != 4) {
431 msSetError(MS_WEBERR, "Not enough arguments for imgext.", "msCGILoadForm()");
432 return MS_FAILURE;
433 }
434
435 GET_NUMERIC(tokens[0],mapserv->ImgExt.minx);
436 GET_NUMERIC(tokens[1],mapserv->ImgExt.miny);
437 GET_NUMERIC(tokens[2],mapserv->ImgExt.maxx);
438 GET_NUMERIC(tokens[3],mapserv->ImgExt.maxy);
439
440 msFreeCharArray(tokens, 4);
441 continue;
442 }
443
444 if(strcasecmp(mapserv->request->ParamNames[i],"searchmap") == 0) {
445 mapserv->SearchMap = MS_TRUE;
446 continue;
447 }
448
449 if(strcasecmp(mapserv->request->ParamNames[i],"id") == 0) {
450 if(msEvalRegex(IDPATTERN, mapserv->request->ParamValues[i]) == MS_FALSE) {
451 msSetError(MS_WEBERR, "Parameter 'id' value fails to validate.", "msCGILoadForm()");
452 return MS_FAILURE;
453 }
454 strlcpy(mapserv->Id, mapserv->request->ParamValues[i], IDSIZE);
455 continue;
456 }
457
458 if(strcasecmp(mapserv->request->ParamNames[i],"mapext") == 0) { /* extent of the new map or query */
459
460 if(strncasecmp(mapserv->request->ParamValues[i],"shape",5) == 0)
461 mapserv->UseShapes = MS_TRUE;
462 else {
463 tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n);
464
465 if(!tokens) {
466 msSetError(MS_MEMERR, NULL, "msCGILoadForm()");
467 return MS_FAILURE;
468 }
469
470 if(n != 4) {
471 msSetError(MS_WEBERR, "Not enough arguments for mapext.", "msCGILoadForm()");
472 return MS_FAILURE;
473 }
474
475 GET_NUMERIC(tokens[0],mapserv->map->extent.minx);
476 GET_NUMERIC(tokens[1],mapserv->map->extent.miny);
477 GET_NUMERIC(tokens[2],mapserv->map->extent.maxx);
478 GET_NUMERIC(tokens[3],mapserv->map->extent.maxy);
479
480 msFreeCharArray(tokens, 4);
481
482#ifdef USE_PROJ
483 /*
484 * If there is a projection in the map file, and it is not lon/lat, and the
485 * extents "look like" they *are* lon/lat, based on their size,
486 * then convert the extents to the map file projection.
487 *
488 * DANGER: If the extents are legitimately in the mapfile projection
489 * and coincidentally fall in the lon/lat range, bad things
490 * will ensue.
491 */
492 if(mapserv->map->projection.proj && !pj_is_latlong(mapserv->map->projection.proj)
493 && (mapserv->map->extent.minx >= -180.0 && mapserv->map->extent.minx <= 180.0)
494 && (mapserv->map->extent.miny >= -90.0 && mapserv->map->extent.miny <= 90.0)
495 && (mapserv->map->extent.maxx >= -180.0 && mapserv->map->extent.maxx <= 180.0)
496 && (mapserv->map->extent.maxy >= -90.0 && mapserv->map->extent.maxy <= 90.0)) {
497 msProjectRect(&(mapserv->map->latlon), &(mapserv->map->projection), &(mapserv->map->extent)); /* extent is a in lat/lon */
498 }
499#endif
500
501 if((mapserv->map->extent.minx != mapserv->map->extent.maxx) && (mapserv->map->extent.miny != mapserv->map->extent.maxy)) { /* extent seems ok */
502 mapserv->CoordSource = FROMUSERBOX;
503 mapserv->QueryCoordSource = FROMUSERBOX;
504 }
505 }
506
507 continue;
508 }
509
510 if(strcasecmp(mapserv->request->ParamNames[i],"minx") == 0) { /* extent of the new map, in pieces */
511 GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->map->extent.minx);
512 continue;
513 }
514 if(strcasecmp(mapserv->request->ParamNames[i],"maxx") == 0) {
515 GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->map->extent.maxx);
516 continue;
517 }
518 if(strcasecmp(mapserv->request->ParamNames[i],"miny") == 0) {
519 GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->map->extent.miny);
520 continue;
521 }
522 if(strcasecmp(mapserv->request->ParamNames[i],"maxy") == 0) {
523 GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->map->extent.maxy);
524 mapserv->CoordSource = FROMUSERBOX;
525 mapserv->QueryCoordSource = FROMUSERBOX;
526 continue;
527 }
528
529 if(strcasecmp(mapserv->request->ParamNames[i],"mapxy") == 0) { /* user map coordinate */
530
531 if(strncasecmp(mapserv->request->ParamValues[i],"shape",5) == 0) {
532 mapserv->UseShapes = MS_TRUE;
533 } else {
534 tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n);
535
536 if(!tokens) {
537 msSetError(MS_MEMERR, NULL, "msCGILoadForm()");
538 return MS_FAILURE;
539 }
540
541 if(n != 2) {
542 msSetError(MS_WEBERR, "Not enough arguments for mapxy.", "msCGILoadForm()");
543 return MS_FAILURE;
544 }
545
546 GET_NUMERIC(tokens[0],mapserv->mappnt.x );
547 GET_NUMERIC(tokens[1],mapserv->mappnt.y );
548
549 msFreeCharArray(tokens, 2);
550
551#ifdef USE_PROJ
552 if(mapserv->map->projection.proj && !pj_is_latlong(mapserv->map->projection.proj)
553 && (mapserv->mappnt.x >= -180.0 && mapserv->mappnt.x <= 180.0)
554 && (mapserv->mappnt.y >= -90.0 && mapserv->mappnt.y <= 90.0)) {
555 msProjectPoint(&(mapserv->map->latlon), &(mapserv->map->projection), &mapserv->mappnt); /* point is a in lat/lon */
556 }
557#endif
558
559 if(mapserv->CoordSource == NONE) { /* don't override previous settings (i.e. buffer or scale ) */
560 mapserv->CoordSource = FROMUSERPNT;
561 mapserv->QueryCoordSource = FROMUSERPNT;
562 }
563 }
564 continue;
565 }
566
567 /*
568 ** Query shape consisting of map or image coordinates. It's almost identical processing so we'll do either in this block...
569 */
570 if(strcasecmp(mapserv->request->ParamNames[i], "mapshape") == 0 || strcasecmp(mapserv->request->ParamNames[i], "imgshape") == 0) {
571 if(strcasecmp(mapserv->request->ParamNames[i],"mapshape") == 0)
572 mapserv->QueryCoordSource = FROMUSERSHAPE;
573 else
574 mapserv->QueryCoordSource = FROMIMGSHAPE;
575
576 if(strchr(mapserv->request->ParamValues[i], '(') != NULL) { /* try WKT */
577 if((mapserv->map->query.shape = msShapeFromWKT(mapserv->request->ParamValues[i])) == NULL) {
578 msSetError(MS_WEBERR, "WKT parse failed for mapshape/imgshape.", "msCGILoadForm()");
579 return MS_FAILURE;
580 }
581 } else {
582 lineObj line={0,NULL};
583 char **tmp=NULL;
584 int n, j;
585
586 tmp = msStringSplit(mapserv->request->ParamValues[i], ' ', &n);
587
588 if(n%2 != 0 || n<8) { /* n must be even and be at least 8 */
589 msSetError(MS_WEBERR, "Malformed polygon geometry for mapshape/imgshape.", "msCGILoadForm()");
590 return MS_FAILURE;
591 }
592
593 line.numpoints = n/2;
594 if((line.point = (pointObj *)malloc(sizeof(pointObj)*line.numpoints)) == NULL) {
595 msSetError(MS_MEMERR, NULL, "msCGILoadForm()");
596 return MS_FAILURE;
597 }
598
599 if((mapserv->map->query.shape = (shapeObj *) malloc(sizeof(shapeObj))) == NULL) {
600 msSetError(MS_MEMERR, NULL, "msCGILoadForm()");
601 return MS_FAILURE;
602 }
603 msInitShape(mapserv->map->query.shape);
604 mapserv->map->query.shape->type = MS_SHAPE_POLYGON;
605
606 for(j=0; j<line.numpoints; j++) {
607 line.point[j].x = atof(tmp[2*j]);
608 line.point[j].y = atof(tmp[2*j+1]);
609
610#ifdef USE_PROJ
611 if(mapserv->QueryCoordSource == FROMUSERSHAPE && mapserv->map->projection.proj && !pj_is_latlong(mapserv->map->projection.proj)
612 && (line.point[j].x >= -180.0 && line.point[j].x <= 180.0)
613 && (line.point[j].y >= -90.0 && line.point[j].y <= 90.0)) {
614 msProjectPoint(&(mapserv->map->latlon), &(mapserv->map->projection), &line.point[j]); /* point is a in lat/lon */
615 }
616#endif
617 }
618
619 if(msAddLine(mapserv->map->query.shape, &line) == -1) {
620 msFree(line.point);
621 msFreeCharArray(tmp, n);
622 return MS_FAILURE;
623 }
624
625 msFree(line.point);
626 msFreeCharArray(tmp, n);
627 }
628
629 continue;
630 }
631
632 if(strcasecmp(mapserv->request->ParamNames[i],"img.x") == 0) { /* mouse click, in pieces */
633 GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->ImgPnt.x);
634 if((mapserv->ImgPnt.x > (2*mapserv->map->maxsize)) || (mapserv->ImgPnt.x < (-2*mapserv->map->maxsize))) {
635 msSetError(MS_WEBERR, "Coordinate out of range.", "msCGILoadForm()");
636 return MS_FAILURE;
637 }
638 mapserv->CoordSource = FROMIMGPNT;
639 mapserv->QueryCoordSource = FROMIMGPNT;
640 continue;
641 }
642 if(strcasecmp(mapserv->request->ParamNames[i],"img.y") == 0) {
643 GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->ImgPnt.y);
644 if((mapserv->ImgPnt.y > (2*mapserv->map->maxsize)) || (mapserv->ImgPnt.y < (-2*mapserv->map->maxsize))) {
645 msSetError(MS_WEBERR, "Coordinate out of range.", "msCGILoadForm()");
646 return MS_FAILURE;
647 }
648 mapserv->CoordSource = FROMIMGPNT;
649 mapserv->QueryCoordSource = FROMIMGPNT;
650 continue;
651 }
652
653 if(strcasecmp(mapserv->request->ParamNames[i],"imgxy") == 0) { /* mouse click, single variable */
654 if(mapserv->CoordSource == FROMIMGPNT)
655 continue;
656
657 tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n);
658
659 if(!tokens) {
660 msSetError(MS_MEMERR, NULL, "msCGILoadForm()");
661 return MS_FAILURE;
662 }
663
664 if(n != 2) {
665 msSetError(MS_WEBERR, "Not enough arguments for imgxy.", "msCGILoadForm()");
666 return MS_FAILURE;
667 }
668
669 GET_NUMERIC(tokens[0],mapserv->ImgPnt.x );
670 GET_NUMERIC(tokens[1],mapserv->ImgPnt.y );
671
672 msFreeCharArray(tokens, 2);
673
674 if((mapserv->ImgPnt.x > (2*mapserv->map->maxsize)) || (mapserv->ImgPnt.x < (-2*mapserv->map->maxsize)) || (mapserv->ImgPnt.y > (2*mapserv->map->maxsize)) || (mapserv->ImgPnt.y < (-2*mapserv->map->maxsize))) {
675 msSetError(MS_WEBERR, "Reference map coordinate out of range.", "msCGILoadForm()");
676 return MS_FAILURE;
677 }
678
679 if(mapserv->CoordSource == NONE) { /* override nothing since this parameter is usually used to hold a default value */
680 mapserv->CoordSource = FROMIMGPNT;
681 mapserv->QueryCoordSource = FROMIMGPNT;
682 }
683 continue;
684 }
685
686 if(strcasecmp(mapserv->request->ParamNames[i],"imgbox") == 0) { /* selection box (eg. mouse drag) */
687 tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n);
688
689 if(!tokens) {
690 msSetError(MS_MEMERR, NULL, "msCGILoadForm()");
691 return MS_FAILURE;
692 }
693
694 if(n != 4) {
695 msSetError(MS_WEBERR, "Not enough arguments for imgbox.", "msCGILoadForm()");
696 return MS_FAILURE;
697 }
698
699 GET_NUMERIC(tokens[0],mapserv->ImgBox.minx);
700 GET_NUMERIC(tokens[1],mapserv->ImgBox.miny);
701 GET_NUMERIC(tokens[2],mapserv->ImgBox.maxx);
702 GET_NUMERIC(tokens[3],mapserv->ImgBox.maxy);
703
704 msFreeCharArray(tokens, 4);
705
706 if((mapserv->ImgBox.minx != mapserv->ImgBox.maxx) && (mapserv->ImgBox.miny != mapserv->ImgBox.maxy)) { /* must not degenerate into a point */
707 mapserv->CoordSource = FROMIMGBOX;
708 mapserv->QueryCoordSource = FROMIMGBOX;
709 }
710 continue;
711 }
712
713 if(strcasecmp(mapserv->request->ParamNames[i],"ref.x") == 0) { /* mouse click in reference image, in pieces */
714 GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->RefPnt.x);
715 if((mapserv->RefPnt.x > (2*mapserv->map->maxsize)) || (mapserv->RefPnt.x < (-2*mapserv->map->maxsize))) {
716 msSetError(MS_WEBERR, "Coordinate out of range.", "msCGILoadForm()");
717 return MS_FAILURE;
718 }
719 mapserv->CoordSource = FROMREFPNT;
720 continue;
721 }
722 if(strcasecmp(mapserv->request->ParamNames[i],"ref.y") == 0) {
723 GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->RefPnt.y);
724 if((mapserv->RefPnt.y > (2*mapserv->map->maxsize)) || (mapserv->RefPnt.y < (-2*mapserv->map->maxsize))) {
725 msSetError(MS_WEBERR, "Coordinate out of range.", "msCGILoadForm()");
726 return MS_FAILURE;
727 }
728 mapserv->CoordSource = FROMREFPNT;
729 continue;
730 }
731
732 if(strcasecmp(mapserv->request->ParamNames[i],"refxy") == 0) { /* mouse click in reference image, single variable */
733 tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n);
734
735 if(!tokens) {
736 msSetError(MS_MEMERR, NULL, "msCGILoadForm()");
737 return MS_FAILURE;
738 }
739
740 if(n != 2) {
741 msSetError(MS_WEBERR, "Not enough arguments for imgxy.", "msCGILoadForm()");
742 return MS_FAILURE;
743 }
744
745 GET_NUMERIC(tokens[0],mapserv->RefPnt.x);
746 GET_NUMERIC(tokens[1],mapserv->RefPnt.y);
747
748 msFreeCharArray(tokens, 2);
749
750 if((mapserv->RefPnt.x > (2*mapserv->map->maxsize)) || (mapserv->RefPnt.x < (-2*mapserv->map->maxsize)) || (mapserv->RefPnt.y > (2*mapserv->map->maxsize)) || (mapserv->RefPnt.y < (-2*mapserv->map->maxsize))) {
751 msSetError(MS_WEBERR, "Reference map coordinate out of range.", "msCGILoadForm()");
752 return MS_FAILURE;
753 }
754
755 mapserv->CoordSource = FROMREFPNT;
756 continue;
757 }
758
759 if(strcasecmp(mapserv->request->ParamNames[i],"buffer") == 0) { /* radius (map units), actually 1/2 square side */
760 GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->Buffer);
761 mapserv->CoordSource = FROMBUF;
762 mapserv->QueryCoordSource = FROMUSERPNT;
763 continue;
764 }
765
766 if(strcasecmp(mapserv->request->ParamNames[i],"scale") == 0 || strcasecmp(mapserv->request->ParamNames[i],"scaledenom") == 0) { /* scale for new map */
767 GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->ScaleDenom);
768 if(mapserv->ScaleDenom <= 0) {
769 msSetError(MS_WEBERR, "Scale out of range.", "msCGILoadForm()");
770 return MS_FAILURE;
771 }
772 mapserv->CoordSource = FROMSCALE;
773 mapserv->QueryCoordSource = FROMUSERPNT;
774 continue;
775 }
776
777 if(strcasecmp(mapserv->request->ParamNames[i],"imgsize") == 0) { /* size of existing image (pixels) */
778 tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n);
779
780 if(!tokens) {
781 msSetError(MS_MEMERR, NULL, "msCGILoadForm()");
782 return MS_FAILURE;
783 }
784
785 if(n != 2) {
786 msSetError(MS_WEBERR, "Not enough arguments for imgsize.", "msCGILoadForm()");
787 return MS_FAILURE;
788 }
789
790 GET_NUMERIC(tokens[0],tmpval);
791 mapserv->ImgCols = (int)tmpval;
792 GET_NUMERIC(tokens[1],tmpval);
793 mapserv->ImgRows = (int)tmpval;
794
795 msFreeCharArray(tokens, 2);
796
797 if(mapserv->ImgCols > mapserv->map->maxsize || mapserv->ImgRows > mapserv->map->maxsize || mapserv->ImgCols <= 0 || mapserv->ImgRows <= 0) {
798 msSetError(MS_WEBERR, "Image size out of range.", "msCGILoadForm()");
799 return MS_FAILURE;
800 }
801
802 continue;
803 }
804
805 if(strcasecmp(mapserv->request->ParamNames[i],"mapsize") == 0) { /* size of new map (pixels) */
806 tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n);
807
808 if(!tokens) {
809 msSetError(MS_MEMERR, NULL, "msCGILoadForm()");
810 return MS_FAILURE;
811 }
812
813 if(n != 2) {
814 msSetError(MS_WEBERR, "Not enough arguments for mapsize.", "msCGILoadForm()");
815 return MS_FAILURE;
816 }
817
818 GET_NUMERIC(tokens[0],tmpval);
819 mapserv->map->width = (int)tmpval;
820 GET_NUMERIC(tokens[1],tmpval);
821 mapserv->map->height = (int)tmpval;
822
823 msFreeCharArray(tokens, 2);
824
825 if(mapserv->map->width > mapserv->map->maxsize || mapserv->map->height > mapserv->map->maxsize || mapserv->map->width <= 0 || mapserv->map->height <= 0) {
826 msSetError(MS_WEBERR, "Image size out of range.", "msCGILoadForm()");
827 return MS_FAILURE;
828 }
829 continue;
830 }
831
832 if(strncasecmp(mapserv->request->ParamNames[i],"layers", 6) == 0) { /* turn a set of layers, delimited by spaces, on */
833
834 /* If layers=all then turn on all layers */
835 if (strcasecmp(mapserv->request->ParamValues[i], "all") == 0 && mapserv->map != NULL) {
836 int l;
837
838 /* Reset NumLayers=0. If individual layers were already selected then free the previous values. */
839 for(l=0; l<mapserv->NumLayers; l++)
840 msFree(mapserv->Layers[l]);
841 mapserv->NumLayers=0;
842
843 for(mapserv->NumLayers=0; mapserv->NumLayers < mapserv->map->numlayers; mapserv->NumLayers++) {
844 if(msGrowMapservLayers(mapserv) == MS_FAILURE)
845 return MS_FAILURE;
846
847 if(GET_LAYER(mapserv->map, mapserv->NumLayers)->name) {
848 mapserv->Layers[mapserv->NumLayers] = msStrdup(GET_LAYER(mapserv->map, mapserv->NumLayers)->name);
849 } else {
850 mapserv->Layers[mapserv->NumLayers] = msStrdup("");
851 }
852 }
853 } else {
854 int num_layers=0, l;
855 char **layers=NULL;
856
857 layers = msStringSplit(mapserv->request->ParamValues[i], ' ', &(num_layers));
858 for(l=0; l<num_layers; l++) {
859 if(msGrowMapservLayers(mapserv) == MS_FAILURE)
860 return MS_FAILURE;
861 mapserv->Layers[mapserv->NumLayers++] = msStrdup(layers[l]);
862 }
863
864 msFreeCharArray(layers, num_layers);
865 num_layers = 0;
866 }
867
868 continue;
869 }
870
871 if(strncasecmp(mapserv->request->ParamNames[i],"layer", 5) == 0) { /* turn a single layer/group on */
872 if(msGrowMapservLayers(mapserv) == MS_FAILURE)
873 return MS_FAILURE;
874 mapserv->Layers[mapserv->NumLayers] = msStrdup(mapserv->request->ParamValues[i]);
875 mapserv->NumLayers++;
876 continue;
877 }
878
879 if(strcasecmp(mapserv->request->ParamNames[i],"qlayer") == 0) { /* layer to query (i.e search) */
880 mapserv->QueryLayer = msStrdup(mapserv->request->ParamValues[i]);
881 continue;
882 }
883
884 if(strcasecmp(mapserv->request->ParamNames[i],"qitem") == 0) { /* attribute to query on (optional) */
885 mapserv->QueryItem = msStrdup(mapserv->request->ParamValues[i]);
886 continue;
887 }
888
889 if(strcasecmp(mapserv->request->ParamNames[i],"qstring") == 0) { /* attribute query string */
890 mapserv->QueryString = msStrdup(mapserv->request->ParamValues[i]);
891 continue;
892 }
893
894 if(strcasecmp(mapserv->request->ParamNames[i],"qformat") == 0) { /* format to apply to query results (shortcut instead of having to use "map.web=QUERYFORMAT+foo") */
895 if(mapserv->map->web.queryformat) free(mapserv->map->web.queryformat); /* avoid leak */
896 mapserv->map->web.queryformat = msStrdup(mapserv->request->ParamValues[i]);
897 continue;
898 }
899
900 if(strcasecmp(mapserv->request->ParamNames[i],"slayer") == 0) { /* layer to select (for feature based search) */
901 mapserv->SelectLayer = msStrdup(mapserv->request->ParamValues[i]);
902 continue;
903 }
904
905 if(strcasecmp(mapserv->request->ParamNames[i],"shapeindex") == 0) { /* used for index queries */
906 GET_NUMERIC(mapserv->request->ParamValues[i],tmpval);
907 mapserv->ShapeIndex = (int)tmpval;
908 continue;
909 }
910 if(strcasecmp(mapserv->request->ParamNames[i],"tileindex") == 0) {
911 GET_NUMERIC(mapserv->request->ParamValues[i],tmpval);
912 mapserv->TileIndex = (int)tmpval;
913 continue;
914 }
915
916 /* --------------------------------------------------------------------
917 * The following code is used to support mode=tile
918 * -------------------------------------------------------------------- */
919
920 if(strcasecmp(mapserv->request->ParamNames[i], "tilemode") == 0) {
921 /* currently, only valid tilemode is "spheremerc" */
922 if( strcasecmp(mapserv->request->ParamValues[i], "gmap") == 0) {
923 mapserv->TileMode = TILE_GMAP;
924 } else if ( strcasecmp(mapserv->request->ParamValues[i], "ve") == 0 ) {
925 mapserv->TileMode = TILE_VE;
926 } else {
927 msSetError(MS_WEBERR, "Invalid tilemode. Use one of: gmap, ve", "msCGILoadForm()");
928 return MS_FAILURE;
929 }
930 continue;
931 }
932
933 if(strcasecmp(mapserv->request->ParamNames[i],"tile") == 0) {
934
935 if( strlen(mapserv->request->ParamValues[i]) < 1 ) {
936 msSetError(MS_WEBERR, "Empty tile parameter.", "msCGILoadForm()");
937 return MS_FAILURE;
938 }
939 mapserv->CoordSource = FROMTILE;
940 mapserv->TileCoords = msStrdup(mapserv->request->ParamValues[i]);
941
942 continue;
943 }
944
945 /* -------------------------------------------------------------------- */
946 /* The following code is used to support the rosa applet (for */
947 /* more information on Rosa, please consult : */
948 /* http://www.maptools.org/rosa/) . */
949 /* This code was provided by Tim.Mackey@agso.gov.au. */
950 /* */
951 /* For Application using it can be seen at : */
952 /* http://www.agso.gov.au/map/pilbara/ */
953 /* */
954 /* -------------------------------------------------------------------- */
955
956 if(strcasecmp(mapserv->request->ParamNames[i],"INPUT_TYPE") == 0)
957 { /* Rosa input type */
958 if(strcasecmp(mapserv->request->ParamValues[i],"auto_rect") == 0)
959 {
960 rosa_type=1; /* rectangle */
961 continue;
962 }
963
964 if(strcasecmp(mapserv->request->ParamValues[i],"auto_point") == 0)
965 {
966 rosa_type=2; /* point */
967 continue;
968 }
969 }
970 if(strcasecmp(mapserv->request->ParamNames[i],"INPUT_COORD") == 0)
971 { /* Rosa coordinates */
972
973 switch(rosa_type)
974 {
975 case 1:
976 sscanf(mapserv->request->ParamValues[i],"%lf,%lf;%lf,%lf",
977 &mapserv->ImgBox.minx,&mapserv->ImgBox.miny,&mapserv->ImgBox.maxx,
978 &mapserv->ImgBox.maxy);
979 if((mapserv->ImgBox.minx != mapserv->ImgBox.maxx) &&
980 (mapserv->ImgBox.miny != mapserv->ImgBox.maxy))
981 {
982 mapserv->CoordSource = FROMIMGBOX;
983 mapserv->QueryCoordSource = FROMIMGBOX;
984 }
985 else
986 {
987 mapserv->CoordSource = FROMIMGPNT;
988 mapserv->QueryCoordSource = FROMIMGPNT;
989 mapserv->ImgPnt.x=mapserv->ImgBox.minx;
990 mapserv->ImgPnt.y=mapserv->ImgBox.miny;
991 }
992 break;
993 case 2:
994 sscanf(mapserv->request->ParamValues[i],"%lf,%lf",&mapserv->ImgPnt.x,
995 &mapserv->ImgPnt.y);
996 mapserv->CoordSource = FROMIMGPNT;
997 mapserv->QueryCoordSource = FROMIMGPNT;
998 break;
999 }
1000 continue;
1001 }
1002 /* -------------------------------------------------------------------- */
1003 /* end of code for Rosa support. */
1004 /* -------------------------------------------------------------------- */
1005
1006 } /* next parameter */
1007
1008 if(mapserv->Mode == ZOOMIN) {
1009 mapserv->ZoomDirection = 1;
1010 mapserv->Mode = BROWSE;
1011 }
1012 if(mapserv->Mode == ZOOMOUT) {
1013 mapserv->ZoomDirection = -1;
1014 mapserv->Mode = BROWSE;
1015 }
1016
1017 if(mapserv->ZoomSize != 0) { /* use direction and magnitude to calculate zoom */
1018 if(mapserv->ZoomDirection == 0) {
1019 mapserv->fZoom = 1;
1020 } else {
1021 mapserv->fZoom = mapserv->ZoomSize*mapserv->ZoomDirection;
1022 if(mapserv->fZoom < 0)
1023 mapserv->fZoom = 1.0/MS_ABS(mapserv->fZoom);
1024 }
1025 } else { /* use single value for zoom */
1026 if((mapserv->Zoom >= -1) && (mapserv->Zoom <= 1)) {
1027 mapserv->fZoom = 1; /* pan */
1028 } else {
1029 if(mapserv->Zoom < 0)
1030 mapserv->fZoom = 1.0/MS_ABS(mapserv->Zoom);
1031 else
1032 mapserv->fZoom = mapserv->Zoom;
1033 }
1034 }
1035
1036 if(mapserv->ImgRows == -1) mapserv->ImgRows = mapserv->map->height;
1037 if(mapserv->ImgCols == -1) mapserv->ImgCols = mapserv->map->width;
1038 if(mapserv->map->height == -1) mapserv->map->height = mapserv->ImgRows;
1039 if(mapserv->map->width == -1) mapserv->map->width = mapserv->ImgCols;
1040 return MS_SUCCESS;
1041}
1042
1043int setExtentFromShapes(mapservObj *mapserv) {
1044 int found=0;
1045 double dx, dy, cellsize;
1046
1047 rectObj tmpext={-1.0,-1.0,-1.0,-1.0};
1048 pointObj tmppnt={-1.0,-1.0};
1049
1050 found = msGetQueryResultBounds(mapserv->map, &(tmpext));
1051
1052 dx = tmpext.maxx - tmpext.minx;
1053 dy = tmpext.maxy - tmpext.miny;
1054
1055 tmppnt.x = (tmpext.maxx + tmpext.minx)/2;
1056 tmppnt.y = (tmpext.maxy + tmpext.miny)/2;
1057 tmpext.minx -= dx*EXTENT_PADDING/2.0;
1058 tmpext.maxx += dx*EXTENT_PADDING/2.0;
1059 tmpext.miny -= dy*EXTENT_PADDING/2.0;
1060 tmpext.maxy += dy*EXTENT_PADDING/2.0;
1061
1062 if(mapserv->ScaleDenom != 0) { /* apply the scale around the center point (tmppnt) */
1063 cellsize = (mapserv->ScaleDenom/mapserv->map->resolution)/msInchesPerUnit(mapserv->map->units,0); /* user supplied a point and a scale */
1064 tmpext.minx = tmppnt.x - cellsize*mapserv->map->width/2.0;
1065 tmpext.miny = tmppnt.y - cellsize*mapserv->map->height/2.0;
1066 tmpext.maxx = tmppnt.x + cellsize*mapserv->map->width/2.0;
1067 tmpext.maxy = tmppnt.y + cellsize*mapserv->map->height/2.0;
1068 } else if(mapserv->Buffer != 0) { /* apply the buffer around the center point (tmppnt) */
1069 tmpext.minx = tmppnt.x - mapserv->Buffer;
1070 tmpext.miny = tmppnt.y - mapserv->Buffer;
1071 tmpext.maxx = tmppnt.x + mapserv->Buffer;
1072 tmpext.maxy = tmppnt.y + mapserv->Buffer;
1073 }
1074
1075 /* in case we don't get usable extent at this point (i.e. single point result) */
1076 if(!MS_VALID_EXTENT(tmpext)) {
1077 if(mapserv->map->web.minscaledenom > 0) { /* try web object minscale first */
1078 cellsize = (mapserv->map->web.minscaledenom/mapserv->map->resolution)/msInchesPerUnit(mapserv->map->units,0); /* user supplied a point and a scale */
1079 tmpext.minx = tmppnt.x - cellsize*mapserv->map->width/2.0;
1080 tmpext.miny = tmppnt.y - cellsize*mapserv->map->height/2.0;
1081 tmpext.maxx = tmppnt.x + cellsize*mapserv->map->width/2.0;
1082 tmpext.maxy = tmppnt.y + cellsize*mapserv->map->height/2.0;
1083 } else {
1084 msSetError(MS_WEBERR, "No way to generate a valid map extent from selected shapes.", "mapserv()");
1085 return MS_FAILURE;
1086 }
1087 }
1088
1089 mapserv->mappnt = tmppnt;
1090 mapserv->map->extent = mapserv->RawExt = tmpext; /* save unadjusted extent */
1091
1092 return MS_SUCCESS;
1093}
1094
1095
1096/* FIX: NEED ERROR CHECKING HERE FOR IMGPNT or MAPPNT */
1097void setCoordinate(mapservObj *mapserv)
1098{
1099 double cellx,celly;
1100
1101 cellx = MS_CELLSIZE(mapserv->ImgExt.minx, mapserv->ImgExt.maxx, mapserv->ImgCols);
1102 celly = MS_CELLSIZE(mapserv->ImgExt.miny, mapserv->ImgExt.maxy, mapserv->ImgRows);
1103
1104 mapserv->mappnt.x = MS_IMAGE2MAP_X(mapserv->ImgPnt.x, mapserv->ImgExt.minx, cellx);
1105 mapserv->mappnt.y = MS_IMAGE2MAP_Y(mapserv->ImgPnt.y, mapserv->ImgExt.maxy, celly);
1106
1107 return;
1108}
1109
1110
1111int msCGIDispatchBrowseRequest(mapservObj *mapserv) {
1112 char *template = NULL;
1113 int i,status;
1114 for(i=0;i<mapserv->request->NumParams;i++) /* find the template param value */
1115 if (strcasecmp(mapserv->request->ParamNames[i], "template") == 0)
1116 template = mapserv->request->ParamValues[i];
1117
1118 if ( (!mapserv->map->web.template) && (template==NULL || (strcasecmp(template, "openlayers")!=0)) ) {
1119 msSetError(MS_WEBERR, "Traditional BROWSE mode requires a TEMPLATE in the WEB section, but none was provided.", "mapserv()");
1120 return MS_FAILURE;
1121 }
1122
1123 if(mapserv->QueryFile) {
1124 status = msLoadQuery(mapserv->map, mapserv->QueryFile);
1125 if(status != MS_SUCCESS) return MS_FAILURE;
1126 }
1127
1128 status = setExtent(mapserv);
1129 if(status != MS_SUCCESS) return MS_FAILURE;
1130 status = checkWebScale(mapserv);
1131 if(status != MS_SUCCESS) return MS_FAILURE;
1132
1133 /* -------------------------------------------------------------------- */
1134 /* generate map, legend, scalebar and refernce images. */
1135 /* -------------------------------------------------------------------- */
1136 if(msGenerateImages(mapserv, MS_FALSE, MS_TRUE) != MS_SUCCESS)
1137 return MS_FAILURE;
1138
1139 if ( (template != NULL) && (strcasecmp(template, "openlayers")==0) ) {
1140 msIO_setHeader("Content-type","text/html");
1141 msIO_sendHeaders();
1142 if (msReturnOpenLayersPage(mapserv) != MS_SUCCESS)
1143 return MS_FAILURE;
1144 }
1145 else if(mapserv->QueryFile) {
1146 if(msReturnTemplateQuery(mapserv, mapserv->map->web.queryformat, NULL) != MS_SUCCESS)
1147 return MS_FAILURE;
1148 } else {
1149 if(TEMPLATE_TYPE(mapserv->map->web.template) == MS_FILE) { /* if thers's an html template, then use it */
1150 if(mapserv->sendheaders) {
1151 msIO_setHeader("Content-type",mapserv->map->web.browseformat); /* write MIME header */
1152 msIO_sendHeaders();
1153 }
1154 if(msReturnPage(mapserv, mapserv->map->web.template, BROWSE, NULL) != MS_SUCCESS)
1155 return MS_FAILURE;
1156 } else {
1157 if(msReturnURL(mapserv, mapserv->map->web.template, BROWSE) != MS_SUCCESS)
1158 return MS_FAILURE;
1159 }
1160 }
1161 return MS_SUCCESS;
1162}
1163
1164
1165int msCGIDispatchCoordinateRequest(mapservObj *mapserv) {
1166 setCoordinate(mapserv); /* mouse click => map coord */
1167 msIO_printf("Your \"<i>click</i>\" corresponds to (approximately): (%g, %g).",
1168 mapserv->mappnt.x, mapserv->mappnt.y);
1169
1170#ifdef USE_PROJ
1171 if(mapserv->map->projection.proj != NULL && !pj_is_latlong(mapserv->map->projection.proj) ) {
1172 pointObj p=mapserv->mappnt;
1173 msProjectPoint(&(mapserv->map->projection), &(mapserv->map->latlon), &p);
1174 msIO_printf("Computed lat/lon value is (%g, %g).\n",p.x, p.y);
1175 }
1176#endif
1177 return MS_SUCCESS;
1178}
1179
1180int msCGIDispatchQueryRequest(mapservObj *mapserv) {
1181 int status,i,j;
1182 char buffer[1024];
1183 if(mapserv->QueryFile) { /* already got a completed query */
1184 status = msLoadQuery(mapserv->map, mapserv->QueryFile);
1185 if(status != MS_SUCCESS) return MS_FAILURE;
1186 } else {
1187
1188 if((mapserv->QueryLayerIndex = msGetLayerIndex(mapserv->map, mapserv->QueryLayer)) != -1) /* force the query layer on */
1189 GET_LAYER(mapserv->map, mapserv->QueryLayerIndex)->status = MS_ON;
1190
1191 switch(mapserv->Mode) {
1192 case ITEMFEATUREQUERY:
1193 case ITEMFEATURENQUERY:
1194 if((mapserv->SelectLayerIndex = msGetLayerIndex(mapserv->map, mapserv->SelectLayer)) == -1) { /* force the selection layer on */
1195 msSetError(MS_WEBERR, "Selection layer not set or references an invalid layer.", "mapserv()");
1196 return MS_FAILURE;
1197 }
1198 GET_LAYER(mapserv->map, mapserv->SelectLayerIndex)->status = MS_ON;
1199
1200 /* validate the qstring parameter */
1201 if(msValidateParameter(mapserv->QueryString, msLookupHashTable(&(GET_LAYER(mapserv->map, mapserv->SelectLayerIndex)->validation), "qstring"),
1202 msLookupHashTable(&(mapserv->map->web.validation), "qstring"),
1203 msLookupHashTable(&(GET_LAYER(mapserv->map, mapserv->SelectLayerIndex)->metadata), "qstring_validation_pattern"), NULL) != MS_SUCCESS) {
1204 msSetError(MS_WEBERR, "Parameter 'qstring' value fails to validate.", "mapserv()");
1205 return MS_FAILURE;
1206 }
1207
1208 if(mapserv->QueryCoordSource != NONE && !mapserv->UseShapes)
1209 if(MS_SUCCESS != setExtent(mapserv)) /* set user area of interest */
1210 return MS_FAILURE;
1211
1212 mapserv->map->query.type = MS_QUERY_BY_ATTRIBUTE;
1213 if(mapserv->QueryItem) mapserv->map->query.item = msStrdup(mapserv->QueryItem);
1214 if(mapserv->QueryString) mapserv->map->query.str = msStrdup(mapserv->QueryString);
1215
1216 mapserv->map->query.rect = mapserv->map->extent;
1217
1218 mapserv->map->query.mode = MS_QUERY_MULTIPLE;
1219 if(mapserv->Mode == ITEMFEATUREQUERY)
1220 mapserv->map->query.mode = MS_QUERY_SINGLE;
1221
1222 mapserv->map->query.layer = mapserv->QueryLayerIndex;
1223 mapserv->map->query.slayer = mapserv->SelectLayerIndex; /* this will trigger the feature query eventually */
1224 break;
1225 case FEATUREQUERY:
1226 case FEATURENQUERY:
1227 if((mapserv->SelectLayerIndex = msGetLayerIndex(mapserv->map, mapserv->SelectLayer)) == -1) { /* force the selection layer on */
1228 msSetError(MS_WEBERR, "Selection layer not set or references an invalid layer.", "mapserv()");
1229 return MS_FAILURE;
1230 }
1231 GET_LAYER(mapserv->map, mapserv->SelectLayerIndex)->status = MS_ON;
1232
1233 if(mapserv->Mode == FEATUREQUERY) {
1234 switch(mapserv->QueryCoordSource) {
1235 case FROMIMGPNT:
1236 mapserv->map->extent = mapserv->ImgExt; /* use the existing map extent */
1237 setCoordinate(mapserv);
1238 break;
1239 case FROMUSERPNT:
1240 break;
1241 default:
1242 msSetError(MS_WEBERR, "No way to perform the initial search, not enough information.", "mapserv()");
1243 return MS_FAILURE;
1244 break;
1245 }
1246
1247 mapserv->map->query.type = MS_QUERY_BY_POINT;
1248 mapserv->map->query.mode = MS_QUERY_SINGLE;
1249
1250 mapserv->map->query.point = mapserv->mappnt;
1251 mapserv->map->query.buffer = mapserv->Buffer;
1252
1253 mapserv->map->query.layer = mapserv->QueryLayerIndex;
1254 mapserv->map->query.slayer = mapserv->SelectLayerIndex; /* this will trigger the feature query eventually */
1255 } else { /* FEATURENQUERY */
1256 switch(mapserv->QueryCoordSource) {
1257 case FROMIMGPNT:
1258 mapserv->map->extent = mapserv->ImgExt; /* use the existing map extent */
1259 setCoordinate(mapserv);
1260 mapserv->map->query.type = MS_QUERY_BY_POINT;
1261 break;
1262 case FROMIMGBOX:
1263 /* TODO: this option was present but with no code to leverage the image box... */
1264 break;
1265 case FROMUSERPNT:
1266 mapserv->map->query.type = MS_QUERY_BY_POINT;
1267 default:
1268 if(MS_SUCCESS != setExtent(mapserv)) {
1269 return MS_FAILURE;
1270 }
1271 mapserv->map->query.type = MS_QUERY_BY_RECT;
1272 break;
1273 }
1274 }
1275
1276 mapserv->map->query.mode = MS_QUERY_MULTIPLE;
1277
1278 mapserv->map->query.rect = mapserv->map->extent;
1279 mapserv->map->query.point = mapserv->mappnt;
1280 mapserv->map->query.buffer = mapserv->Buffer;
1281
1282 mapserv->map->query.layer = mapserv->QueryLayerIndex;
1283 mapserv->map->query.slayer = mapserv->SelectLayerIndex;
1284 break;
1285 case ITEMQUERY:
1286 case ITEMNQUERY:
1287 if(mapserv->QueryLayerIndex < 0 || mapserv->QueryLayerIndex >= mapserv->map->numlayers) {
1288 msSetError(MS_WEBERR, "Query layer not set or references an invalid layer.", "mapserv()");
1289 return MS_FAILURE;
1290 }
1291
1292 /* validate the qstring parameter */
1293 if(msValidateParameter(mapserv->QueryString, msLookupHashTable(&(GET_LAYER(mapserv->map, mapserv->QueryLayerIndex)->validation), "qstring"),
1294 msLookupHashTable(&(mapserv->map->web.validation), "qstring"),
1295 msLookupHashTable(&(GET_LAYER(mapserv->map, mapserv->QueryLayerIndex)->metadata), "qstring_validation_pattern"), NULL) != MS_SUCCESS) {
1296 msSetError(MS_WEBERR, "Parameter 'qstring' value fails to validate.", "mapserv()");
1297 return MS_FAILURE;
1298 }
1299
1300 if(mapserv->QueryCoordSource != NONE && !mapserv->UseShapes)
1301 if(MS_SUCCESS != setExtent(mapserv)) /* set user area of interest */
1302 return MS_FAILURE;
1303
1304 mapserv->map->query.type = MS_QUERY_BY_ATTRIBUTE;
1305 mapserv->map->query.layer = mapserv->QueryLayerIndex;
1306 if(mapserv->QueryItem) mapserv->map->query.item = msStrdup(mapserv->QueryItem);
1307 if(mapserv->QueryString) mapserv->map->query.str = msStrdup(mapserv->QueryString);
1308
1309 mapserv->map->query.rect = mapserv->map->extent;
1310
1311 mapserv->map->query.mode = MS_QUERY_MULTIPLE;
1312 if(mapserv->Mode == ITEMQUERY) mapserv->map->query.mode = MS_QUERY_SINGLE;
1313 break;
1314 case NQUERY:
1315 mapserv->map->query.mode = MS_QUERY_MULTIPLE; /* all of these cases return multiple results */
1316 mapserv->map->query.layer = mapserv->QueryLayerIndex;
1317
1318 switch(mapserv->QueryCoordSource) {
1319 case FROMIMGPNT:
1320 setCoordinate(mapserv);
1321
1322 if(mapserv->SearchMap) { /* compute new extent, pan etc then search that extent */
1323 if(MS_SUCCESS != setExtent(mapserv)) /* set user area of interest */
1324 return MS_FAILURE;
1325 mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height);
1326 if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE;
1327 mapserv->map->query.rect = mapserv->map->extent;
1328 mapserv->map->query.type = MS_QUERY_BY_RECT;
1329 } else {
1330 mapserv->map->extent = mapserv->ImgExt; /* use the existing image parameters */
1331 mapserv->map->width = mapserv->ImgCols;
1332 mapserv->map->height = mapserv->ImgRows;
1333 if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE;
1334 mapserv->map->query.point = mapserv->mappnt;
1335 mapserv->map->query.type = MS_QUERY_BY_POINT;
1336 }
1337
1338 break;
1339 case FROMIMGBOX:
1340 if(mapserv->SearchMap) { /* compute new extent, pan etc then search that extent */
1341 setExtent(mapserv);
1342 if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE;
1343 mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height);
1344 mapserv->map->query.rect = mapserv->map->extent;
1345 mapserv->map->query.type = MS_QUERY_BY_RECT;
1346 } else {
1347 double cellx, celly;
1348
1349 mapserv->map->extent = mapserv->ImgExt; /* use the existing image parameters */
1350 mapserv->map->width = mapserv->ImgCols;
1351 mapserv->map->height = mapserv->ImgRows;
1352 if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE;
1353 cellx = MS_CELLSIZE(mapserv->ImgExt.minx, mapserv->ImgExt.maxx, mapserv->ImgCols); /* calculate the new search extent */
1354 celly = MS_CELLSIZE(mapserv->ImgExt.miny, mapserv->ImgExt.maxy, mapserv->ImgRows);
1355 mapserv->RawExt.minx = MS_IMAGE2MAP_X(mapserv->ImgBox.minx, mapserv->ImgExt.minx, cellx);
1356 mapserv->RawExt.maxx = MS_IMAGE2MAP_X(mapserv->ImgBox.maxx, mapserv->ImgExt.minx, cellx);
1357 mapserv->RawExt.maxy = MS_IMAGE2MAP_Y(mapserv->ImgBox.miny, mapserv->ImgExt.maxy, celly); /* y's are flip flopped because img/map coordinate systems are */
1358 mapserv->RawExt.miny = MS_IMAGE2MAP_Y(mapserv->ImgBox.maxy, mapserv->ImgExt.maxy, celly);
1359
1360 mapserv->map->query.rect = mapserv->RawExt;
1361 mapserv->map->query.type = MS_QUERY_BY_RECT;
1362 }
1363 break;
1364 case FROMIMGSHAPE:
1365 mapserv->map->extent = mapserv->ImgExt; /* use the existing image parameters */
1366 mapserv->map->width = mapserv->ImgCols;
1367 mapserv->map->height = mapserv->ImgRows;
1368 mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height);
1369 if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE;
1370
1371 /* convert from image to map coordinates here (see setCoordinate) */
1372 for(i=0; i<mapserv->map->query.shape->numlines; i++) {
1373 for(j=0; j<mapserv->map->query.shape->line[i].numpoints; j++) {
1374 mapserv->map->query.shape->line[i].point[j].x = MS_IMAGE2MAP_X(mapserv->map->query.shape->line[i].point[j].x, mapserv->map->extent.minx, mapserv->map->cellsize);
1375 mapserv->map->query.shape->line[i].point[j].y = MS_IMAGE2MAP_Y(mapserv->map->query.shape->line[i].point[j].y, mapserv->map->extent.maxy, mapserv->map->cellsize);
1376 }
1377 }
1378
1379 mapserv->map->query.type = MS_QUERY_BY_SHAPE;
1380 break;
1381 case FROMUSERPNT:
1382 if(mapserv->Buffer == 0) { /* do a *pure* point query */
1383 mapserv->map->query.point = mapserv->mappnt;
1384 mapserv->map->query.type = MS_QUERY_BY_POINT;
1385 setExtent(mapserv);
1386 } else {
1387 setExtent(mapserv);
1388 if(mapserv->SearchMap) { /* the extent should be tied to a map, so we need to "adjust" it */
1389 if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE;
1390 mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height);
1391 }
1392 mapserv->map->query.rect = mapserv->map->extent;
1393 mapserv->map->query.type = MS_QUERY_BY_RECT;
1394 }
1395 break;
1396 case FROMUSERSHAPE:
1397 setExtent(mapserv);
1398 mapserv->map->query.type = MS_QUERY_BY_SHAPE;
1399 break;
1400 default: /* from an extent of some sort */
1401 setExtent(mapserv);
1402 if(mapserv->SearchMap) { /* the extent should be tied to a map, so we need to "adjust" it */
1403 if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE;
1404 mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height);
1405 }
1406
1407 mapserv->map->query.rect = mapserv->map->extent;
1408 mapserv->map->query.type = MS_QUERY_BY_RECT;
1409 break;
1410 }
1411 break;
1412 case QUERY:
1413 switch(mapserv->QueryCoordSource) {
1414 case FROMIMGPNT:
1415 setCoordinate(mapserv);
1416 mapserv->map->extent = mapserv->ImgExt; /* use the existing image parameters */
1417 mapserv->map->width = mapserv->ImgCols;
1418 mapserv->map->height = mapserv->ImgRows;
1419 if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE;
1420 break;
1421 case FROMUSERPNT: /* only a buffer makes sense, DOES IT? */
1422 if(setExtent(mapserv) != MS_SUCCESS) return MS_FAILURE;
1423 break;
1424 default:
1425 msSetError(MS_WEBERR, "Query mode needs a point, imgxy and mapxy are not set.", "mapserv()");
1426 return MS_FAILURE;
1427 break;
1428 }
1429
1430 mapserv->map->query.type = MS_QUERY_BY_POINT;
1431 mapserv->map->query.mode = MS_QUERY_SINGLE;
1432 mapserv->map->query.layer = mapserv->QueryLayerIndex;
1433 mapserv->map->query.point = mapserv->mappnt;
1434 mapserv->map->query.buffer = mapserv->Buffer;
1435 break;
1436 case INDEXQUERY:
1437 mapserv->map->query.type = MS_QUERY_BY_INDEX;
1438 mapserv->map->query.mode = MS_QUERY_SINGLE;
1439 mapserv->map->query.layer = mapserv->QueryLayerIndex;
1440 mapserv->map->query.shapeindex = mapserv->ShapeIndex;
1441 mapserv->map->query.tileindex = mapserv->TileIndex;
1442 break;
1443 } /* end mode switch */
1444
1445 /* finally execute the query */
1446 if((status = msExecuteQuery(mapserv->map)) != MS_SUCCESS) return MS_FAILURE;
1447 }
1448
1449 if(mapserv->map->querymap.width != -1) mapserv->map->width = mapserv->map->querymap.width; /* make sure we use the right size */
1450 if(mapserv->map->querymap.height != -1) mapserv->map->height = mapserv->map->querymap.height;
1451
1452 if(mapserv->UseShapes)
1453 if(MS_SUCCESS != setExtentFromShapes(mapserv))
1454 return MS_FAILURE;
1455
1456 if(msReturnTemplateQuery(mapserv, mapserv->map->web.queryformat, NULL) != MS_SUCCESS) return MS_FAILURE;
1457
1458 if(mapserv->savequery) {
1459 snprintf(buffer, sizeof(buffer), "%s%s%s%s", mapserv->map->web.imagepath, mapserv->map->name, mapserv->Id, MS_QUERY_EXTENSION);
1460 if((status = msSaveQuery(mapserv->map, buffer, MS_FALSE)) != MS_SUCCESS) return status;
1461 }
1462 return MS_SUCCESS;
1463}
1464
1465int msCGIDispatchImageRequest(mapservObj *mapserv) {
1466 int status;
1467 imageObj *img;
1468 switch(mapserv->Mode) {
1469 case MAP:
1470 if(mapserv->QueryFile) {
1471 status = msLoadQuery(mapserv->map, mapserv->QueryFile);
1472 if(status != MS_SUCCESS) return MS_FAILURE;
1473 img = msDrawMap(mapserv->map, MS_TRUE);
1474 } else
1475 img = msDrawMap(mapserv->map, MS_FALSE);
1476 break;
1477 case REFERENCE:
1478 mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height);
1479 img = msDrawReferenceMap(mapserv->map);
1480 break;
1481 case SCALEBAR:
1482 img = msDrawScalebar(mapserv->map);
1483 break;
1484 case TILE:
1485 msTileSetExtent(mapserv);
1486 img = msTileDraw(mapserv);
1487 break;
1488 case LEGEND:
1489 img = msDrawLegend(mapserv->map, MS_FALSE);
1490 break;
1491 }
1492
1493 if(!img) return MS_FAILURE;
1494
1495 /*
1496 ** Set the Cache control headers if the option is set.
1497 */
1498 if( mapserv->sendheaders && msLookupHashTable(&(mapserv->map->web.metadata), "http_max_age") ) {
1499 msIO_setHeader("Cache-Control","max-age=%s", msLookupHashTable(&(mapserv->map->web.metadata), "http_max_age"));
1500 }
1501
1502 if(mapserv->sendheaders) {
1503 const char *attachment = msGetOutputFormatOption(mapserv->map->outputformat, "ATTACHMENT", NULL );
1504 if(attachment)
1505 msIO_setHeader("Content-disposition","attachment; filename=%s", attachment);
1506 msIO_setHeader("Content-type",MS_IMAGE_MIME_TYPE(mapserv->map->outputformat));
1507 msIO_sendHeaders();
1508 }
1509
1510 if( mapserv->Mode == MAP || mapserv->Mode == TILE )
1511 status = msSaveImage(mapserv->map, img, NULL);
1512 else
1513 status = msSaveImage(NULL,img, NULL);
1514
1515 if(status != MS_SUCCESS) return MS_FAILURE;
1516
1517 msFreeImage(img);
1518 return MS_SUCCESS;
1519}
1520
1521
1522int msCGIDispatchLegendRequest(mapservObj *mapserv) {
1523 if(mapserv->map->legend.template) {
1524 char *legendTemplate;
1525 legendTemplate = generateLegendTemplate(mapserv);
1526 if(legendTemplate) {
1527 if(mapserv->sendheaders) {
1528 msIO_setHeader("Content-type",mapserv->map->web.legendformat);
1529 msIO_sendHeaders();
1530 }
1531 msIO_fwrite(legendTemplate, strlen(legendTemplate), 1, stdout);
1532
1533 free(legendTemplate);
1534 return MS_SUCCESS;
1535 } else {/* error already generated by (generateLegendTemplate()) */
1536 return MS_FAILURE;
1537 }
1538 } else {
1539 return msCGIDispatchImageRequest(mapserv);
1540 }
1541}
1542
1543int msCGIDispatchLegendIconRequest(mapservObj *mapserv) {
1544 char **tokens;
1545 int numtokens=0;
1546 int layerindex=-1, classindex=0;
1547 outputFormatObj *format = NULL;
1548 imageObj *img;
1549
1550 /* TODO: do we want to set scale here? */
1551
1552 /* do we have enough information */
1553 if(!mapserv->icon) {
1554 msSetError(MS_WEBERR, "Mode=LEGENDICON requires an icon parameter.", "mapserv()");
1555 return MS_FAILURE;
1556 }
1557
1558 /* process the icon definition */
1559 tokens = msStringSplit(mapserv->icon, ',', &numtokens);
1560
1561 if(numtokens != 1 && numtokens != 2) {
1562 msSetError(MS_WEBERR, "%d Malformed icon parameter, should be 'layer,class' or just 'layer' if the layer has only 1 class defined.", "mapserv()", numtokens);
1563 return MS_FAILURE;
1564 }
1565
1566 if((layerindex = msGetLayerIndex(mapserv->map, tokens[0])) == -1) {
1567 msSetError(MS_WEBERR, "Icon layer=%s not found in mapfile.", "mapserv()", tokens[0]);
1568 return MS_FAILURE;
1569 }
1570
1571 if(numtokens == 2) { /* check the class index */
1572 classindex = atoi(tokens[1]);
1573 if(classindex >= GET_LAYER(mapserv->map, layerindex)->numclasses) {
1574 msSetError(MS_WEBERR, "Icon class=%d not found in layer=%s.", "mapserv()", classindex, GET_LAYER(mapserv->map, layerindex)->name);
1575 return MS_FAILURE;
1576 }
1577 }
1578
1579 /* ensure we have an image format representing the options for the legend. */
1580 msApplyOutputFormat(&format, mapserv->map->outputformat, mapserv->map->legend.transparent, mapserv->map->legend.interlace, MS_NOOVERRIDE);
1581
1582 /* initialize the legend image */
1583 if( ! MS_RENDERER_PLUGIN(format) ) {
1584 msSetError(MS_RENDERERERR, "unsupported renderer for legend icon", "mapserv main()");
1585 return MS_FAILURE;
1586 }
1587 img = msImageCreate(mapserv->map->legend.keysizex, mapserv->map->legend.keysizey, format,
1588 mapserv->map->web.imagepath, mapserv->map->web.imageurl, mapserv->map->resolution, mapserv->map->defresolution,
1589 &(mapserv->map->legend.imagecolor));
1590
1591 /* drop this reference to output format */
1592 msApplyOutputFormat(&format, NULL, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE);
1593
1594 if(msDrawLegendIcon(mapserv->map, GET_LAYER(mapserv->map, layerindex), GET_LAYER(mapserv->map, layerindex)->class[classindex], mapserv->map->legend.keysizex, mapserv->map->legend.keysizey, img, 0, 0) != MS_SUCCESS)
1595 return MS_FAILURE;
1596
1597 if(mapserv->sendheaders) {
1598 msIO_setHeader("Content-type",MS_IMAGE_MIME_TYPE(mapserv->map->outputformat));
1599 msIO_sendHeaders();
1600 }
1601 /*
1602 ** Set the Cache control headers if the option is set.
1603 */
1604 if( mapserv->sendheaders && msLookupHashTable(&(mapserv->map->web.metadata), "http_max_age") ) {
1605 msIO_printf("Cache-Control: max-age=%s%c", msLookupHashTable(&(mapserv->map->web.metadata), "http_max_age"), 10);
1606 }
1607 if( msSaveImage(NULL, img, NULL) != MS_SUCCESS)
1608 return MS_FAILURE;
1609
1610 msFreeCharArray(tokens, numtokens);
1611 msFreeImage(img);
1612 return MS_SUCCESS;
1613}
1614
1615int msCGIDispatchRequest(mapservObj *mapserv) {
1616 int i;
1617 int status;
1618
1619 /*
1620 ** Determine 'mode': Check for MS_MODE env. var. and mode=... CGI param
1621 */
1622 mapserv->Mode = -1; /* Not set */
1623 if( msCGISetMode(mapserv) != MS_SUCCESS) {
1624 return MS_FAILURE;
1625 }
1626
1627 /*
1628 ** Start by calling the WMS/WFS/WCS Dispatchers. If they fail then we'll
1629 ** process this as a regular MapServer request.
1630 */
1631 if((mapserv->Mode == -1 || mapserv->Mode == OWS || mapserv->Mode == WFS) &&
1632 (status = msOWSDispatch(mapserv->map, mapserv->request,
1633 mapserv->Mode)) != MS_DONE ) {
1634 /*
1635 ** OWSDispatch returned either MS_SUCCESS or MS_FAILURE
1636 */
1637 if( status == MS_FAILURE ) {
1638 return MS_FAILURE;
1639 }
1640
1641 if (status == MS_SUCCESS &&
1642 strcasecmp(mapserv->map->imagetype, "application/openlayers")==0)
1643 {
1644 char *service = NULL;
1645 for( i=0; i<mapserv->request->NumParams; i++)
1646 {
1647 if(strcasecmp(mapserv->request->ParamNames[i], "SERVICE") == 0) {
1648 service = mapserv->request->ParamValues[i];
1649 break;
1650 }
1651 }
1652 if (service && strcasecmp(service,"WMS")==0)
1653 {
1654 if(mapserv->sendheaders) {
1655 msIO_setHeader("Content-type","text/html");
1656 msIO_sendHeaders();
1657 }
1658
1659 if (msReturnOpenLayersPage(mapserv) != MS_SUCCESS)
1660 return MS_FAILURE;
1661 }
1662 }
1663 return MS_SUCCESS;
1664 } /* done OGC/OWS case */
1665
1666
1667 /*
1668 ** Do "traditional" mode processing.
1669 */
1670 if (mapserv->Mode == -1)
1671 mapserv->Mode = BROWSE;
1672
1673 if(MS_SUCCESS != msCGILoadForm(mapserv)) {
1674 return MS_FAILURE;
1675 }
1676
1677/* Insecure as implemented, need to save someplace non accessible by everyone in the universe
1678 if(mapserv->savemap) {
1679 snprintf(buffer, sizeof(buffer), "%s%s%s.map", mapserv->map->web.imagepath, mapserv->map->name, mapserv->Id);
1680 if(msSaveMap(mapserv->map, buffer) == -1) return MS_FAILURE;
1681 }
1682*/
1683
1684 if((mapserv->CoordSource == FROMIMGPNT) || (mapserv->CoordSource == FROMIMGBOX)) /* make sure extent of existing image matches shape of image */
1685 mapserv->map->cellsize = msAdjustExtent(&mapserv->ImgExt, mapserv->ImgCols, mapserv->ImgRows);
1686
1687 /*
1688 ** For each layer let's set layer status
1689 */
1690 for(i=0;i<mapserv->map->numlayers;i++) {
1691 if((GET_LAYER(mapserv->map, i)->status != MS_DEFAULT)) {
1692 if(isOn(mapserv, GET_LAYER(mapserv->map, i)->name, GET_LAYER(mapserv->map, i)->group) == MS_TRUE) /* Set layer status */
1693 GET_LAYER(mapserv->map, i)->status = MS_ON;
1694 else
1695 GET_LAYER(mapserv->map, i)->status = MS_OFF;
1696 }
1697 }
1698
1699 if(mapserv->CoordSource == FROMREFPNT) /* force browse mode if the reference coords are set */
1700 mapserv->Mode = BROWSE;
1701
1702 if(mapserv->Mode == TILE) {
1703 /*
1704 ** Tile mode:
1705 ** Set the projection up and test the parameters for legality.
1706 */
1707 if( msTileSetup(mapserv) != MS_SUCCESS ) {
1708 return MS_FAILURE;
1709 }
1710 }
1711 if(mapserv->Mode == BROWSE) {
1712 return msCGIDispatchBrowseRequest(mapserv);
1713 } else if(mapserv->Mode == MAP || mapserv->Mode == SCALEBAR || mapserv->Mode == REFERENCE || mapserv->Mode == TILE) { /* "image" only modes */
1714 /* tile, map, scalebar and reference all need the extent to be set up correctly */
1715 if(setExtent(mapserv) != MS_SUCCESS) return MS_FAILURE;
1716 if(checkWebScale(mapserv) != MS_SUCCESS) return MS_FAILURE;
1717 return msCGIDispatchImageRequest(mapserv);
1718 } else if(mapserv->Mode == LEGEND) {
1719 return msCGIDispatchLegendRequest(mapserv);
1720 } else if(mapserv->Mode == LEGENDICON) {
1721 return msCGIDispatchLegendIconRequest(mapserv);
1722 } else if(mapserv->Mode >= QUERY) {
1723 return msCGIDispatchQueryRequest(mapserv);
1724 } else if(mapserv->Mode == COORDINATE) {
1725 return msCGIDispatchCoordinateRequest(mapserv);
1726 }
1727 else {
1728 msSetError(MS_WEBERR, "Bug: unsupported mode", "msDispatchRequest");
1729 return MS_FAILURE;
1730 }
1731}
1732
1733int msCGIHandler(const char *query_string, void **out_buffer, size_t *buffer_length) {
1734 int x,m=0;
1735 struct mstimeval execstarttime, execendtime;
1736 struct mstimeval requeststarttime, requestendtime;
1737 mapservObj* mapserv = NULL;
1738 char *queryString;
1739 int maxParams = MS_DEFAULT_CGI_PARAMS;
1740 msIOContext *ctx;
1741 msIOBuffer *buf;
1742
1743 msIO_installStdoutToBuffer();
1744 /* Use MS_ERRORFILE and MS_DEBUGLEVEL env vars if set */
1745 if( msDebugInitFromEnv() != MS_SUCCESS ) {
1746 msCGIWriteError(mapserv);
1747 goto end_request;
1748 }
1749
1750 if(msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING)
1751 msGettimeofday(&execstarttime, NULL);
1752
1753 mapserv = msAllocMapServObj();
1754 mapserv->request->type = MS_GET_REQUEST;
1755
1756 if(!query_string || !*query_string) {
1757 msIO_setHeader("Content-type","text/html");
1758 msIO_sendHeaders();
1759 msIO_printf("No query information to decode. QUERY_STRING not set.\n");
1760 goto end_request;
1761 }
1762
1763 /* don't modify the string */
1764 queryString = msStrdup(query_string);
1765 for(x=0;queryString[0] != '\0';x++) {
1766 if(m >= maxParams) {
1767 maxParams *= 2;
1768 mapserv->request->ParamNames = (char **) realloc(mapserv->request->ParamNames,sizeof(char *) * maxParams);
1769 if (mapserv->request->ParamNames == NULL) {
1770 msIO_printf("Out of memory trying to allocate name/value pairs.\n");
1771 goto end_request;
1772 }
1773 mapserv->request->ParamValues = (char **) realloc(mapserv->request->ParamValues,sizeof(char *) * maxParams);
1774 if (mapserv->request->ParamValues == NULL) {
1775 msIO_printf("Out of memory trying to allocate name/value pairs.\n");
1776 goto end_request;
1777 }
1778 }
1779 mapserv->request->ParamValues[m] = makeword(queryString,'&');
1780 plustospace(mapserv->request->ParamValues[m]);
1781 unescape_url(mapserv->request->ParamValues[m]);
1782 mapserv->request->ParamNames[m] = makeword(mapserv->request->ParamValues[m],'=');
1783 m++;
1784 }
1785 mapserv->request->NumParams = m;
1786
1787 if( mapserv->request->NumParams == 0 ) {
1788 msCGIWriteError(mapserv);
1789 goto end_request;
1790 }
1791
1792 mapserv->map = msCGILoadMap(mapserv);
1793 if(!mapserv->map) {
1794 msCGIWriteError(mapserv);
1795 goto end_request;
1796 }
1797
1798 if( mapserv->map->debug >= MS_DEBUGLEVEL_TUNING)
1799 msGettimeofday(&requeststarttime, NULL);
1800
1801
1802 if(msCGIDispatchRequest(mapserv) != MS_SUCCESS) {
1803 msCGIWriteError(mapserv);
1804 goto end_request;
1805 }
1806
1807
1808end_request:
1809 if(mapserv) {
1810 if(mapserv->map && mapserv->map->debug >= MS_DEBUGLEVEL_TUNING) {
1811 msGettimeofday(&requestendtime, NULL);
1812 msDebug("mapserv request processing time (msLoadMap not incl.): %.3fs\n",
1813 (requestendtime.tv_sec+requestendtime.tv_usec/1.0e6)-
1814 (requeststarttime.tv_sec+requeststarttime.tv_usec/1.0e6) );
1815 }
1816 msCGIWriteLog(mapserv,MS_FALSE);
1817 msFreeMapServObj(mapserv);
1818 }
1819
1820 /* normal case, processing is complete */
1821 if(msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING) {
1822 msGettimeofday(&execendtime, NULL);
1823 msDebug("mapserv total execution time: %.3fs\n",
1824 (execendtime.tv_sec+execendtime.tv_usec/1.0e6)-
1825 (execstarttime.tv_sec+execstarttime.tv_usec/1.0e6) );
1826 }
1827 ctx = msIO_getHandler( (FILE *) "stdout" );
1828 buf = (msIOBuffer *) ctx->cbData;
1829 *out_buffer = buf->data;
1830 *buffer_length = buf->data_offset;
1831
1832 free(queryString);
1833
1834 return 0;
1835}
Note: See TracBrowser for help on using the repository browser.