Annotation of mandoc/cgi.c, Revision 1.4
1.4 ! schwarze 1: /* $Id: cgi.c,v 1.3 2011/11/13 10:12:05 schwarze Exp $ */
1.1 kristaps 2: #include <assert.h>
3: #include <fcntl.h>
4: #include <regex.h>
5: #include <stdio.h>
6: #include <stdarg.h>
7: #include <stdlib.h>
8: #include <string.h>
9:
1.4 ! schwarze 10: #include "mandoc.h"
! 11: #include "mandocdb.h"
1.3 schwarze 12: #include "apropos_db.h"
1.1 kristaps 13:
14: /*
15: * The page a request is trying to make.
16: */
17: enum page {
18: PAGE_INDEX,
19: PAGE_SEARCH,
20: PAGE__MAX
21: };
22:
23: /*
24: * Key-value pair.
25: * Both key and val are on the heap.
26: */
27: struct kval {
28: char *key;
29: char *val;
30: };
31:
32: /*
33: * The media type, determined by suffix, of the requesting or responding
34: * context.
35: */
36: enum media {
37: MEDIA_HTML,
38: MEDIA__MAX
39: };
40:
41: /*
42: * An HTTP request.
43: */
44: struct req {
45: struct kval *fields; /* query fields */
46: size_t fieldsz;
47: enum media media;
48: enum page page;
49: };
50:
1.2 kristaps 51: #if 0
1.1 kristaps 52: static void html_printtext(const char *);
1.2 kristaps 53: #endif
1.1 kristaps 54: static int kval_decode(char *);
55: static void kval_parse(struct kval **, size_t *, char *);
56: static void kval_free(struct kval *, size_t);
57: static void pg_index(const struct req *, char *);
58: static void pg_search(const struct req *, char *);
1.2 kristaps 59: #if 0
1.1 kristaps 60: static void pg_searchres(struct rec *, size_t, void *);
1.2 kristaps 61: #endif
1.1 kristaps 62:
63: static const char * const pages[PAGE__MAX] = {
64: "index", /* PAGE_INDEX */
65: "search", /* PAGE_SEARCH */
66: };
67:
68: static const char * const medias[MEDIA__MAX] = {
69: "html", /* MEDIA_HTML */
70: };
71:
1.2 kristaps 72: #if 0
1.1 kristaps 73: static void
74: html_printtext(const char *p)
75: {
76: char c;
77:
78: while ('\0' != *p)
79: switch ((c = *p++)) {
80: case ('"'):
81: printf(""e;");
82: break;
83: case ('&'):
84: printf("&");
85: break;
86: case ('>'):
87: printf(">");
88: break;
89: case ('<'):
90: printf("<");
91: break;
92: default:
93: putchar((unsigned char)c);
94: break;
95: }
96: }
1.2 kristaps 97: #endif
1.1 kristaps 98:
99: static void
100: kval_free(struct kval *p, size_t sz)
101: {
102: int i;
103:
104: for (i = 0; i < (int)sz; i++) {
105: free(p[i].key);
106: free(p[i].val);
107: }
108: free(p);
109: }
110:
111: /*
112: * Parse out key-value pairs from an HTTP request variable.
113: * This can be either a cookie or a POST/GET string.
114: */
115: static void
116: kval_parse(struct kval **kv, size_t *kvsz, char *p)
117: {
118: char *key, *val;
119: size_t sz, cur;
120:
121: cur = 0;
122:
123: while (p && '\0' != *p) {
124: while (' ' == *p)
125: p++;
126:
127: key = p;
128: val = NULL;
129:
130: if (NULL != (p = strchr(p, '='))) {
131: *p++ = '\0';
132: val = p;
133:
134: sz = strcspn(p, ";&");
135: /* LINTED */
136: p += sz;
137:
138: if ('\0' != *p)
139: *p++ = '\0';
140: } else {
141: p = key;
142: sz = strcspn(p, ";&");
143: /* LINTED */
144: p += sz;
145:
146: if ('\0' != *p)
147: p++;
148: continue;
149: }
150:
151: if ('\0' == *key || '\0' == *val)
152: continue;
153:
154: /* Just abort handling. */
155:
156: if ( ! kval_decode(key))
157: return;
158: if ( ! kval_decode(val))
159: return;
160:
161: if (*kvsz + 1 >= cur) {
162: cur++;
163: *kv = mandoc_realloc
164: (*kv, cur * sizeof(struct kval));
165: }
166:
167: (*kv)[(int)*kvsz].key = mandoc_strdup(key);
168: (*kv)[(int)*kvsz].val = mandoc_strdup(val);
169: (*kvsz)++;
170: }
171: }
172:
173: /*
174: * In-place HTTP-decode a string. The standard explanation is that this
175: * turns "%4e+foo" into "n foo" in the regular way. This is done
176: * in-place over the allocated string.
177: */
178: static int
179: kval_decode(char *p)
180: {
181: char hex[3];
182: int c;
183:
184: hex[2] = '\0';
185:
186: for ( ; '\0' != *p; p++) {
187: if ('%' == *p) {
188: if ('\0' == (hex[0] = *(p + 1)))
189: return(0);
190: if ('\0' == (hex[1] = *(p + 2)))
191: return(0);
192: if (1 != sscanf(hex, "%x", &c))
193: return(0);
194: if ('\0' == c)
195: return(0);
196:
197: *p = (char)c;
198: memmove(p + 1, p + 3, strlen(p + 3) + 1);
199: } else
200: *p = '+' == *p ? ' ' : *p;
201: }
202:
203: *p = '\0';
204: return(1);
205: }
206:
207:
208: /* ARGSUSED */
209: static void
210: pg_index(const struct req *req, char *path)
211: {
212:
213: }
214:
1.2 kristaps 215: #if 0
1.1 kristaps 216: static void
217: pg_searchres(struct rec *recs, size_t sz, void *arg)
218: {
219: int i;
220: const char *pg;
221:
222: if (NULL == (pg = getenv("SCRIPT_NAME")))
223: pg = "";
224:
225: for (i = 0; i < (int)sz; i++) {
226: printf("<A HREF=\"%s/show/%u.html\">",
227: pg, recs[i].rec);
228: html_printtext(recs[i].title);
229: putchar('(');
230: html_printtext(recs[i].cat);
231: puts(")</A>");
232: }
233: }
1.2 kristaps 234: #endif
1.1 kristaps 235:
236: static void
237: pg_search(const struct req *req, char *path)
238: {
239: int i;
240: struct opts opt;
241:
242: for (i = 0; i < (int)req->fieldsz; i++)
243: if (0 == strcmp(req->fields[i].key, "key"))
244: break;
245:
246: if (i == (int)req->fieldsz)
247: return;
248:
249: memset(&opt, 0, sizeof(struct opts));
1.2 kristaps 250: /*opt.types = TYPE_NAME | TYPE_DESC;
251: apropos_search(&opt, req->fields[i].val, NULL, pg_searchres);*/
1.1 kristaps 252: }
253:
254: int
255: main(void)
256: {
257: int i;
258: struct req req;
259: char *p;
260: char *path, *subpath, *suffix;
261:
262: memset(&req, 0, sizeof(struct req));
263:
264: if (NULL != (p = getenv("QUERY_STRING")))
265: kval_parse(&req.fields, &req.fieldsz, p);
266:
267: suffix = subpath = path = NULL;
268:
269: req.media = MEDIA_HTML;
270: req.page = PAGE__MAX;
271:
272: if (NULL == (path = getenv("PATH_INFO")) || '\0' == *path)
273: req.page = PAGE_INDEX;
274: if (NULL != path && '/' == *path && '\0' == *++path)
275: req.page = PAGE_INDEX;
276:
277: if (NULL != path && NULL != (suffix = strrchr(path, '.')))
278: if (NULL != suffix && NULL == strchr(suffix, '/'))
279: *suffix++ = '\0';
280:
281: if (NULL != path && NULL != (subpath = strchr(path, '/')))
282: *subpath++ = '\0';
283:
284: if (NULL != suffix && '\0' != *suffix)
285: for (i = 0; i < (int)MEDIA__MAX; i++)
286: if (0 == strcmp(medias[i], suffix)) {
287: req.media = (enum media)i;
288: break;
289: }
290:
291: if (NULL != path && '\0' != *path)
292: for (i = 0; i < (int)PAGE__MAX; i++)
293: if (0 == strcmp(pages[i], path)) {
294: req.page = (enum page)i;
295: break;
296: }
297:
298: switch (req.page) {
299: case (PAGE_INDEX):
300: pg_index(&req, subpath);
301: break;
302: case (PAGE_SEARCH):
303: pg_search(&req, subpath);
304: break;
305: default:
306: /* Blah */
307: break;
308: }
309:
310: kval_free(req.fields, req.fieldsz);
311: return(EXIT_SUCCESS);
312: }
CVSweb