comparison libpurple/protocols/myspace/myspace.c @ 18890:00499df91ffe

Use cuddled if's etc. everywhere, to better match style of Pidgin/libpurple.
author Jeffrey Connelly <jaconnel@calpoly.edu>
date Sat, 11 Aug 2007 04:34:20 +0000
parents 644144f1a5c2
children 138e9be2f917
comparison
equal deleted inserted replaced
18889:a3a5b2e9079a 18890:00499df91ffe
178 /* round is part of C99, but sometimes is unavailable before then. 178 /* round is part of C99, but sometimes is unavailable before then.
179 * Based on http://forums.belution.com/en/cpp/000/050/13.shtml 179 * Based on http://forums.belution.com/en/cpp/000/050/13.shtml
180 */ 180 */
181 double round(double value) 181 double round(double value)
182 { 182 {
183 if (value < 0) 183 if (value < 0) {
184 return -(floor(-value + 0.5)); 184 return -(floor(-value + 0.5));
185 else 185 } else {
186 return floor( value + 0.5); 186 return floor( value + 0.5);
187 }
187 } 188 }
188 #endif 189 #endif
189 190
190 /** 191 /**
191 * Load the plugin. 192 * Load the plugin.
192 */ 193 */
193 gboolean 194 gboolean
194 msim_load(PurplePlugin *plugin) 195 msim_load(PurplePlugin *plugin)
195 { 196 {
196 /* If compiled to use RC4 from libpurple, check if it is really there. */ 197 /* If compiled to use RC4 from libpurple, check if it is really there. */
197 if (!purple_ciphers_find_cipher("rc4")) 198 if (!purple_ciphers_find_cipher("rc4")) {
198 {
199 purple_debug_error("msim", "rc4 not in libpurple, but it is required - not loading MySpaceIM plugin!\n"); 199 purple_debug_error("msim", "rc4 not in libpurple, but it is required - not loading MySpaceIM plugin!\n");
200 purple_notify_error(plugin, _("Missing Cipher"), 200 purple_notify_error(plugin, _("Missing Cipher"),
201 _("The RC4 cipher could not be found"), 201 _("The RC4 cipher could not be found"),
202 _("Upgrade " 202 _("Upgrade "
203 "to a libpurple with RC4 support (>= 2.0.1). MySpaceIM " 203 "to a libpurple with RC4 support (>= 2.0.1). MySpaceIM "
260 MsimSession *session; 260 MsimSession *session;
261 gchar *username, *zap_string, *zap_text; 261 gchar *username, *zap_string, *zap_text;
262 guint zap; 262 guint zap;
263 const gchar *zap_gerund[10]; 263 const gchar *zap_gerund[10];
264 264
265 if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) 265 if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) {
266 {
267 /* Only know about buddies for now. */ 266 /* Only know about buddies for now. */
268 return; 267 return;
269 } 268 }
270 269
271 zap_gerund[0] = _("Zapping"); 270 zap_gerund[0] = _("Zapping");
296 zap_text = g_strdup_printf("*** %s! ***", zap_gerund[zap]); 295 zap_text = g_strdup_printf("*** %s! ***", zap_gerund[zap]);
297 296
298 serv_got_im(session->gc, username, zap_text, 297 serv_got_im(session->gc, username, zap_text,
299 PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_SYSTEM, time(NULL)); 298 PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_SYSTEM, time(NULL));
300 299
301 if (!msim_send_bm(session, username, zap_string, MSIM_BM_ACTION)) 300 if (!msim_send_bm(session, username, zap_string, MSIM_BM_ACTION)) {
302 {
303 purple_debug_info("msim_send_zap", "msim_send_bm failed: zapping %s with %s", 301 purple_debug_info("msim_send_zap", "msim_send_bm failed: zapping %s with %s",
304 username, zap_string); 302 username, zap_string);
305 } 303 }
306 304
307 g_free(zap_string); 305 g_free(zap_string);
317 GList *menu, *zap_menu; 315 GList *menu, *zap_menu;
318 PurpleMenuAction *act; 316 PurpleMenuAction *act;
319 const gchar *zap_names[10]; 317 const gchar *zap_names[10];
320 guint i; 318 guint i;
321 319
322 if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) 320 if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) {
323 {
324 /* Only know about buddies for now. */ 321 /* Only know about buddies for now. */
325 return NULL; 322 return NULL;
326 } 323 }
327 324
328 /* Names from official client. */ 325 /* Names from official client. */
337 zap_names[8] = _("punk'd"); 334 zap_names[8] = _("punk'd");
338 zap_names[9] = _("raspberry"); 335 zap_names[9] = _("raspberry");
339 336
340 menu = zap_menu = NULL; 337 menu = zap_menu = NULL;
341 338
342 for (i = 0; i < sizeof(zap_names) / sizeof(zap_names[0]); ++i) 339 for (i = 0; i < sizeof(zap_names) / sizeof(zap_names[0]); ++i) {
343 {
344 act = purple_menu_action_new(zap_names[i], PURPLE_CALLBACK(msim_send_zap), 340 act = purple_menu_action_new(zap_names[i], PURPLE_CALLBACK(msim_send_zap),
345 GUINT_TO_POINTER(i), NULL); 341 GUINT_TO_POINTER(i), NULL);
346 zap_menu = g_list_append(zap_menu, act); 342 zap_menu = g_list_append(zap_menu, act);
347 } 343 }
348 344
451 447
452 g_return_val_if_fail(MSIM_SESSION_VALID(session), -1); 448 g_return_val_if_fail(MSIM_SESSION_VALID(session), -1);
453 449
454 /* Loop until all data is sent, or a failure occurs. */ 450 /* Loop until all data is sent, or a failure occurs. */
455 total_bytes_sent = 0; 451 total_bytes_sent = 0;
456 do 452 do {
457 {
458 int bytes_sent; 453 int bytes_sent;
459 454
460 bytes_sent = send(session->fd, buf + total_bytes_sent, 455 bytes_sent = send(session->fd, buf + total_bytes_sent,
461 total_bytes - total_bytes_sent, 0); 456 total_bytes - total_bytes_sent, 0);
462 457
463 if (bytes_sent < 0) 458 if (bytes_sent < 0) {
464 {
465 purple_debug_info("msim", "msim_send_raw(%s): send() failed: %s\n", 459 purple_debug_info("msim", "msim_send_raw(%s): send() failed: %s\n",
466 buf, g_strerror(errno)); 460 buf, g_strerror(errno));
467 return total_bytes_sent; 461 return total_bytes_sent;
468 } 462 }
469 total_bytes_sent += bytes_sent; 463 total_bytes_sent += bytes_sent;
494 gc = purple_account_get_connection(acct); 488 gc = purple_account_get_connection(acct);
495 gc->proto_data = msim_session_new(acct); 489 gc->proto_data = msim_session_new(acct);
496 gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_URLDESC; 490 gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_URLDESC;
497 491
498 /* Passwords are limited in length. */ 492 /* Passwords are limited in length. */
499 if (strlen(acct->password) > MSIM_MAX_PASSWORD_LENGTH) 493 if (strlen(acct->password) > MSIM_MAX_PASSWORD_LENGTH) {
500 {
501 gchar *str; 494 gchar *str;
502 495
503 str = g_strdup_printf( 496 str = g_strdup_printf(
504 _("Sorry, passwords over %d characters in length (yours is " 497 _("Sorry, passwords over %d characters in length (yours is "
505 "%d) are not supported by the MySpaceIM plugin."), 498 "%d) are not supported by the MySpaceIM plugin."),
526 * """Note that this function name can be misleading--although it is called 519 * """Note that this function name can be misleading--although it is called
527 * "proxy connect," it is used for establishing any outgoing TCP connection, 520 * "proxy connect," it is used for establishing any outgoing TCP connection,
528 * whether through a proxy or not.""" */ 521 * whether through a proxy or not.""" */
529 522
530 /* Calls msim_connect_cb when connected. */ 523 /* Calls msim_connect_cb when connected. */
531 if (purple_proxy_connect(gc, acct, host, port, msim_connect_cb, gc) == NULL) 524 if (!purple_proxy_connect(gc, acct, host, port, msim_connect_cb, gc)) {
532 {
533 /* TODO: try other ports if in auto mode, then save 525 /* TODO: try other ports if in auto mode, then save
534 * working port and try that first next time. */ 526 * working port and try that first next time. */
535 purple_connection_error(gc, _("Couldn't create socket")); 527 purple_connection_error(gc, _("Couldn't create socket"));
536 return; 528 return;
537 } 529 }
565 557
566 purple_connection_update_progress(session->gc, _("Reading challenge"), 1, 4); 558 purple_connection_update_progress(session->gc, _("Reading challenge"), 1, 4);
567 559
568 purple_debug_info("msim", "nc is %d bytes, decoded\n", nc_len); 560 purple_debug_info("msim", "nc is %d bytes, decoded\n", nc_len);
569 561
570 if (nc_len != MSIM_AUTH_CHALLENGE_LENGTH) 562 if (nc_len != MSIM_AUTH_CHALLENGE_LENGTH) {
571 {
572 purple_debug_info("msim", "bad nc length: %x != 0x%x\n", nc_len, MSIM_AUTH_CHALLENGE_LENGTH); 563 purple_debug_info("msim", "bad nc length: %x != 0x%x\n", nc_len, MSIM_AUTH_CHALLENGE_LENGTH);
573 purple_connection_error(session->gc, _("Unexpected challenge length from server")); 564 purple_connection_error(session->gc, _("Unexpected challenge length from server"));
574 return FALSE; 565 return FALSE;
575 } 566 }
576 567
645 &conv_bytes_read, &conv_bytes_written, &conv_error); 636 &conv_bytes_read, &conv_bytes_written, &conv_error);
646 g_free(password_ascii_lc); 637 g_free(password_ascii_lc);
647 638
648 g_return_val_if_fail(conv_bytes_read == strlen(password), NULL); 639 g_return_val_if_fail(conv_bytes_read == strlen(password), NULL);
649 640
650 if (conv_error != NULL) 641 if (conv_error != NULL) {
651 {
652 purple_debug_error("msim", 642 purple_debug_error("msim",
653 "g_convert password UTF8->UTF16LE failed: %s", 643 "g_convert password UTF8->UTF16LE failed: %s",
654 conv_error->message); 644 conv_error->message);
655 g_error_free(conv_error); 645 g_error_free(conv_error);
656 return NULL; 646 return NULL;
675 purple_cipher_context_append(key_context, (guchar *)(nonce + NONCE_SIZE), NONCE_SIZE); 665 purple_cipher_context_append(key_context, (guchar *)(nonce + NONCE_SIZE), NONCE_SIZE);
676 purple_cipher_context_digest(key_context, sizeof(key), key, NULL); 666 purple_cipher_context_digest(key_context, sizeof(key), key, NULL);
677 667
678 #ifdef MSIM_DEBUG_LOGIN_CHALLENGE 668 #ifdef MSIM_DEBUG_LOGIN_CHALLENGE
679 purple_debug_info("msim", "key = "); 669 purple_debug_info("msim", "key = ");
680 for (i = 0; i < sizeof(key); i++) 670 for (i = 0; i < sizeof(key); i++) {
681 {
682 purple_debug_info("msim", "%.2x ", key[i]); 671 purple_debug_info("msim", "%.2x ", key[i]);
683 } 672 }
684 purple_debug_info("msim", "\n"); 673 purple_debug_info("msim", "\n");
685 #endif 674 #endif
686 675
751 740
752 g_return_val_if_fail(MSIM_SESSION_VALID(session), -1); 741 g_return_val_if_fail(MSIM_SESSION_VALID(session), -1);
753 742
754 message_msim = html_to_msim_markup(session, message); 743 message_msim = html_to_msim_markup(session, message);
755 744
756 if (msim_send_bm(session, who, message_msim, MSIM_BM_INSTANT)) 745 if (msim_send_bm(session, who, message_msim, MSIM_BM_INSTANT)) {
757 {
758 /* Return 1 to have Purple show this IM as being sent, 0 to not. I always 746 /* Return 1 to have Purple show this IM as being sent, 0 to not. I always
759 * return 1 even if the message could not be sent, since I don't know if 747 * return 1 even if the message could not be sent, since I don't know if
760 * it has failed yet--because the IM is only sent after the userid is 748 * it has failed yet--because the IM is only sent after the userid is
761 * retrieved from the server (which happens after this function returns). 749 * retrieved from the server (which happens after this function returns).
762 */ 750 */
848 guint size, this_point, base; 836 guint size, this_point, base;
849 gdouble scale; 837 gdouble scale;
850 838
851 base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE); 839 base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
852 840
853 for (size = 0; size < sizeof(_font_scale) / sizeof(_font_scale[0]); ++size) 841 for (size = 0;
854 { 842 size < sizeof(_font_scale) / sizeof(_font_scale[0]);
843 ++size) {
855 scale = _font_scale[CLAMP(size, 1, MAX_FONT_SIZE) - 1]; 844 scale = _font_scale[CLAMP(size, 1, MAX_FONT_SIZE) - 1];
856 this_point = (guint)round(scale * base); 845 this_point = (guint)round(scale * base);
857 846
858 if (this_point >= point) 847 if (this_point >= point) {
859 {
860 purple_debug_info("msim", "msim_point_to_purple_size: %d pt -> size=%d\n", 848 purple_debug_info("msim", "msim_point_to_purple_size: %d pt -> size=%d\n",
861 point, size); 849 point, size);
862 return size; 850 return size;
863 } 851 }
864 } 852 }
922 910
923 face = xmlnode_get_attrib(root, "f"); 911 face = xmlnode_get_attrib(root, "f");
924 height_str = xmlnode_get_attrib(root, "h"); 912 height_str = xmlnode_get_attrib(root, "h");
925 decor_str = xmlnode_get_attrib(root, "s"); 913 decor_str = xmlnode_get_attrib(root, "s");
926 914
927 if (height_str) 915 if (height_str) {
928 height = atol(height_str); 916 height = atol(height_str);
929 else 917 } else {
930 height = 12; 918 height = 12;
931 919 }
932 if (decor_str) 920
921 if (decor_str) {
933 decor = atol(decor_str); 922 decor = atol(decor_str);
934 else 923 } else {
935 decor = 0; 924 decor = 0;
925 }
936 926
937 gs_begin = g_string_new(""); 927 gs_begin = g_string_new("");
938 /* TODO: get font size working */ 928 /* TODO: get font size working */
939 if (height && !face) 929 if (height && !face) {
940 g_string_printf(gs_begin, "<font size='%d'>", 930 g_string_printf(gs_begin, "<font size='%d'>",
941 msim_point_to_purple_size(session, msim_height_to_point(session, height))); 931 msim_point_to_purple_size(session, msim_height_to_point(session, height)));
942 else if (height && face) 932 } else if (height && face) {
943 g_string_printf(gs_begin, "<font face='%s' size='%d'>", face, 933 g_string_printf(gs_begin, "<font face='%s' size='%d'>", face,
944 msim_point_to_purple_size(session, msim_height_to_point(session, height))); 934 msim_point_to_purple_size(session, msim_height_to_point(session, height)));
945 else 935 } else {
946 g_string_printf(gs_begin, "<font>"); 936 g_string_printf(gs_begin, "<font>");
937 }
947 938
948 /* No support for font-size CSS? */ 939 /* No support for font-size CSS? */
949 /* g_string_printf(gs_begin, "<span style='font-family: %s; font-size: %dpt'>", face, 940 /* g_string_printf(gs_begin, "<span style='font-family: %s; font-size: %dpt'>", face,
950 msim_height_to_point(height)); */ 941 msim_height_to_point(height)); */
951 942
952 gs_end = g_string_new("</font>"); 943 gs_end = g_string_new("</font>");
953 944
954 if (decor & MSIM_TEXT_BOLD) 945 if (decor & MSIM_TEXT_BOLD) {
955 {
956 g_string_append(gs_begin, "<b>"); 946 g_string_append(gs_begin, "<b>");
957 g_string_prepend(gs_end, "</b>"); 947 g_string_prepend(gs_end, "</b>");
958 } 948 }
959 949
960 if (decor & MSIM_TEXT_ITALIC) 950 if (decor & MSIM_TEXT_ITALIC) {
961 {
962 g_string_append(gs_begin, "<i>"); 951 g_string_append(gs_begin, "<i>");
963 g_string_append(gs_end, "</i>"); 952 g_string_append(gs_end, "</i>");
964 } 953 }
965 954
966 if (decor & MSIM_TEXT_UNDERLINE) 955 if (decor & MSIM_TEXT_UNDERLINE) {
967 {
968 g_string_append(gs_begin, "<u>"); 956 g_string_append(gs_begin, "<u>");
969 g_string_append(gs_end, "</u>"); 957 g_string_append(gs_end, "</u>");
970 } 958 }
971 959
972 960
983 static char * 971 static char *
984 msim_color_to_purple(const char *msim) 972 msim_color_to_purple(const char *msim)
985 { 973 {
986 guint red, green, blue; 974 guint red, green, blue;
987 975
988 if (!msim) 976 if (!msim) {
989 return g_strdup("black"); 977 return g_strdup("black");
990 978 }
991 if (sscanf(msim, "rgb(%d,%d,%d)", &red, &green, &blue) != 3) 979
992 { 980 if (sscanf(msim, "rgb(%d,%d,%d)", &red, &green, &blue) != 3) {
993 /* Color name. */ 981 /* Color name. */
994 return g_strdup(msim); 982 return g_strdup(msim);
995 } 983 }
996 /* TODO: rgba (alpha). */ 984 /* TODO: rgba (alpha). */
997 985
1015 { 1003 {
1016 const gchar *color; 1004 const gchar *color;
1017 gchar *purple_color; 1005 gchar *purple_color;
1018 1006
1019 color = xmlnode_get_attrib(root, "v"); 1007 color = xmlnode_get_attrib(root, "v");
1020 if (!color) 1008 if (!color) {
1021 {
1022 purple_debug_info("msim", "msim_markup_c_to_html: <c> tag w/o v attr"); 1009 purple_debug_info("msim", "msim_markup_c_to_html: <c> tag w/o v attr");
1023 *begin = g_strdup(""); 1010 *begin = g_strdup("");
1024 *end = g_strdup(""); 1011 *end = g_strdup("");
1025 /* TODO: log as unrecognized */ 1012 /* TODO: log as unrecognized */
1026 return; 1013 return;
1042 { 1029 {
1043 const gchar *color; 1030 const gchar *color;
1044 gchar *purple_color; 1031 gchar *purple_color;
1045 1032
1046 color = xmlnode_get_attrib(root, "v"); 1033 color = xmlnode_get_attrib(root, "v");
1047 if (!color) 1034 if (!color) {
1048 {
1049 *begin = g_strdup(""); 1035 *begin = g_strdup("");
1050 *end = g_strdup(""); 1036 *end = g_strdup("");
1051 purple_debug_info("msim", "msim_markup_b_to_html: <b> w/o v attr"); 1037 purple_debug_info("msim", "msim_markup_b_to_html: <b> w/o v attr");
1052 /* TODO: log as unrecognized. */ 1038 /* TODO: log as unrecognized. */
1053 return; 1039 return;
1069 { 1055 {
1070 const gchar *name; 1056 const gchar *name;
1071 guint i; 1057 guint i;
1072 1058
1073 name = xmlnode_get_attrib(root, "n"); 1059 name = xmlnode_get_attrib(root, "n");
1074 if (!name) 1060 if (!name) {
1075 {
1076 purple_debug_info("msim", "msim_markup_i_to_html: <i> w/o n"); 1061 purple_debug_info("msim", "msim_markup_i_to_html: <i> w/o n");
1077 *begin = g_strdup(""); 1062 *begin = g_strdup("");
1078 *end = g_strdup(""); 1063 *end = g_strdup("");
1079 /* TODO: log as unrecognized */ 1064 /* TODO: log as unrecognized */
1080 return; 1065 return;
1081 } 1066 }
1082 1067
1083 for (i = 0; emoticon_names[i] != NULL; ++i) 1068 for (i = 0; emoticon_names[i] != NULL; ++i) {
1084 { 1069 if (!strcmp(name, emoticon_names[i])) {
1085 if (!strcmp(name, emoticon_names[i]))
1086 {
1087 *begin = g_strdup(emoticon_symbols[i]); 1070 *begin = g_strdup(emoticon_symbols[i]);
1088 *end = g_strdup(""); 1071 *end = g_strdup("");
1089 return; 1072 return;
1090 } 1073 }
1091 } 1074 }
1097 /** Convert an individual msim markup tag to HTML. */ 1080 /** Convert an individual msim markup tag to HTML. */
1098 static void 1081 static void
1099 msim_markup_tag_to_html(MsimSession *session, xmlnode *root, gchar **begin, 1082 msim_markup_tag_to_html(MsimSession *session, xmlnode *root, gchar **begin,
1100 gchar **end) 1083 gchar **end)
1101 { 1084 {
1102 if (!strcmp(root->name, "f")) 1085 if (!strcmp(root->name, "f")) {
1103 {
1104 msim_markup_f_to_html(session, root, begin, end); 1086 msim_markup_f_to_html(session, root, begin, end);
1105 } else if (!strcmp(root->name, "p")) { 1087 } else if (!strcmp(root->name, "p")) {
1106 msim_markup_p_to_html(session, root, begin, end); 1088 msim_markup_p_to_html(session, root, begin, end);
1107 } else if (!strcmp(root->name, "c")) { 1089 } else if (!strcmp(root->name, "c")) {
1108 msim_markup_c_to_html(session, root, begin, end); 1090 msim_markup_c_to_html(session, root, begin, end);
1126 { 1108 {
1127 /* TODO: Coalesce nested tags into one <f> tag! 1109 /* TODO: Coalesce nested tags into one <f> tag!
1128 * Currently, the 's' value will be overwritten when b/i/u is nested 1110 * Currently, the 's' value will be overwritten when b/i/u is nested
1129 * within another one, and only the inner-most formatting will be 1111 * within another one, and only the inner-most formatting will be
1130 * applied to the text. */ 1112 * applied to the text. */
1131 if (!strcmp(root->name, "root")) 1113 if (!strcmp(root->name, "root")) {
1132 {
1133 *begin = g_strdup(""); 1114 *begin = g_strdup("");
1134 *end = g_strdup(""); 1115 *end = g_strdup("");
1135 } else if (!strcmp(root->name, "b")) { 1116 } else if (!strcmp(root->name, "b")) {
1136 *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_BOLD); 1117 *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_BOLD);
1137 *end = g_strdup("</f>"); 1118 *end = g_strdup("</f>");
1183 { 1164 {
1184 xmlnode *node; 1165 xmlnode *node;
1185 gchar *begin, *inner, *end; 1166 gchar *begin, *inner, *end;
1186 GString *final; 1167 GString *final;
1187 1168
1188 if (!root || !root->name) 1169 if (!root || !root->name) {
1189 return g_strdup(""); 1170 return g_strdup("");
1171 }
1190 1172
1191 purple_debug_info("msim", "msim_convert_xmlnode: got root=%s\n", 1173 purple_debug_info("msim", "msim_convert_xmlnode: got root=%s\n",
1192 root->name); 1174 root->name);
1193 1175
1194 begin = inner = end = NULL; 1176 begin = inner = end = NULL;
1198 f(session, root, &begin, &end); 1180 f(session, root, &begin, &end);
1199 1181
1200 g_string_append(final, begin); 1182 g_string_append(final, begin);
1201 1183
1202 /* Loop over all child nodes. */ 1184 /* Loop over all child nodes. */
1203 for (node = root->child; node != NULL; node = node->next) 1185 for (node = root->child; node != NULL; node = node->next) {
1204 { 1186 switch (node->type) {
1205 switch (node->type)
1206 {
1207 case XMLNODE_TYPE_ATTRIB: 1187 case XMLNODE_TYPE_ATTRIB:
1208 /* Attributes handled above. */ 1188 /* Attributes handled above. */
1209 break; 1189 break;
1210 1190
1211 case XMLNODE_TYPE_TAG: 1191 case XMLNODE_TYPE_TAG:
1231 purple_debug_info("msim", 1211 purple_debug_info("msim",
1232 "msim_convert_xmlnode: strange node\n"); 1212 "msim_convert_xmlnode: strange node\n");
1233 inner = g_strdup(""); 1213 inner = g_strdup("");
1234 } 1214 }
1235 1215
1236 if (inner) 1216 if (inner) {
1237 g_string_append(final, inner); 1217 g_string_append(final, inner);
1218 }
1238 } 1219 }
1239 1220
1240 /* TODO: Note that msim counts each piece of text enclosed by <f> as 1221 /* TODO: Note that msim counts each piece of text enclosed by <f> as
1241 * a paragraph and will display each on its own line. You actually have 1222 * a paragraph and will display each on its own line. You actually have
1242 * to _nest_ <f> tags to intersperse different text in one paragraph! 1223 * to _nest_ <f> tags to intersperse different text in one paragraph!
1262 /* Enclose text in one root tag, to try to make it valid XML for parsing. */ 1243 /* Enclose text in one root tag, to try to make it valid XML for parsing. */
1263 enclosed_raw = g_strconcat("<root>", raw, "</root>", NULL); 1244 enclosed_raw = g_strconcat("<root>", raw, "</root>", NULL);
1264 1245
1265 root = xmlnode_from_str(enclosed_raw, -1); 1246 root = xmlnode_from_str(enclosed_raw, -1);
1266 1247
1267 if (!root) 1248 if (!root) {
1268 {
1269 purple_debug_info("msim", "msim_markup_to_html: couldn't parse " 1249 purple_debug_info("msim", "msim_markup_to_html: couldn't parse "
1270 "%s as XML, returning raw: %s\n", enclosed_raw, raw); 1250 "%s as XML, returning raw: %s\n", enclosed_raw, raw);
1271 /* TODO: msim_unrecognized */ 1251 /* TODO: msim_unrecognized */
1272 g_free(enclosed_raw); 1252 g_free(enclosed_raw);
1273 return g_strdup(raw); 1253 return g_strdup(raw);
1296 guint i; 1276 guint i;
1297 1277
1298 old = before; 1278 old = before;
1299 new = NULL; 1279 new = NULL;
1300 1280
1301 for (i = 0; emoticon_symbols[i] != NULL; ++i) 1281 for (i = 0; emoticon_symbols[i] != NULL; ++i) {
1302 {
1303
1304 replacement = g_strdup_printf("<i n=\"%s\"/>", emoticon_names[i]); 1282 replacement = g_strdup_printf("<i n=\"%s\"/>", emoticon_names[i]);
1305 1283
1306 purple_debug_info("msim", "msim_convert_smileys_to_markup: %s->%s\n", 1284 purple_debug_info("msim", "msim_convert_smileys_to_markup: %s->%s\n",
1307 emoticon_symbols[i] ? emoticon_symbols[i] : "(NULL)", 1285 emoticon_symbols[i] ? emoticon_symbols[i] : "(NULL)",
1308 replacement ? replacement : "(NULL)"); 1286 replacement ? replacement : "(NULL)");
1337 gchar *markup; 1315 gchar *markup;
1338 1316
1339 markup = msim_convert_xml(session, raw, 1317 markup = msim_convert_xml(session, raw,
1340 (MSIM_XMLNODE_CONVERT)(html_tag_to_msim_markup)); 1318 (MSIM_XMLNODE_CONVERT)(html_tag_to_msim_markup));
1341 1319
1342 if (purple_account_get_bool(session->account, "emoticons", TRUE)) 1320 if (purple_account_get_bool(session->account, "emoticons", TRUE)) {
1343 {
1344 /* Frees markup and allocates a new one. */ 1321 /* Frees markup and allocates a new one. */
1345 markup = msim_convert_smileys_to_markup(markup); 1322 markup = msim_convert_smileys_to_markup(markup);
1346 } 1323 }
1347 1324
1348 return markup; 1325 return markup;
1362 g_return_val_if_fail(username != NULL, FALSE); 1339 g_return_val_if_fail(username != NULL, FALSE);
1363 g_return_val_if_fail(cv != NULL, FALSE); 1340 g_return_val_if_fail(cv != NULL, FALSE);
1364 1341
1365 buddy = purple_find_buddy(session->account, username); 1342 buddy = purple_find_buddy(session->account, username);
1366 1343
1367 if (buddy) 1344 if (buddy) {
1368 {
1369 purple_blist_node_set_int(&buddy->node, "client_cv", atol(cv)); 1345 purple_blist_node_set_int(&buddy->node, "client_cv", atol(cv));
1370 ret = TRUE; 1346 ret = TRUE;
1371 } else { 1347 } else {
1372 ret = FALSE; 1348 ret = FALSE;
1373 } 1349 }
1386 1362
1387 bm = msim_msg_get_integer(msg, "bm"); 1363 bm = msim_msg_get_integer(msg, "bm");
1388 1364
1389 msim_incoming_bm_record_cv(session, msg); 1365 msim_incoming_bm_record_cv(session, msg);
1390 1366
1391 switch (bm) 1367 switch (bm) {
1392 {
1393 case MSIM_BM_STATUS: 1368 case MSIM_BM_STATUS:
1394 return msim_incoming_status(session, msg); 1369 return msim_incoming_status(session, msg);
1395 case MSIM_BM_INSTANT: 1370 case MSIM_BM_INSTANT:
1396 return msim_incoming_im(session, msg); 1371 return msim_incoming_im(session, msg);
1397 case MSIM_BM_ACTION: 1372 case MSIM_BM_ACTION:
1463 * by Alexandr Shutko, who maintains OSCAR protocol documentation). */ 1438 * by Alexandr Shutko, who maintains OSCAR protocol documentation). */
1464 1439
1465 purple_debug_info("msim", "Unrecognized data on account for %s\n", 1440 purple_debug_info("msim", "Unrecognized data on account for %s\n",
1466 session->account->username ? session->account->username 1441 session->account->username ? session->account->username
1467 : "(NULL)"); 1442 : "(NULL)");
1468 if (note) 1443 if (note) {
1469 {
1470 purple_debug_info("msim", "(Note: %s)\n", note); 1444 purple_debug_info("msim", "(Note: %s)\n", note);
1471 } 1445 }
1472 1446
1473 if (msg) 1447 if (msg) {
1474 {
1475 msim_msg_dump("Unrecognized message dump: %s\n", msg); 1448 msim_msg_dump("Unrecognized message dump: %s\n", msg);
1476 } 1449 }
1477 } 1450 }
1478 1451
1479 /** Process an incoming zap. */ 1452 /** Process an incoming zap. */
1542 g_return_val_if_fail(username != NULL, FALSE); 1515 g_return_val_if_fail(username != NULL, FALSE);
1543 1516
1544 purple_debug_info("msim", "msim_incoming_action: action <%s> from <%d>\n", 1517 purple_debug_info("msim", "msim_incoming_action: action <%s> from <%d>\n",
1545 msg_text, username); 1518 msg_text, username);
1546 1519
1547 if (strcmp(msg_text, "%typing%") == 0) 1520 if (strcmp(msg_text, "%typing%") == 0) {
1548 {
1549 /* TODO: find out if msim repeatedly sends typing messages, so we can 1521 /* TODO: find out if msim repeatedly sends typing messages, so we can
1550 * give it a timeout. Right now, there does seem to be an inordinately 1522 * give it a timeout. Right now, there does seem to be an inordinately
1551 * amount of time between typing stopped-typing notifications. */ 1523 * amount of time between typing stopped-typing notifications. */
1552 serv_got_typing(session->gc, username, 0, PURPLE_TYPING); 1524 serv_got_typing(session->gc, username, 0, PURPLE_TYPING);
1553 rc = TRUE; 1525 rc = TRUE;
1615 g_return_val_if_fail(buddy != NULL, FALSE); 1587 g_return_val_if_fail(buddy != NULL, FALSE);
1616 1588
1617 purple_blist_node_remove_setting(&buddy->node, "client"); 1589 purple_blist_node_remove_setting(&buddy->node, "client");
1618 purple_blist_node_set_string(&buddy->node, "client", client_info); 1590 purple_blist_node_set_string(&buddy->node, "client", client_info);
1619 1591
1620
1621 g_free(username); 1592 g_free(username);
1622 /* Do not free client_info - the blist now owns it. */ 1593 /* Do not free client_info - the blist now owns it. */
1623 1594
1624 return TRUE; 1595 return TRUE;
1625 } 1596 }
1666 1637
1667 session = (MsimSession *)gc->proto_data; 1638 session = (MsimSession *)gc->proto_data;
1668 1639
1669 g_return_val_if_fail(MSIM_SESSION_VALID(session), 0); 1640 g_return_val_if_fail(MSIM_SESSION_VALID(session), 0);
1670 1641
1671 switch (state) 1642 switch (state) {
1672 {
1673 case PURPLE_TYPING: 1643 case PURPLE_TYPING:
1674 typing_str = "%typing%"; 1644 typing_str = "%typing%";
1675 break; 1645 break;
1676 1646
1677 case PURPLE_TYPED: 1647 case PURPLE_TYPED:
1705 orthogonality. */ 1675 orthogonality. */
1706 msg = (MsimMessage *)data; 1676 msg = (MsimMessage *)data;
1707 g_return_if_fail(msg != NULL); 1677 g_return_if_fail(msg != NULL);
1708 1678
1709 user = msim_msg_get_string(msg, "user"); 1679 user = msim_msg_get_string(msg, "user");
1710 if (!user) 1680 if (!user) {
1711 {
1712 purple_debug_info("msim", "msim_get_info_cb: no 'user' in msg"); 1681 purple_debug_info("msim", "msim_get_info_cb: no 'user' in msg");
1713 return; 1682 return;
1714 } 1683 }
1715 1684
1716 msim_msg_free(msg); 1685 msim_msg_free(msg);
1750 purple_notify_user_info_add_pair(user_info, _("Location"), 1719 purple_notify_user_info_add_pair(user_info, _("Location"),
1751 g_strdup(str)); 1720 g_strdup(str));
1752 1721
1753 /* Other information */ 1722 /* Other information */
1754 1723
1755 if (buddy) 1724 if (buddy) {
1756 {
1757 /* Headline comes from buddy status messages */ 1725 /* Headline comes from buddy status messages */
1758 str = purple_blist_node_get_string(&buddy->node, "Headline"); 1726 str = purple_blist_node_get_string(&buddy->node, "Headline");
1759 if (str) 1727 if (str)
1760 purple_notify_user_info_add_pair(user_info, "Headline", str); 1728 purple_notify_user_info_add_pair(user_info, "Headline", str);
1761 } 1729 }
1762 1730
1763 1731
1764 str = g_hash_table_lookup(body, "BandName"); 1732 str = g_hash_table_lookup(body, "BandName");
1765 str2 = g_hash_table_lookup(body, "SongName"); 1733 str2 = g_hash_table_lookup(body, "SongName");
1766 if (str || str2) 1734 if (str || str2) {
1767 {
1768 purple_notify_user_info_add_pair(user_info, _("Song"), 1735 purple_notify_user_info_add_pair(user_info, _("Song"),
1769 g_strdup_printf("%s - %s", 1736 g_strdup_printf("%s - %s",
1770 str ? str : "Unknown Artist", 1737 str ? str : "Unknown Artist",
1771 str2 ? str2 : "Unknown Song")); 1738 str2 ? str2 : "Unknown Song"));
1772 } 1739 }
1773 1740
1774 1741
1775 /* Total friends only available if looked up by uid, not username. */ 1742 /* Total friends only available if looked up by uid, not username. */
1776 str = g_hash_table_lookup(body, "TotalFriends"); 1743 str = g_hash_table_lookup(body, "TotalFriends");
1777 if (str) 1744 if (str) {
1778 purple_notify_user_info_add_pair(user_info, _("Total Friends"), 1745 purple_notify_user_info_add_pair(user_info, _("Total Friends"),
1779 g_strdup(str)); 1746 g_strdup(str));
1780 1747 }
1781 if (buddy) 1748
1782 { 1749 if (buddy) {
1783 gint cv; 1750 gint cv;
1784 1751
1785 str = purple_blist_node_get_string(&buddy->node, "client"); 1752 str = purple_blist_node_get_string(&buddy->node, "client");
1786 cv = purple_blist_node_get_int(&buddy->node, "client_cv"); 1753 cv = purple_blist_node_get_int(&buddy->node, "client_cv");
1787 1754
1788 if (str) 1755 if (str) {
1789 {
1790 purple_notify_user_info_add_pair(user_info, _("Client Version"), 1756 purple_notify_user_info_add_pair(user_info, _("Client Version"),
1791 g_strdup_printf("%s (build %d)", str, cv)); 1757 g_strdup_printf("%s (build %d)", str, cv));
1792 } 1758 }
1793 } 1759 }
1794 1760
1817 1783
1818 g_return_if_fail(MSIM_SESSION_VALID(session)); 1784 g_return_if_fail(MSIM_SESSION_VALID(session));
1819 1785
1820 /* Obtain uid of buddy. */ 1786 /* Obtain uid of buddy. */
1821 buddy = purple_find_buddy(session->account, user); 1787 buddy = purple_find_buddy(session->account, user);
1822 if (buddy) 1788 if (buddy) {
1823 {
1824 uid = purple_blist_node_get_int(&buddy->node, "UserID"); 1789 uid = purple_blist_node_get_int(&buddy->node, "UserID");
1825 if (!uid) 1790 if (!uid) {
1826 {
1827 PurpleNotifyUserInfo *user_info; 1791 PurpleNotifyUserInfo *user_info;
1828 1792
1829 user_info = purple_notify_user_info_new(); 1793 user_info = purple_notify_user_info_new();
1830 purple_notify_user_info_add_pair(user_info, NULL, 1794 purple_notify_user_info_add_pair(user_info, NULL,
1831 _("This buddy appears to not have a userid stored in the buddy list, can't look up. Is the user really on the buddy list?")); 1795 _("This buddy appears to not have a userid stored in the buddy list, can't look up. Is the user really on the buddy list?"));
1835 return; 1799 return;
1836 } 1800 }
1837 1801
1838 user_to_lookup = g_strdup_printf("%d", uid); 1802 user_to_lookup = g_strdup_printf("%d", uid);
1839 } else { 1803 } else {
1840
1841 /* Looking up buddy not on blist. Lookup by whatever user entered. */ 1804 /* Looking up buddy not on blist. Lookup by whatever user entered. */
1842 user_to_lookup = g_strdup(user); 1805 user_to_lookup = g_strdup(user);
1843 } 1806 }
1844 1807
1845 /* Pass the username to msim_get_info_cb(), because since we lookup 1808 /* Pass the username to msim_get_info_cb(), because since we lookup
1869 1832
1870 g_return_if_fail(MSIM_SESSION_VALID(session)); 1833 g_return_if_fail(MSIM_SESSION_VALID(session));
1871 1834
1872 type = purple_status_get_type(status); 1835 type = purple_status_get_type(status);
1873 1836
1874 switch (purple_status_type_get_primitive(type)) 1837 switch (purple_status_type_get_primitive(type)) {
1875 {
1876 case PURPLE_STATUS_AVAILABLE: 1838 case PURPLE_STATUS_AVAILABLE:
1877 purple_debug_info("msim", "msim_set_status: available (%d->%d)\n", PURPLE_STATUS_AVAILABLE, 1839 purple_debug_info("msim", "msim_set_status: available (%d->%d)\n", PURPLE_STATUS_AVAILABLE,
1878 MSIM_STATUS_CODE_ONLINE); 1840 MSIM_STATUS_CODE_ONLINE);
1879 status_code = MSIM_STATUS_CODE_ONLINE; 1841 status_code = MSIM_STATUS_CODE_ONLINE;
1880 break; 1842 break;
1898 break; 1860 break;
1899 } 1861 }
1900 1862
1901 statstring = purple_status_get_attr_string(status, "message"); 1863 statstring = purple_status_get_attr_string(status, "message");
1902 1864
1903 if (!statstring) 1865 if (!statstring) {
1904 statstring = g_strdup(""); 1866 statstring = g_strdup("");
1867 }
1905 1868
1906 msim_set_status_code(session, status_code, g_strdup(statstring)); 1869 msim_set_status_code(session, status_code, g_strdup(statstring));
1907 } 1870 }
1908 1871
1909 /** Go idle. */ 1872 /** Go idle. */
1916 1879
1917 session = (MsimSession *)gc->proto_data; 1880 session = (MsimSession *)gc->proto_data;
1918 1881
1919 g_return_if_fail(MSIM_SESSION_VALID(session)); 1882 g_return_if_fail(MSIM_SESSION_VALID(session));
1920 1883
1921 if (time == 0) 1884 if (time == 0) {
1922 {
1923 /* Going back from idle. In msim, idle is mutually exclusive 1885 /* Going back from idle. In msim, idle is mutually exclusive
1924 * from the other states (you can only be away or idle, but not 1886 * from the other states (you can only be away or idle, but not
1925 * both, for example), so by going non-idle I go online. 1887 * both, for example), so by going non-idle I go online.
1926 */ 1888 */
1927 /* TODO: find out how to keep old status string? */ 1889 /* TODO: find out how to keep old status string? */
2116 msim_preprocess_incoming(MsimSession *session, MsimMessage *msg) 2078 msim_preprocess_incoming(MsimSession *session, MsimMessage *msg)
2117 { 2079 {
2118 g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); 2080 g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
2119 g_return_val_if_fail(msg != NULL, FALSE); 2081 g_return_val_if_fail(msg != NULL, FALSE);
2120 2082
2121 if (msim_msg_get(msg, "bm") && msim_msg_get(msg, "f")) 2083 if (msim_msg_get(msg, "bm") && msim_msg_get(msg, "f")) {
2122 {
2123 guint uid; 2084 guint uid;
2124 const gchar *username; 2085 const gchar *username;
2125 2086
2126 /* 'f' = userid message is from, in buddy messages */ 2087 /* 'f' = userid message is from, in buddy messages */
2127 uid = msim_msg_get_integer(msg, "f"); 2088 uid = msim_msg_get_integer(msg, "f");
2132 username = msim_uid2username_from_blist(session, uid); 2093 username = msim_uid2username_from_blist(session, uid);
2133 #else 2094 #else
2134 username = NULL; 2095 username = NULL;
2135 #endif 2096 #endif
2136 2097
2137 if (username) 2098 if (username) {
2138 {
2139 /* Know username already, use it. */ 2099 /* Know username already, use it. */
2140 purple_debug_info("msim", "msim_preprocess_incoming: tagging with _username=%s\n", 2100 purple_debug_info("msim", "msim_preprocess_incoming: tagging with _username=%s\n",
2141 username); 2101 username);
2142 msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, g_strdup(username)); 2102 msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, g_strdup(username));
2143 return msim_process(session, msg); 2103 return msim_process(session, msg);
2174 2134
2175 g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); 2135 g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
2176 2136
2177 delta = time(NULL) - session->last_comm; 2137 delta = time(NULL) - session->last_comm;
2178 //purple_debug_info("msim", "msim_check_alive: delta=%d\n", delta); 2138 //purple_debug_info("msim", "msim_check_alive: delta=%d\n", delta);
2179 if (delta >= MSIM_KEEPALIVE_INTERVAL) 2139 if (delta >= MSIM_KEEPALIVE_INTERVAL) {
2180 {
2181 errmsg = g_strdup_printf(_("Connection to server lost (no data received within %d seconds)"), (int)delta); 2140 errmsg = g_strdup_printf(_("Connection to server lost (no data received within %d seconds)"), (int)delta);
2182 2141
2183 purple_debug_info("msim", "msim_check_alive: %s > interval of %d, presumed dead\n", 2142 purple_debug_info("msim", "msim_check_alive: %s > interval of %d, presumed dead\n",
2184 errmsg, MSIM_KEEPALIVE_INTERVAL); 2143 errmsg, MSIM_KEEPALIVE_INTERVAL);
2185 purple_connection_error(session->gc, errmsg); 2144 purple_connection_error(session->gc, errmsg);
2257 2216
2258 old_inbox_status = session->inbox_status; 2217 old_inbox_status = session->inbox_status;
2259 2218
2260 n = 0; 2219 n = 0;
2261 2220
2262 for (i = 0; i < sizeof(inbox_keys) / sizeof(inbox_keys[0]); ++i) 2221 for (i = 0; i < sizeof(inbox_keys) / sizeof(inbox_keys[0]); ++i) {
2263 {
2264 const gchar *key; 2222 const gchar *key;
2265 guint bit; 2223 guint bit;
2266 2224
2267 key = inbox_keys[i]; 2225 key = inbox_keys[i];
2268 bit = inbox_bits[i]; 2226 bit = inbox_bits[i];
2269 2227
2270 if (g_hash_table_lookup(body, key)) 2228 if (g_hash_table_lookup(body, key)) {
2271 {
2272 /* Notify only on when _changes_ from no mail -> has mail 2229 /* Notify only on when _changes_ from no mail -> has mail
2273 * (edge triggered) */ 2230 * (edge triggered) */
2274 if (!(session->inbox_status & bit)) 2231 if (!(session->inbox_status & bit)) {
2275 {
2276 purple_debug_info("msim", "msim_check_inbox_cb: got %s, at %d\n", 2232 purple_debug_info("msim", "msim_check_inbox_cb: got %s, at %d\n",
2277 key ? key : "(NULL)", n); 2233 key ? key : "(NULL)", n);
2278 2234
2279 subjects[n] = inbox_text[i]; 2235 subjects[n] = inbox_text[i];
2280 froms[n] = _("MySpace"); 2236 froms[n] = _("MySpace");
2293 2249
2294 session->inbox_status |= bit; 2250 session->inbox_status |= bit;
2295 } 2251 }
2296 } 2252 }
2297 2253
2298 if (n) 2254 if (n) {
2299 {
2300 purple_debug_info("msim", 2255 purple_debug_info("msim",
2301 "msim_check_inbox_cb: notifying of %d\n", n); 2256 "msim_check_inbox_cb: notifying of %d\n", n);
2302 2257
2303 /* TODO: free strings with callback _if_ change to dynamic (w/ token) */ 2258 /* TODO: free strings with callback _if_ change to dynamic (w/ token) */
2304 purple_notify_emails(session->gc, /* handle */ 2259 purple_notify_emails(session->gc, /* handle */
2358 /* Comes with: proof,profileid,userid,uniquenick -- all same values 2313 /* Comes with: proof,profileid,userid,uniquenick -- all same values
2359 * some of the time, but can vary. This is our own user ID. */ 2314 * some of the time, but can vary. This is our own user ID. */
2360 session->userid = msim_msg_get_integer(msg, "userid"); 2315 session->userid = msim_msg_get_integer(msg, "userid");
2361 2316
2362 /* Not sure what profileid is used for. */ 2317 /* Not sure what profileid is used for. */
2363 if (msim_msg_get_integer(msg, "profileid") != session->userid) 2318 if (msim_msg_get_integer(msg, "profileid") != session->userid) {
2364 {
2365 msim_unrecognized(session, msg, 2319 msim_unrecognized(session, msg,
2366 "Profile ID didn't match user ID, don't know why"); 2320 "Profile ID didn't match user ID, don't know why");
2367 } 2321 }
2368 2322
2369 /* We now know are our own username, only after we're logged in.. 2323 /* We now know are our own username, only after we're logged in..
2370 * which is weird, but happens because you login with your email 2324 * which is weird, but happens because you login with your email
2371 * address and not username. Will be freed in msim_session_destroy(). */ 2325 * address and not username. Will be freed in msim_session_destroy(). */
2372 session->username = msim_msg_get_string(msg, "uniquenick"); 2326 session->username = msim_msg_get_string(msg, "uniquenick");
2373 2327
2374 if (msim_msg_get_integer(msg, "uniquenick") == session->userid) 2328 if (msim_msg_get_integer(msg, "uniquenick") == session->userid) {
2375 {
2376 purple_debug_info("msim_we_are_logged_on", "TODO: pick username"); 2329 purple_debug_info("msim_we_are_logged_on", "TODO: pick username");
2377 } 2330 }
2378 2331
2379 body = msim_msg_new(TRUE, 2332 body = msim_msg_new(TRUE,
2380 "UserID", MSIM_TYPE_INTEGER, session->userid, 2333 "UserID", MSIM_TYPE_INTEGER, session->userid,
2449 { 2402 {
2450 g_return_val_if_fail(session != NULL, FALSE); 2403 g_return_val_if_fail(session != NULL, FALSE);
2451 g_return_val_if_fail(msg != NULL, FALSE); 2404 g_return_val_if_fail(msg != NULL, FALSE);
2452 2405
2453 #ifdef MSIM_DEBUG_MSG 2406 #ifdef MSIM_DEBUG_MSG
2454 { 2407 msim_msg_dump("ready to process: %s\n", msg);
2455 msim_msg_dump("ready to process: %s\n", msg);
2456 }
2457 #endif 2408 #endif
2458 2409
2459 if (msim_msg_get_integer(msg, "lc") == 1) 2410 if (msim_msg_get_integer(msg, "lc") == 1) {
2460 {
2461 return msim_login_challenge(session, msg); 2411 return msim_login_challenge(session, msg);
2462 } else if (msim_msg_get_integer(msg, "lc") == 2) { 2412 } else if (msim_msg_get_integer(msg, "lc") == 2) {
2463 return msim_we_are_logged_on(session, msg); 2413 return msim_we_are_logged_on(session, msg);
2464 } else if (msim_msg_get(msg, "bm")) { 2414 } else if (msim_msg_get(msg, "bm")) {
2465 return msim_incoming_bm(session, msg); 2415 return msim_incoming_bm(session, msg);
2486 key_str = (gchar *)key; 2436 key_str = (gchar *)key;
2487 value_str = (gchar *)value; 2437 value_str = (gchar *)value;
2488 2438
2489 if (strcmp(key_str, "UserID") == 0 || 2439 if (strcmp(key_str, "UserID") == 0 ||
2490 strcmp(key_str, "Age") == 0 || 2440 strcmp(key_str, "Age") == 0 ||
2491 strcmp(key_str, "TotalFriends") == 0) 2441 strcmp(key_str, "TotalFriends") == 0) {
2492 {
2493 /* Certain fields get set as integers, instead of strings, for 2442 /* Certain fields get set as integers, instead of strings, for
2494 * convenience. May not be the best way to do it, but having at least 2443 * convenience. May not be the best way to do it, but having at least
2495 * UserID as an integer is convenient...until it overflows! */ 2444 * UserID as an integer is convenient...until it overflows! */
2496 purple_blist_node_set_int(&buddy->node, key_str, atol(value_str)); 2445 purple_blist_node_set_int(&buddy->node, key_str, atol(value_str));
2497 } else { 2446 } else {
2527 g_free(body_str); 2476 g_free(body_str);
2528 2477
2529 /* TODO: implement a better hash-like interface, and use it. */ 2478 /* TODO: implement a better hash-like interface, and use it. */
2530 username = g_hash_table_lookup(body, "UserName"); 2479 username = g_hash_table_lookup(body, "UserName");
2531 2480
2532 if (!username) 2481 if (!username) {
2533 {
2534 purple_debug_info("msim", 2482 purple_debug_info("msim",
2535 "msim_process_reply: not caching body, no UserName\n"); 2483 "msim_process_reply: not caching body, no UserName\n");
2536 g_hash_table_destroy(body); 2484 g_hash_table_destroy(body);
2537 return FALSE; 2485 return FALSE;
2538 } 2486 }
2539 2487
2540 uid = g_hash_table_lookup(body, "UserID"); 2488 uid = g_hash_table_lookup(body, "UserID");
2541 if (!uid) 2489 if (!uid) {
2542 {
2543 g_hash_table_destroy(body); 2490 g_hash_table_destroy(body);
2544 g_return_val_if_fail(uid, FALSE); 2491 g_return_val_if_fail(uid, FALSE);
2545 } 2492 }
2546 2493
2547 purple_debug_info("msim", "associating uid %s with username %s\n", uid, username); 2494 purple_debug_info("msim", "associating uid %s with username %s\n", uid, username);
2548 2495
2549 buddy = purple_find_buddy(session->account, username); 2496 buddy = purple_find_buddy(session->account, username);
2550 if (buddy) 2497 if (buddy) {
2551 {
2552 g_hash_table_foreach(body, msim_store_buddy_info_each, buddy); 2498 g_hash_table_foreach(body, msim_store_buddy_info_each, buddy);
2553 } 2499 }
2554 2500
2555 if (msim_msg_get_integer(msg, "dsn") == MG_OWN_IM_INFO_DSN && 2501 if (msim_msg_get_integer(msg, "dsn") == MG_OWN_IM_INFO_DSN &&
2556 msim_msg_get_integer(msg, "lid") == MG_OWN_IM_INFO_LID) 2502 msim_msg_get_integer(msg, "lid") == MG_OWN_IM_INFO_LID) {
2557 {
2558 /* TODO: do something with our own IM info, if we need it for some 2503 /* TODO: do something with our own IM info, if we need it for some
2559 * specific purpose. Otherwise it is available on the buddy list, 2504 * specific purpose. Otherwise it is available on the buddy list,
2560 * if the user has themselves as their own buddy. */ 2505 * if the user has themselves as their own buddy. */
2561 } else if (msim_msg_get_integer(msg, "dsn") == MG_OWN_MYSPACE_INFO_DSN && 2506 } else if (msim_msg_get_integer(msg, "dsn") == MG_OWN_MYSPACE_INFO_DSN &&
2562 msim_msg_get_integer(msg, "lid") == MG_OWN_MYSPACE_INFO_LID) { 2507 msim_msg_get_integer(msg, "lid") == MG_OWN_MYSPACE_INFO_LID) {
2646 cmd = msim_msg_get_integer(msg, "cmd"); 2591 cmd = msim_msg_get_integer(msg, "cmd");
2647 dsn = msim_msg_get_integer(msg, "dsn"); 2592 dsn = msim_msg_get_integer(msg, "dsn");
2648 lid = msim_msg_get_integer(msg, "lid"); 2593 lid = msim_msg_get_integer(msg, "lid");
2649 2594
2650 /* Unsolicited messages */ 2595 /* Unsolicited messages */
2651 if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_GET)) 2596 if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_GET)) {
2652 { 2597 if (dsn == MG_SERVER_INFO_DSN && lid == MG_SERVER_INFO_LID) {
2653 if (dsn == MG_SERVER_INFO_DSN && lid == MG_SERVER_INFO_LID)
2654 {
2655 return msim_process_server_info(session, msg); 2598 return msim_process_server_info(session, msg);
2656 } else if (dsn == MG_WEB_CHALLENGE_DSN && lid == MG_WEB_CHALLENGE_LID) { 2599 } else if (dsn == MG_WEB_CHALLENGE_DSN && lid == MG_WEB_CHALLENGE_LID) {
2657 return msim_web_challenge(session, msg); 2600 return msim_web_challenge(session, msg);
2658 } 2601 }
2659 } 2602 }
2660 2603
2661 /* If a callback is registered for this userid lookup, call it. */ 2604 /* If a callback is registered for this userid lookup, call it. */
2662 cb = g_hash_table_lookup(session->user_lookup_cb, GUINT_TO_POINTER(rid)); 2605 cb = g_hash_table_lookup(session->user_lookup_cb, GUINT_TO_POINTER(rid));
2663 data = g_hash_table_lookup(session->user_lookup_cb_data, GUINT_TO_POINTER(rid)); 2606 data = g_hash_table_lookup(session->user_lookup_cb_data, GUINT_TO_POINTER(rid));
2664 2607
2665 if (cb) 2608 if (cb) {
2666 {
2667 purple_debug_info("msim", 2609 purple_debug_info("msim",
2668 "msim_process_body: calling callback now\n"); 2610 "msim_process_body: calling callback now\n");
2669 /* Clone message, so that the callback 'cb' can use it (needs to free it also). */ 2611 /* Clone message, so that the callback 'cb' can use it (needs to free it also). */
2670 cb(session, msim_msg_clone(msg), data); 2612 cb(session, msim_msg_clone(msg), data);
2671 g_hash_table_remove(session->user_lookup_cb, GUINT_TO_POINTER(rid)); 2613 g_hash_table_remove(session->user_lookup_cb, GUINT_TO_POINTER(rid));
2707 2649
2708 purple_notify_error(session->account, g_strdup(_("MySpaceIM Error")), 2650 purple_notify_error(session->account, g_strdup(_("MySpaceIM Error")),
2709 full_errmsg, NULL); 2651 full_errmsg, NULL);
2710 2652
2711 /* Destroy session if fatal. */ 2653 /* Destroy session if fatal. */
2712 if (msim_msg_get(msg, "fatal")) 2654 if (msim_msg_get(msg, "fatal")) {
2713 {
2714 purple_debug_info("msim", "fatal error, closing\n"); 2655 purple_debug_info("msim", "fatal error, closing\n");
2715 purple_connection_error(session->gc, full_errmsg); 2656 purple_connection_error(session->gc, full_errmsg);
2716 } 2657 }
2717 2658
2718 return TRUE; 2659 return TRUE;
2771 2712
2772 blist = purple_get_blist(); 2713 blist = purple_get_blist();
2773 2714
2774 /* Add buddy if not found */ 2715 /* Add buddy if not found */
2775 buddy = purple_find_buddy(session->account, username); 2716 buddy = purple_find_buddy(session->account, username);
2776 if (!buddy) 2717 if (!buddy) {
2777 {
2778 purple_debug_info("msim", 2718 purple_debug_info("msim",
2779 "msim_status: making new buddy for %s\n", username); 2719 "msim_status: making new buddy for %s\n", username);
2780 buddy = purple_buddy_new(session->account, username, NULL); 2720 buddy = purple_buddy_new(session->account, username, NULL);
2781 2721
2782 purple_blist_add_buddy(buddy, NULL, NULL, NULL); 2722 purple_blist_add_buddy(buddy, NULL, NULL, NULL);
2790 } 2730 }
2791 2731
2792 purple_blist_node_set_string(&buddy->node, "Headline", status_headline); 2732 purple_blist_node_set_string(&buddy->node, "Headline", status_headline);
2793 2733
2794 /* Set user status */ 2734 /* Set user status */
2795 switch (status_code) 2735 switch (status_code) {
2796 {
2797 case MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN: 2736 case MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN:
2798 purple_status_code = PURPLE_STATUS_OFFLINE; 2737 purple_status_code = PURPLE_STATUS_OFFLINE;
2799 break; 2738 break;
2800 2739
2801 case MSIM_STATUS_CODE_ONLINE: 2740 case MSIM_STATUS_CODE_ONLINE:
2817 purple_status_code = PURPLE_STATUS_AVAILABLE; 2756 purple_status_code = PURPLE_STATUS_AVAILABLE;
2818 } 2757 }
2819 2758
2820 purple_prpl_got_user_status(session->account, username, purple_primitive_get_id_from_type(purple_status_code), NULL); 2759 purple_prpl_got_user_status(session->account, username, purple_primitive_get_id_from_type(purple_status_code), NULL);
2821 2760
2822 if (status_code == MSIM_STATUS_CODE_IDLE) 2761 if (status_code == MSIM_STATUS_CODE_IDLE) {
2823 {
2824 purple_debug_info("msim", "msim_status: got idle: %s\n", username); 2762 purple_debug_info("msim", "msim_status: got idle: %s\n", username);
2825 purple_prpl_got_user_idle(session->account, username, TRUE, time(NULL)); 2763 purple_prpl_got_user_idle(session->account, username, TRUE, time(NULL));
2826 } else { 2764 } else {
2827 /* All other statuses indicate going back to non-idle. */ 2765 /* All other statuses indicate going back to non-idle. */
2828 purple_prpl_got_user_idle(session->account, username, FALSE, time(NULL)); 2766 purple_prpl_got_user_idle(session->account, username, FALSE, time(NULL));
2829 } 2767 }
2830 2768
2831 #ifdef MSIM_SEND_CLIENT_VERSION 2769 #ifdef MSIM_SEND_CLIENT_VERSION
2832 if (status_code == MSIM_STATUS_CODE_ONLINE) 2770 if (status_code == MSIM_STATUS_CODE_ONLINE) {
2833 {
2834 /* Secretly whisper to unofficial clients our own version as they come online */ 2771 /* Secretly whisper to unofficial clients our own version as they come online */
2835 msim_send_unofficial_client(session, username); 2772 msim_send_unofficial_client(session, username);
2836 } 2773 }
2837 #endif 2774 #endif
2838 2775
2860 "sesskey", MSIM_TYPE_INTEGER, session->sesskey, 2797 "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
2861 /* "newprofileid" will be inserted here with uid. */ 2798 /* "newprofileid" will be inserted here with uid. */
2862 "reason", MSIM_TYPE_STRING, g_strdup(""), 2799 "reason", MSIM_TYPE_STRING, g_strdup(""),
2863 NULL); 2800 NULL);
2864 2801
2865 if (!msim_postprocess_outgoing(session, msg, buddy->name, "newprofileid", "reason")) 2802 if (!msim_postprocess_outgoing(session, msg, buddy->name, "newprofileid", "reason")) {
2866 {
2867 purple_notify_error(NULL, NULL, _("Failed to add buddy"), _("'addbuddy' command failed.")); 2803 purple_notify_error(NULL, NULL, _("Failed to add buddy"), _("'addbuddy' command failed."));
2868 msim_msg_free(msg); 2804 msim_msg_free(msg);
2869 return; 2805 return;
2870 } 2806 }
2871 msim_msg_free(msg); 2807 msim_msg_free(msg);
2927 const gchar *uid_field_name, guint uid) 2863 const gchar *uid_field_name, guint uid)
2928 { 2864 {
2929 msim_msg_dump("msim_do_postprocessing msg: %s\n", msg); 2865 msim_msg_dump("msim_do_postprocessing msg: %s\n", msg);
2930 2866
2931 /* First, check - if the field already exists, replace <uid> within it */ 2867 /* First, check - if the field already exists, replace <uid> within it */
2932 if (msim_msg_get(msg, uid_field_name)) 2868 if (msim_msg_get(msg, uid_field_name)) {
2933 {
2934 MsimMessageElement *elem; 2869 MsimMessageElement *elem;
2935 gchar *fmt_string; 2870 gchar *fmt_string;
2936 gchar *uid_str, *new_str; 2871 gchar *uid_str, *new_str;
2937 2872
2938 /* Warning: this is a delicate, but safe, operation */ 2873 /* Warning: this is a delicate, but safe, operation */
3011 uid_before = msim_msg_get_string(msg, "_uid_before"); 2946 uid_before = msim_msg_get_string(msg, "_uid_before");
3012 2947
3013 msg = msim_do_postprocessing(msg, uid_before, uid_field_name, atol(uid)); 2948 msg = msim_do_postprocessing(msg, uid_before, uid_field_name, atol(uid));
3014 2949
3015 /* Send */ 2950 /* Send */
3016 if (!msim_msg_send(session, msg)) 2951 if (!msim_msg_send(session, msg)) {
3017 {
3018 msim_msg_dump("msim_postprocess_outgoing_cb: sending failed for message: %s\n", msg); 2952 msim_msg_dump("msim_postprocess_outgoing_cb: sending failed for message: %s\n", msg);
3019 } 2953 }
3020 2954
3021 2955
3022 /* Free field names AFTER sending message, because MsimMessage does NOT copy 2956 /* Free field names AFTER sending message, because MsimMessage does NOT copy
3056 msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, g_strdup(username)); 2990 msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, g_strdup(username));
3057 msg = msim_msg_append(msg, "_uid_field_name", MSIM_TYPE_STRING, g_strdup(uid_field_name)); 2991 msg = msim_msg_append(msg, "_uid_field_name", MSIM_TYPE_STRING, g_strdup(uid_field_name));
3058 msg = msim_msg_append(msg, "_uid_before", MSIM_TYPE_STRING, g_strdup(uid_before)); 2992 msg = msim_msg_append(msg, "_uid_before", MSIM_TYPE_STRING, g_strdup(uid_before));
3059 2993
3060 /* First, try the most obvious. If numeric userid is given, use that directly. */ 2994 /* First, try the most obvious. If numeric userid is given, use that directly. */
3061 if (msim_is_userid(username)) 2995 if (msim_is_userid(username)) {
3062 {
3063 uid = atol(username); 2996 uid = atol(username);
3064 } else { 2997 } else {
3065 /* Next, see if on buddy list and know uid. */ 2998 /* Next, see if on buddy list and know uid. */
3066 buddy = purple_find_buddy(session->account, username); 2999 buddy = purple_find_buddy(session->account, username);
3067 if (buddy) 3000 if (buddy) {
3068 {
3069 uid = purple_blist_node_get_int(&buddy->node, "UserID"); 3001 uid = purple_blist_node_get_int(&buddy->node, "UserID");
3070 } else { 3002 } else {
3071 uid = 0; 3003 uid = 0;
3072 } 3004 }
3073 3005
3114 "delbuddy", MSIM_TYPE_BOOLEAN, TRUE, 3046 "delbuddy", MSIM_TYPE_BOOLEAN, TRUE,
3115 "sesskey", MSIM_TYPE_INTEGER, session->sesskey, 3047 "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
3116 /* 'delprofileid' with uid will be inserted here. */ 3048 /* 'delprofileid' with uid will be inserted here. */
3117 NULL); 3049 NULL);
3118 3050
3119 if (!msim_postprocess_outgoing(session, delbuddy_msg, buddy->name, "delprofileid", NULL)) 3051 if (!msim_postprocess_outgoing(session, delbuddy_msg, buddy->name, "delprofileid", NULL)) {
3120 {
3121 purple_notify_error(NULL, NULL, _("Failed to remove buddy"), _("'delbuddy' command failed")); 3052 purple_notify_error(NULL, NULL, _("Failed to remove buddy"), _("'delbuddy' command failed"));
3122 msim_msg_free(delbuddy_msg); 3053 msim_msg_free(delbuddy_msg);
3123 return; 3054 return;
3124 } 3055 }
3125 msim_msg_free(delbuddy_msg); 3056 msim_msg_free(delbuddy_msg);
3134 "rid", MSIM_TYPE_INTEGER, session->next_rid++, 3065 "rid", MSIM_TYPE_INTEGER, session->next_rid++,
3135 /* <uid> will be replaced by postprocessing */ 3066 /* <uid> will be replaced by postprocessing */
3136 "body", MSIM_TYPE_STRING, g_strdup("ContactID=<uid>"), 3067 "body", MSIM_TYPE_STRING, g_strdup("ContactID=<uid>"),
3137 NULL); 3068 NULL);
3138 3069
3139 if (!msim_postprocess_outgoing(session, persist_msg, buddy->name, "body", NULL)) 3070 if (!msim_postprocess_outgoing(session, persist_msg, buddy->name, "body", NULL)) {
3140 {
3141 purple_notify_error(NULL, NULL, _("Failed to remove buddy"), _("persist command failed")); 3071 purple_notify_error(NULL, NULL, _("Failed to remove buddy"), _("persist command failed"));
3142 msim_msg_free(persist_msg); 3072 msim_msg_free(persist_msg);
3143 return; 3073 return;
3144 } 3074 }
3145 msim_msg_free(persist_msg); 3075 msim_msg_free(persist_msg);
3157 /* TODO: MsimMessage lists. Currently <uid> isn't replaced in lists. */ 3087 /* TODO: MsimMessage lists. Currently <uid> isn't replaced in lists. */
3158 //"idlist", MSIM_TYPE_STRING, g_strdup("a-|<uid>|b-|<uid>"), 3088 //"idlist", MSIM_TYPE_STRING, g_strdup("a-|<uid>|b-|<uid>"),
3159 "idlist", MSIM_TYPE_LIST, blocklist_updates, 3089 "idlist", MSIM_TYPE_LIST, blocklist_updates,
3160 NULL); 3090 NULL);
3161 3091
3162 if (!msim_postprocess_outgoing(session, blocklist_msg, buddy->name, "idlist", NULL)) 3092 if (!msim_postprocess_outgoing(session, blocklist_msg, buddy->name, "idlist", NULL)) {
3163 {
3164 purple_notify_error(NULL, NULL, _("Failed to remove buddy"), _("blocklist command failed")); 3093 purple_notify_error(NULL, NULL, _("Failed to remove buddy"), _("blocklist command failed"));
3165 msim_msg_free(blocklist_msg); 3094 msim_msg_free(blocklist_msg);
3166 return; 3095 return;
3167 } 3096 }
3168 msim_msg_free(blocklist_msg); 3097 msim_msg_free(blocklist_msg);
3212 3141
3213 /* Only can handle so much data at once... 3142 /* Only can handle so much data at once...
3214 * If this happens, try recompiling with a higher MSIM_READ_BUF_SIZE. 3143 * If this happens, try recompiling with a higher MSIM_READ_BUF_SIZE.
3215 * Should be large enough to hold the largest protocol message. 3144 * Should be large enough to hold the largest protocol message.
3216 */ 3145 */
3217 if (session->rxoff >= MSIM_READ_BUF_SIZE) 3146 if (session->rxoff >= MSIM_READ_BUF_SIZE) {
3218 {
3219 purple_debug_error("msim", 3147 purple_debug_error("msim",
3220 "msim_input_cb: %d-byte read buffer full! rxoff=%d\n", 3148 "msim_input_cb: %d-byte read buffer full! rxoff=%d\n",
3221 MSIM_READ_BUF_SIZE, session->rxoff); 3149 MSIM_READ_BUF_SIZE, session->rxoff);
3222 purple_connection_error(gc, _("Read buffer full")); 3150 purple_connection_error(gc, _("Read buffer full"));
3223 return; 3151 return;
3230 /* Read into buffer. On Win32, need recv() not read(). session->fd also holds 3158 /* Read into buffer. On Win32, need recv() not read(). session->fd also holds
3231 * the file descriptor, but it sometimes differs from the 'source' parameter. 3159 * the file descriptor, but it sometimes differs from the 'source' parameter.
3232 */ 3160 */
3233 n = recv(session->fd, session->rxbuf + session->rxoff, MSIM_READ_BUF_SIZE - session->rxoff, 0); 3161 n = recv(session->fd, session->rxbuf + session->rxoff, MSIM_READ_BUF_SIZE - session->rxoff, 0);
3234 3162
3235 if (n < 0 && errno == EAGAIN) 3163 if (n < 0 && errno == EAGAIN) {
3236 {
3237 return; 3164 return;
3238 } 3165 } else if (n < 0) {
3239 else if (n < 0)
3240 {
3241 purple_debug_error("msim", "msim_input_cb: read error, ret=%d, " 3166 purple_debug_error("msim", "msim_input_cb: read error, ret=%d, "
3242 "error=%s, source=%d, fd=%d (%X))\n", 3167 "error=%s, source=%d, fd=%d (%X))\n",
3243 n, strerror(errno), source, session->fd, session->fd); 3168 n, strerror(errno), source, session->fd, session->fd);
3244 purple_connection_error(gc, _("Read error")); 3169 purple_connection_error(gc, _("Read error"));
3245 return; 3170 return;
3246 } 3171 } else if (n == 0) {
3247 else if (n == 0)
3248 {
3249 purple_debug_info("msim", "msim_input_cb: server disconnected\n"); 3172 purple_debug_info("msim", "msim_input_cb: server disconnected\n");
3250 purple_connection_error(gc, _("Server has disconnected")); 3173 purple_connection_error(gc, _("Server has disconnected"));
3251 return; 3174 return;
3252 } 3175 }
3253 3176
3254 if (n + session->rxoff >= MSIM_READ_BUF_SIZE) 3177 if (n + session->rxoff >= MSIM_READ_BUF_SIZE) {
3255 {
3256 purple_debug_info("msim_input_cb", "received %d bytes, pushing rxoff to %d, over buffer size of %d\n", 3178 purple_debug_info("msim_input_cb", "received %d bytes, pushing rxoff to %d, over buffer size of %d\n",
3257 n, n + session->rxoff, MSIM_READ_BUF_SIZE); 3179 n, n + session->rxoff, MSIM_READ_BUF_SIZE);
3258 /* TODO: g_realloc like msn, yahoo, irc, jabber? */ 3180 /* TODO: g_realloc like msn, yahoo, irc, jabber? */
3259 purple_connection_error(gc, _("Read buffer full")); 3181 purple_connection_error(gc, _("Read buffer full"));
3260 } 3182 }
3264 "at n=%d\n", n); 3186 "at n=%d\n", n);
3265 session->rxbuf[session->rxoff + n] = 0; 3187 session->rxbuf[session->rxoff + n] = 0;
3266 3188
3267 #ifdef MSIM_CHECK_EMBEDDED_NULLS 3189 #ifdef MSIM_CHECK_EMBEDDED_NULLS
3268 /* Check for embedded NULs. I don't handle them, and they shouldn't occur. */ 3190 /* Check for embedded NULs. I don't handle them, and they shouldn't occur. */
3269 if (strlen(session->rxbuf + session->rxoff) != n) 3191 if (strlen(session->rxbuf + session->rxoff) != n) {
3270 {
3271 /* Occurs after login, but it is not a null byte. */ 3192 /* Occurs after login, but it is not a null byte. */
3272 purple_debug_info("msim", "msim_input_cb: strlen=%d, but read %d bytes" 3193 purple_debug_info("msim", "msim_input_cb: strlen=%d, but read %d bytes"
3273 "--null byte encountered?\n", 3194 "--null byte encountered?\n",
3274 strlen(session->rxbuf + session->rxoff), n); 3195 strlen(session->rxbuf + session->rxoff), n);
3275 //purple_connection_error(gc, "Invalid message - null byte on input"); 3196 //purple_connection_error(gc, "Invalid message - null byte on input");
3283 #ifdef MSIM_DEBUG_RXBUF 3204 #ifdef MSIM_DEBUG_RXBUF
3284 purple_debug_info("msim", "buf=<%s>\n", session->rxbuf); 3205 purple_debug_info("msim", "buf=<%s>\n", session->rxbuf);
3285 #endif 3206 #endif
3286 3207
3287 /* Look for \\final\\ end markers. If found, process message. */ 3208 /* Look for \\final\\ end markers. If found, process message. */
3288 while((end = strstr(session->rxbuf, MSIM_FINAL_STRING))) 3209 while((end = strstr(session->rxbuf, MSIM_FINAL_STRING))) {
3289 {
3290 MsimMessage *msg; 3210 MsimMessage *msg;
3291 3211
3292 #ifdef MSIM_DEBUG_RXBUF 3212 #ifdef MSIM_DEBUG_RXBUF
3293 purple_debug_info("msim", "in loop: buf=<%s>\n", session->rxbuf); 3213 purple_debug_info("msim", "in loop: buf=<%s>\n", session->rxbuf);
3294 #endif 3214 #endif
3295 *end = 0; 3215 *end = 0;
3296 msg = msim_parse(g_strdup(session->rxbuf)); 3216 msg = msim_parse(g_strdup(session->rxbuf));
3297 if (!msg) 3217 if (!msg) {
3298 {
3299 purple_debug_info("msim", "msim_input_cb: couldn't parse rxbuf\n"); 3218 purple_debug_info("msim", "msim_input_cb: couldn't parse rxbuf\n");
3300 purple_connection_error(gc, _("Unparseable message")); 3219 purple_connection_error(gc, _("Unparseable message"));
3301 } 3220 } else {
3302 else
3303 {
3304 /* Process message and then free it (processing function should 3221 /* Process message and then free it (processing function should
3305 * clone message if it wants to keep it afterwards.) */ 3222 * clone message if it wants to keep it afterwards.) */
3306 if (!msim_preprocess_incoming(session, msg)) 3223 if (!msim_preprocess_incoming(session, msg)) {
3307 {
3308 msim_msg_dump("msim_input_cb: preprocessing message failed on msg: %s\n", msg); 3224 msim_msg_dump("msim_input_cb: preprocessing message failed on msg: %s\n", msg);
3309 } 3225 }
3310 msim_msg_free(msg); 3226 msim_msg_free(msg);
3311 } 3227 }
3312 3228
3364 g_return_if_fail(data != NULL); 3280 g_return_if_fail(data != NULL);
3365 3281
3366 gc = (PurpleConnection *)data; 3282 gc = (PurpleConnection *)data;
3367 session = (MsimSession *)gc->proto_data; 3283 session = (MsimSession *)gc->proto_data;
3368 3284
3369 if (source < 0) 3285 if (source < 0) {
3370 {
3371 purple_connection_error(gc, _("Couldn't connect to host")); 3286 purple_connection_error(gc, _("Couldn't connect to host"));
3372 purple_connection_error(gc, g_strdup_printf( 3287 purple_connection_error(gc, g_strdup_printf(
3373 _("Couldn't connect to host: %s (%d)"), 3288 _("Couldn't connect to host: %s (%d)"),
3374 error_message ? error_message : "no message given", 3289 error_message ? error_message : "no message given",
3375 source)); 3290 source));
3377 } 3292 }
3378 3293
3379 session->fd = source; 3294 session->fd = source;
3380 3295
3381 gc->inpa = purple_input_add(source, PURPLE_INPUT_READ, msim_input_cb, gc); 3296 gc->inpa = purple_input_add(source, PURPLE_INPUT_READ, msim_input_cb, gc);
3382
3383
3384 } 3297 }
3385 3298
3386 /* Session methods */ 3299 /* Session methods */
3387 3300
3388 /** 3301 /**
3447 3360
3448 /* TODO: Remove. */ 3361 /* TODO: Remove. */
3449 g_hash_table_destroy(session->user_lookup_cb); 3362 g_hash_table_destroy(session->user_lookup_cb);
3450 g_hash_table_destroy(session->user_lookup_cb_data); 3363 g_hash_table_destroy(session->user_lookup_cb_data);
3451 3364
3452 if (session->server_info) 3365 if (session->server_info) {
3453 g_hash_table_destroy(session->server_info); 3366 g_hash_table_destroy(session->server_info);
3367 }
3454 3368
3455 g_free(session); 3369 g_free(session);
3456 } 3370 }
3457 3371
3458 /** 3372 /**
3463 void 3377 void
3464 msim_close(PurpleConnection *gc) 3378 msim_close(PurpleConnection *gc)
3465 { 3379 {
3466 MsimSession *session; 3380 MsimSession *session;
3467 3381
3468 if (gc == NULL) 3382 if (gc == NULL) {
3469 return; 3383 return;
3384 }
3470 3385
3471 session = (MsimSession *)gc->proto_data; 3386 session = (MsimSession *)gc->proto_data;
3472 if (session == NULL) 3387 if (session == NULL)
3473 return; 3388 return;
3474 3389
3475 gc->proto_data = NULL; 3390 gc->proto_data = NULL;
3476 3391
3477 if (!MSIM_SESSION_VALID(session)) 3392 if (!MSIM_SESSION_VALID(session)) {
3478 return; 3393 return;
3479 3394 }
3480 if (session->gc->inpa) 3395
3396 if (session->gc->inpa) {
3481 purple_input_remove(session->gc->inpa); 3397 purple_input_remove(session->gc->inpa);
3398 }
3482 3399
3483 msim_session_destroy(session); 3400 msim_session_destroy(session);
3484 } 3401 }
3485 3402
3486 3403
3551 3468
3552 /* Send request */ 3469 /* Send request */
3553 3470
3554 cmd = MSIM_CMD_GET; 3471 cmd = MSIM_CMD_GET;
3555 3472
3556 if (msim_is_userid(user)) 3473 if (msim_is_userid(user)) {
3557 {
3558 field_name = "UserID"; 3474 field_name = "UserID";
3559 dsn = MG_MYSPACE_INFO_BY_ID_DSN; 3475 dsn = MG_MYSPACE_INFO_BY_ID_DSN;
3560 lid = MG_MYSPACE_INFO_BY_ID_LID; 3476 lid = MG_MYSPACE_INFO_BY_ID_LID;
3561 } else if (msim_is_email(user)) { 3477 } else if (msim_is_email(user)) {
3562 field_name = "Email"; 3478 field_name = "Email";
3605 g_return_val_if_fail(MSIM_SESSION_VALID(session), NULL); 3521 g_return_val_if_fail(MSIM_SESSION_VALID(session), NULL);
3606 3522
3607 display_name = headline = NULL; 3523 display_name = headline = NULL;
3608 3524
3609 /* Retrieve display name and/or headline, depending on user preference. */ 3525 /* Retrieve display name and/or headline, depending on user preference. */
3610 if (purple_account_get_bool(session->account, "show_display_name", TRUE)) 3526 if (purple_account_get_bool(session->account, "show_display_name", TRUE)) {
3611 {
3612 display_name = purple_blist_node_get_string(&buddy->node, "DisplayName"); 3527 display_name = purple_blist_node_get_string(&buddy->node, "DisplayName");
3613 } 3528 }
3614 3529
3615 if (purple_account_get_bool(session->account, "show_headline", FALSE)) 3530 if (purple_account_get_bool(session->account, "show_headline", FALSE)) {
3616 {
3617 headline = purple_blist_node_get_string(&buddy->node, "Headline"); 3531 headline = purple_blist_node_get_string(&buddy->node, "Headline");
3618 } 3532 }
3619 3533
3620 /* Return appropriate combination of display name and/or headline, or neither. */ 3534 /* Return appropriate combination of display name and/or headline, or neither. */
3621 3535
3622 if (display_name && headline) 3536 if (display_name && headline) {
3623 return g_strconcat(display_name, " ", headline, NULL); 3537 return g_strconcat(display_name, " ", headline, NULL);
3624 3538 }
3625 if (display_name) 3539
3540 if (display_name) {
3626 return g_strdup(display_name); 3541 return g_strdup(display_name);
3627 3542 }
3628 if (headline) 3543
3544 if (headline) {
3629 return g_strdup(headline); 3545 return g_strdup(headline);
3546 }
3630 3547
3631 return NULL; 3548 return NULL;
3632 } 3549 }
3633 3550
3634 /** 3551 /**
3647 gint n; 3564 gint n;
3648 3565
3649 g_return_if_fail(buddy != NULL); 3566 g_return_if_fail(buddy != NULL);
3650 g_return_if_fail(user_info != NULL); 3567 g_return_if_fail(user_info != NULL);
3651 3568
3652 if (PURPLE_BUDDY_IS_ONLINE(buddy)) 3569 if (PURPLE_BUDDY_IS_ONLINE(buddy)) {
3653 {
3654 MsimSession *session; 3570 MsimSession *session;
3655 3571
3656 session = (MsimSession *)buddy->account->gc->proto_data; 3572 session = (MsimSession *)buddy->account->gc->proto_data;
3657 3573
3658 g_return_if_fail(MSIM_SESSION_VALID(session)); 3574 g_return_if_fail(MSIM_SESSION_VALID(session));
3660 /* TODO: if (full), do something different */ 3576 /* TODO: if (full), do something different */
3661 3577
3662 /* Useful to identify the account the tooltip refers to. 3578 /* Useful to identify the account the tooltip refers to.
3663 * Other prpls show this. */ 3579 * Other prpls show this. */
3664 str = purple_blist_node_get_string(&buddy->node, "UserName"); 3580 str = purple_blist_node_get_string(&buddy->node, "UserName");
3665 if (str) 3581 if (str) {
3666 purple_notify_user_info_add_pair(user_info, _("User Name"), str); 3582 purple_notify_user_info_add_pair(user_info, _("User Name"), str);
3583 }
3667 3584
3668 /* a/s/l...the vitals */ 3585 /* a/s/l...the vitals */
3669 n = purple_blist_node_get_int(&buddy->node, "Age"); 3586 n = purple_blist_node_get_int(&buddy->node, "Age");
3670 if (n) 3587 if (n) {
3671 purple_notify_user_info_add_pair(user_info, _("Age"), 3588 purple_notify_user_info_add_pair(user_info, _("Age"),
3672 g_strdup_printf("%d", n)); 3589 g_strdup_printf("%d", n));
3590 }
3673 3591
3674 str = purple_blist_node_get_string(&buddy->node, "Gender"); 3592 str = purple_blist_node_get_string(&buddy->node, "Gender");
3675 if (str) 3593 if (str) {
3676 purple_notify_user_info_add_pair(user_info, _("Gender"), str); 3594 purple_notify_user_info_add_pair(user_info, _("Gender"), str);
3595 }
3677 3596
3678 str = purple_blist_node_get_string(&buddy->node, "Location"); 3597 str = purple_blist_node_get_string(&buddy->node, "Location");
3679 if (str) 3598 if (str) {
3680 purple_notify_user_info_add_pair(user_info, _("Location"), str); 3599 purple_notify_user_info_add_pair(user_info, _("Location"), str);
3600 }
3681 3601
3682 /* Other information */ 3602 /* Other information */
3683 str = purple_blist_node_get_string(&buddy->node, "Headline"); 3603 str = purple_blist_node_get_string(&buddy->node, "Headline");
3684 if (str) 3604 if (str) {
3685 purple_notify_user_info_add_pair(user_info, _("Headline"), str); 3605 purple_notify_user_info_add_pair(user_info, _("Headline"), str);
3606 }
3686 3607
3687 str = purple_blist_node_get_string(&buddy->node, "BandName"); 3608 str = purple_blist_node_get_string(&buddy->node, "BandName");
3688 str2 = purple_blist_node_get_string(&buddy->node, "SongName"); 3609 str2 = purple_blist_node_get_string(&buddy->node, "SongName");
3689 if (str || str2) 3610 if (str || str2) {
3690 purple_notify_user_info_add_pair(user_info, _("Song"), 3611 purple_notify_user_info_add_pair(user_info, _("Song"),
3691 g_strdup_printf("%s - %s", 3612 g_strdup_printf("%s - %s",
3692 str ? str : _("Unknown Artist"), 3613 str ? str : _("Unknown Artist"),
3693 str2 ? str2 : _("Unknown Song"))); 3614 str2 ? str2 : _("Unknown Song")));
3615 }
3694 3616
3695 n = purple_blist_node_get_int(&buddy->node, "TotalFriends"); 3617 n = purple_blist_node_get_int(&buddy->node, "TotalFriends");
3696 if (n) 3618 if (n) {
3697 purple_notify_user_info_add_pair(user_info, _("Total Friends"), 3619 purple_notify_user_info_add_pair(user_info, _("Total Friends"),
3698 g_strdup_printf("%d", n)); 3620 g_strdup_printf("%d", n));
3621 }
3699 3622
3700 } 3623 }
3701 } 3624 }
3702 3625
3703 /** Actions menu for account. */ 3626 /** Actions menu for account. */
3726 3649
3727 return menu; 3650 return menu;
3728 } 3651 }
3729 3652
3730 /** Callbacks called by Purple, to access this plugin. */ 3653 /** Callbacks called by Purple, to access this plugin. */
3731 PurplePluginProtocolInfo prpl_info = 3654 PurplePluginProtocolInfo prpl_info = {
3732 {
3733 /* options */ 3655 /* options */
3734 OPT_PROTO_USE_POINTSIZE /* specify font size in sane point size */ 3656 OPT_PROTO_USE_POINTSIZE /* specify font size in sane point size */
3735 | OPT_PROTO_MAIL_CHECK, 3657 | OPT_PROTO_MAIL_CHECK,
3736 3658
3737 /* | OPT_PROTO_IM_IMAGE - TODO: direct images. */ 3659 /* | OPT_PROTO_IM_IMAGE - TODO: direct images. */
3803 }; 3725 };
3804 3726
3805 3727
3806 3728
3807 /** Based on MSN's plugin info comments. */ 3729 /** Based on MSN's plugin info comments. */
3808 PurplePluginInfo info = 3730 PurplePluginInfo info = {
3809 {
3810 PURPLE_PLUGIN_MAGIC, 3731 PURPLE_PLUGIN_MAGIC,
3811 PURPLE_MAJOR_VERSION, 3732 PURPLE_MAJOR_VERSION,
3812 PURPLE_MINOR_VERSION, 3733 PURPLE_MINOR_VERSION,
3813 PURPLE_PLUGIN_PROTOCOL, /**< type */ 3734 PURPLE_PLUGIN_PROTOCOL, /**< type */
3814 NULL, /**< ui_requirement */ 3735 NULL, /**< ui_requirement */
3841 3762
3842 3763
3843 #ifdef MSIM_SELF_TEST 3764 #ifdef MSIM_SELF_TEST
3844 /** Test functions. 3765 /** Test functions.
3845 * Used to test or try out the internal workings of msimprpl. If you're reading 3766 * Used to test or try out the internal workings of msimprpl. If you're reading
3846 * this code for the first time, these functions can be instructive in how 3767 * this code for the first time, these functions can be instructive in learning
3847 * msimprpl is architected. 3768 * how msimprpl is architected.
3848 */ 3769 */
3849 void 3770 void
3850 msim_test_all(void) 3771 msim_test_all(void) {
3851 {
3852 guint failures; 3772 guint failures;
3853 3773
3854 3774
3855 failures = 0; 3775 failures = 0;
3856 failures += msim_test_msg(); 3776 failures += msim_test_msg();
3857 failures += msim_test_escaping(); 3777 failures += msim_test_escaping();
3858 3778
3859 if (failures) 3779 if (failures) {
3860 {
3861 purple_debug_info("msim", "msim_test_all HAD FAILURES: %d\n", failures); 3780 purple_debug_info("msim", "msim_test_all HAD FAILURES: %d\n", failures);
3862 } 3781 } else {
3863 else
3864 {
3865 purple_debug_info("msim", "msim_test_all - all tests passed!\n"); 3782 purple_debug_info("msim", "msim_test_all - all tests passed!\n");
3866 } 3783 }
3867 exit(0); 3784 exit(0);
3868 } 3785 }
3869 3786
3894 purple_debug_info("msim", "msg packed=%s\n", packed); 3811 purple_debug_info("msim", "msg packed=%s\n", packed);
3895 3812
3896 packed_expected = "\\bx\\WFhY\\k1\\v1\\k1\\42\\k1" 3813 packed_expected = "\\bx\\WFhY\\k1\\v1\\k1\\42\\k1"
3897 "\\v43\\k1\\v52/1xxx/2yyy\\k1\\v7\\final\\"; 3814 "\\v43\\k1\\v52/1xxx/2yyy\\k1\\v7\\final\\";
3898 3815
3899 if (0 != strcmp(packed, packed_expected)) 3816 if (0 != strcmp(packed, packed_expected)) {
3900 {
3901 purple_debug_info("msim", "!!!(%d), msim_msg_pack not what expected: %s != %s\n", 3817 purple_debug_info("msim", "!!!(%d), msim_msg_pack not what expected: %s != %s\n",
3902 ++failures, packed, packed_expected); 3818 ++failures, packed, packed_expected);
3903 } 3819 }
3904 3820
3905 3821
3906 msg_cloned = msim_msg_clone(msg); 3822 msg_cloned = msim_msg_clone(msg);
3907 packed_cloned = msim_msg_pack(msg_cloned); 3823 packed_cloned = msim_msg_pack(msg_cloned);
3908 3824
3909 purple_debug_info("msim", "msg cloned=%s\n", packed_cloned); 3825 purple_debug_info("msim", "msg cloned=%s\n", packed_cloned);
3910 if (0 != strcmp(packed, packed_cloned)) 3826 if (0 != strcmp(packed, packed_cloned)) {
3911 {
3912 purple_debug_info("msim", "!!!(%d), msim_msg_pack on cloned message not equal to original: %s != %s\n", 3827 purple_debug_info("msim", "!!!(%d), msim_msg_pack on cloned message not equal to original: %s != %s\n",
3913 ++failures, packed_cloned, packed); 3828 ++failures, packed_cloned, packed);
3914 } 3829 }
3915 3830
3916 g_free(packed); 3831 g_free(packed);
3961 raw = "hello/world\\hello/world"; 3876 raw = "hello/world\\hello/world";
3962 3877
3963 escaped = msim_escape(raw); 3878 escaped = msim_escape(raw);
3964 purple_debug_info("msim", "msim_test_escaping: raw=%s, escaped=%s\n", raw, escaped); 3879 purple_debug_info("msim", "msim_test_escaping: raw=%s, escaped=%s\n", raw, escaped);
3965 expected = "hello/1world/2hello/1world"; 3880 expected = "hello/1world/2hello/1world";
3966 if (0 != strcmp(escaped, expected)) 3881 if (0 != strcmp(escaped, expected)) {
3967 {
3968 purple_debug_info("msim", "!!!(%d), msim_escape failed: %s != %s\n", 3882 purple_debug_info("msim", "!!!(%d), msim_escape failed: %s != %s\n",
3969 ++failures, escaped, expected); 3883 ++failures, escaped, expected);
3970 } 3884 }
3971 3885
3972 3886
3973 unescaped = msim_unescape(escaped); 3887 unescaped = msim_unescape(escaped);
3974 g_free(escaped); 3888 g_free(escaped);
3975 purple_debug_info("msim", "msim_test_escaping: unescaped=%s\n", unescaped); 3889 purple_debug_info("msim", "msim_test_escaping: unescaped=%s\n", unescaped);
3976 if (0 != strcmp(raw, unescaped)) 3890 if (0 != strcmp(raw, unescaped)) {
3977 {
3978 purple_debug_info("msim", "!!!(%d), msim_unescape failed: %s != %s\n", 3891 purple_debug_info("msim", "!!!(%d), msim_unescape failed: %s != %s\n",
3979 ++failures, raw, unescaped); 3892 ++failures, raw, unescaped);
3980 } 3893 }
3981 3894
3982 return failures; 3895 return failures;