1 /*
2 The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3 Copyright (C) 2001-2020 Aymeric MOIZARD amoizard@antisip.com
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 #include <osipparser2/internal.h>
21
22 #include <osipparser2/osip_port.h>
23 #include <osipparser2/osip_parser.h>
24
25 #define MIME_MAX_BOUNDARY_LEN 70
26
27 extern const char *osip_protocol_version;
28
29 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);
30 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);
31
__osip_message_startline_to_strreq(osip_message_t * sip,char ** dest)32 static int __osip_message_startline_to_strreq(osip_message_t *sip, char **dest) {
33 const char *sip_version;
34 char *tmp;
35 char *rquri;
36 int i;
37
38 *dest = NULL;
39
40 if ((sip == NULL) || (sip->req_uri == NULL) || (sip->sip_method == NULL))
41 return OSIP_BADPARAMETER;
42
43 i = osip_uri_to_str(sip->req_uri, &rquri);
44
45 if (i != 0)
46 return i;
47
48 if (sip->sip_version == NULL)
49 sip_version = osip_protocol_version;
50
51 else
52 sip_version = sip->sip_version;
53
54 *dest = (char *) osip_malloc(strlen(sip->sip_method) + strlen(rquri) + strlen(sip_version) + 3);
55
56 if (*dest == NULL) {
57 osip_free(rquri);
58 return OSIP_NOMEM;
59 }
60
61 tmp = *dest;
62
63 tmp = osip_str_append(tmp, sip->sip_method);
64 *tmp = ' ';
65 tmp++;
66 tmp = osip_str_append(tmp, rquri);
67 *tmp = ' ';
68 tmp++;
69 strcpy(tmp, sip_version);
70
71 osip_free(rquri);
72 return OSIP_SUCCESS;
73 }
74
__osip_message_startline_to_strresp(osip_message_t * sip,char ** dest)75 static int __osip_message_startline_to_strresp(osip_message_t *sip, char **dest) {
76 char *tmp;
77 const char *sip_version;
78 char status_code[5];
79
80 *dest = NULL;
81
82 if ((sip == NULL) || (sip->reason_phrase == NULL) || (sip->status_code < 100) || (sip->status_code > 699))
83 return OSIP_BADPARAMETER;
84
85 if (sip->sip_version == NULL)
86 sip_version = osip_protocol_version;
87
88 else
89 sip_version = sip->sip_version;
90
91 sprintf(status_code, "%u", sip->status_code);
92
93 *dest = (char *) osip_malloc(strlen(sip_version) + 3 + strlen(sip->reason_phrase) + 4);
94
95 if (*dest == NULL)
96 return OSIP_NOMEM;
97
98 tmp = *dest;
99
100 tmp = osip_str_append(tmp, sip_version);
101 *tmp = ' ';
102 tmp++;
103
104 tmp = osip_strn_append(tmp, status_code, 3);
105 *tmp = ' ';
106 tmp++;
107 strcpy(tmp, sip->reason_phrase);
108
109 return OSIP_SUCCESS;
110 }
111
__osip_message_startline_to_str(osip_message_t * sip,char ** dest)112 static int __osip_message_startline_to_str(osip_message_t *sip, char **dest) {
113 if (sip->sip_method != NULL)
114 return __osip_message_startline_to_strreq(sip, dest);
115
116 if (sip->status_code != 0)
117 return __osip_message_startline_to_strresp(sip, dest);
118
119 OSIP_TRACE(osip_trace(__FILE__, __LINE__, TRACE_LEVEL1, NULL, "ERROR method has no value or status code is 0!\n"));
120 return OSIP_BADPARAMETER; /* should never come here */
121 }
122
osip_message_get_reason_phrase(const osip_message_t * sip)123 char *osip_message_get_reason_phrase(const osip_message_t *sip) {
124 return sip->reason_phrase;
125 }
126
osip_message_get_status_code(const osip_message_t * sip)127 int osip_message_get_status_code(const osip_message_t *sip) {
128 return sip->status_code;
129 }
130
osip_message_get_method(const osip_message_t * sip)131 char *osip_message_get_method(const osip_message_t *sip) {
132 return sip->sip_method;
133 }
134
osip_message_get_version(const osip_message_t * sip)135 char *osip_message_get_version(const osip_message_t *sip) {
136 return sip->sip_version;
137 }
138
osip_message_get_uri(const osip_message_t * sip)139 osip_uri_t *osip_message_get_uri(const osip_message_t *sip) {
140 return sip->req_uri;
141 }
142
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)143 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) {
144 char *string;
145 char *message;
146 char *tmp;
147 int i;
148
149 string = *_string;
150 message = *_message;
151
152 if (ptr_header != NULL) {
153 if (*malloc_size < message - string + 100 + size_of_header) {
154 /* take some memory in order to avoid using osip_realloc too often */
155 size_t size = message - string;
156
157 *malloc_size = message - string + size_of_header + 100;
158 string = osip_realloc(string, *malloc_size);
159
160 if (string == NULL) {
161 osip_free(*_string); /* pointer for string */
162 *_string = NULL;
163 *_message = NULL;
164 return OSIP_NOMEM;
165 }
166
167 *_string = string;
168 message = string + size;
169 }
170
171 message = osip_strn_append(message, header_name, size_of_header);
172
173 i = xxx_to_str(ptr_header, &tmp);
174
175 if (i != 0) {
176 *_string = string;
177 *_message = message;
178 *next = NULL;
179 return i;
180 }
181
182 if (*malloc_size < message - string + strlen(tmp) + 100) {
183 size_t size = message - string;
184
185 *malloc_size = message - string + strlen(tmp) + 100;
186 string = osip_realloc(string, *malloc_size);
187
188 if (string == NULL) {
189 osip_free(*_string); /* pointer for string */
190 *_string = NULL;
191 *_message = NULL;
192 return OSIP_NOMEM;
193 }
194
195 *_string = string;
196 message = string + size;
197 }
198
199 message = osip_str_append(message, tmp);
200 osip_free(tmp);
201 message = osip_strn_append(message, OSIP_CRLF, 2);
202 }
203
204 *_string = string;
205 *_message = message;
206 *next = message;
207 return OSIP_SUCCESS;
208 }
209
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)210 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) {
211 char *string;
212 char *message;
213 char *tmp;
214 int i;
215 osip_list_iterator_t it;
216 void *elt = osip_list_get_first(headers, &it);
217
218 string = *_string;
219 message = *_message;
220
221 while (elt != OSIP_SUCCESS) {
222 if (*malloc_size < message - string + 100 + size_of_header)
223 /* take some memory avoid to osip_realloc too much often */
224 {
225 /* should not happen often */
226 size_t size = message - string;
227
228 *malloc_size = message - string + size_of_header + 100;
229 string = osip_realloc(string, *malloc_size);
230
231 if (string == NULL) {
232 osip_free(*_string); /* pointer for string */
233 *_string = NULL;
234 *_message = NULL;
235 return OSIP_NOMEM;
236 }
237
238 *_string = string;
239 message = string + size;
240 }
241
242 osip_strncpy(message, header, size_of_header);
243 i = xxx_to_str(elt, &tmp);
244
245 if (i != 0) {
246 *_string = string;
247 *_message = message;
248 *next = NULL;
249 return i;
250 }
251
252 message = message + strlen(message);
253
254 if (*malloc_size < message - string + strlen(tmp) + 100) {
255 size_t size = message - string;
256
257 *malloc_size = message - string + strlen(tmp) + 100;
258 string = osip_realloc(string, *malloc_size);
259
260 if (string == NULL) {
261 osip_free(*_string); /* pointer for string */
262 *_string = NULL;
263 *_message = NULL;
264 return OSIP_NOMEM;
265 }
266
267 *_string = string;
268 message = string + size;
269 }
270
271 message = osip_str_append(message, tmp);
272 osip_free(tmp);
273 message = osip_strn_append(message, OSIP_CRLF, 2);
274 elt = osip_list_get_next(&it);
275 }
276
277 *_string = string;
278 *_message = message;
279 *next = message;
280 return OSIP_SUCCESS;
281 }
282
283 /* return values:
284 1: structure and buffer "message" are identical.
285 2: buffer "message" is not up to date with the structure info (call osip_message_to_str to update it).
286 -1 on error.
287 */
osip_message_get__property(const osip_message_t * sip)288 int osip_message_get__property(const osip_message_t *sip) {
289 if (sip == NULL)
290 return OSIP_BADPARAMETER;
291
292 return sip->message_property;
293 }
294
osip_message_force_update(osip_message_t * sip)295 int osip_message_force_update(osip_message_t *sip) {
296 if (sip == NULL)
297 return OSIP_BADPARAMETER;
298
299 sip->message_property = 2;
300 return OSIP_SUCCESS;
301 }
302
_osip_message_realloc(char ** message,char ** dest,size_t needed,size_t * malloc_size)303 static int _osip_message_realloc(char **message, char **dest, size_t needed, size_t *malloc_size) {
304 size_t size = *message - *dest;
305
306 if (*malloc_size < (size_t)(size + needed + 100)) {
307 *malloc_size = size + needed + 100;
308 *dest = osip_realloc(*dest, *malloc_size);
309
310 if (*dest == NULL)
311 return OSIP_NOMEM;
312
313 *message = *dest + size;
314 }
315
316 return OSIP_SUCCESS;
317 }
318
_osip_message_to_str(osip_message_t * sip,char ** dest,size_t * message_length,int sipfrag)319 static int _osip_message_to_str(osip_message_t *sip, char **dest, size_t *message_length, int sipfrag) {
320 size_t malloc_size;
321 size_t total_length = 0;
322
323 /* Added at SIPit day1 */
324 char *start_of_bodies;
325 char *content_length_to_modify = NULL;
326
327 char *message;
328 char *next;
329 char *tmp;
330 int pos;
331 int i;
332 char *boundary = NULL;
333
334 malloc_size = SIP_MESSAGE_MAX_LENGTH;
335
336 *dest = NULL;
337
338 if (sip == NULL)
339 return OSIP_BADPARAMETER;
340
341 {
342 if (1 == osip_message_get__property(sip)) { /* message is already available in "message" */
343
344 *dest = osip_malloc(sip->message_length + 1);
345
346 if (*dest == NULL)
347 return OSIP_NOMEM;
348
349 memcpy(*dest, sip->message, sip->message_length);
350 (*dest)[sip->message_length] = '\0';
351
352 if (message_length != NULL)
353 *message_length = sip->message_length;
354
355 return OSIP_SUCCESS;
356
357 } else {
358 /* message should be rebuilt: delete the old one if exists. */
359 osip_free(sip->message);
360 sip->message = NULL;
361 }
362 }
363
364 message = (char *) osip_malloc(SIP_MESSAGE_MAX_LENGTH); /* ???? message could be > 4000 */
365
366 if (message == NULL)
367 return OSIP_NOMEM;
368
369 *dest = message;
370
371 /* add the first line of message */
372 i = __osip_message_startline_to_str(sip, &tmp);
373
374 if (i != 0) {
375 if (!sipfrag) {
376 osip_free(*dest);
377 *dest = NULL;
378 return i;
379 }
380
381 /* A start-line isn't required for message/sipfrag parts. */
382
383 } else {
384 size_t message_len = strlen(tmp);
385
386 if (_osip_message_realloc(&message, dest, message_len + 3, &malloc_size) < 0) {
387 osip_free(tmp);
388 *dest = NULL;
389 return OSIP_NOMEM;
390 }
391
392 message = osip_str_append(message, tmp);
393 osip_free(tmp);
394 message = osip_strn_append(message, OSIP_CRLF, 2);
395 }
396
397 {
398 struct to_str_table {
399 char header_name[30];
400 int header_length;
401 osip_list_t *header_list;
402 void *header_data;
403 int (*to_str)(void *, char **);
404 }
405 #ifndef MINISIZE
406 table[25] =
407 #else
408 table[16] =
409 #endif
410 {{"Via: ", 5, NULL, NULL, (int (*)(void *, char **)) & osip_via_to_str},
411 {"Record-Route: ", 14, NULL, NULL, (int (*)(void *, char **)) & osip_record_route_to_str},
412 {"Route: ", 7, NULL, NULL, (int (*)(void *, char **)) & osip_route_to_str},
413 {"From: ", 6, NULL, NULL, (int (*)(void *, char **)) & osip_from_to_str},
414 {"To: ", 4, NULL, NULL, (int (*)(void *, char **)) & osip_to_to_str},
415 {"Call-ID: ", 9, NULL, NULL, (int (*)(void *, char **)) & osip_call_id_to_str},
416 {"CSeq: ", 6, NULL, NULL, (int (*)(void *, char **)) & osip_cseq_to_str},
417 {"Contact: ", 9, NULL, NULL, (int (*)(void *, char **)) & osip_contact_to_str},
418 {"Authorization: ", 15, NULL, NULL, (int (*)(void *, char **)) & osip_authorization_to_str},
419 {"WWW-Authenticate: ", 18, NULL, NULL, (int (*)(void *, char **)) & osip_www_authenticate_to_str},
420 {"Proxy-Authenticate: ", 20, NULL, NULL, (int (*)(void *, char **)) & osip_www_authenticate_to_str},
421 {"Proxy-Authorization: ", 21, NULL, NULL, (int (*)(void *, char **)) & osip_authorization_to_str},
422 {"Call-Info: ", 11, NULL, NULL, (int (*)(void *, char **)) & osip_call_info_to_str},
423 {"Content-Type: ", 14, NULL, NULL, (int (*)(void *, char **)) & osip_content_type_to_str},
424 {"Mime-Version: ", 14, NULL, NULL, (int (*)(void *, char **)) & osip_content_length_to_str},
425 #ifndef MINISIZE
426 {"Allow: ", 7, NULL, NULL, (int (*)(void *, char **)) & osip_allow_to_str},
427 {"Content-Encoding: ", 18, NULL, NULL, (int (*)(void *, char **)) & osip_content_encoding_to_str},
428 {"Alert-Info: ", 12, NULL, NULL, (int (*)(void *, char **)) & osip_call_info_to_str},
429 {"Error-Info: ", 12, NULL, NULL, (int (*)(void *, char **)) & osip_call_info_to_str},
430 {"Accept: ", 8, NULL, NULL, (int (*)(void *, char **)) & osip_accept_to_str},
431 {"Accept-Encoding: ", 17, NULL, NULL, (int (*)(void *, char **)) & osip_accept_encoding_to_str},
432 {"Accept-Language: ", 17, NULL, NULL, (int (*)(void *, char **)) & osip_accept_language_to_str},
433 {"Authentication-Info: ", 21, NULL, NULL, (int (*)(void *, char **)) & osip_authentication_info_to_str},
434 {"Proxy-Authentication-Info: ", 27, NULL, NULL, (int (*)(void *, char **)) & osip_authentication_info_to_str},
435 #endif
436 {{'\0'}, 0, NULL, NULL, NULL}};
437 table[0].header_list = &sip->vias;
438 table[1].header_list = &sip->record_routes;
439 table[2].header_list = &sip->routes;
440 table[3].header_data = sip->from;
441 table[4].header_data = sip->to;
442 table[5].header_data = sip->call_id;
443 table[6].header_data = sip->cseq;
444 table[7].header_list = &sip->contacts;
445 table[8].header_list = &sip->authorizations;
446 table[9].header_list = &sip->www_authenticates;
447 table[10].header_list = &sip->proxy_authenticates;
448 table[11].header_list = &sip->proxy_authorizations;
449 table[12].header_list = &sip->call_infos;
450 table[13].header_data = sip->content_type;
451 table[14].header_data = sip->mime_version;
452 #ifndef MINISIZE
453 table[15].header_list = &sip->allows;
454 table[16].header_list = &sip->content_encodings;
455 table[17].header_list = &sip->alert_infos;
456 table[18].header_list = &sip->error_infos;
457 table[19].header_list = &sip->accepts;
458 table[20].header_list = &sip->accept_encodings;
459 table[21].header_list = &sip->accept_languages;
460 table[22].header_list = &sip->authentication_infos;
461 table[23].header_list = &sip->proxy_authentication_infos;
462 #endif
463
464 pos = 0;
465
466 while (table[pos].header_name[0] != '\0') {
467 if (table[13].header_list == NULL)
468 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);
469
470 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);
471
472 if (i != 0) {
473 osip_free(*dest);
474 *dest = NULL;
475 return i;
476 }
477
478 message = next;
479
480 pos++;
481 }
482 }
483
484 {
485 osip_list_iterator_t it;
486 osip_header_t *header = (osip_header_t *) osip_list_get_first(&sip->headers, &it);
487
488 while (header != OSIP_SUCCESS) {
489 size_t header_len = 0;
490
491 i = osip_header_to_str(header, &tmp);
492
493 if (i != 0) {
494 osip_free(*dest);
495 *dest = NULL;
496 return i;
497 }
498
499 header_len = strlen(tmp);
500
501 if (_osip_message_realloc(&message, dest, header_len + 3, &malloc_size) < 0) {
502 osip_free(tmp);
503 *dest = NULL;
504 return OSIP_NOMEM;
505 }
506
507 message = osip_str_append(message, tmp);
508 osip_free(tmp);
509 message = osip_strn_append(message, OSIP_CRLF, 2);
510
511 header = (osip_header_t *) osip_list_get_next(&it);
512 }
513 }
514
515 /* we have to create the body before adding the contentlength */
516 /* add enough lenght for "Content-Length: " */
517
518 if (_osip_message_realloc(&message, dest, 16, &malloc_size) < 0)
519 return OSIP_NOMEM;
520
521 if (sipfrag && osip_list_eol(&sip->bodies, 0)) {
522 /* end of headers */
523 osip_strncpy(message, OSIP_CRLF, 2);
524 message = message + 2;
525
526 /* same remark as at the beginning of the method */
527 sip->message_property = 1;
528 sip->message = osip_strdup(*dest);
529 sip->message_length = message - *dest;
530
531 if (message_length != NULL)
532 *message_length = message - *dest;
533
534 return OSIP_SUCCESS; /* it's all done */
535 }
536
537 osip_strncpy(message, "Content-Length: ", 16);
538 message = message + 16;
539
540 /* SIPit Day1
541 ALWAYS RECALCULATE?
542 if (sip->contentlength!=NULL)
543 {
544 i = osip_content_length_to_str(sip->contentlength, &tmp);
545 if (i!=0) {
546 osip_free(*dest);
547 *dest = NULL;
548 return i;
549 }
550 osip_strncpy(message,tmp,strlen(tmp));
551 osip_free(tmp);
552 }
553 else
554 { */
555 if (osip_list_eol(&sip->bodies, 0)) /* no body */
556 message = osip_strn_append(message, "0", 1);
557
558 else {
559 /* BUG: p130 (rfc2543bis-04)
560 "No SP after last token or quoted string"
561
562 In fact, if extra spaces exist: the stack can't be used
563 to make user-agent that wants to make authentication...
564 This should be changed...
565 */
566
567 content_length_to_modify = message;
568 message = osip_str_append(message, " ");
569 }
570
571 /* } */
572
573 message = osip_strn_append(message, OSIP_CRLF, 2);
574
575 /* end of headers */
576 message = osip_strn_append(message, OSIP_CRLF, 2);
577
578 start_of_bodies = message;
579 total_length = start_of_bodies - *dest;
580
581 if (osip_list_eol(&sip->bodies, 0)) {
582 /* same remark as at the beginning of the method */
583 sip->message_property = 1;
584 sip->message = osip_strdup(*dest);
585 sip->message_length = total_length;
586
587 if (message_length != NULL)
588 *message_length = total_length;
589
590 return OSIP_SUCCESS; /* it's all done */
591 }
592
593 if (sip->content_type && sip->content_type->type && !osip_strcasecmp(sip->content_type->type, "multipart")) {
594 osip_generic_param_t *ct_param = NULL;
595
596 /* find the boundary */
597 i = osip_generic_param_get_byname(&sip->content_type->gen_params, "boundary", &ct_param);
598
599 if ((i >= 0) && ct_param && ct_param->gvalue) {
600 size_t len = strlen(ct_param->gvalue);
601
602 if (len > MIME_MAX_BOUNDARY_LEN) {
603 osip_free(*dest);
604 *dest = NULL;
605 return OSIP_SYNTAXERROR;
606 }
607
608 if (len == 1 && ct_param->gvalue[0] == '"') { /* fixed Jan 10,2020: avoid a negative length copy if boundary contains only one quote */
609 osip_free(*dest);
610 *dest = NULL;
611 return OSIP_SYNTAXERROR;
612 }
613
614 if (len == 2 && ct_param->gvalue[0] == '"' && ct_param->gvalue[1] == '"') { /* do not accept empty boundary */
615 osip_free(*dest);
616 *dest = NULL;
617 return OSIP_SYNTAXERROR;
618 }
619
620 boundary = osip_malloc(len + 5);
621
622 if (boundary == NULL) {
623 osip_free(*dest);
624 *dest = NULL;
625 return OSIP_NOMEM;
626 }
627
628 osip_strncpy(boundary, OSIP_CRLF, 2);
629 osip_strncpy(boundary + 2, "--", 2);
630
631 if (ct_param->gvalue[0] == '"' && ct_param->gvalue[len - 1] == '"')
632 osip_strncpy(boundary + 4, ct_param->gvalue + 1, len - 2);
633
634 else
635 osip_strncpy(boundary + 4, ct_param->gvalue, len);
636 }
637 }
638
639 {
640 osip_list_iterator_t it;
641 osip_body_t *body = (osip_body_t *) osip_list_get_first(&sip->bodies, &it);
642
643 while (body != OSIP_SUCCESS) {
644 size_t body_length;
645
646 if (boundary) {
647 /* Needs at most 77 bytes,
648 last realloc allocate at least 100 bytes extra */
649 message = osip_str_append(message, boundary);
650 message = osip_strn_append(message, OSIP_CRLF, 2);
651 }
652
653 i = osip_body_to_str(body, &tmp, &body_length);
654
655 if (i != 0) {
656 osip_free(*dest);
657 *dest = NULL;
658
659 if (boundary)
660 osip_free(boundary);
661
662 return i;
663 }
664
665 if (malloc_size < message - *dest + 100 + body_length) {
666 size_t size = message - *dest;
667 int offset_of_body;
668 int offset_content_length_to_modify = 0;
669
670 offset_of_body = (int) (start_of_bodies - *dest);
671
672 if (content_length_to_modify != NULL)
673 offset_content_length_to_modify = (int) (content_length_to_modify - *dest);
674
675 malloc_size = message - *dest + body_length + 100;
676 *dest = osip_realloc(*dest, malloc_size);
677
678 if (*dest == NULL) {
679 osip_free(tmp); /* fixed 09/Jun/2005 */
680
681 if (boundary)
682 osip_free(boundary);
683
684 return OSIP_NOMEM;
685 }
686
687 start_of_bodies = *dest + offset_of_body;
688
689 if (content_length_to_modify != NULL)
690 content_length_to_modify = *dest + offset_content_length_to_modify;
691
692 message = *dest + size;
693 }
694
695 memcpy(message, tmp, body_length);
696 message[body_length] = '\0';
697 osip_free(tmp);
698 message = message + body_length;
699
700 body = (osip_body_t *) osip_list_get_next(&it);
701 }
702 }
703
704 if (boundary) {
705 /* Needs at most 79 bytes,
706 last realloc allocate at least 100 bytes extra */
707 message = osip_str_append(message, boundary);
708 message = osip_strn_append(message, "--", 2);
709 message = osip_strn_append(message, OSIP_CRLF, 2);
710
711 osip_free(boundary);
712 boundary = NULL;
713 }
714
715 if (content_length_to_modify == NULL) {
716 osip_free(*dest);
717 *dest = NULL;
718 return OSIP_SYNTAXERROR;
719 }
720
721 /* we NOW have the length of bodies: */
722 {
723 size_t size = message - start_of_bodies;
724 char tmp2[15];
725
726 total_length += size;
727 snprintf(tmp2, 15, "%i", (int) size);
728 /* do not use osip_strncpy here! */
729 memcpy(content_length_to_modify + 5 - strlen(tmp2), tmp2, strlen(tmp2));
730 }
731
732 /* same remark as at the beginning of the method */
733 sip->message_property = 1;
734 sip->message = osip_malloc(total_length + 1);
735
736 if (sip->message != NULL) {
737 memcpy(sip->message, *dest, total_length);
738 sip->message[total_length] = '\0';
739 sip->message_length = total_length;
740
741 if (message_length != NULL)
742 *message_length = total_length;
743 }
744
745 return OSIP_SUCCESS;
746 }
747
osip_message_to_str(osip_message_t * sip,char ** dest,size_t * message_length)748 int osip_message_to_str(osip_message_t *sip, char **dest, size_t *message_length) {
749 return _osip_message_to_str(sip, dest, message_length, 0);
750 }
751
osip_message_to_str_sipfrag(osip_message_t * sip,char ** dest,size_t * message_length)752 int osip_message_to_str_sipfrag(osip_message_t *sip, char **dest, size_t *message_length) {
753 return _osip_message_to_str(sip, dest, message_length, 1);
754 }
755