1 /*
2  * $Id: parse_common.cpp 850 2008-04-04 21:29:36Z sayer $
3  *
4  * Copyright (C) 2007 Raphael Coeffic
5  *
6  * This file is part of SEMS, a free SIP media server.
7  *
8  * SEMS 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. This program is released under
12  * the GPL with the additional exemption that compiling, linking,
13  * and/or using OpenSSL is allowed.
14  *
15  * For a license to use the SEMS software under conditions
16  * other than those described here, or to purchase support for this
17  * software, please contact iptel.org by e-mail at the following addresses:
18  *    info@iptel.org
19  *
20  * SEMS is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28  */
29 
30 
31 #include "parse_common.h"
32 #include "log.h"
33 
34 #include <string.h>
35 
36 #include <memory>
37 using std::unique_ptr;
38 
parse_sip_version(const char * beg,int len)39 int parse_sip_version(const char* beg, int len)
40 {
41     const char* c = beg;
42     //char* end = c+len;
43 
44     if(len!=SIPVER_len){
45 	DBG("SIP-Version string length != SIPVER_len\n");
46 	return MALFORMED_SIP_MSG;
47     }
48 
49     if( ((c[0] != 'S')&&(c[0] != 's')) ||
50 	((c[1] != 'I')&&(c[1] != 'i')) ||
51 	((c[2] != 'P')&&(c[2] != 'p')) ) {
52 
53 	DBG("SIP-Version does not begin with \"SIP\"\n");
54 	return MALFORMED_SIP_MSG;
55     }
56     c += SIP_len;
57 
58     if(memcmp(c,SUP_SIPVER,SUP_SIPVER_len) != 0){
59 	DBG("Unsupported or malformed SIP-Version\n");
60 	return MALFORMED_SIP_MSG;
61     }
62 
63     //DBG("SIP-Version OK\n");
64     return 0;
65 }
66 
_parse_gen_params(list<sip_avp * > * params,const char ** c,int len,char stop_char,bool beg_w_sc)67 static int _parse_gen_params(list<sip_avp*>* params, const char** c,
68 			     int len, char stop_char, bool beg_w_sc)
69 {
70     enum {
71 	VP_PARAM_SEP=0,
72 	VP_PARAM_SEP_SWS,
73 	VP_PNAME,
74 	VP_PNAME_EQU,
75 	VP_PNAME_EQU_SWS,
76 	VP_PVALUE,
77 	VP_PVALUE_QUOTED
78     };
79 
80     const char* beg = *c;
81     const char* end = beg+len;
82     int saved_st=0;
83 
84     int st = beg_w_sc ? VP_PARAM_SEP : VP_PARAM_SEP_SWS;
85 
86     unique_ptr<sip_avp> avp(new sip_avp());
87 
88     for(;*c!=end;(*c)++){
89 
90 	switch(st){
91 
92 	case VP_PARAM_SEP:
93 	    switch(**c){
94 
95 	    case_CR_LF;
96 
97 	    case SP:
98 	    case HTAB:
99 		break;
100 
101 	    case ';':
102 		st = VP_PARAM_SEP_SWS;
103 		break;
104 
105 	    default:
106 		if(**c == stop_char){
107 		    return 0;
108 		}
109 
110 		DBG("';' expected, found '%c'\n",**c);
111 		return MALFORMED_SIP_MSG;
112 	    }
113 	    break;
114 
115 	case VP_PARAM_SEP_SWS:
116 	    switch(**c){
117 
118 	    case_CR_LF;
119 
120 	    case SP:
121 	    case HTAB:
122 		break;
123 
124 	    default:
125 		st = VP_PNAME;
126 		beg=*c;
127 		break;
128 	    }
129 	    break;
130 
131 	case VP_PNAME:
132 	    switch(**c){
133 
134 	    case_CR_LF;
135 
136 	    case SP:
137 	    case HTAB:
138 		st = VP_PNAME_EQU;
139 		avp->name.set(beg,*c-beg);
140 		break;
141 
142 	    case '=':
143 		st = VP_PNAME_EQU_SWS;
144 		avp->name.set(beg,*c-beg);
145 		break;
146 
147 	    case ';':
148 		st = VP_PARAM_SEP_SWS;
149 		avp->name.set(beg,*c-beg);
150 		params->push_back(avp.release());
151 		avp.reset(new sip_avp());
152 		break;
153 
154 	    default:
155 		if(**c == stop_char){
156 		    avp->name.set(beg,*c-beg);
157 		    params->push_back(avp.release());
158 		    return 0;
159 		}
160 		break;
161 
162 	    }
163 	    break;
164 
165 	case VP_PNAME_EQU:
166 	    switch(**c){
167 
168 	    case_CR_LF;
169 
170 	    case SP:
171 	    case HTAB:
172 		break;
173 
174 	    case '=':
175 		st = VP_PNAME_EQU_SWS;
176 		break;
177 
178 	    case ';':
179 		st = VP_PARAM_SEP_SWS;
180 		params->push_back(avp.release());
181 		avp.reset(new sip_avp());
182 		break;
183 
184 	    default:
185 		if(**c == stop_char){
186 		    params->push_back(avp.release());
187 		    return 0;
188 		}
189 		DBG("'=' expected\n");
190 		return MALFORMED_SIP_MSG;
191 	    }
192 
193 	case VP_PNAME_EQU_SWS:
194 	    switch(**c){
195 
196 	    case_CR_LF;
197 
198 	    case SP:
199 	    case HTAB:
200 		break;
201 
202 	    case '\"':
203 		st = VP_PVALUE_QUOTED;
204 		beg = *c;
205 		break;
206 
207 	    case ';':
208 		st = VP_PARAM_SEP_SWS;
209 		params->push_back(avp.release());
210 		avp.reset(new sip_avp());
211 		break;
212 
213 	    default:
214 		st = VP_PVALUE;
215 		beg = *c;
216 		break;
217 	    }
218 	    break;
219 
220 	case VP_PVALUE:
221 	    switch(**c){
222 
223 	    case_CR_LF;
224 
225 	    case '\"':
226 		st = VP_PVALUE_QUOTED;
227 		break;
228 
229 	    case ';':
230 		st = VP_PARAM_SEP_SWS;
231 		avp->value.set(beg,*c-beg);
232 		params->push_back(avp.release());
233 		avp.reset(new sip_avp());
234 		break;
235 
236 	    default:
237 		if(**c == stop_char){
238 		    avp->value.set(beg,*c-beg);
239 		    params->push_back(avp.release());
240 		    return 0;
241 		}
242 		break;
243 	    }
244 	    break;
245 
246 	case VP_PVALUE_QUOTED:
247 	    switch(**c){
248 
249 	    case_CR_LF;
250 
251 	    case '\"':
252 		st = VP_PARAM_SEP;
253 		avp->value.set(beg,*c+1-beg);
254 		params->push_back(avp.release());
255 		avp.reset(new sip_avp());
256 		break;
257 
258 	    case '\\':
259 		if(!*(++(*c))){
260 		    DBG("Escape char in quoted str at EoT!!!\n");
261 		    return MALFORMED_SIP_MSG;
262 		}
263 		break;
264 	    }
265 	    break;
266 
267 	case_ST_CR(**c);
268 
269 	case ST_LF:
270 	case ST_CRLF:
271 	    switch(saved_st){
272 
273 	    case VP_PNAME:
274 		saved_st = VP_PNAME_EQU;
275 		avp->name.set(beg,*c-(st==ST_CRLF?2:1)-beg);
276 		break;
277 
278 	    case VP_PVALUE:
279 		saved_st = VP_PARAM_SEP;
280 		avp->value.set(beg,*c-(st==ST_CRLF?2:1)-beg);
281 		params->push_back(avp.release());
282 		avp.reset(new sip_avp());
283 		break;
284 	    }
285 	    st = saved_st;
286 	}
287     }
288 
289     switch(st){
290 
291     case VP_PNAME:
292 	avp->name.set(beg,*c-beg);
293 	params->push_back(avp.release());
294 	break;
295 
296     case VP_PVALUE:
297 	avp->value.set(beg,*c-beg);
298 	params->push_back(avp.release());
299 	break;
300 
301     case VP_PARAM_SEP:
302     case VP_PARAM_SEP_SWS:
303 	break;
304 
305     case VP_PNAME_EQU:
306     case VP_PNAME_EQU_SWS:
307 	params->push_back(avp.release());
308 	break;
309 
310     default:
311 	DBG("Wrong state: st=%i\n",st);
312 	return MALFORMED_SIP_MSG;
313     }
314 
315     return 0;
316 }
317 
parse_gen_params_sc(list<sip_avp * > * params,const char ** c,int len,char stop_char)318 int parse_gen_params_sc(list<sip_avp*>* params, const char** c,
319 			int len, char stop_char)
320 {
321     return _parse_gen_params(params,c,len,stop_char,true);
322 }
323 
parse_gen_params(list<sip_avp * > * params,const char ** c,int len,char stop_char)324 int parse_gen_params(list<sip_avp*>* params, const char** c,
325 		     int len, char stop_char)
326 {
327     return _parse_gen_params(params,c,len,stop_char,false);
328 }
329 
free_gen_params(list<sip_avp * > * params)330 void free_gen_params(list<sip_avp*>* params)
331 {
332     while(!params->empty()) {
333 	delete params->front();
334 	params->pop_front();
335     }
336 }
337 
338 /** EMACS **
339  * Local variables:
340  * mode: c++
341  * c-basic-offset: 4
342  * End:
343  */
344