Annotation of libaitio/src/url.c, revision 1.5

1.2       misho       1: /*************************************************************************
                      2: * (C) 2010 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
                      3: *  by Michael Pounov <misho@openbsd-bg.org>
                      4: *
                      5: * $Author: misho $
1.5     ! misho       6: * $Id: url.c,v 1.4.2.1 2011/03/15 11:57:32 misho Exp $
1.2       misho       7: *
                      8: *************************************************************************/
                      9: #include "global.h"
                     10: 
                     11: 
                     12: /*
                     13:  * ioURLGet() Parse and get data from input URL
                     14:  * @csURL = Input URL line
                     15:  * @url = Output parsed URL
                     16:  * return: 0 error format not find tech:// and return URL like path; 
                     17:                -1 error:: can`t read; >0 ok, up bits for known elements
                     18: */
1.4       misho      19: int
                     20: ioURLGet(const char *csURL, struct tagIOURL *url)
1.2       misho      21: {
                     22:        char *pos, *at, *cl, *sl;
                     23:        int ret = 0;
                     24: 
                     25:        if (!url)
                     26:                return -1;
                     27:        else
                     28:                memset(url, 0, sizeof(*url));
                     29: 
                     30:        strlcpy((char*) url->url_line, csURL, BUFSIZ);
                     31:        // Tech
                     32:        if (!(pos = strstr((char*) url->url_line, "://"))) {
                     33:                url->url_path.vallen = strlen((char*) url->url_line);
                     34:                url->url_path.value = (char*) url->url_line;
                     35:                return ret;
                     36:        } else {
                     37:                url->url_tech.value = (char*) url->url_line;
                     38:                url->url_tech.vallen = pos - (char*) url->url_line;
                     39:                if (url->url_tech.vallen)
                     40:                        ret |= 1;
                     41: 
                     42:                *pos = 0;
                     43:                pos += 3;
                     44:        }
                     45: 
                     46:        // User
                     47:        if ((at = strchr(pos, '@'))) {
                     48:                *at++ = 0;
                     49:                // Pass
                     50:                if ((cl = strchr(pos, ':'))) {
                     51:                        *cl++ = 0;
                     52: 
                     53:                        url->url_pass.value = cl;
                     54:                        url->url_pass.vallen = at - cl - 1;
                     55:                        if (url->url_pass.vallen)
                     56:                                ret |= 4;
                     57:                } else
                     58:                        cl = at;
                     59: 
                     60:                url->url_user.value = pos;
                     61:                url->url_user.vallen = cl - pos - 1;
                     62:                if (url->url_user.vallen)
                     63:                        ret |= 2;
                     64: 
                     65:                pos = at;
                     66:        }
                     67: 
                     68:        // Host
                     69:        if ((sl = strchr(pos, '/')))
                     70:                *sl++ = 0;
                     71:        else
                     72:                sl = pos + strlen(pos) + 1;
                     73:        // Port
                     74:        if ((cl = strchr(pos, ':'))) {
                     75:                *cl++ = 0;
                     76: 
                     77:                url->url_port.value = cl;
                     78:                url->url_port.vallen = sl - cl - 1;
                     79:                if (url->url_port.vallen)
                     80:                        ret |= 16;
                     81:        } else
                     82:                cl = sl;
                     83: 
                     84:        url->url_host.value = pos;
                     85:        url->url_host.vallen = cl - pos - 1;
                     86:        if (url->url_host.vallen)
                     87:                ret |= 8;
                     88: 
                     89:        pos = sl;
                     90: 
                     91:        // Args
                     92:        if ((at = strchr(pos, '?'))) {
                     93:                *at++ = 0;
                     94: 
                     95:                url->url_args.value = at;
                     96:                url->url_args.vallen = strlen(at);
                     97:                if (url->url_args.vallen)
                     98:                        ret |= 64;
                     99:        } else
                    100:                at = pos + strlen(pos) + 1;
                    101: 
                    102:        // Path
                    103:        url->url_path.value = pos;
                    104:        url->url_path.vallen = at - pos - 1;
                    105:        if (url->url_path.vallen)
                    106:                ret |= 32;
                    107: 
                    108:        pos = at + strlen(at);
                    109: 
                    110:        // Reserved
                    111:        url->url_reserved = pos;
                    112:        if (*pos)
                    113:                ret |= 128;
                    114: 
                    115:        return ret;
                    116: }
                    117: 
                    118: /*
1.3       misho     119:  * io_MakeArray() Parse and make array of arguments values ... 
                    120:  *     (input string will be modified! and output array must be free)
                    121:  * @psArgs = Input arguments line, after execute string is modified!!!
1.2       misho     122:  * @csDelim = Delimiter(s) for separate
                    123:  * @args = Output array of arguments ... (must be free() after procced function!)
1.3       misho     124:  * @nargs = Maximum requested count of arguments from input string psArgs
1.2       misho     125:  * return: 0 error format; -1 error:: can`t read; >0 ok, number of readed items
                    126: */
