comparison libpurple/protocols/msn/msn.c @ 31292:47b6eda87723

propagate from branch 'im.pidgin.pidgin' (head 07d0765c444a097af45c2650f54323afb900a07b) to branch 'im.pidgin.soc.2010.msn-tlc' (head f3998422a4724ab424e4e2328f58fc0504856557)
author masca@cpw.pidgin.im
date Mon, 19 Jul 2010 21:11:32 +0000
parents 210feb895031
children 23be655cc688
comparison
equal deleted inserted replaced
30698:e874875a74a7 31292:47b6eda87723
21 * along with this program; if not, write to the Free Software 21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
23 */ 23 */
24 #define PHOTO_SUPPORT 1 24 #define PHOTO_SUPPORT 1
25 25
26 #include "msn.h" 26 #include "internal.h"
27
28 #include "debug.h"
29 #include "request.h"
30
27 #include "accountopt.h" 31 #include "accountopt.h"
28 #include "contact.h" 32 #include "contact.h"
29 #include "msg.h" 33 #include "msg.h"
30 #include "page.h" 34 #include "page.h"
31 #include "pluginpref.h" 35 #include "pluginpref.h"
38 #include "core.h" 42 #include "core.h"
39 #include "prpl.h" 43 #include "prpl.h"
40 #include "msnutils.h" 44 #include "msnutils.h"
41 #include "version.h" 45 #include "version.h"
42 46
47 #include "error.h"
43 #include "msg.h" 48 #include "msg.h"
44 #include "switchboard.h" 49 #include "switchboard.h"
45 #include "notification.h" 50 #include "notification.h"
46 #include "sync.h"
47 #include "slplink.h" 51 #include "slplink.h"
48 52
49 #if PHOTO_SUPPORT 53 #if PHOTO_SUPPORT
50 #define MAX_HTTP_BUDDYICON_BYTES (200 * 1024) 54 #define MAX_HTTP_BUDDYICON_BYTES (200 * 1024)
51 #include "imgstore.h" 55 #include "imgstore.h"
114 g_free(tmp); 118 g_free(tmp);
115 119
116 return buf; 120 return buf;
117 } 121 }
118 122
119 gboolean
120 msn_email_is_valid(const char *passport)
121 {
122 if (purple_email_is_valid(passport)) {
123 /* Special characters aren't allowed in domains, so only go to '@' */
124 while (*passport != '@') {
125 if (*passport == '/')
126 return FALSE;
127 else if (*passport == '?')
128 return FALSE;
129 else if (*passport == '=')
130 return FALSE;
131 /* MSN also doesn't like colons, but that's checked already */
132
133 passport++;
134 }
135
136 return TRUE;
137 }
138
139 return FALSE;
140 }
141
142 static gboolean 123 static gboolean
143 msn_send_attention(PurpleConnection *gc, const char *username, guint type) 124 msn_send_attention(PurpleConnection *gc, const char *username, guint type)
144 { 125 {
145 MsnMessage *msg; 126 MsnMessage *msg;
146 MsnSession *session; 127 MsnSession *session;
265 PurpleSetPublicAliasSuccessCallback success_cb, 246 PurpleSetPublicAliasSuccessCallback success_cb,
266 PurpleSetPublicAliasFailureCallback failure_cb) 247 PurpleSetPublicAliasFailureCallback failure_cb)
267 { 248 {
268 MsnCmdProc *cmdproc; 249 MsnCmdProc *cmdproc;
269 MsnSession *session; 250 MsnSession *session;
251 MsnTransaction *trans;
270 PurpleAccount *account; 252 PurpleAccount *account;
271 const char *real_alias; 253 const char *real_alias;
272 MsnTransaction *trans;
273 struct public_alias_closure *closure; 254 struct public_alias_closure *closure;
274 255
275 session = purple_connection_get_protocol_data(pc); 256 session = purple_connection_get_protocol_data(pc);
276 cmdproc = session->notification->cmdproc; 257 cmdproc = session->notification->cmdproc;
277 account = purple_connection_get_account(pc); 258 account = purple_connection_get_account(pc);
358 static void 339 static void
359 msn_set_prp(PurpleConnection *gc, const char *type, const char *entry) 340 msn_set_prp(PurpleConnection *gc, const char *type, const char *entry)
360 { 341 {
361 MsnCmdProc *cmdproc; 342 MsnCmdProc *cmdproc;
362 MsnSession *session; 343 MsnSession *session;
344 MsnTransaction *trans;
363 345
364 session = gc->proto_data; 346 session = gc->proto_data;
365 cmdproc = session->notification->cmdproc; 347 cmdproc = session->notification->cmdproc;
366 348
367 if (entry == NULL || *entry == '\0') 349 if (entry == NULL || *entry == '\0')
368 { 350 {
369 msn_cmdproc_send(cmdproc, "PRP", "%s", type); 351 trans = msn_transaction_new(cmdproc, "PRP", "%s", type);
370 } 352 }
371 else 353 else
372 { 354 {
373 msn_cmdproc_send(cmdproc, "PRP", "%s %s", type, 355 trans = msn_transaction_new(cmdproc, "PRP", "%s %s", type,
374 purple_url_encode(entry)); 356 purple_url_encode(entry));
375 } 357 }
358 msn_cmdproc_send_trans(cmdproc, trans);
376 } 359 }
377 360
378 static void 361 static void
379 msn_set_home_phone_cb(PurpleConnection *gc, const char *entry) 362 msn_set_home_phone_cb(PurpleConnection *gc, const char *entry)
380 { 363 {
476 gc = (PurpleConnection *) action->context; 459 gc = (PurpleConnection *) action->context;
477 account = purple_connection_get_account(gc); 460 account = purple_connection_get_account(gc);
478 461
479 tmp = g_strdup_printf(_("Set friendly name for %s."), 462 tmp = g_strdup_printf(_("Set friendly name for %s."),
480 purple_account_get_username(account)); 463 purple_account_get_username(account));
481 purple_request_input(gc, _("Set your friendly name."), tmp, 464 purple_request_input(gc, _("Set Friendly Name"), tmp,
482 _("This is the name that other MSN buddies will " 465 _("This is the name that other MSN buddies will "
483 "see you as."), 466 "see you as."),
484 purple_connection_get_display_name(gc), FALSE, FALSE, NULL, 467 purple_connection_get_display_name(gc), FALSE, FALSE, NULL,
485 _("OK"), G_CALLBACK(msn_act_id), 468 _("OK"), G_CALLBACK(msn_act_id),
486 _("Cancel"), NULL, 469 _("Cancel"), NULL,
487 account, NULL, NULL, 470 account, NULL, NULL,
488 gc); 471 gc);
489 g_free(tmp); 472 g_free(tmp);
473 }
474
475 typedef struct MsnLocationData {
476 PurpleAccount *account;
477 MsnSession *session;
478 PurpleRequestFieldGroup *group;
479 } MsnLocationData;
480
481 static void
482 update_endpoint_cb(MsnLocationData *data, PurpleRequestFields *fields)
483 {
484 PurpleAccount *account;
485 MsnSession *session;
486 const char *old_name;
487 const char *name;
488 GList *others;
489
490 session = data->session;
491 account = data->account;
492
493 /* Update the current location's name */
494 old_name = purple_account_get_string(account, "endpoint-name", NULL);
495 name = purple_request_fields_get_string(fields, "endpoint-name");
496 if (!g_str_equal(old_name, name)) {
497 purple_account_set_string(account, "endpoint-name", name);
498 msn_notification_send_uux_private_endpointdata(session);
499 }
500
501 /* Sign out other locations */
502 for (others = purple_request_field_group_get_fields(data->group);
503 others;
504 others = g_list_next(others)) {
505 PurpleRequestField *field = others->data;
506 if (purple_request_field_get_type(field) != PURPLE_REQUEST_FIELD_BOOLEAN)
507 continue;
508 if (purple_request_field_bool_get_value(field)) {
509 const char *id = purple_request_field_get_id(field);
510 char *user;
511 purple_debug_info("msn", "Disconnecting Endpoint %s\n", id);
512
513 user = g_strdup_printf("%s;%s", purple_account_get_username(account), id);
514 msn_notification_send_uun(session, user, MSN_UNIFIED_NOTIFICATION_MPOP, "goawyplzthxbye");
515 g_free(user);
516 }
517 }
518
519 g_free(data);
520 }
521
522 static void
523 msn_show_locations(PurplePluginAction *action)
524 {
525 PurpleConnection *pc;
526 PurpleAccount *account;
527 MsnSession *session;
528 PurpleRequestFields *fields;
529 PurpleRequestFieldGroup *group;
530 PurpleRequestField *field;
531 GSList *l;
532 MsnLocationData *data;
533
534 pc = (PurpleConnection *)action->context;
535 account = purple_connection_get_account(pc);
536 session = purple_connection_get_protocol_data(pc);
537
538 fields = purple_request_fields_new();
539
540 group = purple_request_field_group_new(_("This Location"));
541 purple_request_fields_add_group(fields, group);
542 field = purple_request_field_label_new("endpoint-label", _("This is the name that identifies this location"));
543 purple_request_field_group_add_field(group, field);
544 field = purple_request_field_string_new("endpoint-name",
545 _("Name"),
546 purple_account_get_string(account, "endpoint-name", NULL),
547 FALSE);
548 purple_request_field_set_required(field, TRUE);
549 purple_request_field_group_add_field(group, field);
550
551 group = purple_request_field_group_new(_("Other Locations"));
552 purple_request_fields_add_group(fields, group);
553 field = purple_request_field_label_new("others-label", _("You can sign out from other locations here"));
554 purple_request_field_group_add_field(group, field);
555
556 for (l = session->user->endpoints; l; l = l->next) {
557 MsnUserEndpoint *ep = l->data;
558
559 if (g_str_equal(ep->id, session->guid))
560 /* Don't add myself to the list */
561 continue;
562
563 field = purple_request_field_bool_new(ep->id, ep->name, FALSE);
564 purple_request_field_group_add_field(group, field);
565 }
566
567 data = g_new0(MsnLocationData, 1);
568 data->account = account;
569 data->session = session;
570 data->group = group;
571
572 purple_request_fields(pc, NULL, NULL, NULL,
573 fields,
574 _("OK"), G_CALLBACK(update_endpoint_cb),
575 _("Cancel"), G_CALLBACK(g_free),
576 account, NULL, NULL,
577 data);
490 } 578 }
491 579
492 static void 580 static void
493 msn_show_set_home_phone(PurplePluginAction *action) 581 msn_show_set_home_phone(PurplePluginAction *action)
494 { 582 {
657 msn_send_privacy(PurpleConnection *gc) 745 msn_send_privacy(PurpleConnection *gc)
658 { 746 {
659 PurpleAccount *account; 747 PurpleAccount *account;
660 MsnSession *session; 748 MsnSession *session;
661 MsnCmdProc *cmdproc; 749 MsnCmdProc *cmdproc;
750 MsnTransaction *trans;
662 751
663 account = purple_connection_get_account(gc); 752 account = purple_connection_get_account(gc);
664 session = gc->proto_data; 753 session = gc->proto_data;
665 cmdproc = session->notification->cmdproc; 754 cmdproc = session->notification->cmdproc;
666 755
667 if (account->perm_deny == PURPLE_PRIVACY_ALLOW_ALL || 756 if (account->perm_deny == PURPLE_PRIVACY_ALLOW_ALL ||
668 account->perm_deny == PURPLE_PRIVACY_DENY_USERS) 757 account->perm_deny == PURPLE_PRIVACY_DENY_USERS)
669 msn_cmdproc_send(cmdproc, "BLP", "%s", "AL"); 758 trans = msn_transaction_new(cmdproc, "BLP", "%s", "AL");
670 else 759 else
671 msn_cmdproc_send(cmdproc, "BLP", "%s", "BL"); 760 trans = msn_transaction_new(cmdproc, "BLP", "%s", "BL");
761
762 msn_cmdproc_send_trans(cmdproc, trans);
672 } 763 }
673 764
674 static void 765 static void
675 initiate_chat_cb(PurpleBlistNode *node, gpointer data) 766 initiate_chat_cb(PurpleBlistNode *node, gpointer data)
676 { 767 {
710 } 801 }
711 802
712 static void 803 static void
713 t_msn_xfer_init(PurpleXfer *xfer) 804 t_msn_xfer_init(PurpleXfer *xfer)
714 { 805 {
715 MsnSlpLink *slplink = xfer->data; 806 msn_request_ft(xfer);
716 msn_slplink_request_ft(slplink, xfer);
717 msn_slplink_unref(slplink);
718 } 807 }
719 808
720 static void 809 static void
721 t_msn_xfer_cancel_send(PurpleXfer *xfer) 810 t_msn_xfer_cancel_send(PurpleXfer *xfer)
722 { 811 {
1069 act = purple_plugin_action_new(_("Set Friendly Name..."), 1158 act = purple_plugin_action_new(_("Set Friendly Name..."),
1070 msn_show_set_friendly_name); 1159 msn_show_set_friendly_name);
1071 m = g_list_append(m, act); 1160 m = g_list_append(m, act);
1072 m = g_list_append(m, NULL); 1161 m = g_list_append(m, NULL);
1073 1162
1163 act = purple_plugin_action_new(_("View Locations..."),
1164 msn_show_locations);
1165 m = g_list_append(m, act);
1166 m = g_list_append(m, NULL);
1167
1074 act = purple_plugin_action_new(_("Set Home Phone Number..."), 1168 act = purple_plugin_action_new(_("Set Home Phone Number..."),
1075 msn_show_set_home_phone); 1169 msn_show_set_home_phone);
1076 m = g_list_append(m, act); 1170 m = g_list_append(m, act);
1077 1171
1078 act = purple_plugin_action_new(_("Set Work Phone Number..."), 1172 act = purple_plugin_action_new(_("Set Work Phone Number..."),
1202 if (strcmp(username, purple_account_get_username(account))) 1296 if (strcmp(username, purple_account_get_username(account)))
1203 purple_account_set_username(account, username); 1297 purple_account_set_username(account, username);
1204 1298
1205 username = purple_account_get_string(account, "display-name", NULL); 1299 username = purple_account_get_string(account, "display-name", NULL);
1206 purple_connection_set_display_name(gc, username); 1300 purple_connection_set_display_name(gc, username);
1301
1302 if (purple_account_get_string(account, "endpoint-name", NULL) == NULL) {
1303 GHashTable *ui_info = purple_core_get_ui_info();
1304 const gchar *ui_name = ui_info ? g_hash_table_lookup(ui_info, "name") : NULL;
1305 purple_account_set_string(account, "endpoint-name",
1306 ui_name && *ui_name ? ui_name : PACKAGE_NAME);
1307 }
1207 1308
1208 if (!msn_session_connect(session, host, port, http_method)) 1309 if (!msn_session_connect(session, host, port, http_method))
1209 purple_connection_error_reason(gc, 1310 purple_connection_error_reason(gc,
1210 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, 1311 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
1211 _("Unable to connect")); 1312 _("Unable to connect"));
1413 return -E2BIG; 1514 return -E2BIG;
1414 } 1515 }
1415 1516
1416 msg = msn_message_new_plain(msgtext); 1517 msg = msn_message_new_plain(msgtext);
1417 msg->remote_user = g_strdup(who); 1518 msg->remote_user = g_strdup(who);
1418 msn_message_set_attr(msg, "X-MMS-IM-Format", msgformat); 1519 msn_message_set_header(msg, "X-MMS-IM-Format", msgformat);
1419 1520
1420 g_free(msgformat); 1521 g_free(msgformat);
1421 g_free(msgtext); 1522 g_free(msgtext);
1422 1523
1423 purple_debug_info("msn", "prepare to send online Message\n"); 1524 purple_debug_info("msn", "prepare to send online Message\n");
1446 */ 1547 */
1447 body_str = msn_message_to_string(msg); 1548 body_str = msn_message_to_string(msg);
1448 body_enc = g_markup_escape_text(body_str, -1); 1549 body_enc = g_markup_escape_text(body_str, -1);
1449 g_free(body_str); 1550 g_free(body_str);
1450 1551
1451 format = msn_message_get_attr(msg, "X-MMS-IM-Format"); 1552 format = msn_message_get_header_value(msg, "X-MMS-IM-Format");
1452 msn_parse_format(format, &pre, &post); 1553 msn_parse_format(format, &pre, &post);
1453 body_str = g_strdup_printf("%s%s%s", pre ? pre : "", 1554 body_str = g_strdup_printf("%s%s%s", pre ? pre : "",
1454 body_enc ? body_enc : "", post ? post : ""); 1555 body_enc ? body_enc : "", post ? post : "");
1455 g_free(body_enc); 1556 g_free(body_enc);
1456 g_free(pre); 1557 g_free(pre);
1521 swboard->flag |= MSN_SB_FLAG_IM; 1622 swboard->flag |= MSN_SB_FLAG_IM;
1522 1623
1523 msg = msn_message_new(MSN_MSG_TYPING); 1624 msg = msn_message_new(MSN_MSG_TYPING);
1524 msn_message_set_content_type(msg, "text/x-msmsgscontrol"); 1625 msn_message_set_content_type(msg, "text/x-msmsgscontrol");
1525 msn_message_set_flag(msg, 'U'); 1626 msn_message_set_flag(msg, 'U');
1526 msn_message_set_attr(msg, "TypingUser", 1627 msn_message_set_header(msg, "TypingUser",
1527 purple_account_get_username(account)); 1628 purple_account_get_username(account));
1528 msn_message_set_bin_data(msg, "\r\n", 2); 1629 msn_message_set_bin_data(msg, "\r\n", 2);
1529 1630
1530 msn_switchboard_send_msg(swboard, msg, FALSE); 1631 msn_switchboard_send_msg(swboard, msg, FALSE);
1531 1632
1577 if (network != MSN_NETWORK_UNKNOWN) { 1678 if (network != MSN_NETWORK_UNKNOWN) {
1578 MsnUserList *userlist = session->userlist; 1679 MsnUserList *userlist = session->userlist;
1579 MsnUser *user2 = msn_userlist_find_user(userlist, who); 1680 MsnUser *user2 = msn_userlist_find_user(userlist, who);
1580 if (user2 != NULL) { 1681 if (user2 != NULL) {
1581 /* User already in userlist, so just update it. */ 1682 /* User already in userlist, so just update it. */
1582 msn_user_destroy(user); 1683 msn_user_unref(user);
1583 user = user2; 1684 user = user2;
1584 } else { 1685 } else {
1585 msn_userlist_add_user(userlist, user); 1686 msn_userlist_add_user(userlist, user);
1586 } 1687 }
1587 1688
1597 purple_notify_error(purple_account_get_connection(session->account), NULL, _("Unable to Add"), buf); 1698 purple_notify_error(purple_account_get_connection(session->account), NULL, _("Unable to Add"), buf);
1598 g_free(buf); 1699 g_free(buf);
1599 1700
1600 /* Remove from local list */ 1701 /* Remove from local list */
1601 purple_blist_remove_buddy(buddy); 1702 purple_blist_remove_buddy(buddy);
1602 msn_user_destroy(user); 1703 msn_user_unref(user);
1603 } 1704 }
1604 g_free(group); 1705 g_free(group);
1605 } 1706 }
1606 1707
1607 static void 1708 static void
1928 2029
1929 return -E2BIG; 2030 return -E2BIG;
1930 } 2031 }
1931 2032
1932 msg = msn_message_new_plain(msgtext); 2033 msg = msn_message_new_plain(msgtext);
1933 msn_message_set_attr(msg, "X-MMS-IM-Format", msgformat); 2034 msn_message_set_header(msg, "X-MMS-IM-Format", msgformat);
1934 2035
1935 smileys = msn_msg_grab_emoticons(msg->body, username); 2036 smileys = msn_msg_grab_emoticons(msg->body, username);
1936 while (smileys) { 2037 while (smileys) {
1937 smile = (MsnEmoticon *)smileys->data; 2038 smile = (MsnEmoticon *)smileys->data;
1938 emoticons = msn_msg_emoticon_add(emoticons, smile); 2039 emoticons = msn_msg_emoticon_add(emoticons, smile);
1968 2069
1969 static void 2070 static void
1970 msn_keepalive(PurpleConnection *gc) 2071 msn_keepalive(PurpleConnection *gc)
1971 { 2072 {
1972 MsnSession *session; 2073 MsnSession *session;
2074 MsnTransaction *trans;
1973 2075
1974 session = gc->proto_data; 2076 session = gc->proto_data;
1975 2077
1976 if (!session->http_method) 2078 if (!session->http_method)
1977 { 2079 {
1978 MsnCmdProc *cmdproc; 2080 MsnCmdProc *cmdproc;
1979 2081
1980 cmdproc = session->notification->cmdproc; 2082 cmdproc = session->notification->cmdproc;
1981 2083
1982 msn_cmdproc_send_quick(cmdproc, "PNG", NULL, NULL); 2084 trans = msn_transaction_new(cmdproc, "PNG", NULL);
2085 msn_transaction_set_saveable(trans, FALSE);
2086 msn_cmdproc_send_trans(cmdproc, trans);
1983 } 2087 }
1984 } 2088 }
1985 2089
1986 static void msn_alias_buddy(PurpleConnection *pc, const char *name, const char *alias) 2090 static void msn_alias_buddy(PurpleConnection *pc, const char *name, const char *alias)
1987 { 2091 {
2715 2819
2716 static gboolean msn_load(PurplePlugin *plugin) 2820 static gboolean msn_load(PurplePlugin *plugin)
2717 { 2821 {
2718 msn_notification_init(); 2822 msn_notification_init();
2719 msn_switchboard_init(); 2823 msn_switchboard_init();
2720 msn_sync_init();
2721 2824
2722 return TRUE; 2825 return TRUE;
2723 } 2826 }
2724 2827
2725 static gboolean msn_unload(PurplePlugin *plugin) 2828 static gboolean msn_unload(PurplePlugin *plugin)
2726 { 2829 {
2727 msn_notification_end(); 2830 msn_notification_end();
2728 msn_switchboard_end(); 2831 msn_switchboard_end();
2729 msn_sync_end();
2730 2832
2731 return TRUE; 2833 return TRUE;
2732 } 2834 }
2733 2835
2734 static PurpleAccount *find_acct(const char *prpl, const char *acct_id) 2836 static PurpleAccount *find_acct(const char *prpl, const char *acct_id)