]> git.ipfire.org Git - thirdparty/freeswitch.git/blame - src/switch_utils.c
Merge pull request #2848 from signalwire/openssl
[thirdparty/freeswitch.git] / src / switch_utils.c
CommitLineData
df1ab07c 1/*
71963ea8 2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
6e7d5d08 3 * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
71963ea8
MJ
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
ae220d33 20 * Anthony Minessale II <anthm@freeswitch.org>
71963ea8
MJ
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
df1ab07c 25 *
ae220d33 26 * Anthony Minessale II <anthm@freeswitch.org>
9b041ca2 27 * Juan Jose Comellas <juanjo@comellas.org>
f5c0c139 28 * Seven Du <dujinfang@gmail.com>
1d2a1057 29 * Windy Wang <xiaofengcanyuexp@163.com>
71963ea8 30 *
1cda796d 31 * switch_utils.c -- Compatibility and Helper Code
71963ea8
MJ
32 *
33 */
935cbcf9 34
7174e8ae 35#include <switch.h>
fbf2da44 36#include "private/switch_apr_pvt.h"
c845cf28
AM
37#ifndef WIN32
38#include <arpa/inet.h>
ba9c44bb
MG
39#if defined(HAVE_SYS_TIME_H) && defined(HAVE_SYS_RESOURCE_H)
40#include <sys/time.h>
41#include <sys/resource.h>
42#endif
893a3cdc
AV
43#include <sys/types.h>
44#include <unistd.h>
45#else
b8be418f 46#include <intsafe.h> /* SIZETMult() */
893a3cdc
AV
47 /* process.h is required for _getpid() */
48#include <process.h>
c845cf28 49#endif
23aa165d 50#include "private/switch_core_pvt.h"
6e1c32e0 51#define ESCAPE_META '\\'
30c84b4b 52#ifdef SWITCH_HAVE_GUMBO
9b8a5edd 53#include "gumbo.h"
30c84b4b 54#endif
f64d7e43 55
fd27504a
AV
56#if defined(HAVE_OPENSSL)
57#include <openssl/evp.h>
58#endif
59
b8be418f
AV
60#ifdef __GLIBC__
61#include <malloc.h> /* mallinfo() */
62#endif
63
bba65f4a 64struct switch_network_node {
db91f0e8
BW
65 ip_t ip;
66 ip_t mask;
bba65f4a 67 uint32_t bits;
db91f0e8 68 int family;
bba65f4a 69 switch_bool_t ok;
4722de50 70 char *token;
b82984fe 71 char *str;
60956d7f 72 switch_network_port_range_t port_range;
bba65f4a
AM
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;
b82984fe 81 char *name;
bba65f4a
AM
82};
83
8dd27183
AV
84SWITCH_DECLARE(void *) switch_calloc(size_t nmemb, size_t size)
85{
86 return calloc(nmemb, size);
87}
88
29ea1523 89#ifndef WIN32
3fd20448 90SWITCH_DECLARE(int) switch_inet_pton(int af, const char *src, void *dst)
29ea1523
MJ
91{
92 return inet_pton(af, src, dst);
93}
94#endif
bba65f4a 95
2a72b02f
AM
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
535cf469
AM
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);
084e2450 114 new_frame->buflen = (uint32_t)size;
535cf469
AM
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
0d34e8ac
AM
124typedef struct switch_frame_node_s {
125 switch_frame_t *frame;
126 int inuse;
d5e48302 127 struct switch_frame_node_s *prev;
0d34e8ac
AM
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;
c701ce61 134 switch_queue_t *queue;
0d34e8ac 135 switch_mutex_t *mutex;
d5e48302 136 uint32_t total;
0d34e8ac
AM
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);
d5e48302 144
0d34e8ac
AM
145 for (np = fb->head; np; np = np->next) {
146 if (!np->inuse && ((orig->packet && np->frame->packet) || (!orig->packet && !np->frame->packet))) {
d5e48302
AM
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;
0d34e8ac 160 break;
df1ab07c 161 }
0d34e8ac 162 }
df1ab07c 163
0d34e8ac
AM
164 if (!np) {
165 np = switch_core_alloc(fb->pool, sizeof(*np));
166 np->frame = switch_core_alloc(fb->pool, sizeof(*np->frame));
df1ab07c 167
0d34e8ac
AM
168 if (orig->packet) {
169 np->frame->packet = switch_core_alloc(fb->pool, SWITCH_RTP_MAX_BUF_LEN);
170 } else {
1968453e 171 np->frame->packet = NULL;
0d34e8ac
AM
172 np->frame->data = switch_core_alloc(fb->pool, SWITCH_RTP_MAX_BUF_LEN);
173 np->frame->buflen = SWITCH_RTP_MAX_BUF_LEN;
174 }
0d34e8ac
AM
175 }
176
0d34e8ac
AM
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;
c701ce61
AM
186 np->frame->codec = orig->codec;
187 np->frame->pmap = orig->pmap;
0d34e8ac
AM
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 {
1968453e 200 np->frame->packet = NULL;
0d34e8ac
AM
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 }
df1ab07c 209
0d34e8ac
AM
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;
df1ab07c 224
0d34e8ac
AM
225 node = (switch_frame_node_t *) old_frame->extra_data;
226 node->inuse = 0;
227 switch_img_free(&node->frame->img);
df1ab07c 228
d5e48302
AM
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);
df1ab07c 241
0d34e8ac
AM
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);
df1ab07c 259
0d34e8ac
AM
260 *clone = new_frame;
261
262 return SWITCH_STATUS_SUCCESS;
263}
264
c701ce61
AM
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
4926eac4
AM
285SWITCH_DECLARE(int) switch_frame_buffer_size(switch_frame_buffer_t *fb)
286{
287 return switch_queue_size(fb->queue);
288}
289
0d34e8ac
AM
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
c701ce61 301SWITCH_DECLARE(switch_status_t) switch_frame_buffer_create(switch_frame_buffer_t **fbP, switch_size_t qlen)
0d34e8ac
AM
302{
303 switch_frame_buffer_t *fb;
304 switch_memory_pool_t *pool;
305
c701ce61
AM
306 if (!qlen) qlen = 500;
307
0d34e8ac
AM
308 switch_core_new_memory_pool(&pool);
309 fb = switch_core_alloc(pool, sizeof(*fb));
310 fb->pool = pool;
c701ce61 311 switch_queue_create(&fb->queue, qlen, fb->pool);
0d34e8ac
AM
312 switch_mutex_init(&fb->mutex, SWITCH_MUTEX_NESTED, pool);
313 *fbP = fb;
314
315 return SWITCH_STATUS_SUCCESS;
316}
317
318
535cf469
AM
319SWITCH_DECLARE(switch_status_t) switch_frame_dup(switch_frame_t *orig, switch_frame_t **clone)
320{
321 switch_frame_t *new_frame;
322
72c680f0
AM
323 if (!orig) {
324 return SWITCH_STATUS_FALSE;
325 }
326
327 switch_assert(orig->buflen);
328
535cf469 329 new_frame = malloc(sizeof(*new_frame));
383ff711 330 switch_assert(new_frame);
886e1ddb 331
535cf469
AM
332 *new_frame = *orig;
333 switch_set_flag(new_frame, SFF_DYNAMIC);
72c680f0 334
0d34e8ac
AM
335 if (orig->packet) {
336 new_frame->packet = malloc(SWITCH_RTP_MAX_BUF_LEN);
292d0b2e 337 switch_assert(new_frame->packet);
0d34e8ac
AM
338 memcpy(new_frame->packet, orig->packet, orig->packetlen);
339 new_frame->data = ((unsigned char *)new_frame->packet) + 12;
340 } else {
1968453e 341 new_frame->packet = NULL;
0d34e8ac
AM
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
535cf469 347
c701ce61
AM
348 new_frame->codec = orig->codec;
349 new_frame->pmap = orig->pmap;
0d34e8ac 350 new_frame->img = NULL;
c701ce61
AM
351
352
0d34e8ac
AM
353 if (orig->img && !switch_test_flag(orig, SFF_ENCODED)) {
354 switch_img_copy(orig->img, &new_frame->img);
355 }
535cf469
AM
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{
1968453e
MJ
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)) {
535cf469
AM
372 return SWITCH_STATUS_FALSE;
373 }
886e1ddb 374
1968453e
MJ
375 *frame = NULL;
376
377 if (f->img) {
378 switch_img_free(&(f->img));
0d34e8ac
AM
379 }
380
1968453e
MJ
381 if (f->packet) {
382 switch_safe_free(f->packet);
0d34e8ac 383 } else {
1968453e 384 switch_safe_free(f->data);
0d34e8ac 385 }
1968453e
MJ
386
387 free(f);
535cf469
AM
388
389 return SWITCH_STATUS_SUCCESS;
390}
391
abdc4bf0
AM
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 }
df1ab07c 406
abdc4bf0
AM
407 va_end(ap);
408
409 return r;
410}
411
0ed54079
AM
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 == '=') {
084e2450 426 size_t mlen;
0ed54079
AM
427
428 ptr = ++e;
429
430 if (next) {
431 e = next;
432 } else {
433 e = ptr + strlen(ptr);
434 }
df1ab07c 435
0ed54079
AM
436 mlen = (e - ptr) + 1;
437
438 if (pool) {
439 r = switch_core_alloc(pool, mlen);
440 } else {
441 r = malloc(mlen);
442 }
443
0ed54079
AM
444 switch_snprintf(r, mlen, "%s", ptr);
445
446 break;
447 }
448
449 if (next) {
450 ptr = next + 1;
1c60b994 451 } else break;
0ed54079
AM
452 }
453
454 return r;
455}
456
886e1ddb
AM
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)
bba65f4a
AM
459{
460 switch_network_list_t *new_list;
3c349c27 461
bba65f4a
AM
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;
b82984fe 469 new_list->name = switch_core_strdup(new_list->pool, name);
bba65f4a
AM
470
471 *list = new_list;
472
473 return SWITCH_STATUS_SUCCESS;
474}
475
db91f0e8
BW
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}
60956d7f
LA
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)
db91f0e8
BW
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;
3b2d00f3
AM
503
504 if (node->bits >= bits && switch_testv6_subnet(ip, node->ip, node->mask)) {
db91f0e8
BW
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
60956d7f
LA
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)
bba65f4a
AM
545{
546 switch_network_node_t *node;
547 switch_bool_t ok = list->default_type;
548 uint32_t bits = 0;
3c349c27 549
bba65f4a 550 for (node = list->node_head; node; node = node->next) {
db91f0e8 551 if (node->family == AF_INET6) continue; /* want AF_INET */
60956d7f 552 if (node->bits >= bits && switch_test_subnet(ip, node->ip.v4, node->mask.v4) && is_port_in_node(port, node)) {
bba65f4a
AM
553 if (node->ok) {
554 ok = SWITCH_TRUE;
555 } else {
556 ok = SWITCH_FALSE;
557 }
4722de50 558
bba65f4a 559 bits = node->bits;
4722de50
AM
560
561 if (token) {
562 *token = node->token;
563 }
bba65f4a
AM
564 }
565 }
3c349c27 566
bba65f4a
AM
567 return ok;
568}
569
60956d7f
LA
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
28159946
B
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
60956d7f
LA
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
886e1ddb 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,
60956d7f 618 const char *token, switch_network_port_range_p port)
bba65f4a 619{
db91f0e8
BW
620 ip_t ip, mask;
621 uint32_t bits;
bba65f4a 622 switch_network_node_t *node;
28159946 623 char *ipv4 = NULL;
60956d7f 624 char *ports = NULL;
28159946
B
625
626 if ((ipv4 = switch_network_ipv4_mapped_ipv6_addr(cidr_str))) {
627 cidr_str = ipv4;
628 }
3c349c27 629
60956d7f
LA
630 ports = switch_network_port_range_to_string(port);
631
bba65f4a 632 if (switch_parse_cidr(cidr_str, &ip, &mask, &bits)) {
60956d7f
LA
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);
28159946 635 switch_safe_free(ipv4);
60956d7f 636 switch_safe_free(ports);
bba65f4a
AM
637 return SWITCH_STATUS_GENERR;
638 }
3c349c27 639
bba65f4a
AM
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;
b82984fe 646 node->str = switch_core_strdup(list->pool, cidr_str);
60956d7f
LA
647 if(port) {
648 memcpy(&node->port_range, port, sizeof(switch_network_port_range_t));
649 }
650
bba65f4a 651
db91f0e8
BW
652 if (strchr(cidr_str,':')) {
653 node->family = AF_INET6;
654 } else {
655 node->family = AF_INET;
656 }
657
df7637f6 658 if (!zstr(token)) {
4722de50
AM
659 node->token = switch_core_strdup(list->pool, token);
660 }
886e1ddb 661
bba65f4a
AM
662 node->next = list->node_head;
663 list->node_head = node;
3c349c27 664
60956d7f
LA
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);
a6886d18 667
28159946 668 switch_safe_free(ipv4);
60956d7f 669 switch_safe_free(ports);
a6886d18
MR
670 return SWITCH_STATUS_SUCCESS;
671}
672
60956d7f 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)
a6886d18
MR
674{
675 char *cidr_str_dup = NULL;
676 switch_status_t status = SWITCH_STATUS_SUCCESS;
886e1ddb 677
a6886d18 678 if (strchr(cidr_str, ',')) {
a6886d18 679 char *argv[32] = { 0 };
886e1ddb 680 int i, argc;
243b0065 681 cidr_str_dup = strdup(cidr_str);
886e1ddb 682
a6886d18 683 switch_assert(cidr_str_dup);
886e1ddb 684 if ((argc = switch_separate_string(cidr_str_dup, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) {
a6886d18
MR
685 for (i = 0; i < argc; i++) {
686 switch_status_t this_status;
60956d7f 687 if ((this_status = switch_network_list_perform_add_cidr_token(list, argv[i], ok, token, port)) != SWITCH_STATUS_SUCCESS) {
a6886d18
MR
688 status = this_status;
689 }
690 }
691 }
692 } else {
60956d7f 693 status = switch_network_list_perform_add_cidr_token(list, cidr_str, ok, token, port);
a6886d18 694 }
886e1ddb 695
a6886d18
MR
696 switch_safe_free(cidr_str_dup);
697 return status;
bba65f4a
AM
698}
699
60956d7f
LA
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)
bba65f4a 706{
db91f0e8 707 ip_t ip, mask;
bba65f4a
AM
708 switch_network_node_t *node;
709
29ea1523
MJ
710 switch_inet_pton(AF_INET, host, &ip);
711 switch_inet_pton(AF_INET, mask_str, &mask);
3c349c27 712
bba65f4a 713 node = switch_core_alloc(list->pool, sizeof(*node));
3c349c27 714
db91f0e8
BW
715 node->ip.v4 = ntohl(ip.v4);
716 node->mask.v4 = ntohl(mask.v4);
bba65f4a 717 node->ok = ok;
60956d7f
LA
718 if(port) {
719 memcpy(&node->port_range, port, sizeof(switch_network_port_range_t));
720 }
bba65f4a
AM
721
722 /* http://graphics.stanford.edu/~seander/bithacks.html */
db91f0e8
BW
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
b82984fe 727 node->str = switch_core_sprintf(list->pool, "%s:%s", host, mask_str);
886e1ddb 728
bba65f4a
AM
729 node->next = list->node_head;
730 list->node_head = node;
3c349c27 731
bba65f4a
AM
732 return SWITCH_STATUS_SUCCESS;
733}
734
60956d7f
LA
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
bba65f4a 740
db91f0e8 741SWITCH_DECLARE(int) switch_parse_cidr(const char *string, ip_t *ip, ip_t *mask, uint32_t *bitp)
bba65f4a 742{
12e7b5f0 743 char host[128];
bba65f4a
AM
744 char *bit_str;
745 int32_t bits;
db91f0e8
BW
746 const char *ipv6;
747 ip_t *maskv = mask;
748 ip_t *ipv = ip;
bba65f4a 749
d0842438 750 switch_copy_string(host, string, sizeof(host) - 1);
bba65f4a
AM
751 bit_str = strchr(host, '/');
752
753 if (!bit_str) {
754 return -1;
755 }
756
757 *bit_str++ = '\0';
758 bits = atoi(bit_str);
db91f0e8
BW
759 ipv6 = strchr(string, ':');
760 if (ipv6) {
d0842438
AV
761 int32_t i, n;
762 uint32_t k;
763
db91f0e8
BW
764 if (bits < 0 || bits > 128) {
765 return -2;
766 }
d0842438 767
db91f0e8
BW
768 bits = atoi(bit_str);
769 switch_inet_pton(AF_INET6, host, (unsigned char *)ip);
d0842438
AV
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;
db91f0e8
BW
775 }
776 } else {
777 if (bits < 0 || bits > 32) {
778 return -2;
779 }
3c349c27 780
db91f0e8
BW
781 bits = atoi(bit_str);
782 switch_inet_pton(AF_INET, host, (unsigned char *)ip);
783 ipv->v4 = htonl(ipv->v4);
b46693e3 784
db91f0e8
BW
785 maskv->v4 = 0xFFFFFFFF & ~(0xFFFFFFFF >> bits);
786 }
d0842438 787
bba65f4a
AM
788 *bitp = bits;
789
790 return 0;
791}
792
793
c8011a5d
AM
794SWITCH_DECLARE(char *) switch_find_end_paren(const char *s, char open, char close)
795{
796 const char *e = NULL;
797 int depth = 0;
3c349c27 798
c8011a5d
AM
799 while (s && *s && *s == ' ') {
800 s++;
801 }
802
e46266fb 803 if (s && *s == open) {
c8011a5d
AM
804 depth++;
805 for (e = s + 1; e && *e; e++) {
7d1e664d 806 if (*e == open && open != close) {
c8011a5d
AM
807 depth++;
808 } else if (*e == close) {
809 depth--;
810 if (!depth) {
811 break;
812 }
813 }
814 }
815 }
816
531e0f2d 817 return (e && *e == close) ? (char *) e : NULL;
c8011a5d
AM
818}
819
0dbc6515 820SWITCH_DECLARE(switch_size_t) switch_fd_read_line(int fd, char *buf, switch_size_t len)
f64d7e43
AM
821{
822 char c, *p;
823 int cur;
824 switch_size_t total = 0;
825
826 p = buf;
504b632c 827 while (total + 2 < len && (cur = read(fd, &c, 1)) == 1) {
f64d7e43
AM
828 total += cur;
829 *p++ = c;
830 if (c == '\r' || c == '\n') {
831 break;
832 }
833 }
834
835 *p++ = '\0';
504b632c 836 assert(total < len);
f64d7e43
AM
837 return total;
838}
839
c5204c21
AM
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) {
df1ab07c 861 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Single line limit reached!\n");
c5204c21
AM
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) {
df1ab07c 907
c5204c21
AM
908 if (total + 2 >= ilen) {
909 if (ilen + DLINE_BLOCK_SIZE > DLINE_MAX_SIZE) {
df1ab07c 910 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Single line limit reached!\n");
c5204c21
AM
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
ae9f41c3
AM
937SWITCH_DECLARE(char *) switch_amp_encode(char *s, char *buf, switch_size_t len)
938{
939 char *p, *q;
621ce7bb 940 switch_size_t x = 0;
55a194e5 941 switch_assert(s);
ae9f41c3
AM
942
943 q = buf;
944
3c349c27
AM
945 for (p = s; x < len; p++) {
946 switch (*p) {
455b2248
AM
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;
ae9f41c3 983 case '<':
3c349c27 984 if (x + 4 > len - 1) {
ae9f41c3
AM
985 goto end;
986 }
987 *q++ = '&';
988 *q++ = 'l';
989 *q++ = 't';
990 *q++ = ';';
991 x += 4;
992 break;
993 case '>':
3c349c27 994 if (x + 4 > len - 1) {
ae9f41c3
AM
995 goto end;
996 }
997 *q++ = '&';
998 *q++ = 'g';
999 *q++ = 't';
1000 *q++ = ';';
1001 x += 4;
1002 break;
1003 default:
3c349c27 1004 if (x + 1 > len - 1) {
ae9f41c3
AM
1005 goto end;
1006 }
1007 *q++ = *p;
1008 x++;
1009 if (*p == '\0') {
1010 goto end;
1011 }
1012 break;
1013 }
1014 }
1015
3c349c27 1016 end:
ae9f41c3
AM
1017
1018 return buf;
1019}
f64d7e43 1020
7962945c
AM
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{
3c349c27
AM
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;
7d612da4 1032
3c349c27
AM
1033 while (l >= 6) {
1034 out[bytes++] = switch_b64_table[(b >> (l -= 6)) % 64];
66a94a2c 1035 if (bytes >= (int)olen - 1) {
1a3b69a4
AM
1036 goto end;
1037 }
3c349c27
AM
1038 if (++y != 72) {
1039 continue;
1040 }
db91f0e8 1041 /* out[bytes++] = '\n'; */
3c349c27
AM
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) {
66a94a2c 1050 while (l < 6 && bytes < (int)olen - 1) {
7962945c
AM
1051 out[bytes++] = '=', l += 2;
1052 }
1053 }
1054
1a3b69a4
AM
1055 end:
1056
1057 out[bytes] = '\0';
1058
3c349c27 1059 return SWITCH_STATUS_SUCCESS;
7962945c
AM
1060}
1061
1fdd58f5 1062SWITCH_DECLARE(switch_size_t) switch_b64_decode(const char *in, char *out, switch_size_t olen)
fc0dc1f9
AM
1063{
1064
1065 char l64[256];
1066 int b = 0, c, l = 0, i;
1fdd58f5
PG
1067 const char *ip;
1068 char *op = out;
fc0dc1f9
AM
1069 size_t ol = 0;
1070
3c349c27 1071 for (i = 0; i < 256; i++) {
fc0dc1f9
AM
1072 l64[i] = -1;
1073 }
1074
3c349c27
AM
1075 for (i = 0; i < 64; i++) {
1076 l64[(int) switch_b64_table[i]] = (char) i;
fc0dc1f9
AM
1077 }
1078
ef3bd2d8 1079 for (ip = in; ip && *ip && (*ip != '='); ip++) {
3c349c27 1080 c = l64[(int) *ip];
fc0dc1f9
AM
1081 if (c == -1) {
1082 continue;
1083 }
1084
1085 b = (b << 6) + c;
1086 l += 6;
1087
1088 while (l >= 8) {
3c349c27 1089 op[ol++] = (char) ((b >> (l -= 8)) % 256);
1d2a1057 1090 if (ol >= olen - 1) {
fc0dc1f9
AM
1091 goto end;
1092 }
1093 }
1094 }
1095
3c349c27 1096 end:
fc0dc1f9
AM
1097
1098 op[ol++] = '\0';
1099
65668e7e 1100 return ol;
fc0dc1f9
AM
1101}
1102
e7e026b9 1103static int write_buf(int fd, const char *buf)
0a980a4f
AM
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
886e1ddb
AM
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)
0a980a4f
AM
1119{
1120 char *bound = "XXXX_boundary_XXXX";
f64d7e43 1121 const char *mime_type = "audio/inline";
0a980a4f 1122 char filename[80], buf[B64BUFFLEN];
7471ec17 1123 int fd = -1, ifd = -1;
0a980a4f
AM
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];
169195f3
BW
1128 char *dupfile = NULL, *ext = NULL;
1129 char *newfile = NULL;
1130 switch_bool_t rval = SWITCH_FALSE;
0b21064a 1131 const char *err = NULL;
169195f3 1132
5a9eabca
CR
1133 filename[0] = '\0';
1134
4e997750
ML
1135 if (zstr(to)) {
1136 err = "No to address specified";
1137 goto end;
1138 }
1139
29f66f99 1140 if (!zstr(file) && !zstr(convert_cmd) && !zstr(convert_ext)) {
56b6e954 1141 if (strrchr(file, '.')) {
169195f3
BW
1142 dupfile = strdup(file);
1143 if ((ext = strrchr(dupfile, '.'))) {
1144 *ext++ = '\0';
1145 newfile = switch_mprintf("%s.%s", dupfile, convert_ext);
1146 }
1147 }
886e1ddb 1148
169195f3
BW
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);
61dd9c07
MJ
1153 if (strcmp(file, newfile)) {
1154 file = newfile;
1155 } else {
1156 switch_safe_free(newfile);
1157 }
169195f3
BW
1158 }
1159
1160 switch_safe_free(dupfile);
1161 }
0a980a4f 1162
0974bd11 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);
3c349c27 1164
29f66f99
AM
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 }
80542e20
BW
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 }
29f66f99 1185 }
7471ec17 1186
29f66f99 1187 if (headers && !write_buf(fd, headers)) {
886e1ddb 1188 rval = SWITCH_FALSE;
0b21064a 1189 err = "write error.";
ae7b39c9
BW
1190 goto end;
1191 }
0a980a4f 1192
29f66f99
AM
1193 if (!write_buf(fd, "\n\n")) {
1194 rval = SWITCH_FALSE;
1195 err = "write error.";
1196 goto end;
1197 }
3c349c27 1198
80542e20
BW
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 }
7471ec17 1210 }
3c349c27 1211
29f66f99
AM
1212 if (body) {
1213 if (!write_buf(fd, body)) {
1214 rval = SWITCH_FALSE;
1215 err = "write error.";
1216 goto end;
3c349c27 1217 }
3c349c27 1218 }
7471ec17 1219
80542e20 1220 if (file && bound) {
29f66f99
AM
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 }
3c349c27 1231
29f66f99
AM
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 }
7471ec17 1275
7471ec17 1276 }
1f2a97f4 1277
80542e20
BW
1278 if (bound) {
1279 switch_snprintf(buf, B64BUFFLEN, "\n\n--%s--\n.\n", bound);
7471ec17 1280
80542e20
BW
1281 if (!write_buf(fd, buf)) {
1282 rval = SWITCH_FALSE;
1283 err = "write error.";
1284 goto end;
1285 }
29f66f99 1286 }
7471ec17 1287 }
29f66f99 1288
2ee80584
JL
1289 if (fd > -1) {
1290 close(fd);
1291 fd = -1;
1292 }
29f66f99 1293
df7637f6 1294 if (zstr(from)) {
1f2a97f4
AM
1295 from = "freeswitch";
1296 }
04c3b913
TC
1297
1298 {
1299 char *to_arg = switch_util_quote_shell_arg(to);
1300 char *from_arg = switch_util_quote_shell_arg(from);
d2e4dee2 1301#ifdef WIN32
04c3b913 1302 switch_snprintf(buf, B64BUFFLEN, "\"\"%s\" -f %s %s %s < \"%s\"\"", runtime.mailer_app, from_arg, runtime.mailer_app_args, to_arg, filename);
d2e4dee2 1303#else
04c3b913 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);
d2e4dee2 1305#endif
04c3b913
TC
1306 switch_safe_free(to_arg); switch_safe_free(from_arg);
1307 }
1c151468 1308 if (switch_system(buf, SWITCH_TRUE) < 0) {
3c349c27 1309 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to execute command: %s\n", buf);
0b21064a
AM
1310 err = "execute error";
1311 rval = SWITCH_FALSE;
3c349c27 1312 }
0a980a4f 1313
0b21064a
AM
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 }
0a980a4f 1320
0b21064a
AM
1321 rval = SWITCH_TRUE;
1322 }
169195f3 1323
886e1ddb
AM
1324 end:
1325
3ca85365 1326 if (fd > -1) {
7471ec17
AM
1327 close(fd);
1328 }
e31389ac 1329
5a9eabca 1330 if (!zstr_buf(filename) && unlink(filename) != 0) {
e31389ac
AM
1331 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to delete file [%s]\n", filename);
1332 }
1333
3ca85365 1334 if (ifd > -1) {
7471ec17
AM
1335 close(ifd);
1336 }
1337
29f66f99 1338
169195f3
BW
1339 if (newfile) {
1340 unlink(newfile);
1341 free(newfile);
1342 }
1343
0b21064a
AM
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
169195f3 1350 return rval;
0a980a4f
AM
1351}
1352
713afbd9
AM
1353SWITCH_DECLARE(switch_bool_t) switch_is_lan_addr(const char *ip)
1354{
df7637f6 1355 if (zstr(ip))
3c349c27 1356 return SWITCH_FALSE;
713afbd9 1357
dad92067
BW
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) */
713afbd9 1361 strncmp(ip, "255.", 4) &&
df1ab07c 1362 strncmp(ip, "0.", 2) &&
713afbd9
AM
1363 strncmp(ip, "1.", 2) &&
1364 strncmp(ip, "2.", 2) &&
dad92067 1365 strncmp(ip, "172.16.", 7) && /* 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) */
713afbd9
AM
1366 strncmp(ip, "172.17.", 7) &&
1367 strncmp(ip, "172.18.", 7) &&
1368 strncmp(ip, "172.19.", 7) &&
dad92067
BW
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) */
3c349c27 1383 )? SWITCH_FALSE : SWITCH_TRUE;
713afbd9
AM
1384}
1385
3c6b98d0 1386SWITCH_DECLARE(switch_bool_t) switch_ast2regex(const char *pat, char *rbuf, size_t len)
4d2dfa63 1387{
3c6b98d0 1388 const char *p = pat;
e46266fb
MJ
1389
1390 if (!pat) {
1391 return SWITCH_FALSE;
1392 }
1393
4d2dfa63 1394 memset(rbuf, 0, len);
3c349c27 1395
4a60c1e3 1396 *(rbuf + strlen(rbuf)) = '^';
4d2dfa63 1397
3c349c27 1398 while (p && *p) {
4d2dfa63
AM
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 }
4a60c1e3 1412 *(rbuf + strlen(rbuf)) = '$';
4d2dfa63 1413
3c349c27 1414 return strcmp(pat, rbuf) ? SWITCH_TRUE : SWITCH_FALSE;
4d2dfa63 1415}
713afbd9 1416
2372dcdd
AM
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);
55a194e5 1423 switch_assert(p);
2372dcdd
AM
1424 } else {
1425 p = str;
1426 }
1427
3c349c27 1428 for (; p && *p; p++) {
2372dcdd
AM
1429 if (*p == from) {
1430 *p = to;
1431 }
1432 }
1433
1434 return p;
1435}
1436
0367b3b0
MJ
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
5481d9a9
AM
1469SWITCH_DECLARE(char *) switch_strip_whitespace(const char *str)
1470{
1471 const char *sp = str;
1472 char *p, *s = NULL;
c6bdb303 1473 size_t len;
5481d9a9 1474
c6bdb303 1475 if (zstr(sp)) {
7a04104d 1476 return strdup(SWITCH_BLANK_STRING);
c6bdb303 1477 }
5481d9a9 1478
11361f69 1479 while ((*sp == 13 ) || (*sp == 10 ) || (*sp == 9 ) || (*sp == 32) || (*sp == 11) ) {
5481d9a9
AM
1480 sp++;
1481 }
df1ab07c 1482
c6bdb303 1483 if (zstr(sp)) {
7a04104d 1484 return strdup(SWITCH_BLANK_STRING);
c6bdb303 1485 }
5481d9a9
AM
1486
1487 s = strdup(sp);
c6bdb303 1488 switch_assert(s);
5481d9a9 1489
c6bdb303
AM
1490 if ((len = strlen(s)) > 0) {
1491 p = s + (len - 1);
5481d9a9 1492
7a04104d 1493 while ((p >= s) && ((*p == 13 ) || (*p == 10 ) || (*p == 9 ) || (*p == 32) || (*p == 11))) {
c6bdb303
AM
1494 *p-- = '\0';
1495 }
5481d9a9
AM
1496 }
1497
1498 return s;
1499}
1500
4d7e4f1e 1501SWITCH_DECLARE(char *) switch_strip_spaces(char *str, switch_bool_t dup)
713afbd9 1502{
4d7e4f1e 1503 char *sp = str;
713afbd9 1504 char *p, *s = NULL;
c6bdb303 1505 size_t len;
41a0bc8f 1506
c6bdb303 1507 if (zstr(sp)) {
7a04104d 1508 return dup ? strdup(SWITCH_BLANK_STRING) : sp;
c6bdb303 1509 }
3c349c27
AM
1510
1511 while (*sp == ' ') {
713afbd9
AM
1512 sp++;
1513 }
3c349c27 1514
4d7e4f1e
AM
1515 if (dup) {
1516 s = strdup(sp);
c6bdb303 1517 switch_assert(s);
4d7e4f1e
AM
1518 } else {
1519 s = sp;
1520 }
713afbd9 1521
c6bdb303
AM
1522 if (zstr(s)) {
1523 return s;
1524 }
41a0bc8f 1525
c6bdb303
AM
1526 if ((len = strlen(s)) > 0) {
1527 p = s + (len - 1);
713afbd9 1528
7a04104d 1529 while (p && *p && (p >= s) && *p == ' ') {
c6bdb303
AM
1530 *p-- = '\0';
1531 }
713afbd9 1532 }
3c349c27 1533
713afbd9
AM
1534 return s;
1535}
1536
f8974f03
MJ
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;
f8974f03 1546
868e9264
SD
1547 if (++x > len) {
1548 ret = NULL;
1549 break;
1550 }
1551 } else if (*p != ',') {
f8974f03
MJ
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;
f8974f03 1569
868e9264
SD
1570 if (++x > len) {
1571 ret = NULL;
1572 break;
1573 }
f8974f03
MJ
1574 }
1575 }
1576
1577 return ret;
1578}
1579
69f7a9a9
MJ
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';
3c349c27 1588 while (*e == ' ') {
69f7a9a9
MJ
1589 *e-- = '\0';
1590 }
1591 e = args;
1592 br = 1;
3c349c27 1593 while (e && *e) {
69f7a9a9
MJ
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
9347c967
AV
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
713afbd9
AM
1633SWITCH_DECLARE(switch_bool_t) switch_is_number(const char *str)
1634{
1635 const char *p;
1636 switch_bool_t r = SWITCH_TRUE;
1637
55c8fbad
AM
1638 if (*str == '-' || *str == '+') {
1639 str++;
1640 }
1641
713afbd9
AM
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
24084adf
AM
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
a62373c7 1671SWITCH_DECLARE(const char *) switch_stristr(const char *instr, const char *str)
b50e8f5c 1672{
04c1158b
MJ
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*/
04c1158b
MJ
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 */
8fb167c7 1688 for (; ((*start) && (switch_toupper(*start) != switch_toupper(*instr))); start++);
04c1158b
MJ
1689
1690 if (!*start)
1691 return NULL;
1692
1693 pptr = instr;
1694 sptr = start;
1695
8fb167c7 1696 while (switch_toupper(*sptr) == switch_toupper(*pptr)) {
04c1158b
MJ
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;
a93ddbd2 1706 }
a93ddbd2 1707 }
b50e8f5c
AM
1708 return NULL;
1709}
1710
8cc053a6 1711#ifdef HAVE_GETIFADDRS
b82984fe 1712#include <ifaddrs.h>
b82984fe
AM
1713static int get_netmask(struct sockaddr_in *me, int *mask)
1714{
1715 struct ifaddrs *ifaddrs, *i = NULL;
1716
4b4fb6bb 1717 if (!me || getifaddrs(&ifaddrs) < 0) {
b82984fe 1718 return -1;
886e1ddb 1719 }
b82984fe 1720
886e1ddb
AM
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;
b82984fe 1724
2c6427cc 1725 if (s && m && s->sin_family == AF_INET && s->sin_addr.s_addr == me->sin_addr.s_addr) {
b82984fe 1726 *mask = m->sin_addr.s_addr;
3022f3d9 1727 freeifaddrs(ifaddrs);
b82984fe
AM
1728 return 0;
1729 }
1730 }
886e1ddb 1731
8cc053a6 1732 freeifaddrs(ifaddrs);
886e1ddb 1733
b82984fe
AM
1734 return -2;
1735}
8cc053a6
AM
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;
886e1ddb 1745 int nifaces, i;
8cc053a6
AM
1746 int sock;
1747 int r = -1;
886e1ddb
AM
1748
1749 memset(&ifconf, 0, sizeof(ifconf));
1750 ifconf.ifc_buf = (char *) (ifreqs);
8cc053a6 1751 ifconf.ifc_len = sizeof(ifreqs);
8cc053a6 1752
886e1ddb
AM
1753
1754 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
8cc053a6
AM
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
886e1ddb 1764 for (i = 0; i < nifaces; i++) {
8cc053a6
AM
1765 struct sockaddr_in *sin = NULL;
1766 struct in_addr ip;
1767
1768 ioctl(sock, SIOCGIFADDR, &ifreqs[i]);
886e1ddb 1769 sin = (struct sockaddr_in *) &ifreqs[i].ifr_addr;
8cc053a6
AM
1770 ip = sin->sin_addr;
1771
1772 if (ip.s_addr == me->sin_addr.s_addr) {
1773 ioctl(sock, SIOCGIFNETMASK, &ifreqs[i]);
886e1ddb 1774 sin = (struct sockaddr_in *) &ifreqs[i].ifr_addr;
db91f0e8 1775 /* mask = sin->sin_addr; */
8cc053a6
AM
1776 *mask = sin->sin_addr.s_addr;
1777 r = 0;
1778 break;
1779 }
1780
1781 }
886e1ddb
AM
1782
1783 end:
1784
8cc053a6
AM
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{
0e20e489
MJ
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;
45ecc4b0 1798 int r = -1;
0e20e489
MJ
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) {
45ecc4b0
BW
1807 r = -1;
1808 goto end;
0e20e489
MJ
1809 }
1810
886e1ddb 1811 interface_count = bytes / sizeof(INTERFACE_INFO);
0e20e489
MJ
1812
1813 for (x = 0; x < interface_count; ++x) {
886e1ddb 1814 struct sockaddr_in *addr = (struct sockaddr_in *) &(interfaces[x].iiAddress);
0e20e489
MJ
1815
1816 if (addr->sin_addr.s_addr == me->sin_addr.s_addr) {
886e1ddb 1817 struct sockaddr_in *netmask = (struct sockaddr_in *) &(interfaces[x].iiNetmask);
0e20e489 1818 *mask = netmask->sin_addr.s_addr;
45ecc4b0 1819 r = 0;
0e20e489
MJ
1820 break;
1821 }
886e1ddb 1822 }
0e20e489 1823
886e1ddb 1824 end:
45ecc4b0
BW
1825 closesocket(sock);
1826 return r;
8cc053a6
AM
1827}
1828
1829#else
1830
1831static int get_netmask(struct sockaddr_in *me, int *mask)
1832{
1833 return -1;
1834}
1835
b82984fe
AM
1836#endif
1837
ca8dfda0 1838
f28b26b8 1839SWITCH_DECLARE(switch_status_t) switch_resolve_host(const char *host, char *buf, size_t buflen)
ca8dfda0
AM
1840{
1841
886e1ddb 1842 struct addrinfo *ai;
886e1ddb 1843
56b6e954 1844 if (getaddrinfo(host, 0, 0, &ai)) {
886e1ddb
AM
1845 return SWITCH_STATUS_FALSE;
1846 }
ca8dfda0 1847
707502ff 1848 get_addr(buf, buflen, ai->ai_addr, sizeof(struct sockaddr_storage));
ca8dfda0 1849
886e1ddb 1850 freeaddrinfo(ai);
ca8dfda0 1851
886e1ddb 1852 return SWITCH_STATUS_SUCCESS;
ca8dfda0
AM
1853}
1854
1855
b82984fe 1856SWITCH_DECLARE(switch_status_t) switch_find_local_ip(char *buf, int len, int *mask, int family)
c845cf28 1857{
3a541262
AM
1858 switch_status_t status = SWITCH_STATUS_FALSE;
1859 char *base;
4ae8282e
AM
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");
c845cf28
AM
1862
1863#ifdef WIN32
3a541262
AM
1864 SOCKET tmp_socket;
1865 SOCKADDR_STORAGE l_address;
1866 int l_address_len;
1867 struct addrinfo *address_info;
c845cf28 1868#else
23bc4a6c 1869#ifdef __Darwin__
3a541262 1870 int ilen;
c845cf28 1871#else
3a541262 1872 unsigned int ilen;
c845cf28 1873#endif
3a541262
AM
1874 int tmp_socket = -1, on = 1;
1875 char abuf[25] = "";
c845cf28
AM
1876#endif
1877
645edfe3
AM
1878 switch (family) {
1879 case AF_INET:
1880 if (force_local_ip_v4) {
1881 switch_copy_string(buf, force_local_ip_v4, len);
4ae8282e
AM
1882 switch_safe_free(force_local_ip_v4);
1883 switch_safe_free(force_local_ip_v6);
f42c9036 1884 return SWITCH_STATUS_SUCCESS;
645edfe3 1885 }
645edfe3
AM
1886 case AF_INET6:
1887 if (force_local_ip_v6) {
1888 switch_copy_string(buf, force_local_ip_v6, len);
4ae8282e
AM
1889 switch_safe_free(force_local_ip_v4);
1890 switch_safe_free(force_local_ip_v6);
f42c9036 1891 return SWITCH_STATUS_SUCCESS;
645edfe3 1892 }
645edfe3 1893 default:
4ae8282e
AM
1894 switch_safe_free(force_local_ip_v4);
1895 switch_safe_free(force_local_ip_v6);
645edfe3
AM
1896 break;
1897 }
1898
1899
284d03e5
MJ
1900 if (len < 16) {
1901 return status;
1902 }
886e1ddb 1903
3a541262
AM
1904 switch (family) {
1905 case AF_INET:
3d486a34 1906 switch_copy_string(buf, "127.0.0.1", len);
3a541262
AM
1907 base = "82.45.148.209";
1908 break;
1909 case AF_INET6:
3d486a34 1910 switch_copy_string(buf, "::1", len);
db91f0e8 1911 base = "2001:503:BA3E::2:30"; /* DNS Root server A */
3a541262 1912 break;
8e17a9b8
AM
1913 default:
1914 base = "127.0.0.1";
1915 break;
3a541262 1916 }
f8d3093f 1917
c845cf28 1918#ifdef WIN32
3a541262
AM
1919 tmp_socket = socket(family, SOCK_DGRAM, 0);
1920
1921 getaddrinfo(base, NULL, NULL, &address_info);
1922
d4422c59 1923 if (!address_info || WSAIoctl(tmp_socket,
3c349c27
AM
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)) {
3a541262
AM
1927
1928 closesocket(tmp_socket);
d4422c59
MJ
1929 if (address_info)
1930 freeaddrinfo(address_info);
3a541262
AM
1931 return status;
1932 }
1933
b82984fe 1934
3a541262
AM
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)) {
886e1ddb 1939 status = SWITCH_STATUS_SUCCESS;
0e20e489
MJ
1940 if (mask) {
1941 get_netmask((struct sockaddr_in *) &l_address, mask);
1942 }
3a541262 1943 }
c845cf28
AM
1944#else
1945
3a541262
AM
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));
938699d0
WK
1958 if ( (tmp_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ) {
1959 goto doh;
1960 }
3a541262
AM
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
707502ff 1979 switch_copy_string(buf, get_addr(abuf, sizeof(abuf), (struct sockaddr *) &iface_out, sizeof(struct sockaddr_storage)), len);
b82984fe 1980 if (mask) {
886e1ddb 1981 get_netmask((struct sockaddr_in *) &iface_out, mask);
b82984fe
AM
1982 }
1983
3a541262
AM
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;
1d46f922 1994 switch_inet_pton(AF_INET6, base, &remote.sin6_addr);
3a541262
AM
1995 remote.sin6_port = htons(4242);
1996
1997 memset(&iface_out, 0, sizeof(iface_out));
938699d0
WK
1998 if ( (tmp_socket = socket(AF_INET6, SOCK_DGRAM, 0)) == -1 ) {
1999 goto doh;
2000 }
3a541262 2001
1d46f922 2002 if (connect(tmp_socket, (struct sockaddr *) &remote, sizeof(remote)) == -1) {
3a541262
AM
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
3a541262
AM
2011 inet_ntop(AF_INET6, (const void *) &iface_out.sin6_addr, buf, len - 1);
2012 status = SWITCH_STATUS_SUCCESS;
2013 }
2014 break;
2015 }
2016
3a541262 2017 doh:
11e3cff7 2018 if (tmp_socket >= 0) {
3a541262 2019 close(tmp_socket);
3a541262 2020 }
c845cf28
AM
2021#endif
2022
3a541262 2023 return status;
c845cf28
AM
2024}
2025
8e45f23d
AM
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{
e18c12b6 2032 switch_status_t status = SWITCH_STATUS_FALSE;
8e45f23d
AM
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
a4ff7e88 2081SWITCH_DECLARE(switch_time_t) switch_str_time(const char *in)
6a252974 2082{
8951d26f 2083 switch_time_exp_t tm = { 0 }, local_tm = { 0 };
eee5abcc 2084 int proceed = 0, ovector[30], time_only = 0;
3a541262
AM
2085 switch_regex_t *re = NULL;
2086 char replace[1024] = "";
8951d26f 2087 switch_time_t ret = 0, local_time = 0;
3a541262 2088 char *pattern = "^(\\d+)-(\\d+)-(\\d+)\\s*(\\d*):{0,1}(\\d*):{0,1}(\\d*)";
38f06a3b 2089 char *pattern2 = "^(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})";
eee5abcc 2090 char *pattern3 = "^(\\d*):{0,1}(\\d*):{0,1}(\\d*)$";
3a541262 2091
0463541d 2092 switch_time_exp_lt(&tm, switch_micro_time_now());
3a541262 2093
eee5abcc
AM
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 }
38f06a3b 2106 }
eee5abcc
AM
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 }
3a541262
AM
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 }
eee5abcc 2154
38f06a3b
AM
2155 switch_regex_safe_free(re);
2156
8951d26f
BW
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
3a541262
AM
2162 switch_time_exp_gmt_get(&ret, &tm);
2163 return ret;
2164 }
38f06a3b
AM
2165
2166 switch_regex_safe_free(re);
2167
3a541262 2168 return ret;
6a252974
AM
2169}
2170
a4ff7e88 2171SWITCH_DECLARE(const char *) switch_priority_name(switch_priority_t priority)
7174e8ae 2172{
3a541262 2173 switch (priority) { /*lol */
7174e8ae
AM
2174 case SWITCH_PRIORITY_NORMAL:
2175 return "NORMAL";
7174e8ae
AM
2176 case SWITCH_PRIORITY_LOW:
2177 return "LOW";
7174e8ae
AM
2178 case SWITCH_PRIORITY_HIGH:
2179 return "HIGH";
7174e8ae
AM
2180 default:
2181 return "INVALID";
7174e8ae
AM
2182 }
2183}
8311b9a0 2184
01fd1c3a
AM
2185static char RFC2833_CHARS[] = "0123456789*#ABCDF";
2186
965023a8 2187#ifdef _MSC_VER
194d086a
MJ
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
a8a5e462 2217static const char *switch_inet_ntop4(const unsigned char *src, char *dst, size_t size);
194d086a 2218#if HAVE_SIN6
a8a5e462 2219static const char *switch_inet_ntop6(const unsigned char *src, char *dst, size_t size);
194d086a
MJ
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 */
374997f2 2230SWITCH_DECLARE(const char *) switch_inet_ntop(int af, void const *src, char *dst, size_t size)
194d086a
MJ
2231{
2232
2233 switch (af) {
2234 case AF_INET:
a8a5e462 2235 return switch_inet_ntop4(src, dst, size);
194d086a
MJ
2236#if HAVE_SIN6
2237 case AF_INET6:
a8a5e462 2238 return switch_inet_ntop6(src, dst, size);
194d086a
MJ
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 */
3c349c27 2257static const char *switch_inet_ntop4(const unsigned char *src, char *dst, size_t size)
194d086a
MJ
2258{
2259 static const char fmt[] = "%u.%u.%u.%u";
2260 char tmp[sizeof "255.255.255.255"];
2261
3c349c27 2262 if (switch_snprintf(tmp, sizeof tmp, fmt, src[0], src[1], src[2], src[3]) >= (int) size) {
194d086a
MJ
2263 return NULL;
2264 }
2265
2266 return strcpy(dst, tmp);
2267}
2268
5d15dc10 2269#if HAVE_SIN6 || defined(NTDDI_VERSION)
194d086a
MJ
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 */
3c349c27 2276static const char *switch_inet_ntop6(unsigned char const *src, char *dst, size_t size)
194d086a
MJ
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;
3c349c27
AM
2286 struct {
2287 int base, len;
2288 } best = {
2289 -1, 0}, cur = {
2290 -1, 0};
194d086a
MJ
2291 unsigned int words[8];
2292 int i;
2293
2294 /*
2295 * Preprocess:
3c349c27
AM
2296 * Copy the input (bytewise) array into a wordwise array.
2297 * Find the longest run of 0x00's in src[] for :: shorthanding.
194d086a
MJ
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? */
3c349c27 2330 if (best.base != -1 && i >= best.base && i < (best.base + best.len)) {
194d086a
MJ
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? */
3c349c27 2339 if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
99eebf2f 2340 if (!switch_inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp)))
194d086a
MJ
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 */
3c349c27 2355 if ((size_t) (tp - tmp) >= size) {
194d086a
MJ
2356 return NULL;
2357 }
2358
2359 return strcpy(dst, tmp);
2360}
2361#endif
2362
2363#endif
2364
d646547b
AM
2365SWITCH_DECLARE(int) get_addr_int(switch_sockaddr_t *sa)
2366{
886e1ddb 2367 struct sockaddr_in *s = (struct sockaddr_in *) &sa->sa;
d646547b 2368
886e1ddb 2369 return ntohs((unsigned short) s->sin_addr.s_addr);
d646547b
AM
2370}
2371
dc4bef79 2372SWITCH_DECLARE(int) switch_cmp_addr(switch_sockaddr_t *sa1, switch_sockaddr_t *sa2, switch_bool_t ip_only)
d646547b 2373{
10f10c5d
AM
2374 struct sockaddr_in *s1;
2375 struct sockaddr_in *s2;
d646547b 2376
10f10c5d
AM
2377 struct sockaddr_in6 *s16;
2378 struct sockaddr_in6 *s26;
2379
2380 struct sockaddr *ss1;
2381 struct sockaddr *ss2;
2382
886e1ddb
AM
2383 if (!(sa1 && sa2))
2384 return 0;
10f10c5d 2385
886e1ddb
AM
2386 s1 = (struct sockaddr_in *) &sa1->sa;
2387 s2 = (struct sockaddr_in *) &sa2->sa;
10f10c5d 2388
886e1ddb
AM
2389 s16 = (struct sockaddr_in6 *) &sa1->sa;
2390 s26 = (struct sockaddr_in6 *) &sa2->sa;
10f10c5d 2391
886e1ddb
AM
2392 ss1 = (struct sockaddr *) &sa1->sa;
2393 ss2 = (struct sockaddr *) &sa2->sa;
2394
2395 if (ss1->sa_family != ss2->sa_family)
2396 return 0;
10f10c5d
AM
2397
2398 switch (ss1->sa_family) {
2399 case AF_INET:
dc4bef79
AM
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 }
10f10c5d 2405 case AF_INET6:
64f8ff03 2406 {
7ff54ae6
AM
2407 int i;
2408
dc4bef79
AM
2409 if (!ip_only) {
2410 if (s16->sin6_port != s26->sin6_port) return 0;
2411 }
7ff54ae6 2412
886e1ddb 2413 for (i = 0; i < 4; i++) {
dc4bef79 2414 if (*((int32_t *) s16->sin6_addr.s6_addr + i) != *((int32_t *) s26->sin6_addr.s6_addr + i)) return 0;
7ff54ae6
AM
2415 }
2416
2417 return 1;
2418 }
10f10c5d 2419 }
886e1ddb
AM
2420
2421 return 0;
d646547b 2422}
0d626bc7
AM
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;
f8592ab5 2434 //struct sockaddr *ss2;
0d626bc7
AM
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;
f8592ab5 2446 //ss2 = (struct sockaddr *) &sa2->sa;
0d626bc7 2447
0c560819
AM
2448 sa1->port = sa2->port;
2449 sa1->family = sa2->family;
f8592ab5
AM
2450
2451 sa1->sa.sin.sin_family = sa2->family;
2452
0d626bc7
AM
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;
0c560819 2457
0d626bc7
AM
2458 return 1;
2459 case AF_INET6:
64f8ff03 2460 {
0d626bc7
AM
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}
d646547b 2475
f1430d52
AM
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) {
5d15dc10 2482#if defined(NTDDI_VERSION)
ffd28c19 2483 switch_inet_ntop6((unsigned char*)&(sa->sin6_addr), buf, len);
99eebf2f 2484#else
4e5911c2 2485 inet_ntop(AF_INET6, &(sa->sin6_addr), buf, len);
99eebf2f 2486#endif
f1430d52
AM
2487 }
2488
2489 return buf;
2490}
d646547b 2491
1d46f922 2492SWITCH_DECLARE(char *) get_addr(char *buf, switch_size_t len, struct sockaddr *sa, socklen_t salen)
f8d3093f 2493{
55a194e5 2494 switch_assert(buf);
5322410e 2495 *buf = '\0';
d646547b 2496
1d46f922 2497 if (sa) {
886e1ddb 2498 getnameinfo(sa, salen, buf, (socklen_t) len, NULL, 0, NI_NUMERICHOST);
836f55ba 2499 }
f8d3093f
AM
2500 return buf;
2501}
2502
1d46f922
MJ
2503SWITCH_DECLARE(unsigned short) get_port(struct sockaddr *sa)
2504{
2505 unsigned short port = 0;
2506 if (sa) {
2507 switch (sa->sa_family) {
886e1ddb
AM
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;
1d46f922
MJ
2514 }
2515 }
2516 return port;
2517}
2518
886e1ddb 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)
1d46f922
MJ
2520{
2521 char host[NI_MAXHOST], serv[NI_MAXSERV];
85317633 2522 struct sockaddr_in6 si6;
1d46f922
MJ
2523 const struct sockaddr *addr;
2524 const char *colon;
2525
2526 if (flags & SWITCH_URI_NO_SCOPE && sa->family == AF_INET6) {
85317633
MJ
2527 memcpy(&si6, &sa->sa, sa->salen);
2528 si6.sin6_scope_id = 0;
2529
886e1ddb 2530 addr = (const struct sockaddr *) &si6;
1d46f922 2531 } else {
886e1ddb 2532 addr = (const struct sockaddr *) (intptr_t) & sa->sa;
1d46f922
MJ
2533 }
2534
2535 if (getnameinfo(addr, sa->salen, host, sizeof(host), serv, sizeof(serv),
886e1ddb
AM
2536 ((flags & SWITCH_URI_NUMERIC_HOST) ? NI_NUMERICHOST : 0) | ((flags & SWITCH_URI_NUMERIC_PORT) ? NI_NUMERICSERV : 0)) != 0) {
2537 return 0;
1d46f922
MJ
2538 }
2539
2540 colon = strchr(host, ':');
2541
2542 return switch_snprintf(uri, size, "%s:%s%s%s%s%s%s%s", scheme,
886e1ddb 2543 user ? user : "", user ? "@" : "", colon ? "[" : "", host, colon ? "]" : "", serv[0] ? ":" : "", serv[0] ? serv : "");
1d46f922
MJ
2544}
2545
01fd1c3a
AM
2546SWITCH_DECLARE(char) switch_rfc2833_to_char(int event)
2547{
f258e3ea 2548 if (event > -1 && event < (int32_t) sizeof(RFC2833_CHARS)) {
64507e70
AM
2549 return RFC2833_CHARS[event];
2550 }
2551 return '\0';
01fd1c3a
AM
2552}
2553
dbdad460 2554SWITCH_DECLARE(unsigned char) switch_char_to_rfc2833(char key)
01fd1c3a 2555{
3a541262 2556 char *c;
64507e70 2557 unsigned char counter = 0;
01fd1c3a 2558
8fb167c7 2559 key = (char) switch_toupper(key);
3a541262
AM
2560 for (c = RFC2833_CHARS; *c; c++) {
2561 if (*c == key) {
2562 return counter;
2563 }
64507e70
AM
2564 counter++;
2565 }
3a541262 2566 return '\0';
01fd1c3a
AM
2567}
2568
a4ff7e88 2569SWITCH_DECLARE(char *) switch_escape_char(switch_memory_pool_t *pool, char *in, const char *delim, char esc)
0d23976f 2570{
a4ff7e88
MJ
2571 char *data;
2572 const char *p, *d;
3a541262
AM
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 }
0d23976f
AM
2586
2587 if (count == 1) {
2588 return in;
2589 }
2590
2591 data = switch_core_alloc(pool, strlen(in) + count);
3a541262
AM
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;
0d23976f
AM
2606}
2607
9b041ca2
BW
2608/* Helper function used when separating strings to unescape a character. The
2609 supported characters are:
0d23976f 2610
9b041ca2
BW
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;
0a0ee507 2620
9b041ca2 2621 switch (escaped) {
3c349c27
AM
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;
9b041ca2
BW
2636 }
2637 return unescaped;
2638}
2639
30235520
MR
2640SWITCH_DECLARE(char *) switch_escape_string(const char *in, char *out, switch_size_t outlen)
2641{
2642 const char *p;
2643 char *o = out;
886e1ddb
AM
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;
30235520
MR
2670 }
2671 }
2672
2673 *o++ = '\0';
2674
886e1ddb 2675 return out;
30235520
MR
2676}
2677
886e1ddb 2678SWITCH_DECLARE(char *) switch_escape_string_pool(const char *in, switch_memory_pool_t *pool)
30235520 2679{
084e2450 2680 size_t len = strlen(in) * 2 + 1;
30235520
MR
2681 char *buf = switch_core_alloc(pool, len);
2682 return switch_escape_string(in, buf, len);
2683}
2684
9b041ca2
BW
2685/* Helper function used when separating strings to remove quotes, leading /
2686 trailing spaces, and to convert escaped characters. */
475b98f4 2687static char *cleanup_separated_string(char *str, char delim)
8311b9a0 2688{
78d060c6 2689 char *ptr;
9b041ca2
BW
2690 char *dest;
2691 char *start;
2692 char *end = NULL;
2693 int inside_quotes = 0;
8311b9a0 2694
9b041ca2
BW
2695 /* Skip initial whitespace */
2696 for (ptr = str; *ptr == ' '; ++ptr) {
8311b9a0
AM
2697 }
2698
9b041ca2 2699 for (start = dest = ptr; *ptr; ++ptr) {
6e1c32e0
AM
2700 char e;
2701 int esc = 0;
886e1ddb 2702
6e1c32e0 2703 if (*ptr == ESCAPE_META) {
3c349c27 2704 e = *(ptr + 1);
3049cd5c 2705 if (e == '\'' || e == '"' || (delim && e == delim) || e == ESCAPE_META || (e = unescape_char(*(ptr + 1))) != *(ptr + 1)) {
6e1c32e0 2706 ++ptr;
3049cd5c 2707 *dest++ = e;
9b041ca2 2708 end = dest;
6e1c32e0
AM
2709 esc++;
2710 }
2711 }
2712 if (!esc) {
292d0b2e 2713 if (*ptr == '\'' && (inside_quotes || strchr(ptr+1, '\''))) {
f3a42258
AM
2714 if ((inside_quotes = (1 - inside_quotes))) {
2715 end = dest;
2716 }
6e1c32e0
AM
2717 } else {
2718 *dest++ = *ptr;
2719 if (*ptr != ' ' || inside_quotes) {
2720 end = dest;
2721 }
9b041ca2
BW
2722 }
2723 }
2724 }
2725 if (end) {
2726 *end = '\0';
2727 }
3049cd5c 2728
9b041ca2
BW
2729 return start;
2730}
8311b9a0 2731
06a68fce
AM
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);
886e1ddb 2737
06a68fce
AM
2738 array[count++] = buf;
2739
886e1ddb
AM
2740 while (count < arraylen && array[count - 1]) {
2741 if ((d = strstr(array[count - 1], delim))) {
06a68fce
AM
2742 *d = '\0';
2743 d += dlen;
2744 array[count++] = d;
886e1ddb
AM
2745 } else
2746 break;
06a68fce
AM
2747 }
2748
2749 return count;
2750}
2751
9b041ca2 2752/* Separate a string using a delimiter that is not a space */
7cc21a90 2753static unsigned int separate_string_char_delim(char *buf, char delim, char **array, unsigned int arraylen)
9b041ca2
BW
2754{
2755 enum tokenizer_state {
2756 START,
2757 FIND_DELIM
2758 } state = START;
2759
2760 unsigned int count = 0;
2761 char *ptr = buf;
3c349c27 2762 int inside_quotes = 0;
7cc21a90 2763 unsigned int i;
3c349c27 2764
9b041ca2
BW
2765 while (*ptr && count < arraylen) {
2766 switch (state) {
3c349c27
AM
2767 case START:
2768 array[count++] = ptr;
2769 state = FIND_DELIM;
2770 break;
8311b9a0 2771
3c349c27
AM
2772 case FIND_DELIM:
2773 /* escaped characters are copied verbatim to the destination string */
2774 if (*ptr == ESCAPE_META) {
9b041ca2 2775 ++ptr;
292d0b2e 2776 } else if (*ptr == '\'' && (inside_quotes || strchr(ptr+1, '\''))) {
3c349c27
AM
2777 inside_quotes = (1 - inside_quotes);
2778 } else if (*ptr == delim && !inside_quotes) {
2779 *ptr = '\0';
2780 state = START;
2781 }
2782 ++ptr;
2783 break;
8311b9a0
AM
2784 }
2785 }
9b041ca2 2786 /* strip quotes, escaped chars and leading / trailing spaces */
3b5a0ae5
AM
2787
2788 for (i = 0; i < count; ++i) {
2789 array[i] = cleanup_separated_string(array[i], delim);
8311b9a0 2790 }
3b5a0ae5 2791
9b041ca2
BW
2792 return count;
2793}
8311b9a0 2794
9b041ca2 2795/* Separate a string using a delimiter that is a space */
7cc21a90 2796static unsigned int separate_string_blank_delim(char *buf, char **array, unsigned int arraylen)
9b041ca2
BW
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;
3c349c27 2807 int inside_quotes = 0;
7cc21a90 2808 unsigned int i;
713afbd9 2809
9b041ca2
BW
2810 while (*ptr && count < arraylen) {
2811 switch (state) {
3c349c27
AM
2812 case START:
2813 array[count++] = ptr;
2814 state = SKIP_INITIAL_SPACE;
2815 break;
9b041ca2 2816
3c349c27
AM
2817 case SKIP_INITIAL_SPACE:
2818 if (*ptr == ' ') {
2819 ++ptr;
2820 } else {
2821 state = FIND_DELIM;
2822 }
2823 break;
9b041ca2 2824
3c349c27
AM
2825 case FIND_DELIM:
2826 if (*ptr == ESCAPE_META) {
9b041ca2 2827 ++ptr;
3c349c27
AM
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;
9b041ca2 2836
3c349c27
AM
2837 case SKIP_ENDING_SPACE:
2838 if (*ptr == ' ') {
2839 ++ptr;
2840 } else {
2841 state = START;
2842 }
2843 break;
9ab2b1db
AM
2844 }
2845 }
9b041ca2 2846 /* strip quotes, escaped chars and leading / trailing spaces */
3b5a0ae5
AM
2847
2848 for (i = 0; i < count; ++i) {
2849 array[i] = cleanup_separated_string(array[i], 0);
9b041ca2 2850 }
df1ab07c 2851
9b041ca2
BW
2852 return count;
2853}
2854
7cc21a90 2855SWITCH_DECLARE(unsigned int) switch_separate_string(char *buf, char delim, char **array, unsigned int arraylen)
9b041ca2
BW
2856{
2857 if (!buf || !array || !arraylen) {
2858 return 0;
2859 }
2860
e81d31ce
AM
2861
2862 if (*buf == '^' && *(buf+1) == '^') {
2863 char *p = buf + 2;
df1ab07c 2864
292d0b2e 2865 if (*p && *(p+1)) {
e81d31ce
AM
2866 buf = p;
2867 delim = *buf++;
2868 }
2869 }
2870
2871
3c349c27 2872 memset(array, 0, arraylen * sizeof(*array));
9ab2b1db 2873
3c349c27 2874 return (delim == ' ' ? separate_string_blank_delim(buf, array, arraylen) : separate_string_char_delim(buf, delim, array, arraylen));
8311b9a0 2875}
71963ea8 2876
ceafc84c 2877SWITCH_DECLARE(const char *) switch_cut_path(const char *in)
883efd4e 2878{
ceafc84c
MJ
2879 const char *p, *ret = in;
2880 const char delims[] = "/\\";
2881 const char *i;
883efd4e 2882
964aec99
MJ
2883 if (in) {
2884 for (i = delims; *i; i++) {
2885 p = in;
2886 while ((p = strchr(p, *i)) != 0) {
2887 ret = ++p;
2888 }
883efd4e 2889 }
964aec99
MJ
2890 return ret;
2891 } else {
2892 return NULL;
883efd4e 2893 }
883efd4e
AM
2894}
2895
debdfb1a 2896SWITCH_DECLARE(switch_status_t) switch_string_match(const char *string, size_t string_len, const char *search, size_t search_len)
d0a103a3
MJ
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 }
3a541262
AM
2904 }
2905
d0a103a3
MJ
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;
666cd17c 2920 char *dest, *tmp;
3a541262
AM
2921
2922 dest = (char *) malloc(sizeof(char));
e46266fb 2923 switch_assert(dest);
d0a103a3
MJ
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++;
666cd17c
AM
2930 tmp = (char *) realloc(dest, sizeof(char) * (dest_len + 1));
2931 switch_assert(tmp);
2932 dest = tmp;
d0a103a3 2933 }
3a541262 2934 i += search_len - 1;
d0a103a3
MJ
2935 } else {
2936 dest[dest_len] = string[i];
2937 dest_len++;
666cd17c
AM
2938 tmp = (char *) realloc(dest, sizeof(char) * (dest_len + 1));
2939 switch_assert(tmp);
2940 dest = tmp;
d0a103a3
MJ
2941 }
2942 }
2943
2944 dest[dest_len] = 0;
2945 return dest;
2946}
71963ea8 2947
c1c3b65a 2948SWITCH_DECLARE(char *) switch_util_quote_shell_arg(const char *string)
ac0ed44b
NN
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)
c1c3b65a
BW
2954{
2955 size_t string_len = strlen(string);
2956 size_t i;
2957 size_t n = 0;
ac0ed44b
NN
2958 size_t dest_len = 0;
2959 char *dest;
c1c3b65a 2960
ac0ed44b
NN
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 '\'':
e74bba08
NN
2968 /* We replace ' by sq backslace sq sq, so need 3 additional bytes */
2969 dest_len += 3;
ac0ed44b
NN
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 */
e74bba08 2977 if (pool) {
ac0ed44b
NN
2978 dest = switch_core_alloc(pool, sizeof(char) * dest_len);
2979 } else {
2980 dest = (char *) malloc(sizeof(char) * dest_len);
2981 }
c1c3b65a
BW
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 '\'':
e74bba08 2999 /* We replace ' by sq backslash sq sq */
c1c3b65a 3000 dest[n++] = '\'';
e74bba08 3001 dest[n++] = '\\';
c1c3b65a
BW
3002 dest[n++] = '\'';
3003 dest[n++] = '\'';
3004 break;
3005#endif
3006 default:
3007 dest[n++] = string[i];
3008 }
886e1ddb
AM
3009 }
3010
c1c3b65a
BW
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
a2921e26
AM
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;
df1ab07c 3032 }
a2921e26
AM
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 }
df1ab07c 3064
a2921e26
AM
3065 s = poll(pfds, 1, ms);
3066
5ce5199b
AM
3067 if (s < 0) {
3068 if (switch_errno_is_break(switch_errno())) {
3069 s = 0;
3070 }
3071 }
3072
a2921e26
AM
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
4f1b09a3
AM
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));
292d0b2e 3112 switch_assert(pfds);
df1ab07c 3113
4f1b09a3
AM
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;
df1ab07c 3120
4f1b09a3
AM
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 }
df1ab07c 3149
4f1b09a3
AM
3150 s = poll(pfds, len, ms);
3151
5ce5199b
AM
3152 if (s < 0) {
3153 if (switch_errno_is_break(switch_errno())) {
3154 s = 0;
3155 }
3156 }
3157
4f1b09a3
AM
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
b1f382c6
WK
3197 free(pfds);
3198
4f1b09a3
AM
3199 return r;
3200
3201}
3202
a2921e26
AM
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
df1ab07c 3229
a2921e26
AM
3230 if ((flags & SWITCH_POLL_READ)) {
3231
3232#ifdef WIN32
3233#pragma warning( push )
3234#pragma warning( disable : 4127 )
3235 FD_SET(sock, rfds);
df1ab07c 3236#pragma warning( pop )
a2921e26
AM
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);
df1ab07c 3248#pragma warning( pop )
a2921e26
AM
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);
df1ab07c 3260#pragma warning( pop )
a2921e26
AM
3261#else
3262 FD_SET(sock, efds);
3263#endif
3264 }
3265
3266 tv.tv_sec = ms / 1000;
24c3b8d9 3267 tv.tv_usec = (ms % 1000) * 1000;
df1ab07c 3268
a2921e26
AM
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
5ce5199b
AM
3271 if (s < 0) {
3272 if (switch_errno_is_break(switch_errno())) {
3273 s = 0;
3274 }
3275 }
3276
a2921e26
AM
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
4f1b09a3
AM
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;
86ef5d26 3308 unsigned int i;
4f1b09a3
AM
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;
df1ab07c 3334
4f1b09a3
AM
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);
df1ab07c 3341#pragma warning( pop )
4f1b09a3
AM
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);
df1ab07c 3353#pragma warning( pop )
4f1b09a3
AM
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);
df1ab07c 3365#pragma warning( pop )
4f1b09a3
AM
3366#else
3367 FD_SET(waitlist[i].sock, efds);
3368#endif
3369 }
3370 }
3371
3372 tv.tv_sec = ms / 1000;
24c3b8d9 3373 tv.tv_usec = (ms % 1000) * 1000;
df1ab07c 3374
4f1b09a3
AM
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
5ce5199b
AM
3377 if (s < 0) {
3378 if (switch_errno_is_break(switch_errno())) {
3379 s = 0;
3380 }
3381 }
3382
4f1b09a3
AM
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
a2921e26
AM
3410}
3411#endif
3412
3c349c27 3413SWITCH_DECLARE(int) switch_socket_waitfor(switch_pollfd_t *poll, int ms)
71963ea8 3414{
71963ea8 3415 int nsds = 0;
bedcabb8 3416
aa2a793e 3417 switch_poll(poll, 1, &nsds, ms);
71963ea8 3418
bedcabb8 3419 return nsds;
71963ea8 3420}
00aaadc4 3421
ad183fde
MJ
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;
292d0b2e 3442 const char *p, *e;
ad183fde
MJ
3443
3444 if (!url) return NULL;
3445 if (!pool) return NULL;
3446
292d0b2e
AV
3447 e = end_of_p(url);
3448
ad183fde
MJ
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
49778c34 3476SWITCH_DECLARE(char *) switch_url_encode_opt(const char *url, char *buf, size_t len, switch_bool_t double_encode)
f09491a6 3477{
76370f4d 3478 const char *p, *e = end_of_p(url);
3a541262 3479 size_t x = 0;
3a541262 3480 const char hex[] = "0123456789ABCDEF";
f09491a6 3481
c1cf282d
MJ
3482 if (!buf) {
3483 return 0;
3484 }
3485
c1cf282d
MJ
3486 if (!url) {
3487 return 0;
3488 }
3489
5d91bea3
SK
3490 len--;
3491
3a541262 3492 for (p = url; *p; p++) {
76370f4d
AM
3493 int ok = 0;
3494
5d91bea3
SK
3495 if (x >= len) {
3496 break;
3497 }
76370f4d 3498
49778c34 3499 if (!double_encode && *p == '%' && e-p > 1) {
76370f4d
AM
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))) {
59885432 3506 if ((x + 3) > len) {
3a541262
AM
3507 break;
3508 }
3509 buf[x++] = '%';
b5cc1a66 3510 buf[x++] = hex[(*p >> 4) & 0x0f];
3a541262
AM
3511 buf[x++] = hex[*p & 0x0f];
3512 } else {
3513 buf[x++] = *p;
3514 }
3a541262 3515 }
5d91bea3
SK
3516 buf[x] = '\0';
3517
58819523 3518 return buf;
f09491a6
AM
3519}
3520
49778c34
MJ
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
f09491a6
AM
3526SWITCH_DECLARE(char *) switch_url_decode(char *s)
3527{
3528 char *o;
3529 unsigned int tmp;
3530
5111b6ef 3531 if (zstr(s) || !strchr(s, '%')) {
5135dc03
MJ
3532 return s;
3533 }
3534
f09491a6
AM
3535 for (o = s; *s; s++, o++) {
3536 if (*s == '%' && strlen(s) > 2 && sscanf(s + 1, "%2x", &tmp) == 1) {
3a541262 3537 *o = (char) tmp;
f09491a6
AM
3538 s += 2;
3539 } else {
3540 *o = *s;
3541 }
3542 }
3543 *o = '\0';
3544 return s;
3545}
3546
c9fcce08
MOC
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 }
292d0b2e 3564 if (hour) {
c9fcce08
MOC
3565 *hour = atol(shour);
3566 }
292d0b2e 3567 if (min) {
c9fcce08
MOC
3568 *min = atol(smin);
3569 }
292d0b2e 3570 if (sec) {
c9fcce08
MOC
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';
292d0b2e 3594 if (year) {
c9fcce08
MOC
3595 *year = atol(syear);
3596 }
292d0b2e 3597 if (month) {
c9fcce08
MOC
3598 *month = atol(smonth);
3599 }
292d0b2e 3600 if (day) {
c9fcce08
MOC
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;
48b44832
F
3616 char *cur;
3617 char *p;
92b8996e
F
3618 switch_time_t tsStart = 0;
3619 switch_time_t tsEnd = 0;
7f017fd1 3620 int ret = 0;
c9fcce08
MOC
3621
3622 switch_assert(dup);
3623
48b44832
F
3624 cur = dup;
3625 if ((p = strchr(cur, ','))) {
3626 *p++ = '\0';
3627 }
3628
3629 while (cur) {
3630 sStart = cur;
92b8996e 3631 if ((sEnd = strchr(cur, '~'))) {
48b44832 3632 *sEnd++ = '\0';
92b8996e
F
3633
3634 tsStart = switch_str_time(sStart);
3635 tsEnd = switch_str_time(sEnd);
92b8996e 3636
7f017fd1
F
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 }
c9fcce08 3647 }
48b44832 3648
92b8996e 3649 if ((cur = p)) {
48b44832
F
3650 if ((p = strchr(p, ','))) {
3651 *p++ = '\0';
3652 }
3653 }
c9fcce08 3654 }
7f017fd1 3655
c9fcce08 3656 switch_safe_free(dup);
7f017fd1 3657 return ret;
c9fcce08
MOC
3658}
3659
8fb167c7
MJ
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,
886e1ddb
AM
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
8fb167c7
MJ
3698};
3699
3700const short *_switch_toupper_tab_ = _switch_C_toupper_;
3701
5d35d71c 3702SWITCH_DECLARE(int) old_switch_toupper(int c)
8fb167c7 3703{
886e1ddb
AM
3704 if ((unsigned int) c > 255)
3705 return (c);
8fb167c7
MJ
3706 if (c < -1)
3707 return EOF;
886e1ddb 3708 return ((_switch_toupper_tab_ + 1)[c]);
8fb167c7
MJ
3709}
3710
3711const short _switch_C_tolower_[1 + SWITCH_CTYPE_NUM_CHARS] = {
3712 EOF,
886e1ddb
AM
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
8fb167c7
MJ
3745};
3746
3747const short *_switch_tolower_tab_ = _switch_C_tolower_;
3748
17b9f68f 3749SWITCH_DECLARE(int) old_switch_tolower(int c)
8fb167c7 3750{
886e1ddb
AM
3751 if ((unsigned int) c > 255)
3752 return (c);
8fb167c7
MJ
3753 if (c < -1)
3754 return EOF;
886e1ddb 3755 return ((_switch_tolower_tab_ + 1)[c]);
8fb167c7
MJ
3756}
3757
6113ab94
MJ
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
57ffaad4 3810const int _switch_C_ctype_[1 + SWITCH_CTYPE_NUM_CHARS] = {
6113ab94 3811 0,
886e1ddb
AM
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,
6113ab94 3827/* determine printability based on the IS0 8859 8-bit standard */
886e1ddb
AM
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 */
6113ab94
MJ
3846};
3847
57ffaad4 3848const int *_switch_ctype_ = _switch_C_ctype_;
6113ab94
MJ
3849
3850SWITCH_DECLARE(int) switch_isalnum(int c)
3851{
886e1ddb 3852 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & (_U | _L | _N)));
6113ab94
MJ
3853}
3854
3855SWITCH_DECLARE(int) switch_isalpha(int c)
3856{
886e1ddb 3857 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & (_U | _L)));
6113ab94
MJ
3858}
3859
3860SWITCH_DECLARE(int) switch_iscntrl(int c)
3861{
886e1ddb 3862 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & _C));
6113ab94
MJ
3863}
3864
3865SWITCH_DECLARE(int) switch_isdigit(int c)
3866{
886e1ddb 3867 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & _N));
6113ab94
MJ
3868}
3869
3870SWITCH_DECLARE(int) switch_isgraph(int c)
3871{
886e1ddb 3872 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & (_P | _U | _L | _N)));
6113ab94
MJ
3873}
3874
3875SWITCH_DECLARE(int) switch_islower(int c)
3876{
886e1ddb 3877 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & _L));
6113ab94
MJ
3878}
3879
3880SWITCH_DECLARE(int) switch_isprint(int c)
3881{
886e1ddb 3882 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & (_P | _U | _L | _N | _B)));
6113ab94
MJ
3883}
3884
3885SWITCH_DECLARE(int) switch_ispunct(int c)
3886{
886e1ddb 3887 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & _P));
6113ab94
MJ
3888}
3889
3890SWITCH_DECLARE(int) switch_isspace(int c)
3891{
886e1ddb 3892 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & _S));
6113ab94
MJ
3893}
3894
3895SWITCH_DECLARE(int) switch_isupper(int c)
3896{
886e1ddb 3897 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & _U));
6113ab94
MJ
3898}
3899
3900SWITCH_DECLARE(int) switch_isxdigit(int c)
3901{
886e1ddb 3902 return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & (_N | _X)));
6113ab94 3903}
59ec8ced 3904static const char *DOW[] = {
59ec8ced
MOC
3905 "sun",
3906 "mon",
3907 "tue",
3908 "wed",
3909 "thu",
05cb400a
AM
3910 "fri",
3911 "sat"
59ec8ced
MOC
3912};
3913
3914SWITCH_DECLARE(const char *) switch_dow_int2str(int val) {
b639aebd
MR
3915 if (val >= switch_arraylen(DOW)) {
3916 val = val % switch_arraylen(DOW);
59ec8ced
MOC
3917 }
3918 return DOW[val];
3919}
3920
3921SWITCH_DECLARE(int) switch_dow_str2int(const char *exp) {
3922 int ret = -1;
b639aebd 3923 int x;
df1ab07c 3924
b639aebd
MR
3925 for (x = 0; x < switch_arraylen(DOW); x++) {
3926 if (!strncasecmp(DOW[x], exp, 3)) {
05cb400a 3927 ret = x + 1;
59ec8ced
MOC
3928 break;
3929 }
3930 }
3931 return ret;
3932}
3933
b639aebd
MR
3934typedef enum {
3935 DOW_ERR = -2,
3936 DOW_EOF = -1,
05cb400a 3937 DOW_SUN = 1,
b639aebd
MR
3938 DOW_MON,
3939 DOW_TUE,
3940 DOW_WED,
3941 DOW_THU,
3942 DOW_FRI,
05cb400a 3943 DOW_SAT,
b639aebd
MR
3944 DOW_HYPHEN = '-',
3945 DOW_COMA = ','
3946} dow_t;
59ec8ced 3947
df1ab07c 3948static inline dow_t _dow_read_token(const char **s)
b639aebd
MR
3949{
3950 int i;
df1ab07c 3951
b639aebd
MR
3952 if (**s == '-') {
3953 (*s)++;
3954 return DOW_HYPHEN;
3955 } else if (**s == ',') {
3956 (*s)++;
3957 return DOW_COMA;
05cb400a 3958 } else if (**s >= '1' && **s <= '7') {
7fce3995 3959 dow_t r = **s - '0';
b639aebd 3960 (*s)++;
7fce3995 3961 return r;
b639aebd
MR
3962 } else if ((i = switch_dow_str2int(*s)) && i != -1) {
3963 (*s) += 3;
3964 return i;
3965 } else if (!**s) {
3966 return DOW_EOF;
59ec8ced 3967 } else {
b639aebd 3968 return DOW_ERR;
59ec8ced 3969 }
b639aebd 3970}
59ec8ced 3971
b639aebd
MR
3972SWITCH_DECLARE(switch_bool_t) switch_dow_cmp(const char *exp, int val)
3973{
43aeb3b8 3974 dow_t cur, prev = DOW_EOF, range_start = DOW_EOF;
b639aebd 3975 const char *p = exp;
df1ab07c 3976
b639aebd
MR
3977 while ((cur = _dow_read_token(&p)) != DOW_EOF) {
3978 if (cur == DOW_COMA) {
3979 /* Reset state */
292d0b2e 3980 cur = DOW_EOF;
b639aebd 3981 } else if (cur == DOW_HYPHEN) {
43aeb3b8
MR
3982 /* Save the previous token and move to the next one */
3983 range_start = prev;
b639aebd 3984 } else if (cur == DOW_ERR) {
d193789a 3985 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse error for [%s] at position %ld (%.6s)\n", exp, (long) (p - exp), p);
b639aebd
MR
3986 break;
3987 } else {
3988 /* Valid day found */
43aeb3b8 3989 if (range_start != DOW_EOF) { /* Evaluating a range */
48b44832 3990 if (range_start <= cur ? (val >= range_start && val <= cur) : (val >= range_start || val <= cur)) {
05cb400a 3991 return SWITCH_TRUE;
b639aebd 3992 }
43aeb3b8 3993 range_start = DOW_EOF;
b639aebd
MR
3994 } else if (val == cur) {
3995 return SWITCH_TRUE;
3996 }
3997 }
df1ab07c 3998
43aeb3b8 3999 prev = cur;
b639aebd 4000 }
59ec8ced 4001
b639aebd 4002 return SWITCH_FALSE;
59ec8ced
MOC
4003}
4004
835b6d31
AM
4005SWITCH_DECLARE(int) switch_number_cmp(const char *exp, int val)
4006{
2d074488
AZ
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))
886e1ddb 4017 return 1;
886e1ddb 4018 }
2d074488
AZ
4019 if (*exp != ',')
4020 return 0;
886e1ddb 4021 }
835b6d31
AM
4022}
4023
4ab8fa13
MOC
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;
48b44832
F
4033 char *cur;
4034 char *p;
4035 int range_start, range_end;
4ab8fa13
MOC
4036
4037 switch_assert(dup);
4038
48b44832
F
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 }
4ab8fa13 4063
48b44832
F
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 }
4ab8fa13
MOC
4070 }
4071 }
4072 }
48b44832
F
4073
4074 cur = p;
4075 if (p) {
4076 if ((p = strchr(p, ','))) {
4077 *p++ = '\0';
4078 }
4079 }
4080
4ab8fa13 4081 }
48b44832 4082
4ab8fa13
MOC
4083 switch_safe_free(dup);
4084 return 0;
4085
4086}
4087
52f14165 4088SWITCH_DECLARE(int) switch_split_user_domain(char *in, char **user, char **domain)
3f7cafd7 4089{
5aab272b 4090 char *p = NULL, *h = NULL, *u = NULL;
3f7cafd7 4091
5aab272b 4092 if (!in) return 0;
7efeabbd 4093
5aab272b
TC
4094 /* Remove URL scheme */
4095 if (!strncasecmp(in, "sip:", 4)) in += 4;
7cde2adc 4096 else if (!strncasecmp(in, "sips:", 5)) in += 5;
7efeabbd 4097
5aab272b
TC
4098 /* Isolate the host part from the user part */
4099 if ((h = in, p = strchr(h, '@'))) *p = '\0', u = in, h = p+1;
3f7cafd7
MP
4100
4101 /* Clean out the host part of any suffix */
164d6a7b
TC
4102 for (p = h; *p; p++)
4103 if (*p == ':' || *p == ';' || *p == ' ') {
4104 *p = '\0'; break;
4105 }
3f7cafd7 4106
5aab272b
TC
4107 if (user) *user = u;
4108 if (domain) *domain = h;
3f7cafd7
MP
4109 return 1;
4110}
4111
835b6d31 4112
1bf97fa7
AM
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
94b9cc0f
AM
4128SWITCH_DECLARE(char *) switch_format_number(const char *num)
4129{
4130 char *r;
4131 size_t len;
4132 const char *p = num;
d66d4123
MJ
4133
4134 if (!p) {
422df618 4135 return (char*)p;
d66d4123
MJ
4136 }
4137
4138 if (zstr(p)) {
4139 return strdup(p);
4140 }
4141
4142 if (*p == '+') {
94b9cc0f
AM
4143 p++;
4144 }
4145
d66d4123
MJ
4146 if (!switch_is_number(p)) {
4147 return strdup(p);
4148 }
4149
94b9cc0f 4150 len = strlen(p);
df1ab07c 4151
94b9cc0f
AM
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 }
94b9cc0f
AM
4160
4161 return r;
4162}
4163
4164
24288832
JL
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
8bcf3b4f
SK
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 */
eca5c0ad
SK
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;
8bcf3b4f
SK
4202#else
4203 /* Fallback, copy string into private buffer */
4204 switch_copy_string(buf, strerror(errnum), buflen);
4205 return buf;
4206#endif
4207}
4208
f5c0c139
SD
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;
8e4b418e 4214 char *dup = NULL;
f5c0c139
SD
4215
4216 if (qs) {
4217 q = qs;
4218 } else { /*parse our own qs, dup to avoid modify the original string */
8e4b418e 4219 dup = q = strdup(request->qs);
f5c0c139
SD
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
8e4b418e 4246 switch_safe_free(dup);
f5c0c139
SD
4247}
4248
2eed5ecf
SD
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
2eed5ecf
SD
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
f0b9407c
SD
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;
f0b9407c
SD
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
023f6e14 4303 if ((body = strstr(buffer, "\r\n\r\n"))) {
f0b9407c 4304 *body = '\0';
f0b9407c 4305 body += 4;
023f6e14 4306 } else if (( body = strstr(buffer, "\n\n"))) {
f0b9407c 4307 *body = '\0';
f0b9407c 4308 body += 2;
023f6e14
SD
4309 } else {
4310 return status;
f0b9407c
SD
4311 }
4312
4313 request->_buffer = strdup(buffer);
292d0b2e 4314 switch_assert(request->_buffer);
f0b9407c 4315 request->method = request->_buffer;
c02b2427 4316 request->bytes_buffered = datalen;
292d0b2e
AV
4317 request->bytes_header = body - buffer;
4318 request->bytes_read = body - buffer;
f0b9407c
SD
4319
4320 p = strchr(request->method, ' ');
023f6e14
SD
4321
4322 if (!p) goto err;
4323
f0b9407c
SD
4324 *p++ = '\0';
4325
2eed5ecf
SD
4326 if (*p != '/') goto err; /* must start from '/' */
4327
f0b9407c
SD
4328 request->uri = p;
4329 p = strchr(request->uri, ' ');
4330
4331 if (!p) goto err;
f0b9407c 4332
f5c0c139 4333 *p++ = '\0';
f0b9407c 4334 http = p;
f5c0c139
SD
4335
4336 p = strchr(request->uri, '?');
4337
4338 if (p) {
4339 *p++ = '\0';
4340 request->qs = p;
4341 }
4342
2eed5ecf
SD
4343 if (clean_uri((char *)request->uri) != SWITCH_STATUS_SUCCESS) {
4344 goto err;
4345 }
4346
f0b9407c
SD
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
f0b9407c
SD
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
023f6e14
SD
4360 p = strchr(http, '\n');
4361
4362 if (p) {
4363 *p++ = '\0'; // now the first header
4364 } else {
4365 goto noheader;
4366 }
4367
f0b9407c
SD
4368 header_count = switch_separate_string(p, '\n', headers, sizeof(headers)/ sizeof(headers[0]));
4369
023f6e14 4370 if (header_count < 1) goto err;
f0b9407c
SD
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
76b093a0 4400 if (*p) request->port = (switch_port_t)atoi(p);
f0b9407c 4401 }
f5c0c139
SD
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;
f0b9407c
SD
4408 }
4409 }
4410
023f6e14
SD
4411noheader:
4412
f5c0c139
SD
4413 if (request->qs) {
4414 switch_http_parse_qs(request, NULL);
4415 }
4416
f0b9407c
SD
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);
c02b2427
SD
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);
f0b9407c
SD
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}
8bcf3b4f 4462
ba9c44bb
MG
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
9b8a5edd
AM
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;
df1ab07c 4491
9b8a5edd
AM
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;
df1ab07c 4495
9b8a5edd
AM
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 }
df1ab07c 4511
9b8a5edd
AM
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) {
df1ab07c 4517 process((GumboNode*) children->data[i], stream);
9b8a5edd
AM
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 }
df1ab07c 4546
9b8a5edd
AM
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");
e14df00a 4570 text = switch_safe_strdup(html);
9b8a5edd
AM
4571#endif
4572
4573 return text;
4574}
4575
c39a2b11 4576SWITCH_DECLARE(unsigned long) switch_getpid(void)
893a3cdc
AV
4577{
4578#ifndef WIN32
4579 pid_t pid = getpid();
4580#else
4581 int pid = _getpid();
4582#endif
4583
4584 return (unsigned long)pid;
4585}
9b8a5edd 4586
fd27504a
AV
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';
c9def599
DO
4662 } else {
4663 switch_safe_free(digest);
4664 *outputlen = 0;
4665 return SWITCH_STATUS_FALSE;
fd27504a
AV
4666 }
4667 }
4668
4669 switch_safe_free(digest);
4670 *outputlen = i;
4671
4672 return status;
4673}
9b8a5edd 4674
77c8557a 4675SWITCH_DECLARE(char *) switch_must_strdup(const char *_s)
c35a3bb4
AV
4676{
4677 char *s = strdup(_s);
4678 switch_assert(s);
4679 return s;
4680}
4681
b8be418f
AV
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
c7e793c3
AV
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
9f362ea3
AV
4831 BCryptCloseAlgorithmProvider(hAlgorithm, 0);
4832
c7e793c3
AV
4833 return 1;
4834 }
4835
4836 BCryptCloseAlgorithmProvider(hAlgorithm, 0);
4837
a99ed5c4
AV
4838 /* Make sure we return from 0 to SWITCH_RAND_MAX */
4839 return (random_number & (SWITCH_RAND_MAX));
c7e793c3
AV
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
9f362ea3
AV
4861 close(random_fd);
4862
c7e793c3
AV
4863 return 1;
4864 }
4865
4866 close(random_fd);
4867
a99ed5c4
AV
4868 /* Make sure we return from 0 to SWITCH_RAND_MAX */
4869 return (random_number & (SWITCH_RAND_MAX));
c7e793c3
AV
4870#else
4871 return rand();
4872#endif
4873}
4874
44649c70
MJ
4875/* For Emacs:
4876 * Local Variables:
4877 * mode:c
b0ad7ab5 4878 * indent-tabs-mode:t
44649c70
MJ
4879 * tab-width:4
4880 * c-basic-offset:4
4881 * End:
4882 * For VIM:
32adc789 4883 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
44649c70 4884 */