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