comparison src/protocols/toc/toc.c @ 6306:69c9b6e63a98

[gaim-migrate @ 6805] This fixes a crash sending toc messages with certain characters. I broke it in the great constification of 0.64cvs. http://sourceforge.net/tracker/?group_id=235&atid=100235&func=detail&aid=775318 committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Sat, 26 Jul 2003 15:57:07 +0000
parents 11bedb793a44
children 3613007cbb6e
comparison
equal deleted inserted replaced
6305:1fbdca69a25e 6306:69c9b6e63a98
286 pos += g_snprintf(&s[pos], len - pos, "d %s\n", (char *)dlist->data); 286 pos += g_snprintf(&s[pos], len - pos, "d %s\n", (char *)dlist->data);
287 dlist = dlist->next; 287 dlist = dlist->next;
288 } 288 }
289 } 289 }
290 290
291 static int escape_message(char *msg) 291 char *escape_message(const char *msg)
292 { 292 {
293 char *c, *cpy; 293 char *ret;
294 int cnt = 0; 294 int i, j;
295 /* Assumes you have a buffer able to cary at least BUF_LEN * 2 bytes */ 295
296 if (strlen(msg) > BUF_LEN) { 296 if (!msg)
297 debug_printf("Warning: truncating message to 2048 bytes\n"); 297 return NULL;
298 msg[2047] = '\0'; 298
299 } 299 /* Calculate the length after escaping */
300 300 for (i=0, j=0; msg[i]; i++)
301 cpy = g_strdup(msg); 301 switch (msg[i]) {
302 c = cpy; 302 case '$':
303 while (*c) { 303 case '[':
304 switch (*c) { 304 case ']':
305 case '$': 305 case '(':
306 case '[': 306 case ')':
307 case ']': 307 j++;
308 case '(': 308 default:
309 case ')': 309 j++;
310 msg[cnt++] = '\\';
311 /* Fall through */
312 default:
313 msg[cnt++] = *c;
314 } 310 }
315 c++; 311
316 } 312 /* Allocate a string */
317 msg[cnt] = '\0'; 313 ret = (char *)malloc((j+1) * sizeof(char));
318 g_free(cpy); 314
319 return cnt; 315 /* Copy the string */
316 for (i=0, j=0; msg[i]; i++)
317 switch (msg[i]) {
318 case '$':
319 case '[':
320 case ']':
321 case '(':
322 case ')':
323 ret[j++] = '\\';
324 default:
325 ret[j++] = msg[i];
326 }
327 ret[j] = '\0';
328
329 return ret;
320 } 330 }
321 331
322 /* 332 /*
323 * Duplicates the input string, replacing each \n with a <BR>, and 333 * Duplicates the input string, replacing each \n with a <BR>, and
324 * escaping a few other characters. 334 * escaping a few other characters.
330 340
331 if (!msg) 341 if (!msg)
332 return NULL; 342 return NULL;
333 343
334 /* Calculate the length after escaping */ 344 /* Calculate the length after escaping */
335 i = 0; 345 for (i=0, j=0; msg[i]; i++)
336 j = 0;
337 while (msg[i++])
338 switch (msg[i]) { 346 switch (msg[i]) {
339 case '\n': 347 case '\n':
340 j += 4; 348 j += 4;
341 break; 349 break;
342 case '{': 350 case '{':
343 case '}': 351 case '}':
344 case '\\': 352 case '\\':
345 case '"': 353 case '"':
346 j += 1; 354 j += 1;
347 default: 355 default:
348 j += 1; 356 j += 1;
349 } 357 }
350 358
351 /* Allocate a string */ 359 /* Allocate a string */
352 ret = (char *)malloc((j+1) * sizeof(char)); 360 ret = (char *)malloc((j+1) * sizeof(char));
353 361
354 /* Copy the string */ 362 /* Copy the string */
355 i = 0; 363 for (i=0, j=0; msg[i]; i++)
356 j = 0;
357 while (msg[i]) {
358 switch (msg[i]) { 364 switch (msg[i]) {
359 case '\n': 365 case '\n':
360 ret[j] = '<'; 366 ret[j++] = '<';
361 ret[j+1] = 'B'; 367 ret[j++] = 'B';
362 ret[j+2] = 'R'; 368 ret[j++] = 'R';
363 ret[j+3] = '>'; 369 ret[j++] = '>';
364 j += 4; 370 break;
365 break; 371 case '{':
366 case '{': 372 case '}':
367 case '}': 373 case '\\':
368 case '\\': 374 case '"':
369 case '"': 375 ret[j++] = '\\';
370 ret[j] = '\\'; 376 default:
371 j++; 377 ret[j++] = msg[i];
372 default:
373 ret[j] = msg[i];
374 j++;
375 } 378 }
376 i++;
377 }
378 ret[j] = '\0'; 379 ret[j] = '\0';
379 380
380 return ret; 381 return ret;
381 } 382 }
382 383
383 static int sflap_send(GaimConnection *gc, char *buf, int olen, int type) 384 static int sflap_send(GaimConnection *gc, const char *buf, int olen, int type)
384 { 385 {
386 struct toc_data *tdt = (struct toc_data *)gc->proto_data;
385 int len; 387 int len;
386 int slen = 0; 388 int slen = 0;
389 int ret;
387 struct sflap_hdr hdr; 390 struct sflap_hdr hdr;
388 char obuf[MSG_LEN]; 391 char *escaped, *obuf;
389 struct toc_data *tdt = (struct toc_data *)gc->proto_data;
390 392
391 if (tdt->state == STATE_PAUSE) 393 if (tdt->state == STATE_PAUSE)
392 /* TOC has given us the PAUSE message; sending could cause a disconnect 394 /* TOC has given us the PAUSE message; sending could cause a disconnect
393 * so we just return here like everything went through fine */ 395 * so we just return here like everything went through fine */
394 return 0; 396 return 0;
395 397
396 if (olen < 0) 398 if (olen < 0) {
397 len = escape_message(buf); 399 escaped = escape_message(buf);
398 else 400 len = strlen(buf);
401 } else {
402 escaped = g_memdup(buf, olen);
399 len = olen; 403 len = olen;
400 404 }
401 /* One _last_ 2048 check here! This shouldn't ever 405
402 * get hit though, hopefully. If it gets hit on an IM 406 /*
403 * It'll lose the last " and the message won't go through, 407 * One _last_ 2048 check here! This shouldn't ever
404 * but this'll stop a segfault. */ 408 * get hit though, hopefully. If it gets hit on an IM
409 * It'll lose the last " and the message won't go through,
410 * but this'll stop a segfault.
411 */
405 if (len > MSG_LEN) { 412 if (len > MSG_LEN) {
406 debug_printf("message too long, truncating\n"); 413 debug_printf("message too long, truncating\n");
407 buf[MSG_LEN - 1] = '\0'; 414 escaped[MSG_LEN - 1] = '\0';
408 len = MSG_LEN; 415 len = MSG_LEN;
409 } 416 }
410 417
411 if (olen < 0) 418 if (olen < 0)
412 debug_printf("TOC C: %s\n", buf); 419 debug_printf("TOC C: %s\n", escaped);
413 420
414 hdr.ast = '*'; 421 hdr.ast = '*';
415 hdr.type = type; 422 hdr.type = type;
416 hdr.seqno = htons(tdt->seqno++ & 0xffff); 423 hdr.seqno = htons(tdt->seqno++ & 0xffff);
417 hdr.len = htons(len + (type == TYPE_SIGNON ? 0 : 1)); 424 hdr.len = htons(len + (type == TYPE_SIGNON ? 0 : 1));
418 425
426 obuf = (char *)malloc((sizeof(hdr)+len+1) * sizeof(char));
419 memcpy(obuf, &hdr, sizeof(hdr)); 427 memcpy(obuf, &hdr, sizeof(hdr));
420 slen += sizeof(hdr); 428 slen += sizeof(hdr);
421 memcpy(&obuf[slen], buf, len); 429
430 memcpy(&obuf[slen], escaped, len);
422 slen += len; 431 slen += len;
432
423 if (type != TYPE_SIGNON) { 433 if (type != TYPE_SIGNON) {
424 obuf[slen] = '\0'; 434 obuf[slen] = '\0';
425 slen += 1; 435 slen += 1;
426 } 436 }
427 437
428 return toc_write(tdt->toc_fd, obuf, slen); 438 ret = toc_write(tdt->toc_fd, obuf, slen);
439 free(obuf);
440 free(escaped);
441
442 return ret;
429 } 443 }
430 444
431 static int wait_reply(GaimConnection *gc, char *buffer, size_t buflen) 445 static int wait_reply(GaimConnection *gc, char *buffer, size_t buflen)
432 { 446 {
433 struct toc_data *tdt = (struct toc_data *)gc->proto_data; 447 struct toc_data *tdt = (struct toc_data *)gc->proto_data;
1122 1136
1123 static void toc_change_passwd(GaimConnection *g, const char *orig, const char *new) 1137 static void toc_change_passwd(GaimConnection *g, const char *orig, const char *new)
1124 { 1138 {
1125 char buf[BUF_LEN * 2]; 1139 char buf[BUF_LEN * 2];
1126 g_snprintf(buf, BUF_LONG, "toc_change_passwd %s %s", orig, new); 1140 g_snprintf(buf, BUF_LONG, "toc_change_passwd %s %s", orig, new);
1127 sflap_send(g, buf, strlen(buf), TYPE_DATA); 1141 sflap_send(g, buf, -1, TYPE_DATA);
1128 } 1142 }
1129 1143
1130 static void toc_add_buddy(GaimConnection *g, const char *name) 1144 static void toc_add_buddy(GaimConnection *g, const char *name)
1131 { 1145 {
1132 char buf[BUF_LEN * 2]; 1146 char buf[BUF_LEN * 2];