parse_content.c 15 KB

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