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 *
nxt_str_alloc(nxt_mp_t * mp,size_t length)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 *
nxt_str_dup(nxt_mp_t * mp,nxt_str_t * dst,const nxt_str_t * src)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 *
nxt_str_cstrz(nxt_mp_t * mp,const nxt_str_t * src)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
nxt_memcpy_lowcase(u_char * dst,const u_char * src,size_t length)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
nxt_memcpy_upcase(u_char * dst,const u_char * src,size_t length)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 *
nxt_cpystr(u_char * dst,const u_char * src)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 *
nxt_cpystrn(u_char * dst,const u_char * src,size_t length)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
nxt_strcasecmp(const u_char * s1,const u_char * s2)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
nxt_strncasecmp(const u_char * s1,const u_char * s2,size_t length)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
nxt_memcasecmp(const void * p1,const void * p2,size_t length)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 *
nxt_memstrn(const u_char * s,const u_char * end,const char * ss,size_t length)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
260*2231Salx@nginx.com if (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 *
nxt_memcasestrn(const u_char * s,const u_char * end,const char * ss,size_t length)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 *
nxt_rmemstrn(const u_char * s,const u_char * end,const char * ss,size_t length)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) {
328*2231Salx@nginx.com if (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
nxt_str_strip(const u_char * start,u_char * end)3412139Sandrew@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
nxt_strverscmp(const u_char * s1,const u_char * s2)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
nxt_strvers_match(u_char * version,u_char * prefix,size_t length)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 *
nxt_decode_uri(u_char * dst,u_char * src,size_t length)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 *
nxt_decode_uri_plus(u_char * dst,u_char * src,size_t length)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
nxt_encode_uri(u_char * dst,u_char * src,size_t length)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
nxt_encode_complex_uri(u_char * dst,u_char * src,size_t length)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
nxt_is_complex_uri_encoded(u_char * src,size_t length)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
nxt_base64_decode(u_char * dst,u_char * src,size_t length)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