Revert "Revert "and added files""
[bcm963xx.git] / userapps / opensource / libosip2 / src / osipparser2 / osip_content_type.c
1 /*
2   The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3   Copyright (C) 2001,2002,2003  Aymeric MOIZARD jack@atosc.org
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 <stdlib.h>
21 #include <stdio.h>
22
23 #include <osipparser2/osip_port.h>
24 #include <osipparser2/osip_message.h>
25 #include <osipparser2/osip_parser.h>
26 #include "parser.h"
27
28
29 int
30 osip_content_type_init (osip_content_type_t ** content_type)
31 {
32   *content_type =
33     (osip_content_type_t *) osip_malloc (sizeof (osip_content_type_t));
34   if (*content_type == NULL)
35     return -1;
36
37   (*content_type)->type = NULL;
38   (*content_type)->subtype = NULL;
39
40   (*content_type)->gen_params =
41     (osip_list_t *) osip_malloc (sizeof (osip_list_t));
42   if ((*content_type)->gen_params == NULL)
43     {
44       osip_free ((*content_type)->gen_params);
45       *content_type = NULL;
46       return -1;
47     }
48   osip_list_init ((*content_type)->gen_params);
49
50   return 0;
51 }
52
53 /* adds the content_type header to message.              */
54 /* INPUT : char *hvalue | value of header.    */
55 /* OUTPUT: osip_message_t *sip | structure to save results.  */
56 /* returns -1 on error. */
57 int
58 osip_message_set_content_type (osip_message_t * sip, const char *hvalue)
59 {
60   int i;
61
62   if (sip->content_type != NULL)
63     return -1;
64
65   if (hvalue == NULL || hvalue[0] == '\0')
66     return 0;
67
68   i = osip_content_type_init (&(sip->content_type));
69   if (i != 0)
70     return -1;
71   sip->message_property = 2;
72   i = osip_content_type_parse (sip->content_type, hvalue);
73   if (i != 0)
74     {
75       osip_content_type_free (sip->content_type);
76       sip->content_type = NULL;
77     }
78   return 0;
79 }
80
81
82 /* returns the content_type header.            */
83 /* INPUT : osip_message_t *sip | sip message.   */
84 /* returns null on error. */
85 osip_content_type_t *
86 osip_message_get_content_type (const osip_message_t * sip)
87 {
88   return sip->content_type;
89 }
90
91 /* parses the string as a content_type header.                   */
92 /* INPUT : const char *string | pointer to a content_type string.*/
93 /* OUTPUT: osip_content_type_t *content_type | structure to save results.     */
94 /* returns -1 on error. */
95 int
96 osip_content_type_parse (osip_content_type_t * content_type,
97                          const char *hvalue)
98 {
99   char *subtype;
100   char *osip_content_type_params;
101
102   /* How to parse:
103
104      we'll place the pointers:
105      subtype              =>  beginning of subtype
106      osip_content_type_params  =>  beginning of params
107
108      examples:
109
110      application/multipart ; boundary=
111      ^          ^
112    */
113
114   subtype = strchr (hvalue, '/');
115   osip_content_type_params = strchr (hvalue, ';');
116
117   if (subtype == NULL)
118     return -1;                  /* do we really mind such an error */
119
120   if (osip_content_type_params != NULL)
121     {
122       if (__osip_generic_param_parseall (content_type->gen_params,
123                                          osip_content_type_params) == -1)
124         return -1;
125     }
126   else
127     osip_content_type_params = subtype + strlen (subtype);
128
129   if (subtype - hvalue + 1 < 2)
130     return -1;
131   content_type->type = (char *) osip_malloc (subtype - hvalue + 1);
132   if (content_type->type == NULL)
133     return -1;
134   osip_strncpy (content_type->type, hvalue, subtype - hvalue);
135   osip_clrspace (content_type->type);
136
137   if (osip_content_type_params - subtype < 2)
138     return -1;
139   content_type->subtype =
140     (char *) osip_malloc (osip_content_type_params - subtype);
141   if (content_type->subtype == NULL)
142     return -1;
143   osip_strncpy (content_type->subtype, subtype + 1,
144                 osip_content_type_params - subtype - 1);
145   osip_clrspace (content_type->subtype);
146
147   return 0;
148 }
149
150
151 /* returns the content_type header as a string.  */
152 /* INPUT : osip_content_type_t *content_type | content_type header.   */
153 /* returns null on error. */
154 int
155 osip_content_type_to_str (const osip_content_type_t * content_type,
156                           char **dest)
157 {
158   char *buf;
159   char *tmp;
160   size_t len;
161
162   *dest = NULL;
163   if ((content_type == NULL) || (content_type->type == NULL)
164       || (content_type->subtype == NULL))
165     return -1;
166
167   /* try to guess a long enough length */
168   len = strlen (content_type->type) + strlen (content_type->subtype) + 4        /* for '/', ' ', ';' and '\0' */
169     + 10 * osip_list_size (content_type->gen_params);
170
171   buf = (char *) osip_malloc (len);
172   tmp = buf;
173
174   sprintf (tmp, "%s/%s", content_type->type, content_type->subtype);
175
176   tmp = tmp + strlen (tmp);
177   {
178     int pos = 0;
179     osip_generic_param_t *u_param;
180
181     if (!osip_list_eol (content_type->gen_params, pos))
182       {                         /* needed for cannonical form! (authentication issue of rfc2543) */
183         sprintf (tmp, " ");
184         tmp++;
185       }
186     while (!osip_list_eol (content_type->gen_params, pos))
187       {
188         size_t tmp_len;
189
190         u_param =
191           (osip_generic_param_t *) osip_list_get (content_type->gen_params,
192                                                   pos);
193         if (u_param->gvalue == NULL)
194           {
195             osip_free (buf);
196             return -1;
197           }
198         tmp_len = strlen (buf) + 4 + strlen (u_param->gname)
199           + strlen (u_param->gvalue);
200         if (len < tmp_len)
201           {
202             buf = realloc (buf, tmp_len);
203             len = tmp_len;
204             tmp = buf + strlen (buf);
205           }
206         sprintf (tmp, ";%s=%s", u_param->gname, u_param->gvalue);
207         tmp = tmp + strlen (tmp);
208         pos++;
209       }
210   }
211   *dest = buf;
212   return 0;
213 }
214
215
216 /* deallocates a osip_content_type_t structure.  */
217 /* INPUT : osip_content_type_t *content_type | content_type. */
218 void
219 osip_content_type_free (osip_content_type_t * content_type)
220 {
221   if (content_type == NULL)
222     return;
223   osip_free (content_type->type);
224   osip_free (content_type->subtype);
225
226   osip_generic_param_freelist (content_type->gen_params);
227
228   content_type->type = NULL;
229   content_type->subtype = NULL;
230   content_type->gen_params = NULL;
231
232   osip_free (content_type);
233 }
234
235 int
236 osip_content_type_clone (const osip_content_type_t * ctt,
237                          osip_content_type_t ** dest)
238 {
239   int i;
240   osip_content_type_t *ct;
241
242   *dest = NULL;
243   if (ctt == NULL)
244     return -1;
245   if (ctt->type == NULL)
246     return -1;
247   if (ctt->subtype == NULL)
248     return -1;
249
250   i = osip_content_type_init (&ct);
251   if (i != 0)                   /* allocation failed */
252     return -1;
253   ct->type = osip_strdup (ctt->type);
254   ct->subtype = osip_strdup (ctt->subtype);
255
256   {
257     int pos = 0;
258     osip_generic_param_t *u_param;
259     osip_generic_param_t *dest_param;
260
261     while (!osip_list_eol (ctt->gen_params, pos))
262       {
263         u_param =
264           (osip_generic_param_t *) osip_list_get (ctt->gen_params, pos);
265         i = osip_generic_param_clone (u_param, &dest_param);
266         if (i != 0)
267           {
268             osip_content_type_free (ct);
269             osip_free (ct);
270             return -1;
271           }
272         osip_list_add (ct->gen_params, dest_param, -1);
273         pos++;
274       }
275   }
276   *dest = ct;
277   return 0;
278 }