1 /*
2   The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3   Copyright (C) 2001-2020 Aymeric MOIZARD amoizard@antisip.com
4 
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9 
10   This library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14 
15   You should have received a copy of the GNU Lesser General Public
16   License along with this library; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19 
20 #include <osipparser2/internal.h>
21 
22 #include <osipparser2/osip_port.h>
23 #include <osipparser2/osip_message.h>
24 #include <osipparser2/osip_parser.h>
25 
26 /* Add a header to a SIP message.                           */
27 /* INPUT :  char *hname | pointer to a header name.         */
28 /* INPUT :  char *hvalue | pointer to a header value.       */
29 /* OUTPUT: osip_message_t *sip | structure to save results.          */
30 /* returns -1 on error. */
osip_message_set_header(osip_message_t * sip,const char * hname,const char * hvalue)31 int osip_message_set_header(osip_message_t *sip, const char *hname, const char *hvalue) {
32   osip_header_t *h;
33   int i;
34 
35   if (sip == NULL || hname == NULL)
36     return OSIP_BADPARAMETER;
37 
38   i = osip_header_init(&h);
39 
40   if (i != 0)
41     return i;
42 
43   h->hname = (char *) osip_malloc(strlen(hname) + 1);
44 
45   if (h->hname == NULL) {
46     osip_header_free(h);
47     return OSIP_NOMEM;
48   }
49 
50   osip_clrncpy(h->hname, hname, strlen(hname));
51 
52   if (hvalue != NULL) { /* some headers can be null ("subject:") */
53     h->hvalue = (char *) osip_malloc(strlen(hvalue) + 1);
54 
55     if (h->hvalue == NULL) {
56       osip_header_free(h);
57       return OSIP_NOMEM;
58     }
59 
60     osip_clrncpy(h->hvalue, hvalue, strlen(hvalue));
61 
62   } else
63     h->hvalue = NULL;
64 
65   sip->message_property = 2;
66   osip_list_add(&sip->headers, h, -1);
67   return OSIP_SUCCESS; /* ok */
68 }
69 
70 /* Add a or replace exising header  to a SIP message.       */
71 /* INPUT :  char *hname | pointer to a header name.         */
72 /* INPUT :  char *hvalue | pointer to a header value.       */
73 /* OUTPUT: osip_message_t *sip | structure to save results. */
74 /* returns -1 on error. */
osip_message_replace_header(osip_message_t * sip,const char * hname,const char * hvalue)75 int osip_message_replace_header(osip_message_t *sip, const char *hname, const char *hvalue) {
76   osip_header_t *h, *oldh;
77   int i, oldpos = -1;
78 
79   if (sip == NULL || hname == NULL)
80     return OSIP_BADPARAMETER;
81 
82   oldpos = osip_message_header_get_byname(sip, hname, 0, &oldh);
83 
84   i = osip_header_init(&h);
85 
86   if (i != 0)
87     return i;
88 
89   h->hname = (char *) osip_malloc(strlen(hname) + 1);
90 
91   if (h->hname == NULL) {
92     osip_header_free(h);
93     return OSIP_NOMEM;
94   }
95 
96   osip_clrncpy(h->hname, hname, strlen(hname));
97 
98   if (hvalue != NULL) { /* some headers can be null ("subject:") */
99     h->hvalue = (char *) osip_malloc(strlen(hvalue) + 1);
100 
101     if (h->hvalue == NULL) {
102       osip_header_free(h);
103       return OSIP_NOMEM;
104     }
105 
106     osip_clrncpy(h->hvalue, hvalue, strlen(hvalue));
107 
108   } else
109     h->hvalue = NULL;
110 
111   if (oldpos != -1) {
112     osip_list_remove(&sip->headers, oldpos);
113     osip_header_free(oldh);
114   }
115 
116   sip->message_property = 2;
117   osip_list_add(&sip->headers, h, -1);
118   return OSIP_SUCCESS; /* ok */
119 }
120 
121 #ifndef MINISIZE
122 /* Add a header to a SIP message at the top of the list.    */
123 /* INPUT :  char *hname | pointer to a header name.         */
124 /* INPUT :  char *hvalue | pointer to a header value.       */
125 /* OUTPUT: osip_message_t *sip | structure to save results.          */
126 /* returns -1 on error. */
osip_message_set_topheader(osip_message_t * sip,const char * hname,const char * hvalue)127 int osip_message_set_topheader(osip_message_t *sip, const char *hname, const char *hvalue) {
128   osip_header_t *h;
129   int i;
130 
131   if (sip == NULL || hname == NULL)
132     return OSIP_BADPARAMETER;
133 
134   i = osip_header_init(&h);
135 
136   if (i != 0)
137     return i;
138 
139   h->hname = (char *) osip_malloc(strlen(hname) + 1);
140 
141   if (h->hname == NULL) {
142     osip_header_free(h);
143     return OSIP_NOMEM;
144   }
145 
146   osip_clrncpy(h->hname, hname, strlen(hname));
147 
148   if (hvalue != NULL) { /* some headers can be null ("subject:") */
149     h->hvalue = (char *) osip_malloc(strlen(hvalue) + 1);
150 
151     if (h->hvalue == NULL) {
152       osip_header_free(h);
153       return OSIP_NOMEM;
154     }
155 
156     osip_clrncpy(h->hvalue, hvalue, strlen(hvalue));
157 
158   } else
159     h->hvalue = NULL;
160 
161   sip->message_property = 2;
162   osip_list_add(&sip->headers, h, 0);
163   return OSIP_SUCCESS; /* ok */
164 }
165 
166 /* Get a header in a SIP message.                       */
167 /* INPUT : int pos | position of number in message.     */
168 /* OUTPUT: osip_message_t *sip | structure to scan for a header .*/
169 /* return null on error. */
osip_message_get_header(const osip_message_t * sip,int pos,osip_header_t ** dest)170 int osip_message_get_header(const osip_message_t *sip, int pos, osip_header_t **dest) {
171   *dest = NULL;
172 
173   if (osip_list_size(&sip->headers) <= pos)
174     return OSIP_UNDEFINED_ERROR; /* NULL */
175 
176   *dest = (osip_header_t *) osip_list_get(&sip->headers, pos);
177   return pos;
178 }
179 #endif
180 
181 /* Get a header in a SIP message.                       */
182 /* INPUT : int pos | position where we start the search */
183 /* OUTPUT: osip_message_t *sip | structure to look for header.   */
184 /* return the current position of the header found      */
185 /* and -1 on error. */
osip_message_header_get_byname(const osip_message_t * sip,const char * hname,int pos,osip_header_t ** dest)186 int osip_message_header_get_byname(const osip_message_t *sip, const char *hname, int pos, osip_header_t **dest) {
187   int i;
188   osip_header_t *tmp;
189 
190   *dest = NULL;
191   i = pos;
192 
193   if (osip_list_size(&sip->headers) <= pos)
194     return OSIP_UNDEFINED_ERROR; /* NULL */
195 
196   while (osip_list_size(&sip->headers) > i) {
197     tmp = (osip_header_t *) osip_list_get(&sip->headers, i);
198 
199     if (osip_strcasecmp(tmp->hname, hname) == 0) {
200       *dest = tmp;
201       return i;
202     }
203 
204     i++;
205   }
206 
207   return OSIP_UNDEFINED_ERROR; /* not found */
208 }
209 
osip_header_init(osip_header_t ** header)210 int osip_header_init(osip_header_t **header) {
211   *header = (osip_header_t *) osip_malloc(sizeof(osip_header_t));
212 
213   if (*header == NULL)
214     return OSIP_NOMEM;
215 
216   (*header)->hname = NULL;
217   (*header)->hvalue = NULL;
218   return OSIP_SUCCESS;
219 }
220 
osip_header_free(osip_header_t * header)221 void osip_header_free(osip_header_t *header) {
222   if (header == NULL)
223     return;
224 
225   osip_free(header->hname);
226   osip_free(header->hvalue);
227   header->hname = NULL;
228   header->hvalue = NULL;
229 
230   osip_free(header);
231 }
232 
233 /* returns the header as a string.    */
234 /* INPUT : osip_header_t *header | header. */
235 /* returns null on error. */
osip_header_to_str(const osip_header_t * header,char ** dest)236 int osip_header_to_str(const osip_header_t *header, char **dest) {
237   size_t len, hlen;
238 
239   *dest = NULL;
240 
241   if ((header == NULL) || (header->hname == NULL))
242     return OSIP_BADPARAMETER;
243 
244   len = 0;
245   hlen = strlen(header->hname);
246 
247   if (header->hvalue != NULL)
248     len = strlen(header->hvalue);
249 
250   *dest = (char *) osip_malloc(hlen + len + 3);
251 
252   if (*dest == NULL)
253     return OSIP_NOMEM;
254 
255   if (header->hvalue != NULL)
256     snprintf(*dest, hlen + len + 3, "%s: %s", header->hname, header->hvalue);
257 
258   else
259     snprintf(*dest, hlen + len + 3, "%s: ", header->hname);
260 
261   if (*dest[0] >= 'a' && *dest[0] <= 'z')
262     *dest[0] = (*dest[0] - 32);
263 
264   return OSIP_SUCCESS;
265 }
266 
osip_header_get_name(const osip_header_t * header)267 char *osip_header_get_name(const osip_header_t *header) {
268   if (header == NULL)
269     return NULL;
270 
271   return header->hname;
272 }
273 
osip_header_set_name(osip_header_t * header,char * name)274 void osip_header_set_name(osip_header_t *header, char *name) {
275   header->hname = name;
276 }
277 
osip_header_get_value(const osip_header_t * header)278 char *osip_header_get_value(const osip_header_t *header) {
279   if (header == NULL)
280     return NULL;
281 
282   return header->hvalue;
283 }
284 
osip_header_set_value(osip_header_t * header,char * value)285 void osip_header_set_value(osip_header_t *header, char *value) {
286   header->hvalue = value;
287 }
288 
osip_header_clone(const osip_header_t * header,osip_header_t ** dest)289 int osip_header_clone(const osip_header_t *header, osip_header_t **dest) {
290   int i;
291   osip_header_t *he;
292 
293   *dest = NULL;
294 
295   if (header == NULL)
296     return OSIP_BADPARAMETER;
297 
298   if (header->hname == NULL)
299     return OSIP_BADPARAMETER;
300 
301   i = osip_header_init(&he);
302 
303   if (i != 0)
304     return i;
305 
306   he->hname = osip_strdup(header->hname);
307 
308   if (he->hname == NULL) {
309     osip_header_free(he);
310     return OSIP_NOMEM;
311   }
312 
313   if (header->hvalue != NULL) {
314     he->hvalue = osip_strdup(header->hvalue);
315 
316     if (he->hvalue == NULL) {
317       osip_header_free(he);
318       return OSIP_NOMEM;
319     }
320   }
321 
322   *dest = he;
323   return OSIP_SUCCESS;
324 }
325