text: ﻿/*
    The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
    Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Aymeric MOIZARD jack@atosc.org
    
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.
    
    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.
    
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  
  
  #include <stdio.h>
  #include <stdlib.h>
  
  #include <osipparser2/osip_port.h>
  #include <osipparser2/osip_parser.h>
  
  #define MIME_MAX_BOUNDARY_LEN 70
  
  extern const char *osip_protocol_version;
  
  static int strcat_simple_header(char **_string, size_t * malloc_size,
  								char **_message, void *ptr_header,
  								char *header_name, size_t size_of_header,
  								int (*xxx_to_str) (void *, char **), char **next);
  static int strcat_headers_one_per_line(char **_string, size_t * malloc_size,
  									   char **_message,
  									   osip_list_t * headers, char *header,
  									   size_t size_of_header,
  									   int (*xxx_to_str) (void *, char **),
  									   char **next);
  #if 0
  static int strcat_headers_all_on_one_line(char **_string,
  										  size_t * malloc_size,
  										  char **_message,
  										  osip_list_t * headers,
  										  char *header,
  										  size_t size_of_header,
  										  int (*xxx_to_str) (void *,
  															 char **),
  										  char **next);
  #endif
  
  static int __osip_message_startline_to_strreq(osip_message_t * sip, char **dest)
  {
  	const char *sip_version;
  	char *tmp;
  	char *rquri;
  	int i;
  
  	*dest = NULL;
  	if ((sip == NULL) || (sip->req_uri == NULL) || (sip->sip_method == NULL))
  		return OSIP_BADPARAMETER;
  
  	i = osip_uri_to_str(sip->req_uri, &rquri);
  	if (i != 0)
  		return i;
  
  	if (sip->sip_version == NULL)
  		sip_version = osip_protocol_version;
  	else
  		sip_version = sip->sip_version;
  
  	*dest = (char *) osip_malloc(strlen(sip->sip_method)
  								 + strlen(rquri) + strlen(sip_version) + 3);
  	if (*dest == NULL) {
  		osip_free(rquri);
  		return OSIP_NOMEM;
  	}
  	tmp = *dest;
  
  	tmp = osip_str_append(tmp, sip->sip_method);
  	*tmp = ' ';
  	tmp++;
  	tmp = osip_str_append(tmp, rquri);
  	*tmp = ' ';
  	tmp++;
  	strcpy(tmp, sip_version);
  
  	osip_free(rquri);
  	return OSIP_SUCCESS;
  }
  
  static int __osip_message_startline_to_strresp(osip_message_t * sip, char **dest)
  {
  	char *tmp;
  	const char *sip_version;
  	char status_code[5];
  
  	*dest = NULL;
  	if ((sip == NULL) || (sip->reason_phrase == NULL)
  		|| (sip->status_code < 100) || (sip->status_code > 699))
  		return OSIP_BADPARAMETER;
  
  	if (sip->sip_version == NULL)
  		sip_version = osip_protocol_version;
  	else
  		sip_version = sip->sip_version;
  
  	sprintf(status_code, "%u", sip->status_code);
  
  	*dest = (char *) osip_malloc(strlen(sip_version)
  								 + 3 + strlen(sip->reason_phrase) + 4);
  	if (*dest == NULL)
  		return OSIP_NOMEM;
  	tmp = *dest;
  
  	tmp = osip_str_append(tmp, sip_version);
  	*tmp = ' ';
  	tmp++;
  
  	tmp = osip_strn_append(tmp, status_code, 3);
  	*tmp = ' ';
  	tmp++;
  	strcpy(tmp, sip->reason_phrase);
  
  	return OSIP_SUCCESS;
  }
  
  static int __osip_message_startline_to_str(osip_message_t * sip, char **dest)
  {
  
  	if (sip->sip_method != NULL)
  		return __osip_message_startline_to_strreq(sip, dest);
  	if (sip->status_code != 0)
  		return __osip_message_startline_to_strresp(sip, dest);
  
  	OSIP_TRACE(osip_trace
  			   (__FILE__, __LINE__, TRACE_LEVEL1, NULL,
  				"ERROR method has no value or status code is 0!\n"));
  	return OSIP_BADPARAMETER;	/* should never come here */
  }
  
  char *osip_message_get_reason_phrase(const osip_message_t * sip)
  {
  	return sip->reason_phrase;
  }
  
  int osip_message_get_status_code(const osip_message_t * sip)
  {
  	return sip->status_code;
  }
  
  char *osip_message_get_method(const osip_message_t * sip)
  {
  	return sip->sip_method;
  }
  
  char *osip_message_get_version(const osip_message_t * sip)
  {
  	return sip->sip_version;
  }
  
  osip_uri_t *osip_message_get_uri(const osip_message_t * sip)
  {
  	return sip->req_uri;
  }
  
  static int
  strcat_simple_header(char **_string, size_t * malloc_size,
  					 char **_message, void *ptr_header, char *header_name,
  					 size_t size_of_header, int (*xxx_to_str) (void *,
  															   char **),
  					 char **next)
  {
  	char *string;
  	char *message;
  	char *tmp;
  	int i;
  
  	string = *_string;
  	message = *_message;
  
  	if (ptr_header != NULL) {
  		if (*malloc_size < message - string + 100 + size_of_header)
  			/* take some memory avoid to osip_realloc too much often */
  		{						/* should not happen often */
  			size_t size = message - string;
  
  			*malloc_size = message - string + size_of_header + 100;
  			string = osip_realloc(string, *malloc_size);
  			if (string == NULL) {
  				*_string = NULL;
  				*_message = NULL;
  				return OSIP_NOMEM;
  			}
  			message = string + size;
  		}
  		message = osip_strn_append(message, header_name, size_of_header);
  
  		i = xxx_to_str(ptr_header, &tmp);
  		if (i != 0) {
  			*_string = string;
  			*_message = message;
  			*next = NULL;
  			return i;
  		}
  		if (*malloc_size < message - string + strlen(tmp) + 100) {
  			size_t size = message - string;
  
  			*malloc_size = message - string + strlen(tmp) + 100;
  			string = osip_realloc(string, *malloc_size);
  			if (string == NULL) {
  				*_string = NULL;
  				*_message = NULL;
  				return OSIP_NOMEM;
  			}
  			message = string + size;
  		}
  
  		message = osip_str_append(message, tmp);
  		osip_free(tmp);
  		message = osip_strn_append(message, CRLF, 2);
  	}
  	*_string = string;
  	*_message = message;
  	*next = message;
  	return OSIP_SUCCESS;
  }
  
  static int
  strcat_headers_one_per_line(char **_string, size_t * malloc_size,
  							char **_message, osip_list_t * headers,
  							char *header, size_t size_of_header,
  							int (*xxx_to_str) (void *, char **), char **next)
  {
  	char *string;
  	char *message;
  	char *tmp;
  	int pos = 0;
  	int i;
  
  	string = *_string;
  	message = *_message;
  
  	while (!osip_list_eol(headers, pos)) {
  		void *elt;
  
  		elt = (void *) osip_list_get(headers, pos);
  
  		if (*malloc_size < message - string + 100 + size_of_header)
  			/* take some memory avoid to osip_realloc too much often */
  		{						/* should not happen often */
  			size_t size = message - string;
  
  			*malloc_size = message - string + size_of_header + 100;
  			string = osip_realloc(string, *malloc_size);
  			if (string == NULL) {
  				*_string = NULL;
  				*_message = NULL;
  				return OSIP_NOMEM;
  			}
  			message = string + size;
  		}
  		osip_strncpy(message, header, size_of_header);
  		i = xxx_to_str(elt, &tmp);
  		if (i != 0) {
  			*_string = string;
  			*_message = message;
  			*next = NULL;
  			return i;
  		}
  		message = message + strlen(message);
  
  		if (*malloc_size < message - string + strlen(tmp) + 100) {
  			size_t size = message - string;
  
  			*malloc_size = message - string + strlen(tmp) + 100;
  			string = osip_realloc(string, *malloc_size);
  			if (string == NULL) {
  				*_string = NULL;
  				*_message = NULL;
  				return OSIP_NOMEM;
  			}
  			message = string + size;
  		}
  		message = osip_str_append(message, tmp);
  		osip_free(tmp);
  		message = osip_strn_append(message, CRLF, 2);
  		pos++;
  	}
  	*_string = string;
  	*_message = message;
  	*next = message;
  	return OSIP_SUCCESS;
  }
  
  #if 0
  static int
  strcat_headers_all_on_one_line(char **_string, size_t * malloc_size,
  							   char **_message, osip_list_t * headers,
  							   char *header, size_t size_of_header,
  							   int (*xxx_to_str) (void *, char **), char **next)
  {
  	char *string;
  	char *message;
  	char *tmp;
  	int pos = 0;
  	int i;
  
  	string = *_string;
  	message = *_message;
  
  	pos = 0;
  	while (!osip_list_eol(headers, pos)) {
  		if (*malloc_size < message - string + 100 + size_of_header)
  			/* take some memory avoid to osip_realloc too much often */
  		{						/* should not happen often */
  			size_t size = message - string;
  
  			*malloc_size = message - string + size_of_header + 100;
  			string = osip_realloc(string, *malloc_size);
  			if (string == NULL) {
  				*_string = NULL;
  				*_message = NULL;
  				return OSIP_NOMEM;
  			}
  			message = string + size;
  		}
  		message = osip_strn_append(message, header, size_of_header);
  
  		while (!osip_list_eol(headers, pos)) {
  			void *elt;
  
  			elt = (void *) osip_list_get(headers, pos);
  			i = xxx_to_str(elt, &tmp);
  			if (i != 0) {
  				*_string = string;
  				*_message = message;
  				*next = NULL;
  				return i;
  			}
  			if (*malloc_size < message - string + strlen(tmp) + 100) {
  				size_t size = message - string;
  
  				*malloc_size = message - string + (int) strlen(tmp) + 100;
  				string = osip_realloc(string, *malloc_size);
  				if (string == NULL) {
  					*_string = NULL;
  					*_message = NULL;
  					return OSIP_NOMEM;
  				}
  				message = string + size;
  			}
  
  			message = osip_str_append(message, tmp);
  			osip_free(tmp);
  
  			pos++;
  			if (!osip_list_eol(headers, pos)) {
  				message = osip_strn_append(message, ", ", 2);
  			}
  		}
  		message = osip_strn_append(message, CRLF, 2);
  	}
  	*_string = string;
  	*_message = message;
  	*next = message;
  	return OSIP_SUCCESS;
  }
  #endif
  
   /* return values:
      1: structure and buffer "message" are identical.
      2: buffer "message" is not up to date with the structure info (call osip_message_to_str to update it).
      -1 on error.
    */
  int osip_message_get__property(const osip_message_t * sip)
  {
  	if (sip == NULL)
  		return OSIP_BADPARAMETER;
  	return sip->message_property;
  }
  
  int osip_message_force_update(osip_message_t * sip)
  {
  	if (sip == NULL)
  		return OSIP_BADPARAMETER;
  	sip->message_property = 2;
  	return OSIP_SUCCESS;
  }
  
  static int
  _osip_message_realloc(char **message, char **dest, size_t needed,
  					  size_t * malloc_size)
  {
  	size_t size = *message - *dest;
  
  	if (*malloc_size < (size_t) (size + needed + 100)) {
  		*malloc_size = size + needed + 100;
  		*dest = osip_realloc(*dest, *malloc_size);
  		if (*dest == NULL)
  			return OSIP_NOMEM;
  		*message = *dest + size;
  	}
  
  	return OSIP_SUCCESS;
  }
  
  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}
  		};
  		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);
  			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);
  			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", 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;
  }
  
  int osip_message_to_str(osip_message_t * sip, char **dest, size_t * message_length)
  {
  	return _osip_message_to_str(sip, dest, message_length, 0);
  }
  
  int
  osip_message_to_str_sipfrag(osip_message_t * sip, char **dest,
  							size_t * message_length)
  {
  	return _osip_message_to_str(sip, dest, message_length, 1);
  }
  