1.4       misho     127: inline int
                    128: io_MakeArray(char * __restrict psArgs, const char *csDelim, char *** __restrict args, int nargs)
1.2       misho     129: {
                    130:        char **app;
                    131:        register int i;
                    132: 
                    133:        if (!psArgs || !csDelim || !args || !nargs)
                    134:                return -1;
                    135:        if (!(*args = malloc(sizeof(char*) * nargs))) {
                    136:                LOGERR;
                    137:                return -1;
                    138:        } else
                    139:                memset(*args, 0, sizeof(char*) * nargs);
                    140: 
1.5     ! misho     141:        for (i = 0, app = *args; app < *args + nargs && (*app = strsep((char **) &psArgs, csDelim)); 
1.2       misho     142:                                **app ? i++ : i, **app ? app++ : app);
                    143:        return i;
                    144: }
                    145: /*
                    146:  * io_SizeArray() Parse and calculate size of array
                    147:  * @csArgs = Input arguments line
                    148:  * @csDelim = Delimiter(s) for separate
                    149:  * return: 0 error format; -1 error:: can`t read; >0 ok, number of items
                    150: */
1.4       misho     151: inline int
                    152: io_SizeArray(const char *csArgs, const char *csDelim)
1.2       misho     153: {
                    154:        register int res;
                    155:        char *pos;
                    156: 
                    157:        if (!csArgs || !csDelim)
                    158:                return -1;
                    159: 
                    160:        for (res = 1, pos = (char*) csArgs; (pos = strpbrk(pos, csDelim)); res++, pos++);
                    161:        return res;
                    162: }
                    163: /*
                    164:  * io_MakeAV() Parse and make attribute/value pair
                    165:  * @csArgs = Input argument line
                    166:  * @csDelim = Delimiter for separate
                    167:  * @psAttr = Output Attribute
                    168:  * @attrLen = Size of attribute array
                    169:  * @psValue = Output Value, if ==NULL this element not present value or not wanted for return
                    170:  * @valLen = Size of value array
                    171:  * return: 0 error format; -1 error:: can`t read; >0 ok, number of readed items
                    172: */
1.4       misho     173: inline int
                    174: io_MakeAV(const char * __restrict csArgs, const char *csDelim, 
1.2       misho     175:                char * __restrict psAttr, int attrLen, char * __restrict psValue, int valLen)
                    176: {
                    177:        register int ret = 0;
                    178:        char *pos, *psBuf;
                    179: 
                    180:        if (!csArgs || !csDelim || !psAttr || !attrLen)
                    181:                return -1;
                    182:        if (psValue && !valLen)
                    183:                return -1;
                    184:        else
                    185:                memset(psValue, 0, valLen);
                    186:        psBuf = strdup(csArgs);
                    187:        if (!psBuf) {
                    188:                LOGERR;
                    189:                return -1;
                    190:        }
                    191: 
                    192:        pos = strpbrk(psBuf, csDelim);
                    193:        if (pos)
                    194:                *pos++ = 0;
                    195:        ret++;
                    196:        strlcpy(psAttr, psBuf, attrLen);
                    197: 
                    198:        if (pos && *pos) {
                    199:                ret++;
                    200:                if (psValue)
                    201:                        strlcpy(psValue, pos, valLen);
                    202:        }
                    203: 
                    204:        free(psBuf);
                    205:        return ret;
                    206: }
                    207: 
                    208: /*
                    209:  * io_Path2File() Parse and make path/filename pair
                    210:  * @csArgs = Input argument line
                    211:  * @psPath = Output Path, if ==NULL path not returned
                    212:  * @pathLen = Size of path array
                    213:  * @psFile = Output File
                    214:  * @fileLen = Size of file array
                    215:  * return: 0 error format; -1 error:: can`t read; >0 ok, number of readed items
                    216: */
