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 * 11310Sigor@sysoev.ru nxt_cpystrn(u_char *dst, const u_char *src, size_t length) 1140Sigor@sysoev.ru { 11510Sigor@sysoev.ru if (length == 0) { 1160Sigor@sysoev.ru return dst; 1170Sigor@sysoev.ru } 1180Sigor@sysoev.ru 11910Sigor@sysoev.ru while (--length != 0) { 1200Sigor@sysoev.ru *dst = *src; 1210Sigor@sysoev.ru 1220Sigor@sysoev.ru if (*dst == '\0') { 1230Sigor@sysoev.ru return dst; 1240Sigor@sysoev.ru } 1250Sigor@sysoev.ru 1260Sigor@sysoev.ru dst++; 1270Sigor@sysoev.ru src++; 1280Sigor@sysoev.ru } 1290Sigor@sysoev.ru 1300Sigor@sysoev.ru *dst = '\0'; 1310Sigor@sysoev.ru 1320Sigor@sysoev.ru return dst; 1330Sigor@sysoev.ru } 1340Sigor@sysoev.ru 1350Sigor@sysoev.ru 1360Sigor@sysoev.ru nxt_int_t 1370Sigor@sysoev.ru nxt_strcasecmp(const u_char *s1, const u_char *s2) 1380Sigor@sysoev.ru { 1390Sigor@sysoev.ru u_char c1, c2; 1400Sigor@sysoev.ru nxt_int_t n; 1410Sigor@sysoev.ru 1420Sigor@sysoev.ru for ( ;; ) { 1430Sigor@sysoev.ru c1 = *s1++; 1440Sigor@sysoev.ru c2 = *s2++; 1450Sigor@sysoev.ru 1460Sigor@sysoev.ru c1 = nxt_lowcase(c1); 1470Sigor@sysoev.ru c2 = nxt_lowcase(c2); 1480Sigor@sysoev.ru 1490Sigor@sysoev.ru n = c1 - c2; 1500Sigor@sysoev.ru 1510Sigor@sysoev.ru if (n != 0) { 1520Sigor@sysoev.ru return n; 1530Sigor@sysoev.ru } 1540Sigor@sysoev.ru 1550Sigor@sysoev.ru if (c1 == 0) { 1560Sigor@sysoev.ru return 0; 1570Sigor@sysoev.ru } 1580Sigor@sysoev.ru } 1590Sigor@sysoev.ru } 1600Sigor@sysoev.ru 1610Sigor@sysoev.ru 1620Sigor@sysoev.ru nxt_int_t 16310Sigor@sysoev.ru nxt_strncasecmp(const u_char *s1, const u_char *s2, size_t length) 1640Sigor@sysoev.ru { 1650Sigor@sysoev.ru u_char c1, c2; 1660Sigor@sysoev.ru nxt_int_t n; 1670Sigor@sysoev.ru 16810Sigor@sysoev.ru while (length-- != 0) { 1690Sigor@sysoev.ru c1 = *s1++; 1700Sigor@sysoev.ru c2 = *s2++; 1710Sigor@sysoev.ru 1720Sigor@sysoev.ru c1 = nxt_lowcase(c1); 1730Sigor@sysoev.ru c2 = nxt_lowcase(c2); 1740Sigor@sysoev.ru 1750Sigor@sysoev.ru n = c1 - c2; 1760Sigor@sysoev.ru 1770Sigor@sysoev.ru if (n != 0) { 1780Sigor@sysoev.ru return n; 1790Sigor@sysoev.ru } 1800Sigor@sysoev.ru 1810Sigor@sysoev.ru if (c1 == 0) { 1820Sigor@sysoev.ru return 0; 1830Sigor@sysoev.ru } 1840Sigor@sysoev.ru } 1850Sigor@sysoev.ru 1860Sigor@sysoev.ru return 0; 1870Sigor@sysoev.ru } 1880Sigor@sysoev.ru 1890Sigor@sysoev.ru 1900Sigor@sysoev.ru nxt_int_t 191*1234Sigor@sysoev.ru nxt_memcasecmp(const void *p1, const void *p2, size_t length) 1920Sigor@sysoev.ru { 193*1234Sigor@sysoev.ru u_char c1, c2; 194*1234Sigor@sysoev.ru nxt_int_t n; 195*1234Sigor@sysoev.ru const u_char *s1, *s2; 196*1234Sigor@sysoev.ru 197*1234Sigor@sysoev.ru s1 = p1; 198*1234Sigor@sysoev.ru s2 = p2; 1990Sigor@sysoev.ru 20010Sigor@sysoev.ru while (length-- != 0) { 2010Sigor@sysoev.ru c1 = *s1++; 2020Sigor@sysoev.ru c2 = *s2++; 2030Sigor@sysoev.ru 2040Sigor@sysoev.ru c1 = nxt_lowcase(c1); 2050Sigor@sysoev.ru c2 = nxt_lowcase(c2); 2060Sigor@sysoev.ru 2070Sigor@sysoev.ru n = c1 - c2; 2080Sigor@sysoev.ru 2090Sigor@sysoev.ru if (n != 0) { 2100Sigor@sysoev.ru return n; 2110Sigor@sysoev.ru } 2120Sigor@sysoev.ru } 2130Sigor@sysoev.ru 2140Sigor@sysoev.ru return 0; 2150Sigor@sysoev.ru } 2160Sigor@sysoev.ru 2170Sigor@sysoev.ru 2180Sigor@sysoev.ru /* 2190Sigor@sysoev.ru * nxt_memstrn() is intended for search of static substring "ss" 22010Sigor@sysoev.ru * with known length "length" in string "s" limited by parameter "end". 2210Sigor@sysoev.ru * Zeros are ignored in both strings. 2220Sigor@sysoev.ru */ 2230Sigor@sysoev.ru 2240Sigor@sysoev.ru u_char * 22510Sigor@sysoev.ru nxt_memstrn(const u_char *s, const u_char *end, const char *ss, size_t length) 2260Sigor@sysoev.ru { 2270Sigor@sysoev.ru u_char c1, c2, *s2; 2280Sigor@sysoev.ru 2290Sigor@sysoev.ru s2 = (u_char *) ss; 2300Sigor@sysoev.ru c2 = *s2++; 23110Sigor@sysoev.ru length--; 2320Sigor@sysoev.ru 2330Sigor@sysoev.ru while (s < end) { 2340Sigor@sysoev.ru c1 = *s++; 2350Sigor@sysoev.ru 2360Sigor@sysoev.ru if (c1 == c2) { 2370Sigor@sysoev.ru 23810Sigor@sysoev.ru if (s + length > end) { 2390Sigor@sysoev.ru return NULL; 2400Sigor@sysoev.ru } 2410Sigor@sysoev.ru 24210Sigor@sysoev.ru if (nxt_memcmp(s, s2, length) == 0) { 2430Sigor@sysoev.ru return (u_char *) s - 1; 2440Sigor@sysoev.ru } 2450Sigor@sysoev.ru } 2460Sigor@sysoev.ru } 2470Sigor@sysoev.ru 2480Sigor@sysoev.ru return NULL; 2490Sigor@sysoev.ru } 2500Sigor@sysoev.ru 2510Sigor@sysoev.ru 2520Sigor@sysoev.ru /* 2530Sigor@sysoev.ru * nxt_strcasestrn() is intended for caseless search of static substring 25410Sigor@sysoev.ru * "ss" with known length "length" in string "s" limited by parameter "end". 2550Sigor@sysoev.ru * Zeros are ignored in both strings. 2560Sigor@sysoev.ru */ 2570Sigor@sysoev.ru 2580Sigor@sysoev.ru u_char * 25910Sigor@sysoev.ru nxt_memcasestrn(const u_char *s, const u_char *end, const char *ss, 26010Sigor@sysoev.ru size_t length) 2610Sigor@sysoev.ru { 2620Sigor@sysoev.ru u_char c1, c2, *s2; 2630Sigor@sysoev.ru 2640Sigor@sysoev.ru s2 = (u_char *) ss; 2650Sigor@sysoev.ru c2 = *s2++; 2660Sigor@sysoev.ru c2 = nxt_lowcase(c2); 26710Sigor@sysoev.ru length--; 2680Sigor@sysoev.ru 2690Sigor@sysoev.ru while (s < end) { 2700Sigor@sysoev.ru c1 = *s++; 2710Sigor@sysoev.ru c1 = nxt_lowcase(c1); 2720Sigor@sysoev.ru 2730Sigor@sysoev.ru if (c1 == c2) { 2740Sigor@sysoev.ru 27510Sigor@sysoev.ru if (s + length > end) { 2760Sigor@sysoev.ru return NULL; 2770Sigor@sysoev.ru } 2780Sigor@sysoev.ru 27910Sigor@sysoev.ru if (nxt_memcasecmp(s, s2, length) == 0) { 2800Sigor@sysoev.ru return (u_char *) s - 1; 2810Sigor@sysoev.ru } 2820Sigor@sysoev.ru } 2830Sigor@sysoev.ru } 2840Sigor@sysoev.ru 2850Sigor@sysoev.ru return NULL; 2860Sigor@sysoev.ru } 2870Sigor@sysoev.ru 2880Sigor@sysoev.ru 2890Sigor@sysoev.ru /* 2900Sigor@sysoev.ru * nxt_rstrstrn() is intended to search for static substring "ss" 29110Sigor@sysoev.ru * with known length "length" in string "s" limited by parameter "end" 2920Sigor@sysoev.ru * in reverse order. Zeros are ignored in both strings. 2930Sigor@sysoev.ru */ 2940Sigor@sysoev.ru 2950Sigor@sysoev.ru u_char * 29610Sigor@sysoev.ru nxt_rmemstrn(const u_char *s, const u_char *end, const char *ss, size_t length) 2970Sigor@sysoev.ru { 2980Sigor@sysoev.ru u_char c1, c2; 2990Sigor@sysoev.ru const u_char *s1, *s2; 3000Sigor@sysoev.ru 30110Sigor@sysoev.ru s1 = end - length; 3020Sigor@sysoev.ru s2 = (u_char *) ss; 3030Sigor@sysoev.ru c2 = *s2++; 30410Sigor@sysoev.ru length--; 3050Sigor@sysoev.ru 3060Sigor@sysoev.ru while (s < s1) { 3070Sigor@sysoev.ru c1 = *s1; 3080Sigor@sysoev.ru 3090Sigor@sysoev.ru if (c1 == c2) { 31010Sigor@sysoev.ru if (nxt_memcmp(s1 + 1, s2, length) == 0) { 3110Sigor@sysoev.ru return (u_char *) s1; 3120Sigor@sysoev.ru } 3130Sigor@sysoev.ru } 3140Sigor@sysoev.ru 3150Sigor@sysoev.ru s1--; 3160Sigor@sysoev.ru } 3170Sigor@sysoev.ru 3180Sigor@sysoev.ru return NULL; 3190Sigor@sysoev.ru } 3200Sigor@sysoev.ru 3210Sigor@sysoev.ru 3220Sigor@sysoev.ru size_t 3230Sigor@sysoev.ru nxt_str_strip(u_char *start, u_char *end) 3240Sigor@sysoev.ru { 3250Sigor@sysoev.ru u_char *p; 3260Sigor@sysoev.ru 3270Sigor@sysoev.ru for (p = end - 1; p >= start; p--) { 328704Sigor@sysoev.ru if (*p != '\r' && *p != '\n') { 3290Sigor@sysoev.ru break; 3300Sigor@sysoev.ru } 3310Sigor@sysoev.ru } 3320Sigor@sysoev.ru 3330Sigor@sysoev.ru return (p + 1) - start; 3340Sigor@sysoev.ru } 335354Svbart@nginx.com 336354Svbart@nginx.com 337354Svbart@nginx.com nxt_int_t 338354Svbart@nginx.com nxt_strverscmp(const u_char *s1, const u_char *s2) 339354Svbart@nginx.com { 340354Svbart@nginx.com u_char c1, c2; 341354Svbart@nginx.com nxt_int_t diff; 342354Svbart@nginx.com 343354Svbart@nginx.com enum { 344354Svbart@nginx.com st_str = 0, 345354Svbart@nginx.com st_num, 346354Svbart@nginx.com st_zero, 347354Svbart@nginx.com st_frac, 348354Svbart@nginx.com } state; 349354Svbart@nginx.com 350354Svbart@nginx.com state = st_str; 351354Svbart@nginx.com 352354Svbart@nginx.com for ( ;; ) { 353354Svbart@nginx.com c1 = *s1++; 354354Svbart@nginx.com c2 = *s2++; 355354Svbart@nginx.com 356354Svbart@nginx.com diff = c1 - c2; 357354Svbart@nginx.com 358354Svbart@nginx.com if (diff != 0) { 359354Svbart@nginx.com break; 360354Svbart@nginx.com } 361354Svbart@nginx.com 362354Svbart@nginx.com if (c1 == '\0') { 363354Svbart@nginx.com return 0; 364354Svbart@nginx.com } 365354Svbart@nginx.com 366354Svbart@nginx.com if (!nxt_isdigit(c1)) { 367354Svbart@nginx.com state = st_str; 368354Svbart@nginx.com continue; 369354Svbart@nginx.com } 370354Svbart@nginx.com 371354Svbart@nginx.com if (state == st_str) { 372354Svbart@nginx.com state = (c1 != '0') ? st_num : st_zero; 373354Svbart@nginx.com continue; 374354Svbart@nginx.com } 375354Svbart@nginx.com 376354Svbart@nginx.com if (state == st_zero && c1 != '0') { 377354Svbart@nginx.com state = st_frac; 378354Svbart@nginx.com continue; 379354Svbart@nginx.com } 380354Svbart@nginx.com } 381354Svbart@nginx.com 382354Svbart@nginx.com switch (state) { 383354Svbart@nginx.com 384354Svbart@nginx.com case st_str: 385354Svbart@nginx.com 386354Svbart@nginx.com if ((u_char) (c1 - '1') > 8 || (u_char) (c2 - '1') > 8) { 387354Svbart@nginx.com return diff; 388354Svbart@nginx.com } 389354Svbart@nginx.com 390354Svbart@nginx.com c1 = *s1++; 391354Svbart@nginx.com c2 = *s2++; 392354Svbart@nginx.com 393354Svbart@nginx.com /* Fall through. */ 394354Svbart@nginx.com 395354Svbart@nginx.com case st_num: 396354Svbart@nginx.com 397354Svbart@nginx.com while (nxt_isdigit(c1) && nxt_isdigit(c2)) { 398354Svbart@nginx.com c1 = *s1++; 399354Svbart@nginx.com c2 = *s2++; 400354Svbart@nginx.com } 401354Svbart@nginx.com 402354Svbart@nginx.com if (nxt_isdigit(c1)) { 403354Svbart@nginx.com return 1; 404354Svbart@nginx.com } 405354Svbart@nginx.com 406354Svbart@nginx.com if (nxt_isdigit(c2)) { 407354Svbart@nginx.com return -1; 408354Svbart@nginx.com } 409354Svbart@nginx.com 410354Svbart@nginx.com return diff; 411354Svbart@nginx.com 412354Svbart@nginx.com case st_zero: 413354Svbart@nginx.com 414354Svbart@nginx.com if (c1 == '0' || c2 == '\0') { 415354Svbart@nginx.com return -1; 416354Svbart@nginx.com } 417354Svbart@nginx.com 418354Svbart@nginx.com if (c2 == '0' || c1 == '\0') { 419354Svbart@nginx.com return 1; 420354Svbart@nginx.com } 421354Svbart@nginx.com 422354Svbart@nginx.com /* Fall through. */ 423354Svbart@nginx.com 424354Svbart@nginx.com case st_frac: 425355Svbart@nginx.com default: 426354Svbart@nginx.com return diff; 427354Svbart@nginx.com } 428354Svbart@nginx.com } 429354Svbart@nginx.com 430354Svbart@nginx.com 431354Svbart@nginx.com nxt_bool_t 432354Svbart@nginx.com nxt_strvers_match(u_char *version, u_char *prefix, size_t length) 433354Svbart@nginx.com { 434354Svbart@nginx.com u_char next, last; 435354Svbart@nginx.com 436362Svbart@nginx.com if (length == 0) { 437362Svbart@nginx.com return 1; 438362Svbart@nginx.com } 439362Svbart@nginx.com 440354Svbart@nginx.com if (nxt_strncmp(version, prefix, length) == 0) { 441354Svbart@nginx.com 442354Svbart@nginx.com next = version[length]; 443354Svbart@nginx.com 444354Svbart@nginx.com if (next == '\0') { 445354Svbart@nginx.com return 1; 446354Svbart@nginx.com } 447354Svbart@nginx.com 448354Svbart@nginx.com last = version[length - 1]; 449354Svbart@nginx.com 450354Svbart@nginx.com if (nxt_isdigit(last) != nxt_isdigit(next)) { 451354Svbart@nginx.com /* This is a version part boundary. */ 452354Svbart@nginx.com return 1; 453354Svbart@nginx.com } 454354Svbart@nginx.com } 455354Svbart@nginx.com 456354Svbart@nginx.com return 0; 457354Svbart@nginx.com } 4581167Svbart@nginx.com 4591167Svbart@nginx.com 4601167Svbart@nginx.com u_char * 4611167Svbart@nginx.com nxt_decode_uri(u_char *dst, u_char *src, size_t length) 4621167Svbart@nginx.com { 4631167Svbart@nginx.com u_char *end, ch; 4641167Svbart@nginx.com uint8_t d0, d1; 4651167Svbart@nginx.com 4661167Svbart@nginx.com static const uint8_t hex[256] 4671167Svbart@nginx.com nxt_aligned(32) = 4681167Svbart@nginx.com { 4691167Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4701167Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4711167Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4721167Svbart@nginx.com 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 16, 16, 16, 16, 16, 4731167Svbart@nginx.com 16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4741167Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4751167Svbart@nginx.com 16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4761167Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4771167Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4781167Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4791167Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4801167Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4811167Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4821167Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4831167Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4841167Svbart@nginx.com 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4851167Svbart@nginx.com }; 4861167Svbart@nginx.com 4871167Svbart@nginx.com nxt_prefetch(&hex['0']); 4881167Svbart@nginx.com 4891167Svbart@nginx.com end = src + length; 4901167Svbart@nginx.com 4911167Svbart@nginx.com while (src < end) { 4921167Svbart@nginx.com ch = *src++; 4931167Svbart@nginx.com 4941167Svbart@nginx.com if (ch == '%') { 4951167Svbart@nginx.com if (nxt_slow_path(end - src < 2)) { 4961167Svbart@nginx.com return NULL; 4971167Svbart@nginx.com } 4981167Svbart@nginx.com 4991167Svbart@nginx.com d0 = hex[*src++]; 5001167Svbart@nginx.com d1 = hex[*src++]; 5011167Svbart@nginx.com 5021167Svbart@nginx.com if (nxt_slow_path((d0 | d1) >= 16)) { 5031167Svbart@nginx.com return NULL; 5041167Svbart@nginx.com } 5051167Svbart@nginx.com 5061167Svbart@nginx.com ch = (d0 << 4) + d1; 5071167Svbart@nginx.com } 5081167Svbart@nginx.com 5091167Svbart@nginx.com *dst++ = ch; 5101167Svbart@nginx.com } 5111167Svbart@nginx.com 5121167Svbart@nginx.com return dst; 5131167Svbart@nginx.com } 5141183Svbart@nginx.com 5151183Svbart@nginx.com 5161183Svbart@nginx.com uintptr_t 5171183Svbart@nginx.com nxt_encode_uri(u_char *dst, u_char *src, size_t length) 5181183Svbart@nginx.com { 5191183Svbart@nginx.com u_char *end; 5201183Svbart@nginx.com nxt_uint_t n; 5211183Svbart@nginx.com 5221183Svbart@nginx.com static const u_char hex[16] = "0123456789ABCDEF"; 5231183Svbart@nginx.com 5241183Svbart@nginx.com /* " ", "#", "%", "?", %00-%1F, %7F-%FF */ 5251183Svbart@nginx.com 5261183Svbart@nginx.com static const uint32_t escape[] = { 5271183Svbart@nginx.com 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 5281183Svbart@nginx.com 5291183Svbart@nginx.com /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ 5301183Svbart@nginx.com 0x80000029, /* 1000 0000 0000 0000 0000 0000 0010 1001 */ 5311183Svbart@nginx.com 5321183Svbart@nginx.com /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ 5331183Svbart@nginx.com 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ 5341183Svbart@nginx.com 5351183Svbart@nginx.com /* ~}| {zyx wvut srqp onml kjih gfed cba` */ 5361183Svbart@nginx.com 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ 5371183Svbart@nginx.com 5381183Svbart@nginx.com 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 5391183Svbart@nginx.com 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 5401183Svbart@nginx.com 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 5411183Svbart@nginx.com 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 5421183Svbart@nginx.com }; 5431183Svbart@nginx.com 5441183Svbart@nginx.com end = src + length; 5451183Svbart@nginx.com 5461183Svbart@nginx.com if (dst == NULL) { 5471183Svbart@nginx.com 5481183Svbart@nginx.com /* Find the number of the characters to be escaped. */ 5491183Svbart@nginx.com 5501183Svbart@nginx.com n = 0; 5511183Svbart@nginx.com 5521183Svbart@nginx.com while (src < end) { 5531183Svbart@nginx.com 5541183Svbart@nginx.com if (escape[*src >> 5] & (1U << (*src & 0x1f))) { 5551183Svbart@nginx.com n++; 5561183Svbart@nginx.com } 5571183Svbart@nginx.com 5581183Svbart@nginx.com src++; 5591183Svbart@nginx.com } 5601183Svbart@nginx.com 5611183Svbart@nginx.com return (uintptr_t) n; 5621183Svbart@nginx.com } 5631183Svbart@nginx.com 5641183Svbart@nginx.com while (src < end) { 5651183Svbart@nginx.com 5661183Svbart@nginx.com if (escape[*src >> 5] & (1U << (*src & 0x1f))) { 5671183Svbart@nginx.com *dst++ = '%'; 5681183Svbart@nginx.com *dst++ = hex[*src >> 4]; 5691183Svbart@nginx.com *dst++ = hex[*src & 0xf]; 5701183Svbart@nginx.com 5711183Svbart@nginx.com } else { 5721183Svbart@nginx.com *dst++ = *src; 5731183Svbart@nginx.com } 5741183Svbart@nginx.com 5751183Svbart@nginx.com src++; 5761183Svbart@nginx.com } 5771183Svbart@nginx.com 5781183Svbart@nginx.com return (uintptr_t) dst; 5791183Svbart@nginx.com } 580