/** * Parse a Application Server. * @param doc - the XML document * @param node - the current node * @param as - structure to fill * @returns 1 on success, 0 on failure */ static int parse_application_server(xmlDocPtr doc,xmlNodePtr node,ims_application_server *as) { xmlNodePtr child; xmlChar *x; as->server_name.s=NULL;as->server_name.len=0; as->default_handling=IFC_NO_DEFAULT_HANDLING; as->service_info.s=NULL;as->service_info.len=0; for(child=node->children ; child ; child=child->next) if (child->type==XML_ELEMENT_NODE) switch (child->name[0]) { case 'S':case 's': {//ServerName / ServiceInfo switch (child->name[4]) { case 'E':case 'e': //ServerName x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); space_trim_dup(&(as->server_name),(char*)x); xmlFree((char*)x); break; case 'I':case 'i': //ServiceInfo x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); space_trim_dup(&(as->service_info),(char*)x); xmlFree(x); break; } break; } case 'D':case 'd': //DefaultHandling x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); as->default_handling=ifc_tDefaultHandling2char(x); xmlFree(x); break; } return 1; }
/** * Parse SPT for SIP Header. * @param doc - the XML document * @param node - the current node * @param sh - structure to fill * @returns 1 on success, 0 on failure */ static int parse_sip_header(xmlDocPtr doc,xmlNodePtr node,ims_sip_header *sh) { xmlNodePtr child; xmlChar *x; char c[256]; int len; struct hdr_field hf; sh->header.s=NULL;sh->header.len=0; sh->content.s=NULL;sh->content.len=0; for(child=node->children ; child ; child=child->next) if (child->type==XML_ELEMENT_NODE) switch (child->name[0]) { case 'H':case 'h': //Header x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); len = strlen((char*)x); memcpy(c,x,len); c[len++]=':'; c[len]=0; space_trim_dup(&(sh->header),(char*)x); parse_hname2(c,c+(len<4?4:len),&hf); sh->type=(short)hf.type; //LOG(L_CRIT,"[%.*s(%d)]\n",sh->header.len,sh->header.s,sh->type); xmlFree(x); break; case 'C':case 'c': //Content x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); space_quotes_trim_dup(&(sh->content),(char*)x); xmlFree(x); break; } return 1; }
/** * Parse a IMS Subscription. * @param doc - the XML document * @param root - the current node * @returns the ims_subscription* on success or NULL on error */ static ims_subscription* parse_ims_subscription(xmlDocPtr doc, xmlNodePtr root) { xmlNodePtr child; xmlChar *x; ims_subscription *s; unsigned short sp_cnt=0; int rc; if (!root) return 0; while(root->type!=XML_ELEMENT_NODE || strcasecmp((char*)root->name,"IMSSubscription")!=0){ root = root->next; } if (!root) { LM_ERR("No IMSSubscription node found\n"); return 0; } s = (ims_subscription*) shm_malloc(sizeof(ims_subscription)); if (!s) { LM_ERR("Out of memory allocating %lx bytes\n",sizeof(ims_subscription)); return 0; } memset(s,0,sizeof(ims_subscription)); for(child=root->children;child;child=child->next) if (child->type==XML_ELEMENT_NODE) switch (child->name[0]){ case 'P':case 'p': /* Private Identity */ if (!s->private_identity.len){ x = xmlNodeListGetString(doc,child->xmlChildrenNode,1); space_trim_dup(&(s->private_identity),(char*)x); xmlFree(x); } break; case 'S':case 's': /* Service Profile */ sp_cnt++; break; } s->service_profiles = (ims_service_profile*) shm_malloc(sp_cnt * sizeof(ims_service_profile)); if (!s->service_profiles) { LM_ERR("Out of memory allocating %lx bytes\n",sp_cnt*sizeof(ims_service_profile)); return s; } memset(s->service_profiles,0,sp_cnt * sizeof(ims_service_profile)); for(child=root->children;child;child=child->next) if (child->type==XML_ELEMENT_NODE) if (child->name[0]=='S' || child->name[0]=='s') { rc=parse_service_profile(doc,child,&(s->service_profiles[s->service_profiles_cnt])); if (rc==2) s->wpsi=1; if (rc) s->service_profiles_cnt++; } s->lock = lock_alloc(); s->lock = lock_init(s->lock); return s; }
/** * Parse SPT for Session Description. * @param doc - the XML document * @param node - the current node * @param sd - structure to fill * @returns 1 on success, 0 on failure */ static int parse_session_desc(xmlDocPtr doc,xmlNodePtr node,ims_session_desc *sd) { xmlNodePtr child; xmlChar *x; sd->line.s=NULL;sd->line.len=0; sd->content.s=NULL;sd->content.len=0; for(child=node->children ; child ; child=child->next) if (child->type==XML_ELEMENT_NODE) switch (child->name[0]) { case 'L':case 'l': //Line x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); space_trim_dup(&(sd->line),(char*)x); xmlFree(x); break; case 'C':case 'c': //Content x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); space_quotes_trim_dup(&(sd->content),(char*)x); xmlFree(x); break; } return 1; }
/** * Parse the Public Identity. * @param doc - the XML document * @param root - the current node * @param pi - structure to fill * @returns 1 on success, 0 on failure */ static int parse_public_identity(xmlDocPtr doc, xmlNodePtr root, ims_public_identity *pi) { xmlNodePtr child; xmlChar *x; for(child=root->children;child;child=child->next) if (child->type==XML_ELEMENT_NODE) switch (child->name[0]){ case 'I': case 'i': if (!pi->public_identity.len){ x = xmlNodeListGetString(doc,child->xmlChildrenNode,1); space_trim_dup(&(pi->public_identity),x); xmlFree(x); } break; case 'B': case 'b': x = xmlNodeListGetString(doc,child->xmlChildrenNode,1); pi->barring = ifc_tBool2char(x); xmlFree(x); break; } return 1; }
/** * Parses a notification and creates the r_notification object * @param xml - the XML data * @returns the new r_notification* or NULL on error */ r_notification* r_notification_parse(str xml) { r_notification *n; r_registration *r; r_regcontact *rc; xmlDocPtr doc=0; xmlNodePtr root=0,child=0,nephew=0,node=0; xmlChar *reginfo_state=0,*x; char c=0; n = pkg_malloc(sizeof(r_notification)); if (!n) { LOG(L_ERR,"ERR:"M_NAME":r_notification_parse: Error allocating %d bytes\n", sizeof(r_notification)); goto error; } memset(n,0,sizeof(r_notification)); if (!dtd) parser_init(pcscf_reginfo_dtd); doc=0; c = xml.s[xml.len]; xml.s[xml.len]=0; doc = xmlParseDoc((unsigned char *)xml.s); if (!doc){ LOG(L_ERR,"ERR:"M_NAME":r_notification_parse: This is not a valid XML <%.*s>\n", xml.len,xml.s); goto error; } if (xmlValidateDtd(&cvp,doc,dtd)!=1){ LOG(L_ERR,"ERR:"M_NAME":r_notification_parse: Verification of XML against DTD failed <%.*s>\n", xml.len,xml.s); goto error; } root = xmlDocGetRootElement(doc); if (!root){ LOG(L_ERR,"ERR:"M_NAME":r_notification_parse: Empty XML <%.*s>\n", xml.len,xml.s); goto error; } reginfo_state = xmlGetProp(root,(xmlChar*)"state"); LOG(L_DBG,"DBG:"M_NAME":r_notification_parse: reginfo_state <%s>\n", reginfo_state); if (reginfo_state[0]=='f'||reginfo_state[0]=='F') n->state = IMS_REGINFO_FULL; else n->state = IMS_REGINFO_PARTIAL; for(child = root->children; child; child = child->next) if (child->type == XML_ELEMENT_NODE) { r = pkg_malloc(sizeof(r_registration)); if (!r){ LOG(L_ERR,"ERR:"M_NAME":r_notification_parse: Error allocating %d bytes\n", sizeof(r_registration)); goto error; } memset(r,0,sizeof(r_registration)); x = xmlGetProp(child,(xmlChar*)"id"); space_trim_dup(&(r->id),(char*)x); xmlFree(x); x = xmlGetProp(child,(xmlChar*)"aor"); space_trim_dup(&(r->aor),(char*)x); xmlFree(x); x = xmlGetProp(child,(xmlChar*)"state"); if (x[0]=='a'||x[0]=='A') r->state = IMS_REGINFO_ACTIVE; else r->state = IMS_REGINFO_TERMINATED; xmlFree(x); for(nephew = child->children; nephew; nephew = nephew->next) if (nephew->type == XML_ELEMENT_NODE) { rc = pkg_malloc(sizeof(r_regcontact)); if (!rc){ LOG(L_ERR,"ERR:"M_NAME":r_notification_parse: Error allocating %d bytes\n", sizeof(r_regcontact)); goto error; } memset(rc,0,sizeof(r_regcontact)); x = xmlGetProp(nephew,(xmlChar*)"id"); space_trim_dup(&(rc->id),(char*)x); xmlFree(x); x = xmlGetProp(nephew,(xmlChar*)"state"); if (x[0]=='a'||x[0]=='A') rc->state = IMS_REGINFO_ACTIVE; else rc->state = IMS_REGINFO_TERMINATED; xmlFree(x); x = xmlGetProp(nephew,(xmlChar*)"event"); switch(x[0]){ case 'r':case 'R': switch (x[2]){ case 'g': case 'G': rc->event = IMS_REGINFO_CONTACT_REGISTERED; break; case 'f': case 'F': rc->event = IMS_REGINFO_CONTACT_REFRESHED; break; case 'j': case 'J': rc->event = IMS_REGINFO_CONTACT_REJECTED; break; default: rc->event = IMS_REGINFO_NONE; } break; case 'c':case 'C': rc->event = IMS_REGINFO_CONTACT_CREATED; break; case 's':case 'S': rc->event = IMS_REGINFO_CONTACT_SHORTENED; break; case 'e':case 'E': rc->event = IMS_REGINFO_CONTACT_EXPIRED; break; case 'd':case 'D': rc->event = IMS_REGINFO_CONTACT_DEACTIVATED; break; case 'p':case 'P': rc->event = IMS_REGINFO_CONTACT_PROBATION; break; case 'u':case 'U': rc->event = IMS_REGINFO_CONTACT_UNREGISTERED; break; default: rc->event = IMS_REGINFO_NONE; } xmlFree(x); x = xmlGetProp(nephew,(xmlChar*)"expires"); if (x) { rc->expires = atoi((char*)x); xmlFree(x); } node = nephew->children; while(node && node->type!=XML_ELEMENT_NODE) node =node->next; if (node) { x = xmlNodeGetContent(node); space_trim_dup(&(rc->uri),(char*)x); xmlFree(x); } rc->next = r->contact; r->contact = rc; } r->next = n->registration; n->registration = r; } if (reginfo_state) xmlFree(reginfo_state); if (doc) xmlFreeDoc(doc); xml.s[xml.len]=c; return n; error: if (reginfo_state) xmlFree(reginfo_state); if (doc) xmlFreeDoc(doc); xml.s[xml.len]=c; if (n) r_notification_free(n); return 0; }
/** * Parse the Public Identity. * @param doc - the XML document * @param root - the current node * @param pi - structure to fill * @returns 1 on success, 0 on failure , 2 if its a wildcardpsi */ static int parse_public_identity(xmlDocPtr doc, xmlNodePtr root, ims_public_identity *pi) { xmlNodePtr child; xmlNodePtr grandson; xmlChar *x; int return_code=1; for(child=root->children;child;child=child->next) if (child->type==XML_ELEMENT_NODE) switch (child->name[0]){ case 'I': case 'i': if (!pi->public_identity.len){ x = xmlNodeListGetString(doc,child->xmlChildrenNode,1); space_trim_dup(&(pi->public_identity),(char*)x); xmlFree(x); } break; case 'B': case 'b': x = xmlNodeListGetString(doc,child->xmlChildrenNode,1); pi->barring = ifc_tBool2char(x); xmlFree(x); break; //lets add something case 'E' : case 'e': // that would be Extension // here i need to parse Identity Type // if its two then wildcardedpsi // and then extension!!! // I have to check how you parse this shit for(grandson=child->children;grandson;grandson=grandson->next) { if (grandson->type==XML_ELEMENT_NODE) { switch (grandson->name[0]) { case 'I' : case 'i': //identity type 0 public identity 1 distinct psi 2 wildcard psi //x = xmlNodeListGetString(doc,grandson->xmlChildrenNode,1); // i need to compare x with 2, but i have to trim leading // space characters or tabs //xmlFree(x); break; case 'W' : case 'w': //wildcardpsi if(!scscf_support_wildcardPSI) { LOG(L_ERR,"Configured without support for Wildcard PSI and got one from HSS\n"); LOG(L_ERR,"the identity will be stored but never be matched, please include the parameter to support wildcard PSI in the config file\n"); } x = xmlNodeListGetString(doc,grandson->xmlChildrenNode,1); space_trim_dup(&(pi->wildcarded_psi),(char*)x); xmlFree(x); return_code=2; break; default : break; } } } break; } return return_code; }
/** * Parse a Service Point Trigger. * @param doc - the XML document * @param node - the current node * @param spt_to - structure to fill * @param spt_cnt - structure to fill with the spt count * @returns 1 on success, 0 on failure */ static int parse_spt(xmlDocPtr doc,xmlNodePtr node,ims_spt *spt_to,unsigned short *spt_cnt) { xmlNodePtr child,saved=0; xmlChar *x; ims_spt *spt,*spt2; int group; spt = spt_to + *spt_cnt; spt->condition_negated=0; spt->group=0; spt->type=IFC_UNKNOWN; spt->registration_type=0; for(child=node->children ; child ; child=child->next) if (child->type==XML_ELEMENT_NODE) switch (child->name[0]) { case 'C':case 'c': //ConditionNegated x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); spt->condition_negated=ifc_tBool2char(x); xmlFree(x); break; case 'G':case 'g': //Group x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); spt->group=atoi((char*)x); xmlFree(x); break; case 'R':case 'r': //RequestUri spt->type=IFC_REQUEST_URI; x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); space_trim_dup(&(spt->request_uri),(char*)x); xmlFree(x); break; case 'E':case 'e': //Extension parse_spt_extension(doc,child,spt); break; case 'M':case 'm': //method spt->type=IFC_METHOD; x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); space_trim_dup(&(spt->method),(char*)x); xmlFree(x); break; case 'S':case 's': {//SIPHeader/SessionCase/SessionDescription switch(child->name[7]) { case 'E':case 'e'://SIP_HEADER spt->type=IFC_SIP_HEADER; parse_sip_header(doc,child,&(spt->sip_header)); saved = child; break; case 'C':case 'c'://Session Case spt->type=IFC_SESSION_CASE; x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); spt->session_case=ifc_tDirectionOfRequest2char(x); xmlFree(x); break; case 'D':case 'd'://Session Description spt->type=IFC_SESSION_DESC; parse_session_desc(doc,child,&(spt->session_desc)); saved = child; break; } } break; } *spt_cnt=*spt_cnt+1; /* adding the other nodes for multiple groups */ for(child=node->children ; child ; child=child->next) if (child->type==XML_ELEMENT_NODE) switch (child->name[0]) { case 'G':case 'g': //Group x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); group=atoi((char*)x); xmlFree(x); if (group != spt->group){ spt2 = spt_to + *spt_cnt; spt2->condition_negated = spt->condition_negated; spt2->group = group; spt2->type = spt->type; switch(spt2->type){ case IFC_REQUEST_URI: spt2->request_uri.len = spt->request_uri.len; spt2->request_uri.s = shm_malloc(spt2->request_uri.len); if (!spt2->request_uri.s){ LM_ERR("Out of memory allocating %d bytes\n",spt->request_uri.len); break; } memcpy(spt2->request_uri.s,spt->request_uri.s,spt->request_uri.len); break; case IFC_METHOD: spt2->method.len = spt->method.len; spt2->method.s = shm_malloc(spt2->method.len); if (!spt2->method.s){ LM_ERR("Out of memory allocating %d bytes\n",spt->method.len); break; } memcpy(spt2->method.s,spt->method.s,spt->method.len); break; case IFC_SIP_HEADER: parse_sip_header(doc,saved,&(spt2->sip_header)); break; case IFC_SESSION_CASE: spt2->session_case = spt->session_case; break; case IFC_SESSION_DESC: parse_session_desc(doc,saved,&(spt2->session_desc)); break; } spt2->registration_type = spt->registration_type; *spt_cnt = *spt_cnt+1; } break; } return 1; }