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