Annotation of libaitmqtt/src/aitmqtt.c, revision 1.3.4.4

1.1       misho       1: /*************************************************************************
                      2: * (C) 2011 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
                      3: *  by Michael Pounov <misho@openbsd-bg.org>
                      4: *
                      5: * $Author: misho $
1.3.4.4 ! misho       6: * $Id: aitmqtt.c,v 1.3.4.3 2022/09/13 22:20:59 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: 
1.3.4.2   misho      15: Copyright 2004 - 2022
1.1       misho      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: 
                     48: 
                     49: #pragma GCC visibility push(hidden)
                     50: 
                     51: int mqtt_Errno;
                     52: char mqtt_Error[STRSIZ];
                     53: 
                     54: #pragma GCC visibility pop
                     55: 
                     56: // mqtt_GetErrno() Get error code of last operation
1.3       misho      57: int
1.1       misho      58: mqtt_GetErrno()
                     59: {
                     60:        return mqtt_Errno;
                     61: }
                     62: 
                     63: // mqtt_GetError() Get error text of last operation
1.3       misho      64: const char *
1.1       misho      65: mqtt_GetError()
                     66: {
                     67:        return mqtt_Error;
                     68: }
                     69: 
                     70: // mqtt_SetErr() Set error to variables for internal use!!!
1.3       misho      71: void
1.1       misho      72: mqtt_SetErr(int eno, char *estr, ...)
                     73: {
                     74:        va_list lst;
                     75: 
                     76:        mqtt_Errno = eno;
                     77:        memset(mqtt_Error, 0, sizeof mqtt_Error);
                     78:        va_start(lst, estr);
                     79:        vsnprintf(mqtt_Error, sizeof mqtt_Error, estr, lst);
                     80:        va_end(lst);
                     81: }
                     82: 
                     83: 
                     84: /*
                     85:  * mqtt_msgFree() Free MQTT message
                     86:  *
                     87:  * @msg = Message buffer
1.3.4.3   misho      88:  * @keepmsg = !=0 just free message content
1.1       misho      89:  * return: none
                     90:  */
1.3       misho      91: void
1.3.4.3   misho      92: mqtt_msgFree(mqtt_msg_t ** __restrict msg, int keepmsg)
1.1       misho      93: {
                     94:        if (msg && *msg) {
                     95:                if ((*msg)->msg_base) {
1.3.4.4 ! misho      96:                        e_free((*msg)->msg_base);
1.1       misho      97:                        (*msg)->msg_base = NULL;
                     98:                }
1.3.4.3   misho      99:                if (!keepmsg) {
1.3.4.4 ! misho     100:                        e_free(*msg);
1.1       misho     101:                        *msg = NULL;
                    102:                } else
                    103:                        (*msg)->msg_len ^= (*msg)->msg_len;
                    104:        }
                    105: }
                    106: 
                    107: /*
                    108:  * mqtt_msgAlloc() Allocate memory for MQTT Message
                    109:  *
                    110:  * @len = >0 Allocate buffer with length
                    111:  * return: NULL error or Message, after use must call mqtt_msgFree() with all!=0
                    112:  */
1.3       misho     113: mqtt_msg_t *
1.3.4.1   misho     114: mqtt_msgAlloc(u_int len)
1.1       misho     115: {
                    116:        mqtt_msg_t *m = NULL;
                    117: 
1.3.4.4 ! misho     118:        m = e_malloc(sizeof(mqtt_msg_t));
1.1       misho     119:        if (!m) {
                    120:                LOGERR;
                    121:                return NULL;
                    122:        } else
                    123:                memset(m, 0, sizeof(mqtt_msg_t));
                    124: 
                    125:        if (len) {
                    126:                m->msg_len = len;
1.3.4.4 ! misho     127:                m->msg_base = e_malloc(m->msg_len);
1.1       misho     128:                if (!m->msg_base) {
                    129:                        LOGERR;
1.3.4.4 ! misho     130:                        e_free(m);
1.1       misho     131:                        return NULL;
                    132:                } else
                    133:                        memset(m->msg_base, 0, m->msg_len);
                    134:        }
                    135: 
                    136:        return m;
                    137: }
                    138: 
                    139: /*
                    140:  * mqtt_msgRealloc() Reallocate MQTT message buffer
                    141:  *
                    142:  * @msg = MQTT message
                    143:  * @len = new length
                    144:  * return: -1 error or >-1 old buffer length
                    145:  */
