Coverage Report

Created: 2025-07-12 06:14

/src/opensips/parser/contact/parse_contact.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Contact header field body parser
3
 *
4
 * Copyright (C) 2001-2003 FhG Fokus
5
 *
6
 * This file is part of opensips, a free SIP server.
7
 *
8
 * opensips is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 2 of the License, or
11
 * (at your option) any later version
12
 *
13
 * opensips is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
21
 *
22
 * History:
23
 * -------
24
 *  2003-03-25 Adapted to use new parameter parser (janakj)
25
 */
26
27
#include <string.h>          /* memset */
28
#include "../hf.h"
29
#include "../../mem/mem.h"   /* pkg_malloc, pkg_free */
30
#include "../../dprint.h"
31
#include "../../trim.h"      /* trim_leading */
32
#include "../../errinfo.h"      /* trim_leading */
33
#include "../../ut.h"        /* _isalnum */
34
#include "parse_contact.h"
35
36
37
38
static inline int contact_parser(char* _s, int _l, contact_body_t* _c)
39
1.07k
{
40
1.07k
  str tmp;
41
42
1.07k
  tmp.s = _s;
43
1.07k
  tmp.len = _l;
44
45
1.07k
  trim_leading(&tmp);
46
47
1.07k
  if (tmp.len == 0) {
48
4
    LM_ERR("empty body\n");
49
4
    return -1;
50
4
  }
51
52
1.07k
  if (tmp.s[0] == '*') {
53
13
    _c->star = 1;
54
13
    if (tmp.len!=1) {
55
12
      LM_ERR("invalid START Contact header (more than START only)\n");
56
12
      return -2;
57
12
    }
58
1.05k
  } else {
59
1.05k
    if (parse_contacts(&tmp, &(_c->contacts)) < 0) {
60
537
      LM_ERR("failed to parse contacts\n");
61
537
      return -3;
62
537
    }
63
1.05k
  }
64
65
522
  return 0;
66
1.07k
}
67
68
69
/*
70
 * Parse contact header field body
71
 */
72
int parse_contact(struct hdr_field* _h)
73
1.07k
{
74
1.07k
  contact_body_t* b;
75
76
1.07k
  if (_h->parsed != 0) {
77
0
    return 0;  /* Already parsed */
78
0
  }
79
80
1.07k
  b = (contact_body_t*)pkg_malloc(sizeof(contact_body_t));
81
1.07k
  if (b == 0) {
82
0
    LM_ERR("no pkg memory left\n");
83
0
    return -1;
84
0
  }
85
86
1.07k
  memset(b, 0, sizeof(contact_body_t));
87
88
1.07k
  if (contact_parser(_h->body.s, _h->body.len, b) < 0) {
89
553
    LM_ERR("failed to parse contact\n");
90
553
    pkg_free(b);
91
553
    set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM,
92
553
      "error parsing CONTACT headers");
93
553
    set_err_reply(400, "bad headers");
94
553
    return -2;
95
553
  }
96
97
522
  _h->parsed = (void*)b;
98
522
  return 0;
99
1.07k
}
100
101
102
/*
103
 * Free all memory
104
 */
105
void free_contact(contact_body_t** _c)
106
522
{
107
522
  if ((*_c)->contacts) {
108
521
    free_contacts(&((*_c)->contacts));
109
521
  }
110
111
522
  pkg_free(*_c);
112
522
  *_c = 0;
113
522
}
114
115
116
/*
117
 * Print structure, for debugging only
118
 */
119
void log_contact(contact_body_t* _c)
120
0
{
121
0
  LM_DBG("===Contact body===\n");
122
0
  LM_DBG("star: %d\n", _c->star);
123
0
  log_contacts(_c->contacts);
124
0
  LM_DBG("===/Contact body===\n");
125
0
}
126
127
128
/*
129
 * Contact header field iterator, returns next contact if any, it doesn't
130
 * parse message header if not absolutely necessary
131
 */
132
int contact_iterator(contact_t** c, struct sip_msg* msg, contact_t* prev)
133
0
{
134
0
  static struct hdr_field* hdr = 0;
135
0
  struct hdr_field* last;
136
0
  contact_body_t* cb;
137
138
0
  if (!msg) {
139
0
    LM_ERR("invalid parameter value\n");
140
0
    return -1;
141
0
  }
142
143
0
  if (!prev) {
144
         /* No pointer to previous contact given, find topmost
145
          * contact and return pointer to the first contact
146
          * inside that header field
147
          */
148
0
    hdr = msg->contact;
149
0
    if (!hdr) {
150
0
      if (parse_headers(msg, HDR_CONTACT_F, 0) == -1) {
151
0
        LM_ERR("failed to parse headers\n");
152
0
        return -1;
153
0
      }
154
155
0
      hdr = msg->contact;
156
0
    }
157
158
0
    if (hdr) {
159
0
      if (parse_contact(hdr) < 0) {
160
0
        LM_ERR("failed to parse Contact\n");
161
0
        return -1;
162
0
      }
163
0
    } else {
164
0
      *c = 0;
165
0
      return 1;
166
0
    }
167
168
0
    cb = (contact_body_t*)hdr->parsed;
169
0
    *c = cb->contacts;
170
0
    return 0;
171
0
  } else {
172
         /* Check if there is another contact in the
173
          * same header field and if so then return it
174
          */
175
0
    if (prev->next) {
176
0
      *c = prev->next;
177
0
      return 0;
178
0
    }
179
180
         /* Try to find and parse another Contact
181
          * header field
182
          */
183
0
    last = hdr;
184
0
    hdr = hdr->next;
185
186
         /* Search another already parsed Contact
187
          * header field
188
          */
189
0
    while(hdr && hdr->type != HDR_CONTACT_T) {
190
0
      hdr = hdr->next;
191
0
    }
192
193
0
    if (!hdr) {
194
           /* Look for another Contact HF in unparsed
195
            * part of the message header
196
            */
197
0
      if (parse_headers(msg, HDR_CONTACT_F, 1) == -1) {
198
0
        LM_ERR("failed to parse message header\n");
199
0
        return -1;
200
0
      }
201
202
           /* Check if last found header field is Contact
203
            * and if it is not the same header field as the
204
            * previous Contact HF (that indicates that the previous
205
            * one was the last header field in the header)
206
            */
207
0
      if ((msg->last_header->type == HDR_CONTACT_T) &&
208
0
          (msg->last_header != last)) {
209
0
        hdr = msg->last_header;
210
0
      } else {
211
0
        *c = 0;
212
0
        return 1;
213
0
      }
214
0
    }
215
216
0
    if (parse_contact(hdr) < 0) {
217
0
      LM_ERR("failed to parse Contact HF body\n");
218
0
      return -1;
219
0
    }
220
221
         /* And return first contact within that
222
          * header field
223
          */
224
0
    cb = (contact_body_t*)hdr->parsed;
225
0
    *c = cb->contacts;
226
0
    return 0;
227
0
  }
228
0
}
229
230
int should_quote_contact_param_value(str *val)
231
0
{
232
0
  char *p, *end = val->s + val->len;
233
0
  for (p = val->s; p < end; p++) {
234
0
    if (_isalnum(*p))
235
0
      continue;
236
0
    switch (*p) {
237
      /* token chars */
238
0
      case '-':
239
0
      case '.':
240
0
      case '!':
241
0
      case '%':
242
0
      case '*':
243
0
      case '_':
244
0
      case '+':
245
0
      case '`':
246
0
      case '\'':
247
0
      case '~':
248
0
        break;
249
0
      default:
250
0
        return 1;
251
0
    }
252
0
  }
253
0
  return 0;
254
0
}