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(&params);
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