comparison src/protocols/msn/msg.c @ 8646:1e211dde3cae

[gaim-migrate @ 9398] Added a patch by shx to clean up the message-handling code and split the command stuff from it, among a few other things. Also, I fixed a crash in message parsing, which I think may close a couple bug reports. committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Tue, 13 Apr 2004 04:08:22 +0000
parents 06f57183e29f
children d16e1bfaf08a
comparison
equal deleted inserted replaced
8645:47f647dd2ac3 8646:1e211dde3cae
128 msg->msnslp_header.ack_length_2 = acked_msg->msnslp_header.total_size_2; 128 msg->msnslp_header.ack_length_2 = acked_msg->msnslp_header.total_size_2;
129 129
130 return msg; 130 return msg;
131 } 131 }
132 132
133 MsnMessage * 133 void
134 msn_message_new_from_str(MsnSession *session, const char *str) 134 msn_message_parse_payload(MsnMessage *msg, const char *payload,
135 { 135 size_t payload_len)
136 MsnMessage *msg; 136 {
137 char *command_header; 137 char *tmp_base, *tmp, *c;
138 char *tmp_base, *msg_base, *tmp, *field1, *field2, *c;
139 const char *content_type; 138 const char *content_type;
140 const char *c2; 139
141 140 tmp_base = g_malloc(payload_len + 1);
142 g_return_val_if_fail(str != NULL, NULL); 141 memcpy(tmp_base, payload, payload_len);
143 g_return_val_if_fail(!g_ascii_strncasecmp(str, "MSG", 3), NULL); 142 tmp_base[payload_len] = '\0';
144
145 msg = msn_message_new();
146
147 /* Clear out the old stuff. */
148 msn_message_set_attr(msg, "User-Agent", NULL);
149 msn_message_set_content_type(msg, NULL);
150 msn_message_set_charset(msg, NULL);
151
152 /*
153 * We need to grab the header and then the size, since this might have
154 * binary data.
155 */
156 if ((c2 = strchr(str, '\r')) != NULL)
157 {
158 tmp = command_header = g_strndup(str, (c2 - str));
159
160 GET_NEXT(tmp); /* Skip MSG */
161 field1 = tmp;
162
163 GET_NEXT(tmp); /* Skip the passport or TID */
164 field2 = tmp;
165
166 GET_NEXT(tmp); /* Skip the username or flag */
167 msg->size = atoi(tmp);
168 }
169 else
170 {
171 /* Kind of screwed :) This won't happen. */
172 msn_message_destroy(msg);
173
174 return NULL;
175 }
176
177 tmp_base = g_malloc(msg->size + 1);
178 memcpy(tmp_base, c2 + 2, msg->size);
179 tmp_base[msg->size] = '\0';
180 143
181 tmp = tmp_base; 144 tmp = tmp_base;
182 145
183 /*
184 * We're going to make sure this is incoming by checking field1.
185 * If it has any non-numbers in it, it's incoming. Otherwise, outgoing.
186 */
187 msg->incoming = FALSE;
188
189 for (c = field1; *c != '\0'; c++) {
190 if (*c < '0' || *c > '9') {
191 msg->incoming = TRUE;
192 break;
193 }
194 }
195
196 if (msg->incoming) {
197 msg->sender = msn_users_find_with_passport(session->users, field1);
198
199 if (msg->sender == NULL)
200 msg->sender = msn_user_new(session, field1, field2);
201 else
202 msn_user_ref(msg->sender);
203 }
204 else {
205 msg->tid = atoi(field1);
206 msg->flag = *field2;
207 }
208
209 msg_base = tmp;
210
211 /* Back to the parsination. */ 146 /* Back to the parsination. */
212 while (*tmp != '\r') { 147 while (*tmp != '\r')
148 {
213 char *key, *value; 149 char *key, *value;
214 150
215 key = tmp; 151 key = tmp;
216 152
217 GET_NEXT(tmp); /* Key */ 153 GET_NEXT(tmp); /* Key */
221 GET_NEXT_LINE(tmp); /* Value */ 157 GET_NEXT_LINE(tmp); /* Value */
222 158
223 if ((c = strchr(key, ':')) != NULL) 159 if ((c = strchr(key, ':')) != NULL)
224 *c = '\0'; 160 *c = '\0';
225 161
226 if (!g_ascii_strcasecmp(key, "Content-Type")) { 162 if (!g_ascii_strcasecmp(key, "Content-Type"))
163 {
227 char *charset; 164 char *charset;
228 165
229 if ((c = strchr(value, ';')) != NULL) { 166 if ((c = strchr(value, ';')) != NULL)
230 if ((charset = strchr(c, '=')) != NULL) { 167 {
168 if ((charset = strchr(c, '=')) != NULL)
169 {
231 charset++; 170 charset++;
232 msn_message_set_charset(msg, charset); 171 msn_message_set_charset(msg, charset);
233 } 172 }
234 173
235 *c = '\0'; 174 *c = '\0';
259 198
260 memcpy(header, tmp, 48); 199 memcpy(header, tmp, 48);
261 200
262 tmp += 48; 201 tmp += 48;
263 202
264 body_len = msg->size - (tmp - tmp_base) - 5; 203 body_len = payload_len - (tmp - tmp_base) - 5;
265 msg->body = g_malloc(body_len + 1);
266 204
267 if (body_len > 0) 205 if (body_len > 0)
206 {
207 msg->body = g_malloc(body_len + 1);
268 memcpy(msg->body, tmp, body_len); 208 memcpy(msg->body, tmp, body_len);
269 209 msg->body[body_len] = '\0';
270 msg->body[body_len] = '\0'; 210
271 211 tmp++;
272 tmp++; 212 }
213 else
214 msg->body = NULL;
273 215
274 memcpy(footer, tmp, 4); 216 memcpy(footer, tmp, 4);
275 217
276 tmp += 4; 218 tmp += 4;
277 219
310 else 252 else
311 { 253 {
312 char *tmp2; 254 char *tmp2;
313 size_t body_len; 255 size_t body_len;
314 256
315 body_len = msg->size - (tmp - tmp_base); 257 body_len = payload_len - (tmp - tmp_base);
316 258
317 tmp2 = g_malloc(body_len + 1); 259 tmp2 = g_malloc(body_len + 1);
318 260
319 if (body_len > 0) 261 if (body_len > 0)
320 memcpy(tmp2, tmp, body_len); 262 memcpy(tmp2, tmp, body_len);
324 msn_message_set_body(msg, tmp2); 266 msn_message_set_body(msg, tmp2);
325 267
326 g_free(tmp2); 268 g_free(tmp2);
327 } 269 }
328 270
329 g_free(command_header);
330 g_free(tmp_base); 271 g_free(tmp_base);
331 272
332 /* Done! */ 273 /* Done! */
333
334 return msg;
335 } 274 }
336 275
337 void 276 void
338 msn_message_destroy(MsnMessage *msg) 277 msn_message_destroy(MsnMessage *msg)
339 { 278 {
340 g_return_if_fail(msg != NULL); 279 g_return_if_fail(msg != NULL);
341 280
342 if (msg->ref_count > 0) { 281 if (msg->ref_count > 0)
282 {
343 msn_message_unref(msg); 283 msn_message_unref(msg);
344 284
345 return; 285 return;
346 } 286 }
347
348 if (msg->sender != NULL)
349 msn_user_unref(msg->sender);
350
351 if (msg->receiver != NULL)
352 msn_user_unref(msg->receiver);
353 287
354 if (msg->body != NULL) 288 if (msg->body != NULL)
355 g_free(msg->body); 289 g_free(msg->body);
356 290
357 if (msg->content_type != NULL) 291 if (msg->content_type != NULL)
398 332
399 return msg; 333 return msg;
400 } 334 }
401 335
402 char * 336 char *
403 msn_message_to_string(const MsnMessage *msg, size_t *ret_size) 337 msn_message_gen_payload(const MsnMessage *msg, size_t *ret_size)
404 { 338 {
405 GList *l; 339 GList *l;
406 char *msg_start;
407 char *str; 340 char *str;
408 char buf[MSN_BUF_LEN]; 341 char buf[MSN_BUF_LEN];
409 int len; 342 int len;
410 343
411 /* 344 /*
417 * 350 *
418 * -- ChipX86 351 * -- ChipX86
419 */ 352 */
420 g_return_val_if_fail(msg != NULL, NULL); 353 g_return_val_if_fail(msg != NULL, NULL);
421 354
422 if (msn_message_is_incoming(msg)) { 355 len = msg->size + 1;
423 MsnUser *sender = msn_message_get_sender(msg);
424
425 g_snprintf(buf, sizeof(buf), "MSG %s %s %d\r\n",
426 msn_user_get_passport(sender), msn_user_get_name(sender),
427 (int)msg->size);
428 }
429 else {
430 g_snprintf(buf, sizeof(buf), "MSG %d %c %d\r\n",
431 msn_message_get_transaction_id(msg),
432 msn_message_get_flag(msg), (int)msg->size);
433 }
434
435 len = strlen(buf) + msg->size + 1;
436 356
437 str = g_new0(char, len + 1); 357 str = g_new0(char, len + 1);
438 358
439 g_strlcpy(str, buf, len);
440
441 msg_start = str + strlen(str);
442
443 /* Standard header. */ 359 /* Standard header. */
444 if (msg->charset == NULL) { 360 if (msg->charset == NULL)
361 {
445 g_snprintf(buf, sizeof(buf), 362 g_snprintf(buf, sizeof(buf),
446 "MIME-Version: 1.0\r\n" 363 "MIME-Version: 1.0\r\n"
447 "Content-Type: %s\r\n", 364 "Content-Type: %s\r\n",
448 msg->content_type); 365 msg->content_type);
449 } 366 }
450 else { 367 else
368 {
451 g_snprintf(buf, sizeof(buf), 369 g_snprintf(buf, sizeof(buf),
452 "MIME-Version: 1.0\r\n" 370 "MIME-Version: 1.0\r\n"
453 "Content-Type: %s; charset=%s\r\n", 371 "Content-Type: %s; charset=%s\r\n",
454 msg->content_type, msg->charset); 372 msg->content_type, msg->charset);
455 } 373 }
456 374
457 g_strlcat(str, buf, len); 375 g_strlcat(str, buf, len);
458 376
459 for (l = msg->attr_list; l != NULL; l = l->next) { 377 for (l = msg->attr_list; l != NULL; l = l->next)
378 {
460 const char *key = (char *)l->data; 379 const char *key = (char *)l->data;
461 const char *value; 380 const char *value;
462 381
463 value = msn_message_get_attr(msg, key); 382 value = msn_message_get_attr(msg, key);
464 383
520 { 439 {
521 const char *body = msn_message_get_body(msg); 440 const char *body = msn_message_get_body(msg);
522 441
523 if (body != NULL) 442 if (body != NULL)
524 { 443 {
525 g_strlcpy(c, body, msg->size - (c - msg_start)); 444 g_strlcpy(c, body, msg->size - (c - str));
526 445
527 c += strlen(body); 446 c += strlen(body);
528 447
529 if (strlen(body) > 0) 448 if (strlen(body) > 0)
530 *c++ = '\0'; 449 *c++ = '\0';
531 } 450 }
532 } 451 }
533 452
534 c += msn_put32(c, msg->msnslp_footer.app_id); 453 c += msn_put32(c, msg->msnslp_footer.app_id);
535 454
536 if (msg->size != (c - msg_start)) 455 if (msg->size != (c - str))
537 { 456 {
538 gaim_debug(GAIM_DEBUG_ERROR, "msn", 457 gaim_debug(GAIM_DEBUG_ERROR, "msn",
539 "Outgoing message size (%d) and data length (%d) " 458 "Outgoing message size (%d) and data length (%d) "
540 "do not match!\n", msg->size, (c - msg_start)); 459 "do not match!\n", msg->size, (c - str));
541 } 460 }
542 } 461 }
543 else 462 else
544 { 463 {
545 const char *body = msn_message_get_body(msg); 464 const char *body = msn_message_get_body(msg);
546 465
547 g_strlcat(str, body, len); 466 g_strlcat(str, body, len);
548 467
549 if (msg->size != strlen(msg_start)) { 468 if (msg->size != strlen(str))
469 {
550 gaim_debug(GAIM_DEBUG_ERROR, "msn", 470 gaim_debug(GAIM_DEBUG_ERROR, "msn",
551 "Outgoing message size (%d) and string length (%d) " 471 "Outgoing message size (%d) and string length (%d) "
552 "do not match!\n", msg->size, strlen(msg_start)); 472 "do not match!\n", msg->size, strlen(str));
553 } 473 }
554 } 474 }
555 475
556 if (ret_size != NULL) 476 if (ret_size != NULL)
557 *ret_size = len - 1; 477 *ret_size = len - 1;
558 478
559 return str; 479 return str;
560 }
561
562 gboolean
563 msn_message_is_outgoing(const MsnMessage *msg)
564 {
565 g_return_val_if_fail(msg != NULL, FALSE);
566
567 return !msg->incoming;
568 }
569
570 gboolean
571 msn_message_is_incoming(const MsnMessage *msg)
572 {
573 g_return_val_if_fail(msg != NULL, FALSE);
574
575 return msg->incoming;
576 }
577
578 void
579 msn_message_set_sender(MsnMessage *msg, MsnUser *user)
580 {
581 g_return_if_fail(msg != NULL);
582 g_return_if_fail(user != NULL);
583
584 msg->sender = user;
585
586 msn_user_ref(msg->sender);
587 }
588
589 MsnUser *
590 msn_message_get_sender(const MsnMessage *msg)
591 {
592 g_return_val_if_fail(msg != NULL, NULL);
593
594 return msg->sender;
595 }
596
597 void
598 msn_message_set_receiver(MsnMessage *msg, MsnUser *user)
599 {
600 g_return_if_fail(msg != NULL);
601 g_return_if_fail(user != NULL);
602
603 msg->receiver = user;
604
605 if (msg->msnslp_message)
606 msn_message_set_attr(msg, "P2P-Dest", msn_user_get_passport(user));
607
608 msn_user_ref(msg->receiver);
609 }
610
611 MsnUser *
612 msn_message_get_receiver(const MsnMessage *msg)
613 {
614 g_return_val_if_fail(msg != NULL, NULL);
615
616 return msg->receiver;
617 }
618
619 void
620 msn_message_set_transaction_id(MsnMessage *msg, unsigned int tid)
621 {
622 g_return_if_fail(msg != NULL);
623 g_return_if_fail(tid > 0);
624
625 msg->tid = tid;
626 }
627
628 unsigned int
629 msn_message_get_transaction_id(const MsnMessage *msg)
630 {
631 g_return_val_if_fail(msg != NULL, 0);
632
633 return msg->tid;
634 } 480 }
635 481
636 void 482 void
637 msn_message_set_flag(MsnMessage *msg, char flag) 483 msn_message_set_flag(MsnMessage *msg, char flag)
638 { 484 {