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