parse_content.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. /*
  2. * $Id$
  3. *
  4. *
  5. * Copyright (C) 2001-2003 FhG Fokus
  6. *
  7. * This file is part of ser, a free SIP server.
  8. *
  9. * ser is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version
  13. *
  14. * ser is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22. *
  23. * History:
  24. * 2003-08-04 parse_content_type_hdr separates type from subtype inside
  25. * the mime type (bogdan)
  26. * 2003-08-04 CPL subtype added (bogdan)
  27. * 2003-08-05 parse_accept_hdr function added (bogdan)
  28. * 2008-05-23 reset the type/subtype to unknown, if the end of
  29. * tree has reached, but the type/subtype has still
  30. * some remaining characters (Miklos)
  31. */
  32. /*! \file
  33. * \brief Parser :: Content part
  34. *
  35. * \ingroup parser
  36. */
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <sys/types.h>
  40. #include <unistd.h>
  41. #include "../mem/mem.h"
  42. #include "../dprint.h"
  43. #include "../str.h"
  44. #include "../ut.h"
  45. #include "parse_content.h"
  46. #define is_mime_char(_c_) \
  47. (isalpha((int)_c_) || (_c_)=='-' || (_c_)=='+' || (_c_)=='.')
  48. #define is_char_equal(_c_,_cs_) \
  49. ( (isalpha((int)_c_)?(((_c_)|0x20)==(_cs_)):((_c_)==(_cs_)))==1 )
  50. /*! \brief
  51. * Node of the type's tree; this tree contains all the known types;
  52. */
  53. typedef struct type_node_s {
  54. char c; /*!< char contained by this node */
  55. unsigned char final; /*!< says what mime type/subtype was detected
  56. *!< if string ends at this node */
  57. unsigned char nr_sons; /*!< the number of sub-nodes */
  58. int next; /*!< the next sibling node */
  59. }type_node_t;
  60. static type_node_t type_tree[] = {
  61. {'t',TYPE_UNKNOWN,1,4}, /* 0 */
  62. {'e',TYPE_UNKNOWN,1,-1},
  63. {'x',TYPE_UNKNOWN,1,-1},
  64. {'t',TYPE_TEXT,0,-1},
  65. {'m',TYPE_UNKNOWN,2,19}, /* 4 */
  66. {'e',TYPE_UNKNOWN,1,11}, /* 5 */
  67. {'s',TYPE_UNKNOWN,1,-1},
  68. {'s',TYPE_UNKNOWN,1,-1},
  69. {'a',TYPE_UNKNOWN,1,-1},
  70. {'g',TYPE_UNKNOWN,1,-1},
  71. {'e',TYPE_MESSAGE,0,-1},
  72. {'u',TYPE_UNKNOWN,1,-1}, /* 11 */
  73. {'l',TYPE_UNKNOWN,1,-1},
  74. {'t',TYPE_UNKNOWN,1,-1},
  75. {'i',TYPE_UNKNOWN,1,-1},
  76. {'p',TYPE_UNKNOWN,1,-1},
  77. {'a',TYPE_UNKNOWN,1,-1},
  78. {'r',TYPE_UNKNOWN,1,-1},
  79. {'t',TYPE_MULTIPART,0,-1},
  80. {'a',TYPE_UNKNOWN,1,-1}, /* 19 */
  81. {'p',TYPE_UNKNOWN,1,-1},
  82. {'p',TYPE_UNKNOWN,1,-1},
  83. {'l',TYPE_UNKNOWN,1,-1},
  84. {'i',TYPE_UNKNOWN,1,-1},
  85. {'c',TYPE_UNKNOWN,1,-1},
  86. {'a',TYPE_UNKNOWN,1,-1},
  87. {'t',TYPE_UNKNOWN,1,-1},
  88. {'i',TYPE_UNKNOWN,1,-1},
  89. {'o',TYPE_UNKNOWN,1,-1},
  90. {'n',TYPE_APPLICATION,0,-1},
  91. };
  92. static type_node_t subtype_tree[] = {
  93. {'p',SUBTYPE_UNKNOWN,2,13},
  94. {'l',SUBTYPE_UNKNOWN,1,5},
  95. {'a',SUBTYPE_UNKNOWN,1,-1},
  96. {'i',SUBTYPE_UNKNOWN,1,-1},
  97. {'n',SUBTYPE_PLAIN,0,-1},
  98. {'i',SUBTYPE_UNKNOWN,1,-1}, /* 5 */
  99. {'d',SUBTYPE_UNKNOWN,1,-1},
  100. {'f',SUBTYPE_UNKNOWN,1,-1},
  101. {'+',TYPE_UNKNOWN,1,-1},
  102. {'x',TYPE_UNKNOWN,1,-1},
  103. {'m',TYPE_UNKNOWN,1,-1},
  104. {'l',SUBTYPE_PIDFXML,0,-1},
  105. {'l',SUBTYPE_PIDFXML,0,-1},
  106. {'s',SUBTYPE_UNKNOWN,1,16}, /* 13 */
  107. {'d',SUBTYPE_UNKNOWN,1,-1},
  108. {'p',SUBTYPE_SDP,0,-1},
  109. {'c',SUBTYPE_UNKNOWN,1,34}, /* 16 */
  110. {'p',SUBTYPE_UNKNOWN,2,-1},
  111. {'i',SUBTYPE_UNKNOWN,1,29},
  112. {'m',SUBTYPE_CPIM,1,-1},
  113. {'-',SUBTYPE_UNKNOWN,1,-1},
  114. {'p',SUBTYPE_UNKNOWN,1,-1},
  115. {'i',SUBTYPE_UNKNOWN,1,-1},
  116. {'d',SUBTYPE_UNKNOWN,1,-1},
  117. {'f',SUBTYPE_UNKNOWN,1,-1},
  118. {'+',SUBTYPE_UNKNOWN,1,-1},
  119. {'x',SUBTYPE_UNKNOWN,1,-1},
  120. {'m',SUBTYPE_UNKNOWN,1,-1},
  121. {'l',SUBTYPE_CPIM_PIDFXML,0,-1},
  122. {'l',SUBTYPE_UNKNOWN,1,-1}, /* 29 */
  123. {'+',TYPE_UNKNOWN,1,-1},
  124. {'x',TYPE_UNKNOWN,1,-1},
  125. {'m',TYPE_UNKNOWN,1,-1},
  126. {'l',SUBTYPE_CPLXML,0,-1},
  127. {'r',SUBTYPE_UNKNOWN,2,48}, /* 34 */
  128. {'l',SUBTYPE_UNKNOWN,1,42},/* 35 */
  129. {'m',SUBTYPE_UNKNOWN,1,-1},
  130. {'i',SUBTYPE_UNKNOWN,1,-1},
  131. {'+',TYPE_UNKNOWN,1,-1},
  132. {'x',TYPE_UNKNOWN,1,-1},
  133. {'m',TYPE_UNKNOWN,1,-1},
  134. {'l',SUBTYPE_RLMIXML,0,-1},
  135. {'e',SUBTYPE_UNKNOWN,1,-1}, /* 42 */
  136. {'l',SUBTYPE_UNKNOWN,1,-1},
  137. {'a',SUBTYPE_UNKNOWN,1,-1},
  138. {'t',SUBTYPE_UNKNOWN,1,-1},
  139. {'e',SUBTYPE_UNKNOWN,1,-1},
  140. {'d',SUBTYPE_RELATED,0,-1},
  141. {'l',SUBTYPE_UNKNOWN,1,57}, /* 48 */
  142. {'p',SUBTYPE_UNKNOWN,1,-1},
  143. {'i',SUBTYPE_UNKNOWN,1,-1},
  144. {'d',SUBTYPE_UNKNOWN,1,-1},
  145. {'f',SUBTYPE_UNKNOWN,1,-1},
  146. {'+',SUBTYPE_UNKNOWN,1,-1},
  147. {'x',SUBTYPE_UNKNOWN,1,-1},
  148. {'m',SUBTYPE_UNKNOWN,1,-1},
  149. {'l',SUBTYPE_LPIDFXML,0,-1},
  150. {'w',SUBTYPE_UNKNOWN,1,72}, /* 57 */
  151. {'a',SUBTYPE_UNKNOWN,1,-1},
  152. {'t',SUBTYPE_UNKNOWN,1,-1},
  153. {'c',SUBTYPE_UNKNOWN,1,-1},
  154. {'h',SUBTYPE_UNKNOWN,1,-1},
  155. {'e',SUBTYPE_UNKNOWN,1,-1},
  156. {'r',SUBTYPE_UNKNOWN,1,-1},
  157. {'i',TYPE_UNKNOWN,1,-1},
  158. {'n',TYPE_UNKNOWN,1,-1},
  159. {'f',TYPE_UNKNOWN,1,-1},
  160. {'o',TYPE_UNKNOWN,1,-1},
  161. {'+',TYPE_UNKNOWN,1,-1},
  162. {'x',TYPE_UNKNOWN,1,-1},
  163. {'m',TYPE_UNKNOWN,1,-1},
  164. {'l',SUBTYPE_WATCHERINFOXML,0,-1},
  165. {'x',SUBTYPE_UNKNOWN,2,94}, /* 72 */
  166. {'p',SUBTYPE_UNKNOWN,1,81}, /* 73 */
  167. {'i',SUBTYPE_UNKNOWN,1,-1},
  168. {'d',SUBTYPE_UNKNOWN,1,-1},
  169. {'f',SUBTYPE_UNKNOWN,1,-1},
  170. {'+',SUBTYPE_UNKNOWN,1,-1},
  171. {'x',SUBTYPE_UNKNOWN,1,-1},
  172. {'m',SUBTYPE_UNKNOWN,1,-1},
  173. {'l',SUBTYPE_XPIDFXML,0,-1},
  174. {'m',SUBTYPE_UNKNOWN,1,-1}, /* 81 */
  175. {'l',SUBTYPE_UNKNOWN,1,-1},
  176. {'+',SUBTYPE_UNKNOWN,1,-1},
  177. {'m',SUBTYPE_UNKNOWN,1,-1},
  178. {'s',SUBTYPE_UNKNOWN,1,-1},
  179. {'r',SUBTYPE_UNKNOWN,1,-1},
  180. {'t',SUBTYPE_UNKNOWN,1,-1},
  181. {'c',SUBTYPE_UNKNOWN,1,-1},
  182. {'.',SUBTYPE_UNKNOWN,1,-1},
  183. {'p',SUBTYPE_UNKNOWN,1,-1},
  184. {'i',SUBTYPE_UNKNOWN,1,-1},
  185. {'d',SUBTYPE_UNKNOWN,1,-1},
  186. {'f',SUBTYPE_XML_MSRTC_PIDF,0,-1},
  187. {'e',SUBTYPE_UNKNOWN,1,107}, /* 94 */
  188. {'x',SUBTYPE_UNKNOWN,1,-1},
  189. {'t',SUBTYPE_UNKNOWN,1,-1},
  190. {'e',SUBTYPE_UNKNOWN,1,-1},
  191. {'r',SUBTYPE_UNKNOWN,1,-1},
  192. {'n',SUBTYPE_UNKNOWN,1,-1},
  193. {'a',SUBTYPE_UNKNOWN,1,-1},
  194. {'l',SUBTYPE_UNKNOWN,1,-1},
  195. {'-',SUBTYPE_UNKNOWN,1,-1},
  196. {'b',SUBTYPE_UNKNOWN,1,-1},
  197. {'o',SUBTYPE_UNKNOWN,1,-1},
  198. {'d',SUBTYPE_UNKNOWN,1,-1},
  199. {'y',SUBTYPE_EXTERNAL_BODY,0,-1},
  200. {'m',SUBTYPE_UNKNOWN,1,-1}, /* 107 */
  201. {'i',SUBTYPE_UNKNOWN,1,-1},
  202. {'x',SUBTYPE_UNKNOWN,1,-1},
  203. {'e',SUBTYPE_UNKNOWN,1,-1},
  204. {'d',SUBTYPE_MIXED,0,-1},
  205. };
  206. char* parse_content_length( char* buffer, char* end, int* length)
  207. {
  208. int number;
  209. char *p;
  210. int size;
  211. p = buffer;
  212. /* search the begining of the number */
  213. while ( p<end && (*p==' ' || *p=='\t' ||
  214. (*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
  215. p++;
  216. if (p==end)
  217. goto error;
  218. /* parse the number */
  219. size = 0;
  220. number = 0;
  221. while (p<end && *p>='0' && *p<='9') {
  222. number = number*10 + (*p)-'0';
  223. size ++;
  224. p++;
  225. }
  226. if (p==end || size==0)
  227. goto error;
  228. /* now we should have only spaces at the end */
  229. while ( p<end && (*p==' ' || *p=='\t' ||
  230. (*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
  231. p++;
  232. if (p==end)
  233. goto error;
  234. /* the header ends proper? */
  235. if ( (*(p++)!='\n') && (*(p-1)!='\r' || *(p++)!='\n' ) )
  236. goto error;
  237. *length = number;
  238. return p;
  239. error:
  240. LOG(L_ERR,"ERROR:parse_content_length: parse error near char [%d][%c]\n",
  241. *p,*p);
  242. return 0;
  243. }
  244. char* decode_mime_type(char *start, char *end, unsigned int *mime_type)
  245. {
  246. int node;
  247. char *mark;
  248. char *p;
  249. unsigned int type_candidate;
  250. p = start;
  251. /* search the begining of the type */
  252. while ( p<end && (*p==' ' || *p=='\t' ||
  253. (*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
  254. p++;
  255. if (p==end)
  256. goto error;
  257. /* parse the type */
  258. if (*p=='*') {
  259. *mime_type = TYPE_ALL<<16;
  260. p++;
  261. } else {
  262. node = 0;
  263. mark = p;
  264. type_candidate = TYPE_UNKNOWN;
  265. while (p<end && is_mime_char(*p) ) {
  266. while ( node!=-1 && !is_char_equal(*p,type_tree[node].c) ){
  267. node = type_tree[node].next;
  268. }
  269. if (node!=-1) {
  270. type_candidate = type_tree[node].final;
  271. if (type_tree[node].nr_sons)
  272. node++;
  273. else
  274. node = -1;
  275. } else {
  276. /* end of the type tree has reached,
  277. but the type has still some remaining
  278. characters (Miklos) */
  279. type_candidate = TYPE_UNKNOWN;
  280. }
  281. p++;
  282. }
  283. if (p==end || mark==p)
  284. goto error;
  285. *mime_type = type_candidate<<16;
  286. }
  287. /* search the '/' separator */
  288. while ( p<end && (*p==' ' || *p=='\t' ||
  289. (*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
  290. p++;
  291. if ( p==end || *(p++)!='/')
  292. goto error;
  293. /* search the begining of the sub-type */
  294. while ( p<end && (*p==' ' || *p=='\t' ||
  295. (*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
  296. p++;
  297. if (p==end)
  298. goto error;
  299. /* parse the sub-type */
  300. if (*p=='*') {
  301. *mime_type |= SUBTYPE_ALL;
  302. p++;
  303. } else {
  304. node = 0;
  305. mark = p;
  306. type_candidate = SUBTYPE_UNKNOWN;
  307. while (p<end && is_mime_char(*p) ) {
  308. while(node!=-1 && !is_char_equal(*p,subtype_tree[node].c) )
  309. node = subtype_tree[node].next;
  310. if (node!=-1) {
  311. type_candidate = subtype_tree[node].final;
  312. if (subtype_tree[node].nr_sons)
  313. node++;
  314. else
  315. node = -1;
  316. } else {
  317. /* end of the subtype tree has reached,
  318. but the subtype has still some remaining
  319. characters (Miklos) */
  320. type_candidate = SUBTYPE_UNKNOWN;
  321. }
  322. p++;
  323. }
  324. if (p==mark)
  325. goto error;
  326. *mime_type |= type_candidate;;
  327. }
  328. /* now its possible to have some spaces */
  329. while ( p<end && (*p==' ' || *p=='\t' ||
  330. (*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
  331. p++;
  332. /* if there are params, ignore them!! -> eat everything to
  333. * the end or to the first ',' */
  334. if ( p<end && *p==';' )
  335. for(p++; p<end && *p!=','; p++);
  336. /* is this the correct end? */
  337. if (p!=end && *p!=',' )
  338. goto error;
  339. /* check the format of the decoded mime */
  340. if ((*mime_type)>>16==TYPE_ALL && ((*mime_type)&0x00ff)!=SUBTYPE_ALL) {
  341. LOG(L_ERR,"ERROR:decode_mime_type: invalid mime format found "
  342. " <*/submime> in [%.*s]!!\n", (int)(end-start),start);
  343. return 0;
  344. }
  345. return p;
  346. error:
  347. LOG(L_ERR,"ERROR:decode_mime_type: parse error near in [%.*s] char"
  348. "[%d][%c] offset=%d\n", (int)(end-start),start,*p,*p,(int)(p-start));
  349. return 0;
  350. }
  351. /*! \brief
  352. * \return
  353. * - > 0 mime found
  354. * - = 0 hdr not found
  355. * - =-1 error */
  356. int parse_content_type_hdr( struct sip_msg *msg )
  357. {
  358. char *end;
  359. char *ret;
  360. unsigned int mime;
  361. /* is the header already found? */
  362. if ( msg->content_type==0 ) {
  363. /* if not, found it */
  364. if ( parse_headers(msg, HDR_CONTENTTYPE_F, 0)==-1)
  365. goto error;
  366. if ( msg->content_type==0 ) {
  367. DBG("DEBUG:parse_content_type_hdr: missing Content-Type"
  368. "header\n");
  369. return 0;
  370. }
  371. }
  372. /* maybe the header is already parsed! */
  373. if ( msg->content_type->parsed!=0)
  374. return get_content_type(msg);
  375. /* it seams we have to parse it! :-( */
  376. end = msg->content_type->body.s + msg->content_type->body.len;
  377. ret = decode_mime_type(msg->content_type->body.s, end , &mime);
  378. if (ret==0)
  379. goto error;
  380. if (ret!=end) {
  381. LOG(L_ERR,"ERROR:parse_content_type_hdr: CONTENT_TYPE hdr contains "
  382. "more then one mime type :-(!\n");
  383. goto error;
  384. }
  385. if ((mime&0x00ff)==SUBTYPE_ALL || (mime>>16)==TYPE_ALL) {
  386. LOG(L_ERR,"ERROR:parse_content_type_hdr: invalid mime with wildcard "
  387. "'*' in Content-Type hdr!\n");
  388. goto error;
  389. }
  390. msg->content_type->parsed = (void*)(unsigned long)mime;
  391. return mime;
  392. error:
  393. return -1;
  394. }
  395. int parse_accept_body(struct hdr_field *hdr)
  396. {
  397. static unsigned int mimes[MAX_MIMES_NR];
  398. int nr_mimes;
  399. unsigned int mime;
  400. char *end;
  401. char *ret;
  402. if (!hdr) return -1;
  403. /* maybe the header is already parsed! */
  404. if (hdr->parsed!=0) return 1;
  405. /* it seams we have to parse it! :-( */
  406. ret = hdr->body.s;
  407. end = ret + hdr->body.len;
  408. nr_mimes = 0;
  409. while (1){
  410. ret = decode_mime_type(ret, end , &mime);
  411. if (ret==0)
  412. goto error;
  413. /* a new mime was found -> put it into array */
  414. if (nr_mimes==MAX_MIMES_NR) {
  415. LOG(L_ERR,"ERROR:parse_accept_hdr: Accept hdr contains more than"
  416. " %d mime type -> buffer overflow!!\n",MAX_MIMES_NR);
  417. goto error;
  418. }
  419. mimes[nr_mimes++] = mime;
  420. /* is another mime following? */
  421. if (ret==end )
  422. break;
  423. /* parse the mime separator ',' */
  424. if (*ret!=',' || ret+1==end) {
  425. LOG(L_ERR,"ERROR:parse_accept_hdr: parse error between mimes at "
  426. "char <%x> (offset=%d) in <%.*s>!\n",
  427. *ret, (int)(ret-hdr->body.s),
  428. hdr->body.len, hdr->body.s);
  429. goto error;
  430. }
  431. /* skip the ',' */
  432. ret++;
  433. }
  434. /* copy and link the mime buffer into the message */
  435. hdr->parsed = (void*)pkg_malloc((nr_mimes+1)*sizeof(int));
  436. if (hdr->parsed==0) {
  437. LOG(L_ERR,"ERROR:parse_accept: no more pkg memory\n");
  438. goto error;
  439. }
  440. memcpy(hdr->parsed,mimes,nr_mimes*sizeof(int));
  441. /* make the buffer null terminated */
  442. ((int*)hdr->parsed)[nr_mimes] = 0;
  443. return 1;
  444. error:
  445. return -1;
  446. }
  447. /*! \brief
  448. * returns: > 0 ok
  449. * = 0 hdr not found
  450. * = -1 error */
  451. int parse_accept_hdr( struct sip_msg *msg )
  452. {
  453. static unsigned int mimes[MAX_MIMES_NR];
  454. int nr_mimes;
  455. unsigned int mime;
  456. char *end;
  457. char *ret;
  458. /* is the header already found? */
  459. if ( msg->accept==0 ) {
  460. /* if not, found it */
  461. if ( parse_headers(msg, HDR_ACCEPT_F, 0)==-1)
  462. goto error;
  463. if ( msg->accept==0 ) {
  464. DBG("DEBUG:parse_accept_hdr: missing Accept header\n");
  465. return 0;
  466. }
  467. }
  468. /* maybe the header is already parsed! */
  469. if ( msg->accept->parsed!=0)
  470. return 1;
  471. /* it seams we have to parse it! :-( */
  472. ret = msg->accept->body.s;
  473. end = ret + msg->accept->body.len;
  474. nr_mimes = 0;
  475. while (1){
  476. ret = decode_mime_type(ret, end , &mime);
  477. if (ret==0)
  478. goto error;
  479. /* a new mime was found -> put it into array */
  480. if (nr_mimes==MAX_MIMES_NR) {
  481. LOG(L_ERR,"ERROR:parse_accept_hdr: Accept hdr contains more than"
  482. " %d mime type -> buffer overflow!!\n",MAX_MIMES_NR);
  483. goto error;
  484. }
  485. mimes[nr_mimes++] = mime;
  486. /* is another mime following? */
  487. if (ret==end )
  488. break;
  489. /* parse the mime separator ',' */
  490. if (*ret!=',' || ret+1==end) {
  491. LOG(L_ERR,"ERROR:parse_accept_hdr: parse error between mimes at "
  492. "char <%x> (offset=%d) in <%.*s>!\n",
  493. *ret, (int)(ret-msg->accept->body.s),
  494. msg->accept->body.len, msg->accept->body.s);
  495. goto error;
  496. }
  497. /* skip the ',' */
  498. ret++;
  499. }
  500. /* copy and link the mime buffer into the message */
  501. msg->accept->parsed = (void*)pkg_malloc((nr_mimes+1)*sizeof(int));
  502. if (msg->accept->parsed==0) {
  503. LOG(L_ERR,"ERROR:parse_accept_hdr: no more pkg memory\n");
  504. goto error;
  505. }
  506. memcpy(msg->accept->parsed,mimes,nr_mimes*sizeof(int));
  507. /* make the buffer null terminated */
  508. ((int*)msg->accept->parsed)[nr_mimes] = 0;
  509. return 1;
  510. error:
  511. return -1;
  512. }