static int
msg_osip_body_parse(osip_message_t * sip, const char *start_of_buf,
					const char **next_body, size_t length)
{
	const char *start_of_body;
	const char *end_of_body;
	const char *end_of_buf;
	char *tmp;
	int i;

	char *sep_boundary;
	size_t len_sep_boundary;
	osip_generic_param_t *ct_param;

	if (sip->content_type == NULL
		|| sip->content_type->type == NULL || sip->content_type->subtype == NULL)
		return OSIP_SUCCESS;	/* no body is attached */

	if (0 != osip_strcasecmp(sip->content_type->type, "multipart")) {
		size_t osip_body_len;

		if (start_of_buf[0] == '\0')
			return OSIP_SYNTAXERROR;	/* final CRLF is missing */
		/* get rid of the first CRLF */
		if ('\r' == start_of_buf[0]) {
			if ('\n' == start_of_buf[1])
				start_of_body = start_of_buf + 2;
			else
				start_of_body = start_of_buf + 1;
		} else if ('\n' == start_of_buf[0])
			start_of_body = start_of_buf + 1;
		else
			return OSIP_SYNTAXERROR;	/* message does not end with CRLFCRLF, CRCR or LFLF */

		/* update length (without CRLFCRLF */
		length = length - (start_of_body - start_of_buf);	/* fixed 24 08 2004 */
		if (length <= 0)
			return OSIP_SYNTAXERROR;

		if (sip->content_length != NULL)
			osip_body_len = osip_atoi(sip->content_length->value);
		else {
			/* if content_length does not exist, set it. */
			char tmp[16];

			/* case where content-length is missing but the
			   body only contains non-binary data */
			if (0 == osip_strcasecmp(sip->content_type->type, "application")
				&& 0 == osip_strcasecmp(sip->content_type->subtype, "sdp")) {
				osip_body_len = strlen(start_of_body);
				sprintf(tmp, "%i", osip_body_len);
				i = osip_message_set_content_length(sip, tmp);
				if (i != 0)
					return i;
			} else
				return OSIP_SYNTAXERROR;	/* Content-type may be non binary data */
		}

		if (length < osip_body_len) {
			OSIP_TRACE(osip_trace
					   (__FILE__, __LINE__, OSIP_ERROR, NULL,
						"Message was not receieved enterely. length=%i osip_body_len=%i\n",
						length, osip_body_len));
			return OSIP_SYNTAXERROR;
		}

		end_of_body = start_of_body + osip_body_len;
		tmp = osip_malloc(end_of_body - start_of_body + 2);
		if (tmp == NULL)
			return OSIP_NOMEM;
		memcpy(tmp, start_of_body, end_of_body - start_of_body);
		tmp[end_of_body - start_of_body] = '\0';

		i = osip_message_set_body(sip, tmp, end_of_body - start_of_body);
		osip_free(tmp);
		if (i != 0)
			return i;
		return OSIP_SUCCESS;
	}

	/* find the boundary */
	i = osip_generic_param_get_byname(&sip->content_type->gen_params,
									  "boundary", &ct_param);
	if (i != 0)
		return i;

	if (ct_param == NULL)
		return OSIP_SYNTAXERROR;
	if (ct_param->gvalue == NULL)
		return OSIP_SYNTAXERROR;	/* No boundary but multiple headers??? */

	{
		const char *boundary_prefix = "\n--";

		size_t len = strlen(ct_param->gvalue);

		sep_boundary = (char *) osip_malloc(len + 4);
		if (sep_boundary == NULL)
			return OSIP_NOMEM;
		strcpy(sep_boundary, boundary_prefix);
		if (ct_param->gvalue[0] == '"' && ct_param->gvalue[len - 1] == '"')
			strncat(sep_boundary, ct_param->gvalue + 1, len - 2);
		else
			strncat(sep_boundary, ct_param->gvalue, len);
	}

	len_sep_boundary = strlen(sep_boundary);

	*next_body = NULL;
	start_of_body = start_of_buf;

	end_of_buf = start_of_buf + length;

	for (;;) {
		size_t body_len = 0;

		i = __osip_find_next_occurence(sep_boundary, start_of_body,
									   &start_of_body, end_of_buf);
		if (i != 0) {
			osip_free(sep_boundary);
			return i;
		}

		i = __osip_find_next_occurence(sep_boundary,
									   start_of_body + len_sep_boundary,
									   &end_of_body, end_of_buf);
		if (i != 0) {
			osip_free(sep_boundary);
			return i;
		}

		/* this is the real beginning of body */
		start_of_body = start_of_body + len_sep_boundary + 1;
		if ('\n' == start_of_body[0] || '\r' == start_of_body[0])
			start_of_body++;

		body_len = end_of_body - start_of_body;

		/* Skip CR before end boundary. */
		if (*(end_of_body - 1) == '\r')
			body_len--;

		tmp = osip_malloc(body_len + 2);
		if (tmp == NULL) {
			osip_free(sep_boundary);
			return OSIP_NOMEM;
		}
		memcpy(tmp, start_of_body, body_len);
		tmp[body_len] = '\0';

		i = osip_message_set_body_mime(sip, tmp, body_len);
		osip_free(tmp);
		if (i != 0) {
			osip_free(sep_boundary);
			return i;
		}

		if (strncmp(end_of_body + len_sep_boundary, "--", 2) == 0) {	/* end of all bodies */
			*next_body = end_of_body;
			osip_free(sep_boundary);
			return OSIP_SUCCESS;
		}

		/* continue on the next body */
		start_of_body = end_of_body;
	}
	/* Unreachable code */
	/* osip_free (sep_boundary); */
	return OSIP_SYNTAXERROR;
}
static int
_osip_message_to_str (osip_message_t * sip, char **dest, size_t * message_length, int sipfrag)
{
  size_t malloc_size;
  size_t total_length = 0;

  /* Added at SIPit day1 */
  char *start_of_bodies;
  char *content_length_to_modify = NULL;

  char *message;
  char *next;
  char *tmp;
  int pos;
  int i;
  char *boundary = NULL;

  malloc_size = SIP_MESSAGE_MAX_LENGTH;

  *dest = NULL;
  if (sip == NULL)
    return OSIP_BADPARAMETER;

  {
    if (1 == osip_message_get__property (sip)) {        /* message is already available in "message" */

      *dest = osip_malloc (sip->message_length + 1);
      if (*dest == NULL)
        return OSIP_NOMEM;
      memcpy (*dest, sip->message, sip->message_length);
      (*dest)[sip->message_length] = '\0';
      if (message_length != NULL)
        *message_length = sip->message_length;
      return OSIP_SUCCESS;
    }
    else {
      /* message should be rebuilt: delete the old one if exists. */
      osip_free (sip->message);
      sip->message = NULL;
    }
  }

  message = (char *) osip_malloc (SIP_MESSAGE_MAX_LENGTH);      /* ???? message could be > 4000  */
  if (message == NULL)
    return OSIP_NOMEM;
  *dest = message;

  /* add the first line of message */
  i = __osip_message_startline_to_str (sip, &tmp);
  if (i != 0) {
    if (!sipfrag) {
      osip_free (*dest);
      *dest = NULL;
      return i;
    }

    /* A start-line isn't required for message/sipfrag parts. */
  }
  else {
    message = osip_str_append (message, tmp);
    osip_free (tmp);
    message = osip_strn_append (message, CRLF, 2);
  }

  {
    struct to_str_table {
      char header_name[30];
      int header_length;
      osip_list_t *header_list;
      void *header_data;
      int (*to_str) (void *, char **);
    }
#ifndef MINISIZE
    table[25] =
#else
    table[15] =
#endif
    {
      {
      "Via: ", 5, NULL, NULL, (int (*)(void *, char **)) &osip_via_to_str}, {
      "Record-Route: ", 14, NULL, NULL, (int (*)(void *, char **)) &osip_record_route_to_str}, {
      "Route: ", 7, NULL, NULL, (int (*)(void *, char **)) &osip_route_to_str}, {
      "From: ", 6, NULL, NULL, (int (*)(void *, char **)) &osip_from_to_str}, {
      "To: ", 4, NULL, NULL, (int (*)(void *, char **)) &osip_to_to_str}, {
      "Call-ID: ", 9, NULL, NULL, (int (*)(void *, char **)) &osip_call_id_to_str}, {
      "CSeq: ", 6, NULL, NULL, (int (*)(void *, char **)) &osip_cseq_to_str}, {
      "Contact: ", 9, NULL, NULL, (int (*)(void *, char **)) &osip_contact_to_str}, {
      "Authorization: ", 15, NULL, NULL, (int (*)(void *, char **)) &osip_authorization_to_str}, {
      "WWW-Authenticate: ", 18, NULL, NULL, (int (*)(void *, char **)) &osip_www_authenticate_to_str}, {
      "Proxy-Authenticate: ", 20, NULL, NULL, (int (*)(void *, char **)) &osip_www_authenticate_to_str}, {
      "Proxy-Authorization: ", 21, NULL, NULL, (int (*)(void *, char **)) &osip_authorization_to_str}, {
      "Content-Type: ", 14, NULL, NULL, (int (*)(void *, char **)) &osip_content_type_to_str}, {
      "Mime-Version: ", 14, NULL, NULL, (int (*)(void *, char **)) &osip_content_length_to_str},
#ifndef MINISIZE
      {
      "Allow: ", 7, NULL, NULL, (int (*)(void *, char **)) &osip_allow_to_str}, {
      "Content-Encoding: ", 18, NULL, NULL, (int (*)(void *, char **)) &osip_content_encoding_to_str}, {
      "Call-Info: ", 11, NULL, NULL, (int (*)(void *, char **)) &osip_call_info_to_str}, {
      "Alert-Info: ", 12, NULL, NULL, (int (*)(void *, char **)) &osip_call_info_to_str}, {
      "Error-Info: ", 12, NULL, NULL, (int (*)(void *, char **)) &osip_call_info_to_str}, {
      "Accept: ", 8, NULL, NULL, (int (*)(void *, char **)) &osip_accept_to_str}, {
      "Accept-Encoding: ", 17, NULL, NULL, (int (*)(void *, char **)) &osip_accept_encoding_to_str}, {
      "Accept-Language: ", 17, NULL, NULL, (int (*)(void *, char **)) &osip_accept_language_to_str}, {
      "Authentication-Info: ", 21, NULL, NULL, (int (*)(void *, char **)) &osip_authentication_info_to_str}, {
      "Proxy-Authentication-Info: ", 27, NULL, NULL, (int (*)(void *, char **)) &osip_authentication_info_to_str},
#endif
      { {
      '\0'}, 0, NULL, NULL, NULL}
    };

    /* BEGIN: Added by l00183184, 2013/8/5   PN:DTS2013071906746 alg升级 */
    /* 判断list是否需要强制分为多行写 */
#ifndef MINISIZE
    char MultiLine[25] = {1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 
    0, 0, 1, 1, 1, 0, 0, 0, 0, 0};
#else
    char MultiLine[15] = {1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0};
#endif
    /* END:   Added by l00183184, 2013/8/5   PN:DTS2013071906746 alg升级 */

    table[0].header_list = &sip->vias;
    table[1].header_list = &sip->record_routes;
    table[2].header_list = &sip->routes;
    table[3].header_data = sip->from;
    table[4].header_data = sip->to;
    table[5].header_data = sip->call_id;
    table[6].header_data = sip->cseq;
    table[7].header_list = &sip->contacts;
    table[8].header_list = &sip->authorizations;
    table[9].header_list = &sip->www_authenticates;
    table[10].header_list = &sip->proxy_authenticates;
    table[11].header_list = &sip->proxy_authorizations;
    table[12].header_data = sip->content_type;
    table[13].header_data = sip->mime_version;
#ifndef MINISIZE
    table[14].header_list = &sip->allows;
    table[15].header_list = &sip->content_encodings;
    table[16].header_list = &sip->call_infos;
    table[17].header_list = &sip->alert_infos;
    table[18].header_list = &sip->error_infos;
    table[19].header_list = &sip->accepts;
    table[20].header_list = &sip->accept_encodings;
    table[21].header_list = &sip->accept_languages;
    table[22].header_list = &sip->authentication_infos;
    table[23].header_list = &sip->proxy_authentication_infos;
#endif

    pos = 0;
    while (table[pos].header_name[0] != '\0') {
      if (table[13].header_list == NULL)
        i = strcat_simple_header (dest, &malloc_size, &message, table[pos].header_data, table[pos].header_name, table[pos].header_length, ((int (*)(void *, char **))
                                                                                                                                           table[pos].to_str), &next);
      /* BEGIN: Modified by l00183184, 2013/8/5   PN:DTS2013071906746 alg升级 */
      /* 只有对应的routes等这几个头域的list分行写,其他的list合在一行 */
      /* 根据Rfc3261:
      Multiple header field rows with the same field-name MAY be present in
      a message if and only if the entire field-value for that header field
      is defined as a comma-separated list (that is, if follows the grammar
      defined in Section 7.3).*/
      if (1 == MultiLine[pos])
      {
          i = strcat_headers_one_per_line (dest, &malloc_size, &message, table[pos].header_list, table[pos].header_name, table[pos].header_length, ((int (*)(void *, char **))
                                                                                                                                                    table[pos].to_str), &next);
      }
      else
      {
          i = strcat_headers_all_on_one_line (dest, &malloc_size, &message, table[pos].header_list, table[pos].header_name, table[pos].header_length, ((int (*)(void *, char **))
                                                                                                                                                 table[pos].to_str), &next);
      }
      /* END:   Modified by l00183184, 2013/8/5   PN:DTS2013071906746 alg升级 */
      if (i != 0) {
        osip_free (*dest);
        *dest = NULL;
        return i;
      }
      message = next;

      pos++;
    }
  }

  pos = 0;
  while (!osip_list_eol (&sip->headers, pos)) {
    osip_header_t *header;
    size_t header_len = 0;

    header = (osip_header_t *) osip_list_get (&sip->headers, pos);
    i = osip_header_to_str (header, &tmp);
    if (i != 0) {
      osip_free (*dest);
      *dest = NULL;
      return i;
    }

    header_len = strlen (tmp);

    if (_osip_message_realloc (&message, dest, header_len + 3, &malloc_size) < 0) {
      osip_free (tmp);
      *dest = NULL;
      return OSIP_NOMEM;
    }

    message = osip_str_append (message, tmp);
    osip_free (tmp);
    message = osip_strn_append (message, CRLF, 2);

    pos++;
  }

  /* we have to create the body before adding the contentlength */
  /* add enough lenght for "Content-Length: " */

  if (_osip_message_realloc (&message, dest, 16, &malloc_size) < 0)
    return OSIP_NOMEM;

  if (sipfrag && osip_list_eol (&sip->bodies, 0)) {
    /* end of headers */
    osip_strncpy (message, CRLF, 2);
    message = message + 2;

    /* same remark as at the beginning of the method */
    sip->message_property = 1;
    sip->message = osip_strdup (*dest);
    sip->message_length = message - *dest;
    if (message_length != NULL)
      *message_length = message - *dest;

    return OSIP_SUCCESS;        /* it's all done */
  }

  osip_strncpy (message, "Content-Length: ", 16);
  message = message + 16;

  /* SIPit Day1
     ALWAYS RECALCULATE?
     if (sip->contentlength!=NULL)
     {
     i = osip_content_length_to_str(sip->contentlength, &tmp);
     if (i!=0) {
     osip_free(*dest);
     *dest = NULL;
     return i;
     }
     osip_strncpy(message,tmp,strlen(tmp));
     osip_free(tmp);
     }
     else
     { */
  if (osip_list_eol (&sip->bodies, 0))  /* no body */
    message = osip_strn_append (message, "0", 1);
  else {
    /* BUG: p130 (rfc2543bis-04)
       "No SP after last token or quoted string"

       In fact, if extra spaces exist: the stack can't be used
       to make user-agent that wants to make authentication...
       This should be changed...
     */

    content_length_to_modify = message;
    message = osip_str_append (message, "     ");
  }
  /*  } */

  message = osip_strn_append (message, CRLF, 2);


  /* end of headers */
  message = osip_strn_append (message, CRLF, 2);

  start_of_bodies = message;
  total_length = start_of_bodies - *dest;

  if (osip_list_eol (&sip->bodies, 0)) {
    /* same remark as at the beginning of the method */
    sip->message_property = 1;
    sip->message = osip_strdup (*dest);
    sip->message_length = total_length;
    if (message_length != NULL)
      *message_length = total_length;

    return OSIP_SUCCESS;        /* it's all done */
  }

  if (sip->mime_version != NULL && sip->content_type && sip->content_type->type && !osip_strcasecmp (sip->content_type->type, "multipart")) {
    osip_generic_param_t *ct_param = NULL;

    /* find the boundary */
    i = osip_generic_param_get_byname (&sip->content_type->gen_params, "boundary", &ct_param);
    if ((i >= 0) && ct_param && ct_param->gvalue) {
      size_t len = strlen (ct_param->gvalue);

      if (len > MIME_MAX_BOUNDARY_LEN) {
        osip_free (*dest);
        *dest = NULL;
        return OSIP_SYNTAXERROR;
      }

      boundary = osip_malloc (len + 5);
      if (boundary == NULL) {
        osip_free (*dest);
        *dest = NULL;
        return OSIP_NOMEM;
      }

      osip_strncpy (boundary, CRLF, 2);
      osip_strncpy (boundary + 2, "--", 2);

      if (ct_param->gvalue[0] == '"' && ct_param->gvalue[len - 1] == '"')
        osip_strncpy (boundary + 4, ct_param->gvalue + 1, len - 2);
      else
        osip_strncpy (boundary + 4, ct_param->gvalue, len);
    }
  }

  pos = 0;
  while (!osip_list_eol (&sip->bodies, pos)) {
    osip_body_t *body;
    size_t body_length;

    body = (osip_body_t *) osip_list_get (&sip->bodies, pos);

    if (boundary) {
      /* Needs at most 77 bytes,
         last realloc allocate at least 100 bytes extra */
      message = osip_str_append (message, boundary);
      message = osip_strn_append (message, CRLF, 2);
    }

    i = osip_body_to_str (body, &tmp, &body_length);
    if (i != 0) {
      osip_free (*dest);
      *dest = NULL;
      if (boundary)
        osip_free (boundary);
      return i;
    }

    if (malloc_size < message - *dest + 100 + body_length) {
      size_t size = message - *dest;
      int offset_of_body;
      int offset_content_length_to_modify = 0;

      offset_of_body = (int) (start_of_bodies - *dest);
      if (content_length_to_modify != NULL)
        offset_content_length_to_modify = (int) (content_length_to_modify - *dest);
      malloc_size = message - *dest + body_length + 100;
      *dest = osip_realloc (*dest, malloc_size);
      if (*dest == NULL) {
        osip_free (tmp);        /* fixed 09/Jun/2005 */
        if (boundary)
          osip_free (boundary);
        return OSIP_NOMEM;
      }
      start_of_bodies = *dest + offset_of_body;
      if (content_length_to_modify != NULL)
        content_length_to_modify = *dest + offset_content_length_to_modify;
      message = *dest + size;
    }

    memcpy (message, tmp, body_length);
    message[body_length] = '\0';
    osip_free (tmp);
    message = message + body_length;

    pos++;
  }

  if (boundary) {
    /* Needs at most 79 bytes,
       last realloc allocate at least 100 bytes extra */
    message = osip_str_append (message, boundary);
    message = osip_strn_append (message, "--", 2);
    message = osip_strn_append (message, CRLF, 2);

    osip_free (boundary);
    boundary = NULL;
  }

  if (content_length_to_modify == NULL) {
    osip_free (*dest);
    *dest = NULL;
    return OSIP_SYNTAXERROR;
  }

  /* we NOW have the length of bodies: */
  {
    size_t size = message - start_of_bodies;
    char tmp2[15];

    total_length += size;
    snprintf (tmp2, 15, "%i", (int) size);
    /* do not use osip_strncpy here! */
    strncpy (content_length_to_modify + 5 - strlen (tmp2), tmp2, strlen (tmp2));
  }

  /* same remark as at the beginning of the method */
  sip->message_property = 1;
  sip->message = osip_malloc (total_length + 1);
  if (sip->message != NULL) {
    memcpy (sip->message, *dest, total_length);
    sip->message[total_length] = '\0';
    sip->message_length = total_length;
    if (message_length != NULL)
      *message_length = total_length;
  }
  return OSIP_SUCCESS;
}
示例#3
0
static int
_osip_message_to_str (osip_message_t * sip, char **dest,
                      size_t * message_length, int sipfrag)
{
  size_t malloc_size;
  size_t total_length = 0;

  /* Added at SIPit day1 */
  char *start_of_bodies;
  char *content_length_to_modify = NULL;

  char *message;
  char *next;
  char *tmp;
  int pos;
  int i;
  char *boundary = NULL;

  malloc_size = SIP_MESSAGE_MAX_LENGTH;

  *dest = NULL;
  if ((sip == NULL))
    return -1;

  {
    if (1 == osip_message_get__property (sip))
      {                         /* message is already available in "message" */

        *dest = osip_malloc (sip->message_length + 1);
        if (*dest == NULL)
          return -1;
        memcpy (*dest, sip->message, sip->message_length);
        (*dest)[sip->message_length] = '\0';
        if (message_length != NULL)
          *message_length = sip->message_length;
        return 0;
    } else
      {
        /* message should be rebuilt: delete the old one if exists. */
        osip_free (sip->message);
        sip->message = NULL;
      }
  }

  message = (char *) osip_malloc (SIP_MESSAGE_MAX_LENGTH);      /* ???? message could be > 4000  */
  if (message == NULL)
    return -1;
  *dest = message;

  /* add the first line of message */
  i = __osip_message_startline_to_str (sip, &tmp);
  if (i == -1)
    {
      if (!sipfrag)
        {
          osip_free (*dest);
          *dest = NULL;
          return -1;
        }

      /* A start-line isn't required for message/sipfrag parts. */
  } else
    {
      message = osip_str_append (message, tmp);
      osip_free (tmp);
      message = osip_strn_append (message, CRLF, 2);
    }

  i =
    strcat_headers_one_per_line (dest, &malloc_size, &message, &sip->vias,
                                 "Via: ", 5,
                                 ((int (*)(void *, char **))
                                  &osip_via_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i =
    strcat_headers_one_per_line (dest, &malloc_size, &message,
                                 &sip->record_routes, "Record-Route: ", 14,
                                 ((int (*)(void *, char **))
                                  &osip_record_route_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i =
    strcat_headers_one_per_line (dest, &malloc_size, &message, &sip->routes,
                                 "Route: ", 7,
                                 ((int (*)(void *, char **))
                                  &osip_route_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i = strcat_simple_header (dest, &malloc_size, &message,
                            sip->from, "From: ", 6,
                            ((int (*)(void *, char **)) &osip_from_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i = strcat_simple_header (dest, &malloc_size, &message,
                            sip->to, "To: ", 4,
                            ((int (*)(void *, char **)) &osip_to_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i = strcat_simple_header (dest, &malloc_size, &message,
                            sip->call_id, "Call-ID: ", 9,
                            ((int (*)(void *, char **)) &osip_call_id_to_str),
                            &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i = strcat_simple_header (dest, &malloc_size, &message,
                            sip->cseq, "CSeq: ", 6,
                            ((int (*)(void *, char **)) &osip_cseq_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i =
    strcat_headers_one_per_line (dest, &malloc_size, &message, &sip->contacts,
                                 "Contact: ", 9,
                                 ((int (*)(void *, char **))
                                  &osip_contact_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i = strcat_headers_one_per_line (dest, &malloc_size, &message,
                                   &sip->authorizations, "Authorization: ", 15,
                                   ((int (*)(void *, char **))
                                    &osip_authorization_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i =
    strcat_headers_one_per_line (dest, &malloc_size, &message,
                                 &sip->www_authenticates, "WWW-Authenticate: ",
                                 18,
                                 ((int (*)(void *, char **))
                                  &osip_www_authenticate_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i =
    strcat_headers_one_per_line (dest, &malloc_size, &message,
                                 &sip->proxy_authenticates,
                                 "Proxy-Authenticate: ", 20,
                                 ((int (*)(void *, char **))
                                  &osip_www_authenticate_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i =
    strcat_headers_one_per_line (dest, &malloc_size, &message,
                                 &sip->proxy_authorizations,
                                 "Proxy-Authorization: ", 21,
                                 ((int (*)(void *, char **))
                                  &osip_authorization_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  pos = 0;
  while (!osip_list_eol (&sip->headers, pos))
    {
      osip_header_t *header;
      size_t header_len = 0;

      header = (osip_header_t *) osip_list_get (&sip->headers, pos);
      i = osip_header_to_str (header, &tmp);
      if (i == -1)
        {
          osip_free (*dest);
          *dest = NULL;
          return -1;
        }

      header_len = strlen (tmp);

      if (_osip_message_realloc (&message, dest, header_len + 3, &malloc_size) < 0)
	{
	  osip_free (tmp);
          *dest = NULL;
	  return -1;
	}

      message = osip_str_append (message, tmp);
      osip_free (tmp);
      message = osip_strn_append (message, CRLF, 2);

      pos++;
    }

  i =
    strcat_headers_all_on_one_line (dest, &malloc_size, &message, &sip->allows,
                                    "Allow: ", 7,
                                    ((int (*)(void *, char **))
                                     &osip_content_length_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i = strcat_simple_header (dest, &malloc_size, &message,
                            sip->content_type, "Content-Type: ", 14,
                            ((int (*)(void *, char **))
                             &osip_content_type_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i =
    strcat_headers_all_on_one_line (dest, &malloc_size, &message,
                                    &sip->content_encodings,
                                    "Content-Encoding: ", 18,
                                    ((int (*)(void *, char **))
                                     &osip_content_length_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i = strcat_simple_header (dest, &malloc_size, &message,
                            sip->mime_version, "Mime-Version: ", 14,
                            ((int (*)(void *, char **))
                             &osip_content_length_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i =
    strcat_headers_one_per_line (dest, &malloc_size, &message,
                                 &sip->call_infos, "Call-Info: ", 11,
                                 ((int (*)(void *, char **))
                                  &osip_call_info_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i =
    strcat_headers_one_per_line (dest, &malloc_size, &message,
                                 &sip->alert_infos, "Alert-Info: ", 12,
                                 ((int (*)(void *, char **))
                                  &osip_call_info_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i =
    strcat_headers_one_per_line (dest, &malloc_size, &message,
                                 &sip->error_infos, "Error-Info: ", 12,
                                 ((int (*)(void *, char **))
                                  &osip_call_info_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i =
    strcat_headers_all_on_one_line (dest, &malloc_size, &message,
                                    &sip->accepts, "Accept: ", 8,
                                    ((int (*)(void *, char **))
                                     &osip_accept_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i =
    strcat_headers_all_on_one_line (dest, &malloc_size, &message,
                                    &sip->accept_encodings,
                                    "Accept-Encoding: ", 17,
                                    ((int (*)(void *, char **))
                                     &osip_accept_encoding_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i =
    strcat_headers_all_on_one_line (dest, &malloc_size, &message,
                                    &sip->accept_languages,
                                    "Accept-Language: ", 17,
                                    ((int (*)(void *, char **))
                                     &osip_accept_encoding_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i =
    strcat_headers_one_per_line (dest, &malloc_size, &message,
                                 &sip->authentication_infos,
                                 "Authentication-Info: ", 21,
                                 ((int (*)(void *, char **))
                                  &osip_authentication_info_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;

  i =
    strcat_headers_one_per_line (dest, &malloc_size, &message,
                                 &sip->proxy_authentication_infos,
                                 "Proxy-Authentication-Info: ", 27,
                                 ((int (*)(void *, char **))
                                  &osip_authentication_info_to_str), &next);
  if (i != 0)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }
  message = next;


  /* we have to create the body before adding the contentlength */
  /* add enough lenght for "Content-Length: " */

  if (_osip_message_realloc (&message, dest, 16, &malloc_size) < 0)
    return -1;

  if (sipfrag && osip_list_eol (&sip->bodies, 0))
    {
      /* end of headers */
      osip_strncpy (message, CRLF, 2);
      message = message + 2;

      /* same remark as at the beginning of the method */
      sip->message_property = 1;
      sip->message = osip_strdup (*dest);
      sip->message_length = message - *dest;
      if (message_length != NULL)
        *message_length = message - *dest;

      return 0;                 /* it's all done */
    }

  osip_strncpy (message, "Content-Length: ", 16);
  message = message + 16;

  /* SIPit Day1
     ALWAYS RECALCULATE?
     if (sip->contentlength!=NULL)
     {
     i = osip_content_length_to_str(sip->contentlength, &tmp);
     if (i==-1) {
     osip_free(*dest);
     *dest = NULL;
     return -1;
     }
     osip_strncpy(message,tmp,strlen(tmp));
     osip_free(tmp);
     }
     else
     { */
  if (osip_list_eol (&sip->bodies, 0))   /* no body */
    message = osip_strn_append (message, "0", 1);
  else
    {
      /* BUG: p130 (rfc2543bis-04)
         "No SP after last token or quoted string"

         In fact, if extra spaces exist: the stack can't be used
         to make user-agent that wants to make authentication...
         This should be changed...
       */

      content_length_to_modify = message;
      message = osip_str_append (message, "     ");
    }
  /*  } */

  message = osip_strn_append (message, CRLF, 2);


  /* end of headers */
  message = osip_strn_append (message, CRLF, 2);

  start_of_bodies = message;
  total_length = start_of_bodies - *dest;

  if (osip_list_eol (&sip->bodies, 0))
    {
      /* same remark as at the beginning of the method */
      sip->message_property = 1;
      sip->message = osip_strdup (*dest);
      sip->message_length = total_length;
      if (message_length != NULL)
        *message_length = total_length;

      return 0;                 /* it's all done */
    }

  if (sip->mime_version != NULL && sip->content_type
      && sip->content_type->type
      && !osip_strcasecmp (sip->content_type->type, "multipart"))
    {
      osip_generic_param_t *ct_param = NULL;

      /* find the boundary */
      i = osip_generic_param_get_byname (&sip->content_type->gen_params,
                                         "boundary", &ct_param);
      if ((i >= 0) && ct_param && ct_param->gvalue)
        {
          size_t len = strlen (ct_param->gvalue);

          if (len > MIME_MAX_BOUNDARY_LEN)
            {
              osip_free (*dest);
              *dest = NULL;
              return -1;
            }

          boundary = osip_malloc (len + 5);

          osip_strncpy (boundary, CRLF, 2);
          osip_strncpy (boundary + 2, "--", 2);

          if (ct_param->gvalue[0] == '"' && ct_param->gvalue[len - 1] == '"')
            osip_strncpy (boundary + 4, ct_param->gvalue + 1, len - 2);
          else
            osip_strncpy (boundary + 4, ct_param->gvalue, len);
        }
    }

  pos = 0;
  while (!osip_list_eol (&sip->bodies, pos))
    {
      osip_body_t *body;
      size_t body_length;

      body = (osip_body_t *) osip_list_get (&sip->bodies, pos);

      if (boundary)
        {
          /* Needs at most 77 bytes,
             last realloc allocate at least 100 bytes extra */
          message = osip_str_append (message, boundary);
          message = osip_strn_append (message, CRLF, 2);
        }

      i = osip_body_to_str (body, &tmp, &body_length);
      if (i != 0)
        {
          osip_free (*dest);
          *dest = NULL;
          if (boundary)
            osip_free (boundary);
          return -1;
        }

      if (malloc_size < message - *dest + 100 + body_length)
        {
          size_t size = message - *dest;
          int offset_of_body;
          int offset_content_length_to_modify = 0;

          offset_of_body = (int) (start_of_bodies - *dest);
          if (content_length_to_modify != NULL)
            offset_content_length_to_modify =
              (int) (content_length_to_modify - *dest);
          malloc_size = message - *dest + body_length + 100;
          *dest = osip_realloc (*dest, malloc_size);
          if (*dest == NULL)
            {
              osip_free (tmp);  /* fixed 09/Jun/2005 */
              if (boundary)
                osip_free (boundary);
              return -1;
            }
          start_of_bodies = *dest + offset_of_body;
          if (content_length_to_modify != NULL)
            content_length_to_modify = *dest + offset_content_length_to_modify;
          message = *dest + size;
        }

      memcpy (message, tmp, body_length);
      message[body_length] = '\0';
      osip_free (tmp);
      message = message + body_length;

      pos++;
    }

  if (boundary)
    {
      /* Needs at most 79 bytes,
         last realloc allocate at least 100 bytes extra */
      message = osip_str_append (message, boundary);
      message = osip_strn_append (message, "--", 2);
      message = osip_strn_append (message, CRLF, 2);

      osip_free (boundary);
      boundary = NULL;
    }

  if (content_length_to_modify == NULL)
    {
      osip_free (*dest);
      *dest = NULL;
      return -1;
    }

  /* we NOW have the length of bodies: */
  {
    size_t size = message - start_of_bodies;
    char tmp2[15];

    total_length += size;
    sprintf (tmp2, "%i", size);
    /* do not use osip_strncpy here! */
    strncpy (content_length_to_modify + 5 - strlen (tmp2), tmp2, strlen (tmp2));
  }

  /* same remark as at the beginning of the method */
  sip->message_property = 1;
  sip->message = osip_malloc (total_length + 1);
  if (sip->message != NULL)
    {
      memcpy (sip->message, *dest, total_length);
      sip->message[total_length] = '\0';
      sip->message_length = total_length;
      if (message_length != NULL)
        *message_length = total_length;
    }
  return 0;
}