resource_list.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. /*
  2. * Copyright (C) 2005 iptelorg GmbH
  3. *
  4. * This file is part of ser, a free SIP server.
  5. *
  6. * ser 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. * For a license to use the ser software under conditions
  12. * other than those described here, or to purchase support for this
  13. * software, please contact iptel.org by e-mail at the following addresses:
  14. * [email protected]
  15. *
  16. * ser is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  24. */
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <time.h>
  29. #include <cds/dstring.h>
  30. #include <xcap/xcap_client.h>
  31. #include <xcap/resource_list.h>
  32. #include <xcap/resource_lists_parser.h>
  33. #include <xcap/rls_services_parser.h>
  34. #include <xcap/xcap_result_codes.h>
  35. #include <libxml/parser.h>
  36. #include <cds/logger.h>
  37. #define STR_OK(s) (s)?(s):""
  38. typedef struct _traversed_list_t {
  39. struct _traversed_list_t *next;
  40. char *uri;
  41. } traversed_list_t;
  42. typedef struct {
  43. const str_t *xcap_root;
  44. xcap_query_params_t *xcap_params;
  45. traversed_list_t *traversed;
  46. traversed_list_t *traversed_last;
  47. flat_list_t *flat;
  48. flat_list_t *flat_last;
  49. } process_params_t;
  50. void canonicalize_uri(const str_t *uri, str_t *dst)
  51. {
  52. /* TODO: do the operation according to draft-ietf-simple-xcap-list-usage-05.txt */
  53. if (!dst) return;
  54. if (!uri) {
  55. dst->len = 0;
  56. dst->s = NULL;
  57. return;
  58. }
  59. if (uri->len > 0) {
  60. dst->s = (char*)cds_malloc(uri->len);
  61. if (!dst->s) dst->len = 0;
  62. else {
  63. memcpy(dst->s, uri->s, uri->len);
  64. dst->len = uri->len;
  65. }
  66. }
  67. else {
  68. dst->len = 0;
  69. dst->s = NULL;
  70. }
  71. /* DEBUG_LOG("canonicalized uri: \'%.*s\'\n", dst->len, dst->s); */
  72. }
  73. char *xcap_uri_for_rls_resource(const str_t *xcap_root, const str_t *uri)
  74. {
  75. dstring_t s;
  76. int l;
  77. str_t c_uri;
  78. char *dst = NULL;
  79. if (!xcap_root) return NULL;
  80. dstr_init(&s, 2 * xcap_root->len + 32);
  81. dstr_append_str(&s, xcap_root);
  82. if (xcap_root->s[xcap_root->len - 1] != '/') dstr_append(&s, "/", 1);
  83. dstr_append_zt(&s, "rls-services/global/index/~~/rls-services/service[@uri=%22");
  84. canonicalize_uri(uri, &c_uri);
  85. dstr_append_str(&s, &c_uri);
  86. if (c_uri.s) cds_free(c_uri.s);
  87. dstr_append_zt(&s, "%22]");
  88. l = dstr_get_data_length(&s);
  89. if (l > 0) {
  90. dst = (char *)cds_malloc(l + 1);
  91. if (dst) {
  92. dstr_get_data(&s, dst);
  93. dst[l] = 0;
  94. }
  95. }
  96. dstr_destroy(&s);
  97. return dst;
  98. }
  99. char *xcap_uri_for_rls_services(const str_t *xcap_root)
  100. {
  101. dstring_t s;
  102. int l;
  103. char *dst = NULL;
  104. if (!xcap_root) return NULL;
  105. dstr_init(&s, 2 * xcap_root->len + 32);
  106. dstr_append_str(&s, xcap_root);
  107. if (xcap_root->s[xcap_root->len - 1] != '/') dstr_append(&s, "/", 1);
  108. dstr_append_zt(&s, "rls-services/global/index");
  109. l = dstr_get_data_length(&s);
  110. if (l > 0) {
  111. dst = (char *)cds_malloc(l + 1);
  112. if (dst) {
  113. dstr_get_data(&s, dst);
  114. dst[l] = 0;
  115. }
  116. }
  117. dstr_destroy(&s);
  118. return dst;
  119. }
  120. void free_flat_list(flat_list_t *list)
  121. {
  122. flat_list_t *f, *e;
  123. e = list;
  124. while (e) {
  125. f = e->next;
  126. if (e->uri) cds_free(e->uri);
  127. free_display_names(e->names);
  128. cds_free(e);
  129. e = f;
  130. }
  131. }
  132. void free_traversed_list(traversed_list_t *list)
  133. {
  134. traversed_list_t *f, *e;
  135. e = list;
  136. while (e) {
  137. f = e->next;
  138. if (e->uri) cds_free(e->uri);
  139. cds_free(e);
  140. e = f;
  141. }
  142. }
  143. /* ------- helper functions (doing flat list) ------- */
  144. static char *relative2absolute_uri(const str_t *xcap_root, const char *relative)
  145. {
  146. /* FIXME: do absolute uri from ref (RFC 3986, section 5.2) */
  147. int len;
  148. int root_len = 0;
  149. int rel_len = 0;
  150. int slash_len = 0;
  151. char *dst = NULL;
  152. if (xcap_root) {
  153. root_len = xcap_root->len;
  154. if (xcap_root->s[root_len - 1] != '/') slash_len = 1;
  155. }
  156. if (relative) rel_len = strlen(relative);
  157. len = root_len + slash_len + rel_len + 1;
  158. dst = (char *)cds_malloc(len);
  159. if (!dst) return NULL;
  160. if (xcap_root) memcpy(dst, xcap_root->s, root_len);
  161. if (slash_len) dst[root_len] = '/';
  162. if (relative) memcpy(dst + root_len + slash_len, relative, rel_len);
  163. dst[len - 1] = 0;
  164. return dst;
  165. }
  166. static display_name_t *duplicate_display_name(display_name_t *src)
  167. {
  168. display_name_t *n;
  169. if (!src) return NULL;
  170. n = (display_name_t*)cds_malloc(sizeof(*n));
  171. if (!n) return NULL;
  172. memset(n, 0, sizeof(*n));
  173. if (src->name) n->name = zt_strdup(src->name);
  174. if (src->lang) n->lang = zt_strdup(src->lang);
  175. return n;
  176. }
  177. int add_entry_to_flat(process_params_t *params, entry_t *entry)
  178. {
  179. flat_list_t *f;
  180. display_name_t *d, *n, *last;
  181. char *uri;
  182. if (!entry) return -1;
  183. uri = entry->uri;
  184. if (!uri) return -1; /* can't be added */
  185. /* try to find the uri in the flat list first */
  186. f = params->flat;
  187. while (f) {
  188. if (strcmp(f->uri, uri) == 0) return 1; /* not significant for the caller */
  189. f = f->next;
  190. }
  191. f = (flat_list_t*)cds_malloc(sizeof(flat_list_t));
  192. if (!f) return -1;
  193. memset(f, 0, sizeof(*f));
  194. f->uri = zt_strdup(uri);
  195. f->next = NULL;
  196. if (params->flat_last) params->flat_last->next = f;
  197. else params->flat = f;
  198. params->flat_last = f;
  199. /* add all entry's names */
  200. last = NULL;
  201. d = SEQUENCE_FIRST(entry->display_names);
  202. while (d) {
  203. n = duplicate_display_name(d);
  204. if (n) SEQUENCE_ADD(f->names, last, n);
  205. d = SEQUENCE_NEXT(d);
  206. }
  207. return 0;
  208. }
  209. int add_uri_to_traversed(process_params_t *params, const char *uri)
  210. {
  211. traversed_list_t *f;
  212. if (!uri) return -1; /* can't be added */
  213. /* try to find the uri in the flat list first */
  214. f = params->traversed;
  215. while (f) {
  216. if (!f->uri) continue;
  217. if (strcmp(f->uri, uri) == 0) return 1; /* this should be taken as an error */
  218. f = f->next;
  219. }
  220. f = (traversed_list_t*)cds_malloc(sizeof(traversed_list_t));
  221. if (!f) return -1;
  222. f->uri = zt_strdup(uri);
  223. f->next = NULL;
  224. if (params->traversed_last) params->traversed_last->next = f;
  225. else params->traversed = f;
  226. params->traversed_last = f;
  227. return 0;
  228. }
  229. /* ------- processing functions (doing flat list) ------- */
  230. static int process_list(list_t *list, process_params_t *params);
  231. static int process_entry(entry_t *entry, process_params_t *params)
  232. {
  233. if (!entry) return RES_OK;
  234. if (!entry->uri) return RES_OK;
  235. /* DEBUG_LOG("processing entry with uri \'%s\'\n", STR_OK(entry->uri)); */
  236. add_entry_to_flat(params, entry);
  237. return RES_OK;
  238. }
  239. static int process_entry_ref(entry_ref_t *entry_ref, process_params_t *params)
  240. {
  241. char *data = NULL;
  242. int dsize = 0;
  243. entry_t *entry = NULL;
  244. char *xcap_uri;
  245. int res;
  246. /* DEBUG_LOG("processing entry-ref with ref \'%s\'\n", STR_OK(entry_ref->ref)); */
  247. if (!entry_ref) return RES_OK;
  248. if (!entry_ref->ref) return RES_OK;
  249. if (add_uri_to_traversed(params, entry_ref->ref) != 0) {
  250. /* It is existing yet? */
  251. ERROR_LOG("Duplicate URI in traversed set\n");
  252. return RES_BAD_GATEWAY_ERR; /* 502 Bad GW */
  253. }
  254. /* XCAP query for the ref uri */
  255. xcap_uri = relative2absolute_uri(params->xcap_root, entry_ref->ref);
  256. res = xcap_query(xcap_uri, params->xcap_params, &data, &dsize);
  257. if (res != 0) {
  258. ERROR_LOG("XCAP problems for uri \'%s\'\n", xcap_uri ? xcap_uri: "???");
  259. if (data) cds_free(data);
  260. if (xcap_uri) cds_free(xcap_uri);
  261. return RES_BAD_GATEWAY_ERR; /* 502 Bad GW */
  262. }
  263. if (xcap_uri) cds_free(xcap_uri);
  264. /* parse document as an entry element */
  265. if (parse_entry_xml(data, dsize, &entry) != 0) {
  266. ERROR_LOG("Parsing problems!\n");
  267. if (entry) free_entry(entry);
  268. if (data) cds_free(data);
  269. return RES_BAD_GATEWAY_ERR; /* 502 Bad GW */
  270. }
  271. if (data) cds_free(data);
  272. if (!entry) return RES_INTERNAL_ERR; /* ??? */
  273. res = process_entry(entry, params);
  274. free_entry(entry);
  275. return res;
  276. }
  277. static int process_external(external_t *external, process_params_t *params)
  278. {
  279. char *data = NULL;
  280. int dsize = 0;
  281. list_t *list = NULL;
  282. int res;
  283. /* DEBUG_LOG("processing external with anchor \'%s\'\n", STR_OK(external->anchor)); */
  284. if (!external) return RES_OK;
  285. if (!external->anchor) return RES_OK;
  286. if (add_uri_to_traversed(params, external->anchor) != 0) {
  287. /* It is existing yet? */
  288. ERROR_LOG("Duplicate URI in traversed set\n");
  289. return RES_BAD_GATEWAY_ERR; /* 502 Bad GW */
  290. }
  291. /* XCAP query for the ref uri */
  292. res = xcap_query(external->anchor, params->xcap_params, &data, &dsize);
  293. if (res != 0) {
  294. ERROR_LOG("XCAP problems for uri \'%s\'\n", external->anchor ? external->anchor: "???");
  295. if (data) cds_free(data);
  296. return RES_BAD_GATEWAY_ERR; /* 502 Bad GW */
  297. }
  298. /* parse document as an entry element */
  299. if (parse_list_xml(data, dsize, &list) != 0) {
  300. ERROR_LOG("Parsing problems!\n");
  301. if (list) free_list(list);
  302. if (data) cds_free(data);
  303. return RES_BAD_GATEWAY_ERR; /* 502 Bad GW */
  304. }
  305. if (data) cds_free(data);
  306. if (!list) return RES_INTERNAL_ERR; /* ??? */
  307. res = process_list(list, params);
  308. free_list(list);
  309. return res;
  310. }
  311. static int process_list(list_t *list, process_params_t *params)
  312. {
  313. list_content_t *e;
  314. int res = 0;
  315. if (!list) return RES_INTERNAL_ERR;
  316. /* DEBUG_LOG("processing list \'%s\'\n", STR_OK(list->name)); */
  317. e = SEQUENCE_FIRST(list->content);
  318. while (e) {
  319. switch (e->type) {
  320. case lct_list:
  321. res = process_list(e->u.list, params);
  322. break;
  323. case lct_entry:
  324. res = process_entry(e->u.entry, params);
  325. break;
  326. case lct_entry_ref:
  327. res = process_entry_ref(e->u.entry_ref, params);
  328. break;
  329. case lct_external:
  330. res = process_external(e->u.external, params);
  331. break;
  332. }
  333. if (res != 0) break;
  334. e = SEQUENCE_NEXT(e);
  335. }
  336. return res;
  337. }
  338. static int process_resource_list(const char *rl_uri, process_params_t *params)
  339. {
  340. char *data = NULL;
  341. int dsize = 0;
  342. int res = 0;
  343. list_t *list = NULL;
  344. /* DEBUG_LOG("processing resource list\n"); */
  345. /* do an xcap query */
  346. if (xcap_query(rl_uri, params->xcap_params, &data, &dsize) != 0) {
  347. ERROR_LOG("XCAP problems for uri \'%s\'\n", rl_uri ? rl_uri: "???");
  348. if (data) cds_free(data);
  349. return RES_BAD_GATEWAY_ERR; /* -> 502 Bad GW */
  350. }
  351. /* parse query result */
  352. if (parse_list_xml(data, dsize, &list) != 0) {
  353. if (data) cds_free(data);
  354. return RES_BAD_GATEWAY_ERR; /* -> 502 Bad GW */
  355. }
  356. if (data) {
  357. cds_free(data);
  358. }
  359. if (!list) return RES_INTERNAL_ERR; /* ??? */
  360. res = process_list(list, params);
  361. if (list) {
  362. free_list(list);
  363. }
  364. return res;
  365. }
  366. static int create_flat_list(service_t *srv,
  367. xcap_query_params_t *xcap_params,
  368. flat_list_t **dst)
  369. {
  370. process_params_t params;
  371. int res = -1;
  372. if (!srv) return RES_INTERNAL_ERR;
  373. params.xcap_params = xcap_params;
  374. params.flat = NULL;
  375. params.flat_last = NULL;
  376. params.traversed = NULL;
  377. params.traversed_last = NULL;
  378. if (srv->content_type == stc_list) {
  379. res = process_list(srv->content.list, &params);
  380. }
  381. else {
  382. res = process_resource_list(srv->content.resource_list, &params);
  383. }
  384. if (dst) *dst = params.flat;
  385. free_traversed_list(params.traversed);
  386. return res;
  387. }
  388. /* ------- helper functions for rls examining ------- */
  389. /** compare str_t and zero terminated string */
  390. static int str_strcmp(const str_t *a, const char *b)
  391. {
  392. int i;
  393. if (!a) {
  394. if (!b) return 0;
  395. else return 1;
  396. }
  397. if (!a->s) {
  398. if (!b) return 0;
  399. else return 1;
  400. }
  401. if (!b) return -1;
  402. for (i = 0; i < a->len; i++) {
  403. if (a->s[i] != b[i]) return -1;
  404. if (b[i] == 0) break;
  405. }
  406. if (i == a->len) return 0;
  407. else return 1;
  408. }
  409. static int verify_package(service_t *srv, const str_t *package)
  410. {
  411. package_t *e;
  412. if (!package) return 0;
  413. if (!package->len) return 0;
  414. if (!package->s) return 0;
  415. if (!srv) return 1;
  416. if (srv->packages) {
  417. e = SEQUENCE_FIRST(srv->packages->package);
  418. while (e) {
  419. if (str_strcmp(package, e->name) == 0) return 0;
  420. e = SEQUENCE_NEXT(e);
  421. }
  422. ERROR_LOG("Unsupported package \"%.*s\"\n", package->len, package->s);
  423. return -1;
  424. }
  425. return 0;
  426. }
  427. static service_t *find_service(rls_services_t *rls, const str_t *uri)
  428. {
  429. service_t *srv;
  430. if (!rls) return NULL;
  431. srv = SEQUENCE_FIRST(rls->rls_services);
  432. while (srv) {
  433. /* TRACE_LOG("comparing %s to %.*s\n", srv->uri, FMT_STR(*uri)); */
  434. if (str_strcmp(uri, srv->uri) == 0) return srv;
  435. srv = SEQUENCE_NEXT(srv);
  436. }
  437. return NULL;
  438. }
  439. /* ------- rls examining ------- */
  440. int get_rls(const str_t *uri, xcap_query_params_t *xcap_params,
  441. const str_t *package, flat_list_t **dst)
  442. {
  443. char *data = NULL;
  444. int dsize = 0;
  445. service_t *service = NULL;
  446. char *xcap_uri = NULL;
  447. str_t *filename = NULL;
  448. int res;
  449. if (!dst) return RES_INTERNAL_ERR;
  450. /* get basic document */
  451. xcap_uri = xcap_uri_for_global_document(xcap_doc_rls_services,
  452. filename, xcap_params);
  453. if (!xcap_uri) {
  454. ERROR_LOG("can't get XCAP uri\n");
  455. return RES_XCAP_QUERY_ERR;
  456. }
  457. res = xcap_query(xcap_uri, xcap_params, &data, &dsize);
  458. if (res != 0) {
  459. ERROR_LOG("XCAP problems for uri \'%s\'\n", xcap_uri);
  460. if (data) {
  461. cds_free(data);
  462. }
  463. cds_free(xcap_uri);
  464. return RES_XCAP_QUERY_ERR;
  465. }
  466. cds_free(xcap_uri);
  467. /* parse document as a service element in rls-sources */
  468. if (parse_service(data, dsize, &service) != 0) {
  469. ERROR_LOG("Parsing problems!\n");
  470. if (service) free_service(service);
  471. if (data) {
  472. cds_free(data);
  473. }
  474. return RES_XCAP_PARSE_ERR;
  475. }
  476. /* DEBUG_LOG("%.*s\n", dsize, data);*/
  477. if (data) cds_free(data);
  478. if (!service) {
  479. DEBUG_LOG("Empty service!\n");
  480. return RES_XCAP_QUERY_ERR;
  481. }
  482. /* verify the package */
  483. if (verify_package(service, package) != 0) {
  484. free_service(service);
  485. return RES_BAD_EVENT_PACKAGE_ERR;
  486. }
  487. /* create flat document */
  488. res = create_flat_list(service, xcap_params, dst);
  489. if (res != RES_OK) {
  490. ERROR_LOG("Flat list creation error\n");
  491. free_service(service);
  492. free_flat_list(*dst);
  493. *dst = NULL;
  494. return res;
  495. }
  496. free_service(service);
  497. return RES_OK;
  498. }
  499. int get_rls_from_full_doc(const str_t *uri,
  500. /* const str_t *filename, */
  501. xcap_query_params_t *xcap_params,
  502. const str_t *package, flat_list_t **dst)
  503. {
  504. char *data = NULL;
  505. int dsize = 0;
  506. rls_services_t *rls = NULL;
  507. service_t *service = NULL;
  508. str_t curi;
  509. int res;
  510. char *xcap_uri = NULL;
  511. str_t *filename = NULL;
  512. if (!dst) return RES_INTERNAL_ERR;
  513. /* get basic document */
  514. xcap_uri = xcap_uri_for_global_document(xcap_doc_rls_services,
  515. filename, xcap_params);
  516. if (!xcap_uri) {
  517. ERROR_LOG("can't get XCAP uri\n");
  518. return -1;
  519. }
  520. res = xcap_query(xcap_uri, xcap_params, &data, &dsize);
  521. if (res != 0) {
  522. ERROR_LOG("XCAP problems for uri \'%s\'\n", xcap_uri);
  523. if (data) {
  524. cds_free(data);
  525. }
  526. cds_free(xcap_uri);
  527. return RES_XCAP_QUERY_ERR;
  528. }
  529. cds_free(xcap_uri);
  530. /* parse document as a service element in rls-sources */
  531. if (parse_rls_services_xml(data, dsize, &rls) != 0) {
  532. ERROR_LOG("Parsing problems!\n");
  533. if (rls) free_rls_services(rls);
  534. if (data) {
  535. cds_free(data);
  536. }
  537. return RES_XCAP_PARSE_ERR;
  538. }
  539. /* DEBUG_LOG("%.*s\n", dsize, data);*/
  540. if (data) cds_free(data);
  541. /* try to find given service according to uri */
  542. canonicalize_uri(uri, &curi);
  543. service = find_service(rls, &curi);
  544. if (!service) DEBUG_LOG("Service %.*s not found!\n", FMT_STR(curi));
  545. str_free_content(&curi);
  546. if (!service) {
  547. if (rls) free_rls_services(rls);
  548. return RES_XCAP_QUERY_ERR;
  549. }
  550. /* verify the package */
  551. if (verify_package(service, package) != 0) {
  552. free_rls_services(rls);
  553. return RES_BAD_EVENT_PACKAGE_ERR;
  554. }
  555. /* create flat document */
  556. res = create_flat_list(service, xcap_params, dst);
  557. if (res != RES_OK) {
  558. ERROR_LOG("Flat list creation error\n");
  559. free_rls_services(rls);
  560. free_flat_list(*dst);
  561. *dst = NULL;
  562. return res;
  563. }
  564. free_rls_services(rls);
  565. return RES_OK;
  566. }
  567. static list_t *find_list(list_t *root, const char *name)
  568. {
  569. list_content_t *c;
  570. if (!root) return root;
  571. if (!name) return root;
  572. if (!*name) return root; /* empty name = whole doc */
  573. c = root->content;
  574. while (c) {
  575. if (c->type == lct_list) {
  576. if (c->u.list) {
  577. if (strcmp(name, c->u.list->name) == 0)
  578. return c->u.list;
  579. }
  580. }
  581. c = SEQUENCE_NEXT(c);
  582. }
  583. ERROR_LOG("list \'%s\' not found\n", name);
  584. return NULL;
  585. }
  586. /* catches and processes user's resource list as rls-services document */
  587. int get_resource_list_from_full_doc(const str_t *user,
  588. const str_t *filename,
  589. xcap_query_params_t *xcap_params,
  590. const char *list_name, flat_list_t **dst)
  591. {
  592. char *data = NULL;
  593. int dsize = 0;
  594. service_t *service = NULL;
  595. list_t *list = NULL, *right = NULL;
  596. int res;
  597. char *uri = NULL;
  598. if (!dst) return RES_INTERNAL_ERR;
  599. /* get basic document */
  600. uri = xcap_uri_for_users_document(xcap_doc_resource_lists,
  601. user, filename, xcap_params);
  602. if (!uri) {
  603. ERROR_LOG("can't get XCAP uri\n");
  604. return -1;
  605. }
  606. DEBUG_LOG("XCAP uri \'%s\'\n", uri);
  607. res = xcap_query(uri, xcap_params, &data, &dsize);
  608. if (res != 0) {
  609. ERROR_LOG("XCAP problems for uri \'%s\'\n", uri);
  610. if (data) {
  611. cds_free(data);
  612. }
  613. cds_free(uri);
  614. return RES_XCAP_QUERY_ERR;
  615. }
  616. cds_free(uri);
  617. /* parse document as a list element in resource-lists */
  618. if (parse_as_list_content_xml(data, dsize, &list) != 0) {
  619. ERROR_LOG("Parsing problems!\n");
  620. if (list) free_list(list);
  621. if (data) {
  622. cds_free(data);
  623. }
  624. return RES_XCAP_PARSE_ERR;
  625. }
  626. /* DEBUG_LOG("%.*s\n", dsize, data);*/
  627. if (data) cds_free(data);
  628. /* rs -> list */
  629. if (!list) {
  630. ERROR_LOG("Empty resource list!\n");
  631. *dst = NULL;
  632. return 0; /* this is not error! */
  633. /* return RES_INTERNAL_ERR; */
  634. }
  635. /* search for right list element */
  636. right = find_list(list, list_name);
  637. service = (service_t*)cds_malloc(sizeof(*service));
  638. if (!service) {
  639. ERROR_LOG("Can't allocate memory!\n");
  640. return RES_MEMORY_ERR;
  641. }
  642. memset(service, 0, sizeof(*service));
  643. service->content_type = stc_list;
  644. service->content.list = right;
  645. /*service->uri = ??? */
  646. /* create flat document */
  647. res = create_flat_list(service, xcap_params, dst);
  648. service->content.list = list; /* free whole document not only "right" list */
  649. free_service(service);
  650. if (res != RES_OK) {
  651. ERROR_LOG("Flat list creation error\n");
  652. free_flat_list(*dst);
  653. *dst = NULL;
  654. return res;
  655. }
  656. return RES_OK;
  657. }