[BACK]Return to cgi.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Annotation of mandoc/cgi.c, Revision 1.2

1.2     ! kristaps    1: /*     $Id: cgi.c,v 1.1 2011/11/09 01:24:23 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:
                     10: #include "apropos.h"
                     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("&quote;");
                     81:                        break;
                     82:                case ('&'):
                     83:                        printf("&amp;");
                     84:                        break;
                     85:                case ('>'):
                     86:                        printf("&gt;");
                     87:                        break;
                     88:                case ('<'):
                     89:                        printf("&lt;");
                     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