Mercurial > hg > nginx-vendor-0-6
diff src/core/ngx_string.c @ 10:46833bd150cb NGINX_0_1_5
nginx 0.1.5
*) Bugfix: on Solaris and Linux there may be too many "recvmsg()
returned not enough data" alerts.
*) Bugfix: there were the "writev() failed (22: Invalid argument)"
errors on Solaris in proxy mode without sendfile. On other platforms
that do not support sendfile at all the process got caught in an
endless loop.
*) Bugfix: segmentation fault on Solaris in proxy mode and using
sendfile.
*) Bugfix: segmentation fault on Solaris.
*) Bugfix: on-line upgrade did not work on Linux.
*) Bugfix: the ngx_http_autoindex_module module did not escape the
spaces, the quotes, and the percent signs in the directory listing.
*) Change: the decrease of the copy operations.
*) Feature: the userid_p3p directive.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Thu, 11 Nov 2004 00:00:00 +0300 |
parents | 80ba094c6b3e |
children | 74b1868dd3cd |
line wrap: on
line diff
--- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -30,42 +30,92 @@ u_char *ngx_cpystrn(u_char *dst, u_char /* * supported formats: - * %[0][width]O off_t - * %[0][width]T time_t - * %[0][width]S ssize_t - * %[0][width]uS size_t - * %[0][width]uxS size_t in hex - * %[0][width]l long - * %[0][width]d int - * %[0][width]i ngx_int_t - * %[0][width]ui ngx_uint_t - * %[0][width]uxi ngx_uint_t in hex - * %s null-terminated string - * %c char - * %% % + * %[0][width]O off_t + * %[0][width]T time_t + * %[0][width][u][x|X]z ssize_t/size_t + * %[0][width][u][x|X]d int/u_int + * %[0][width][u][x|X]l long + * %[0][width|m][u][x|X]i ngx_int_t/ngx_uint_t + * %[0][width][u][x|X]D int32_t/uint32_t + * %[0][width][u][x|X]L int64_t/uint64_t + * %P ngx_pid_t + * %r rlim_t + * %p pointer + * %V pointer to ngx_str_t + * %s null-terminated string + * %Z '\0' + * %c char + * %% % * + * TODO: + * %M ngx_msec_t + * %A ngx_atomic_t + * + * reserved: + * %t ptrdiff_t + * %S null-teminated wchar string + * %C wchar */ -u_char *ngx_sprintf(u_char *buf, char *fmt, ...) + +u_char *ngx_sprintf(u_char *buf, const char *fmt, ...) +{ + u_char *p; + va_list args; + + va_start(args, fmt); + p = ngx_vsnprintf(buf, /* STUB */ 65536, fmt, args); + va_end(args); + + return p; +} + + +u_char *ngx_snprintf(u_char *buf, size_t max, const char *fmt, ...) { - u_char *p, c, temp[NGX_MAX_INT_LEN]; - int d; - long l; - off_t offset; - size_t size, len; - ssize_t ssize; - time_t sec; - va_list arg; - ngx_int_t i; - ngx_uint_t ui, zero, width, sign, hexadecimal; - static u_char hex[] = "0123456789abcdef"; + u_char *p; + va_list args; + + va_start(args, fmt); + p = ngx_vsnprintf(buf, max, fmt, args); + va_end(args); + + return p; +} + - va_start(arg, fmt); +u_char *ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args) +{ + u_char *p, zero, *last, temp[NGX_MAX_INT_LEN]; + int d; + size_t len; + uint32_t ui32; + int64_t i64; + uint64_t ui64; + ngx_str_t *s; + ngx_uint_t width, sign, hexadecimal; + static u_char hex[] = "0123456789abcdef"; + static u_char HEX[] = "0123456789ABCDEF"; - while (*fmt) { + if (max == 0) { + return buf; + } + + last = buf + max; + + while (*fmt && buf < last) { + + /* + * "buf < last" means that we could copy at least one character: + * the plain character, "%%", "%c", and minus without the checking + */ + if (*fmt == '%') { - zero = (*++fmt == '0') ? 1 : 0; + i64 = 0; + ui64 = 0; + + zero = (u_char) ((*++fmt == '0') ? '0' : ' '); width = 0; sign = 1; hexadecimal = 0; @@ -85,8 +135,15 @@ u_char *ngx_sprintf(u_char *buf, char *f fmt++; continue; + case 'X': + hexadecimal = 2; + sign = 0; + fmt++; + continue; + case 'x': hexadecimal = 1; + sign = 0; fmt++; continue; @@ -100,137 +157,116 @@ u_char *ngx_sprintf(u_char *buf, char *f switch (*fmt) { - case 'O': - offset = va_arg(arg, off_t); - - if (offset < 0) { - *buf++ = '-'; - offset = -offset; - } - - do { - *--p = (u_char) (offset % 10 + '0'); - } while (offset /= 10); - - break; - - case 'T': - sec = va_arg(arg, time_t); - - if (sec < 0) { - *buf++ = '-'; - sec = -sec; - } - - do { - *--p = (u_char) (sec % 10 + '0'); - } while (sec /= 10); - - break; - - case 'S': - if (sign) { - ssize = va_arg(arg, ssize_t); - - if (ssize < 0) { - *buf++ = '-'; - size = (size_t) -ssize; - - } else { - size = (size_t) ssize; - } - - } else { - size = va_arg(arg, size_t); - } - - if (hexadecimal) { - do { - *--p = hex[size & 0xf]; - } while (size >>= 4); - - } else { - do { - *--p = (u_char) (size % 10 + '0'); - } while (size /= 10); - } - - break; + case 'V': + s = va_arg(args, ngx_str_t *); - case 'l': - l = va_arg(arg, long); - - if (l < 0) { - *buf++ = '-'; - l = -l; - } - - do { - *--p = (u_char) (l % 10 + '0'); - } while (l /= 10); - - break; - - case 'd': - d = va_arg(arg, int); - - if (d < 0) { - *buf++ = '-'; - d = -d; - } - - do { - *--p = (u_char) (d % 10 + '0'); - } while (d /= 10); - - break; + len = (buf + s->len < last) ? s->len : (size_t) (last - buf); + buf = ngx_cpymem(buf, s->data, len); + fmt++; - case 'i': - if (sign) { - i = va_arg(arg, ngx_int_t); - - if (i < 0) { - *buf++ = '-'; - ui = (ngx_uint_t) -i; - - } else { - ui = (ngx_uint_t) i; - } - - } else { - ui = va_arg(arg, ngx_uint_t); - } - - if (hexadecimal) { - do { - *--p = hex[ui & 0xf]; - } while (ui >>= 4); - - } else { - do { - *--p = (u_char) (ui % 10 + '0'); - } while (ui /= 10); - } - - break; + continue; case 's': - p = va_arg(arg, u_char *); + p = va_arg(args, u_char *); - while (*p) { + while (*p && buf < last) { *buf++ = *p++; } fmt++; continue; + case 'O': + i64 = (int64_t) va_arg(args, off_t); + sign = 1; + break; + + case 'P': + i64 = (int64_t) va_arg(args, ngx_pid_t); + sign = 1; + break; + + case 'T': + i64 = (int64_t) va_arg(args, time_t); + sign = 1; + break; + + case 'z': + if (sign) { + i64 = (int64_t) va_arg(args, ssize_t); + } else { + ui64 = (uint64_t) va_arg(args, size_t); + } + break; + + case 'i': + if (sign) { + i64 = (int64_t) va_arg(args, ngx_int_t); + } else { + ui64 = (uint64_t) va_arg(args, ngx_uint_t); + } + break; + + case 'd': + if (sign) { + i64 = (int64_t) va_arg(args, int); + } else { + ui64 = (uint64_t) va_arg(args, u_int); + } + break; + + case 'l': + if (sign) { + i64 = (int64_t) va_arg(args, long); + } else { + ui64 = (uint64_t) va_arg(args, u_long); + } + break; + + case 'D': + if (sign) { + i64 = (int64_t) va_arg(args, int32_t); + } else { + ui64 = (uint64_t) va_arg(args, uint32_t); + } + break; + + case 'L': + if (sign) { + i64 = va_arg(args, int64_t); + } else { + ui64 = va_arg(args, uint64_t); + } + break; + +#if !(NGX_WIN32) + case 'r': + i64 = (int64_t) va_arg(args, rlim_t); + sign = 1; + break; +#endif + + case 'p': + ui64 = (uintptr_t) va_arg(args, void *); + hexadecimal = 2; + sign = 0; + zero = '0'; + width = 8; + break; + case 'c': - d = va_arg(arg, int); + d = va_arg(args, int); *buf++ = (u_char) (d & 0xff); fmt++; continue; + case 'Z': + *buf++ = '\0'; + fmt++; + + continue; + case '%': *buf++ = '%'; fmt++; @@ -243,15 +279,71 @@ u_char *ngx_sprintf(u_char *buf, char *f continue; } + if (sign) { + if (i64 < 0) { + *buf++ = '-'; + ui64 = (uint64_t) -i64; + + } else { + ui64 = (uint64_t) i64; + } + } + + if (hexadecimal == 1) { + do { + + /* the "(uint32_t)" cast disables the BCC's warning */ + *--p = hex[(uint32_t) (ui64 & 0xf)]; + + } while (ui64 >>= 4); + + } else if (hexadecimal == 2) { + do { + + /* the "(uint32_t)" cast disables the BCC's warning */ + *--p = HEX[(uint32_t) (ui64 & 0xf)]; + + } while (ui64 >>= 4); + + } else if (ui64 <= NGX_MAX_UINT32_VALUE) { + + /* + * To divide 64-bit number and to find the remainder + * on the x86 platform gcc and icc call the libc functions + * [u]divdi3() and [u]moddi3(), they call another function + * in return. On FreeBSD it is the qdivrem() function, + * its source code is about 170 lines of the code. + * The glibc counterpart is about 150 lines of the code. + * + * For 32-bit numbers gcc and icc use the inlined + * multiplication and shifts. For example, unsigned + * "i32 / 10" is compiled to "(i32 * 0xCCCCCCCD) >> 35". + */ + + ui32 = (uint32_t) ui64; + + do { + *--p = (u_char) (ui32 % 10 + '0'); + } while (ui32 /= 10); + + } else { + do { + *--p = (u_char) (ui64 % 10 + '0'); + } while (ui64 /= 10); + } + len = (temp + NGX_MAX_INT_LEN) - p; - c = (u_char) (zero ? '0' : ' '); - - while (len++ < width) { - *buf++ = c; + while (len++ < width && buf < last) { + *buf++ = zero; } - buf = ngx_cpymem(buf, p, ((temp + NGX_MAX_INT_LEN) - p)); + len = (temp + NGX_MAX_INT_LEN) - p; + if (buf + len > last) { + len = last - buf; + } + + buf = ngx_cpymem(buf, p, len); fmt++; @@ -260,10 +352,6 @@ u_char *ngx_sprintf(u_char *buf, char *f } } - va_end(arg); - - *buf = '\0'; - return buf; } @@ -505,12 +593,14 @@ ngx_int_t ngx_decode_base64(ngx_str_t *d } -ngx_int_t ngx_escape_uri(u_char *dst, u_char *src, size_t size) +ngx_uint_t ngx_escape_uri(u_char *dst, u_char *src, size_t size, + ngx_uint_t type) { - ngx_int_t n; - ngx_uint_t i; + ngx_uint_t i, n; + uint32_t *escape; static u_char hex[] = "0123456789abcdef"; - static uint32_t escape[] = + + static uint32_t uri[] = { 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ @@ -527,6 +617,31 @@ ngx_int_t ngx_escape_uri(u_char *dst, u_ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ }; + static uint32_t html[] = + { 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + + /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ + 0x80000021, /* 0000 0000 0000 0000 0000 0000 1010 0101 */ + + /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + + /* ~}| {zyx wvut srqp onml kjih gfed cba` */ + 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ + + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ }; + + + if (type == NGX_ESCAPE_HTML) { + escape = html; + + } else { + escape = uri; + } + if (dst == NULL) { /* find the number of the characters to be escaped */ @@ -555,5 +670,5 @@ ngx_int_t ngx_escape_uri(u_char *dst, u_ } } - return NGX_OK; + return 0; }