1.3       misho     146: int
1.3.4.1   misho     147: mqtt_msgRealloc(mqtt_msg_t * __restrict msg, u_int len)
1.1       misho     148: {
                    149:        void *p = NULL;
                    150:        int ret = 0;
                    151: 
                    152:        if (!msg)
                    153:                return -1;
                    154: 
1.2       misho     155:        if (len <= msg->msg_len)
1.1       misho     156:                return len;
                    157: 
1.3.4.4 ! misho     158:        p = e_realloc(msg->msg_base, len);
1.1       misho     159:        if (!p) {
                    160:                LOGERR;
                    161:                return -1;
                    162:        }
                    163: 
                    164:        ret = msg->msg_len;
                    165:        msg->msg_len = len;
                    166:        msg->msg_base = p;
                    167: 
                    168:        return ret;
                    169: }
                    170: 
                    171: /*
1.2       misho     172:  * mqtt_msgDup() - Duplicate message buffer
                    173:  *
                    174:  * @msg = Message
                    175:  * return: NULL error or !=NULL duplicated message, after use must call mqtt_msgFree() with all!=0
                    176:  */
1.3       misho     177: mqtt_msg_t *
1.2       misho     178: mqtt_msgDup(mqtt_msg_t * __restrict msg)
                    179: {
                    180:        mqtt_msg_t *m = NULL;
                    181: 
1.3.4.4 ! misho     182:        m = e_malloc(sizeof(mqtt_msg_t));
1.2       misho     183:        if (!m) {
                    184:                LOGERR;
                    185:                return NULL;
                    186:        } else
                    187:                memset(m, 0, sizeof(mqtt_msg_t));
                    188: 
                    189:        if (msg->msg_len) {
                    190:                m->msg_len = msg->msg_len;
1.3.4.4 ! misho     191:                m->msg_base = e_malloc(m->msg_len);
1.2       misho     192:                if (!m->msg_base) {
                    193:                        LOGERR;
1.3.4.4 ! misho     194:                        e_free(m);
1.2       misho     195:                        return NULL;
                    196:                } else
                    197:                        memcpy(m->msg_base, msg->msg_base, m->msg_len);
                    198:        }
                    199: 
                    200:        return m;
                    201: }
                    202: 
                    203: /*
1.1       misho     204:  * mqtt_encodeLen() Encode number to MQTT length field
                    205:  *
                    206:  * @num = number for encode
                    207:  * return: -1 error or >-1 length
                    208:  */
1.3       misho     209: u_int
1.1       misho     210: mqtt_encodeLen(u_int num)
                    211: {
                    212:        register u_int dig, i;
                    213:        u_int ret = 0;
                    214: 
1.3.4.1   misho     215:        if (num > MQTT_DATA_MAX)
1.1       misho     216:                return (u_int) -1;
                    217: 
                    218:        for (i = 0; i < sizeof ret && num > 0; i++) {
                    219:                dig = num % 0x80;
                    220:                num /= 0x80;
                    221:                if (num > 0)
                    222:                        dig |= 0x80;
                    223: 
                    224:                *((u_char*) &ret + i) = (u_char) dig;
                    225:        }
                    226: 
                    227:        return ret;
                    228: }
                    229: 
                    230: /*
                    231:  * mqtt_decodeLen() Decode length from MQTT packet
                    232:  *
                    233:  * @len = length from MQTT header
                    234:  * @n = sizeof bytes, if !=NULL
                    235:  * return: -1 error, >-1 length of message
                    236:  */