1.4       misho     217: inline int
                    218: io_Path2File(const char * __restrict csArgs, char * __restrict psPath, int pathLen, 
1.2       misho     219:                char * __restrict psFile, int fileLen)
                    220: {
                    221:        char *pos, *psBuf;
                    222: 
                    223:        if (!csArgs || !psFile || !fileLen)
                    224:                return -1;
                    225:        if (psPath && !pathLen)
                    226:                return -1;
                    227:        else
                    228:                memset(psPath, 0, pathLen);
                    229:        psBuf = strdup(csArgs);
                    230:        if (!psBuf) {
                    231:                LOGERR;
                    232:                return -1;
                    233:        }
                    234: 
                    235:        pos = strrchr(psBuf, '/');
                    236:        if (!pos) {
                    237:                strlcpy(psFile, psBuf, fileLen);
                    238: 
                    239:                free(psBuf);
                    240:                return 1;
                    241:        } else
                    242:                *pos++ = 0;
                    243: 
                    244:        strlcpy(psFile, pos, fileLen);
                    245:        if (psPath)
                    246:                strlcpy(psPath, psBuf, pathLen);
                    247: 
                    248:        free(psBuf);
                    249:        return 2;
                    250: }
                    251: 
                    252: /*
                    253:  * ioURLGetValue() Get value from parsed URL
                    254:  * @url = Input parsed URL
                    255:  * @csAttr = Attribute for search
                    256:  * @psValue = Return value of attribute, if ==NULL only check for existence of attribute
                    257:  * @valLen = Size of psValue array
                    258:  * return: 0 error attribute not find; -1 error:: can`t read; >0 ok, find at position
                    259: */
1.4       misho     260: int
                    261: ioURLGetValue(struct tagIOURL *url, const char *csAttr, char * __restrict psValue, int valLen)
1.2       misho     262: {
                    263:        register int i, ret = 0;
                    264:        char szBuf[BUFSIZ], **items, szElem[2][BUFSIZ];
                    265:        int len;
                    266: 
                    267:        if (!url || !csAttr)
                    268:                return -1;
                    269: 
                    270:        strlcpy(szBuf, url->url_args.value, BUFSIZ);
                    271:        if (io_MakeArray(szBuf, "&", &items, (len = io_SizeArray(szBuf, "&"))) < 1)
                    272:                return ret;
                    273: 
                    274:        for (i = 0; i < len && items[i]; i++) {
                    275:                if (io_MakeAV(items[i], "=", szElem[0], BUFSIZ, szElem[1], BUFSIZ) < 1)
                    276:                        continue;
                    277: 
                    278:                if (!strcmp(szElem[0], csAttr)) {
                    279:                        ret = i + 1;
                    280:                        if (psValue && valLen)
                    281:                                strlcpy(psValue, szElem[1], valLen);
                    282:                        break;
                    283:                }
                    284:        }
                    285: 
                    286:        free(items);
                    287:        return ret;
                    288: }
                    289: 
                    290: /*
                    291:  * ioURLGetFile() Get file from parsed URL
                    292:  * @url = Input parsed URL
                    293:  * @psValue = Return filename, if not specified file in url path, replace with /
                    294:  * @valLen = Size of psValue array
                    295:  * return: -1 error:: can`t read; 0 ok
                    296: */
1.4       misho     297: int
                    298: ioURLGetFile(struct tagIOURL *url, char * __restrict psValue, int valLen)
1.2       misho     299: {
                    300:        if (!url || !psValue || !valLen)
                    301:                return -1;
                    302: 
                    303:        if (io_Path2File(url->url_path.value, NULL, 0, psValue, valLen) < 1)
                    304:                return -1;
                    305: 
                    306:        // If not specified file in path, default replace to /
                    307:        if (!*psValue)
                    308:                strlcpy(psValue, "/", valLen);
                    309:        return 0;
                    310: }
