blob: 29dc39f5aa813ff0d552865409d96a99e4a149f5 [file] [log] [blame]
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00001
Igor Sysoevd90282d2004-09-28 08:34:51 +00002/*
Igor Sysoevff8da912004-09-29 16:00:49 +00003 * Copyright (C) Igor Sysoev
Igor Sysoevd90282d2004-09-28 08:34:51 +00004 */
5
6
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00007#include <ngx_config.h>
Igor Sysoevdc479b42003-03-20 16:09:44 +00008#include <ngx_core.h>
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00009
10
Igor Sysoevd039a2e2005-02-22 14:40:13 +000011u_char *
12ngx_cpystrn(u_char *dst, u_char *src, size_t n)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000013{
Igor Sysoev3d09c8d2003-05-06 17:03:16 +000014 if (n == 0) {
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000015 return dst;
Igor Sysoev3d09c8d2003-05-06 17:03:16 +000016 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000017
Igor Sysoev4959ec42005-05-23 12:07:45 +000018 for ( /* void */ ; --n; dst++, src++) {
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000019 *dst = *src;
20
Igor Sysoev3d09c8d2003-05-06 17:03:16 +000021 if (*dst == '\0') {
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000022 return dst;
Igor Sysoev3d09c8d2003-05-06 17:03:16 +000023 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000024 }
25
26 *dst = '\0';
27
28 return dst;
29}
Igor Sysoevdc479b42003-03-20 16:09:44 +000030
31
Igor Sysoevd039a2e2005-02-22 14:40:13 +000032u_char *
33ngx_pstrdup(ngx_pool_t *pool, ngx_str_t *src)
Igor Sysoev805d9db2005-02-03 19:33:37 +000034{
35 u_char *dst;
36
Igor Sysoevc1571722005-03-19 12:38:37 +000037 dst = ngx_palloc(pool, src->len);
38 if (dst == NULL) {
Igor Sysoev805d9db2005-02-03 19:33:37 +000039 return NULL;
40 }
41
42 ngx_memcpy(dst, src->data, src->len);
43
44 return dst;
45}
46
47
Igor Sysoevc0edbcc2004-10-21 15:34:38 +000048/*
49 * supported formats:
Igor Sysoev42b12b32004-12-02 18:40:46 +000050 * %[0][width][x][X]O off_t
Igor Sysoev1b735832004-11-11 14:07:14 +000051 * %[0][width]T time_t
52 * %[0][width][u][x|X]z ssize_t/size_t
53 * %[0][width][u][x|X]d int/u_int
54 * %[0][width][u][x|X]l long
55 * %[0][width|m][u][x|X]i ngx_int_t/ngx_uint_t
56 * %[0][width][u][x|X]D int32_t/uint32_t
57 * %[0][width][u][x|X]L int64_t/uint64_t
Igor Sysoev4a715592005-02-24 12:29:09 +000058 * %[0][width|m][u][x|X]A ngx_atomic_int_t/ngx_atomic_uint_t
Igor Sysoev1b735832004-11-11 14:07:14 +000059 * %P ngx_pid_t
Igor Sysoev208eed22005-10-07 13:30:52 +000060 * %M ngx_msec_t
Igor Sysoev1b735832004-11-11 14:07:14 +000061 * %r rlim_t
62 * %p pointer
63 * %V pointer to ngx_str_t
64 * %s null-terminated string
65 * %Z '\0'
Igor Sysoev85ef94b2005-06-23 13:41:06 +000066 * %N '\n'
Igor Sysoev1b735832004-11-11 14:07:14 +000067 * %c char
68 * %% %
Igor Sysoevc0edbcc2004-10-21 15:34:38 +000069 *
Igor Sysoev1b735832004-11-11 14:07:14 +000070 * reserved:
71 * %t ptrdiff_t
72 * %S null-teminated wchar string
73 * %C wchar
Igor Sysoevc0edbcc2004-10-21 15:34:38 +000074 */
75
Igor Sysoev1b735832004-11-11 14:07:14 +000076
Igor Sysoev4d656dc2005-03-22 16:02:46 +000077u_char * ngx_cdecl
Igor Sysoevd039a2e2005-02-22 14:40:13 +000078ngx_sprintf(u_char *buf, const char *fmt, ...)
Igor Sysoevc0edbcc2004-10-21 15:34:38 +000079{
Igor Sysoev1b735832004-11-11 14:07:14 +000080 u_char *p;
81 va_list args;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +000082
Igor Sysoev1b735832004-11-11 14:07:14 +000083 va_start(args, fmt);
84 p = ngx_vsnprintf(buf, /* STUB */ 65536, fmt, args);
85 va_end(args);
Igor Sysoevc0edbcc2004-10-21 15:34:38 +000086
Igor Sysoev1b735832004-11-11 14:07:14 +000087 return p;
88}
89
90
Igor Sysoev4d656dc2005-03-22 16:02:46 +000091u_char * ngx_cdecl
Igor Sysoevd039a2e2005-02-22 14:40:13 +000092ngx_snprintf(u_char *buf, size_t max, const char *fmt, ...)
Igor Sysoev1b735832004-11-11 14:07:14 +000093{
94 u_char *p;
95 va_list args;
96
97 va_start(args, fmt);
98 p = ngx_vsnprintf(buf, max, fmt, args);
99 va_end(args);
100
101 return p;
102}
103
104
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000105u_char *
106ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args)
Igor Sysoev1b735832004-11-11 14:07:14 +0000107{
Igor Sysoev02025fd2005-01-18 13:03:58 +0000108 u_char *p, zero, *last, temp[NGX_INT64_LEN + 1];
109 /*
110 * really we need temp[NGX_INT64_LEN] only,
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000111 * but icc issues the warning
Igor Sysoev02025fd2005-01-18 13:03:58 +0000112 */
Igor Sysoev1b735832004-11-11 14:07:14 +0000113 int d;
114 size_t len;
115 uint32_t ui32;
116 int64_t i64;
117 uint64_t ui64;
Igor Sysoev78452232005-10-12 13:50:36 +0000118 ngx_msec_t ms;
Igor Sysoev1b735832004-11-11 14:07:14 +0000119 ngx_str_t *s;
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000120 ngx_uint_t width, sign, hexadecimal, max_width;
Igor Sysoev1b735832004-11-11 14:07:14 +0000121 static u_char hex[] = "0123456789abcdef";
122 static u_char HEX[] = "0123456789ABCDEF";
123
124 if (max == 0) {
125 return buf;
126 }
127
128 last = buf + max;
129
130 while (*fmt && buf < last) {
131
132 /*
133 * "buf < last" means that we could copy at least one character:
134 * the plain character, "%%", "%c", and minus without the checking
135 */
136
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000137 if (*fmt == '%') {
138
Igor Sysoev1b735832004-11-11 14:07:14 +0000139 i64 = 0;
140 ui64 = 0;
141
142 zero = (u_char) ((*++fmt == '0') ? '0' : ' ');
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000143 width = 0;
144 sign = 1;
145 hexadecimal = 0;
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000146 max_width = 0;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000147
Igor Sysoevb1dfe472004-12-21 12:30:30 +0000148 p = temp + NGX_INT64_LEN;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000149
150 while (*fmt >= '0' && *fmt <= '9') {
151 width = width * 10 + *fmt++ - '0';
152 }
153
154
155 for ( ;; ) {
156 switch (*fmt) {
157
158 case 'u':
159 sign = 0;
160 fmt++;
161 continue;
162
Igor Sysoevd43bee82004-11-20 19:52:20 +0000163 case 'm':
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000164 max_width = 1;
Igor Sysoevd43bee82004-11-20 19:52:20 +0000165 fmt++;
166 continue;
167
Igor Sysoev1b735832004-11-11 14:07:14 +0000168 case 'X':
169 hexadecimal = 2;
170 sign = 0;
171 fmt++;
172 continue;
173
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000174 case 'x':
175 hexadecimal = 1;
Igor Sysoev1b735832004-11-11 14:07:14 +0000176 sign = 0;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000177 fmt++;
178 continue;
179
180 default:
181 break;
182 }
183
184 break;
185 }
186
187
188 switch (*fmt) {
189
Igor Sysoev1b735832004-11-11 14:07:14 +0000190 case 'V':
191 s = va_arg(args, ngx_str_t *);
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000192
Igor Sysoev09c684b2005-11-09 17:25:55 +0000193 len = s->len & 0xffff;
194 len = (buf + len < last) ? len : (size_t) (last - buf);
195
Igor Sysoev1b735832004-11-11 14:07:14 +0000196 buf = ngx_cpymem(buf, s->data, len);
197 fmt++;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000198
Igor Sysoev1b735832004-11-11 14:07:14 +0000199 continue;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000200
201 case 's':
Igor Sysoev1b735832004-11-11 14:07:14 +0000202 p = va_arg(args, u_char *);
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000203
Igor Sysoev1b735832004-11-11 14:07:14 +0000204 while (*p && buf < last) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000205 *buf++ = *p++;
206 }
207 fmt++;
208
209 continue;
210
Igor Sysoev1b735832004-11-11 14:07:14 +0000211 case 'O':
212 i64 = (int64_t) va_arg(args, off_t);
213 sign = 1;
214 break;
215
216 case 'P':
217 i64 = (int64_t) va_arg(args, ngx_pid_t);
218 sign = 1;
219 break;
220
221 case 'T':
222 i64 = (int64_t) va_arg(args, time_t);
223 sign = 1;
224 break;
225
Igor Sysoev208eed22005-10-07 13:30:52 +0000226 case 'M':
Igor Sysoev78452232005-10-12 13:50:36 +0000227 ms = (ngx_msec_t) va_arg(args, ngx_msec_t);
228 if ((ngx_msec_int_t) ms == -1) {
229 sign = 1;
230 i64 = -1;
231 } else {
232 sign = 0;
233 ui64 = (uint64_t) ms;
234 }
Igor Sysoev208eed22005-10-07 13:30:52 +0000235 break;
236
Igor Sysoev1b735832004-11-11 14:07:14 +0000237 case 'z':
238 if (sign) {
239 i64 = (int64_t) va_arg(args, ssize_t);
240 } else {
241 ui64 = (uint64_t) va_arg(args, size_t);
242 }
243 break;
244
245 case 'i':
246 if (sign) {
247 i64 = (int64_t) va_arg(args, ngx_int_t);
248 } else {
249 ui64 = (uint64_t) va_arg(args, ngx_uint_t);
250 }
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000251
252 if (max_width) {
253 width = NGX_INT_T_LEN;
254 }
255
Igor Sysoev1b735832004-11-11 14:07:14 +0000256 break;
257
258 case 'd':
259 if (sign) {
260 i64 = (int64_t) va_arg(args, int);
261 } else {
262 ui64 = (uint64_t) va_arg(args, u_int);
263 }
264 break;
265
266 case 'l':
267 if (sign) {
268 i64 = (int64_t) va_arg(args, long);
269 } else {
270 ui64 = (uint64_t) va_arg(args, u_long);
271 }
272 break;
273
274 case 'D':
275 if (sign) {
276 i64 = (int64_t) va_arg(args, int32_t);
277 } else {
278 ui64 = (uint64_t) va_arg(args, uint32_t);
279 }
280 break;
281
282 case 'L':
283 if (sign) {
284 i64 = va_arg(args, int64_t);
285 } else {
286 ui64 = va_arg(args, uint64_t);
287 }
288 break;
289
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000290 case 'A':
291 if (sign) {
292 i64 = (int64_t) va_arg(args, ngx_atomic_int_t);
293 } else {
Igor Sysoev4a715592005-02-24 12:29:09 +0000294 ui64 = (uint64_t) va_arg(args, ngx_atomic_uint_t);
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000295 }
296
297 if (max_width) {
298 width = NGX_ATOMIC_T_LEN;
299 }
300
301 break;
302
Igor Sysoev1b735832004-11-11 14:07:14 +0000303#if !(NGX_WIN32)
304 case 'r':
305 i64 = (int64_t) va_arg(args, rlim_t);
306 sign = 1;
307 break;
308#endif
309
310 case 'p':
311 ui64 = (uintptr_t) va_arg(args, void *);
312 hexadecimal = 2;
313 sign = 0;
314 zero = '0';
Igor Sysoevc2807ec2006-02-16 15:26:46 +0000315 width = NGX_PTR_SIZE * 2;
Igor Sysoev1b735832004-11-11 14:07:14 +0000316 break;
317
Igor Sysoev723e6cc2004-10-25 15:29:23 +0000318 case 'c':
Igor Sysoev1b735832004-11-11 14:07:14 +0000319 d = va_arg(args, int);
Igor Sysoev723e6cc2004-10-25 15:29:23 +0000320 *buf++ = (u_char) (d & 0xff);
321 fmt++;
322
323 continue;
324
Igor Sysoev1b735832004-11-11 14:07:14 +0000325 case 'Z':
326 *buf++ = '\0';
327 fmt++;
328
329 continue;
330
Igor Sysoev85ef94b2005-06-23 13:41:06 +0000331 case 'N':
332#if (NGX_WIN32)
333 *buf++ = CR;
334#endif
335 *buf++ = LF;
336 fmt++;
337
338 continue;
339
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000340 case '%':
341 *buf++ = '%';
342 fmt++;
343
344 continue;
345
346 default:
347 *buf++ = *fmt++;
348
349 continue;
350 }
351
Igor Sysoev1b735832004-11-11 14:07:14 +0000352 if (sign) {
353 if (i64 < 0) {
354 *buf++ = '-';
355 ui64 = (uint64_t) -i64;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000356
Igor Sysoev1b735832004-11-11 14:07:14 +0000357 } else {
358 ui64 = (uint64_t) i64;
359 }
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000360 }
361
Igor Sysoev1b735832004-11-11 14:07:14 +0000362 if (hexadecimal == 1) {
363 do {
364
365 /* the "(uint32_t)" cast disables the BCC's warning */
366 *--p = hex[(uint32_t) (ui64 & 0xf)];
367
368 } while (ui64 >>= 4);
369
370 } else if (hexadecimal == 2) {
371 do {
372
373 /* the "(uint32_t)" cast disables the BCC's warning */
374 *--p = HEX[(uint32_t) (ui64 & 0xf)];
375
376 } while (ui64 >>= 4);
377
378 } else if (ui64 <= NGX_MAX_UINT32_VALUE) {
379
380 /*
381 * To divide 64-bit number and to find the remainder
382 * on the x86 platform gcc and icc call the libc functions
383 * [u]divdi3() and [u]moddi3(), they call another function
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000384 * in its turn. On FreeBSD it is the qdivrem() function,
Igor Sysoev1b735832004-11-11 14:07:14 +0000385 * its source code is about 170 lines of the code.
386 * The glibc counterpart is about 150 lines of the code.
387 *
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000388 * For 32-bit numbers and some divisors gcc and icc use
389 * the inlined multiplication and shifts. For example,
390 * unsigned "i32 / 10" is compiled to
391 *
392 * (i32 * 0xCCCCCCCD) >> 35
Igor Sysoev1b735832004-11-11 14:07:14 +0000393 */
394
395 ui32 = (uint32_t) ui64;
396
397 do {
398 *--p = (u_char) (ui32 % 10 + '0');
399 } while (ui32 /= 10);
400
401 } else {
402 do {
403 *--p = (u_char) (ui64 % 10 + '0');
404 } while (ui64 /= 10);
405 }
406
Igor Sysoevb1dfe472004-12-21 12:30:30 +0000407 len = (temp + NGX_INT64_LEN) - p;
Igor Sysoev1b735832004-11-11 14:07:14 +0000408
409 while (len++ < width && buf < last) {
410 *buf++ = zero;
411 }
412
Igor Sysoevb1dfe472004-12-21 12:30:30 +0000413 len = (temp + NGX_INT64_LEN) - p;
Igor Sysoev1b735832004-11-11 14:07:14 +0000414 if (buf + len > last) {
415 len = last - buf;
416 }
417
418 buf = ngx_cpymem(buf, p, len);
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000419
420 fmt++;
421
422 } else {
423 *buf++ = *fmt++;
424 }
425 }
426
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000427 return buf;
428}
429
430
Igor Sysoev722231f2007-02-14 18:51:19 +0000431/*
432 * We use ngx_strcasecmp()/ngx_strncasecmp() for 7-bit ASCII string only,
433 * and implement our own ngx_strcasecmp()/ngx_strncasecmp()
434 * to avoid libc locale overhead. Besides, we use the ngx_uint_t's
435 * instead of the u_char's, because they are slightly faster.
436 */
437
438ngx_int_t
439ngx_strcasecmp(u_char *s1, u_char *s2)
440{
441 ngx_uint_t c1, c2;
442
443 for ( ;; ) {
444 c1 = (ngx_uint_t) *s1++;
445 c2 = (ngx_uint_t) *s2++;
446
447 c1 = (c1 >= 'A' && c1 <= 'Z') ? (c1 | 0x20) : c1;
448 c2 = (c2 >= 'A' && c2 <= 'Z') ? (c2 | 0x20) : c2;
449
450 if (c1 == c2) {
451
452 if (c1) {
453 continue;
454 }
455
456 return 0;
457 }
458
459 return c1 - c2;
460 }
461}
462
463
464ngx_int_t
465ngx_strncasecmp(u_char *s1, u_char *s2, size_t n)
466{
467 ngx_uint_t c1, c2;
468
469 while (n) {
470 c1 = (ngx_uint_t) *s1++;
471 c2 = (ngx_uint_t) *s2++;
472
473 c1 = (c1 >= 'A' && c1 <= 'Z') ? (c1 | 0x20) : c1;
474 c2 = (c2 >= 'A' && c2 <= 'Z') ? (c2 | 0x20) : c2;
475
476 if (c1 == c2) {
477
478 if (c1) {
479 n--;
480 continue;
481 }
482
483 return 0;
484 }
485
486 return c1 - c2;
487 }
488
489 return 0;
490}
491
492
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000493ngx_int_t
494ngx_rstrncmp(u_char *s1, u_char *s2, size_t n)
Igor Sysoev3d09c8d2003-05-06 17:03:16 +0000495{
496 if (n == 0) {
497 return 0;
498 }
499
500 n--;
501
502 for ( ;; ) {
503 if (s1[n] != s2[n]) {
Igor Sysoev10a543a2004-03-16 07:10:12 +0000504 return s1[n] - s2[n];
Igor Sysoev3d09c8d2003-05-06 17:03:16 +0000505 }
506
507 if (n == 0) {
508 return 0;
509 }
510
511 n--;
512 }
513}
514
515
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000516ngx_int_t
517ngx_rstrncasecmp(u_char *s1, u_char *s2, size_t n)
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000518{
519 u_char c1, c2;
520
521 if (n == 0) {
522 return 0;
523 }
524
525 n--;
526
527 for ( ;; ) {
528 c1 = s1[n];
529 if (c1 >= 'a' && c1 <= 'z') {
530 c1 -= 'a' - 'A';
531 }
532
533 c2 = s2[n];
534 if (c2 >= 'a' && c2 <= 'z') {
535 c2 -= 'a' - 'A';
536 }
537
538 if (c1 != c2) {
539 return c1 - c2;
540 }
541
542 if (n == 0) {
543 return 0;
544 }
545
546 n--;
547 }
548}
549
550
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000551ngx_int_t
Igor Sysoevec3cabd2007-01-12 21:58:02 +0000552ngx_memn2cmp(u_char *s1, u_char *s2, size_t n1, size_t n2)
Igor Sysoev37cc1652007-01-12 20:15:59 +0000553{
554 size_t n;
555 ngx_int_t m, z;
556
557 if (n1 <= n2) {
558 n = n1;
559 z = -1;
560
561 } else {
562 n = n2;
563 z = 1;
564 }
565
Igor Sysoevec3cabd2007-01-12 21:58:02 +0000566 m = ngx_memcmp(s1, s2, n);
Igor Sysoev37cc1652007-01-12 20:15:59 +0000567
568 if (m || n1 == n2) {
569 return m;
570 }
571
572 return z;
573}
574
575
576ngx_int_t
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000577ngx_atoi(u_char *line, size_t n)
Igor Sysoevdc479b42003-03-20 16:09:44 +0000578{
Igor Sysoev10a543a2004-03-16 07:10:12 +0000579 ngx_int_t value;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000580
Igor Sysoev3d09c8d2003-05-06 17:03:16 +0000581 if (n == 0) {
582 return NGX_ERROR;
583 }
584
Igor Sysoevdc479b42003-03-20 16:09:44 +0000585 for (value = 0; n--; line++) {
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +0000586 if (*line < '0' || *line > '9') {
587 return NGX_ERROR;
588 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000589
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +0000590 value = value * 10 + (*line - '0');
Igor Sysoevdc479b42003-03-20 16:09:44 +0000591 }
592
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +0000593 if (value < 0) {
594 return NGX_ERROR;
Igor Sysoev18684bd2004-05-20 17:33:52 +0000595
596 } else {
597 return value;
598 }
599}
600
601
Igor Sysoevc1571722005-03-19 12:38:37 +0000602ssize_t
603ngx_atosz(u_char *line, size_t n)
604{
605 ssize_t value;
606
607 if (n == 0) {
608 return NGX_ERROR;
609 }
610
611 for (value = 0; n--; line++) {
612 if (*line < '0' || *line > '9') {
613 return NGX_ERROR;
614 }
615
616 value = value * 10 + (*line - '0');
617 }
618
619 if (value < 0) {
620 return NGX_ERROR;
621
622 } else {
623 return value;
624 }
625}
626
627
628off_t
629ngx_atoof(u_char *line, size_t n)
630{
631 off_t value;
632
633 if (n == 0) {
634 return NGX_ERROR;
635 }
636
637 for (value = 0; n--; line++) {
638 if (*line < '0' || *line > '9') {
639 return NGX_ERROR;
640 }
641
642 value = value * 10 + (*line - '0');
643 }
644
645 if (value < 0) {
646 return NGX_ERROR;
647
648 } else {
649 return value;
650 }
651}
652
653
654time_t
655ngx_atotm(u_char *line, size_t n)
656{
657 time_t value;
658
659 if (n == 0) {
660 return NGX_ERROR;
661 }
662
663 for (value = 0; n--; line++) {
664 if (*line < '0' || *line > '9') {
665 return NGX_ERROR;
666 }
667
668 value = value * 10 + (*line - '0');
669 }
670
671 if (value < 0) {
672 return NGX_ERROR;
673
674 } else {
675 return value;
676 }
677}
678
679
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000680ngx_int_t
681ngx_hextoi(u_char *line, size_t n)
Igor Sysoev18684bd2004-05-20 17:33:52 +0000682{
Igor Sysoev066496a2006-10-16 12:21:17 +0000683 u_char c, ch;
Igor Sysoev18684bd2004-05-20 17:33:52 +0000684 ngx_int_t value;
685
686 if (n == 0) {
687 return NGX_ERROR;
688 }
689
690 for (value = 0; n--; line++) {
691 ch = *line;
692
693 if (ch >= '0' && ch <= '9') {
694 value = value * 16 + (ch - '0');
695 continue;
696 }
697
Igor Sysoev066496a2006-10-16 12:21:17 +0000698 c = (u_char) (ch | 0x20);
Igor Sysoev18684bd2004-05-20 17:33:52 +0000699
Igor Sysoev066496a2006-10-16 12:21:17 +0000700 if (c >= 'a' && c <= 'f') {
701 value = value * 16 + (c - 'a' + 10);
Igor Sysoev18684bd2004-05-20 17:33:52 +0000702 continue;
703 }
704
705 return NGX_ERROR;
706 }
707
708 if (value < 0) {
709 return NGX_ERROR;
710
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +0000711 } else {
712 return value;
713 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000714}
715
716
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000717void
718ngx_md5_text(u_char *text, u_char *md5)
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000719{
Igor Sysoev10a543a2004-03-16 07:10:12 +0000720 int i;
721 static u_char hex[] = "0123456789abcdef";
Igor Sysoeve8732b02003-11-05 17:03:41 +0000722
Igor Sysoev74e95c22003-11-09 20:03:38 +0000723 for (i = 0; i < 16; i++) {
724 *text++ = hex[md5[i] >> 4];
725 *text++ = hex[md5[i] & 0xf];
726 }
727
728 *text = '\0';
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000729}
730
731
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000732void
733ngx_encode_base64(ngx_str_t *dst, ngx_str_t *src)
Igor Sysoev6deb0412004-07-30 17:05:14 +0000734{
735 u_char *d, *s;
Igor Sysoev967fd632004-08-27 15:40:59 +0000736 size_t len;
Igor Sysoev6deb0412004-07-30 17:05:14 +0000737 static u_char basis64[] =
738 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
739
Igor Sysoev967fd632004-08-27 15:40:59 +0000740 len = src->len;
Igor Sysoeva7c4a2a2004-08-29 03:55:41 +0000741 s = src->data;
742 d = dst->data;
Igor Sysoev6deb0412004-07-30 17:05:14 +0000743
Igor Sysoev967fd632004-08-27 15:40:59 +0000744 while (len > 2) {
745 *d++ = basis64[(s[0] >> 2) & 0x3f];
746 *d++ = basis64[((s[0] & 3) << 4) | (s[1] >> 4)];
747 *d++ = basis64[((s[1] & 0x0f) << 2) | (s[2] >> 6)];
748 *d++ = basis64[s[2] & 0x3f];
749
750 s += 3;
751 len -= 3;
Igor Sysoev6deb0412004-07-30 17:05:14 +0000752 }
753
Igor Sysoev967fd632004-08-27 15:40:59 +0000754 if (len) {
755 *d++ = basis64[(s[0] >> 2) & 0x3f];
Igor Sysoev6deb0412004-07-30 17:05:14 +0000756
Igor Sysoev967fd632004-08-27 15:40:59 +0000757 if (len == 1) {
758 *d++ = basis64[(s[0] & 3) << 4];
Igor Sysoev6deb0412004-07-30 17:05:14 +0000759 *d++ = '=';
760
761 } else {
Igor Sysoev967fd632004-08-27 15:40:59 +0000762 *d++ = basis64[((s[0] & 3) << 4) | (s[1] >> 4)];
763 *d++ = basis64[(s[1] & 0x0f) << 2];
Igor Sysoev6deb0412004-07-30 17:05:14 +0000764 }
765
766 *d++ = '=';
767 }
768
769 dst->len = d - dst->data;
Igor Sysoev6deb0412004-07-30 17:05:14 +0000770}
771
772
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000773ngx_int_t
774ngx_decode_base64(ngx_str_t *dst, ngx_str_t *src)
Igor Sysoev6deb0412004-07-30 17:05:14 +0000775{
Igor Sysoev967fd632004-08-27 15:40:59 +0000776 size_t len;
777 u_char *d, *s;
Igor Sysoevb5c75dc2006-10-28 14:36:44 +0000778 static u_char basis64[] = {
779 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
780 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
781 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 62, 77, 77, 77, 63,
782 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 77, 77, 77, 77, 77, 77,
783 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
784 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 77, 77, 77, 77, 77,
785 77, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
786 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 77, 77, 77, 77, 77,
Igor Sysoev6deb0412004-07-30 17:05:14 +0000787
Igor Sysoevb5c75dc2006-10-28 14:36:44 +0000788 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
789 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
790 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
791 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
792 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
793 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
794 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
795 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77
796 };
Igor Sysoev967fd632004-08-27 15:40:59 +0000797
798 for (len = 0; len < src->len; len++) {
799 if (src->data[len] == '=') {
800 break;
801 }
802
803 if (basis64[src->data[len]] == 77) {
804 return NGX_ERROR;
805 }
806 }
807
808 if (len % 4 == 1) {
809 return NGX_ERROR;
810 }
811
Igor Sysoev6deb0412004-07-30 17:05:14 +0000812 s = src->data;
Igor Sysoeva7c4a2a2004-08-29 03:55:41 +0000813 d = dst->data;
Igor Sysoev6deb0412004-07-30 17:05:14 +0000814
Igor Sysoev967fd632004-08-27 15:40:59 +0000815 while (len > 3) {
Igor Sysoeva7c4a2a2004-08-29 03:55:41 +0000816 *d++ = (u_char) (basis64[s[0]] << 2 | basis64[s[1]] >> 4);
817 *d++ = (u_char) (basis64[s[1]] << 4 | basis64[s[2]] >> 2);
818 *d++ = (u_char) (basis64[s[2]] << 6 | basis64[s[3]]);
Igor Sysoev6deb0412004-07-30 17:05:14 +0000819
Igor Sysoev967fd632004-08-27 15:40:59 +0000820 s += 4;
821 len -= 4;
Igor Sysoev6deb0412004-07-30 17:05:14 +0000822 }
823
Igor Sysoev967fd632004-08-27 15:40:59 +0000824 if (len > 1) {
Igor Sysoeva7c4a2a2004-08-29 03:55:41 +0000825 *d++ = (u_char) (basis64[s[0]] << 2 | basis64[s[1]] >> 4);
Igor Sysoev967fd632004-08-27 15:40:59 +0000826 }
827
828 if (len > 2) {
Igor Sysoeva7c4a2a2004-08-29 03:55:41 +0000829 *d++ = (u_char) (basis64[s[1]] << 4 | basis64[s[2]] >> 2);
Igor Sysoev967fd632004-08-27 15:40:59 +0000830 }
831
832 dst->len = d - dst->data;
Igor Sysoev967fd632004-08-27 15:40:59 +0000833
Igor Sysoev6deb0412004-07-30 17:05:14 +0000834 return NGX_OK;
835}
836
837
Igor Sysoevef809b82006-06-28 16:00:26 +0000838/*
839 * ngx_utf_decode() decodes two and more bytes UTF sequences only
840 * the return values:
841 * 0x80 - 0x10ffff valid character
842 * 0x10ffff - 0xfffffffd invalid sequence
843 * 0xfffffffe incomplete sequence
844 * 0xffffffff error
845 */
846
847uint32_t
848ngx_utf_decode(u_char **p, size_t n)
849{
850 size_t len;
851 uint32_t u, i, valid;
852
853 u = **p;
854
855 if (u > 0xf0) {
856
857 u &= 0x07;
858 valid = 0xffff;
859 len = 3;
860
861 } else if (u > 0xe0) {
862
863 u &= 0x0f;
864 valid = 0x7ff;
865 len = 2;
866
867 } else if (u > 0xc0) {
868
869 u &= 0x1f;
870 valid = 0x7f;
871 len = 1;
872
873 } else {
874 (*p)++;
875 return 0xffffffff;
876 }
877
878 if (n - 1 < len) {
879 return 0xfffffffe;
880 }
881
882 (*p)++;
883
884 while (len) {
885 i = *(*p)++;
886
887 if (i < 0x80) {
888 return 0xffffffff;
889 }
890
891 u = (u << 6) | (i & 0x3f);
892
893 len--;
894 }
895
896 if (u > valid) {
897 return u;
898 }
899
900 return 0xffffffff;
901}
902
903
Igor Sysoevb145b062005-06-15 18:33:41 +0000904size_t
Igor Sysoevef809b82006-06-28 16:00:26 +0000905ngx_utf_length(u_char *p, size_t n)
Igor Sysoevb145b062005-06-15 18:33:41 +0000906{
907 u_char c;
908 size_t len;
909 ngx_uint_t i;
910
Igor Sysoevef809b82006-06-28 16:00:26 +0000911 for (len = 0, i = 0; i < n; len++, i++) {
Igor Sysoevb145b062005-06-15 18:33:41 +0000912
Igor Sysoevef809b82006-06-28 16:00:26 +0000913 c = p[i];
Igor Sysoevb145b062005-06-15 18:33:41 +0000914
915 if (c < 0x80) {
916 continue;
917 }
918
Igor Sysoev5192b362005-07-08 14:34:20 +0000919 if (c >= 0xc0) {
920 for (c <<= 1; c & 0x80; c <<= 1) {
921 i++;
922 }
923
924 continue;
Igor Sysoevb145b062005-06-15 18:33:41 +0000925 }
926
Igor Sysoev5192b362005-07-08 14:34:20 +0000927 /* invalid utf */
928
Igor Sysoevef809b82006-06-28 16:00:26 +0000929 return n;
Igor Sysoevb145b062005-06-15 18:33:41 +0000930 }
931
932 return len;
933}
934
935
Igor Sysoev5192b362005-07-08 14:34:20 +0000936u_char *
937ngx_utf_cpystrn(u_char *dst, u_char *src, size_t n)
938{
939 u_char c;
940
941 if (n == 0) {
942 return dst;
943 }
944
945 for ( /* void */ ; --n; dst++, src++) {
946
947 c = *src;
948 *dst = c;
949
950 if (c < 0x80) {
951 if (*dst != '\0') {
952 continue;
953 }
954
955 return dst;
956 }
957
958 if (c >= 0xc0) {
959 for (c <<= 1; c & 0x80; c <<= 1) {
960 *++dst = *++src;
961 }
962
963 continue;
964 }
965
966 /* invalid utf */
967 }
968
969 *dst = '\0';
970
971 return dst;
972}
973
974
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000975uintptr_t
976ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
Igor Sysoevdc479b42003-03-20 16:09:44 +0000977{
Igor Sysoevb5c75dc2006-10-28 14:36:44 +0000978 ngx_uint_t i, n;
979 uint32_t *escape;
980 static u_char hex[] = "0123456789abcdef";
Igor Sysoev1b735832004-11-11 14:07:14 +0000981
Igor Sysoevb5c75dc2006-10-28 14:36:44 +0000982 /* " ", "#", "%", "?", %00-%1F, %7F-%FF */
Igor Sysoev805d9db2005-02-03 19:33:37 +0000983
Igor Sysoevb5c75dc2006-10-28 14:36:44 +0000984 static uint32_t uri[] = {
985 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
Igor Sysoevdc479b42003-03-20 16:09:44 +0000986
Igor Sysoevb5c75dc2006-10-28 14:36:44 +0000987 /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
988 0x80000029, /* 1000 0000 0000 0000 0000 0000 0010 1001 */
Igor Sysoevdc479b42003-03-20 16:09:44 +0000989
Igor Sysoevb5c75dc2006-10-28 14:36:44 +0000990 /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
991 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
Igor Sysoevdc479b42003-03-20 16:09:44 +0000992
Igor Sysoevb5c75dc2006-10-28 14:36:44 +0000993 /* ~}| {zyx wvut srqp onml kjih gfed cba` */
994 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
Igor Sysoev924bd792004-10-11 15:07:03 +0000995
Igor Sysoevb5c75dc2006-10-28 14:36:44 +0000996 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
997 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
998 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
999 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1000 };
Igor Sysoev924bd792004-10-11 15:07:03 +00001001
Igor Sysoevb5c75dc2006-10-28 14:36:44 +00001002 /* " ", "#", "%", "+", "?", %00-%1F, %7F-%FF */
Igor Sysoev805d9db2005-02-03 19:33:37 +00001003
Igor Sysoevb5c75dc2006-10-28 14:36:44 +00001004 static uint32_t args[] = {
1005 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
Igor Sysoev805d9db2005-02-03 19:33:37 +00001006
Igor Sysoevb5c75dc2006-10-28 14:36:44 +00001007 /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
1008 0x80000829, /* 1000 0000 0000 0000 0000 1000 0010 1001 */
Igor Sysoev805d9db2005-02-03 19:33:37 +00001009
Igor Sysoevb5c75dc2006-10-28 14:36:44 +00001010 /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
1011 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
Igor Sysoev805d9db2005-02-03 19:33:37 +00001012
Igor Sysoevb5c75dc2006-10-28 14:36:44 +00001013 /* ~}| {zyx wvut srqp onml kjih gfed cba` */
1014 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
Igor Sysoev805d9db2005-02-03 19:33:37 +00001015
Igor Sysoevb5c75dc2006-10-28 14:36:44 +00001016 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1017 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1018 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1019 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1020 };
Igor Sysoev805d9db2005-02-03 19:33:37 +00001021
Igor Sysoevb5c75dc2006-10-28 14:36:44 +00001022 /* " ", """, "%", "'", %00-%1F, %7F-%FF */
Igor Sysoev805d9db2005-02-03 19:33:37 +00001023
Igor Sysoevb5c75dc2006-10-28 14:36:44 +00001024 static uint32_t html[] = {
1025 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
Igor Sysoev1b735832004-11-11 14:07:14 +00001026
Igor Sysoevb5c75dc2006-10-28 14:36:44 +00001027 /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
Igor Sysoev049ae002007-07-13 09:35:51 +00001028 0x000000ad, /* 0000 0000 0000 0000 0000 0000 1010 1101 */
Igor Sysoev1b735832004-11-11 14:07:14 +00001029
Igor Sysoevb5c75dc2006-10-28 14:36:44 +00001030 /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
1031 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
Igor Sysoev1b735832004-11-11 14:07:14 +00001032
Igor Sysoevb5c75dc2006-10-28 14:36:44 +00001033 /* ~}| {zyx wvut srqp onml kjih gfed cba` */
1034 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
Igor Sysoev1b735832004-11-11 14:07:14 +00001035
Igor Sysoevb5c75dc2006-10-28 14:36:44 +00001036 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1037 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1038 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1039 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1040 };
Igor Sysoev1b735832004-11-11 14:07:14 +00001041
Igor Sysoev8662b6b2007-07-13 09:37:01 +00001042 /* " ", """, "'", %00-%1F, %7F-%FF */
Igor Sysoev1b735832004-11-11 14:07:14 +00001043
Igor Sysoev8662b6b2007-07-13 09:37:01 +00001044 static uint32_t refresh[] = {
1045 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1046
1047 /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
1048 0x00000085, /* 0000 0000 0000 0000 0000 0000 1000 0101 */
1049
1050 /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
1051 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
1052
1053 /* ~}| {zyx wvut srqp onml kjih gfed cba` */
1054 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
1055
1056 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1057 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1058 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1059 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */
1060 };
1061
1062 static uint32_t *map[] = { uri, args, html, refresh };
1063
1064
1065 escape = map[type];
Igor Sysoev1b735832004-11-11 14:07:14 +00001066
Igor Sysoev924bd792004-10-11 15:07:03 +00001067 if (dst == NULL) {
1068
1069 /* find the number of the characters to be escaped */
1070
1071 n = 0;
1072
1073 for (i = 0; i < size; i++) {
1074 if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
1075 n++;
1076 }
1077 src++;
1078 }
1079
Igor Sysoev805d9db2005-02-03 19:33:37 +00001080 return (uintptr_t) n;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001081 }
1082
Igor Sysoev924bd792004-10-11 15:07:03 +00001083 for (i = 0; i < size; i++) {
1084 if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
1085 *dst++ = '%';
1086 *dst++ = hex[*src >> 4];
1087 *dst++ = hex[*src & 0xf];
1088 src++;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001089
Igor Sysoev924bd792004-10-11 15:07:03 +00001090 } else {
1091 *dst++ = *src++;
1092 }
Igor Sysoevdc479b42003-03-20 16:09:44 +00001093 }
1094
Igor Sysoev805d9db2005-02-03 19:33:37 +00001095 return (uintptr_t) dst;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001096}
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001097
1098
1099void
Igor Sysoevae33d012006-01-17 20:04:32 +00001100ngx_unescape_uri(u_char **dst, u_char **src, size_t size, ngx_uint_t type)
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001101{
1102 u_char *d, *s, ch, c, decoded;
1103 enum {
1104 sw_usual = 0,
1105 sw_quoted,
1106 sw_quoted_second
1107 } state;
1108
1109 d = *dst;
1110 s = *src;
1111
1112 state = 0;
1113 decoded = 0;
1114
1115 while (size--) {
1116
1117 ch = *s++;
1118
1119 switch (state) {
1120 case sw_usual:
Igor Sysoevae33d012006-01-17 20:04:32 +00001121 if (ch == '?' && type == NGX_UNESCAPE_URI) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001122 *d++ = ch;
1123 goto done;
1124 }
1125
1126 if (ch == '%') {
1127 state = sw_quoted;
1128 break;
1129 }
1130
1131 *d++ = ch;
1132 break;
1133
1134 case sw_quoted:
1135
1136 if (ch >= '0' && ch <= '9') {
1137 decoded = (u_char) (ch - '0');
1138 state = sw_quoted_second;
1139 break;
1140 }
1141
1142 c = (u_char) (ch | 0x20);
1143 if (c >= 'a' && c <= 'f') {
1144 decoded = (u_char) (c - 'a' + 10);
1145 state = sw_quoted_second;
1146 break;
1147 }
1148
Igor Sysoev24025022005-12-16 15:07:08 +00001149 /* the invalid quoted character */
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001150
Igor Sysoev24025022005-12-16 15:07:08 +00001151 state = sw_usual;
1152
1153 *d++ = ch;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001154
1155 break;
1156
1157 case sw_quoted_second:
1158
Igor Sysoev24025022005-12-16 15:07:08 +00001159 state = sw_usual;
1160
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001161 if (ch >= '0' && ch <= '9') {
1162 ch = (u_char) ((decoded << 4) + ch - '0');
1163
Igor Sysoevae33d012006-01-17 20:04:32 +00001164 if (type == NGX_UNESCAPE_URI) {
1165 if (ch > '%' && ch < 0x7f) {
1166 *d++ = ch;
1167 break;
1168 }
1169
1170 *d++ = '%'; *d++ = *(s - 2); *d++ = *(s - 1);
1171
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001172 break;
1173 }
1174
Igor Sysoevae33d012006-01-17 20:04:32 +00001175 *d++ = ch;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001176
1177 break;
1178 }
1179
1180 c = (u_char) (ch | 0x20);
1181 if (c >= 'a' && c <= 'f') {
1182 ch = (u_char) ((decoded << 4) + c - 'a' + 10);
1183
Igor Sysoevae33d012006-01-17 20:04:32 +00001184 if (type == NGX_UNESCAPE_URI) {
1185 if (ch == '?') {
1186 *d++ = ch;
1187 goto done;
1188 }
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001189
Igor Sysoevae33d012006-01-17 20:04:32 +00001190 if (ch > '%' && ch < 0x7f) {
1191 *d++ = ch;
1192 break;
1193 }
1194
1195 *d++ = '%'; *d++ = *(s - 2); *d++ = *(s - 1);
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001196 break;
1197 }
1198
Igor Sysoevae33d012006-01-17 20:04:32 +00001199 *d++ = ch;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001200
1201 break;
1202 }
1203
Igor Sysoev24025022005-12-16 15:07:08 +00001204 /* the invalid quoted character */
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001205
1206 break;
1207 }
1208 }
1209
1210done:
1211
1212 *dst = d;
1213 *src = s;
1214}
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001215
1216
Igor Sysoev35921282007-05-21 14:05:23 +00001217/* ngx_sort() is implemented as insertion sort because we need stable sort */
1218
1219void
1220ngx_sort(void *base, size_t n, size_t size,
1221 int (*cmp)(const void *, const void *))
1222{
1223 u_char *p1, *p2;
1224 u_char buf[256];
1225
1226 for (p1 = (u_char *) base + size;
1227 p1 < (u_char *) base + n * size;
1228 p1 += size)
1229 {
1230 ngx_memcpy(buf, p1, size);
1231
1232 for (p2 = p1;
1233 p2 > (u_char *) base && cmp(p2 - size, buf) > 0;
1234 p2 -= size)
1235 {
1236 ngx_memcpy(p2, p2 - size, size);
1237 }
1238
1239 ngx_memcpy(p2, buf, size);
1240 }
1241}
1242
1243
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001244#if (NGX_MEMCPY_LIMIT)
1245
1246void *
1247ngx_memcpy(void *dst, void *src, size_t n)
1248{
1249 if (n > NGX_MEMCPY_LIMIT) {
1250 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "memcpy %uz bytes", n);
1251 ngx_debug_point();
1252 }
1253
1254 return memcpy(dst, src, n);
1255}
1256
1257#endif