1.3       misho     237: u_int
1.1       misho     238: mqtt_decodeLen(void * __restrict len, int * __restrict n)
                    239: {
                    240:        register u_int i, dig, mul;
                    241:        u_int ret = 0;
                    242:        u_char *p = (u_char*) len;
                    243: 
                    244:        if (!len)
                    245:                return (u_int) -1;
                    246: 
                    247:        for (mul = 1, i = 0; i < sizeof ret; i++, mul *= 0x80) {
                    248:                dig = p[i];
                    249:                ret += (dig & 0x7f) * mul;
                    250: 
                    251:                if (!(dig & 0x80))
                    252:                        break;
                    253:        }
                    254: 
                    255:        if (n)
                    256:                *n = (char) (i & 0x7f) + 1;
1.3.4.1   misho     257: 
1.1       misho     258:        return ret;
                    259: }
                    260: 
                    261: /*
                    262:  * mqtt_sizeLen Return sizeof len field
                    263:  *
                    264:  * @len = length
                    265:  * return: -1 error, >-1 sizeof len in bytes
                    266:  */
1.3       misho     267: char
1.1       misho     268: mqtt_sizeLen(u_int len)
                    269: {
                    270:        register char i;
                    271:        u_char *p = (u_char*) &len;
                    272: 
                    273:        if (len > 0xffffff7f)
                    274:                return -1;
                    275: 
                    276:        for (i = 0; i < sizeof len; i++)
                    277:                if (!(*(p + i) & 0x80))
                    278:                        break;
                    279: 
                    280:        return ++i;
                    281: }
                    282: 
                    283: /*
1.2       misho     284:  * mqtt_pktLen() - Get total packet length
                    285:  *
                    286:  * @hdr = MQTT packet header
                    287:  * return: packet length
                    288:  */
1.3       misho     289: u_int
1.2       misho     290: mqtt_pktLen(struct mqtthdr * __restrict hdr)
                    291: {
                    292:        int siz, n = 0;
                    293: 
                    294:        if (!hdr)
                    295:                return 0;
                    296: 
                    297:        siz = mqtt_decodeLen(hdr->mqtt_len, &n);
                    298:        siz += sizeof(struct mqtthdr) + n - 1;
                    299: 
                    300:        return siz;
                    301: }
                    302: 
                    303: /*
                    304:  * mqtt_str2subs Create MQTT subscribe variable from string(s)
1.1       misho     305:  *
1.2       misho     306:  * @csStr = null terminated string array
1.3.4.1   misho     307:  * @strnum = copy at most number of strings elements, ==0 till NULL element
1.1       misho     308:  * @qoses = QoS elements applied to subscribe variable, 
                    309:  *             count of elements must be equal with csStr elements
                    310:  * return: NULL error or != subscribe variables array, must be free after use with mqtt_freeSub()
                    311:  */
1.3       misho     312: mqtt_subscr_t *
1.3.4.1   misho     313: mqtt_strs2subs(const char **csStr, u_short strnum, u_char *qoses)
1.1       misho     314: {
                    315:        mqtt_subscr_t *v;
                    316:        register int i, items;
                    317:        const char **strs;
                    318: 
                    319:        if (!csStr)
                    320:                return NULL;
1.2       misho     321: 
                    322:        for (items = 0, strs = csStr; 
                    323:                        (!strnum || (strnum && items < strnum)) && *strs; 
                    324:                        items++, strs++);
1.1       misho     325: 
1.3.4.4 ! misho     326:        if (!(v = e_malloc((items + 1) * sizeof(mqtt_subscr_t)))) {
1.1       misho     327:                LOGERR;
                    328:                return NULL;
                    329:        } else
                    330:                memset(v, 0, (items + 1) * sizeof(mqtt_subscr_t));
                    331: 
                    332:        for (i = 0; i < items; i++) {
                    333:                v[i].sub_topic.msg_len = strlen(csStr[i]);
1.3.4.4 ! misho     334:                v[i].sub_topic.msg_base = (u_char*) e_strdup(csStr[i]);
1.1       misho     335:                if (qoses && qoses[i] < MQTT_QOS_RESERVED)
                    336:                        v[i].sub_ret = qoses[i];
                    337:        }
                    338: 
                    339:        return v;
                    340: }
                    341: 
                    342: /*
                    343:  * mqtt_subFree() Free array from subscribe variables
                    344:  *
                    345:  * @subs = Subscribe variables
                    346:  * return: none
                    347:  */
