attrs.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * Accounting module
  3. *
  4. * $Id$
  5. *
  6. * Copyright (C) 2001-2003 FhG FOKUS
  7. * Copyright (C) 2005 iptelorg GmbH
  8. *
  9. * This file is part of ser, a free SIP server.
  10. *
  11. * ser is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version
  15. *
  16. * For a license to use the ser software under conditions
  17. * other than those described here, or to purchase support for this
  18. * software, please contact iptel.org by e-mail at the following addresses:
  19. * [email protected]
  20. *
  21. * ser is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * GNU General Public License for more details.
  25. *
  26. * You should have received a copy of the GNU General Public License
  27. * along with this program; if not, write to the Free Software
  28. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  29. *
  30. */
  31. #ifndef _ATTRS_H
  32. #define _ATTRS_H
  33. #include <string.h>
  34. #include "../../mem/mem.h"
  35. #include "../../dprint.h"
  36. #include "../../usr_avp.h"
  37. #include "../../trim.h"
  38. #include "../../str.h"
  39. #include "../../ut.h"
  40. /*
  41. * Parse the value of attrs parameter
  42. */
  43. static int parse_attrs(avp_ident_t** avps, int* avps_n, char* attrs)
  44. {
  45. str token;
  46. token.s = strtok(attrs, ",");
  47. *avps = 0;
  48. *avps_n = 0;
  49. while(token.s) {
  50. token.len = strlen(token.s);
  51. trim(&token);
  52. if (token.len && token.s[0] == '$') {
  53. token.s++;
  54. token.len--;
  55. } else goto skip;
  56. *avps = pkg_realloc(*avps, sizeof(avp_ident_t) * (*avps_n + 1));
  57. if (!*avps) {
  58. ERR("No memory left\n");
  59. goto err;
  60. }
  61. if (parse_avp_ident(&token, &(*avps)[*avps_n]) < 0) {
  62. ERR("Error while parsing AVP id '%.*s'\n", token.len, ZSW(token.s));
  63. goto err;
  64. }
  65. DBG("Found attribute $%.*s\n", (*avps)[*avps_n].name.s.len, (*avps)[*avps_n].name.s.s);
  66. (*avps_n)++;
  67. skip:
  68. token.s = strtok(0, ",");
  69. }
  70. return 0;
  71. err:
  72. if (*avps) pkg_free(*avps);
  73. return -1;
  74. }
  75. #define attrs_append(dst, src) \
  76. do { \
  77. if ((dst).len < (src).len) { \
  78. ERR("Buffer too small\n"); \
  79. goto error; \
  80. } \
  81. memcpy((dst).s, (src).s, (src).len); \
  82. (dst).s += (src).len; \
  83. (dst).len -= (src).len; \
  84. } while(0)
  85. /*
  86. * Escape delimiter characters
  87. */
  88. #define attrs_append_esc(dst, src, esc_quote) \
  89. do { \
  90. int i; \
  91. char* w; \
  92. \
  93. if ((dst).len < ((src).len * 2)) { \
  94. ERR("Buffer too small\n"); \
  95. goto error; \
  96. } \
  97. \
  98. w = (dst).s; \
  99. for(i = 0; i < (src).len; i++) { \
  100. switch((src).s[i]) { \
  101. case '\n': *w++ = '\\'; *w++ = 'n'; break; \
  102. case '\r': *w++ = '\\'; *w++ = 'r'; break; \
  103. case '\t': *w++ = '\\'; *w++ = 't'; break; \
  104. case '\\': *w++ = '\\'; *w++ = '\\'; break; \
  105. case '\0': *w++ = '\\'; *w++ = '0'; break; \
  106. case '"': \
  107. if (esc_quote) { \
  108. *w++ = '\\'; *w++ = 'q'; \
  109. } else { \
  110. *w++ = (src).s[i]; \
  111. } \
  112. break; \
  113. case ':': *w++ = '\\'; *w++ = 'o'; break; \
  114. case ',': *w++ = '\\'; *w++ = 'c'; break; \
  115. default: *w++ = (src).s[i]; break; \
  116. } \
  117. } \
  118. (dst).len -= w - (dst).s; \
  119. (dst).s = w; \
  120. } while(0)
  121. #define attrs_append_printf(dst, fmt, args...) \
  122. do { \
  123. int len = snprintf((dst).s, (dst).len, (fmt), ## args); \
  124. if (len < 0 || len >= (dst).len) { \
  125. ERR("Buffer too small\n"); \
  126. goto error; \
  127. } \
  128. (dst).s += len; \
  129. (dst).len -= len; \
  130. } while(0)
  131. #define ATTRS_BUF_LEN 4096
  132. static str* print_attrs(avp_ident_t* avps, int avps_n, int quote)
  133. {
  134. static str quote_s = STR_STATIC_INIT("\"");
  135. static str attrs_name_delim = STR_STATIC_INIT(":");
  136. static str attrs_delim = STR_STATIC_INIT(",");
  137. static char buf[ATTRS_BUF_LEN];
  138. static str res;
  139. int i;
  140. struct search_state st;
  141. avp_value_t val;
  142. str p;
  143. p.s = buf;
  144. p.len = ATTRS_BUF_LEN - 1;
  145. if (quote && avps_n) {
  146. attrs_append(p, quote_s);
  147. }
  148. for(i = 0; i < avps_n; i++) {
  149. avp_t *this_avp = search_first_avp(avps[i].flags, avps[i].name, &val, &st);
  150. if (!this_avp) continue;
  151. attrs_append(p, avps[i].name.s);
  152. attrs_append(p, attrs_name_delim);
  153. if (this_avp->flags & AVP_VAL_STR)
  154. attrs_append_esc(p, val.s, quote);
  155. else
  156. attrs_append_printf(p, "%d", val.n);
  157. while(search_next_avp(&st, &val)) {
  158. attrs_append(p, attrs_delim);
  159. attrs_append(p, avps[i].name.s);
  160. attrs_append(p, attrs_name_delim);
  161. attrs_append_esc(p, val.s, quote);
  162. }
  163. if (i < (avps_n - 1)) attrs_append(p, attrs_delim);
  164. }
  165. if (quote && avps_n) {
  166. attrs_append(p, quote_s);
  167. }
  168. *p.s = '\0';
  169. res.s = buf;
  170. res.len = p.s - buf;
  171. return &res;
  172. error:
  173. return 0;
  174. }
  175. #endif /* _ATTRS_H */