Mercurial > pidgin.yaz
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 { |