1 /* $Id$ */
2 /*
3  * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4  * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include <pjsip-simple/pidf.h>
21 #include <pj/string.h>
22 #include <pj/pool.h>
23 #include <pj/assert.h>
24 
25 
26 struct pjpidf_op_desc pjpidf_op =
27 {
28     {
29 	&pjpidf_pres_construct,
30 	&pjpidf_pres_add_tuple,
31 	&pjpidf_pres_get_first_tuple,
32 	&pjpidf_pres_get_next_tuple,
33 	&pjpidf_pres_find_tuple,
34 	&pjpidf_pres_remove_tuple,
35 	&pjpidf_pres_add_note,
36 	&pjpidf_pres_get_first_note,
37 	&pjpidf_pres_get_next_note
38     },
39     {
40 	&pjpidf_tuple_construct,
41 	&pjpidf_tuple_get_id,
42 	&pjpidf_tuple_set_id,
43 	&pjpidf_tuple_get_status,
44 	&pjpidf_tuple_get_contact,
45 	&pjpidf_tuple_set_contact,
46 	&pjpidf_tuple_set_contact_prio,
47 	&pjpidf_tuple_get_contact_prio,
48 	&pjpidf_tuple_add_note,
49 	&pjpidf_tuple_get_first_note,
50 	&pjpidf_tuple_get_next_note,
51 	&pjpidf_tuple_get_timestamp,
52 	&pjpidf_tuple_set_timestamp,
53 	&pjpidf_tuple_set_timestamp_np
54     },
55     {
56 	&pjpidf_status_construct,
57 	&pjpidf_status_is_basic_open,
58 	&pjpidf_status_set_basic_open
59     }
60 };
61 
62 static pj_str_t PRESENCE = { "presence", 8 };
63 static pj_str_t ENTITY = { "entity", 6};
64 static pj_str_t	TUPLE = { "tuple", 5 };
65 static pj_str_t ID = { "id", 2 };
66 static pj_str_t NOTE = { "note", 4 };
67 static pj_str_t STATUS = { "status", 6 };
68 static pj_str_t CONTACT = { "contact", 7 };
69 static pj_str_t PRIORITY = { "priority", 8 };
70 static pj_str_t TIMESTAMP = { "timestamp", 9 };
71 static pj_str_t BASIC = { "basic", 5 };
72 static pj_str_t OPEN = { "open", 4 };
73 static pj_str_t CLOSED = { "closed", 6 };
74 static pj_str_t EMPTY_STRING = { NULL, 0 };
75 
76 static pj_str_t XMLNS = { "xmlns", 5 };
77 static pj_str_t PIDF_XMLNS = { "urn:ietf:params:xml:ns:pidf", 27 };
78 
xml_init_node(pj_pool_t * pool,pj_xml_node * node,pj_str_t * name,const pj_str_t * value)79 static void xml_init_node(pj_pool_t *pool, pj_xml_node *node,
80 			  pj_str_t *name, const pj_str_t *value)
81 {
82     pj_list_init(&node->attr_head);
83     pj_list_init(&node->node_head);
84     node->name = *name;
85     if (value) pj_strdup(pool, &node->content, value);
86     else node->content.ptr=NULL, node->content.slen=0;
87 }
88 
xml_create_attr(pj_pool_t * pool,pj_str_t * name,const pj_str_t * value)89 static pj_xml_attr* xml_create_attr(pj_pool_t *pool, pj_str_t *name,
90 				    const pj_str_t *value)
91 {
92     pj_xml_attr *attr = PJ_POOL_ALLOC_T(pool, pj_xml_attr);
93     attr->name = *name;
94     pj_strdup(pool, &attr->value, value);
95     return attr;
96 }
97 
98 /* Presence */
pjpidf_pres_construct(pj_pool_t * pool,pjpidf_pres * pres,const pj_str_t * entity)99 PJ_DEF(void) pjpidf_pres_construct(pj_pool_t *pool, pjpidf_pres *pres,
100 				   const pj_str_t *entity)
101 {
102     pj_xml_attr *attr;
103 
104     xml_init_node(pool, pres, &PRESENCE, NULL);
105     attr = xml_create_attr(pool, &ENTITY, entity);
106     pj_xml_add_attr(pres, attr);
107     attr = xml_create_attr(pool, &XMLNS, &PIDF_XMLNS);
108     pj_xml_add_attr(pres, attr);
109 }
110 
pjpidf_pres_add_tuple(pj_pool_t * pool,pjpidf_pres * pres,const pj_str_t * id)111 PJ_DEF(pjpidf_tuple*) pjpidf_pres_add_tuple(pj_pool_t *pool, pjpidf_pres *pres,
112 					    const pj_str_t *id)
113 {
114     pjpidf_tuple *t = PJ_POOL_ALLOC_T(pool, pjpidf_tuple);
115     pjpidf_tuple_construct(pool, t, id);
116     pj_xml_add_node(pres, t);
117     return t;
118 }
119 
pjpidf_pres_get_first_tuple(pjpidf_pres * pres)120 PJ_DEF(pjpidf_tuple*) pjpidf_pres_get_first_tuple(pjpidf_pres *pres)
121 {
122     return pj_xml_find_node(pres, &TUPLE);
123 }
124 
pjpidf_pres_get_next_tuple(pjpidf_pres * pres,pjpidf_tuple * tuple)125 PJ_DEF(pjpidf_tuple*) pjpidf_pres_get_next_tuple(pjpidf_pres *pres,
126 						 pjpidf_tuple *tuple)
127 {
128     return pj_xml_find_next_node(pres, tuple, &TUPLE);
129 }
130 
find_tuple_by_id(const pj_xml_node * node,const void * id)131 static pj_bool_t find_tuple_by_id(const pj_xml_node *node, const void *id)
132 {
133     return pj_xml_find_attr(node, &ID, (const pj_str_t*)id) != NULL;
134 }
135 
pjpidf_pres_find_tuple(pjpidf_pres * pres,const pj_str_t * id)136 PJ_DEF(pjpidf_tuple*) pjpidf_pres_find_tuple(pjpidf_pres *pres, const pj_str_t *id)
137 {
138     return pj_xml_find(pres, &TUPLE, id, &find_tuple_by_id);
139 }
140 
pjpidf_pres_remove_tuple(pjpidf_pres * pres,pjpidf_tuple * t)141 PJ_DEF(void) pjpidf_pres_remove_tuple(pjpidf_pres *pres, pjpidf_tuple *t)
142 {
143     PJ_UNUSED_ARG(pres);
144     pj_list_erase(t);
145 }
146 
pjpidf_pres_add_note(pj_pool_t * pool,pjpidf_pres * pres,const pj_str_t * text)147 PJ_DEF(pjpidf_note*) pjpidf_pres_add_note(pj_pool_t *pool, pjpidf_pres *pres,
148 					  const pj_str_t *text)
149 {
150     pjpidf_note *note = PJ_POOL_ALLOC_T(pool, pjpidf_note);
151     xml_init_node(pool, note, &NOTE, text);
152     pj_xml_add_node(pres, note);
153     return note;
154 }
155 
pjpidf_pres_get_first_note(pjpidf_pres * pres)156 PJ_DEF(pjpidf_note*) pjpidf_pres_get_first_note(pjpidf_pres *pres)
157 {
158     return pj_xml_find_node( pres, &NOTE);
159 }
160 
pjpidf_pres_get_next_note(pjpidf_pres * t,pjpidf_note * note)161 PJ_DEF(pjpidf_note*) pjpidf_pres_get_next_note(pjpidf_pres *t, pjpidf_note *note)
162 {
163     return pj_xml_find_next_node(t, note, &NOTE);
164 }
165 
166 
167 /* Tuple */
pjpidf_tuple_construct(pj_pool_t * pool,pjpidf_tuple * t,const pj_str_t * id)168 PJ_DEF(void) pjpidf_tuple_construct(pj_pool_t *pool, pjpidf_tuple *t,
169 				    const pj_str_t *id)
170 {
171     pj_xml_attr *attr;
172     pjpidf_status *st;
173 
174     xml_init_node(pool, t, &TUPLE, NULL);
175     attr = xml_create_attr(pool, &ID, id);
176     pj_xml_add_attr(t, attr);
177     st = PJ_POOL_ALLOC_T(pool, pjpidf_status);
178     pjpidf_status_construct(pool, st);
179     pj_xml_add_node(t, st);
180 }
181 
pjpidf_tuple_get_id(const pjpidf_tuple * t)182 PJ_DEF(const pj_str_t*) pjpidf_tuple_get_id(const pjpidf_tuple *t)
183 {
184     const pj_xml_attr *attr = pj_xml_find_attr((pj_xml_node*)t, &ID, NULL);
185     pj_assert(attr);
186     return &attr->value;
187 }
188 
pjpidf_tuple_set_id(pj_pool_t * pool,pjpidf_tuple * t,const pj_str_t * id)189 PJ_DEF(void) pjpidf_tuple_set_id(pj_pool_t *pool, pjpidf_tuple *t, const pj_str_t *id)
190 {
191     pj_xml_attr *attr = pj_xml_find_attr(t, &ID, NULL);
192     pj_assert(attr);
193     pj_strdup(pool, &attr->value, id);
194 }
195 
196 
pjpidf_tuple_get_status(pjpidf_tuple * t)197 PJ_DEF(pjpidf_status*) pjpidf_tuple_get_status(pjpidf_tuple *t)
198 {
199     pjpidf_status *st = (pjpidf_status*)pj_xml_find_node(t, &STATUS);
200     pj_assert(st);
201     return st;
202 }
203 
204 
pjpidf_tuple_get_contact(const pjpidf_tuple * t)205 PJ_DEF(const pj_str_t*) pjpidf_tuple_get_contact(const pjpidf_tuple *t)
206 {
207     pj_xml_node *node = pj_xml_find_node((pj_xml_node*)t, &CONTACT);
208     if (!node)
209 	return &EMPTY_STRING;
210     return &node->content;
211 }
212 
pjpidf_tuple_set_contact(pj_pool_t * pool,pjpidf_tuple * t,const pj_str_t * contact)213 PJ_DEF(void) pjpidf_tuple_set_contact(pj_pool_t *pool, pjpidf_tuple *t,
214 				      const pj_str_t *contact)
215 {
216     pj_xml_node *node = pj_xml_find_node(t, &CONTACT);
217     if (!node) {
218 	node = PJ_POOL_ALLOC_T(pool, pj_xml_node);
219 	xml_init_node(pool, node, &CONTACT, contact);
220 	pj_xml_add_node(t, node);
221     } else {
222 	pj_strdup(pool, &node->content, contact);
223     }
224 }
225 
pjpidf_tuple_set_contact_prio(pj_pool_t * pool,pjpidf_tuple * t,const pj_str_t * prio)226 PJ_DEF(void) pjpidf_tuple_set_contact_prio(pj_pool_t *pool, pjpidf_tuple *t,
227 					   const pj_str_t *prio)
228 {
229     pj_xml_node *node = pj_xml_find_node(t, &CONTACT);
230     pj_xml_attr *attr;
231 
232     if (!node) {
233 	node = PJ_POOL_ALLOC_T(pool, pj_xml_node);
234 	xml_init_node(pool, node, &CONTACT, NULL);
235 	pj_xml_add_node(t, node);
236     }
237     attr = pj_xml_find_attr(node, &PRIORITY, NULL);
238     if (!attr) {
239 	attr = xml_create_attr(pool, &PRIORITY, prio);
240 	pj_xml_add_attr(node, attr);
241     } else {
242 	pj_strdup(pool, &attr->value, prio);
243     }
244 }
245 
pjpidf_tuple_get_contact_prio(const pjpidf_tuple * t)246 PJ_DEF(const pj_str_t*) pjpidf_tuple_get_contact_prio(const pjpidf_tuple *t)
247 {
248     pj_xml_node *node = pj_xml_find_node((pj_xml_node*)t, &CONTACT);
249     pj_xml_attr *attr;
250 
251     if (!node)
252 	return &EMPTY_STRING;
253     attr = pj_xml_find_attr(node, &PRIORITY, NULL);
254     if (!attr)
255 	return &EMPTY_STRING;
256     return &attr->value;
257 }
258 
259 
pjpidf_tuple_add_note(pj_pool_t * pool,pjpidf_tuple * t,const pj_str_t * text)260 PJ_DEF(pjpidf_note*) pjpidf_tuple_add_note(pj_pool_t *pool, pjpidf_tuple *t,
261 					   const pj_str_t *text)
262 {
263     pjpidf_note *note = PJ_POOL_ALLOC_T(pool, pjpidf_note);
264     xml_init_node(pool, note, &NOTE, text);
265     pj_xml_add_node(t, note);
266     return note;
267 }
268 
pjpidf_tuple_get_first_note(pjpidf_tuple * t)269 PJ_DEF(pjpidf_note*) pjpidf_tuple_get_first_note(pjpidf_tuple *t)
270 {
271     return pj_xml_find_node(t, &NOTE);
272 }
273 
pjpidf_tuple_get_next_note(pjpidf_tuple * t,pjpidf_note * n)274 PJ_DEF(pjpidf_note*) pjpidf_tuple_get_next_note(pjpidf_tuple *t, pjpidf_note *n)
275 {
276     return pj_xml_find_next_node(t, n, &NOTE);
277 }
278 
279 
pjpidf_tuple_get_timestamp(const pjpidf_tuple * t)280 PJ_DEF(const pj_str_t*) pjpidf_tuple_get_timestamp(const pjpidf_tuple *t)
281 {
282     pj_xml_node *node = pj_xml_find_node((pj_xml_node*)t, &TIMESTAMP);
283     return node ? &node->content : &EMPTY_STRING;
284 }
285 
pjpidf_tuple_set_timestamp(pj_pool_t * pool,pjpidf_tuple * t,const pj_str_t * ts)286 PJ_DEF(void) pjpidf_tuple_set_timestamp(pj_pool_t *pool, pjpidf_tuple *t,
287 					const pj_str_t *ts)
288 {
289     pj_xml_node *node = pj_xml_find_node(t, &TIMESTAMP);
290     if (!node) {
291 	node = PJ_POOL_ALLOC_T(pool, pj_xml_node);
292 	xml_init_node(pool, node, &TIMESTAMP, ts);
293 	pj_xml_add_node(t, node);
294     } else {
295 	pj_strdup(pool, &node->content, ts);
296     }
297 }
298 
299 
pjpidf_tuple_set_timestamp_np(pj_pool_t * pool,pjpidf_tuple * t,pj_str_t * ts)300 PJ_DEF(void) pjpidf_tuple_set_timestamp_np(pj_pool_t *pool, pjpidf_tuple *t,
301 					   pj_str_t *ts)
302 {
303     pj_xml_node *node = pj_xml_find_node(t, &TIMESTAMP);
304     if (!node) {
305 	node = PJ_POOL_ALLOC_T(pool, pj_xml_node);
306 	xml_init_node(pool, node, &TIMESTAMP, ts);
307     } else {
308 	node->content = *ts;
309     }
310 }
311 
312 
313 /* Status */
pjpidf_status_construct(pj_pool_t * pool,pjpidf_status * st)314 PJ_DEF(void) pjpidf_status_construct(pj_pool_t *pool, pjpidf_status *st)
315 {
316     pj_xml_node *node;
317 
318     xml_init_node(pool, st, &STATUS, NULL);
319     node = PJ_POOL_ALLOC_T(pool, pj_xml_node);
320     xml_init_node(pool, node, &BASIC, &CLOSED);
321     pj_xml_add_node(st, node);
322 }
323 
pjpidf_status_is_basic_open(const pjpidf_status * st)324 PJ_DEF(pj_bool_t) pjpidf_status_is_basic_open(const pjpidf_status *st)
325 {
326     pj_xml_node *node = pj_xml_find_node((pj_xml_node*)st, &BASIC);
327     if (!node)
328 	return PJ_FALSE;
329     return pj_stricmp(&node->content, &OPEN)==0;
330 }
331 
pjpidf_status_set_basic_open(pjpidf_status * st,pj_bool_t open)332 PJ_DEF(void) pjpidf_status_set_basic_open(pjpidf_status *st, pj_bool_t open)
333 {
334     pj_xml_node *node = pj_xml_find_node(st, &BASIC);
335     if (node)
336 	node->content = open ? OPEN : CLOSED;
337 }
338 
pjpidf_create(pj_pool_t * pool,const pj_str_t * entity)339 PJ_DEF(pjpidf_pres*) pjpidf_create(pj_pool_t *pool, const pj_str_t *entity)
340 {
341     pjpidf_pres *pres = PJ_POOL_ALLOC_T(pool, pjpidf_pres);
342     pjpidf_pres_construct(pool, pres, entity);
343     return pres;
344 }
345 
pjpidf_parse(pj_pool_t * pool,char * text,int len)346 PJ_DEF(pjpidf_pres*) pjpidf_parse(pj_pool_t *pool, char *text, int len)
347 {
348     pjpidf_pres *pres = pj_xml_parse(pool, text, len);
349     if (pres && pres->name.slen >= 8) {
350 	pj_str_t name;
351 
352 	name.ptr = pres->name.ptr + (pres->name.slen - 8);
353 	name.slen = 8;
354 
355 	if (pj_stricmp(&name, &PRESENCE) == 0)
356 	    return pres;
357     }
358     return NULL;
359 }
360 
pjpidf_print(const pjpidf_pres * pres,char * buf,int len)361 PJ_DEF(int) pjpidf_print(const pjpidf_pres* pres, char *buf, int len)
362 {
363     return pj_xml_print(pres, buf, len, PJ_TRUE);
364 }
365 
366