📄 notification.c
字号:
/** * @file notification.c Notification server functions * * purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include "msn.h"#include "notification.h"#include "state.h"#include "error.h"#include "msn-utils.h"#include "page.h"#include "userlist.h"#include "sync.h"#include "slplink.h"static MsnTable *cbs_table;/************************************************************************** * Main **************************************************************************/static voiddestroy_cb(MsnServConn *servconn){ MsnNotification *notification; notification = servconn->cmdproc->data; g_return_if_fail(notification != NULL); msn_notification_destroy(notification);}MsnNotification *msn_notification_new(MsnSession *session){ MsnNotification *notification; MsnServConn *servconn; g_return_val_if_fail(session != NULL, NULL); notification = g_new0(MsnNotification, 1); notification->session = session; notification->servconn = servconn = msn_servconn_new(session, MSN_SERVCONN_NS); msn_servconn_set_destroy_cb(servconn, destroy_cb); notification->cmdproc = servconn->cmdproc; notification->cmdproc->data = notification; notification->cmdproc->cbs_table = cbs_table; return notification;}voidmsn_notification_destroy(MsnNotification *notification){ notification->cmdproc->data = NULL; msn_servconn_set_destroy_cb(notification->servconn, NULL); msn_servconn_destroy(notification->servconn); g_free(notification);}/************************************************************************** * Connect **************************************************************************/static voidconnect_cb(MsnServConn *servconn){ MsnCmdProc *cmdproc; MsnSession *session; PurpleAccount *account; char **a, **c, *vers; int i; g_return_if_fail(servconn != NULL); cmdproc = servconn->cmdproc; session = servconn->session; account = session->account; /* Allocate an array for CVR0, NULL, and all the versions */ a = c = g_new0(char *, session->protocol_ver - 8 + 3); for (i = session->protocol_ver; i >= 8; i--) *c++ = g_strdup_printf("MSNP%d", i); *c++ = g_strdup("CVR0"); vers = g_strjoinv(" ", a); if (session->login_step == MSN_LOGIN_STEP_START) msn_session_set_login_step(session, MSN_LOGIN_STEP_HANDSHAKE); else msn_session_set_login_step(session, MSN_LOGIN_STEP_HANDSHAKE2); msn_cmdproc_send(cmdproc, "VER", "%s", vers); g_strfreev(a); g_free(vers);}gbooleanmsn_notification_connect(MsnNotification *notification, const char *host, int port){ MsnServConn *servconn; g_return_val_if_fail(notification != NULL, FALSE); servconn = notification->servconn; msn_servconn_set_connect_cb(servconn, connect_cb); notification->in_use = msn_servconn_connect(servconn, host, port); return notification->in_use;}voidmsn_notification_disconnect(MsnNotification *notification){ g_return_if_fail(notification != NULL); g_return_if_fail(notification->in_use); msn_servconn_disconnect(notification->servconn); notification->in_use = FALSE;}/************************************************************************** * Util **************************************************************************/static voidgroup_error_helper(MsnSession *session, const char *msg, int group_id, int error){ PurpleAccount *account; PurpleConnection *gc; char *reason = NULL; char *title = NULL; account = session->account; gc = purple_account_get_connection(account); if (error == 224) { if (group_id == 0) { return; } else { const char *group_name; group_name = msn_userlist_find_group_name(session->userlist, group_id); reason = g_strdup_printf(_("%s is not a valid group."), group_name); } } else { reason = g_strdup(_("Unknown error.")); } title = g_strdup_printf(_("%s on %s (%s)"), msg, purple_account_get_username(account), purple_account_get_protocol_name(account)); purple_notify_error(gc, NULL, title, reason); g_free(title); g_free(reason);}/************************************************************************** * Login **************************************************************************/voidmsn_got_login_params(MsnSession *session, const char *login_params){ MsnCmdProc *cmdproc; cmdproc = session->notification->cmdproc; msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_END); msn_cmdproc_send(cmdproc, "USR", "TWN S %s", login_params);}static voidcvr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd){ PurpleAccount *account; account = cmdproc->session->account; msn_cmdproc_send(cmdproc, "USR", "TWN I %s", purple_account_get_username(account));}static voidusr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd){ MsnSession *session; PurpleAccount *account; PurpleConnection *gc; session = cmdproc->session; account = session->account; gc = purple_account_get_connection(account); if (!g_ascii_strcasecmp(cmd->params[1], "OK")) { /* OK */ const char *friendly = purple_url_decode(cmd->params[3]); purple_connection_set_display_name(gc, friendly); msn_session_set_login_step(session, MSN_LOGIN_STEP_SYN); msn_cmdproc_send(cmdproc, "SYN", "%s", "0"); } else if (!g_ascii_strcasecmp(cmd->params[1], "TWN")) { /* Passport authentication */ char **elems, **cur, **tokens; session->nexus = msn_nexus_new(session); /* Parse the challenge data. */ elems = g_strsplit(cmd->params[3], ",", 0); for (cur = elems; *cur != NULL; cur++) { tokens = g_strsplit(*cur, "=", 2); g_hash_table_insert(session->nexus->challenge_data, tokens[0], tokens[1]); /* Don't free each of the tokens, only the array. */ g_free(tokens); } g_strfreev(elems); msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_START); msn_nexus_connect(session->nexus); }}static voidusr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error){ MsnErrorType msnerr = 0; switch (error) { case 500: case 601: case 910: case 921: msnerr = MSN_ERROR_SERV_UNAVAILABLE; break; case 911: msnerr = MSN_ERROR_AUTH; break; default: return; break; } msn_session_set_error(cmdproc->session, msnerr, NULL);}static voidver_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd){ MsnSession *session; PurpleAccount *account; gboolean protocol_supported = FALSE; char proto_str[8]; size_t i; session = cmdproc->session; account = session->account; g_snprintf(proto_str, sizeof(proto_str), "MSNP%d", session->protocol_ver); for (i = 1; i < cmd->param_count; i++) { if (!strcmp(cmd->params[i], proto_str)) { protocol_supported = TRUE; break; } } if (!protocol_supported) { msn_session_set_error(session, MSN_ERROR_UNSUPPORTED_PROTOCOL, NULL); return; } msn_cmdproc_send(cmdproc, "CVR", "0x0409 winnt 5.1 i386 MSNMSGR 6.0.0602 MSMSGS %s", purple_account_get_username(account));}/************************************************************************** * Log out **************************************************************************/static voidout_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd){ if (!g_ascii_strcasecmp(cmd->params[0], "OTH")) msn_session_set_error(cmdproc->session, MSN_ERROR_SIGN_OTHER, NULL); else if (!g_ascii_strcasecmp(cmd->params[0], "SSD")) msn_session_set_error(cmdproc->session, MSN_ERROR_SERV_DOWN, NULL);}voidmsn_notification_close(MsnNotification *notification){ g_return_if_fail(notification != NULL); if (!notification->in_use) return; msn_cmdproc_send_quick(notification->cmdproc, "OUT", NULL, NULL); msn_notification_disconnect(notification);}/************************************************************************** * Messages **************************************************************************/static voidmsg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len){ MsnMessage *msg; msg = msn_message_new_from_cmd(cmdproc->session, cmd); msn_message_parse_payload(msg, payload, len);#ifdef MSN_DEBUG_NS msn_message_show_readable(msg, "Notification", TRUE);#endif msn_cmdproc_process_msg(cmdproc, msg); msn_message_destroy(msg);}static voidmsg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd){ /* NOTE: cmd is not always cmdproc->last_cmd, sometimes cmd is a queued * command and we are processing it */ if (cmd->payload == NULL) { cmdproc->last_cmd->payload_cb = msg_cmd_post; cmdproc->servconn->payload_len = atoi(cmd->params[2]); } else { g_return_if_fail(cmd->payload_cb != NULL); cmd->payload_cb(cmdproc, cmd, cmd->payload, cmd->payload_len); }}/************************************************************************** * Challenges **************************************************************************/static voidchl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd){ MsnTransaction *trans; char buf[33]; const char *challenge_resp; PurpleCipher *cipher; PurpleCipherContext *context; guchar digest[16]; int i; cipher = purple_ciphers_find_cipher("md5"); context = purple_cipher_context_new(cipher, NULL); purple_cipher_context_append(context, (const guchar *)cmd->params[1], strlen(cmd->params[1])); challenge_resp = "VT6PX?UQTM4WM%YR"; purple_cipher_context_append(context, (const guchar *)challenge_resp, strlen(challenge_resp)); purple_cipher_context_digest(context, sizeof(digest), digest, NULL); purple_cipher_context_destroy(context); for (i = 0; i < 16; i++) g_snprintf(buf + (i*2), 3, "%02x", digest[i]); trans = msn_transaction_new(cmdproc, "QRY", "%s 32", "PROD0038W!61ZTF9"); msn_transaction_set_payload(trans, buf, 32); msn_cmdproc_send_trans(cmdproc, trans);}/************************************************************************** * Buddy Lists **************************************************************************/static voidadd_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd){ MsnSession *session; MsnUser *user; const char *list; const char *passport; const char *friendly; MsnListId list_id; int group_id; list = cmd->params[1]; passport = cmd->params[3]; friendly = purple_url_decode(cmd->params[4]); session = cmdproc->session; user = msn_userlist_find_user(session->userlist, passport); if (user == NULL) { user = msn_user_new(session->userlist, passport, friendly); msn_userlist_add_user(session->userlist, user); } else msn_user_set_friendly_name(user, friendly); list_id = msn_get_list_id(list); if (cmd->param_count >= 6) group_id = atoi(cmd->params[5]); else group_id = -1; msn_got_add_user(session, user, list_id, group_id); msn_user_update(user);}static voidadd_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error){ MsnSession *session; PurpleAccount *account; PurpleConnection *gc; const char *list, *passport; char *reason = NULL; char *msg = NULL; char **params; session = cmdproc->session;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -