10Sigor@sysoev.ru 20Sigor@sysoev.ru /* 30Sigor@sysoev.ru * Copyright (C) Igor Sysoev 40Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 50Sigor@sysoev.ru */ 60Sigor@sysoev.ru 70Sigor@sysoev.ru #include <nxt_main.h> 80Sigor@sysoev.ru 90Sigor@sysoev.ru 100Sigor@sysoev.ru nxt_str_t * 1165Sigor@sysoev.ru nxt_str_alloc(nxt_mp_t *mp, size_t length) 120Sigor@sysoev.ru { 130Sigor@sysoev.ru nxt_str_t *s; 140Sigor@sysoev.ru 1510Sigor@sysoev.ru /* The string start is allocated aligned to be close to nxt_str_t. */ 1665Sigor@sysoev.ru s = nxt_mp_get(mp, sizeof(nxt_str_t) + length); 170Sigor@sysoev.ru 180Sigor@sysoev.ru if (nxt_fast_path(s != NULL)) { 1910Sigor@sysoev.ru s->length = length; 2098Svbart@nginx.com s->start = nxt_pointer_to(s, sizeof(nxt_str_t)); 210Sigor@sysoev.ru } 220Sigor@sysoev.ru 230Sigor@sysoev.ru return s; 240Sigor@sysoev.ru } 250Sigor@sysoev.ru 260Sigor@sysoev.ru 270Sigor@sysoev.ru /* 280Sigor@sysoev.ru * nxt_str_dup() creates a new string with a copy of a source string. 290Sigor@sysoev.ru * If length of the source string is zero, then the new string anyway 300Sigor@sysoev.ru * gets a pointer somewhere in mem_pool. 310Sigor@sysoev.ru */ 320Sigor@sysoev.ru 330Sigor@sysoev.ru nxt_str_t * 3465Sigor@sysoev.ru nxt_str_dup(nxt_mp_t *mp, nxt_str_t *dst, const nxt_str_t *src) 350Sigor@sysoev.ru { 360Sigor@sysoev.ru u_char *p; 370Sigor@sysoev.ru 380Sigor@sysoev.ru if (dst == NULL) { 3910Sigor@sysoev.ru /* The string start is allocated aligned to be close to nxt_str_t. */ 4065Sigor@sysoev.ru dst = nxt_mp_get(mp, sizeof(nxt_str_t) + src->length); 410Sigor@sysoev.ru if (nxt_slow_path(dst == NULL)) { 420Sigor@sysoev.ru return NULL; 430Sigor@sysoev.ru } 440Sigor@sysoev.ru 450Sigor@sysoev.ru p = (u_char *) dst; 460Sigor@sysoev.ru p += sizeof(nxt_str_t); 4710Sigor@sysoev.ru dst->start = p; 480Sigor@sysoev.ru 490Sigor@sysoev.ru } else { 5065Sigor@sysoev.ru dst->start = nxt_mp_nget(mp, src->length); 5110Sigor@sysoev.ru if (nxt_slow_path(dst->start == NULL)) { 520Sigor@sysoev.ru return NULL; 530Sigor@sysoev.ru } 540Sigor@sysoev.ru } 550Sigor@sysoev.ru 5610Sigor@sysoev.ru nxt_memcpy(dst->start, src->start, src->length); 5710Sigor@sysoev.ru dst->length = src->length; 580Sigor@sysoev.ru 590Sigor@sysoev.ru return dst; 600Sigor@sysoev.ru } 610Sigor@sysoev.ru 620Sigor@sysoev.ru 630Sigor@sysoev.ru /* 64212Svbart@nginx.com * nxt_str_cstrz() creates a C style zero-terminated copy of a source 650Sigor@sysoev.ru * nxt_str_t. The function is intended to create strings suitable 660Sigor@sysoev.ru * for libc and kernel interfaces so result is pointer to char instead 67216Sigor@sysoev.ru * of u_char to minimize casts. 680Sigor@sysoev.ru */ 690Sigor@sysoev.ru 700Sigor@sysoev.ru char * 71212Svbart@nginx.com nxt_str_cstrz(nxt_mp_t *mp, const nxt_str_t *src) 720Sigor@sysoev.ru { 730Sigor@sysoev.ru char *p, *dst; 740Sigor@sysoev.ru 75216Sigor@sysoev.ru dst = nxt_mp_alloc(mp, src->length + 1); 760Sigor@sysoev.ru 770Sigor@sysoev.ru if (nxt_fast_path(dst != NULL)) { 7810Sigor@sysoev.ru p = nxt_cpymem(dst, src->start, src->length); 790Sigor@sysoev.ru *p = '\0'; 800Sigor@sysoev.ru } 810Sigor@sysoev.ru 820Sigor@sysoev.ru return dst; 830Sigor@sysoev.ru } 840Sigor@sysoev.ru 850Sigor@sysoev.ru 860Sigor@sysoev.ru void 8710Sigor@sysoev.ru nxt_memcpy_lowcase(u_char *dst, const u_char *src, size_t length) 880Sigor@sysoev.ru { 890Sigor@sysoev.ru u_char c; 900Sigor@sysoev.ru 9110Sigor@sysoev.ru while (length != 0) { 920Sigor@sysoev.ru c = *src++; 930Sigor@sysoev.ru *dst++ = nxt_lowcase(c); 9410Sigor@sysoev.ru length--; 950Sigor@sysoev.ru } 960Sigor@sysoev.ru } 970Sigor@sysoev.ru 980Sigor@sysoev.ru 99963Sigor@sysoev.ru void 100963Sigor@sysoev.ru nxt_memcpy_upcase(u_char *dst, const u_char *src, size_t length) 101963Sigor@sysoev.ru { 102963Sigor@sysoev.ru u_char c; 103963Sigor@sysoev.ru 104963Sigor@sysoev.ru while (length != 0) { 105963Sigor@sysoev.ru c = *src++; 106963Sigor@sysoev.ru *dst++ = nxt_upcase(c); 107963Sigor@sysoev.ru length--; 108963Sigor@sysoev.ru } 109963Sigor@sysoev.ru } 110963Sigor@sysoev.ru 111963Sigor@sysoev.ru 1120Sigor@sysoev.ru u_char * 1131439Svbart@nginx.com nxt_cpystr(u_char *dst, const u_char *src) 1141439Svbart@nginx.com { 1151439Svbart@nginx.com for ( ;; ) { 1161439Svbart@nginx.com *dst = *src; 1171439Svbart@nginx.com 1181439Svbart@nginx.com if (*dst == '\0') { 1191439Svbart@nginx.com break; 1201439Svbart@nginx.com } 1211439Svbart@nginx.com 1221439Svbart@nginx.com dst++; 1231439Svbart@nginx.com src++; 1241439Svbart@nginx.com } 1251439Svbart@nginx.com 1261439Svbart@nginx.com return dst; 1271439Svbart@nginx.com } 1281439Svbart@nginx.com 1291439Svbart@nginx.com 1301439Svbart@nginx.com u_char * 13110Sigor@sysoev.ru nxt_cpystrn(u_char *dst, const u_char *src, size_t length) 1320Sigor@sysoev.ru { 13310Sigor@sysoev.ru if (length == 0) { 1340Sigor@sysoev.ru return dst; 1350Sigor@sysoev.ru } 1360Sigor@sysoev.ru 13710Sigor@sysoev.ru while (--length != 0) { 1380Sigor@sysoev.ru *dst = *src; 1390Sigor@sysoev.ru 1400Sigor@sysoev.ru if (*dst == '\0') { 1410Sigor@sysoev.ru return dst; 1420Sigor@sysoev.ru } 1430Sigor@sysoev.ru 1440Sigor@sysoev.ru dst++; 1450Sigor@sysoev.ru src++; 1460Sigor@sysoev.ru } 1470Sigor@sysoev.ru 1480Sigor@sysoev.ru *dst = '\0'; 1490Sigor@sysoev.ru 1500Sigor@sysoev.ru return dst; 1510Sigor@sysoev.ru } 1520Sigor@sysoev.ru 1530Sigor@sysoev.ru 1540Sigor@sysoev.ru nxt_int_t 1550Sigor@sysoev.ru nxt_strcasecmp(const u_char *s1, const u_char *s2) 1560Sigor@sysoev.ru { 1570Sigor@sysoev.ru u_char c1, c2; 1580Sigor@sysoev.ru nxt_int_t n; 1590Sigor@sysoev.ru 1600Sigor@sysoev.ru for ( ;; ) { 1610Sigor@sysoev.ru c1 = *s1++; 1620Sigor@sysoev.ru c2 = *s2++; 1630Sigor@sysoev.ru 1640Sigor@sysoev.ru c1 = nxt_lowcase(c1); 1650Sigor@sysoev.ru c2 = nxt_lowcase(c2); 1660Sigor@sysoev.ru 1670Sigor@sysoev.ru n = c1 - c2; 1680Sigor@sysoev.ru 1690Sigor@sysoev.ru if (n != 0) { 1700Sigor@sysoev.ru return n; 1710Sigor@sysoev.ru } 1720Sigor@sysoev.ru 1730Sigor@sysoev.ru if (c1 == 0) { 1740Sigor@sysoev.ru return 0; 1750Sigor@sysoev.ru } 1760Sigor@sysoev.ru } 1770Sigor@sysoev.ru } 1780Sigor@sysoev.ru 1790Sigor@sysoev.ru 1800Sigor@sysoev.ru nxt_int_t 18110Sigor@sysoev.ru nxt_strncasecmp(const u_char *s1, const u_char *s2, size_t length) 1820Sigor@sysoev.ru { 1830Sigor@sysoev.ru u_char c1, c2; 1840Sigor@sysoev.ru nxt_int_t n; 1850Sigor@sysoev.ru 18610Sigor@sysoev.ru while (length-- != 0) { 1870Sigor@sysoev.ru c1 = *s1++; 1880Sigor@sysoev.ru c2 = *s2++; 1890Sigor@sysoev.ru 1900Sigor@sysoev.ru c1 = nxt_lowcase(c1); 1910Sigor@sysoev.ru c2 = nxt_lowcase(c2); 1920Sigor@sysoev.ru 1930Sigor@sysoev.ru n = c1 - c2; 1940Sigor@sysoev.ru 1950Sigor@sysoev.ru if (n != 0) { 1960Sigor@sysoev.ru return n; 1970Sigor@sysoev.ru } 1980Sigor@sysoev.ru 1990Sigor@sysoev.ru if (c1 == 0) { 2000Sigor@sysoev.ru return 0; 2010Sigor@sysoev.ru } 2020Sigor@sysoev.ru } 2030Sigor@sysoev.ru 2040Sigor@sysoev.ru return 0; 2050Sigor@sysoev.ru } 2060Sigor@sysoev.ru 2070Sigor@sysoev.ru 2080Sigor@sysoev.ru nxt_int_t 2091234Sigor@sysoev.ru nxt_memcasecmp(const void *p1, const void *p2, size_t length) 2100Sigor@sysoev.ru { 2111234Sigor@sysoev.ru u_char c1, c2; 2121234Sigor@sysoev.ru nxt_int_t n; 2131234Sigor@sysoev.ru const u_char *s1, *s2; 2141234Sigor@sysoev.ru 2151234Sigor@sysoev.ru s1 = p1; 2161234Sigor@sysoev.ru s2 = p2; 2170Sigor@sysoev.ru 21810Sigor@sysoev.ru while (length-- != 0) { 2190Sigor@sysoev.ru c1 = *s1++; 2200Sigor@sysoev.ru c2 = *s2++; 2210Sigor@sysoev.ru 2220Sigor@sysoev.ru c1 = nxt_lowcase(c1); 2230Sigor@sysoev.ru c2 = nxt_lowcase(c2); 2240Sigor@sysoev.ru 2250Sigor@sysoev.ru n = c1 - c2; 2260Sigor@sysoev.ru 2270Sigor@sysoev.ru if (n != 0) { 2280Sigor@sysoev.ru return n; 2290Sigor@sysoev.ru } 2300Sigor@sysoev.ru } 2310Sigor@sysoev.ru 2320Sigor@sysoev.ru return 0; 2330Sigor@sysoev.ru } 2340Sigor@sysoev.ru 2350Sigor@sysoev.ru 2360Sigor@sysoev.ru /* 2370Sigor@sysoev.ru * nxt_memstrn() is intended for search of static substring "ss" 23810Sigor@sysoev.ru * with known length "length" in string "s" limited by parameter "end". 2390Sigor@sysoev.ru * Zeros are ignored in both strings. 2400Sigor@sysoev.ru */ 2410Sigor@sysoev.ru 2420Sigor@sysoev.ru u_char * 24310Sigor@sysoev.ru nxt_memstrn(const u_char *s, const u_char *end, const char *ss, size_t length) 2440Sigor@sysoev.ru { 2450Sigor@sysoev.ru u_char c1, c2, *s2; 2460Sigor@sysoev.ru 2470Sigor@sysoev.ru s2 = (u_char *) ss; 2480Sigor@sysoev.ru c2 = *s2++; 24910Sigor@sysoev.ru length--; 2500Sigor@sysoev.ru 2510Sigor@sysoev.ru while (s < end) { 2520Sigor@sysoev.ru c1 = *s++; 2530Sigor@sysoev.ru 2540Sigor@sysoev.ru if (c1 == c2) { 2550Sigor@sysoev.ru 25610Sigor@sysoev.ru if (s + length > end) { 2570Sigor@sysoev.ru return NULL; 2580Sigor@sysoev.ru } 2590Sigor@sysoev.ru 26010Sigor@sysoev.ru if (nxt_memcmp(s, s2, length) == 0) { 2610Sigor@sysoev.ru return (u_char *) s - 1; 2620Sigor@sysoev.ru } 2630Sigor@sysoev.ru } 2640Sigor@sysoev.ru } 2650Sigor@sysoev.ru 2660Sigor@sysoev.ru return NULL; 2670Sigor@sysoev.ru } 2680Sigor@sysoev.ru 2690Sigor@sysoev.ru 2700Sigor@sysoev.ru /* 2710Sigor@sysoev.ru * nxt_strcasestrn() is intended for caseless search of static substring 27210Sigor@sysoev.ru * "ss" with known length "length" in string "s" limited by parameter "end". 2730Sigor@sysoev.ru * Zeros are ignored in both strings. 2740Sigor@sysoev.ru */ 2750Sigor@sysoev.ru 2760Sigor@sysoev.ru u_char * 27710Sigor@sysoev.ru nxt_memcasestrn(const u_char *s, const u_char *end, const char *ss, 27810Sigor@sysoev.ru size_t length) 2790Sigor@sysoev.ru { 2800Sigor@sysoev.ru u_char c1, c2, *s2; 2810Sigor@sysoev.ru 2820Sigor@sysoev.ru s2 = (u_char *) ss; 2830Sigor@sysoev.ru c2 = *s2++; 2840Sigor@sysoev.ru c2 = nxt_lowcase(c2); 28510Sigor@sysoev.ru length--; 2860Sigor@sysoev.ru 2870Sigor@sysoev.ru while (s < end) { 2880Sigor@sysoev.ru c1 = *s++; 2890Sigor@sysoev.ru c1 = nxt_lowcase(c1); 2900Sigor@sysoev.ru 2910Sigor@sysoev.ru if (c1 == c2) { 2920Sigor@sysoev.ru 29310Sigor@sysoev.ru if (s + length > end) { 2940Sigor@sysoev.ru return NULL; 2950Sigor@sysoev.ru } 2960Sigor@sysoev.ru 29710Sigor@sysoev.ru if (nxt_memcasecmp(s, s2, length) == 0) { 2980Sigor@sysoev.ru return (u_char *) s - 1; 2990Sigor@sysoev.ru } 3000Sigor@sysoev.ru } 3010Sigor@sysoev.ru } 3020Sigor@sysoev.ru 3030Sigor@sysoev.ru return NULL; 3040Sigor@sysoev.ru } 3050Sigor@sysoev.ru 3060Sigor@sysoev.ru 3070Sigor@sysoev.ru /* 3080Sigor@sysoev.ru * nxt_rstrstrn() is intended to search for static substring "ss" 30910Sigor@sysoev.ru * with known length "length" in string "s" limited by parameter "end" 3100Sigor@sysoev.ru * in reverse order. Zeros are ignored in both strings. 3110Sigor@sysoev.ru */ 3120Sigor@sysoev.ru 3130Sigor@sysoev.ru u_char * 31410Sigor@sysoev.ru nxt_rmemstrn(const u_char *s, const u_char *end, const char *ss, size_t length) 3150Sigor@sysoev.ru { 3160Sigor@sysoev.ru u_char c1, c2; 3170Sigor@sysoev.ru const u_char *s1, *s2; 3180Sigor@sysoev.ru 31910Sigor@sysoev.ru s1 = end - length; 3200Sigor@sysoev.ru s2 = (u_char *) ss; 3210Sigor@sysoev.ru c2 = *s2++; 32210Sigor@sysoev.ru length--; 3230Sigor@sysoev.ru 3240Sigor@sysoev.ru while (s < s1) { 3250Sigor@sysoev.ru c1 = *s1; 3260Sigor@sysoev.ru 3270Sigor@sysoev.ru if (c1 == c2) { 32810Sigor@sysoev.ru if (nxt_memcmp(s1 + 1, s2, length) == 0) { 3290Sigor@sysoev.ru return (u_char *) s1; 3300Sigor@sysoev.ru } 3310Sigor@sysoev.ru } 3320Sigor@sysoev.ru 3330Sigor@sysoev.ru s1--; 3340Sigor@sysoev.ru } 3350Sigor@sysoev.ru 3360Sigor@sysoev.ru return NULL; 3370Sigor@sysoev.ru } 3380Sigor@sysoev.ru 3390Sigor@sysoev.ru 3400Sigor@sysoev.ru size_t 341*2139Sandrew@digital-domain.net nxt_str_strip(const u_char *start, u_char *end) 3420Sigor@sysoev.ru { 3430Sigor@sysoev.ru u_char *p; 3440Sigor@sysoev.ru 3450Sigor@sysoev.ru for (p = end - 1; p >= start; p--) { 346704Sigor@sysoev.ru if (*p != '\r' && *p != '\n') { 3470Sigor@sysoev.ru break; 3480Sigor@sysoev.ru } 3490Sigor@sysoev.ru } 3500Sigor@sysoev.ru 3510Sigor@sysoev.ru return (p + 1) - start; 3520Sigor@sysoev.ru } 353354Svbart@nginx.com 354354Svbart@nginx.com 355354Svbart@nginx.com nxt_int_t 356354Svbart@nginx.com nxt_strverscmp(const u_char *s1, const u_char *s2) 357354Svbart@nginx.com { 358354Svbart@nginx.com u_char c1, c2; 359354Svbart@nginx.com nxt_int_t diff; 360354Svbart@nginx.com 361354Svbart@nginx.com enum { 362354Svbart@nginx.com st_str = 0, 363354Svbart@nginx.com st_num, 364354Svbart@nginx.com st_zero, 365354Svbart@nginx.com st_frac, 366354Svbart@nginx.com } state; 367354Svbart@nginx.com 368354Svbart@nginx.com state = st_str; 369354Svbart@nginx.com 370354Svbart@nginx.com for ( ;; ) { 371354Svbart@nginx.com c1 = *s1++; 372354Svbart@nginx.com c2 = *s2++; 373354Svbart@nginx.com 374354Svbart@nginx.com diff = c1 - c2; 375354Svbart@nginx.com 376354Svbart@nginx.com if (diff != 0) { 377354Svbart@nginx.com break; 378354Svbart@nginx.com } 379354Svbart@nginx.com 380354Svbart@nginx.com if (c1 == '\0') { 381354Svbart@nginx.com return 0; 382354Svbart@nginx.com } 383354Svbart@nginx.com 384354Svbart@nginx.com if (!nxt_isdigit(c1)) { 385354Svbart@nginx.com state = st_str; 386354Svbart@nginx.com continue; 387354Svbart@nginx.com } 388354Svbart@nginx.com 389354Svbart@nginx.com if (state == st_str) { 390354Svbart@nginx.com state = (c1 != '0') ? st_num : st_zero; 391354Svbart@nginx.com continue; 392354Svbart@nginx.com } 393354Svbart@nginx.com 394354Svbart@nginx.com if (state == st_zero && c1 != '0') { 395354Svbart@nginx.com state = st_frac; 396354Svbart@nginx.com continue; 397354Svbart@nginx.com } 398354Svbart@nginx.com } 399354Svbart@nginx.com 400354Svbart@nginx.com switch (state) { 401354Svbart@nginx.com 402354Svbart@nginx.com case st_str: 403354Svbart@nginx.com 404354Svbart@nginx.com if ((u_char) (c1 - '1') > 8 || (u_char) (c2 - '1') > 8) { 405354Svbart@nginx.com return diff; 406354Svbart@nginx.com } 407354Svbart@nginx.com 408354Svbart@nginx.com c1 = *s1++; 409354Svbart@nginx.com c2 = *s2++; 410354Svbart@nginx.com 411354Svbart@nginx.com /* Fall through. */ 412354Svbart@nginx.com 413354Svbart@nginx.com case st_num: 414354Svbart@nginx.com 415354Svbart@nginx.com while (nxt_isdigit(c1) && nxt_isdigit(c2)) { 416354Svbart@nginx.com c1 = *s1++; 417354Svbart@nginx.com c2 = *s2++; 418354Svbart@nginx.com } 419354Svbart@nginx.com 420354Svbart@nginx.com if (nxt_isdigit(c1)) { 421354Svbart@nginx.com return 1; 422354Svbart@nginx.com } 423354Svbart@nginx.com 424354Svbart@nginx.com if (nxt_isdigit(c2)) { 425354Svbart@nginx.com return -1; 426354Svbart@nginx.com } 427354Svbart@nginx.com 428354Svbart@nginx.com return diff; 429354Svbart@nginx.com 430354Svbart@nginx.com case st_zero: 431354Svbart@nginx.com 432354Svbart@nginx.com if (c1 == '0' || c2 == '\0') { 433354Svbart@nginx.com return -1; 434354Svbart@nginx.com } 435354Svbart@nginx.com 436354Svbart@nginx.com if (c2 == '0' || c1 == '\0') { 437354Svbart@nginx.com return 1; 438354Svbart@nginx.com } 439354Svbart@nginx.com 440354Svbart@nginx.com /* Fall through. */ 441354Svbart@nginx.com 442354Svbart@nginx.com case st_frac: 443355Svbart@nginx.com default: 444354Svbart@nginx.com return diff; 445354Svbart@nginx.com } 446354Svbart@nginx.com } 447354Svbart@nginx.com 448354Svbart@nginx.com 449354Svbart@nginx.com nxt_bool_t 450354Svbart@nginx.com nxt_strvers_match(u_char *version, u_char *prefix, size_t length) 451354Svbart@nginx.com { 452354Svbart@nginx.com u_char next, last; 453354Svbart@nginx.com 454362Svbart@nginx.com if (length == 0) { 455362Svbart@nginx.com return 1; 456362Svbart@nginx.com } 457362Svbart@nginx.com 458354Svbart@nginx.com if (nxt_strncmp(version, prefix, length) == 0) { 459354Svbart@nginx.com 460354Svbart@nginx.com next = version[length]; 461354Svbart@nginx.com 462354Svbart@nginx.com if (next == '\0') { 463354Svbart@nginx.com return 1; 464354Svbart@nginx.com } 465354Svbart@nginx.com 466354Svbart@nginx.com last = version[length - 1]; 467354Svbart@nginx.com 468354Svbart@nginx.com if (nxt_isdigit(last) != nxt_isdigit(next)) { 469354Svbart@nginx.com /* This is a version part boundary. */ 470354Svbart@nginx.com return 1; 471354Svbart@nginx.com } 472354Svbart@nginx.com } 473354Svbart@nginx.com 474354Svbart@nginx.com return 0; 475354Svbart@nginx.com } 4761167Svbart@nginx.com 4771167Svbart@nginx.com 4781474Saxel.duch@nginx.com const uint8_t nxt_hex2int[256] 4791431Svbart@nginx.com nxt_aligned(32) = 4801431Svbart@nginx.com { 4811431Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4821431Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4831431Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4841431Svbart@nginx.com 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 16, 16, 16, 16, 16, 4851431Svbart@nginx.com 16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4861431Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4871431Svbart@nginx.com 16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4881431Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4891431Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4901431Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4911431Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4921431Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4931431Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4941431Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4951431Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4961431Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4971431Svbart@nginx.com }; 4981431Svbart@nginx.com 4991431Svbart@nginx.com 5001431Svbart@nginx.com static const uint32_t nxt_uri_escape[] = { 5011431Svbart@nginx.com 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 5021431Svbart@nginx.com 5031431Svbart@nginx.com /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ 5041431Svbart@nginx.com 0xd000002d, /* 1101 0000 0000 0000 0000 0000 0010 1101 */ 5051431Svbart@nginx.com 5061431Svbart@nginx.com /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ 5071431Svbart@nginx.com 0x50000000, /* 0101 0000 0000 0000 0000 0000 0000 0000 */ 5081431Svbart@nginx.com 5091431Svbart@nginx.com /* ~}| {zyx wvut srqp onml kjih gfed cba` */ 5101431Svbart@nginx.com 0xb8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */ 5111431Svbart@nginx.com 5121431Svbart@nginx.com 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 5131431Svbart@nginx.com 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 5141431Svbart@nginx.com 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 5151431Svbart@nginx.com 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 5161431Svbart@nginx.com }; 5171431Svbart@nginx.com 5181431Svbart@nginx.com 5191167Svbart@nginx.com u_char * 5201167Svbart@nginx.com nxt_decode_uri(u_char *dst, u_char *src, size_t length) 5211167Svbart@nginx.com { 5221167Svbart@nginx.com u_char *end, ch; 5231167Svbart@nginx.com uint8_t d0, d1; 5241167Svbart@nginx.com 5251431Svbart@nginx.com nxt_prefetch(&nxt_hex2int['0']); 5261167Svbart@nginx.com 5271167Svbart@nginx.com end = src + length; 5281167Svbart@nginx.com 5291167Svbart@nginx.com while (src < end) { 5301167Svbart@nginx.com ch = *src++; 5311167Svbart@nginx.com 5321167Svbart@nginx.com if (ch == '%') { 5331167Svbart@nginx.com if (nxt_slow_path(end - src < 2)) { 5341167Svbart@nginx.com return NULL; 5351167Svbart@nginx.com } 5361167Svbart@nginx.com 5371431Svbart@nginx.com d0 = nxt_hex2int[*src++]; 5381431Svbart@nginx.com d1 = nxt_hex2int[*src++]; 5391167Svbart@nginx.com 5401167Svbart@nginx.com if (nxt_slow_path((d0 | d1) >= 16)) { 5411167Svbart@nginx.com return NULL; 5421167Svbart@nginx.com } 5431167Svbart@nginx.com 5441167Svbart@nginx.com ch = (d0 << 4) + d1; 5451167Svbart@nginx.com } 5461167Svbart@nginx.com 5471167Svbart@nginx.com *dst++ = ch; 5481167Svbart@nginx.com } 5491167Svbart@nginx.com 5501167Svbart@nginx.com return dst; 5511167Svbart@nginx.com } 5521183Svbart@nginx.com 5531183Svbart@nginx.com 5541474Saxel.duch@nginx.com u_char * 5551474Saxel.duch@nginx.com nxt_decode_uri_plus(u_char *dst, u_char *src, size_t length) 5561474Saxel.duch@nginx.com { 5571474Saxel.duch@nginx.com u_char *end, ch; 5581474Saxel.duch@nginx.com uint8_t d0, d1; 5591474Saxel.duch@nginx.com 5601474Saxel.duch@nginx.com nxt_prefetch(&nxt_hex2int['0']); 5611474Saxel.duch@nginx.com 5621474Saxel.duch@nginx.com end = src + length; 5631474Saxel.duch@nginx.com 5641474Saxel.duch@nginx.com while (src < end) { 5651474Saxel.duch@nginx.com ch = *src++; 5661474Saxel.duch@nginx.com 5671474Saxel.duch@nginx.com switch (ch) { 5681474Saxel.duch@nginx.com case '%': 5691474Saxel.duch@nginx.com if (nxt_slow_path(end - src < 2)) { 5701474Saxel.duch@nginx.com return NULL; 5711474Saxel.duch@nginx.com } 5721474Saxel.duch@nginx.com 5731474Saxel.duch@nginx.com d0 = nxt_hex2int[*src++]; 5741474Saxel.duch@nginx.com d1 = nxt_hex2int[*src++]; 5751474Saxel.duch@nginx.com 5761474Saxel.duch@nginx.com if (nxt_slow_path((d0 | d1) >= 16)) { 5771474Saxel.duch@nginx.com return NULL; 5781474Saxel.duch@nginx.com } 5791474Saxel.duch@nginx.com 5801474Saxel.duch@nginx.com ch = (d0 << 4) + d1; 5811474Saxel.duch@nginx.com break; 5821474Saxel.duch@nginx.com 5831474Saxel.duch@nginx.com case '+': 5841474Saxel.duch@nginx.com ch = ' '; 5851474Saxel.duch@nginx.com break; 5861474Saxel.duch@nginx.com } 5871474Saxel.duch@nginx.com 5881474Saxel.duch@nginx.com *dst++ = ch; 5891474Saxel.duch@nginx.com } 5901474Saxel.duch@nginx.com 5911474Saxel.duch@nginx.com return dst; 5921474Saxel.duch@nginx.com } 5931474Saxel.duch@nginx.com 5941474Saxel.duch@nginx.com 5951183Svbart@nginx.com uintptr_t 5961183Svbart@nginx.com nxt_encode_uri(u_char *dst, u_char *src, size_t length) 5971183Svbart@nginx.com { 5981183Svbart@nginx.com u_char *end; 5991183Svbart@nginx.com nxt_uint_t n; 6001183Svbart@nginx.com 6011183Svbart@nginx.com static const u_char hex[16] = "0123456789ABCDEF"; 6021183Svbart@nginx.com 6031183Svbart@nginx.com end = src + length; 6041183Svbart@nginx.com 6051183Svbart@nginx.com if (dst == NULL) { 6061183Svbart@nginx.com 6071183Svbart@nginx.com /* Find the number of the characters to be escaped. */ 6081183Svbart@nginx.com 6091183Svbart@nginx.com n = 0; 6101183Svbart@nginx.com 6111183Svbart@nginx.com while (src < end) { 6121183Svbart@nginx.com 6131431Svbart@nginx.com if (nxt_uri_escape[*src >> 5] & (1U << (*src & 0x1f))) { 6141183Svbart@nginx.com n++; 6151183Svbart@nginx.com } 6161183Svbart@nginx.com 6171183Svbart@nginx.com src++; 6181183Svbart@nginx.com } 6191183Svbart@nginx.com 6201183Svbart@nginx.com return (uintptr_t) n; 6211183Svbart@nginx.com } 6221183Svbart@nginx.com 6231183Svbart@nginx.com while (src < end) { 6241183Svbart@nginx.com 6251431Svbart@nginx.com if (nxt_uri_escape[*src >> 5] & (1U << (*src & 0x1f))) { 6261183Svbart@nginx.com *dst++ = '%'; 6271183Svbart@nginx.com *dst++ = hex[*src >> 4]; 6281183Svbart@nginx.com *dst++ = hex[*src & 0xf]; 6291183Svbart@nginx.com 6301183Svbart@nginx.com } else { 6311183Svbart@nginx.com *dst++ = *src; 6321183Svbart@nginx.com } 6331183Svbart@nginx.com 6341183Svbart@nginx.com src++; 6351183Svbart@nginx.com } 6361183Svbart@nginx.com 6371183Svbart@nginx.com return (uintptr_t) dst; 6381183Svbart@nginx.com } 6391431Svbart@nginx.com 6401431Svbart@nginx.com 6411431Svbart@nginx.com uintptr_t 6421431Svbart@nginx.com nxt_encode_complex_uri(u_char *dst, u_char *src, size_t length) 6431431Svbart@nginx.com { 6441431Svbart@nginx.com u_char *reserved, *end, ch; 6451431Svbart@nginx.com nxt_uint_t n; 6461431Svbart@nginx.com 6471431Svbart@nginx.com static const u_char hex[16] = "0123456789ABCDEF"; 6481431Svbart@nginx.com 6491431Svbart@nginx.com reserved = (u_char *) "?#\0"; 6501431Svbart@nginx.com 6511431Svbart@nginx.com end = src + length; 6521431Svbart@nginx.com 6531431Svbart@nginx.com if (dst == NULL) { 6541431Svbart@nginx.com 6551431Svbart@nginx.com /* Find the number of the characters to be escaped. */ 6561431Svbart@nginx.com 6571431Svbart@nginx.com n = 0; 6581431Svbart@nginx.com 6591431Svbart@nginx.com while (src < end) { 6601431Svbart@nginx.com ch = *src++; 6611431Svbart@nginx.com 6621431Svbart@nginx.com if (nxt_uri_escape[ch >> 5] & (1U << (ch & 0x1f))) { 6631431Svbart@nginx.com if (ch == reserved[0]) { 6641431Svbart@nginx.com reserved++; 6651431Svbart@nginx.com continue; 6661431Svbart@nginx.com } 6671431Svbart@nginx.com 6681431Svbart@nginx.com if (ch == reserved[1]) { 6691431Svbart@nginx.com reserved += 2; 6701431Svbart@nginx.com continue; 6711431Svbart@nginx.com } 6721431Svbart@nginx.com 6731431Svbart@nginx.com n++; 6741431Svbart@nginx.com } 6751431Svbart@nginx.com } 6761431Svbart@nginx.com 6771431Svbart@nginx.com return (uintptr_t) n; 6781431Svbart@nginx.com } 6791431Svbart@nginx.com 6801431Svbart@nginx.com while (src < end) { 6811431Svbart@nginx.com ch = *src++; 6821431Svbart@nginx.com 6831431Svbart@nginx.com if (nxt_uri_escape[ch >> 5] & (1U << (ch & 0x1f))) { 6841431Svbart@nginx.com if (ch == reserved[0]) { 6851431Svbart@nginx.com reserved++; 6861431Svbart@nginx.com 6871431Svbart@nginx.com } else if (ch == reserved[1]) { 6881431Svbart@nginx.com reserved += 2; 6891431Svbart@nginx.com 6901431Svbart@nginx.com } else { 6911431Svbart@nginx.com *dst++ = '%'; 6921431Svbart@nginx.com *dst++ = hex[ch >> 4]; 6931431Svbart@nginx.com *dst++ = hex[ch & 0xf]; 6941431Svbart@nginx.com continue; 6951431Svbart@nginx.com } 6961431Svbart@nginx.com } 6971431Svbart@nginx.com 6981431Svbart@nginx.com *dst++ = ch; 6991431Svbart@nginx.com } 7001431Svbart@nginx.com 7011431Svbart@nginx.com return (uintptr_t) dst; 7021431Svbart@nginx.com } 7031431Svbart@nginx.com 7041431Svbart@nginx.com 7051431Svbart@nginx.com nxt_bool_t 7061431Svbart@nginx.com nxt_is_complex_uri_encoded(u_char *src, size_t length) 7071431Svbart@nginx.com { 7081431Svbart@nginx.com u_char *reserved, *end, ch; 7091431Svbart@nginx.com uint8_t d0, d1; 7101431Svbart@nginx.com 7111431Svbart@nginx.com reserved = (u_char *) "?#\0"; 7121431Svbart@nginx.com 7131431Svbart@nginx.com for (end = src + length; src < end; src++) { 7141431Svbart@nginx.com ch = *src; 7151431Svbart@nginx.com 7161431Svbart@nginx.com if (nxt_uri_escape[ch >> 5] & (1U << (ch & 0x1f))) { 7171431Svbart@nginx.com if (ch == '%') { 7181431Svbart@nginx.com if (end - src < 2) { 7191431Svbart@nginx.com return 0; 7201431Svbart@nginx.com } 7211431Svbart@nginx.com 7221431Svbart@nginx.com d0 = nxt_hex2int[*++src]; 7231431Svbart@nginx.com d1 = nxt_hex2int[*++src]; 7241431Svbart@nginx.com 7251431Svbart@nginx.com if ((d0 | d1) >= 16) { 7261431Svbart@nginx.com return 0; 7271431Svbart@nginx.com } 7281431Svbart@nginx.com 7291431Svbart@nginx.com continue; 7301431Svbart@nginx.com } 7311431Svbart@nginx.com 7321431Svbart@nginx.com if (ch == reserved[0]) { 7331431Svbart@nginx.com reserved++; 7341431Svbart@nginx.com continue; 7351431Svbart@nginx.com } 7361431Svbart@nginx.com 7371431Svbart@nginx.com if (ch == reserved[1]) { 7381431Svbart@nginx.com reserved += 2; 7391431Svbart@nginx.com continue; 7401431Svbart@nginx.com } 7411431Svbart@nginx.com 7421431Svbart@nginx.com return 0; 7431431Svbart@nginx.com } 7441431Svbart@nginx.com } 7451431Svbart@nginx.com 7461431Svbart@nginx.com return 1; 7471431Svbart@nginx.com } 7481975Svbart@nginx.com 7491975Svbart@nginx.com 7501975Svbart@nginx.com ssize_t 7511975Svbart@nginx.com nxt_base64_decode(u_char *dst, u_char *src, size_t length) 7521975Svbart@nginx.com { 7531975Svbart@nginx.com u_char *end, *p; 7541975Svbart@nginx.com size_t pad; 7551975Svbart@nginx.com uint8_t v1, v2, v3, v4; 7561975Svbart@nginx.com 7571975Svbart@nginx.com static const uint8_t decode[] = { 7581975Svbart@nginx.com 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 7591975Svbart@nginx.com 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 7601975Svbart@nginx.com 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 62, 77, 77, 77, 63, 7611975Svbart@nginx.com 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 77, 77, 77, 77, 77, 77, 7621975Svbart@nginx.com 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7631975Svbart@nginx.com 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 77, 77, 77, 77, 77, 7641975Svbart@nginx.com 77, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 7651975Svbart@nginx.com 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 77, 77, 77, 77, 77, 7661975Svbart@nginx.com 7671975Svbart@nginx.com 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 7681975Svbart@nginx.com 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 7691975Svbart@nginx.com 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 7701975Svbart@nginx.com 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 7711975Svbart@nginx.com 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 7721975Svbart@nginx.com 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 7731975Svbart@nginx.com 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 7741975Svbart@nginx.com 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77 7751975Svbart@nginx.com }; 7761975Svbart@nginx.com 7771975Svbart@nginx.com end = src + length; 7781975Svbart@nginx.com pad = (4 - (length % 4)) % 4; 7791975Svbart@nginx.com 7801975Svbart@nginx.com if (dst == NULL) { 7811975Svbart@nginx.com if (pad > 2) { 7821975Svbart@nginx.com return NXT_ERROR; 7831975Svbart@nginx.com } 7841975Svbart@nginx.com 7851975Svbart@nginx.com while (src < end) { 7861975Svbart@nginx.com if (decode[*src] != 77) { 7871975Svbart@nginx.com src++; 7881975Svbart@nginx.com continue; 7891975Svbart@nginx.com } 7901975Svbart@nginx.com 7911975Svbart@nginx.com if (pad == 0) { 7921975Svbart@nginx.com pad = end - src; 7931975Svbart@nginx.com 7941975Svbart@nginx.com if ((pad == 1 || (pad == 2 && src[1] == '=')) && src[0] == '=') 7951975Svbart@nginx.com { 7961975Svbart@nginx.com break; 7971975Svbart@nginx.com } 7981975Svbart@nginx.com } 7991975Svbart@nginx.com 8001975Svbart@nginx.com return NXT_ERROR; 8011975Svbart@nginx.com } 8021975Svbart@nginx.com 8031975Svbart@nginx.com return (length + 3) / 4 * 3 - pad; 8041975Svbart@nginx.com } 8051975Svbart@nginx.com 8061975Svbart@nginx.com nxt_assert(length != 0); 8071975Svbart@nginx.com 8081975Svbart@nginx.com if (pad == 0) { 8091975Svbart@nginx.com pad = (end[-1] == '=') + (end[-2] == '='); 8101975Svbart@nginx.com end -= (pad + 3) & 4; 8111975Svbart@nginx.com 8121975Svbart@nginx.com } else { 8131975Svbart@nginx.com end -= 4 - pad; 8141975Svbart@nginx.com } 8151975Svbart@nginx.com 8161975Svbart@nginx.com p = dst; 8171975Svbart@nginx.com 8181975Svbart@nginx.com while (src < end) { 8191975Svbart@nginx.com v1 = decode[src[0]]; 8201975Svbart@nginx.com v2 = decode[src[1]]; 8211975Svbart@nginx.com v3 = decode[src[2]]; 8221975Svbart@nginx.com v4 = decode[src[3]]; 8231975Svbart@nginx.com 8241975Svbart@nginx.com *p++ = (v1 << 2 | v2 >> 4); 8251975Svbart@nginx.com *p++ = (v2 << 4 | v3 >> 2); 8261975Svbart@nginx.com *p++ = (v3 << 6 | v4); 8271975Svbart@nginx.com 8281975Svbart@nginx.com src += 4; 8291975Svbart@nginx.com } 8301975Svbart@nginx.com 8311975Svbart@nginx.com if (pad > 0) { 8321975Svbart@nginx.com v1 = decode[src[0]]; 8331975Svbart@nginx.com v2 = decode[src[1]]; 8341975Svbart@nginx.com 8351975Svbart@nginx.com *p++ = (v1 << 2 | v2 >> 4); 8361975Svbart@nginx.com 8371975Svbart@nginx.com if (pad == 1) { 8381975Svbart@nginx.com v3 = decode[src[2]]; 8391975Svbart@nginx.com *p++ = (v2 << 4 | v3 >> 2); 8401975Svbart@nginx.com } 8411975Svbart@nginx.com } 8421975Svbart@nginx.com 8431975Svbart@nginx.com return (p - dst); 8441975Svbart@nginx.com } 845