Browse code

Contact parser

Jan Janak authored on 15/08/2002 11:53:51
Showing 6 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,213 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * Parses one Contact in Contact HF body
5
+ */
6
+
7
+#include "contact.h"
8
+#include "../../mem/mem.h" /* pkg_malloc, pkg_free */
9
+#include "../../dprint.h"
10
+#include <string.h>        /* memset */
11
+#include "../../trim.h"    /* trim_leading, trim_trailing */
12
+#include <stdio.h>         /* printf */
13
+
14
+
15
+#define ST1 1 /* Basic state */
16
+#define ST2 2 /* Quoted */
17
+#define ST3 3 /* Angle quoted */
18
+#define ST4 4 /* Angle quoted and quoted */
19
+#define ST5 5 /* Escape in quoted */
20
+#define ST6 6 /* Escape in angle quoted and quoted */
21
+
22
+
23
+/*
24
+ * Skip URI, stops when , (next contact)
25
+ * or ; (parameter) is found
26
+ */
27
+static inline int skip_uri(str* _s)
28
+{
29
+	register int st = ST1;
30
+
31
+	while(_s->len) {
32
+		switch(*(_s->s)) {
33
+		case ',':
34
+		case ';':
35
+			if (st == ST1) return 0;
36
+			break;
37
+
38
+		case '\"':
39
+			switch(st) {
40
+			case ST1: st = ST2; break;
41
+			case ST2: st = ST1; break;
42
+			case ST3: st = ST4; break;
43
+			case ST4: st = ST3; break;
44
+			case ST5: st = ST2; break;
45
+			case ST6: st = ST4; break;
46
+			}
47
+			break;
48
+
49
+		case '<':
50
+			switch(st) {
51
+			case ST1: st = ST3; break;
52
+			case ST3: 
53
+				LOG(L_ERR, "skip_uri(): Second < found\n");
54
+				return -1;
55
+			case ST5: st = ST2; break;
56
+			case ST6: st = ST4; break;
57
+			}
58
+			break;
59
+			
60
+		case '>':
61
+			switch(st) {
62
+			case ST1: 
63
+				LOG(L_ERR, "skip_uri(): > is first\n");
64
+				return -2;
65
+
66
+			case ST3: st = ST1; break;
67
+			case ST5: st = ST2; break;
68
+			case ST6: st = ST4; break;
69
+			}
70
+			break;
71
+
72
+		case '\\':
73
+			switch(st) {
74
+			case ST2: st = ST5; break;
75
+			case ST4: st = ST6; break;
76
+			case ST5: st = ST2; break;
77
+			case ST6: st = ST4; break;
78
+			}
79
+			break;
80
+
81
+		default: break;
82
+
83
+		}
84
+
85
+		_s->s++;
86
+		_s->len--;
87
+	}
88
+
89
+	if (st != ST1) {
90
+		LOG(L_ERR, "skip_uri(): < or \" not closed\n");
91
+		return -3;
92
+	}
93
+
94
+	return 0;
95
+}
96
+
97
+
98
+
99
+/*
100
+ * Parse contacts in a Contact HF
101
+ */
102
+int parse_contacts(str* _s, contact_t** _c)
103
+{
104
+	contact_t* c;
105
+
106
+	while(1) {
107
+		     /* Allocate and clear contact stucture */
108
+		c = (contact_t*)pkg_malloc(sizeof(contact_t));
109
+		if (c == 0) {
110
+			LOG(L_ERR, "parse_contacts(): No memory left\n");
111
+			goto error;
112
+		}
113
+		memset(c, 0, sizeof(contact_t));
114
+		
115
+		     /* Save beginning of URI */
116
+		c->uri.s = _s->s;
117
+		
118
+		     /* Find the end of the URI */
119
+		if (skip_uri(_s) < 0) {
120
+			LOG(L_ERR, "parse_contacts(): Error while skipping URI\n");
121
+			goto error;
122
+		}
123
+		
124
+		c->uri.len = _s->s - c->uri.s; /* Calculate URI length */
125
+		trim_trailing(&(c->uri));      /* Remove any trailing spaces from URI */
126
+
127
+		if (_s->len == 0) goto ok;
128
+		
129
+		if (_s->s[0] == ';') {         /* Contact parameter found */
130
+			_s->s++;
131
+			_s->len--;
132
+			trim_leading(_s);
133
+			
134
+			if (_s->len == 0) {
135
+				LOG(L_ERR, "parse_contacts(): Error while parsing params\n");
136
+				goto error;
137
+			}
138
+
139
+			if (parse_cparams(_s, &(c->params), &(c->q), &(c->expires), &(c->method)) < 0) {
140
+				LOG(L_ERR, "parse_contacts(): Error while parsing params\n");
141
+				goto error;
142
+			}
143
+
144
+			if (_s->len == 0) goto ok;
145
+		}
146
+
147
+		     /* Next character is comma */
148
+		_s->s++;
149
+		_s->len--;
150
+		trim_leading(_s);
151
+
152
+		if (_s->len == 0) {
153
+			LOG(L_ERR, "parse_contacts(): Text after comma missing\n");
154
+			goto error;
155
+		}
156
+
157
+		c->next = *_c;
158
+		*_c = c;
159
+	}
160
+
161
+ error:
162
+	if (c) pkg_free(c);
163
+	free_contacts(_c); /* Free any contacts created so far */
164
+	return -1;
165
+
166
+ ok:
167
+	c->next = *_c;
168
+	*_c = c;
169
+	return 0;
170
+}
171
+
172
+
173
+/*
174
+ * Free list of contacts
175
+ * _c is head of the list
176
+ */
177
+void free_contacts(contact_t** _c)
178
+{
179
+	contact_t* ptr;
180
+
181
+	while(*_c) {
182
+		ptr = *_c;
183
+		*_c = (*_c)->next;
184
+		if (ptr->params) {
185
+			free_cparams(&(ptr->params));
186
+		}
187
+		pkg_free(ptr);
188
+	}
189
+}
190
+
191
+
192
+/*
193
+ * Print list of contacts, just for debugging
194
+ */
195
+void print_contacts(contact_t* _c)
196
+{
197
+	contact_t* ptr;
198
+
199
+	ptr = _c;
200
+
201
+	while(ptr) {
202
+		printf("---Contact---\n");
203
+		printf("URI    : \'%.*s\'\n", ptr->uri.len, ptr->uri.s);
204
+		printf("q      : %p\n", ptr->q);
205
+		printf("expires: %p\n", ptr->expires);
206
+		printf("method : %p\n", ptr->method);
207
+		if (ptr->params) {
208
+			print_cparams(ptr->params);
209
+		}
210
+		printf("---/Contact---\n");
211
+		ptr = ptr->next;
212
+	}
213
+}
0 214
new file mode 100644
... ...
@@ -0,0 +1,47 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * Contact datatype
5
+ */
6
+
7
+#ifndef CONTACT_H
8
+#define CONTACT_H
9
+
10
+
11
+#include "cparam.h"    /* cparam_t */
12
+#include "../../str.h"
13
+
14
+
15
+/*
16
+ * Structure representing a Contac HF body
17
+ */
18
+typedef struct contact {
19
+	str uri;                /* contact uri */
20
+	cparam_t* q;            /* q parameter hook */
21
+	cparam_t* expires;      /* expires parameter hook */
22
+	cparam_t* method;       /* method parameter hook */
23
+	cparam_t* params;       /* List of all parameters */
24
+        struct contact* next; /* Next contact in the list */
25
+} contact_t;
26
+
27
+
28
+/*
29
+ * Parse contacts in a Contact HF
30
+ */
31
+int parse_contacts(str* _s, contact_t** _c);
32
+
33
+
34
+/*
35
+ * Free list of contacts
36
+ * _c is head of the list
37
+ */
38
+void free_contacts(contact_t** _c);
39
+
40
+
41
+/*
42
+ * Print list of contacts, just for debugging
43
+ */
44
+void print_contacts(contact_t* _c);
45
+
46
+
47
+#endif /* CONTACT_H */
0 48
new file mode 100644
... ...
@@ -0,0 +1,342 @@
1
+#include "cparam.h"
2
+#include "../../mem/mem.h"
3
+#include <stdio.h>         /* printf */
4
+#include "../../ut.h"      /* q_memchr */
5
+#include <string.h>        /* memset */
6
+#include "../../trim.h"
7
+
8
+
9
+/*
10
+ * Parse quoted string in a parameter body
11
+ * return the string without quotes in _r
12
+ * parameter and update _s to point behind the
13
+ * closing quote
14
+ */
15
+static inline int parse_quoted(str* _s, str* _r)
16
+{
17
+	char* end_quote;
18
+
19
+	     /* The string must have at least
20
+	      * surrounding quotes
21
+	      */
22
+	if (_s->len < 2) {
23
+		return -1;
24
+	}
25
+
26
+	     /* Skip opening quote */
27
+	_s->s++;
28
+	_s->len--;
29
+
30
+
31
+	     /* Find closing quote */
32
+	end_quote = q_memchr(_s->s, '\"', _s->len);
33
+
34
+	     /* Not found, return error */
35
+	if (!end_quote) {
36
+		return -2;
37
+	}
38
+
39
+	     /* Let _r point to the string without
40
+	      * surrounding quotes
41
+	      */
42
+	_r->s = _s->s;
43
+	_r->len = end_quote - _s->s;
44
+
45
+	     /* Update _s parameter to point
46
+	      * behind the closing quote
47
+	      */
48
+	_s->len -= (end_quote - _s->s + 1);
49
+	_s->s = end_quote + 1;
50
+
51
+	     /* Everything went OK */
52
+	return 0;
53
+}
54
+
55
+
56
+/*
57
+ * Parse unquoted token in a parameter body
58
+ * let _r point to the token and update _s
59
+ * to point right behind the token
60
+ */
61
+static inline int parse_token(str* _s, str* _r)
62
+{
63
+	int i;
64
+
65
+	     /* There is nothing to parse,
66
+	      * return error
67
+	      */
68
+	if (_s->len == 0) {
69
+		return -1;
70
+	}
71
+
72
+	     /* Save the begining of the
73
+	      * token in _r->s
74
+	      */
75
+	_r->s = _s->s;
76
+
77
+	     /* Iterate throught the
78
+	      * token body
79
+	      */
80
+	for(i = 0; i < _s->len; i++) {
81
+
82
+		     /* All these characters
83
+		      * mark end of the token
84
+		      */
85
+		switch(_s->s[i]) {
86
+		case ' ':
87
+		case '\t':
88
+		case '\r':
89
+		case '\n':
90
+		case ',':
91
+		case ';':
92
+			     /* So if you find
93
+			      * any of them
94
+			      * stop iterating
95
+			      */
96
+			goto out;
97
+		}
98
+	}
99
+ out:
100
+	if (i == 0) {
101
+		return -1;
102
+        }
103
+
104
+	     /* Save length of the token */
105
+        _r->len = i;
106
+
107
+	     /* Update _s parameter so it points
108
+	      * right behind the end of the token
109
+	      */
110
+	_s->s = _s->s + i;
111
+	_s->len -= i;
112
+
113
+	     /* Everything went OK */
114
+	return 0;
115
+}
116
+
117
+
118
+/*
119
+ * Parse type of a parameter
120
+ */
121
+static inline int parse_param_type(cparam_t* _c)
122
+{
123
+	switch(_c->name.s[0]) {
124
+	case 'q':
125
+	case 'Q':
126
+		if (_c->name.len == 1) {
127
+			_c->type = CP_Q;
128
+		}
129
+		return 0;
130
+		
131
+	case 'e':
132
+	case 'E':
133
+		if ((_c->name.len == 7) &&
134
+		    (!strncasecmp(_c->name.s + 1, "xpires", 6))) {
135
+			_c->type = CP_EXPIRES;
136
+		}
137
+		return 0;
138
+		
139
+	case 'm':
140
+	case 'M':
141
+		if ((_c->name.len == 6) &&
142
+		    (!strncasecmp(_c->name.s + 1, "ethod", 5))) {
143
+			_c->type = CP_METHOD;
144
+		}
145
+		return 0;
146
+	}
147
+	return 0;
148
+}
149
+
150
+
151
+/*
152
+ * Parse body of a parameter. It can be quoted string or
153
+ * a single token.
154
+ */
155
+static inline int parse_body(str* _s, cparam_t* _c)
156
+{
157
+	if (_s->s[0] == '\"') {
158
+		if (parse_quoted(_s, &(_c->body)) < 0) {
159
+			LOG(L_ERR, "parse_body(): Error while parsing quoted string\n");
160
+			return -2;
161
+		}
162
+	} else {
163
+		if (parse_token(_s, &(_c->body)) < 0) {
164
+			LOG(L_ERR, "parse_body(): Error while parsing token\n");
165
+			return -3;
166
+		}
167
+	}
168
+
169
+	return 0;
170
+}
171
+
172
+
173
+/*
174
+ * Parse a parameter name
175
+ */
176
+static inline int parse_param_name(str* _s, cparam_t* _p)
177
+{
178
+	_p->name.s = _s->s;
179
+
180
+	while(_s->len) {
181
+		switch(_s->s[0]) {
182
+		case ' ':
183
+		case '\t':
184
+		case '\r':
185
+		case '\n':
186
+		case ';':
187
+		case ',':
188
+		case '=':
189
+			goto out;
190
+		}
191
+		_s->s++;
192
+		_s->len--;
193
+	}
194
+
195
+ out:
196
+	_p->name.len = _s->s - _p->name.s;
197
+	
198
+	if (parse_param_type(_p) < 0) {
199
+		LOG(L_ERR, "parse_param_name(): Error while parsing type\n");
200
+		return -2;
201
+	}
202
+	
203
+	return 0;
204
+}
205
+
206
+
207
+/*
208
+ * Parse contact parameters
209
+ */
210
+int parse_cparams(str* _s, cparam_t** _p, cparam_t** _q, cparam_t** _e, cparam_t** _m)
211
+{
212
+	cparam_t* c;
213
+
214
+	while(1) {
215
+		c = (cparam_t*)pkg_malloc(sizeof(cparam_t));
216
+		if (c == 0) {
217
+			LOG(L_ERR, "parse_cparams(): No memory left\n");
218
+			goto error;
219
+		}
220
+		memset(c, 0, sizeof(cparam_t));
221
+
222
+		if (parse_param_name(_s, c) < 0) {
223
+			LOG(L_ERR, "parse_cparams(): Error while parsing param name\n");
224
+			goto error;
225
+		}
226
+
227
+		trim_leading(_s);
228
+		
229
+		if (_s->len == 0) { /* The last parameter without body */
230
+			goto ok;
231
+		}
232
+		
233
+		if (_s->s[0] == '=') {
234
+			_s->s++;
235
+			_s->len--;
236
+			trim_leading(_s);
237
+
238
+			if (_s->len == 0) {
239
+				LOG(L_ERR, "parse_cparams(): Body missing\n");
240
+				goto error;
241
+			}
242
+
243
+			if (parse_body(_s, c) < 0) {
244
+				LOG(L_ERR, "parse_cparams(): Error while parsing param body\n");
245
+				goto error;
246
+			}
247
+
248
+			trim_leading(_s);
249
+			if (_s->len == 0) {
250
+				goto ok;
251
+			}
252
+		}
253
+
254
+		if (_s->s[0] == ',') goto ok;
255
+
256
+		if (_s->s[0] != ';') {
257
+			LOG(L_ERR, "parse_cparams(): Invalid character, ; expected\n");
258
+			goto error;
259
+		}
260
+
261
+		_s->s++;
262
+		_s->len--;
263
+		trim_leading(_s);
264
+		
265
+		if (_s->len == 0) {
266
+			LOG(L_ERR, "parse_cparams(): Param name missing after ;\n");
267
+			goto error;
268
+		}
269
+
270
+		c->next = *_p;
271
+		*_p = c;
272
+		switch(c->type) {    /* Update hook pointers */
273
+		case CP_Q:       *_q = c; break;
274
+		case CP_EXPIRES: *_e = c; break;
275
+		case CP_METHOD:  *_m = c; break;
276
+		case CP_OTHER:            break;
277
+		}		
278
+	}
279
+
280
+ error:
281
+	if (c) pkg_free(c);
282
+	free_cparams(_p);
283
+	return -1;
284
+
285
+ ok:
286
+	c->next = *_p;
287
+	*_p = c;
288
+	switch(c->type) {    /* Update hook pointers */
289
+	case CP_Q:       *_q = c; break;
290
+	case CP_EXPIRES: *_e = c; break;
291
+	case CP_METHOD:  *_m = c; break;
292
+	case CP_OTHER:          ; break;
293
+	}
294
+	return 0;
295
+}
296
+
297
+
298
+/*
299
+ * Free the whole contact parameter list
300
+ */
301
+void free_cparams(cparam_t** _p)
302
+{
303
+	cparam_t* ptr;
304
+
305
+	while(*_p) {
306
+		ptr = *_p;
307
+		pkg_free(ptr);
308
+		*_p = (*_p)->next;
309
+	}
310
+}
311
+
312
+
313
+/*
314
+ * Print contact parameter list
315
+ */
316
+void print_cparams(cparam_t* _p)
317
+{
318
+	cparam_t* ptr;
319
+	char* type;
320
+
321
+	ptr = _p;
322
+
323
+	while(ptr) {
324
+		printf("...cparam(%p)...\n", ptr);
325
+
326
+		switch(ptr->type) {
327
+		case CP_OTHER:   type = "CP_OTHER";   break;
328
+		case CP_Q:       type = "CP_Q";       break;
329
+		case CP_EXPIRES: type = "CP_EXPIRES"; break;
330
+		case CP_METHOD:  type = "CP_METHOD";  break;
331
+		default:         type = "UNKNOWN";    break;
332
+		}
333
+
334
+		printf("type: %s\n", type);
335
+		printf("name: \'%.*s\'\n", ptr->name.len, ptr->name.s);
336
+		printf("body: \'%.*s\'\n", ptr->body.len, ptr->body.s);
337
+
338
+		printf(".../cparam...\n");
339
+
340
+		ptr = ptr->next;
341
+	}
342
+}
0 343
new file mode 100644
... ...
@@ -0,0 +1,52 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * Contact parameter datatype
5
+ */
6
+
7
+#ifndef CPARAM_H
8
+#define CPARAM_H
9
+
10
+#include "../../str.h"
11
+
12
+/*
13
+ * Supported types of contact parameters
14
+ */
15
+typedef enum cptype {
16
+	CP_OTHER = 0,  /* Unknown parameter */
17
+	CP_Q,          /* Q parameter */
18
+	CP_EXPIRES,    /* Expires parameter */
19
+	CP_METHOD      /* Method parameter */
20
+} cptype_t;
21
+
22
+
23
+/*
24
+ * Structure representing a contact
25
+ */
26
+typedef struct cparam {
27
+	cptype_t type;       /* Type of the parameter */
28
+	str name;            /* Parameter name */
29
+	str body;            /* Parameter body */
30
+	struct cparam* next; /* Next parameter in the list */
31
+} cparam_t;
32
+
33
+
34
+/*
35
+ * Parse contact parameters
36
+ */
37
+int parse_cparams(str* _s, cparam_t** _p, cparam_t** _q, cparam_t** _e, cparam_t** _m);
38
+
39
+
40
+/*
41
+ * Free the whole contact parameter list
42
+ */
43
+void free_cparams(cparam_t** _p);
44
+
45
+
46
+/*
47
+ * Print contact parameter list
48
+ */
49
+void print_cparams(cparam_t* _p);
50
+
51
+
52
+#endif /* CPARAM_H */
0 53
new file mode 100644
... ...
@@ -0,0 +1,96 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * Contact header field body parser
5
+ */
6
+
7
+#include "parse_contact.h"
8
+#include "../hf.h"     
9
+#include "../../mem/mem.h"   /* pkg_malloc, pkg_free */
10
+#include "../../dprint.h"
11
+#include <stdio.h>           /* printf */
12
+#include "../../trim.h"      /* trim_leading */
13
+#include <string.h>          /* memset */
14
+
15
+
16
+static inline int contact_parser(char* _s, int _l, contact_body_t* _c)
17
+{
18
+	str tmp;
19
+
20
+	tmp.s = _s;
21
+	tmp.len = _l;
22
+
23
+	trim_leading(&tmp);
24
+
25
+	if (tmp.len == 0) {
26
+		LOG(L_ERR, "contact_parser(): Empty body\n");
27
+		return -1;
28
+	}
29
+
30
+	if (tmp.s[0] == '*') {
31
+		_c->star = 1;
32
+	} else {
33
+		if (parse_contacts(&tmp, &(_c->contacts)) < 0) {
34
+			LOG(L_ERR, "contact_parser(): Error while parsing contacts\n");
35
+			return -2;
36
+		}
37
+	}
38
+
39
+	return 0;
40
+}
41
+
42
+
43
+/*
44
+ * Parse contact header field body
45
+ */
46
+int parse_contact(struct hdr_field* _h)
47
+{
48
+	contact_body_t* b;
49
+
50
+	if (_h->parsed != 0) {
51
+		return 0;  /* Already parsed */
52
+	}
53
+
54
+	b = (contact_body_t*)pkg_malloc(sizeof(contact_body_t));
55
+	if (b == 0) {
56
+		LOG(L_ERR, "parse_contact(): No memory left\n");
57
+		return -1;
58
+	}
59
+
60
+	memset(b, 0, sizeof(contact_body_t));
61
+
62
+	if (contact_parser(_h->body.s, _h->body.len, b) < 0) {
63
+		LOG(L_ERR, "parse_contact(): Error while parsing\n");
64
+		pkg_free(b);
65
+		return -2;
66
+	}
67
+
68
+	_h->parsed = (void*)b;
69
+	return 0;
70
+}
71
+
72
+
73
+/*
74
+ * Free all memory
75
+ */
76
+void free_contact(contact_body_t** _c)
77
+{
78
+	if ((*_c)->contacts) {
79
+		free_contacts(&((*_c)->contacts));
80
+	}
81
+	
82
+	pkg_free(*_c);
83
+	*_c = 0;
84
+}
85
+
86
+
87
+/*
88
+ * Print structure, for debugging only
89
+ */
90
+void print_contact(contact_body_t* _c)
91
+{
92
+	printf("===Contact body===\n");
93
+	printf("star: %d\n", _c->star);
94
+	print_contacts(_c->contacts);
95
+	printf("===/Contact body===\n");
96
+}
0 97
new file mode 100644
... ...
@@ -0,0 +1,39 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * Contact header field body parser
5
+ */
6
+
7
+#ifndef PARSE_CONTACT_H
8
+#define PARSE_CONTACT_H
9
+
10
+#include "../hf.h"
11
+#include "../../str.h"
12
+#include "contact.h"
13
+
14
+
15
+typedef struct contact_body {
16
+	unsigned char star;    /* Star contact */
17
+	contact_t* contacts;   /* List of contacts */
18
+} contact_body_t;
19
+
20
+
21
+/*
22
+ * Parse contact header field body
23
+ */
24
+int parse_contact(struct hdr_field* _h);
25
+
26
+
27
+/*
28
+ * Free all memory
29
+ */
30
+void free_contact(contact_body_t** _c);
31
+
32
+
33
+/*
34
+ * Print structure, for debugging only
35
+ */
36
+void print_contact(contact_body_t* _c);
37
+
38
+
39
+#endif /* PARSE_CONTACT_H */