Mercurial > pidgin
comparison libpurple/protocols/oscar/oscar.c @ 27590:a08e84032814
merge of '2348ff22f0ff3453774b8b25b36238465580c609'
and 'e76f11543c2a4aa05bdf584f087cbe3439029661'
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Sun, 12 Jul 2009 05:43:38 +0000 |
parents | 5048054d319a |
children | bff61dad9a6b bd9df4e45904 |
comparison
equal
deleted
inserted
replaced
27104:048bcf41deef | 27590:a08e84032814 |
---|---|
143 N_("Not while on AOL") | 143 N_("Not while on AOL") |
144 }; | 144 }; |
145 static const int msgerrreasonlen = G_N_ELEMENTS(msgerrreason); | 145 static const int msgerrreasonlen = G_N_ELEMENTS(msgerrreason); |
146 | 146 |
147 /* All the libfaim->purple callback functions */ | 147 /* All the libfaim->purple callback functions */ |
148 | |
149 /* Only used when connecting with the old-style BUCP login */ | |
148 static int purple_parse_auth_resp (OscarData *, FlapConnection *, FlapFrame *, ...); | 150 static int purple_parse_auth_resp (OscarData *, FlapConnection *, FlapFrame *, ...); |
149 static int purple_parse_login (OscarData *, FlapConnection *, FlapFrame *, ...); | 151 static int purple_parse_login (OscarData *, FlapConnection *, FlapFrame *, ...); |
150 static int purple_parse_auth_securid_request(OscarData *, FlapConnection *, FlapFrame *, ...); | 152 static int purple_parse_auth_securid_request(OscarData *, FlapConnection *, FlapFrame *, ...); |
153 | |
151 static int purple_handle_redirect (OscarData *, FlapConnection *, FlapFrame *, ...); | 154 static int purple_handle_redirect (OscarData *, FlapConnection *, FlapFrame *, ...); |
152 static int purple_info_change (OscarData *, FlapConnection *, FlapFrame *, ...); | 155 static int purple_info_change (OscarData *, FlapConnection *, FlapFrame *, ...); |
153 static int purple_account_confirm (OscarData *, FlapConnection *, FlapFrame *, ...); | 156 static int purple_account_confirm (OscarData *, FlapConnection *, FlapFrame *, ...); |
154 static int purple_parse_oncoming (OscarData *, FlapConnection *, FlapFrame *, ...); | 157 static int purple_parse_oncoming (OscarData *, FlapConnection *, FlapFrame *, ...); |
155 static int purple_parse_offgoing (OscarData *, FlapConnection *, FlapFrame *, ...); | 158 static int purple_parse_offgoing (OscarData *, FlapConnection *, FlapFrame *, ...); |
202 static void purple_icons_fetch(PurpleConnection *gc); | 205 static void purple_icons_fetch(PurpleConnection *gc); |
203 | 206 |
204 void oscar_set_info(PurpleConnection *gc, const char *info); | 207 void oscar_set_info(PurpleConnection *gc, const char *info); |
205 static void oscar_set_info_and_status(PurpleAccount *account, gboolean setinfo, const char *rawinfo, gboolean setstatus, PurpleStatus *status); | 208 static void oscar_set_info_and_status(PurpleAccount *account, gboolean setinfo, const char *rawinfo, gboolean setstatus, PurpleStatus *status); |
206 static void oscar_set_extendedstatus(PurpleConnection *gc); | 209 static void oscar_set_extendedstatus(PurpleConnection *gc); |
207 static void oscar_format_username(PurpleConnection *gc, const char *nick); | |
208 static gboolean purple_ssi_rerequestdata(gpointer data); | 210 static gboolean purple_ssi_rerequestdata(gpointer data); |
209 | 211 |
210 static void oscar_free_name_data(struct name_data *data) { | 212 static void oscar_free_name_data(struct name_data *data) { |
211 g_free(data->name); | 213 g_free(data->name); |
212 g_free(data->nick); | 214 g_free(data->nick); |
1105 purple_debug_error("oscar", "unable to connect to FLAP " | 1107 purple_debug_error("oscar", "unable to connect to FLAP " |
1106 "server of type 0x%04hx\n", conn->type); | 1108 "server of type 0x%04hx\n", conn->type); |
1107 | 1109 |
1108 if (conn->type == SNAC_FAMILY_AUTH) | 1110 if (conn->type == SNAC_FAMILY_AUTH) |
1109 { | 1111 { |
1112 /* This only happens when connecting with the old-style BUCP login */ | |
1110 gchar *msg; | 1113 gchar *msg; |
1111 msg = g_strdup_printf(_("Could not connect to authentication server:\n%s"), | 1114 msg = g_strdup_printf(_("Unable to connect to authentication server: %s"), |
1112 error_message); | 1115 error_message); |
1113 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); | 1116 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); |
1114 g_free(msg); | 1117 g_free(msg); |
1115 } | 1118 } |
1116 else if (conn->type == SNAC_FAMILY_LOCATE) | 1119 else if (conn->type == SNAC_FAMILY_LOCATE) |
1117 { | 1120 { |
1118 gchar *msg; | 1121 gchar *msg; |
1119 msg = g_strdup_printf(_("Could not connect to BOS server:\n%s"), | 1122 msg = g_strdup_printf(_("Unable to connect to BOS server: %s"), |
1120 error_message); | 1123 error_message); |
1121 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); | 1124 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); |
1122 g_free(msg); | 1125 g_free(msg); |
1123 } | 1126 } |
1124 else | 1127 else |
1150 | 1153 |
1151 if (conn->cookie == NULL) | 1154 if (conn->cookie == NULL) |
1152 flap_connection_send_version(od, conn); | 1155 flap_connection_send_version(od, conn); |
1153 else | 1156 else |
1154 { | 1157 { |
1155 flap_connection_send_version_with_cookie(od, conn, | 1158 if (purple_account_get_bool(account, "use_clientlogin", OSCAR_DEFAULT_USE_CLIENTLOGIN)) |
1156 conn->cookielen, conn->cookie); | 1159 { |
1160 ClientInfo aiminfo = CLIENTINFO_PURPLE_AIM; | |
1161 ClientInfo icqinfo = CLIENTINFO_PURPLE_ICQ; | |
1162 flap_connection_send_version_with_cookie_and_clientinfo(od, | |
1163 conn, conn->cookielen, conn->cookie, | |
1164 od->icq ? &icqinfo : &aiminfo); | |
1165 } else { | |
1166 flap_connection_send_version_with_cookie(od, conn, | |
1167 conn->cookielen, conn->cookie); | |
1168 } | |
1169 | |
1170 | |
1157 g_free(conn->cookie); | 1171 g_free(conn->cookie); |
1158 conn->cookie = NULL; | 1172 conn->cookie = NULL; |
1159 } | 1173 } |
1160 | 1174 |
1161 if (conn->type == SNAC_FAMILY_AUTH) | 1175 if (conn->type == SNAC_FAMILY_AUTH) |
1162 { | 1176 { |
1177 /* This only happens when connecting with the old-style BUCP login */ | |
1163 aim_request_login(od, conn, purple_account_get_username(account)); | 1178 aim_request_login(od, conn, purple_account_get_username(account)); |
1164 purple_debug_info("oscar", "Username sent, waiting for response\n"); | 1179 purple_debug_info("oscar", "Username sent, waiting for response\n"); |
1165 purple_connection_update_progress(gc, _("Username sent"), 1, OSCAR_CONNECT_STEPS); | 1180 purple_connection_update_progress(gc, _("Username sent"), 1, OSCAR_CONNECT_STEPS); |
1166 ck[1] = 0x65; | 1181 ck[1] = 0x65; |
1167 } | 1182 } |
1428 void | 1443 void |
1429 oscar_login(PurpleAccount *account) | 1444 oscar_login(PurpleAccount *account) |
1430 { | 1445 { |
1431 PurpleConnection *gc; | 1446 PurpleConnection *gc; |
1432 OscarData *od; | 1447 OscarData *od; |
1433 FlapConnection *newconn; | |
1434 | 1448 |
1435 gc = purple_account_get_connection(account); | 1449 gc = purple_account_get_connection(account); |
1436 od = oscar_data_new(); | 1450 od = oscar_data_new(); |
1437 od->gc = gc; | 1451 od->gc = gc; |
1438 purple_connection_set_protocol_data(gc, od); | 1452 purple_connection_set_protocol_data(gc, od); |
1443 oscar_data_addhandler(od, SNAC_FAMILY_ADMIN, 0x0003, purple_info_change, 0); | 1457 oscar_data_addhandler(od, SNAC_FAMILY_ADMIN, 0x0003, purple_info_change, 0); |
1444 oscar_data_addhandler(od, SNAC_FAMILY_ADMIN, 0x0005, purple_info_change, 0); | 1458 oscar_data_addhandler(od, SNAC_FAMILY_ADMIN, 0x0005, purple_info_change, 0); |
1445 oscar_data_addhandler(od, SNAC_FAMILY_ADMIN, 0x0007, purple_account_confirm, 0); | 1459 oscar_data_addhandler(od, SNAC_FAMILY_ADMIN, 0x0007, purple_account_confirm, 0); |
1446 oscar_data_addhandler(od, SNAC_FAMILY_ALERT, 0x0001, purple_parse_genericerr, 0); | 1460 oscar_data_addhandler(od, SNAC_FAMILY_ALERT, 0x0001, purple_parse_genericerr, 0); |
1447 oscar_data_addhandler(od, SNAC_FAMILY_ALERT, SNAC_SUBTYPE_ALERT_MAILSTATUS, purple_email_parseupdate, 0); | 1461 oscar_data_addhandler(od, SNAC_FAMILY_ALERT, SNAC_SUBTYPE_ALERT_MAILSTATUS, purple_email_parseupdate, 0); |
1462 | |
1463 /* These are only needed when connecting with the old-style BUCP login */ | |
1448 oscar_data_addhandler(od, SNAC_FAMILY_AUTH, 0x0003, purple_parse_auth_resp, 0); | 1464 oscar_data_addhandler(od, SNAC_FAMILY_AUTH, 0x0003, purple_parse_auth_resp, 0); |
1449 oscar_data_addhandler(od, SNAC_FAMILY_AUTH, 0x0007, purple_parse_login, 0); | 1465 oscar_data_addhandler(od, SNAC_FAMILY_AUTH, 0x0007, purple_parse_login, 0); |
1450 oscar_data_addhandler(od, SNAC_FAMILY_AUTH, SNAC_SUBTYPE_AUTH_SECURID_REQUEST, purple_parse_auth_securid_request, 0); | 1466 oscar_data_addhandler(od, SNAC_FAMILY_AUTH, SNAC_SUBTYPE_AUTH_SECURID_REQUEST, purple_parse_auth_securid_request, 0); |
1467 | |
1451 oscar_data_addhandler(od, SNAC_FAMILY_BART, SNAC_SUBTYPE_BART_RESPONSE, purple_icon_parseicon, 0); | 1468 oscar_data_addhandler(od, SNAC_FAMILY_BART, SNAC_SUBTYPE_BART_RESPONSE, purple_icon_parseicon, 0); |
1452 oscar_data_addhandler(od, SNAC_FAMILY_BOS, 0x0001, purple_parse_genericerr, 0); | 1469 oscar_data_addhandler(od, SNAC_FAMILY_BOS, 0x0001, purple_parse_genericerr, 0); |
1453 oscar_data_addhandler(od, SNAC_FAMILY_BOS, 0x0003, purple_bosrights, 0); | 1470 oscar_data_addhandler(od, SNAC_FAMILY_BOS, 0x0003, purple_bosrights, 0); |
1454 oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, 0x0001, purple_parse_genericerr, 0); | 1471 oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, 0x0001, purple_parse_genericerr, 0); |
1455 oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, SNAC_SUBTYPE_BUDDY_RIGHTSINFO, purple_parse_buddyrights, 0); | 1472 oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, SNAC_SUBTYPE_BUDDY_RIGHTSINFO, purple_parse_buddyrights, 0); |
1502 | 1519 |
1503 purple_debug_misc("oscar", "oscar_login: gc = %p\n", gc); | 1520 purple_debug_misc("oscar", "oscar_login: gc = %p\n", gc); |
1504 | 1521 |
1505 if (!oscar_util_valid_name(purple_account_get_username(account))) { | 1522 if (!oscar_util_valid_name(purple_account_get_username(account))) { |
1506 gchar *buf; | 1523 gchar *buf; |
1507 buf = g_strdup_printf(_("Unable to login: Could not sign on as %s because the username is invalid. Usernames must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), purple_account_get_username(account)); | 1524 buf = g_strdup_printf(_("Unable to sign on as %s because the username is invalid. Usernames must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), purple_account_get_username(account)); |
1508 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, buf); | 1525 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, buf); |
1509 g_free(buf); | 1526 g_free(buf); |
1510 return; | 1527 return; |
1511 } | 1528 } |
1512 | 1529 |
1515 } else { | 1532 } else { |
1516 gc->flags |= PURPLE_CONNECTION_HTML; | 1533 gc->flags |= PURPLE_CONNECTION_HTML; |
1517 gc->flags |= PURPLE_CONNECTION_AUTO_RESP; | 1534 gc->flags |= PURPLE_CONNECTION_AUTO_RESP; |
1518 } | 1535 } |
1519 | 1536 |
1537 od->default_port = purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT); | |
1520 od->use_ssl = purple_account_get_bool(account, "use_ssl", OSCAR_DEFAULT_USE_SSL); | 1538 od->use_ssl = purple_account_get_bool(account, "use_ssl", OSCAR_DEFAULT_USE_SSL); |
1521 | 1539 |
1522 /* Connect to core Purple signals */ | 1540 /* Connect to core Purple signals */ |
1523 purple_prefs_connect_callback(gc, "/purple/away/idle_reporting", idle_reporting_pref_cb, gc); | 1541 purple_prefs_connect_callback(gc, "/purple/away/idle_reporting", idle_reporting_pref_cb, gc); |
1524 purple_prefs_connect_callback(gc, "/plugins/prpl/oscar/recent_buddies", recent_buddies_pref_cb, gc); | 1542 purple_prefs_connect_callback(gc, "/plugins/prpl/oscar/recent_buddies", recent_buddies_pref_cb, gc); |
1525 | 1543 |
1526 newconn = flap_connection_new(od, SNAC_FAMILY_AUTH); | 1544 /* |
1527 if (od->use_ssl) { | 1545 * On 2008-03-05 AOL released some documentation on the OSCAR protocol |
1528 if (purple_ssl_is_supported()) { | 1546 * which includes a new login method called clientLogin. It is similar |
1529 const char *server = purple_account_get_string(account, "server", OSCAR_DEFAULT_SSL_LOGIN_SERVER); | 1547 * (though not the same?) as what the AIM 6.0 series uses to |
1548 * authenticate. | |
1549 * | |
1550 * AIM 5.9 and lower use an MD5-based login procedure called "BUCP". | |
1551 * This authentication method is used for both ICQ and AIM when | |
1552 * clientLogin is not enabled. | |
1553 */ | |
1554 if (purple_account_get_bool(account, "use_clientlogin", OSCAR_DEFAULT_USE_CLIENTLOGIN)) { | |
1555 send_client_login(od, purple_account_get_username(account)); | |
1556 } else { | |
1557 FlapConnection *newconn; | |
1558 const char *server; | |
1559 | |
1560 newconn = flap_connection_new(od, SNAC_FAMILY_AUTH); | |
1561 | |
1562 if (od->use_ssl) { | |
1563 if (!purple_ssl_is_supported()) { | |
1564 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, | |
1565 _("SSL support unavailable")); | |
1566 return; | |
1567 } | |
1568 | |
1569 server = purple_account_get_string(account, "server", OSCAR_DEFAULT_SSL_LOGIN_SERVER); | |
1570 | |
1530 /* | 1571 /* |
1531 * If the account's server is what the oscar prpl has offered as | 1572 * If the account's server is what the oscar prpl has offered as |
1532 * the default login server through the vast eons (all two of | 1573 * the default login server through the vast eons (all two of |
1533 * said default options, AFAIK) and the user wants SSL, we'll | 1574 * said default options, AFAIK) and the user wants SSL, we'll |
1534 * do what we know is best for them and change the setting out | 1575 * do what we know is best for them and change the setting out |
1542 | 1583 |
1543 newconn->gsc = purple_ssl_connect(account, server, | 1584 newconn->gsc = purple_ssl_connect(account, server, |
1544 purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT), | 1585 purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT), |
1545 ssl_connection_established_cb, ssl_connection_error_cb, newconn); | 1586 ssl_connection_established_cb, ssl_connection_error_cb, newconn); |
1546 } else { | 1587 } else { |
1547 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, | 1588 server = purple_account_get_string(account, "server", OSCAR_DEFAULT_LOGIN_SERVER); |
1548 _("SSL support unavailable")); | 1589 |
1549 } | 1590 /* |
1550 } else { | 1591 * See the comment above. We do the reverse here. If they don't want |
1551 const char *server = purple_account_get_string(account, "server", OSCAR_DEFAULT_LOGIN_SERVER); | 1592 * SSL but their server is set to OSCAR_DEFAULT_SSL_LOGIN_SERVER, |
1552 | 1593 * set it back to the default. |
1553 /* | 1594 */ |
1554 * See the comment above. We do the reverse here. If they don't want | 1595 if (!strcmp(server, OSCAR_DEFAULT_SSL_LOGIN_SERVER)) { |
1555 * SSL but their server is set to OSCAR_DEFAULT_SSL_LOGIN_SERVER, | 1596 purple_debug_info("oscar", "Account does not use SSL, so changing server back to non-SSL\n"); |
1556 * set it back to the default. | 1597 purple_account_set_string(account, "server", OSCAR_DEFAULT_LOGIN_SERVER); |
1557 */ | 1598 server = OSCAR_DEFAULT_LOGIN_SERVER; |
1558 if (!strcmp(server, OSCAR_DEFAULT_SSL_LOGIN_SERVER)) { | 1599 } |
1559 purple_debug_info("oscar", "Account does not use SSL, so changing server back to non-SSL\n"); | 1600 |
1560 purple_account_set_string(account, "server", OSCAR_DEFAULT_LOGIN_SERVER); | 1601 newconn->connect_data = purple_proxy_connect(NULL, account, server, |
1561 server = OSCAR_DEFAULT_LOGIN_SERVER; | 1602 purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT), |
1562 } | 1603 connection_established_cb, newconn); |
1563 | 1604 } |
1564 newconn->connect_data = purple_proxy_connect(NULL, account, server, | 1605 |
1565 purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT), | 1606 if (newconn->gsc == NULL && newconn->connect_data == NULL) { |
1566 connection_established_cb, newconn); | 1607 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, |
1567 } | 1608 _("Unable to connect")); |
1568 | 1609 return; |
1569 if (newconn->gsc == NULL && newconn->connect_data == NULL) { | 1610 } |
1570 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | |
1571 _("Couldn't connect to host")); | |
1572 return; | |
1573 } | 1611 } |
1574 | 1612 |
1575 purple_connection_update_progress(gc, _("Connecting"), 0, OSCAR_CONNECT_STEPS); | 1613 purple_connection_update_progress(gc, _("Connecting"), 0, OSCAR_CONNECT_STEPS); |
1576 ck[0] = 0x5a; | 1614 ck[0] = 0x5a; |
1577 } | 1615 } |
1602 purple_prefs_disconnect_by_handle(gc); | 1640 purple_prefs_disconnect_by_handle(gc); |
1603 | 1641 |
1604 purple_debug_info("oscar", "Signed off.\n"); | 1642 purple_debug_info("oscar", "Signed off.\n"); |
1605 } | 1643 } |
1606 | 1644 |
1645 /* XXX - Should use purple_util_fetch_url for the below stuff */ | |
1646 struct pieceofcrap { | |
1647 PurpleConnection *gc; | |
1648 unsigned long offset; | |
1649 unsigned long len; | |
1650 char *modname; | |
1651 int fd; | |
1652 FlapConnection *conn; | |
1653 unsigned int inpa; | |
1654 }; | |
1655 | |
1656 static void damn_you(gpointer data, gint source, PurpleInputCondition c) | |
1657 { | |
1658 struct pieceofcrap *pos = data; | |
1659 OscarData *od = purple_connection_get_protocol_data(pos->gc); | |
1660 char in = '\0'; | |
1661 int x = 0; | |
1662 unsigned char m[17]; | |
1663 GString *msg; | |
1664 | |
1665 while (read(pos->fd, &in, 1) == 1) { | |
1666 if (in == '\n') | |
1667 x++; | |
1668 else if (in != '\r') | |
1669 x = 0; | |
1670 if (x == 2) | |
1671 break; | |
1672 in = '\0'; | |
1673 } | |
1674 if (in != '\n') { | |
1675 char buf[256]; | |
1676 g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly. " | |
1677 "If so, check %s for updates."), | |
1678 oscar_get_ui_info_string("website", PURPLE_WEBSITE)); | |
1679 purple_notify_warning(pos->gc, NULL, | |
1680 _("Unable to get a valid AIM login hash."), | |
1681 buf); | |
1682 purple_input_remove(pos->inpa); | |
1683 close(pos->fd); | |
1684 g_free(pos); | |
1685 return; | |
1686 } | |
1687 if (read(pos->fd, m, 16) != 16) | |
1688 { | |
1689 purple_debug_warning("oscar", "Could not read full AIM login hash " | |
1690 "from " AIMHASHDATA "--that's bad.\n"); | |
1691 } | |
1692 m[16] = '\0'; | |
1693 | |
1694 msg = g_string_new("Sending hash: "); | |
1695 for (x = 0; x < 16; x++) | |
1696 g_string_append_printf(msg, "%02hhx ", (unsigned char)m[x]); | |
1697 g_string_append(msg, "\n"); | |
1698 purple_debug_misc("oscar", "%s", msg->str); | |
1699 g_string_free(msg, TRUE); | |
1700 | |
1701 purple_input_remove(pos->inpa); | |
1702 close(pos->fd); | |
1703 aim_sendmemblock(od, pos->conn, 0, 16, m, AIM_SENDMEMBLOCK_FLAG_ISHASH); | |
1704 g_free(pos); | |
1705 } | |
1706 | |
1707 static void | |
1708 straight_to_hell(gpointer data, gint source, const gchar *error_message) | |
1709 { | |
1710 struct pieceofcrap *pos = data; | |
1711 gchar *buf; | |
1712 gssize result; | |
1713 | |
1714 pos->fd = source; | |
1715 | |
1716 if (source < 0) { | |
1717 buf = g_strdup_printf(_("You may be disconnected shortly. " | |
1718 "If so, check %s for updates."), | |
1719 oscar_get_ui_info_string("website", PURPLE_WEBSITE)); | |
1720 purple_notify_warning(pos->gc, NULL, | |
1721 _("Unable to get a valid AIM login hash."), | |
1722 buf); | |
1723 g_free(buf); | |
1724 g_free(pos->modname); | |
1725 g_free(pos); | |
1726 return; | |
1727 } | |
1728 | |
1729 buf = g_strdup_printf("GET " AIMHASHDATA "?offset=%ld&len=%ld&modname=%s HTTP/1.0\n\n", | |
1730 pos->offset, pos->len, pos->modname ? pos->modname : ""); | |
1731 result = send(pos->fd, buf, strlen(buf), 0); | |
1732 if (result != strlen(buf)) { | |
1733 if (result < 0) | |
1734 purple_debug_error("oscar", "Error writing %" G_GSIZE_FORMAT | |
1735 " bytes to fetch AIM hash data: %s\n", | |
1736 strlen(buf), g_strerror(errno)); | |
1737 else | |
1738 purple_debug_error("oscar", "Tried to write %" | |
1739 G_GSIZE_FORMAT " bytes to fetch AIM hash data but " | |
1740 "instead wrote %" G_GSSIZE_FORMAT " bytes\n", | |
1741 strlen(buf), result); | |
1742 } | |
1743 g_free(buf); | |
1744 g_free(pos->modname); | |
1745 pos->inpa = purple_input_add(pos->fd, PURPLE_INPUT_READ, damn_you, pos); | |
1746 return; | |
1747 } | |
1748 | |
1749 /* size of icbmui.ocm, the largest module in AIM 3.5 */ | |
1750 #define AIM_MAX_FILE_SIZE 98304 | |
1751 | |
1752 static int purple_memrequest(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) | |
1753 { | |
1754 va_list ap; | |
1755 struct pieceofcrap *pos; | |
1756 guint32 offset, len; | |
1757 char *modname; | |
1758 | |
1759 va_start(ap, fr); | |
1760 offset = va_arg(ap, guint32); | |
1761 len = va_arg(ap, guint32); | |
1762 modname = va_arg(ap, char *); | |
1763 va_end(ap); | |
1764 | |
1765 purple_debug_misc("oscar", "offset: %u, len: %u, file: %s\n", | |
1766 offset, len, (modname ? modname : "aim.exe")); | |
1767 | |
1768 if (len == 0) { | |
1769 purple_debug_misc("oscar", "len is 0, hashing NULL\n"); | |
1770 aim_sendmemblock(od, conn, offset, len, NULL, | |
1771 AIM_SENDMEMBLOCK_FLAG_ISREQUEST); | |
1772 return 1; | |
1773 } | |
1774 /* uncomment this when you're convinced it's right. remember, it's been wrong before. */ | |
1775 #if 0 | |
1776 if (offset > AIM_MAX_FILE_SIZE || len > AIM_MAX_FILE_SIZE) { | |
1777 char *buf; | |
1778 int i = 8; | |
1779 if (modname) | |
1780 i += strlen(modname); | |
1781 buf = g_malloc(i); | |
1782 i = 0; | |
1783 if (modname) { | |
1784 memcpy(buf, modname, strlen(modname)); | |
1785 i += strlen(modname); | |
1786 } | |
1787 buf[i++] = offset & 0xff; | |
1788 buf[i++] = (offset >> 8) & 0xff; | |
1789 buf[i++] = (offset >> 16) & 0xff; | |
1790 buf[i++] = (offset >> 24) & 0xff; | |
1791 buf[i++] = len & 0xff; | |
1792 buf[i++] = (len >> 8) & 0xff; | |
1793 buf[i++] = (len >> 16) & 0xff; | |
1794 buf[i++] = (len >> 24) & 0xff; | |
1795 purple_debug_misc("oscar", "len + offset is invalid, " | |
1796 "hashing request\n"); | |
1797 aim_sendmemblock(od, command->conn, offset, i, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST); | |
1798 g_free(buf); | |
1799 return 1; | |
1800 } | |
1801 #endif | |
1802 | |
1803 pos = g_new0(struct pieceofcrap, 1); | |
1804 pos->gc = od->gc; | |
1805 pos->conn = conn; | |
1806 | |
1807 pos->offset = offset; | |
1808 pos->len = len; | |
1809 pos->modname = g_strdup(modname); | |
1810 | |
1811 if (purple_proxy_connect(pos->gc, pos->gc->account, "pidgin.im", 80, | |
1812 straight_to_hell, pos) == NULL) | |
1813 { | |
1814 char buf[256]; | |
1815 g_free(pos->modname); | |
1816 g_free(pos); | |
1817 | |
1818 g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly. " | |
1819 "If so, check %s for updates."), | |
1820 oscar_get_ui_info_string("website", PURPLE_WEBSITE)); | |
1821 purple_notify_warning(pos->gc, NULL, | |
1822 _("Unable to get a valid login hash."), | |
1823 buf); | |
1824 } | |
1825 | |
1826 return 1; | |
1827 } | |
1828 | |
1829 int oscar_connect_to_bos(PurpleConnection *gc, OscarData *od, const char *host, guint16 port, guint8 *cookie, guint16 cookielen) | |
1830 { | |
1831 FlapConnection *conn; | |
1832 | |
1833 conn = flap_connection_new(od, SNAC_FAMILY_LOCATE); | |
1834 conn->cookielen = cookielen; | |
1835 conn->cookie = g_memdup(cookie, cookielen); | |
1836 conn->connect_data = purple_proxy_connect(NULL, | |
1837 purple_connection_get_account(gc), host, port, | |
1838 connection_established_cb, conn); | |
1839 if (conn->connect_data == NULL) | |
1840 { | |
1841 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); | |
1842 return 0; | |
1843 } | |
1844 | |
1845 od->default_port = port; | |
1846 | |
1847 purple_connection_update_progress(gc, _("Received authorization"), 3, OSCAR_CONNECT_STEPS); | |
1848 ck[3] = 0x64; | |
1849 | |
1850 return 1; | |
1851 } | |
1852 | |
1853 /** | |
1854 * Only used when connecting with the old-style BUCP login. | |
1855 */ | |
1607 static int | 1856 static int |
1608 purple_parse_auth_resp(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) | 1857 purple_parse_auth_resp(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
1609 { | 1858 { |
1610 PurpleConnection *gc = od->gc; | 1859 PurpleConnection *gc = od->gc; |
1611 PurpleAccount *account = purple_connection_get_account(gc); | 1860 PurpleAccount *account = purple_connection_get_account(gc); |
1613 int i; | 1862 int i; |
1614 FlapConnection *newconn; | 1863 FlapConnection *newconn; |
1615 va_list ap; | 1864 va_list ap; |
1616 struct aim_authresp_info *info; | 1865 struct aim_authresp_info *info; |
1617 | 1866 |
1618 port = purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT); | 1867 port = purple_account_get_int(account, "port", od->default_port); |
1619 | 1868 |
1620 va_start(ap, fr); | 1869 va_start(ap, fr); |
1621 info = va_arg(ap, struct aim_authresp_info *); | 1870 info = va_arg(ap, struct aim_authresp_info *); |
1622 va_end(ap); | 1871 va_end(ap); |
1623 | 1872 |
1627 if (info->errorcode || !info->bosip || !info->cookielen || !info->cookie) { | 1876 if (info->errorcode || !info->bosip || !info->cookielen || !info->cookie) { |
1628 char buf[256]; | 1877 char buf[256]; |
1629 switch (info->errorcode) { | 1878 switch (info->errorcode) { |
1630 case 0x01: | 1879 case 0x01: |
1631 /* Unregistered username */ | 1880 /* Unregistered username */ |
1632 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_USERNAME, _("Invalid username.")); | 1881 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_USERNAME, _("Username does not exist")); |
1633 break; | 1882 break; |
1634 case 0x05: | 1883 case 0x05: |
1635 /* Incorrect password */ | 1884 /* Incorrect password */ |
1636 if (!purple_account_get_remember_password(account)) | 1885 if (!purple_account_get_remember_password(account)) |
1637 purple_account_set_password(account, NULL); | 1886 purple_account_set_password(account, NULL); |
1638 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Incorrect password.")); | 1887 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Incorrect password")); |
1639 break; | 1888 break; |
1640 case 0x11: | 1889 case 0x11: |
1641 /* Suspended account */ | 1890 /* Suspended account */ |
1642 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Your account is currently suspended.")); | 1891 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Your account is currently suspended")); |
1643 break; | 1892 break; |
1644 case 0x02: | 1893 case 0x02: |
1645 case 0x14: | 1894 case 0x14: |
1646 /* service temporarily unavailable */ | 1895 /* service temporarily unavailable */ |
1647 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("The AOL Instant Messenger service is temporarily unavailable.")); | 1896 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("The AOL Instant Messenger service is temporarily unavailable.")); |
1651 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("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.")); | 1900 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("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.")); |
1652 break; | 1901 break; |
1653 case 0x1c: | 1902 case 0x1c: |
1654 { | 1903 { |
1655 /* client too old */ | 1904 /* client too old */ |
1656 GHashTable *ui_info = purple_core_get_ui_info(); | |
1657 g_snprintf(buf, sizeof(buf), _("The client version you are using is too old. Please upgrade at %s"), | 1905 g_snprintf(buf, sizeof(buf), _("The client version you are using is too old. Please upgrade at %s"), |
1658 ((ui_info && g_hash_table_lookup(ui_info, "website")) ? (char *)g_hash_table_lookup(ui_info, "website") : PURPLE_WEBSITE)); | 1906 oscar_get_ui_info_string("website", PURPLE_WEBSITE)); |
1659 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, buf); | 1907 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, buf); |
1660 break; | 1908 break; |
1661 } | 1909 } |
1662 case 0x1d: | 1910 case 0x1d: |
1663 /* IP address connecting too frequently */ | 1911 /* IP address connecting too frequently */ |
1664 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("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.")); | 1912 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("You have been connecting and disconnecting too frequently. Wait a minute and try again. If you continue to try, you will need to wait even longer.")); |
1665 break; | 1913 break; |
1666 default: | 1914 default: |
1667 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Authentication failed")); | 1915 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Unknown reason")); |
1668 break; | 1916 break; |
1669 } | 1917 } |
1670 purple_debug_info("oscar", "Login Error Code 0x%04hx\n", info->errorcode); | 1918 purple_debug_info("oscar", "Login Error Code 0x%04hx\n", info->errorcode); |
1671 purple_debug_info("oscar", "Error URL: %s\n", info->errorurl ? info->errorurl : ""); | 1919 purple_debug_info("oscar", "Error URL: %s\n", info->errorurl ? info->errorurl : ""); |
1672 return 1; | 1920 return 1; |
1709 } | 1957 } |
1710 | 1958 |
1711 g_free(host); | 1959 g_free(host); |
1712 if (newconn->connect_data == NULL) | 1960 if (newconn->connect_data == NULL) |
1713 { | 1961 { |
1714 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Could Not Connect")); | 1962 purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); |
1715 return 0; | 1963 return 0; |
1716 } | 1964 } |
1717 | 1965 |
1718 purple_connection_update_progress(gc, _("Received authorization"), 3, OSCAR_CONNECT_STEPS); | 1966 purple_connection_update_progress(gc, _("Received authorization"), 3, OSCAR_CONNECT_STEPS); |
1719 ck[3] = 0x64; | 1967 ck[3] = 0x64; |
1720 | 1968 |
1721 return 1; | 1969 return 1; |
1722 } | 1970 } |
1723 | 1971 |
1972 /** | |
1973 * Only used when connecting with the old-style BUCP login. | |
1974 */ | |
1724 static void | 1975 static void |
1725 purple_parse_auth_securid_request_yes_cb(gpointer user_data, const char *msg) | 1976 purple_parse_auth_securid_request_yes_cb(gpointer user_data, const char *msg) |
1726 { | 1977 { |
1727 PurpleConnection *gc = user_data; | 1978 PurpleConnection *gc = user_data; |
1728 OscarData *od = purple_connection_get_protocol_data(gc); | 1979 OscarData *od = purple_connection_get_protocol_data(gc); |
1729 | 1980 |
1730 aim_auth_securid_send(od, msg); | 1981 aim_auth_securid_send(od, msg); |
1731 } | 1982 } |
1732 | 1983 |
1984 /** | |
1985 * Only used when connecting with the old-style BUCP login. | |
1986 */ | |
1733 static void | 1987 static void |
1734 purple_parse_auth_securid_request_no_cb(gpointer user_data, const char *value) | 1988 purple_parse_auth_securid_request_no_cb(gpointer user_data, const char *value) |
1735 { | 1989 { |
1736 PurpleConnection *gc = user_data; | 1990 PurpleConnection *gc = user_data; |
1737 | 1991 |
1738 /* Disconnect */ | 1992 /* Disconnect */ |
1739 purple_connection_error_reason(gc, | 1993 purple_connection_error_reason(gc, |
1740 PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, | 1994 PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, |
1741 _("The SecurID key entered is invalid.")); | 1995 _("The SecurID key entered is invalid")); |
1742 } | 1996 } |
1743 | 1997 |
1998 /** | |
1999 * Only used when connecting with the old-style BUCP login. | |
2000 */ | |
1744 static int | 2001 static int |
1745 purple_parse_auth_securid_request(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) | 2002 purple_parse_auth_securid_request(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
1746 { | 2003 { |
1747 PurpleConnection *gc = od->gc; | 2004 PurpleConnection *gc = od->gc; |
1748 PurpleAccount *account = purple_connection_get_account(gc); | 2005 PurpleAccount *account = purple_connection_get_account(gc); |
1761 g_free(primary); | 2018 g_free(primary); |
1762 | 2019 |
1763 return 1; | 2020 return 1; |
1764 } | 2021 } |
1765 | 2022 |
1766 /* XXX - Should use purple_util_fetch_url for the below stuff */ | 2023 /** |
1767 struct pieceofcrap { | 2024 * Only used when connecting with the old-style BUCP login. |
1768 PurpleConnection *gc; | 2025 */ |
1769 unsigned long offset; | |
1770 unsigned long len; | |
1771 char *modname; | |
1772 int fd; | |
1773 FlapConnection *conn; | |
1774 unsigned int inpa; | |
1775 }; | |
1776 | |
1777 static void damn_you(gpointer data, gint source, PurpleInputCondition c) | |
1778 { | |
1779 struct pieceofcrap *pos = data; | |
1780 OscarData *od = purple_connection_get_protocol_data(pos->gc); | |
1781 char in = '\0'; | |
1782 int x = 0; | |
1783 unsigned char m[17]; | |
1784 GString *msg; | |
1785 | |
1786 while (read(pos->fd, &in, 1) == 1) { | |
1787 if (in == '\n') | |
1788 x++; | |
1789 else if (in != '\r') | |
1790 x = 0; | |
1791 if (x == 2) | |
1792 break; | |
1793 in = '\0'; | |
1794 } | |
1795 if (in != '\n') { | |
1796 char buf[256]; | |
1797 GHashTable *ui_info = purple_core_get_ui_info(); | |
1798 g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly. " | |
1799 "If so, check %s for updates."), | |
1800 ((ui_info && g_hash_table_lookup(ui_info, "website")) ? (char *)g_hash_table_lookup(ui_info, "website") : PURPLE_WEBSITE)); | |
1801 purple_notify_warning(pos->gc, NULL, | |
1802 _("Unable to get a valid AIM login hash."), | |
1803 buf); | |
1804 purple_input_remove(pos->inpa); | |
1805 close(pos->fd); | |
1806 g_free(pos); | |
1807 return; | |
1808 } | |
1809 if (read(pos->fd, m, 16) != 16) | |
1810 { | |
1811 purple_debug_warning("oscar", "Could not read full AIM login hash " | |
1812 "from " AIMHASHDATA "--that's bad.\n"); | |
1813 } | |
1814 m[16] = '\0'; | |
1815 | |
1816 msg = g_string_new("Sending hash: "); | |
1817 for (x = 0; x < 16; x++) | |
1818 g_string_append_printf(msg, "%02hhx ", (unsigned char)m[x]); | |
1819 g_string_append(msg, "\n"); | |
1820 purple_debug_misc("oscar", "%s", msg->str); | |
1821 g_string_free(msg, TRUE); | |
1822 | |
1823 purple_input_remove(pos->inpa); | |
1824 close(pos->fd); | |
1825 aim_sendmemblock(od, pos->conn, 0, 16, m, AIM_SENDMEMBLOCK_FLAG_ISHASH); | |
1826 g_free(pos); | |
1827 } | |
1828 | |
1829 static void | |
1830 straight_to_hell(gpointer data, gint source, const gchar *error_message) | |
1831 { | |
1832 struct pieceofcrap *pos = data; | |
1833 gchar *buf; | |
1834 gssize result; | |
1835 | |
1836 if (!PURPLE_CONNECTION_IS_VALID(pos->gc)) | |
1837 { | |
1838 g_free(pos->modname); | |
1839 g_free(pos); | |
1840 return; | |
1841 } | |
1842 | |
1843 pos->fd = source; | |
1844 | |
1845 if (source < 0) { | |
1846 GHashTable *ui_info = purple_core_get_ui_info(); | |
1847 buf = g_strdup_printf(_("You may be disconnected shortly. " | |
1848 "Check %s for updates."), | |
1849 ((ui_info && g_hash_table_lookup(ui_info, "website")) ? (char *)g_hash_table_lookup(ui_info, "website") : PURPLE_WEBSITE)); | |
1850 purple_notify_warning(pos->gc, NULL, | |
1851 _("Unable to get a valid AIM login hash."), | |
1852 buf); | |
1853 g_free(buf); | |
1854 g_free(pos->modname); | |
1855 g_free(pos); | |
1856 return; | |
1857 } | |
1858 | |
1859 buf = g_strdup_printf("GET " AIMHASHDATA "?offset=%ld&len=%ld&modname=%s HTTP/1.0\n\n", | |
1860 pos->offset, pos->len, pos->modname ? pos->modname : ""); | |
1861 result = send(pos->fd, buf, strlen(buf), 0); | |
1862 if (result != strlen(buf)) { | |
1863 if (result < 0) | |
1864 purple_debug_error("oscar", "Error writing %" G_GSIZE_FORMAT | |
1865 " bytes to fetch AIM hash data: %s\n", | |
1866 strlen(buf), g_strerror(errno)); | |
1867 else | |
1868 purple_debug_error("oscar", "Tried to write %" | |
1869 G_GSIZE_FORMAT " bytes to fetch AIM hash data but " | |
1870 "instead wrote %" G_GSSIZE_FORMAT " bytes\n", | |
1871 strlen(buf), result); | |
1872 } | |
1873 g_free(buf); | |
1874 g_free(pos->modname); | |
1875 pos->inpa = purple_input_add(pos->fd, PURPLE_INPUT_READ, damn_you, pos); | |
1876 return; | |
1877 } | |
1878 | |
1879 /* size of icbmui.ocm, the largest module in AIM 3.5 */ | |
1880 #define AIM_MAX_FILE_SIZE 98304 | |
1881 | |
1882 int purple_memrequest(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { | |
1883 va_list ap; | |
1884 struct pieceofcrap *pos; | |
1885 guint32 offset, len; | |
1886 char *modname; | |
1887 | |
1888 va_start(ap, fr); | |
1889 offset = va_arg(ap, guint32); | |
1890 len = va_arg(ap, guint32); | |
1891 modname = va_arg(ap, char *); | |
1892 va_end(ap); | |
1893 | |
1894 purple_debug_misc("oscar", "offset: %u, len: %u, file: %s\n", | |
1895 offset, len, (modname ? modname : "aim.exe")); | |
1896 | |
1897 if (len == 0) { | |
1898 purple_debug_misc("oscar", "len is 0, hashing NULL\n"); | |
1899 aim_sendmemblock(od, conn, offset, len, NULL, | |
1900 AIM_SENDMEMBLOCK_FLAG_ISREQUEST); | |
1901 return 1; | |
1902 } | |
1903 /* uncomment this when you're convinced it's right. remember, it's been wrong before. */ | |
1904 #if 0 | |
1905 if (offset > AIM_MAX_FILE_SIZE || len > AIM_MAX_FILE_SIZE) { | |
1906 char *buf; | |
1907 int i = 8; | |
1908 if (modname) | |
1909 i += strlen(modname); | |
1910 buf = g_malloc(i); | |
1911 i = 0; | |
1912 if (modname) { | |
1913 memcpy(buf, modname, strlen(modname)); | |
1914 i += strlen(modname); | |
1915 } | |
1916 buf[i++] = offset & 0xff; | |
1917 buf[i++] = (offset >> 8) & 0xff; | |
1918 buf[i++] = (offset >> 16) & 0xff; | |
1919 buf[i++] = (offset >> 24) & 0xff; | |
1920 buf[i++] = len & 0xff; | |
1921 buf[i++] = (len >> 8) & 0xff; | |
1922 buf[i++] = (len >> 16) & 0xff; | |
1923 buf[i++] = (len >> 24) & 0xff; | |
1924 purple_debug_misc("oscar", "len + offset is invalid, " | |
1925 "hashing request\n"); | |
1926 aim_sendmemblock(od, command->conn, offset, i, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST); | |
1927 g_free(buf); | |
1928 return 1; | |
1929 } | |
1930 #endif | |
1931 | |
1932 pos = g_new0(struct pieceofcrap, 1); | |
1933 pos->gc = od->gc; | |
1934 pos->conn = conn; | |
1935 | |
1936 pos->offset = offset; | |
1937 pos->len = len; | |
1938 pos->modname = g_strdup(modname); | |
1939 | |
1940 /* TODO: Keep track of this return value. */ | |
1941 if (purple_proxy_connect(NULL, pos->gc->account, "pidgin.im", 80, | |
1942 straight_to_hell, pos) == NULL) | |
1943 { | |
1944 char buf[256]; | |
1945 GHashTable *ui_info = purple_core_get_ui_info(); | |
1946 g_free(pos->modname); | |
1947 g_free(pos); | |
1948 | |
1949 g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly. " | |
1950 "Check %s for updates."), | |
1951 ((ui_info && g_hash_table_lookup(ui_info, "website")) ? (char *)g_hash_table_lookup(ui_info, "website") : PURPLE_WEBSITE)); | |
1952 purple_notify_warning(pos->gc, NULL, | |
1953 _("Unable to get a valid login hash."), | |
1954 buf); | |
1955 } | |
1956 | |
1957 return 1; | |
1958 } | |
1959 | |
1960 static int | 2026 static int |
1961 purple_parse_login(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) | 2027 purple_parse_login(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
1962 { | 2028 { |
1963 PurpleConnection *gc; | 2029 PurpleConnection *gc; |
1964 PurpleAccount *account; | 2030 PurpleAccount *account; |
2000 | 2066 |
2001 va_start(ap, fr); | 2067 va_start(ap, fr); |
2002 redir = va_arg(ap, struct aim_redirect_data *); | 2068 redir = va_arg(ap, struct aim_redirect_data *); |
2003 va_end(ap); | 2069 va_end(ap); |
2004 | 2070 |
2005 port = purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT); | 2071 port = od->default_port; |
2006 separator = strchr(redir->ip, ':'); | 2072 separator = strchr(redir->ip, ':'); |
2007 if (separator != NULL) | 2073 if (separator != NULL) |
2008 { | 2074 { |
2009 host = g_strndup(redir->ip, separator - redir->ip); | 2075 host = g_strndup(redir->ip, separator - redir->ip); |
2010 port = atoi(separator + 1); | 2076 port = atoi(separator + 1); |
2150 if (info->status != NULL && info->status[0] != '\0') | 2216 if (info->status != NULL && info->status[0] != '\0') |
2151 /* Grab the available message */ | 2217 /* Grab the available message */ |
2152 message = oscar_encoding_to_utf8(account, info->status_encoding, | 2218 message = oscar_encoding_to_utf8(account, info->status_encoding, |
2153 info->status, info->status_len); | 2219 info->status, info->status_len); |
2154 | 2220 |
2155 tmp2 = tmp = (message ? g_markup_escape_text(message, -1) : NULL); | 2221 tmp2 = tmp = (message ? purple_markup_escape_text(message, -1) : NULL); |
2156 | 2222 |
2157 if (strcmp(status_id, OSCAR_STATUS_ID_AVAILABLE) == 0) { | 2223 if (strcmp(status_id, OSCAR_STATUS_ID_AVAILABLE) == 0) { |
2158 if (info->itmsurl_encoding && info->itmsurl && info->itmsurl_len) | 2224 if (info->itmsurl_encoding && info->itmsurl && info->itmsurl_len) |
2159 /* Grab the iTunes Music Store URL */ | 2225 /* Grab the iTunes Music Store URL */ |
2160 itmsurl = oscar_encoding_to_utf8(account, info->itmsurl_encoding, | 2226 itmsurl = oscar_encoding_to_utf8(account, info->itmsurl_encoding, |
2833 gchar *uin = NULL, *message = NULL; | 2899 gchar *uin = NULL, *message = NULL; |
2834 | 2900 |
2835 /* From libicq2000-0.3.2/src/ICQ.cpp */ | 2901 /* From libicq2000-0.3.2/src/ICQ.cpp */ |
2836 byte_stream_init(&qbs, (guint8 *)args->msg, args->msglen); | 2902 byte_stream_init(&qbs, (guint8 *)args->msg, args->msglen); |
2837 byte_stream_advance(&qbs, 21); | 2903 byte_stream_advance(&qbs, 21); |
2904 /* expected: 01 00 00 20 00 0e 28 f6 00 11 e7 d3 11 bc f3 00 04 ac 96 9d c2 | 00 00 | 06 00 00 00 | 49 43 51 53 43 53 ...*/ | |
2905 /* unexpected: 00 00 26 00 81 1a 18 bc 0e 6c 18 47 a5 91 6f 18 dc c7 6f 1a | 00 00 | 0d 00 00 00 | 49 43 51 57 65 62 4d 65 73 73 61 67 65 ... */ | |
2838 smstype = byte_stream_getle16(&qbs); | 2906 smstype = byte_stream_getle16(&qbs); |
2907 if (smstype != 0) | |
2908 break; | |
2839 taglen = byte_stream_getle32(&qbs); | 2909 taglen = byte_stream_getle32(&qbs); |
2840 tagstr = byte_stream_getstr(&qbs, taglen); | 2910 tagstr = byte_stream_getstr(&qbs, taglen); |
2911 if (tagstr == NULL) | |
2912 break; | |
2841 byte_stream_advance(&qbs, 3); | 2913 byte_stream_advance(&qbs, 3); |
2842 byte_stream_advance(&qbs, 4); | 2914 byte_stream_advance(&qbs, 4); |
2843 smslen = byte_stream_getle32(&qbs); | 2915 smslen = byte_stream_getle32(&qbs); |
2844 smsmsg = byte_stream_getstr(&qbs, smslen); | 2916 smsmsg = byte_stream_getstr(&qbs, smslen); |
2845 | 2917 |
3853 | 3925 |
3854 static int purple_bosrights(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { | 3926 static int purple_bosrights(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
3855 PurpleConnection *gc; | 3927 PurpleConnection *gc; |
3856 PurpleAccount *account; | 3928 PurpleAccount *account; |
3857 PurpleStatus *status; | 3929 PurpleStatus *status; |
3930 gboolean is_available; | |
3858 PurplePresence *presence; | 3931 PurplePresence *presence; |
3859 const char *username, *message, *itmsurl; | 3932 const char *username, *message, *itmsurl; |
3860 char *tmp; | 3933 char *tmp; |
3861 va_list ap; | 3934 va_list ap; |
3862 guint16 maxpermits, maxdenies; | 3935 guint16 maxpermits, maxdenies; |
3893 */ | 3966 */ |
3894 oscar_format_username(gc, username); | 3967 oscar_format_username(gc, username); |
3895 | 3968 |
3896 /* Set our available message based on the current status */ | 3969 /* Set our available message based on the current status */ |
3897 status = purple_account_get_active_status(account); | 3970 status = purple_account_get_active_status(account); |
3898 if (purple_status_is_available(status)) | 3971 is_available = purple_status_is_available(status); |
3972 if (is_available) | |
3899 message = purple_status_get_attr_string(status, "message"); | 3973 message = purple_status_get_attr_string(status, "message"); |
3900 else | 3974 else |
3901 message = NULL; | 3975 message = NULL; |
3902 tmp = purple_markup_strip_html(message); | 3976 tmp = purple_markup_strip_html(message); |
3903 itmsurl = purple_status_get_attr_string(status, "itmsurl"); | 3977 itmsurl = purple_status_get_attr_string(status, "itmsurl"); |
3904 aim_srv_setextrainfo(od, FALSE, 0, TRUE, tmp, itmsurl); | 3978 aim_srv_setextrainfo(od, FALSE, 0, is_available, tmp, itmsurl); |
3905 g_free(tmp); | 3979 g_free(tmp); |
3906 | 3980 |
3907 presence = purple_status_get_presence(status); | 3981 presence = purple_status_get_presence(status); |
3908 aim_srv_setidle(od, !purple_presence_is_idle(presence) ? 0 : time(NULL) - purple_presence_get_idle_time(presence)); | 3982 aim_srv_setidle(od, !purple_presence_is_idle(presence) ? 0 : time(NULL) - purple_presence_get_idle_time(presence)); |
3909 | 3983 |
3918 aim_icq_setsecurity(od, | 3992 aim_icq_setsecurity(od, |
3919 purple_account_get_bool(account, "authorization", OSCAR_DEFAULT_AUTHORIZATION), | 3993 purple_account_get_bool(account, "authorization", OSCAR_DEFAULT_AUTHORIZATION), |
3920 purple_account_get_bool(account, "web_aware", OSCAR_DEFAULT_WEB_AWARE)); | 3994 purple_account_get_bool(account, "web_aware", OSCAR_DEFAULT_WEB_AWARE)); |
3921 } | 3995 } |
3922 | 3996 |
3997 aim_srv_requestnew(od, SNAC_FAMILY_ALERT); | |
3923 aim_srv_requestnew(od, SNAC_FAMILY_CHATNAV); | 3998 aim_srv_requestnew(od, SNAC_FAMILY_CHATNAV); |
3924 | |
3925 /* | |
3926 * The "if" statement here is a pathetic attempt to not attempt to | |
3927 * connect to the alerts servce (aka email notification) if this | |
3928 * username does not support it. I think mail notification | |
3929 * works for @mac.com accounts but does not work for the newer | |
3930 * @anythingelse.com accounts. If that's true then this change | |
3931 * breaks mail notification for @mac.com accounts, but it gets rid | |
3932 * of an annoying error at signon for @anythingelse.com accounts. | |
3933 */ | |
3934 if (od->authinfo->email != NULL && strchr(username, '@') == NULL) | |
3935 aim_srv_requestnew(od, SNAC_FAMILY_ALERT); | |
3936 | 3999 |
3937 return 1; | 4000 return 1; |
3938 } | 4001 } |
3939 | 4002 |
3940 #ifdef OLDSTYLE_ICQ_OFFLINEMSGS | 4003 #ifdef OLDSTYLE_ICQ_OFFLINEMSGS |
4434 msg = g_string_append_len(msg, data->str, data->len); | 4497 msg = g_string_append_len(msg, data->str, data->len); |
4435 msg = g_string_append(msg, "</BINARY>"); | 4498 msg = g_string_append(msg, "</BINARY>"); |
4436 } | 4499 } |
4437 g_string_free(data, TRUE); | 4500 g_string_free(data, TRUE); |
4438 | 4501 |
4439 peer_odc_send_im(conn, msg->str, msg->len, charset, (imflags & PURPLE_MESSAGE_AUTO_RESP)); | 4502 peer_odc_send_im(conn, msg->str, msg->len, charset, |
4503 imflags & PURPLE_MESSAGE_AUTO_RESP); | |
4440 g_string_free(msg, TRUE); | 4504 g_string_free(msg, TRUE); |
4441 } | 4505 } |
4442 | 4506 |
4443 int | 4507 int |
4444 oscar_send_im(PurpleConnection *gc, const char *name, const char *message, PurpleMessageFlags imflags) | 4508 oscar_send_im(PurpleConnection *gc, const char *name, const char *message, PurpleMessageFlags imflags) |
4908 bname = purple_buddy_get_name(buddy); | 4972 bname = purple_buddy_get_name(buddy); |
4909 gname = purple_group_get_name(group); | 4973 gname = purple_group_get_name(group); |
4910 | 4974 |
4911 if (!oscar_util_valid_name(bname)) { | 4975 if (!oscar_util_valid_name(bname)) { |
4912 gchar *buf; | 4976 gchar *buf; |
4913 buf = g_strdup_printf(_("Could not add the buddy %s because the username is invalid. Usernames must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), bname); | 4977 buf = g_strdup_printf(_("Unable to add the buddy %s because the username is invalid. Usernames must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), bname); |
4914 if (!purple_conv_present_error(bname, account, buf)) | 4978 if (!purple_conv_present_error(bname, account, buf)) |
4915 purple_notify_error(gc, NULL, _("Unable to Add"), buf); | 4979 purple_notify_error(gc, NULL, _("Unable to Add"), buf); |
4916 g_free(buf); | 4980 g_free(buf); |
4917 | 4981 |
4918 /* Remove from local list */ | 4982 /* Remove from local list */ |
5393 case 0x0000: { /* added successfully */ | 5457 case 0x0000: { /* added successfully */ |
5394 } break; | 5458 } break; |
5395 | 5459 |
5396 case 0x000c: { /* you are over the limit, the cheat is to the limit, come on fhqwhgads */ | 5460 case 0x000c: { /* you are over the limit, the cheat is to the limit, come on fhqwhgads */ |
5397 gchar *buf; | 5461 gchar *buf; |
5398 buf = g_strdup_printf(_("Could not add the buddy %s because you have too many buddies in your buddy list. Please remove one and try again."), (retval->name ? retval->name : _("(no name)"))); | 5462 buf = g_strdup_printf(_("Unable to add the buddy %s because you have too many buddies in your buddy list. Please remove one and try again."), (retval->name ? retval->name : _("(no name)"))); |
5399 if ((retval->name != NULL) && !purple_conv_present_error(retval->name, purple_connection_get_account(gc), buf)) | 5463 if ((retval->name != NULL) && !purple_conv_present_error(retval->name, purple_connection_get_account(gc), buf)) |
5400 purple_notify_error(gc, NULL, _("Unable to Add"), buf); | 5464 purple_notify_error(gc, NULL, _("Unable to Add"), buf); |
5401 g_free(buf); | 5465 g_free(buf); |
5402 } | 5466 } |
5403 | 5467 |
5407 } break; | 5471 } break; |
5408 | 5472 |
5409 default: { /* La la la */ | 5473 default: { /* La la la */ |
5410 gchar *buf; | 5474 gchar *buf; |
5411 purple_debug_error("oscar", "ssi: Action 0x%04hx was unsuccessful with error 0x%04hx\n", retval->action, retval->ack); | 5475 purple_debug_error("oscar", "ssi: Action 0x%04hx was unsuccessful with error 0x%04hx\n", retval->action, retval->ack); |
5412 buf = g_strdup_printf(_("Could not add the buddy %s for an unknown reason."), | 5476 buf = g_strdup_printf(_("Unable to add the buddy %s for an unknown reason."), |
5413 (retval->name ? retval->name : _("(no name)"))); | 5477 (retval->name ? retval->name : _("(no name)"))); |
5414 if ((retval->name != NULL) && !purple_conv_present_error(retval->name, purple_connection_get_account(gc), buf)) | 5478 if ((retval->name != NULL) && !purple_conv_present_error(retval->name, purple_connection_get_account(gc), buf)) |
5415 purple_notify_error(gc, NULL, _("Unable to Add"), buf); | 5479 purple_notify_error(gc, NULL, _("Unable to Add"), buf); |
5416 g_free(buf); | 5480 g_free(buf); |
5417 } break; | 5481 } break; |
6382 #endif | 6446 #endif |
6383 } | 6447 } |
6384 | 6448 |
6385 if (od->ssi.received_data && purple_buddy_get_group(buddy) != NULL) | 6449 if (od->ssi.received_data && purple_buddy_get_group(buddy) != NULL) |
6386 { | 6450 { |
6451 /* | |
6452 * We only do this if the user is in our buddy list and we're | |
6453 * waiting for authorization. | |
6454 */ | |
6387 char *gname; | 6455 char *gname; |
6388 gname = aim_ssi_itemlist_findparentname(od->ssi.local, bname); | 6456 gname = aim_ssi_itemlist_findparentname(od->ssi.local, bname); |
6389 if (gname && aim_ssi_waitingforauth(od->ssi.local, gname, bname)) | 6457 if (gname && aim_ssi_waitingforauth(od->ssi.local, gname, bname)) |
6390 { | 6458 { |
6391 act = purple_menu_action_new(_("Re-request Authorization"), | 6459 act = purple_menu_action_new(_("Re-request Authorization"), |
6461 _("Cancel"), NULL, | 6529 _("Cancel"), NULL, |
6462 purple_connection_get_account(gc), NULL, NULL, | 6530 purple_connection_get_account(gc), NULL, NULL, |
6463 gc); | 6531 gc); |
6464 } | 6532 } |
6465 | 6533 |
6466 static void oscar_format_username(PurpleConnection *gc, const char *nick) { | 6534 void oscar_format_username(PurpleConnection *gc, const char *nick) { |
6467 OscarData *od = purple_connection_get_protocol_data(gc); | 6535 OscarData *od = purple_connection_get_protocol_data(gc); |
6468 if (!oscar_util_name_compare(purple_account_get_username(purple_connection_get_account(gc)), nick)) { | 6536 if (!oscar_util_name_compare(purple_account_get_username(purple_connection_get_account(gc)), nick)) { |
6469 if (!flap_connection_getbytype(od, SNAC_FAMILY_ADMIN)) { | 6537 if (!flap_connection_getbytype(od, SNAC_FAMILY_ADMIN)) { |
6470 od->setnick = TRUE; | 6538 od->setnick = TRUE; |
6471 g_free(od->newformatting); | 6539 g_free(od->newformatting); |
6622 { | 6690 { |
6623 PurpleConnection *gc = (PurpleConnection *) action->context; | 6691 PurpleConnection *gc = (PurpleConnection *) action->context; |
6624 purple_account_request_change_password(purple_connection_get_account(gc)); | 6692 purple_account_request_change_password(purple_connection_get_account(gc)); |
6625 } | 6693 } |
6626 | 6694 |
6695 /** | |
6696 * Only used when connecting with the old-style BUCP login. | |
6697 */ | |
6627 static void oscar_show_chpassurl(PurplePluginAction *action) | 6698 static void oscar_show_chpassurl(PurplePluginAction *action) |
6628 { | 6699 { |
6629 PurpleConnection *gc = (PurpleConnection *) action->context; | 6700 PurpleConnection *gc = (PurpleConnection *) action->context; |
6630 OscarData *od = purple_connection_get_protocol_data(gc); | 6701 OscarData *od = purple_connection_get_protocol_data(gc); |
6631 gchar *substituted = purple_strreplace(od->authinfo->chpassurl, "%s", purple_account_get_username(purple_connection_get_account(gc))); | 6702 gchar *substituted = purple_strreplace(od->authinfo->chpassurl, "%s", purple_account_get_username(purple_connection_get_account(gc))); |
6762 | 6833 |
6763 act = purple_plugin_action_new(_("Change Password..."), | 6834 act = purple_plugin_action_new(_("Change Password..."), |
6764 oscar_change_pass); | 6835 oscar_change_pass); |
6765 menu = g_list_prepend(menu, act); | 6836 menu = g_list_prepend(menu, act); |
6766 | 6837 |
6767 if (od->authinfo->chpassurl != NULL) | 6838 if (od->authinfo != NULL && od->authinfo->chpassurl != NULL) |
6768 { | 6839 { |
6840 /* This only happens when connecting with the old-style BUCP login */ | |
6769 act = purple_plugin_action_new(_("Change Password (web)"), | 6841 act = purple_plugin_action_new(_("Change Password (web)"), |
6770 oscar_show_chpassurl); | 6842 oscar_show_chpassurl); |
6771 menu = g_list_prepend(menu, act); | 6843 menu = g_list_prepend(menu, act); |
6772 | 6844 } |
6845 | |
6846 if (!od->icq) | |
6847 { | |
6773 act = purple_plugin_action_new(_("Configure IM Forwarding (web)"), | 6848 act = purple_plugin_action_new(_("Configure IM Forwarding (web)"), |
6774 oscar_show_imforwardingurl); | 6849 oscar_show_imforwardingurl); |
6775 menu = g_list_prepend(menu, act); | 6850 menu = g_list_prepend(menu, act); |
6776 } | 6851 } |
6777 | 6852 |
7004 | 7079 |
7005 option = purple_account_option_bool_new(_("Use SSL"), "use_ssl", | 7080 option = purple_account_option_bool_new(_("Use SSL"), "use_ssl", |
7006 OSCAR_DEFAULT_USE_SSL); | 7081 OSCAR_DEFAULT_USE_SSL); |
7007 prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); | 7082 prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); |
7008 | 7083 |
7084 option = purple_account_option_bool_new(_("Use clientLogin"), "use_clientlogin", | |
7085 OSCAR_DEFAULT_USE_CLIENTLOGIN); | |
7086 prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); | |
7087 | |
7009 option = purple_account_option_bool_new( | 7088 option = purple_account_option_bool_new( |
7010 _("Always use AIM/ICQ proxy server for\nfile transfers and direct IM (slower,\nbut does not reveal your IP address)"), "always_use_rv_proxy", | 7089 _("Always use AIM/ICQ proxy server for\nfile transfers and direct IM (slower,\nbut does not reveal your IP address)"), "always_use_rv_proxy", |
7011 OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY); | 7090 OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY); |
7012 prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); | 7091 prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); |
7013 | 7092 |
7021 | 7100 |
7022 /* Preferences */ | 7101 /* Preferences */ |
7023 purple_prefs_add_none("/plugins/prpl/oscar"); | 7102 purple_prefs_add_none("/plugins/prpl/oscar"); |
7024 purple_prefs_add_bool("/plugins/prpl/oscar/recent_buddies", FALSE); | 7103 purple_prefs_add_bool("/plugins/prpl/oscar/recent_buddies", FALSE); |
7025 | 7104 |
7026 /* | |
7027 * These two preferences will normally not be changed. UIs can optionally | |
7028 * use them to override these two version fields which are sent to the | |
7029 * server when logging in. AOL requested this change to allow clients to | |
7030 * use custom values. | |
7031 */ | |
7032 purple_prefs_add_string("/plugins/prpl/oscar/clientstring", NULL); | |
7033 purple_prefs_add_int("/plugins/prpl/oscar/distid", -1); | |
7034 | |
7035 purple_prefs_remove("/plugins/prpl/oscar/show_idle"); | 7105 purple_prefs_remove("/plugins/prpl/oscar/show_idle"); |
7036 purple_prefs_remove("/plugins/prpl/oscar/always_use_rv_proxy"); | 7106 purple_prefs_remove("/plugins/prpl/oscar/always_use_rv_proxy"); |
7037 | 7107 |
7038 /* protocol handler */ | 7108 /* protocol handler */ |
7039 /* TODO: figure out a good instance to use here */ | 7109 /* TODO: figure out a good instance to use here */ |