parse_content.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  *
00005  * Copyright (C) 2001-2003 FhG Fokus
00006  *
00007  * This file is part of ser, a free SIP server.
00008  *
00009  * ser 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  * ser is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License 
00020  * along with this program; if not, write to the Free Software 
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  * History:
00024  * 2003-08-04 parse_content_type_hdr separates type from subtype inside
00025  * the mime type (bogdan)
00026  * 2003-08-04 CPL subtype added (bogdan)
00027  * 2003-08-05 parse_accept_hdr function added (bogdan)
00028  * 2008-05-23 reset the type/subtype to unknown, if the end of
00029  *              tree has reached, but the type/subtype has still
00030  *              some remaining characters (Miklos)
00031  */
00032 
00040 #include <stdio.h>
00041 #include <stdlib.h>
00042 #include <sys/types.h>
00043 #include <unistd.h>
00044 #include "../mem/mem.h"
00045 #include "../dprint.h"
00046 #include "../str.h"
00047 #include "../ut.h"
00048 #include "parse_content.h"
00049 
00050 
00051 #define is_mime_char(_c_) \
00052         (isalpha((int)_c_) || (_c_)=='-' || (_c_)=='+' || (_c_)=='.')
00053 #define is_char_equal(_c_,_cs_) \
00054         ( (isalpha((int)_c_)?(((_c_)|0x20)==(_cs_)):((_c_)==(_cs_)))==1 )
00055 
00056 
00060 typedef struct type_node_s {
00061         char c;                      
00062         unsigned char final;         
00064         unsigned char nr_sons;       
00065         int next;                    
00066 }type_node_t;
00067 
00068 
00069 static type_node_t type_tree[] = {
00070         {'t',TYPE_UNKNOWN,1,4}, /* 0 */
00071                 {'e',TYPE_UNKNOWN,1,-1},
00072                         {'x',TYPE_UNKNOWN,1,-1},
00073                                 {'t',TYPE_TEXT,0,-1},
00074         {'m',TYPE_UNKNOWN,2,19}, /* 4 */
00075                 {'e',TYPE_UNKNOWN,1,11}, /* 5 */
00076                         {'s',TYPE_UNKNOWN,1,-1},
00077                                 {'s',TYPE_UNKNOWN,1,-1},
00078                                         {'a',TYPE_UNKNOWN,1,-1},
00079                                                 {'g',TYPE_UNKNOWN,1,-1},
00080                                                         {'e',TYPE_MESSAGE,0,-1},
00081                 {'u',TYPE_UNKNOWN,1,-1}, /* 11 */
00082                         {'l',TYPE_UNKNOWN,1,-1},
00083                                 {'t',TYPE_UNKNOWN,1,-1},
00084                                         {'i',TYPE_UNKNOWN,1,-1},
00085                                                 {'p',TYPE_UNKNOWN,1,-1},
00086                                                         {'a',TYPE_UNKNOWN,1,-1},
00087                                                                 {'r',TYPE_UNKNOWN,1,-1},
00088                                                                         {'t',TYPE_MULTIPART,0,-1},
00089         {'a',TYPE_UNKNOWN,1,-1}, /* 19 */
00090                 {'p',TYPE_UNKNOWN,1,-1},
00091                         {'p',TYPE_UNKNOWN,1,-1},
00092                                 {'l',TYPE_UNKNOWN,1,-1},
00093                                         {'i',TYPE_UNKNOWN,1,-1},
00094                                                 {'c',TYPE_UNKNOWN,1,-1},
00095                                                         {'a',TYPE_UNKNOWN,1,-1},
00096                                                                 {'t',TYPE_UNKNOWN,1,-1},
00097                                                                         {'i',TYPE_UNKNOWN,1,-1},
00098                                                                                 {'o',TYPE_UNKNOWN,1,-1},
00099                                                                                         {'n',TYPE_APPLICATION,0,-1},
00100         };
00101 
00102 static type_node_t subtype_tree[] = {
00103         {'p',SUBTYPE_UNKNOWN,2,13},
00104                 {'l',SUBTYPE_UNKNOWN,1,5},
00105                         {'a',SUBTYPE_UNKNOWN,1,-1},
00106                                 {'i',SUBTYPE_UNKNOWN,1,-1},
00107                                         {'n',SUBTYPE_PLAIN,0,-1},
00108                 {'i',SUBTYPE_UNKNOWN,1,-1}, /* 5 */
00109                         {'d',SUBTYPE_UNKNOWN,1,-1},
00110                                 {'f',SUBTYPE_UNKNOWN,1,-1},
00111                                         {'+',TYPE_UNKNOWN,1,-1},
00112                                                 {'x',TYPE_UNKNOWN,1,-1},
00113                                                         {'m',TYPE_UNKNOWN,1,-1},
00114                                                                 {'l',SUBTYPE_PIDFXML,0,-1},
00115                                                                         {'l',SUBTYPE_PIDFXML,0,-1},
00116         {'s',SUBTYPE_UNKNOWN,1,16}, /* 13 */
00117                 {'d',SUBTYPE_UNKNOWN,1,-1},
00118                         {'p',SUBTYPE_SDP,0,-1},
00119         {'c',SUBTYPE_UNKNOWN,1,34}, /* 16 */
00120                 {'p',SUBTYPE_UNKNOWN,2,-1},
00121                         {'i',SUBTYPE_UNKNOWN,1,29},
00122                                 {'m',SUBTYPE_CPIM,1,-1},
00123                                         {'-',SUBTYPE_UNKNOWN,1,-1},
00124                                                 {'p',SUBTYPE_UNKNOWN,1,-1},
00125                                                         {'i',SUBTYPE_UNKNOWN,1,-1},
00126                                                                 {'d',SUBTYPE_UNKNOWN,1,-1},
00127                                                                         {'f',SUBTYPE_UNKNOWN,1,-1},
00128                                                                                 {'+',SUBTYPE_UNKNOWN,1,-1},
00129                                                                                         {'x',SUBTYPE_UNKNOWN,1,-1},
00130                                                                                                 {'m',SUBTYPE_UNKNOWN,1,-1},
00131                                                                                                         {'l',SUBTYPE_CPIM_PIDFXML,0,-1},
00132                         {'l',SUBTYPE_UNKNOWN,1,-1}, /* 29 */
00133                                 {'+',TYPE_UNKNOWN,1,-1},
00134                                         {'x',TYPE_UNKNOWN,1,-1},
00135                                                 {'m',TYPE_UNKNOWN,1,-1},
00136                                                         {'l',SUBTYPE_CPLXML,0,-1},
00137         {'r',SUBTYPE_UNKNOWN,2,48}, /* 34 */
00138                 {'l',SUBTYPE_UNKNOWN,1,42},/* 35 */
00139                         {'m',SUBTYPE_UNKNOWN,1,-1},
00140                                 {'i',SUBTYPE_UNKNOWN,1,-1},
00141                                         {'+',TYPE_UNKNOWN,1,-1},
00142                                                 {'x',TYPE_UNKNOWN,1,-1},
00143                                                         {'m',TYPE_UNKNOWN,1,-1},
00144                                                                 {'l',SUBTYPE_RLMIXML,0,-1},
00145                 {'e',SUBTYPE_UNKNOWN,1,-1}, /* 42 */
00146                         {'l',SUBTYPE_UNKNOWN,1,-1},
00147                                 {'a',SUBTYPE_UNKNOWN,1,-1},
00148                                         {'t',SUBTYPE_UNKNOWN,1,-1},
00149                                                 {'e',SUBTYPE_UNKNOWN,1,-1},
00150                                                         {'d',SUBTYPE_RELATED,0,-1},
00151         {'l',SUBTYPE_UNKNOWN,1,57}, /* 48 */
00152                 {'p',SUBTYPE_UNKNOWN,1,-1},
00153                         {'i',SUBTYPE_UNKNOWN,1,-1},
00154                                 {'d',SUBTYPE_UNKNOWN,1,-1},
00155                                         {'f',SUBTYPE_UNKNOWN,1,-1},
00156                                                 {'+',SUBTYPE_UNKNOWN,1,-1},
00157                                                         {'x',SUBTYPE_UNKNOWN,1,-1},
00158                                                                 {'m',SUBTYPE_UNKNOWN,1,-1},
00159                                                                         {'l',SUBTYPE_LPIDFXML,0,-1},
00160         {'w',SUBTYPE_UNKNOWN,1,72}, /* 57 */
00161                 {'a',SUBTYPE_UNKNOWN,1,-1},
00162                         {'t',SUBTYPE_UNKNOWN,1,-1},
00163                                 {'c',SUBTYPE_UNKNOWN,1,-1},
00164                                         {'h',SUBTYPE_UNKNOWN,1,-1},
00165                                                 {'e',SUBTYPE_UNKNOWN,1,-1},
00166                                                         {'r',SUBTYPE_UNKNOWN,1,-1},
00167                                                                 {'i',TYPE_UNKNOWN,1,-1},
00168                                                                         {'n',TYPE_UNKNOWN,1,-1},
00169                                                                                 {'f',TYPE_UNKNOWN,1,-1},
00170                                                                                         {'o',TYPE_UNKNOWN,1,-1},
00171                                                                                                 {'+',TYPE_UNKNOWN,1,-1},
00172                                                                                                         {'x',TYPE_UNKNOWN,1,-1},
00173                                                                                                                 {'m',TYPE_UNKNOWN,1,-1},
00174                                                                                                                         {'l',SUBTYPE_WATCHERINFOXML,0,-1},
00175         {'x',SUBTYPE_UNKNOWN,2,94}, /* 72 */
00176                 {'p',SUBTYPE_UNKNOWN,1,81}, /* 73 */
00177                         {'i',SUBTYPE_UNKNOWN,1,-1},
00178                                 {'d',SUBTYPE_UNKNOWN,1,-1},
00179                                         {'f',SUBTYPE_UNKNOWN,1,-1},
00180                                                 {'+',SUBTYPE_UNKNOWN,1,-1},
00181                                                         {'x',SUBTYPE_UNKNOWN,1,-1},
00182                                                                 {'m',SUBTYPE_UNKNOWN,1,-1},
00183                                                                         {'l',SUBTYPE_XPIDFXML,0,-1},
00184                 {'m',SUBTYPE_UNKNOWN,1,-1}, /* 81 */
00185                         {'l',SUBTYPE_UNKNOWN,1,-1},
00186                                 {'+',SUBTYPE_UNKNOWN,1,-1},
00187                                         {'m',SUBTYPE_UNKNOWN,1,-1},
00188                                                 {'s',SUBTYPE_UNKNOWN,1,-1},
00189                                                         {'r',SUBTYPE_UNKNOWN,1,-1},
00190                                                                 {'t',SUBTYPE_UNKNOWN,1,-1},
00191                                                                         {'c',SUBTYPE_UNKNOWN,1,-1},
00192                                                                                 {'.',SUBTYPE_UNKNOWN,1,-1},
00193                                                                                         {'p',SUBTYPE_UNKNOWN,1,-1},
00194                                                                                                 {'i',SUBTYPE_UNKNOWN,1,-1}, 
00195                                                                                                         {'d',SUBTYPE_UNKNOWN,1,-1},
00196                                                                                                                 {'f',SUBTYPE_XML_MSRTC_PIDF,0,-1},
00197         {'e',SUBTYPE_UNKNOWN,1,107}, /* 94 */
00198                 {'x',SUBTYPE_UNKNOWN,1,-1},
00199                         {'t',SUBTYPE_UNKNOWN,1,-1},
00200                                 {'e',SUBTYPE_UNKNOWN,1,-1},
00201                                         {'r',SUBTYPE_UNKNOWN,1,-1},
00202                                                 {'n',SUBTYPE_UNKNOWN,1,-1},
00203                                                         {'a',SUBTYPE_UNKNOWN,1,-1},
00204                                                                 {'l',SUBTYPE_UNKNOWN,1,-1},
00205                                                                         {'-',SUBTYPE_UNKNOWN,1,-1},
00206                                                                                 {'b',SUBTYPE_UNKNOWN,1,-1},
00207                                                                                         {'o',SUBTYPE_UNKNOWN,1,-1},
00208                                                                                                 {'d',SUBTYPE_UNKNOWN,1,-1},
00209                                                                                                         {'y',SUBTYPE_EXTERNAL_BODY,0,-1},
00210         {'m',SUBTYPE_UNKNOWN,1,-1}, /* 107 */
00211                 {'i',SUBTYPE_UNKNOWN,1,-1},
00212                         {'x',SUBTYPE_UNKNOWN,1,-1},
00213                                 {'e',SUBTYPE_UNKNOWN,1,-1},
00214                                         {'d',SUBTYPE_MIXED,0,-1},
00215 };
00216 
00217 
00218 
00219 char* parse_content_length( char* buffer, char* end, int* length)
00220 {
00221         int number;
00222         char *p;
00223         int  size;
00224 
00225         p = buffer;
00226         /* search the begining of the number */
00227         while ( p<end && (*p==' ' || *p=='\t' ||
00228         (*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
00229                 p++;
00230         if (p==end)
00231                 goto error;
00232         /* parse the number */
00233         size = 0;
00234         number = 0;
00235         while (p<end && *p>='0' && *p<='9') {
00236                 number = number*10 + (*p)-'0';
00237                 size ++;
00238                 p++;
00239         }
00240         if (p==end || size==0)
00241                 goto error;
00242         /* now we should have only spaces at the end */
00243         while ( p<end && (*p==' ' || *p=='\t' ||
00244         (*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
00245                 p++;
00246         if (p==end)
00247                 goto error;
00248         /* the header ends proper? */
00249         if ( (*(p++)!='\n') && (*(p-1)!='\r' || *(p++)!='\n' ) )
00250                 goto error;
00251 
00252         *length = number;
00253         return p;
00254 error:
00255         LOG(L_ERR,"ERROR:parse_content_length: parse error near char [%d][%c]\n",
00256                 *p,*p);
00257         return 0;
00258 }
00259 
00260 
00261 
00262 char* decode_mime_type(char *start, char *end, unsigned int *mime_type)
00263 {
00264         int node;
00265         char *mark;
00266         char *p;
00267         unsigned int type_candidate;
00268 
00269         p = start;
00270 
00271         /* search the begining of the type */
00272         while ( p<end && (*p==' ' || *p=='\t' ||
00273         (*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
00274                 p++;
00275         if (p==end)
00276                 goto error;
00277 
00278         /* parse the type */
00279         if (*p=='*') {
00280                 *mime_type = TYPE_ALL<<16;
00281                 p++;
00282         } else {
00283                 node = 0;
00284                 mark = p;
00285                 type_candidate = TYPE_UNKNOWN;
00286                 while (p<end && is_mime_char(*p)  ) {
00287                         while ( node!=-1 && !is_char_equal(*p,type_tree[node].c) ){
00288                                 node = type_tree[node].next;
00289                         }
00290                         if (node!=-1) {
00291                                 type_candidate = type_tree[node].final;
00292                                 if (type_tree[node].nr_sons)
00293                                         node++;
00294                                 else
00295                                         node = -1;
00296                         } else {
00297                                 /* end of the type tree has reached,
00298                                 but the type has still some remaining
00299                                 characters (Miklos) */
00300                                 type_candidate = TYPE_UNKNOWN;
00301                         }
00302                         p++;
00303                 }
00304                 if (p==end || mark==p)
00305                         goto error;
00306                 *mime_type = type_candidate<<16;
00307         }
00308 
00309         /* search the '/' separator */
00310         while ( p<end && (*p==' ' || *p=='\t' ||
00311         (*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
00312                 p++;
00313         if ( p==end || *(p++)!='/')
00314                 goto error;
00315 
00316         /* search the begining of the sub-type */
00317         while ( p<end && (*p==' ' || *p=='\t' ||
00318         (*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
00319                 p++;
00320         if (p==end)
00321                 goto error;
00322 
00323         /* parse the sub-type */
00324         if (*p=='*') {
00325                 *mime_type |= SUBTYPE_ALL;
00326                 p++;
00327         } else {
00328                 node = 0;
00329                 mark = p;
00330                 type_candidate = SUBTYPE_UNKNOWN;
00331                 while (p<end && is_mime_char(*p) ) {
00332                         while(node!=-1 && !is_char_equal(*p,subtype_tree[node].c) )
00333                                 node = subtype_tree[node].next;
00334                         if (node!=-1) {
00335                                 type_candidate = subtype_tree[node].final;
00336                                 if (subtype_tree[node].nr_sons)
00337                                         node++;
00338                                 else
00339                                         node = -1;
00340                         } else {
00341                                 /* end of the subtype tree has reached,
00342                                 but the subtype has still some remaining
00343                                 characters (Miklos) */
00344                                 type_candidate = SUBTYPE_UNKNOWN;
00345                         }
00346                         p++;
00347                 }
00348                 if (p==mark)
00349                         goto error;
00350                 *mime_type |= type_candidate;;
00351         }
00352 
00353         /* now its possible to have some spaces */
00354         while ( p<end && (*p==' ' || *p=='\t' ||
00355         (*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
00356                 p++;
00357 
00358         /* if there are params, ignore them!! -> eat everything to
00359          * the end or to the first ',' */
00360         if ( p<end && *p==';' )
00361                 for(p++; p<end && *p!=','; p++);
00362 
00363         /* is this the correct end? */
00364         if (p!=end && *p!=',' )
00365                 goto error;
00366 
00367         /* check the format of the decoded mime */
00368         if ((*mime_type)>>16==TYPE_ALL && ((*mime_type)&0x00ff)!=SUBTYPE_ALL) {
00369                 LOG(L_ERR,"ERROR:decode_mime_type: invalid mime format found "
00370                         " <*/submime> in [%.*s]!!\n", (int)(end-start),start);
00371                 return 0;
00372         }
00373 
00374         return p;
00375 error:
00376         LOG(L_ERR,"ERROR:decode_mime_type: parse error near in [%.*s] char"
00377                 "[%d][%c] offset=%d\n", (int)(end-start),start,*p,*p,(int)(p-start));
00378         return 0;
00379 }
00380 
00381 
00382 
00388 int parse_content_type_hdr( struct sip_msg *msg )
00389 {
00390         char *end;
00391         char *ret;
00392         unsigned int  mime;
00393 
00394         /* is the header already found? */
00395         if ( msg->content_type==0 ) {
00396                 /* if not, found it */
00397                 if ( parse_headers(msg, HDR_CONTENTTYPE_F, 0)==-1)
00398                         goto error;
00399                 if ( msg->content_type==0 ) {
00400                         DBG("DEBUG:parse_content_type_hdr: missing Content-Type"
00401                                 "header\n");
00402                         return 0;
00403                 }
00404         }
00405 
00406         /* maybe the header is already parsed! */
00407         if ( msg->content_type->parsed!=0)
00408                 return get_content_type(msg);
00409 
00410         /* it seams we have to parse it! :-( */
00411         end = msg->content_type->body.s + msg->content_type->body.len;
00412         ret = decode_mime_type(msg->content_type->body.s, end , &mime);
00413         if (ret==0)
00414                 goto error;
00415         if (ret!=end) {
00416                 LOG(L_ERR,"ERROR:parse_content_type_hdr: CONTENT_TYPE hdr contains "
00417                         "more then one mime type :-(!\n");
00418                 goto error;
00419         }
00420         if ((mime&0x00ff)==SUBTYPE_ALL || (mime>>16)==TYPE_ALL) {
00421                 LOG(L_ERR,"ERROR:parse_content_type_hdr: invalid mime with wildcard "
00422                         "'*' in Content-Type hdr!\n");
00423                 goto error;
00424         }
00425 
00426         msg->content_type->parsed = (void*)(unsigned long)mime;
00427         return mime;
00428 
00429 error:
00430         return -1;
00431 }
00432 
00433 int parse_accept_body(struct hdr_field *hdr)
00434 {
00435         static unsigned int mimes[MAX_MIMES_NR];
00436         int nr_mimes;
00437         unsigned int mime;
00438         char *end;
00439         char *ret;
00440 
00441         if (!hdr) return -1;
00442         
00443         /* maybe the header is already parsed! */
00444         if (hdr->parsed!=0) return 1;
00445         
00446         /* it seams we have to parse it! :-( */
00447         ret = hdr->body.s;
00448         end = ret + hdr->body.len;
00449         nr_mimes = 0;
00450         while (1){
00451                 ret = decode_mime_type(ret, end , &mime);
00452                 if (ret==0)
00453                         goto error;
00454                 /* a new mime was found  -> put it into array */
00455                 if (nr_mimes==MAX_MIMES_NR) {
00456                         LOG(L_ERR,"ERROR:parse_accept_hdr: Accept hdr contains more than"
00457                                 " %d mime type -> buffer overflow!!\n",MAX_MIMES_NR);
00458                         goto error;
00459                 }
00460                 mimes[nr_mimes++] = mime;
00461                 /* is another mime following? */
00462                 if (ret==end )
00463                         break;
00464                 /* parse the mime separator ',' */
00465                 if (*ret!=',' || ret+1==end) {
00466                         LOG(L_ERR,"ERROR:parse_accept_hdr: parse error between mimes at "
00467                                 "char <%x> (offset=%d) in <%.*s>!\n",
00468                                 *ret, (int)(ret-hdr->body.s),
00469                                 hdr->body.len, hdr->body.s);
00470                         goto error;
00471                 }
00472                 /* skip the ',' */
00473                 ret++;
00474         }
00475 
00476         /* copy and link the mime buffer into the message */
00477         hdr->parsed = (void*)pkg_malloc((nr_mimes+1)*sizeof(int));
00478         if (hdr->parsed==0) {
00479                 LOG(L_ERR,"ERROR:parse_accept: no more pkg memory\n");
00480                 goto error;
00481         }
00482         memcpy(hdr->parsed,mimes,nr_mimes*sizeof(int));
00483         /* make the buffer null terminated */
00484         ((int*)hdr->parsed)[nr_mimes] = 0;
00485 
00486         return 1;
00487 error:
00488         return -1;
00489 }
00490 
00495 int parse_accept_hdr( struct sip_msg *msg )
00496 {
00497         static unsigned int mimes[MAX_MIMES_NR];
00498         int nr_mimes;
00499         unsigned int mime;
00500         char *end;
00501         char *ret;
00502 
00503         /* is the header already found? */
00504         if ( msg->accept==0 ) {
00505                 /* if not, found it */
00506                 if ( parse_headers(msg, HDR_ACCEPT_F, 0)==-1)
00507                         goto error;
00508                 if ( msg->accept==0 ) {
00509                         DBG("DEBUG:parse_accept_hdr: missing Accept header\n");
00510                         return 0;
00511                 }
00512         }
00513 
00514         /* maybe the header is already parsed! */
00515         if ( msg->accept->parsed!=0)
00516                 return 1;
00517 
00518         /* it seams we have to parse it! :-( */
00519         ret = msg->accept->body.s;
00520         end = ret + msg->accept->body.len;
00521         nr_mimes = 0;
00522         while (1){
00523                 ret = decode_mime_type(ret, end , &mime);
00524                 if (ret==0)
00525                         goto error;
00526                 /* a new mime was found  -> put it into array */
00527                 if (nr_mimes==MAX_MIMES_NR) {
00528                         LOG(L_ERR,"ERROR:parse_accept_hdr: Accept hdr contains more than"
00529                                 " %d mime type -> buffer overflow!!\n",MAX_MIMES_NR);
00530                         goto error;
00531                 }
00532                 mimes[nr_mimes++] = mime;
00533                 /* is another mime following? */
00534                 if (ret==end )
00535                         break;
00536                 /* parse the mime separator ',' */
00537                 if (*ret!=',' || ret+1==end) {
00538                         LOG(L_ERR,"ERROR:parse_accept_hdr: parse error between mimes at "
00539                                 "char <%x> (offset=%d) in <%.*s>!\n",
00540                                 *ret, (int)(ret-msg->accept->body.s),
00541                                 msg->accept->body.len, msg->accept->body.s);
00542                         goto error;
00543                 }
00544                 /* skip the ',' */
00545                 ret++;
00546         }
00547 
00548         /* copy and link the mime buffer into the message */
00549         msg->accept->parsed = (void*)pkg_malloc((nr_mimes+1)*sizeof(int));
00550         if (msg->accept->parsed==0) {
00551                 LOG(L_ERR,"ERROR:parse_accept_hdr: no more pkg memory\n");
00552                 goto error;
00553         }
00554         memcpy(msg->accept->parsed,mimes,nr_mimes*sizeof(int));
00555         /* make the buffer null terminated */
00556         ((int*)msg->accept->parsed)[nr_mimes] = 0;
00557 
00558         return 1;
00559 error:
00560         return -1;
00561 }
00562