📄 oscar.c
字号:
oscar_data_addhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_ERROR, purple_parse_locerr, 0); oscar_data_addhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_GOTINFOBLOCK, purple_got_infoblock, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x0001, purple_parse_genericerr, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x000f, purple_selfinfo, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x001f, purple_memrequest, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x0021, oscar_icon_req,0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_RATECHANGE, purple_parse_ratechange, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_REDIRECT, purple_handle_redirect, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_MOTD, purple_parse_motd, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_EVIL, purple_parse_evilnotify, 0); oscar_data_addhandler(od, SNAC_FAMILY_POPUP, 0x0002, purple_popup, 0); oscar_data_addhandler(od, SNAC_FAMILY_USERLOOKUP, SNAC_SUBTYPE_USERLOOKUP_ERROR, purple_parse_searcherror, 0); oscar_data_addhandler(od, SNAC_FAMILY_USERLOOKUP, 0x0003, purple_parse_searchreply, 0); purple_debug_misc("oscar", "oscar_login: gc = %p\n", gc); if (!aim_snvalid(purple_account_get_username(account))) { gchar *buf; buf = g_strdup_printf(_("Unable to login: Could not sign on as %s because the screen name is invalid. Screen names must either start with a letter and contain only letters, numbers and spaces, or contain only numbers."), purple_account_get_username(account)); gc->wants_to_die = TRUE; purple_connection_error(gc, buf); g_free(buf); } if (aim_sn_is_icq((purple_account_get_username(account)))) { od->icq = TRUE; } else { gc->flags |= PURPLE_CONNECTION_HTML; gc->flags |= PURPLE_CONNECTION_AUTO_RESP; } /* Connect to core Purple signals */ purple_prefs_connect_callback(gc, "/plugins/prpl/oscar/recent_buddies", recent_buddies_cb, gc); newconn = flap_connection_new(od, SNAC_FAMILY_AUTH); newconn->connect_data = purple_proxy_connect(NULL, account, purple_account_get_string(account, "server", OSCAR_DEFAULT_LOGIN_SERVER), purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT), connection_established_cb, newconn); if (newconn->connect_data == NULL) { purple_connection_error(gc, _("Couldn't connect to host")); return; } purple_connection_update_progress(gc, _("Connecting"), 0, OSCAR_CONNECT_STEPS); ck[0] = 0x5a;}voidoscar_close(PurpleConnection *gc){ OscarData *od; od = (OscarData *)gc->proto_data; while (od->oscar_chats) { struct chat_connection *cc = od->oscar_chats->data; od->oscar_chats = g_slist_remove(od->oscar_chats, cc); oscar_chat_destroy(cc); } while (od->create_rooms) { struct create_room *cr = od->create_rooms->data; g_free(cr->name); od->create_rooms = g_slist_remove(od->create_rooms, cr); g_free(cr); } oscar_data_destroy(od); gc->proto_data = NULL; purple_prefs_disconnect_by_handle(gc); purple_debug_info("oscar", "Signed off.\n");}static intpurple_parse_auth_resp(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...){ PurpleConnection *gc = od->gc; PurpleAccount *account = gc->account; char *host; int port; int i; FlapConnection *newconn; va_list ap; struct aim_authresp_info *info; port = purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT); va_start(ap, fr); info = va_arg(ap, struct aim_authresp_info *); va_end(ap); purple_debug_info("oscar", "inside auth_resp (Screen name: %s)\n", info->sn); if (info->errorcode || !info->bosip || !info->cookielen || !info->cookie) { char buf[256]; switch (info->errorcode) { case 0x01: /* Unregistered screen name */ gc->wants_to_die = TRUE; purple_connection_error(gc, _("Invalid screen name.")); break; case 0x05: /* Incorrect password */ gc->wants_to_die = TRUE; if (!purple_account_get_remember_password(account)) purple_account_set_password(account, NULL); purple_connection_error(gc, _("Incorrect password.")); break; case 0x11: /* Suspended account */ gc->wants_to_die = TRUE; purple_connection_error(gc, _("Your account is currently suspended.")); break; case 0x14: /* service temporarily unavailable */ purple_connection_error(gc, _("The AOL Instant Messenger service is temporarily unavailable.")); break; case 0x18: /* screen name connecting too frequently */ gc->wants_to_die = TRUE; purple_connection_error(gc, _("You have been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer.")); break; case 0x1c: /* client too old */ gc->wants_to_die = TRUE; g_snprintf(buf, sizeof(buf), _("The client version you are using is too old. Please upgrade at %s"), PURPLE_WEBSITE); purple_connection_error(gc, buf); break; case 0x1d: /* IP address connecting too frequently */ gc->wants_to_die = TRUE; purple_connection_error(gc, _("You have been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer.")); break; default: purple_connection_error(gc, _("Authentication failed")); break; } purple_debug_info("oscar", "Login Error Code 0x%04hx\n", info->errorcode); purple_debug_info("oscar", "Error URL: %s\n", info->errorurl); od->killme = TRUE; return 1; } purple_debug_misc("oscar", "Reg status: %hu\n", info->regstatus); purple_debug_misc("oscar", "E-mail: %s\n", (info->email != NULL) ? info->email : "null"); purple_debug_misc("oscar", "BOSIP: %s\n", info->bosip); purple_debug_info("oscar", "Closing auth connection...\n"); flap_connection_schedule_destroy(conn, OSCAR_DISCONNECT_DONE, NULL); for (i = 0; i < strlen(info->bosip); i++) { if (info->bosip[i] == ':') { port = atoi(&(info->bosip[i+1])); break; } } host = g_strndup(info->bosip, i); newconn = flap_connection_new(od, SNAC_FAMILY_LOCATE); newconn->cookielen = info->cookielen; newconn->cookie = g_memdup(info->cookie, info->cookielen); newconn->connect_data = purple_proxy_connect(NULL, account, host, port, connection_established_cb, newconn); g_free(host); if (newconn->connect_data == NULL) { purple_connection_error(gc, _("Could Not Connect")); od->killme = TRUE; return 0; } purple_connection_update_progress(gc, _("Received authorization"), 3, OSCAR_CONNECT_STEPS); ck[3] = 0x64; return 1;}static voidpurple_parse_auth_securid_request_yes_cb(gpointer user_data, const char *msg){ PurpleConnection *gc = user_data; OscarData *od = gc->proto_data; aim_auth_securid_send(od, msg);}static voidpurple_parse_auth_securid_request_no_cb(gpointer user_data, const char *value){ PurpleConnection *gc = user_data; OscarData *od = gc->proto_data; /* Disconnect */ gc->wants_to_die = TRUE; purple_connection_error(gc, _("The SecurID key entered is invalid.")); od->killme = TRUE;}static intpurple_parse_auth_securid_request(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...){ PurpleConnection *gc = od->gc; PurpleAccount *account = purple_connection_get_account(gc); gchar *primary; purple_debug_info("oscar", "Got SecurID request\n"); primary = g_strdup_printf("Enter the SecurID key for %s.", purple_account_get_username(account)); purple_request_input(gc, NULL, _("Enter SecurID"), primary, _("Enter the 6 digit number from the digital display."), FALSE, FALSE, NULL, _("_OK"), G_CALLBACK(purple_parse_auth_securid_request_yes_cb), _("_Cancel"), G_CALLBACK(purple_parse_auth_securid_request_no_cb), account, NULL, NULL, gc); g_free(primary); return 1;}/* XXX - Should use purple_util_fetch_url for the below stuff */struct pieceofcrap { PurpleConnection *gc; unsigned long offset; unsigned long len; char *modname; int fd; FlapConnection *conn; unsigned int inpa;};static void damn_you(gpointer data, gint source, PurpleInputCondition c){ struct pieceofcrap *pos = data; OscarData *od = pos->gc->proto_data; char in = '\0'; int x = 0; unsigned char m[17]; while (read(pos->fd, &in, 1) == 1) { if (in == '\n') x++; else if (in != '\r') x = 0; if (x == 2) break; in = '\0'; } if (in != '\n') { char buf[256]; g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly. You may want to use TOC until " "this is fixed. Check %s for updates."), PURPLE_WEBSITE); purple_notify_warning(pos->gc, NULL, _("Unable to get a valid AIM login hash."), buf); purple_input_remove(pos->inpa); close(pos->fd); g_free(pos); return; } if (read(pos->fd, m, 16) != 16) { purple_debug_warning("oscar", "Could not read full AIM login hash " "from " AIMHASHDATA "--that's bad.\n"); } m[16] = '\0'; purple_debug_misc("oscar", "Sending hash: "); for (x = 0; x < 16; x++) purple_debug_misc(NULL, "%02hhx ", (unsigned char)m[x]); purple_debug_misc(NULL, "\n"); purple_input_remove(pos->inpa); close(pos->fd); aim_sendmemblock(od, pos->conn, 0, 16, m, AIM_SENDMEMBLOCK_FLAG_ISHASH); g_free(pos);}static voidstraight_to_hell(gpointer data, gint source, const gchar *error_message){ struct pieceofcrap *pos = data; gchar *buf; if (!PURPLE_CONNECTION_IS_VALID(pos->gc)) { g_free(pos->modname); g_free(pos); return; } pos->fd = source; if (source < 0) { buf = g_strdup_printf(_("You may be disconnected shortly. You may want to use TOC until " "this is fixed. Check %s for updates."), PURPLE_WEBSITE); purple_notify_warning(pos->gc, NULL, _("Unable to get a valid AIM login hash."), buf); g_free(buf); g_free(pos->modname); g_free(pos); return; } buf = g_strdup_printf("GET " AIMHASHDATA "?offset=%ld&len=%ld&modname=%s HTTP/1.0\n\n", pos->offset, pos->len, pos->modname ? pos->modname : ""); write(pos->fd, buf, strlen(buf)); g_free(buf); g_free(pos->modname); pos->inpa = purple_input_add(pos->fd, PURPLE_INPUT_READ, damn_you, pos); return;}/* size of icbmui.ocm, the largest module in AIM 3.5 */#define AIM_MAX_FILE_SIZE 98304int purple_memrequest(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { va_list ap; struct pieceofcrap *pos; guint32 offset, len; char *modname; va_start(ap, fr); offset = va_arg(ap, guint32); len = va_arg(ap, guint32); modname = va_arg(ap, char *); va_end(ap); purple_debug_misc("oscar", "offset: %u, len: %u, file: %s\n", offset, len, (modname ? modname : "aim.exe")); if (len == 0) { purple_debug_misc("oscar", "len is 0, hashing NULL\n"); aim_sendmemblock(od, conn, offset, len, NULL, AIM_SENDMEMBLOCK_FLAG_ISREQUEST); return 1; } /* uncomment this when you're convinced it's right. remember, it's been wrong before. */#if 0 if (offset > AIM_MAX_FILE_SIZE || len > AIM_MAX_FILE_SIZE) { char *buf; int i = 8; if (modname) i += strlen(modname); buf = g_malloc(i); i = 0; if (modname) { memcpy(buf, modname, strlen(modname)); i += strlen(modname); } buf[i++] = offset & 0xff; buf[i++] = (offset >> 8) & 0xff; buf[i++] = (offset >> 16) & 0xff; buf[i++] = (offset >> 24) & 0xff; buf[i++] = len & 0xff; buf[i++] = (len >> 8) & 0xff; buf[i++] = (len >> 16) & 0xff; buf[i++] = (len >> 24) & 0xff; purple_debug_misc("oscar", "len + offset is invalid, " "hashing request\n"); aim_sendmemblock(od, command->conn, offset, i, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST); g_free(buf); return 1; }#endif pos = g_new0(struct pieceofcrap, 1); pos->gc = od->gc; pos->conn = conn; pos->offset = offset; pos->len = len; pos->modname = g_strdup(modname); /* TODO: Keep track of this return value. */ if (purple_proxy_connect(NULL, pos->gc->account, "pidgin.im", 80, straight_to_hell, pos) == NULL) { char buf[256]; g_free(pos->modname); g_free(pos); g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly. " "Check %s for updates."), PURPLE_WEBSITE); purple_notify_warning(pos->gc, NULL, _("Unable to get a valid login hash."), buf); } return 1;}static intpurple_parse_login(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...){ PurpleConnection *gc; PurpleAccount *account; ClientInfo info = CLIENTINFO_PURPLE; va_list ap; char *key; gboolean truncate_pass; gc = od->gc; account = purple_connection_get_account(gc); va_start(ap, fr); key = va_arg(ap, char *); truncate_pass = va_arg(ap, int); va_end(ap); aim_send_login(od, conn, purple_account_get_username(account), purple_connection_get_password(gc), truncate_pass,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -