⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msg_mime.c

📁 sip协议栈
💻 C
📖 第 1 页 / 共 5 页
字号:
    while (p[0] == ' ')       p++;    p += p[0] == '\r' ? 1 + (p[1] == '\n') : (p[0] == '\n');    len = end - p;    if (len < blen)      break;    next = memmem(p, len, boundary + 1, m = blen);    if (!next)      break;			/* error */    if (next != p && next[-1] == '\r')      next--, m++;    mp = (msg_multipart_t *)msg_header_alloc(msg_home(msg), msg_multipart_class, 0);    if (mp == NULL)      break;			/* error */    *mmp = mp; mmp = &mp->mp_next;    /* Put delimiter transport-padding CRLF here */    mp->mp_common->h_data = b;    mp->mp_common->h_len = p - b;    /* .. and body-part here */    mp->mp_data = p;    mp->mp_len = next - p;    if (next[m] == '-' && next[m + 1] == '-') {      /* We found close-delimiter */      assert(mp);      if (!mp)	break;			/* error */      mp->mp_close_delim = (msg_payload_t *)	msg_header_alloc(msg_home(msg), msg_payload_class, 0);      if (!mp->mp_close_delim)	break;			/* error */      /* Include also transport-padding and epilogue in the close-delimiter */      mp->mp_close_delim->pl_data = next;      mp->mp_close_delim->pl_len = p + len - next;      break;    }    b = next; p = next + m;   }  if (!mp || !mp->mp_close_delim) {    su_home_deinit(msg_home(msg));    /* Delimiter error */    return NULL;  }  /* Parse each part */  for (mp = all; mp; mp = mp->mp_next) {    msg->m_object = (msg_pub_t *)mp; p = mp->mp_data; next = p + mp->mp_len;    if (msg->m_tail)      mp->mp_common->h_prev = msg->m_tail,	*msg->m_tail = (msg_header_t *)mp;    msg->m_chain = (msg_header_t *)mp;    msg->m_tail = &mp->mp_common->h_succ;    save = *next; *next = '\0';	/* NUL-terminate this part */    for (len = next - p; len > 0; len -= m, p += m) {      if (IS_CRLF(p[0])) {	m = msg_extract_separator(msg, (msg_pub_t*)mp, p, len, 1);	assert(m > 0);	p += m; len -= m;	if (len > 0) {	  m = msg_extract_payload(msg, (msg_pub_t*)mp, NULL, len, p, len, 1);	  assert(m > 0);	  assert(len == m);	}	break;      }      m = msg_extract_header(msg, (msg_pub_t*)mp, p, len, 1);      if (m <= 0) {	assert(m > 0);	/* Xyzzy */      }    }    *next = save; /* XXX - Should we leave the payload NUL-terminated? */  }  /* Postprocess */  blen = strlen(boundary);  for (mp = all; mp; mp = mp->mp_next) {    mp->mp_data = boundary;     mp->mp_len = blen;    assert(mp->mp_payload || mp->mp_separator);    if (mp->mp_close_delim) {      msg_header_t **tail;      if (mp->mp_payload)	tail = &mp->mp_payload->pl_common->h_succ;      else	tail = &mp->mp_separator->sep_common->h_succ;      assert(msg->m_chain == (msg_header_t *)mp);      assert(*tail == NULL);      mp->mp_close_delim->pl_common->h_prev = tail;      *tail = (msg_header_t *)mp->mp_close_delim;    }  }  msg_fragment_clear(pl->pl_common);  pl->pl_len = all->mp_data - (char *)pl->pl_data;  su_home_move(home, msg_home(msg)); su_home_deinit(msg_home(msg));  return all;}/**Add all missing parts to the multipart. *  * The function msg_multipart_complete() adds missing components to the * multipart message. The missing components may include boundaries between * body parts, separators between body-part headers and data, and * close-delimiter after last body-part. *  * @param home home for allocating structures [IN/OUT] * @param c    content-type header for multipart [IN/OUT] * @param mp   pointer to first multipart structure [IN/OUT] * * @return * The function msg_multipart_complete() returns 0 when successful, * -1 upon an error. * * @ERRORS  * @ERROR EBADMSG * The @b Content-Type header @a c is malformed, or multipart message * contains a malformed @b Content-Type header. * @ERROR ENOMEM * A memory allocation failed. * @ERROR EINVAL * The function msg_multipart_complete() was given invalid arguments. */int msg_multipart_complete(su_home_t *home,			   msg_content_type_t *c,			   msg_multipart_t *mp){  char *boundary;  char const *b;  int blen, m;  if (c == NULL || mp == NULL)    return (errno = EINVAL), -1;  if (!(b = msg_header_find_param(c->c_common, "boundary="))) {    /* Generate boundary */    enum { tlen = 16 * 4 / 3 };    char token[sizeof("boundary=") + tlen + 1];    if (mp->mp_data) {      b = mp->mp_data;      m = mp->mp_len;      if (strncmp(b, CR LF "--", 4) == 0)	b += 4, m -= 4;      else if (strncmp(b, "--", 2) == 0)	b += 2, m -= 2;      else	return (errno = EBADMSG), -1;      /* XXX - quoting? */      b = su_sprintf(home, "boundary=\"%.*s\"", m, b);    }    else {      strcpy(token, "boundary=");      msg_random_token(token + strlen("boundary="), tlen, NULL, 0);      b = su_strdup(home, token);    }    if (!b)      return -1;    msg_params_replace(home, (msg_param_t **)&c->c_params, b);    b += strlen("boundary=");  }  if (!(boundary = msg_multipart_boundary(home, b)))    return -1;  blen = strlen(boundary); m = blen - 2;  for (; mp; mp = mp->mp_next) {    if (mp->mp_data == NULL) {      mp->mp_data = boundary, mp->mp_len = blen;    } else {      if (mp->mp_len < 3)	return -1;      if (mp->mp_data[0] == '\r' && mp->mp_data[1] == '\n') {	if (mp->mp_len < m || memcmp(mp->mp_data + 2, boundary + 2, m - 2))	  return -1;      } else if (mp->mp_data[0] == '\n') {	if (mp->mp_len < m - 1 || memcmp(mp->mp_data + 1, boundary + 2, m - 2))	  return -1;      } else {	if (mp->mp_len < m - 2 || memcmp(mp->mp_data, boundary + 2, m - 2))	  return -1;      }    }    if (mp->mp_next == NULL) {      if (!mp->mp_close_delim)	mp->mp_close_delim = msg_payload_format(home, "%.*s--" CR LF, 						m, boundary);      if (!mp->mp_close_delim)	return -1;    }    else if (mp->mp_close_delim) {      msg_payload_t *e = mp->mp_close_delim;      mp->mp_close_delim = NULL;      if (e->pl_common->h_prev)	*e->pl_common->h_prev = e->pl_common->h_succ;      if (e->pl_common->h_succ)	e->pl_common->h_succ->sh_prev = e->pl_common->h_prev;    }    mp->mp_common->h_data = mp->mp_data;    mp->mp_common->h_len = mp->mp_len;    if (!mp->mp_separator)      if (!(mp->mp_separator = msg_separator_make(home, CR LF)))	return -1;    if (mp->mp_multipart) {      c = mp->mp_content_type;      if (c == NULL)	return (errno = EBADMSG), -1;      if (msg_multipart_complete(home, c, mp->mp_multipart) < 0)	return -1;    }    if (!mp->mp_payload)      if (!(mp->mp_payload = msg_payload_create(home, NULL, 0)))	return -1;  }  return 0;}/** Serialize a multipart message. * */msg_header_t *msg_multipart_serialize(msg_header_t **head0,				      msg_multipart_t *mp){  msg_header_t *h_succ_all = NULL;  msg_header_t *h, **head, **hh, *h0, *h_succ;  void *hend;#define is_in_chain(h) ((h) && ((msg_frg_t*)(h))->h_prev != NULL)#define insert(head, h) \  ((h)->sh_succ = *(head), *(head) = (h), \   (h)->sh_prev = (head), (head) = &(h)->sh_succ)  if (mp == NULL || head0 == NULL)    return NULL;  h_succ_all = *head0; head = head0;  for (; mp; mp = mp->mp_next) {    h0 = (msg_header_t *)mp;    assert(mp->mp_separator); assert(mp->mp_payload);    assert(mp->mp_next || mp->mp_close_delim);    if (!mp->mp_separator || !mp->mp_payload ||	(!mp->mp_next && !mp->mp_close_delim))      return NULL;    if ((void *)mp == h_succ_all)      h_succ_all = NULL;    *head0 = h0; h0->sh_prev = head;    if (is_in_chain(mp->mp_separator))      hend = mp->mp_separator;    else if (is_in_chain(mp->mp_payload))      hend = mp->mp_payload;    else if (is_in_chain(mp->mp_multipart))      hend = mp->mp_multipart;    else if (is_in_chain(mp->mp_close_delim))      hend = mp->mp_close_delim;    else if (is_in_chain(mp->mp_next))      hend = mp->mp_next;    else      hend = NULL;    /* Search latest header in chain */    for (head = &mp->mp_common->h_succ;	 *head && *head != hend;	 head = &(*head)->sh_succ)      ;    h_succ = *head;    /* Serialize headers */    for (hh = (msg_header_t **)&mp->mp_content_type;	 hh < (msg_header_t **)&mp->mp_separator;	 hh++) {      h = *hh; if (!h) continue;      for (h = *hh; h; h = h->sh_next) {	if (h == h_succ || !is_in_chain(h)) {	  *head = h; h->sh_prev = head; head = &h->sh_succ;	  while (*head && *head != hend)	    head = &(*head)->sh_succ;	  if (h == h_succ)	    h_succ = *head;	}	else {	  /* XXX Check that h is between head and hend */	}      }    }    if (!is_in_chain(mp->mp_separator)) {      insert(head, (msg_header_t *)mp->mp_separator);    } else {      assert(h_succ == (msg_header_t *)mp->mp_separator);      mp->mp_separator->sep_common->h_prev = head;      *head = (msg_header_t *)mp->mp_separator;      head = &mp->mp_separator->sep_common->h_succ;      h_succ = *head;    }    if (!is_in_chain(mp->mp_payload)) {      insert(head, (msg_header_t *)mp->mp_payload);    } else {      assert(h_succ == (msg_header_t *)mp->mp_payload);      mp->mp_payload->pl_common->h_prev = head;      *head = (msg_header_t *)mp->mp_payload;      head = &mp->mp_payload->pl_common->h_succ;      h_succ = *head;    }    if (mp->mp_multipart) {      if ((*head = h_succ))	h_succ->sh_prev = head;      if (!(h = msg_multipart_serialize(head, mp->mp_multipart)))	return NULL;      head = &h->sh_succ; h_succ = *head;    }    if (mp->mp_close_delim) {      if (!is_in_chain(mp->mp_close_delim)) {	insert(head, (msg_header_t*)mp->mp_close_delim);      } else {	assert(h_succ == (msg_header_t *)mp->mp_close_delim);	mp->mp_close_delim->pl_common->h_prev = head;	*head = (msg_header_t *)mp->mp_close_delim;	head = &mp->mp_close_delim->pl_common->h_succ;      }      if (h_succ_all)	*head = h_succ_all, h_succ_all->sh_prev = head;      return (msg_header_t *)mp->mp_close_delim;    }    *head = h_succ;    head0 = head;  }  assert(!mp);  return NULL;}/** Encode a multipart. * * @return The size of multipart in bytes, or -1 upon an error. */int msg_multipart_prepare(msg_t *msg, msg_multipart_t *mp, int flags){  if (!mp || !mp->mp_data)    return -1;  if (!mp->mp_common->h_data ||       mp->mp_common->h_len != mp->mp_len - 2 ||      memcmp(mp->mp_common->h_data, mp->mp_data + 2, mp->mp_len - 2)) {    mp->mp_common->h_data = mp->mp_data + 2;    mp->mp_common->h_len = mp->mp_len - 2;  }  return msg_headers_prepare(msg, (msg_header_t *)mp, flags);}/** Decode a multipart. */int msg_multipart_d(su_home_t *home, msg_header_t *h, char *s, int slen){  su_home_t tmphome[1] = { SU_HOME_INIT(tmphome) };  msg_payload_t pl[1];  msg_multipart_t *mp, *result;  assert(h && msg_is_multipart(h));  msg_payload_init(pl);    result = (msg_multipart_t *)h;  pl->pl_data = s;   pl->pl_len = slen;  mp = msg_multipart_parse(tmphome, NULL, pl);  if (mp) {    *result = *mp;    if (result->mp_common->h_succ->sh_prev)      result->mp_common->h_succ->sh_prev = 	&result->mp_common->h_succ;    su_free(tmphome, mp);        su_home_move(home, tmphome);  }     su_home_deinit(tmphome);  return mp ? 0 : -1;}/** Encode a multipart. * * Please note that here we just encode a element, the msg_multipart_t * itself. */int msg_multipart_e(char b[], int bsiz, msg_header_t const *h, int flags){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -