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