Mercurial > pidgin
comparison libpurple/protocols/msnp9/msn.c @ 21312:a07cfce78345
Add MSNP9 back as an alternative alongside the existing MSN prpl. Cowardly
old fools like me who prefer the stability of our MSNP9 code over the
features of MSNP14 can enable this using the --disable-msnp14 ./configure
option.
If we want to release from i.p.p and MSN stability is the only blocker, we
can trivially flick the default to use MSNP9 in configure.ac
author | Stu Tomlinson <stu@nosnilmot.com> |
---|---|
date | Sun, 11 Nov 2007 12:57:52 +0000 |
parents | |
children | 73788974b883 |
comparison
equal
deleted
inserted
replaced
21311:7d031cec5ba2 | 21312:a07cfce78345 |
---|---|
1 /** | |
2 * @file msn.c The MSN protocol plugin | |
3 * | |
4 * purple | |
5 * | |
6 * Purple is the legal property of its developers, whose names are too numerous | |
7 * to list here. Please refer to the COPYRIGHT file distributed with this | |
8 * source distribution. | |
9 * | |
10 * This program is free software; you can redistribute it and/or modify | |
11 * it under the terms of the GNU General Public License as published by | |
12 * the Free Software Foundation; either version 2 of the License, or | |
13 * (at your option) any later version. | |
14 * | |
15 * This program is distributed in the hope that it will be useful, | |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 * GNU General Public License for more details. | |
19 * | |
20 * You should have received a copy of the GNU General Public License | |
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 | |
23 */ | |
24 #define PHOTO_SUPPORT 1 | |
25 | |
26 #include <glib.h> | |
27 | |
28 #include "msn.h" | |
29 #include "accountopt.h" | |
30 #include "msg.h" | |
31 #include "page.h" | |
32 #include "pluginpref.h" | |
33 #include "prefs.h" | |
34 #include "session.h" | |
35 #include "state.h" | |
36 #include "util.h" | |
37 #include "cmds.h" | |
38 #include "core.h" | |
39 #include "prpl.h" | |
40 #include "msn-utils.h" | |
41 #include "version.h" | |
42 | |
43 #include "switchboard.h" | |
44 #include "notification.h" | |
45 #include "sync.h" | |
46 #include "slplink.h" | |
47 | |
48 #if PHOTO_SUPPORT | |
49 #include "imgstore.h" | |
50 #endif | |
51 | |
52 typedef struct | |
53 { | |
54 PurpleConnection *gc; | |
55 const char *passport; | |
56 | |
57 } MsnMobileData; | |
58 | |
59 typedef struct | |
60 { | |
61 PurpleConnection *gc; | |
62 char *name; | |
63 | |
64 } MsnGetInfoData; | |
65 | |
66 typedef struct | |
67 { | |
68 MsnGetInfoData *info_data; | |
69 char *stripped; | |
70 char *url_buffer; | |
71 PurpleNotifyUserInfo *user_info; | |
72 char *photo_url_text; | |
73 | |
74 } MsnGetInfoStepTwoData; | |
75 | |
76 typedef struct | |
77 { | |
78 PurpleConnection *gc; | |
79 const char *who; | |
80 char *msg; | |
81 PurpleMessageFlags flags; | |
82 time_t when; | |
83 } MsnIMData; | |
84 | |
85 static const char * | |
86 msn_normalize(const PurpleAccount *account, const char *str) | |
87 { | |
88 static char buf[BUF_LEN]; | |
89 char *tmp; | |
90 | |
91 g_return_val_if_fail(str != NULL, NULL); | |
92 | |
93 g_snprintf(buf, sizeof(buf), "%s%s", str, | |
94 (strchr(str, '@') ? "" : "@hotmail.com")); | |
95 | |
96 tmp = g_utf8_strdown(buf, -1); | |
97 strncpy(buf, tmp, sizeof(buf)); | |
98 g_free(tmp); | |
99 | |
100 return buf; | |
101 } | |
102 | |
103 static gboolean | |
104 msn_send_attention(PurpleConnection *gc, const char *username, guint type) | |
105 { | |
106 MsnMessage *msg; | |
107 MsnSession *session; | |
108 MsnSwitchBoard *swboard; | |
109 | |
110 msg = msn_message_new_nudge(); | |
111 session = gc->proto_data; | |
112 swboard = msn_session_get_swboard(session, username, MSN_SB_FLAG_IM); | |
113 | |
114 if (swboard == NULL) | |
115 return FALSE; | |
116 | |
117 msn_switchboard_send_msg(swboard, msg, TRUE); | |
118 | |
119 return TRUE; | |
120 } | |
121 | |
122 static GList * | |
123 msn_attention_types(PurpleAccount *account) | |
124 { | |
125 PurpleAttentionType *attn; | |
126 static GList *list = NULL; | |
127 | |
128 if (!list) { | |
129 attn = g_new0(PurpleAttentionType, 1); | |
130 attn->name = _("Nudge"); | |
131 attn->incoming_description = _("%s has nudged you!"); | |
132 attn->outgoing_description = _("Nudging %s..."); | |
133 list = g_list_append(list, attn); | |
134 } | |
135 | |
136 return list; | |
137 } | |
138 | |
139 | |
140 static PurpleCmdRet | |
141 msn_cmd_nudge(PurpleConversation *conv, const gchar *cmd, gchar **args, gchar **error, void *data) | |
142 { | |
143 PurpleAccount *account = purple_conversation_get_account(conv); | |
144 PurpleConnection *gc = purple_account_get_connection(account); | |
145 const gchar *username; | |
146 | |
147 username = purple_conversation_get_name(conv); | |
148 | |
149 serv_send_attention(gc, username, MSN_NUDGE); | |
150 | |
151 return PURPLE_CMD_RET_OK; | |
152 } | |
153 | |
154 static void | |
155 msn_act_id(PurpleConnection *gc, const char *entry) | |
156 { | |
157 MsnCmdProc *cmdproc; | |
158 MsnSession *session; | |
159 PurpleAccount *account; | |
160 const char *alias; | |
161 | |
162 session = gc->proto_data; | |
163 cmdproc = session->notification->cmdproc; | |
164 account = purple_connection_get_account(gc); | |
165 | |
166 if(entry && strlen(entry)) | |
167 alias = purple_url_encode(entry); | |
168 else | |
169 alias = ""; | |
170 | |
171 if (strlen(alias) > BUDDY_ALIAS_MAXLEN) | |
172 { | |
173 purple_notify_error(gc, NULL, | |
174 _("Your new MSN friendly name is too long."), NULL); | |
175 return; | |
176 } | |
177 | |
178 msn_cmdproc_send(cmdproc, "REA", "%s %s", | |
179 purple_account_get_username(account), | |
180 alias); | |
181 } | |
182 | |
183 static void | |
184 msn_set_prp(PurpleConnection *gc, const char *type, const char *entry) | |
185 { | |
186 MsnCmdProc *cmdproc; | |
187 MsnSession *session; | |
188 | |
189 session = gc->proto_data; | |
190 cmdproc = session->notification->cmdproc; | |
191 | |
192 if (entry == NULL || *entry == '\0') | |
193 { | |
194 msn_cmdproc_send(cmdproc, "PRP", "%s", type); | |
195 } | |
196 else | |
197 { | |
198 msn_cmdproc_send(cmdproc, "PRP", "%s %s", type, | |
199 purple_url_encode(entry)); | |
200 } | |
201 } | |
202 | |
203 static void | |
204 msn_set_home_phone_cb(PurpleConnection *gc, const char *entry) | |
205 { | |
206 msn_set_prp(gc, "PHH", entry); | |
207 } | |
208 | |
209 static void | |
210 msn_set_work_phone_cb(PurpleConnection *gc, const char *entry) | |
211 { | |
212 msn_set_prp(gc, "PHW", entry); | |
213 } | |
214 | |
215 static void | |
216 msn_set_mobile_phone_cb(PurpleConnection *gc, const char *entry) | |
217 { | |
218 msn_set_prp(gc, "PHM", entry); | |
219 } | |
220 | |
221 static void | |
222 enable_msn_pages_cb(PurpleConnection *gc) | |
223 { | |
224 msn_set_prp(gc, "MOB", "Y"); | |
225 } | |
226 | |
227 static void | |
228 disable_msn_pages_cb(PurpleConnection *gc) | |
229 { | |
230 msn_set_prp(gc, "MOB", "N"); | |
231 } | |
232 | |
233 static void | |
234 send_to_mobile(PurpleConnection *gc, const char *who, const char *entry) | |
235 { | |
236 MsnTransaction *trans; | |
237 MsnSession *session; | |
238 MsnCmdProc *cmdproc; | |
239 MsnPage *page; | |
240 char *payload; | |
241 size_t payload_len; | |
242 | |
243 session = gc->proto_data; | |
244 cmdproc = session->notification->cmdproc; | |
245 | |
246 page = msn_page_new(); | |
247 msn_page_set_body(page, entry); | |
248 | |
249 payload = msn_page_gen_payload(page, &payload_len); | |
250 | |
251 trans = msn_transaction_new(cmdproc, "PGD", "%s 1 %d", who, payload_len); | |
252 | |
253 msn_transaction_set_payload(trans, payload, payload_len); | |
254 | |
255 msn_page_destroy(page); | |
256 | |
257 msn_cmdproc_send_trans(cmdproc, trans); | |
258 } | |
259 | |
260 static void | |
261 send_to_mobile_cb(MsnMobileData *data, const char *entry) | |
262 { | |
263 send_to_mobile(data->gc, data->passport, entry); | |
264 g_free(data); | |
265 } | |
266 | |
267 static void | |
268 close_mobile_page_cb(MsnMobileData *data, const char *entry) | |
269 { | |
270 g_free(data); | |
271 } | |
272 | |
273 /* -- */ | |
274 | |
275 static void | |
276 msn_show_set_friendly_name(PurplePluginAction *action) | |
277 { | |
278 PurpleConnection *gc; | |
279 | |
280 gc = (PurpleConnection *) action->context; | |
281 | |
282 purple_request_input(gc, NULL, _("Set your friendly name."), | |
283 _("This is the name that other MSN buddies will " | |
284 "see you as."), | |
285 purple_connection_get_display_name(gc), FALSE, FALSE, NULL, | |
286 _("OK"), G_CALLBACK(msn_act_id), | |
287 _("Cancel"), NULL, | |
288 purple_connection_get_account(gc), NULL, NULL, | |
289 gc); | |
290 } | |
291 | |
292 static void | |
293 msn_show_set_home_phone(PurplePluginAction *action) | |
294 { | |
295 PurpleConnection *gc; | |
296 MsnSession *session; | |
297 | |
298 gc = (PurpleConnection *) action->context; | |
299 session = gc->proto_data; | |
300 | |
301 purple_request_input(gc, NULL, _("Set your home phone number."), NULL, | |
302 msn_user_get_home_phone(session->user), FALSE, FALSE, NULL, | |
303 _("OK"), G_CALLBACK(msn_set_home_phone_cb), | |
304 _("Cancel"), NULL, | |
305 purple_connection_get_account(gc), NULL, NULL, | |
306 gc); | |
307 } | |
308 | |
309 static void | |
310 msn_show_set_work_phone(PurplePluginAction *action) | |
311 { | |
312 PurpleConnection *gc; | |
313 MsnSession *session; | |
314 | |
315 gc = (PurpleConnection *) action->context; | |
316 session = gc->proto_data; | |
317 | |
318 purple_request_input(gc, NULL, _("Set your work phone number."), NULL, | |
319 msn_user_get_work_phone(session->user), FALSE, FALSE, NULL, | |
320 _("OK"), G_CALLBACK(msn_set_work_phone_cb), | |
321 _("Cancel"), NULL, | |
322 purple_connection_get_account(gc), NULL, NULL, | |
323 gc); | |
324 } | |
325 | |
326 static void | |
327 msn_show_set_mobile_phone(PurplePluginAction *action) | |
328 { | |
329 PurpleConnection *gc; | |
330 MsnSession *session; | |
331 | |
332 gc = (PurpleConnection *) action->context; | |
333 session = gc->proto_data; | |
334 | |
335 purple_request_input(gc, NULL, _("Set your mobile phone number."), NULL, | |
336 msn_user_get_mobile_phone(session->user), FALSE, FALSE, NULL, | |
337 _("OK"), G_CALLBACK(msn_set_mobile_phone_cb), | |
338 _("Cancel"), NULL, | |
339 purple_connection_get_account(gc), NULL, NULL, | |
340 gc); | |
341 } | |
342 | |
343 static void | |
344 msn_show_set_mobile_pages(PurplePluginAction *action) | |
345 { | |
346 PurpleConnection *gc; | |
347 | |
348 gc = (PurpleConnection *) action->context; | |
349 | |
350 purple_request_action(gc, NULL, _("Allow MSN Mobile pages?"), | |
351 _("Do you want to allow or disallow people on " | |
352 "your buddy list to send you MSN Mobile pages " | |
353 "to your cell phone or other mobile device?"), | |
354 -1, | |
355 purple_connection_get_account(gc), NULL, NULL, | |
356 gc, 3, | |
357 _("Allow"), G_CALLBACK(enable_msn_pages_cb), | |
358 _("Disallow"), G_CALLBACK(disable_msn_pages_cb), | |
359 _("Cancel"), NULL); | |
360 } | |
361 | |
362 static void | |
363 msn_show_hotmail_inbox(PurplePluginAction *action) | |
364 { | |
365 PurpleConnection *gc; | |
366 MsnSession *session; | |
367 | |
368 gc = (PurpleConnection *) action->context; | |
369 session = gc->proto_data; | |
370 | |
371 if (session->passport_info.file == NULL) | |
372 { | |
373 purple_notify_error(gc, NULL, | |
374 _("This Hotmail account may not be active."), NULL); | |
375 return; | |
376 } | |
377 | |
378 purple_notify_uri(gc, session->passport_info.file); | |
379 } | |
380 | |
381 static void | |
382 show_send_to_mobile_cb(PurpleBlistNode *node, gpointer ignored) | |
383 { | |
384 PurpleBuddy *buddy; | |
385 PurpleConnection *gc; | |
386 MsnSession *session; | |
387 MsnMobileData *data; | |
388 | |
389 g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); | |
390 | |
391 buddy = (PurpleBuddy *) node; | |
392 gc = purple_account_get_connection(buddy->account); | |
393 | |
394 session = gc->proto_data; | |
395 | |
396 data = g_new0(MsnMobileData, 1); | |
397 data->gc = gc; | |
398 data->passport = buddy->name; | |
399 | |
400 purple_request_input(gc, NULL, _("Send a mobile message."), NULL, | |
401 NULL, TRUE, FALSE, NULL, | |
402 _("Page"), G_CALLBACK(send_to_mobile_cb), | |
403 _("Close"), G_CALLBACK(close_mobile_page_cb), | |
404 purple_connection_get_account(gc), purple_buddy_get_name(buddy), NULL, | |
405 data); | |
406 } | |
407 | |
408 static gboolean | |
409 msn_offline_message(const PurpleBuddy *buddy) { | |
410 MsnUser *user; | |
411 if (buddy == NULL) | |
412 return FALSE; | |
413 user = buddy->proto_data; | |
414 return user && user->mobile; | |
415 } | |
416 | |
417 static void | |
418 initiate_chat_cb(PurpleBlistNode *node, gpointer data) | |
419 { | |
420 PurpleBuddy *buddy; | |
421 PurpleConnection *gc; | |
422 | |
423 MsnSession *session; | |
424 MsnSwitchBoard *swboard; | |
425 | |
426 g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); | |
427 | |
428 buddy = (PurpleBuddy *) node; | |
429 gc = purple_account_get_connection(buddy->account); | |
430 | |
431 session = gc->proto_data; | |
432 | |
433 swboard = msn_switchboard_new(session); | |
434 msn_switchboard_request(swboard); | |
435 msn_switchboard_request_add_user(swboard, buddy->name); | |
436 | |
437 /* TODO: This might move somewhere else, after USR might be */ | |
438 swboard->chat_id = session->conv_seq++; | |
439 swboard->conv = serv_got_joined_chat(gc, swboard->chat_id, "MSN Chat"); | |
440 swboard->flag = MSN_SB_FLAG_IM; | |
441 | |
442 purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv), | |
443 purple_account_get_username(buddy->account), NULL, PURPLE_CBFLAGS_NONE, TRUE); | |
444 } | |
445 | |
446 static void | |
447 t_msn_xfer_init(PurpleXfer *xfer) | |
448 { | |
449 MsnSlpLink *slplink = xfer->data; | |
450 msn_slplink_request_ft(slplink, xfer); | |
451 } | |
452 | |
453 static PurpleXfer* | |
454 msn_new_xfer(PurpleConnection *gc, const char *who) | |
455 { | |
456 MsnSession *session; | |
457 MsnSlpLink *slplink; | |
458 PurpleXfer *xfer; | |
459 | |
460 session = gc->proto_data; | |
461 | |
462 xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who); | |
463 if (xfer) | |
464 { | |
465 slplink = msn_session_get_slplink(session, who); | |
466 | |
467 xfer->data = slplink; | |
468 | |
469 purple_xfer_set_init_fnc(xfer, t_msn_xfer_init); | |
470 } | |
471 | |
472 return xfer; | |
473 } | |
474 | |
475 static void | |
476 msn_send_file(PurpleConnection *gc, const char *who, const char *file) | |
477 { | |
478 PurpleXfer *xfer = msn_new_xfer(gc, who); | |
479 | |
480 if (file) | |
481 purple_xfer_request_accepted(xfer, file); | |
482 else | |
483 purple_xfer_request(xfer); | |
484 } | |
485 | |
486 static gboolean | |
487 msn_can_receive_file(PurpleConnection *gc, const char *who) | |
488 { | |
489 PurpleAccount *account; | |
490 char *normal; | |
491 gboolean ret; | |
492 | |
493 account = purple_connection_get_account(gc); | |
494 | |
495 normal = g_strdup(msn_normalize(account, purple_account_get_username(account))); | |
496 | |
497 ret = strcmp(normal, msn_normalize(account, who)); | |
498 | |
499 g_free(normal); | |
500 | |
501 return ret; | |
502 } | |
503 | |
504 /************************************************************************** | |
505 * Protocol Plugin ops | |
506 **************************************************************************/ | |
507 | |
508 static const char * | |
509 msn_list_icon(PurpleAccount *a, PurpleBuddy *b) | |
510 { | |
511 return "msn"; | |
512 } | |
513 | |
514 static char * | |
515 msn_status_text(PurpleBuddy *buddy) | |
516 { | |
517 PurplePresence *presence; | |
518 PurpleStatus *status; | |
519 | |
520 presence = purple_buddy_get_presence(buddy); | |
521 status = purple_presence_get_active_status(presence); | |
522 | |
523 if (!purple_presence_is_available(presence) && !purple_presence_is_idle(presence)) | |
524 { | |
525 return g_strdup(purple_status_get_name(status)); | |
526 } | |
527 | |
528 return NULL; | |
529 } | |
530 | |
531 static void | |
532 msn_tooltip_text(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboolean full) | |
533 { | |
534 MsnUser *user; | |
535 PurplePresence *presence = purple_buddy_get_presence(buddy); | |
536 PurpleStatus *status = purple_presence_get_active_status(presence); | |
537 | |
538 user = buddy->proto_data; | |
539 | |
540 | |
541 if (purple_presence_is_online(presence)) | |
542 { | |
543 purple_notify_user_info_add_pair(user_info, _("Status"), | |
544 (purple_presence_is_idle(presence) ? _("Idle") : purple_status_get_name(status))); | |
545 } | |
546 | |
547 if (full && user) | |
548 { | |
549 purple_notify_user_info_add_pair(user_info, _("Has you"), | |
550 ((user->list_op & (1 << MSN_LIST_RL)) ? _("Yes") : _("No"))); | |
551 } | |
552 | |
553 /* XXX: This is being shown in non-full tooltips because the | |
554 * XXX: blocked icon overlay isn't always accurate for MSN. | |
555 * XXX: This can die as soon as purple_privacy_check() knows that | |
556 * XXX: this prpl always honors both the allow and deny lists. */ | |
557 /* While the above comment may be strictly correct (the privacy API needs | |
558 * rewriteing), purple_privacy_check() is going to be more accurate at | |
559 * indicating whether a particular buddy is going to be able to message | |
560 * you, which is the important information that this is trying to convey. */ | |
561 if (full && user) | |
562 { | |
563 purple_notify_user_info_add_pair(user_info, _("Blocked"), | |
564 ((user->list_op & (1 << MSN_LIST_BL)) ? _("Yes") : _("No"))); | |
565 } | |
566 } | |
567 | |
568 static GList * | |
569 msn_status_types(PurpleAccount *account) | |
570 { | |
571 PurpleStatusType *status; | |
572 GList *types = NULL; | |
573 | |
574 status = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, | |
575 NULL, NULL, FALSE, TRUE, FALSE); | |
576 types = g_list_append(types, status); | |
577 | |
578 status = purple_status_type_new_full(PURPLE_STATUS_AWAY, | |
579 NULL, NULL, FALSE, TRUE, FALSE); | |
580 types = g_list_append(types, status); | |
581 | |
582 status = purple_status_type_new_full(PURPLE_STATUS_AWAY, | |
583 "brb", _("Be Right Back"), FALSE, TRUE, FALSE); | |
584 types = g_list_append(types, status); | |
585 | |
586 status = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, | |
587 "busy", _("Busy"), FALSE, TRUE, FALSE); | |
588 types = g_list_append(types, status); | |
589 | |
590 status = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, | |
591 "phone", _("On the Phone"), FALSE, TRUE, FALSE); | |
592 types = g_list_append(types, status); | |
593 | |
594 status = purple_status_type_new_full(PURPLE_STATUS_AWAY, | |
595 "lunch", _("Out to Lunch"), FALSE, TRUE, FALSE); | |
596 types = g_list_append(types, status); | |
597 | |
598 status = purple_status_type_new_full(PURPLE_STATUS_INVISIBLE, | |
599 NULL, NULL, FALSE, TRUE, FALSE); | |
600 types = g_list_append(types, status); | |
601 | |
602 status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, | |
603 NULL, NULL, FALSE, TRUE, FALSE); | |
604 types = g_list_append(types, status); | |
605 | |
606 status = purple_status_type_new_full(PURPLE_STATUS_MOBILE, | |
607 "mobile", NULL, FALSE, FALSE, TRUE); | |
608 types = g_list_append(types, status); | |
609 | |
610 return types; | |
611 } | |
612 | |
613 static GList * | |
614 msn_actions(PurplePlugin *plugin, gpointer context) | |
615 { | |
616 PurpleConnection *gc = (PurpleConnection *)context; | |
617 PurpleAccount *account; | |
618 const char *user; | |
619 | |
620 GList *m = NULL; | |
621 PurplePluginAction *act; | |
622 | |
623 act = purple_plugin_action_new(_("Set Friendly Name..."), | |
624 msn_show_set_friendly_name); | |
625 m = g_list_append(m, act); | |
626 m = g_list_append(m, NULL); | |
627 | |
628 act = purple_plugin_action_new(_("Set Home Phone Number..."), | |
629 msn_show_set_home_phone); | |
630 m = g_list_append(m, act); | |
631 | |
632 act = purple_plugin_action_new(_("Set Work Phone Number..."), | |
633 msn_show_set_work_phone); | |
634 m = g_list_append(m, act); | |
635 | |
636 act = purple_plugin_action_new(_("Set Mobile Phone Number..."), | |
637 msn_show_set_mobile_phone); | |
638 m = g_list_append(m, act); | |
639 m = g_list_append(m, NULL); | |
640 | |
641 #if 0 | |
642 act = purple_plugin_action_new(_("Enable/Disable Mobile Devices..."), | |
643 msn_show_set_mobile_support); | |
644 m = g_list_append(m, act); | |
645 #endif | |
646 | |
647 act = purple_plugin_action_new(_("Allow/Disallow Mobile Pages..."), | |
648 msn_show_set_mobile_pages); | |
649 m = g_list_append(m, act); | |
650 | |
651 account = purple_connection_get_account(gc); | |
652 user = msn_normalize(account, purple_account_get_username(account)); | |
653 | |
654 if ((strstr(user, "@hotmail.") != NULL) || | |
655 (strstr(user, "@msn.com") != NULL)) | |
656 { | |
657 m = g_list_append(m, NULL); | |
658 act = purple_plugin_action_new(_("Open Hotmail Inbox"), | |
659 msn_show_hotmail_inbox); | |
660 m = g_list_append(m, act); | |
661 } | |
662 | |
663 return m; | |
664 } | |
665 | |
666 static GList * | |
667 msn_buddy_menu(PurpleBuddy *buddy) | |
668 { | |
669 MsnUser *user; | |
670 | |
671 GList *m = NULL; | |
672 PurpleMenuAction *act; | |
673 | |
674 g_return_val_if_fail(buddy != NULL, NULL); | |
675 | |
676 user = buddy->proto_data; | |
677 | |
678 if (user != NULL) | |
679 { | |
680 if (user->mobile) | |
681 { | |
682 act = purple_menu_action_new(_("Send to Mobile"), | |
683 PURPLE_CALLBACK(show_send_to_mobile_cb), | |
684 NULL, NULL); | |
685 m = g_list_append(m, act); | |
686 } | |
687 } | |
688 | |
689 if (g_ascii_strcasecmp(buddy->name, | |
690 purple_account_get_username(buddy->account))) | |
691 { | |
692 act = purple_menu_action_new(_("Initiate _Chat"), | |
693 PURPLE_CALLBACK(initiate_chat_cb), | |
694 NULL, NULL); | |
695 m = g_list_append(m, act); | |
696 } | |
697 | |
698 return m; | |
699 } | |
700 | |
701 static GList * | |
702 msn_blist_node_menu(PurpleBlistNode *node) | |
703 { | |
704 if(PURPLE_BLIST_NODE_IS_BUDDY(node)) | |
705 { | |
706 return msn_buddy_menu((PurpleBuddy *) node); | |
707 } | |
708 else | |
709 { | |
710 return NULL; | |
711 } | |
712 } | |
713 | |
714 static void | |
715 msn_login(PurpleAccount *account) | |
716 { | |
717 PurpleConnection *gc; | |
718 MsnSession *session; | |
719 const char *username; | |
720 const char *host; | |
721 gboolean http_method = FALSE; | |
722 int port; | |
723 | |
724 gc = purple_account_get_connection(account); | |
725 | |
726 if (!purple_ssl_is_supported()) | |
727 { | |
728 gc->wants_to_die = TRUE; | |
729 purple_connection_error(gc, | |
730 _("SSL support is needed for MSN. Please install a supported " | |
731 "SSL library.")); | |
732 return; | |
733 } | |
734 | |
735 http_method = purple_account_get_bool(account, "http_method", FALSE); | |
736 | |
737 if (http_method) | |
738 host = purple_account_get_string(account, "http_method_server", MSN_HTTPCONN_SERVER); | |
739 else | |
740 host = purple_account_get_string(account, "server", MSN_SERVER); | |
741 port = purple_account_get_int(account, "port", MSN_PORT); | |
742 | |
743 session = msn_session_new(account); | |
744 | |
745 gc->proto_data = session; | |
746 gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_FORMATTING_WBFO | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_FONTSIZE | PURPLE_CONNECTION_NO_URLDESC; | |
747 | |
748 msn_session_set_login_step(session, MSN_LOGIN_STEP_START); | |
749 | |
750 /* Hmm, I don't like this. */ | |
751 /* XXX shx: Me neither */ | |
752 username = msn_normalize(account, purple_account_get_username(account)); | |
753 | |
754 if (strcmp(username, purple_account_get_username(account))) | |
755 purple_account_set_username(account, username); | |
756 | |
757 if (!msn_session_connect(session, host, port, http_method)) | |
758 purple_connection_error(gc, _("Failed to connect to server.")); | |
759 } | |
760 | |
761 static void | |
762 msn_close(PurpleConnection *gc) | |
763 { | |
764 MsnSession *session; | |
765 | |
766 session = gc->proto_data; | |
767 | |
768 g_return_if_fail(session != NULL); | |
769 | |
770 msn_session_destroy(session); | |
771 | |
772 gc->proto_data = NULL; | |
773 } | |
774 | |
775 static gboolean | |
776 msn_send_me_im(gpointer data) | |
777 { | |
778 MsnIMData *imdata = data; | |
779 serv_got_im(imdata->gc, imdata->who, imdata->msg, imdata->flags, imdata->when); | |
780 g_free(imdata->msg); | |
781 g_free(imdata); | |
782 return FALSE; | |
783 } | |
784 | |
785 static int | |
786 msn_send_im(PurpleConnection *gc, const char *who, const char *message, | |
787 PurpleMessageFlags flags) | |
788 { | |
789 PurpleAccount *account; | |
790 PurpleBuddy *buddy = purple_find_buddy(gc->account, who); | |
791 MsnMessage *msg; | |
792 char *msgformat; | |
793 char *msgtext; | |
794 | |
795 account = purple_connection_get_account(gc); | |
796 | |
797 if (buddy) { | |
798 PurplePresence *p = purple_buddy_get_presence(buddy); | |
799 if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_MOBILE)) { | |
800 char *text = purple_markup_strip_html(message); | |
801 send_to_mobile(gc, who, text); | |
802 g_free(text); | |
803 return 1; | |
804 } | |
805 } | |
806 | |
807 msn_import_html(message, &msgformat, &msgtext); | |
808 | |
809 if (strlen(msgtext) + strlen(msgformat) + strlen(DISPLAY_VERSION) > 1564) | |
810 { | |
811 g_free(msgformat); | |
812 g_free(msgtext); | |
813 | |
814 return -E2BIG; | |
815 } | |
816 | |
817 msg = msn_message_new_plain(msgtext); | |
818 msn_message_set_attr(msg, "X-MMS-IM-Format", msgformat); | |
819 | |
820 g_free(msgformat); | |
821 g_free(msgtext); | |
822 | |
823 if (g_ascii_strcasecmp(who, purple_account_get_username(account))) | |
824 { | |
825 MsnSession *session; | |
826 MsnSwitchBoard *swboard; | |
827 | |
828 session = gc->proto_data; | |
829 swboard = msn_session_get_swboard(session, who, MSN_SB_FLAG_IM); | |
830 | |
831 msn_switchboard_send_msg(swboard, msg, TRUE); | |
832 } | |
833 else | |
834 { | |
835 char *body_str, *body_enc, *pre, *post; | |
836 const char *format; | |
837 MsnIMData *imdata = g_new0(MsnIMData, 1); | |
838 /* | |
839 * In MSN, you can't send messages to yourself, so | |
840 * we'll fake like we received it ;) | |
841 */ | |
842 body_str = msn_message_to_string(msg); | |
843 body_enc = g_markup_escape_text(body_str, -1); | |
844 g_free(body_str); | |
845 | |
846 format = msn_message_get_attr(msg, "X-MMS-IM-Format"); | |
847 msn_parse_format(format, &pre, &post); | |
848 body_str = g_strdup_printf("%s%s%s", pre ? pre : "", | |
849 body_enc ? body_enc : "", post ? post : ""); | |
850 g_free(body_enc); | |
851 g_free(pre); | |
852 g_free(post); | |
853 | |
854 serv_got_typing_stopped(gc, who); | |
855 imdata->gc = gc; | |
856 imdata->who = who; | |
857 imdata->msg = body_str; | |
858 imdata->flags = flags; | |
859 imdata->when = time(NULL); | |
860 g_idle_add(msn_send_me_im, imdata); | |
861 } | |
862 | |
863 msn_message_destroy(msg); | |
864 | |
865 return 1; | |
866 } | |
867 | |
868 static unsigned int | |
869 msn_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state) | |
870 { | |
871 PurpleAccount *account; | |
872 MsnSession *session; | |
873 MsnSwitchBoard *swboard; | |
874 MsnMessage *msg; | |
875 | |
876 account = purple_connection_get_account(gc); | |
877 session = gc->proto_data; | |
878 | |
879 /* | |
880 * TODO: I feel like this should be "if (state != PURPLE_TYPING)" | |
881 * but this is how it was before, and I don't want to break | |
882 * anything. --KingAnt | |
883 */ | |
884 if (state == PURPLE_NOT_TYPING) | |
885 return 0; | |
886 | |
887 if (!g_ascii_strcasecmp(who, purple_account_get_username(account))) | |
888 { | |
889 /* We'll just fake it, since we're sending to ourself. */ | |
890 serv_got_typing(gc, who, MSN_TYPING_RECV_TIMEOUT, PURPLE_TYPING); | |
891 | |
892 return MSN_TYPING_SEND_TIMEOUT; | |
893 } | |
894 | |
895 swboard = msn_session_find_swboard(session, who); | |
896 | |
897 if (swboard == NULL || !msn_switchboard_can_send(swboard)) | |
898 return 0; | |
899 | |
900 swboard->flag |= MSN_SB_FLAG_IM; | |
901 | |
902 msg = msn_message_new(MSN_MSG_TYPING); | |
903 msn_message_set_content_type(msg, "text/x-msmsgscontrol"); | |
904 msn_message_set_flag(msg, 'U'); | |
905 msn_message_set_attr(msg, "TypingUser", | |
906 purple_account_get_username(account)); | |
907 msn_message_set_bin_data(msg, "\r\n", 2); | |
908 | |
909 msn_switchboard_send_msg(swboard, msg, FALSE); | |
910 | |
911 msn_message_destroy(msg); | |
912 | |
913 return MSN_TYPING_SEND_TIMEOUT; | |
914 } | |
915 | |
916 static void | |
917 msn_set_status(PurpleAccount *account, PurpleStatus *status) | |
918 { | |
919 PurpleConnection *gc; | |
920 MsnSession *session; | |
921 | |
922 gc = purple_account_get_connection(account); | |
923 | |
924 if (gc != NULL) | |
925 { | |
926 session = gc->proto_data; | |
927 msn_change_status(session); | |
928 } | |
929 } | |
930 | |
931 static void | |
932 msn_set_idle(PurpleConnection *gc, int idle) | |
933 { | |
934 MsnSession *session; | |
935 | |
936 session = gc->proto_data; | |
937 | |
938 msn_change_status(session); | |
939 } | |
940 | |
941 #if 0 | |
942 static void | |
943 fake_userlist_add_buddy(MsnUserList *userlist, | |
944 const char *who, int list_id, | |
945 const char *group_name) | |
946 { | |
947 MsnUser *user; | |
948 static int group_id_c = 1; | |
949 int group_id; | |
950 | |
951 group_id = -1; | |
952 | |
953 if (group_name != NULL) | |
954 { | |
955 MsnGroup *group; | |
956 group = msn_group_new(userlist, group_id_c, group_name); | |
957 group_id = group_id_c++; | |
958 } | |
959 | |
960 user = msn_userlist_find_user(userlist, who); | |
961 | |
962 if (user == NULL) | |
963 { | |
964 user = msn_user_new(userlist, who, NULL); | |
965 msn_userlist_add_user(userlist, user); | |
966 } | |
967 else | |
968 if (user->list_op & (1 << list_id)) | |
969 { | |
970 if (list_id == MSN_LIST_FL) | |
971 { | |
972 if (group_id >= 0) | |
973 if (g_list_find(user->group_ids, | |
974 GINT_TO_POINTER(group_id))) | |
975 return; | |
976 } | |
977 else | |
978 return; | |
979 } | |
980 | |
981 if (group_id >= 0) | |
982 { | |
983 user->group_ids = g_list_append(user->group_ids, | |
984 GINT_TO_POINTER(group_id)); | |
985 } | |
986 | |
987 user->list_op |= (1 << list_id); | |
988 } | |
989 #endif | |
990 | |
991 static void | |
992 msn_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) | |
993 { | |
994 MsnSession *session; | |
995 MsnUserList *userlist; | |
996 const char *who; | |
997 | |
998 session = gc->proto_data; | |
999 userlist = session->userlist; | |
1000 who = msn_normalize(gc->account, buddy->name); | |
1001 | |
1002 if (!session->logged_in) | |
1003 { | |
1004 #if 0 | |
1005 fake_userlist_add_buddy(session->sync_userlist, who, MSN_LIST_FL, | |
1006 group ? group->name : NULL); | |
1007 #else | |
1008 purple_debug_error("msn", "msn_add_buddy called before connected\n"); | |
1009 #endif | |
1010 | |
1011 return; | |
1012 } | |
1013 | |
1014 #if 0 | |
1015 if (group != NULL && group->name != NULL) | |
1016 purple_debug_info("msn", "msn_add_buddy: %s, %s\n", who, group->name); | |
1017 else | |
1018 purple_debug_info("msn", "msn_add_buddy: %s\n", who); | |
1019 #endif | |
1020 | |
1021 #if 0 | |
1022 /* Which is the max? */ | |
1023 if (session->fl_users_count >= 150) | |
1024 { | |
1025 purple_debug_info("msn", "Too many buddies\n"); | |
1026 /* Buddy list full */ | |
1027 /* TODO: purple should be notified of this */ | |
1028 return; | |
1029 } | |
1030 #endif | |
1031 | |
1032 /* XXX - Would group ever be NULL here? I don't think so... | |
1033 * shx: Yes it should; MSN handles non-grouped buddies, and this is only | |
1034 * internal. */ | |
1035 msn_userlist_add_buddy(userlist, who, MSN_LIST_FL, | |
1036 group ? group->name : NULL); | |
1037 } | |
1038 | |
1039 static void | |
1040 msn_rem_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) | |
1041 { | |
1042 MsnSession *session; | |
1043 MsnUserList *userlist; | |
1044 | |
1045 session = gc->proto_data; | |
1046 userlist = session->userlist; | |
1047 | |
1048 if (!session->logged_in) | |
1049 return; | |
1050 | |
1051 /* XXX - Does buddy->name need to be msn_normalize'd here? --KingAnt */ | |
1052 msn_userlist_rem_buddy(userlist, buddy->name, MSN_LIST_FL, group->name); | |
1053 } | |
1054 | |
1055 static void | |
1056 msn_add_permit(PurpleConnection *gc, const char *who) | |
1057 { | |
1058 MsnSession *session; | |
1059 MsnUserList *userlist; | |
1060 MsnUser *user; | |
1061 | |
1062 session = gc->proto_data; | |
1063 userlist = session->userlist; | |
1064 user = msn_userlist_find_user(userlist, who); | |
1065 | |
1066 if (!session->logged_in) | |
1067 return; | |
1068 | |
1069 if (user != NULL && user->list_op & MSN_LIST_BL_OP) | |
1070 msn_userlist_rem_buddy(userlist, who, MSN_LIST_BL, NULL); | |
1071 | |
1072 msn_userlist_add_buddy(userlist, who, MSN_LIST_AL, NULL); | |
1073 } | |
1074 | |
1075 static void | |
1076 msn_add_deny(PurpleConnection *gc, const char *who) | |
1077 { | |
1078 MsnSession *session; | |
1079 MsnUserList *userlist; | |
1080 MsnUser *user; | |
1081 | |
1082 session = gc->proto_data; | |
1083 userlist = session->userlist; | |
1084 user = msn_userlist_find_user(userlist, who); | |
1085 | |
1086 if (!session->logged_in) | |
1087 return; | |
1088 | |
1089 if (user != NULL && user->list_op & MSN_LIST_AL_OP) | |
1090 msn_userlist_rem_buddy(userlist, who, MSN_LIST_AL, NULL); | |
1091 | |
1092 msn_userlist_add_buddy(userlist, who, MSN_LIST_BL, NULL); | |
1093 } | |
1094 | |
1095 static void | |
1096 msn_rem_permit(PurpleConnection *gc, const char *who) | |
1097 { | |
1098 MsnSession *session; | |
1099 MsnUserList *userlist; | |
1100 MsnUser *user; | |
1101 | |
1102 session = gc->proto_data; | |
1103 userlist = session->userlist; | |
1104 | |
1105 if (!session->logged_in) | |
1106 return; | |
1107 | |
1108 user = msn_userlist_find_user(userlist, who); | |
1109 | |
1110 msn_userlist_rem_buddy(userlist, who, MSN_LIST_AL, NULL); | |
1111 | |
1112 if (user != NULL && user->list_op & MSN_LIST_RL_OP) | |
1113 msn_userlist_add_buddy(userlist, who, MSN_LIST_BL, NULL); | |
1114 } | |
1115 | |
1116 static void | |
1117 msn_rem_deny(PurpleConnection *gc, const char *who) | |
1118 { | |
1119 MsnSession *session; | |
1120 MsnUserList *userlist; | |
1121 MsnUser *user; | |
1122 | |
1123 session = gc->proto_data; | |
1124 userlist = session->userlist; | |
1125 | |
1126 if (!session->logged_in) | |
1127 return; | |
1128 | |
1129 user = msn_userlist_find_user(userlist, who); | |
1130 | |
1131 msn_userlist_rem_buddy(userlist, who, MSN_LIST_BL, NULL); | |
1132 | |
1133 if (user != NULL && user->list_op & MSN_LIST_RL_OP) | |
1134 msn_userlist_add_buddy(userlist, who, MSN_LIST_AL, NULL); | |
1135 } | |
1136 | |
1137 static void | |
1138 msn_set_permit_deny(PurpleConnection *gc) | |
1139 { | |
1140 PurpleAccount *account; | |
1141 MsnSession *session; | |
1142 MsnCmdProc *cmdproc; | |
1143 | |
1144 account = purple_connection_get_account(gc); | |
1145 session = gc->proto_data; | |
1146 cmdproc = session->notification->cmdproc; | |
1147 | |
1148 if (account->perm_deny == PURPLE_PRIVACY_ALLOW_ALL || | |
1149 account->perm_deny == PURPLE_PRIVACY_DENY_USERS) | |
1150 { | |
1151 msn_cmdproc_send(cmdproc, "BLP", "%s", "AL"); | |
1152 } | |
1153 else | |
1154 { | |
1155 msn_cmdproc_send(cmdproc, "BLP", "%s", "BL"); | |
1156 } | |
1157 } | |
1158 | |
1159 static void | |
1160 msn_chat_invite(PurpleConnection *gc, int id, const char *msg, | |
1161 const char *who) | |
1162 { | |
1163 MsnSession *session; | |
1164 MsnSwitchBoard *swboard; | |
1165 | |
1166 session = gc->proto_data; | |
1167 | |
1168 swboard = msn_session_find_swboard_with_id(session, id); | |
1169 | |
1170 if (swboard == NULL) | |
1171 { | |
1172 /* if we have no switchboard, everyone else left the chat already */ | |
1173 swboard = msn_switchboard_new(session); | |
1174 msn_switchboard_request(swboard); | |
1175 swboard->chat_id = id; | |
1176 swboard->conv = purple_find_chat(gc, id); | |
1177 } | |
1178 | |
1179 swboard->flag |= MSN_SB_FLAG_IM; | |
1180 | |
1181 msn_switchboard_request_add_user(swboard, who); | |
1182 } | |
1183 | |
1184 static void | |
1185 msn_chat_leave(PurpleConnection *gc, int id) | |
1186 { | |
1187 MsnSession *session; | |
1188 MsnSwitchBoard *swboard; | |
1189 PurpleConversation *conv; | |
1190 | |
1191 session = gc->proto_data; | |
1192 | |
1193 swboard = msn_session_find_swboard_with_id(session, id); | |
1194 | |
1195 /* if swboard is NULL we were the only person left anyway */ | |
1196 if (swboard == NULL) | |
1197 return; | |
1198 | |
1199 conv = swboard->conv; | |
1200 | |
1201 msn_switchboard_release(swboard, MSN_SB_FLAG_IM); | |
1202 | |
1203 /* If other switchboards managed to associate themselves with this | |
1204 * conv, make sure they know it's gone! */ | |
1205 if (conv != NULL) | |
1206 { | |
1207 while ((swboard = msn_session_find_swboard_with_conv(session, conv)) != NULL) | |
1208 swboard->conv = NULL; | |
1209 } | |
1210 } | |
1211 | |
1212 static int | |
1213 msn_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags) | |
1214 { | |
1215 PurpleAccount *account; | |
1216 MsnSession *session; | |
1217 MsnSwitchBoard *swboard; | |
1218 MsnMessage *msg; | |
1219 char *msgformat; | |
1220 char *msgtext; | |
1221 | |
1222 account = purple_connection_get_account(gc); | |
1223 session = gc->proto_data; | |
1224 swboard = msn_session_find_swboard_with_id(session, id); | |
1225 | |
1226 if (swboard == NULL) | |
1227 return -EINVAL; | |
1228 | |
1229 if (!swboard->ready) | |
1230 return 0; | |
1231 | |
1232 swboard->flag |= MSN_SB_FLAG_IM; | |
1233 | |
1234 msn_import_html(message, &msgformat, &msgtext); | |
1235 | |
1236 if (strlen(msgtext) + strlen(msgformat) + strlen(DISPLAY_VERSION) > 1564) | |
1237 { | |
1238 g_free(msgformat); | |
1239 g_free(msgtext); | |
1240 | |
1241 return -E2BIG; | |
1242 } | |
1243 | |
1244 msg = msn_message_new_plain(msgtext); | |
1245 msn_message_set_attr(msg, "X-MMS-IM-Format", msgformat); | |
1246 msn_switchboard_send_msg(swboard, msg, FALSE); | |
1247 msn_message_destroy(msg); | |
1248 | |
1249 g_free(msgformat); | |
1250 g_free(msgtext); | |
1251 | |
1252 serv_got_chat_in(gc, id, purple_account_get_username(account), 0, | |
1253 message, time(NULL)); | |
1254 | |
1255 return 0; | |
1256 } | |
1257 | |
1258 static void | |
1259 msn_keepalive(PurpleConnection *gc) | |
1260 { | |
1261 MsnSession *session; | |
1262 | |
1263 session = gc->proto_data; | |
1264 | |
1265 if (!session->http_method) | |
1266 { | |
1267 MsnCmdProc *cmdproc; | |
1268 | |
1269 cmdproc = session->notification->cmdproc; | |
1270 | |
1271 msn_cmdproc_send_quick(cmdproc, "PNG", NULL, NULL); | |
1272 } | |
1273 } | |
1274 | |
1275 static void | |
1276 msn_group_buddy(PurpleConnection *gc, const char *who, | |
1277 const char *old_group_name, const char *new_group_name) | |
1278 { | |
1279 MsnSession *session; | |
1280 MsnUserList *userlist; | |
1281 | |
1282 session = gc->proto_data; | |
1283 userlist = session->userlist; | |
1284 | |
1285 msn_userlist_move_buddy(userlist, who, old_group_name, new_group_name); | |
1286 } | |
1287 | |
1288 static void | |
1289 msn_rename_group(PurpleConnection *gc, const char *old_name, | |
1290 PurpleGroup *group, GList *moved_buddies) | |
1291 { | |
1292 MsnSession *session; | |
1293 MsnCmdProc *cmdproc; | |
1294 int old_gid; | |
1295 const char *enc_new_group_name; | |
1296 | |
1297 session = gc->proto_data; | |
1298 cmdproc = session->notification->cmdproc; | |
1299 enc_new_group_name = purple_url_encode(group->name); | |
1300 | |
1301 old_gid = msn_userlist_find_group_id(session->userlist, old_name); | |
1302 | |
1303 if (old_gid >= 0) | |
1304 { | |
1305 msn_cmdproc_send(cmdproc, "REG", "%d %s 0", old_gid, | |
1306 enc_new_group_name); | |
1307 } | |
1308 else | |
1309 { | |
1310 msn_cmdproc_send(cmdproc, "ADG", "%s 0", enc_new_group_name); | |
1311 } | |
1312 } | |
1313 | |
1314 static void | |
1315 msn_convo_closed(PurpleConnection *gc, const char *who) | |
1316 { | |
1317 MsnSession *session; | |
1318 MsnSwitchBoard *swboard; | |
1319 PurpleConversation *conv; | |
1320 | |
1321 session = gc->proto_data; | |
1322 | |
1323 swboard = msn_session_find_swboard(session, who); | |
1324 | |
1325 /* | |
1326 * Don't perform an assertion here. If swboard is NULL, then the | |
1327 * switchboard was either closed by the other party, or the person | |
1328 * is talking to himself. | |
1329 */ | |
1330 if (swboard == NULL) | |
1331 return; | |
1332 | |
1333 conv = swboard->conv; | |
1334 | |
1335 /* If we release the switchboard here, it may still have messages | |
1336 pending ACK which would result in incorrect unsent message errors. | |
1337 Just let it timeout... This is *so* going to screw with people who | |
1338 use dumb clients that report "User has closed the conversation window" */ | |
1339 /* msn_switchboard_release(swboard, MSN_SB_FLAG_IM); */ | |
1340 swboard->conv = NULL; | |
1341 | |
1342 /* If other switchboards managed to associate themselves with this | |
1343 * conv, make sure they know it's gone! */ | |
1344 if (conv != NULL) | |
1345 { | |
1346 while ((swboard = msn_session_find_swboard_with_conv(session, conv)) != NULL) | |
1347 swboard->conv = NULL; | |
1348 } | |
1349 } | |
1350 | |
1351 static void | |
1352 msn_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img) | |
1353 { | |
1354 MsnSession *session; | |
1355 MsnUser *user; | |
1356 | |
1357 session = gc->proto_data; | |
1358 user = session->user; | |
1359 | |
1360 msn_user_set_buddy_icon(user, img); | |
1361 | |
1362 msn_change_status(session); | |
1363 } | |
1364 | |
1365 static void | |
1366 msn_remove_group(PurpleConnection *gc, PurpleGroup *group) | |
1367 { | |
1368 MsnSession *session; | |
1369 MsnCmdProc *cmdproc; | |
1370 int group_id; | |
1371 | |
1372 session = gc->proto_data; | |
1373 cmdproc = session->notification->cmdproc; | |
1374 | |
1375 if ((group_id = msn_userlist_find_group_id(session->userlist, group->name)) >= 0) | |
1376 { | |
1377 msn_cmdproc_send(cmdproc, "RMG", "%d", group_id); | |
1378 } | |
1379 } | |
1380 | |
1381 /** | |
1382 * Extract info text from info_data and add it to user_info | |
1383 */ | |
1384 static gboolean | |
1385 msn_tooltip_extract_info_text(PurpleNotifyUserInfo *user_info, MsnGetInfoData *info_data) | |
1386 { | |
1387 PurpleBuddy *b; | |
1388 | |
1389 b = purple_find_buddy(purple_connection_get_account(info_data->gc), | |
1390 info_data->name); | |
1391 | |
1392 if (b) | |
1393 { | |
1394 char *tmp; | |
1395 | |
1396 if (b->alias && b->alias[0]) | |
1397 { | |
1398 char *aliastext = g_markup_escape_text(b->alias, -1); | |
1399 purple_notify_user_info_add_pair(user_info, _("Alias"), aliastext); | |
1400 g_free(aliastext); | |
1401 } | |
1402 | |
1403 if (b->server_alias) | |
1404 { | |
1405 char *nicktext = g_markup_escape_text(b->server_alias, -1); | |
1406 tmp = g_strdup_printf("<font sml=\"msn\">%s</font><br>", nicktext); | |
1407 purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp); | |
1408 g_free(tmp); | |
1409 g_free(nicktext); | |
1410 } | |
1411 | |
1412 /* Add the tooltip information */ | |
1413 msn_tooltip_text(b, user_info, TRUE); | |
1414 | |
1415 return TRUE; | |
1416 } | |
1417 | |
1418 return FALSE; | |
1419 } | |
1420 | |
1421 #if PHOTO_SUPPORT | |
1422 | |
1423 static char * | |
1424 msn_get_photo_url(const char *url_text) | |
1425 { | |
1426 char *p, *q; | |
1427 | |
1428 if ((p = strstr(url_text, " contactparams:photopreauthurl=\"")) != NULL) | |
1429 { | |
1430 p += strlen(" contactparams:photopreauthurl=\""); | |
1431 } | |
1432 | |
1433 if (p && (strncmp(p, "http://", 8) == 0) && ((q = strchr(p, '"')) != NULL)) | |
1434 return g_strndup(p, q - p); | |
1435 | |
1436 return NULL; | |
1437 } | |
1438 | |
1439 static void msn_got_photo(PurpleUtilFetchUrlData *url_data, gpointer data, | |
1440 const gchar *url_text, size_t len, const gchar *error_message); | |
1441 | |
1442 #endif | |
1443 | |
1444 #if 0 | |
1445 static char *msn_info_date_reformat(const char *field, size_t len) | |
1446 { | |
1447 char *tmp = g_strndup(field, len); | |
1448 time_t t = purple_str_to_time(tmp, FALSE, NULL, NULL, NULL); | |
1449 | |
1450 g_free(tmp); | |
1451 return g_strdup(purple_date_format_short(localtime(&t))); | |
1452 } | |
1453 #endif | |
1454 | |
1455 #define MSN_GOT_INFO_GET_FIELD(a, b) \ | |
1456 found = purple_markup_extract_info_field(stripped, stripped_len, user_info, \ | |
1457 "\n" a ":", 0, "\n", 0, "Undisclosed", b, 0, NULL, NULL); \ | |
1458 if (found) \ | |
1459 sect_info = TRUE; | |
1460 | |
1461 #define MSN_GOT_INFO_GET_FIELD_NO_SEARCH(a, b) \ | |
1462 found = purple_markup_extract_info_field(stripped, stripped_len, user_info, \ | |
1463 "\n" a ":", 0, "\n", 0, "Undisclosed", b, 0, NULL, msn_info_strip_search_link); \ | |
1464 if (found) \ | |
1465 sect_info = TRUE; | |
1466 | |
1467 static char * | |
1468 msn_info_strip_search_link(const char *field, size_t len) | |
1469 { | |
1470 const char *c; | |
1471 if ((c = strstr(field, " (http://spaces.live.com/default.aspx?page=searchresults")) == NULL && | |
1472 (c = strstr(field, " (http://spaces.msn.com/default.aspx?page=searchresults")) == NULL) | |
1473 return g_strndup(field, len); | |
1474 return g_strndup(field, c - field); | |
1475 } | |
1476 | |
1477 static void | |
1478 msn_got_info(PurpleUtilFetchUrlData *url_data, gpointer data, | |
1479 const gchar *url_text, size_t len, const gchar *error_message) | |
1480 { | |
1481 MsnGetInfoData *info_data = (MsnGetInfoData *)data; | |
1482 PurpleNotifyUserInfo *user_info; | |
1483 char *stripped, *p, *q, *tmp; | |
1484 char *user_url = NULL; | |
1485 gboolean found; | |
1486 gboolean has_tooltip_text = FALSE; | |
1487 gboolean has_info = FALSE; | |
1488 gboolean sect_info = FALSE; | |
1489 gboolean has_contact_info = FALSE; | |
1490 char *url_buffer; | |
1491 int stripped_len; | |
1492 #if PHOTO_SUPPORT | |
1493 char *photo_url_text = NULL; | |
1494 MsnGetInfoStepTwoData *info2_data = NULL; | |
1495 #endif | |
1496 | |
1497 purple_debug_info("msn", "In msn_got_info\n"); | |
1498 | |
1499 /* Make sure the connection is still valid */ | |
1500 if (g_list_find(purple_connections_get_all(), info_data->gc) == NULL) | |
1501 { | |
1502 purple_debug_warning("msn", "invalid connection. ignoring buddy info.\n"); | |
1503 g_free(info_data->name); | |
1504 g_free(info_data); | |
1505 return; | |
1506 } | |
1507 | |
1508 user_info = purple_notify_user_info_new(); | |
1509 has_tooltip_text = msn_tooltip_extract_info_text(user_info, info_data); | |
1510 | |
1511 if (error_message != NULL || url_text == NULL || strcmp(url_text, "") == 0) | |
1512 { | |
1513 tmp = g_strdup_printf("<b>%s</b>", _("Error retrieving profile")); | |
1514 purple_notify_user_info_add_pair(user_info, NULL, tmp); | |
1515 g_free(tmp); | |
1516 | |
1517 purple_notify_userinfo(info_data->gc, info_data->name, user_info, NULL, NULL); | |
1518 purple_notify_user_info_destroy(user_info); | |
1519 | |
1520 g_free(info_data->name); | |
1521 g_free(info_data); | |
1522 return; | |
1523 } | |
1524 | |
1525 url_buffer = g_strdup(url_text); | |
1526 | |
1527 /* If they have a homepage link, MSN masks it such that we need to | |
1528 * fetch the url out before purple_markup_strip_html() nukes it */ | |
1529 /* I don't think this works with the new spaces profiles - Stu 3/2/06 */ | |
1530 if ((p = strstr(url_text, | |
1531 "Take a look at my </font><A class=viewDesc title=\"")) != NULL) | |
1532 { | |
1533 p += 50; | |
1534 | |
1535 if ((q = strchr(p, '"')) != NULL) | |
1536 user_url = g_strndup(p, q - p); | |
1537 } | |
1538 | |
1539 /* | |
1540 * purple_markup_strip_html() doesn't strip out character entities like | |
1541 * and · | |
1542 */ | |
1543 while ((p = strstr(url_buffer, " ")) != NULL) | |
1544 { | |
1545 *p = ' '; /* Turn 's into ordinary blanks */ | |
1546 p += 1; | |
1547 memmove(p, p + 5, strlen(p + 5)); | |
1548 url_buffer[strlen(url_buffer) - 5] = '\0'; | |
1549 } | |
1550 | |
1551 while ((p = strstr(url_buffer, "·")) != NULL) | |
1552 { | |
1553 memmove(p, p + 6, strlen(p + 6)); | |
1554 url_buffer[strlen(url_buffer) - 6] = '\0'; | |
1555 } | |
1556 | |
1557 /* Nuke the nasty \r's that just get in the way */ | |
1558 purple_str_strip_char(url_buffer, '\r'); | |
1559 | |
1560 /* MSN always puts in ' for apostrophes...replace them */ | |
1561 while ((p = strstr(url_buffer, "'")) != NULL) | |
1562 { | |
1563 *p = '\''; | |
1564 memmove(p + 1, p + 5, strlen(p + 5)); | |
1565 url_buffer[strlen(url_buffer) - 4] = '\0'; | |
1566 } | |
1567 | |
1568 /* Nuke the html, it's easier than trying to parse the horrid stuff */ | |
1569 stripped = purple_markup_strip_html(url_buffer); | |
1570 stripped_len = strlen(stripped); | |
1571 | |
1572 purple_debug_misc("msn", "stripped = %p\n", stripped); | |
1573 purple_debug_misc("msn", "url_buffer = %p\n", url_buffer); | |
1574 | |
1575 /* General section header */ | |
1576 if (has_tooltip_text) | |
1577 purple_notify_user_info_add_section_break(user_info); | |
1578 | |
1579 purple_notify_user_info_add_section_header(user_info, _("General")); | |
1580 | |
1581 /* Extract their Name and put it in */ | |
1582 MSN_GOT_INFO_GET_FIELD("Name", _("Name")); | |
1583 | |
1584 /* General */ | |
1585 MSN_GOT_INFO_GET_FIELD("Nickname", _("Nickname")); | |
1586 MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Age", _("Age")); | |
1587 MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Gender", _("Gender")); | |
1588 MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Occupation", _("Occupation")); | |
1589 MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Location", _("Location")); | |
1590 | |
1591 /* Extract their Interests and put it in */ | |
1592 found = purple_markup_extract_info_field(stripped, stripped_len, user_info, | |
1593 "\nInterests\t", 0, " (/default.aspx?page=searchresults", 0, | |
1594 "Undisclosed", _("Hobbies and Interests") /* _("Interests") */, | |
1595 0, NULL, NULL); | |
1596 | |
1597 if (found) | |
1598 sect_info = TRUE; | |
1599 | |
1600 MSN_GOT_INFO_GET_FIELD("More about me", _("A Little About Me")); | |
1601 | |
1602 if (sect_info) | |
1603 { | |
1604 has_info = TRUE; | |
1605 sect_info = FALSE; | |
1606 } | |
1607 else | |
1608 { | |
1609 /* Remove the section header */ | |
1610 purple_notify_user_info_remove_last_item(user_info); | |
1611 if (has_tooltip_text) | |
1612 purple_notify_user_info_remove_last_item(user_info); | |
1613 } | |
1614 | |
1615 /* Social */ | |
1616 purple_notify_user_info_add_section_break(user_info); | |
1617 purple_notify_user_info_add_section_header(user_info, _("Social")); | |
1618 | |
1619 MSN_GOT_INFO_GET_FIELD("Marital status", _("Marital Status")); | |
1620 MSN_GOT_INFO_GET_FIELD("Interested in", _("Interests")); | |
1621 MSN_GOT_INFO_GET_FIELD("Pets", _("Pets")); | |
1622 MSN_GOT_INFO_GET_FIELD("Hometown", _("Hometown")); | |
1623 MSN_GOT_INFO_GET_FIELD("Places lived", _("Places Lived")); | |
1624 MSN_GOT_INFO_GET_FIELD("Fashion", _("Fashion")); | |
1625 MSN_GOT_INFO_GET_FIELD("Humor", _("Humor")); | |
1626 MSN_GOT_INFO_GET_FIELD("Music", _("Music")); | |
1627 MSN_GOT_INFO_GET_FIELD("Favorite quote", _("Favorite Quote")); | |
1628 | |
1629 if (sect_info) | |
1630 { | |
1631 has_info = TRUE; | |
1632 sect_info = FALSE; | |
1633 } | |
1634 else | |
1635 { | |
1636 /* Remove the section header */ | |
1637 purple_notify_user_info_remove_last_item(user_info); | |
1638 purple_notify_user_info_remove_last_item(user_info); | |
1639 } | |
1640 | |
1641 /* Contact Info */ | |
1642 /* Personal */ | |
1643 purple_notify_user_info_add_section_break(user_info); | |
1644 purple_notify_user_info_add_section_header(user_info, _("Contact Info")); | |
1645 purple_notify_user_info_add_section_header(user_info, _("Personal")); | |
1646 | |
1647 MSN_GOT_INFO_GET_FIELD("Name", _("Name")); | |
1648 MSN_GOT_INFO_GET_FIELD("Significant other", _("Significant Other")); | |
1649 MSN_GOT_INFO_GET_FIELD("Home phone", _("Home Phone")); | |
1650 MSN_GOT_INFO_GET_FIELD("Home phone 2", _("Home Phone 2")); | |
1651 MSN_GOT_INFO_GET_FIELD("Home address", _("Home Address")); | |
1652 MSN_GOT_INFO_GET_FIELD("Personal Mobile", _("Personal Mobile")); | |
1653 MSN_GOT_INFO_GET_FIELD("Home fax", _("Home Fax")); | |
1654 MSN_GOT_INFO_GET_FIELD("Personal e-mail", _("Personal E-Mail")); | |
1655 MSN_GOT_INFO_GET_FIELD("Personal IM", _("Personal IM")); | |
1656 MSN_GOT_INFO_GET_FIELD("Birthday", _("Birthday")); | |
1657 MSN_GOT_INFO_GET_FIELD("Anniversary", _("Anniversary")); | |
1658 MSN_GOT_INFO_GET_FIELD("Notes", _("Notes")); | |
1659 | |
1660 if (sect_info) | |
1661 { | |
1662 has_info = TRUE; | |
1663 sect_info = FALSE; | |
1664 has_contact_info = TRUE; | |
1665 } | |
1666 else | |
1667 { | |
1668 /* Remove the section header */ | |
1669 purple_notify_user_info_remove_last_item(user_info); | |
1670 } | |
1671 | |
1672 /* Business */ | |
1673 purple_notify_user_info_add_section_header(user_info, _("Work")); | |
1674 MSN_GOT_INFO_GET_FIELD("Name", _("Name")); | |
1675 MSN_GOT_INFO_GET_FIELD("Job title", _("Job Title")); | |
1676 MSN_GOT_INFO_GET_FIELD("Company", _("Company")); | |
1677 MSN_GOT_INFO_GET_FIELD("Department", _("Department")); | |
1678 MSN_GOT_INFO_GET_FIELD("Profession", _("Profession")); | |
1679 MSN_GOT_INFO_GET_FIELD("Work phone 1", _("Work Phone")); | |
1680 MSN_GOT_INFO_GET_FIELD("Work phone 2", _("Work Phone 2")); | |
1681 MSN_GOT_INFO_GET_FIELD("Work address", _("Work Address")); | |
1682 MSN_GOT_INFO_GET_FIELD("Work mobile", _("Work Mobile")); | |
1683 MSN_GOT_INFO_GET_FIELD("Work pager", _("Work Pager")); | |
1684 MSN_GOT_INFO_GET_FIELD("Work fax", _("Work Fax")); | |
1685 MSN_GOT_INFO_GET_FIELD("Work e-mail", _("Work E-Mail")); | |
1686 MSN_GOT_INFO_GET_FIELD("Work IM", _("Work IM")); | |
1687 MSN_GOT_INFO_GET_FIELD("Start date", _("Start Date")); | |
1688 MSN_GOT_INFO_GET_FIELD("Notes", _("Notes")); | |
1689 | |
1690 if (sect_info) | |
1691 { | |
1692 has_info = TRUE; | |
1693 sect_info = FALSE; | |
1694 has_contact_info = TRUE; | |
1695 } | |
1696 else | |
1697 { | |
1698 /* Remove the section header */ | |
1699 purple_notify_user_info_remove_last_item(user_info); | |
1700 } | |
1701 | |
1702 if (!has_contact_info) | |
1703 { | |
1704 /* Remove the Contact Info section header */ | |
1705 purple_notify_user_info_remove_last_item(user_info); | |
1706 } | |
1707 | |
1708 #if 0 /* these probably don't show up any more */ | |
1709 /* | |
1710 * The fields, 'A Little About Me', 'Favorite Things', 'Hobbies | |
1711 * and Interests', 'Favorite Quote', and 'My Homepage' may or may | |
1712 * not appear, in any combination. However, they do appear in | |
1713 * certain order, so we can successively search to pin down the | |
1714 * distinct values. | |
1715 */ | |
1716 | |
1717 /* Check if they have A Little About Me */ | |
1718 found = purple_markup_extract_info_field(stripped, stripped_len, s, | |
1719 " A Little About Me \n\n", 0, "Favorite Things", '\n', NULL, | |
1720 _("A Little About Me"), 0, NULL, NULL); | |
1721 | |
1722 if (!found) | |
1723 { | |
1724 found = purple_markup_extract_info_field(stripped, stripped_len, s, | |
1725 " A Little About Me \n\n", 0, "Hobbies and Interests", '\n', | |
1726 NULL, _("A Little About Me"), 0, NULL, NULL); | |
1727 } | |
1728 | |
1729 if (!found) | |
1730 { | |
1731 found = purple_markup_extract_info_field(stripped, stripped_len, s, | |
1732 " A Little About Me \n\n", 0, "Favorite Quote", '\n', NULL, | |
1733 _("A Little About Me"), 0, NULL, NULL); | |
1734 } | |
1735 | |
1736 if (!found) | |
1737 { | |
1738 found = purple_markup_extract_info_field(stripped, stripped_len, s, | |
1739 " A Little About Me \n\n", 0, "My Homepage \n\nTake a look", | |
1740 '\n', | |
1741 NULL, _("A Little About Me"), 0, NULL, NULL); | |
1742 } | |
1743 | |
1744 if (!found) | |
1745 { | |
1746 purple_markup_extract_info_field(stripped, stripped_len, s, | |
1747 " A Little About Me \n\n", 0, "last updated", '\n', NULL, | |
1748 _("A Little About Me"), 0, NULL, NULL); | |
1749 } | |
1750 | |
1751 if (found) | |
1752 has_info = TRUE; | |
1753 | |
1754 /* Check if they have Favorite Things */ | |
1755 found = purple_markup_extract_info_field(stripped, stripped_len, s, | |
1756 " Favorite Things \n\n", 0, "Hobbies and Interests", '\n', NULL, | |
1757 _("Favorite Things"), 0, NULL, NULL); | |
1758 | |
1759 if (!found) | |
1760 { | |
1761 found = purple_markup_extract_info_field(stripped, stripped_len, s, | |
1762 " Favorite Things \n\n", 0, "Favorite Quote", '\n', NULL, | |
1763 _("Favorite Things"), 0, NULL, NULL); | |
1764 } | |
1765 | |
1766 if (!found) | |
1767 { | |
1768 found = purple_markup_extract_info_field(stripped, stripped_len, s, | |
1769 " Favorite Things \n\n", 0, "My Homepage \n\nTake a look", '\n', | |
1770 NULL, _("Favorite Things"), 0, NULL, NULL); | |
1771 } | |
1772 | |
1773 if (!found) | |
1774 { | |
1775 purple_markup_extract_info_field(stripped, stripped_len, s, | |
1776 " Favorite Things \n\n", 0, "last updated", '\n', NULL, | |
1777 _("Favorite Things"), 0, NULL, NULL); | |
1778 } | |
1779 | |
1780 if (found) | |
1781 has_info = TRUE; | |
1782 | |
1783 /* Check if they have Hobbies and Interests */ | |
1784 found = purple_markup_extract_info_field(stripped, stripped_len, s, | |
1785 " Hobbies and Interests \n\n", 0, "Favorite Quote", '\n', NULL, | |
1786 _("Hobbies and Interests"), 0, NULL, NULL); | |
1787 | |
1788 if (!found) | |
1789 { | |
1790 found = purple_markup_extract_info_field(stripped, stripped_len, s, | |
1791 " Hobbies and Interests \n\n", 0, "My Homepage \n\nTake a look", | |
1792 '\n', NULL, _("Hobbies and Interests"), 0, NULL, NULL); | |
1793 } | |
1794 | |
1795 if (!found) | |
1796 { | |
1797 purple_markup_extract_info_field(stripped, stripped_len, s, | |
1798 " Hobbies and Interests \n\n", 0, "last updated", '\n', NULL, | |
1799 _("Hobbies and Interests"), 0, NULL, NULL); | |
1800 } | |
1801 | |
1802 if (found) | |
1803 has_info = TRUE; | |
1804 | |
1805 /* Check if they have Favorite Quote */ | |
1806 found = purple_markup_extract_info_field(stripped, stripped_len, s, | |
1807 "Favorite Quote \n\n", 0, "My Homepage \n\nTake a look", '\n', NULL, | |
1808 _("Favorite Quote"), 0, NULL, NULL); | |
1809 | |
1810 if (!found) | |
1811 { | |
1812 purple_markup_extract_info_field(stripped, stripped_len, s, | |
1813 "Favorite Quote \n\n", 0, "last updated", '\n', NULL, | |
1814 _("Favorite Quote"), 0, NULL, NULL); | |
1815 } | |
1816 | |
1817 if (found) | |
1818 has_info = TRUE; | |
1819 | |
1820 /* Extract the last updated date and put it in */ | |
1821 found = purple_markup_extract_info_field(stripped, stripped_len, s, | |
1822 " last updated:", 1, "\n", 0, NULL, _("Last Updated"), 0, | |
1823 NULL, msn_info_date_reformat); | |
1824 | |
1825 if (found) | |
1826 has_info = TRUE; | |
1827 #endif | |
1828 | |
1829 /* If we were able to fetch a homepage url earlier, stick it in there */ | |
1830 if (user_url != NULL) | |
1831 { | |
1832 tmp = g_strdup_printf("<a href=\"%s\">%s</a>", user_url, user_url); | |
1833 purple_notify_user_info_add_pair(user_info, _("Homepage"), tmp); | |
1834 g_free(tmp); | |
1835 g_free(user_url); | |
1836 | |
1837 has_info = TRUE; | |
1838 } | |
1839 | |
1840 if (!has_info) | |
1841 { | |
1842 /* MSN doesn't actually distinguish between "unknown member" and | |
1843 * a known member with an empty profile. Try to explain this fact. | |
1844 * Note that if we have a nonempty tooltip_text, we know the user | |
1845 * exists. | |
1846 */ | |
1847 /* This doesn't work with the new spaces profiles - Stu 3/2/06 | |
1848 char *p = strstr(url_buffer, "Unknown Member </TITLE>"); | |
1849 * This might not work for long either ... */ | |
1850 /* Nope, it failed some time before 5/2/07 :( | |
1851 char *p = strstr(url_buffer, "form id=\"SpacesSearch\" name=\"SpacesSearch\""); | |
1852 * Let's see how long this one holds out for ... */ | |
1853 char *p = strstr(url_buffer, "<form id=\"profile_form\" name=\"profile_form\" action=\"http://spaces.live.com/profile.aspx?cid=0\""); | |
1854 PurpleBuddy *b = purple_find_buddy | |
1855 (purple_connection_get_account(info_data->gc), info_data->name); | |
1856 purple_notify_user_info_add_pair(user_info, _("Error retrieving profile"), | |
1857 ((p && b) ? _("The user has not created a public profile.") : | |
1858 (p ? _("MSN reported not being able to find the user's profile. " | |
1859 "This either means that the user does not exist, " | |
1860 "or that the user exists " | |
1861 "but has not created a public profile.") : | |
1862 _("Could not find " /* This should never happen */ | |
1863 "any information in the user's profile. " | |
1864 "The user most likely does not exist.")))); | |
1865 } | |
1866 | |
1867 /* put a link to the actual profile URL */ | |
1868 tmp = g_strdup_printf("<a href=\"%s%s\">%s%s</a>", | |
1869 PROFILE_URL, info_data->name, PROFILE_URL, info_data->name); | |
1870 purple_notify_user_info_add_pair(user_info, _("Profile URL"), tmp); | |
1871 g_free(tmp); | |
1872 | |
1873 #if PHOTO_SUPPORT | |
1874 /* Find the URL to the photo; must be before the marshalling [Bug 994207] */ | |
1875 photo_url_text = msn_get_photo_url(url_text); | |
1876 | |
1877 /* Marshall the existing state */ | |
1878 info2_data = g_malloc0(sizeof(MsnGetInfoStepTwoData)); | |
1879 info2_data->info_data = info_data; | |
1880 info2_data->stripped = stripped; | |
1881 info2_data->url_buffer = url_buffer; | |
1882 info2_data->user_info = user_info; | |
1883 info2_data->photo_url_text = photo_url_text; | |
1884 | |
1885 /* Try to put the photo in there too, if there's one */ | |
1886 if (photo_url_text) | |
1887 { | |
1888 purple_util_fetch_url(photo_url_text, FALSE, NULL, FALSE, msn_got_photo, | |
1889 info2_data); | |
1890 } | |
1891 else | |
1892 { | |
1893 /* Emulate a callback */ | |
1894 /* TODO: Huh? */ | |
1895 msn_got_photo(NULL, info2_data, NULL, 0, NULL); | |
1896 } | |
1897 } | |
1898 | |
1899 static void | |
1900 msn_got_photo(PurpleUtilFetchUrlData *url_data, gpointer user_data, | |
1901 const gchar *url_text, size_t len, const gchar *error_message) | |
1902 { | |
1903 MsnGetInfoStepTwoData *info2_data = (MsnGetInfoStepTwoData *)user_data; | |
1904 int id = -1; | |
1905 | |
1906 /* Unmarshall the saved state */ | |
1907 MsnGetInfoData *info_data = info2_data->info_data; | |
1908 char *stripped = info2_data->stripped; | |
1909 char *url_buffer = info2_data->url_buffer; | |
1910 PurpleNotifyUserInfo *user_info = info2_data->user_info; | |
1911 char *photo_url_text = info2_data->photo_url_text; | |
1912 | |
1913 /* Make sure the connection is still valid if we got here by fetching a photo url */ | |
1914 if (url_text && (error_message != NULL || | |
1915 g_list_find(purple_connections_get_all(), info_data->gc) == NULL)) | |
1916 { | |
1917 purple_debug_warning("msn", "invalid connection. ignoring buddy photo info.\n"); | |
1918 g_free(stripped); | |
1919 g_free(url_buffer); | |
1920 g_free(user_info); | |
1921 g_free(info_data->name); | |
1922 g_free(info_data); | |
1923 g_free(photo_url_text); | |
1924 g_free(info2_data); | |
1925 | |
1926 return; | |
1927 } | |
1928 | |
1929 /* Try to put the photo in there too, if there's one and is readable */ | |
1930 if (user_data && url_text && len != 0) | |
1931 { | |
1932 if (strstr(url_text, "400 Bad Request") | |
1933 || strstr(url_text, "403 Forbidden") | |
1934 || strstr(url_text, "404 Not Found")) | |
1935 { | |
1936 | |
1937 purple_debug_info("msn", "Error getting %s: %s\n", | |
1938 photo_url_text, url_text); | |
1939 } | |
1940 else | |
1941 { | |
1942 char buf[1024]; | |
1943 purple_debug_info("msn", "%s is %d bytes\n", photo_url_text, len); | |
1944 id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL); | |
1945 g_snprintf(buf, sizeof(buf), "<img id=\"%d\"><br>", id); | |
1946 purple_notify_user_info_prepend_pair(user_info, NULL, buf); | |
1947 } | |
1948 } | |
1949 | |
1950 /* We continue here from msn_got_info, as if nothing has happened */ | |
1951 #endif | |
1952 purple_notify_userinfo(info_data->gc, info_data->name, user_info, NULL, NULL); | |
1953 | |
1954 g_free(stripped); | |
1955 g_free(url_buffer); | |
1956 purple_notify_user_info_destroy(user_info); | |
1957 g_free(info_data->name); | |
1958 g_free(info_data); | |
1959 #if PHOTO_SUPPORT | |
1960 g_free(photo_url_text); | |
1961 g_free(info2_data); | |
1962 if (id != -1) | |
1963 purple_imgstore_unref_by_id(id); | |
1964 #endif | |
1965 } | |
1966 | |
1967 static void | |
1968 msn_get_info(PurpleConnection *gc, const char *name) | |
1969 { | |
1970 MsnGetInfoData *data; | |
1971 char *url; | |
1972 | |
1973 data = g_new0(MsnGetInfoData, 1); | |
1974 data->gc = gc; | |
1975 data->name = g_strdup(name); | |
1976 | |
1977 url = g_strdup_printf("%s%s", PROFILE_URL, name); | |
1978 | |
1979 purple_util_fetch_url(url, FALSE, | |
1980 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)", | |
1981 TRUE, msn_got_info, data); | |
1982 | |
1983 g_free(url); | |
1984 } | |
1985 | |
1986 static gboolean msn_load(PurplePlugin *plugin) | |
1987 { | |
1988 msn_notification_init(); | |
1989 msn_switchboard_init(); | |
1990 msn_sync_init(); | |
1991 | |
1992 return TRUE; | |
1993 } | |
1994 | |
1995 static gboolean msn_unload(PurplePlugin *plugin) | |
1996 { | |
1997 msn_notification_end(); | |
1998 msn_switchboard_end(); | |
1999 msn_sync_end(); | |
2000 | |
2001 return TRUE; | |
2002 } | |
2003 | |
2004 static PurpleAccount *find_acct(const char *prpl, const char *acct_id) | |
2005 { | |
2006 PurpleAccount *acct = NULL; | |
2007 | |
2008 /* If we have a specific acct, use it */ | |
2009 if (acct_id) { | |
2010 acct = purple_accounts_find(acct_id, prpl); | |
2011 if (acct && !purple_account_is_connected(acct)) | |
2012 acct = NULL; | |
2013 } else { /* Otherwise find an active account for the protocol */ | |
2014 GList *l = purple_accounts_get_all(); | |
2015 while (l) { | |
2016 if (!strcmp(prpl, purple_account_get_protocol_id(l->data)) | |
2017 && purple_account_is_connected(l->data)) { | |
2018 acct = l->data; | |
2019 break; | |
2020 } | |
2021 l = l->next; | |
2022 } | |
2023 } | |
2024 | |
2025 return acct; | |
2026 } | |
2027 | |
2028 static gboolean msn_uri_handler(const char *proto, const char *cmd, GHashTable *params) | |
2029 { | |
2030 char *acct_id = g_hash_table_lookup(params, "account"); | |
2031 PurpleAccount *acct; | |
2032 | |
2033 if (g_ascii_strcasecmp(proto, "msnim")) | |
2034 return FALSE; | |
2035 | |
2036 acct = find_acct("prpl-msn", acct_id); | |
2037 | |
2038 if (!acct) | |
2039 return FALSE; | |
2040 | |
2041 /* msnim:chat?contact=user@domain.tld */ | |
2042 if (!g_ascii_strcasecmp(cmd, "Chat")) { | |
2043 char *sname = g_hash_table_lookup(params, "contact"); | |
2044 if (sname) { | |
2045 PurpleConversation *conv = purple_find_conversation_with_account( | |
2046 PURPLE_CONV_TYPE_IM, sname, acct); | |
2047 if (conv == NULL) | |
2048 conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, sname); | |
2049 purple_conversation_present(conv); | |
2050 } | |
2051 /*else | |
2052 **If pidgindialogs_im() was in the core, we could use it here. | |
2053 * It is all purple_request_* based, but I'm not sure it really belongs in the core | |
2054 pidgindialogs_im();*/ | |
2055 | |
2056 return TRUE; | |
2057 } | |
2058 /* msnim:add?contact=user@domain.tld */ | |
2059 else if (!g_ascii_strcasecmp(cmd, "Add")) { | |
2060 char *name = g_hash_table_lookup(params, "contact"); | |
2061 purple_blist_request_add_buddy(acct, name, NULL, NULL); | |
2062 return TRUE; | |
2063 } | |
2064 | |
2065 return FALSE; | |
2066 } | |
2067 | |
2068 | |
2069 static PurplePluginProtocolInfo prpl_info = | |
2070 { | |
2071 OPT_PROTO_MAIL_CHECK, | |
2072 NULL, /* user_splits */ | |
2073 NULL, /* protocol_options */ | |
2074 {"png", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_SEND}, /* icon_spec */ | |
2075 msn_list_icon, /* list_icon */ | |
2076 NULL, /* list_emblems */ | |
2077 msn_status_text, /* status_text */ | |
2078 msn_tooltip_text, /* tooltip_text */ | |
2079 msn_status_types, /* away_states */ | |
2080 msn_blist_node_menu, /* blist_node_menu */ | |
2081 NULL, /* chat_info */ | |
2082 NULL, /* chat_info_defaults */ | |
2083 msn_login, /* login */ | |
2084 msn_close, /* close */ | |
2085 msn_send_im, /* send_im */ | |
2086 NULL, /* set_info */ | |
2087 msn_send_typing, /* send_typing */ | |
2088 msn_get_info, /* get_info */ | |
2089 msn_set_status, /* set_away */ | |
2090 msn_set_idle, /* set_idle */ | |
2091 NULL, /* change_passwd */ | |
2092 msn_add_buddy, /* add_buddy */ | |
2093 NULL, /* add_buddies */ | |
2094 msn_rem_buddy, /* remove_buddy */ | |
2095 NULL, /* remove_buddies */ | |
2096 msn_add_permit, /* add_permit */ | |
2097 msn_add_deny, /* add_deny */ | |
2098 msn_rem_permit, /* rem_permit */ | |
2099 msn_rem_deny, /* rem_deny */ | |
2100 msn_set_permit_deny, /* set_permit_deny */ | |
2101 NULL, /* join_chat */ | |
2102 NULL, /* reject chat invite */ | |
2103 NULL, /* get_chat_name */ | |
2104 msn_chat_invite, /* chat_invite */ | |
2105 msn_chat_leave, /* chat_leave */ | |
2106 NULL, /* chat_whisper */ | |
2107 msn_chat_send, /* chat_send */ | |
2108 msn_keepalive, /* keepalive */ | |
2109 NULL, /* register_user */ | |
2110 NULL, /* get_cb_info */ | |
2111 NULL, /* get_cb_away */ | |
2112 NULL, /* alias_buddy */ | |
2113 msn_group_buddy, /* group_buddy */ | |
2114 msn_rename_group, /* rename_group */ | |
2115 NULL, /* buddy_free */ | |
2116 msn_convo_closed, /* convo_closed */ | |
2117 msn_normalize, /* normalize */ | |
2118 msn_set_buddy_icon, /* set_buddy_icon */ | |
2119 msn_remove_group, /* remove_group */ | |
2120 NULL, /* get_cb_real_name */ | |
2121 NULL, /* set_chat_topic */ | |
2122 NULL, /* find_blist_chat */ | |
2123 NULL, /* roomlist_get_list */ | |
2124 NULL, /* roomlist_cancel */ | |
2125 NULL, /* roomlist_expand_category */ | |
2126 msn_can_receive_file, /* can_receive_file */ | |
2127 msn_send_file, /* send_file */ | |
2128 msn_new_xfer, /* new_xfer */ | |
2129 msn_offline_message, /* offline_message */ | |
2130 NULL, /* whiteboard_prpl_ops */ | |
2131 NULL, /* send_raw */ | |
2132 NULL, /* roomlist_room_serialize */ | |
2133 NULL, /* unregister_user */ | |
2134 msn_send_attention, /* send_attention */ | |
2135 msn_attention_types, /* attention_types */ | |
2136 | |
2137 /* padding */ | |
2138 NULL | |
2139 }; | |
2140 | |
2141 static PurplePluginInfo info = | |
2142 { | |
2143 PURPLE_PLUGIN_MAGIC, | |
2144 PURPLE_MAJOR_VERSION, | |
2145 PURPLE_MINOR_VERSION, | |
2146 PURPLE_PLUGIN_PROTOCOL, /**< type */ | |
2147 NULL, /**< ui_requirement */ | |
2148 0, /**< flags */ | |
2149 NULL, /**< dependencies */ | |
2150 PURPLE_PRIORITY_DEFAULT, /**< priority */ | |
2151 | |
2152 "prpl-msn", /**< id */ | |
2153 "MSN", /**< name */ | |
2154 DISPLAY_VERSION, /**< version */ | |
2155 /** summary */ | |
2156 N_("MSN Protocol Plugin"), | |
2157 /** description */ | |
2158 N_("MSN Protocol Plugin"), | |
2159 "Christian Hammond <chipx86@gnupdate.org>", /**< author */ | |
2160 PURPLE_WEBSITE, /**< homepage */ | |
2161 | |
2162 msn_load, /**< load */ | |
2163 msn_unload, /**< unload */ | |
2164 NULL, /**< destroy */ | |
2165 | |
2166 NULL, /**< ui_info */ | |
2167 &prpl_info, /**< extra_info */ | |
2168 NULL, /**< prefs_info */ | |
2169 msn_actions, | |
2170 | |
2171 /* padding */ | |
2172 NULL, | |
2173 NULL, | |
2174 NULL, | |
2175 NULL | |
2176 }; | |
2177 | |
2178 static void | |
2179 init_plugin(PurplePlugin *plugin) | |
2180 { | |
2181 PurpleAccountOption *option; | |
2182 | |
2183 option = purple_account_option_string_new(_("Server"), "server", | |
2184 MSN_SERVER); | |
2185 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, | |
2186 option); | |
2187 | |
2188 option = purple_account_option_int_new(_("Port"), "port", 1863); | |
2189 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, | |
2190 option); | |
2191 | |
2192 option = purple_account_option_bool_new(_("Use HTTP Method"), | |
2193 "http_method", FALSE); | |
2194 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, | |
2195 option); | |
2196 | |
2197 option = purple_account_option_string_new(_("HTTP Method Server"), | |
2198 "http_method_server", MSN_HTTPCONN_SERVER); | |
2199 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, | |
2200 option); | |
2201 | |
2202 option = purple_account_option_bool_new(_("Show custom smileys"), | |
2203 "custom_smileys", TRUE); | |
2204 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, | |
2205 option); | |
2206 | |
2207 purple_cmd_register("nudge", "", PURPLE_CMD_P_PRPL, | |
2208 PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY, | |
2209 "prpl-msn", msn_cmd_nudge, | |
2210 _("nudge: nudge a user to get their attention"), NULL); | |
2211 | |
2212 purple_prefs_remove("/plugins/prpl/msn"); | |
2213 | |
2214 purple_signal_connect(purple_get_core(), "uri-handler", plugin, | |
2215 PURPLE_CALLBACK(msn_uri_handler), NULL); | |
2216 } | |
2217 | |
2218 PURPLE_INIT_PLUGIN(msn, init_plugin, info); |