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

Annotation of mandoc/cgi.c, Revision 1.1

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

CVSweb