comparison libpurple/protocols/msn/msg.c @ 30694:33b4ae796648

Rename "attribute" to "header" in a bunch of places. The SLP protocol is fashioned after HTTP. Well, more accurately after SIP. And these are generally referred to as headers pretty much everywhere.
author Mark Doliner <mark@kingant.net>
date Mon, 08 Feb 2010 07:41:15 +0000
parents 9262c8f306a6
children a786d893df2b
comparison
equal deleted inserted replaced
30693:6376fc7a092e 30694:33b4ae796648
34 msg->type = type; 34 msg->type = type;
35 35
36 if (purple_debug_is_verbose()) 36 if (purple_debug_is_verbose())
37 purple_debug_info("msn", "message new (%p)(%d)\n", msg, type); 37 purple_debug_info("msn", "message new (%p)(%d)\n", msg, type);
38 38
39 msg->attr_table = g_hash_table_new_full(g_str_hash, g_str_equal, 39 msg->header_table = g_hash_table_new_full(g_str_hash, g_str_equal,
40 g_free, g_free); 40 g_free, g_free);
41 41
42 msn_message_ref(msg); 42 msn_message_ref(msg);
43 43
44 return msg; 44 return msg;
62 g_free(msg->remote_user); 62 g_free(msg->remote_user);
63 g_free(msg->body); 63 g_free(msg->body);
64 g_free(msg->content_type); 64 g_free(msg->content_type);
65 g_free(msg->charset); 65 g_free(msg->charset);
66 66
67 g_hash_table_destroy(msg->attr_table); 67 g_hash_table_destroy(msg->header_table);
68 g_list_free(msg->attr_list); 68 g_list_free(msg->header_list);
69 69
70 g_free(msg); 70 g_free(msg);
71 } 71 }
72 72
73 MsnMessage * 73 MsnMessage *
110 MsnMessage *msg; 110 MsnMessage *msg;
111 char *message_cr; 111 char *message_cr;
112 112
113 msg = msn_message_new(MSN_MSG_TEXT); 113 msg = msn_message_new(MSN_MSG_TEXT);
114 msg->retries = 1; 114 msg->retries = 1;
115 msn_message_set_attr(msg, "User-Agent", PACKAGE_NAME "/" VERSION); 115 msn_message_set_header(msg, "User-Agent", PACKAGE_NAME "/" VERSION);
116 msn_message_set_content_type(msg, "text/plain"); 116 msn_message_set_content_type(msg, "text/plain");
117 msn_message_set_charset(msg, "UTF-8"); 117 msn_message_set_charset(msg, "UTF-8");
118 msn_message_set_flag(msg, 'A'); 118 msn_message_set_flag(msg, 'A');
119 msn_message_set_attr(msg, "X-MMS-IM-Format", 119 msn_message_set_header(msg, "X-MMS-IM-Format",
120 "FN=Segoe%20UI; EF=; CO=0; CS=1;PF=0"); 120 "FN=Segoe%20UI; EF=; CO=0; CS=1;PF=0");
121 121
122 message_cr = purple_str_add_cr(message); 122 message_cr = purple_str_add_cr(message);
123 msn_message_set_bin_data(msg, message_cr, strlen(message_cr)); 123 msn_message_set_bin_data(msg, message_cr, strlen(message_cr));
124 g_free(message_cr); 124 g_free(message_cr);
131 { 131 {
132 MsnMessage *msg; 132 MsnMessage *msg;
133 133
134 msg = msn_message_new(MSN_MSG_SLP); 134 msg = msn_message_new(MSN_MSG_SLP);
135 135
136 msn_message_set_attr(msg, "User-Agent", NULL); 136 msn_message_set_header(msg, "User-Agent", NULL);
137 137
138 msg->msnslp_message = TRUE; 138 msg->msnslp_message = TRUE;
139 139
140 msn_message_set_flag(msg, 'D'); 140 msn_message_set_flag(msg, 'D');
141 msn_message_set_content_type(msg, "application/x-msnmsgrp2p"); 141 msn_message_set_content_type(msg, "application/x-msnmsgrp2p");
167 167
168 if (len < sizeof(header)) { 168 if (len < sizeof(header)) {
169 g_return_if_reached(); 169 g_return_if_reached();
170 } 170 }
171 171
172 /* Import the header. */ 172 /* Extract the binary SLP header */
173 memcpy(&header, tmp, sizeof(header)); 173 memcpy(&header, tmp, sizeof(header));
174 tmp += sizeof(header); 174 tmp += sizeof(header);
175 175
176 msg->msnslp_header.session_id = GUINT32_FROM_LE(header.session_id); 176 msg->msnslp_header.session_id = GUINT32_FROM_LE(header.session_id);
177 msg->msnslp_header.id = GUINT32_FROM_LE(header.id); 177 msg->msnslp_header.id = GUINT32_FROM_LE(header.id);
181 msg->msnslp_header.flags = GUINT32_FROM_LE(header.flags); 181 msg->msnslp_header.flags = GUINT32_FROM_LE(header.flags);
182 msg->msnslp_header.ack_id = GUINT32_FROM_LE(header.ack_id); 182 msg->msnslp_header.ack_id = GUINT32_FROM_LE(header.ack_id);
183 msg->msnslp_header.ack_sub_id = GUINT32_FROM_LE(header.ack_sub_id); 183 msg->msnslp_header.ack_sub_id = GUINT32_FROM_LE(header.ack_sub_id);
184 msg->msnslp_header.ack_size = GUINT64_FROM_LE(header.ack_size); 184 msg->msnslp_header.ack_size = GUINT64_FROM_LE(header.ack_size);
185 185
186 /* Import the body. */ 186 /* Extract the body */
187 body_len = len - (tmp - body); 187 body_len = len - (tmp - body);
188 /* msg->body_len = msg->msnslp_header.length; */ 188 /* msg->body_len = msg->msnslp_header.length; */
189 189
190 if (body_len > 0) { 190 if (body_len > 0) {
191 msg->body_len = len - (tmp - body); 191 msg->body_len = len - (tmp - body);
209 g_return_if_fail(payload != NULL); 209 g_return_if_fail(payload != NULL);
210 tmp_base = tmp = g_malloc(payload_len + 1); 210 tmp_base = tmp = g_malloc(payload_len + 1);
211 memcpy(tmp_base, payload, payload_len); 211 memcpy(tmp_base, payload, payload_len);
212 tmp_base[payload_len] = '\0'; 212 tmp_base[payload_len] = '\0';
213 213
214 /* Parse the attributes. */ 214 /* Find the end of the headers */
215 end = strstr(tmp, body_dem); 215 end = strstr(tmp, body_dem);
216 /* TODO? some clients use \r delimiters instead of \r\n, the official client 216 /* TODO? some clients use \r delimiters instead of \r\n, the official client
217 * doesn't send such messages, but does handle receiving them. We'll just 217 * doesn't send such messages, but does handle receiving them. We'll just
218 * avoid crashing for now */ 218 * avoid crashing for now */
219 if (end == NULL) { 219 if (end == NULL) {
220 g_free(tmp_base); 220 g_free(tmp_base);
221 g_return_if_reached(); 221 g_return_if_reached();
222 } 222 }
223 *end = '\0'; 223 *end = '\0';
224 224
225 /* Split the headers and parse each one */
225 elems = g_strsplit(tmp, line_dem, 0); 226 elems = g_strsplit(tmp, line_dem, 0);
226
227 for (cur = elems; *cur != NULL; cur++) 227 for (cur = elems; *cur != NULL; cur++)
228 { 228 {
229 const char *key, *value; 229 const char *key, *value;
230 230
231 /* If this line starts with whitespace, it's been folded from the 231 /* If this line starts with whitespace, it's been folded from the
238 /* The only one I care about is 'boundary' (which is folded from 238 /* The only one I care about is 'boundary' (which is folded from
239 the key 'Content-Type'), so only process that. */ 239 the key 'Content-Type'), so only process that. */
240 if (!strcmp(key, "boundary")) { 240 if (!strcmp(key, "boundary")) {
241 char *end = strchr(value, '\"'); 241 char *end = strchr(value, '\"');
242 *end = '\0'; 242 *end = '\0';
243 msn_message_set_attr(msg, key, value); 243 msn_message_set_header(msg, key, value);
244 } 244 }
245 245
246 g_strfreev(tokens); 246 g_strfreev(tokens);
247 continue; 247 continue;
248 } 248 }
276 276
277 msn_message_set_content_type(msg, value); 277 msn_message_set_content_type(msg, value);
278 } 278 }
279 else 279 else
280 { 280 {
281 msn_message_set_attr(msg, key, value); 281 msn_message_set_header(msg, key, value);
282 } 282 }
283 283
284 g_strfreev(tokens); 284 g_strfreev(tokens);
285 } 285 }
286
287 g_strfreev(elems); 286 g_strfreev(elems);
288 287
289 /* Proceed to the end of the "\r\n\r\n" */ 288 /* Proceed to the end of the "\r\n\r\n" */
290 tmp = end + strlen(body_dem); 289 tmp = end + strlen(body_dem);
291 290
304 g_return_if_reached(); 303 g_return_if_reached();
305 } 304 }
306 305
307 msg->msnslp_message = TRUE; 306 msg->msnslp_message = TRUE;
308 307
309 /* Import the header. */ 308 /* Extract the binary SLP header */
310 memcpy(&header, tmp, sizeof(header)); 309 memcpy(&header, tmp, sizeof(header));
311 tmp += sizeof(header); 310 tmp += sizeof(header);
312 311
313 msg->msnslp_header.session_id = GUINT32_FROM_LE(header.session_id); 312 msg->msnslp_header.session_id = GUINT32_FROM_LE(header.session_id);
314 msg->msnslp_header.id = GUINT32_FROM_LE(header.id); 313 msg->msnslp_header.id = GUINT32_FROM_LE(header.id);
320 msg->msnslp_header.ack_sub_id = GUINT32_FROM_LE(header.ack_sub_id); 319 msg->msnslp_header.ack_sub_id = GUINT32_FROM_LE(header.ack_sub_id);
321 msg->msnslp_header.ack_size = GUINT64_FROM_LE(header.ack_size); 320 msg->msnslp_header.ack_size = GUINT64_FROM_LE(header.ack_size);
322 321
323 body_len = payload_len - (tmp - tmp_base) - sizeof(footer); 322 body_len = payload_len - (tmp - tmp_base) - sizeof(footer);
324 323
325 /* Import the body. */ 324 /* Extract the body */
326 if (body_len > 0) { 325 if (body_len > 0) {
327 msg->body_len = body_len; 326 msg->body_len = body_len;
328 g_free(msg->body); 327 g_free(msg->body);
329 msg->body = g_malloc(msg->body_len + 1); 328 msg->body = g_malloc(msg->body_len + 1);
330 memcpy(msg->body, tmp, msg->body_len); 329 memcpy(msg->body, tmp, msg->body_len);
331 msg->body[msg->body_len] = '\0'; 330 msg->body[msg->body_len] = '\0';
332 tmp += body_len; 331 tmp += body_len;
333 } 332 }
334 333
335 /* Import the footer. */ 334 /* Extract the footer */
336 if (body_len >= 0) { 335 if (body_len >= 0) {
337 memcpy(&footer, tmp, sizeof(footer)); 336 memcpy(&footer, tmp, sizeof(footer));
338 tmp += sizeof(footer); 337 tmp += sizeof(footer);
339 msg->msnslp_footer.value = GUINT32_FROM_BE(footer.value); 338 msg->msnslp_footer.value = GUINT32_FROM_BE(footer.value);
340 } 339 }
346 g_free(msg->body); 345 g_free(msg->body);
347 msg->body = g_malloc(msg->body_len + 1); 346 msg->body = g_malloc(msg->body_len + 1);
348 memcpy(msg->body, tmp, msg->body_len); 347 memcpy(msg->body, tmp, msg->body_len);
349 msg->body[msg->body_len] = '\0'; 348 msg->body[msg->body_len] = '\0';
350 } 349 }
351 350
352 if ((!content_type || !strcmp(content_type, "text/plain")) 351 if ((!content_type || !strcmp(content_type, "text/plain"))
353 && msg->charset == NULL) { 352 && msg->charset == NULL) {
354 char *body = g_convert(msg->body, msg->body_len, "UTF-8", 353 char *body = g_convert(msg->body, msg->body_len, "UTF-8",
355 "ISO-8859-1", NULL, &msg->body_len, NULL); 354 "ISO-8859-1", NULL, &msg->body_len, NULL);
356 g_free(msg->body); 355 g_free(msg->body);
452 msg->content_type, msg->charset); 451 msg->content_type, msg->charset);
453 } 452 }
454 453
455 n += strlen(n); 454 n += strlen(n);
456 455
457 for (l = msg->attr_list; l != NULL; l = l->next) 456 for (l = msg->header_list; l != NULL; l = l->next)
458 { 457 {
459 const char *key; 458 const char *key;
460 const char *value; 459 const char *value;
461 460
462 key = l->data; 461 key = l->data;
463 value = msn_message_get_attr(msg, key); 462 value = msn_message_get_header_value(msg, key);
464 463
465 g_snprintf(n, end - n, "%s: %s\r\n", key, value); 464 g_snprintf(n, end - n, "%s: %s\r\n", key, value);
466 n += strlen(n); 465 n += strlen(n);
467 } 466 }
468 467
608 607
609 return msg->charset; 608 return msg->charset;
610 } 609 }
611 610
612 void 611 void
613 msn_message_set_attr(MsnMessage *msg, const char *attr, const char *value) 612 msn_message_set_header(MsnMessage *msg, const char *name, const char *value)
614 { 613 {
615 const char *temp; 614 const char *temp;
616 char *new_attr; 615 char *new_name;
617 616
618 g_return_if_fail(msg != NULL); 617 g_return_if_fail(msg != NULL);
619 g_return_if_fail(attr != NULL); 618 g_return_if_fail(name != NULL);
620 619
621 temp = msn_message_get_attr(msg, attr); 620 temp = msn_message_get_header_value(msg, name);
622 621
623 if (value == NULL) 622 if (value == NULL)
624 { 623 {
625 if (temp != NULL) 624 if (temp != NULL)
626 { 625 {
627 GList *l; 626 GList *l;
628 627
629 for (l = msg->attr_list; l != NULL; l = l->next) 628 for (l = msg->header_list; l != NULL; l = l->next)
630 { 629 {
631 if (!g_ascii_strcasecmp(l->data, attr)) 630 if (!g_ascii_strcasecmp(l->data, name))
632 { 631 {
633 msg->attr_list = g_list_remove(msg->attr_list, l->data); 632 msg->header_list = g_list_remove(msg->header_list, l->data);
634 633
635 break; 634 break;
636 } 635 }
637 } 636 }
638 637
639 g_hash_table_remove(msg->attr_table, attr); 638 g_hash_table_remove(msg->header_table, name);
640 } 639 }
641 640
642 return; 641 return;
643 } 642 }
644 643
645 new_attr = g_strdup(attr); 644 new_name = g_strdup(name);
646 645
647 g_hash_table_insert(msg->attr_table, new_attr, g_strdup(value)); 646 g_hash_table_insert(msg->header_table, new_name, g_strdup(value));
648 647
649 if (temp == NULL) 648 if (temp == NULL)
650 msg->attr_list = g_list_append(msg->attr_list, new_attr); 649 msg->header_list = g_list_append(msg->header_list, new_name);
651 } 650 }
652 651
653 const char * 652 const char *
654 msn_message_get_attr(const MsnMessage *msg, const char *attr) 653 msn_message_get_header_value(const MsnMessage *msg, const char *name)
655 { 654 {
656 g_return_val_if_fail(msg != NULL, NULL); 655 g_return_val_if_fail(msg != NULL, NULL);
657 g_return_val_if_fail(attr != NULL, NULL); 656 g_return_val_if_fail(name != NULL, NULL);
658 657
659 return g_hash_table_lookup(msg->attr_table, attr); 658 return g_hash_table_lookup(msg->header_table, name);
660 } 659 }
661 660
662 GHashTable * 661 GHashTable *
663 msn_message_get_hashtable_from_body(const MsnMessage *msg) 662 msn_message_get_hashtable_from_body(const MsnMessage *msg)
664 { 663 {
739 "MIME-Version: 1.0\r\n" 738 "MIME-Version: 1.0\r\n"
740 "Content-Type: %s; charset=%s\r\n", 739 "Content-Type: %s; charset=%s\r\n",
741 msg->content_type, msg->charset); 740 msg->content_type, msg->charset);
742 } 741 }
743 742
744 for (l = msg->attr_list; l; l = l->next) 743 for (l = msg->header_list; l; l = l->next)
745 { 744 {
746 char *key; 745 char *key;
747 const char *value; 746 const char *value;
748 747
749 key = l->data; 748 key = l->data;
750 value = msn_message_get_attr(msg, key); 749 value = msn_message_get_header_value(msg, key);
751 750
752 g_string_append_printf(str, "%s: %s\r\n", key, value); 751 g_string_append_printf(str, "%s: %s\r\n", key, value);
753 } 752 }
754 753
755 g_string_append(str, "\r\n"); 754 g_string_append(str, "\r\n");
838 { 837 {
839 return; 838 return;
840 } 839 }
841 840
842 #if 0 841 #if 0
843 if ((value = msn_message_get_attr(msg, "User-Agent")) != NULL) 842 if ((value = msn_message_get_header_value(msg, "User-Agent")) != NULL)
844 { 843 {
845 purple_debug_misc("msn", "User-Agent = '%s'\n", value); 844 purple_debug_misc("msn", "User-Agent = '%s'\n", value);
846 } 845 }
847 #endif 846 #endif
848 847
849 if ((value = msn_message_get_attr(msg, "X-MMS-IM-Format")) != NULL) 848 if ((value = msn_message_get_header_value(msg, "X-MMS-IM-Format")) != NULL)
850 { 849 {
851 char *pre, *post; 850 char *pre, *post;
852 851
853 msn_parse_format(value, &pre, &post); 852 msn_parse_format(value, &pre, &post);
854 853
912 char *passport; 911 char *passport;
913 912
914 gc = cmdproc->session->account->gc; 913 gc = cmdproc->session->account->gc;
915 passport = msg->remote_user; 914 passport = msg->remote_user;
916 915
917 if (msn_message_get_attr(msg, "TypingUser") == NULL) 916 if (msn_message_get_header_value(msg, "TypingUser") == NULL)
918 return; 917 return;
919 918
920 if (cmdproc->servconn->type == MSN_SERVCONN_SB) { 919 if (cmdproc->servconn->type == MSN_SERVCONN_SB) {
921 MsnSwitchBoard *swboard = cmdproc->data; 920 MsnSwitchBoard *swboard = cmdproc->data;
922 921