123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602 |
- /*
- * $Id: xcap_functions.c 2230 2007-06-06 07:13:20Z anca_vamanu $
- *
- * xcap_client module - XCAP client for Kamailio
- *
- * Copyright (C) 2007 Voice Sistem S.R.L.
- *
- * This file is part of Kamailio, a free SIP server.
- *
- * Kamailio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * Kamailio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * History:
- * --------
- * 2007-08-20 initial version (anca)
- */
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <time.h>
- #include <curl/curl.h>
- #include "../../mem/mem.h"
- #include "../../lib/srdb1/db.h"
- #include "xcap_functions.h"
- #include "xcap_client.h"
- #include "../presence/hash.h"
- #define ETAG_HDR "Etag: "
- #define ETAG_HDR_LEN strlen("Etag: ")
- size_t write_function( void *ptr, size_t size, size_t nmemb, void *stream);
- char* get_xcap_path(xcap_get_req_t req);
- int bind_xcap(xcap_api_t* api)
- {
- if (!api)
- {
- LM_ERR("Invalid parameter value\n");
- return -1;
- }
- api->get_elem= xcapGetElem;
- api->int_node_sel= xcapInitNodeSel;
- api->add_step= xcapNodeSelAddStep;
- api->add_terminal= xcapNodeSelAddTerminal;
- api->free_node_sel= xcapFreeNodeSel;
- api->register_xcb= register_xcapcb;
- api->getNewDoc= xcapGetNewDoc;
-
- return 0;
- }
- void xcapFreeNodeSel(xcap_node_sel_t* node)
- {
- step_t* s, *p;
- ns_list_t* n, *m;
- s= node->steps;
- while(s)
- {
- p= s;
- s= s->next;
- pkg_free(p->val.s);
- pkg_free(p);
- }
- n= node->ns_list;
- while(n)
- {
- m= n;
- n= n->next;
- pkg_free(m->value.s);
- pkg_free(m);
- }
- pkg_free(node);
- }
- xcap_node_sel_t* xcapInitNodeSel(void)
- {
- xcap_node_sel_t* nsel= NULL;
- nsel= (xcap_node_sel_t*)pkg_malloc(sizeof(xcap_node_sel_t));
- if(nsel== NULL)
- {
- ERR_MEM(PKG_MEM_STR);
- }
- memset(nsel, 0, sizeof(xcap_node_sel_t));
- nsel->steps= (step_t*)pkg_malloc(sizeof(step_t));
- if(nsel->steps== NULL)
- {
- ERR_MEM(PKG_MEM_STR);
- }
- memset(nsel->steps, 0, sizeof(step_t));
- nsel->last_step= nsel->steps;
- nsel->ns_list= (ns_list_t*)pkg_malloc(sizeof(ns_list_t));
- if(nsel->ns_list== NULL)
- {
- ERR_MEM(PKG_MEM_STR);
- }
- memset(nsel->ns_list, 0, sizeof(ns_list_t));
- nsel->last_ns= nsel->ns_list;
- return nsel;
- error:
- if(nsel)
- {
- if(nsel->steps)
- pkg_free(nsel->steps);
- if(nsel->ns_list)
- pkg_free(nsel->ns_list);
- pkg_free(nsel);
- }
- return NULL;
- }
- xcap_node_sel_t* xcapNodeSelAddStep(xcap_node_sel_t* curr_sel, str* name,
- str* namespace, int pos, attr_test_t* attr_test, str* extra_sel)
- {
- int size= 0;
- str new_step= {NULL, 0};
- step_t* s= NULL;
- char ns_card= 'a';
- ns_list_t* ns= NULL;
- if(name)
- size+= name->len;
- else
- size+= 1;
- if(namespace)
- size+= 2;
- if(pos> 0)
- size+= 7;
- if(attr_test)
- size+= 2+ attr_test->name.len+ attr_test->value.len;
- if(extra_sel)
- size+= 2+ extra_sel->len;
-
- new_step.s= (char*)pkg_malloc(size* sizeof(char));
- if(new_step.s== NULL)
- {
- ERR_MEM(PKG_MEM_STR);
- }
- if(name)
- {
- if(namespace)
- {
- ns_card= curr_sel->ns_no+ 'a';
- curr_sel->ns_no++;
- if(ns_card> 'z')
- {
- LM_ERR("Insuficient name cards for namespaces\n");
- goto error;
- }
- new_step.len= sprintf(new_step.s, "%c:", ns_card);
- }
- memcpy(new_step.s+new_step.len, name->s, name->len);
- new_step.len+= name->len;
- }
- else
- memcpy(new_step.s+new_step.len, "*", 1);
- if(attr_test)
- {
- new_step.len+= sprintf(new_step.s+ new_step.len, "[%.*s=%.*s]", attr_test->name.len,
- attr_test->name.s, attr_test->value.len, attr_test->value.s);
- }
- if(pos> 0)
- new_step.len+= sprintf(new_step.s+ new_step.len, "[%d]", pos);
- if(extra_sel)
- {
- memcpy(new_step.s+ new_step.len, extra_sel->s, extra_sel->len);
- new_step.len= extra_sel->len;
- }
- s= (step_t*)pkg_malloc(sizeof(step_t));
- if(s== NULL)
- {
- ERR_MEM(PKG_MEM_STR);
- }
- s->val= new_step;
- s->next= NULL;
- curr_sel->last_step->next= s;
- curr_sel->last_step= s;
- /* add the namespace binding if present */
- if(namespace)
- {
- ns= (ns_list_t*)pkg_malloc(sizeof(ns_list_t));
- if(ns== NULL)
- {
- ERR_MEM(PKG_MEM_STR);
- }
- ns->name= ns_card;
- ns->value.s= (char*)pkg_malloc(namespace->len* sizeof(char));
- if(ns->value.s== NULL)
- {
- ERR_MEM(PKG_MEM_STR);
- }
- memcpy(ns->value.s, namespace->s, namespace->len);
- ns->value.len= namespace->len;
- curr_sel->last_ns->next= ns;
- curr_sel->last_ns= ns;
- }
- curr_sel->size+= 1+ new_step.len;
- if(namespace->len)
- {
- curr_sel->size+= namespace->len+ 3;
- }
-
- return curr_sel;
- error:
- if(new_step.s)
- pkg_free(new_step.s);
- if(s)
- pkg_free(s);
- if(ns)
- {
- if(ns->value.s)
- pkg_free(ns->value.s);
- pkg_free(ns);
- }
- return NULL;
- }
- xcap_node_sel_t* xcapNodeSelAddTerminal(xcap_node_sel_t* curr_sel,
- char* attr_sel, char* namespace_sel, char* extra_sel )
- {
- return NULL;
- }
- char* get_node_selector(xcap_node_sel_t* node_sel)
- {
- char* buf= NULL;
- step_t* s;
- int len= 0;
- ns_list_t* ns_elem;
- buf= (char*)pkg_malloc((node_sel->size+ 10)* sizeof(char));
- if(buf== NULL)
- {
- ERR_MEM(PKG_MEM_STR);
- }
- s= node_sel->steps->next;
- while(1)
- {
- memcpy(buf+ len, s->val.s, s->val.len);
- len+= s->val.len;
- s= s->next;
- if(s)
- buf[len++]= '/';
- else
- break;
- }
- ns_elem= node_sel->ns_list;
- if(ns_elem)
- buf[len++]= '?';
-
- while(ns_elem)
- {
- len+= sprintf(buf+ len, "xmlns(%c=%.*s)", ns_elem->name,
- ns_elem->value.len, ns_elem->value.s);
- ns_elem= ns_elem->next;
- }
-
- buf[len]= '\0';
- return buf;
- error:
- return NULL;
- }
- char* xcapGetNewDoc(xcap_get_req_t req, str user, str domain)
- {
- char* etag= NULL;
- char* doc= NULL;
- db_key_t query_cols[9];
- db_val_t query_vals[9];
- int n_query_cols = 0;
- char* path= NULL;
- path= get_xcap_path(req);
- if(path== NULL)
- {
- LM_ERR("while constructing xcap path\n");
- return NULL;
- }
- /* send HTTP request */
- doc= send_http_get(path, req.port, NULL, 0, &etag);
- if(doc== NULL)
- {
- LM_DBG("the searched document was not found\n");
- goto done;
- }
- if(etag== NULL)
- {
- LM_ERR("no etag found\n");
- pkg_free(doc);
- doc= NULL;
- goto done;
- }
- /* insert in xcap table*/
- query_cols[n_query_cols] = &str_username_col;
- query_vals[n_query_cols].type = DB1_STR;
- query_vals[n_query_cols].nul = 0;
- query_vals[n_query_cols].val.str_val = user;
- n_query_cols++;
-
- query_cols[n_query_cols] = &str_domain_col;
- query_vals[n_query_cols].type = DB1_STR;
- query_vals[n_query_cols].nul = 0;
- query_vals[n_query_cols].val.str_val = domain;
- n_query_cols++;
-
- query_cols[n_query_cols] = &str_doc_type_col;
- query_vals[n_query_cols].type = DB1_INT;
- query_vals[n_query_cols].nul = 0;
- query_vals[n_query_cols].val.int_val= req.doc_sel.doc_type;
- n_query_cols++;
- query_cols[n_query_cols] = &str_doc_col;
- query_vals[n_query_cols].type = DB1_STRING;
- query_vals[n_query_cols].nul = 0;
- query_vals[n_query_cols].val.string_val= doc;
- n_query_cols++;
- query_cols[n_query_cols] = &str_etag_col;
- query_vals[n_query_cols].type = DB1_STRING;
- query_vals[n_query_cols].nul = 0;
- query_vals[n_query_cols].val.string_val= etag;
- n_query_cols++;
- query_cols[n_query_cols] = &str_source_col;
- query_vals[n_query_cols].type = DB1_INT;
- query_vals[n_query_cols].nul = 0;
- query_vals[n_query_cols].val.int_val= XCAP_CL_MOD;
- n_query_cols++;
- query_cols[n_query_cols] = &str_doc_uri_col;
- query_vals[n_query_cols].type = DB1_STRING;
- query_vals[n_query_cols].nul = 0;
- query_vals[n_query_cols].val.string_val= path;
- n_query_cols++;
-
- query_cols[n_query_cols] = &str_port_col;
- query_vals[n_query_cols].type = DB1_INT;
- query_vals[n_query_cols].nul = 0;
- query_vals[n_query_cols].val.int_val= req.port;
- n_query_cols++;
- if (xcap_dbf.use_table(xcap_db, &xcap_db_table) < 0)
- {
- LM_ERR("in use_table-[table]= %.*s\n", xcap_db_table.len, xcap_db_table.s);
- goto done;
- }
-
- if(xcap_dbf.insert(xcap_db, query_cols, query_vals, n_query_cols)< 0)
- {
- LM_ERR("in sql insert\n");
- goto done;
- }
- done:
- pkg_free(path);
- return doc;
- }
- char* get_xcap_path(xcap_get_req_t req)
- {
- int len= 0, size;
- char* path= NULL;
- char* node_selector= NULL;
- len= (strlen(req.xcap_root)+ 1+ req.doc_sel.auid.len+ 5+
- req.doc_sel.xid.len+ req.doc_sel.filename.len+ 50)* sizeof(char);
-
- if(req.node_sel)
- len+= req.node_sel->size;
- path= (char*)pkg_malloc(len);
- if(path== NULL)
- {
- ERR_MEM(PKG_MEM_STR);
- }
- if(req.node_sel)
- {
- node_selector= get_node_selector(req.node_sel);
- if(node_selector== NULL)
- {
- LM_ERR("while constructing node selector\n");
- goto error;
- }
- }
-
- size= sprintf(path, "%s/%.*s/", req.xcap_root, req.doc_sel.auid.len,
- req.doc_sel.auid.s);
- if(req.doc_sel.type==USERS_TYPE)
- size+= sprintf(path+ size, "%s/%.*s/", "users", req.doc_sel.xid.len,
- req.doc_sel.xid.s);
- else
- size+= sprintf(path+ size, "%s/", "global");
- size+= sprintf(path+ size, "%.*s", req.doc_sel.filename.len,
- req.doc_sel.filename.s);
-
- if(node_selector)
- {
- size+= sprintf(path+ size, "/~~%s", node_selector);
- }
- if(size> len)
- {
- LM_ERR("buffer size overflow\n");
- goto error;
- }
- pkg_free(node_selector);
- return path;
-
- error:
- if(path)
- pkg_free(path);
- if(node_selector)
- pkg_free(node_selector);
- return NULL;
- }
- /* xcap_root must be a NULL terminated string */
- char* xcapGetElem(xcap_get_req_t req, char** etag)
- {
- char* path= NULL;
- char* stream= NULL;
-
- path= get_xcap_path(req);
- if(path== NULL)
- {
- LM_ERR("while constructing xcap path\n");
- return NULL;
- }
- stream= send_http_get(path, req.port, req.etag, req.match_type, etag);
- if(stream== NULL)
- {
- LM_DBG("the serched element was not found\n");
- }
-
- if(etag== NULL)
- {
- LM_ERR("no etag found\n");
- pkg_free(stream);
- stream= NULL;
- }
- if(path)
- pkg_free(path);
-
- return stream;
- }
- size_t get_xcap_etag( void *ptr, size_t size, size_t nmemb, void *stream)
- {
- int len= 0;
- char* etag= NULL;
- if(strncasecmp(ptr, ETAG_HDR, ETAG_HDR_LEN)== 0)
- {
- len= size* nmemb- ETAG_HDR_LEN;
- etag= (char*)pkg_malloc((len+ 1)* sizeof(char));
- if(etag== NULL)
- {
- ERR_MEM(PKG_MEM_STR);
- }
- memcpy(etag, ptr+ETAG_HDR_LEN, len);
- etag[len]= '\0';
- *((char**)stream)= etag;
- }
- return len;
- error:
- return -1;
- }
- char* send_http_get(char* path, unsigned int xcap_port, char* match_etag,
- int match_type, char** etag)
- {
- int len;
- char* stream= NULL;
- CURLcode ret_code;
- CURL* curl_handle= NULL;
- static char buf[128];
- char* match_header= NULL;
- *etag= NULL;
-
- if(match_etag)
- {
- char* hdr_name= NULL;
-
- memset(buf, 0, 128* sizeof(char));
- match_header= buf;
-
- hdr_name= (match_type==IF_MATCH)?"If-Match":"If-None-Match";
-
- len=sprintf(match_header, "%s: %s\n", hdr_name, match_etag);
-
- match_header[len]= '\0';
- }
- curl_handle = curl_easy_init();
-
- curl_easy_setopt(curl_handle, CURLOPT_URL, path);
-
- curl_easy_setopt(curl_handle, CURLOPT_PORT, xcap_port);
- curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1);
- curl_easy_setopt(curl_handle, CURLOPT_STDERR, stdout);
-
- curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_function);
-
- curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &stream);
- curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, get_xcap_etag);
-
- curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, &etag);
- if(match_header)
- curl_easy_setopt(curl_handle, CURLOPT_HEADER, (long)match_header);
- /* non-2xx => error */
- curl_easy_setopt(curl_handle, CURLOPT_FAILONERROR, 1);
- ret_code= curl_easy_perform(curl_handle );
-
- if( ret_code== CURLE_WRITE_ERROR)
- {
- LM_ERR("while performing curl option\n");
- if(stream)
- pkg_free(stream);
- stream= NULL;
- return NULL;
- }
- curl_global_cleanup();
- return stream;
- }
- size_t write_function( void *ptr, size_t size, size_t nmemb, void *stream)
- {
- /* allocate memory and copy */
- char* data;
- data= (char*)pkg_malloc(size* nmemb);
- if(data== NULL)
- {
- ERR_MEM(PKG_MEM_STR);
- }
- memcpy(data, (char*)ptr, size* nmemb);
-
- *((char**) stream)= data;
- return size* nmemb;
- error:
- return CURLE_WRITE_ERROR;
- }
|