1.3       misho     348: void
1.1       misho     349: mqtt_subFree(mqtt_subscr_t ** __restrict subs)
                    350: {
                    351:        mqtt_subscr_t *v;
                    352: 
                    353:        if (!subs)
                    354:                return;
                    355: 
                    356:        for (v = *subs; v->sub_topic.msg_base; v++) {
1.3.4.4 ! misho     357:                e_free(v->sub_topic.msg_base);
1.1       misho     358:                v->sub_topic.msg_base = NULL;
                    359:                v->sub_topic.msg_len = 0;
                    360: 
                    361:                if (v->sub_value.msg_base) {
1.3.4.4 ! misho     362:                        e_free(v->sub_value.msg_base);
1.1       misho     363:                        v->sub_value.msg_base = NULL;
                    364:                        v->sub_value.msg_len = 0;
                    365:                }
                    366:        }
                    367: 
1.3.4.4 ! misho     368:        e_free(*subs);
1.1       misho     369:        *subs = NULL;
                    370: }
                    371: 
                    372: /*
                    373:  * mqtt_subAlloc() Create array from subscribe variables
                    374:  *
                    375:  * @num = Number of elements
                    376:  * return: NULL error or subscribe array, after use must call mqtt_subFree()
                    377:  */
1.3       misho     378: mqtt_subscr_t *
1.1       misho     379: mqtt_subAlloc(u_short num)
                    380: {
                    381:        mqtt_subscr_t *s = NULL;
                    382: 
1.3.4.4 ! misho     383:        s = e_malloc((num + 1) * sizeof(mqtt_subscr_t));
1.1       misho     384:        if (!s) {
                    385:                LOGERR;
                    386:                return NULL;
                    387:        } else
                    388:                memset(s, 0, (num + 1) * sizeof(mqtt_subscr_t));
                    389: 
                    390:        return s;
                    391: }
                    392: 
                    393: /*
                    394:  * mqtt_subRealloc() Reallocate array from subscribe variables
                    395:  *
                    396:  * @subs = Subscribe array
                    397:  * @num = Number of elements
                    398:  * return: NULL error or subscribe array, after use must call mqtt_subFree()
                    399:  */
1.3       misho     400: mqtt_subscr_t *
1.2       misho     401: mqtt_subRealloc(mqtt_subscr_t ** __restrict subs, u_short num)
1.1       misho     402: {
1.3.4.2   misho     403:        mqtt_subscr_t *ss, *s = NULL;
1.3.4.1   misho     404:        register int i;
1.1       misho     405: 
1.2       misho     406:        if (!subs)
                    407:                return NULL;
                    408: 
1.3.4.2   misho     409:        for (i = 0, ss = *subs; ss; i++, ss++);
1.3.4.1   misho     410:        if (i < num)
                    411:                return NULL;
                    412:        if (i == num)
                    413:                return *subs;
                    414: 
1.3.4.4 ! misho     415:        s = e_realloc(*subs, (num + 1) * sizeof(mqtt_subscr_t));
1.1       misho     416:        if (!s) {
                    417:                LOGERR;
                    418:                return NULL;
1.2       misho     419:        } else {
                    420:                memset(s + num, 0, sizeof(mqtt_subscr_t));
                    421:                *subs = s;
                    422:        }
                    423: 
                    424:        return *subs;
                    425: }
                    426: 
                    427: /*
                    428:  * mqtt_subCopy() - Copy subscription structure to another one
                    429:  *
                    430:  * @dst = destination subscription
                    431:  * @src = source subscription
                    432:  * return: =NULL error or !=NULL successful copied a structure
                    433:  */
