1 /*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4 *
5 * Version: MPL 1.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18 *
19 * The Initial Developer of the Original Code is
20 * Anthony Minessale II <anthm@freeswitch.org>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Anthony Minessale II <anthm@freeswitch.org>
27 * Juan Jose Comellas <juanjo@comellas.org>
28 * Seven Du <dujinfang@gmail.com>
29 *
30 *
31 * switch_utils.c -- Compatibility and Helper Code
32 *
33 */
34
35 #include <switch.h>
36 #ifndef WIN32
37 #include <arpa/inet.h>
38 #if defined(HAVE_SYS_TIME_H) && defined(HAVE_SYS_RESOURCE_H)
39 #include <sys/time.h>
40 #include <sys/resource.h>
41 #endif
42 #include <sys/types.h>
43 #include <unistd.h>
44 #else
45 /* process.h is required for _getpid() */
46 #include <process.h>
47 #endif
48 #include "private/switch_core_pvt.h"
49 #define ESCAPE_META '\\'
50 #ifdef SWITCH_HAVE_GUMBO
51 #include "gumbo.h"
52 #endif
53
54 struct switch_network_node {
55 ip_t ip;
56 ip_t mask;
57 uint32_t bits;
58 int family;
59 switch_bool_t ok;
60 char *token;
61 char *str;
62 switch_network_port_range_t port_range;
63 struct switch_network_node *next;
64 };
65 typedef struct switch_network_node switch_network_node_t;
66
67 struct switch_network_list {
68 struct switch_network_node *node_head;
69 switch_bool_t default_type;
70 switch_memory_pool_t *pool;
71 char *name;
72 };
73
switch_calloc(size_t nmemb,size_t size)74 SWITCH_DECLARE(void *) switch_calloc(size_t nmemb, size_t size)
75 {
76 return calloc(nmemb, size);
77 }
78
79 #ifndef WIN32
switch_inet_pton(int af,const char * src,void * dst)80 SWITCH_DECLARE(int) switch_inet_pton(int af, const char *src, void *dst)
81 {
82 return inet_pton(af, src, dst);
83 }
84 #endif
85
switch_print_host(switch_sockaddr_t * addr,char * buf,switch_size_t len)86 SWITCH_DECLARE(char *) switch_print_host(switch_sockaddr_t *addr, char *buf, switch_size_t len)
87 {
88 switch_port_t port;
89
90 switch_get_addr(buf, len, addr);
91 port = switch_sockaddr_get_port(addr);
92
93 snprintf(buf + strlen(buf), len - strlen(buf), ":%d", port);
94 return buf;
95 }
96
switch_frame_alloc(switch_frame_t ** frame,switch_size_t size)97 SWITCH_DECLARE(switch_status_t) switch_frame_alloc(switch_frame_t **frame, switch_size_t size)
98 {
99 switch_frame_t *new_frame;
100
101 switch_zmalloc(new_frame, sizeof(*new_frame));
102
103 switch_set_flag(new_frame, SFF_DYNAMIC);
104 new_frame->buflen = (uint32_t)size;
105 new_frame->data = malloc(size);
106 switch_assert(new_frame->data);
107
108 *frame = new_frame;
109
110 return SWITCH_STATUS_SUCCESS;
111 }
112
113
114 typedef struct switch_frame_node_s {
115 switch_frame_t *frame;
116 int inuse;
117 struct switch_frame_node_s *prev;
118 struct switch_frame_node_s *next;
119 } switch_frame_node_t;
120
121 struct switch_frame_buffer_s {
122 switch_frame_node_t *head;
123 switch_memory_pool_t *pool;
124 switch_queue_t *queue;
125 switch_mutex_t *mutex;
126 uint32_t total;
127 };
128
find_free_frame(switch_frame_buffer_t * fb,switch_frame_t * orig)129 static switch_frame_t *find_free_frame(switch_frame_buffer_t *fb, switch_frame_t *orig)
130 {
131 switch_frame_node_t *np;
132 int x = 0;
133
134 switch_mutex_lock(fb->mutex);
135
136 for (np = fb->head; np; np = np->next) {
137 x++;
138
139 if (!np->inuse && ((orig->packet && np->frame->packet) || (!orig->packet && !np->frame->packet))) {
140
141 if (np == fb->head) {
142 fb->head = np->next;
143 } else if (np->prev) {
144 np->prev->next = np->next;
145 }
146
147 if (np->next) {
148 np->next->prev = np->prev;
149 }
150
151 fb->total--;
152 np->prev = np->next = NULL;
153 break;
154 }
155 }
156
157 if (!np) {
158 np = switch_core_alloc(fb->pool, sizeof(*np));
159 np->frame = switch_core_alloc(fb->pool, sizeof(*np->frame));
160
161 if (orig->packet) {
162 np->frame->packet = switch_core_alloc(fb->pool, SWITCH_RTP_MAX_BUF_LEN);
163 } else {
164 np->frame->packet = NULL;
165 np->frame->data = switch_core_alloc(fb->pool, SWITCH_RTP_MAX_BUF_LEN);
166 np->frame->buflen = SWITCH_RTP_MAX_BUF_LEN;
167 }
168 }
169
170 np->frame->samples = orig->samples;
171 np->frame->rate = orig->rate;
172 np->frame->channels = orig->channels;
173 np->frame->payload = orig->payload;
174 np->frame->timestamp = orig->timestamp;
175 np->frame->seq = orig->seq;
176 np->frame->ssrc = orig->ssrc;
177 np->frame->m = orig->m;
178 np->frame->flags = orig->flags;
179 np->frame->codec = orig->codec;
180 np->frame->pmap = orig->pmap;
181 np->frame->img = NULL;
182 np->frame->extra_data = np;
183 np->inuse = 1;
184
185 switch_set_flag(np->frame, SFF_DYNAMIC);
186
187 if (orig->packet) {
188 memcpy(np->frame->packet, orig->packet, orig->packetlen);
189 np->frame->packetlen = orig->packetlen;
190 np->frame->data = ((unsigned char *)np->frame->packet) + 12;
191 np->frame->datalen = orig->datalen;
192 } else {
193 np->frame->packet = NULL;
194 np->frame->packetlen = 0;
195 memcpy(np->frame->data, orig->data, orig->datalen);
196 np->frame->datalen = orig->datalen;
197 }
198
199 if (orig->img && !switch_test_flag(orig, SFF_ENCODED)) {
200 switch_img_copy(orig->img, &np->frame->img);
201 }
202
203 switch_mutex_unlock(fb->mutex);
204
205 return np->frame;
206 }
207
switch_frame_buffer_free(switch_frame_buffer_t * fb,switch_frame_t ** frameP)208 SWITCH_DECLARE(switch_status_t) switch_frame_buffer_free(switch_frame_buffer_t *fb, switch_frame_t **frameP)
209 {
210 switch_frame_t *old_frame;
211 switch_frame_node_t *node;
212
213 switch_mutex_lock(fb->mutex);
214
215 old_frame = *frameP;
216 *frameP = NULL;
217
218 node = (switch_frame_node_t *) old_frame->extra_data;
219 node->inuse = 0;
220 switch_img_free(&node->frame->img);
221
222 fb->total++;
223
224 if (fb->head) {
225 fb->head->prev = node;
226 }
227
228 node->next = fb->head;
229 node->prev = NULL;
230 fb->head = node;
231
232 switch_assert(node->next != node);
233 switch_assert(node->prev != node);
234
235
236 switch_mutex_unlock(fb->mutex);
237
238 return SWITCH_STATUS_SUCCESS;
239 }
240
switch_frame_buffer_dup(switch_frame_buffer_t * fb,switch_frame_t * orig,switch_frame_t ** clone)241 SWITCH_DECLARE(switch_status_t) switch_frame_buffer_dup(switch_frame_buffer_t *fb, switch_frame_t *orig, switch_frame_t **clone)
242 {
243 switch_frame_t *new_frame;
244
245 if (!orig) {
246 return SWITCH_STATUS_FALSE;
247 }
248
249 switch_assert(orig->buflen);
250
251 new_frame = find_free_frame(fb, orig);
252
253 *clone = new_frame;
254
255 return SWITCH_STATUS_SUCCESS;
256 }
257
switch_frame_buffer_push(switch_frame_buffer_t * fb,void * ptr)258 SWITCH_DECLARE(switch_status_t) switch_frame_buffer_push(switch_frame_buffer_t *fb, void *ptr)
259 {
260 return switch_queue_push(fb->queue, ptr);
261 }
262
switch_frame_buffer_trypush(switch_frame_buffer_t * fb,void * ptr)263 SWITCH_DECLARE(switch_status_t) switch_frame_buffer_trypush(switch_frame_buffer_t *fb, void *ptr)
264 {
265 return switch_queue_trypush(fb->queue, ptr);
266 }
267
switch_frame_buffer_pop(switch_frame_buffer_t * fb,void ** ptr)268 SWITCH_DECLARE(switch_status_t) switch_frame_buffer_pop(switch_frame_buffer_t *fb, void **ptr)
269 {
270 return switch_queue_pop(fb->queue, ptr);
271 }
272
switch_frame_buffer_trypop(switch_frame_buffer_t * fb,void ** ptr)273 SWITCH_DECLARE(switch_status_t) switch_frame_buffer_trypop(switch_frame_buffer_t *fb, void **ptr)
274 {
275 return switch_queue_trypop(fb->queue, ptr);
276 }
277
switch_frame_buffer_size(switch_frame_buffer_t * fb)278 SWITCH_DECLARE(int) switch_frame_buffer_size(switch_frame_buffer_t *fb)
279 {
280 return switch_queue_size(fb->queue);
281 }
282
switch_frame_buffer_destroy(switch_frame_buffer_t ** fbP)283 SWITCH_DECLARE(switch_status_t) switch_frame_buffer_destroy(switch_frame_buffer_t **fbP)
284 {
285 switch_frame_buffer_t *fb = *fbP;
286 switch_memory_pool_t *pool;
287 *fbP = NULL;
288 pool = fb->pool;
289 switch_core_destroy_memory_pool(&pool);
290
291 return SWITCH_STATUS_SUCCESS;
292 }
293
switch_frame_buffer_create(switch_frame_buffer_t ** fbP,switch_size_t qlen)294 SWITCH_DECLARE(switch_status_t) switch_frame_buffer_create(switch_frame_buffer_t **fbP, switch_size_t qlen)
295 {
296 switch_frame_buffer_t *fb;
297 switch_memory_pool_t *pool;
298
299 if (!qlen) qlen = 500;
300
301 switch_core_new_memory_pool(&pool);
302 fb = switch_core_alloc(pool, sizeof(*fb));
303 fb->pool = pool;
304 switch_queue_create(&fb->queue, qlen, fb->pool);
305 switch_mutex_init(&fb->mutex, SWITCH_MUTEX_NESTED, pool);
306 *fbP = fb;
307
308 return SWITCH_STATUS_SUCCESS;
309 }
310
311
switch_frame_dup(switch_frame_t * orig,switch_frame_t ** clone)312 SWITCH_DECLARE(switch_status_t) switch_frame_dup(switch_frame_t *orig, switch_frame_t **clone)
313 {
314 switch_frame_t *new_frame;
315
316 if (!orig) {
317 return SWITCH_STATUS_FALSE;
318 }
319
320 switch_assert(orig->buflen);
321
322 new_frame = malloc(sizeof(*new_frame));
323 switch_assert(new_frame);
324
325 *new_frame = *orig;
326 switch_set_flag(new_frame, SFF_DYNAMIC);
327
328 if (orig->packet) {
329 new_frame->packet = malloc(SWITCH_RTP_MAX_BUF_LEN);
330 switch_assert(new_frame->packet);
331 memcpy(new_frame->packet, orig->packet, orig->packetlen);
332 new_frame->data = ((unsigned char *)new_frame->packet) + 12;
333 } else {
334 new_frame->packet = NULL;
335 new_frame->data = malloc(new_frame->buflen);
336 switch_assert(new_frame->data);
337 memcpy(new_frame->data, orig->data, orig->datalen);
338 }
339
340
341 new_frame->codec = orig->codec;
342 new_frame->pmap = orig->pmap;
343 new_frame->img = NULL;
344
345
346 if (orig->img && !switch_test_flag(orig, SFF_ENCODED)) {
347 switch_img_copy(orig->img, &new_frame->img);
348 }
349 *clone = new_frame;
350
351 return SWITCH_STATUS_SUCCESS;
352 }
353
switch_frame_free(switch_frame_t ** frame)354 SWITCH_DECLARE(switch_status_t) switch_frame_free(switch_frame_t **frame)
355 {
356 switch_frame_t * f;
357
358 if (!frame) {
359 return SWITCH_STATUS_FALSE;
360 }
361
362 f = *frame;
363
364 if (!f || !switch_test_flag(f, SFF_DYNAMIC)) {
365 return SWITCH_STATUS_FALSE;
366 }
367
368 *frame = NULL;
369
370 if (f->img) {
371 switch_img_free(&(f->img));
372 }
373
374 if (f->packet) {
375 switch_safe_free(f->packet);
376 } else {
377 switch_safe_free(f->data);
378 }
379
380 free(f);
381
382 return SWITCH_STATUS_SUCCESS;
383 }
384
switch_strcasecmp_any(const char * str,...)385 SWITCH_DECLARE(int) switch_strcasecmp_any(const char *str, ...)
386 {
387 va_list ap;
388 const char *next_str = 0;
389 int r = 0;
390
391 va_start(ap, str);
392
393 while ((next_str = va_arg(ap, const char *))) {
394 if (!strcasecmp(str, next_str)) {
395 r = 1;
396 break;
397 }
398 }
399
400 va_end(ap);
401
402 return r;
403 }
404
405
switch_find_parameter(const char * str,const char * param,switch_memory_pool_t * pool)406 SWITCH_DECLARE(char *) switch_find_parameter(const char *str, const char *param, switch_memory_pool_t *pool)
407 {
408 char *e, *r = NULL, *ptr = NULL, *next = NULL;
409 size_t len;
410
411 ptr = (char *) str;
412
413 while (ptr) {
414 len = strlen(param);
415 e = ptr+len;
416 next = strchr(ptr, ';');
417
418 if (!strncasecmp(ptr, param, len) && *e == '=') {
419 size_t mlen;
420
421 ptr = ++e;
422
423 if (next) {
424 e = next;
425 } else {
426 e = ptr + strlen(ptr);
427 }
428
429 mlen = (e - ptr) + 1;
430
431 if (pool) {
432 r = switch_core_alloc(pool, mlen);
433 } else {
434 r = malloc(mlen);
435 }
436
437 switch_snprintf(r, mlen, "%s", ptr);
438
439 break;
440 }
441
442 if (next) {
443 ptr = next + 1;
444 } else break;
445 }
446
447 return r;
448 }
449
switch_network_list_create(switch_network_list_t ** list,const char * name,switch_bool_t default_type,switch_memory_pool_t * pool)450 SWITCH_DECLARE(switch_status_t) switch_network_list_create(switch_network_list_t **list, const char *name, switch_bool_t default_type,
451 switch_memory_pool_t *pool)
452 {
453 switch_network_list_t *new_list;
454
455 if (!pool) {
456 switch_core_new_memory_pool(&pool);
457 }
458
459 new_list = switch_core_alloc(pool, sizeof(**list));
460 new_list->pool = pool;
461 new_list->default_type = default_type;
462 new_list->name = switch_core_strdup(new_list->pool, name);
463
464 *list = new_list;
465
466 return SWITCH_STATUS_SUCCESS;
467 }
468
469 #define IN6_AND_MASK(result, ip, mask) \
470 ((uint32_t *) (result))[0] =((const uint32_t *) (ip))[0] & ((const uint32_t *)(mask))[0]; \
471 ((uint32_t *) (result))[1] =((const uint32_t *) (ip))[1] & ((const uint32_t *)(mask))[1]; \
472 ((uint32_t *) (result))[2] =((const uint32_t *) (ip))[2] & ((const uint32_t *)(mask))[2]; \
473 ((uint32_t *) (result))[3] =((const uint32_t *) (ip))[3] & ((const uint32_t *)(mask))[3];
switch_testv6_subnet(ip_t _ip,ip_t _net,ip_t _mask)474 SWITCH_DECLARE(switch_bool_t) switch_testv6_subnet(ip_t _ip, ip_t _net, ip_t _mask) {
475 if (!IN6_IS_ADDR_UNSPECIFIED(&_mask.v6)) {
476 struct in6_addr a, b;
477 IN6_AND_MASK(&a, &_net, &_mask);
478 IN6_AND_MASK(&b, &_ip, &_mask);
479 return !memcmp(&a,&b, sizeof(struct in6_addr));
480 } else {
481 if (!IN6_IS_ADDR_UNSPECIFIED(&_net.v6)) {
482 return !memcmp(&_net,&_ip,sizeof(struct in6_addr));
483 }
484 else return SWITCH_TRUE;
485 }
486 }
487
switch_network_list_validate_ip6_port_token(switch_network_list_t * list,ip_t ip,int port,const char ** token)488 SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip6_port_token(switch_network_list_t *list, ip_t ip, int port, const char **token)
489 {
490 switch_network_node_t *node;
491 switch_bool_t ok = list->default_type;
492 uint32_t bits = 0;
493
494 for (node = list->node_head; node; node = node->next) {
495 if (node->family == AF_INET) continue;
496
497 if (node->bits >= bits && switch_testv6_subnet(ip, node->ip, node->mask)) {
498 if (node->ok) {
499 ok = SWITCH_TRUE;
500 } else {
501 ok = SWITCH_FALSE;
502 }
503
504 bits = node->bits;
505
506 if (token) {
507 *token = node->token;
508 }
509 }
510 }
511
512 return ok;
513 }
514
is_port_in_node(int port,switch_network_node_t * node)515 SWITCH_DECLARE(switch_bool_t) is_port_in_node(int port, switch_network_node_t *node)
516 {
517 if(port == 0)
518 return SWITCH_TRUE;
519 if(node->port_range.port != 0 && node->port_range.port != port)
520 return SWITCH_FALSE;
521 if(node->port_range.ports[0] != 0) {
522 int i;
523 for(i=0; i < MAX_NETWORK_PORTS && node->port_range.ports[i] != 0; i++) {
524 if(port == node->port_range.ports[i])
525 return SWITCH_TRUE;
526 }
527 return SWITCH_FALSE;
528 }
529 if(node->port_range.min_port != 0 || node->port_range.max_port != 0) {
530 if(port >= node->port_range.min_port && port <= node->port_range.max_port)
531 return SWITCH_TRUE;
532 return SWITCH_FALSE;
533 }
534 return SWITCH_TRUE;
535 }
536
switch_network_list_validate_ip_port_token(switch_network_list_t * list,uint32_t ip,int port,const char ** token)537 SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_port_token(switch_network_list_t *list, uint32_t ip, int port, const char **token)
538 {
539 switch_network_node_t *node;
540 switch_bool_t ok = list->default_type;
541 uint32_t bits = 0;
542
543 for (node = list->node_head; node; node = node->next) {
544 if (node->family == AF_INET6) continue; /* want AF_INET */
545 if (node->bits >= bits && switch_test_subnet(ip, node->ip.v4, node->mask.v4) && is_port_in_node(port, node)) {
546 if (node->ok) {
547 ok = SWITCH_TRUE;
548 } else {
549 ok = SWITCH_FALSE;
550 }
551
552 bits = node->bits;
553
554 if (token) {
555 *token = node->token;
556 }
557 }
558 }
559
560 return ok;
561 }
562
switch_network_list_validate_ip6_token(switch_network_list_t * list,ip_t ip,const char ** token)563 SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip6_token(switch_network_list_t *list, ip_t ip, const char **token)
564 {
565 return switch_network_list_validate_ip6_port_token(list, ip, 0, token);
566 }
567
switch_network_list_validate_ip_token(switch_network_list_t * list,uint32_t ip,const char ** token)568 SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_token(switch_network_list_t *list, uint32_t ip, const char **token)
569 {
570 return switch_network_list_validate_ip_port_token(list, ip, 0, token);
571 }
572
switch_network_ipv4_mapped_ipv6_addr(const char * ip_str)573 SWITCH_DECLARE(char *) switch_network_ipv4_mapped_ipv6_addr(const char* ip_str)
574 {
575 /* ipv4 mapped ipv6 address */
576
577 if (strncasecmp(ip_str, "::ffff:", 7)) {
578 return NULL;
579 }
580
581 return strdup(ip_str + 7);
582 }
583
switch_network_port_range_to_string(switch_network_port_range_p port)584 SWITCH_DECLARE(char*) switch_network_port_range_to_string(switch_network_port_range_p port)
585 {
586 if (!port) {
587 return NULL;
588 }
589
590 if (port->port != 0) {
591 return switch_mprintf("port: %i ", port->port);
592 }
593
594 if (port->ports[0] != 0) {
595 int i, written = 0;
596 char buf[MAX_NETWORK_PORTS * 6];
597 for (i = 0; i < MAX_NETWORK_PORTS && port->ports[i] != 0; i++) {
598 written += snprintf(buf + written, sizeof(buf) - written, (i != 0 ? ", %u" : "%u"), port->ports[i]);
599 }
600 return switch_mprintf("ports: [%s] ", buf);
601 }
602
603 if (port->min_port != 0 || port->max_port != 0) {
604 return switch_mprintf("port range: [%i-%i] ", port->min_port, port->max_port);
605 }
606
607 return NULL;
608 }
609
switch_network_list_perform_add_cidr_token(switch_network_list_t * list,const char * cidr_str,switch_bool_t ok,const char * token,switch_network_port_range_p port)610 SWITCH_DECLARE(switch_status_t) switch_network_list_perform_add_cidr_token(switch_network_list_t *list, const char *cidr_str, switch_bool_t ok,
611 const char *token, switch_network_port_range_p port)
612 {
613 ip_t ip, mask;
614 uint32_t bits;
615 switch_network_node_t *node;
616 char *ipv4 = NULL;
617 char *ports = NULL;
618
619 if ((ipv4 = switch_network_ipv4_mapped_ipv6_addr(cidr_str))) {
620 cidr_str = ipv4;
621 }
622
623 ports = switch_network_port_range_to_string(port);
624
625 if (switch_parse_cidr(cidr_str, &ip, &mask, &bits)) {
626 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Adding %s %s(%s) [%s] to list %s\n",
627 cidr_str, ports ? ports : "", ok ? "allow" : "deny", switch_str_nil(token), list->name);
628 switch_safe_free(ipv4);
629 switch_safe_free(ports);
630 return SWITCH_STATUS_GENERR;
631 }
632
633 node = switch_core_alloc(list->pool, sizeof(*node));
634
635 node->ip = ip;
636 node->mask = mask;
637 node->ok = ok;
638 node->bits = bits;
639 node->str = switch_core_strdup(list->pool, cidr_str);
640 if(port) {
641 memcpy(&node->port_range, port, sizeof(switch_network_port_range_t));
642 }
643
644
645 if (strchr(cidr_str,':')) {
646 node->family = AF_INET6;
647 } else {
648 node->family = AF_INET;
649 }
650
651 if (!zstr(token)) {
652 node->token = switch_core_strdup(list->pool, token);
653 }
654
655 node->next = list->node_head;
656 list->node_head = node;
657
658 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s %s(%s) [%s] to list %s\n",
659 cidr_str, ports ? ports : "", ok ? "allow" : "deny", switch_str_nil(token), list->name);
660
661 switch_safe_free(ipv4);
662 switch_safe_free(ports);
663 return SWITCH_STATUS_SUCCESS;
664 }
665
switch_network_list_add_cidr_port_token(switch_network_list_t * list,const char * cidr_str,switch_bool_t ok,const char * token,switch_network_port_range_p port)666 SWITCH_DECLARE(switch_status_t) switch_network_list_add_cidr_port_token(switch_network_list_t *list, const char *cidr_str, switch_bool_t ok, const char *token, switch_network_port_range_p port)
667 {
668 char *cidr_str_dup = NULL;
669 switch_status_t status = SWITCH_STATUS_SUCCESS;
670
671 if (strchr(cidr_str, ',')) {
672 char *argv[32] = { 0 };
673 int i, argc;
674 cidr_str_dup = strdup(cidr_str);
675
676 switch_assert(cidr_str_dup);
677 if ((argc = switch_separate_string(cidr_str_dup, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) {
678 for (i = 0; i < argc; i++) {
679 switch_status_t this_status;
680 if ((this_status = switch_network_list_perform_add_cidr_token(list, argv[i], ok, token, port)) != SWITCH_STATUS_SUCCESS) {
681 status = this_status;
682 }
683 }
684 }
685 } else {
686 status = switch_network_list_perform_add_cidr_token(list, cidr_str, ok, token, port);
687 }
688
689 switch_safe_free(cidr_str_dup);
690 return status;
691 }
692
switch_network_list_add_cidr_token(switch_network_list_t * list,const char * cidr_str,switch_bool_t ok,const char * token)693 SWITCH_DECLARE(switch_status_t) switch_network_list_add_cidr_token(switch_network_list_t *list, const char *cidr_str, switch_bool_t ok, const char *token)
694 {
695 return switch_network_list_add_cidr_port_token(list, cidr_str, ok, token, NULL);
696 }
697
switch_network_list_add_host_port_mask(switch_network_list_t * list,const char * host,const char * mask_str,switch_bool_t ok,switch_network_port_range_p port)698 SWITCH_DECLARE(switch_status_t) switch_network_list_add_host_port_mask(switch_network_list_t *list, const char *host, const char *mask_str, switch_bool_t ok, switch_network_port_range_p port)
699 {
700 ip_t ip, mask;
701 switch_network_node_t *node;
702
703 switch_inet_pton(AF_INET, host, &ip);
704 switch_inet_pton(AF_INET, mask_str, &mask);
705
706 node = switch_core_alloc(list->pool, sizeof(*node));
707
708 node->ip.v4 = ntohl(ip.v4);
709 node->mask.v4 = ntohl(mask.v4);
710 node->ok = ok;
711 if(port) {
712 memcpy(&node->port_range, port, sizeof(switch_network_port_range_t));
713 }
714
715 /* http://graphics.stanford.edu/~seander/bithacks.html */
716 mask.v4 = mask.v4 - ((mask.v4 >> 1) & 0x55555555);
717 mask.v4 = (mask.v4 & 0x33333333) + ((mask.v4 >> 2) & 0x33333333);
718 node->bits = (((mask.v4 + (mask.v4 >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
719
720 node->str = switch_core_sprintf(list->pool, "%s:%s", host, mask_str);
721
722 node->next = list->node_head;
723 list->node_head = node;
724
725 return SWITCH_STATUS_SUCCESS;
726 }
727
switch_network_list_add_host_mask(switch_network_list_t * list,const char * host,const char * mask_str,switch_bool_t ok)728 SWITCH_DECLARE(switch_status_t) switch_network_list_add_host_mask(switch_network_list_t *list, const char *host, const char *mask_str, switch_bool_t ok)
729 {
730 return switch_network_list_add_host_port_mask(list, host, mask_str, ok, NULL);
731 }
732
733
switch_parse_cidr(const char * string,ip_t * ip,ip_t * mask,uint32_t * bitp)734 SWITCH_DECLARE(int) switch_parse_cidr(const char *string, ip_t *ip, ip_t *mask, uint32_t *bitp)
735 {
736 char host[128];
737 char *bit_str;
738 int32_t bits;
739 const char *ipv6;
740 ip_t *maskv = mask;
741 ip_t *ipv = ip;
742
743 switch_copy_string(host, string, sizeof(host)-1);
744 bit_str = strchr(host, '/');
745
746 if (!bit_str) {
747 return -1;
748 }
749
750 *bit_str++ = '\0';
751 bits = atoi(bit_str);
752 ipv6 = strchr(string, ':');
753 if (ipv6) {
754 int i,n;
755 if (bits < 0 || bits > 128) {
756 return -2;
757 }
758 bits = atoi(bit_str);
759 switch_inet_pton(AF_INET6, host, (unsigned char *)ip);
760 for (n=bits,i=0 ;i < 16; i++){
761 if (n >= 8) {
762 maskv->v6.s6_addr[i] = 0xFF;
763 n -= 8;
764 } else if (n < 8) {
765 maskv->v6.s6_addr[i] = 0xFF & ~(0xFF >> n);
766 n -= n;
767 } else if (n == 0) {
768 maskv->v6.s6_addr[i] = 0x00;
769 }
770 }
771 } else {
772 if (bits < 0 || bits > 32) {
773 return -2;
774 }
775
776 bits = atoi(bit_str);
777 switch_inet_pton(AF_INET, host, (unsigned char *)ip);
778 ipv->v4 = htonl(ipv->v4);
779
780 maskv->v4 = 0xFFFFFFFF & ~(0xFFFFFFFF >> bits);
781 }
782 *bitp = bits;
783
784 return 0;
785 }
786
787
switch_find_end_paren(const char * s,char open,char close)788 SWITCH_DECLARE(char *) switch_find_end_paren(const char *s, char open, char close)
789 {
790 const char *e = NULL;
791 int depth = 0;
792
793 while (s && *s && *s == ' ') {
794 s++;
795 }
796
797 if (s && *s == open) {
798 depth++;
799 for (e = s + 1; e && *e; e++) {
800 if (*e == open && open != close) {
801 depth++;
802 } else if (*e == close) {
803 depth--;
804 if (!depth) {
805 break;
806 }
807 }
808 }
809 }
810
811 return (e && *e == close) ? (char *) e : NULL;
812 }
813
switch_fd_read_line(int fd,char * buf,switch_size_t len)814 SWITCH_DECLARE(switch_size_t) switch_fd_read_line(int fd, char *buf, switch_size_t len)
815 {
816 char c, *p;
817 int cur;
818 switch_size_t total = 0;
819
820 p = buf;
821 while (total + 2 < len && (cur = read(fd, &c, 1)) == 1) {
822 total += cur;
823 *p++ = c;
824 if (c == '\r' || c == '\n') {
825 break;
826 }
827 }
828
829 *p++ = '\0';
830 assert(total < len);
831 return total;
832 }
833
834 #define DLINE_BLOCK_SIZE 1024
835 #define DLINE_MAX_SIZE 1048576
switch_fd_read_dline(int fd,char ** buf,switch_size_t * len)836 SWITCH_DECLARE(switch_size_t) switch_fd_read_dline(int fd, char **buf, switch_size_t *len)
837 {
838 char c, *p;
839 int cur;
840 switch_size_t total = 0;
841 char *data = *buf;
842 switch_size_t ilen = *len;
843
844 if (!data) {
845 *len = ilen = DLINE_BLOCK_SIZE;
846 data = malloc(ilen);
847 memset(data, 0, ilen);
848 }
849
850 p = data;
851 while ((cur = read(fd, &c, 1)) == 1) {
852
853 if (total + 2 >= ilen) {
854 if (ilen + DLINE_BLOCK_SIZE > DLINE_MAX_SIZE) {
855 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Single line limit reached!\n");
856 break;
857 }
858
859 ilen += DLINE_BLOCK_SIZE;
860 data = realloc(data, ilen);
861 switch_assert(data);
862 p = data + total;
863
864 }
865
866 total += cur;
867 *p++ = c;
868
869 if (c == '\r' || c == '\n') {
870 break;
871 }
872 }
873
874 *p++ = '\0';
875
876 *len = ilen;
877 *buf = data;
878
879 return total;
880 }
881
882
883
switch_fp_read_dline(FILE * fd,char ** buf,switch_size_t * len)884 SWITCH_DECLARE(switch_size_t) switch_fp_read_dline(FILE *fd, char **buf, switch_size_t *len)
885 {
886 char c, *p;
887 switch_size_t total = 0;
888 char *data = *buf;
889 switch_size_t ilen = *len;
890
891 if (!data) {
892 *len = ilen = DLINE_BLOCK_SIZE;
893 data = malloc(ilen);
894 memset(data, 0, ilen);
895 }
896
897 p = data;
898 //while ((c = fgetc(fd)) != EOF) {
899
900 while (fread(&c, 1, 1, fd) == 1) {
901
902 if (total + 2 >= ilen) {
903 if (ilen + DLINE_BLOCK_SIZE > DLINE_MAX_SIZE) {
904 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Single line limit reached!\n");
905 break;
906 }
907
908 ilen += DLINE_BLOCK_SIZE;
909 data = realloc(data, ilen);
910 switch_assert(data);
911 p = data + total;
912
913 }
914
915 total++;
916 *p++ = c;
917
918 if (c == '\r' || c == '\n') {
919 break;
920 }
921 }
922
923 *p++ = '\0';
924
925 *len = ilen;
926 *buf = data;
927
928 return total;
929 }
930
switch_amp_encode(char * s,char * buf,switch_size_t len)931 SWITCH_DECLARE(char *) switch_amp_encode(char *s, char *buf, switch_size_t len)
932 {
933 char *p, *q;
934 switch_size_t x = 0;
935 switch_assert(s);
936
937 q = buf;
938
939 for (p = s; x < len; p++) {
940 switch (*p) {
941
942 case '"':
943 if (x + 6 > len - 1) {
944 goto end;
945 }
946 *q++ = '&';
947 *q++ = 'q';
948 *q++ = 'u';
949 *q++ = 'o';
950 *q++ = 't';
951 *q++ = ';';
952 x += 6;
953 break;
954 case '\'':
955 if (x + 6 > len - 1) {
956 goto end;
957 }
958 *q++ = '&';
959 *q++ = 'a';
960 *q++ = 'p';
961 *q++ = 'o';
962 *q++ = 's';
963 *q++ = ';';
964 x += 6;
965 break;
966 case '&':
967 if (x + 5 > len - 1) {
968 goto end;
969 }
970 *q++ = '&';
971 *q++ = 'a';
972 *q++ = 'm';
973 *q++ = 'p';
974 *q++ = ';';
975 x += 5;
976 break;
977 case '<':
978 if (x + 4 > len - 1) {
979 goto end;
980 }
981 *q++ = '&';
982 *q++ = 'l';
983 *q++ = 't';
984 *q++ = ';';
985 x += 4;
986 break;
987 case '>':
988 if (x + 4 > len - 1) {
989 goto end;
990 }
991 *q++ = '&';
992 *q++ = 'g';
993 *q++ = 't';
994 *q++ = ';';
995 x += 4;
996 break;
997 default:
998 if (x + 1 > len - 1) {
999 goto end;
1000 }
1001 *q++ = *p;
1002 x++;
1003 if (*p == '\0') {
1004 goto end;
1005 }
1006 break;
1007 }
1008 }
1009
1010 end:
1011
1012 return buf;
1013 }
1014
1015 static const char switch_b64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1016 #define B64BUFFLEN 1024
switch_b64_encode(unsigned char * in,switch_size_t ilen,unsigned char * out,switch_size_t olen)1017 SWITCH_DECLARE(switch_status_t) switch_b64_encode(unsigned char *in, switch_size_t ilen, unsigned char *out, switch_size_t olen)
1018 {
1019 int y = 0, bytes = 0;
1020 size_t x = 0;
1021 unsigned int b = 0, l = 0;
1022
1023 for (x = 0; x < ilen; x++) {
1024 b = (b << 8) + in[x];
1025 l += 8;
1026
1027 while (l >= 6) {
1028 out[bytes++] = switch_b64_table[(b >> (l -= 6)) % 64];
1029 if (bytes >= (int)olen - 1) {
1030 goto end;
1031 }
1032 if (++y != 72) {
1033 continue;
1034 }
1035 /* out[bytes++] = '\n'; */
1036 y = 0;
1037 }
1038 }
1039
1040 if (l > 0) {
1041 out[bytes++] = switch_b64_table[((b % 16) << (6 - l)) % 64];
1042 }
1043 if (l != 0) {
1044 while (l < 6 && bytes < (int)olen - 1) {
1045 out[bytes++] = '=', l += 2;
1046 }
1047 }
1048
1049 end:
1050
1051 out[bytes] = '\0';
1052
1053 return SWITCH_STATUS_SUCCESS;
1054 }
1055
switch_b64_decode(const char * in,char * out,switch_size_t olen)1056 SWITCH_DECLARE(switch_size_t) switch_b64_decode(const char *in, char *out, switch_size_t olen)
1057 {
1058
1059 char l64[256];
1060 int b = 0, c, l = 0, i;
1061 const char *ip;
1062 char *op = out;
1063 size_t ol = 0;
1064
1065 for (i = 0; i < 256; i++) {
1066 l64[i] = -1;
1067 }
1068
1069 for (i = 0; i < 64; i++) {
1070 l64[(int) switch_b64_table[i]] = (char) i;
1071 }
1072
1073 for (ip = in; ip && *ip; ip++) {
1074 c = l64[(int) *ip];
1075 if (c == -1) {
1076 continue;
1077 }
1078
1079 b = (b << 6) + c;
1080 l += 6;
1081
1082 while (l >= 8) {
1083 op[ol++] = (char) ((b >> (l -= 8)) % 256);
1084 if (ol >= olen - 2) {
1085 goto end;
1086 }
1087 }
1088 }
1089
1090 end:
1091
1092 op[ol++] = '\0';
1093
1094 return ol;
1095 }
1096
write_buf(int fd,const char * buf)1097 static int write_buf(int fd, const char *buf)
1098 {
1099
1100 int len = (int) strlen(buf);
1101 if (fd && write(fd, buf, len) != len) {
1102 close(fd);
1103 return 0;
1104 }
1105
1106 return 1;
1107 }
1108
switch_simple_email(const char * to,const char * from,const char * headers,const char * body,const char * file,const char * convert_cmd,const char * convert_ext)1109 SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to,
1110 const char *from,
1111 const char *headers,
1112 const char *body, const char *file, const char *convert_cmd, const char *convert_ext)
1113 {
1114 char *bound = "XXXX_boundary_XXXX";
1115 const char *mime_type = "audio/inline";
1116 char filename[80], buf[B64BUFFLEN];
1117 int fd = -1, ifd = -1;
1118 int x = 0, y = 0, bytes = 0, ilen = 0;
1119 unsigned int b = 0, l = 0;
1120 unsigned char in[B64BUFFLEN];
1121 unsigned char out[B64BUFFLEN + 512];
1122 char *dupfile = NULL, *ext = NULL;
1123 char *newfile = NULL;
1124 switch_bool_t rval = SWITCH_FALSE;
1125 const char *err = NULL;
1126
1127 if (zstr(to)) {
1128 err = "No to address specified";
1129 goto end;
1130 }
1131
1132 if (!zstr(file) && !zstr(convert_cmd) && !zstr(convert_ext)) {
1133 if ((ext = strrchr(file, '.'))) {
1134 dupfile = strdup(file);
1135 if ((ext = strrchr(dupfile, '.'))) {
1136 *ext++ = '\0';
1137 newfile = switch_mprintf("%s.%s", dupfile, convert_ext);
1138 }
1139 }
1140
1141 if (newfile) {
1142 char cmd[1024] = "";
1143 switch_snprintf(cmd, sizeof(cmd), "%s %s %s", convert_cmd, file, newfile);
1144 switch_system(cmd, SWITCH_TRUE);
1145 if (strcmp(file, newfile)) {
1146 file = newfile;
1147 } else {
1148 switch_safe_free(newfile);
1149 }
1150 }
1151
1152 switch_safe_free(dupfile);
1153 }
1154
1155 switch_snprintf(filename, 80, "%s%smail.%d%04x", SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, (int) switch_epoch_time_now(NULL), rand() & 0xffff);
1156
1157 if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644)) > -1) {
1158 if (file) {
1159 if ((ifd = open(file, O_RDONLY | O_BINARY)) < 0) {
1160 rval = SWITCH_FALSE;
1161 err = "Cannot open tmp file\n";
1162 goto end;
1163 }
1164 }
1165
1166 if (!file && (!body || !switch_stristr("content-type", body))) {
1167 bound = NULL;
1168 }
1169
1170 if (bound) {
1171 switch_snprintf(buf, B64BUFFLEN, "MIME-Version: 1.0\nContent-Type: multipart/mixed; boundary=\"%s\"\n", bound);
1172 if (!write_buf(fd, buf)) {
1173 rval = SWITCH_FALSE;
1174 err = "write error.";
1175 goto end;
1176 }
1177 }
1178
1179 if (headers && !write_buf(fd, headers)) {
1180 rval = SWITCH_FALSE;
1181 err = "write error.";
1182 goto end;
1183 }
1184
1185 if (!write_buf(fd, "\n\n")) {
1186 rval = SWITCH_FALSE;
1187 err = "write error.";
1188 goto end;
1189 }
1190
1191 if (bound) {
1192 if (body && switch_stristr("content-type", body)) {
1193 switch_snprintf(buf, B64BUFFLEN, "--%s\n", bound);
1194 } else {
1195 switch_snprintf(buf, B64BUFFLEN, "--%s\nContent-Type: text/plain\n\n", bound);
1196 }
1197 if (!write_buf(fd, buf)) {
1198 rval = SWITCH_FALSE;
1199 err = "write error.";
1200 goto end;
1201 }
1202 }
1203
1204 if (body) {
1205 if (!write_buf(fd, body)) {
1206 rval = SWITCH_FALSE;
1207 err = "write error.";
1208 goto end;
1209 }
1210 }
1211
1212 if (file && bound) {
1213 const char *stipped_file = switch_cut_path(file);
1214 const char *new_type;
1215 char *ext;
1216
1217 if ((ext = strrchr(stipped_file, '.'))) {
1218 ext++;
1219 if ((new_type = switch_core_mime_ext2type(ext))) {
1220 mime_type = new_type;
1221 }
1222 }
1223
1224 switch_snprintf(buf, B64BUFFLEN,
1225 "\n\n--%s\nContent-Type: %s; name=\"%s\"\n"
1226 "Content-ID: <ATTACHED@freeswitch.org>\n"
1227 "Content-Transfer-Encoding: base64\n"
1228 "Content-Description: Sound attachment.\n"
1229 "Content-Disposition: attachment; filename=\"%s\"\n\n", bound, mime_type, stipped_file, stipped_file);
1230 if (!write_buf(fd, buf)) {
1231 rval = SWITCH_FALSE;
1232 err = "write error.";
1233 goto end;
1234 }
1235
1236 while ((ilen = read(ifd, in, B64BUFFLEN))) {
1237 for (x = 0; x < ilen; x++) {
1238 b = (b << 8) + in[x];
1239 l += 8;
1240 while (l >= 6) {
1241 out[bytes++] = switch_b64_table[(b >> (l -= 6)) % 64];
1242 if (++y != 72)
1243 continue;
1244 out[bytes++] = '\n';
1245 y = 0;
1246 }
1247 }
1248 if (write(fd, &out, bytes) != bytes) {
1249 rval = -1;
1250 break;
1251 } else {
1252 bytes = 0;
1253 }
1254
1255 }
1256
1257 if (l > 0) {
1258 out[bytes++] = switch_b64_table[((b % 16) << (6 - l)) % 64];
1259 }
1260 if (l != 0)
1261 while (l < 6) {
1262 out[bytes++] = '=', l += 2;
1263 }
1264 if (write(fd, &out, bytes) != bytes) {
1265 rval = -1;
1266 }
1267
1268 }
1269
1270 if (bound) {
1271 switch_snprintf(buf, B64BUFFLEN, "\n\n--%s--\n.\n", bound);
1272
1273 if (!write_buf(fd, buf)) {
1274 rval = SWITCH_FALSE;
1275 err = "write error.";
1276 goto end;
1277 }
1278 }
1279 }
1280
1281 if (fd > -1) {
1282 close(fd);
1283 fd = -1;
1284 }
1285
1286 if (zstr(from)) {
1287 from = "freeswitch";
1288 }
1289
1290 {
1291 char *to_arg = switch_util_quote_shell_arg(to);
1292 char *from_arg = switch_util_quote_shell_arg(from);
1293 #ifdef WIN32
1294 switch_snprintf(buf, B64BUFFLEN, "\"\"%s\" -f %s %s %s < \"%s\"\"", runtime.mailer_app, from_arg, runtime.mailer_app_args, to_arg, filename);
1295 #else
1296 switch_snprintf(buf, B64BUFFLEN, "/bin/cat %s | %s -f %s %s %s", filename, runtime.mailer_app, from_arg, runtime.mailer_app_args, to_arg);
1297 #endif
1298 switch_safe_free(to_arg); switch_safe_free(from_arg);
1299 }
1300 if (switch_system(buf, SWITCH_TRUE) < 0) {
1301 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to execute command: %s\n", buf);
1302 err = "execute error";
1303 rval = SWITCH_FALSE;
1304 }
1305
1306 if (zstr(err)) {
1307 if (file) {
1308 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Emailed file [%s] to [%s]\n", filename, to);
1309 } else {
1310 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Emailed data to [%s]\n", to);
1311 }
1312
1313 rval = SWITCH_TRUE;
1314 }
1315
1316 end:
1317
1318 if (fd > -1) {
1319 close(fd);
1320 }
1321
1322 if (unlink(filename) != 0) {
1323 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to delete file [%s]\n", filename);
1324 }
1325
1326 if (ifd > -1) {
1327 close(ifd);
1328 }
1329
1330
1331 if (newfile) {
1332 unlink(newfile);
1333 free(newfile);
1334 }
1335
1336 if (rval != SWITCH_TRUE) {
1337 if (zstr(err)) err = "Unknown Error";
1338
1339 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "EMAIL NOT SENT, error [%s]\n", err);
1340 }
1341
1342 return rval;
1343 }
1344
switch_is_lan_addr(const char * ip)1345 SWITCH_DECLARE(switch_bool_t) switch_is_lan_addr(const char *ip)
1346 {
1347 if (zstr(ip))
1348 return SWITCH_FALSE;
1349
1350 return (strncmp(ip, "10.", 3) && /* 10.0.0.0 - 10.255.255.255 (10/8 prefix) */
1351 strncmp(ip, "192.168.", 8) && /* 192.168.0.0 - 192.168.255.255 (192.168/16 prefix) */
1352 strncmp(ip, "127.", 4) && /* 127.0.0.0 - 127.255.255.255 (127/8 prefix) */
1353 strncmp(ip, "255.", 4) &&
1354 strncmp(ip, "0.", 2) &&
1355 strncmp(ip, "1.", 2) &&
1356 strncmp(ip, "2.", 2) &&
1357 strncmp(ip, "172.16.", 7) && /* 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) */
1358 strncmp(ip, "172.17.", 7) &&
1359 strncmp(ip, "172.18.", 7) &&
1360 strncmp(ip, "172.19.", 7) &&
1361 strncmp(ip, "172.20.", 7) &&
1362 strncmp(ip, "172.21.", 7) &&
1363 strncmp(ip, "172.22.", 7) &&
1364 strncmp(ip, "172.23.", 7) &&
1365 strncmp(ip, "172.24.", 7) &&
1366 strncmp(ip, "172.25.", 7) &&
1367 strncmp(ip, "172.26.", 7) &&
1368 strncmp(ip, "172.27.", 7) &&
1369 strncmp(ip, "172.28.", 7) &&
1370 strncmp(ip, "172.29.", 7) &&
1371 strncmp(ip, "172.30.", 7) &&
1372 strncmp(ip, "172.31.", 7) &&
1373 strncmp(ip, "192.0.2.", 8) && /* 192.0.2.0 - 192.0.2.255 (192.0.2/24 prefix) */
1374 strncmp(ip, "169.254.", 8) /* 169.254.0.0 - 169.254.255.255 (169.254/16 prefix) */
1375 )? SWITCH_FALSE : SWITCH_TRUE;
1376 }
1377
switch_ast2regex(const char * pat,char * rbuf,size_t len)1378 SWITCH_DECLARE(switch_bool_t) switch_ast2regex(const char *pat, char *rbuf, size_t len)
1379 {
1380 const char *p = pat;
1381
1382 if (!pat) {
1383 return SWITCH_FALSE;
1384 }
1385
1386 memset(rbuf, 0, len);
1387
1388 *(rbuf + strlen(rbuf)) = '^';
1389
1390 while (p && *p) {
1391 if (*p == 'N') {
1392 strncat(rbuf, "[2-9]", len - strlen(rbuf));
1393 } else if (*p == 'X') {
1394 strncat(rbuf, "[0-9]", len - strlen(rbuf));
1395 } else if (*p == 'Z') {
1396 strncat(rbuf, "[1-9]", len - strlen(rbuf));
1397 } else if (*p == '.') {
1398 strncat(rbuf, ".*", len - strlen(rbuf));
1399 } else if (strlen(rbuf) < len - 1) {
1400 *(rbuf + strlen(rbuf)) = *p;
1401 }
1402 p++;
1403 }
1404 *(rbuf + strlen(rbuf)) = '$';
1405
1406 return strcmp(pat, rbuf) ? SWITCH_TRUE : SWITCH_FALSE;
1407 }
1408
switch_replace_char(char * str,char from,char to,switch_bool_t dup)1409 SWITCH_DECLARE(char *) switch_replace_char(char *str, char from, char to, switch_bool_t dup)
1410 {
1411 char *p;
1412
1413 if (dup) {
1414 p = strdup(str);
1415 switch_assert(p);
1416 } else {
1417 p = str;
1418 }
1419
1420 for (; p && *p; p++) {
1421 if (*p == from) {
1422 *p = to;
1423 }
1424 }
1425
1426 return p;
1427 }
1428
switch_pool_strip_whitespace(switch_memory_pool_t * pool,const char * str)1429 SWITCH_DECLARE(char *) switch_pool_strip_whitespace(switch_memory_pool_t *pool, const char *str)
1430 {
1431 const char *sp = str;
1432 char *p, *s = NULL;
1433 size_t len;
1434
1435 if (zstr(sp)) {
1436 return switch_core_strdup(pool, SWITCH_BLANK_STRING);
1437 }
1438
1439 while ((*sp == 13 ) || (*sp == 10 ) || (*sp == 9 ) || (*sp == 32) || (*sp == 11) ) {
1440 sp++;
1441 }
1442
1443 if (zstr(sp)) {
1444 return switch_core_strdup(pool, SWITCH_BLANK_STRING);
1445 }
1446
1447 s = switch_core_strdup(pool, sp);
1448 switch_assert(s);
1449
1450 if ((len = strlen(s)) > 0) {
1451 p = s + (len - 1);
1452
1453 while ((p >= s) && ((*p == 13 ) || (*p == 10 ) || (*p == 9 ) || (*p == 32) || (*p == 11))) {
1454 *p-- = '\0';
1455 }
1456 }
1457
1458 return s;
1459 }
1460
switch_strip_whitespace(const char * str)1461 SWITCH_DECLARE(char *) switch_strip_whitespace(const char *str)
1462 {
1463 const char *sp = str;
1464 char *p, *s = NULL;
1465 size_t len;
1466
1467 if (zstr(sp)) {
1468 return strdup(SWITCH_BLANK_STRING);
1469 }
1470
1471 while ((*sp == 13 ) || (*sp == 10 ) || (*sp == 9 ) || (*sp == 32) || (*sp == 11) ) {
1472 sp++;
1473 }
1474
1475 if (zstr(sp)) {
1476 return strdup(SWITCH_BLANK_STRING);
1477 }
1478
1479 s = strdup(sp);
1480 switch_assert(s);
1481
1482 if ((len = strlen(s)) > 0) {
1483 p = s + (len - 1);
1484
1485 while ((p >= s) && ((*p == 13 ) || (*p == 10 ) || (*p == 9 ) || (*p == 32) || (*p == 11))) {
1486 *p-- = '\0';
1487 }
1488 }
1489
1490 return s;
1491 }
1492
switch_strip_spaces(char * str,switch_bool_t dup)1493 SWITCH_DECLARE(char *) switch_strip_spaces(char *str, switch_bool_t dup)
1494 {
1495 char *sp = str;
1496 char *p, *s = NULL;
1497 size_t len;
1498
1499 if (zstr(sp)) {
1500 return dup ? strdup(SWITCH_BLANK_STRING) : sp;
1501 }
1502
1503 while (*sp == ' ') {
1504 sp++;
1505 }
1506
1507 if (dup) {
1508 s = strdup(sp);
1509 switch_assert(s);
1510 } else {
1511 s = sp;
1512 }
1513
1514 if (zstr(s)) {
1515 return s;
1516 }
1517
1518 if ((len = strlen(s)) > 0) {
1519 p = s + (len - 1);
1520
1521 while (p && *p && (p >= s) && *p == ' ') {
1522 *p-- = '\0';
1523 }
1524 }
1525
1526 return s;
1527 }
1528
switch_strip_commas(char * in,char * out,switch_size_t len)1529 SWITCH_DECLARE(char *) switch_strip_commas(char *in, char *out, switch_size_t len)
1530 {
1531 char *p = in, *q = out;
1532 char *ret = out;
1533 switch_size_t x = 0;
1534
1535 for (; p && *p; p++) {
1536 if ((*p > 47 && *p < 58)) {
1537 *q++ = *p;
1538
1539 if (++x > len) {
1540 ret = NULL;
1541 break;
1542 }
1543 } else if (*p != ',') {
1544 ret = NULL;
1545 break;
1546 }
1547 }
1548
1549 return ret;
1550 }
1551
switch_strip_nonnumerics(char * in,char * out,switch_size_t len)1552 SWITCH_DECLARE(char *) switch_strip_nonnumerics(char *in, char *out, switch_size_t len)
1553 {
1554 char *p = in, *q = out;
1555 char *ret = out;
1556 switch_size_t x = 0;
1557 /* valid are 0 - 9, period (.), minus (-), and plus (+) - remove all others */
1558 for (; p && *p; p++) {
1559 if ((*p > 47 && *p < 58) || *p == '.' || *p == '-' || *p == '+') {
1560 *q++ = *p;
1561
1562 if (++x > len) {
1563 ret = NULL;
1564 break;
1565 }
1566 }
1567 }
1568
1569 return ret;
1570 }
1571
switch_separate_paren_args(char * str)1572 SWITCH_DECLARE(char *) switch_separate_paren_args(char *str)
1573 {
1574 char *e, *args;
1575 switch_size_t br;
1576
1577 if ((args = strchr(str, '('))) {
1578 e = args - 1;
1579 *args++ = '\0';
1580 while (*e == ' ') {
1581 *e-- = '\0';
1582 }
1583 e = args;
1584 br = 1;
1585 while (e && *e) {
1586 if (*e == '(') {
1587 br++;
1588 } else if (br > 1 && *e == ')') {
1589 br--;
1590 } else if (br == 1 && *e == ')') {
1591 *e = '\0';
1592 break;
1593 }
1594 e++;
1595 }
1596 }
1597
1598 return args;
1599 }
1600
switch_is_number(const char * str)1601 SWITCH_DECLARE(switch_bool_t) switch_is_number(const char *str)
1602 {
1603 const char *p;
1604 switch_bool_t r = SWITCH_TRUE;
1605
1606 if (*str == '-' || *str == '+') {
1607 str++;
1608 }
1609
1610 for (p = str; p && *p; p++) {
1611 if (!(*p == '.' || (*p > 47 && *p < 58))) {
1612 r = SWITCH_FALSE;
1613 break;
1614 }
1615 }
1616
1617 return r;
1618 }
1619
switch_is_leading_number(const char * str)1620 SWITCH_DECLARE(switch_bool_t) switch_is_leading_number(const char *str)
1621 {
1622 const char *p;
1623 switch_bool_t r = SWITCH_FALSE;
1624
1625 if (*str == '-' || *str == '+') {
1626 str++;
1627 }
1628
1629 for (p = str; p && *p; p++) {
1630 if ((*p == '.' || (*p > 47 && *p < 58))) {
1631 r = SWITCH_TRUE;
1632 break;
1633 }
1634 }
1635
1636 return r;
1637 }
1638
switch_stristr(const char * instr,const char * str)1639 SWITCH_DECLARE(const char *) switch_stristr(const char *instr, const char *str)
1640 {
1641 /*
1642 ** Rev History: 16/07/97 Greg Thayer Optimized
1643 ** 07/04/95 Bob Stout ANSI-fy
1644 ** 02/03/94 Fred Cole Original
1645 ** 09/01/03 Bob Stout Bug fix (lines 40-41) per Fred Bulback
1646 **
1647 ** Hereby donated to public domain.
1648 */
1649 const char *pptr, *sptr, *start;
1650
1651 if (!str || !instr)
1652 return NULL;
1653
1654 for (start = str; *start; start++) {
1655 /* find start of pattern in string */
1656 for (; ((*start) && (switch_toupper(*start) != switch_toupper(*instr))); start++);
1657
1658 if (!*start)
1659 return NULL;
1660
1661 pptr = instr;
1662 sptr = start;
1663
1664 while (switch_toupper(*sptr) == switch_toupper(*pptr)) {
1665 sptr++;
1666 pptr++;
1667
1668 /* if end of pattern then pattern was found */
1669 if (!*pptr)
1670 return (start);
1671
1672 if (!*sptr)
1673 return NULL;
1674 }
1675 }
1676 return NULL;
1677 }
1678
1679 #ifdef HAVE_GETIFADDRS
1680 #include <ifaddrs.h>
get_netmask(struct sockaddr_in * me,int * mask)1681 static int get_netmask(struct sockaddr_in *me, int *mask)
1682 {
1683 struct ifaddrs *ifaddrs, *i = NULL;
1684
1685 if (!me || getifaddrs(&ifaddrs) < 0) {
1686 return -1;
1687 }
1688
1689 for (i = ifaddrs; i; i = i->ifa_next) {
1690 struct sockaddr_in *s = (struct sockaddr_in *) i->ifa_addr;
1691 struct sockaddr_in *m = (struct sockaddr_in *) i->ifa_netmask;
1692
1693 if (s && m && s->sin_family == AF_INET && s->sin_addr.s_addr == me->sin_addr.s_addr) {
1694 *mask = m->sin_addr.s_addr;
1695 freeifaddrs(ifaddrs);
1696 return 0;
1697 }
1698 }
1699
1700 freeifaddrs(ifaddrs);
1701
1702 return -2;
1703 }
1704 #elif defined(__linux__)
1705
1706 #include <sys/ioctl.h>
1707 #include <net/if.h>
get_netmask(struct sockaddr_in * me,int * mask)1708 static int get_netmask(struct sockaddr_in *me, int *mask)
1709 {
1710
1711 static struct ifreq ifreqs[20] = { {{{0}}} };
1712 struct ifconf ifconf;
1713 int nifaces, i;
1714 int sock;
1715 int r = -1;
1716
1717 memset(&ifconf, 0, sizeof(ifconf));
1718 ifconf.ifc_buf = (char *) (ifreqs);
1719 ifconf.ifc_len = sizeof(ifreqs);
1720
1721
1722 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
1723 goto end;
1724 }
1725
1726 if (ioctl(sock, SIOCGIFCONF, (char *) &ifconf) < 0) {
1727 goto end;
1728 }
1729
1730 nifaces = ifconf.ifc_len / sizeof(struct ifreq);
1731
1732 for (i = 0; i < nifaces; i++) {
1733 struct sockaddr_in *sin = NULL;
1734 struct in_addr ip;
1735
1736 ioctl(sock, SIOCGIFADDR, &ifreqs[i]);
1737 sin = (struct sockaddr_in *) &ifreqs[i].ifr_addr;
1738 ip = sin->sin_addr;
1739
1740 if (ip.s_addr == me->sin_addr.s_addr) {
1741 ioctl(sock, SIOCGIFNETMASK, &ifreqs[i]);
1742 sin = (struct sockaddr_in *) &ifreqs[i].ifr_addr;
1743 /* mask = sin->sin_addr; */
1744 *mask = sin->sin_addr.s_addr;
1745 r = 0;
1746 break;
1747 }
1748
1749 }
1750
1751 end:
1752
1753 close(sock);
1754 return r;
1755
1756 }
1757
1758 #elif defined(WIN32)
1759
get_netmask(struct sockaddr_in * me,int * mask)1760 static int get_netmask(struct sockaddr_in *me, int *mask)
1761 {
1762 SOCKET sock = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
1763 INTERFACE_INFO interfaces[20];
1764 unsigned long bytes;
1765 int interface_count, x;
1766 int r = -1;
1767
1768 *mask = 0;
1769
1770 if (sock == SOCKET_ERROR) {
1771 return -1;
1772 }
1773
1774 if (WSAIoctl(sock, SIO_GET_INTERFACE_LIST, 0, 0, &interfaces, sizeof(interfaces), &bytes, 0, 0) == SOCKET_ERROR) {
1775 r = -1;
1776 goto end;
1777 }
1778
1779 interface_count = bytes / sizeof(INTERFACE_INFO);
1780
1781 for (x = 0; x < interface_count; ++x) {
1782 struct sockaddr_in *addr = (struct sockaddr_in *) &(interfaces[x].iiAddress);
1783
1784 if (addr->sin_addr.s_addr == me->sin_addr.s_addr) {
1785 struct sockaddr_in *netmask = (struct sockaddr_in *) &(interfaces[x].iiNetmask);
1786 *mask = netmask->sin_addr.s_addr;
1787 r = 0;
1788 break;
1789 }
1790 }
1791
1792 end:
1793 closesocket(sock);
1794 return r;
1795 }
1796
1797 #else
1798
get_netmask(struct sockaddr_in * me,int * mask)1799 static int get_netmask(struct sockaddr_in *me, int *mask)
1800 {
1801 return -1;
1802 }
1803
1804 #endif
1805
1806
switch_resolve_host(const char * host,char * buf,size_t buflen)1807 SWITCH_DECLARE(switch_status_t) switch_resolve_host(const char *host, char *buf, size_t buflen)
1808 {
1809
1810 struct addrinfo *ai;
1811 int err;
1812
1813 if ((err = getaddrinfo(host, 0, 0, &ai))) {
1814 return SWITCH_STATUS_FALSE;
1815 }
1816
1817 get_addr(buf, buflen, ai->ai_addr, sizeof(struct sockaddr_storage));
1818
1819 freeaddrinfo(ai);
1820
1821 return SWITCH_STATUS_SUCCESS;
1822 }
1823
1824
switch_find_local_ip(char * buf,int len,int * mask,int family)1825 SWITCH_DECLARE(switch_status_t) switch_find_local_ip(char *buf, int len, int *mask, int family)
1826 {
1827 switch_status_t status = SWITCH_STATUS_FALSE;
1828 char *base;
1829 char *force_local_ip_v4 = switch_core_get_variable_dup("force_local_ip_v4");
1830 char *force_local_ip_v6 = switch_core_get_variable_dup("force_local_ip_v6");
1831
1832 #ifdef WIN32
1833 SOCKET tmp_socket;
1834 SOCKADDR_STORAGE l_address;
1835 int l_address_len;
1836 struct addrinfo *address_info;
1837 #else
1838 #ifdef __Darwin__
1839 int ilen;
1840 #else
1841 unsigned int ilen;
1842 #endif
1843 int tmp_socket = -1, on = 1;
1844 char abuf[25] = "";
1845 #endif
1846
1847 switch (family) {
1848 case AF_INET:
1849 if (force_local_ip_v4) {
1850 switch_copy_string(buf, force_local_ip_v4, len);
1851 switch_safe_free(force_local_ip_v4);
1852 switch_safe_free(force_local_ip_v6);
1853 return SWITCH_STATUS_SUCCESS;
1854 }
1855 case AF_INET6:
1856 if (force_local_ip_v6) {
1857 switch_copy_string(buf, force_local_ip_v6, len);
1858 switch_safe_free(force_local_ip_v4);
1859 switch_safe_free(force_local_ip_v6);
1860 return SWITCH_STATUS_SUCCESS;
1861 }
1862 default:
1863 switch_safe_free(force_local_ip_v4);
1864 switch_safe_free(force_local_ip_v6);
1865 break;
1866 }
1867
1868
1869 if (len < 16) {
1870 return status;
1871 }
1872
1873 switch (family) {
1874 case AF_INET:
1875 switch_copy_string(buf, "127.0.0.1", len);
1876 base = "82.45.148.209";
1877 break;
1878 case AF_INET6:
1879 switch_copy_string(buf, "::1", len);
1880 base = "2001:503:BA3E::2:30"; /* DNS Root server A */
1881 break;
1882 default:
1883 base = "127.0.0.1";
1884 break;
1885 }
1886
1887 #ifdef WIN32
1888 tmp_socket = socket(family, SOCK_DGRAM, 0);
1889
1890 getaddrinfo(base, NULL, NULL, &address_info);
1891
1892 if (!address_info || WSAIoctl(tmp_socket,
1893 SIO_ROUTING_INTERFACE_QUERY,
1894 address_info->ai_addr, (DWORD) address_info->ai_addrlen, &l_address, sizeof(l_address), (LPDWORD) & l_address_len, NULL,
1895 NULL)) {
1896
1897 closesocket(tmp_socket);
1898 if (address_info)
1899 freeaddrinfo(address_info);
1900 return status;
1901 }
1902
1903
1904 closesocket(tmp_socket);
1905 freeaddrinfo(address_info);
1906
1907 if (!getnameinfo((const struct sockaddr *) &l_address, l_address_len, buf, len, NULL, 0, NI_NUMERICHOST)) {
1908 status = SWITCH_STATUS_SUCCESS;
1909 if (mask) {
1910 get_netmask((struct sockaddr_in *) &l_address, mask);
1911 }
1912 }
1913 #else
1914
1915 switch (family) {
1916 case AF_INET:
1917 {
1918 struct sockaddr_in iface_out;
1919 struct sockaddr_in remote;
1920 memset(&remote, 0, sizeof(struct sockaddr_in));
1921
1922 remote.sin_family = AF_INET;
1923 remote.sin_addr.s_addr = inet_addr(base);
1924 remote.sin_port = htons(4242);
1925
1926 memset(&iface_out, 0, sizeof(iface_out));
1927 if ( (tmp_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ) {
1928 goto doh;
1929 }
1930
1931 if (setsockopt(tmp_socket, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) == -1) {
1932 goto doh;
1933 }
1934
1935 if (connect(tmp_socket, (struct sockaddr *) &remote, sizeof(struct sockaddr_in)) == -1) {
1936 goto doh;
1937 }
1938
1939 ilen = sizeof(iface_out);
1940 if (getsockname(tmp_socket, (struct sockaddr *) &iface_out, &ilen) == -1) {
1941 goto doh;
1942 }
1943
1944 if (iface_out.sin_addr.s_addr == 0) {
1945 goto doh;
1946 }
1947
1948 switch_copy_string(buf, get_addr(abuf, sizeof(abuf), (struct sockaddr *) &iface_out, sizeof(iface_out)), len);
1949 if (mask) {
1950 get_netmask((struct sockaddr_in *) &iface_out, mask);
1951 }
1952
1953 status = SWITCH_STATUS_SUCCESS;
1954 }
1955 break;
1956 case AF_INET6:
1957 {
1958 struct sockaddr_in6 iface_out;
1959 struct sockaddr_in6 remote;
1960 memset(&remote, 0, sizeof(struct sockaddr_in6));
1961
1962 remote.sin6_family = AF_INET6;
1963 switch_inet_pton(AF_INET6, base, &remote.sin6_addr);
1964 remote.sin6_port = htons(4242);
1965
1966 memset(&iface_out, 0, sizeof(iface_out));
1967 if ( (tmp_socket = socket(AF_INET6, SOCK_DGRAM, 0)) == -1 ) {
1968 goto doh;
1969 }
1970
1971 if (connect(tmp_socket, (struct sockaddr *) &remote, sizeof(remote)) == -1) {
1972 goto doh;
1973 }
1974
1975 ilen = sizeof(iface_out);
1976 if (getsockname(tmp_socket, (struct sockaddr *) &iface_out, &ilen) == -1) {
1977 goto doh;
1978 }
1979
1980 inet_ntop(AF_INET6, (const void *) &iface_out.sin6_addr, buf, len - 1);
1981 status = SWITCH_STATUS_SUCCESS;
1982 }
1983 break;
1984 }
1985
1986 doh:
1987 if (tmp_socket > 0) {
1988 close(tmp_socket);
1989 }
1990 #endif
1991
1992 return status;
1993 }
1994
1995 #ifdef HAVE_GETIFADDRS
1996 # include <ifaddrs.h>
1997 # include <net/if.h>
1998 #endif
switch_find_interface_ip(char * buf,int len,int * mask,const char * ifname,int family)1999 SWITCH_DECLARE(switch_status_t) switch_find_interface_ip(char *buf, int len, int *mask, const char *ifname, int family)
2000 {
2001 switch_status_t status = SWITCH_STATUS_FALSE;
2002
2003 #ifdef HAVE_GETIFADDRS
2004
2005 struct ifaddrs *addrs, *addr;
2006
2007 getifaddrs(&addrs);
2008 for(addr = addrs; addr; addr = addr->ifa_next)
2009 {
2010 if (!(addr->ifa_flags & IFF_UP)) continue; // Address is not UP
2011 if (!addr->ifa_addr) continue; // No address set
2012 if (!addr->ifa_netmask) continue; // No netmask set
2013 if (family != AF_UNSPEC && addr->ifa_addr->sa_family != family) continue; // Not the address family we're looking for
2014 if (strcmp(addr->ifa_name, ifname)) continue; // Not the interface we're looking for
2015
2016 switch(addr->ifa_addr->sa_family) {
2017 case AF_INET:
2018 inet_ntop(AF_INET, &( ((struct sockaddr_in*)(addr->ifa_addr))->sin_addr ), buf, len - 1);
2019 break;
2020 case AF_INET6:
2021 inet_ntop(AF_INET6, &( ((struct sockaddr_in6*)(addr->ifa_addr))->sin6_addr ), buf, len - 1);
2022 break;
2023 default:
2024 continue;
2025 }
2026
2027 if (mask && addr->ifa_netmask->sa_family == AF_INET) {
2028 *mask = ((struct sockaddr_in*)(addr->ifa_addr))->sin_addr.s_addr;
2029 }
2030
2031 status = SWITCH_STATUS_SUCCESS;
2032 break;
2033 }
2034 freeifaddrs(addrs);
2035
2036 #elif defined(__linux__)
2037
2038 // TODO Not implemented, contributions welcome.
2039
2040 #elif defined(WIN32)
2041
2042 // TODO Not implemented, contributions welcome.
2043
2044 #endif
2045
2046 return status;
2047 }
2048
2049
switch_str_time(const char * in)2050 SWITCH_DECLARE(switch_time_t) switch_str_time(const char *in)
2051 {
2052 switch_time_exp_t tm = { 0 }, local_tm = { 0 };
2053 int proceed = 0, ovector[30], time_only = 0;
2054 switch_regex_t *re = NULL;
2055 char replace[1024] = "";
2056 switch_time_t ret = 0, local_time = 0;
2057 char *pattern = "^(\\d+)-(\\d+)-(\\d+)\\s*(\\d*):{0,1}(\\d*):{0,1}(\\d*)";
2058 char *pattern2 = "^(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})";
2059 char *pattern3 = "^(\\d*):{0,1}(\\d*):{0,1}(\\d*)$";
2060
2061 switch_time_exp_lt(&tm, switch_micro_time_now());
2062
2063
2064 if ((time_only = switch_regex_perform(in, pattern3, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
2065 tm.tm_hour = 0;
2066 tm.tm_min = 0;
2067 tm.tm_sec = 0;
2068 } else {
2069 tm.tm_year = tm.tm_mon = tm.tm_mday = tm.tm_hour = tm.tm_min = tm.tm_sec = tm.tm_usec = 0;
2070
2071 if (!(proceed = switch_regex_perform(in, pattern, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
2072 switch_regex_safe_free(re);
2073 proceed = switch_regex_perform(in, pattern2, &re, ovector, sizeof(ovector) / sizeof(ovector[0]));
2074 }
2075 }
2076
2077 if (proceed || time_only) {
2078
2079 if (time_only > 1) {
2080 switch_regex_copy_substring(in, ovector, time_only, 1, replace, sizeof(replace));
2081 tm.tm_hour = atoi(replace);
2082 }
2083
2084 if (time_only > 2) {
2085 switch_regex_copy_substring(in, ovector, time_only, 2, replace, sizeof(replace));
2086 tm.tm_min = atoi(replace);
2087 }
2088
2089 if (time_only > 3) {
2090 switch_regex_copy_substring(in, ovector, time_only, 3, replace, sizeof(replace));
2091 tm.tm_sec = atoi(replace);
2092 }
2093
2094 if (proceed > 1) {
2095 switch_regex_copy_substring(in, ovector, proceed, 1, replace, sizeof(replace));
2096 tm.tm_year = atoi(replace) - 1900;
2097 }
2098
2099 if (proceed > 2) {
2100 switch_regex_copy_substring(in, ovector, proceed, 2, replace, sizeof(replace));
2101 tm.tm_mon = atoi(replace) - 1;
2102 }
2103
2104 if (proceed > 3) {
2105 switch_regex_copy_substring(in, ovector, proceed, 3, replace, sizeof(replace));
2106 tm.tm_mday = atoi(replace);
2107 }
2108
2109 if (proceed > 4) {
2110 switch_regex_copy_substring(in, ovector, proceed, 4, replace, sizeof(replace));
2111 tm.tm_hour = atoi(replace);
2112 }
2113
2114 if (proceed > 5) {
2115 switch_regex_copy_substring(in, ovector, proceed, 5, replace, sizeof(replace));
2116 tm.tm_min = atoi(replace);
2117 }
2118
2119 if (proceed > 6) {
2120 switch_regex_copy_substring(in, ovector, proceed, 6, replace, sizeof(replace));
2121 tm.tm_sec = atoi(replace);
2122 }
2123
2124 switch_regex_safe_free(re);
2125
2126 switch_time_exp_get(&local_time, &tm);
2127 switch_time_exp_lt(&local_tm, local_time);
2128 tm.tm_isdst = local_tm.tm_isdst;
2129 tm.tm_gmtoff = local_tm.tm_gmtoff;
2130
2131 switch_time_exp_gmt_get(&ret, &tm);
2132 return ret;
2133 }
2134
2135 switch_regex_safe_free(re);
2136
2137 return ret;
2138 }
2139
switch_priority_name(switch_priority_t priority)2140 SWITCH_DECLARE(const char *) switch_priority_name(switch_priority_t priority)
2141 {
2142 switch (priority) { /*lol */
2143 case SWITCH_PRIORITY_NORMAL:
2144 return "NORMAL";
2145 case SWITCH_PRIORITY_LOW:
2146 return "LOW";
2147 case SWITCH_PRIORITY_HIGH:
2148 return "HIGH";
2149 default:
2150 return "INVALID";
2151 }
2152 }
2153
2154 static char RFC2833_CHARS[] = "0123456789*#ABCDF";
2155
2156 #ifdef _MSC_VER
2157 /* Copyright (c) 1996 by Internet Software Consortium.
2158 *
2159 * Permission to use, copy, modify, and distribute this software for any
2160 * purpose with or without fee is hereby granted, provided that the above
2161 * copyright notice and this permission notice appear in all copies.
2162 *
2163 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
2164 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
2165 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
2166 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
2167 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
2168 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
2169 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2170 * SOFTWARE.
2171 */
2172
2173 #include <ctype.h>
2174 #include <errno.h>
2175 #include <stdio.h>
2176 #include <string.h>
2177 #include <stdlib.h>
2178
2179 #include <sys/types.h>
2180
2181 /*
2182 * WARNING: Don't even consider trying to compile this on a system where
2183 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
2184 */
2185
2186 static const char *switch_inet_ntop4(const unsigned char *src, char *dst, size_t size);
2187 #if HAVE_SIN6
2188 static const char *switch_inet_ntop6(const unsigned char *src, char *dst, size_t size);
2189 #endif
2190
2191 /* char *
2192 * inet_ntop(af, src, dst, size)
2193 * convert a network format address to presentation format.
2194 * return:
2195 * pointer to presentation format address (`dst'), or NULL (see errno).
2196 * author:
2197 * Paul Vixie, 1996.
2198 */
switch_inet_ntop(int af,void const * src,char * dst,size_t size)2199 SWITCH_DECLARE(const char *) switch_inet_ntop(int af, void const *src, char *dst, size_t size)
2200 {
2201
2202 switch (af) {
2203 case AF_INET:
2204 return switch_inet_ntop4(src, dst, size);
2205 #if HAVE_SIN6
2206 case AF_INET6:
2207 return switch_inet_ntop6(src, dst, size);
2208 #endif
2209 default:
2210 return NULL;
2211 }
2212 /* NOTREACHED */
2213 }
2214
2215 /* const char *
2216 * inet_ntop4(src, dst, size)
2217 * format an IPv4 address, more or less like inet_ntoa()
2218 * return:
2219 * `dst' (as a const)
2220 * notes:
2221 * (1) uses no statics
2222 * (2) takes a unsigned char* not an in_addr as input
2223 * author:
2224 * Paul Vixie, 1996.
2225 */
switch_inet_ntop4(const unsigned char * src,char * dst,size_t size)2226 static const char *switch_inet_ntop4(const unsigned char *src, char *dst, size_t size)
2227 {
2228 static const char fmt[] = "%u.%u.%u.%u";
2229 char tmp[sizeof "255.255.255.255"];
2230
2231 if (switch_snprintf(tmp, sizeof tmp, fmt, src[0], src[1], src[2], src[3]) >= (int) size) {
2232 return NULL;
2233 }
2234
2235 return strcpy(dst, tmp);
2236 }
2237
2238 #if HAVE_SIN6 || defined(NTDDI_VERSION)
2239 /* const char *
2240 * inet_ntop6(src, dst, size)
2241 * convert IPv6 binary address into presentation (printable) format
2242 * author:
2243 * Paul Vixie, 1996.
2244 */
switch_inet_ntop6(unsigned char const * src,char * dst,size_t size)2245 static const char *switch_inet_ntop6(unsigned char const *src, char *dst, size_t size)
2246 {
2247 /*
2248 * Note that int32_t and int16_t need only be "at least" large enough
2249 * to contain a value of the specified size. On some systems, like
2250 * Crays, there is no such thing as an integer variable with 16 bits.
2251 * Keep this in mind if you think this function should have been coded
2252 * to use pointer overlays. All the world's not a VAX.
2253 */
2254 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
2255 struct {
2256 int base, len;
2257 } best = {
2258 -1, 0}, cur = {
2259 -1, 0};
2260 unsigned int words[8];
2261 int i;
2262
2263 /*
2264 * Preprocess:
2265 * Copy the input (bytewise) array into a wordwise array.
2266 * Find the longest run of 0x00's in src[] for :: shorthanding.
2267 */
2268 for (i = 0; i < 16; i += 2)
2269 words[i / 2] = (src[i] << 8) | (src[i + 1]);
2270 best.base = -1;
2271 cur.base = -1;
2272 for (i = 0; i < 8; i++) {
2273 if (words[i] == 0) {
2274 if (cur.base == -1)
2275 cur.base = i, cur.len = 1;
2276 else
2277 cur.len++;
2278 } else {
2279 if (cur.base != -1) {
2280 if (best.base == -1 || cur.len > best.len)
2281 best = cur;
2282 cur.base = -1;
2283 }
2284 }
2285 }
2286 if (cur.base != -1) {
2287 if (best.base == -1 || cur.len > best.len)
2288 best = cur;
2289 }
2290 if (best.base != -1 && best.len < 2)
2291 best.base = -1;
2292
2293 /*
2294 * Format the result.
2295 */
2296 tp = tmp;
2297 for (i = 0; i < 8; i++) {
2298 /* Are we inside the best run of 0x00's? */
2299 if (best.base != -1 && i >= best.base && i < (best.base + best.len)) {
2300 if (i == best.base)
2301 *tp++ = ':';
2302 continue;
2303 }
2304 /* Are we following an initial run of 0x00s or any real hex? */
2305 if (i != 0)
2306 *tp++ = ':';
2307 /* Is this address an encapsulated IPv4? */
2308 if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
2309 if (!switch_inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp)))
2310 return (NULL);
2311 tp += strlen(tp);
2312 break;
2313 }
2314 tp += sprintf(tp, "%x", words[i]);
2315 }
2316 /* Was it a trailing run of 0x00's? */
2317 if (best.base != -1 && (best.base + best.len) == 8)
2318 *tp++ = ':';
2319 *tp++ = '\0';
2320
2321 /*
2322 * Check for overflow, copy, and we're done.
2323 */
2324 if ((size_t) (tp - tmp) >= size) {
2325 return NULL;
2326 }
2327
2328 return strcpy(dst, tmp);
2329 }
2330 #endif
2331
2332 #endif
2333
get_addr_int(switch_sockaddr_t * sa)2334 SWITCH_DECLARE(int) get_addr_int(switch_sockaddr_t *sa)
2335 {
2336 struct sockaddr_in *s = (struct sockaddr_in *) &sa->sa;
2337
2338 return ntohs((unsigned short) s->sin_addr.s_addr);
2339 }
2340
switch_cmp_addr(switch_sockaddr_t * sa1,switch_sockaddr_t * sa2)2341 SWITCH_DECLARE(int) switch_cmp_addr(switch_sockaddr_t *sa1, switch_sockaddr_t *sa2)
2342 {
2343 struct sockaddr_in *s1;
2344 struct sockaddr_in *s2;
2345
2346 struct sockaddr_in6 *s16;
2347 struct sockaddr_in6 *s26;
2348
2349 struct sockaddr *ss1;
2350 struct sockaddr *ss2;
2351
2352 if (!(sa1 && sa2))
2353 return 0;
2354
2355 s1 = (struct sockaddr_in *) &sa1->sa;
2356 s2 = (struct sockaddr_in *) &sa2->sa;
2357
2358 s16 = (struct sockaddr_in6 *) &sa1->sa;
2359 s26 = (struct sockaddr_in6 *) &sa2->sa;
2360
2361 ss1 = (struct sockaddr *) &sa1->sa;
2362 ss2 = (struct sockaddr *) &sa2->sa;
2363
2364 if (ss1->sa_family != ss2->sa_family)
2365 return 0;
2366
2367 switch (ss1->sa_family) {
2368 case AF_INET:
2369 return (s1->sin_addr.s_addr == s2->sin_addr.s_addr && s1->sin_port == s2->sin_port);
2370 case AF_INET6:
2371 if (s16->sin6_addr.s6_addr && s26->sin6_addr.s6_addr) {
2372 int i;
2373
2374 if (s16->sin6_port != s26->sin6_port)
2375 return 0;
2376
2377 for (i = 0; i < 4; i++) {
2378 if (*((int32_t *) s16->sin6_addr.s6_addr + i) != *((int32_t *) s26->sin6_addr.s6_addr + i))
2379 return 0;
2380 }
2381
2382 return 1;
2383 }
2384 }
2385
2386 return 0;
2387 }
2388
2389
switch_cp_addr(switch_sockaddr_t * sa1,switch_sockaddr_t * sa2)2390 SWITCH_DECLARE(int) switch_cp_addr(switch_sockaddr_t *sa1, switch_sockaddr_t *sa2)
2391 {
2392 struct sockaddr_in *s1;
2393 struct sockaddr_in *s2;
2394
2395 struct sockaddr_in6 *s16;
2396 struct sockaddr_in6 *s26;
2397
2398 struct sockaddr *ss1;
2399 //struct sockaddr *ss2;
2400
2401 if (!(sa1 && sa2))
2402 return 0;
2403
2404 s1 = (struct sockaddr_in *) &sa1->sa;
2405 s2 = (struct sockaddr_in *) &sa2->sa;
2406
2407 s16 = (struct sockaddr_in6 *) &sa1->sa;
2408 s26 = (struct sockaddr_in6 *) &sa2->sa;
2409
2410 ss1 = (struct sockaddr *) &sa1->sa;
2411 //ss2 = (struct sockaddr *) &sa2->sa;
2412
2413 sa1->port = sa2->port;
2414 sa1->family = sa2->family;
2415
2416 sa1->sa.sin.sin_family = sa2->family;
2417
2418 switch (ss1->sa_family) {
2419 case AF_INET:
2420 s1->sin_addr.s_addr = s2->sin_addr.s_addr;
2421 s1->sin_port = s2->sin_port;
2422
2423 return 1;
2424 case AF_INET6:
2425 if (s16->sin6_addr.s6_addr && s26->sin6_addr.s6_addr) {
2426 int i;
2427
2428 s16->sin6_port = s26->sin6_port;
2429
2430 for (i = 0; i < 4; i++) {
2431 *((int32_t *) s16->sin6_addr.s6_addr + i) = *((int32_t *) s26->sin6_addr.s6_addr + i);
2432 }
2433
2434 return 1;
2435 }
2436 }
2437
2438 return 0;
2439 }
2440
get_addr6(char * buf,switch_size_t len,struct sockaddr_in6 * sa,socklen_t salen)2441 SWITCH_DECLARE(char *) get_addr6(char *buf, switch_size_t len, struct sockaddr_in6 *sa, socklen_t salen)
2442 {
2443 switch_assert(buf);
2444 *buf = '\0';
2445
2446 if (sa) {
2447 #if defined(NTDDI_VERSION)
2448 switch_inet_ntop6((unsigned char*)&(sa->sin6_addr), buf, len);
2449 #else
2450 inet_ntop(AF_INET6, &(sa->sin6_addr), buf, len);
2451 #endif
2452 }
2453
2454 return buf;
2455 }
2456
get_addr(char * buf,switch_size_t len,struct sockaddr * sa,socklen_t salen)2457 SWITCH_DECLARE(char *) get_addr(char *buf, switch_size_t len, struct sockaddr *sa, socklen_t salen)
2458 {
2459 switch_assert(buf);
2460 *buf = '\0';
2461
2462 if (sa) {
2463 getnameinfo(sa, salen, buf, (socklen_t) len, NULL, 0, NI_NUMERICHOST);
2464 }
2465 return buf;
2466 }
2467
get_port(struct sockaddr * sa)2468 SWITCH_DECLARE(unsigned short) get_port(struct sockaddr *sa)
2469 {
2470 unsigned short port = 0;
2471 if (sa) {
2472 switch (sa->sa_family) {
2473 case AF_INET:
2474 port = ntohs(((struct sockaddr_in *) sa)->sin_port);
2475 break;
2476 case AF_INET6:
2477 port = ntohs(((struct sockaddr_in6 *) sa)->sin6_port);
2478 break;
2479 }
2480 }
2481 return port;
2482 }
2483
switch_build_uri(char * uri,switch_size_t size,const char * scheme,const char * user,const switch_sockaddr_t * sa,int flags)2484 SWITCH_DECLARE(int) switch_build_uri(char *uri, switch_size_t size, const char *scheme, const char *user, const switch_sockaddr_t *sa, int flags)
2485 {
2486 char host[NI_MAXHOST], serv[NI_MAXSERV];
2487 struct sockaddr_in6 si6;
2488 const struct sockaddr *addr;
2489 const char *colon;
2490
2491 if (flags & SWITCH_URI_NO_SCOPE && sa->family == AF_INET6) {
2492 memcpy(&si6, &sa->sa, sa->salen);
2493 si6.sin6_scope_id = 0;
2494
2495 addr = (const struct sockaddr *) &si6;
2496 } else {
2497 addr = (const struct sockaddr *) (intptr_t) & sa->sa;
2498 }
2499
2500 if (getnameinfo(addr, sa->salen, host, sizeof(host), serv, sizeof(serv),
2501 ((flags & SWITCH_URI_NUMERIC_HOST) ? NI_NUMERICHOST : 0) | ((flags & SWITCH_URI_NUMERIC_PORT) ? NI_NUMERICSERV : 0)) != 0) {
2502 return 0;
2503 }
2504
2505 colon = strchr(host, ':');
2506
2507 return switch_snprintf(uri, size, "%s:%s%s%s%s%s%s%s", scheme,
2508 user ? user : "", user ? "@" : "", colon ? "[" : "", host, colon ? "]" : "", serv[0] ? ":" : "", serv[0] ? serv : "");
2509 }
2510
switch_rfc2833_to_char(int event)2511 SWITCH_DECLARE(char) switch_rfc2833_to_char(int event)
2512 {
2513 if (event > -1 && event < (int32_t) sizeof(RFC2833_CHARS)) {
2514 return RFC2833_CHARS[event];
2515 }
2516 return '\0';
2517 }
2518
switch_char_to_rfc2833(char key)2519 SWITCH_DECLARE(unsigned char) switch_char_to_rfc2833(char key)
2520 {
2521 char *c;
2522 unsigned char counter = 0;
2523
2524 key = (char) switch_toupper(key);
2525 for (c = RFC2833_CHARS; *c; c++) {
2526 if (*c == key) {
2527 return counter;
2528 }
2529 counter++;
2530 }
2531 return '\0';
2532 }
2533
switch_escape_char(switch_memory_pool_t * pool,char * in,const char * delim,char esc)2534 SWITCH_DECLARE(char *) switch_escape_char(switch_memory_pool_t *pool, char *in, const char *delim, char esc)
2535 {
2536 char *data;
2537 const char *p, *d;
2538 int count = 1, i = 0;
2539
2540 p = in;
2541 while (*p) {
2542 d = delim;
2543 while (*d) {
2544 if (*p == *d) {
2545 count++;
2546 }
2547 d++;
2548 }
2549 p++;
2550 }
2551
2552 if (count == 1) {
2553 return in;
2554 }
2555
2556 data = switch_core_alloc(pool, strlen(in) + count);
2557
2558 p = in;
2559 while (*p) {
2560 d = delim;
2561 while (*d) {
2562 if (*p == *d) {
2563 data[i++] = esc;
2564 }
2565 d++;
2566 }
2567 data[i++] = *p;
2568 p++;
2569 }
2570 return data;
2571 }
2572
2573 /* Helper function used when separating strings to unescape a character. The
2574 supported characters are:
2575
2576 \n linefeed
2577 \r carriage return
2578 \t tab
2579 \s space
2580
2581 Any other character is returned as it was received. */
unescape_char(char escaped)2582 static char unescape_char(char escaped)
2583 {
2584 char unescaped;
2585
2586 switch (escaped) {
2587 case 'n':
2588 unescaped = '\n';
2589 break;
2590 case 'r':
2591 unescaped = '\r';
2592 break;
2593 case 't':
2594 unescaped = '\t';
2595 break;
2596 case 's':
2597 unescaped = ' ';
2598 break;
2599 default:
2600 unescaped = escaped;
2601 }
2602 return unescaped;
2603 }
2604
switch_escape_string(const char * in,char * out,switch_size_t outlen)2605 SWITCH_DECLARE(char *) switch_escape_string(const char *in, char *out, switch_size_t outlen)
2606 {
2607 const char *p;
2608 char *o = out;
2609
2610 for (p = in; *p; p++) {
2611 switch (*p) {
2612 case '\n':
2613 *o++ = '\\';
2614 *o++ = 'n';
2615 break;
2616 case '\r':
2617 *o++ = '\\';
2618 *o++ = 'r';
2619 break;
2620 case '\t':
2621 *o++ = '\\';
2622 *o++ = 't';
2623 break;
2624 case ' ':
2625 *o++ = '\\';
2626 *o++ = 's';
2627 break;
2628 case '$':
2629 *o++ = '\\';
2630 *o++ = '$';
2631 break;
2632 default:
2633 *o++ = *p;
2634 break;
2635 }
2636 }
2637
2638 *o++ = '\0';
2639
2640 return out;
2641 }
2642
switch_escape_string_pool(const char * in,switch_memory_pool_t * pool)2643 SWITCH_DECLARE(char *) switch_escape_string_pool(const char *in, switch_memory_pool_t *pool)
2644 {
2645 size_t len = strlen(in) * 2 + 1;
2646 char *buf = switch_core_alloc(pool, len);
2647 return switch_escape_string(in, buf, len);
2648 }
2649
2650 /* Helper function used when separating strings to remove quotes, leading /
2651 trailing spaces, and to convert escaped characters. */
cleanup_separated_string(char * str,char delim)2652 static char *cleanup_separated_string(char *str, char delim)
2653 {
2654 char *ptr;
2655 char *dest;
2656 char *start;
2657 char *end = NULL;
2658 int inside_quotes = 0;
2659
2660 /* Skip initial whitespace */
2661 for (ptr = str; *ptr == ' '; ++ptr) {
2662 }
2663
2664 for (start = dest = ptr; *ptr; ++ptr) {
2665 char e;
2666 int esc = 0;
2667
2668 if (*ptr == ESCAPE_META) {
2669 e = *(ptr + 1);
2670 if (e == '\'' || e == '"' || (delim && e == delim) || e == ESCAPE_META || (e = unescape_char(*(ptr + 1))) != *(ptr + 1)) {
2671 ++ptr;
2672 *dest++ = e;
2673 end = dest;
2674 esc++;
2675 }
2676 }
2677 if (!esc) {
2678 if (*ptr == '\'' && (inside_quotes || strchr(ptr+1, '\''))) {
2679 if ((inside_quotes = (1 - inside_quotes))) {
2680 end = dest;
2681 }
2682 } else {
2683 *dest++ = *ptr;
2684 if (*ptr != ' ' || inside_quotes) {
2685 end = dest;
2686 }
2687 }
2688 }
2689 }
2690 if (end) {
2691 *end = '\0';
2692 }
2693
2694 return start;
2695 }
2696
switch_separate_string_string(char * buf,char * delim,char ** array,unsigned int arraylen)2697 SWITCH_DECLARE(unsigned int) switch_separate_string_string(char *buf, char *delim, char **array, unsigned int arraylen)
2698 {
2699 unsigned int count = 0;
2700 char *d;
2701 size_t dlen = strlen(delim);
2702
2703 array[count++] = buf;
2704
2705 while (count < arraylen && array[count - 1]) {
2706 if ((d = strstr(array[count - 1], delim))) {
2707 *d = '\0';
2708 d += dlen;
2709 array[count++] = d;
2710 } else
2711 break;
2712 }
2713
2714 return count;
2715 }
2716
2717 /* Separate a string using a delimiter that is not a space */
separate_string_char_delim(char * buf,char delim,char ** array,unsigned int arraylen)2718 static unsigned int separate_string_char_delim(char *buf, char delim, char **array, unsigned int arraylen)
2719 {
2720 enum tokenizer_state {
2721 START,
2722 FIND_DELIM
2723 } state = START;
2724
2725 unsigned int count = 0;
2726 char *ptr = buf;
2727 int inside_quotes = 0;
2728 unsigned int i;
2729
2730 while (*ptr && count < arraylen) {
2731 switch (state) {
2732 case START:
2733 array[count++] = ptr;
2734 state = FIND_DELIM;
2735 break;
2736
2737 case FIND_DELIM:
2738 /* escaped characters are copied verbatim to the destination string */
2739 if (*ptr == ESCAPE_META) {
2740 ++ptr;
2741 } else if (*ptr == '\'' && (inside_quotes || strchr(ptr+1, '\''))) {
2742 inside_quotes = (1 - inside_quotes);
2743 } else if (*ptr == delim && !inside_quotes) {
2744 *ptr = '\0';
2745 state = START;
2746 }
2747 ++ptr;
2748 break;
2749 }
2750 }
2751 /* strip quotes, escaped chars and leading / trailing spaces */
2752
2753 for (i = 0; i < count; ++i) {
2754 array[i] = cleanup_separated_string(array[i], delim);
2755 }
2756
2757 return count;
2758 }
2759
2760 /* Separate a string using a delimiter that is a space */
separate_string_blank_delim(char * buf,char ** array,unsigned int arraylen)2761 static unsigned int separate_string_blank_delim(char *buf, char **array, unsigned int arraylen)
2762 {
2763 enum tokenizer_state {
2764 START,
2765 SKIP_INITIAL_SPACE,
2766 FIND_DELIM,
2767 SKIP_ENDING_SPACE
2768 } state = START;
2769
2770 unsigned int count = 0;
2771 char *ptr = buf;
2772 int inside_quotes = 0;
2773 unsigned int i;
2774
2775 while (*ptr && count < arraylen) {
2776 switch (state) {
2777 case START:
2778 array[count++] = ptr;
2779 state = SKIP_INITIAL_SPACE;
2780 break;
2781
2782 case SKIP_INITIAL_SPACE:
2783 if (*ptr == ' ') {
2784 ++ptr;
2785 } else {
2786 state = FIND_DELIM;
2787 }
2788 break;
2789
2790 case FIND_DELIM:
2791 if (*ptr == ESCAPE_META) {
2792 ++ptr;
2793 } else if (*ptr == '\'') {
2794 inside_quotes = (1 - inside_quotes);
2795 } else if (*ptr == ' ' && !inside_quotes) {
2796 *ptr = '\0';
2797 state = SKIP_ENDING_SPACE;
2798 }
2799 ++ptr;
2800 break;
2801
2802 case SKIP_ENDING_SPACE:
2803 if (*ptr == ' ') {
2804 ++ptr;
2805 } else {
2806 state = START;
2807 }
2808 break;
2809 }
2810 }
2811 /* strip quotes, escaped chars and leading / trailing spaces */
2812
2813 for (i = 0; i < count; ++i) {
2814 array[i] = cleanup_separated_string(array[i], 0);
2815 }
2816
2817 return count;
2818 }
2819
switch_separate_string(char * buf,char delim,char ** array,unsigned int arraylen)2820 SWITCH_DECLARE(unsigned int) switch_separate_string(char *buf, char delim, char **array, unsigned int arraylen)
2821 {
2822 if (!buf || !array || !arraylen) {
2823 return 0;
2824 }
2825
2826
2827 if (*buf == '^' && *(buf+1) == '^') {
2828 char *p = buf + 2;
2829
2830 if (*p && *(p+1)) {
2831 buf = p;
2832 delim = *buf++;
2833 }
2834 }
2835
2836
2837 memset(array, 0, arraylen * sizeof(*array));
2838
2839 return (delim == ' ' ? separate_string_blank_delim(buf, array, arraylen) : separate_string_char_delim(buf, delim, array, arraylen));
2840 }
2841
switch_cut_path(const char * in)2842 SWITCH_DECLARE(const char *) switch_cut_path(const char *in)
2843 {
2844 const char *p, *ret = in;
2845 const char delims[] = "/\\";
2846 const char *i;
2847
2848 if (in) {
2849 for (i = delims; *i; i++) {
2850 p = in;
2851 while ((p = strchr(p, *i)) != 0) {
2852 ret = ++p;
2853 }
2854 }
2855 return ret;
2856 } else {
2857 return NULL;
2858 }
2859 }
2860
switch_string_match(const char * string,size_t string_len,const char * search,size_t search_len)2861 SWITCH_DECLARE(switch_status_t) switch_string_match(const char *string, size_t string_len, const char *search, size_t search_len)
2862 {
2863 size_t i;
2864
2865 for (i = 0; (i < search_len) && (i < string_len); i++) {
2866 if (string[i] != search[i]) {
2867 return SWITCH_STATUS_FALSE;
2868 }
2869 }
2870
2871 if (i == search_len) {
2872 return SWITCH_STATUS_SUCCESS;
2873 }
2874
2875 return SWITCH_STATUS_FALSE;
2876 }
2877
switch_string_replace(const char * string,const char * search,const char * replace)2878 SWITCH_DECLARE(char *) switch_string_replace(const char *string, const char *search, const char *replace)
2879 {
2880 size_t string_len = strlen(string);
2881 size_t search_len = strlen(search);
2882 size_t replace_len = strlen(replace);
2883 size_t i, n;
2884 size_t dest_len = 0;
2885 char *dest, *tmp;
2886
2887 dest = (char *) malloc(sizeof(char));
2888 switch_assert(dest);
2889
2890 for (i = 0; i < string_len; i++) {
2891 if (switch_string_match(string + i, string_len - i, search, search_len) == SWITCH_STATUS_SUCCESS) {
2892 for (n = 0; n < replace_len; n++) {
2893 dest[dest_len] = replace[n];
2894 dest_len++;
2895 tmp = (char *) realloc(dest, sizeof(char) * (dest_len + 1));
2896 switch_assert(tmp);
2897 dest = tmp;
2898 }
2899 i += search_len - 1;
2900 } else {
2901 dest[dest_len] = string[i];
2902 dest_len++;
2903 tmp = (char *) realloc(dest, sizeof(char) * (dest_len + 1));
2904 switch_assert(tmp);
2905 dest = tmp;
2906 }
2907 }
2908
2909 dest[dest_len] = 0;
2910 return dest;
2911 }
2912
switch_util_quote_shell_arg(const char * string)2913 SWITCH_DECLARE(char *) switch_util_quote_shell_arg(const char *string)
2914 {
2915 return switch_util_quote_shell_arg_pool(string, NULL);
2916 }
2917
switch_util_quote_shell_arg_pool(const char * string,switch_memory_pool_t * pool)2918 SWITCH_DECLARE(char *) switch_util_quote_shell_arg_pool(const char *string, switch_memory_pool_t *pool)
2919 {
2920 size_t string_len = strlen(string);
2921 size_t i;
2922 size_t n = 0;
2923 size_t dest_len = 0;
2924 char *dest;
2925
2926 /* first pass through, figure out how large to make the allocation */
2927 dest_len = strlen(string) + 1; /* string + null */
2928 dest_len += 1; /* opening quote */
2929 for (i = 0; i < string_len; i++) {
2930 switch (string[i]) {
2931 #ifndef WIN32
2932 case '\'':
2933 /* We replace ' by sq backslace sq sq, so need 3 additional bytes */
2934 dest_len += 3;
2935 break;
2936 #endif
2937 }
2938 }
2939 dest_len += 1; /* closing quote */
2940
2941 /* if we're given a pool, allocate from it, otherwise use malloc */
2942 if (pool) {
2943 dest = switch_core_alloc(pool, sizeof(char) * dest_len);
2944 } else {
2945 dest = (char *) malloc(sizeof(char) * dest_len);
2946 }
2947 switch_assert(dest);
2948
2949 #ifdef WIN32
2950 dest[n++] = '"';
2951 #else
2952 dest[n++] = '\'';
2953 #endif
2954
2955 for (i = 0; i < string_len; i++) {
2956 switch (string[i]) {
2957 #ifdef WIN32
2958 case '"':
2959 case '%':
2960 dest[n++] = ' ';
2961 break;
2962 #else
2963 case '\'':
2964 /* We replace ' by sq backslash sq sq */
2965 dest[n++] = '\'';
2966 dest[n++] = '\\';
2967 dest[n++] = '\'';
2968 dest[n++] = '\'';
2969 break;
2970 #endif
2971 default:
2972 dest[n++] = string[i];
2973 }
2974 }
2975
2976 #ifdef WIN32
2977 dest[n++] = '"';
2978 #else
2979 dest[n++] = '\'';
2980 #endif
2981 dest[n++] = 0;
2982 switch_assert(n == dest_len);
2983 return dest;
2984 }
2985
2986
2987
2988 #ifdef HAVE_POLL
2989 #include <poll.h>
switch_wait_sock(switch_os_socket_t sock,uint32_t ms,switch_poll_t flags)2990 SWITCH_DECLARE(int) switch_wait_sock(switch_os_socket_t sock, uint32_t ms, switch_poll_t flags)
2991 {
2992 struct pollfd pfds[2] = { { 0 } };
2993 int s = 0, r = 0;
2994
2995 if (sock == SWITCH_SOCK_INVALID) {
2996 return SWITCH_SOCK_INVALID;
2997 }
2998
2999 pfds[0].fd = sock;
3000
3001
3002 if ((flags & SWITCH_POLL_READ)) {
3003 pfds[0].events |= POLLIN;
3004 }
3005
3006 if ((flags & SWITCH_POLL_WRITE)) {
3007 pfds[0].events |= POLLOUT;
3008 }
3009
3010 if ((flags & SWITCH_POLL_ERROR)) {
3011 pfds[0].events |= POLLERR;
3012 }
3013
3014 if ((flags & SWITCH_POLL_HUP)) {
3015 pfds[0].events |= POLLHUP;
3016 }
3017
3018 if ((flags & SWITCH_POLL_RDNORM)) {
3019 pfds[0].events |= POLLRDNORM;
3020 }
3021
3022 if ((flags & SWITCH_POLL_RDBAND)) {
3023 pfds[0].events |= POLLRDBAND;
3024 }
3025
3026 if ((flags & SWITCH_POLL_PRI)) {
3027 pfds[0].events |= POLLPRI;
3028 }
3029
3030 s = poll(pfds, 1, ms);
3031
3032 if (s < 0) {
3033 if (switch_errno_is_break(switch_errno())) {
3034 s = 0;
3035 }
3036 }
3037
3038 if (s < 0) {
3039 r = s;
3040 } else if (s > 0) {
3041 if ((pfds[0].revents & POLLIN)) {
3042 r |= SWITCH_POLL_READ;
3043 }
3044 if ((pfds[0].revents & POLLOUT)) {
3045 r |= SWITCH_POLL_WRITE;
3046 }
3047 if ((pfds[0].revents & POLLERR)) {
3048 r |= SWITCH_POLL_ERROR;
3049 }
3050 if ((pfds[0].revents & POLLHUP)) {
3051 r |= SWITCH_POLL_HUP;
3052 }
3053 if ((pfds[0].revents & POLLRDNORM)) {
3054 r |= SWITCH_POLL_RDNORM;
3055 }
3056 if ((pfds[0].revents & POLLRDBAND)) {
3057 r |= SWITCH_POLL_RDBAND;
3058 }
3059 if ((pfds[0].revents & POLLPRI)) {
3060 r |= SWITCH_POLL_PRI;
3061 }
3062 if ((pfds[0].revents & POLLNVAL)) {
3063 r |= SWITCH_POLL_INVALID;
3064 }
3065 }
3066
3067 return r;
3068
3069 }
3070
switch_wait_socklist(switch_waitlist_t * waitlist,uint32_t len,uint32_t ms)3071 SWITCH_DECLARE(int) switch_wait_socklist(switch_waitlist_t *waitlist, uint32_t len, uint32_t ms)
3072 {
3073 struct pollfd *pfds;
3074 int s = 0, r = 0, i;
3075
3076 pfds = calloc(len, sizeof(struct pollfd));
3077 switch_assert(pfds);
3078
3079 for (i = 0; i < len; i++) {
3080 if (waitlist[i].sock == SWITCH_SOCK_INVALID) {
3081 break;
3082 }
3083
3084 pfds[i].fd = waitlist[i].sock;
3085
3086 if ((waitlist[i].events & SWITCH_POLL_READ)) {
3087 pfds[i].events |= POLLIN;
3088 }
3089
3090 if ((waitlist[i].events & SWITCH_POLL_WRITE)) {
3091 pfds[i].events |= POLLOUT;
3092 }
3093
3094 if ((waitlist[i].events & SWITCH_POLL_ERROR)) {
3095 pfds[i].events |= POLLERR;
3096 }
3097
3098 if ((waitlist[i].events & SWITCH_POLL_HUP)) {
3099 pfds[i].events |= POLLHUP;
3100 }
3101
3102 if ((waitlist[i].events & SWITCH_POLL_RDNORM)) {
3103 pfds[i].events |= POLLRDNORM;
3104 }
3105
3106 if ((waitlist[i].events & SWITCH_POLL_RDBAND)) {
3107 pfds[i].events |= POLLRDBAND;
3108 }
3109
3110 if ((waitlist[i].events & SWITCH_POLL_PRI)) {
3111 pfds[i].events |= POLLPRI;
3112 }
3113 }
3114
3115 s = poll(pfds, len, ms);
3116
3117 if (s < 0) {
3118 if (switch_errno_is_break(switch_errno())) {
3119 s = 0;
3120 }
3121 }
3122
3123 if (s < 0) {
3124 r = s;
3125 } else if (s > 0) {
3126 for (i = 0; i < len; i++) {
3127 if ((pfds[i].revents & POLLIN)) {
3128 r |= SWITCH_POLL_READ;
3129 waitlist[i].revents |= SWITCH_POLL_READ;
3130 }
3131 if ((pfds[i].revents & POLLOUT)) {
3132 r |= SWITCH_POLL_WRITE;
3133 waitlist[i].revents |= SWITCH_POLL_WRITE;
3134 }
3135 if ((pfds[i].revents & POLLERR)) {
3136 r |= SWITCH_POLL_ERROR;
3137 waitlist[i].revents |= SWITCH_POLL_ERROR;
3138 }
3139 if ((pfds[i].revents & POLLHUP)) {
3140 r |= SWITCH_POLL_HUP;
3141 waitlist[i].revents |= SWITCH_POLL_HUP;
3142 }
3143 if ((pfds[i].revents & POLLRDNORM)) {
3144 r |= SWITCH_POLL_RDNORM;
3145 waitlist[i].revents |= SWITCH_POLL_RDNORM;
3146 }
3147 if ((pfds[i].revents & POLLRDBAND)) {
3148 r |= SWITCH_POLL_RDBAND;
3149 waitlist[i].revents |= SWITCH_POLL_RDBAND;
3150 }
3151 if ((pfds[i].revents & POLLPRI)) {
3152 r |= SWITCH_POLL_PRI;
3153 waitlist[i].revents |= SWITCH_POLL_PRI;
3154 }
3155 if ((pfds[i].revents & POLLNVAL)) {
3156 r |= SWITCH_POLL_INVALID;
3157 waitlist[i].revents |= SWITCH_POLL_INVALID;
3158 }
3159 }
3160 }
3161
3162 free(pfds);
3163
3164 return r;
3165
3166 }
3167
3168 #else
3169 /* use select instead of poll */
switch_wait_sock(switch_os_socket_t sock,uint32_t ms,switch_poll_t flags)3170 SWITCH_DECLARE(int) switch_wait_sock(switch_os_socket_t sock, uint32_t ms, switch_poll_t flags)
3171 {
3172 int s = 0, r = 0;
3173 fd_set *rfds;
3174 fd_set *wfds;
3175 fd_set *efds;
3176 struct timeval tv;
3177
3178 if (sock == SWITCH_SOCK_INVALID) {
3179 return SWITCH_SOCK_INVALID;
3180 }
3181
3182 rfds = malloc(sizeof(fd_set));
3183 wfds = malloc(sizeof(fd_set));
3184 efds = malloc(sizeof(fd_set));
3185
3186 FD_ZERO(rfds);
3187 FD_ZERO(wfds);
3188 FD_ZERO(efds);
3189
3190 #ifndef WIN32
3191 /* Wouldn't you rather know?? */
3192 assert(sock <= FD_SETSIZE);
3193 #endif
3194
3195 if ((flags & SWITCH_POLL_READ)) {
3196
3197 #ifdef WIN32
3198 #pragma warning( push )
3199 #pragma warning( disable : 4127 )
3200 FD_SET(sock, rfds);
3201 #pragma warning( pop )
3202 #else
3203 FD_SET(sock, rfds);
3204 #endif
3205 }
3206
3207 if ((flags & SWITCH_POLL_WRITE)) {
3208
3209 #ifdef WIN32
3210 #pragma warning( push )
3211 #pragma warning( disable : 4127 )
3212 FD_SET(sock, wfds);
3213 #pragma warning( pop )
3214 #else
3215 FD_SET(sock, wfds);
3216 #endif
3217 }
3218
3219 if ((flags & SWITCH_POLL_ERROR)) {
3220
3221 #ifdef WIN32
3222 #pragma warning( push )
3223 #pragma warning( disable : 4127 )
3224 FD_SET(sock, efds);
3225 #pragma warning( pop )
3226 #else
3227 FD_SET(sock, efds);
3228 #endif
3229 }
3230
3231 tv.tv_sec = ms / 1000;
3232 tv.tv_usec = (ms % 1000) * 1000;
3233
3234 s = select(sock + 1, (flags & SWITCH_POLL_READ) ? rfds : NULL, (flags & SWITCH_POLL_WRITE) ? wfds : NULL, (flags & SWITCH_POLL_ERROR) ? efds : NULL, &tv);
3235
3236 if (s < 0) {
3237 if (switch_errno_is_break(switch_errno())) {
3238 s = 0;
3239 }
3240 }
3241
3242 if (s < 0) {
3243 r = s;
3244 } else if (s > 0) {
3245 if ((flags & SWITCH_POLL_READ) && FD_ISSET(sock, rfds)) {
3246 r |= SWITCH_POLL_READ;
3247 }
3248
3249 if ((flags & SWITCH_POLL_WRITE) && FD_ISSET(sock, wfds)) {
3250 r |= SWITCH_POLL_WRITE;
3251 }
3252
3253 if ((flags & SWITCH_POLL_ERROR) && FD_ISSET(sock, efds)) {
3254 r |= SWITCH_POLL_ERROR;
3255 }
3256 }
3257
3258 free(rfds);
3259 free(wfds);
3260 free(efds);
3261
3262 return r;
3263
3264 }
3265
switch_wait_socklist(switch_waitlist_t * waitlist,uint32_t len,uint32_t ms)3266 SWITCH_DECLARE(int) switch_wait_socklist(switch_waitlist_t *waitlist, uint32_t len, uint32_t ms)
3267 {
3268 int s = 0, r = 0;
3269 fd_set *rfds;
3270 fd_set *wfds;
3271 fd_set *efds;
3272 struct timeval tv;
3273 unsigned int i;
3274 switch_os_socket_t max_fd = 0;
3275 int flags = 0;
3276
3277 rfds = malloc(sizeof(fd_set));
3278 wfds = malloc(sizeof(fd_set));
3279 efds = malloc(sizeof(fd_set));
3280
3281 FD_ZERO(rfds);
3282 FD_ZERO(wfds);
3283 FD_ZERO(efds);
3284
3285 for (i = 0; i < len; i++) {
3286 if (waitlist[i].sock == SWITCH_SOCK_INVALID) {
3287 break;
3288 }
3289
3290 if (waitlist[i].sock > max_fd) {
3291 max_fd = waitlist[i].sock;
3292 }
3293
3294 #ifndef WIN32
3295 /* Wouldn't you rather know?? */
3296 assert(waitlist[i].sock <= FD_SETSIZE);
3297 #endif
3298 flags |= waitlist[i].events;
3299
3300 if ((waitlist[i].events & SWITCH_POLL_READ)) {
3301
3302 #ifdef WIN32
3303 #pragma warning( push )
3304 #pragma warning( disable : 4127 )
3305 FD_SET(waitlist[i].sock, rfds);
3306 #pragma warning( pop )
3307 #else
3308 FD_SET(waitlist[i].sock, rfds);
3309 #endif
3310 }
3311
3312 if ((waitlist[i].events & SWITCH_POLL_WRITE)) {
3313
3314 #ifdef WIN32
3315 #pragma warning( push )
3316 #pragma warning( disable : 4127 )
3317 FD_SET(waitlist[i].sock, wfds);
3318 #pragma warning( pop )
3319 #else
3320 FD_SET(waitlist[i].sock, wfds);
3321 #endif
3322 }
3323
3324 if ((waitlist[i].events & SWITCH_POLL_ERROR)) {
3325
3326 #ifdef WIN32
3327 #pragma warning( push )
3328 #pragma warning( disable : 4127 )
3329 FD_SET(waitlist[i].sock, efds);
3330 #pragma warning( pop )
3331 #else
3332 FD_SET(waitlist[i].sock, efds);
3333 #endif
3334 }
3335 }
3336
3337 tv.tv_sec = ms / 1000;
3338 tv.tv_usec = (ms % 1000) * 1000;
3339
3340 s = select(max_fd + 1, (flags & SWITCH_POLL_READ) ? rfds : NULL, (flags & SWITCH_POLL_WRITE) ? wfds : NULL, (flags & SWITCH_POLL_ERROR) ? efds : NULL, &tv);
3341
3342 if (s < 0) {
3343 if (switch_errno_is_break(switch_errno())) {
3344 s = 0;
3345 }
3346 }
3347
3348 if (s < 0) {
3349 r = s;
3350 } else if (s > 0) {
3351 for (i = 0; i < len; i++) {
3352 if ((waitlist[i].events & SWITCH_POLL_READ) && FD_ISSET(waitlist[i].sock, rfds)) {
3353 r |= SWITCH_POLL_READ;
3354 waitlist[i].revents |= SWITCH_POLL_READ;
3355 }
3356
3357 if ((waitlist[i].events & SWITCH_POLL_WRITE) && FD_ISSET(waitlist[i].sock, wfds)) {
3358 r |= SWITCH_POLL_WRITE;
3359 waitlist[i].revents |= SWITCH_POLL_WRITE;
3360 }
3361
3362 if ((waitlist[i].events & SWITCH_POLL_ERROR) && FD_ISSET(waitlist[i].sock, efds)) {
3363 r |= SWITCH_POLL_ERROR;
3364 waitlist[i].revents |= SWITCH_POLL_ERROR;
3365 }
3366 }
3367 }
3368
3369 free(rfds);
3370 free(wfds);
3371 free(efds);
3372
3373 return r;
3374
3375 }
3376 #endif
3377
switch_socket_waitfor(switch_pollfd_t * poll,int ms)3378 SWITCH_DECLARE(int) switch_socket_waitfor(switch_pollfd_t *poll, int ms)
3379 {
3380 int nsds = 0;
3381
3382 switch_poll(poll, 1, &nsds, ms);
3383
3384 return nsds;
3385 }
3386
switch_core_session_url_encode(switch_core_session_t * session,const char * url)3387 SWITCH_DECLARE(char *) switch_core_session_url_encode(switch_core_session_t *session, const char *url)
3388 {
3389 return switch_core_url_encode_opt(switch_core_session_get_pool(session), url, SWITCH_FALSE);
3390 }
3391
switch_core_session_url_encode_opt(switch_core_session_t * session,const char * url,switch_bool_t double_encode)3392 SWITCH_DECLARE(char *) switch_core_session_url_encode_opt(switch_core_session_t *session, const char *url, switch_bool_t double_encode)
3393 {
3394 return switch_core_url_encode_opt(switch_core_session_get_pool(session), url, double_encode);
3395 }
3396
switch_core_url_encode(switch_memory_pool_t * pool,const char * url)3397 SWITCH_DECLARE(char *) switch_core_url_encode(switch_memory_pool_t *pool, const char *url)
3398 {
3399 return switch_core_url_encode_opt(pool, url, SWITCH_FALSE);
3400 }
3401
switch_core_url_encode_opt(switch_memory_pool_t * pool,const char * url,switch_bool_t double_encode)3402 SWITCH_DECLARE(char *) switch_core_url_encode_opt(switch_memory_pool_t *pool, const char *url, switch_bool_t double_encode)
3403 {
3404 const char hex[] = "0123456789ABCDEF";
3405 switch_size_t len = 0;
3406 switch_size_t slen = 0;
3407 const char *p, *e;
3408
3409 if (!url) return NULL;
3410 if (!pool) return NULL;
3411
3412 e = end_of_p(url);
3413
3414 for (p = url; *p; p++) {
3415 int ok = 0;
3416
3417 len++;
3418 slen++;
3419
3420 if (!double_encode && *p == '%' && e-p > 1) {
3421 if (strchr(hex, *(p+1)) && strchr(hex, *(p+2))) {
3422 ok = 1;
3423 }
3424 }
3425
3426 if (!ok && (*p < ' ' || *p > '~' || strchr(SWITCH_URL_UNSAFE, *p))) {
3427 len += 2;
3428 }
3429 }
3430
3431 slen++;
3432 len++; /* NULL Terminatior */
3433
3434 if (slen == len) {
3435 return switch_core_strdup(pool, url);
3436 } else {
3437 return switch_url_encode_opt(url, switch_core_alloc(pool, sizeof(char) * len), len, double_encode);
3438 }
3439 }
3440
switch_url_encode_opt(const char * url,char * buf,size_t len,switch_bool_t double_encode)3441 SWITCH_DECLARE(char *) switch_url_encode_opt(const char *url, char *buf, size_t len, switch_bool_t double_encode)
3442 {
3443 const char *p, *e = end_of_p(url);
3444 size_t x = 0;
3445 const char hex[] = "0123456789ABCDEF";
3446
3447 if (!buf) {
3448 return 0;
3449 }
3450
3451 if (!url) {
3452 return 0;
3453 }
3454
3455 len--;
3456
3457 for (p = url; *p; p++) {
3458 int ok = 0;
3459
3460 if (x >= len) {
3461 break;
3462 }
3463
3464 if (!double_encode && *p == '%' && e-p > 1) {
3465 if (strchr(hex, *(p+1)) && strchr(hex, *(p+2))) {
3466 ok = 1;
3467 }
3468 }
3469
3470 if (!ok && (*p < ' ' || *p > '~' || strchr(SWITCH_URL_UNSAFE, *p))) {
3471 if ((x + 3) > len) {
3472 break;
3473 }
3474 buf[x++] = '%';
3475 buf[x++] = hex[(*p >> 4) & 0x0f];
3476 buf[x++] = hex[*p & 0x0f];
3477 } else {
3478 buf[x++] = *p;
3479 }
3480 }
3481 buf[x] = '\0';
3482
3483 return buf;
3484 }
3485
switch_url_encode(const char * url,char * buf,size_t len)3486 SWITCH_DECLARE(char *) switch_url_encode(const char *url, char *buf, size_t len)
3487 {
3488 return switch_url_encode_opt(url, buf, len, SWITCH_FALSE);
3489 }
3490
switch_url_decode(char * s)3491 SWITCH_DECLARE(char *) switch_url_decode(char *s)
3492 {
3493 char *o;
3494 unsigned int tmp;
3495
3496 if (zstr(s)) {
3497 return s;
3498 }
3499
3500 for (o = s; *s; s++, o++) {
3501 if (*s == '%' && strlen(s) > 2 && sscanf(s + 1, "%2x", &tmp) == 1) {
3502 *o = (char) tmp;
3503 s += 2;
3504 } else {
3505 *o = *s;
3506 }
3507 }
3508 *o = '\0';
3509 return s;
3510 }
3511
switch_split_time(const char * exp,int * hour,int * min,int * sec)3512 SWITCH_DECLARE(void) switch_split_time(const char *exp, int *hour, int *min, int *sec)
3513 {
3514 char *dup = strdup(exp);
3515 char *shour = NULL;
3516 char *smin = NULL;
3517 char *ssec = NULL;
3518
3519 switch_assert(dup);
3520
3521 shour = dup;
3522 if ((smin=strchr(dup, ':'))) {
3523 *smin++ = '\0';
3524 if ((ssec=strchr(smin, ':'))) {
3525 *ssec++ = '\0';
3526 } else {
3527 ssec = "00";
3528 }
3529 if (hour) {
3530 *hour = atol(shour);
3531 }
3532 if (min) {
3533 *min = atol(smin);
3534 }
3535 if (sec) {
3536 *sec = atol(ssec);
3537 }
3538
3539 }
3540 switch_safe_free(dup);
3541 return;
3542
3543 }
3544
switch_split_date(const char * exp,int * year,int * month,int * day)3545 SWITCH_DECLARE(void) switch_split_date(const char *exp, int *year, int *month, int *day)
3546 {
3547 char *dup = strdup(exp);
3548 char *syear = NULL;
3549 char *smonth = NULL;
3550 char *sday = NULL;
3551
3552 switch_assert(dup);
3553
3554 syear = dup;
3555 if ((smonth=strchr(dup, '-'))) {
3556 *smonth++ = '\0';
3557 if ((sday=strchr(smonth, '-'))) {
3558 *sday++ = '\0';
3559 if (year) {
3560 *year = atol(syear);
3561 }
3562 if (month) {
3563 *month = atol(smonth);
3564 }
3565 if (day) {
3566 *day = atol(sday);
3567 }
3568 }
3569 }
3570 switch_safe_free(dup);
3571 return;
3572
3573 }
3574
3575 /* Ex exp value "2009-10-10 14:33:22~2009-11-10 17:32:31" */
switch_fulldate_cmp(const char * exp,switch_time_t * ts)3576 SWITCH_DECLARE(int) switch_fulldate_cmp(const char *exp, switch_time_t *ts)
3577 {
3578 char *dup = strdup(exp);
3579 char *sStart;
3580 char *sEnd;
3581 char *cur;
3582 char *p;
3583 switch_time_t tsStart = 0;
3584 switch_time_t tsEnd = 0;
3585 int ret = 0;
3586
3587 switch_assert(dup);
3588
3589 cur = dup;
3590 if ((p = strchr(cur, ','))) {
3591 *p++ = '\0';
3592 }
3593
3594 while (cur) {
3595 sStart = cur;
3596 if ((sEnd = strchr(cur, '~'))) {
3597 *sEnd++ = '\0';
3598
3599 tsStart = switch_str_time(sStart);
3600 tsEnd = switch_str_time(sEnd);
3601
3602
3603 if (tsStart == 0 || tsEnd == 0) {
3604 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse error for date time range (%s~%s)\n", sStart, sEnd);
3605 break;
3606 }
3607
3608 if (tsStart <= *ts && tsEnd > *ts) {
3609 ret = 1;
3610 break;
3611 }
3612 }
3613
3614 if ((cur = p)) {
3615 if ((p = strchr(p, ','))) {
3616 *p++ = '\0';
3617 }
3618 }
3619 }
3620
3621 switch_safe_free(dup);
3622 return ret;
3623 }
3624
3625
3626 /* Written by Marc Espie, public domain */
3627 #define SWITCH_CTYPE_NUM_CHARS 256
3628
3629 const short _switch_C_toupper_[1 + SWITCH_CTYPE_NUM_CHARS] = {
3630 EOF,
3631 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
3632 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
3633 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
3634 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
3635 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
3636 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
3637 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
3638 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
3639 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
3640 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
3641 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
3642 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
3643 0x60, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
3644 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
3645 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
3646 'X', 'Y', 'Z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
3647 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
3648 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
3649 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
3650 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
3651 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
3652 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
3653 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
3654 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
3655 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
3656 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
3657 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
3658 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
3659 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
3660 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
3661 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
3662 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
3663 };
3664
3665 const short *_switch_toupper_tab_ = _switch_C_toupper_;
3666
old_switch_toupper(int c)3667 SWITCH_DECLARE(int) old_switch_toupper(int c)
3668 {
3669 if ((unsigned int) c > 255)
3670 return (c);
3671 if (c < -1)
3672 return EOF;
3673 return ((_switch_toupper_tab_ + 1)[c]);
3674 }
3675
3676 const short _switch_C_tolower_[1 + SWITCH_CTYPE_NUM_CHARS] = {
3677 EOF,
3678 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
3679 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
3680 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
3681 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
3682 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
3683 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
3684 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
3685 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
3686 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
3687 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
3688 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
3689 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
3690 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
3691 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
3692 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
3693 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
3694 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
3695 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
3696 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
3697 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
3698 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
3699 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
3700 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
3701 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
3702 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
3703 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
3704 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
3705 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
3706 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
3707 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
3708 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
3709 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
3710 };
3711
3712 const short *_switch_tolower_tab_ = _switch_C_tolower_;
3713
old_switch_tolower(int c)3714 SWITCH_DECLARE(int) old_switch_tolower(int c)
3715 {
3716 if ((unsigned int) c > 255)
3717 return (c);
3718 if (c < -1)
3719 return EOF;
3720 return ((_switch_tolower_tab_ + 1)[c]);
3721 }
3722
3723 /*
3724 * Copyright (c) 1989 The Regents of the University of California.
3725 * All rights reserved.
3726 * (c) UNIX System Laboratories, Inc.
3727 * All or some portions of this file are derived from material licensed
3728 * to the University of California by American Telephone and Telegraph
3729 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
3730 * the permission of UNIX System Laboratories, Inc.
3731 *
3732 * Redistribution and use in source and binary forms, with or without
3733 * modification, are permitted provided that the following conditions
3734 * are met:
3735 * 1. Redistributions of source code must retain the above copyright
3736 * notice, this list of conditions and the following disclaimer.
3737 * 2. Redistributions in binary form must reproduce the above copyright
3738 * notice, this list of conditions and the following disclaimer in the
3739 * documentation and/or other materials provided with the distribution.
3740 * 3. Neither the name of the University nor the names of its contributors
3741 * may be used to endorse or promote products derived from this software
3742 * without specific prior written permission.
3743 *
3744 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
3745 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3746 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3747 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3748 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3749 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3750 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3751 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3752 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3753 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3754 * SUCH DAMAGE.
3755 */
3756
3757 #undef _U
3758 #undef _L
3759 #undef _N
3760 #undef _S
3761 #undef _P
3762 #undef _C
3763 #undef _X
3764 #undef _B
3765
3766 #define _U 0x01
3767 #define _L 0x02
3768 #define _N 0x04
3769 #define _S 0x08
3770 #define _P 0x10
3771 #define _C 0x20
3772 #define _X 0x40
3773 #define _B 0x80
3774
3775 const int _switch_C_ctype_[1 + SWITCH_CTYPE_NUM_CHARS] = {
3776 0,
3777 _C, _C, _C, _C, _C, _C, _C, _C,
3778 _C, _C | _S, _C | _S, _C | _S, _C | _S, _C | _S, _C, _C,
3779 _C, _C, _C, _C, _C, _C, _C, _C,
3780 _C, _C, _C, _C, _C, _C, _C, _C,
3781 _S | _B, _P, _P, _P, _P, _P, _P, _P,
3782 _P, _P, _P, _P, _P, _P, _P, _P,
3783 _N, _N, _N, _N, _N, _N, _N, _N,
3784 _N, _N, _P, _P, _P, _P, _P, _P,
3785 _P, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U,
3786 _U, _U, _U, _U, _U, _U, _U, _U,
3787 _U, _U, _U, _U, _U, _U, _U, _U,
3788 _U, _U, _U, _P, _P, _P, _P, _P,
3789 _P, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X, _L,
3790 _L, _L, _L, _L, _L, _L, _L, _L,
3791 _L, _L, _L, _L, _L, _L, _L, _L,
3792 /* determine printability based on the IS0 8859 8-bit standard */
3793 _L, _L, _L, _P, _P, _P, _P, _C,
3794
3795 _C, _C, _C, _C, _C, _C, _C, _C, /* 80 */
3796 _C, _C, _C, _C, _C, _C, _C, _C, /* 88 */
3797 _C, _C, _C, _C, _C, _C, _C, _C, /* 90 */
3798 _C, _C, _C, _C, _C, _C, _C, _C, /* 98 */
3799 _P, _P, _P, _P, _P, _P, _P, _P, /* A0 */
3800 _P, _P, _P, _P, _P, _P, _P, _P, /* A8 */
3801 _P, _P, _P, _P, _P, _P, _P, _P, /* B0 */
3802 _P, _P, _P, _P, _P, _P, _P, _P, /* B8 */
3803 _P, _P, _P, _P, _P, _P, _P, _P, /* C0 */
3804 _P, _P, _P, _P, _P, _P, _P, _P, /* C8 */
3805 _P, _P, _P, _P, _P, _P, _P, _P, /* D0 */
3806 _P, _P, _P, _P, _P, _P, _P, _P, /* D8 */
3807 _P, _P, _P, _P, _P, _P, _P, _P, /* E0 */
3808 _P, _P, _P, _P, _P, _P, _P, _P, /* E8 */
3809 _P, _P, _P, _P, _P, _P, _P, _P, /* F0 */
3810 _P, _P, _P, _P, _P, _P, _P, _P /* F8 */
3811 };
3812
3813 const int *_switch_ctype_ = _switch_C_ctype_;
3814
switch_isalnum(int c)3815 SWITCH_DECLARE(int) switch_isalnum(int c)
3816 {
3817 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & (_U | _L | _N)));
3818 }
3819
switch_isalpha(int c)3820 SWITCH_DECLARE(int) switch_isalpha(int c)
3821 {
3822 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & (_U | _L)));
3823 }
3824
switch_iscntrl(int c)3825 SWITCH_DECLARE(int) switch_iscntrl(int c)
3826 {
3827 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & _C));
3828 }
3829
switch_isdigit(int c)3830 SWITCH_DECLARE(int) switch_isdigit(int c)
3831 {
3832 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & _N));
3833 }
3834
switch_isgraph(int c)3835 SWITCH_DECLARE(int) switch_isgraph(int c)
3836 {
3837 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & (_P | _U | _L | _N)));
3838 }
3839
switch_islower(int c)3840 SWITCH_DECLARE(int) switch_islower(int c)
3841 {
3842 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & _L));
3843 }
3844
switch_isprint(int c)3845 SWITCH_DECLARE(int) switch_isprint(int c)
3846 {
3847 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & (_P | _U | _L | _N | _B)));
3848 }
3849
switch_ispunct(int c)3850 SWITCH_DECLARE(int) switch_ispunct(int c)
3851 {
3852 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & _P));
3853 }
3854
switch_isspace(int c)3855 SWITCH_DECLARE(int) switch_isspace(int c)
3856 {
3857 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & _S));
3858 }
3859
switch_isupper(int c)3860 SWITCH_DECLARE(int) switch_isupper(int c)
3861 {
3862 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & _U));
3863 }
3864
switch_isxdigit(int c)3865 SWITCH_DECLARE(int) switch_isxdigit(int c)
3866 {
3867 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & (_N | _X)));
3868 }
3869 static const char *DOW[] = {
3870 "sun",
3871 "mon",
3872 "tue",
3873 "wed",
3874 "thu",
3875 "fri",
3876 "sat"
3877 };
3878
switch_dow_int2str(int val)3879 SWITCH_DECLARE(const char *) switch_dow_int2str(int val) {
3880 if (val >= switch_arraylen(DOW)) {
3881 val = val % switch_arraylen(DOW);
3882 }
3883 return DOW[val];
3884 }
3885
switch_dow_str2int(const char * exp)3886 SWITCH_DECLARE(int) switch_dow_str2int(const char *exp) {
3887 int ret = -1;
3888 int x;
3889
3890 for (x = 0; x < switch_arraylen(DOW); x++) {
3891 if (!strncasecmp(DOW[x], exp, 3)) {
3892 ret = x + 1;
3893 break;
3894 }
3895 }
3896 return ret;
3897 }
3898
3899 typedef enum {
3900 DOW_ERR = -2,
3901 DOW_EOF = -1,
3902 DOW_SUN = 1,
3903 DOW_MON,
3904 DOW_TUE,
3905 DOW_WED,
3906 DOW_THU,
3907 DOW_FRI,
3908 DOW_SAT,
3909 DOW_HYPHEN = '-',
3910 DOW_COMA = ','
3911 } dow_t;
3912
_dow_read_token(const char ** s)3913 static inline dow_t _dow_read_token(const char **s)
3914 {
3915 int i;
3916
3917 if (**s == '-') {
3918 (*s)++;
3919 return DOW_HYPHEN;
3920 } else if (**s == ',') {
3921 (*s)++;
3922 return DOW_COMA;
3923 } else if (**s >= '1' && **s <= '7') {
3924 dow_t r = **s - '0';
3925 (*s)++;
3926 return r;
3927 } else if ((i = switch_dow_str2int(*s)) && i != -1) {
3928 (*s) += 3;
3929 return i;
3930 } else if (!**s) {
3931 return DOW_EOF;
3932 } else {
3933 return DOW_ERR;
3934 }
3935 }
3936
switch_dow_cmp(const char * exp,int val)3937 SWITCH_DECLARE(switch_bool_t) switch_dow_cmp(const char *exp, int val)
3938 {
3939 dow_t cur, prev = DOW_EOF, range_start = DOW_EOF;
3940 const char *p = exp;
3941
3942 while ((cur = _dow_read_token(&p)) != DOW_EOF) {
3943 if (cur == DOW_COMA) {
3944 /* Reset state */
3945 cur = DOW_EOF;
3946 } else if (cur == DOW_HYPHEN) {
3947 /* Save the previous token and move to the next one */
3948 range_start = prev;
3949 } else if (cur == DOW_ERR) {
3950 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse error for [%s] at position %ld (%.6s)\n", exp, (long) (p - exp), p);
3951 break;
3952 } else {
3953 /* Valid day found */
3954 if (range_start != DOW_EOF) { /* Evaluating a range */
3955 if (range_start <= cur ? (val >= range_start && val <= cur) : (val >= range_start || val <= cur)) {
3956 return SWITCH_TRUE;
3957 }
3958 range_start = DOW_EOF;
3959 } else if (val == cur) {
3960 return SWITCH_TRUE;
3961 }
3962 }
3963
3964 prev = cur;
3965 }
3966
3967 return SWITCH_FALSE;
3968 }
3969
switch_number_cmp(const char * exp,int val)3970 SWITCH_DECLARE(int) switch_number_cmp(const char *exp, int val)
3971 {
3972 // Expression exp must be a comma separated list of numbers or ranges.
3973 // To match numbers not in range 9-17, enter the reversed range 18-8.
3974 for (;; ++exp) {
3975 int a = strtol(exp, (char **)&exp, 10);
3976 if (*exp != '-') {
3977 if (a == val)
3978 return 1;
3979 } else {
3980 int b = strtol(++exp, (char **)&exp, 10);
3981 if (a <= b ? (val >= a && val <=b ) : (val >= a || val <= b))
3982 return 1;
3983 }
3984 if (*exp != ',')
3985 return 0;
3986 }
3987 }
3988
switch_tod_cmp(const char * exp,int val)3989 SWITCH_DECLARE(int) switch_tod_cmp(const char *exp, int val)
3990 {
3991 char *dup = strdup(exp);
3992 char *minh;
3993 char *minm;
3994 char *mins;
3995 char *maxh;
3996 char *maxm;
3997 char *maxs;
3998 char *cur;
3999 char *p;
4000 int range_start, range_end;
4001
4002 switch_assert(dup);
4003
4004 cur = dup;
4005 if ((p = strchr(cur, ','))) {
4006 *p++ = '\0';
4007 }
4008
4009 while (cur) {
4010 minh = cur;
4011 if ((minm=strchr(cur, ':'))) {
4012 *minm++ = '\0';
4013 if ((maxh=strchr(minm, '-'))) {
4014 if ((maxm=strchr(maxh, ':'))) {
4015 *maxh++ = '\0';
4016 *maxm++ = '\0';
4017 /* Check if min/max seconds are present */
4018 if ((mins=strchr(minm, ':'))) {
4019 *mins++ = '\0';
4020 } else {
4021 mins = "00";
4022 }
4023 if ((maxs=strchr(maxm, ':'))) {
4024 *maxs++ = '\0';
4025 } else {
4026 maxs = "00";
4027 }
4028
4029 range_start = (atol(minh) * 60 * 60) + (atol(minm) * 60) + atol(mins);
4030 range_end = (atol(maxh) * 60 * 60) + (atol(maxm) * 60) + atol(maxs);
4031 if (range_start <= range_end ? (val >= range_start && val <= range_end) : (val >= range_start || val <= range_end)) {
4032 switch_safe_free(dup);
4033 return 1;
4034 }
4035 }
4036 }
4037 }
4038
4039 cur = p;
4040 if (p) {
4041 if ((p = strchr(p, ','))) {
4042 *p++ = '\0';
4043 }
4044 }
4045
4046 }
4047
4048 switch_safe_free(dup);
4049 return 0;
4050
4051 }
4052
switch_split_user_domain(char * in,char ** user,char ** domain)4053 SWITCH_DECLARE(int) switch_split_user_domain(char *in, char **user, char **domain)
4054 {
4055 char *p = NULL, *h = NULL, *u = NULL;
4056
4057 if (!in) return 0;
4058
4059 /* Remove URL scheme */
4060 if (!strncasecmp(in, "sip:", 4)) in += 4;
4061 else if (!strncasecmp(in, "sips:", 5)) in += 5;
4062
4063 /* Isolate the host part from the user part */
4064 if ((h = in, p = strchr(h, '@'))) *p = '\0', u = in, h = p+1;
4065
4066 /* Clean out the host part of any suffix */
4067 for (p = h; *p; p++)
4068 if (*p == ':' || *p == ';' || *p == ' ') {
4069 *p = '\0'; break;
4070 }
4071
4072 if (user) *user = u;
4073 if (domain) *domain = h;
4074 return 1;
4075 }
4076
4077
switch_uuid_str(char * buf,switch_size_t len)4078 SWITCH_DECLARE(char *) switch_uuid_str(char *buf, switch_size_t len)
4079 {
4080 switch_uuid_t uuid;
4081
4082 if (len < (SWITCH_UUID_FORMATTED_LENGTH + 1)) {
4083 switch_snprintf(buf, len, "INVALID");
4084 } else {
4085 switch_uuid_get(&uuid);
4086 switch_uuid_format(buf, &uuid);
4087 }
4088
4089 return buf;
4090 }
4091
4092
switch_format_number(const char * num)4093 SWITCH_DECLARE(char *) switch_format_number(const char *num)
4094 {
4095 char *r;
4096 size_t len;
4097 const char *p = num;
4098
4099 if (!p) {
4100 return (char*)p;
4101 }
4102
4103 if (zstr(p)) {
4104 return strdup(p);
4105 }
4106
4107 if (*p == '+') {
4108 p++;
4109 }
4110
4111 if (!switch_is_number(p)) {
4112 return strdup(p);
4113 }
4114
4115 len = strlen(p);
4116
4117 /* region 1, TBD add more....*/
4118 if (len == 11 && p[0] == '1') {
4119 r = switch_mprintf("%c (%c%c%c) %c%c%c-%c%c%c%c", p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9],p[10]);
4120 } else if (len == 10) {
4121 r = switch_mprintf("1 (%c%c%c) %c%c%c-%c%c%c%c", p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9]);
4122 } else {
4123 r = strdup(num);
4124 }
4125
4126 return r;
4127 }
4128
4129
switch_atoui(const char * nptr)4130 SWITCH_DECLARE(unsigned int) switch_atoui(const char *nptr)
4131 {
4132 int tmp = atoi(nptr);
4133 if (tmp < 0) return 0;
4134 else return (unsigned int) tmp;
4135 }
4136
switch_atoul(const char * nptr)4137 SWITCH_DECLARE(unsigned long) switch_atoul(const char *nptr)
4138 {
4139 long tmp = atol(nptr);
4140 if (tmp < 0) return 0;
4141 else return (unsigned long) tmp;
4142 }
4143
4144
switch_strerror_r(int errnum,char * buf,switch_size_t buflen)4145 SWITCH_DECLARE(char *) switch_strerror_r(int errnum, char *buf, switch_size_t buflen)
4146 {
4147 #ifdef HAVE_STRERROR_R
4148 #ifdef STRERROR_R_CHAR_P
4149 /* GNU variant returning char *, avoids warn-unused-result error */
4150 return strerror_r(errnum, buf, buflen);
4151 #else
4152 /*
4153 * XSI variant returning int, with GNU compatible error string,
4154 * if no message could be found
4155 */
4156 if (strerror_r(errnum, buf, buflen)) {
4157 switch_snprintf(buf, buflen, "Unknown error %d", errnum);
4158 }
4159 return buf;
4160 #endif /* STRERROR_R_CHAR_P */
4161 #elif defined(WIN32)
4162 /* WIN32 variant */
4163 if (strerror_s(buf, buflen, errnum)) {
4164 switch_snprintf(buf, buflen, "Unknown error %d", errnum);
4165 }
4166 return buf;
4167 #else
4168 /* Fallback, copy string into private buffer */
4169 switch_copy_string(buf, strerror(errnum), buflen);
4170 return buf;
4171 #endif
4172 }
4173
switch_http_parse_qs(switch_http_request_t * request,char * qs)4174 SWITCH_DECLARE(void) switch_http_parse_qs(switch_http_request_t *request, char *qs)
4175 {
4176 char *q;
4177 char *next;
4178 char *name, *val;
4179
4180 if (qs) {
4181 q = qs;
4182 } else { /*parse our own qs, dup to avoid modify the original string */
4183 q = strdup(request->qs);
4184 }
4185
4186 switch_assert(q);
4187 next = q;
4188
4189 do {
4190 char *p;
4191
4192 if ((next = strchr(next, '&'))) {
4193 *next++ = '\0';
4194 }
4195
4196 for (p = q; p && *p; p++) {
4197 if (*p == '+') *p = ' ';
4198 }
4199
4200 switch_url_decode(q);
4201
4202 name = q;
4203 if ((val = strchr(name, '='))) {
4204 *val++ = '\0';
4205 switch_event_add_header_string(request->headers, SWITCH_STACK_BOTTOM, name, val);
4206 }
4207 q = next;
4208 } while (q);
4209
4210 if (!qs) {
4211 switch_safe_free(q);
4212 }
4213 }
4214
4215 /* clean the uri to protect us from vulnerability attack */
clean_uri(char * uri)4216 switch_status_t clean_uri(char *uri)
4217 {
4218 int argc;
4219 char *argv[64];
4220 int last, i, len, uri_len = 0;
4221
4222 argc = switch_separate_string(uri, '/', argv, sizeof(argv) / sizeof(argv[0]));
4223
4224 if (argc == sizeof(argv)) { /* too deep */
4225 return SWITCH_STATUS_FALSE;
4226 }
4227
4228 last = 1;
4229 for(i = 1; i < argc; i++) {
4230 if (*argv[i] == '\0' || !strcmp(argv[i], ".")) {
4231 /* ignore //// or /././././ */
4232 } else if (!strcmp(argv[i], "..")) {
4233 /* got /../, go up one level */
4234 if (last > 1) last--;
4235 } else {
4236 argv[last++] = argv[i];
4237 }
4238 }
4239
4240 for(i = 1; i < last; i++) {
4241 len = strlen(argv[i]);
4242 sprintf(uri + uri_len, "/%s", argv[i]);
4243 uri_len += (len + 1);
4244 }
4245
4246 return SWITCH_STATUS_SUCCESS;
4247 }
4248
switch_http_parse_header(char * buffer,uint32_t datalen,switch_http_request_t * request)4249 SWITCH_DECLARE(switch_status_t) switch_http_parse_header(char *buffer, uint32_t datalen, switch_http_request_t *request)
4250 {
4251 switch_status_t status = SWITCH_STATUS_FALSE;
4252 char *p = buffer;
4253 int i = 10;
4254 char *http = NULL;
4255 int header_count;
4256 char *headers[64] = { 0 };
4257 int argc;
4258 char *argv[2] = { 0 };
4259 char *body = NULL;
4260
4261 if (datalen < 16) return status; /* minimum GET / HTTP/1.1\r\n */
4262
4263 while(i--) { // sanity check
4264 if (*p++ == ' ') break;
4265 }
4266
4267 if (i == 0) return status;
4268
4269 if ((body = strstr(buffer, "\r\n\r\n"))) {
4270 *body = '\0';
4271 body += 4;
4272 } else if (( body = strstr(buffer, "\n\n"))) {
4273 *body = '\0';
4274 body += 2;
4275 } else {
4276 return status;
4277 }
4278
4279 request->_buffer = strdup(buffer);
4280 switch_assert(request->_buffer);
4281 request->method = request->_buffer;
4282 request->bytes_buffered = datalen;
4283 request->bytes_header = body - buffer;
4284 request->bytes_read = body - buffer;
4285
4286 p = strchr(request->method, ' ');
4287
4288 if (!p) goto err;
4289
4290 *p++ = '\0';
4291
4292 if (*p != '/') goto err; /* must start from '/' */
4293
4294 request->uri = p;
4295 p = strchr(request->uri, ' ');
4296
4297 if (!p) goto err;
4298
4299 *p++ = '\0';
4300 http = p;
4301
4302 p = strchr(request->uri, '?');
4303
4304 if (p) {
4305 *p++ = '\0';
4306 request->qs = p;
4307 }
4308
4309 if (clean_uri((char *)request->uri) != SWITCH_STATUS_SUCCESS) {
4310 goto err;
4311 }
4312
4313 if (!strncmp(http, "HTTP/1.1", 8)) {
4314 request->keepalive = SWITCH_TRUE;
4315 } else if (strncmp(http, "HTTP/1.0", 8)) {
4316 goto err;
4317 }
4318
4319 if (!request->headers) {
4320 if (switch_event_create(&request->headers, SWITCH_EVENT_CHANNEL_DATA) != SWITCH_STATUS_SUCCESS) {
4321 goto err;
4322 }
4323 request->_destroy_headers = SWITCH_TRUE;
4324 }
4325
4326 p = strchr(http, '\n');
4327
4328 if (p) {
4329 *p++ = '\0'; // now the first header
4330 } else {
4331 goto noheader;
4332 }
4333
4334 header_count = switch_separate_string(p, '\n', headers, sizeof(headers)/ sizeof(headers[0]));
4335
4336 if (header_count < 1) goto err;
4337
4338 for (i = 0; i < header_count; i++) {
4339 char *header, *value;
4340 int len;
4341
4342 argc = switch_separate_string(headers[i], ':', argv, 2);
4343
4344 if (argc != 2) goto err;
4345
4346 header = argv[0];
4347 value = argv[1];
4348
4349 if (*value == ' ') value++;
4350
4351 len = strlen(value);
4352
4353 if (len && *(value + len - 1) == '\r') *(value + len - 1) = '\0';
4354
4355 switch_event_add_header_string(request->headers, SWITCH_STACK_BOTTOM, header, value);
4356
4357 if (!strncasecmp(header, "User-Agent", 10)) {
4358 request->user_agent = value;
4359 } else if (!strncasecmp(header, "Host", 4)) {
4360 request->host = value;
4361 p = strchr(value, ':');
4362
4363 if (p) {
4364 *p++ = '\0';
4365
4366 if (*p) request->port = (switch_port_t)atoi(p);
4367 }
4368 } else if (!strncasecmp(header, "Content-Type", 12)) {
4369 request->content_type = value;
4370 } else if (!strncasecmp(header, "Content-Length", 14)) {
4371 request->content_length = atoi(value);
4372 } else if (!strncasecmp(header, "Referer", 7)) {
4373 request->referer = value;
4374 }
4375 }
4376
4377 noheader:
4378
4379 if (request->qs) {
4380 switch_http_parse_qs(request, NULL);
4381 }
4382
4383 return SWITCH_STATUS_SUCCESS;
4384
4385 err:
4386 switch_http_free_request(request);
4387 return status;
4388 }
4389
switch_http_free_request(switch_http_request_t * request)4390 SWITCH_DECLARE(void) switch_http_free_request(switch_http_request_t *request)
4391 {
4392 if (request->_buffer) free(request->_buffer);
4393 if (request->_destroy_headers && request->headers) {
4394 switch_event_destroy(&request->headers);
4395 }
4396 }
4397
4398 /* for debugging only */
switch_http_dump_request(switch_http_request_t * request)4399 SWITCH_DECLARE(void) switch_http_dump_request(switch_http_request_t *request)
4400 {
4401 switch_assert(request->method);
4402
4403 printf("method: %s\n", request->method);
4404
4405 if (request->uri) printf("uri: %s\n", request->uri);
4406 if (request->qs) printf("qs: %s\n", request->qs);
4407 if (request->host) printf("host: %s\n", request->host);
4408 if (request->port) printf("port: %d\n", request->port);
4409 if (request->from) printf("from: %s\n", request->from);
4410 if (request->user_agent) printf("user_agent: %s\n", request->user_agent);
4411 if (request->referer) printf("referer: %s\n", request->referer);
4412 if (request->user) printf("user: %s\n", request->user);
4413 if (request->keepalive) printf("uri: %d\n", request->keepalive);
4414 if (request->content_type) printf("uri: %s\n", request->content_type);
4415 if (request->content_length) printf("uri: %" SWITCH_SIZE_T_FMT "\n", request->content_length);
4416
4417 {
4418 switch_event_header_t *header = request->headers->headers;
4419
4420 printf("headers:\n-------------------------\n");
4421
4422 while(header) {
4423 printf("%s: %s\n", header->name, header->value);
4424 header = header->next;
4425 }
4426 }
4427 }
4428
switch_getcputime(switch_cputime * t)4429 SWITCH_DECLARE(void) switch_getcputime(switch_cputime *t)
4430 {
4431 #if defined(_WIN32)
4432 FILETIME ct, et, kt, ut; // Times are in 100-ns ticks (div 10000 to get ms)
4433 GetProcessTimes(GetCurrentProcess(), &ct, &et, &kt, &ut);
4434 t->userms = ((int64_t)ut.dwLowDateTime | ((int64_t)ut.dwHighDateTime << 32)) / 10000;
4435 t->kernelms = ((int64_t)kt.dwLowDateTime | ((int64_t)kt.dwHighDateTime << 32)) / 10000;
4436 #elif defined(HAVE_GETRUSAGE)
4437 struct rusage r;
4438 getrusage(RUSAGE_SELF, &r);
4439 t->userms = r.ru_utime.tv_sec * 1000 + r.ru_utime.tv_usec / 1000;
4440 t->kernelms = r.ru_stime.tv_sec * 1000 + r.ru_stime.tv_usec / 1000;
4441 #else
4442 t->userms = -1;
4443 t->kernelms = -1;
4444 #endif
4445 }
4446
4447
4448 #ifdef SWITCH_HAVE_GUMBO
process(GumboNode * node,switch_stream_handle_t * stream)4449 static void process(GumboNode *node, switch_stream_handle_t *stream)
4450 {
4451 if (node->type == GUMBO_NODE_TEXT) {
4452 stream->write_function(stream, "%s", node->v.text.text);
4453 return;
4454 } else if (node->type == GUMBO_NODE_ELEMENT && node->v.element.tag != GUMBO_TAG_SCRIPT && node->v.element.tag != GUMBO_TAG_STYLE) {
4455 GumboVector *children = &node->v.element.children;
4456 int i;
4457
4458 if (node->v.element.tag != GUMBO_TAG_UNKNOWN && node->v.element.tag <= GUMBO_TAG_LAST) {
4459 GumboAttribute* attr = NULL;
4460 const char *aval = NULL;
4461
4462 if (node->v.element.tag == GUMBO_TAG_SPAN) {
4463 if ((attr = gumbo_get_attribute(&node->v.element.attributes, "class"))) {
4464 aval = attr->value;
4465 }
4466 }
4467
4468 if (aval && !strcasecmp(aval, "Apple-converted-space")) {
4469 const char *txt = ((GumboNode*)children->data[0])->v.text.text;
4470 int x, len = 0;
4471
4472 for (x = 0; txt[x]; x++) {
4473 if (txt[x] == ' ') {
4474 len++;
4475 }
4476 }
4477
4478 for (x = 0; x < len*2; x++) {
4479 stream->write_function(stream, "%s", " ");
4480 }
4481 } else {
4482 for (i = 0; i < children->length; ++i) {
4483 process((GumboNode*) children->data[i], stream);
4484 }
4485 }
4486
4487 if (node->v.element.tag == GUMBO_TAG_P || node->v.element.tag == GUMBO_TAG_BR) {
4488 stream->write_function(stream, "%s", "\n");
4489 }
4490
4491 }
4492 }
4493 }
4494 #endif
4495
switch_html_strip(const char * str)4496 SWITCH_DECLARE(char *)switch_html_strip(const char *str)
4497 {
4498 char *p, *html = NULL, *text = NULL;
4499 int x = 0, got_ct = 0;
4500 #ifdef SWITCH_HAVE_GUMBO
4501 GumboOutput *output;
4502 switch_stream_handle_t stream;
4503
4504 SWITCH_STANDARD_STREAM(stream);
4505 #endif
4506
4507 for(p = (char *)str; p && *p; p++) {
4508
4509 if (!strncasecmp(p, "Content-Type:", 13)) {
4510 got_ct++;
4511 }
4512
4513 if (!got_ct) continue;
4514
4515 if (*p == '\n') {
4516 x++;
4517 if (x == 2) {
4518 break;
4519 }
4520 } else if (x && (*p != '\r')) {
4521 x = 0;
4522 }
4523 }
4524
4525 html = p;
4526
4527 #ifdef SWITCH_HAVE_GUMBO
4528 if ((output = gumbo_parse_with_options(&kGumboDefaultOptions, html, strlen(html)))) {
4529 process(output->root, &stream);
4530 gumbo_destroy_output(&kGumboDefaultOptions, output);
4531 }
4532
4533 text = (char *)stream.data;
4534 #else
4535 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Support for html parser is not compiled.\n");
4536 text = strdup(html);
4537 #endif
4538
4539 return text;
4540 }
4541
switch_getpid(void)4542 SWITCH_DECLARE(unsigned long) switch_getpid(void)
4543 {
4544 #ifndef WIN32
4545 pid_t pid = getpid();
4546 #else
4547 int pid = _getpid();
4548 #endif
4549
4550 return (unsigned long)pid;
4551 }
4552
4553
4554 /* For Emacs:
4555 * Local Variables:
4556 * mode:c
4557 * indent-tabs-mode:t
4558 * tab-width:4
4559 * c-basic-offset:4
4560 * End:
4561 * For VIM:
4562 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
4563 */
4564