Apache HTTPD
mod_imagemap.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * This imagemap module started as a port of the original imagemap.c
19 * written by Rob McCool (11/13/93 [email protected]).
20 * This version includes the mapping algorithms found in version 1.3
21 * of imagemap.c.
22 *
23 * Contributors to this code include:
24 *
25 * Kevin Hughes, [email protected]
26 *
27 * Eric Haines, [email protected]
28 * "macmartinized" polygon code copyright 1992 by Eric Haines, [email protected]
29 *
30 * Randy Terbush, [email protected]
31 * port to Apache module format, "base_uri" and support for relative URLs
32 *
33 * James H. Cloos, Jr., [email protected]
34 * Added point datatype, using code in NCSA's version 1.8 imagemap.c
35 * program, as distributed with version 1.4.1 of their server.
36 * The point code is originally added by Craig Milo Rogers, [email protected]
37 *
38 * Nathan Kurz, [email protected]
39 * Rewrite/reorganization. New handling of default, base and relative URLs.
40 * New Configuration directives:
41 * ImapMenu {none, formatted, semiformatted, unformatted}
42 * ImapDefault {error, nocontent, referer, menu, URL}
43 * ImapBase {map, referer, URL}
44 * Support for creating non-graphical menu added. (backwards compatible):
45 * Old: directive URL [x,y ...]
46 * New: directive URL "Menu text" [x,y ...]
47 * or: directive URL x,y ... "Menu text"
48 * Map format and menu concept courtesy Joshua Bell, [email protected].
49 *
50 * Mark Cox, [email protected], Allow relative URLs even when no base specified
51 */
52
53#include "apr.h"
54#include "apr_strings.h"
55#include "apr_lib.h"
56
57#define APR_WANT_STDIO /* for sscanf() */
58#define APR_WANT_STRFUNC
59#include "apr_want.h"
60
61#include "ap_config.h"
62#include "httpd.h"
63#include "http_config.h"
64#include "http_request.h"
65#include "http_core.h"
66#include "http_protocol.h"
67#include "http_main.h"
68#include "http_log.h"
69#include "util_script.h"
70#include "mod_core.h"
71
72
73#define IMAP_MAGIC_TYPE "application/x-httpd-imap"
74#define MAXVERTS 100
75#define X 0
76#define Y 1
77
78#define IMAP_MENU_DEFAULT "formatted"
79#define IMAP_DEFAULT_DEFAULT "nocontent"
80#define IMAP_BASE_DEFAULT "map"
81
82module AP_MODULE_DECLARE_DATA imagemap_module;
83
84typedef struct {
85 char *imap_menu;
87 char *imap_base;
89
91{
94
96 icr->imap_default = NULL;
97 icr->imap_base = NULL;
98
99 return icr;
100}
101
102static void *merge_imap_dir_configs(apr_pool_t *p, void *basev, void *addv)
103{
107
108 new->imap_menu = add->imap_menu ? add->imap_menu : base->imap_menu;
109 new->imap_default = add->imap_default ? add->imap_default
110 : base->imap_default;
111 new->imap_base = add->imap_base ? add->imap_base : base->imap_base;
112
113 return new;
114}
115
116
117static const command_rec imap_cmds[] =
118{
120 (void *)APR_OFFSETOF(imap_conf_rec, imap_menu), OR_INDEXES,
121 "the type of menu generated: none, formatted, semiformatted, "
122 "unformatted"),
123 AP_INIT_TAKE1("ImapDefault", ap_set_string_slot,
124 (void *)APR_OFFSETOF(imap_conf_rec, imap_default), OR_INDEXES,
125 "the action taken if no match: error, nocontent, referer, "
126 "menu, URL"),
128 (void *)APR_OFFSETOF(imap_conf_rec, imap_base), OR_INDEXES,
129 "the base for all URL's: map, referer, URL (or start of)"),
130 {NULL}
131};
132
133static int pointinrect(const double point[2], double coords[MAXVERTS][2])
134{
135 double max[2], min[2];
136 if (coords[0][X] > coords[1][X]) {
137 max[0] = coords[0][X];
138 min[0] = coords[1][X];
139 }
140 else {
141 max[0] = coords[1][X];
142 min[0] = coords[0][X];
143 }
144
145 if (coords[0][Y] > coords[1][Y]) {
146 max[1] = coords[0][Y];
147 min[1] = coords[1][Y];
148 }
149 else {
150 max[1] = coords[1][Y];
151 min[1] = coords[0][Y];
152 }
153
154 return ((point[X] >= min[0] && point[X] <= max[0]) &&
155 (point[Y] >= min[1] && point[Y] <= max[1]));
156}
157
158static int pointincircle(const double point[2], double coords[MAXVERTS][2])
159{
160 double radius1, radius2;
161
162 radius1 = ((coords[0][Y] - coords[1][Y]) * (coords[0][Y] - coords[1][Y]))
163 + ((coords[0][X] - coords[1][X]) * (coords[0][X] - coords[1][X]));
164
165 radius2 = ((coords[0][Y] - point[Y]) * (coords[0][Y] - point[Y]))
166 + ((coords[0][X] - point[X]) * (coords[0][X] - point[X]));
167
168 return (radius2 <= radius1);
169}
170
171#define fmin(a,b) (((a)>(b))?(b):(a))
172#define fmax(a,b) (((a)>(b))?(a):(b))
173
174static int pointinpoly(const double point[2], double pgon[MAXVERTS][2])
175{
176 int i, numverts, crossings = 0;
177 double x = point[X], y = point[Y];
178
179 for (numverts = 0; numverts < MAXVERTS && pgon[numverts][X] != -1;
180 numverts++) {
181 /* just counting the vertexes */
182 }
183
184 for (i = 0; i < numverts; i++) {
185 double x1=pgon[i][X];
186 double y1=pgon[i][Y];
187 double x2=pgon[(i + 1) % numverts][X];
188 double y2=pgon[(i + 1) % numverts][Y];
189 double d=(y - y1) * (x2 - x1) - (x - x1) * (y2 - y1);
190
191 if ((y1 >= y) != (y2 >= y)) {
192 crossings +=y2 - y1 >= 0 ? d >= 0 : d <= 0;
193 }
194 if (!d && fmin(x1,x2) <= x && x <= fmax(x1,x2)
195 && fmin(y1,y2) <= y && y <= fmax(y1,y2)) {
196 return 1;
197 }
198 }
199 return crossings & 0x01;
200}
201
202
203static int is_closer(const double point[2], double coords[MAXVERTS][2],
204 double *closest)
205{
206 double dist_squared = ((point[X] - coords[0][X])
207 * (point[X] - coords[0][X]))
208 + ((point[Y] - coords[0][Y])
209 * (point[Y] - coords[0][Y]));
210
211 if (point[X] < 0 || point[Y] < 0) {
212 return (0); /* don't mess around with negative coordinates */
213 }
214
215 if (*closest < 0 || dist_squared < *closest) {
217 return (1); /* if this is the first point or is the closest yet
218 set 'closest' equal to this distance^2 */
219 }
220
221 return (0); /* if it's not the first or closest */
222
223}
224
225static double get_x_coord(const char *args)
226{
227 char *endptr; /* we want it non-null */
228 double x_coord = -1; /* -1 is returned if no coordinate is given */
229
230 if (args == NULL) {
231 return (-1); /* in case we aren't passed anything */
232 }
233
234 while (*args && !apr_isdigit(*args) && *args != ',') {
235 args++; /* jump to the first digit, but not past
236 a comma or end */
237 }
238
240
241 if (endptr > args) { /* if a conversion was made */
242 return (x_coord);
243 }
244
245 return (-1); /* else if no conversion was made,
246 or if no args was given */
247}
248
249static double get_y_coord(const char *args)
250{
251 char *endptr; /* we want it non-null */
252 const char *start_of_y = NULL;
253 double y_coord = -1; /* -1 is returned on error */
254
255 if (args == NULL) {
256 return (-1); /* in case we aren't passed anything */
257 }
258
259 start_of_y = ap_strchr_c(args, ','); /* the comma */
260
261 if (start_of_y) {
262
263 start_of_y++; /* start looking at the character after
264 the comma */
265
266 while (*start_of_y && !apr_isdigit(*start_of_y)) {
267 start_of_y++; /* jump to the first digit, but not
268 past the end */
269 }
270
272
273 if (endptr > start_of_y) {
274 return (y_coord);
275 }
276 }
277
278 return (-1); /* if no conversion was made, or
279 no comma was found in args */
280}
281
282
283/* See if string has a "quoted part", and if so set *quoted_part to
284 * the first character of the quoted part, then hammer a \0 onto the
285 * trailing quote, and set *string to point at the first character
286 * past the second quote.
287 *
288 * Otherwise set *quoted_part to NULL, and leave *string alone.
289 */
290static void read_quoted(char **string, char **quoted_part)
291{
292 char *strp = *string;
293
294 /* assume there's no quoted part */
295 *quoted_part = NULL;
296
297 while (apr_isspace(*strp)) {
298 strp++; /* go along string until non-whitespace */
299 }
300
301 if (*strp == '"') { /* if that character is a double quote */
302 strp++; /* step over it */
303 *quoted_part = strp; /* note where the quoted part begins */
304
305 while (*strp && *strp != '"') {
306 ++strp; /* skip the quoted portion */
307 }
308
309 *strp = '\0'; /* end the string with a NUL */
310
311 strp++; /* step over the last double quote */
312 *string = strp;
313 }
314}
315
316/*
317 * returns the mapped URL or NULL.
318 */
319static const char *imap_url(request_rec *r, const char *base, const char *value)
320{
321/* translates a value into a URL. */
323 char *string_pos = NULL;
324 const char *string_pos_const = NULL;
325 char *directory = NULL;
326 const char *referer = NULL;
327 char *my_base;
328
329 if (!strcasecmp(value, "map") || !strcasecmp(value, "menu")) {
330 return ap_construct_url(r->pool, r->uri, r);
331 }
332
333 if (!strcasecmp(value, "nocontent") || !strcasecmp(value, "error")) {
334 return apr_pstrdup(r->pool, value); /* these are handled elsewhere,
335 so just copy them */
336 }
337
338 if (!strcasecmp(value, "referer")) {
339 referer = apr_table_get(r->headers_in, "Referer");
340 if (referer && *referer) {
341 return referer;
342 }
343 else {
344 /* XXX: This used to do *value = '\0'; ... which is totally bogus
345 * because it hammers the passed in value, which can be a string
346 * constant, or part of a config, or whatever. Total garbage.
347 * This works around that without changing the rest of this
348 * code much
349 */
350 value = ""; /* if 'referer' but no referring page,
351 null the value */
352 }
353 }
354
356 while (apr_isalpha(*string_pos_const)) {
357 string_pos_const++; /* go along the URL from the map
358 until a non-letter */
359 }
360 if (*string_pos_const == ':') {
361 /* if letters and then a colon (like http:) */
362 /* it's an absolute URL, so use it! */
363 return apr_pstrdup(r->pool, value);
364 }
365
366 if (!base || !*base) {
367 if (value && *value) {
368 return apr_pstrdup(r->pool, value); /* no base: use what is given */
369 }
370 /* no base, no value: pick a simple default */
371 return ap_construct_url(r->pool, "/", r);
372 }
373
374 /* must be a relative URL to be combined with base */
375 if (ap_strchr_c(base, '/') == NULL && (!strncmp(value, "../", 3)
376 || !strcmp(value, ".."))) {
378 "invalid base directive in map file: %s", r->uri);
379 return NULL;
380 }
383 while (*string_pos) {
384 if (*string_pos == '/' && *(string_pos + 1) == '/') {
385 string_pos += 2; /* if there are two slashes, jump over them */
386 continue;
387 }
388 if (*string_pos == '/') { /* the first single slash */
389 if (value[0] == '/') {
390 *string_pos = '\0';
391 } /* if the URL from the map starts from root,
392 end the base URL string at the first single
393 slash */
394 else {
395 directory = string_pos; /* save the start of
396 the directory portion */
397
398 string_pos = strrchr(string_pos, '/'); /* now reuse
399 string_pos */
400 string_pos++; /* step over that last slash */
401 *string_pos = '\0';
402 } /* but if the map url is relative, leave the
403 slash on the base (if there is one) */
404 break;
405 }
406 string_pos++; /* until we get to the end of my_base without
407 finding a slash by itself */
408 }
409
410 while (!strncmp(value, "../", 3) || !strcmp(value, "..")) {
411
412 if (directory && (slen = strlen(directory))) {
413
414 /* for each '..', knock a directory off the end
415 by ending the string right at the last slash.
416 But only consider the directory portion: don't eat
417 into the server name. And only try if a directory
418 portion was found */
419
420 clen = slen - 1;
421
422 while ((slen - clen) == 1) {
423
424 if ((string_pos = strrchr(directory, '/'))) {
425 *string_pos = '\0';
426 }
427 clen = strlen(directory);
428 if (clen == 0) {
429 break;
430 }
431 }
432
433 value += 2; /* jump over the '..' that we found in the
434 value */
435 }
436 else if (directory) {
438 "invalid directory name in map file: %s", r->uri);
439 return NULL;
440 }
441
442 if (!strncmp(value, "/../", 4) || !strcmp(value, "/..")) {
443 value++; /* step over the '/' if there are more '..'
444 to do. This way, we leave the starting
445 '/' on value after the last '..', but get
446 rid of it otherwise */
447 }
448
449 } /* by this point, value does not start
450 with '..' */
451
452 if (value && *value) {
453 return apr_pstrcat(r->pool, my_base, value, NULL);
454 }
455 return my_base;
456}
457
458static int imap_reply(request_rec *r, const char *redirect)
459{
460 if (!strcasecmp(redirect, "error")) {
461 /* they actually requested an error! */
463 }
464 if (!strcasecmp(redirect, "nocontent")) {
465 /* tell the client to keep the page it has */
466 return HTTP_NO_CONTENT;
467 }
468 if (redirect && *redirect) {
469 /* must be a URL, so redirect to it */
470 apr_table_setn(r->headers_out, "Location", redirect);
472 }
474}
475
476static void menu_header(request_rec *r, char *menu)
477{
478 ap_set_content_type_ex(r, "text/html; charset=ISO-8859-1", 1);
479
480 ap_rvputs(r, DOCTYPE_HTML_3_2, "<html><head>\n<title>Menu for ",
482 "</title>\n</head><body>\n", NULL);
483
484 if (!strcasecmp(menu, "formatted")) {
485 ap_rvputs(r, "<h1>Menu for ",
487 "</h1>\n<hr />\n\n", NULL);
488 }
489}
490
491static void menu_blank(request_rec *r, char *menu)
492{
493 if (!strcasecmp(menu, "formatted")) {
494 ap_rputs("\n", r);
495 }
496 else if (!strcasecmp(menu, "semiformatted")) {
497 ap_rputs("<br />\n", r);
498 }
499 else if (!strcasecmp(menu, "unformatted")) {
500 ap_rputs("\n", r);
501 }
502}
503
504static void menu_comment(request_rec *r, char *menu, char *comment)
505{
506 /* comments are ignored in the 'formatted' form */
507 if (!strcasecmp(menu, "formatted")) {
508 ap_rputs("\n", r); /* print just a newline if 'formatted' */
509 }
510 else if (!strcasecmp(menu, "semiformatted") && *comment) {
511 ap_rvputs(r, comment, "\n", NULL);
512 }
513 else if (!strcasecmp(menu, "unformatted") && *comment) {
514 ap_rvputs(r, comment, "\n", NULL);
515 }
516}
517
518static void menu_default(request_rec *r, const char *menu, const char *href, const char *text)
519{
520 char *ehref, *etext;
521 if (!strcasecmp(href, "error") || !strcasecmp(href, "nocontent")) {
522 return; /* don't print such lines, these aren't
523 really href's */
524 }
525
526 ehref = ap_escape_uri(r->pool, href);
528
529 if (!strcasecmp(menu, "formatted")) {
530 ap_rvputs(r, "<pre>(Default) <a href=\"", ehref, "\">", etext,
531 "</a></pre>\n", NULL);
532 }
533 else if (!strcasecmp(menu, "semiformatted")) {
534 ap_rvputs(r, "<pre>(Default) <a href=\"", ehref, "\">", etext,
535 "</a></pre>\n", NULL);
536 }
537 else if (!strcasecmp(menu, "unformatted")) {
538 ap_rvputs(r, "<a href=\"", ehref, "\">", etext, "</a>", NULL);
539 }
540}
541
542static void menu_directive(request_rec *r, const char *menu, const char *href, const char *text)
543{
544 char *ehref, *etext;
545 if (!strcasecmp(href, "error") || !strcasecmp(href, "nocontent")) {
546 return; /* don't print such lines, as this isn't
547 really an href */
548 }
549
550 ehref = ap_escape_uri(r->pool, href);
552
553 if (!strcasecmp(menu, "formatted")) {
554 ap_rvputs(r, "<pre> <a href=\"", ehref, "\">", etext,
555 "</a></pre>\n", NULL);
556 }
557 else if (!strcasecmp(menu, "semiformatted")) {
558 ap_rvputs(r, "<pre> <a href=\"", ehref, "\">", etext,
559 "</a></pre>\n", NULL);
560 }
561 else if (!strcasecmp(menu, "unformatted")) {
562 ap_rvputs(r, "<a href=\"", ehref, "\">", etext, "</a>", NULL);
563 }
564}
565
567{
568 ap_rputs("\n\n</body>\n</html>\n", r); /* finish the menu */
569}
570
572{
573 char input[MAX_STRING_LEN];
574 char *directive;
575 char *value;
576 char *href_text;
577 const char *base;
578 const char *redirect;
579 const char *mapdflt;
580 char *closest = NULL;
581 double closest_yet = -1;
583
584 double testpoint[2];
585 double pointarray[MAXVERTS + 1][2];
586 int vertex;
587
588 char *string_pos;
589 int showmenu = 0;
590
592
593 char *imap_menu;
594 char *imap_default;
595 char *imap_base;
596
598
599 icr = ap_get_module_config(r->per_dir_config, &imagemap_module);
600
601 imap_menu = icr->imap_menu ? icr->imap_menu : IMAP_MENU_DEFAULT;
602 imap_default = icr->imap_default
603 ? icr->imap_default : IMAP_DEFAULT_DEFAULT;
604 imap_base = icr->imap_base ? icr->imap_base : IMAP_BASE_DEFAULT;
605
607
608 if (status != APR_SUCCESS) {
609 return HTTP_NOT_FOUND;
610 }
611
612 base = imap_url(r, NULL, imap_base); /* set base according
613 to default */
614 if (!base) {
616 }
617 mapdflt = imap_url(r, NULL, imap_default); /* and default to
618 global default */
619 if (!mapdflt) {
621 }
622
625
626 if ((testpoint[X] == -1 || testpoint[Y] == -1) ||
627 (testpoint[X] == 0 && testpoint[Y] == 0)) {
628 /* if either is -1 or if both are zero (new Lynx) */
629 /* we don't have valid coordinates */
630 testpoint[X] = -1;
631 testpoint[Y] = -1;
632 if (strncasecmp(imap_menu, "none", 2)) {
633 showmenu = 1; /* show the menu _unless_ ImapMenu is
634 'none' or 'no' */
635 }
636 }
637
638 if (showmenu) { /* send start of imagemap menu if
639 we're going to */
640 menu_header(r, imap_menu);
641 }
642
643 while (!ap_cfg_getline(input, sizeof(input), imap)) {
644 if (!input[0]) {
645 if (showmenu) {
646 menu_blank(r, imap_menu);
647 }
648 continue;
649 }
650
651 if (input[0] == '#') {
652 if (showmenu) {
653 menu_comment(r, imap_menu, input + 1);
654 }
655 continue;
656 } /* blank lines and comments are ignored
657 if we aren't printing a menu */
658
659 /* find the first two space delimited fields, recall that
660 * ap_cfg_getline has removed leading/trailing whitespace.
661 *
662 * note that we're tokenizing as we go... if we were to use the
663 * ap_getword() class of functions we would end up allocating extra
664 * memory for every line of the map file
665 */
667 if (!*string_pos) { /* need at least two fields */
668 goto need_2_fields;
669 }
670
671 directive = string_pos;
672 while (*string_pos && !apr_isspace(*string_pos)) { /* past directive */
673 ++string_pos;
674 }
675 if (!*string_pos) { /* need at least two fields */
676 goto need_2_fields;
677 }
678 *string_pos++ = '\0';
679
680 if (!*string_pos) { /* need at least two fields */
681 goto need_2_fields;
682 }
683 while (apr_isspace(*string_pos)) { /* past whitespace */
684 ++string_pos;
685 }
686
688 while (*string_pos && !apr_isspace(*string_pos)) { /* past value */
689 ++string_pos;
690 }
691 if (apr_isspace(*string_pos)) {
692 *string_pos++ = '\0';
693 }
694 else {
695 /* end of input, don't advance past it */
696 *string_pos = '\0';
697 }
698
699 if (!strncasecmp(directive, "base", 4)) { /* base, base_uri */
700 base = imap_url(r, NULL, value);
701 if (!base) {
702 goto menu_bail;
703 }
704 continue; /* base is never printed to a menu */
705 }
706
708
709 if (!strcasecmp(directive, "default")) { /* default */
711 if (!mapdflt) {
712 goto menu_bail;
713 }
714 if (showmenu) { /* print the default if there's a menu */
715 redirect = imap_url(r, base, mapdflt);
716 if (!redirect) {
717 goto menu_bail;
718 }
719 menu_default(r, imap_menu, redirect,
721 }
722 continue;
723 }
724
725 vertex = 0;
726 while (vertex < MAXVERTS &&
727 sscanf(string_pos, "%lf%*[, ]%lf",
728 &pointarray[vertex][X], &pointarray[vertex][Y]) == 2) {
729 /* Now skip what we just read... we can't use ANSIism %n */
730 while (apr_isspace(*string_pos)) { /* past whitespace */
731 string_pos++;
732 }
733 while (apr_isdigit(*string_pos)) { /* and the 1st number */
734 string_pos++;
735 }
736 string_pos++; /* skip the ',' */
737 while (apr_isspace(*string_pos)) { /* past any more whitespace */
738 string_pos++;
739 }
740 while (apr_isdigit(*string_pos)) { /* 2nd number */
741 string_pos++;
742 }
743 vertex++;
744 } /* so long as there are more vertices to
745 read, and we have room, read them in.
746 We start where we left off of the last
747 sscanf, not at the beginning. */
748
749 pointarray[vertex][X] = -1; /* signals the end of vertices */
750
751 if (showmenu) {
752 if (!href_text) {
753 read_quoted(&string_pos, &href_text); /* href text could
754 be here instead */
755 }
756 redirect = imap_url(r, base, value);
757 if (!redirect) {
758 goto menu_bail;
759 }
760 menu_directive(r, imap_menu, redirect,
762 continue;
763 }
764 /* note that we don't make it past here if we are making a menu */
765
766 if (testpoint[X] == -1 || pointarray[0][X] == -1) {
767 continue; /* don't try the following tests if testpoints
768 are invalid, or if there are no
769 coordinates */
770 }
771
772 if (!strcasecmp(directive, "poly")) { /* poly */
773
776 redirect = imap_url(r, base, value);
777 if (!redirect) {
779 }
780 return (imap_reply(r, redirect));
781 }
782 continue;
783 }
784
785 if (!strcasecmp(directive, "circle")) { /* circle */
786
789 redirect = imap_url(r, base, value);
790 if (!redirect) {
792 }
793 return (imap_reply(r, redirect));
794 }
795 continue;
796 }
797
798 if (!strcasecmp(directive, "rect")) { /* rect */
799
802 redirect = imap_url(r, base, value);
803 if (!redirect) {
805 }
806 return (imap_reply(r, redirect));
807 }
808 continue;
809 }
810
811 if (!strcasecmp(directive, "point")) { /* point */
812
815 }
816
817 continue;
818 } /* move on to next line whether it's
819 closest or not */
820
821 } /* nothing matched, so we get another line! */
822
823 ap_cfg_closefile(imap); /* we are done with the map file; close it */
824
825 if (showmenu) {
826 menu_footer(r); /* finish the menu and we are done */
827 return OK;
828 }
829
830 if (closest) { /* if a 'point' directive has been seen */
831 redirect = imap_url(r, base, closest);
832 if (!redirect) {
834 }
835 return (imap_reply(r, redirect));
836 }
837
838 if (mapdflt) { /* a default should be defined, even if
839 only 'nocontent' */
840 redirect = imap_url(r, base, mapdflt);
841 if (!redirect) {
843 }
844 return (imap_reply(r, redirect));
845 }
846
847 return HTTP_INTERNAL_SERVER_ERROR; /* If we make it this far,
848 we failed. They lose! */
849
852 "map file %s, line %d syntax error: requires at "
853 "least two fields", r->uri, imap->line_number);
854 /* fall through */
857 if (showmenu) {
858 /* There's not much else we can do ... we've already sent the headers
859 * to the client.
860 */
861 ap_rputs("\n\n[an internal server error occured]\n", r);
862 menu_footer(r);
863 return OK;
864 }
866}
867
869{
870 /* Optimization: skip the allocation of large local variables on the
871 * stack (in imap_handler_internal()) on requests that aren't using
872 * imagemaps
873 */
875 && strcmp(r->handler, "imap-file"))) {
876 return DECLINED;
877 }
878 else {
879 return imap_handler_internal(r);
880 }
881}
882
887
889{
891 create_imap_dir_config, /* dir config creater */
892 merge_imap_dir_configs, /* dir merger --- default is to override */
893 NULL, /* server config */
894 NULL, /* merge server config */
895 imap_cmds, /* command apr_table_t */
896 register_hooks /* register hooks */
897};
Symbol export macros and hook functions.
const char * string
Definition ap_regex.h:171
APR general purpose library routines.
#define min(a, b)
Definition apr_random.c:32
apr_size_t const unsigned char unsigned int unsigned int d
Definition apr_siphash.h:72
APR Strings library.
APR Standard Headers Support.
#define AP_INIT_TAKE1(directive, func, mconfig, where, help)
#define ap_get_module_config(v, m)
int ap_cfg_closefile(ap_configfile_t *cfp)
Definition util.c:931
apr_status_t ap_pcfg_openfile(ap_configfile_t **ret_cfg, apr_pool_t *p, const char *name)
Definition util.c:957
#define AP_DECLARE_MODULE(foo)
ap_conf_vector_t * base
void ap_hook_handler(ap_HOOK_handler_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:170
const char * ap_set_string_slot(cmd_parms *cmd, void *struct_ptr, const char *arg)
Definition config.c:1469
request_rec * r
apr_status_t ap_cfg_getline(char *buf, apr_size_t bufsize, ap_configfile_t *cfp)
Definition util.c:1198
#define MAX_STRING_LEN
Definition httpd.h:300
#define DOCTYPE_HTML_3_2
Definition httpd.h:238
#define DECLINED
Definition httpd.h:457
#define OK
Definition httpd.h:456
char * ap_construct_url(apr_pool_t *p, const char *uri, request_rec *r)
Definition core.c:1246
#define APLOGNO(n)
Definition http_log.h:117
#define ap_log_rerror
Definition http_log.h:454
#define APLOG_ERR
Definition http_log.h:67
#define APLOG_MARK
Definition http_log.h:283
int ap_rvputs(request_rec *r,...)
Definition protocol.c:2220
static APR_INLINE int ap_rputs(const char *str, request_rec *r)
void ap_set_content_type_ex(request_rec *r, const char *ct, int trusted)
void * dummy
Definition http_vhost.h:62
apr_off_t point
const char apr_ssize_t slen
Definition apr_encode.h:168
#define APR_HOOK_MIDDLE
Definition apr_hooks.h:303
apr_text_header const char * text
Definition apr_xml.h:78
#define OR_INDEXES
#define HTTP_INTERNAL_SERVER_ERROR
Definition httpd.h:535
#define HTTP_MOVED_TEMPORARILY
Definition httpd.h:502
#define HTTP_NOT_FOUND
Definition httpd.h:512
#define HTTP_NO_CONTENT
Definition httpd.h:494
#define M_GET
Definition httpd.h:592
#define STANDARD20_MODULE_STUFF
#define ap_escape_uri(ppool, path)
Definition httpd.h:1836
#define ap_strchr_c(s, c)
Definition httpd.h:2353
#define ap_escape_html(p, s)
Definition httpd.h:1860
apr_size_t size
const char * input
Definition apr_cstr.h:93
#define apr_isspace(c)
Definition apr_lib.h:225
#define apr_isdigit(c)
Definition apr_lib.h:209
#define apr_isalpha(c)
Definition apr_lib.h:205
const char * value
Definition apr_env.h:51
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
int strcasecmp(const char *a, const char *b)
int strncasecmp(const char *a, const char *b, size_t n)
const char const char *const * args
int int status
apr_size_t apr_size_t max
Definition apr_time.h:220
Apache Configuration.
CORE HTTP Daemon.
Apache Logging library.
Command line options.
HTTP protocol handling.
Apache Request library.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
static const char *const directory
mod_core private header file
static int imap_handler(request_rec *r)
static void * merge_imap_dir_configs(apr_pool_t *p, void *basev, void *addv)
static const char * imap_url(request_rec *r, const char *base, const char *value)
static double get_x_coord(const char *args)
static int imap_handler_internal(request_rec *r)
#define X
#define IMAP_BASE_DEFAULT
#define IMAP_DEFAULT_DEFAULT
static void * create_imap_dir_config(apr_pool_t *p, char *dummy)
#define fmin(a, b)
static double get_y_coord(const char *args)
static int is_closer(const double point[2], double coords[100][2], double *closest)
static void menu_blank(request_rec *r, char *menu)
#define IMAP_MENU_DEFAULT
static void menu_comment(request_rec *r, char *menu, char *comment)
#define Y
static int pointincircle(const double point[2], double coords[100][2])
static void register_hooks(apr_pool_t *p)
#define IMAP_MAGIC_TYPE
static void menu_footer(request_rec *r)
static void menu_header(request_rec *r, char *menu)
#define MAXVERTS
static int pointinrect(const double point[2], double coords[100][2])
static int imap_reply(request_rec *r, const char *redirect)
static int pointinpoly(const double point[2], double pgon[100][2])
static void menu_default(request_rec *r, const char *menu, const char *href, const char *text)
static void read_quoted(char **string, char **quoted_part)
static const command_rec imap_cmds[]
#define fmax(a, b)
static void menu_directive(request_rec *r, const char *menu, const char *href, const char *text)
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
char * imap_default
A structure that represents the current request.
Definition httpd.h:845
char * uri
Definition httpd.h:1016
const char * handler
Definition httpd.h:994
int method_number
Definition httpd.h:898
apr_pool_t * pool
Definition httpd.h:847
char * filename
Definition httpd.h:1018
apr_table_t * headers_in
Definition httpd.h:976
struct ap_conf_vector_t * per_dir_config
Definition httpd.h:1047
char * args
Definition httpd.h:1026
apr_table_t * headers_out
Definition httpd.h:978
Apache script tools.