1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 #ifdef XP_UNIX
42 #include <sys/types.h>
43 #include <sys/wait.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46 #include <limits.h>
47 #include "prthread.h"
48 #endif
49
50
51
52 #include <errno.h>
53
54 #include "../daemon/netsite.h"
55 #include "../public/nsapi.h"
56 #include <cx/string.h>
57 #include <cx/mempool.h>
58 #include <cx/utils.h>
59 #include <cx/printf.h>
60
61 #include "pblock.h"
62 #include "util.h"
63
64 #include <openssl/bio.h>
65 #include <openssl/buffer.h>
66 #include <openssl/evp.h>
67
68
69
70
71 static const unsigned char pr2six[
256] = {
72 64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
73 64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
62,
64,
64,
64,
63,
74 52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
64,
64,
64,
64,
64,
64,
64,
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
75 10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
64,
64,
64,
64,
64,
64,
26,
27,
76 28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
77 64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
78 64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
79 64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
80 64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
81 64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
82 64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64,
64
83 };
84
85
86 size_t util_base64decode(
char *bufcoded,
size_t codedbytes,
char *bufout) {
87 register char *bufin = bufcoded;
88 register int nprbytes;
89 size_t nbytesdecoded;
90
91
92 nprbytes = (
int) codedbytes;
93 while(pr2six[(
int)(bufin[nprbytes-
1])] >=
64) {
94 nprbytes--;
95 }
96 nbytesdecoded = ((nprbytes+
3)/
4) *
3;
97
98 while (nprbytes >
0) {
99 *(bufout++) = (
unsigned char)
100 (pr2six[(
int)(*bufin)] <<
2 | pr2six[(
int)bufin[
1]] >>
4);
101 *(bufout++) = (
unsigned char)
102 (pr2six[(
int)bufin[
1]] <<
4 | pr2six[(
int)bufin[
2]] >>
2);
103 *(bufout++) = (
unsigned char)
104 (pr2six[(
int)bufin[
2]] <<
6 | pr2six[(
int)bufin[
3]]);
105 bufin +=
4;
106 nprbytes -=
4;
107 }
108
109 if(nprbytes &
03) {
110 if(pr2six[(
int)bufin[-
2]] >
63)
111 nbytesdecoded -=
2;
112 else
113 nbytesdecoded -=
1;
114 }
115
116 return nbytesdecoded;
117 }
118
119 char* util_base64encode(
char *in,
size_t len) {
120 BIO *b;
121 BIO *e;
122 BUF_MEM *mem;
123
124 e = BIO_new(BIO_f_base64());
125 b = BIO_new(BIO_s_mem());
126 BIO_set_flags(e,
BIO_FLAGS_BASE64_NO_NL);
127
128 e = BIO_push(e, b);
129 BIO_write(e, in, len);
130 BIO_flush(e);
131
132 BIO_get_mem_ptr(e, &mem);
133 char *out = malloc(mem->length +
1);
134 memcpy(out, mem->data, mem->length);
135 out[mem->length] =
'\0';
136
137 BIO_free_all(e);
138
139 return out;
140 }
141
142
143
144
145
146 NSAPI_PUBLIC char **util_env_create(
char **env,
int n,
int *pos)
147 {
148 int x;
149
150 if(!env) {
151 *pos =
0;
152 return (
char **)
MALLOC((n +
1)*
sizeof(
char *));
153 }
154 else {
155 for(x =
0; (env[x]); x++);
156 env = (
char **)
REALLOC(env, (n + x +
1)*(
sizeof(
char *)));
157 *pos = x;
158 return env;
159 }
160 }
161
162
163
164
165
166 NSAPI_PUBLIC void util_env_free(
char **env)
167 {
168 register char **ep = env;
169
170 for(ep = env; *ep; ep++)
171 FREE(*ep);
172 FREE(env);
173 }
174
175
176
177
178 NSAPI_PUBLIC char *util_env_str(
const char *name,
const char *value) {
179 char *t;
180
181 size_t len = strlen(name) + strlen(value) +
2;
182 t = (
char *)
MALLOC(len);
183
184 snprintf(t, len,
"%s=%s", name, value);
185
186 return t;
187 }
188
189
190
191
192
193 NSAPI_PUBLIC void util_env_replace(
char **env,
const char *name,
const char *value)
194 {
195 int x, y, z;
196 char *i;
197
198 for(x =
0; env[x]; x++) {
199 i = strchr(env[x],
'=');
200 *i =
'\0';
201 if(!strcmp(env[x], name)) {
202 y = strlen(env[x]);
203 z = strlen(value);
204
205 env[x] = (
char *)
REALLOC(env[x], y + z +
2);
206 util_sprintf(&env[x][y],
"=%s", value);
207 return;
208 }
209 *i =
'=';
210 }
211 }
212
213
214
215
216
217 NSAPI_PUBLIC char *util_sh_escape(
char *s)
218 {
219 char *ns = (
char *)
MALLOC(strlen(s) *
2 +
1);
220 register char *t, *u;
221
222 for(t = s, u = ns; *t; ++t, ++u) {
223 if(strchr(
"&;`''\"|*?~<>^()[]{}$\\ #!", *t))
224 *u++ =
'\\';
225 *u = *t;
226 }
227 *u =
'\0';
228 return ns;
229 }
230
231
232
233
234
235 NSAPI_PUBLIC char *util_env_find(
char **env,
const char *name)
236 {
237 char *i;
238 int x, r;
239
240 for(x =
0; env[x]; x++) {
241 i = strchr(env[x],
'=');
242 *i =
'\0';
243 r = !strcmp(env[x], name);
244 *i =
'=';
245 if(r)
246 return i +
1;
247 }
248 return NULL;
249 }
250
251
252
253
254
255 NSAPI_PUBLIC char **util_env_copy(
char **src,
char **dst)
256 {
257 char **src_ptr;
258 int src_cnt;
259 int index;
260
261 if (!src)
262 return NULL;
263
264 for (src_cnt =
0, src_ptr = src; *src_ptr; src_ptr++, src_cnt++);
265
266 if (!src_cnt)
267 return NULL;
268
269 dst = util_env_create(dst, src_cnt, &index);
270
271 for (src_ptr = src; *src_ptr; index++, src_ptr++)
272 dst[index] =
STRDUP(*src_ptr);
273 dst[index] =
NULL;
274
275 return dst;
276 }
277
278
279
280 NSAPI_PUBLIC int util_vsnprintf(
char *s,
int n,
register const char *fmt,
281 va_list args)
282 {
283 return vsnprintf(s, n, fmt, args);
284 }
285
286 NSAPI_PUBLIC int util_snprintf(
char *s,
int n,
const char *fmt, ...)
287 {
288 va_list args;
289 va_start(args, fmt);
290 return vsnprintf(s, n, fmt, args);
291 }
292
293 NSAPI_PUBLIC int util_vasprintf(
pool_handle_t *pool,
char **s,
const char *fmt,
294 va_list args)
295 {
296 CxAllocator *a = pool_allocator(pool);
297 va_list ap;
298 va_copy(ap, args);
299 cxmutstr str = cx_vasprintf_a(a, fmt, ap);
300 *s = str.ptr;
301 return str.length;
302 }
303
304 NSAPI_PUBLIC int util_asprintf(
pool_handle_t *pool,
char **s,
const char *fmt, ...)
305 {
306 va_list args;
307 va_start(args, fmt);
308 return util_vasprintf(pool, s, fmt, args);
309 }
310
311 NSAPI_PUBLIC int util_vsprintf(
char *s,
register const char *fmt, va_list args)
312 {
313 return vsprintf(s, fmt, args);
314 }
315
316 NSAPI_PUBLIC int util_sprintf(
char *s,
const char *fmt, ...)
317 {
318 va_list args;
319 va_start(args, fmt);
320 return vsprintf(s, fmt, args);
321 }
322
323
324
325
326
327
328
329 NSAPI_PUBLIC void util_uri_unescape(
char *s)
330 {
331 char *t, *u;
332
333 for(t = s, u = s; *t; ++t, ++u) {
334 if((*t ==
'%') && t[
1] && t[
2]) {
335 *u = ((t[
1] >=
'A' ? ((t[
1] & 0xdf) -
'A')+
10 : (t[
1] -
'0'))*
16) +
336 (t[
2] >=
'A' ? ((t[
2] & 0xdf) -
'A')+
10 : (t[
2] -
'0'));
337 t +=
2;
338 }
339 else
340 if(u != t)
341 *u = *t;
342 }
343 *u = *t;
344 }
345
346
347
348
349 NSAPI_PUBLIC int util_uri_unescape_strict(
char *s)
350 {
351 char *t, *u, t1, t2;
352 int rv =
1;
353
354 for(t = s, u = s; *t; ++t, ++u) {
355 if (*t ==
'%') {
356 t1 = t[
1] & 0xdf;
357 if ((t1 <
'A' || t1 >
'F') && (t[
1] <
'0' || t[
1] >
'9'))
358 rv =
0;
359
360 t2 = t[
2] & 0xdf;
361 if ((t2 <
'A' || t2 >
'F') && (t[
2] <
'0' || t[
2] >
'9'))
362 rv =
0;
363
364 *u = ((t[
1] >=
'A' ? ((t[
1] & 0xdf) -
'A')+
10 : (t[
1] -
'0'))*
16) +
365 (t[
2] >=
'A' ? ((t[
2] & 0xdf) -
'A')+
10 : (t[
2] -
'0'));
366 t +=
2;
367 }
368 else if (u != t)
369 *u = *t;
370 }
371 *u = *t;
372
373 return rv;
374 }
375
376
377 NSAPI_PUBLIC int
378 util_uri_unescape_plus (
const char *src,
char *trg,
int len)
379 {
380 const char *t = src;
381 char *u = trg ==
NULL ? (
char *)src : trg;
382 int rlen =
0;
383
384 if (len == -
1)
385 len = strlen (src);
386
387 for( ; len && *t; ++t, ++u, len--, rlen++)
388 {
389 if((*t ==
'%') && t[
1] && t[
2])
390 {
391 *u = ((t[
1] >=
'A' ? ((t[
1] & 0xdf) -
'A') +
10 : (t[
1] -
'0')) *
16) +
392 (t[
2] >=
'A' ? ((t[
2] & 0xdf) -
'A') +
10 : (t[
2] -
'0'));
393 t +=
2;
394 len-=
2;
395 }
396 else
397 if (*t ==
'+')
398 *u =
' ';
399 else
400 *u = *t;
401 }
402 *u =
0;
403 return rlen;
404 }
405
406
407 NSAPI_PUBLIC int INTutil_getboolean(
const char *v,
int def) {
408 if(v[
0] ==
'T' || v[
0] ==
't') {
409 return 1;
410 }
411 if(v[
0] ==
'F' || v[
0] ==
'f') {
412 return 0;
413 }
414 return def;
415 }
416
417 int util_getboolean_s(cxstring s,
int def) {
418 if(s.length ==
0) {
419 return def;
420 }
421 if(s.ptr[
0] ==
'T' || s.ptr[
0] ==
't') {
422 return 1;
423 }
424 if(s.ptr[
0] ==
'F' || s.ptr[
0] ==
'f') {
425 return 0;
426 }
427 return def;
428 }
429
430 NSAPI_PUBLIC int util_strtoint(
const char *str,
int64_t *value) {
431 char *end;
432 errno =
0;
433 int64_t val = strtoll(str, &end,
0);
434 if(errno ==
0 && *end ==
'\0') {
435 *value = val;
436 return 1;
437 }
else {
438 return 0;
439 }
440 }
441
442 NSAPI_PUBLIC const char* util_resource_name(
const char *url) {
443 cxstring urlstr = cx_str(url);
444 if(urlstr.ptr[urlstr.length-
1] ==
'/') {
445 urlstr.length--;
446 }
447 cxstring resname = cx_strrchr(urlstr,
'/');
448 if(resname.length >
1) {
449 return resname.ptr+
1;
450 }
else {
451 return url;
452 }
453 }
454
455 NSAPI_PUBLIC char* util_parent_path(
const char *path) {
456 char *name = (
char*)util_resource_name((
char*)path);
457 size_t namelen = strlen(name);
458 size_t pathlen = strlen(path);
459 size_t parentlen = pathlen - namelen;
460 char *parent =
MALLOC(parentlen +
1);
461 memcpy(parent, path, parentlen);
462 parent[parentlen] =
'\0';
463 return parent;
464 }
465
466 NSAPI_PUBLIC char* util_parent_path_pool(
pool_handle_t *pool,
const char *path) {
467
468 char *name = (
char*)util_resource_name((
char*)path);
469 size_t namelen = strlen(name);
470 size_t pathlen = strlen(path);
471 size_t parentlen = pathlen - namelen;
472 char *parent = pool_malloc(pool, parentlen +
1);
473 memcpy(parent, path, parentlen);
474 parent[parentlen] =
'\0';
475 return parent;
476 }
477
478
479
480
481
482
483
484
485
486
487
488
489 NSAPI_PUBLIC int INTutil_itoa(
int i,
char *a) {
490 return INTutil_i64toa(i, a);
491 }
492
493
494
495
496
497
498
499
500
501 NSAPI_PUBLIC int INTutil_i64toa(
int64_t i,
char *a)
502 {
503 register int x, y, p;
504 register char c;
505 int negative;
506
507 negative =
0;
508 if(i <
0) {
509 *a++ =
'-';
510 negative =
1;
511 i = -i;
512 }
513 p =
0;
514 while(i >
9) {
515 a[p++] = (i%
10) +
'0';
516 i /=
10;
517 }
518 a[p++] = i +
'0';
519
520 if(p >
1) {
521 for(x =
0, y = p -
1; x < y; ++x, --y) {
522 c = a[x];
523 a[x] = a[y];
524 a[y] = c;
525 }
526 }
527 a[p] =
'\0';
528
529
530
531 return p + negative;
532 }
533
534
535
536 #ifndef XP_WIN32
537 NSAPI_PUBLIC struct passwd *
538 util_getpwnam(
const char *name,
struct passwd *result,
char *buffer,
539 int buflen)
540 {
541 struct passwd *rv;
542
543 errno = getpwnam_r(name, result, buffer, buflen, &rv);
544 if (errno !=
0)
545 rv =
NULL;
546
547 return rv;
548 }
549 #endif
550
551
552 #ifndef XP_WIN32
553 NSAPI_PUBLIC struct passwd *
554 util_getpwuid(
uid_t uid,
struct passwd *result,
char *buffer,
int buflen)
555 {
556 struct passwd *rv;
557
558 errno = getpwuid_r(uid, result, buffer, buflen, &rv);
559 if (errno !=
0)
560 rv =
NULL;
561
562 return rv;
563 }
564 #endif
565
566
567 NSAPI_PUBLIC int util_errno2status(
int errno_value) {
568 switch(errno_value) {
569 case 0: {
570 return 200;
571 }
572 case EACCES: {
573 return 403;
574 }
575 case ENOENT: {
576 return 404;
577 break;
578 }
579 }
580 return 500;
581 }
582
583
584
585 NSAPI_PUBLIC
586 cxmutstr util_path_append(
pool_handle_t *pool,
char *path,
char *ch) {
587 cxmutstr parent = cx_mutstr(path);
588 cxmutstr child = cx_mutstr(ch);
589 cxmutstr newstr;
590
591 CxAllocator *a = pool_allocator(pool);
592 if(parent.ptr[parent.length-
1] ==
'/') {
593 newstr = cx_strcat_a(a,
2, parent, child);
594 }
else {
595 newstr = cx_strcat_a(a,
3, parent, cx_str(
"/"), child);
596 }
597
598 return newstr;
599 }
600
601 cxmutstr util_path_remove_last(cxmutstr path) {
602 int i;
603 for(i=path.length-
1;i>=
0;i--) {
604 char c = path.ptr[i];
605 if(c ==
'/') {
606 path.ptr[i] =
0;
607 path.length = i;
608 break;
609 }
610 }
611 if(i <
0) {
612 path.ptr =
NULL;
613 path.length =
0;
614 }
615 return path;
616 }
617
618 void util_add_ppath(cxmutstr root, cxmutstr path, pblock *vars) {
619
620 size_t length = root.length + path.length;
621 char *translated_path = alloca(length);
622
623 memcpy(translated_path, root.ptr, root.length);
624 memcpy(translated_path + root.length, path.ptr, path.length);
625
626
627
628 pblock_kvinsert(
629 pb_key_ppath,
630 translated_path,
631 length,
632 vars);
633 }
634
635
636
637 NSAPI_PUBLIC pblock* util_parse_param(
pool_handle_t *pool,
char *query) {
638 pblock *pb = pblock_create_pool(pool,
32);
639 if(!pb) {
640 return NULL;
641 }
642 if(!query || !(*query)) {
643 return pb;
644 }
645
646 int loopFlag =
1;
647 int nl =
0;
648 int vl =
0;
649 int state =
0;
650 const char *np = query;
651 const char *vp =
NULL;
652
653 while (loopFlag) {
654 char delim = *query++;
655 switch (delim) {
656 case '&':
657 case '\0': {
658 if(!delim) {
659 loopFlag =
0;
660 }
661
662 state =
0;
663
664 if(nl >
0) {
665 util_uri_unescape_plus(np,
NULL, nl);
666 util_uri_unescape_plus(vp,
NULL, vl);
667 pblock_nvlinsert(np, nl, vp, vl, pb);
668 }
669
670 nl =
0;
671 vl =
0;
672 vp =
NULL;
673 np = query;
674 break;
675 }
676 case '=': {
677 state =
1;
678 vp = query;
679 break;
680 }
681 default: {
682 if(state) {
683 vl++;
684 }
else {
685 nl++;
686 }
687 }
688 }
689 }
690
691 return pb;
692 }
693
694
695
696
697 static const int MSTR2NUM_HT_MASK = 0xf;
698
699 struct mstr2num_ht {
700 unsigned ucmstr;
701 int mnum;
702 };
703
704 struct mstr2num_ht
MSTR2NUM_HT[] = {
705 {
'A' <<
16 |
'P' <<
8 |
'R',
3 },
706 {
'S' <<
16 |
'E' <<
8 |
'P',
8 },
707 {
'M' <<
16 |
'A' <<
8 |
'Y',
4 },
708 {
0, -
1 },
709 {
'M' <<
16 |
'A' <<
8 |
'R',
2 },
710 {
'F' <<
16 |
'E' <<
8 |
'B',
1 },
711 {
0, -
1 },
712 {
'D' <<
16 |
'E' <<
8 |
'C',
11 },
713 {
'O' <<
16 |
'C' <<
8 |
'T',
9 },
714 {
'J' <<
16 |
'U' <<
8 |
'N',
5 },
715 {
0, -
1 },
716 {
'A' <<
16 |
'U' <<
8 |
'G',
7 },
717 {
'J' <<
16 |
'A' <<
8 |
'N',
0 },
718 {
'J' <<
16 |
'U' <<
8 |
'L',
6 },
719 {
0, -
1 },
720 {
'N' <<
16 |
'O' <<
8 |
'V',
10 }
721 };
722
723 static inline
int _mstr2num(
const char *s)
724 {
725 const unsigned char *mstr = (
const unsigned char *) s;
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746 unsigned char ucmstr0 = mstr[
0] & 0xdf;
747 unsigned ucmstr = ucmstr0 <<
16;
748 if (ucmstr0 !=
'\0') {
749 unsigned char ucmstr1 = mstr[
1] & 0xdf;
750 ucmstr |= ucmstr1 <<
8;
751 if (ucmstr1 !=
'\0') {
752 unsigned char ucmstr2 = mstr[
2] & 0xdf;
753 ucmstr |= ucmstr2;
754
755 unsigned hash = (ucmstr1 >>
2) ^ (ucmstr2 <<
1);
756
757 int i = hash &
MSTR2NUM_HT_MASK;
758
759 if (
MSTR2NUM_HT[i].ucmstr == ucmstr)
760 return MSTR2NUM_HT[i].mnum;
761 }
762 }
763
764 return -
1;
765 }
766
767 NSAPI_PUBLIC int util_mstr2num(
const char *s)
768 {
769 return _mstr2num(s);
770 }
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786 static inline
const char * _parse_day_month(
const char *p,
int *day,
int *month)
787 {
788 *day =
0;
789
790 if (*p ==
',') {
791
792 p++;
793 if (*p ==
' ')
794 p++;
795 while (*p >=
'0' && *p <=
'9')
796 *day = *day *
10 + (*p++ -
'0');
797 if (*p ==
' ' || *p ==
'-')
798 p++;
799 *month = _mstr2num(p);
800 if (*month != -
1)
801 p +=
3;
802 }
else {
803
804 if (*p ==
' ')
805 p++;
806 *month = _mstr2num(p);
807 if (*month != -
1)
808 p +=
3;
809 while (*p ==
' ')
810 p++;
811 while (*p >=
'0' && *p <=
'9')
812 *day = *day *
10 + (*p++ -
'0');
813 }
814
815 return p;
816 }
817
818 static inline
void _parse_year_time(
const char *p,
int *year,
const char ** time)
819 {
820 int _year =
0;
821
822 if (*p ==
'-') {
823
824 p++;
825 while (*p >=
'0' && *p <=
'9')
826 _year = _year *
10 + (*p++ -
'0');
827 if (_year <
70) {
828 _year +=
2000;
829 }
else {
830 _year +=
1900;
831 }
832 if (*p ==
' ')
833 p++;
834 *time = p;
835 }
else {
836
837 if (*p ==
' ')
838 p++;
839 if (p[
0] && p[
1] && p[
2] ==
':') {
840
841 *time = p;
842 p +=
3;
843 while (*p && *p !=
' ')
844 p++;
845 if (*p ==
' ')
846 p++;
847 while (*p >=
'0' && *p <=
'9')
848 _year = _year *
10 + (*p++ -
'0');
849 }
else {
850
851 while (*p >=
'0' && *p <=
'9')
852 _year = _year *
10 + (*p++ -
'0');
853 if (*p ==
' ')
854 p++;
855 *time = p;
856 }
857 }
858
859 *year = _year;
860 }
861
862 NSAPI_PUBLIC int util_str_time_equal(
const char *t1,
const char *t2)
863 {
864
865 while (isspace(*t1))
866 t1++;
867 while (isalpha(*t1))
868 t1++;
869 while (isspace(*t2))
870 t2++;
871 while (isalpha(*t2))
872 t2++;
873
874
875 int day1;
876 int month1;
877 t1 = _parse_day_month(t1, &day1, &month1);
878 int day2;
879 int month2;
880 t2 = _parse_day_month(t2, &day2, &month2);
881 if (day1 != day2)
882 return -
1;
883 if (month1 != month2)
884 return -
1;
885
886
887 int year1;
888 const char *time1;
889 _parse_year_time(t1, &year1, &time1);
890 int year2;
891 const char *time2;
892 _parse_year_time(t2, &year2, &time2);
893 if (year1 != year2)
894 return -
1;
895 while (*time1 && *time1 !=
' ' && *time1 == *time2) {
896 time1++;
897 time2++;
898 }
899 if (*time2 && *time2 !=
' ')
900 return -
1;
901
902 return 0;
903 }
904
905
906
907
908 static int _time_compare(
const struct tm *lms,
const char *ims)
909 {
910 while (isspace(*ims))
911 ims++;
912 while (isalpha(*ims))
913 ims++;
914
915 int day;
916 int month;
917 ims = _parse_day_month(ims, &day, &month);
918 if (month == -
1)
919 return 1;
920
921 int year;
922 const char *time;
923 _parse_year_time(ims, &year, &time);
924
925 int rv;
926
927 rv = (lms->tm_year +
1900) - year;
928 if (rv)
929 return rv;
930
931 rv = lms->tm_mon - month;
932 if (rv)
933 return rv;
934
935 rv = lms->tm_mday - day;
936 if (rv)
937 return rv;
938
939 const char *p = time;
940
941 int hour =
0;
942 while (*p >=
'0' && *p <=
'9')
943 hour = hour *
10 + (*p++ -
'0');
944 if (*p ==
':')
945 p++;
946
947 rv = lms->tm_hour - hour;
948 if (rv)
949 return rv;
950
951 int minutes =
0;
952 while (*p >=
'0' && *p <=
'9')
953 minutes = minutes *
10 + (*p++ -
'0');
954 if (*p ==
':')
955 p++;
956
957 rv = lms->tm_min - minutes;
958 if (rv)
959 return rv;
960
961 int seconds =
0;
962 while (*p >=
'0' && *p <=
'9')
963 seconds = seconds *
10 + (*p++ -
'0');
964 if (*p ==
':')
965 p++;
966
967 rv = lms->tm_sec - seconds;
968 if (rv)
969 return rv;
970
971 return 0;
972 }
973
974 NSAPI_PUBLIC int util_later_than(
const struct tm *lms,
const char *ims)
975 {
976
977
978
979
980
981
982
983 return _time_compare(lms, ims) <=
0;
984 }
985
986 NSAPI_PUBLIC int util_time_equal(
const struct tm *lms,
const char *ims)
987 {
988 return _time_compare(lms, ims) ==
0;
989 }
990
991
992 NSAPI_PUBLIC struct tm *
993 util_gmtime(
const time_t *clock,
struct tm *res)
994 {
995 return gmtime_r(clock, res);
996 }
997
998 int util_isdate(
const char *str) {
999 cxstring datestr = cx_str(str);
1000 cxstring example = cx_str(
"Sun, 06 Nov 1994 08:49:37 GMT");
1001
1002 if(datestr.length != example.length) {
1003 return 0;
1004 }
1005
1006 for(
int i=
0;i<datestr.length;i++) {
1007 char e = example.ptr[i];
1008 if(isdigit(e)) {
1009 if(!isdigit(datestr.ptr[i])) {
1010 return 0;
1011 }
1012 }
else if(e ==
' ') {
1013 if(datestr.ptr[i] !=
' ') {
1014 return 0;
1015 }
1016 }
else if(e ==
',') {
1017 if(datestr.ptr[i] !=
',') {
1018 return 0;
1019 }
1020 }
else if(e ==
':') {
1021 if(datestr.ptr[i] !=
':') {
1022 return 0;
1023 }
1024 }
1025 }
1026
1027 if(!cx_strsuffix(datestr, cx_str(
"GMT"))) {
1028 return 0;
1029 }
1030
1031 return 1;
1032 }
1033
1034
1035
1036
1037
1038 NSAPI_PUBLIC int util_mime_separator(
char *sep)
1039 {
1040 int size =
35;
1041 int pos =
0;
1042
1043 sep[pos++] =
CR;
1044 sep[pos++] =
LF;
1045 sep[pos++] =
'-';
1046 sep[pos++] =
'-';
1047
1048 int r[
6];
1049 for(
int i=
0;i<
6;i++) {
1050 r[i] = rand() %
10000;
1051 }
1052 pos += snprintf(
1053 sep+
4,
1054 size-
4,
1055 "X%04x%04x%04x%04x%04x%04xE",
1056 r[
0],
1057 r[
1],
1058 r[
2],
1059 r[
3],
1060 r[
4],
1061 r[
5]);
1062
1063 return pos;
1064 }
1065
1066
1067
1068
1069 NSAPI_PUBLIC char *util_html_escape(
const char *s)
1070 {
1071 const char *in;
1072
1073 int len =
0;
1074 for (in = s; *in; in++) {
1075 switch (*in) {
1076 case '<':
1077 len +=
4;
1078 break;
1079 case '>':
1080 len +=
4;
1081 break;
1082 case '&':
1083 len +=
5;
1084 break;
1085 case '""':
1086 len +=
6;
1087 break;
1088 case '\'':
1089 len +=
6;
1090 break;
1091 case '+':
1092 len +=
5;
1093 break;
1094 default:
1095 len++;
1096 break;
1097 }
1098 }
1099
1100 char *ns = (
char *)
MALLOC(len +
1);
1101 if (!ns)
1102 return ns;
1103
1104 char *out = ns;
1105 for (in = s; *in; in++) {
1106 switch (*in) {
1107 case '<':
1108 *out++ =
'&';
1109 *out++ =
'l';
1110 *out++ =
't';
1111 *out++ =
';';
1112 break;
1113 case '>':
1114 *out++ =
'&';
1115 *out++ =
'g';
1116 *out++ =
't';
1117 *out++ =
';';
1118 break;
1119 case '&':
1120 *out++ =
'&';
1121 *out++ =
'a';
1122 *out++ =
'm';
1123 *out++ =
'p';
1124 *out++ =
';';
1125 break;
1126 case '""':
1127 *out++ =
'&';
1128 *out++ =
'q';
1129 *out++ =
'u';
1130 *out++ =
'o';
1131 *out++ =
't';
1132 *out++ =
';';
1133 break;
1134 case '\'':
1135 *out++ =
'&';
1136 *out++ =
'a';
1137 *out++ =
'p';
1138 *out++ =
'o';
1139 *out++ =
's';
1140 *out++ =
';';
1141 break;
1142 case '+':
1143 *out++ =
'&';
1144 *out++ =
'#';
1145 *out++ =
'4';
1146 *out++ =
'3';
1147 *out++ =
';';
1148 break;
1149 default:
1150 *out++ = *in;
1151 break;
1152 }
1153 }
1154 *out =
'\0';
1155
1156 return ns;
1157 }
1158
1159