Mercurial > hg > nginx-vendor-0-8
comparison 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 |
comparison
equal
deleted
inserted
replaced
9:77eee314ddbd | 10:46833bd150cb |
---|---|
28 } | 28 } |
29 | 29 |
30 | 30 |
31 /* | 31 /* |
32 * supported formats: | 32 * supported formats: |
33 * %[0][width]O off_t | 33 * %[0][width]O off_t |
34 * %[0][width]T time_t | 34 * %[0][width]T time_t |
35 * %[0][width]S ssize_t | 35 * %[0][width][u][x|X]z ssize_t/size_t |
36 * %[0][width]uS size_t | 36 * %[0][width][u][x|X]d int/u_int |
37 * %[0][width]uxS size_t in hex | 37 * %[0][width][u][x|X]l long |
38 * %[0][width]l long | 38 * %[0][width|m][u][x|X]i ngx_int_t/ngx_uint_t |
39 * %[0][width]d int | 39 * %[0][width][u][x|X]D int32_t/uint32_t |
40 * %[0][width]i ngx_int_t | 40 * %[0][width][u][x|X]L int64_t/uint64_t |
41 * %[0][width]ui ngx_uint_t | 41 * %P ngx_pid_t |
42 * %[0][width]uxi ngx_uint_t in hex | 42 * %r rlim_t |
43 * %s null-terminated string | 43 * %p pointer |
44 * %c char | 44 * %V pointer to ngx_str_t |
45 * %% % | 45 * %s null-terminated string |
46 * %Z '\0' | |
47 * %c char | |
48 * %% % | |
46 * | 49 * |
50 * TODO: | |
51 * %M ngx_msec_t | |
52 * %A ngx_atomic_t | |
53 * | |
54 * reserved: | |
55 * %t ptrdiff_t | |
56 * %S null-teminated wchar string | |
57 * %C wchar | |
47 */ | 58 */ |
48 | 59 |
49 u_char *ngx_sprintf(u_char *buf, char *fmt, ...) | 60 |
50 { | 61 u_char *ngx_sprintf(u_char *buf, const char *fmt, ...) |
51 u_char *p, c, temp[NGX_MAX_INT_LEN]; | 62 { |
52 int d; | 63 u_char *p; |
53 long l; | 64 va_list args; |
54 off_t offset; | 65 |
55 size_t size, len; | 66 va_start(args, fmt); |
56 ssize_t ssize; | 67 p = ngx_vsnprintf(buf, /* STUB */ 65536, fmt, args); |
57 time_t sec; | 68 va_end(args); |
58 va_list arg; | 69 |
59 ngx_int_t i; | 70 return p; |
60 ngx_uint_t ui, zero, width, sign, hexadecimal; | 71 } |
61 static u_char hex[] = "0123456789abcdef"; | 72 |
62 | 73 |
63 va_start(arg, fmt); | 74 u_char *ngx_snprintf(u_char *buf, size_t max, const char *fmt, ...) |
64 | 75 { |
65 while (*fmt) { | 76 u_char *p; |
77 va_list args; | |
78 | |
79 va_start(args, fmt); | |
80 p = ngx_vsnprintf(buf, max, fmt, args); | |
81 va_end(args); | |
82 | |
83 return p; | |
84 } | |
85 | |
86 | |
87 u_char *ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args) | |
88 { | |
89 u_char *p, zero, *last, temp[NGX_MAX_INT_LEN]; | |
90 int d; | |
91 size_t len; | |
92 uint32_t ui32; | |
93 int64_t i64; | |
94 uint64_t ui64; | |
95 ngx_str_t *s; | |
96 ngx_uint_t width, sign, hexadecimal; | |
97 static u_char hex[] = "0123456789abcdef"; | |
98 static u_char HEX[] = "0123456789ABCDEF"; | |
99 | |
100 if (max == 0) { | |
101 return buf; | |
102 } | |
103 | |
104 last = buf + max; | |
105 | |
106 while (*fmt && buf < last) { | |
107 | |
108 /* | |
109 * "buf < last" means that we could copy at least one character: | |
110 * the plain character, "%%", "%c", and minus without the checking | |
111 */ | |
112 | |
66 if (*fmt == '%') { | 113 if (*fmt == '%') { |
67 | 114 |
68 zero = (*++fmt == '0') ? 1 : 0; | 115 i64 = 0; |
116 ui64 = 0; | |
117 | |
118 zero = (u_char) ((*++fmt == '0') ? '0' : ' '); | |
69 width = 0; | 119 width = 0; |
70 sign = 1; | 120 sign = 1; |
71 hexadecimal = 0; | 121 hexadecimal = 0; |
72 | 122 |
73 p = temp + NGX_MAX_INT_LEN; | 123 p = temp + NGX_MAX_INT_LEN; |
83 case 'u': | 133 case 'u': |
84 sign = 0; | 134 sign = 0; |
85 fmt++; | 135 fmt++; |
86 continue; | 136 continue; |
87 | 137 |
138 case 'X': | |
139 hexadecimal = 2; | |
140 sign = 0; | |
141 fmt++; | |
142 continue; | |
143 | |
88 case 'x': | 144 case 'x': |
89 hexadecimal = 1; | 145 hexadecimal = 1; |
146 sign = 0; | |
90 fmt++; | 147 fmt++; |
91 continue; | 148 continue; |
92 | 149 |
93 default: | 150 default: |
94 break; | 151 break; |
98 } | 155 } |
99 | 156 |
100 | 157 |
101 switch (*fmt) { | 158 switch (*fmt) { |
102 | 159 |
160 case 'V': | |
161 s = va_arg(args, ngx_str_t *); | |
162 | |
163 len = (buf + s->len < last) ? s->len : (size_t) (last - buf); | |
164 buf = ngx_cpymem(buf, s->data, len); | |
165 fmt++; | |
166 | |
167 continue; | |
168 | |
169 case 's': | |
170 p = va_arg(args, u_char *); | |
171 | |
172 while (*p && buf < last) { | |
173 *buf++ = *p++; | |
174 } | |
175 fmt++; | |
176 | |
177 continue; | |
178 | |
103 case 'O': | 179 case 'O': |
104 offset = va_arg(arg, off_t); | 180 i64 = (int64_t) va_arg(args, off_t); |
105 | 181 sign = 1; |
106 if (offset < 0) { | 182 break; |
107 *buf++ = '-'; | 183 |
108 offset = -offset; | 184 case 'P': |
109 } | 185 i64 = (int64_t) va_arg(args, ngx_pid_t); |
110 | 186 sign = 1; |
111 do { | |
112 *--p = (u_char) (offset % 10 + '0'); | |
113 } while (offset /= 10); | |
114 | |
115 break; | 187 break; |
116 | 188 |
117 case 'T': | 189 case 'T': |
118 sec = va_arg(arg, time_t); | 190 i64 = (int64_t) va_arg(args, time_t); |
119 | 191 sign = 1; |
120 if (sec < 0) { | 192 break; |
121 *buf++ = '-'; | 193 |
122 sec = -sec; | 194 case 'z': |
123 } | |
124 | |
125 do { | |
126 *--p = (u_char) (sec % 10 + '0'); | |
127 } while (sec /= 10); | |
128 | |
129 break; | |
130 | |
131 case 'S': | |
132 if (sign) { | 195 if (sign) { |
133 ssize = va_arg(arg, ssize_t); | 196 i64 = (int64_t) va_arg(args, ssize_t); |
134 | |
135 if (ssize < 0) { | |
136 *buf++ = '-'; | |
137 size = (size_t) -ssize; | |
138 | |
139 } else { | |
140 size = (size_t) ssize; | |
141 } | |
142 | |
143 } else { | 197 } else { |
144 size = va_arg(arg, size_t); | 198 ui64 = (uint64_t) va_arg(args, size_t); |
145 } | 199 } |
146 | |
147 if (hexadecimal) { | |
148 do { | |
149 *--p = hex[size & 0xf]; | |
150 } while (size >>= 4); | |
151 | |
152 } else { | |
153 do { | |
154 *--p = (u_char) (size % 10 + '0'); | |
155 } while (size /= 10); | |
156 } | |
157 | |
158 break; | |
159 | |
160 case 'l': | |
161 l = va_arg(arg, long); | |
162 | |
163 if (l < 0) { | |
164 *buf++ = '-'; | |
165 l = -l; | |
166 } | |
167 | |
168 do { | |
169 *--p = (u_char) (l % 10 + '0'); | |
170 } while (l /= 10); | |
171 | |
172 break; | |
173 | |
174 case 'd': | |
175 d = va_arg(arg, int); | |
176 | |
177 if (d < 0) { | |
178 *buf++ = '-'; | |
179 d = -d; | |
180 } | |
181 | |
182 do { | |
183 *--p = (u_char) (d % 10 + '0'); | |
184 } while (d /= 10); | |
185 | |
186 break; | 200 break; |
187 | 201 |
188 case 'i': | 202 case 'i': |
189 if (sign) { | 203 if (sign) { |
190 i = va_arg(arg, ngx_int_t); | 204 i64 = (int64_t) va_arg(args, ngx_int_t); |
191 | |
192 if (i < 0) { | |
193 *buf++ = '-'; | |
194 ui = (ngx_uint_t) -i; | |
195 | |
196 } else { | |
197 ui = (ngx_uint_t) i; | |
198 } | |
199 | |
200 } else { | 205 } else { |
201 ui = va_arg(arg, ngx_uint_t); | 206 ui64 = (uint64_t) va_arg(args, ngx_uint_t); |
202 } | 207 } |
203 | 208 break; |
204 if (hexadecimal) { | 209 |
205 do { | 210 case 'd': |
206 *--p = hex[ui & 0xf]; | 211 if (sign) { |
207 } while (ui >>= 4); | 212 i64 = (int64_t) va_arg(args, int); |
208 | |
209 } else { | 213 } else { |
210 do { | 214 ui64 = (uint64_t) va_arg(args, u_int); |
211 *--p = (u_char) (ui % 10 + '0'); | 215 } |
212 } while (ui /= 10); | 216 break; |
213 } | 217 |
214 | 218 case 'l': |
215 break; | 219 if (sign) { |
216 | 220 i64 = (int64_t) va_arg(args, long); |
217 case 's': | 221 } else { |
218 p = va_arg(arg, u_char *); | 222 ui64 = (uint64_t) va_arg(args, u_long); |
219 | 223 } |
220 while (*p) { | 224 break; |
221 *buf++ = *p++; | 225 |
222 } | 226 case 'D': |
227 if (sign) { | |
228 i64 = (int64_t) va_arg(args, int32_t); | |
229 } else { | |
230 ui64 = (uint64_t) va_arg(args, uint32_t); | |
231 } | |
232 break; | |
233 | |
234 case 'L': | |
235 if (sign) { | |
236 i64 = va_arg(args, int64_t); | |
237 } else { | |
238 ui64 = va_arg(args, uint64_t); | |
239 } | |
240 break; | |
241 | |
242 #if !(NGX_WIN32) | |
243 case 'r': | |
244 i64 = (int64_t) va_arg(args, rlim_t); | |
245 sign = 1; | |
246 break; | |
247 #endif | |
248 | |
249 case 'p': | |
250 ui64 = (uintptr_t) va_arg(args, void *); | |
251 hexadecimal = 2; | |
252 sign = 0; | |
253 zero = '0'; | |
254 width = 8; | |
255 break; | |
256 | |
257 case 'c': | |
258 d = va_arg(args, int); | |
259 *buf++ = (u_char) (d & 0xff); | |
223 fmt++; | 260 fmt++; |
224 | 261 |
225 continue; | 262 continue; |
226 | 263 |
227 case 'c': | 264 case 'Z': |
228 d = va_arg(arg, int); | 265 *buf++ = '\0'; |
229 *buf++ = (u_char) (d & 0xff); | |
230 fmt++; | 266 fmt++; |
231 | 267 |
232 continue; | 268 continue; |
233 | 269 |
234 case '%': | 270 case '%': |
241 *buf++ = *fmt++; | 277 *buf++ = *fmt++; |
242 | 278 |
243 continue; | 279 continue; |
244 } | 280 } |
245 | 281 |
282 if (sign) { | |
283 if (i64 < 0) { | |
284 *buf++ = '-'; | |
285 ui64 = (uint64_t) -i64; | |
286 | |
287 } else { | |
288 ui64 = (uint64_t) i64; | |
289 } | |
290 } | |
291 | |
292 if (hexadecimal == 1) { | |
293 do { | |
294 | |
295 /* the "(uint32_t)" cast disables the BCC's warning */ | |
296 *--p = hex[(uint32_t) (ui64 & 0xf)]; | |
297 | |
298 } while (ui64 >>= 4); | |
299 | |
300 } else if (hexadecimal == 2) { | |
301 do { | |
302 | |
303 /* the "(uint32_t)" cast disables the BCC's warning */ | |
304 *--p = HEX[(uint32_t) (ui64 & 0xf)]; | |
305 | |
306 } while (ui64 >>= 4); | |
307 | |
308 } else if (ui64 <= NGX_MAX_UINT32_VALUE) { | |
309 | |
310 /* | |
311 * To divide 64-bit number and to find the remainder | |
312 * on the x86 platform gcc and icc call the libc functions | |
313 * [u]divdi3() and [u]moddi3(), they call another function | |
314 * in return. On FreeBSD it is the qdivrem() function, | |
315 * its source code is about 170 lines of the code. | |
316 * The glibc counterpart is about 150 lines of the code. | |
317 * | |
318 * For 32-bit numbers gcc and icc use the inlined | |
319 * multiplication and shifts. For example, unsigned | |
320 * "i32 / 10" is compiled to "(i32 * 0xCCCCCCCD) >> 35". | |
321 */ | |
322 | |
323 ui32 = (uint32_t) ui64; | |
324 | |
325 do { | |
326 *--p = (u_char) (ui32 % 10 + '0'); | |
327 } while (ui32 /= 10); | |
328 | |
329 } else { | |
330 do { | |
331 *--p = (u_char) (ui64 % 10 + '0'); | |
332 } while (ui64 /= 10); | |
333 } | |
334 | |
246 len = (temp + NGX_MAX_INT_LEN) - p; | 335 len = (temp + NGX_MAX_INT_LEN) - p; |
247 | 336 |
248 c = (u_char) (zero ? '0' : ' '); | 337 while (len++ < width && buf < last) { |
249 | 338 *buf++ = zero; |
250 while (len++ < width) { | 339 } |
251 *buf++ = c; | 340 |
252 } | 341 len = (temp + NGX_MAX_INT_LEN) - p; |
253 | 342 if (buf + len > last) { |
254 buf = ngx_cpymem(buf, p, ((temp + NGX_MAX_INT_LEN) - p)); | 343 len = last - buf; |
344 } | |
345 | |
346 buf = ngx_cpymem(buf, p, len); | |
255 | 347 |
256 fmt++; | 348 fmt++; |
257 | 349 |
258 } else { | 350 } else { |
259 *buf++ = *fmt++; | 351 *buf++ = *fmt++; |
260 } | 352 } |
261 } | 353 } |
262 | |
263 va_end(arg); | |
264 | |
265 *buf = '\0'; | |
266 | 354 |
267 return buf; | 355 return buf; |
268 } | 356 } |
269 | 357 |
270 | 358 |
503 | 591 |
504 return NGX_OK; | 592 return NGX_OK; |
505 } | 593 } |
506 | 594 |
507 | 595 |
508 ngx_int_t ngx_escape_uri(u_char *dst, u_char *src, size_t size) | 596 ngx_uint_t ngx_escape_uri(u_char *dst, u_char *src, size_t size, |
509 { | 597 ngx_uint_t type) |
510 ngx_int_t n; | 598 { |
511 ngx_uint_t i; | 599 ngx_uint_t i, n; |
600 uint32_t *escape; | |
512 static u_char hex[] = "0123456789abcdef"; | 601 static u_char hex[] = "0123456789abcdef"; |
513 static uint32_t escape[] = | 602 |
603 static uint32_t uri[] = | |
514 { 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ | 604 { 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ |
515 | 605 |
516 /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ | 606 /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ |
517 0x80000021, /* 1000 0000 0000 0000 0000 0000 0010 0001 */ | 607 0x80000021, /* 1000 0000 0000 0000 0000 0000 0010 0001 */ |
518 | 608 |
524 | 614 |
525 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ | 615 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ |
526 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ | 616 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ |
527 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ | 617 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ |
528 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ }; | 618 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ }; |
619 | |
620 static uint32_t html[] = | |
621 { 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ | |
622 | |
623 /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ | |
624 0x80000021, /* 0000 0000 0000 0000 0000 0000 1010 0101 */ | |
625 | |
626 /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ | |
627 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ | |
628 | |
629 /* ~}| {zyx wvut srqp onml kjih gfed cba` */ | |
630 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ | |
631 | |
632 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ | |
633 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ | |
634 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ | |
635 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ }; | |
636 | |
637 | |
638 if (type == NGX_ESCAPE_HTML) { | |
639 escape = html; | |
640 | |
641 } else { | |
642 escape = uri; | |
643 } | |
529 | 644 |
530 if (dst == NULL) { | 645 if (dst == NULL) { |
531 | 646 |
532 /* find the number of the characters to be escaped */ | 647 /* find the number of the characters to be escaped */ |
533 | 648 |
553 } else { | 668 } else { |
554 *dst++ = *src++; | 669 *dst++ = *src++; |
555 } | 670 } |
556 } | 671 } |
557 | 672 |
558 return NGX_OK; | 673 return 0; |
559 } | 674 } |