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