1.4       misho     311: 
                    312: // ------------------------------------------
                    313: 
                    314: /*
                    315:  * ioXMLGet() Parse and get data from input XML request string [ns:]container[|attribute[=value]][?data]
                    316:  * @csXML = Input XML request line
                    317:  * @xml = Output parsed XML request
                    318:  * return: 0 error format incorrect, -1 error:: can`t read; >0 ok readed elements bits
                    319: */
                    320: int
                    321: ioXMLGet(const char *csXML, struct tagReqXML *xml)
                    322: {
                    323:        char *pos, *p, *end;
                    324:        int ret = 0;
                    325: 
                    326:        if (!csXML || !xml)
                    327:                return -1;
                    328:        else
                    329:                memset(xml, 0, sizeof *xml);
                    330: 
                    331:        strlcpy((char*) xml->xml_line, csXML, BUFSIZ);
                    332:        // if namespace present
                    333:        if ((pos = strchr((char*) xml->xml_line, ':'))) {
                    334:                xml->xml_namespace.value = (char*) xml->xml_line;
                    335:                xml->xml_namespace.vallen = pos - (char*) xml->xml_line;
                    336:                if (xml->xml_namespace.vallen)
                    337:                        ret |= 1;
                    338:                *pos++ = 0;
                    339:        } else
                    340:                pos = (char*) xml->xml_line;
                    341:        // if container is path
                    342:        if (*pos == '/') {
                    343:                xml->xml_node.path.value = pos;
                    344:                xml->xml_node.path.vallen = strlen(pos);
                    345:                if (!xml->xml_node.path.vallen)
                    346:                        ret = 0;
                    347:                else
                    348:                        ret |= 32;
                    349:                return ret;
                    350:        } else {
                    351:        // container
                    352:                xml->xml_node.container.value = pos;
                    353:                xml->xml_node.container.vallen = strlen(pos);
                    354:                if (!xml->xml_node.container.vallen)
                    355:                        return 0;
                    356:                else
                    357:                        ret |= 2;
                    358:        }
                    359:        end = strchr(pos, '?');
                    360:        // if attribute present
                    361:        if (pos && (p = strchr(pos, '|')) && (!end || end > p)) {
                    362:                pos = p;
                    363:                *pos++ = 0;
                    364:                xml->xml_node.container.vallen = strlen(xml->xml_node.container.value);
                    365:                if (!xml->xml_node.container.vallen)
                    366:                        return 0;
                    367: 
                    368:                xml->xml_attribute.value = pos;
                    369:                xml->xml_attribute.vallen = strlen(pos);
                    370:                if (xml->xml_attribute.vallen)
                    371:                        ret |= 4;
                    372:        }
                    373:        // if value present
                    374:        if (pos && (p = strchr(pos, '=')) && (!end || end > p)) {
                    375:                if (!(ret & 4))
                    376:                        return 0;
                    377:                else
                    378:                        pos = p;
                    379:                *pos++ = 0;
                    380:                xml->xml_attribute.vallen = strlen(xml->xml_attribute.value);
                    381:                if (!xml->xml_attribute.vallen)
                    382:                        return 0;
                    383: 
                    384:                xml->xml_value.value = pos;
                    385:                xml->xml_value.vallen = strlen(pos);
                    386:                if (xml->xml_value.vallen)
                    387:                        ret |= 8;
                    388:        }
                    389:        // if data present
                    390:        if (pos && end) {
                    391:                if (ret < 2)
                    392:                        return 0;
                    393:                else
                    394:                        pos = end;
                    395:                *pos++ = 0;
                    396:                if (ret & 8) {
                    397:                        xml->xml_value.vallen = strlen(xml->xml_value.value);
                    398:                        if (!xml->xml_value.vallen)
                    399:                                return 0;
                    400:                } else if (ret & 4) {
                    401:                        xml->xml_attribute.vallen = strlen(xml->xml_attribute.value);
                    402:                        if (!xml->xml_attribute.vallen)
                    403:                                return 0;
                    404:                } else if (ret & 2) {
                    405:                        xml->xml_node.container.vallen = strlen(xml->xml_node.container.value);
                    406:                        if (!xml->xml_node.container.vallen)
                    407:                                return 0;
                    408:                } else
                    409:                        return 0;
                    410: 
                    411:                xml->xml_data.value = pos;
                    412:                xml->xml_data.vallen = strlen(pos);
                    413:                if (xml->xml_data.vallen)
                    414:                        ret |= 16;
                    415:        }
                    416: 
                    417:        return ret;
                    418: }

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