registrar_parser.c

Go to the documentation of this file.
00001 /*
00002  * $Id: registrar_parser.c 546 2008-04-01 11:45:59Z vingarzan $
00003  *  
00004  * Copyright (C) 2004-2006 FhG Fokus
00005  *
00006  * This file is part of Open IMS Core - an open source IMS CSCFs & HSS
00007  * implementation
00008  *
00009  * Open IMS Core is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * For a license to use the Open IMS Core software under conditions
00015  * other than those described here, or to purchase support for this
00016  * software, please contact Fraunhofer FOKUS by e-mail at the following
00017  * addresses:
00018  *     info@open-ims.org
00019  *
00020  * Open IMS Core is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  * 
00025  * It has to be noted that this Open Source IMS Core System is not 
00026  * intended to become or act as a product in a commercial context! Its 
00027  * sole purpose is to provide an IMS core reference implementation for 
00028  * IMS technology testing and IMS application prototyping for research 
00029  * purposes, typically performed in IMS test-beds.
00030  * 
00031  * Users of the Open Source IMS Core System have to be aware that IMS
00032  * technology may be subject of patents and licence terms, as being 
00033  * specified within the various IMS-related IETF, ITU-T, ETSI, and 3GPP
00034  * standards. Thus all Open IMS Core users have to take notice of this 
00035  * fact and have to agree to check out carefully before installing, 
00036  * using and extending the Open Source IMS Core System, if related 
00037  * patents and licences may become applicable to the intended usage 
00038  * context.  
00039  *
00040  * You should have received a copy of the GNU General Public License
00041  * along with this program; if not, write to the Free Software
00042  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00043  * 
00044  */
00045  
00057 #include <libxml/xmlschemas.h>
00058 #include <libxml/xmlschemastypes.h>
00059 #include <libxml/parser.h>
00060 
00061 #include "registrar_parser.h"
00062 
00063 #include "mod.h" 
00064 #include "../../mem/shm_mem.h"
00065 #include "../../parser/parse_hname2.h"
00066 
00067 
00068 
00069 extern char *scscf_user_data_dtd; /* Path to "CxDataType.dtd"                               */
00070 extern char *scscf_user_data_xsd; /* Path to "CxDataType_Rel6.xsd" or "CxDataType_Rel7.xsd" */
00071 
00072 extern int scscf_support_wildcardPSI;
00073 
00074 int ctxtInit=0;                         
00076 static xmlDtdPtr    dtd=0;              
00077 static xmlValidCtxtPtr  dtdCtxt=0;      
00079 static xmlSchemaPtr xsd=0;              
00080 static xmlSchemaValidCtxtPtr xsdCtxt=0; 
00089 int parser_init(char *dtd_filename,char *xsd_filename)
00090 {
00091     if (dtd_filename){
00092         dtd = xmlParseDTD(NULL,(unsigned char*)dtd_filename);
00093         if (!dtd){
00094             LOG(L_ERR,"ERR:"M_NAME":parser_init: unsuccesful DTD parsing from file <%s>\n",
00095                 dtd_filename);
00096             return 0;
00097         }
00098         dtdCtxt = xmlNewValidCtxt();
00099         dtdCtxt->userData = (void*)stderr;
00100         dtdCtxt->error = (xmlValidityErrorFunc) fprintf;
00101         dtdCtxt->warning = (xmlValidityWarningFunc) fprintf;
00102     }
00103     if (xsd_filename){
00104         xmlSchemaParserCtxtPtr ctxt;
00105         ctxt = xmlSchemaNewParserCtxt(xsd_filename);
00106         if (!ctxt) {
00107             LOG(L_ERR,"ERR:"M_NAME":parser_init: unsuccesful XSD parsing from file <%s>\n",
00108                 xsd_filename);
00109             return 0;
00110         }
00111         xmlSchemaSetParserErrors(ctxt,(xmlValidityErrorFunc) fprintf,(xmlValidityWarningFunc) fprintf,stderr);
00112         xsd = xmlSchemaParse(ctxt);
00113         xmlSchemaFreeParserCtxt(ctxt);      
00114         
00115         xsdCtxt = xmlSchemaNewValidCtxt(xsd);
00116         xmlSchemaSetValidErrors(xsdCtxt,(xmlValidityErrorFunc) fprintf,(xmlValidityWarningFunc) fprintf,stderr);
00117     }
00118     ctxtInit=1;
00119     return 1;
00120 }
00121 
00125 void parser_destroy()
00126 {
00127     if (dtdCtxt){
00128         xmlFreeValidCtxt(dtdCtxt);
00129     }
00130     if (xsdCtxt){
00131         xmlSchemaFreeValidCtxt(xsdCtxt);
00132         xmlSchemaCleanupTypes();
00133     }
00134     xmlCleanupParser();
00135     
00136 }
00137 
00143 void space_quotes_trim_dup(str *dest,char * src) {
00144     int i = 0;
00145     //right space trim
00146     if (src == NULL) return ;
00147     dest->len = strlen(src);
00148     i = dest->len - 1;
00149     while((src[i] == ' '||src[i]=='\t') && i > 0) {
00150         dest->len--;
00151         i--;
00152     }
00153     //left space trim
00154     i = 0;
00155     while((src[i] == ' '||src[i]=='\t') && i<dest->len)
00156         i++;
00157 
00158     while(i<dest->len &&(src[i]=='\"'&&src[dest->len-1]=='\"')){
00159         i++;
00160         if (i<dest->len) dest->len--;
00161     }
00162 
00163     dest->len -= i;
00164     if (dest->len<=0) return;
00165     dest->s = shm_malloc(dest->len);
00166     memcpy(dest->s, src+i , dest->len);
00167 }
00168 
00174 static inline void space_trim_dup(str *dest, char *src)
00175 {
00176     int i;
00177     dest->s=0;
00178     dest->len=0;
00179     if (!src) return;
00180     dest->len = strlen(src);
00181     i = dest->len-1;
00182     while((src[i]==' '||src[i]=='\t') && i>0) 
00183         i--;
00184     i=0;
00185     while((src[i]==' '||src[i]=='\t') && i<dest->len)
00186         i++;
00187     dest->len -= i;
00188     dest->s = shm_malloc(dest->len);
00189     if (!dest->s) {
00190         LOG(L_ERR,"ERR:"M_NAME":space_trim_dup: Out of memory allocating %d bytes\n",dest->len);
00191         dest->len=0;
00192         return;
00193     }
00194     memcpy(dest->s,src+i,dest->len);
00195 }
00196 
00197 
00198 
00206 static inline char ifc_tBool2char(xmlChar *x)
00207 {
00208     int r=0;    
00209     while(x[r]){
00210         switch(x[r]){
00211             case '0': return 0;
00212             case '1': return 1;
00213             case 't': case 'T': return 1;
00214             case 'f': case 'F': return 0;
00215         }
00216         r++;
00217     }
00218     return 0;
00219 }
00220 
00228 static inline char ifc_tDefaultHandling2char(xmlChar *x)
00229 {
00230     char r; 
00231     r = strtol((char*)x, (char **)NULL, 10);
00232     if (errno==EINVAL){
00233         while(x[0]){
00234             if (x[0]=='c'||x[0]=='C') return 0;//SESSION_CONTINUED
00235             if (x[0]=='r'||x[0]=='R') return 1;//SESSION_TERMINATED
00236             x++;
00237         }
00238         return 0;
00239     } 
00240     else return (char)r; 
00241 }
00242 
00251 static inline char ifc_tDirectionOfRequest2char(xmlChar *x)
00252 {
00253     int r;  
00254     r = strtol((char*)x, (char **)NULL, 10);
00255     if (errno==EINVAL){
00256         while(x[0]){
00257             if (x[0]=='o'||x[0]=='O') return 0;//ORIGINATING_SESSION
00258             if (x[0]=='s'||x[0]=='S') return 1;//TERMINATING_REGISTERED
00259             if (x[0]=='u'||x[0]=='U') return 2;//TERMINATING_UNREGISTERED
00260             x++;
00261         }
00262         return 0;
00263     } 
00264     else return (char)r; 
00265 }
00266 
00275 static inline char ifc_tProfilePartIndicator2char(xmlChar *x)
00276 {
00277     int r;  
00278     if (x==0||x[0]==0) return -1;
00279     r = strtol((char*)x, (char **)NULL, 10);
00280     if (errno==EINVAL){
00281         while(x[0]){
00282             if (x[0]=='r'||x[0]=='R') return 0;//REGISTERED
00283             if (x[0]=='u'||x[0]=='U') return 1;//UNREGISTERED
00284             x++;
00285         }
00286         return 0;
00287     } 
00288     else return (char)r; 
00289 }
00290 
00291 
00299 static int parse_public_identity(xmlDocPtr doc, xmlNodePtr root, ims_public_identity *pi)
00300 {
00301     xmlNodePtr child;
00302     xmlNodePtr grandson;
00303     xmlChar *x;
00304     int return_code=1;
00305     
00306     for(child=root->children;child;child=child->next)
00307         if (child->type==XML_ELEMENT_NODE)
00308             switch (child->name[0]){
00309                 case 'I': case 'i':
00310                     if (!pi->public_identity.len){
00311                         x = xmlNodeListGetString(doc,child->xmlChildrenNode,1);
00312                         space_trim_dup(&(pi->public_identity),(char*)x);
00313                         xmlFree(x);
00314                     }                   
00315                     break;
00316                 case 'B': case 'b':
00317                     x = xmlNodeListGetString(doc,child->xmlChildrenNode,1);
00318                     pi->barring = ifc_tBool2char(x);
00319                     xmlFree(x);
00320                     break;
00321                 //lets add something 
00322                 case 'E' : case 'e':
00323                     // that would be Extension
00324                     // here i need to parse Identity Type 
00325                     // if its two then  wildcardedpsi
00326                     // and then extension!!!
00327                     // I have to check how you parse this shit
00328 
00329                     for(grandson=child->children;grandson;grandson=grandson->next)
00330                     {
00331                                                 
00332                         if (grandson->type==XML_ELEMENT_NODE)
00333                         {
00334                             switch (grandson->name[0]) {
00335                                 case 'I' : case 'i':
00336                                     //identity type 0 public identity 1 distinct psi 2 wildcard psi
00337                                     //x = xmlNodeListGetString(doc,grandson->xmlChildrenNode,1);
00338                                     // i need to compare x with 2, but i have to trim leading 
00339                                     // space characters or tabs         
00340                                     //xmlFree(x);
00341                                     break;
00342                                 case 'W' : case 'w':
00343                                     //wildcardpsi
00344                                     if(!scscf_support_wildcardPSI) {
00345                                         LOG(L_ERR,"Configured without support for Wildcard PSI and got one from HSS\n");
00346                                         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");
00347                                     }
00348                                     
00349                                     x = xmlNodeListGetString(doc,grandson->xmlChildrenNode,1);
00350                                     
00351                                     space_trim_dup(&(pi->wildcarded_psi),(char*)x);
00352                                     
00353                                     xmlFree(x);
00354                                     return_code=2;
00355                                     break;
00356                                 default :
00357                                     break;
00358                             }
00359                         }
00360                     }
00361                                         
00362                     break;              
00363             }
00364 
00365     return return_code;
00366 }
00367 
00375 static int parse_sip_header(xmlDocPtr doc,xmlNodePtr node,ims_sip_header *sh)
00376 {
00377     xmlNodePtr child;
00378     xmlChar *x;
00379     char c[256];
00380     int len;
00381     struct hdr_field hf;
00382     sh->header.s=NULL;sh->header.len=0;
00383     sh->content.s=NULL;sh->content.len=0;
00384 
00385     for(child=node->children ; child ; child=child->next)
00386         if (child->type==XML_ELEMENT_NODE)
00387             switch (child->name[0]) {
00388                 case 'H':case 'h':  //Header
00389                     x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00390                     len = strlen((char*)x);     
00391                     memcpy(c,x,len);
00392                     c[len++]=':';
00393                     c[len]=0;
00394                     space_trim_dup(&(sh->header),(char*)x);
00395                     parse_hname2(c,c+(len<4?4:len),&hf);
00396                     sh->type=(short)hf.type;
00397                     //LOG(L_CRIT,"[%.*s(%d)]\n",sh->header.len,sh->header.s,sh->type);
00398                     xmlFree(x);
00399                     break;
00400                 case 'C':case 'c':  //Content
00401                     x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00402                     space_quotes_trim_dup(&(sh->content),(char*)x);
00403                     xmlFree(x);
00404                     break;
00405             }
00406     return 1;
00407 }
00408 
00416 static int parse_session_desc(xmlDocPtr doc,xmlNodePtr node,ims_session_desc *sd)
00417 {
00418     xmlNodePtr child;
00419     xmlChar *x;
00420     sd->line.s=NULL;sd->line.len=0;
00421     sd->content.s=NULL;sd->content.len=0;
00422 
00423     for(child=node->children ; child ; child=child->next)
00424         if (child->type==XML_ELEMENT_NODE)
00425             switch (child->name[0]) {
00426                 case 'L':case 'l':  //Line
00427                     x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00428                     space_trim_dup(&(sd->line),(char*)x);
00429                     xmlFree(x);
00430                     break;
00431                 case 'C':case 'c':  //Content
00432                     x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00433                     space_quotes_trim_dup(&(sd->content),(char*)x);
00434                     xmlFree(x);
00435                     break;
00436             }
00437     return 1;
00438 }
00439 
00447 static int parse_spt_extension(xmlDocPtr doc,xmlNodePtr node,ims_spt *spt)
00448 {
00449     xmlNodePtr child;
00450     xmlChar *x;
00451 
00452     for(child=node->children ; child ; child=child->next) {
00453         if (child->type==XML_ELEMENT_NODE && (child->name[0]=='R' || child->name[0]=='r')) {
00454             x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00455             switch(atoi((char*)x)) {
00456                 case 0:
00457                     spt->registration_type |= IFC_INITIAL_REGISTRATION;
00458                     break;
00459                 case 1:
00460                     spt->registration_type |= IFC_RE_REGISTRATION;
00461                     break;
00462                 case 2:
00463                     spt->registration_type |= IFC_DE_REGISTRATION;
00464                     break;
00465             }                               
00466             xmlFree(x);
00467         }
00468     }
00469 //  LOG(L_CRIT,"INFO:"M_NAME":parse_spt_extension: spt->registration_type=%d\n",spt->registration_type);
00470     return 1;           
00471 }
00472 
00481 static int parse_spt(xmlDocPtr doc,xmlNodePtr node,ims_spt *spt_to,unsigned short *spt_cnt)
00482 {
00483     xmlNodePtr child,saved=0;
00484     xmlChar *x;
00485 
00486     ims_spt *spt,*spt2;
00487     int group;
00488     
00489     spt = spt_to + *spt_cnt;
00490     
00491     spt->condition_negated=0;
00492     spt->group=0;
00493     spt->type=IFC_UNKNOWN;
00494     spt->registration_type=0;
00495 
00496     for(child=node->children ; child ; child=child->next)
00497         if (child->type==XML_ELEMENT_NODE)
00498             switch (child->name[0]) {
00499                 case 'C':case 'c': //ConditionNegated
00500                     x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00501                     spt->condition_negated=ifc_tBool2char(x);
00502                     xmlFree(x);
00503                     break;
00504                 case 'G':case 'g': //Group
00505                     x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00506                     spt->group=atoi((char*)x);
00507                     xmlFree(x);
00508                     break;
00509                 case 'R':case 'r': //RequestUri
00510                     spt->type=IFC_REQUEST_URI;
00511                     x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00512                     space_trim_dup(&(spt->request_uri),(char*)x);
00513                     xmlFree(x);
00514                     break;
00515                 case 'E':case 'e': //Extension
00516                     parse_spt_extension(doc,child,spt);
00517                     break;
00518                 case 'M':case 'm': //method
00519                     spt->type=IFC_METHOD;
00520                     x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00521                     space_trim_dup(&(spt->method),(char*)x);
00522                     xmlFree(x);
00523                     break;
00524                 case 'S':case 's': {//SIPHeader/SessionCase/SessionDescription
00525                     switch(child->name[7]) {
00526                         case 'E':case 'e'://SIP_HEADER
00527                             spt->type=IFC_SIP_HEADER;
00528                             parse_sip_header(doc,child,&(spt->sip_header));
00529                             saved = child;
00530                             break;
00531                         case 'C':case 'c'://Session Case
00532                             spt->type=IFC_SESSION_CASE;
00533                             x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00534                             spt->session_case=ifc_tDirectionOfRequest2char(x);
00535                             xmlFree(x);
00536                             break;
00537                         case 'D':case 'd'://Session Description
00538                             spt->type=IFC_SESSION_DESC;
00539                             parse_session_desc(doc,child,&(spt->session_desc));
00540                             saved = child;
00541                             break;
00542                     }
00543 
00544                 }
00545                     break;
00546             }
00547     *spt_cnt=*spt_cnt+1;
00548 
00549     /* adding the other nodes for multiple groups */            
00550     for(child=node->children ; child ; child=child->next)
00551         if (child->type==XML_ELEMENT_NODE)
00552             switch (child->name[0]) {
00553                 case 'G':case 'g': //Group
00554                     x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00555                     group=atoi((char*)x);
00556                     xmlFree(x);
00557                     if (group != spt->group){
00558                         spt2 = spt_to + *spt_cnt;
00559                         spt2->condition_negated = spt->condition_negated;
00560                         spt2->group = group;
00561                         spt2->type = spt->type;
00562                         switch(spt2->type){
00563                             case IFC_REQUEST_URI:
00564                                 spt2->request_uri.len = spt->request_uri.len;
00565                                 spt2->request_uri.s = shm_malloc(spt2->request_uri.len);
00566                                 if (!spt2->request_uri.s){
00567                                     LOG(L_ERR,"ERR:"M_NAME":parse_spt: Out of memory allocating %d bytes\n",spt->request_uri.len);
00568                                     break;
00569                                 }
00570                                 memcpy(spt2->request_uri.s,spt->request_uri.s,spt->request_uri.len);
00571                                 break;
00572                             case IFC_METHOD:
00573                                 spt2->method.len = spt->method.len;
00574                                 spt2->method.s = shm_malloc(spt2->method.len);
00575                                 if (!spt2->method.s){
00576                                     LOG(L_ERR,"ERR:"M_NAME":parse_spt: Out of memory allocating %d bytes\n",spt->method.len);
00577                                     break;
00578                                 }
00579                                 memcpy(spt2->method.s,spt->method.s,spt->method.len);
00580                                 break;
00581                             case IFC_SIP_HEADER:
00582                                 parse_sip_header(doc,saved,&(spt2->sip_header));
00583                                 break;
00584                             case IFC_SESSION_CASE:
00585                                 spt2->session_case = spt->session_case;
00586                                 break;
00587                             case IFC_SESSION_DESC:
00588                                 parse_session_desc(doc,saved,&(spt2->session_desc));
00589                                 break;                              
00590                         }
00591                         spt2->registration_type = spt->registration_type;
00592                         *spt_cnt = *spt_cnt+1;                      
00593                     }
00594                     break;
00595             }
00596     return 1;           
00597 }
00598 
00607 static int parse_trigger_point(xmlDocPtr doc,xmlNodePtr node,ims_trigger_point *tp)
00608 {
00609     xmlNodePtr child,child2;
00610     xmlChar *x;
00611     unsigned short spt_cnt=0;
00612     int i,j;
00613     ims_spt spttemp;
00614     tp->condition_type_cnf=IFC_DNF;//0
00615     tp->spt=NULL;
00616     tp->spt_cnt=0;
00617 
00618     for(child=node->children ; child ; child=child->next)
00619         if (child->type==XML_ELEMENT_NODE)
00620             switch (child->name[0]) {
00621                 case 'C':case 'c': //ConditionTypeCNF
00622                     x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00623                     tp->condition_type_cnf=ifc_tBool2char(x);
00624                     xmlFree(x);
00625                     break;
00626                 case 'S':case 's': //SPT - Service Point Trigger
00627                     // COUNT all in another groups
00628                     for(child2=child->children ; child2 ; child2=child2->next)
00629                         if (child2->type==XML_ELEMENT_NODE)
00630                             switch (child2->name[0]) {
00631                                 case 'G':case 'g':
00632                                     spt_cnt++;
00633                             }
00634                     break;
00635             }
00636     tp->spt = (ims_spt*) shm_malloc(sizeof(ims_spt)*spt_cnt);
00637     if (!tp->spt){
00638         LOG(L_ERR,"ERR:"M_NAME":parse_trigger_point: Out of memory allocating %d bytes\n",sizeof(ims_spt)*spt_cnt);
00639         return 0;
00640     }
00641     for(child=node->children ; child ; child=child->next)
00642         if (child->type==XML_ELEMENT_NODE)
00643             switch (child->name[0]) {
00644                 case 'S':case 's': //SPT - Service Point Trigger
00645                     parse_spt(doc,child,tp->spt,&(tp->spt_cnt));
00646                     /*i=0;
00647                     while(i<tp->spt_cnt&&tp->spt[i].group<spttemp.group)
00648                         i++;
00649                     for(j=tp->spt_cnt-1;j>=i;j--)
00650                         tp->spt[j+1]=tp->spt[j];
00651                     tp->spt[i]=spttemp;
00652                     tp->spt_cnt++;*/
00653             
00654                     break;
00655             }
00656     
00657     j=1;
00658     while(j){
00659         j=0;
00660         for(i=0;i<tp->spt_cnt-1;i++)
00661             if (tp->spt[i].group > tp->spt[i+1].group){
00662                 j=1;
00663                 spttemp = tp->spt[i];
00664                 tp->spt[i]=tp->spt[i+1];
00665                 tp->spt[i+1]=spttemp;
00666             }           
00667     }
00668     return 1;
00669 }
00677 static int parse_application_server(xmlDocPtr doc,xmlNodePtr node,ims_application_server *as)
00678 {
00679     xmlNodePtr child;
00680     xmlChar *x;
00681     as->server_name.s=NULL;as->server_name.len=0;
00682     as->default_handling=IFC_NO_DEFAULT_HANDLING;
00683     as->service_info.s=NULL;as->service_info.len=0;
00684 
00685     for(child=node->children ; child ; child=child->next)
00686         if (child->type==XML_ELEMENT_NODE)
00687             switch (child->name[0]) {
00688                 case 'S':case 's':  {//ServerName / ServiceInfo
00689                     switch (child->name[4]) {
00690                         case 'E':case 'e':  //ServerName
00691                             x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00692                             space_trim_dup(&(as->server_name),(char*)x);
00693                             xmlFree((char*)x);
00694                             break;
00695                         case 'I':case 'i':  //ServiceInfo
00696                             x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00697                             space_trim_dup(&(as->service_info),(char*)x);
00698                             xmlFree(x);
00699                             break;
00700                     }
00701                     break;
00702                 }
00703                 case 'D':case 'd': //DefaultHandling
00704                     x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00705                     as->default_handling=ifc_tDefaultHandling2char(x);
00706                     xmlFree(x);
00707                     break;
00708             }
00709     return 1;
00710 }
00711 
00712 
00713 
00721 static int parse_filter_criteria(xmlDocPtr doc,xmlNodePtr node,ims_filter_criteria *fc)
00722 {
00723     xmlNodePtr child;
00724     xmlChar *x;
00725     char k;
00726     fc->priority=0;
00727     fc->trigger_point=NULL;
00728     fc->profile_part_indicator=NULL;
00729     //fc->apllication_server init mai tarziu
00730     for(child=node->children ; child ; child=child->next)
00731         if (child->type==XML_ELEMENT_NODE)
00732             switch (child->name[3]) {
00733                 case 'O':case 'o':  //Priority
00734                     x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00735                     fc->priority=atoi((char*)x);
00736                     xmlFree(x);
00737                     break;
00738                 case 'G':case 'g':  //TriggerPoint
00739                     fc->trigger_point=(ims_trigger_point*) shm_malloc(sizeof(ims_trigger_point));
00740                     if (!fc->trigger_point){
00741                         LOG(L_ERR,"ERR:"M_NAME":parse_filter_criteria: Out of memory allocating %d bytes\n",sizeof(ims_trigger_point));
00742                         break;
00743                     }
00744                     if (!parse_trigger_point(doc,child,fc->trigger_point)){
00745                         shm_free(fc->trigger_point);
00746                         fc->trigger_point=0;
00747                         return 0;
00748                     }
00749                     break;
00750                 case 'L':case 'l':  //ApplicationServer
00751                     parse_application_server(doc,child,&(fc->application_server));
00752                     break;
00753                 case 'F':case 'f':  //ProfilePartIndicator
00754                     x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00755                     k = ifc_tProfilePartIndicator2char(x);
00756                     if (k<0) break;
00757                     fc->profile_part_indicator=(char*)shm_malloc(sizeof(char));
00758                     if (!fc->profile_part_indicator){
00759                         LOG(L_ERR,"ERR:"M_NAME":parse_filter_criteria: Out of memory allocating %d bytes\n",sizeof(ims_trigger_point));
00760                         break;
00761                     }
00762                     *fc->profile_part_indicator=k;
00763                     xmlFree(x);
00764                     break;
00765             }
00766     return 1;
00767 }
00768 
00769 
00777 static int parse_cn_service_auth(xmlDocPtr doc,xmlNodePtr node,ims_cn_service_auth *cn)
00778 {
00779     xmlNodePtr child;
00780     xmlChar *x;
00781     cn->subscribed_media_profile_id=-1;
00782     for(child=node->children ; child ; child=child->next)
00783         if (child->type==XML_ELEMENT_NODE)
00784             switch (child->name[0]) {
00785                 case 'S':case 's':  //BarringIndication
00786                     x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00787                     cn->subscribed_media_profile_id=atoi((char*)x);
00788                     xmlFree(x);
00789                     return 1;
00790                     break;
00791 
00792             }
00793     return 0;
00794 }
00795 
00803 static int parse_service_profile(xmlDocPtr doc, xmlNodePtr root, ims_service_profile *sp)
00804 {
00805     xmlNodePtr child;
00806     xmlChar *x;
00807     unsigned short pi_cnt=0,ifc_cnt=0,sh_cnt=0;
00808     int i,j;
00809     ims_filter_criteria fctemp;
00810     int returncode=0;
00811     
00812     for(child=root->children;child;child=child->next)
00813         if (child->type==XML_ELEMENT_NODE)
00814             switch (child->name[0]){
00815                 case 'P': case 'p':
00816                     pi_cnt++;
00817                     break;  
00818                 case 'i':case 'I':  //InitialFilterCriteria
00819                     ifc_cnt++;
00820                     break;
00821                 case 'c':case 'C':  //CoreNetworkServiceAuthorization
00822                     sp->cn_service_auth = (ims_cn_service_auth*) shm_malloc(
00823                                                     sizeof(ims_cn_service_auth));
00824                     break;
00825                 case 's':case 'S':  //SharedIFCSet
00826                     sh_cnt++;
00827                     break;
00828                                     
00829             }   
00830 
00831     sp->public_identities = shm_malloc(pi_cnt*sizeof(ims_public_identity));
00832     if (!sp->public_identities) {
00833         LOG(L_ERR,"ERR:"M_NAME":parse_service_profile: Out of memory allocating %d bytes\n",pi_cnt*sizeof(ims_public_identity));
00834         return 0;
00835     }
00836     memset(sp->public_identities,0,pi_cnt*sizeof(ims_public_identity));
00837 
00838     sp->filter_criteria = (ims_filter_criteria*) shm_malloc(sizeof(ims_filter_criteria)*ifc_cnt);
00839     if (!sp->filter_criteria) {
00840         LOG(L_ERR,"ERR:"M_NAME":parse_service_profile: Out of memory allocating %d bytes\n",ifc_cnt*sizeof(ims_filter_criteria));
00841         return 0;
00842     }
00843     memset(sp->filter_criteria,0,ifc_cnt*sizeof(ims_filter_criteria));
00844 
00845     sp->shared_ifc_set = (int*) shm_malloc(sizeof(int)*sh_cnt);
00846     if (!sp->shared_ifc_set) {
00847         LOG(L_ERR,"ERR:"M_NAME":parse_service_profile: Out of memory allocating %d bytes\n",sh_cnt*sizeof(int));
00848         return 0;
00849     }
00850     memset(sp->shared_ifc_set,0,sh_cnt*sizeof(int));
00851     
00852     for(child=root->children;child;child=child->next)
00853         if (child->type==XML_ELEMENT_NODE)
00854             switch (child->name[0]){
00855                 case 'P': case 'p':
00856                     returncode=parse_public_identity(doc,child,&(sp->public_identities[sp->public_identities_cnt]));
00857                     if (returncode)
00858                         sp->public_identities_cnt++;
00859                     break;      
00860                 case 'I':case 'i':  //InitialFilterCriteria
00861                     if (!parse_filter_criteria(doc,child,&(fctemp))) 
00862                         break;
00863                     i=0;
00864                     while(i<sp->filter_criteria_cnt&&sp->filter_criteria[i].priority<fctemp.priority)
00865                         i++;
00866                     for(j=sp->filter_criteria_cnt-1;j>=i;j--)
00867                         sp->filter_criteria[j+1]=sp->filter_criteria[j];
00868                     sp->filter_criteria[i]=fctemp;
00869                     sp->filter_criteria_cnt++;
00870                     break;
00871                 case 'C':case 'c':  //CoreNetworkServiceAuthorization
00872                     if (!parse_cn_service_auth(doc,child,sp->cn_service_auth)){
00873                         shm_free(sp->cn_service_auth);
00874                         sp->cn_service_auth=0;
00875                     }
00876                     break;
00877                 case 'S':case 's':  //SharedIFCSet
00878                     x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
00879                     sp->shared_ifc_set[sp->shared_ifc_set_cnt++]=atoi((char*)x);
00880                     xmlFree(x);
00881                     break;                              
00882             }
00883     if (returncode==2)
00884         return 2; // i need to know if there is a wildcardpsi hiding in the public_identity
00885     return 1;
00886 }
00887 
00894 static ims_subscription* parse_ims_subscription(xmlDocPtr doc, xmlNodePtr root)
00895 {
00896     xmlNodePtr child;
00897     xmlChar *x;
00898     ims_subscription *s;
00899     unsigned short sp_cnt=0;
00900     int rc;
00901     
00902     if (!root) return 0;
00903     while(root->type!=XML_ELEMENT_NODE || strcasecmp((char*)root->name,"IMSSubscription")!=0){
00904         root = root->next;
00905     }
00906     if (!root) {
00907         LOG(L_ERR,"ERR:"M_NAME":parse_user_data:  No IMSSubscription node found\n");
00908         return 0;
00909     }
00910     s = (ims_subscription*) shm_malloc(sizeof(ims_subscription));
00911     if (!s) {
00912         LOG(L_ERR,"ERR:"M_NAME":parse_ims_subscription: Out of memory allocating %d bytes\n",sizeof(ims_subscription));
00913         return 0;
00914     }
00915     memset(s,0,sizeof(ims_subscription));
00916     for(child=root->children;child;child=child->next)
00917         if (child->type==XML_ELEMENT_NODE)
00918             switch (child->name[0]){
00919                 case 'P':case 'p':  /* Private Identity */
00920                     if (!s->private_identity.len){
00921                         x = xmlNodeListGetString(doc,child->xmlChildrenNode,1);
00922                         space_trim_dup(&(s->private_identity),(char*)x);
00923                         xmlFree(x);
00924                     }
00925                     break;
00926                 case 'S':case 's':  /* Service Profile */
00927                     sp_cnt++;
00928                     break;                  
00929             }
00930     s->service_profiles = (ims_service_profile*) shm_malloc(sp_cnt * sizeof(ims_service_profile));
00931     if (!s->service_profiles) {
00932         LOG(L_ERR,"ERR:"M_NAME":parse_ims_subscription: Out of memory allocating %d bytes\n",sp_cnt*sizeof(ims_service_profile));
00933         return s;   
00934     }
00935     memset(s->service_profiles,0,sp_cnt * sizeof(ims_service_profile));
00936     for(child=root->children;child;child=child->next)
00937         if (child->type==XML_ELEMENT_NODE)
00938             if (child->name[0]=='S' || child->name[0]=='s')
00939             {
00940                 rc=parse_service_profile(doc,child,&(s->service_profiles[s->service_profiles_cnt]));
00941                 if (rc==2)
00942                     s->wpsi=1;
00943                 if (rc)
00944                     s->service_profiles_cnt++;
00945             }               
00946     s->lock = lock_alloc();
00947     s->lock = lock_init(s->lock);
00948     return s;
00949 }
00950 
00951 
00957 ims_subscription *parse_user_data(str xml)
00958 {
00959     xmlDocPtr doc=0;
00960     xmlNodePtr root=0;
00961     char c;
00962     ims_subscription *s;
00963     if (!ctxtInit) parser_init(scscf_user_data_dtd,scscf_user_data_xsd);    
00964     doc=0;
00965     c = xml.s[xml.len];
00966     xml.s[xml.len]=0;
00967     doc = xmlParseDoc((unsigned char *)xml.s);
00968     if (!doc){
00969         LOG(L_ERR,"ERR:"M_NAME":parse_user_data:  This is not a valid XML <%.*s>\n",
00970             xml.len,xml.s);
00971         goto error;
00972     }
00973     if (dtdCtxt){
00974         if (xmlValidateDtd(dtdCtxt,doc,dtd)!=1){
00975             LOG(L_ERR,"ERR:"M_NAME":parse_user_data:  Verification of XML against DTD failed <%.*s>\n",
00976                 xml.len,xml.s);
00977             goto error;
00978         }
00979     }
00980     if (xsdCtxt){
00981         if (xmlSchemaValidateDoc(xsdCtxt,doc)!=0){
00982             LOG(L_ERR,"ERR:"M_NAME":parse_user_data:  Verification of XML against XSD failed <%.*s>\n",
00983                 xml.len,xml.s);
00984             goto error;
00985         }
00986     }
00987     root = xmlDocGetRootElement(doc);
00988     if (!root){
00989         LOG(L_ERR,"ERR:"M_NAME":parse_user_data:  Empty XML <%.*s>\n",
00990             xml.len,xml.s);
00991         goto error;
00992     }
00993     s = parse_ims_subscription(doc,root);
00994     if (!s){
00995         LOG(L_ERR,"ERR:"M_NAME":parse_user_data:  Error while loading into  ims subscription structure\n");
00996         goto error;     
00997     }
00998     xmlFreeDoc(doc);
00999 //  print_user_data(L_CRIT,s);
01000     return s;
01001 error:  
01002     if (doc) xmlFreeDoc(doc);
01003     xml.s[xml.len]=c;
01004     return 0;   
01005 }
01006 
01012 void print_user_data(int log_level,ims_subscription *s)
01013 {
01014     int i,j,k;
01015     if (debug<log_level) return; /* to avoid useless calls when nothing will be printed */
01016     LOG(log_level,"INF:"M_NAME":IMSSubscription:\n");
01017     if (!s) return;
01018     lock_get(s->lock);
01019     LOG(log_level,"INF:"M_NAME":\tPrivate Identity: <%.*s>\n",s->private_identity.len,s->private_identity.s);
01020     for(i=0;i<s->service_profiles_cnt;i++){
01021         LOG(log_level,"INF:"M_NAME":\tService Profile:\n");
01022         for(j=0;j<s->service_profiles[i].public_identities_cnt;j++){    
01023             LOG(log_level,"INF:"M_NAME":\t\tPublic Identity: Barring [%d] <%.*s> \n",
01024                 s->service_profiles[i].public_identities[j].barring,
01025                 s->service_profiles[i].public_identities[j].public_identity.len,
01026                 s->service_profiles[i].public_identities[j].public_identity.s);         
01027         }
01028         for(j=0;j<s->service_profiles[i].filter_criteria_cnt;j++){  
01029             LOG(log_level,"INF:"M_NAME":\t\tFilter Criteria: Priority [%d]ProfilePartInd [%d]\n",
01030                 s->service_profiles[i].filter_criteria[j].priority,
01031                 s->service_profiles[i].filter_criteria[j].profile_part_indicator?
01032                  *(s->service_profiles[i].filter_criteria[j].profile_part_indicator):-1 );              
01033             if (s->service_profiles[i].filter_criteria[j].trigger_point){
01034                 LOG(log_level,"INF:"M_NAME":\t\t\tTrigger Point: CNF [%c] %s\n",
01035                     s->service_profiles[i].filter_criteria[j].trigger_point->condition_type_cnf?'X':' ',
01036                     s->service_profiles[i].filter_criteria[j].trigger_point->condition_type_cnf?"(_|_)&(_|_)":"(_&_)|(_&_)"
01037                     );                                          
01038