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

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