blob: b90725d4e45a0f49c675f5f6776b8c29edd200c0 [file] [log] [blame]
Alexandre Lision67916dd2014-01-24 13:33:04 -05001/* $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
26struct 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
62static pj_str_t PRESENCE = { "presence", 8 };
63static pj_str_t ENTITY = { "entity", 6};
64static pj_str_t TUPLE = { "tuple", 5 };
65static pj_str_t ID = { "id", 2 };
66static pj_str_t NOTE = { "note", 4 };
67static pj_str_t STATUS = { "status", 6 };
68static pj_str_t CONTACT = { "contact", 7 };
69static pj_str_t PRIORITY = { "priority", 8 };
70static pj_str_t TIMESTAMP = { "timestamp", 9 };
71static pj_str_t BASIC = { "basic", 5 };
72static pj_str_t OPEN = { "open", 4 };
73static pj_str_t CLOSED = { "closed", 6 };
74static pj_str_t EMPTY_STRING = { NULL, 0 };
75
76static pj_str_t XMLNS = { "xmlns", 5 };
77static pj_str_t PIDF_XMLNS = { "urn:ietf:params:xml:ns:pidf", 27 };
78
79static 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
89static 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 */
99PJ_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
111PJ_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
120PJ_DEF(pjpidf_tuple*) pjpidf_pres_get_first_tuple(pjpidf_pres *pres)
121{
122 return pj_xml_find_node(pres, &TUPLE);
123}
124
125PJ_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
131static 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
136PJ_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
141PJ_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
147PJ_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
156PJ_DEF(pjpidf_note*) pjpidf_pres_get_first_note(pjpidf_pres *pres)
157{
158 return pj_xml_find_node( pres, &NOTE);
159}
160
161PJ_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 */
168PJ_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
182PJ_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
189PJ_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
197PJ_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
205PJ_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
213PJ_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
226PJ_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
246PJ_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
260PJ_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
269PJ_DEF(pjpidf_note*) pjpidf_tuple_get_first_note(pjpidf_tuple *t)
270{
271 return pj_xml_find_node(t, &NOTE);
272}
273
274PJ_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
280PJ_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
286PJ_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
300PJ_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 */
314PJ_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
324PJ_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
332PJ_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
339PJ_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
346PJ_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
361PJ_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