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

📄 msg_mime.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 4 页
字号:
  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. *  * Add missing components such as boundaries between body parts, separators * between body-part headers and data, and close-delimiter after last * body-part to the multipart message. *  * @param[in,out] home home for allocating structures  * @param[in,out] c    content-type header for multipart  * @param[in,out] mp   pointer to first multipart structure  * * @retval 0 when successful * @retval -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;  size_t 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\"", (int)m, b);    }    else {      strcpy(token, "boundary=");      msg_random_token(token + strlen("boundary="), (size_t)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, 						(int)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_pub_t*)mp)->msg_request;	 (char *)hh < (char *)&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. */issize_t 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. */issize_t msg_multipart_d(su_home_t *home, msg_header_t *h, char *s, isize_t 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. */issize_t msg_multipart_e(char b[], isize_t bsiz, msg_header_t const *h, int flags){  return msg_payload_e(b, bsiz, h, flags);}/** Calculate extra size of a multipart */isize_t msg_multipart_dup_xtra(msg_header_t const *h, isize_t offset){  msg_multipart_t const *mp = (msg_multipart_t *)h;  msg_header_t const * const *hh;  offset = msg_payload_dup_xtra(h, offset);  for (hh = (msg_header_t const **)&((msg_pub_t *)mp)->msg_request;       (char *)hh <= (char *)&mp->mp_close_delim;        hh++) {    for (h = *hh; h; h = h->sh_next) {      MSG_STRUCT_SIZE_ALIGN(offset);      offset = h->sh_class->hc_dxtra(h, offset + h->sh_class->hc_size);    }  }  return offset;}/** Duplicate one msg_multipart_t object */char *msg_multipart_dup_one(msg_header_t *dst, msg_header_t const *src,			    char *b, isize_t xtra){  msg_multipart_t const *mp = (msg_multipart_t *)src;  msg_header_t *h, **hh;  char *end = b + xtra;  b = msg_payload_dup_one(dst, src, b, xtra);  for (hh = &((msg_pub_t*)mp)->msg_request;       (char *)hh <= (char *)&mp->mp_close_delim;        hh++) {    for (h = *hh; h; h = h->sh_next) {      MSG_STRUCT_ALIGN(b);      dst = (msg_header_t *)b;      memset(dst, 0, sizeof dst->sh_common);      dst->sh_class = h->sh_class;      b = h->sh_class->hc_dup_one(dst, h, b + h->sh_class->hc_size, end - b);      if (h->sh_class->hc_update)	msg_header_update_params(h->sh_common, 0);      assert(b <= end);    }  }  return b;}#if 0msg_hclass_t msg_multipart_class[] =MSG_HEADER_CLASS(msg_, multipart, NULL, "", mp_common, append, msg_multipart);#endif/**Calculate Q value. * * The function msg_q_value() converts q-value string @a q to numeric value * in range (0..1000).  Q values are used, for instance, to describe * relative priorities of registered contacts. * * @param q q-value string ("1" | "." 1,3DIGIT) * * @return * The function msg_q_value() returns an integer in range 0 .. 1000. */unsigned msg_q_value(char const *q){  unsigned value = 0;  if (!q)    return 500;  if (q[0] != '0' && q[0] != '.' && q[0] != '1')    return 500;  while (q[0] == '0')    q++;  if (q[0] >= '1' && q[0] <= '9')    return 1000;  if (q[0] == '\0')    return 0;  if (q[0] != '.')    /* Garbage... */    return 500;  if (q[1] >= '0' && q[1] <= '9') {    value = (q[1] - '0') * 100;    if (q[2] >= '0' && q[2] <= '9') {      value += (q[2] - '0') * 10;      if (q[3] >= '0' && q[3] <= '9') {	value += (q[3] - '0');	if (q[4] > '5' && q[4] <= '9')	  /* Round upwards */	  value += 1;	else if (q[4] == '5')	  value += value & 1; /* Round to even */      }    }  }  return value;}/** Parse media type (type/subtype). * * The function msg_mediatype_d() parses a mediatype string. * * @param[in,out] ss    string to be parsed  * @param[out]    type  value result for media type  * * @retval 0 when successful, * @retval -1 upon an error. */issize_t msg_mediatype_d(char **ss, char const **type){  char *s = *ss;  char const *result = s;  size_t l1 = 0, l2 = 0, n;  /* Media type consists of two tokens, separated by / */  l1 = span_token(s);  for (n = l1; IS_LWS(s[n]); n++);  if (s[n] == '/') {    for (n++; IS_LWS(s[n]); n++);    l2 = span_token(s + n);    n += l2;  }  if (l1 == 0 || l2 == 0)    return -1;  /* If there is extra ws between tokens, compact version */  if (n > l1 + 1 + l2) {    s[l1] = '/';    memmove(s + l1 + 1, s + n - l2, l2);    s[l1 + 1 + l2] = 0;  }  s += n;  while (IS_WS(*s)) *s++ = '\0';  *ss = s;  if (type)    *type = result;  return 0;}/* ====================================================================== *//**@ingroup msg_mime * @defgroup msg_accept Accept Header * * The @b Accept request-header field can be used to specify certain media * types which are acceptable for the response. Its syntax is defined in * [H14.1, S20.1] as follows: * * @code *    Accept         = "Accept" ":" #( media-range [ accept-params ] ) * *    media-range    = ( "*" "/" "*" *                     | ( type "/" "*" ) *                     | ( type "/" subtype ) ) *( ";" parameter ) * *    accept-params  = ";" "q" "=" qvalue *( accept-extension ) * *    accept-extension = ";" token [ "=" ( token | quoted-string ) ] * @endcode * *//**@ingroup msg_accept * @typedef typedef struct msg_accept_s msg_accept_t; * * The structure msg_accept_t contains representation of an @b Accept * header. * * The msg_accept_t is defined as follows: * @code * typedef struct msg_accept_s { *   msg_common_t        ac_common[1]; // Common fragment info *   msg_accept_t       *ac_next;      // Pointer to next Accept header *   char const         *ac_type;      // Pointer to type/subtype *   char const         *ac_subtype;   // Points after first slash in type *   msg_param_t const  *ac_params;    // List of parameters *   msg_param_t         ac_q;         // Value of q parameter * } msg_accept_t; * @endcode */msg_hclass_t msg_accept_class[] =MSG_HEADER_CLASS(msg_, accept, "Accept", "", ac_params, apndlist, 		 msg_accept, msg_accept);issize_t msg_accept_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen){  msg_accept_t *ac = (msg_accept_t *)h;  while (*s == ',')   /* Ignore empty entries (comma-whitespace) */    *s = '\0', s += span_lws(s + 1) + 1;  if (*s == '\0') {    /* Empty Accept list is not an error */    ac->ac_type = ac->ac_subtype = "";    return 0;  }

⌨️ 快捷键说明

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