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