1.3       misho     434: mqtt_subscr_t *
1.2       misho     435: mqtt_subCopy(mqtt_subscr_t * __restrict dst, mqtt_subscr_t * __restrict src)
                    436: {
                    437:        if (!dst || !src)
                    438:                return NULL;
                    439: 
                    440:        if (src->sub_topic.msg_base) {
1.3.4.4 ! misho     441:                dst->sub_topic.msg_base = e_malloc(src->sub_topic.msg_len + 1);
1.2       misho     442:                if (!dst->sub_topic.msg_base) {
                    443:                        LOGERR;
                    444:                        memset(dst, 0, sizeof(mqtt_subscr_t));
                    445:                        return NULL;
                    446:                } else {
                    447:                        dst->sub_topic.msg_len = src->sub_topic.msg_len;
                    448:                        ((char*) dst->sub_topic.msg_base)[dst->sub_topic.msg_len] = 0;
                    449:                        memcpy(dst->sub_topic.msg_base, src->sub_topic.msg_base, 
                    450:                                        dst->sub_topic.msg_len);
                    451:                }
                    452:        } else {
                    453:                dst->sub_topic.msg_base = NULL;
                    454:                dst->sub_topic.msg_len = 0;
                    455:        }
1.3.4.1   misho     456: 
1.2       misho     457:        if (src->sub_value.msg_base) {
1.3.4.4 ! misho     458:                dst->sub_value.msg_base = e_malloc(src->sub_value.msg_len + 1);
1.2       misho     459:                if (!dst->sub_value.msg_base) {
                    460:                        LOGERR;
                    461:                        if (dst->sub_topic.msg_base)
1.3.4.4 ! misho     462:                                e_free(dst->sub_topic.msg_base);
1.2       misho     463:                        memset(dst, 0, sizeof(mqtt_subscr_t));
                    464:                        return NULL;
                    465:                } else {
                    466:                        dst->sub_value.msg_len = src->sub_value.msg_len;
                    467:                        ((char*) dst->sub_value.msg_base)[dst->sub_value.msg_len] = 0;
                    468:                        memcpy(dst->sub_value.msg_base, src->sub_value.msg_base, 
                    469:                                        dst->sub_value.msg_len);
                    470:                }
                    471:        } else {
                    472:                dst->sub_value.msg_base = NULL;
                    473:                dst->sub_value.msg_len = 0;
                    474:        }
                    475: 
                    476:        dst->sub_ret = src->sub_ret;
                    477:        return dst;
                    478: }
                    479: 
                    480: 
                    481: /*
                    482:  * mqtt_expandTopic() - Expanding topic to regular expression
                    483:  *
                    484:  * @csInput = Input topic
                    485:  * @psRegEx = Output to regular expression
                    486:  * @regexLen = Length of psRegEx
                    487:  * @BOL = Begin of Line, if =0 not added
                    488:  * @EOL = End of Line, if =0 not appended
                    489:  * return: -1 error, 0 nothing expanded or >0 expanded bytes
                    490:  */
                    491: int
                    492: mqtt_expandTopic(const char *csInput, char * __restrict psRegEx, int regexLen, u_char BOL, u_char EOL)
                    493: {
                    494:        int ret = 0;
                    495:        register int i;
                    496:        char *pos, *s;
                    497:        const char reROM[] = "[](){}^$\\-|?.+*";
                    498: 
                    499:        if (!csInput || !psRegEx || regexLen < 1)
                    500:                return -1;
                    501:        else
                    502:                memset(psRegEx, 0, regexLen);
                    503: 
                    504:        /* check # */
                    505:        for (i = 0, pos = (char*) csInput; *pos && i < 2; pos++)
                    506:                if (*pos == '#')
                    507:                        i++;
                    508:        if (i == 2) {
                    509:                mqtt_SetErr(EINVAL, "Syntax error, multiple occurrences of #..#");
                    510:                return -1;
                    511:        }
                    512:        if (i == 1 && (pos = strrchr(csInput, '#')))
                    513:                if ((pos != csInput && *(pos - 1) != '/') || *(pos + 1)) {
                    514:                        mqtt_SetErr(EINVAL, "Syntax error, bad format of #");
                    515:                        return -1;
                    516:                }
                    517:        /* check + */
                    518:        for (pos = (char*) csInput; *pos && (pos = strchr(pos, '+')); pos++)
                    519:                if ((pos != csInput && *(pos - 1) != '/') || (*(pos + 1) && *(pos + 1) != '/')) {
                    520:                        mqtt_SetErr(EINVAL, "Syntax error, bad format of +");
                    521:                        return -1;
                    522:                }
                    523: 
                    524:        /* BUILD REGEX */
                    525:        s = psRegEx;
                    526:        if (BOL) {
                    527:                *s++ = '^';
                    528:                ret++;
                    529:        }
                    530:        for (pos = (char*) csInput; s < psRegEx + regexLen && *pos; s++, pos++) {
                    531:                if (*pos == '#') {
                    532:                        strlcat(s, ".*", regexLen - (s - psRegEx));
                    533:                        s++;
                    534:                        ret++;
                    535:                        break;
                    536:                }
                    537:                if (*pos == '+') {
                    538:                        if (*(pos + 1)) {
                    539:                                strlcat(s, ".*", regexLen - (s - psRegEx));
                    540:                                s++;
                    541:                                ret++;
                    542:                                continue;
                    543:                        } else {
                    544:                                strlcat(s, ".*/", regexLen - (s - psRegEx));
                    545:                                ret += 2;
                    546:                                break;
                    547:                        }
                    548:                }
                    549:                for (i = 0; i < sizeof reROM - 1; i++)
                    550:                        if (*pos == reROM[i] && regexLen - (s - psRegEx) - 1 > 0) {
                    551:                                *s++ = '\\';
                    552:                                ret++;
                    553:                                break;
                    554:                        }
                    555: 
                    556:                *s = *pos;
1.1       misho     557:        }
1.2       misho     558:        if (EOL) {
                    559:                strlcat(psRegEx, "$", regexLen);
                    560:                ret++;
                    561:        }
                    562: 
                    563:        return ret;
                    564: }
                    565: 
                    566: /*
                    567:  * mqtt_sqlTopic() - Expanding topic to SQL search string
                    568:  *
                    569:  * @csInput = Input topic
                    570:  * @psSQL = Output to SQL search string
                    571:  * @sqlLen = Length of psSQL
                    572:  * return: -1 error, 0 changed bytes
                    573:  */
                    574: int
                    575: mqtt_sqlTopic(const char *csInput, char * __restrict psSQL, int sqlLen)
                    576: {
                    577:        int ret = 0;
                    578:        register int i;
                    579:        char *pos, *s;
                    580: 
                    581:        if (!csInput || !psSQL || sqlLen < 1)
                    582:                return -1;
                    583:        else
                    584:                memset(psSQL, 0, sqlLen);
1.1       misho     585: 
1.2       misho     586:        /* check # */
                    587:        for (i = 0, pos = (char*) csInput; *pos && i < 2; pos++)
                    588:                if (*pos == '#')
                    589:                        i++;
                    590:        if (i == 2) {
                    591:                mqtt_SetErr(EINVAL, "Syntax error, multiple occurrences of #..#");
                    592:                return -1;
                    593:        }
                    594:        if (i == 1 && (pos = strrchr(csInput, '#')))
                    595:                if ((pos != csInput && *(pos - 1) != '/') || *(pos + 1)) {
                    596:                        mqtt_SetErr(EINVAL, "Syntax error, bad format of #");
                    597:                        return -1;
                    598:                }
                    599:        /* check + */
                    600:        for (pos = (char*) csInput; *pos && (pos = strchr(pos, '+')); pos++)
                    601:                if ((pos != csInput && *(pos - 1) != '/') || (*(pos + 1) && *(pos + 1) != '/')) {
                    602:                        mqtt_SetErr(EINVAL, "Syntax error, bad format of +");
                    603:                        return -1;
                    604:                }
                    605: 
                    606:        /* BUILD SEARCH STRING */
                    607:        s = psSQL;
                    608:        for (pos = (char*) csInput; s < psSQL + sqlLen && *pos; s++, pos++) {
                    609:                if (*pos == '#') {
                    610:                        *s = '%';
                    611:                        s++;
                    612:                        ret++;
                    613:                        break;
                    614:                }
                    615:                if (*pos == '+') {
                    616:                        if (*(pos + 1)) {
                    617:                                *s = '%';
                    618:                                ret++;
                    619:                                continue;
                    620:                        } else {
                    621:                                strlcat(s, "%/", sqlLen - (s - psSQL));
                    622:                                ret += 2;
                    623:                                break;
                    624:                        }
                    625:                }
                    626:                /*
                    627:                for (i = 0; i < sizeof reROM - 1; i++)
                    628:                        if (*pos == reROM[i] && regexLen - (s - psRegEx) - 1 > 0) {
                    629:                                *s++ = '\\';
                    630:                                ret++;
                    631:                                break;
                    632:                        }
                    633:                        */
                    634: 
                    635:                *s = *pos;
                    636:        }
                    637: 
                    638:        return ret;
1.1       misho     639: }

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