Annotation of libaitwww/src/aitwww.c, revision 1.4

1.1       misho       1: /*************************************************************************
                      2: * (C) 2012 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
                      3: *  by Michael Pounov <misho@elwix.org>
                      4: *
                      5: * $Author: misho $
1.4     ! misho       6: * $Id: aitwww.c,v 1.3.4.3 2012/07/31 23:08:40 misho Exp $
1.1       misho       7: *
                      8: **************************************************************************
                      9: The ELWIX and AITNET software is distributed under the following
                     10: terms:
                     11: 
                     12: All of the documentation and software included in the ELWIX and AITNET
                     13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
                     14: 
                     15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
                     16:        by Michael Pounov <misho@elwix.org>.  All rights reserved.
                     17: 
                     18: Redistribution and use in source and binary forms, with or without
                     19: modification, are permitted provided that the following conditions
                     20: are met:
                     21: 1. Redistributions of source code must retain the above copyright
                     22:    notice, this list of conditions and the following disclaimer.
                     23: 2. Redistributions in binary form must reproduce the above copyright
                     24:    notice, this list of conditions and the following disclaimer in the
                     25:    documentation and/or other materials provided with the distribution.
                     26: 3. All advertising materials mentioning features or use of this software
                     27:    must display the following acknowledgement:
                     28: This product includes software developed by Michael Pounov <misho@elwix.org>
                     29: ELWIX - Embedded LightWeight unIX and its contributors.
                     30: 4. Neither the name of AITNET nor the names of its contributors
                     31:    may be used to endorse or promote products derived from this software
                     32:    without specific prior written permission.
                     33: 
                     34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
                     35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     37: ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     44: SUCH DAMAGE.
                     45: */
                     46: #include "global.h"
                     47: #include "mime.h"
                     48: 
                     49: 
                     50: #pragma GCC visibility push(hidden)
                     51: 
                     52: int www_Errno;
                     53: char www_Error[STRSIZ];
                     54: 
                     55: #pragma GCC visibility pop
                     56: 
                     57: // www_GetErrno() Get error code of last operation
                     58: inline int
                     59: www_GetErrno()
                     60: {
                     61:        return www_Errno;
                     62: }
                     63: 
                     64: // www_GetError() Get error text of last operation
                     65: inline const char *
                     66: www_GetError()
                     67: {
                     68:        return www_Error;
                     69: }
                     70: 
                     71: // www_SetErr() Set error to variables for internal use!!!
                     72: inline void
                     73: www_SetErr(int eno, char *estr, ...)
                     74: {
                     75:        va_list lst;
                     76: 
                     77:        www_Errno = eno;
1.4     ! misho      78:        memset(www_Error, 0, sizeof www_Errno);
1.1       misho      79:        va_start(lst, estr);
1.4     ! misho      80:        vsnprintf(www_Error, sizeof www_Errno, estr, lst);
1.1       misho      81:        va_end(lst);
                     82: }
                     83: 
                     84: /* -------------------------------------------------------------- */
                     85: 
                     86: /*
                     87:  * www_initCGI() - Init CGI program
                     88:  *
                     89:  * return: NULL error or allocated cgi session
                     90:  */
                     91: cgi_t *
                     92: www_initCGI(void)
                     93: {
                     94:        char *s, *str;
                     95:        int ctlen, rlen;
                     96:        register int i;
                     97:        cgi_t *cgi = NULL;
                     98: 
                     99:        str = getenv("REQUEST_METHOD");
                    100:        if (!str) {
1.3       misho     101:                www_SetErr(EFAULT, "Request method not found");
1.1       misho     102:                return NULL;
                    103:        }
                    104:        if (!strcmp(str, "GET") || !strcmp(str, "HEAD")) {
                    105:                /* GET | HEAD */
                    106:                str = getenv("QUERY_STRING");
                    107:                if (!str) {
1.3       misho     108:                        www_SetErr(EFAULT, "Query string not found");
1.1       misho     109:                        return NULL;
                    110:                }
                    111:                cgi = www_parseQuery(str);
                    112:        } else if (!strcmp(str, "POST")) {
                    113:                /* POST */
                    114:                str = getenv("CONTENT_LENGTH");
                    115:                if (!str) {
1.3       misho     116:                        www_SetErr(EFAULT, "Content length not found");
1.1       misho     117:                        return NULL;
                    118:                } else
                    119:                        ctlen = strtol(str, NULL, 0);
                    120: 
                    121:                s = getenv("CONTENT_TYPE");
                    122:                if (!s) {
1.3       misho     123:                        www_SetErr(EFAULT, "Content type not found");
1.1       misho     124:                        return NULL;
                    125:                }
                    126:                if (www_cmp(s, "multipart/form-data") && 
                    127:                                www_cmp(s, "application/x-www-form-urlencoded")) {
1.3       misho     128:                        www_SetErr(EFAULT, "MIME parts are broken");
1.1       misho     129:                        return NULL;
                    130:                }
                    131: 
                    132:                /* allocated space for post data */
1.4     ! misho     133:                str = io_malloc(ctlen + 1);
1.1       misho     134:                if (!str) {
1.4     ! misho     135:                        www_SetErr(io_GetErrno(), "%s", io_GetError());
1.1       misho     136:                        return NULL;
1.2       misho     137:                } else
                    138:                        memset(str, 0, ctlen + 1);
1.1       misho     139:                for (i = 0; i < ctlen && (rlen = 
                    140:                                        read(STDIN_FILENO, (void*) str + i, ctlen - i)) > 0; i += rlen);
                    141:                str[ctlen] = 0;
                    142: 
                    143:                if (!www_cmp(s, "application/x-www-form-urlencoded"))
                    144:                        cgi = www_parseQuery(str);
                    145:                else if (!www_cmp(s, "multipart/form-data"))
                    146:                        cgi = www_parseMultiPart(str, ctlen, s);
                    147: 
1.4     ! misho     148:                io_free(str);
1.1       misho     149:        } else {
                    150:                /* Unknown method */
1.3       misho     151:                www_SetErr(EFAULT, "Unknown request method");
1.1       misho     152:                return NULL;
                    153:        }
                    154: 
                    155:        return cgi;
                    156: }
                    157: 
                    158: /*
                    159:  * www_closeCGI() - Close and free all CGI resources
                    160:  *
                    161:  * @cgi = Inited cgi session
                    162:  * return: none
                    163:  */
                    164: void
                    165: www_closeCGI(cgi_t ** __restrict cgi)
                    166: {
                    167:        struct tagCGI *t;
                    168: 
                    169:        if (!cgi || !*cgi)
                    170:                return;
                    171: 
                    172:        while ((t = SLIST_FIRST(*cgi))) {
1.4     ! misho     173:                io_freeVar(&t->cgi_name);
        !           174:                io_freeVar(&t->cgi_value);
1.1       misho     175: 
                    176:                SLIST_REMOVE_HEAD(*cgi, cgi_node);
1.4     ! misho     177:                io_free(t);
1.1       misho     178:        }
                    179: 
1.4     ! misho     180:        io_free(*cgi);
1.1       misho     181:        *cgi = NULL;
                    182: }
                    183: 
                    184: /*
                    185:  * www_parseQuery() - Parse CGI query string
                    186:  *
                    187:  * @str = String
                    188:  * return: NULL error or allocated cgi session
                    189:  */
                    190: cgi_t *
                    191: www_parseQuery(const char *str)
                    192: {
                    193:        char *base, *wrk;
                    194:        cgi_t *cgi;
                    195:        struct tagCGI *t, *old = NULL;
                    196: 
                    197:        if (!str) {
                    198:                www_SetErr(EINVAL, "String is NULL");
                    199:                return NULL;
                    200:        }
                    201: 
1.4     ! misho     202:        cgi = io_malloc(sizeof(cgi_t));
1.1       misho     203:        if (!cgi) {
1.4     ! misho     204:                www_SetErr(io_GetErrno(), "%s", io_GetError());
1.1       misho     205:                return NULL;
                    206:        } else {
                    207:                memset(cgi, 0, sizeof(cgi_t));
                    208:                SLIST_INIT(cgi);
                    209:        }
                    210: 
1.4     ! misho     211:        base = wrk = io_strdup(str);
1.1       misho     212: 
                    213:        while (*wrk) {
1.4     ! misho     214:                t = io_malloc(sizeof(struct tagCGI));
1.1       misho     215:                if (!t) {
1.4     ! misho     216:                        www_SetErr(io_GetErrno(), "%s", io_GetError());
1.1       misho     217:                        www_closeCGI(&cgi);
                    218:                        return NULL;
                    219:                } else
                    220:                        memset(t, 0, sizeof(struct tagCGI));
                    221: 
                    222:                t->cgi_name = www_getpair(&wrk, "=");
1.4     ! misho     223:                www_unescape(AIT_GET_STR(t->cgi_name));
1.1       misho     224: 
                    225:                t->cgi_value = www_getpair(&wrk, "&;");
1.4     ! misho     226:                www_unescape(AIT_GET_STR(t->cgi_value));
1.1       misho     227: 
                    228:                if (!old)
                    229:                        SLIST_INSERT_HEAD(cgi, t, cgi_node);
                    230:                else
                    231:                        SLIST_INSERT_AFTER(old, t, cgi_node);
                    232:                old = t;
                    233:        }
                    234: 
1.4     ! misho     235:        io_free(base);
1.2       misho     236:        return cgi;
1.1       misho     237: }
                    238: 
                    239: /*
                    240:  * www_getValue() - Get Value from CGI session
                    241:  *
                    242:  * @cgi = Inited cgi session
                    243:  * @name = Name of cgi variable
                    244:  * return: NULL not found or !=NULL value
                    245:  */
                    246: inline const char *
                    247: www_getValue(cgi_t * __restrict cgi, const char *name)
                    248: {
                    249:        struct tagCGI *t;
                    250: 
                    251:        if (!cgi || !name) {
                    252:                www_SetErr(EINVAL, "Invalid argument(s)");
                    253:                return NULL;
                    254:        }
                    255: 
                    256:        SLIST_FOREACH(t, cgi, cgi_node)
1.4     ! misho     257:                if (t->cgi_name && !strcmp(name, AIT_GET_STR(t->cgi_name)))
        !           258:                        return AIT_GET_STR(t->cgi_value);
1.1       misho     259: 
1.2       misho     260:        return NULL;
1.1       misho     261: }
                    262: 
                    263: /*
                    264:  * www_addValue() - Add new or update if exists CGI variable
                    265:  *
                    266:  * @cgi = Inited cgi session
                    267:  * @name = Name of cgi variable
                    268:  * @value = Value of cgi variable
                    269:  * return: -1 error, 0 add new one or 1 updated variable
                    270:  */
                    271: int
                    272: www_addValue(cgi_t * __restrict cgi, const char *name, const char *value)
                    273: {
                    274:        struct tagCGI *t, *tmp;
                    275: 
                    276:        if (!cgi || !name) {
                    277:                www_SetErr(EINVAL, "Invalid argument(s)");
                    278:                return -1;
                    279:        }
                    280: 
                    281:        /* search for update */
                    282:        SLIST_FOREACH_SAFE(t, cgi, cgi_node, tmp) {
1.4     ! misho     283:                if (t->cgi_name && !strcmp(name, AIT_GET_STR(t->cgi_name))) {
        !           284:                        AIT_FREE_VAL(t->cgi_value);
        !           285:                        AIT_SET_STR(t->cgi_value, value);
1.1       misho     286:                        /* update */
                    287:                        return 1;
                    288:                }
                    289:                /* save last cgi pair */
                    290:                if (!tmp)
                    291:                        break;
                    292:        }
                    293: 
                    294:        /* add new one */
1.4     ! misho     295:        tmp = io_malloc(sizeof(struct tagCGI));
1.1       misho     296:        if (!tmp) {
1.4     ! misho     297:                www_SetErr(io_GetErrno(), "%s", io_GetError());
1.1       misho     298:                return -1;
                    299:        } else
                    300:                memset(tmp, 0, sizeof(struct tagCGI));
                    301: 
1.4     ! misho     302:        tmp->cgi_name = io_allocVar();
        !           303:        if (!tmp->cgi_name) {
        !           304:                www_SetErr(io_GetErrno(), "%s", io_GetError());
        !           305:                io_free(tmp);
        !           306:                return -1;
        !           307:        } else
        !           308:                AIT_SET_STR(tmp->cgi_name, name);
        !           309:        tmp->cgi_value = io_allocVar();
        !           310:        if (!tmp->cgi_name) {
        !           311:                www_SetErr(io_GetErrno(), "%s", io_GetError());
        !           312:                io_freeVar(&tmp->cgi_name);
        !           313:                io_free(tmp);
        !           314:                return -1;
        !           315:        } else
        !           316:                AIT_SET_STR(tmp->cgi_value, value);
1.1       misho     317: 
1.2       misho     318:        if (!t)
                    319:                SLIST_INSERT_HEAD(cgi, tmp, cgi_node);
                    320:        else
                    321:                SLIST_INSERT_AFTER(t, tmp, cgi_node);
1.1       misho     322:        return 0;
                    323: }
                    324: 
                    325: /*
                    326:  * www_delPair() - Delete CGI variable from session
                    327:  *
                    328:  * @cgi = Inited cgi session
                    329:  * @name = Name of cgi variable
                    330:  * return: -1 error, 0 not found or 1 deleted ok
                    331:  */
                    332: int
                    333: www_delPair(cgi_t * __restrict cgi, const char *name)
                    334: {
1.2       misho     335:        struct tagCGI *t, *tmp;
1.1       misho     336: 
                    337:        if (!cgi || !name) {
                    338:                www_SetErr(EINVAL, "Invalid argument(s)");
                    339:                return -1;
                    340:        }
                    341: 
                    342:        /* search for delete */
1.2       misho     343:        SLIST_FOREACH_SAFE(t, cgi, cgi_node, tmp)
1.4     ! misho     344:                if (t->cgi_name && !strcmp(name, AIT_GET_STR(t->cgi_name))) {
1.1       misho     345:                        SLIST_REMOVE(cgi, t, tagCGI, cgi_node);
1.2       misho     346: 
1.4     ! misho     347:                        io_freeVar(&t->cgi_name);
        !           348:                        io_freeVar(&t->cgi_value);
        !           349:                        io_free(t);
1.1       misho     350:                        return 1;
                    351:                }
                    352: 
                    353:        return 0;
                    354: }
                    355: 
                    356: /*
1.2       misho     357:  * www_listPairs() - Walk over CGI session variables
                    358:  *
                    359:  * @cgi = Cgi session
                    360:  * @func = If !=NULL call function for each element
                    361:  * @arg = Optional argument pass through callback
                    362:  * return: -1 error or >-1 number of elements
                    363:  */
                    364: inline int
                    365: www_listPairs(cgi_t * __restrict cgi, list_cb_t func, void *arg)
                    366: {
                    367:        register int ret = 0;
                    368:        struct tagCGI *t;
                    369: 
                    370:        if (!cgi) {
                    371:                www_SetErr(EINVAL, "Invalid CGI session argument");
                    372:                return -1;
                    373:        }
                    374: 
                    375:        SLIST_FOREACH(t, cgi, cgi_node) {
                    376:                ret++;
                    377: 
                    378:                if (func)
                    379:                        func(t, arg);
                    380:        }
                    381: 
                    382:        return ret;
                    383: }
                    384: 
                    385: /*
1.1       misho     386:  * www_header() - Output initial html header
                    387:  *
                    388:  * @output = file handle
                    389:  * return: <1 error or >0 writed bytes
                    390:  */
                    391: inline int
                    392: www_header(FILE *output)
                    393: {
                    394:        FILE *f = output ? output : stdout;
                    395: 
                    396:        return fputs("Content-type: text/html\n\n", f);
                    397: }
                    398: 
