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