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 }