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