Browse code

Identity-info Header Field parsing functions and macros

First release

Gergely Kovacs authored on 08/03/2007 15:22:56
Showing 2 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,311 @@
0
+/*
1
+ * $Id$ 
2
+ *
3
+ * Copyright (c) 2007 iptelorg GmbH
4
+ *
5
+ * This file is part of ser, a free SIP server.
6
+ *
7
+ * ser 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
11
+ *
12
+ * For a license to use the ser software under conditions
13
+ * other than those described here, or to purchase support for this
14
+ * software, please contact iptel.org by e-mail at the following addresses:
15
+ *    info@iptel.org
16
+ *
17
+ * ser is distributed in the hope that it will be useful,
18
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
+ * GNU General Public License for more details.
21
+ *
22
+ * You should have received a copy of the GNU General Public License
23
+ * along with this program; if not, write to the Free Software
24
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
+ */
26
+
27
+#include <stdlib.h>
28
+#include <string.h>
29
+#include <ctype.h>
30
+#include "../mem/mem.h"
31
+#include "parse_def.h"
32
+#include "parse_identityinfo.h"
33
+#include "parser_f.h"  /* eat_space_end and so on */
34
+
35
+
36
+char* parse_identityinfo(char *buffer, char *end, struct identityinfo_body *ii_b)
37
+{
38
+	int status = II_START;
39
+	int mainstatus = II_M_START;
40
+	char *p;
41
+
42
+
43
+	if (!buffer || !end || !ii_b) return NULL;
44
+
45
+	ii_b->error = PARSE_ERROR;
46
+
47
+	for(p = buffer; p < end; p++) {
48
+		switch(*p) {
49
+			case '<':
50
+				if (status == II_START) {
51
+					status=II_URI_BEGIN;
52
+					mainstatus = II_M_URI_BEGIN;
53
+					ii_b->uri.s = p + 1;
54
+				} else
55
+					goto parseerror;
56
+					break;
57
+			case 'h':
58
+				case 'H': /* "http://" or "https://" part  */
59
+					switch (status) {
60
+						case II_URI_BEGIN:
61
+							if (end - p <= 8 || strncasecmp(p,"http",strlen("http")))
62
+								goto parseerror;
63
+							p+=4;
64
+							if (*p == 's' || *p == 'S') p++;
65
+							if (memcmp(p,"://",strlen("://")))
66
+								goto parseerror;
67
+							p+=2;
68
+							status = II_URI_DOMAIN;
69
+							break;
70
+						case II_URI_DOMAIN:
71
+							status = II_URI_IPV4;
72
+						case II_URI_IPV4:
73
+						case II_URI_IPV6:
74
+						case II_URI_PATH:
75
+						case II_TOKEN:
76
+						case II_TAG:
77
+							break;
78
+						case II_EQUAL:
79
+							status = II_TOKEN;
80
+							mainstatus = II_M_TOKEN;
81
+							ii_b->alg.s = p;
82
+							break;
83
+						default:
84
+							goto parseerror;
85
+					}
86
+					break;
87
+			case '/':
88
+				switch(status){
89
+					case II_URI_IPV4:
90
+						ii_b->domain.len = p - ii_b->domain.s;
91
+						status = II_URI_PATH;
92
+						break;
93
+					case II_URI_PATH:
94
+						break;
95
+					case II_URI_IPV6:
96
+					default:
97
+						goto parseerror;
98
+				}
99
+				break;
100
+			case '>':
101
+				if (status == II_URI_PATH) {
102
+					ii_b->uri.len = p - ii_b->uri.s;
103
+					status = II_URI_END;
104
+					mainstatus = II_M_URI_END;
105
+				} else
106
+					goto parseerror;
107
+					break;
108
+			case ' ':
109
+			case '\t':
110
+				switch (status) {
111
+					case II_EQUAL:
112
+					case II_TAG:
113
+					case II_SEMIC:
114
+					case II_URI_END:
115
+						status = II_LWS;
116
+						break;
117
+					case II_LWS:
118
+						break;
119
+					case II_LWSCRLF:
120
+						status = II_LWSCRLFSP;
121
+						break;
122
+					default:
123
+						goto parseerror;
124
+				}
125
+				break;
126
+			case '\r':
127
+				switch (status) {
128
+					case II_TOKEN:
129
+						ii_b->alg.len = p - ii_b->alg.s;
130
+						status = II_ENDHEADER;
131
+						break;
132
+					case II_EQUAL:
133
+					case II_TAG:
134
+					case II_SEMIC:
135
+					case II_URI_END:
136
+					case II_LWS:
137
+						status = II_LWSCR;
138
+						break;
139
+					default:
140
+						goto parseerror;
141
+				}
142
+				break;
143
+			case '\n':
144
+				switch (status) {
145
+					case II_EQUAL:
146
+					case II_TAG:
147
+					case II_SEMIC:
148
+					case II_URI_END:
149
+					case II_LWS:
150
+					case II_LWSCR:
151
+						status = II_LWSCRLF;
152
+						break;
153
+						case II_TOKEN: /* if there was not '\r' */
154
+							ii_b->alg.len = p - ii_b->alg.s;
155
+					case II_ENDHEADER:
156
+						p=eat_lws_end(p, end);
157
+						/*check if the header ends here*/
158
+						if (p>=end) {
159
+							LOG(L_ERR, "ERROR: parse_date: strange EoHF\n");
160
+							goto parseerror;
161
+						}
162
+						if (*p=='\r' && p+1<end && *(p+1)=='\n') {
163
+							ii_b->error=PARSE_OK;
164
+							return p+2;
165
+						}
166
+						if (*p=='\n') {
167
+							ii_b->error=PARSE_OK;
168
+							return p+1;
169
+						}
170
+						LOG(L_ERR, "ERROR: Date EoL expected\n");
171
+						goto error;
172
+						break;
173
+					default:
174
+						goto parseerror;
175
+				}
176
+				break;
177
+			case ';':
178
+				switch (status) {
179
+					case II_URI_END:
180
+					case II_LWS:
181
+					case II_LWSCRLFSP:
182
+						if (mainstatus == II_M_URI_END) {
183
+							status = II_SEMIC;
184
+							mainstatus = II_M_SEMIC;
185
+						} else
186
+							goto parseerror;
187
+						break;
188
+					default:
189
+						goto parseerror;
190
+				}
191
+				break;
192
+				case 'a': /* tag part of 'alg' parameter */
193
+			case 'A':
194
+				switch (status) {
195
+					case II_LWS:
196
+					case II_LWSCRLFSP:
197
+					case II_SEMIC:
198
+						if (mainstatus == II_M_SEMIC) {
199
+							mainstatus = II_M_TAG;
200
+							status = II_TAG;
201
+							if (end - p <= 3 || strncasecmp(p,"alg",strlen("alg")))
202
+								goto parseerror;
203
+							p+=2;
204
+						} else
205
+							goto parseerror;
206
+						break;
207
+					case II_URI_DOMAIN:
208
+						status = II_URI_IPV4;
209
+					case II_URI_IPV4:
210
+					case II_URI_IPV6:
211
+					case II_URI_PATH:
212
+					case II_TOKEN:
213
+						break;
214
+					case II_EQUAL:
215
+						status = II_TOKEN;
216
+						mainstatus = II_M_TOKEN;
217
+						ii_b->alg.s = p;
218
+						break;
219
+					default:
220
+						goto parseerror;
221
+				}
222
+				break;
223
+			case '=':
224
+				switch (status) {
225
+					case II_TAG:
226
+					case II_LWS:
227
+					case II_LWSCRLFSP:
228
+						if (mainstatus == II_M_TAG) {
229
+							status = II_EQUAL;
230
+							mainstatus = II_M_EQUAL;
231
+						} else
232
+							goto parseerror;
233
+						break;
234
+					case II_URI_PATH:
235
+						break;
236
+					default:
237
+						goto parseerror;
238
+				}
239
+				break;
240
+			case '[':
241
+				switch (status) {
242
+					case II_URI_DOMAIN:
243
+						status = II_URI_IPV6;
244
+						ii_b->domain.s = p + 1;
245
+						break;
246
+					default:
247
+						goto parseerror;
248
+				}
249
+				break;
250
+			case ']':
251
+				switch (status) {
252
+					case II_URI_IPV6:
253
+						ii_b->domain.len = p - ii_b->domain.s;
254
+						status = II_URI_PATH;
255
+						break;
256
+					case II_URI_IPV4:
257
+					case II_URI_PATH:
258
+						goto parseerror;
259
+				}
260
+				break;
261
+			case ':':
262
+				if (status == II_URI_IPV4) {
263
+					ii_b->domain.len = p - ii_b->domain.s;
264
+					status = II_URI_PATH;
265
+				}
266
+				break;
267
+			default:
268
+				switch (status) {
269
+					case II_EQUAL:
270
+					case II_LWS:
271
+					case II_LWSCRLFSP:
272
+						if (mainstatus == II_M_EQUAL) {
273
+							status = II_TOKEN;
274
+							mainstatus = II_M_TOKEN;
275
+							ii_b->alg.s = p;
276
+						} else
277
+							goto parseerror;
278
+						break;
279
+					case II_TOKEN:
280
+						break;
281
+					case II_URI_DOMAIN:
282
+						ii_b->domain.s = p;
283
+						status = II_URI_IPV4;
284
+					case II_URI_IPV4:
285
+					case II_URI_IPV6:
286
+						if (isalnum(*p)
287
+						    || *p == '-'
288
+						    || *p == '.'
289
+						    || *p == ':' )
290
+							break;
291
+					case II_START:
292
+						goto parseerror;
293
+				}
294
+				break;
295
+		}
296
+	}
297
+
298
+parseerror:
299
+		LOG( L_ERR , "ERROR: parse_identityinfo: "
300
+		"unexpected char [%c] in status %d: <<%.*s>> .\n",
301
+		*p,status, (int)(p-buffer), ZSW(buffer));
302
+error:
303
+		return p;
304
+}
305
+
306
+
307
+void free_identityinfo(struct identityinfo_body *ii_b)
308
+{
309
+	pkg_free(ii_b);
310
+}
0 311
new file mode 100644
... ...
@@ -0,0 +1,89 @@
0
+/*
1
+ * $Id$ 
2
+ *
3
+ * Copyright (c) 2007 iptelorg GmbH
4
+ *
5
+ * This file is part of ser, a free SIP server.
6
+ *
7
+ * ser 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
11
+ *
12
+ * For a license to use the ser software under conditions
13
+ * other than those described here, or to purchase support for this
14
+ * software, please contact iptel.org by e-mail at the following addresses:
15
+ *    info@iptel.org
16
+ *
17
+ * ser is distributed in the hope that it will be useful,
18
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
+ * GNU General Public License for more details.
21
+ *
22
+ * You should have received a copy of the GNU General Public License
23
+ * along with this program; if not, write to the Free Software
24
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
+ */
26
+
27
+
28
+#ifndef PARSE_IDENTITYNFO
29
+#define PARSE_IDENTITYNFO
30
+
31
+#include "../str.h"
32
+
33
+enum {
34
+	II_START,
35
+	II_URI_BEGIN,
36
+	II_URI_DOMAIN,
37
+	II_URI_IPV4,
38
+	II_URI_IPV6,
39
+	II_URI_PATH,
40
+	II_URI_END,
41
+	II_LWS,
42
+	II_LWSCR,
43
+	II_LWSCRLF,
44
+	II_LWSCRLFSP,
45
+	II_SEMIC,
46
+	II_TAG,
47
+	II_EQUAL,
48
+	II_TOKEN,
49
+	II_ENDHEADER
50
+};
51
+
52
+enum {
53
+	II_M_START,
54
+	II_M_URI_BEGIN,
55
+	II_M_URI_END,
56
+	II_M_SEMIC,
57
+	II_M_TAG,
58
+	II_M_EQUAL,
59
+	II_M_TOKEN
60
+};
61
+
62
+#define ZSW(_c) ((_c)?(_c):"")
63
+
64
+struct identityinfo_body {
65
+	int error;  	/* Error code */
66
+	str uri;    	/* URI */
67
+	str domain; 	/* Domain part of the URI */
68
+	str alg; 		/* Identity-Info header field MUST contain an 'alg' parameter */
69
+};
70
+
71
+
72
+/* casting macro for accessing IDENTITY-INFO body */
73
+#define get_identityinfo(p_msg) ((struct identityinfo_body*)(p_msg)->identity_info->parsed)
74
+
75
+
76
+/*
77
+ * Parse Identity-Info header field
78
+ */
79
+char* parse_identityinfo(char *buffer, char* end, struct identityinfo_body *ii_b);
80
+
81
+
82
+/*
83
+ * Free all associated memory
84
+ */
85
+void free_identityinfo(struct identityinfo_body *ii_b);
86
+
87
+
88
+#endif