lost: end of line normalization to linux line ending format
authorHenning Westerholt <hw@skalatan.de>
Mon, 9 Sep 2019 19:28:45 +0000 (21:28 +0200)
committerHenning Westerholt <hw@skalatan.de>
Mon, 9 Sep 2019 19:28:45 +0000 (21:28 +0200)
src/modules/lost/functions.c
src/modules/lost/functions.h
src/modules/lost/lost.c
src/modules/lost/pidf.c
src/modules/lost/pidf.h
src/modules/lost/utilities.c
src/modules/lost/utilities.h

index d38f9bf..9f04265 100644 (file)
-/*\r
- * lost module functions\r
- *\r
- * Copyright (C) 2019 Wolfgang Kampichler\r
- * DEC112, FREQUENTIS AG\r
- *\r
- * This file is part of Kamailio, a free SIP server.\r
- *\r
- * Kamailio is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version\r
- *\r
- * Kamailio is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
- *\r
- */\r
-\r
-/*!\r
- * \file\r
- * \brief Kamailio lost :: functions\r
- * \ingroup lost\r
- * Module: \ref lost\r
- */\r
-/*****************/\r
-\r
-#include "../../modules/http_client/curl_api.h"\r
-\r
-#include "../../core/mod_fix.h"\r
-#include "../../core/pvar.h"\r
-#include "../../core/route_struct.h"\r
-#include "../../core/ut.h"\r
-#include "../../core/trim.h"\r
-#include "../../core/mem/mem.h"\r
-#include "../../core/parser/msg_parser.h"\r
-#include "../../core/parser/parse_body.h"\r
-#include "../../core/lvalue.h"\r
-\r
-#include "pidf.h"\r
-#include "utilities.h"\r
-\r
-#define LOST_SUCCESS 200\r
-#define LOST_CLIENT_ERROR 400\r
-#define LOST_SERVER_ERROR 500\r
-\r
-extern httpc_api_t httpapi;\r
-\r
-char mtheld[] = "application/held+xml;charset=utf-8";\r
-char mtlost[] = "application/lost+xml;charset=utf-8";\r
-\r
-char uri_element[] = "uri";\r
-char name_element[] = "displayName";\r
-char errors_element[] = "errors";\r
-\r
-/*\r
- * lost_function_held(msg, con, pidf, url, err, id)\r
- * assembles and runs HELD locationRequest, parses results\r
- */\r
-int lost_function_held(struct sip_msg *_m, char *_con, char *_pidf, char *_url,\r
-               char *_err, char *_id)\r
-{\r
-       pv_spec_t *pspidf;\r
-       pv_spec_t *psurl;\r
-       pv_spec_t *pserr;\r
-\r
-       pv_value_t pvpidf;\r
-       pv_value_t pvurl;\r
-       pv_value_t pverr;\r
-\r
-       xmlDocPtr doc = NULL;\r
-       xmlNodePtr root = NULL;\r
-\r
-       str did = {NULL, 0};\r
-       str que = {NULL, 0};\r
-       str con = {NULL, 0};\r
-       str geo = {NULL, 0};\r
-       str err = {NULL, 0};\r
-       str res = {NULL, 0};\r
-       str idhdr = {NULL, 0};\r
-\r
-       int curlres = 0;\r
-\r
-       if(_con == NULL || _pidf == NULL || _url == NULL || _err == NULL) {\r
-               LM_ERR("invalid parameter\n");\r
-               goto err;\r
-       }\r
-       /* connection from parameter */\r
-       if(fixup_get_svalue(_m, (gparam_p)_con, &con) != 0) {\r
-               LM_ERR("cannot get connection string\n");\r
-               goto err;\r
-       }\r
-       /* id from parameter */\r
-       if(_id) {\r
-               if(fixup_get_svalue(_m, (gparam_p)_id, &did) != 0) {\r
-                       LM_ERR("cannot get device id\n");\r
-                       goto err;\r
-               }\r
-               if(!did.s) {\r
-                       LM_ERR("no device found\n");\r
-                       goto err;\r
-               }\r
-       } else {\r
-\r
-               LM_DBG("parsing P-A-I header\n");\r
-\r
-               /* id from P-A-I header */\r
-               idhdr.s = lost_get_pai_header(_m, &idhdr.len);\r
-               if(idhdr.len == 0) {\r
-                       LM_WARN("P-A-I header not found, trying From header ...\n");\r
-\r
-                       LM_DBG("parsing From header\n");\r
-                       \r
-                       /* id from From header */\r
-                       idhdr.s = lost_get_from_header(_m, &idhdr.len);\r
-                       if(idhdr.len == 0) {\r
-                               LM_ERR("no device id found\n");\r
-                               goto err;\r
-                       }\r
-               }\r
-               did.s = idhdr.s;\r
-               did.len = idhdr.len;\r
-       }\r
-       LM_INFO("### HELD id [%.*s]\n", did.len, did.s);\r
-\r
-       /* check if connection exists */\r
-       if(httpapi.http_connection_exists(&con) == 0) {\r
-               LM_ERR("connection: [%s] does not exist\n", con.s);\r
-               goto err;\r
-       }\r
-\r
-       /* assemble locationRequest */\r
-       que.s = lost_held_location_request(did.s, &que.len);\r
-       /* free memory */\r
-       lost_free_string(&idhdr);\r
-       did.s = NULL;\r
-       did.len = 0;\r
-       if(!que.s) {\r
-               LM_ERR("held request document error\n");\r
-               goto err;\r
-       }\r
-\r
-       LM_DBG("held location request: [%s]\n", que.s);\r
-\r
-       /* send locationRequest to location server - HTTP POST */\r
-       curlres = httpapi.http_connect(_m, &con, NULL, &res, mtheld, &que);\r
-       /* only HTTP 2xx responses are accepted */ \r
-       if(curlres >= 300 || curlres < 100) {\r
-               LM_ERR("[%.*s] failed with error: %d\n", con.len, con.s, curlres);\r
-               res.s = NULL;\r
-               res.len = 0;\r
-               goto err;\r
-       }\r
-\r
-       LM_DBG("[%.*s] returned: %d\n", con.len, con.s, curlres);\r
-\r
-       /* free memory */\r
-       lost_free_string(&que);\r
-       /* read and parse the returned xml */\r
-       doc = xmlReadMemory(res.s, res.len, 0, NULL,\r
-                       XML_PARSE_NOBLANKS | XML_PARSE_NONET | XML_PARSE_NOCDATA);\r
-       if(!doc) {\r
-               LM_WARN("invalid xml document: [%.*s]\n", res.len, res.s);\r
-               doc = xmlRecoverMemory(res.s, res.len);\r
-               if(!doc) {\r
-                       LM_ERR("xml document recovery failed on: [%.*s]\n", res.len,\r
-                                       res.s);\r
-                       goto err;\r
-               }\r
-\r
-               LM_DBG("xml document recovered\n");\r
-       }\r
-       root = xmlDocGetRootElement(doc);\r
-       if(!root) {\r
-               LM_ERR("empty xml document\n");\r
-               goto err;\r
-       }\r
-       /* check the root element, shall be locationResponse, or errors */\r
-       if(!xmlStrcmp(root->name, (const xmlChar *)"locationResponse")) {\r
-\r
-               LM_DBG("HELD location response [%.*s]\n", res.len, res.s);\r
-\r
-               /* get the locationUri element */\r
-               geo.s = lost_get_content(root, (char *)"locationURI", &geo.len);\r
-               if(!geo.s) {\r
-                       LM_ERR("no locationURI element found\n");\r
-                       goto err;\r
-               }\r
-       } else if(!xmlStrcmp(root->name, (const xmlChar *)"error")) {\r
-\r
-               LM_DBG("HELD error response [%.*s]\n", res.len, res.s);\r
-\r
-               /* get the error patterm */\r
-               err.s = lost_get_property(root, (char *)"code", &err.len);\r
-               if(!err.s) {\r
-                       LM_ERR("error - code property not found: [%.*s]\n", res.len,\r
-                                       res.s);\r
-                       goto err;\r
-               }\r
-               LM_WARN("locationRequest error response: [%.*s]\n", err.len, err.s);\r
-       } else {\r
-               LM_ERR("root element is not valid: [%.*s]\n", res.len, res.s);\r
-               goto err;\r
-       }\r
-       xmlFreeDoc(doc);\r
-\r
-       /* set writeable pvars */\r
-       pvpidf.rs = res;\r
-       pvpidf.rs.s = res.s;\r
-       pvpidf.rs.len = res.len;\r
-\r
-       pvpidf.flags = PV_VAL_STR;\r
-       pspidf = (pv_spec_t *)_pidf;\r
-       pspidf->setf(_m, &pspidf->pvp, (int)EQ_T, &pvpidf);\r
-\r
-       pvurl.rs = geo;\r
-       pvurl.rs.s = geo.s;\r
-       pvurl.rs.len = geo.len;\r
-\r
-       pvurl.flags = PV_VAL_STR;\r
-       psurl = (pv_spec_t *)_url;\r
-       psurl->setf(_m, &psurl->pvp, (int)EQ_T, &pvurl);\r
-\r
-       pverr.rs = err;\r
-       pverr.rs.s = err.s;\r
-       pverr.rs.len = err.len;\r
-\r
-       pverr.flags = PV_VAL_STR;\r
-       pserr = (pv_spec_t *)_err;\r
-       pserr->setf(_m, &pserr->pvp, (int)EQ_T, &pverr);\r
-\r
-       return (err.len > 0) ? LOST_SERVER_ERROR : LOST_SUCCESS;\r
-\r
-err:\r
-       if(doc)\r
-               xmlFreeDoc(doc);\r
-       \r
-       lost_free_string(&idhdr);\r
-       lost_free_string(&que);\r
-\r
-       return LOST_CLIENT_ERROR;\r
-}\r
-\r
-/*\r
- * lost_function(msg, con, pidf, uri, name, err, pidf, urn)\r
- * assembles and runs LOST findService request, parses results\r
- */\r
-int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name,\r
-               char *_err, char *_pidf, char *_urn)\r
-{\r
-       pv_spec_t *psname;\r
-       pv_spec_t *psuri;\r
-       pv_spec_t *pserr;\r
-\r
-       pv_value_t pvname;\r
-       pv_value_t pvuri;\r
-       pv_value_t pverr;\r
-\r
-       p_loc_t loc = NULL;\r
-\r
-       xmlDocPtr doc = NULL;\r
-       xmlNodePtr root = NULL;\r
-\r
-       str uri = {NULL, 0};\r
-       str urn = {NULL, 0};\r
-       str err = {NULL, 0};\r
-       str res = {NULL, 0};\r
-       str con = {NULL, 0};\r
-       str ret = {NULL, 0};\r
-       str geo = {NULL, 0};\r
-       str geohdr = {NULL, 0};\r
-       str name = {NULL, 0};\r
-       str pidf = {NULL, 0};\r
-       str pidfhdr = {NULL, 0};\r
-\r
-       struct msg_start *fl;\r
-       char *search = NULL;\r
-       int curlres = 0;\r
-       \r
-       if(_con == NULL || _uri == NULL || _name == NULL || _err == NULL) {\r
-               LM_ERR("invalid parameter\n");\r
-               goto err;\r
-       }\r
-       if(fixup_get_svalue(_m, (gparam_p)_con, &con) != 0) {\r
-               LM_ERR("cannot get connection string\n");\r
-               goto err;\r
-       }\r
-       /* urn from parameter */\r
-       if(_urn) {\r
-               if(fixup_get_svalue(_m, (gparam_p)_urn, &urn) != 0) {\r
-                       LM_ERR("cannot get service urn\n");\r
-                       goto err;\r
-               }\r
-       }\r
-       /* urn from request line */\r
-       if(urn.len == 0) {\r
-               LM_WARN("no sevice urn parameter, trying request line ...\n");\r
-               fl = &(_m->first_line);\r
-               urn.len = fl->u.request.uri.len;\r
-               urn.s = fl->u.request.uri.s;\r
-       }\r
-       /* check urn scheme */\r
-       if(urn.len > 3) {\r
-               search = urn.s;\r
-               if(((*(search + 0) == 'u') || (*(search + 0) == 'U'))\r
-                               && ((*(search + 1) == 'r') || (*(search + 1) == 'R'))\r
-                               && ((*(search + 2) == 'n') || (*(search + 2) == 'N'))\r
-                               && (*(search + 3) == ':')) {\r
-                       LM_INFO("### LOST urn [%.*s]\n", urn.len, urn.s);\r
-               } else {\r
-                       LM_ERR("service urn not found\n");\r
-                       goto err;\r
-               }\r
-       } else {\r
-               LM_ERR("service urn not found\n");\r
-               goto err;\r
-       }\r
-       /* pidf from parameter */\r
-       if(_pidf) {\r
-               if(fixup_get_svalue(_m, (gparam_p)_pidf, &pidf) != 0) {\r
-                       LM_ERR("cannot get pidf-lo\n");\r
-                       goto err;\r
-               }\r
-       }\r
-       /* pidf from geolocation header */\r
-       if(pidf.len == 0) {\r
-               LM_WARN("no pidf parameter, trying geolocation header ...\n");\r
-               geohdr.s = lost_get_geolocation_header(_m, &geohdr.len);\r
-               if(!geohdr.s) {\r
-                       LM_ERR("geolocation header not found\n");\r
-                       goto err;\r
-               } else {\r
-\r
-                       LM_DBG("geolocation header found\n");\r
-\r
-                       /* pidf from multipart body, check cid scheme */\r
-                       if(geohdr.len > 6) {\r
-                               search = geohdr.s;\r
-                               if((*(search + 0) == '<')\r
-                                               && ((*(search + 1) == 'c') || (*(search + 1) == 'C'))\r
-                                               && ((*(search + 2) == 'i') || (*(search + 2) == 'I'))\r
-                                               && ((*(search + 3) == 'd') || (*(search + 3) == 'D'))\r
-                                               && (*(search + 4) == ':')) {\r
-                                       search += 4;\r
-                                       *search = '<';\r
-                                       geo.s = search;\r
-                                       geo.len = geo.len - 4;\r
-\r
-                                       LM_DBG("cid: [%.*s]\n", geo.len, geo.s);\r
-\r
-                                       /* get body part - filter=>content id */\r
-                                       pidf.s = get_body_part_by_filter(\r
-                                                       _m, 0, 0, geo.s, NULL, &pidf.len);\r
-                                       if(!pidf.s) {\r
-                                               LM_ERR("no multipart body found\n");\r
-                                               goto err;\r
-                                       }\r
-                               }\r
-                               /* no pidf-lo so far ... check http(s) scheme */\r
-                               if(((*(search + 0) == 'h') || (*(search + 0) == 'H'))\r
-                                               && ((*(search + 1) == 't') || (*(search + 1) == 'T'))\r
-                                               && ((*(search + 2) == 't') || (*(search + 2) == 'T'))\r
-                                               && ((*(search + 3) == 'p') || (*(search + 3) == 'P'))) {\r
-                                       geo.s = geohdr.s;\r
-                                       geo.len = geohdr.len;\r
-\r
-                                       if(*(search + 4) == ':') {\r
-                                       \r
-                                               LM_DBG("http url: [%.*s]\n", geo.len, geo.s);\r
-                                       \r
-                                       } else if(((*(search + 4) == 's') || (*(search + 4) == 'S'))\r
-                                                       && (*(search + 5) == ':')) {\r
-                                       \r
-                                               LM_DBG("https url: [%.*s]\n", geo.len, geo.s);\r
-                                       \r
-                                       } else {\r
-                                               LM_ERR("invalid url: [%.*s]\n", geo.len, geo.s);\r
-                                               goto err;\r
-                                       }\r
-\r
-                                       /* ! dereference pidf.lo at location server - HTTP GET */\r
-                                       /* ! requires hack in http_client module */\r
-                                       /* ! functions.c => http_client_query => query_params.oneline = 0; */\r
-                                       curlres = httpapi.http_client_query(_m, geo.s, &pidfhdr, NULL, NULL);\r
-                                       /* free memory */\r
-                                       lost_free_string(&geohdr);\r
-                                       geo.s = NULL;\r
-                                       geo.len = 0;\r
-                                       /* only HTTP 2xx responses are accepted */ \r
-                                       if(curlres >= 300 || curlres < 100) {\r
-                                               LM_ERR("http GET failed with error: %d\n", curlres);\r
-                                               pidfhdr.s = NULL;\r
-                                               pidfhdr.len = 0;\r
-                                               goto err;\r
-                                       }\r
-\r
-                                       LM_DBG("http GET returned: %d\n", curlres);\r
-\r
-                                       if(!pidfhdr.s) {\r
-                                               LM_ERR("dereferencing location failed\n");\r
-                                               goto err;\r
-                                       }\r
-                                       pidf.s = pidfhdr.s;\r
-                                       pidf.len = pidfhdr.len;\r
-                               }\r
-                       } else {\r
-                               LM_ERR("invalid geolocation header\n");\r
-                               goto err;\r
-                       }\r
-               }\r
-       }\r
-\r
-       /* no pidf-lo return error */\r
-       if(!pidf.s) {\r
-               LM_ERR("pidf-lo not found\n");\r
-               goto err;\r
-       }\r
-\r
-       LM_DBG("pidf-lo: [%.*s]\n", pidf.len, pidf.s);\r
-\r
-       /* read and parse pidf-lo */\r
-       doc = xmlReadMemory(pidf.s, pidf.len, 0, NULL,\r
-                       XML_PARSE_NOBLANKS | XML_PARSE_NONET | XML_PARSE_NOCDATA);\r
-\r
-       if(!doc) {\r
-               LM_WARN("invalid xml (pidf-lo): [%.*s]\n", pidf.len, pidf.s);\r
-               doc = xmlRecoverMemory(pidf.s, pidf.len);\r
-               if(!doc) {\r
-                       LM_ERR("xml (pidf-lo) recovery failed on: [%.*s]\n", pidf.len,\r
-                                       pidf.s);\r
-                       goto err;\r
-               }\r
-\r
-               LM_DBG("xml (pidf-lo) recovered\n");\r
-       }\r
-\r
-       root = xmlDocGetRootElement(doc);\r
-       if(!root) {\r
-               LM_ERR("empty pidf-lo document\n");\r
-               goto err;\r
-       }\r
-       if((!xmlStrcmp(root->name, (const xmlChar *)"presence"))\r
-                       || (!xmlStrcmp(root->name, (const xmlChar *)"locationResponse"))) {\r
-               /* get the geolocation: point or circle, urn, ... */\r
-               loc = lost_new_loc(urn);\r
-               if(!loc) {\r
-                       LM_ERR("location object allocation failed\n");\r
-                       goto err;                       \r
-               }\r
-               if(lost_parse_location_info(root, loc) < 0) {\r
-                       LM_ERR("location element not found\n");\r
-                       goto err;\r
-               }\r
-       } else {\r
-               LM_ERR("findServiceResponse or presence element not found in "\r
-                          "[%.*s]\n",\r
-                               pidf.len, pidf.s);\r
-               goto err;\r
-       }\r
-\r
-       /* free memory */\r
-       lost_free_string(&pidfhdr);\r
-       pidf.s = NULL;\r
-       pidf.len = 0;\r
-\r
-       /* check if connection exits */\r
-       if(httpapi.http_connection_exists(&con) == 0) {\r
-               LM_ERR("connection: [%.*s] does not exist\n", con.len, con.s);\r
-               goto err;\r
-       }\r
-       /* assemble findService request */\r
-       res.s = lost_find_service_request(loc, &res.len);\r
-       /* free memory */\r
-       if(loc) {\r
-               lost_free_loc(loc);\r
-               loc = NULL;\r
-       }\r
-       xmlFreeDoc(doc);\r
-       doc = NULL;\r
-\r
-       if(!res.s) {\r
-               LM_ERR("lost request failed\n");\r
-               goto err;\r
-       }\r
-\r
-       LM_DBG("findService request: [%.*s]\n", res.len, res.s);\r
-\r
-       /* send findService request to mapping server - HTTP POST */\r
-       curlres = httpapi.http_connect(_m, &con, NULL, &ret, mtlost, &res);\r
-       /* only HTTP 2xx responses are accepted */ \r
-       if(curlres >= 300 || curlres < 100) {\r
-               LM_ERR("[%.*s] failed with error: %d\n", con.len, con.s, curlres);\r
-               ret.s = NULL;\r
-               ret.len = 0;\r
-               goto err;\r
-       }\r
-\r
-       LM_DBG("[%.*s] returned: %d\n", con.len, con.s, curlres);\r
-\r
-       /* free memory */\r
-       lost_free_string(&res);\r
-\r
-       if(!ret.s) {\r
-               LM_ERR("findService request failed\n");\r
-               goto err;\r
-       }\r
-\r
-       LM_DBG("findService response: [%.*s]\n", ret.len, ret.s);\r
-\r
-       /* read and parse the returned xml */\r
-       doc = xmlReadMemory(ret.s, ret.len, 0, 0,\r
-                       XML_PARSE_NOBLANKS | XML_PARSE_NONET | XML_PARSE_NOCDATA);\r
-\r
-       if(!doc) {\r
-               LM_ERR("invalid xml document: [%.*s]\n", ret.len, ret.s);\r
-               doc = xmlRecoverMemory(ret.s, ret.len);\r
-               if(!doc) {\r
-                       LM_ERR("xml document recovery failed on: [%.*s]\n", ret.len,\r
-                                       ret.s);\r
-                       goto err;\r
-               }\r
-\r
-               LM_DBG("xml document recovered\n");\r
-       }\r
-       root = xmlDocGetRootElement(doc);\r
-       if(!root) {\r
-               LM_ERR("empty xml document: [%.*s]\n", ret.len, ret.s);\r
-               goto err;\r
-       }\r
-       /* check the root element, shall be findServiceResponse, or errors */\r
-       if((!xmlStrcmp(root->name, (const xmlChar *)"findServiceResponse"))) {\r
-               /* get the uri element */\r
-               uri.s = lost_get_content(root, uri_element, &uri.len);\r
-               if(!uri.s) {\r
-                       LM_ERR("uri element not found: [%.*s]\n", ret.len, ret.s);\r
-                       goto err;\r
-               }\r
-               LM_INFO("### LOST uri [%.*s]\n", uri.len, uri.s);\r
-               /* get the displayName element */\r
-               name.s = lost_get_content(root, name_element, &name.len);\r
-               if(!name.s) {\r
-                       LM_ERR("displayName element not found: [%.*s]\n", ret.len, ret.s);\r
-                       goto err;\r
-               }\r
-               LM_INFO("### LOST name [%.*s]\n", name.len, name.s);\r
-       } else if((!xmlStrcmp(root->name, (const xmlChar *)"errors"))) {\r
-\r
-               LM_DBG("findService error response received\n");\r
-\r
-               /* get the error patterm */\r
-               err.s = lost_get_childname(root, errors_element, &err.len);\r
-               if(!err.s) {\r
-                       LM_ERR("error pattern element not found: [%.*s]\n", ret.len,\r
-                                       ret.s);\r
-                       goto err;\r
-               }\r
-               LM_WARN("findService error response: [%.*s]\n", err.len, err.s);\r
-       } else {\r
-               LM_ERR("root element is not valid: [%.*s]\n", ret.len, ret.s);\r
-               goto err;\r
-       }\r
-\r
-       /* free memory */\r
-       xmlFreeDoc(doc);\r
-       doc = NULL;\r
-       lost_free_string(&ret);\r
-\r
-       /* set writable pvars */\r
-       pvname.rs = name;\r
-       pvname.rs.s = name.s;\r
-       pvname.rs.len = name.len;\r
-\r
-       pvname.flags = PV_VAL_STR;\r
-       psname = (pv_spec_t *)_name;\r
-       psname->setf(_m, &psname->pvp, (int)EQ_T, &pvname);\r
-\r
-       pvuri.rs = uri;\r
-       pvuri.rs.s = uri.s;\r
-       pvuri.rs.len = uri.len;\r
-\r
-       pvuri.flags = PV_VAL_STR;\r
-       psuri = (pv_spec_t *)_uri;\r
-       psuri->setf(_m, &psuri->pvp, (int)EQ_T, &pvuri);\r
-\r
-       pverr.rs = err;\r
-       pverr.rs.s = err.s;\r
-       pverr.rs.len = err.len;\r
-\r
-       pverr.flags = PV_VAL_STR;\r
-       pserr = (pv_spec_t *)_err;\r
-       pserr->setf(_m, &pserr->pvp, (int)EQ_T, &pverr);\r
-\r
-       return (err.len > 0) ? LOST_SERVER_ERROR : LOST_SUCCESS;\r
-\r
-err:\r
-       if(loc)\r
-               lost_free_loc(loc);\r
-       if(doc)\r
-               xmlFreeDoc(doc);\r
-\r
-       lost_free_string(&pidfhdr);\r
-       lost_free_string(&geohdr);\r
-       lost_free_string(&ret);\r
-\r
-       return LOST_CLIENT_ERROR;\r
-}\r
+/*
+ * lost module functions
+ *
+ * Copyright (C) 2019 Wolfgang Kampichler
+ * DEC112, FREQUENTIS AG
+ *
+ * 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
+ *
+ */
+
+/*!
+ * \file
+ * \brief Kamailio lost :: functions
+ * \ingroup lost
+ * Module: \ref lost
+ */
+/*****************/
+
+#include "../../modules/http_client/curl_api.h"
+
+#include "../../core/mod_fix.h"
+#include "../../core/pvar.h"
+#include "../../core/route_struct.h"
+#include "../../core/ut.h"
+#include "../../core/trim.h"
+#include "../../core/mem/mem.h"
+#include "../../core/parser/msg_parser.h"
+#include "../../core/parser/parse_body.h"
+#include "../../core/lvalue.h"
+
+#include "pidf.h"
+#include "utilities.h"
+
+#define LOST_SUCCESS 200
+#define LOST_CLIENT_ERROR 400
+#define LOST_SERVER_ERROR 500
+
+extern httpc_api_t httpapi;
+
+char mtheld[] = "application/held+xml;charset=utf-8";
+char mtlost[] = "application/lost+xml;charset=utf-8";
+
+char uri_element[] = "uri";
+char name_element[] = "displayName";
+char errors_element[] = "errors";
+
+/*
+ * lost_function_held(msg, con, pidf, url, err, id)
+ * assembles and runs HELD locationRequest, parses results
+ */
+int lost_function_held(struct sip_msg *_m, char *_con, char *_pidf, char *_url,
+               char *_err, char *_id)
+{
+       pv_spec_t *pspidf;
+       pv_spec_t *psurl;
+       pv_spec_t *pserr;
+
+       pv_value_t pvpidf;
+       pv_value_t pvurl;
+       pv_value_t pverr;
+
+       xmlDocPtr doc = NULL;
+       xmlNodePtr root = NULL;
+
+       str did = {NULL, 0};
+       str que = {NULL, 0};
+       str con = {NULL, 0};
+       str geo = {NULL, 0};
+       str err = {NULL, 0};
+       str res = {NULL, 0};
+       str idhdr = {NULL, 0};
+
+       int curlres = 0;
+
+       if(_con == NULL || _pidf == NULL || _url == NULL || _err == NULL) {
+               LM_ERR("invalid parameter\n");
+               goto err;
+       }
+       /* connection from parameter */
+       if(fixup_get_svalue(_m, (gparam_p)_con, &con) != 0) {
+               LM_ERR("cannot get connection string\n");
+               goto err;
+       }
+       /* id from parameter */
+       if(_id) {
+               if(fixup_get_svalue(_m, (gparam_p)_id, &did) != 0) {
+                       LM_ERR("cannot get device id\n");
+                       goto err;
+               }
+               if(!did.s) {
+                       LM_ERR("no device found\n");
+                       goto err;
+               }
+       } else {
+
+               LM_DBG("parsing P-A-I header\n");
+
+               /* id from P-A-I header */
+               idhdr.s = lost_get_pai_header(_m, &idhdr.len);
+               if(idhdr.len == 0) {
+                       LM_WARN("P-A-I header not found, trying From header ...\n");
+
+                       LM_DBG("parsing From header\n");
+                       
+                       /* id from From header */
+                       idhdr.s = lost_get_from_header(_m, &idhdr.len);
+                       if(idhdr.len == 0) {
+                               LM_ERR("no device id found\n");
+                               goto err;
+                       }
+               }
+               did.s = idhdr.s;
+               did.len = idhdr.len;
+       }
+       LM_INFO("### HELD id [%.*s]\n", did.len, did.s);
+
+       /* check if connection exists */
+       if(httpapi.http_connection_exists(&con) == 0) {
+               LM_ERR("connection: [%s] does not exist\n", con.s);
+               goto err;
+       }
+
+       /* assemble locationRequest */
+       que.s = lost_held_location_request(did.s, &que.len);
+       /* free memory */
+       lost_free_string(&idhdr);
+       did.s = NULL;
+       did.len = 0;
+       if(!que.s) {
+               LM_ERR("held request document error\n");
+               goto err;
+       }
+
+       LM_DBG("held location request: [%s]\n", que.s);
+
+       /* send locationRequest to location server - HTTP POST */
+       curlres = httpapi.http_connect(_m, &con, NULL, &res, mtheld, &que);
+       /* only HTTP 2xx responses are accepted */ 
+       if(curlres >= 300 || curlres < 100) {
+               LM_ERR("[%.*s] failed with error: %d\n", con.len, con.s, curlres);
+               res.s = NULL;
+               res.len = 0;
+               goto err;
+       }
+
+       LM_DBG("[%.*s] returned: %d\n", con.len, con.s, curlres);
+
+       /* free memory */
+       lost_free_string(&que);
+       /* read and parse the returned xml */
+       doc = xmlReadMemory(res.s, res.len, 0, NULL,
+                       XML_PARSE_NOBLANKS | XML_PARSE_NONET | XML_PARSE_NOCDATA);
+       if(!doc) {
+               LM_WARN("invalid xml document: [%.*s]\n", res.len, res.s);
+               doc = xmlRecoverMemory(res.s, res.len);
+               if(!doc) {
+                       LM_ERR("xml document recovery failed on: [%.*s]\n", res.len,
+                                       res.s);
+                       goto err;
+               }
+
+               LM_DBG("xml document recovered\n");
+       }
+       root = xmlDocGetRootElement(doc);
+       if(!root) {
+               LM_ERR("empty xml document\n");
+               goto err;
+       }
+       /* check the root element, shall be locationResponse, or errors */
+       if(!xmlStrcmp(root->name, (const xmlChar *)"locationResponse")) {
+
+               LM_DBG("HELD location response [%.*s]\n", res.len, res.s);
+
+               /* get the locationUri element */
+               geo.s = lost_get_content(root, (char *)"locationURI", &geo.len);
+               if(!geo.s) {
+                       LM_ERR("no locationURI element found\n");
+                       goto err;
+               }
+       } else if(!xmlStrcmp(root->name, (const xmlChar *)"error")) {
+
+               LM_DBG("HELD error response [%.*s]\n", res.len, res.s);
+
+               /* get the error patterm */
+               err.s = lost_get_property(root, (char *)"code", &err.len);
+               if(!err.s) {
+                       LM_ERR("error - code property not found: [%.*s]\n", res.len,
+                                       res.s);
+                       goto err;
+               }
+               LM_WARN("locationRequest error response: [%.*s]\n", err.len, err.s);
+       } else {
+               LM_ERR("root element is not valid: [%.*s]\n", res.len, res.s);
+               goto err;
+       }
+       xmlFreeDoc(doc);
+
+       /* set writeable pvars */
+       pvpidf.rs = res;
+       pvpidf.rs.s = res.s;
+       pvpidf.rs.len = res.len;
+
+       pvpidf.flags = PV_VAL_STR;
+       pspidf = (pv_spec_t *)_pidf;
+       pspidf->setf(_m, &pspidf->pvp, (int)EQ_T, &pvpidf);
+
+       pvurl.rs = geo;
+       pvurl.rs.s = geo.s;
+       pvurl.rs.len = geo.len;
+
+       pvurl.flags = PV_VAL_STR;
+       psurl = (pv_spec_t *)_url;
+       psurl->setf(_m, &psurl->pvp, (int)EQ_T, &pvurl);
+
+       pverr.rs = err;
+       pverr.rs.s = err.s;
+       pverr.rs.len = err.len;
+
+       pverr.flags = PV_VAL_STR;
+       pserr = (pv_spec_t *)_err;
+       pserr->setf(_m, &pserr->pvp, (int)EQ_T, &pverr);
+
+       return (err.len > 0) ? LOST_SERVER_ERROR : LOST_SUCCESS;
+
+err:
+       if(doc)
+               xmlFreeDoc(doc);
+       
+       lost_free_string(&idhdr);
+       lost_free_string(&que);
+
+       return LOST_CLIENT_ERROR;
+}
+
+/*
+ * lost_function(msg, con, pidf, uri, name, err, pidf, urn)
+ * assembles and runs LOST findService request, parses results
+ */
+int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name,
+               char *_err, char *_pidf, char *_urn)
+{
+       pv_spec_t *psname;
+       pv_spec_t *psuri;
+       pv_spec_t *pserr;
+
+       pv_value_t pvname;
+       pv_value_t pvuri;
+       pv_value_t pverr;
+
+       p_loc_t loc = NULL;
+
+       xmlDocPtr doc = NULL;
+       xmlNodePtr root = NULL;
+
+       str uri = {NULL, 0};
+       str urn = {NULL, 0};
+       str err = {NULL, 0};
+       str res = {NULL, 0};
+       str con = {NULL, 0};
+       str ret = {NULL, 0};
+       str geo = {NULL, 0};
+       str geohdr = {NULL, 0};
+       str name = {NULL, 0};
+       str pidf = {NULL, 0};
+       str pidfhdr = {NULL, 0};
+
+       struct msg_start *fl;
+       char *search = NULL;
+       int curlres = 0;
+       
+       if(_con == NULL || _uri == NULL || _name == NULL || _err == NULL) {
+               LM_ERR("invalid parameter\n");
+               goto err;
+       }
+       if(fixup_get_svalue(_m, (gparam_p)_con, &con) != 0) {
+               LM_ERR("cannot get connection string\n");
+               goto err;
+       }
+       /* urn from parameter */
+       if(_urn) {
+               if(fixup_get_svalue(_m, (gparam_p)_urn, &urn) != 0) {
+                       LM_ERR("cannot get service urn\n");
+                       goto err;
+               }
+       }
+       /* urn from request line */
+       if(urn.len == 0) {
+               LM_WARN("no sevice urn parameter, trying request line ...\n");
+               fl = &(_m->first_line);
+               urn.len = fl->u.request.uri.len;
+               urn.s = fl->u.request.uri.s;
+       }
+       /* check urn scheme */
+       if(urn.len > 3) {
+               search = urn.s;
+               if(((*(search + 0) == 'u') || (*(search + 0) == 'U'))
+                               && ((*(search + 1) == 'r') || (*(search + 1) == 'R'))
+                               && ((*(search + 2) == 'n') || (*(search + 2) == 'N'))
+                               && (*(search + 3) == ':')) {
+                       LM_INFO("### LOST urn [%.*s]\n", urn.len, urn.s);
+               } else {
+                       LM_ERR("service urn not found\n");
+                       goto err;
+               }
+       } else {
+               LM_ERR("service urn not found\n");
+               goto err;
+       }
+       /* pidf from parameter */
+       if(_pidf) {
+               if(fixup_get_svalue(_m, (gparam_p)_pidf, &pidf) != 0) {
+                       LM_ERR("cannot get pidf-lo\n");
+                       goto err;
+               }
+       }
+       /* pidf from geolocation header */
+       if(pidf.len == 0) {
+               LM_WARN("no pidf parameter, trying geolocation header ...\n");
+               geohdr.s = lost_get_geolocation_header(_m, &geohdr.len);
+               if(!geohdr.s) {
+                       LM_ERR("geolocation header not found\n");
+                       goto err;
+               } else {
+
+                       LM_DBG("geolocation header found\n");
+
+                       /* pidf from multipart body, check cid scheme */
+                       if(geohdr.len > 6) {
+                               search = geohdr.s;
+                               if((*(search + 0) == '<')
+                                               && ((*(search + 1) == 'c') || (*(search + 1) == 'C'))
+                                               && ((*(search + 2) == 'i') || (*(search + 2) == 'I'))
+                                               && ((*(search + 3) == 'd') || (*(search + 3) == 'D'))
+                                               && (*(search + 4) == ':')) {
+                                       search += 4;
+                                       *search = '<';
+                                       geo.s = search;
+                                       geo.len = geo.len - 4;
+
+                                       LM_DBG("cid: [%.*s]\n", geo.len, geo.s);
+
+                                       /* get body part - filter=>content id */
+                                       pidf.s = get_body_part_by_filter(
+                                                       _m, 0, 0, geo.s, NULL, &pidf.len);
+                                       if(!pidf.s) {
+                                               LM_ERR("no multipart body found\n");
+                                               goto err;
+                                       }
+                               }
+                               /* no pidf-lo so far ... check http(s) scheme */
+                               if(((*(search + 0) == 'h') || (*(search + 0) == 'H'))
+                                               && ((*(search + 1) == 't') || (*(search + 1) == 'T'))
+                                               && ((*(search + 2) == 't') || (*(search + 2) == 'T'))
+                                               && ((*(search + 3) == 'p') || (*(search + 3) == 'P'))) {
+                                       geo.s = geohdr.s;
+                                       geo.len = geohdr.len;
+
+                                       if(*(search + 4) == ':') {
+                                       
+                                               LM_DBG("http url: [%.*s]\n", geo.len, geo.s);
+                                       
+                                       } else if(((*(search + 4) == 's') || (*(search + 4) == 'S'))
+                                                       && (*(search + 5) == ':')) {
+                                       
+                                               LM_DBG("https url: [%.*s]\n", geo.len, geo.s);
+                                       
+                                       } else {
+                                               LM_ERR("invalid url: [%.*s]\n", geo.len, geo.s);
+                                               goto err;
+                                       }
+
+                                       /* ! dereference pidf.lo at location server - HTTP GET */
+                                       /* ! requires hack in http_client module */
+                                       /* ! functions.c => http_client_query => query_params.oneline = 0; */
+                                       curlres = httpapi.http_client_query(_m, geo.s, &pidfhdr, NULL, NULL);
+                                       /* free memory */
+                                       lost_free_string(&geohdr);
+                                       geo.s = NULL;
+                                       geo.len = 0;
+                                       /* only HTTP 2xx responses are accepted */ 
+                                       if(curlres >= 300 || curlres < 100) {
+                                               LM_ERR("http GET failed with error: %d\n", curlres);
+                                               pidfhdr.s = NULL;
+                                               pidfhdr.len = 0;
+                                               goto err;
+                                       }
+
+                                       LM_DBG("http GET returned: %d\n", curlres);
+
+                                       if(!pidfhdr.s) {
+                                               LM_ERR("dereferencing location failed\n");
+                                               goto err;
+                                       }
+                                       pidf.s = pidfhdr.s;
+                                       pidf.len = pidfhdr.len;
+                               }
+                       } else {
+                               LM_ERR("invalid geolocation header\n");
+                               goto err;
+                       }
+               }
+       }
+
+       /* no pidf-lo return error */
+       if(!pidf.s) {
+               LM_ERR("pidf-lo not found\n");
+               goto err;
+       }
+
+       LM_DBG("pidf-lo: [%.*s]\n", pidf.len, pidf.s);
+
+       /* read and parse pidf-lo */
+       doc = xmlReadMemory(pidf.s, pidf.len, 0, NULL,
+                       XML_PARSE_NOBLANKS | XML_PARSE_NONET | XML_PARSE_NOCDATA);
+
+       if(!doc) {
+               LM_WARN("invalid xml (pidf-lo): [%.*s]\n", pidf.len, pidf.s);
+               doc = xmlRecoverMemory(pidf.s, pidf.len);
+               if(!doc) {
+                       LM_ERR("xml (pidf-lo) recovery failed on: [%.*s]\n", pidf.len,
+                                       pidf.s);
+                       goto err;
+               }
+
+               LM_DBG("xml (pidf-lo) recovered\n");
+       }
+
+       root = xmlDocGetRootElement(doc);
+       if(!root) {
+               LM_ERR("empty pidf-lo document\n");
+               goto err;
+       }
+       if((!xmlStrcmp(root->name, (const xmlChar *)"presence"))
+                       || (!xmlStrcmp(root->name, (const xmlChar *)"locationResponse"))) {
+               /* get the geolocation: point or circle, urn, ... */
+               loc = lost_new_loc(urn);
+               if(!loc) {
+                       LM_ERR("location object allocation failed\n");
+                       goto err;                       
+               }
+               if(lost_parse_location_info(root, loc) < 0) {
+                       LM_ERR("location element not found\n");
+                       goto err;
+               }
+       } else {
+               LM_ERR("findServiceResponse or presence element not found in "
+                          "[%.*s]\n",
+                               pidf.len, pidf.s);
+               goto err;
+       }
+
+       /* free memory */
+       lost_free_string(&pidfhdr);
+       pidf.s = NULL;
+       pidf.len = 0;
+
+       /* check if connection exits */
+       if(httpapi.http_connection_exists(&con) == 0) {
+               LM_ERR("connection: [%.*s] does not exist\n", con.len, con.s);
+               goto err;
+       }
+       /* assemble findService request */
+       res.s = lost_find_service_request(loc, &res.len);
+       /* free memory */
+       if(loc) {
+               lost_free_loc(loc);
+               loc = NULL;
+       }
+       xmlFreeDoc(doc);
+       doc = NULL;
+
+       if(!res.s) {
+               LM_ERR("lost request failed\n");
+               goto err;
+       }
+
+       LM_DBG("findService request: [%.*s]\n", res.len, res.s);
+
+       /* send findService request to mapping server - HTTP POST */
+       curlres = httpapi.http_connect(_m, &con, NULL, &ret, mtlost, &res);
+       /* only HTTP 2xx responses are accepted */ 
+       if(curlres >= 300 || curlres < 100) {
+               LM_ERR("[%.*s] failed with error: %d\n", con.len, con.s, curlres);
+               ret.s = NULL;
+               ret.len = 0;
+               goto err;
+       }
+
+       LM_DBG("[%.*s] returned: %d\n", con.len, con.s, curlres);
+
+       /* free memory */
+       lost_free_string(&res);
+
+       if(!ret.s) {
+               LM_ERR("findService request failed\n");
+               goto err;
+       }
+
+       LM_DBG("findService response: [%.*s]\n", ret.len, ret.s);
+
+       /* read and parse the returned xml */
+       doc = xmlReadMemory(ret.s, ret.len, 0, 0,
+                       XML_PARSE_NOBLANKS | XML_PARSE_NONET | XML_PARSE_NOCDATA);
+
+       if(!doc) {
+               LM_ERR("invalid xml document: [%.*s]\n", ret.len, ret.s);
+               doc = xmlRecoverMemory(ret.s, ret.len);
+               if(!doc) {
+                       LM_ERR("xml document recovery failed on: [%.*s]\n", ret.len,
+                                       ret.s);
+                       goto err;
+               }
+
+               LM_DBG("xml document recovered\n");
+       }
+       root = xmlDocGetRootElement(doc);
+       if(!root) {
+               LM_ERR("empty xml document: [%.*s]\n", ret.len, ret.s);
+               goto err;
+       }
+       /* check the root element, shall be findServiceResponse, or errors */
+       if((!xmlStrcmp(root->name, (const xmlChar *)"findServiceResponse"))) {
+               /* get the uri element */
+               uri.s = lost_get_content(root, uri_element, &uri.len);
+               if(!uri.s) {
+                       LM_ERR("uri element not found: [%.*s]\n", ret.len, ret.s);
+                       goto err;
+               }
+               LM_INFO("### LOST uri [%.*s]\n", uri.len, uri.s);
+               /* get the displayName element */
+               name.s = lost_get_content(root, name_element, &name.len);
+               if(!name.s) {
+                       LM_ERR("displayName element not found: [%.*s]\n", ret.len, ret.s);
+                       goto err;
+               }
+               LM_INFO("### LOST name [%.*s]\n", name.len, name.s);
+       } else if((!xmlStrcmp(root->name, (const xmlChar *)"errors"))) {
+
+               LM_DBG("findService error response received\n");
+
+               /* get the error patterm */
+               err.s = lost_get_childname(root, errors_element, &err.len);
+               if(!err.s) {
+                       LM_ERR("error pattern element not found: [%.*s]\n", ret.len,
+                                       ret.s);
+                       goto err;
+               }
+               LM_WARN("findService error response: [%.*s]\n", err.len, err.s);
+       } else {
+               LM_ERR("root element is not valid: [%.*s]\n", ret.len, ret.s);
+               goto err;
+       }
+
+       /* free memory */
+       xmlFreeDoc(doc);
+       doc = NULL;
+       lost_free_string(&ret);
+
+       /* set writable pvars */
+       pvname.rs = name;
+       pvname.rs.s = name.s;
+       pvname.rs.len = name.len;
+
+       pvname.flags = PV_VAL_STR;
+       psname = (pv_spec_t *)_name;
+       psname->setf(_m, &psname->pvp, (int)EQ_T, &pvname);
+
+       pvuri.rs = uri;
+       pvuri.rs.s = uri.s;
+       pvuri.rs.len = uri.len;
+
+       pvuri.flags = PV_VAL_STR;
+       psuri = (pv_spec_t *)_uri;
+       psuri->setf(_m, &psuri->pvp, (int)EQ_T, &pvuri);
+
+       pverr.rs = err;
+       pverr.rs.s = err.s;
+       pverr.rs.len = err.len;
+
+       pverr.flags = PV_VAL_STR;
+       pserr = (pv_spec_t *)_err;
+       pserr->setf(_m, &pserr->pvp, (int)EQ_T, &pverr);
+
+       return (err.len > 0) ? LOST_SERVER_ERROR : LOST_SUCCESS;
+
+err:
+       if(loc)
+               lost_free_loc(loc);
+       if(doc)
+               xmlFreeDoc(doc);
+
+       lost_free_string(&pidfhdr);
+       lost_free_string(&geohdr);
+       lost_free_string(&ret);
+
+       return LOST_CLIENT_ERROR;
+}
index 52b8b1b..7267af8 100755 (executable)
@@ -1,40 +1,40 @@
-/*\r
- * lost module functions\r
- *\r
- * Copyright (C) 2019 Wolfgang Kampichler\r
- * DEC112, FREQUENTIS AG\r
- *\r
- * This file is part of Kamailio, a free SIP server.\r
- *\r
- * Kamailio is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version\r
- *\r
- * Kamailio is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
- *\r
- */\r
-\r
-/*!\r
- * \file\r
- * \brief Kamailio lost :: functions\r
- * \ingroup lost\r
- * Module: \ref lost\r
- */\r
-\r
-#ifndef LOST_FUNCTIONS_H\r
-#define LOST_FUNCTIONS_H\r
-\r
-int lost_function_held(\r
-               struct sip_msg *, char *, char *, char *, char *, char *);\r
-int lost_function(\r
-               struct sip_msg *, char *, char *, char *, char *, char *, char *);\r
-\r
-#endif\r
+/*
+ * lost module functions
+ *
+ * Copyright (C) 2019 Wolfgang Kampichler
+ * DEC112, FREQUENTIS AG
+ *
+ * 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
+ *
+ */
+
+/*!
+ * \file
+ * \brief Kamailio lost :: functions
+ * \ingroup lost
+ * Module: \ref lost
+ */
+
+#ifndef LOST_FUNCTIONS_H
+#define LOST_FUNCTIONS_H
+
+int lost_function_held(
+               struct sip_msg *, char *, char *, char *, char *, char *);
+int lost_function(
+               struct sip_msg *, char *, char *, char *, char *, char *, char *);
+
+#endif
index 5bdba54..ae5da27 100644 (file)
-/*\r
- * lost module\r
- *\r
- * Copyright (C) 2019 Wolfgang Kampichler\r
- * DEC112, FREQUENTIS AG\r
- *\r
- * This file is part of Kamailio, a free SIP server.\r
- *\r
- * Kamailio is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version\r
- *\r
- * Kamailio is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
- *\r
- */\r
-\r
-/*!\r
- * \file\r
- * \brief Kamailio lost ::\r
- * \ingroup lost\r
- * Module: \ref lost\r
- */\r
-\r
-#include "../../modules/http_client/curl_api.h"\r
-\r
-#include "../../core/mod_fix.h"\r
-#include "../../core/sr_module.h"\r
-#include "../../core/ut.h"\r
-#include "../../core/locking.h"\r
-\r
-#include "../../core/pvar.h"\r
-#include "../../core/mem/mem.h"\r
-#include "../../core/dprint.h"\r
-\r
-#include "../../core/script_cb.h"\r
-\r
-#include "functions.h"\r
-\r
-MODULE_VERSION\r
-\r
-/* Module parameter variables */\r
-httpc_api_t httpapi;\r
-\r
-/* Module management function prototypes */\r
-static int mod_init(void);\r
-static int child_init(int);\r
-static void destroy(void);\r
-\r
-/* Fixup functions to be defined later */\r
-static int fixup_lost_held_query(void **param, int param_no);\r
-static int fixup_free_lost_held_query(void **param, int param_no);\r
-static int fixup_lost_held_query_id(void **param, int param_no);\r
-static int fixup_free_lost_held_query_id(void **param, int param_no);\r
-\r
-static int fixup_lost_query(void **param, int param_no);\r
-static int fixup_free_lost_query(void **param, int param_no);\r
-static int fixup_lost_query_all(void **param, int param_no);\r
-static int fixup_free_lost_query_all(void **param, int param_no);\r
-\r
-/* Wrappers for http_query to be defined later */\r
-static int w_lost_held_query(\r
-               struct sip_msg *_m, char *_con, char *_pidf, char *_url, char *_err);\r
-static int w_lost_held_query_id(struct sip_msg *_m, char *_con, char *_id,\r
-               char *_pidf, char *_url, char *_err);\r
-static int w_lost_query(\r
-               struct sip_msg *_m, char *_con, char *_uri, char *_name, char *_err);\r
-static int w_lost_query_all(struct sip_msg *_m, char *_con, char *_pidf,\r
-               char *_urn, char *_uri, char *_name, char *_err);\r
-\r
-/* Exported functions */\r
-static cmd_export_t cmds[] = {\r
-               {"lost_held_query", (cmd_function)w_lost_held_query, 4,\r
-                               fixup_lost_held_query, fixup_free_lost_held_query,\r
-                               REQUEST_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},\r
-               {"lost_held_query", (cmd_function)w_lost_held_query_id, 5,\r
-                               fixup_lost_held_query_id, fixup_free_lost_held_query_id,\r
-                               REQUEST_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},\r
-               {"lost_query", (cmd_function)w_lost_query, 4, fixup_lost_query,\r
-                               fixup_free_lost_query,\r
-                               REQUEST_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},\r
-               {"lost_query", (cmd_function)w_lost_query_all, 6, fixup_lost_query_all,\r
-                               fixup_free_lost_query_all,\r
-                               REQUEST_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},\r
-               {0, 0, 0, 0, 0, 0}};\r
-\r
-\r
-/* Module interface */\r
-struct module_exports exports = {\r
-               "lost",                  /* module name*/\r
-               DEFAULT_DLFLAGS, /* dlopen flags */\r
-               cmds,                    /* exported functions */\r
-               0,                               /* exported parameters */\r
-               0,                               /* RPC method exports */\r
-               0,                               /* exported pseudo-variables */\r
-               0,                               /* response handling function */\r
-               mod_init,                /* module initialization function */\r
-               child_init,              /* per-child init function */\r
-               destroy                  /* module destroy function */\r
-};\r
-\r
-/* Module initialization function */\r
-static int mod_init(void)\r
-{\r
-       LM_DBG("init lost module\n");\r
-\r
-       if(httpc_load_api(&httpapi) != 0) {\r
-               LM_ERR("Can not bind to http_client API \n");\r
-               return -1;\r
-       }\r
-\r
-       LM_DBG("**** init lost module done.\n");\r
-\r
-       return 0;\r
-}\r
-\r
-/* Child initialization function */\r
-static int child_init(int rank)\r
-{\r
-       return 0;\r
-}\r
-\r
-static void destroy(void)\r
-{\r
-       ;\r
-       /* do nothing */\r
-}\r
-\r
-/*\r
- * Fix 4 lost_held_query params: con (string/pvar)\r
- * and pidf, url, err (writable pvar).\r
- */\r
-static int fixup_lost_held_query(void **param, int param_no)\r
-{\r
-       if(param_no == 1) {\r
-               return fixup_spve_null(param, 1);\r
-       }\r
-       if((param_no == 2) || (param_no == 3) || (param_no == 4)) {\r
-               if(fixup_pvar_null(param, 1) != 0) {\r
-                       LM_ERR("failed to fixup result pvar\n");\r
-                       return -1;\r
-               }\r
-               if(((pv_spec_t *)(*param))->setf == NULL) {\r
-                       LM_ERR("result pvar is not writable\n");\r
-                       return -1;\r
-               }\r
-               return 0;\r
-       }\r
-       LM_ERR("invalid parameter number <%d>\n", param_no);\r
-       return -1;\r
-}\r
-\r
-/*\r
- * Free lost_held_query params.\r
- */\r
-static int fixup_free_lost_held_query(void **param, int param_no)\r
-{\r
-       if(param_no == 1) {\r
-               /* char strings don't need freeing */\r
-               return 0;\r
-       }\r
-       if((param_no == 2) || (param_no == 3) || (param_no == 4)) {\r
-               return fixup_free_pvar_null(param, 1);\r
-       }\r
-       LM_ERR("invalid parameter number <%d>\n", param_no);\r
-       return -1;\r
-}\r
-\r
-/*\r
- * Fix 5 lost_held_query_id params: con (string/pvar) id (string that may contain\r
- * pvars) and pidf, url, err (writable pvar).\r
- */\r
-static int fixup_lost_held_query_id(void **param, int param_no)\r
-{\r
-       if(param_no == 1) {\r
-               return fixup_spve_null(param, 1);\r
-       }\r
-       if(param_no == 2) {\r
-               return fixup_spve_null(param, 1);\r
-       }\r
-       if((param_no == 3) || (param_no == 4) || (param_no == 5)) {\r
-               if(fixup_pvar_null(param, 1) != 0) {\r
-                       LM_ERR("failed to fixup result pvar\n");\r
-                       return -1;\r
-               }\r
-               if(((pv_spec_t *)(*param))->setf == NULL) {\r
-                       LM_ERR("result pvar is not writable\n");\r
-                       return -1;\r
-               }\r
-               return 0;\r
-       }\r
-       LM_ERR("invalid parameter number <%d>\n", param_no);\r
-       return -1;\r
-}\r
-\r
-/*\r
- * Free lost_held_query_id params.\r
- */\r
-static int fixup_free_lost_held_query_id(void **param, int param_no)\r
-{\r
-       if(param_no == 1) {\r
-               return fixup_free_spve_null(param, 1);\r
-       }\r
-       if(param_no == 2) {\r
-               return fixup_free_spve_null(param, 1);\r
-       }\r
-       if((param_no == 3) || (param_no == 4) || (param_no == 5)) {\r
-               return fixup_free_pvar_null(param, 1);\r
-       }\r
-       LM_ERR("invalid parameter number <%d>\n", param_no);\r
-       return -1;\r
-}\r
-\r
-/*\r
- * Fix 4 lost_query params: con (string/pvar)\r
- * and uri, name, err (writable pvar).\r
- */\r
-static int fixup_lost_query(void **param, int param_no)\r
-{\r
-       if(param_no == 1) {\r
-               return fixup_spve_null(param, 1);\r
-       }\r
-       if((param_no == 2) || (param_no == 3) || (param_no == 4)) {\r
-               if(fixup_pvar_null(param, 1) != 0) {\r
-                       LM_ERR("failed to fixup result pvar\n");\r
-                       return -1;\r
-               }\r
-               if(((pv_spec_t *)(*param))->setf == NULL) {\r
-                       LM_ERR("result pvar is not writable\n");\r
-                       return -1;\r
-               }\r
-               return 0;\r
-       }\r
-       LM_ERR("invalid parameter number <%d>\n", param_no);\r
-       return -1;\r
-}\r
-\r
-/*\r
- * Free lost_held_query_id params.\r
- */\r
-static int fixup_free_lost_query(void **param, int param_no)\r
-{\r
-       if(param_no == 1) {\r
-               return fixup_free_spve_null(param, 1);\r
-       }\r
-       if((param_no == 2) || (param_no == 3) || (param_no == 4)) {\r
-               return fixup_free_pvar_null(param, 1);\r
-       }\r
-       LM_ERR("invalid parameter number <%d>\n", param_no);\r
-       return -1;\r
-}\r
-\r
-/*\r
- * Fix 6 lost_query params: con (string/pvar) pidf, urn (string that may contain\r
- * pvars) and uri, name, err (writable pvar).\r
- */\r
-static int fixup_lost_query_all(void **param, int param_no)\r
-{\r
-       if(param_no == 1) {\r
-               return fixup_spve_null(param, 1);\r
-       }\r
-       if((param_no == 2) || (param_no == 3)) {\r
-               return fixup_spve_null(param, 1);\r
-       }\r
-       if((param_no == 4) || (param_no == 5) || (param_no == 6)) {\r
-               if(fixup_pvar_null(param, 1) != 0) {\r
-                       LM_ERR("failed to fixup result pvar\n");\r
-                       return -1;\r
-               }\r
-               if(((pv_spec_t *)(*param))->setf == NULL) {\r
-                       LM_ERR("result pvar is not writable\n");\r
-                       return -1;\r
-               }\r
-               return 0;\r
-       }\r
-       LM_ERR("invalid parameter number <%d>\n", param_no);\r
-       return -1;\r
-}\r
-\r
-/*\r
- * Free lost_held_query_id params.\r
- */\r
-static int fixup_free_lost_query_all(void **param, int param_no)\r
-{\r
-       if(param_no == 1) {\r
-               return fixup_free_spve_null(param, 1);\r
-       }\r
-       if((param_no == 2) || (param_no == 3)) {\r
-               return fixup_free_spve_null(param, 1);\r
-       }\r
-       if((param_no == 4) || (param_no == 5) || (param_no == 6)) {\r
-               return fixup_free_pvar_null(param, 1);\r
-       }\r
-       LM_ERR("invalid parameter number <%d>\n", param_no);\r
-       return -1;\r
-}\r
-\r
-/*\r
- * Wrapper for lost_held_query w/o id\r
- */\r
-static int w_lost_held_query(\r
-               struct sip_msg *_m, char *_con, char *_pidf, char *_url, char *_err)\r
-{\r
-       return lost_function_held(_m, _con, _pidf, _url, _err, NULL);\r
-}\r
-\r
-/*\r
- * Wrapper for lost_held_query with id\r
- */\r
-static int w_lost_held_query_id(struct sip_msg *_m, char *_con, char *_id,\r
-               char *_pidf, char *_url, char *_err)\r
-{\r
-       return lost_function_held(_m, _con, _pidf, _url, _err, _id);\r
-}\r
-\r
-/*\r
- * Wrapper for lost_query w/o pudf, urn\r
- */\r
-static int w_lost_query(\r
-               struct sip_msg *_m, char *_con, char *_uri, char *_name, char *_err)\r
-{\r
-       return lost_function(_m, _con, _uri, _name, _err, NULL, NULL);\r
-}\r
-\r
-/*\r
- * Wrapper for lost_query with pidf, urn\r
- */\r
-static int w_lost_query_all(struct sip_msg *_m, char *_con, char *_pidf,\r
-               char *_urn, char *_uri, char *_name, char *_err)\r
-{\r
-       return lost_function(_m, _con, _uri, _name, _err, _pidf, _urn);\r
-}\r
+/*
+ * lost module
+ *
+ * Copyright (C) 2019 Wolfgang Kampichler
+ * DEC112, FREQUENTIS AG
+ *
+ * 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
+ *
+ */
+
+/*!
+ * \file
+ * \brief Kamailio lost ::
+ * \ingroup lost
+ * Module: \ref lost
+ */
+
+#include "../../modules/http_client/curl_api.h"
+
+#include "../../core/mod_fix.h"
+#include "../../core/sr_module.h"
+#include "../../core/ut.h"
+#include "../../core/locking.h"
+
+#include "../../core/pvar.h"
+#include "../../core/mem/mem.h"
+#include "../../core/dprint.h"
+
+#include "../../core/script_cb.h"
+
+#include "functions.h"
+
+MODULE_VERSION
+
+/* Module parameter variables */
+httpc_api_t httpapi;
+
+/* Module management function prototypes */
+static int mod_init(void);
+static int child_init(int);
+static void destroy(void);
+
+/* Fixup functions to be defined later */
+static int fixup_lost_held_query(void **param, int param_no);
+static int fixup_free_lost_held_query(void **param, int param_no);
+static int fixup_lost_held_query_id(void **param, int param_no);
+static int fixup_free_lost_held_query_id(void **param, int param_no);
+
+static int fixup_lost_query(void **param, int param_no);
+static int fixup_free_lost_query(void **param, int param_no);
+static int fixup_lost_query_all(void **param, int param_no);
+static int fixup_free_lost_query_all(void **param, int param_no);
+
+/* Wrappers for http_query to be defined later */
+static int w_lost_held_query(
+               struct sip_msg *_m, char *_con, char *_pidf, char *_url, char *_err);
+static int w_lost_held_query_id(struct sip_msg *_m, char *_con, char *_id,
+               char *_pidf, char *_url, char *_err);
+static int w_lost_query(
+               struct sip_msg *_m, char *_con, char *_uri, char *_name, char *_err);
+static int w_lost_query_all(struct sip_msg *_m, char *_con, char *_pidf,
+               char *_urn, char *_uri, char *_name, char *_err);
+
+/* Exported functions */
+static cmd_export_t cmds[] = {
+               {"lost_held_query", (cmd_function)w_lost_held_query, 4,
+                               fixup_lost_held_query, fixup_free_lost_held_query,
+                               REQUEST_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},
+               {"lost_held_query", (cmd_function)w_lost_held_query_id, 5,
+                               fixup_lost_held_query_id, fixup_free_lost_held_query_id,
+                               REQUEST_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},
+               {"lost_query", (cmd_function)w_lost_query, 4, fixup_lost_query,
+                               fixup_free_lost_query,
+                               REQUEST_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},
+               {"lost_query", (cmd_function)w_lost_query_all, 6, fixup_lost_query_all,
+                               fixup_free_lost_query_all,
+                               REQUEST_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},
+               {0, 0, 0, 0, 0, 0}};
+
+
+/* Module interface */
+struct module_exports exports = {
+               "lost",                  /* module name*/
+               DEFAULT_DLFLAGS, /* dlopen flags */
+               cmds,                    /* exported functions */
+               0,                               /* exported parameters */
+               0,                               /* RPC method exports */
+               0,                               /* exported pseudo-variables */
+               0,                               /* response handling function */
+               mod_init,                /* module initialization function */
+               child_init,              /* per-child init function */
+               destroy                  /* module destroy function */
+};
+
+/* Module initialization function */
+static int mod_init(void)
+{
+       LM_DBG("init lost module\n");
+
+       if(httpc_load_api(&httpapi) != 0) {
+               LM_ERR("Can not bind to http_client API \n");
+               return -1;
+       }
+
+       LM_DBG("**** init lost module done.\n");
+
+       return 0;
+}
+
+/* Child initialization function */
+static int child_init(int rank)
+{
+       return 0;
+}
+
+static void destroy(void)
+{
+       ;
+       /* do nothing */
+}
+
+/*
+ * Fix 4 lost_held_query params: con (string/pvar)
+ * and pidf, url, err (writable pvar).
+ */
+static int fixup_lost_held_query(void **param, int param_no)
+{
+       if(param_no == 1) {
+               return fixup_spve_null(param, 1);
+       }
+       if((param_no == 2) || (param_no == 3) || (param_no == 4)) {
+               if(fixup_pvar_null(param, 1) != 0) {
+                       LM_ERR("failed to fixup result pvar\n");
+                       return -1;
+               }
+               if(((pv_spec_t *)(*param))->setf == NULL) {
+                       LM_ERR("result pvar is not writable\n");
+                       return -1;
+               }
+               return 0;
+       }
+       LM_ERR("invalid parameter number <%d>\n", param_no);
+       return -1;
+}
+
+/*
+ * Free lost_held_query params.
+ */
+static int fixup_free_lost_held_query(void **param, int param_no)
+{
+       if(param_no == 1) {
+               /* char strings don't need freeing */
+               return 0;
+       }
+       if((param_no == 2) || (param_no == 3) || (param_no == 4)) {
+               return fixup_free_pvar_null(param, 1);
+       }
+       LM_ERR("invalid parameter number <%d>\n", param_no);
+       return -1;
+}
+
+/*
+ * Fix 5 lost_held_query_id params: con (string/pvar) id (string that may contain
+ * pvars) and pidf, url, err (writable pvar).
+ */
+static int fixup_lost_held_query_id(void **param, int param_no)
+{
+       if(param_no == 1) {
+               return fixup_spve_null(param, 1);
+       }
+       if(param_no == 2) {
+               return fixup_spve_null(param, 1);
+       }
+       if((param_no == 3) || (param_no == 4) || (param_no == 5)) {
+               if(fixup_pvar_null(param, 1) != 0) {
+                       LM_ERR("failed to fixup result pvar\n");
+                       return -1;
+               }
+               if(((pv_spec_t *)(*param))->setf == NULL) {
+                       LM_ERR("result pvar is not writable\n");
+                       return -1;
+               }
+               return 0;
+       }
+       LM_ERR("invalid parameter number <%d>\n", param_no);
+       return -1;
+}
+
+/*
+ * Free lost_held_query_id params.
+ */
+static int fixup_free_lost_held_query_id(void **param, int param_no)
+{
+       if(param_no == 1) {
+               return fixup_free_spve_null(param, 1);
+       }
+       if(param_no == 2) {
+               return fixup_free_spve_null(param, 1);
+       }
+       if((param_no == 3) || (param_no == 4) || (param_no == 5)) {
+               return fixup_free_pvar_null(param, 1);
+       }
+       LM_ERR("invalid parameter number <%d>\n", param_no);
+       return -1;
+}
+
+/*
+ * Fix 4 lost_query params: con (string/pvar)
+ * and uri, name, err (writable pvar).
+ */
+static int fixup_lost_query(void **param, int param_no)
+{
+       if(param_no == 1) {
+               return fixup_spve_null(param, 1);
+       }
+       if((param_no == 2) || (param_no == 3) || (param_no == 4)) {
+               if(fixup_pvar_null(param, 1) != 0) {
+                       LM_ERR("failed to fixup result pvar\n");
+                       return -1;
+               }
+               if(((pv_spec_t *)(*param))->setf == NULL) {
+                       LM_ERR("result pvar is not writable\n");
+                       return -1;
+               }
+               return 0;
+       }
+       LM_ERR("invalid parameter number <%d>\n", param_no);
+       return -1;
+}
+
+/*
+ * Free lost_held_query_id params.
+ */
+static int fixup_free_lost_query(void **param, int param_no)
+{
+       if(param_no == 1) {
+               return fixup_free_spve_null(param, 1);
+       }
+       if((param_no == 2) || (param_no == 3) || (param_no == 4)) {
+               return fixup_free_pvar_null(param, 1);
+       }
+       LM_ERR("invalid parameter number <%d>\n", param_no);
+       return -1;
+}
+
+/*
+ * Fix 6 lost_query params: con (string/pvar) pidf, urn (string that may contain
+ * pvars) and uri, name, err (writable pvar).
+ */
+static int fixup_lost_query_all(void **param, int param_no)
+{
+       if(param_no == 1) {
+               return fixup_spve_null(param, 1);
+       }
+       if((param_no == 2) || (param_no == 3)) {
+               return fixup_spve_null(param, 1);
+       }
+       if((param_no == 4) || (param_no == 5) || (param_no == 6)) {
+               if(fixup_pvar_null(param, 1) != 0) {
+                       LM_ERR("failed to fixup result pvar\n");
+                       return -1;
+               }
+               if(((pv_spec_t *)(*param))->setf == NULL) {
+                       LM_ERR("result pvar is not writable\n");
+                       return -1;
+               }
+               return 0;
+       }
+       LM_ERR("invalid parameter number <%d>\n", param_no);
+       return -1;
+}
+
+/*
+ * Free lost_held_query_id params.
+ */
+static int fixup_free_lost_query_all(void **param, int param_no)
+{
+       if(param_no == 1) {
+               return fixup_free_spve_null(param, 1);
+       }
+       if((param_no == 2) || (param_no == 3)) {
+               return fixup_free_spve_null(param, 1);
+       }
+       if((param_no == 4) || (param_no == 5) || (param_no == 6)) {
+               return fixup_free_pvar_null(param, 1);
+       }
+       LM_ERR("invalid parameter number <%d>\n", param_no);
+       return -1;
+}
+
+/*
+ * Wrapper for lost_held_query w/o id
+ */
+static int w_lost_held_query(
+               struct sip_msg *_m, char *_con, char *_pidf, char *_url, char *_err)
+{
+       return lost_function_held(_m, _con, _pidf, _url, _err, NULL);
+}
+
+/*
+ * Wrapper for lost_held_query with id
+ */
+static int w_lost_held_query_id(struct sip_msg *_m, char *_con, char *_id,
+               char *_pidf, char *_url, char *_err)
+{
+       return lost_function_held(_m, _con, _pidf, _url, _err, _id);
+}
+
+/*
+ * Wrapper for lost_query w/o pudf, urn
+ */
+static int w_lost_query(
+               struct sip_msg *_m, char *_con, char *_uri, char *_name, char *_err)
+{
+       return lost_function(_m, _con, _uri, _name, _err, NULL, NULL);
+}
+
+/*
+ * Wrapper for lost_query with pidf, urn
+ */
+static int w_lost_query_all(struct sip_msg *_m, char *_con, char *_pidf,
+               char *_urn, char *_uri, char *_name, char *_err)
+{
+       return lost_function(_m, _con, _uri, _name, _err, _pidf, _urn);
+}
index c018313..25302cd 100755 (executable)
-/*\r
- * $Id: pidf.c 1953 2007-04-04 08:50:33Z anca_vamanu $\r
- *\r
- * presence module - presence server implementation\r
- *\r
- * Copyright (C) 2006 Voice Sistem S.R.L.\r
- *\r
- * This file is part of Kamailio, a free SIP server.\r
- *\r
- * Kamailio is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version\r
- *\r
- * Kamailio is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
- *\r
- */\r
-\r
-/*! \file\r
- * \brief Kamailio lost ::  PIDF handling\r
- * \ingroup lost\r
- */\r
-\r
-\r
-/**\r
- * make strptime available\r
- * use 600 for 'Single UNIX Specification, Version 3'\r
- * _XOPEN_SOURCE creates conflict in header definitions in Solaris\r
- */\r
-#ifndef __OS_solaris\r
-#define _XOPEN_SOURCE 600 /* glibc2 on linux, bsd */\r
-#define _BSD_SOURCE \\r
-       1                                         /* needed on linux to "fix" the effect\r
-                                                                                 of the above define on\r
-                                                                                 features.h/unistd.h syscall() */\r
-#define _DEFAULT_SOURCE 1 /* _BSD_SOURCE is deprecated */\r
-#define _DARWIN_C_SOURCE 1\r
-#else\r
-#define _XOPEN_SOURCE_EXTENDED 1 /* solaris */\r
-#endif\r
-\r
-#include <time.h>\r
-\r
-#undef _XOPEN_SOURCE\r
-#undef _XOPEN_SOURCE_EXTENDED\r
-\r
-#include <string.h>\r
-#include <stdlib.h>\r
-#include <libxml/parser.h>\r
-\r
-#include "../../core/mem/mem.h"\r
-#include "../../core/dprint.h"\r
-\r
-#include "pidf.h"\r
-\r
-xmlAttrPtr xmlNodeGetAttrByName(xmlNodePtr node, const char *name)\r
-{\r
-       xmlAttrPtr attr = node->properties;\r
-       while(attr) {\r
-               if(xmlStrcasecmp(attr->name, (unsigned char *)name) == 0)\r
-                       return attr;\r
-               attr = attr->next;\r
-       }\r
-       return NULL;\r
-}\r
-\r
-char *xmlNodeGetAttrContentByName(xmlNodePtr node, const char *name)\r
-{\r
-       xmlAttrPtr attr = xmlNodeGetAttrByName(node, name);\r
-       if(attr)\r
-               return (char *)xmlNodeGetContent(attr->children);\r
-       else\r
-               return NULL;\r
-}\r
-\r
-xmlNodePtr xmlNodeGetChildByName(xmlNodePtr node, const char *name)\r
-{\r
-       xmlNodePtr cur = node->children;\r
-       while(cur) {\r
-               if(xmlStrcasecmp(cur->name, (unsigned char *)name) == 0)\r
-                       return cur;\r
-               cur = cur->next;\r
-       }\r
-       return NULL;\r
-}\r
-\r
-xmlNodePtr xmlNodeGetNodeByName(\r
-               xmlNodePtr node, const char *name, const char *ns)\r
-{\r
-       xmlNodePtr cur = node;\r
-       while(cur) {\r
-               xmlNodePtr match = NULL;\r
-               if(xmlStrcasecmp(cur->name, (unsigned char *)name) == 0) {\r
-                       if(!ns || (cur->ns &&\r
-                               xmlStrcasecmp(cur->ns->prefix, (unsigned char *)ns) == 0))\r
-                       return cur;\r
-               }\r
-               match = xmlNodeGetNodeByName(cur->children, name, ns);\r
-               if(match)\r
-                       return match;\r
-               cur = cur->next;\r
-       }\r
-       return NULL;\r
-}\r
-\r
-char *xmlNodeGetNodeContentByName(\r
-               xmlNodePtr root, const char *name, const char *ns)\r
-{\r
-       xmlNodePtr node = xmlNodeGetNodeByName(root, name, ns);\r
-       if(node)\r
-               return (char *)xmlNodeGetContent(node->children);\r
-       else\r
-               return NULL;\r
-}\r
-\r
-xmlNodePtr xmlDocGetNodeByName(xmlDocPtr doc, const char *name, const char *ns)\r
-{\r
-       xmlNodePtr cur = doc->children;\r
-       return xmlNodeGetNodeByName(cur, name, ns);\r
-}\r
-\r
-char *xmlDocGetNodeContentByName(\r
-               xmlDocPtr doc, const char *name, const char *ns)\r
-{\r
-       xmlNodePtr node = xmlDocGetNodeByName(doc, name, ns);\r
-       if(node)\r
-               return (char *)xmlNodeGetContent(node->children);\r
-       else\r
-               return NULL;\r
-}\r
+/*
+ * $Id: pidf.c 1953 2007-04-04 08:50:33Z anca_vamanu $
+ *
+ * presence module - presence server implementation
+ *
+ * Copyright (C) 2006 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
+ *
+ */
+
+/*! \file
+ * \brief Kamailio lost ::  PIDF handling
+ * \ingroup lost
+ */
+
+
+/**
+ * make strptime available
+ * use 600 for 'Single UNIX Specification, Version 3'
+ * _XOPEN_SOURCE creates conflict in header definitions in Solaris
+ */
+#ifndef __OS_solaris
+#define _XOPEN_SOURCE 600 /* glibc2 on linux, bsd */
+#define _BSD_SOURCE \
+       1                                         /* needed on linux to "fix" the effect
+                                                                                 of the above define on
+                                                                                 features.h/unistd.h syscall() */
+#define _DEFAULT_SOURCE 1 /* _BSD_SOURCE is deprecated */
+#define _DARWIN_C_SOURCE 1
+#else
+#define _XOPEN_SOURCE_EXTENDED 1 /* solaris */
+#endif
+
+#include <time.h>
+
+#undef _XOPEN_SOURCE
+#undef _XOPEN_SOURCE_EXTENDED
+
+#include <string.h>
+#include <stdlib.h>
+#include <libxml/parser.h>
+
+#include "../../core/mem/mem.h"
+#include "../../core/dprint.h"
+
+#include "pidf.h"
+
+xmlAttrPtr xmlNodeGetAttrByName(xmlNodePtr node, const char *name)
+{
+       xmlAttrPtr attr = node->properties;
+       while(attr) {
+               if(xmlStrcasecmp(attr->name, (unsigned char *)name) == 0)
+                       return attr;
+               attr = attr->next;
+       }
+       return NULL;
+}
+
+char *xmlNodeGetAttrContentByName(xmlNodePtr node, const char *name)
+{
+       xmlAttrPtr attr = xmlNodeGetAttrByName(node, name);
+       if(attr)
+               return (char *)xmlNodeGetContent(attr->children);
+       else
+               return NULL;
+}
+
+xmlNodePtr xmlNodeGetChildByName(xmlNodePtr node, const char *name)
+{
+       xmlNodePtr cur = node->children;
+       while(cur) {
+               if(xmlStrcasecmp(cur->name, (unsigned char *)name) == 0)
+                       return cur;
+               cur = cur->next;
+       }
+       return NULL;
+}
+
+xmlNodePtr xmlNodeGetNodeByName(
+               xmlNodePtr node, const char *name, const char *ns)
+{
+       xmlNodePtr cur = node;
+       while(cur) {
+               xmlNodePtr match = NULL;
+               if(xmlStrcasecmp(cur->name, (unsigned char *)name) == 0) {
+                       if(!ns || (cur->ns &&
+                               xmlStrcasecmp(cur->ns->prefix, (unsigned char *)ns) == 0))
+                       return cur;
+               }
+               match = xmlNodeGetNodeByName(cur->children, name, ns);
+               if(match)
+                       return match;
+               cur = cur->next;
+       }
+       return NULL;
+}
+
+char *xmlNodeGetNodeContentByName(
+               xmlNodePtr root, const char *name, const char *ns)
+{
+       xmlNodePtr node = xmlNodeGetNodeByName(root, name, ns);
+       if(node)
+               return (char *)xmlNodeGetContent(node->children);
+       else
+               return NULL;
+}
+
+xmlNodePtr xmlDocGetNodeByName(xmlDocPtr doc, const char *name, const char *ns)
+{
+       xmlNodePtr cur = doc->children;
+       return xmlNodeGetNodeByName(cur, name, ns);
+}
+
+char *xmlDocGetNodeContentByName(
+               xmlDocPtr doc, const char *name, const char *ns)
+{
+       xmlNodePtr node = xmlDocGetNodeByName(doc, name, ns);
+       if(node)
+               return (char *)xmlNodeGetContent(node->children);
+       else
+               return NULL;
+}
index 78c5d84..c0b1e4b 100755 (executable)
@@ -1,50 +1,50 @@
-/*\r
- * $Id: pidf.h 1401 2006-12-14 11:12:42Z anca_vamanu $\r
- *\r
- * presence module - presence server implementation\r
- *\r
- * Copyright (C) 2006 Voice Sistem S.R.L.\r
- *\r
- * This file is part of Kamailio, a free SIP server.\r
- *\r
- * Kamailio is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version\r
- *\r
- * Kamailio is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
- *\r
- */\r
-\r
-/*! \file\r
- * \brief Kamailio Presence_XML :: PIDF handling\r
- * \ref pidf.c\r
- * \ingroup lost\r
- */\r
-\r
-\r
-#ifndef PIDF_H\r
-#define PIDF_H\r
-\r
-#include "../../core/str.h"\r
-#include <libxml/parser.h>\r
-\r
-xmlNodePtr xmlNodeGetNodeByName(\r
-               xmlNodePtr node, const char *name, const char *ns);\r
-xmlNodePtr xmlDocGetNodeByName(xmlDocPtr doc, const char *name, const char *ns);\r
-xmlNodePtr xmlNodeGetChildByName(xmlNodePtr node, const char *name);\r
-\r
-char *xmlDocGetNodeContentByName(\r
-               xmlDocPtr doc, const char *name, const char *ns);\r
-char *xmlNodeGetNodeContentByName(\r
-               xmlNodePtr root, const char *name, const char *ns);\r
-char *xmlNodeGetAttrContentByName(xmlNodePtr node, const char *name);\r
-\r
-#endif\r
+/*
+ * $Id: pidf.h 1401 2006-12-14 11:12:42Z anca_vamanu $
+ *
+ * presence module - presence server implementation
+ *
+ * Copyright (C) 2006 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
+ *
+ */
+
+/*! \file
+ * \brief Kamailio Presence_XML :: PIDF handling
+ * \ref pidf.c
+ * \ingroup lost
+ */
+
+
+#ifndef PIDF_H
+#define PIDF_H
+
+#include "../../core/str.h"
+#include <libxml/parser.h>
+
+xmlNodePtr xmlNodeGetNodeByName(
+               xmlNodePtr node, const char *name, const char *ns);
+xmlNodePtr xmlDocGetNodeByName(xmlDocPtr doc, const char *name, const char *ns);
+xmlNodePtr xmlNodeGetChildByName(xmlNodePtr node, const char *name);
+
+char *xmlDocGetNodeContentByName(
+               xmlDocPtr doc, const char *name, const char *ns);
+char *xmlNodeGetNodeContentByName(
+               xmlNodePtr root, const char *name, const char *ns);
+char *xmlNodeGetAttrContentByName(xmlNodePtr node, const char *name);
+
+#endif
index e40d5d4..f32de7f 100644 (file)
-/*\r
- * lost module utility functions\r
- *\r
- * Copyright (C) 2019 Wolfgang Kampichler\r
- * DEC112, FREQUENTIS AG\r
- *\r
- * This file is part of Kamailio, a free SIP server.\r
- *\r
- * Kamailio is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version\r
- *\r
- * Kamailio is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
- *\r
- */\r
-\r
-/*!\r
- * \file\r
- * \brief Kamailio lost :: utilities\r
- * \ingroup lost\r
- * Module: \ref lost\r
- */\r
-\r
-#include <stdio.h>\r
-#include <string.h>\r
-#include <stdlib.h>\r
-#include <ctype.h>\r
-#include <time.h>\r
-\r
-#include <libxml/xmlmemory.h>\r
-#include <libxml/parser.h>\r
-#include "../../core/parser/msg_parser.h"\r
-#include "../../core/parser/parse_content.h"\r
-#include "../../core/parser/parse_uri.h"\r
-#include "../../core/parser/parse_from.h"\r
-#include "../../core/parser/parse_ppi_pai.h"\r
-#include "../../core/dprint.h"\r
-#include "../../core/mem/mem.h"\r
-#include "../../core/mem/shm_mem.h"\r
-#include "../../core/rand/kam_rand.h"\r
-\r
-#include "pidf.h"\r
-#include "utilities.h"\r
-\r
-/*\r
- * lost_trim_content(dest, lgth)\r
- * removes whitespace that my occur in a content of an xml element\r
- */\r
-char *lost_trim_content(char *str, int *lgth)\r
-{\r
-       char *end;\r
-\r
-       while(isspace(*str))\r
-               str++;\r
-\r
-       if(*str == 0)\r
-               return NULL;\r
-\r
-       end = str + strlen(str) - 1;\r
-\r
-       while(end > str && isspace(*end))\r
-               end--;\r
-\r
-       *(end + 1) = '\0';\r
-\r
-       *lgth = (end + 1) - str;\r
-\r
-       return str;\r
-}\r
-\r
-/*\r
- * lost_rand_str(dest, length)\r
- * creates a random string used as temporary id in a findService request\r
- */\r
-void lost_rand_str(char *dest, size_t lgth)\r
-{\r
-       size_t index;\r
-       char charset[] = "0123456789"\r
-                                        "abcdefghijklmnopqrstuvwxyz"\r
-                                        "ABCDEFGHIJKLMNOPQRSTUVWXYZ";\r
-       kam_srand(time(NULL));\r
-       while(lgth-- > 0) {\r
-               index = (double)kam_rand() / RAND_MAX * (sizeof charset - 1);\r
-               *dest++ = charset[index];\r
-       }\r
-       *dest = '\0';\r
-}\r
-\r
-/*\r
- * lost_free_loc(ptr)\r
- * frees a location object\r
- */\r
-void lost_free_loc(p_loc_t ptr)\r
-{\r
-       pkg_free(ptr->identity);\r
-       pkg_free(ptr->urn);\r
-       pkg_free(ptr->longitude);\r
-       pkg_free(ptr->latitude);\r
-       pkg_free(ptr);\r
-}\r
-\r
-/*\r
- * lost_free_string(ptr)\r
- * frees and resets a string\r
- */\r
-void lost_free_string(str *string)\r
-{\r
-       str ptr = *string;\r
-\r
-       if(ptr.s) {\r
-               pkg_free(ptr.s);\r
-               ptr.s = NULL;\r
-               ptr.len = 0;\r
-       }\r
-}\r
-\r
-/*\r
- * lost_new_loc(urn)\r
- * creates a new location object in private memory and returns a pointer\r
- */\r
-p_loc_t lost_new_loc(str rurn)\r
-{\r
-       s_loc_t *ptr = NULL;;\r
-       char *id = NULL;\r
-       char *urn = NULL;\r
-\r
-       ptr = (s_loc_t *)pkg_malloc(sizeof(s_loc_t));\r
-       if(ptr == NULL) {\r
-               goto err;\r
-       }\r
-\r
-       id = (char *)pkg_malloc(RANDSTRSIZE * sizeof(char) + 1);\r
-       if(id == NULL) {\r
-               pkg_free(ptr);\r
-               goto err;\r
-       }\r
-\r
-       urn = (char *)pkg_malloc(rurn.len + 1);\r
-       if(urn == NULL) {\r
-               pkg_free(ptr);\r
-               pkg_free(id);\r
-               goto err;\r
-       }\r
-\r
-       memset(urn, 0, rurn.len + 1);\r
-       memcpy(urn, rurn.s, rurn.len);\r
-       urn[rurn.len] = '\0';\r
-\r
-       lost_rand_str(id, RANDSTRSIZE);\r
-\r
-       ptr->identity = id;\r
-       ptr->urn = urn;\r
-       ptr->longitude = NULL;\r
-       ptr->latitude = NULL;\r
-       ptr->radius = 0;\r
-       ptr->recursive = 0;\r
-\r
-       return ptr;\r
-\r
-err:   \r
-       LM_ERR("no more private memory\n");\r
-       return NULL;\r
-}\r
-\r
-/*\r
- * lost_get_content(node, name, lgth)\r
- * gets a nodes "name" content and returns string allocated in private memory\r
- */\r
-char *lost_get_content(xmlNodePtr node, const char *name, int *lgth)\r
-{\r
-       xmlNodePtr cur = node;\r
-       char *content;\r
-       char *cnt = NULL;\r
-       int len;\r
-\r
-       *lgth = 0;\r
-       content = xmlNodeGetNodeContentByName(cur, name, NULL);\r
-       if (content == NULL) {\r
-               LM_ERR("could not get XML node content\n");\r
-               return cnt;\r
-       } else {\r
-               len = strlen(content);\r
-               cnt = (char *)pkg_malloc((len + 1) * sizeof(char));\r
-               if(cnt == NULL) {\r
-                       LM_ERR("no more private memory\n");\r
-                       xmlFree(content);\r
-                       return cnt;\r
-               }\r
-               memset(cnt, 0, len + 1);\r
-               memcpy(cnt, content, len);\r
-               cnt[len] = '\0';\r
-       }\r
-\r
-       xmlFree(content);\r
-       *lgth = strlen(cnt);\r
-\r
-       return cnt;\r
-}\r
-\r
-/*\r
- * lost_get_property(node, name, lgth)\r
- * gets a nodes property "name" and returns string allocated in private memory\r
- */\r
-char *lost_get_property(xmlNodePtr node, const char *name, int *lgth)\r
-{\r
-       xmlNodePtr cur = node;\r
-       char *content;\r
-       char *cnt = NULL;\r
-       int len;\r
-\r
-       *lgth = 0;\r
-       content = xmlNodeGetAttrContentByName(cur, name);\r
-       if (content == NULL) {\r
-               LM_ERR("could not get XML node content\n");\r
-               return cnt;\r
-       } else {\r
-               len = strlen(content);\r
-               cnt = (char *)pkg_malloc((len + 1) * sizeof(char));\r
-               if(cnt == NULL) {\r
-                       LM_ERR("no more private memory\n");\r
-                       xmlFree(content);\r
-                       return cnt;\r
-               }\r
-               memset(cnt, 0, len + 1);\r
-               memcpy(cnt, content, len);\r
-               cnt[len] = '\0';\r
-       }\r
-\r
-       xmlFree(content);\r
-       *lgth = strlen(cnt);\r
-\r
-       return cnt;\r
-}\r
-\r
-/*\r
- * lost_get_childname(name, lgth)\r
- * gets a nodes child name and returns string allocated in private memory\r
- */\r
-char *lost_get_childname(xmlNodePtr node, const char *name, int *lgth)\r
-{\r
-       xmlNodePtr cur = node;\r
-       xmlNodePtr parent = NULL;\r
-       xmlNodePtr child = NULL;\r
-       char *cnt = NULL;\r
-       int len;\r
-\r
-       *lgth = 0;\r
-       parent = xmlNodeGetNodeByName(cur, name, NULL);\r
-       child = parent->children;\r
-\r
-       if(child) {\r
-               len = strlen((char *)child->name);\r
-               cnt = (char *)pkg_malloc((len + 1) * sizeof(char));\r
-               if(cnt == NULL) {\r
-                       LM_ERR("no more private memory\n");\r
-                       return cnt;\r
-               }\r
-\r
-               memset(cnt, 0, len + 1);\r
-               memcpy(cnt, child->name, len);\r
-               cnt[len] = '\0';\r
-\r
-               *lgth = strlen(cnt);\r
-       }\r
-       return cnt;\r
-}\r
-\r
-/*\r
- * lost_get_geolocation_header(msg, lgth)\r
- * gets the Geolocation header value and returns string allocated in\r
- * private memory\r
- */\r
-char *lost_get_geolocation_header(struct sip_msg *msg, int *lgth)\r
-{\r
-       struct hdr_field *hf;\r
-       char *res = NULL;\r
-\r
-       *lgth = 0;\r
-\r
-       if(parse_headers(msg, HDR_EOH_F, 0) == -1) {\r
-               LM_ERR("failed to parse geolocation header\n");\r
-               return res;\r
-       }\r
-\r
-       for(hf = msg->headers; hf; hf = hf->next) {\r
-               if((hf->type == HDR_OTHER_T)\r
-                               && (hf->name.len == LOST_GEOLOC_HEADER_SIZE - 2)) {\r
-                       /* possible hit */\r
-                       if(strncasecmp(\r
-                                          hf->name.s, LOST_GEOLOC_HEADER, LOST_GEOLOC_HEADER_SIZE)\r
-                                       == 0) {\r
-\r
-                               res = (char *)pkg_malloc((hf->body.len + 1) * sizeof(char));\r
-                               if(res == NULL) {\r
-                                       LM_ERR("no more private memory\n");\r
-                                       return res;\r
-                               } else {\r
-                                       memset(res, 0, hf->body.len + 1);\r
-                                       memcpy(res, hf->body.s, hf->body.len + 1);\r
-                                       res[hf->body.len] = '\0';\r
-\r
-                                       *lgth = strlen(res);\r
-                               }\r
-                       } else {\r
-                               LM_ERR("header '%.*s' length %d\n", hf->body.len, hf->body.s,\r
-                                               hf->body.len);\r
-                       }\r
-                       break;\r
-               }\r
-       }\r
-       return res;\r
-}\r
-\r
-/*\r
- * lost_get_pai_header(msg, lgth)\r
- * gets the P-A-I header value and returns string allocated in\r
- * private memory\r
- */\r
-char *lost_get_pai_header(struct sip_msg *msg, int *lgth)\r
-{\r
-       struct hdr_field *hf;\r
-       to_body_t *pai_body;\r
-       char *res = NULL;\r
-\r
-       *lgth = 0;\r
-\r
-       if (parse_headers(msg, HDR_PAI_F, 0) == -1) {\r
-               LM_ERR("could not parse P-A-I header\n");\r
-               return res;\r
-       }\r
-\r
-       for(hf = msg->headers; hf; hf = hf->next) {\r
-               if((hf->type == HDR_PAI_T)\r
-                               && (hf->name.len == LOST_PAI_HEADER_SIZE - 2)) {\r
-                       /* possible hit */\r
-                       if(strncasecmp(hf->name.s, LOST_PAI_HEADER, LOST_PAI_HEADER_SIZE)\r
-                                       == 0) {\r
-\r
-                               LM_DBG("P-A-I body:  [%.*s]\n", hf->body.len, hf->body.s);\r
-\r
-                               /* first, get some memory */\r
-                               pai_body = pkg_malloc(sizeof(to_body_t));\r
-                               if (pai_body == NULL) {\r
-                                       LM_ERR("no more private memory\n");\r
-                                       return res;\r
-                               }\r
-                               /* parse P-A-I body */\r
-                               memset(pai_body, 0, sizeof(to_body_t));\r
-                               parse_to(hf->body.s, hf->body.s + hf->body.len + 1, pai_body);\r
-                               if (pai_body->error == PARSE_ERROR) {\r
-                                       LM_ERR("bad P-A-I header\n");\r
-                                       pkg_free(pai_body);\r
-                                       return res;\r
-                               }\r
-                               if (pai_body->error == PARSE_OK) {\r
-                                       res = (char *)pkg_malloc((pai_body->uri.len + 1) * sizeof(char));\r
-                                       if(res == NULL) {\r
-                                               LM_ERR("no more private memory\n");\r
-                                               pkg_free(pai_body);\r
-                                               return res;\r
-                                       } else {\r
-                                               memset(res, 0, pai_body->uri.len + 1);\r
-                                               memcpy(res, pai_body->uri.s, pai_body->uri.len + 1);\r
-                                               res[pai_body->uri.len] = '\0';\r
-                                               pkg_free(pai_body);\r
-\r
-                                               *lgth = strlen(res);\r
-                                       }\r
-                               }\r
-                       } else {\r
-                               LM_ERR("header '%.*s' length %d\n", hf->body.len, hf->body.s,\r
-                                               hf->body.len);\r
-                       }\r
-                       break;\r
-               }\r
-       }\r
-       return res;\r
-}\r
-\r
-/*\r
- * lost_get_from_header(msg, lgth)\r
- * gets the From header value and returns string allocated in\r
- * private memory\r
- */\r
-char *lost_get_from_header(struct sip_msg *msg, int *lgth)\r
-{\r
-       to_body_t *f_body;\r
-       char *res = NULL;\r
-\r
-       *lgth = 0;\r
-\r
-       if(parse_headers(msg, HDR_FROM_F, 0) == -1) {\r
-               LM_ERR("failed to parse From header\n");\r
-               return res;\r
-       }\r
-\r
-       if(msg->from == NULL || get_from(msg) == NULL) {\r
-               LM_ERR("From header not found\n");\r
-               return res;\r
-       }\r
-       f_body = get_from(msg);\r
-\r
-       LM_DBG("From body:  [%.*s]\n", f_body->body.len, f_body->body.s);\r
-\r
-       res = (char *)pkg_malloc((f_body->uri.len + 1) * sizeof(char));\r
-       if(res == NULL) {\r
-               LM_ERR("no more private memory\n");\r
-               return res;\r
-       } else {\r
-               memset(res, 0, f_body->uri.len + 1);\r
-               memcpy(res, f_body->uri.s, f_body->uri.len + 1);\r
-               res[f_body->uri.len] = '\0';\r
-\r
-               *lgth = strlen(res);\r
-       }\r
-       return res;\r
-}\r
-\r
-/*\r
- * lost_parse_location_info(node, loc)\r
- * parses locationResponse and writes results to location object\r
- */\r
-int lost_parse_location_info(xmlNodePtr node, p_loc_t loc)\r
-{\r
-       char bufLat[BUFSIZE];\r
-       char bufLon[BUFSIZE];\r
-       int iRadius;\r
-       char *content = NULL;\r
-       int ret = -1;\r
-\r
-       xmlNodePtr cur = node;\r
-\r
-       content = xmlNodeGetNodeContentByName(cur, "pos", NULL);\r
-       if(content) {\r
-               sscanf(content, "%s %s", bufLat, bufLon);\r
-\r
-               loc->latitude = (char *)pkg_malloc(strlen((char *)bufLat) + 1);\r
-               snprintf(loc->latitude, strlen((char *)bufLat) + 1, "%s",\r
-                               (char *)bufLat);\r
-\r
-               loc->longitude = (char *)pkg_malloc(strlen((char *)bufLon) + 1);\r
-               snprintf(loc->longitude, strlen((char *)bufLon) + 1, "%s",\r
-                               (char *)bufLon);\r
-\r
-               loc->radius = 0;\r
-               ret = 0;\r
-       }\r
-\r
-       content = xmlNodeGetNodeContentByName(cur, "radius", NULL);\r
-       if(content) {\r
-               iRadius = 0;\r
-\r
-               sscanf(content, "%d", &iRadius);\r
-               loc->radius = iRadius;\r
-               ret = 0;\r
-       }\r
-\r
-       if(ret < 0) {\r
-               LM_ERR("could not parse location information\n");\r
-       }\r
-       return ret;\r
-}\r
-\r
-/*\r
- * lost_held_location_request(id, lgth)\r
- * assembles and returns locationRequest string (allocated in private memory)\r
- */\r
-char *lost_held_location_request(char *id, int *lgth)\r
-{\r
-       int buffersize = 0;\r
-\r
-       char buf[BUFSIZE];\r
-       char *doc = NULL;\r
-\r
-       xmlChar *xmlbuff = NULL;\r
-       xmlDocPtr request = NULL;\r
-\r
-       xmlNodePtr ptrLocationRequest = NULL;\r
-       xmlNodePtr ptrLocationType = NULL;\r
-       xmlNodePtr ptrDevice = NULL;\r
-\r
-       xmlKeepBlanksDefault(1);\r
-       *lgth = 0;\r
-\r
-       /*\r
-https://tools.ietf.org/html/rfc6155\r
-\r
-<?xml version="1.0" encoding="UTF-8"?>\r
-<locationRequest xmlns="urn:ietf:params:xml:ns:geopriv:held" responseTime="8">\r
-    <locationType exact="true">geodetic locationURI</locationType>\r
-    <device xmlns="urn:ietf:params:xml:ns:geopriv:held:id">\r
-        <uri>sip:user@example.net</uri>\r
-    </device>\r
-</locationRequest>\r
-*/\r
-\r
-       /* create request */\r
-       request = xmlNewDoc(BAD_CAST "1.0");\r
-       if(!request) {\r
-               LM_ERR("locationRequest xmlNewDoc() failed\n");\r
-               return doc;\r
-       }\r
-       /* locationRequest - element */\r
-       ptrLocationRequest = xmlNewNode(NULL, BAD_CAST "locationRequest");\r
-       if(!ptrLocationRequest) {\r
-               LM_ERR("locationRequest xmlNewNode() failed\n");\r
-               xmlFreeDoc(request);\r
-               return doc;\r
-       }\r
-       xmlDocSetRootElement(request, ptrLocationRequest);\r
-       /* properties */\r
-       xmlNewProp(ptrLocationRequest, BAD_CAST "xmlns",\r
-                       BAD_CAST "urn:ietf:params:xml:ns:geopriv:held");\r
-       xmlNewProp(ptrLocationRequest, BAD_CAST "responseTime", BAD_CAST "8");\r
-       /* locationType - element */\r
-       ptrLocationType = xmlNewChild(ptrLocationRequest, NULL,\r
-                       BAD_CAST "locationType", BAD_CAST "geodetic locationURI");\r
-       /* properties */\r
-       xmlNewProp(ptrLocationType, BAD_CAST "exact", BAD_CAST "false");\r
-       /* device - element */\r
-       ptrDevice = xmlNewChild(ptrLocationRequest, NULL, BAD_CAST "device", NULL);\r
-       if(!ptrDevice) {\r
-               LM_ERR("locationRequest xmlNewChild() failed\n");\r
-               xmlFreeDoc(request);\r
-               return doc;\r
-       }\r
-       /* properties */\r
-       xmlNewProp(ptrDevice, BAD_CAST "xmlns",\r
-                       BAD_CAST "urn:ietf:params:xml:ns:geopriv:held:id");\r
-       /* uri - element */\r
-       snprintf(buf, BUFSIZE, "%s", id);\r
-       xmlNewChild(ptrDevice, NULL, BAD_CAST "uri", BAD_CAST buf);\r
-\r
-       xmlDocDumpFormatMemory(request, &xmlbuff, &buffersize, 0);\r
-       if(!xmlbuff) {\r
-               LM_ERR("locationRequest xmlDocDumpFormatMemory() failed\n");\r
-               xmlFreeDoc(request);\r
-               return doc;\r
-       }\r
-\r
-       doc = (char *)pkg_malloc((buffersize + 1) * sizeof(char));\r
-       if(doc == NULL) {\r
-               LM_ERR("no more private memory\n");\r
-               xmlFree(xmlbuff);\r
-               xmlFreeDoc(request);\r
-               return doc;\r
-       }\r
-\r
-       memset(doc, 0, buffersize + 1);\r
-       memcpy(doc, (char *)xmlbuff, buffersize);\r
-       doc[buffersize] = '\0';\r
-\r
-       *lgth = strlen(doc);\r
-\r
-       xmlFree(xmlbuff);\r
-       xmlFreeDoc(request);\r
-\r
-       return doc;\r
-}\r
-\r
-/*\r
- * lost_find_service_request(loc, lgth)\r
- * assembles and returns findService request string (allocated in private memory)\r
- */\r
-char *lost_find_service_request(p_loc_t loc, int *lgth)\r
-{\r
-       int buffersize = 0;\r
-\r
-       char buf[BUFSIZE];\r
-       char *doc = NULL;\r
-\r
-       xmlChar *xmlbuff = NULL;\r
-       xmlDocPtr request = NULL;\r
-\r
-       xmlNodePtr ptrFindService = NULL;\r
-       xmlNodePtr ptrLocation = NULL;\r
-       xmlNodePtr ptrPoint = NULL;\r
-       xmlNodePtr ptrCircle = NULL;\r
-       xmlNodePtr ptrRadius = NULL;\r
-\r
-       xmlKeepBlanksDefault(1);\r
-       *lgth = 0;\r
-\r
-       /*\r
-https://tools.ietf.org/html/rfc5222\r
-\r
-<?xml version="1.0" encoding="UTF-8"?>\r
-<findService\r
- xmlns="urn:ietf:params:xml:ns:lost1"\r
- xmlns:p2="http://www.opengis.net/gml"\r
- serviceBoundary="value"\r
- recursive="true">\r
-    <location id="6020688f1ce1896d" profile="geodetic-2d">\r
-        <p2:Point id="point1" srsName="urn:ogc:def:crs:EPSG::4326">\r
-            <p2:pos>37.775 -122.422</p2:pos>\r
-        </p2:Point>\r
-    </location>\r
-    <service>urn:service:sos.police</service>\r
-</findService>\r
- */\r
-       /* create request */\r
-       request = xmlNewDoc(BAD_CAST "1.0");\r
-       if(!request) {\r
-               LM_ERR("findService request xmlNewDoc() failed\n");\r
-               return doc;\r
-       }\r
-       /* findService - element */\r
-       ptrFindService = xmlNewNode(NULL, BAD_CAST "findService");\r
-       if(!ptrFindService) {\r
-               LM_ERR("findService xmlNewNode() failed\n");\r
-               xmlFreeDoc(request);\r
-               return doc;\r
-       }\r
-       xmlDocSetRootElement(request, ptrFindService);\r
-       /* set properties */\r
-       xmlNewProp(ptrFindService, BAD_CAST "xmlns",\r
-                       BAD_CAST "urn:ietf:params:xml:ns:lost1");\r
-       xmlNewProp(ptrFindService, BAD_CAST "xmlns:p2",\r
-                       BAD_CAST "http://www.opengis.net/gml");\r
-       xmlNewProp(\r
-                       ptrFindService, BAD_CAST "serviceBoundary", BAD_CAST "reference");\r
-       xmlNewProp(ptrFindService, BAD_CAST "recursive", BAD_CAST "true");\r
-       /* location - element */\r
-       ptrLocation = xmlNewChild(ptrFindService, NULL, BAD_CAST "location", NULL);\r
-       xmlNewProp(ptrLocation, BAD_CAST "id", BAD_CAST loc->identity);\r
-       xmlNewProp(ptrLocation, BAD_CAST "profile", BAD_CAST "geodetic-2d");\r
-       /* set pos */\r
-       snprintf(buf, BUFSIZE, "%s %s", loc->latitude, loc->longitude);\r
-       /* Point */\r
-       if(loc->radius == 0) {\r
-               ptrPoint = xmlNewChild(ptrLocation, NULL, BAD_CAST "Point", NULL);\r
-               if(!ptrPoint) {\r
-                       LM_ERR("locationRequest xmlNewChild() failed\n");\r
-                       xmlFreeDoc(request);\r
-                       return doc;\r
-               }\r
-               xmlNewProp(ptrPoint, BAD_CAST "xmlns",\r
-                               BAD_CAST "http://www.opengis.net/gml");\r
-               xmlNewProp(ptrPoint, BAD_CAST "srsName",\r
-                               BAD_CAST "urn:ogc:def:crs:EPSG::4326");\r
-               /* pos */\r
-               xmlNewChild(ptrPoint, NULL, BAD_CAST "pos", BAD_CAST buf);\r
-       } else {\r
-               /* circle - Point */\r
-               ptrCircle = xmlNewChild(ptrLocation, NULL, BAD_CAST "gs:Circle", NULL);\r
-               if(!ptrCircle) {\r
-                       LM_ERR("locationRequest xmlNewChild() failed\n");\r
-                       xmlFreeDoc(request);\r
-                       return doc;\r
-               }\r
-               xmlNewProp(ptrCircle, BAD_CAST "xmlns:gml",\r
-                               BAD_CAST "http://www.opengis.net/gml");\r
-               xmlNewProp(ptrCircle, BAD_CAST "xmlns:gs",\r
-                               BAD_CAST "http://www.opengis.net/pidflo/1.0");\r
-               xmlNewProp(ptrCircle, BAD_CAST "srsName",\r
-                               BAD_CAST "urn:ogc:def:crs:EPSG::4326");\r
-               /* pos */\r
-               xmlNewChild(ptrCircle, NULL, BAD_CAST "gml:pos", BAD_CAST buf);\r
-               /* circle - radius */\r
-               snprintf(buf, BUFSIZE, "%d", loc->radius);\r
-               ptrRadius = xmlNewChild(\r
-                               ptrCircle, NULL, BAD_CAST "gs:radius", BAD_CAST buf);\r
-               if(!ptrRadius) {\r
-                       LM_ERR("locationRequest xmlNewChild() failed\n");\r
-                       xmlFreeDoc(request);\r
-                       return doc;\r
-               }\r
-               xmlNewProp(ptrRadius, BAD_CAST "uom",\r
-                               BAD_CAST "urn:ogc:def:uom:EPSG::9001");\r
-       }\r
-       /* service - element */\r
-       snprintf(buf, BUFSIZE, "%s", loc->urn);\r
-       xmlNewChild(ptrFindService, NULL, BAD_CAST "service", BAD_CAST buf);\r
-\r
-       xmlDocDumpFormatMemory(request, &xmlbuff, &buffersize, 0);\r
-       if(!xmlbuff) {\r
-               LM_ERR("findService request xmlDocDumpFormatMemory() failed\n");\r
-               xmlFreeDoc(request);\r
-               return doc;\r
-       }\r
-\r
-       doc = (char *)pkg_malloc((buffersize + 1) * sizeof(char));\r
-       if(doc == NULL) {\r
-               LM_ERR("no more private memory\n");\r
-               xmlFree(xmlbuff);\r
-               xmlFreeDoc(request);\r
-               return doc;\r
-       }\r
-\r
-       memset(doc, 0, buffersize + 1);\r
-       memcpy(doc, (char *)xmlbuff, buffersize);\r
-       doc[buffersize] = '\0';\r
-\r
-       *lgth = strlen(doc);\r
-\r
-       xmlFree(xmlbuff);\r
-       xmlFreeDoc(request);\r
-\r
-       return doc;\r
-}\r
+/*
+ * lost module utility functions
+ *
+ * Copyright (C) 2019 Wolfgang Kampichler
+ * DEC112, FREQUENTIS AG
+ *
+ * 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
+ *
+ */
+
+/*!
+ * \file
+ * \brief Kamailio lost :: utilities
+ * \ingroup lost
+ * Module: \ref lost
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include "../../core/parser/msg_parser.h"
+#include "../../core/parser/parse_content.h"
+#include "../../core/parser/parse_uri.h"
+#include "../../core/parser/parse_from.h"
+#include "../../core/parser/parse_ppi_pai.h"
+#include "../../core/dprint.h"
+#include "../../core/mem/mem.h"
+#include "../../core/mem/shm_mem.h"
+#include "../../core/rand/kam_rand.h"
+
+#include "pidf.h"
+#include "utilities.h"
+
+/*
+ * lost_trim_content(dest, lgth)
+ * removes whitespace that my occur in a content of an xml element
+ */
+char *lost_trim_content(char *str, int *lgth)
+{
+       char *end;
+
+       while(isspace(*str))
+               str++;
+
+       if(*str == 0)
+               return NULL;
+
+       end = str + strlen(str) - 1;
+
+       while(end > str && isspace(*end))
+               end--;
+
+       *(end + 1) = '\0';
+
+       *lgth = (end + 1) - str;
+
+       return str;
+}
+
+/*
+ * lost_rand_str(dest, length)
+ * creates a random string used as temporary id in a findService request
+ */
+void lost_rand_str(char *dest, size_t lgth)
+{
+       size_t index;
+       char charset[] = "0123456789"
+                                        "abcdefghijklmnopqrstuvwxyz"
+                                        "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+       kam_srand(time(NULL));
+       while(lgth-- > 0) {
+               index = (double)kam_rand() / RAND_MAX * (sizeof charset - 1);
+               *dest++ = charset[index];
+       }
+       *dest = '\0';
+}
+
+/*
+ * lost_free_loc(ptr)
+ * frees a location object
+ */
+void lost_free_loc(p_loc_t ptr)
+{
+       pkg_free(ptr->identity);
+       pkg_free(ptr->urn);
+       pkg_free(ptr->longitude);
+       pkg_free(ptr->latitude);
+       pkg_free(ptr);
+}
+
+/*
+ * lost_free_string(ptr)
+ * frees and resets a string
+ */
+void lost_free_string(str *string)
+{
+       str ptr = *string;
+
+       if(ptr.s) {
+               pkg_free(ptr.s);
+               ptr.s = NULL;
+               ptr.len = 0;
+       }
+}
+
+/*
+ * lost_new_loc(urn)
+ * creates a new location object in private memory and returns a pointer
+ */
+p_loc_t lost_new_loc(str rurn)
+{
+       s_loc_t *ptr = NULL;;
+       char *id = NULL;
+       char *urn = NULL;
+
+       ptr = (s_loc_t *)pkg_malloc(sizeof(s_loc_t));
+       if(ptr == NULL) {
+               goto err;
+       }
+
+       id = (char *)pkg_malloc(RANDSTRSIZE * sizeof(char) + 1);
+       if(id == NULL) {
+               pkg_free(ptr);
+               goto err;
+       }
+
+       urn = (char *)pkg_malloc(rurn.len + 1);
+       if(urn == NULL) {
+               pkg_free(ptr);
+               pkg_free(id);
+               goto err;
+       }
+
+       memset(urn, 0, rurn.len + 1);
+       memcpy(urn, rurn.s, rurn.len);
+       urn[rurn.len] = '\0';
+
+       lost_rand_str(id, RANDSTRSIZE);
+
+       ptr->identity = id;
+       ptr->urn = urn;
+       ptr->longitude = NULL;
+       ptr->latitude = NULL;
+       ptr->radius = 0;
+       ptr->recursive = 0;
+
+       return ptr;
+
+err:   
+       LM_ERR("no more private memory\n");
+       return NULL;
+}
+
+/*
+ * lost_get_content(node, name, lgth)
+ * gets a nodes "name" content and returns string allocated in private memory
+ */
+char *lost_get_content(xmlNodePtr node, const char *name, int *lgth)
+{
+       xmlNodePtr cur = node;
+       char *content;
+       char *cnt = NULL;
+       int len;
+
+       *lgth = 0;
+       content = xmlNodeGetNodeContentByName(cur, name, NULL);
+       if (content == NULL) {
+               LM_ERR("could not get XML node content\n");
+               return cnt;
+       } else {
+               len = strlen(content);
+               cnt = (char *)pkg_malloc((len + 1) * sizeof(char));
+               if(cnt == NULL) {
+                       LM_ERR("no more private memory\n");
+                       xmlFree(content);
+                       return cnt;
+               }
+               memset(cnt, 0, len + 1);
+               memcpy(cnt, content, len);
+               cnt[len] = '\0';
+       }
+
+       xmlFree(content);
+       *lgth = strlen(cnt);
+
+       return cnt;
+}
+
+/*
+ * lost_get_property(node, name, lgth)
+ * gets a nodes property "name" and returns string allocated in private memory
+ */
+char *lost_get_property(xmlNodePtr node, const char *name, int *lgth)
+{
+       xmlNodePtr cur = node;
+       char *content;
+       char *cnt = NULL;
+       int len;
+
+       *lgth = 0;
+       content = xmlNodeGetAttrContentByName(cur, name);
+       if (content == NULL) {
+               LM_ERR("could not get XML node content\n");
+               return cnt;
+       } else {
+               len = strlen(content);
+               cnt = (char *)pkg_malloc((len + 1) * sizeof(char));
+               if(cnt == NULL) {
+                       LM_ERR("no more private memory\n");
+                       xmlFree(content);
+                       return cnt;
+               }
+               memset(cnt, 0, len + 1);
+               memcpy(cnt, content, len);
+               cnt[len] = '\0';
+       }
+
+       xmlFree(content);
+       *lgth = strlen(cnt);
+
+       return cnt;
+}
+
+/*
+ * lost_get_childname(name, lgth)
+ * gets a nodes child name and returns string allocated in private memory
+ */
+char *lost_get_childname(xmlNodePtr node, const char *name, int *lgth)
+{
+       xmlNodePtr cur = node;
+       xmlNodePtr parent = NULL;
+       xmlNodePtr child = NULL;
+       char *cnt = NULL;
+       int len;
+
+       *lgth = 0;
+       parent = xmlNodeGetNodeByName(cur, name, NULL);
+       child = parent->children;
+
+       if(child) {
+               len = strlen((char *)child->name);
+               cnt = (char *)pkg_malloc((len + 1) * sizeof(char));
+               if(cnt == NULL) {
+                       LM_ERR("no more private memory\n");
+                       return cnt;
+               }
+
+               memset(cnt, 0, len + 1);
+               memcpy(cnt, child->name, len);
+               cnt[len] = '\0';
+
+               *lgth = strlen(cnt);
+       }
+       return cnt;
+}
+
+/*
+ * lost_get_geolocation_header(msg, lgth)
+ * gets the Geolocation header value and returns string allocated in
+ * private memory
+ */
+char *lost_get_geolocation_header(struct sip_msg *msg, int *lgth)
+{
+       struct hdr_field *hf;
+       char *res = NULL;
+
+       *lgth = 0;
+
+       if(parse_headers(msg, HDR_EOH_F, 0) == -1) {
+               LM_ERR("failed to parse geolocation header\n");
+               return res;
+       }
+
+       for(hf = msg->headers; hf; hf = hf->next) {
+               if((hf->type == HDR_OTHER_T)
+                               && (hf->name.len == LOST_GEOLOC_HEADER_SIZE - 2)) {
+                       /* possible hit */
+                       if(strncasecmp(
+                                          hf->name.s, LOST_GEOLOC_HEADER, LOST_GEOLOC_HEADER_SIZE)
+                                       == 0) {
+
+                               res = (char *)pkg_malloc((hf->body.len + 1) * sizeof(char));
+                               if(res == NULL) {
+                                       LM_ERR("no more private memory\n");
+                                       return res;
+                               } else {
+                                       memset(res, 0, hf->body.len + 1);
+                                       memcpy(res, hf->body.s, hf->body.len + 1);
+                                       res[hf->body.len] = '\0';
+
+                                       *lgth = strlen(res);
+                               }
+                       } else {
+                               LM_ERR("header '%.*s' length %d\n", hf->body.len, hf->body.s,
+                                               hf->body.len);
+                       }
+                       break;
+               }
+       }
+       return res;
+}
+
+/*
+ * lost_get_pai_header(msg, lgth)
+ * gets the P-A-I header value and returns string allocated in
+ * private memory
+ */
+char *lost_get_pai_header(struct sip_msg *msg, int *lgth)
+{
+       struct hdr_field *hf;
+       to_body_t *pai_body;
+       char *res = NULL;
+
+       *lgth = 0;
+
+       if (parse_headers(msg, HDR_PAI_F, 0) == -1) {
+               LM_ERR("could not parse P-A-I header\n");
+               return res;
+       }
+
+       for(hf = msg->headers; hf; hf = hf->next) {
+               if((hf->type == HDR_PAI_T)
+                               && (hf->name.len == LOST_PAI_HEADER_SIZE - 2)) {
+                       /* possible hit */
+                       if(strncasecmp(hf->name.s, LOST_PAI_HEADER, LOST_PAI_HEADER_SIZE)
+                                       == 0) {
+
+                               LM_DBG("P-A-I body:  [%.*s]\n", hf->body.len, hf->body.s);
+
+                               /* first, get some memory */
+                               pai_body = pkg_malloc(sizeof(to_body_t));
+                               if (pai_body == NULL) {
+                                       LM_ERR("no more private memory\n");
+                                       return res;
+                               }
+                               /* parse P-A-I body */
+                               memset(pai_body, 0, sizeof(to_body_t));
+                               parse_to(hf->body.s, hf->body.s + hf->body.len + 1, pai_body);
+                               if (pai_body->error == PARSE_ERROR) {
+                                       LM_ERR("bad P-A-I header\n");
+                                       pkg_free(pai_body);
+                                       return res;
+                               }
+                               if (pai_body->error == PARSE_OK) {
+                                       res = (char *)pkg_malloc((pai_body->uri.len + 1) * sizeof(char));
+                                       if(res == NULL) {
+                                               LM_ERR("no more private memory\n");
+                                               pkg_free(pai_body);
+                                               return res;
+                                       } else {
+                                               memset(res, 0, pai_body->uri.len + 1);
+                                               memcpy(res, pai_body->uri.s, pai_body->uri.len + 1);
+                                               res[pai_body->uri.len] = '\0';
+                                               pkg_free(pai_body);
+
+                                               *lgth = strlen(res);
+                                       }
+                               }
+                       } else {
+                               LM_ERR("header '%.*s' length %d\n", hf->body.len, hf->body.s,
+                                               hf->body.len);
+                       }
+                       break;
+               }
+       }
+       return res;
+}
+
+/*
+ * lost_get_from_header(msg, lgth)
+ * gets the From header value and returns string allocated in
+ * private memory
+ */
+char *lost_get_from_header(struct sip_msg *msg, int *lgth)
+{
+       to_body_t *f_body;
+       char *res = NULL;
+
+       *lgth = 0;
+
+       if(parse_headers(msg, HDR_FROM_F, 0) == -1) {
+               LM_ERR("failed to parse From header\n");
+               return res;
+       }
+
+       if(msg->from == NULL || get_from(msg) == NULL) {
+               LM_ERR("From header not found\n");
+               return res;
+       }
+       f_body = get_from(msg);
+
+       LM_DBG("From body:  [%.*s]\n", f_body->body.len, f_body->body.s);
+
+       res = (char *)pkg_malloc((f_body->uri.len + 1) * sizeof(char));
+       if(res == NULL) {
+               LM_ERR("no more private memory\n");
+               return res;
+       } else {
+               memset(res, 0, f_body->uri.len + 1);
+               memcpy(res, f_body->uri.s, f_body->uri.len + 1);
+               res[f_body->uri.len] = '\0';
+
+               *lgth = strlen(res);
+       }
+       return res;
+}
+
+/*
+ * lost_parse_location_info(node, loc)
+ * parses locationResponse and writes results to location object
+ */
+int lost_parse_location_info(xmlNodePtr node, p_loc_t loc)
+{
+       char bufLat[BUFSIZE];
+       char bufLon[BUFSIZE];
+       int iRadius;
+       char *content = NULL;
+       int ret = -1;
+
+       xmlNodePtr cur = node;
+
+       content = xmlNodeGetNodeContentByName(cur, "pos", NULL);
+       if(content) {
+               sscanf(content, "%s %s", bufLat, bufLon);
+
+               loc->latitude = (char *)pkg_malloc(strlen((char *)bufLat) + 1);
+               snprintf(loc->latitude, strlen((char *)bufLat) + 1, "%s",
+                               (char *)bufLat);
+
+               loc->longitude = (char *)pkg_malloc(strlen((char *)bufLon) + 1);
+               snprintf(loc->longitude, strlen((char *)bufLon) + 1, "%s",
+                               (char *)bufLon);
+
+               loc->radius = 0;
+               ret = 0;
+       }
+
+       content = xmlNodeGetNodeContentByName(cur, "radius", NULL);
+       if(content) {
+               iRadius = 0;
+
+               sscanf(content, "%d", &iRadius);
+               loc->radius = iRadius;
+               ret = 0;
+       }
+
+       if(ret < 0) {
+               LM_ERR("could not parse location information\n");
+       }
+       return ret;
+}
+
+/*
+ * lost_held_location_request(id, lgth)
+ * assembles and returns locationRequest string (allocated in private memory)
+ */
+char *lost_held_location_request(char *id, int *lgth)
+{
+       int buffersize = 0;
+
+       char buf[BUFSIZE];
+       char *doc = NULL;
+
+       xmlChar *xmlbuff = NULL;
+       xmlDocPtr request = NULL;
+
+       xmlNodePtr ptrLocationRequest = NULL;
+       xmlNodePtr ptrLocationType = NULL;
+       xmlNodePtr ptrDevice = NULL;
+
+       xmlKeepBlanksDefault(1);
+       *lgth = 0;
+
+       /*
+https://tools.ietf.org/html/rfc6155
+
+<?xml version="1.0" encoding="UTF-8"?>
+<locationRequest xmlns="urn:ietf:params:xml:ns:geopriv:held" responseTime="8">
+    <locationType exact="true">geodetic locationURI</locationType>
+    <device xmlns="urn:ietf:params:xml:ns:geopriv:held:id">
+        <uri>sip:user@example.net</uri>
+    </device>
+</locationRequest>
+*/
+
+       /* create request */
+       request = xmlNewDoc(BAD_CAST "1.0");
+       if(!request) {
+               LM_ERR("locationRequest xmlNewDoc() failed\n");
+               return doc;
+       }
+       /* locationRequest - element */
+       ptrLocationRequest = xmlNewNode(NULL, BAD_CAST "locationRequest");
+       if(!ptrLocationRequest) {
+               LM_ERR("locationRequest xmlNewNode() failed\n");
+               xmlFreeDoc(request);
+               return doc;
+       }
+       xmlDocSetRootElement(request, ptrLocationRequest);
+       /* properties */
+       xmlNewProp(ptrLocationRequest, BAD_CAST "xmlns",
+                       BAD_CAST "urn:ietf:params:xml:ns:geopriv:held");
+       xmlNewProp(ptrLocationRequest, BAD_CAST "responseTime", BAD_CAST "8");
+       /* locationType - element */
+       ptrLocationType = xmlNewChild(ptrLocationRequest, NULL,
+                       BAD_CAST "locationType", BAD_CAST "geodetic locationURI");
+       /* properties */
+       xmlNewProp(ptrLocationType, BAD_CAST "exact", BAD_CAST "false");
+       /* device - element */
+       ptrDevice = xmlNewChild(ptrLocationRequest, NULL, BAD_CAST "device", NULL);
+       if(!ptrDevice) {
+               LM_ERR("locationRequest xmlNewChild() failed\n");
+               xmlFreeDoc(request);
+               return doc;
+       }
+       /* properties */
+       xmlNewProp(ptrDevice, BAD_CAST "xmlns",
+                       BAD_CAST "urn:ietf:params:xml:ns:geopriv:held:id");
+       /* uri - element */
+       snprintf(buf, BUFSIZE, "%s", id);
+       xmlNewChild(ptrDevice, NULL, BAD_CAST "uri", BAD_CAST buf);
+
+       xmlDocDumpFormatMemory(request, &xmlbuff, &buffersize, 0);
+       if(!xmlbuff) {
+               LM_ERR("locationRequest xmlDocDumpFormatMemory() failed\n");
+               xmlFreeDoc(request);
+               return doc;
+       }
+
+       doc = (char *)pkg_malloc((buffersize + 1) * sizeof(char));
+       if(doc == NULL) {
+               LM_ERR("no more private memory\n");
+               xmlFree(xmlbuff);
+               xmlFreeDoc(request);
+               return doc;
+       }
+
+       memset(doc, 0, buffersize + 1);
+       memcpy(doc, (char *)xmlbuff, buffersize);
+       doc[buffersize] = '\0';
+
+       *lgth = strlen(doc);
+
+       xmlFree(xmlbuff);
+       xmlFreeDoc(request);
+
+       return doc;
+}
+
+/*
+ * lost_find_service_request(loc, lgth)
+ * assembles and returns findService request string (allocated in private memory)
+ */
+char *lost_find_service_request(p_loc_t loc, int *lgth)
+{
+       int buffersize = 0;
+
+       char buf[BUFSIZE];
+       char *doc = NULL;
+
+       xmlChar *xmlbuff = NULL;
+       xmlDocPtr request = NULL;
+
+       xmlNodePtr ptrFindService = NULL;
+       xmlNodePtr ptrLocation = NULL;
+       xmlNodePtr ptrPoint = NULL;
+       xmlNodePtr ptrCircle = NULL;
+       xmlNodePtr ptrRadius = NULL;
+
+       xmlKeepBlanksDefault(1);
+       *lgth = 0;
+
+       /*
+https://tools.ietf.org/html/rfc5222
+
+<?xml version="1.0" encoding="UTF-8"?>
+<findService
+ xmlns="urn:ietf:params:xml:ns:lost1"
+ xmlns:p2="http://www.opengis.net/gml"
+ serviceBoundary="value"
+ recursive="true">
+    <location id="6020688f1ce1896d" profile="geodetic-2d">
+        <p2:Point id="point1" srsName="urn:ogc:def:crs:EPSG::4326">
+            <p2:pos>37.775 -122.422</p2:pos>
+        </p2:Point>
+    </location>
+    <service>urn:service:sos.police</service>
+</findService>
+ */
+       /* create request */
+       request = xmlNewDoc(BAD_CAST "1.0");
+       if(!request) {
+               LM_ERR("findService request xmlNewDoc() failed\n");
+               return doc;
+       }
+       /* findService - element */
+       ptrFindService = xmlNewNode(NULL, BAD_CAST "findService");
+       if(!ptrFindService) {
+               LM_ERR("findService xmlNewNode() failed\n");
+               xmlFreeDoc(request);
+               return doc;
+       }
+       xmlDocSetRootElement(request, ptrFindService);
+       /* set properties */
+       xmlNewProp(ptrFindService, BAD_CAST "xmlns",
+                       BAD_CAST "urn:ietf:params:xml:ns:lost1");
+       xmlNewProp(ptrFindService, BAD_CAST "xmlns:p2",
+                       BAD_CAST "http://www.opengis.net/gml");
+       xmlNewProp(
+                       ptrFindService, BAD_CAST "serviceBoundary", BAD_CAST "reference");
+       xmlNewProp(ptrFindService, BAD_CAST "recursive", BAD_CAST "true");
+       /* location - element */
+       ptrLocation = xmlNewChild(ptrFindService, NULL, BAD_CAST "location", NULL);
+       xmlNewProp(ptrLocation, BAD_CAST "id", BAD_CAST loc->identity);
+       xmlNewProp(ptrLocation, BAD_CAST "profile", BAD_CAST "geodetic-2d");
+       /* set pos */
+       snprintf(buf, BUFSIZE, "%s %s", loc->latitude, loc->longitude);
+       /* Point */
+       if(loc->radius == 0) {
+               ptrPoint = xmlNewChild(ptrLocation, NULL, BAD_CAST "Point", NULL);
+               if(!ptrPoint) {
+                       LM_ERR("locationRequest xmlNewChild() failed\n");
+                       xmlFreeDoc(request);
+                       return doc;
+               }
+               xmlNewProp(ptrPoint, BAD_CAST "xmlns",
+                               BAD_CAST "http://www.opengis.net/gml");
+               xmlNewProp(ptrPoint, BAD_CAST "srsName",
+                               BAD_CAST "urn:ogc:def:crs:EPSG::4326");
+               /* pos */
+               xmlNewChild(ptrPoint, NULL, BAD_CAST "pos", BAD_CAST buf);
+       } else {
+               /* circle - Point */
+               ptrCircle = xmlNewChild(ptrLocation, NULL, BAD_CAST "gs:Circle", NULL);
+               if(!ptrCircle) {
+                       LM_ERR("locationRequest xmlNewChild() failed\n");
+                       xmlFreeDoc(request);
+                       return doc;
+               }
+               xmlNewProp(ptrCircle, BAD_CAST "xmlns:gml",
+                               BAD_CAST "http://www.opengis.net/gml");
+               xmlNewProp(ptrCircle, BAD_CAST "xmlns:gs",
+                               BAD_CAST "http://www.opengis.net/pidflo/1.0");
+               xmlNewProp(ptrCircle, BAD_CAST "srsName",
+                               BAD_CAST "urn:ogc:def:crs:EPSG::4326");
+               /* pos */
+               xmlNewChild(ptrCircle, NULL, BAD_CAST "gml:pos", BAD_CAST buf);
+               /* circle - radius */
+               snprintf(buf, BUFSIZE, "%d", loc->radius);
+               ptrRadius = xmlNewChild(
+                               ptrCircle, NULL, BAD_CAST "gs:radius", BAD_CAST buf);
+               if(!ptrRadius) {
+                       LM_ERR("locationRequest xmlNewChild() failed\n");
+                       xmlFreeDoc(request);
+                       return doc;
+               }
+               xmlNewProp(ptrRadius, BAD_CAST "uom",
+                               BAD_CAST "urn:ogc:def:uom:EPSG::9001");
+       }
+       /* service - element */
+       snprintf(buf, BUFSIZE, "%s", loc->urn);
+       xmlNewChild(ptrFindService, NULL, BAD_CAST "service", BAD_CAST buf);
+
+       xmlDocDumpFormatMemory(request, &xmlbuff, &buffersize, 0);
+       if(!xmlbuff) {
+               LM_ERR("findService request xmlDocDumpFormatMemory() failed\n");
+               xmlFreeDoc(request);
+               return doc;
+       }
+
+       doc = (char *)pkg_malloc((buffersize + 1) * sizeof(char));
+       if(doc == NULL) {
+               LM_ERR("no more private memory\n");
+               xmlFree(xmlbuff);
+               xmlFreeDoc(request);
+               return doc;
+       }
+
+       memset(doc, 0, buffersize + 1);
+       memcpy(doc, (char *)xmlbuff, buffersize);
+       doc[buffersize] = '\0';
+
+       *lgth = strlen(doc);
+
+       xmlFree(xmlbuff);
+       xmlFreeDoc(request);
+
+       return doc;
+}
index 6872214..cb8f529 100644 (file)
@@ -1,76 +1,76 @@
-/*\r
- * lost module utility functions\r
- *\r
- * Copyright (C) 2019 Wolfgang Kampichler\r
- * DEC112, FREQUENTIS AG\r
- *\r
- * This file is part of Kamailio, a free SIP server.\r
- *\r
- * Kamailio is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version\r
- *\r
- * Kamailio is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
- *\r
- */\r
-\r
-/*!\r
- * \file\r
- * \brief Kamailio lost :: functions\r
- * \ingroup lost\r
- * Module: \ref lost\r
- */\r
-\r
-#ifndef LOST_UTILITIES_H\r
-#define LOST_UTILITIES_H\r
-\r
-#define LOST_GEOLOC_HEADER "Geolocation: "\r
-#define LOST_GEOLOC_HEADER_SIZE strlen(LOST_GEOLOC_HEADER)\r
-#define LOST_PAI_HEADER "P-Asserted-Identity: "\r
-#define LOST_PAI_HEADER_SIZE strlen(LOST_PAI_HEADER)\r
-\r
-#define BUFSIZE 128    /* temporary buffer to hold geolocation */\r
-#define RANDSTRSIZE 16 /* temporary id in a findService request */\r
-\r
-#define LOSTFREE(x) pkg_free(x); x = NULL;\r
-\r
-typedef struct\r
-{\r
-       char *identity;\r
-       char *urn;\r
-       char *longitude;\r
-       char *latitude;\r
-       char *uri;\r
-       char *ref;\r
-       int radius;\r
-       int recursive;\r
-} s_loc_t, *p_loc_t;\r
-\r
-void lost_rand_str(char *, size_t);\r
-void lost_free_loc(p_loc_t);\r
-void lost_free_string(str *);\r
-\r
-int lost_get_location_object(p_loc_t, xmlDocPtr, xmlNodePtr);\r
-int lost_parse_location_info(xmlNodePtr node, p_loc_t loc);\r
-\r
-char *lost_find_service_request(p_loc_t, int *);\r
-char *lost_held_location_request(char *, int *);\r
-char *lost_get_content(xmlNodePtr, const char *, int *);\r
-char *lost_get_property(xmlNodePtr, const char *, int *);\r
-char *lost_get_geolocation_header(struct sip_msg *, int *);\r
-char *lost_get_from_header(struct sip_msg *, int *);\r
-char *lost_get_pai_header(struct sip_msg *, int *);\r
-char *lost_get_childname(xmlNodePtr, const char *, int *);\r
-char *lost_trim_content(char *, int *);\r
-\r
-p_loc_t lost_new_loc(str);\r
-\r
-#endif\r
+/*
+ * lost module utility functions
+ *
+ * Copyright (C) 2019 Wolfgang Kampichler
+ * DEC112, FREQUENTIS AG
+ *
+ * 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
+ *
+ */
+
+/*!
+ * \file
+ * \brief Kamailio lost :: functions
+ * \ingroup lost
+ * Module: \ref lost
+ */
+
+#ifndef LOST_UTILITIES_H
+#define LOST_UTILITIES_H
+
+#define LOST_GEOLOC_HEADER "Geolocation: "
+#define LOST_GEOLOC_HEADER_SIZE strlen(LOST_GEOLOC_HEADER)
+#define LOST_PAI_HEADER "P-Asserted-Identity: "
+#define LOST_PAI_HEADER_SIZE strlen(LOST_PAI_HEADER)
+
+#define BUFSIZE 128    /* temporary buffer to hold geolocation */
+#define RANDSTRSIZE 16 /* temporary id in a findService request */
+
+#define LOSTFREE(x) pkg_free(x); x = NULL;
+
+typedef struct
+{
+       char *identity;
+       char *urn;
+       char *longitude;
+       char *latitude;
+       char *uri;
+       char *ref;
+       int radius;
+       int recursive;
+} s_loc_t, *p_loc_t;
+
+void lost_rand_str(char *, size_t);
+void lost_free_loc(p_loc_t);
+void lost_free_string(str *);
+
+int lost_get_location_object(p_loc_t, xmlDocPtr, xmlNodePtr);
+int lost_parse_location_info(xmlNodePtr node, p_loc_t loc);
+
+char *lost_find_service_request(p_loc_t, int *);
+char *lost_held_location_request(char *, int *);
+char *lost_get_content(xmlNodePtr, const char *, int *);
+char *lost_get_property(xmlNodePtr, const char *, int *);
+char *lost_get_geolocation_header(struct sip_msg *, int *);
+char *lost_get_from_header(struct sip_msg *, int *);
+char *lost_get_pai_header(struct sip_msg *, int *);
+char *lost_get_childname(xmlNodePtr, const char *, int *);
+char *lost_trim_content(char *, int *);
+
+p_loc_t lost_new_loc(str);
+
+#endif