1 /*
2  * Contact header field body parser
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *
6  * This file is part of ser, a free SIP server.
7  *
8  * ser 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
12  *
13  * For a license to use the ser software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * ser is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
26  *
27  */
28 
29 #include <string.h>          /* memset */
30 #include "../hf.h"
31 #include "../../mem/mem.h"   /* pkg_malloc, pkg_free */
32 #include "../../dprint.h"
33 #include "../../trim.h"      /* trim_leading */
34 #include "parse_contact.h"
35 
36 
37 
contact_parser(char * _s,int _l,contact_body_t * _c)38 static inline int contact_parser(char* _s, int _l, contact_body_t* _c)
39 {
40 	str tmp;
41 
42 	tmp.s = _s;
43 	tmp.len = _l;
44 
45 	trim_leading(&tmp);
46 
47 	if (tmp.len == 0) {
48 		LM_ERR("empty body\n");
49 		return -1;
50 	}
51 
52 	if (tmp.s[0] == '*') {
53 		_c->star = 1;
54 	} else {
55 		if (parse_contacts(&tmp, &(_c->contacts)) < 0) {
56 			LM_ERR("error while parsing contacts\n");
57 			return -2;
58 		}
59 	}
60 
61 	return 0;
62 }
63 
64 
65 /*
66  * Parse contact header field body
67  */
parse_contact(struct hdr_field * _h)68 int parse_contact(struct hdr_field* _h)
69 {
70 	contact_body_t* b;
71 
72 	if (_h->parsed != 0) {
73 		return 0;  /* Already parsed */
74 	}
75 
76 	b = (contact_body_t*)pkg_malloc(sizeof(contact_body_t));
77 	if (b == 0) {
78 		PKG_MEM_ERROR;
79 		return -1;
80 	}
81 
82 	memset(b, 0, sizeof(contact_body_t));
83 
84 	if (contact_parser(_h->body.s, _h->body.len, b) < 0) {
85 		LM_ERR("error while parsing\n");
86 		pkg_free(b);
87 		return -2;
88 	}
89 
90 	_h->parsed = (void*)b;
91 	return 0;
92 }
93 
94 
95 /*
96  * Free all memory
97  */
free_contact(contact_body_t ** _c)98 void free_contact(contact_body_t** _c)
99 {
100 	if(*_c==NULL)
101 		return;
102 	if ((*_c)->contacts) {
103 		free_contacts(&((*_c)->contacts));
104 	}
105 
106 	pkg_free(*_c);
107 	*_c = 0;
108 }
109 
110 
111 /*
112  * Print structure, for debugging only
113  */
print_contact(FILE * _o,contact_body_t * _c)114 void print_contact(FILE* _o, contact_body_t* _c)
115 {
116 	fprintf(_o, "===Contact body===\n");
117 	fprintf(_o, "star: %d\n", _c->star);
118 	print_contacts(_o, _c->contacts);
119 	fprintf(_o, "===/Contact body===\n");
120 }
121 
122 
123 /*
124  * Contact header field iterator, returns next contact if any, it doesn't
125  * parse message header if not absolutely necessary
126  */
contact_iterator(contact_t ** c,struct sip_msg * msg,contact_t * prev)127 int contact_iterator(contact_t** c, struct sip_msg* msg, contact_t* prev)
128 {
129 	static struct hdr_field* hdr = 0;
130 	struct hdr_field* last;
131 	contact_body_t* cb;
132 
133 	if (!msg) {
134 		LM_ERR("invalid parameter value\n");
135 		return -1;
136 	}
137 
138 	if (!prev) {
139 		/* No pointer to previous contact given, find topmost
140 		 * contact and return pointer to the first contact
141 		 * inside that header field
142 		 */
143 		hdr = msg->contact;
144 		if (!hdr) {
145 			if (parse_headers(msg, HDR_CONTACT_F, 0) == -1) {
146 				LM_ERR("error while parsing headers\n");
147 				return -1;
148 			}
149 
150 			hdr = msg->contact;
151 		}
152 
153 		if (hdr) {
154 			if (parse_contact(hdr) < 0) {
155 				LM_ERR("error while parsing Contact\n");
156 				return -1;
157 			}
158 		} else {
159 			*c = 0;
160 			return 1;
161 		}
162 
163 		cb = (contact_body_t*)hdr->parsed;
164 		*c = cb->contacts;
165 		return 0;
166 	} else {
167 		/* Check if there is another contact in the
168 		 * same header field and if so then return it
169 		 */
170 		if (prev->next) {
171 			*c = prev->next;
172 			return 0;
173 		}
174 
175 		if(hdr==NULL) {
176 			LM_ERR("contact iterator not initialized\n");
177 			return -1;
178 		}
179 
180 		/* Try to find and parse another Contact
181 		 * header field
182 		 */
183 		last = hdr;
184 		hdr = hdr->next;
185 
186 		/* Search another already parsed Contact
187 		 * header field
188 		 */
189 		while(hdr && hdr->type != HDR_CONTACT_T) {
190 			hdr = hdr->next;
191 		}
192 
193 		if (!hdr) {
194 			/* Look for another Contact HF in unparsed
195 			 * part of the message header
196 			 */
197 			if (parse_headers(msg, HDR_CONTACT_F, 1) == -1) {
198 				LM_ERR("error while parsing message header\n");
199 				return -1;
200 			}
201 
202 			/* Check if last found header field is Contact
203 			 * and if it is not the same header field as the
204 			 * previous Contact HF (that indicates that the previous
205 			 * one was the last header field in the header)
206 			 */
207 			if ((msg->last_header->type == HDR_CONTACT_T) &&
208 					(msg->last_header != last)) {
209 				hdr = msg->last_header;
210 			} else {
211 				*c = 0;
212 				return 1;
213 			}
214 		}
215 
216 		if (parse_contact(hdr) < 0) {
217 			LM_ERR("error while parsing Contact HF body\n");
218 			return -1;
219 		}
220 
221 		/* And return first contact within that
222 		 * header field
223 		 */
224 		cb = (contact_body_t*)hdr->parsed;
225 		*c = cb->contacts;
226 		return 0;
227 	}
228 }
229