1 /* $Id$
2  *
3  * Copyright (C) 2006-2007 VozTelecom Sistemas S.L
4  *
5  * This file is part of Kamailio, a free SIP server.
6  *
7  * Kamailio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version
11  *
12  * Kamailio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 /*
23  * =====================================================================================
24  *
25  *        Filename:  encode_parameters.c
26  *
27  *     Description:  Functions to encode/print parameters
28  *
29  *         Version:  1.0
30  *         Created:  25/01/06 17:46:04 CET
31  *        Revision:  none
32  *        Compiler:  gcc
33  *
34  *          Author:  Elias Baixas (EB), elias@conillera.net
35  *         Company:  VozTele.com
36  *
37  * =====================================================================================
38  */
39 #define _GNU_SOURCE
40 #include <stdio.h>
41 #include "../../core/str.h"
42 #include "../../core/parser/parse_param.h"
43 #include "../../core/parser/parse_to.h"
44 #include "../../core/parser/parse_via.h"
45 #include "../../core/parser/parse_disposition.h"
46 #include "encode_parameters.h"
47 
48 #define REL_PTR(a,b) (unsigned char)((b)-(a))
49 
50 /**
51  * Returns how many bytes in *where have been used
52  *
53  * TODO this is little shitty, someone should unify all the param flavours
54  * to a sigle universal type of parameter (to_param,param,disposition_param)
55  * the way is done here, at least, we dont have the parameter-hanling code spread all around.
56  */
encode_parameters(unsigned char * where,void * pars,char * hdrstart,void * _body,char to)57 int encode_parameters(unsigned char *where,void *pars,char *hdrstart,void *_body,char to)
58 {
59    struct param *parametro,*params;
60    struct to_param *toparam,*toparams;
61    struct disposition_param *dparam,*dparams;
62    struct via_param *vparam,*vparams;
63    struct via_body *vbody;
64    struct to_body *tbody;
65    char *mylittlepointer,*paramstart;
66    int i,j,paramlen;
67    i=0;
68    if(!pars)
69       return 0;
70    if(to=='t'){
71       toparams=(struct to_param*)pars;
72       tbody=(struct to_body*)_body;
73       for(toparam=toparams;toparam;toparam=toparam->next){
74 	 where[i++]=(unsigned char)(toparam->name.s-hdrstart);
75 	 if(toparam->value.s)
76 	    mylittlepointer=toparam->value.s;
77 	 else
78 	    if(toparam->next)
79 	       mylittlepointer=toparam->next->name.s;
80 	    else
81 	       mylittlepointer=toparam->name.s+toparam->name.len+1;
82          if(mylittlepointer[-1]=='\"')/*check if the parameter was quoted*/
83             mylittlepointer--;/*if so, account for quotes*/
84 	 where[i++]=(unsigned char)(mylittlepointer-hdrstart);
85       }
86       if((toparam=tbody->last_param)){
87 	 if(toparam->value.s)
88 	    mylittlepointer=toparam->value.s+toparam->value.len;
89 	 else
90 	    mylittlepointer=toparam->name.s+toparam->name.len;
91          if(mylittlepointer[0]=='\"')/*check if the parameter was quoted*/
92             mylittlepointer++;/*if so, account for quotes*/
93 	 where[i++]=(unsigned char)(mylittlepointer-hdrstart+1);
94       }
95       return i;
96    }else if(to=='n'){
97       params=(struct param*)pars;
98       for(parametro=reverseParameters(params);parametro;parametro=parametro->next){
99 	 where[i++]=(unsigned char)(parametro->name.s-hdrstart);
100 	 if(parametro->body.s)
101 	    mylittlepointer=parametro->body.s;
102 	 else
103 	    if(parametro->next)
104 	       mylittlepointer=parametro->next->name.s;
105 	    else
106 	       mylittlepointer=parametro->name.s+parametro->name.len+1;
107          if(mylittlepointer[-1]=='\"')/*check if the parameter was quoted*/
108             mylittlepointer--;/*if so, account for quotes*/
109 	 where[i++]=(unsigned char)(mylittlepointer-hdrstart);
110       }
111       /*look for the last parameter*/
112       /*WARNING the ** parameters are in reversed order !!! */
113       /*TODO parameter encoding logic should be moved to a specific function...*/
114       for(parametro=params;parametro && parametro->next;parametro=parametro->next);
115       /*printf("PARAMETRO:%.*s\n",parametro->name.len,parametro->name.s);*/
116       if(parametro){
117 	 if(parametro->body.s)
118 	    mylittlepointer=parametro->body.s+parametro->body.len;
119 	 else
120 	    mylittlepointer=parametro->name.s+parametro->name.len;
121          if(mylittlepointer[0]=='\"')/*check if the parameter was quoted*/
122             mylittlepointer++;/*if so, account for quotes*/
123 	 where[i++]=(unsigned char)(mylittlepointer-hdrstart+1);
124       }
125       return i;
126    }else if(to=='d'){
127       dparams=(struct disposition_param*)pars;
128       for(dparam=dparams;dparam;dparam=dparam->next){
129 	 where[i++]=(unsigned char)(dparam->name.s-hdrstart);
130 	 if(dparam->body.s)
131 	    mylittlepointer=dparam->body.s;
132 	 else
133 	    if(dparam->next)
134 	       mylittlepointer=dparam->next->name.s;
135 	    else
136 	       mylittlepointer=dparam->name.s+dparam->name.len+1;
137          if(mylittlepointer[-1]=='\"')/*check if the parameter was quoted*/
138             mylittlepointer--;/*if so, account for quotes*/
139 	 where[i++]=(unsigned char)(mylittlepointer-hdrstart);
140       }
141       /*WARNING the ** parameters are in reversed order !!! */
142       /*TODO parameter encoding logic should be moved to a specific function...*/
143       for(dparam=dparams;dparam && dparam->next;dparam=dparam->next);
144       if(dparam){
145 	 if(dparam->body.s)
146 	    mylittlepointer=dparam->body.s+dparam->body.len;
147 	 else
148 	    mylittlepointer=dparam->name.s+dparam->name.len;
149          if(mylittlepointer[0]=='\"')/*check if the parameter was quoted*/
150             mylittlepointer++;/*if so, account for quotes*/
151 	 where[i++]=(unsigned char)(mylittlepointer-hdrstart+1);
152       }
153       return i;
154    }else if(to=='v'){
155       vparams=(struct via_param*)pars;
156       vbody=(struct via_body*)_body;
157       for(vparam=vparams;vparam;vparam=vparam->next){
158 	 where[i++]=REL_PTR(hdrstart,vparam->name.s);
159 	 if(vparam->value.s)
160 	    mylittlepointer=vparam->value.s;
161 	 else
162 	    if(vparam->next)
163 	       mylittlepointer=vparam->next->name.s;
164 	    else
165 	       mylittlepointer=vparam->name.s+vparam->name.len+1;
166          if(mylittlepointer[-1]=='\"')/*check if the parameter was quoted*/
167             mylittlepointer--;/*if so, account for quotes*/
168 	 where[i++]=REL_PTR(hdrstart,mylittlepointer);
169       }
170       if((vparam=vbody->last_param)){
171 	 if(vparam->value.s)
172 	    mylittlepointer=vparam->value.s+vparam->value.len;
173 	 else
174 	    mylittlepointer=vparam->name.s+vparam->name.len;
175          if(mylittlepointer[0]=='\"')/*check if the parameter was quoted*/
176             mylittlepointer++;/*if so, account for quotes*/
177 	 where[i++]=REL_PTR(hdrstart,mylittlepointer+1);
178       }
179       return i;
180    }else if(to=='u'){
181       paramlen=*((int*)_body);
182       paramstart=(char *)pars;
183       j=i=0;
184       if(paramstart==0 || paramlen==0)
185 	 return 0;
186       /*the first parameter start index, I suppose paramstart points to the first
187        letter of the first parameter: sip:elias@voztele.com;param1=true;param2=false
188                                      paramstart points to __^
189        each parameter is codified with its {param_name_start_idx,[param_value_start_idx|next_param_start_idx]} */
190       where[j++]=paramstart-hdrstart;
191       while(i<paramlen){
192 	 i++;
193 	 if(paramstart[i]==';'){/*no '=' found !*/
194 	    where[j++]=(unsigned char)(&paramstart[i+1]-hdrstart);
195 	    where[j++]=(unsigned char)(&paramstart[i+1]-hdrstart);
196 	 }
197 	 if(paramstart[i]=='='){/* '=' found, look for the next ';' and let 'i' pointing to it*/
198 	    where[j++]=(unsigned char)(&paramstart[i+1]-hdrstart);
199 	    for(;i<paramlen&&paramstart[i]!=';';i++);
200 	    if(paramstart[i]==';')
201 	       where[j++]=(unsigned char)(&paramstart[i+1]-hdrstart);
202 	 }
203       }
204       where[j++]=(unsigned char)(&paramstart[i+1]-hdrstart);
205       if(j%2 == 0)/*this is because maybe the LAST parameter doesn't have an '='*/
206 	 where[j++]=(unsigned char)(&paramstart[i+1]-hdrstart);
207       return j;
208    }
209    return 0;
210 }
211 
212 /**reverses a param_t linked-list
213  */
reverseParameters(param_t * p)214 param_t *reverseParameters(param_t *p)
215 {
216    param_t *previous=NULL,*tmp;
217    while (p != NULL)
218    {
219       tmp = p->next;/* store the next */
220       p->next = previous;/* next = previous */
221       previous = p;/* previous = current */
222       p = tmp;/* current = "the next" */
223    }
224    return previous;
225 }
226 
227 /*prints the encoded parameters
228  */
print_encoded_parameters(FILE * fd,unsigned char * payload,char * hdr,int paylen,char * prefix)229 int print_encoded_parameters(FILE *fd,unsigned char *payload,char *hdr,int paylen,char *prefix)
230 {
231    int i;
232    for(i=0;i<paylen-1;i+=2){
233       fprintf(fd,"%s[PARAMETER[%.*s]",prefix,payload[i+1]-payload[i]-1,&hdr[payload[i]]);
234       fprintf(fd,"VALUE[%.*s]]\n",(payload[i+2]-payload[i+1])==0?0:(payload[i+2]-payload[i+1]-1),&hdr[payload[i+1]]);
235    }
236    return 0;
237 }
238