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