comparison src/protocols/msn/msg.c @ 9193:502707ca1836

[gaim-migrate @ 9988] Patch by Felipe Contreras to add MSN file transfer and buddy icons. Please test and report any bugs! committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Sun, 06 Jun 2004 02:39:08 +0000
parents c30d81b4dd22
children ab6636c5a136
comparison
equal deleted inserted replaced
9192:5655dcd94d0f 9193:502707ca1836
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */ 21 */
22 #include "msn.h" 22 #include "msn.h"
23 #include "msg.h" 23 #include "msg.h"
24 24
25 #define GET_NEXT(tmp) \
26 while (*(tmp) && *(tmp) != ' ' && *(tmp) != '\r') \
27 (tmp)++; \
28 if (*(tmp) != '\0') *(tmp)++ = '\0'; \
29 if (*(tmp) == '\n') (tmp)++; \
30 while (*(tmp) && *(tmp) == ' ') \
31 (tmp)++
32
33 #define GET_NEXT_LINE(tmp) \
34 while (*(tmp) && *(tmp) != '\r') \
35 (tmp)++; \
36 if (*(tmp) != '\0') *(tmp)++ = '\0'; \
37 if (*(tmp) == '\n') (tmp)++
38
39
40 #define msn_put16(buf, data) ( \
41 (*(buf) = (unsigned char)((data)>>8)&0xff), \
42 (*((buf)+1) = (unsigned char)(data)&0xff), \
43 2)
44 #define msn_get16(buf) ((((*(buf))<<8)&0xff00) + ((*((buf)+1)) & 0xff))
45 #define msn_put32(buf, data) ( \
46 (*((buf)) = (unsigned char)((data)>>24)&0xff), \
47 (*((buf)+1) = (unsigned char)((data)>>16)&0xff), \
48 (*((buf)+2) = (unsigned char)((data)>>8)&0xff), \
49 (*((buf)+3) = (unsigned char)(data)&0xff), \
50 4)
51 #define msn_get32(buf) ((((*(buf))<<24)&0xff000000) + \
52 (((*((buf)+1))<<16)&0x00ff0000) + \
53 (((*((buf)+2))<< 8)&0x0000ff00) + \
54 (((*((buf)+3) )&0x000000ff)))
55
56
57 MsnMessage * 25 MsnMessage *
58 msn_message_new(void) 26 msn_message_new(void)
59 { 27 {
60 MsnMessage *msg; 28 MsnMessage *msg;
61 29
105 msn_message_set_content_type(msg, "application/x-msnmsgrp2p"); 73 msn_message_set_content_type(msg, "application/x-msnmsgrp2p");
106 74
107 return msg; 75 return msg;
108 } 76 }
109 77
110 MsnMessage * 78 void
111 msn_message_new_msnslp_ack(MsnMessage *acked_msg) 79 msn_message_parse_slp_body(MsnMessage *msg, const char *body, size_t len)
112 { 80 {
113 MsnMessage *msg; 81 MsnSlpHeader header;
114 82 const char *tmp;
115 g_return_val_if_fail(acked_msg != NULL, NULL); 83
116 g_return_val_if_fail(acked_msg->msnslp_message, NULL); 84 tmp = body;
117 85
118 msg = msn_message_new_msnslp(); 86 /* Import the header. */
119 87 memcpy(&header, tmp, sizeof(header));
120 msg->msnslp_ack_message = TRUE; 88 tmp += sizeof(header);
121 msg->acked_msg = msn_message_ref(acked_msg); 89
122 90 msg->msnslp_header.session_id = GUINT32_FROM_LE(header.session_id);
123 msg->msnslp_header.session_id = acked_msg->msnslp_header.session_id; 91 msg->msnslp_header.id = GUINT32_FROM_LE(header.id);
124 msg->msnslp_header.total_size = acked_msg->msnslp_header.total_size; 92 msg->msnslp_header.offset = GUINT64_FROM_LE(header.offset);
125 msg->msnslp_header.flags = 0x02; 93 msg->msnslp_header.total_size = GUINT64_FROM_LE(header.total_size);
126 msg->msnslp_header.ack_id = acked_msg->msnslp_header.id; 94 msg->msnslp_header.length = GUINT32_FROM_LE(header.length);
127 msg->msnslp_header.ack_sub_id = acked_msg->msnslp_header.ack_id; 95 msg->msnslp_header.flags = GUINT32_FROM_LE(header.flags);
128 msg->msnslp_header.ack_size = acked_msg->msnslp_header.total_size; 96 msg->msnslp_header.ack_id = GUINT32_FROM_LE(header.ack_id);
129 97 msg->msnslp_header.ack_sub_id = GUINT32_FROM_LE(header.ack_sub_id);
130 return msg; 98 msg->msnslp_header.ack_size = GUINT64_FROM_LE(header.ack_size);
99
100 /* Import the body. */
101 /* msg->body_len = msg->msnslp_header.length; */
102 msg->body_len = len - (tmp - body);
103
104 if (msg->body_len > 0)
105 msg->body = g_memdup(tmp, msg->body_len);
106
107 tmp += msg->body_len;
131 } 108 }
132 109
133 void 110 void
134 msn_message_parse_payload(MsnMessage *msg, 111 msn_message_parse_payload(MsnMessage *msg,
135 const char *payload, size_t payload_len) 112 const char *payload, size_t payload_len)
136 { 113 {
137 char *tmp_base, *tmp; 114 char *tmp_base, *tmp;
138 const char *content_type; 115 const char *content_type;
116 char *end;
117 char **elems, **cur, **tokens;
139 118
140 g_return_if_fail(payload != NULL); 119 g_return_if_fail(payload != NULL);
141 120
142 tmp_base = tmp = g_memdup(payload, payload_len); 121 tmp_base = tmp = g_memdup(payload, payload_len + 1);
143 122 tmp[payload_len] = '\0';
144 /* Back to the parsination. */ 123
145 while (*tmp != '\r') 124 /* Parse the attributes. */
146 { 125 end = strstr(tmp, "\r\n\r\n");
147 char *key, *value, *c; 126 g_return_if_fail(end != NULL);
148 127 *end = '\0';
149 key = tmp; 128
150 129 elems = g_strsplit(tmp, "\r\n", 0);
151 GET_NEXT(tmp); /* Key */ 130
152 131 for (cur = elems; *cur != NULL; cur++)
153 value = tmp; 132 {
154 133 const char *key, *value;
155 GET_NEXT_LINE(tmp); /* Value */ 134
156 135 tokens = g_strsplit(*cur, ": ", 2);
157 if ((c = strchr(key, ':')) != NULL) 136
158 *c = '\0'; 137 key = tokens[0];
159 138 value = tokens[1];
160 if (!g_ascii_strcasecmp(key, "MIME-Version")) 139
140 if (!strcmp(key, "MIME-Version"))
161 continue; 141 continue;
162 142
163 if (!g_ascii_strcasecmp(key, "Content-Type")) 143 if (!strcmp(key, "Content-Type"))
164 { 144 {
165 char *charset; 145 char *charset, *c;
166 146
167 if ((c = strchr(value, ';')) != NULL) 147 if ((c = strchr(value, ';')) != NULL)
168 { 148 {
169 if ((charset = strchr(c, '=')) != NULL) 149 if ((charset = strchr(c, '=')) != NULL)
170 { 150 {
176 } 156 }
177 157
178 msn_message_set_content_type(msg, value); 158 msn_message_set_content_type(msg, value);
179 } 159 }
180 else 160 else
161 {
181 msn_message_set_attr(msg, key, value); 162 msn_message_set_attr(msg, key, value);
182 } 163 }
183 164
184 /* "\r\n" */ 165 g_strfreev(tokens);
185 tmp += 2; 166 }
167
168 g_strfreev(elems);
169
170 tmp = end + 4;
186 171
187 /* Now we *should* be at the body. */ 172 /* Now we *should* be at the body. */
188 content_type = msn_message_get_content_type(msg); 173 content_type = msn_message_get_content_type(msg);
189 174
190 if (content_type != NULL && 175 if (content_type != NULL &&
198 /* Import the header. */ 183 /* Import the header. */
199 memcpy(&header, tmp, sizeof(header)); 184 memcpy(&header, tmp, sizeof(header));
200 tmp += sizeof(header); 185 tmp += sizeof(header);
201 186
202 msg->msnslp_header.session_id = GUINT32_FROM_LE(header.session_id); 187 msg->msnslp_header.session_id = GUINT32_FROM_LE(header.session_id);
203 msg->msnslp_header.id = GUINT64_FROM_LE(header.id); 188 msg->msnslp_header.id = GUINT32_FROM_LE(header.id);
204 msg->msnslp_header.offset = GUINT64_FROM_LE(header.offset); 189 msg->msnslp_header.offset = GUINT64_FROM_LE(header.offset);
205 msg->msnslp_header.total_size = GUINT32_FROM_LE(header.total_size); 190 msg->msnslp_header.total_size = GUINT64_FROM_LE(header.total_size);
206 msg->msnslp_header.length = GUINT32_FROM_LE(header.length); 191 msg->msnslp_header.length = GUINT32_FROM_LE(header.length);
207 msg->msnslp_header.flags = GUINT32_FROM_LE(header.flags); 192 msg->msnslp_header.flags = GUINT32_FROM_LE(header.flags);
208 msg->msnslp_header.ack_id = GUINT32_FROM_LE(header.ack_id); 193 msg->msnslp_header.ack_id = GUINT32_FROM_LE(header.ack_id);
209 msg->msnslp_header.ack_sub_id = GUINT32_FROM_LE(header.ack_sub_id); 194 msg->msnslp_header.ack_sub_id = GUINT32_FROM_LE(header.ack_sub_id);
210 msg->msnslp_header.ack_size = GUINT64_FROM_LE(header.ack_size); 195 msg->msnslp_header.ack_size = GUINT64_FROM_LE(header.ack_size);
228 msg->body_len = payload_len - (tmp - tmp_base); 213 msg->body_len = payload_len - (tmp - tmp_base);
229 msg->body = g_memdup(tmp, msg->body_len); 214 msg->body = g_memdup(tmp, msg->body_len);
230 } 215 }
231 216
232 g_free(tmp_base); 217 g_free(tmp_base);
233 218 }
234 /* Done! */ 219
220 MsnMessage *
221 msn_message_new_from_cmd(MsnSession *session, MsnCommand *cmd)
222 {
223 MsnMessage *msg;
224
225 g_return_val_if_fail(cmd != NULL, NULL);
226
227 msg = msn_message_new();
228
229 msg->remote_user = g_strdup(cmd->params[0]);
230 /* msg->size = atoi(cmd->params[2]); */
231 msg->cmd = cmd;
232
233 return msg;
235 } 234 }
236 235
237 void 236 void
238 msn_message_destroy(MsnMessage *msg) 237 msn_message_destroy(MsnMessage *msg)
239 { 238 {
243 { 242 {
244 msn_message_unref(msg); 243 msn_message_unref(msg);
245 244
246 return; 245 return;
247 } 246 }
247
248 if (msg->remote_user != NULL)
249 g_free(msg->remote_user);
248 250
249 if (msg->body != NULL) 251 if (msg->body != NULL)
250 g_free(msg->body); 252 g_free(msg->body);
251 253
252 if (msg->content_type != NULL) 254 if (msg->content_type != NULL)
256 g_free(msg->charset); 258 g_free(msg->charset);
257 259
258 g_hash_table_destroy(msg->attr_table); 260 g_hash_table_destroy(msg->attr_table);
259 g_list_free(msg->attr_list); 261 g_list_free(msg->attr_list);
260 262
261 if (msg->msnslp_ack_message)
262 msn_message_unref(msg->acked_msg);
263
264 g_free(msg); 263 g_free(msg);
265 } 264 }
266 265
267 MsnMessage * 266 MsnMessage *
268 msn_message_ref(MsnMessage *msg) 267 msn_message_ref(MsnMessage *msg)
282 if (msg->ref_count <= 0) 281 if (msg->ref_count <= 0)
283 return NULL; 282 return NULL;
284 283
285 msg->ref_count--; 284 msg->ref_count--;
286 285
287 if (msg->ref_count == 0) { 286 if (msg->ref_count == 0)
287 {
288 msn_message_destroy(msg); 288 msn_message_destroy(msg);
289 289
290 return NULL; 290 return NULL;
291 } 291 }
292 292
293 return msg; 293 return msg;
294 } 294 }
295 295
296 char * 296 char *
297 msn_message_gen_payload(const MsnMessage *msg, size_t *ret_size) 297 msn_message_gen_slp_body(MsnMessage *msg, size_t *ret_size)
298 {
299 MsnSlpHeader header;
300
301 char *tmp, *base;
302 const void *body;
303 size_t len, body_len;
304
305 g_return_val_if_fail(msg != NULL, NULL);
306
307 len = MSN_BUF_LEN;
308
309 base = tmp = g_malloc(len + 1);
310
311 body = msn_message_get_bin_data(msg, &body_len);
312
313 header.session_id = GUINT32_TO_LE(msg->msnslp_header.session_id);
314 header.id = GUINT32_TO_LE(msg->msnslp_header.id);
315 header.offset = GUINT64_TO_LE(msg->msnslp_header.offset);
316 header.total_size = GUINT64_TO_LE(msg->msnslp_header.total_size);
317 header.length = GUINT32_TO_LE(msg->msnslp_header.length);
318 header.flags = GUINT32_TO_LE(msg->msnslp_header.flags);
319 header.ack_id = GUINT32_TO_LE(msg->msnslp_header.ack_id);
320 header.ack_sub_id = GUINT32_TO_LE(msg->msnslp_header.ack_sub_id);
321 header.ack_size = GUINT64_TO_LE(msg->msnslp_header.ack_size);
322
323 memcpy(tmp, &header, 48);
324 tmp += 48;
325
326 if (body != NULL)
327 {
328 memcpy(tmp, body, body_len);
329 tmp += body_len;
330 }
331
332 if (ret_size != NULL)
333 *ret_size = tmp - base;
334
335 return base;
336 }
337
338 char *
339 msn_message_gen_payload(MsnMessage *msg, size_t *ret_size)
298 { 340 {
299 GList *l; 341 GList *l;
300 char *n, *base, *end; 342 char *n, *base, *end;
301 int len; 343 int len;
302 size_t body_len; 344 size_t body_len;
347 { 389 {
348 MsnSlpHeader header; 390 MsnSlpHeader header;
349 MsnSlpFooter footer; 391 MsnSlpFooter footer;
350 392
351 header.session_id = GUINT32_TO_LE(msg->msnslp_header.session_id); 393 header.session_id = GUINT32_TO_LE(msg->msnslp_header.session_id);
352 header.id = GUINT64_TO_LE(msg->msnslp_header.id); 394 header.id = GUINT32_TO_LE(msg->msnslp_header.id);
353 header.offset = GUINT64_TO_LE(msg->msnslp_header.offset); 395 header.offset = GUINT64_TO_LE(msg->msnslp_header.offset);
354 header.total_size = GUINT32_TO_LE(msg->msnslp_header.total_size); 396 header.total_size = GUINT64_TO_LE(msg->msnslp_header.total_size);
355 header.length = GUINT32_TO_LE(msg->msnslp_header.length); 397 header.length = GUINT32_TO_LE(msg->msnslp_header.length);
356 header.flags = GUINT32_TO_LE(msg->msnslp_header.flags); 398 header.flags = GUINT32_TO_LE(msg->msnslp_header.flags);
357 header.ack_id = GUINT32_TO_LE(msg->msnslp_header.ack_id); 399 header.ack_id = GUINT32_TO_LE(msg->msnslp_header.ack_id);
358 header.ack_sub_id = GUINT32_TO_LE(msg->msnslp_header.ack_sub_id); 400 header.ack_sub_id = GUINT32_TO_LE(msg->msnslp_header.ack_sub_id);
359 header.ack_size = GUINT64_TO_LE(msg->msnslp_header.ack_size); 401 header.ack_size = GUINT64_TO_LE(msg->msnslp_header.ack_size);
362 n += 48; 404 n += 48;
363 405
364 if (body != NULL) 406 if (body != NULL)
365 { 407 {
366 memcpy(n, body, body_len); 408 memcpy(n, body, body_len);
409
367 n += body_len; 410 n += body_len;
368 } 411 }
369 412
370 footer.value = GUINT32_TO_BE(msg->msnslp_footer.value); 413 footer.value = GUINT32_TO_BE(msg->msnslp_footer.value);
371 414
381 } 424 }
382 } 425 }
383 426
384 if (ret_size != NULL) 427 if (ret_size != NULL)
385 { 428 {
386 *ret_size = n - base;
387
388 if (*ret_size > 1664) 429 if (*ret_size > 1664)
389 *ret_size = 1664; 430 *ret_size = 1664;
431
432 *ret_size = n - base;
390 } 433 }
391 434
392 return base; 435 return base;
393 } 436 }
394 437
450 g_return_if_fail(msg != NULL); 493 g_return_if_fail(msg != NULL);
451 494
452 if (msg->content_type != NULL) 495 if (msg->content_type != NULL)
453 g_free(msg->content_type); 496 g_free(msg->content_type);
454 497
455 if (type != NULL) 498 msg->content_type = (type != NULL) ? g_strdup(type) : NULL;
456 msg->content_type = g_strdup(type);
457 else
458 msg->content_type = NULL;
459 } 499 }
460 500
461 const char * 501 const char *
462 msn_message_get_content_type(const MsnMessage *msg) 502 msn_message_get_content_type(const MsnMessage *msg)
463 { 503 {
472 g_return_if_fail(msg != NULL); 512 g_return_if_fail(msg != NULL);
473 513
474 if (msg->charset != NULL) 514 if (msg->charset != NULL)
475 g_free(msg->charset); 515 g_free(msg->charset);
476 516
477 if (charset != NULL) 517 msg->charset = (charset != NULL) ? g_strdup(charset) : NULL;
478 msg->charset = g_strdup(charset);
479 else
480 msg->charset = NULL;
481 } 518 }
482 519
483 const char * 520 const char *
484 msn_message_get_charset(const MsnMessage *msg) 521 msn_message_get_charset(const MsnMessage *msg)
485 { 522 {
540 577
541 GHashTable * 578 GHashTable *
542 msn_message_get_hashtable_from_body(const MsnMessage *msg) 579 msn_message_get_hashtable_from_body(const MsnMessage *msg)
543 { 580 {
544 GHashTable *table; 581 GHashTable *table;
545 char *body, *s, *c; 582 const char *body;
546 583 char **elems, **cur, **tokens;
547 g_return_val_if_fail(msg != NULL, NULL); 584
548 585 g_return_val_if_fail(msg != NULL, NULL);
549 s = body = g_strdup(msn_message_get_bin_data(msg, NULL)); 586
587 table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
588
589 body = msn_message_get_bin_data(msg, NULL);
550 590
551 g_return_val_if_fail(body != NULL, NULL); 591 g_return_val_if_fail(body != NULL, NULL);
552 592
553 table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); 593 elems = g_strsplit(body, "\r\n", 0);
554 594
555 while (*s != '\r' && *s != '\0') 595 for (cur = elems; *cur != NULL; cur++)
556 { 596 {
557 char *key, *value; 597 if (**cur == '\0')
558 598 break;
559 key = s; 599
560 600 tokens = g_strsplit(*cur, ": ", 2);
561 GET_NEXT(s); 601
562 602 if (tokens[0] != NULL && tokens[1] != NULL)
563 value = s; 603 g_hash_table_insert(table, tokens[0], tokens[1]);
564 604
565 GET_NEXT_LINE(s); 605 g_free(tokens);
566 606 }
567 if ((c = strchr(key, ':')) != NULL) 607
608 g_strfreev(elems);
609
610 return table;
611 }
612
613 void
614 msn_message_show_readable(MsnMessage *msg, const char *info,
615 gboolean text_body)
616 {
617 GString *str;
618 size_t body_len;
619 const char *body;
620 GList *l;
621
622 g_return_if_fail(msg != NULL);
623
624 str = g_string_new(NULL);
625
626 /* Standard header. */
627 if (msg->charset == NULL)
628 {
629 g_string_append_printf(str,
630 "MIME-Version: 1.0\r\n"
631 "Content-Type: %s\r\n",
632 msg->content_type);
633 }
634 else
635 {
636 g_string_append_printf(str,
637 "MIME-Version: 1.0\r\n"
638 "Content-Type: %s; charset=%s\r\n",
639 msg->content_type, msg->charset);
640 }
641
642 for (l = msg->attr_list; l; l = l->next)
643 {
644 char *key;
645 const char *value;
646
647 key = l->data;
648 value = msn_message_get_attr(msg, key);
649
650 g_string_append_printf(str, "%s: %s\r\n", key, value);
651 }
652
653 g_string_append(str, "\r\n");
654
655 body = msn_message_get_bin_data(msg, &body_len);
656
657 if (msg->msnslp_message)
658 {
659 g_string_append_printf(str, "%u ", msg->msnslp_header.session_id);
660 g_string_append_printf(str, "%u ", msg->msnslp_header.id);
661 g_string_append_printf(str, "%llu ", msg->msnslp_header.offset);
662 g_string_append(str, "\r\n");
663 g_string_append_printf(str, "%llu ",
664 msg->msnslp_header.total_size);
665 g_string_append_printf(str, "%u ", msg->msnslp_header.length);
666 g_string_append_printf(str, "%u ", msg->msnslp_header.flags);
667 g_string_append(str, "\r\n");
668 g_string_append_printf(str, "%u ", msg->msnslp_header.ack_id);
669 g_string_append_printf(str, "%u ", msg->msnslp_header.ack_sub_id);
670 g_string_append_printf(str, "%lld ", msg->msnslp_header.ack_size);
671 g_string_append(str, "\r\n");
672
673 if (body != NULL)
568 { 674 {
569 *c = '\0'; 675 if (text_body)
570 676 {
571 g_hash_table_insert(table, g_strdup(key), g_strdup(value)); 677 g_string_append_len(str, body, body_len);
678 if (body[body_len - 1] == '\0')
679 {
680 str->len--;
681 g_string_append(str, " 0x00");
682 }
683 g_string_append(str, "\r\n");
684 }
685 else
686 {
687 int i;
688 for (i = 0; i < msg->body_len; i++)
689 {
690 g_string_append_printf(str, "%.2hhX ", body[i]);
691 if ((i % 16) == 15)
692 g_string_append(str, "\r\n");
693 }
694 g_string_append(str, "\r\n");
695 }
572 } 696 }
573 } 697
574 698 g_string_append_printf(str, "%u ", msg->msnslp_footer.value);
575 g_free(body); 699 g_string_append(str, "\r\n");
576 700 }
577 return table; 701 else
578 } 702 {
703 if (body != NULL)
704 {
705 g_string_append_len(str, body, body_len);
706 g_string_append(str, "\r\n");
707 }
708 }
709
710 gaim_debug_info("msn", "Message %s:\n{%s}\n", info, str->str);
711
712 g_string_free(str, TRUE);
713 }