1 /*
2 * Copyright (C) 2011 Raphael Coeffic
3 * 2012 Frafos GmbH
4 *
5 * This file is part of SEMS, a free SIP media server.
6 *
7 * SEMS is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version. This program is released under
11 * the GPL with the additional exemption that compiling, linking,
12 * and/or using OpenSSL is allowed.
13 *
14 * For a license to use the SEMS software under conditions
15 * other than those described here, or to purchase support for this
16 * software, please contact iptel.org by e-mail at the following addresses:
17 * info@iptel.org
18 *
19 * SEMS is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 */
28 #include "parse_nameaddr.h"
29 #include "parse_common.h"
30 #include "log.h"
31
32 #include <assert.h>
33
~sip_nameaddr()34 sip_nameaddr::~sip_nameaddr()
35 {
36 free_gen_params(¶ms);
37 }
38
parse_nameaddr(sip_nameaddr * na,const char ** c,int len)39 int parse_nameaddr(sip_nameaddr* na, const char** c, int len)
40 {
41 enum {
42
43 NA_SWS,
44 NA_MAYBE_URI,
45 NA_MAYBE_URI_END,
46 NA_DISP,
47 NA_DISP_QUOTED,
48 NA_DISP_LAQUOT,
49 NA_URI
50 };
51
52
53 const char* beg = *c;
54 const char* end = *c + len;
55
56 const char* uri_end=0;
57
58 int saved_st=0, st=NA_SWS;
59 //int ret=0;
60
61 for(;*c!=end;(*c)++){
62
63 switch(st){
64
65 case NA_SWS:
66 switch(**c){
67
68 case '\"':
69 st = NA_DISP_QUOTED;
70 beg = *c;
71 break;
72
73 case '<':
74 st = NA_URI;
75 beg = *c+1;
76 break;
77
78 case CR:
79 case LF:
80 case SP:
81 case HTAB:
82 break;
83
84 default:
85 st = NA_MAYBE_URI;
86 beg = *c;
87 break;
88 }
89 break;
90
91 case NA_MAYBE_URI:
92 switch(**c){
93
94 case_CR_LF;
95
96 case SP:
97 case HTAB:
98 st = NA_MAYBE_URI_END;
99 uri_end = *c;
100 break;
101
102 case '<':
103 st = NA_URI;
104 na->name.set(beg, *c - beg);
105 beg = *c+1;
106 break;
107
108 case ';':
109 na->addr.set(beg, *c - beg);
110 return parse_gen_params_sc(&na->params,c, end-*c, 0);
111 }
112 break;
113
114 case NA_MAYBE_URI_END:
115 switch(**c){
116
117 case_CR_LF;
118
119 case ';':
120 na->addr.set(beg, uri_end - beg);
121 return parse_gen_params_sc(&na->params,c, end-*c, 0);
122
123 case '<':
124 st = NA_URI;
125 na->name.set(beg, uri_end - beg);
126 beg = *c+1;
127 break;
128
129 case SP:
130 case HTAB:
131 break;
132
133 default:
134 st = NA_DISP;
135 break;
136 }
137 break;
138
139 case NA_DISP:
140 switch(**c){
141
142 case '\"':
143 st = NA_DISP_QUOTED;
144 beg = *c;
145 break;
146
147 case '<':
148 st = NA_URI;
149 na->name.set(beg, *c - beg);
150 beg = *c+1;
151 break;
152 }
153 break;
154
155 case NA_DISP_QUOTED:
156 switch(**c){
157
158 case '\"':
159 st = NA_DISP_LAQUOT;
160 na->name.set(beg, *c - beg + 1);
161 break;
162
163 case '\\':
164 if(!*(++(*c))){
165 DBG("Escape char in quoted str at EoT!!!\n");
166 return MALFORMED_SIP_MSG;
167 }
168 break;
169 }
170 break;
171
172 case NA_DISP_LAQUOT:
173 switch(**c){
174
175 case_CR_LF;
176
177 case '<':
178 st = NA_URI;
179 beg = *c+1;
180 break;
181
182 case SP:
183 case HTAB:
184 break;
185
186 default:
187 DBG("'<' expected, found %c\n",**c);
188 return MALFORMED_SIP_MSG;
189 }
190 break;
191
192 case NA_URI:
193 if(**c == '>'){
194
195 na->addr.set(beg, *c - beg);
196 (*c)++;
197 return parse_gen_params_sc(&na->params,c, end-*c, 0);
198 }
199 break;
200
201 case_ST_CR(**c);
202
203 case ST_LF:
204 case ST_CRLF:
205 switch(saved_st){
206 case NA_MAYBE_URI:
207 saved_st = NA_MAYBE_URI_END;
208 uri_end = *c - (st==ST_CRLF?2:1);
209 break;
210 }
211 st = saved_st;
212 break;
213 }
214 }
215
216
217 switch(st){
218 case NA_MAYBE_URI:
219 uri_end = *c;
220 case NA_MAYBE_URI_END:
221 na->addr.set(beg, uri_end - beg);
222 break;
223
224 default:
225 DBG("Incomplete name-addr (st=%i) <%.*s>\n",st,(int)(end-beg),beg);
226 return MALFORMED_SIP_MSG;
227 }
228
229 return parse_gen_params_sc(&na->params,c, end-*c, 0);
230 }
231
parse_nameaddr_uri(sip_nameaddr * na,const char ** c,int len)232 int parse_nameaddr_uri(sip_nameaddr* na, const char** c, int len)
233 {
234 if(parse_nameaddr(na, c, len) < 0) {
235
236 DBG("Parsing name-addr failed\n");
237 return -1;
238 }
239
240 if(parse_uri(&na->uri,na->addr.s,na->addr.len) < 0) {
241
242 DBG("Parsing uri failed\n");
243 return -1;
244 }
245
246 return 0;
247 }
248
skip_2_next_nameaddr(const char * & c,const char * & na_end,const char * end)249 static int skip_2_next_nameaddr(const char*& c,
250 const char*& na_end,
251 const char* end)
252 {
253 assert(c && end && (c<=end));
254
255 // detect beginning of next nameaddr
256 enum {
257 RR_BEGIN=0,
258 RR_QUOTED,
259 RR_SWS,
260 RR_SEP_SWS, // space(s) after ','
261 RR_NXT_NA
262 };
263
264 int st = RR_BEGIN;
265 na_end = NULL;
266 for(;c<end;c++){
267
268 switch(st){
269 case RR_BEGIN:
270 switch(*c){
271 case SP:
272 case HTAB:
273 case CR:
274 case LF:
275 st = RR_SWS;
276 na_end = c;
277 break;
278 case COMMA:
279 st = RR_SEP_SWS;
280 na_end = c;
281 break;
282 case DQUOTE:
283 st = RR_QUOTED;
284 break;
285 }
286 break;
287 case RR_QUOTED:
288 switch(*c){
289 case BACKSLASH:
290 if(++c == end) goto error;
291 break;
292 case DQUOTE:
293 st = RR_BEGIN;
294 break;
295 }
296 break;
297 case RR_SWS:
298 switch(*c){
299 case SP:
300 case HTAB:
301 case CR:
302 case LF:
303 break;
304 case COMMA:
305 st = RR_SEP_SWS;
306 break;
307 default:
308 st = RR_BEGIN;
309 na_end = NULL;
310 break;
311 }
312 break;
313 case RR_SEP_SWS:
314 switch(*c){
315 case SP:
316 case HTAB:
317 case CR:
318 case LF:
319 break;
320 default:
321 st = RR_NXT_NA;
322 goto nxt_nameaddr;
323 }
324 break;
325 }
326 }
327
328 nxt_nameaddr:
329 error:
330
331 switch(st){
332 case RR_QUOTED:
333 DBG("Malformed nameaddr\n");
334 return -1;
335
336 case RR_SEP_SWS: // not fine, but acceptable
337 case RR_BEGIN: // end of route header
338 na_end = c;
339 return 0;
340
341 case RR_NXT_NA:
342 return 1; // next nameaddr available
343 }
344
345 // should never be reached
346 // makes GCC happy
347 return 0;
348 }
349
parse_nameaddr_list(list<cstring> & nas,const char * c,int len)350 int parse_nameaddr_list(list<cstring>& nas, const char* c, int len)
351 {
352 const char* end = c + len;
353 const char* na_end = NULL;
354
355 while(c < end) {
356
357 const char* na_begin = c;
358 int err = skip_2_next_nameaddr(c,na_end,end);
359 if(err < 0){
360 ERROR("While parsing nameaddr list ('%.*s')\n",len,na_begin);
361 return -1;
362 }
363
364 if(na_end) {
365 nas.push_back(cstring(na_begin, na_end-na_begin));
366 }
367
368 if(err == 0)
369 break;
370 }
371
372 return 0;
373 }
374
parse_first_nameaddr(sip_nameaddr * na,const char * c,int len)375 int parse_first_nameaddr(sip_nameaddr* na, const char* c, int len)
376 {
377 const char* tmp_c = c;
378 const char* end = c + len;
379 const char* na_end = NULL;
380
381 int err = skip_2_next_nameaddr(tmp_c,na_end,end);
382 if(err < 0){
383 ERROR("While parsing first nameaddr ('%.*s')\n",len,c);
384 return -1;
385 }
386
387 tmp_c = c;
388 return parse_nameaddr(na,&tmp_c,na_end-tmp_c);
389 }
390