1.4     ! misho     399: static ait_val_t *
1.1       misho     400: quotStr(const char *str, const char **end)
                    401: {
1.4     ! misho     402:        char *e;
1.1       misho     403:        int n, len = 0;
                    404:        register int i;
1.4     ! misho     405:        ait_val_t *s;
1.1       misho     406: 
                    407:        /* get str w/o " */
                    408:        if (*str != '"') {
                    409:                n = strspn(str, "!#$%&'*+-.0123456789?ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                    410:                                "^_`abcdefghijklmnopqrstuvwxyz{|}~");
1.4     ! misho     411:                s = io_allocVar();
1.1       misho     412:                if (!s) {
1.4     ! misho     413:                        www_SetErr(io_GetErrno(), "%s", io_GetError());
1.1       misho     414:                        return NULL;
                    415:                } else {
1.4     ! misho     416:                        AIT_SET_STRSIZ(s, n + 1);
        !           417:                        strlcpy(AIT_GET_STR(s), str, AIT_LEN(s));
1.1       misho     418:                        *end = str + n;
                    419:                        return s;
                    420:                }
                    421:        } else
                    422:                str++;
                    423:        /* get quoted string */
                    424:        if (!(e = strchr(str, '"')))
                    425:                return NULL;
                    426:        else
                    427:                len = e - str;
1.4     ! misho     428: 
        !           429:        s = io_allocVar();
1.1       misho     430:        if (!s) {
1.4     ! misho     431:                www_SetErr(io_GetErrno(), "%s", io_GetError());
1.1       misho     432:                return NULL;
1.4     ! misho     433:        } else {
        !           434:                AIT_SET_STRSIZ(s, len + 1);
        !           435:                e = AIT_GET_STR(s);
1.1       misho     436:        }
                    437: 
                    438:        for (i = 0; i < len; i++, str++) {
                    439:                if (*str == '\\' || *str == '\n')
1.4     ! misho     440:                        e[i] = *++str;
1.1       misho     441:                else if (*str == '"')
                    442:                        break;
                    443:                else
1.4     ! misho     444:                        e[i] = *str;
1.1       misho     445:        }
1.4     ! misho     446:        e[i] = 0;
1.1       misho     447: 
                    448:        *end = ++str;
                    449:        return s;
                    450: }
                    451: 
                    452: static struct tagCGI *
                    453: addAttr(const char **ct)
                    454: {
                    455:        struct tagCGI *a;
1.4     ! misho     456:        const char *c;
        !           457:        char *eq;
1.1       misho     458: 
                    459:        if (!*ct || !(c = strchr(*ct, ';')))
                    460:                return NULL;
                    461:        else
                    462:                c++;
1.4     ! misho     463:        while (isspace((int) *c))
1.1       misho     464:                c++;
                    465: 
                    466:        if (!(eq = strchr(c, '=')))
                    467:                return NULL;
                    468: 
1.4     ! misho     469:        a = io_malloc(sizeof(struct tagCGI));
        !           470:        if (!a) {
        !           471:                www_SetErr(io_GetErrno(), "%s", io_GetError());
1.1       misho     472:                return NULL;
                    473:        }
1.4     ! misho     474:        a->cgi_name = io_allocVar();
        !           475:        if (!a->cgi_name) {
        !           476:                www_SetErr(io_GetErrno(), "%s", io_GetError());
        !           477:                io_free(a);
1.1       misho     478:                return NULL;
                    479:        }
                    480: 
1.4     ! misho     481:        *eq++ = 0;
        !           482:        AIT_SET_STR(a->cgi_name, c);
        !           483:        a->cgi_value = quotStr(eq, &c);
        !           484:        if (!a->cgi_value) {
        !           485:                io_freeVar(&a->cgi_name);
        !           486:                io_free(a);
1.1       misho     487:                return NULL;
                    488:        }
1.4     ! misho     489: 
        !           490:        *ct = c;
1.1       misho     491:        return a;
                    492: }
                    493: 
                    494: /*
                    495:  * www_parseMultiPart() - Parse Multi part POST CGI query string
                    496:  *
                    497:  * @str = String
                    498:  * @ctlen = Content length
                    499:  * @ct = Content type
                    500:  * return: NULL error or allocated cgi session
                    501:  */
                    502: cgi_t *
                    503: www_parseMultiPart(const char *str, int ctlen, const char *ct)
                    504: {
                    505:        cgi_t *cgi, *attr;
                    506:        mime_t *mime = NULL;
                    507:        struct tagMIME *m;
                    508:        struct tagCGI *t, *old = NULL;
                    509:        const char *s;
                    510:        int len;
1.4     ! misho     511:        ait_val_t *v;
1.1       misho     512: 
                    513:        if (!str) {
                    514:                www_SetErr(EINVAL, "String is NULL");
                    515:                return NULL;
                    516:        }
                    517: 
1.4     ! misho     518:        cgi = io_malloc(sizeof(cgi_t));
1.1       misho     519:        if (!cgi) {
1.4     ! misho     520:                www_SetErr(io_GetErrno(), "%s", io_GetError());
1.1       misho     521:                return NULL;
                    522:        } else {
                    523:                memset(cgi, 0, sizeof(cgi_t));
                    524:                SLIST_INIT(cgi);
                    525:        }
                    526: 
                    527:        /* parse MIME messages */
                    528:        attr = www_parseAttributes(&ct);
                    529:        if (!attr) {
                    530:                www_closeCGI(&cgi);
                    531:                return NULL;
                    532:        }
1.4     ! misho     533:        v = www_getAttribute(attr, "boundary");
        !           534:        mime = mime_parseMultiPart(str, ctlen, AIT_GET_STR(v), NULL);
1.1       misho     535:        www_freeAttributes(&attr);
1.2       misho     536:        if (!mime) {
                    537:                www_closeCGI(&cgi);
                    538:                return NULL;
                    539:        }
1.1       misho     540: 
                    541:        SLIST_FOREACH(m, mime, mime_node) {
                    542:                s = mime_getValue(m, "content-disposition");
                    543:                attr = www_parseAttributes(&s);
1.2       misho     544:                if (!www_getAttribute(attr, "name")) {
                    545:                        www_freeAttributes(&attr);
                    546:                        continue;
                    547:                }
1.1       misho     548: 
1.4     ! misho     549:                t = io_malloc(sizeof(struct tagCGI));
1.1       misho     550:                if (!t) {
1.4     ! misho     551:                        www_SetErr(io_GetErrno(), "%s", io_GetError());
1.1       misho     552:                        mime_close(&mime);
                    553:                        www_closeCGI(&cgi);
                    554:                        return NULL;
                    555:                } else
                    556:                        memset(t, 0, sizeof(struct tagCGI));
                    557: 
1.4     ! misho     558:                AIT_COPY_VAL(t->cgi_name, www_getAttribute(attr, "name"));
1.1       misho     559:                len = mime_calcRawSize(m);
1.4     ! misho     560:                t->cgi_value = io_allocVar();
        !           561:                if (!t->cgi_value) {
        !           562:                        www_SetErr(io_GetErrno(), "%s", io_GetError());
        !           563:                        io_freeVar(&t->cgi_name);
        !           564:                        io_free(t);
        !           565:                        mime_close(&mime);
        !           566:                        www_closeCGI(&cgi);
        !           567:                        return NULL;
        !           568:                } else {
        !           569:                        AIT_SET_STRSIZ(t->cgi_value, len + 1);
        !           570:                        len = mime_getRawData(m, AIT_GET_STR(t->cgi_value), AIT_LEN(t->cgi_value));
1.1       misho     571:                }
                    572: 
                    573:                www_freeAttributes(&attr);
                    574: 
                    575:                if (!old)
                    576:                        SLIST_INSERT_HEAD(cgi, t, cgi_node);
                    577:                else
                    578:                        SLIST_INSERT_AFTER(old, t, cgi_node);
                    579:                old = t;
                    580:        }
                    581: 
                    582:        mime_close(&mime);
                    583:        return cgi;
                    584: }
                    585: 
                    586: /*
                    587:  * www_parseAttributes() - Parse attributes
                    588:  *
                    589:  * @ct = Content type
                    590:  * return: NULL error or !=NULL attributes
                    591:  */
                    592: inline cgi_t *
                    593: www_parseAttributes(const char **ct)
                    594: {
                    595:        struct tagCGI *t, *old = NULL;
                    596:        cgi_t *attr = NULL;
                    597: 
                    598:        if (!ct) {
                    599:                www_SetErr(EINVAL, "String is NULL");
                    600:                return NULL;
                    601:        }
                    602: 
1.4     ! misho     603:        attr = io_malloc(sizeof(cgi_t));
1.1       misho     604:        if (!attr) {
1.4     ! misho     605:                www_SetErr(io_GetErrno(), "%s", io_GetError());
1.1       misho     606:                return NULL;
                    607:        } else {
                    608:                memset(attr, 0, sizeof(cgi_t));
                    609:                SLIST_INIT(attr);
                    610:        }
                    611: 
                    612:        /* get mime attributes */
                    613:        while ((t = addAttr(ct))) {
                    614:                if (!old)
                    615:                        SLIST_INSERT_HEAD(attr, t, cgi_node);
                    616:                else
                    617:                        SLIST_INSERT_AFTER(old, t, cgi_node);
                    618:                old = t;
                    619:        }
                    620: 
                    621:        return attr;
                    622: }
                    623: 
                    624: /*
1.4     ! misho     625:  * www_getAttribute() - Get Attribute from attribute session
1.1       misho     626:  *
1.4     ! misho     627:  * @cgi = Inited attribute session
        !           628:  * @name = Name of attribute variable
        !           629:  * return: NULL not found or !=NULL value
1.1       misho     630:  */
1.4     ! misho     631: inline ait_val_t *
        !           632: www_getAttribute(cgi_t * __restrict cgi, const char *name)
1.1       misho     633: {
                    634:        struct tagCGI *t;
                    635: 
1.4     ! misho     636:        if (!cgi || !name) {
        !           637:                www_SetErr(EINVAL, "Invalid argument(s)");
        !           638:                return NULL;
1.1       misho     639:        }
                    640: 
1.4     ! misho     641:        SLIST_FOREACH(t, cgi, cgi_node)
        !           642:                if (t->cgi_name && !strcmp(name, AIT_GET_STR(t->cgi_name)))
1.1       misho     643:                        return t->cgi_value;
                    644: 
                    645:        return NULL;
                    646: }
1.4     ! misho     647: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>