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

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("&quote;");
                     83:                        break;
                     84:                case ('&'):
                     85:                        printf("&amp;");
                     86:                        break;
                     87:                case ('>'):
                     88:                        printf("&gt;");
                     89:                        break;
                     90:                case ('<'):
                     91:                        printf("&lt;");
                     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