Annotation of embedaddon/nginx/src/core/ngx_string.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (C) Igor Sysoev
                      4:  * Copyright (C) Nginx, Inc.
                      5:  */
                      6: 
                      7: 
                      8: #include <ngx_config.h>
                      9: #include <ngx_core.h>
                     10: 
                     11: 
                     12: static u_char *ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64,
                     13:     u_char zero, ngx_uint_t hexadecimal, ngx_uint_t width);
                     14: static ngx_int_t ngx_decode_base64_internal(ngx_str_t *dst, ngx_str_t *src,
                     15:     const u_char *basis);
                     16: 
                     17: 
                     18: void
                     19: ngx_strlow(u_char *dst, u_char *src, size_t n)
                     20: {
                     21:     while (n) {
                     22:         *dst = ngx_tolower(*src);
                     23:         dst++;
                     24:         src++;
                     25:         n--;
                     26:     }
                     27: }
                     28: 
                     29: 
                     30: u_char *
                     31: ngx_cpystrn(u_char *dst, u_char *src, size_t n)
                     32: {
                     33:     if (n == 0) {
                     34:         return dst;
                     35:     }
                     36: 
                     37:     while (--n) {
                     38:         *dst = *src;
                     39: 
                     40:         if (*dst == '\0') {
                     41:             return dst;
                     42:         }
                     43: 
                     44:         dst++;
                     45:         src++;
                     46:     }
                     47: 
                     48:     *dst = '\0';
                     49: 
                     50:     return dst;
                     51: }
                     52: 
                     53: 
                     54: u_char *
                     55: ngx_pstrdup(ngx_pool_t *pool, ngx_str_t *src)
                     56: {
                     57:     u_char  *dst;
                     58: 
                     59:     dst = ngx_pnalloc(pool, src->len);
                     60:     if (dst == NULL) {
                     61:         return NULL;
                     62:     }
                     63: 
                     64:     ngx_memcpy(dst, src->data, src->len);
                     65: 
                     66:     return dst;
                     67: }
                     68: 
                     69: 
                     70: /*
                     71:  * supported formats:
                     72:  *    %[0][width][x][X]O        off_t
                     73:  *    %[0][width]T              time_t
                     74:  *    %[0][width][u][x|X]z      ssize_t/size_t
                     75:  *    %[0][width][u][x|X]d      int/u_int
                     76:  *    %[0][width][u][x|X]l      long
                     77:  *    %[0][width|m][u][x|X]i    ngx_int_t/ngx_uint_t
                     78:  *    %[0][width][u][x|X]D      int32_t/uint32_t
                     79:  *    %[0][width][u][x|X]L      int64_t/uint64_t
                     80:  *    %[0][width|m][u][x|X]A    ngx_atomic_int_t/ngx_atomic_uint_t
                     81:  *    %[0][width][.width]f      double, max valid number fits to %18.15f
                     82:  *    %P                        ngx_pid_t
                     83:  *    %M                        ngx_msec_t
                     84:  *    %r                        rlim_t
                     85:  *    %p                        void *
                     86:  *    %V                        ngx_str_t *
                     87:  *    %v                        ngx_variable_value_t *
                     88:  *    %s                        null-terminated string
                     89:  *    %*s                       length and string
                     90:  *    %Z                        '\0'
                     91:  *    %N                        '\n'
                     92:  *    %c                        char
                     93:  *    %%                        %
                     94:  *
                     95:  *  reserved:
                     96:  *    %t                        ptrdiff_t
                     97:  *    %S                        null-terminated wchar string
                     98:  *    %C                        wchar
                     99:  */
                    100: 
                    101: 
                    102: u_char * ngx_cdecl
                    103: ngx_sprintf(u_char *buf, const char *fmt, ...)
                    104: {
                    105:     u_char   *p;
                    106:     va_list   args;
                    107: 
                    108:     va_start(args, fmt);
                    109:     p = ngx_vslprintf(buf, (void *) -1, fmt, args);
                    110:     va_end(args);
                    111: 
                    112:     return p;
                    113: }
                    114: 
                    115: 
                    116: u_char * ngx_cdecl
                    117: ngx_snprintf(u_char *buf, size_t max, const char *fmt, ...)
                    118: {
                    119:     u_char   *p;
                    120:     va_list   args;
                    121: 
                    122:     va_start(args, fmt);
                    123:     p = ngx_vslprintf(buf, buf + max, fmt, args);
                    124:     va_end(args);
                    125: 
                    126:     return p;
                    127: }
                    128: 
                    129: 
                    130: u_char * ngx_cdecl
                    131: ngx_slprintf(u_char *buf, u_char *last, const char *fmt, ...)
                    132: {
                    133:     u_char   *p;
                    134:     va_list   args;
                    135: 
                    136:     va_start(args, fmt);
                    137:     p = ngx_vslprintf(buf, last, fmt, args);
                    138:     va_end(args);
                    139: 
                    140:     return p;
                    141: }
                    142: 
                    143: 
                    144: u_char *
                    145: ngx_vslprintf(u_char *buf, u_char *last, const char *fmt, va_list args)
                    146: {
                    147:     u_char                *p, zero;
                    148:     int                    d;
                    149:     double                 f;
                    150:     size_t                 len, slen;
                    151:     int64_t                i64;
                    152:     uint64_t               ui64, frac;
                    153:     ngx_msec_t             ms;
                    154:     ngx_uint_t             width, sign, hex, max_width, frac_width, scale, n;
                    155:     ngx_str_t             *v;
                    156:     ngx_variable_value_t  *vv;
                    157: 
                    158:     while (*fmt && buf < last) {
                    159: 
                    160:         /*
                    161:          * "buf < last" means that we could copy at least one character:
                    162:          * the plain character, "%%", "%c", and minus without the checking
                    163:          */
                    164: 
                    165:         if (*fmt == '%') {
                    166: 
                    167:             i64 = 0;
                    168:             ui64 = 0;
                    169: 
                    170:             zero = (u_char) ((*++fmt == '0') ? '0' : ' ');
                    171:             width = 0;
                    172:             sign = 1;
                    173:             hex = 0;
                    174:             max_width = 0;
                    175:             frac_width = 0;
                    176:             slen = (size_t) -1;
                    177: 
                    178:             while (*fmt >= '0' && *fmt <= '9') {
                    179:                 width = width * 10 + *fmt++ - '0';
                    180:             }
                    181: 
                    182: 
                    183:             for ( ;; ) {
                    184:                 switch (*fmt) {
                    185: 
                    186:                 case 'u':
                    187:                     sign = 0;
                    188:                     fmt++;
                    189:                     continue;
                    190: 
                    191:                 case 'm':
                    192:                     max_width = 1;
                    193:                     fmt++;
                    194:                     continue;
                    195: 
                    196:                 case 'X':
                    197:                     hex = 2;
                    198:                     sign = 0;
                    199:                     fmt++;
                    200:                     continue;
                    201: 
                    202:                 case 'x':
                    203:                     hex = 1;
                    204:                     sign = 0;
                    205:                     fmt++;
                    206:                     continue;
                    207: 
                    208:                 case '.':
                    209:                     fmt++;
                    210: 
                    211:                     while (*fmt >= '0' && *fmt <= '9') {
                    212:                         frac_width = frac_width * 10 + *fmt++ - '0';
                    213:                     }
                    214: 
                    215:                     break;
                    216: 
                    217:                 case '*':
                    218:                     slen = va_arg(args, size_t);
                    219:                     fmt++;
                    220:                     continue;
                    221: 
                    222:                 default:
                    223:                     break;
                    224:                 }
                    225: 
                    226:                 break;
                    227:             }
                    228: 
                    229: 
                    230:             switch (*fmt) {
                    231: 
                    232:             case 'V':
                    233:                 v = va_arg(args, ngx_str_t *);
                    234: 
                    235:                 len = ngx_min(((size_t) (last - buf)), v->len);
                    236:                 buf = ngx_cpymem(buf, v->data, len);
                    237:                 fmt++;
                    238: 
                    239:                 continue;
                    240: 
                    241:             case 'v':
                    242:                 vv = va_arg(args, ngx_variable_value_t *);
                    243: 
                    244:                 len = ngx_min(((size_t) (last - buf)), vv->len);
                    245:                 buf = ngx_cpymem(buf, vv->data, len);
                    246:                 fmt++;
                    247: 
                    248:                 continue;
                    249: 
                    250:             case 's':
                    251:                 p = va_arg(args, u_char *);
                    252: 
                    253:                 if (slen == (size_t) -1) {
                    254:                     while (*p && buf < last) {
                    255:                         *buf++ = *p++;
                    256:                     }
                    257: 
                    258:                 } else {
                    259:                     len = ngx_min(((size_t) (last - buf)), slen);
                    260:                     buf = ngx_cpymem(buf, p, len);
                    261:                 }
                    262: 
                    263:                 fmt++;
                    264: 
                    265:                 continue;
                    266: 
                    267:             case 'O':
                    268:                 i64 = (int64_t) va_arg(args, off_t);
                    269:                 sign = 1;
                    270:                 break;
                    271: 
                    272:             case 'P':
                    273:                 i64 = (int64_t) va_arg(args, ngx_pid_t);
                    274:                 sign = 1;
                    275:                 break;
                    276: 
                    277:             case 'T':
                    278:                 i64 = (int64_t) va_arg(args, time_t);
                    279:                 sign = 1;
                    280:                 break;
                    281: 
                    282:             case 'M':
                    283:                 ms = (ngx_msec_t) va_arg(args, ngx_msec_t);
                    284:                 if ((ngx_msec_int_t) ms == -1) {
                    285:                     sign = 1;
                    286:                     i64 = -1;
                    287:                 } else {
                    288:                     sign = 0;
                    289:                     ui64 = (uint64_t) ms;
                    290:                 }
                    291:                 break;
                    292: 
                    293:             case 'z':
                    294:                 if (sign) {
                    295:                     i64 = (int64_t) va_arg(args, ssize_t);
                    296:                 } else {
                    297:                     ui64 = (uint64_t) va_arg(args, size_t);
                    298:                 }
                    299:                 break;
                    300: 
                    301:             case 'i':
                    302:                 if (sign) {
                    303:                     i64 = (int64_t) va_arg(args, ngx_int_t);
                    304:                 } else {
                    305:                     ui64 = (uint64_t) va_arg(args, ngx_uint_t);
                    306:                 }
                    307: 
                    308:                 if (max_width) {
                    309:                     width = NGX_INT_T_LEN;
                    310:                 }
                    311: 
                    312:                 break;
                    313: 
                    314:             case 'd':
                    315:                 if (sign) {
                    316:                     i64 = (int64_t) va_arg(args, int);
                    317:                 } else {
                    318:                     ui64 = (uint64_t) va_arg(args, u_int);
                    319:                 }
                    320:                 break;
                    321: 
                    322:             case 'l':
                    323:                 if (sign) {
                    324:                     i64 = (int64_t) va_arg(args, long);
                    325:                 } else {
                    326:                     ui64 = (uint64_t) va_arg(args, u_long);
                    327:                 }
                    328:                 break;
                    329: 
                    330:             case 'D':
                    331:                 if (sign) {
                    332:                     i64 = (int64_t) va_arg(args, int32_t);
                    333:                 } else {
                    334:                     ui64 = (uint64_t) va_arg(args, uint32_t);
                    335:                 }
                    336:                 break;
                    337: 
                    338:             case 'L':
                    339:                 if (sign) {
                    340:                     i64 = va_arg(args, int64_t);
                    341:                 } else {
                    342:                     ui64 = va_arg(args, uint64_t);
                    343:                 }
                    344:                 break;
                    345: 
                    346:             case 'A':
                    347:                 if (sign) {
                    348:                     i64 = (int64_t) va_arg(args, ngx_atomic_int_t);
                    349:                 } else {
                    350:                     ui64 = (uint64_t) va_arg(args, ngx_atomic_uint_t);
                    351:                 }
                    352: 
                    353:                 if (max_width) {
                    354:                     width = NGX_ATOMIC_T_LEN;
                    355:                 }
                    356: 
                    357:                 break;
                    358: 
                    359:             case 'f':
                    360:                 f = va_arg(args, double);
                    361: 
                    362:                 if (f < 0) {
                    363:                     *buf++ = '-';
                    364:                     f = -f;
                    365:                 }
                    366: 
                    367:                 ui64 = (int64_t) f;
                    368:                 frac = 0;
                    369: 
                    370:                 if (frac_width) {
                    371: 
                    372:                     scale = 1;
                    373:                     for (n = frac_width; n; n--) {
                    374:                         scale *= 10;
                    375:                     }
                    376: 
                    377:                     frac = (uint64_t) ((f - (double) ui64) * scale + 0.5);
                    378: 
                    379:                     if (frac == scale) {
                    380:                         ui64++;
                    381:                         frac = 0;
                    382:                     }
                    383:                 }
                    384: 
                    385:                 buf = ngx_sprintf_num(buf, last, ui64, zero, 0, width);
                    386: 
                    387:                 if (frac_width) {
                    388:                     if (buf < last) {
                    389:                         *buf++ = '.';
                    390:                     }
                    391: 
                    392:                     buf = ngx_sprintf_num(buf, last, frac, '0', 0, frac_width);
                    393:                 }
                    394: 
                    395:                 fmt++;
                    396: 
                    397:                 continue;
                    398: 
                    399: #if !(NGX_WIN32)
                    400:             case 'r':
                    401:                 i64 = (int64_t) va_arg(args, rlim_t);
                    402:                 sign = 1;
                    403:                 break;
                    404: #endif
                    405: 
                    406:             case 'p':
                    407:                 ui64 = (uintptr_t) va_arg(args, void *);
                    408:                 hex = 2;
                    409:                 sign = 0;
                    410:                 zero = '0';
                    411:                 width = NGX_PTR_SIZE * 2;
                    412:                 break;
                    413: 
                    414:             case 'c':
                    415:                 d = va_arg(args, int);
                    416:                 *buf++ = (u_char) (d & 0xff);
                    417:                 fmt++;
                    418: 
                    419:                 continue;
                    420: 
                    421:             case 'Z':
                    422:                 *buf++ = '\0';
                    423:                 fmt++;
                    424: 
                    425:                 continue;
                    426: 
                    427:             case 'N':
                    428: #if (NGX_WIN32)
                    429:                 *buf++ = CR;
                    430: #endif
                    431:                 *buf++ = LF;
                    432:                 fmt++;
                    433: 
                    434:                 continue;
                    435: 
                    436:             case '%':
                    437:                 *buf++ = '%';
                    438:                 fmt++;
                    439: 
                    440:                 continue;
                    441: 
                    442:             default:
                    443:                 *buf++ = *fmt++;
                    444: 
                    445:                 continue;
                    446:             }
                    447: 
                    448:             if (sign) {
                    449:                 if (i64 < 0) {
                    450:                     *buf++ = '-';
                    451:                     ui64 = (uint64_t) -i64;
                    452: 
                    453:                 } else {
                    454:                     ui64 = (uint64_t) i64;
                    455:                 }
                    456:             }
                    457: 
                    458:             buf = ngx_sprintf_num(buf, last, ui64, zero, hex, width);
                    459: 
                    460:             fmt++;
                    461: 
                    462:         } else {
                    463:             *buf++ = *fmt++;
                    464:         }
                    465:     }
                    466: 
                    467:     return buf;
                    468: }
                    469: 
                    470: 
                    471: static u_char *
                    472: ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64, u_char zero,
                    473:     ngx_uint_t hexadecimal, ngx_uint_t width)
                    474: {
                    475:     u_char         *p, temp[NGX_INT64_LEN + 1];
                    476:                        /*
                    477:                         * we need temp[NGX_INT64_LEN] only,
                    478:                         * but icc issues the warning
                    479:                         */
                    480:     size_t          len;
                    481:     uint32_t        ui32;
                    482:     static u_char   hex[] = "0123456789abcdef";
                    483:     static u_char   HEX[] = "0123456789ABCDEF";
                    484: 
                    485:     p = temp + NGX_INT64_LEN;
                    486: 
                    487:     if (hexadecimal == 0) {
                    488: 
                    489:         if (ui64 <= NGX_MAX_UINT32_VALUE) {
                    490: 
                    491:             /*
                    492:              * To divide 64-bit numbers and to find remainders
                    493:              * on the x86 platform gcc and icc call the libc functions
                    494:              * [u]divdi3() and [u]moddi3(), they call another function
                    495:              * in its turn.  On FreeBSD it is the qdivrem() function,
                    496:              * its source code is about 170 lines of the code.
                    497:              * The glibc counterpart is about 150 lines of the code.
                    498:              *
                    499:              * For 32-bit numbers and some divisors gcc and icc use
                    500:              * a inlined multiplication and shifts.  For example,
                    501:              * unsigned "i32 / 10" is compiled to
                    502:              *
                    503:              *     (i32 * 0xCCCCCCCD) >> 35
                    504:              */
                    505: 
                    506:             ui32 = (uint32_t) ui64;
                    507: 
                    508:             do {
                    509:                 *--p = (u_char) (ui32 % 10 + '0');
                    510:             } while (ui32 /= 10);
                    511: 
                    512:         } else {
                    513:             do {
                    514:                 *--p = (u_char) (ui64 % 10 + '0');
                    515:             } while (ui64 /= 10);
                    516:         }
                    517: 
                    518:     } else if (hexadecimal == 1) {
                    519: 
                    520:         do {
                    521: 
                    522:             /* the "(uint32_t)" cast disables the BCC's warning */
                    523:             *--p = hex[(uint32_t) (ui64 & 0xf)];
                    524: 
                    525:         } while (ui64 >>= 4);
                    526: 
                    527:     } else { /* hexadecimal == 2 */
                    528: 
                    529:         do {
                    530: 
                    531:             /* the "(uint32_t)" cast disables the BCC's warning */
                    532:             *--p = HEX[(uint32_t) (ui64 & 0xf)];
                    533: 
                    534:         } while (ui64 >>= 4);
                    535:     }
                    536: 
                    537:     /* zero or space padding */
                    538: 
                    539:     len = (temp + NGX_INT64_LEN) - p;
                    540: 
                    541:     while (len++ < width && buf < last) {
                    542:         *buf++ = zero;
                    543:     }
                    544: 
                    545:     /* number safe copy */
                    546: 
                    547:     len = (temp + NGX_INT64_LEN) - p;
                    548: 
                    549:     if (buf + len > last) {
                    550:         len = last - buf;
                    551:     }
                    552: 
                    553:     return ngx_cpymem(buf, p, len);
                    554: }
                    555: 
                    556: 
                    557: /*
                    558:  * We use ngx_strcasecmp()/ngx_strncasecmp() for 7-bit ASCII strings only,
                    559:  * and implement our own ngx_strcasecmp()/ngx_strncasecmp()
                    560:  * to avoid libc locale overhead.  Besides, we use the ngx_uint_t's
                    561:  * instead of the u_char's, because they are slightly faster.
                    562:  */
                    563: 
                    564: ngx_int_t
                    565: ngx_strcasecmp(u_char *s1, u_char *s2)
                    566: {
                    567:     ngx_uint_t  c1, c2;
                    568: 
                    569:     for ( ;; ) {
                    570:         c1 = (ngx_uint_t) *s1++;
                    571:         c2 = (ngx_uint_t) *s2++;
                    572: 
                    573:         c1 = (c1 >= 'A' && c1 <= 'Z') ? (c1 | 0x20) : c1;
                    574:         c2 = (c2 >= 'A' && c2 <= 'Z') ? (c2 | 0x20) : c2;
                    575: 
                    576:         if (c1 == c2) {
                    577: 
                    578:             if (c1) {
                    579:                 continue;
                    580:             }
                    581: 
                    582:             return 0;
                    583:         }
                    584: 
                    585:         return c1 - c2;
                    586:     }
                    587: }
                    588: 
                    589: 
                    590: ngx_int_t
                    591: ngx_strncasecmp(u_char *s1, u_char *s2, size_t n)
                    592: {
                    593:     ngx_uint_t  c1, c2;
                    594: 
                    595:     while (n) {
                    596:         c1 = (ngx_uint_t) *s1++;
                    597:         c2 = (ngx_uint_t) *s2++;
                    598: 
                    599:         c1 = (c1 >= 'A' && c1 <= 'Z') ? (c1 | 0x20) : c1;
                    600:         c2 = (c2 >= 'A' && c2 <= 'Z') ? (c2 | 0x20) : c2;
                    601: 
                    602:         if (c1 == c2) {
                    603: 
                    604:             if (c1) {
                    605:                 n--;
                    606:                 continue;
                    607:             }
                    608: 
                    609:             return 0;
                    610:         }
                    611: 
                    612:         return c1 - c2;
                    613:     }
                    614: 
                    615:     return 0;
                    616: }
                    617: 
                    618: 
                    619: u_char *
                    620: ngx_strnstr(u_char *s1, char *s2, size_t len)
                    621: {
                    622:     u_char  c1, c2;
                    623:     size_t  n;
                    624: 
                    625:     c2 = *(u_char *) s2++;
                    626: 
                    627:     n = ngx_strlen(s2);
                    628: 
                    629:     do {
                    630:         do {
                    631:             if (len-- == 0) {
                    632:                 return NULL;
                    633:             }
                    634: 
                    635:             c1 = *s1++;
                    636: 
                    637:             if (c1 == 0) {
                    638:                 return NULL;
                    639:             }
                    640: 
                    641:         } while (c1 != c2);
                    642: 
                    643:         if (n > len) {
                    644:             return NULL;
                    645:         }
                    646: 
                    647:     } while (ngx_strncmp(s1, (u_char *) s2, n) != 0);
                    648: 
                    649:     return --s1;
                    650: }
                    651: 
                    652: 
                    653: /*
                    654:  * ngx_strstrn() and ngx_strcasestrn() are intended to search for static
                    655:  * substring with known length in null-terminated string. The argument n
                    656:  * must be length of the second substring - 1.
                    657:  */
                    658: 
                    659: u_char *
                    660: ngx_strstrn(u_char *s1, char *s2, size_t n)
                    661: {
                    662:     u_char  c1, c2;
                    663: 
                    664:     c2 = *(u_char *) s2++;
                    665: 
                    666:     do {
                    667:         do {
                    668:             c1 = *s1++;
                    669: 
                    670:             if (c1 == 0) {
                    671:                 return NULL;
                    672:             }
                    673: 
                    674:         } while (c1 != c2);
                    675: 
                    676:     } while (ngx_strncmp(s1, (u_char *) s2, n) != 0);
                    677: 
                    678:     return --s1;
                    679: }
                    680: 
                    681: 
                    682: u_char *
                    683: ngx_strcasestrn(u_char *s1, char *s2, size_t n)
                    684: {
                    685:     ngx_uint_t  c1, c2;
                    686: 
                    687:     c2 = (ngx_uint_t) *s2++;
                    688:     c2 = (c2 >= 'A' && c2 <= 'Z') ? (c2 | 0x20) : c2;
                    689: 
                    690:     do {
                    691:         do {
                    692:             c1 = (ngx_uint_t) *s1++;
                    693: 
                    694:             if (c1 == 0) {
                    695:                 return NULL;
                    696:             }
                    697: 
                    698:             c1 = (c1 >= 'A' && c1 <= 'Z') ? (c1 | 0x20) : c1;
                    699: 
                    700:         } while (c1 != c2);
                    701: 
                    702:     } while (ngx_strncasecmp(s1, (u_char *) s2, n) != 0);
                    703: 
                    704:     return --s1;
                    705: }
                    706: 
                    707: 
                    708: /*
                    709:  * ngx_strlcasestrn() is intended to search for static substring
                    710:  * with known length in string until the argument last. The argument n
                    711:  * must be length of the second substring - 1.
                    712:  */
                    713: 
                    714: u_char *
                    715: ngx_strlcasestrn(u_char *s1, u_char *last, u_char *s2, size_t n)
                    716: {
                    717:     ngx_uint_t  c1, c2;
                    718: 
                    719:     c2 = (ngx_uint_t) *s2++;
                    720:     c2 = (c2 >= 'A' && c2 <= 'Z') ? (c2 | 0x20) : c2;
                    721:     last -= n;
                    722: 
                    723:     do {
                    724:         do {
                    725:             if (s1 >= last) {
                    726:                 return NULL;
                    727:             }
                    728: 
                    729:             c1 = (ngx_uint_t) *s1++;
                    730: 
                    731:             c1 = (c1 >= 'A' && c1 <= 'Z') ? (c1 | 0x20) : c1;
                    732: 
                    733:         } while (c1 != c2);
                    734: 
                    735:     } while (ngx_strncasecmp(s1, s2, n) != 0);
                    736: 
                    737:     return --s1;
                    738: }
                    739: 
                    740: 
                    741: ngx_int_t
                    742: ngx_rstrncmp(u_char *s1, u_char *s2, size_t n)
                    743: {
                    744:     if (n == 0) {
                    745:         return 0;
                    746:     }
                    747: 
                    748:     n--;
                    749: 
                    750:     for ( ;; ) {
                    751:         if (s1[n] != s2[n]) {
                    752:             return s1[n] - s2[n];
                    753:         }
                    754: 
                    755:         if (n == 0) {
                    756:             return 0;
                    757:         }
                    758: 
                    759:         n--;
                    760:     }
                    761: }
                    762: 
                    763: 
                    764: ngx_int_t
                    765: ngx_rstrncasecmp(u_char *s1, u_char *s2, size_t n)
                    766: {
                    767:     u_char  c1, c2;
                    768: 
                    769:     if (n == 0) {
                    770:         return 0;
                    771:     }
                    772: 
                    773:     n--;
                    774: 
                    775:     for ( ;; ) {
                    776:         c1 = s1[n];
                    777:         if (c1 >= 'a' && c1 <= 'z') {
                    778:             c1 -= 'a' - 'A';
                    779:         }
                    780: 
                    781:         c2 = s2[n];
                    782:         if (c2 >= 'a' && c2 <= 'z') {
                    783:             c2 -= 'a' - 'A';
                    784:         }
                    785: 
                    786:         if (c1 != c2) {
                    787:             return c1 - c2;
                    788:         }
                    789: 
                    790:         if (n == 0) {
                    791:             return 0;
                    792:         }
                    793: 
                    794:         n--;
                    795:     }
                    796: }
                    797: 
                    798: 
                    799: ngx_int_t
                    800: ngx_memn2cmp(u_char *s1, u_char *s2, size_t n1, size_t n2)
                    801: {
                    802:     size_t     n;
                    803:     ngx_int_t  m, z;
                    804: 
                    805:     if (n1 <= n2) {
                    806:         n = n1;
                    807:         z = -1;
                    808: 
                    809:     } else {
                    810:         n = n2;
                    811:         z = 1;
                    812:     }
                    813: 
                    814:     m = ngx_memcmp(s1, s2, n);
                    815: 
                    816:     if (m || n1 == n2) {
                    817:         return m;
                    818:     }
                    819: 
                    820:     return z;
                    821: }
                    822: 
                    823: 
                    824: ngx_int_t
                    825: ngx_dns_strcmp(u_char *s1, u_char *s2)
                    826: {
                    827:     ngx_uint_t  c1, c2;
                    828: 
                    829:     for ( ;; ) {
                    830:         c1 = (ngx_uint_t) *s1++;
                    831:         c2 = (ngx_uint_t) *s2++;
                    832: 
                    833:         c1 = (c1 >= 'A' && c1 <= 'Z') ? (c1 | 0x20) : c1;
                    834:         c2 = (c2 >= 'A' && c2 <= 'Z') ? (c2 | 0x20) : c2;
                    835: 
                    836:         if (c1 == c2) {
                    837: 
                    838:             if (c1) {
                    839:                 continue;
                    840:             }
                    841: 
                    842:             return 0;
                    843:         }
                    844: 
                    845:         /* in ASCII '.' > '-', but we need '.' to be the lowest character */
                    846: 
                    847:         c1 = (c1 == '.') ? ' ' : c1;
                    848:         c2 = (c2 == '.') ? ' ' : c2;
                    849: 
                    850:         return c1 - c2;
                    851:     }
                    852: }
                    853: 
                    854: 
                    855: ngx_int_t
                    856: ngx_atoi(u_char *line, size_t n)
                    857: {
                    858:     ngx_int_t  value;
                    859: 
                    860:     if (n == 0) {
                    861:         return NGX_ERROR;
                    862:     }
                    863: 
                    864:     for (value = 0; n--; line++) {
                    865:         if (*line < '0' || *line > '9') {
                    866:             return NGX_ERROR;
                    867:         }
                    868: 
                    869:         value = value * 10 + (*line - '0');
                    870:     }
                    871: 
                    872:     if (value < 0) {
                    873:         return NGX_ERROR;
                    874: 
                    875:     } else {
                    876:         return value;
                    877:     }
                    878: }
                    879: 
                    880: 
                    881: /* parse a fixed point number, e.g., ngx_atofp("10.5", 4, 2) returns 1050 */
                    882: 
                    883: ngx_int_t
                    884: ngx_atofp(u_char *line, size_t n, size_t point)
                    885: {
                    886:     ngx_int_t   value;
                    887:     ngx_uint_t  dot;
                    888: 
                    889:     if (n == 0) {
                    890:         return NGX_ERROR;
                    891:     }
                    892: 
                    893:     dot = 0;
                    894: 
                    895:     for (value = 0; n--; line++) {
                    896: 
                    897:         if (point == 0) {
                    898:             return NGX_ERROR;
                    899:         }
                    900: 
                    901:         if (*line == '.') {
                    902:             if (dot) {
                    903:                 return NGX_ERROR;
                    904:             }
                    905: 
                    906:             dot = 1;
                    907:             continue;
                    908:         }
                    909: 
                    910:         if (*line < '0' || *line > '9') {
                    911:             return NGX_ERROR;
                    912:         }
                    913: 
                    914:         value = value * 10 + (*line - '0');
                    915:         point -= dot;
                    916:     }
                    917: 
                    918:     while (point--) {
                    919:         value = value * 10;
                    920:     }
                    921: 
                    922:     if (value < 0) {
                    923:         return NGX_ERROR;
                    924: 
                    925:     } else {
                    926:         return value;
                    927:     }
                    928: }
                    929: 
                    930: 
                    931: ssize_t
                    932: ngx_atosz(u_char *line, size_t n)
                    933: {
                    934:     ssize_t  value;
                    935: 
                    936:     if (n == 0) {
                    937:         return NGX_ERROR;
                    938:     }
                    939: 
                    940:     for (value = 0; n--; line++) {
                    941:         if (*line < '0' || *line > '9') {
                    942:             return NGX_ERROR;
                    943:         }
                    944: 
                    945:         value = value * 10 + (*line - '0');
                    946:     }
                    947: 
                    948:     if (value < 0) {
                    949:         return NGX_ERROR;
                    950: 
                    951:     } else {
                    952:         return value;
                    953:     }
                    954: }
                    955: 
                    956: 
                    957: off_t
                    958: ngx_atoof(u_char *line, size_t n)
                    959: {
                    960:     off_t  value;
                    961: 
                    962:     if (n == 0) {
                    963:         return NGX_ERROR;
                    964:     }
                    965: 
                    966:     for (value = 0; n--; line++) {
                    967:         if (*line < '0' || *line > '9') {
                    968:             return NGX_ERROR;
                    969:         }
                    970: 
                    971:         value = value * 10 + (*line - '0');
                    972:     }
                    973: 
                    974:     if (value < 0) {
                    975:         return NGX_ERROR;
                    976: 
                    977:     } else {
                    978:         return value;
                    979:     }
                    980: }
                    981: 
                    982: 
                    983: time_t
                    984: ngx_atotm(u_char *line, size_t n)
                    985: {
                    986:     time_t  value;
                    987: 
                    988:     if (n == 0) {
                    989:         return NGX_ERROR;
                    990:     }
                    991: 
                    992:     for (value = 0; n--; line++) {
                    993:         if (*line < '0' || *line > '9') {
                    994:             return NGX_ERROR;
                    995:         }
                    996: 
                    997:         value = value * 10 + (*line - '0');
                    998:     }
                    999: 
                   1000:     if (value < 0) {
                   1001:         return NGX_ERROR;
                   1002: 
                   1003:     } else {
                   1004:         return value;
                   1005:     }
                   1006: }
                   1007: 
                   1008: 
                   1009: ngx_int_t
                   1010: ngx_hextoi(u_char *line, size_t n)
                   1011: {
                   1012:     u_char     c, ch;
                   1013:     ngx_int_t  value;
                   1014: 
                   1015:     if (n == 0) {
                   1016:         return NGX_ERROR;
                   1017:     }
                   1018: 
                   1019:     for (value = 0; n--; line++) {
                   1020:         ch = *line;
                   1021: 
                   1022:         if (ch >= '0' && ch <= '9') {
                   1023:             value = value * 16 + (ch - '0');
                   1024:             continue;
                   1025:         }
                   1026: 
                   1027:         c = (u_char) (ch | 0x20);
                   1028: 
                   1029:         if (c >= 'a' && c <= 'f') {
                   1030:             value = value * 16 + (c - 'a' + 10);
                   1031:             continue;
                   1032:         }
                   1033: 
                   1034:         return NGX_ERROR;
                   1035:     }
                   1036: 
                   1037:     if (value < 0) {
                   1038:         return NGX_ERROR;
                   1039: 
                   1040:     } else {
                   1041:         return value;
                   1042:     }
                   1043: }
                   1044: 
                   1045: 
                   1046: u_char *
                   1047: ngx_hex_dump(u_char *dst, u_char *src, size_t len)
                   1048: {
                   1049:     static u_char  hex[] = "0123456789abcdef";
                   1050: 
                   1051:     while (len--) {
                   1052:         *dst++ = hex[*src >> 4];
                   1053:         *dst++ = hex[*src++ & 0xf];
                   1054:     }
                   1055: 
                   1056:     return dst;
                   1057: }
                   1058: 
                   1059: 
                   1060: void
                   1061: ngx_encode_base64(ngx_str_t *dst, ngx_str_t *src)
                   1062: {
                   1063:     u_char         *d, *s;
                   1064:     size_t          len;
                   1065:     static u_char   basis64[] =
                   1066:             "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
                   1067: 
                   1068:     len = src->len;
                   1069:     s = src->data;
                   1070:     d = dst->data;
                   1071: 
                   1072:     while (len > 2) {
                   1073:         *d++ = basis64[(s[0] >> 2) & 0x3f];
                   1074:         *d++ = basis64[((s[0] & 3) << 4) | (s[1] >> 4)];
                   1075:         *d++ = basis64[((s[1] & 0x0f) << 2) | (s[2] >> 6)];
                   1076:         *d++ = basis64[s[2] & 0x3f];
                   1077: 
                   1078:         s += 3;
                   1079:         len -= 3;
                   1080:     }
                   1081: 
                   1082:     if (len) {
                   1083:         *d++ = basis64[(s[0] >> 2) & 0x3f];
                   1084: 
                   1085:         if (len == 1) {
                   1086:             *d++ = basis64[(s[0] & 3) << 4];
                   1087:             *d++ = '=';
                   1088: 
                   1089:         } else {
                   1090:             *d++ = basis64[((s[0] & 3) << 4) | (s[1] >> 4)];
                   1091:             *d++ = basis64[(s[1] & 0x0f) << 2];
                   1092:         }
                   1093: 
                   1094:         *d++ = '=';
                   1095:     }
                   1096: 
                   1097:     dst->len = d - dst->data;
                   1098: }
                   1099: 
                   1100: 
                   1101: ngx_int_t
                   1102: ngx_decode_base64(ngx_str_t *dst, ngx_str_t *src)
                   1103: {
                   1104:     static u_char   basis64[] = {
                   1105:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
                   1106:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
                   1107:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 62, 77, 77, 77, 63,
                   1108:         52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 77, 77, 77, 77, 77, 77,
                   1109:         77,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
                   1110:         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 77, 77, 77, 77, 77,
                   1111:         77, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
                   1112:         41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 77, 77, 77, 77, 77,
                   1113: 
                   1114:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
                   1115:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
                   1116:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
                   1117:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
                   1118:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
                   1119:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
                   1120:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
                   1121:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77
                   1122:     };
                   1123: 
                   1124:     return ngx_decode_base64_internal(dst, src, basis64);
                   1125: }
                   1126: 
                   1127: 
                   1128: ngx_int_t
                   1129: ngx_decode_base64url(ngx_str_t *dst, ngx_str_t *src)
                   1130: {
                   1131:     static u_char   basis64[] = {
                   1132:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
                   1133:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
                   1134:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 62, 77, 77,
                   1135:         52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 77, 77, 77, 77, 77, 77,
                   1136:         77,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
                   1137:         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 77, 77, 77, 77, 63,
                   1138:         77, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
                   1139:         41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 77, 77, 77, 77, 77,
                   1140: 
                   1141:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
                   1142:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
                   1143:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
                   1144:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
                   1145:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
                   1146:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
                   1147:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
                   1148:         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77
                   1149:     };
                   1150: 
                   1151:     return ngx_decode_base64_internal(dst, src, basis64);
                   1152: }
                   1153: 
                   1154: 
                   1155: static ngx_int_t
                   1156: ngx_decode_base64_internal(ngx_str_t *dst, ngx_str_t *src, const u_char *basis)
                   1157: {
                   1158:     size_t          len;
                   1159:     u_char         *d, *s;
                   1160: 
                   1161:     for (len = 0; len < src->len; len++) {
                   1162:         if (src->data[len] == '=') {
                   1163:             break;
                   1164:         }
                   1165: 
                   1166:         if (basis[src->data[len]] == 77) {
                   1167:             return NGX_ERROR;
                   1168:         }
                   1169:     }
                   1170: 
                   1171:     if (len % 4 == 1) {
                   1172:         return NGX_ERROR;
                   1173:     }
                   1174: 
                   1175:     s = src->data;
                   1176:     d = dst->data;
                   1177: 
                   1178:     while (len > 3) {
                   1179:         *d++ = (u_char) (basis[s[0]] << 2 | basis[s[1]] >> 4);
                   1180:         *d++ = (u_char) (basis[s[1]] << 4 | basis[s[2]] >> 2);
                   1181:         *d++ = (u_char) (basis[s[2]] << 6 | basis[s[3]]);
                   1182: 
                   1183:         s += 4;
                   1184:         len -= 4;
                   1185:     }
                   1186: 
                   1187:     if (len > 1) {
                   1188:         *d++ = (u_char) (basis[s[0]] << 2 | basis[s[1]] >> 4);
                   1189:     }
                   1190: 
                   1191:     if (len > 2) {
                   1192:         *d++ = (u_char) (basis[s[1]] << 4 | basis[s[2]] >> 2);
                   1193:     }
                   1194: 
                   1195:     dst->len = d - dst->data;
                   1196: 
                   1197:     return NGX_OK;
                   1198: }
                   1199: 
                   1200: 
                   1201: /*
                   1202:  * ngx_utf8_decode() decodes two and more bytes UTF sequences only
                   1203:  * the return values:
                   1204:  *    0x80 - 0x10ffff         valid character
                   1205:  *    0x110000 - 0xfffffffd   invalid sequence
                   1206:  *    0xfffffffe              incomplete sequence
                   1207:  *    0xffffffff              error
                   1208:  */
                   1209: 
                   1210: uint32_t
                   1211: ngx_utf8_decode(u_char **p, size_t n)
                   1212: {
                   1213:     size_t    len;
                   1214:     uint32_t  u, i, valid;
                   1215: 
                   1216:     u = **p;
                   1217: 
                   1218:     if (u >= 0xf0) {
                   1219: 
                   1220:         u &= 0x07;
                   1221:         valid = 0xffff;
                   1222:         len = 3;
                   1223: 
                   1224:     } else if (u >= 0xe0) {
                   1225: 
                   1226:         u &= 0x0f;
                   1227:         valid = 0x7ff;
                   1228:         len = 2;
                   1229: 
                   1230:     } else if (u >= 0xc2) {
                   1231: 
                   1232:         u &= 0x1f;
                   1233:         valid = 0x7f;
                   1234:         len = 1;
                   1235: 
                   1236:     } else {
                   1237:         (*p)++;
                   1238:         return 0xffffffff;
                   1239:     }
                   1240: 
                   1241:     if (n - 1 < len) {
                   1242:         return 0xfffffffe;
                   1243:     }
                   1244: 
                   1245:     (*p)++;
                   1246: 
                   1247:     while (len) {
                   1248:         i = *(*p)++;
                   1249: 
                   1250:         if (i < 0x80) {
                   1251:             return 0xffffffff;
                   1252:         }
                   1253: 
                   1254:         u = (u << 6) | (i & 0x3f);
                   1255: 
                   1256:         len--;
                   1257:     }
                   1258: 
                   1259:     if (u > valid) {
                   1260:         return u;
                   1261:     }
                   1262: 
                   1263:     return 0xffffffff;
                   1264: }
                   1265: 
                   1266: 
                   1267: size_t
                   1268: ngx_utf8_length(u_char *p, size_t n)
                   1269: {
                   1270:     u_char  c, *last;
                   1271:     size_t  len;
                   1272: 
                   1273:     last = p + n;
                   1274: 
                   1275:     for (len = 0; p < last; len++) {
                   1276: 
                   1277:         c = *p;
                   1278: 
                   1279:         if (c < 0x80) {
                   1280:             p++;
                   1281:             continue;
                   1282:         }
                   1283: 
                   1284:         if (ngx_utf8_decode(&p, n) > 0x10ffff) {
                   1285:             /* invalid UTF-8 */
                   1286:             return n;
                   1287:         }
                   1288:     }
                   1289: 
                   1290:     return len;
                   1291: }
                   1292: 
                   1293: 
                   1294: u_char *
                   1295: ngx_utf8_cpystrn(u_char *dst, u_char *src, size_t n, size_t len)
                   1296: {
                   1297:     u_char  c, *next;
                   1298: 
                   1299:     if (n == 0) {
                   1300:         return dst;
                   1301:     }
                   1302: 
                   1303:     while (--n) {
                   1304: 
                   1305:         c = *src;
                   1306:         *dst = c;
                   1307: 
                   1308:         if (c < 0x80) {
                   1309: 
                   1310:             if (c != '\0') {
                   1311:                 dst++;
                   1312:                 src++;
                   1313:                 len--;
                   1314: 
                   1315:                 continue;
                   1316:             }
                   1317: 
                   1318:             return dst;
                   1319:         }
                   1320: 
                   1321:         next = src;
                   1322: 
                   1323:         if (ngx_utf8_decode(&next, len) > 0x10ffff) {
                   1324:             /* invalid UTF-8 */
                   1325:             break;
                   1326:         }
                   1327: 
                   1328:         while (src < next) {
                   1329:             *dst++ = *src++;
                   1330:             len--;
                   1331:         }
                   1332:     }
                   1333: 
                   1334:     *dst = '\0';
                   1335: 
                   1336:     return dst;
                   1337: }
                   1338: 
                   1339: 
                   1340: uintptr_t
                   1341: ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
                   1342: {
                   1343:     ngx_uint_t      n;
                   1344:     uint32_t       *escape;
                   1345:     static u_char   hex[] = "0123456789abcdef";
                   1346: 
                   1347:                     /* " ", "#", "%", "?", %00-%1F, %7F-%FF */
                   1348: 
                   1349:     static uint32_t   uri[] = {
                   1350:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1351: 
                   1352:                     /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
                   1353:         0x80000029, /* 1000 0000 0000 0000  0000 0000 0010 1001 */
                   1354: 
                   1355:                     /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
                   1356:         0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
                   1357: 
                   1358:                     /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */
                   1359:         0x80000000, /* 1000 0000 0000 0000  0000 0000 0000 0000 */
                   1360: 
                   1361:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1362:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1363:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1364:         0xffffffff  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1365:     };
                   1366: 
                   1367:                     /* " ", "#", "%", "&", "+", "?", %00-%1F, %7F-%FF */
                   1368: 
                   1369:     static uint32_t   args[] = {
                   1370:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1371: 
                   1372:                     /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
                   1373:         0x88000869, /* 1000 1000 0000 0000  0000 1000 0110 1001 */
                   1374: 
                   1375:                     /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
                   1376:         0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
                   1377: 
                   1378:                     /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */
                   1379:         0x80000000, /* 1000 0000 0000 0000  0000 0000 0000 0000 */
                   1380: 
                   1381:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1382:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1383:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1384:         0xffffffff  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1385:     };
                   1386: 
                   1387:                     /* not ALPHA, DIGIT, "-", ".", "_", "~" */
                   1388: 
                   1389:     static uint32_t   uri_component[] = {
                   1390:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1391: 
                   1392:                     /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
                   1393:         0xfc009fff, /* 1111 1100 0000 0000  1001 1111 1111 1111 */
                   1394: 
                   1395:                     /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
                   1396:         0x78000001, /* 0111 1000 0000 0000  0000 0000 0000 0001 */
                   1397: 
                   1398:                     /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */
                   1399:         0xb8000001, /* 1011 1000 0000 0000  0000 0000 0000 0001 */
                   1400: 
                   1401:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1402:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1403:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1404:         0xffffffff  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1405:     };
                   1406: 
                   1407:                     /* " ", "#", """, "%", "'", %00-%1F, %7F-%FF */
                   1408: 
                   1409:     static uint32_t   html[] = {
                   1410:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1411: 
                   1412:                     /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
                   1413:         0x000000ad, /* 0000 0000 0000 0000  0000 0000 1010 1101 */
                   1414: 
                   1415:                     /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
                   1416:         0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
                   1417: 
                   1418:                     /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */
                   1419:         0x80000000, /* 1000 0000 0000 0000  0000 0000 0000 0000 */
                   1420: 
                   1421:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1422:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1423:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1424:         0xffffffff  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1425:     };
                   1426: 
                   1427:                     /* " ", """, "%", "'", %00-%1F, %7F-%FF */
                   1428: 
                   1429:     static uint32_t   refresh[] = {
                   1430:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1431: 
                   1432:                     /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
                   1433:         0x00000085, /* 0000 0000 0000 0000  0000 0000 1000 0101 */
                   1434: 
                   1435:                     /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
                   1436:         0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
                   1437: 
                   1438:                     /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */
                   1439:         0x80000000, /* 1000 0000 0000 0000  0000 0000 0000 0000 */
                   1440: 
                   1441:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1442:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1443:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1444:         0xffffffff  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1445:     };
                   1446: 
                   1447:                     /* " ", "%", %00-%1F */
                   1448: 
                   1449:     static uint32_t   memcached[] = {
                   1450:         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
                   1451: 
                   1452:                     /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
                   1453:         0x00000021, /* 0000 0000 0000 0000  0000 0000 0010 0001 */
                   1454: 
                   1455:                     /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
                   1456:         0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
                   1457: 
                   1458:                     /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */
                   1459:         0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
                   1460: 
                   1461:         0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
                   1462:         0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
                   1463:         0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
                   1464:         0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
                   1465:     };
                   1466: 
                   1467:                     /* mail_auth is the same as memcached */
                   1468: 
                   1469:     static uint32_t  *map[] =
                   1470:         { uri, args, uri_component, html, refresh, memcached, memcached };
                   1471: 
                   1472: 
                   1473:     escape = map[type];
                   1474: 
                   1475:     if (dst == NULL) {
                   1476: 
                   1477:         /* find the number of the characters to be escaped */
                   1478: 
                   1479:         n = 0;
                   1480: 
                   1481:         while (size) {
                   1482:             if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
                   1483:                 n++;
                   1484:             }
                   1485:             src++;
                   1486:             size--;
                   1487:         }
                   1488: 
                   1489:         return (uintptr_t) n;
                   1490:     }
                   1491: 
                   1492:     while (size) {
                   1493:         if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
                   1494:             *dst++ = '%';
                   1495:             *dst++ = hex[*src >> 4];
                   1496:             *dst++ = hex[*src & 0xf];
                   1497:             src++;
                   1498: 
                   1499:         } else {
                   1500:             *dst++ = *src++;
                   1501:         }
                   1502:         size--;
                   1503:     }
                   1504: 
                   1505:     return (uintptr_t) dst;
                   1506: }
                   1507: 
                   1508: 
                   1509: void
                   1510: ngx_unescape_uri(u_char **dst, u_char **src, size_t size, ngx_uint_t type)
                   1511: {
                   1512:     u_char  *d, *s, ch, c, decoded;
                   1513:     enum {
                   1514:         sw_usual = 0,
                   1515:         sw_quoted,
                   1516:         sw_quoted_second
                   1517:     } state;
                   1518: 
                   1519:     d = *dst;
                   1520:     s = *src;
                   1521: 
                   1522:     state = 0;
                   1523:     decoded = 0;
                   1524: 
                   1525:     while (size--) {
                   1526: 
                   1527:         ch = *s++;
                   1528: 
                   1529:         switch (state) {
                   1530:         case sw_usual:
                   1531:             if (ch == '?'
                   1532:                 && (type & (NGX_UNESCAPE_URI|NGX_UNESCAPE_REDIRECT)))
                   1533:             {
                   1534:                 *d++ = ch;
                   1535:                 goto done;
                   1536:             }
                   1537: 
                   1538:             if (ch == '%') {
                   1539:                 state = sw_quoted;
                   1540:                 break;
                   1541:             }
                   1542: 
                   1543:             *d++ = ch;
                   1544:             break;
                   1545: 
                   1546:         case sw_quoted:
                   1547: 
                   1548:             if (ch >= '0' && ch <= '9') {
                   1549:                 decoded = (u_char) (ch - '0');
                   1550:                 state = sw_quoted_second;
                   1551:                 break;
                   1552:             }
                   1553: 
                   1554:             c = (u_char) (ch | 0x20);
                   1555:             if (c >= 'a' && c <= 'f') {
                   1556:                 decoded = (u_char) (c - 'a' + 10);
                   1557:                 state = sw_quoted_second;
                   1558:                 break;
                   1559:             }
                   1560: 
                   1561:             /* the invalid quoted character */
                   1562: 
                   1563:             state = sw_usual;
                   1564: 
                   1565:             *d++ = ch;
                   1566: 
                   1567:             break;
                   1568: 
                   1569:         case sw_quoted_second:
                   1570: 
                   1571:             state = sw_usual;
                   1572: 
                   1573:             if (ch >= '0' && ch <= '9') {
                   1574:                 ch = (u_char) ((decoded << 4) + ch - '0');
                   1575: 
                   1576:                 if (type & NGX_UNESCAPE_REDIRECT) {
                   1577:                     if (ch > '%' && ch < 0x7f) {
                   1578:                         *d++ = ch;
                   1579:                         break;
                   1580:                     }
                   1581: 
                   1582:                     *d++ = '%'; *d++ = *(s - 2); *d++ = *(s - 1);
                   1583: 
                   1584:                     break;
                   1585:                 }
                   1586: 
                   1587:                 *d++ = ch;
                   1588: 
                   1589:                 break;
                   1590:             }
                   1591: 
                   1592:             c = (u_char) (ch | 0x20);
                   1593:             if (c >= 'a' && c <= 'f') {
                   1594:                 ch = (u_char) ((decoded << 4) + c - 'a' + 10);
                   1595: 
                   1596:                 if (type & NGX_UNESCAPE_URI) {
                   1597:                     if (ch == '?') {
                   1598:                         *d++ = ch;
                   1599:                         goto done;
                   1600:                     }
                   1601: 
                   1602:                     *d++ = ch;
                   1603:                     break;
                   1604:                 }
                   1605: 
                   1606:                 if (type & NGX_UNESCAPE_REDIRECT) {
                   1607:                     if (ch == '?') {
                   1608:                         *d++ = ch;
                   1609:                         goto done;
                   1610:                     }
                   1611: 
                   1612:                     if (ch > '%' && ch < 0x7f) {
                   1613:                         *d++ = ch;
                   1614:                         break;
                   1615:                     }
                   1616: 
                   1617:                     *d++ = '%'; *d++ = *(s - 2); *d++ = *(s - 1);
                   1618:                     break;
                   1619:                 }
                   1620: 
                   1621:                 *d++ = ch;
                   1622: 
                   1623:                 break;
                   1624:             }
                   1625: 
                   1626:             /* the invalid quoted character */
                   1627: 
                   1628:             break;
                   1629:         }
                   1630:     }
                   1631: 
                   1632: done:
                   1633: 
                   1634:     *dst = d;
                   1635:     *src = s;
                   1636: }
                   1637: 
                   1638: 
                   1639: uintptr_t
                   1640: ngx_escape_html(u_char *dst, u_char *src, size_t size)
                   1641: {
                   1642:     u_char      ch;
                   1643:     ngx_uint_t  len;
                   1644: 
                   1645:     if (dst == NULL) {
                   1646: 
                   1647:         len = 0;
                   1648: 
                   1649:         while (size) {
                   1650:             switch (*src++) {
                   1651: 
                   1652:             case '<':
                   1653:                 len += sizeof("&lt;") - 2;
                   1654:                 break;
                   1655: 
                   1656:             case '>':
                   1657:                 len += sizeof("&gt;") - 2;
                   1658:                 break;
                   1659: 
                   1660:             case '&':
                   1661:                 len += sizeof("&amp;") - 2;
                   1662:                 break;
                   1663: 
                   1664:             case '"':
                   1665:                 len += sizeof("&quot;") - 2;
                   1666:                 break;
                   1667: 
                   1668:             default:
                   1669:                 break;
                   1670:             }
                   1671:             size--;
                   1672:         }
                   1673: 
                   1674:         return (uintptr_t) len;
                   1675:     }
                   1676: 
                   1677:     while (size) {
                   1678:         ch = *src++;
                   1679: 
                   1680:         switch (ch) {
                   1681: 
                   1682:         case '<':
                   1683:             *dst++ = '&'; *dst++ = 'l'; *dst++ = 't'; *dst++ = ';';
                   1684:             break;
                   1685: 
                   1686:         case '>':
                   1687:             *dst++ = '&'; *dst++ = 'g'; *dst++ = 't'; *dst++ = ';';
                   1688:             break;
                   1689: 
                   1690:         case '&':
                   1691:             *dst++ = '&'; *dst++ = 'a'; *dst++ = 'm'; *dst++ = 'p';
                   1692:             *dst++ = ';';
                   1693:             break;
                   1694: 
                   1695:         case '"':
                   1696:             *dst++ = '&'; *dst++ = 'q'; *dst++ = 'u'; *dst++ = 'o';
                   1697:             *dst++ = 't'; *dst++ = ';';
                   1698:             break;
                   1699: 
                   1700:         default:
                   1701:             *dst++ = ch;
                   1702:             break;
                   1703:         }
                   1704:         size--;
                   1705:     }
                   1706: 
                   1707:     return (uintptr_t) dst;
                   1708: }
                   1709: 
                   1710: 
                   1711: void
                   1712: ngx_str_rbtree_insert_value(ngx_rbtree_node_t *temp,
                   1713:     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
                   1714: {
                   1715:     ngx_str_node_t      *n, *t;
                   1716:     ngx_rbtree_node_t  **p;
                   1717: 
                   1718:     for ( ;; ) {
                   1719: 
                   1720:         n = (ngx_str_node_t *) node;
                   1721:         t = (ngx_str_node_t *) temp;
                   1722: 
                   1723:         if (node->key != temp->key) {
                   1724: 
                   1725:             p = (node->key < temp->key) ? &temp->left : &temp->right;
                   1726: 
                   1727:         } else if (n->str.len != t->str.len) {
                   1728: 
                   1729:             p = (n->str.len < t->str.len) ? &temp->left : &temp->right;
                   1730: 
                   1731:         } else {
                   1732:             p = (ngx_memcmp(n->str.data, t->str.data, n->str.len) < 0)
                   1733:                  ? &temp->left : &temp->right;
                   1734:         }
                   1735: 
                   1736:         if (*p == sentinel) {
                   1737:             break;
                   1738:         }
                   1739: 
                   1740:         temp = *p;
                   1741:     }
                   1742: 
                   1743:     *p = node;
                   1744:     node->parent = temp;
                   1745:     node->left = sentinel;
                   1746:     node->right = sentinel;
                   1747:     ngx_rbt_red(node);
                   1748: }
                   1749: 
                   1750: 
                   1751: ngx_str_node_t *
                   1752: ngx_str_rbtree_lookup(ngx_rbtree_t *rbtree, ngx_str_t *val, uint32_t hash)
                   1753: {
                   1754:     ngx_int_t           rc;
                   1755:     ngx_str_node_t     *n;
                   1756:     ngx_rbtree_node_t  *node, *sentinel;
                   1757: 
                   1758:     node = rbtree->root;
                   1759:     sentinel = rbtree->sentinel;
                   1760: 
                   1761:     while (node != sentinel) {
                   1762: 
                   1763:         n = (ngx_str_node_t *) node;
                   1764: 
                   1765:         if (hash != node->key) {
                   1766:             node = (hash < node->key) ? node->left : node->right;
                   1767:             continue;
                   1768:         }
                   1769: 
                   1770:         if (val->len != n->str.len) {
                   1771:             node = (val->len < n->str.len) ? node->left : node->right;
                   1772:             continue;
                   1773:         }
                   1774: 
                   1775:         rc = ngx_memcmp(val->data, n->str.data, val->len);
                   1776: 
                   1777:         if (rc < 0) {
                   1778:             node = node->left;
                   1779:             continue;
                   1780:         }
                   1781: 
                   1782:         if (rc > 0) {
                   1783:             node = node->right;
                   1784:             continue;
                   1785:         }
                   1786: 
                   1787:         return n;
                   1788:     }
                   1789: 
                   1790:     return NULL;
                   1791: }
                   1792: 
                   1793: 
                   1794: /* ngx_sort() is implemented as insertion sort because we need stable sort */
                   1795: 
                   1796: void
                   1797: ngx_sort(void *base, size_t n, size_t size,
                   1798:     ngx_int_t (*cmp)(const void *, const void *))
                   1799: {
                   1800:     u_char  *p1, *p2, *p;
                   1801: 
                   1802:     p = ngx_alloc(size, ngx_cycle->log);
                   1803:     if (p == NULL) {
                   1804:         return;
                   1805:     }
                   1806: 
                   1807:     for (p1 = (u_char *) base + size;
                   1808:          p1 < (u_char *) base + n * size;
                   1809:          p1 += size)
                   1810:     {
                   1811:         ngx_memcpy(p, p1, size);
                   1812: 
                   1813:         for (p2 = p1;
                   1814:              p2 > (u_char *) base && cmp(p2 - size, p) > 0;
                   1815:              p2 -= size)
                   1816:         {
                   1817:             ngx_memcpy(p2, p2 - size, size);
                   1818:         }
                   1819: 
                   1820:         ngx_memcpy(p2, p, size);
                   1821:     }
                   1822: 
                   1823:     ngx_free(p);
                   1824: }
                   1825: 
                   1826: 
                   1827: #if (NGX_MEMCPY_LIMIT)
                   1828: 
                   1829: void *
                   1830: ngx_memcpy(void *dst, const void *src, size_t n)
                   1831: {
                   1832:     if (n > NGX_MEMCPY_LIMIT) {
                   1833:         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "memcpy %uz bytes", n);
                   1834:         ngx_debug_point();
                   1835:     }
                   1836: 
                   1837:     return memcpy(dst, src, n);
                   1838: }
                   1839: 
                   1840: #endif

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