# HG changeset patch # User Elliott Sales de Andrade # Date 1216791896 0 # Node ID ec227bab07b665668e232ce5750e34b78ea1dc12 # Parent b79cfdcb704e899b2d018cb5b4c4866f2b7592df# Parent d70aad03b491363bf65d926f78bd5472898ea68e merge of '5b3cd3600d9a992cc943d490b68c1174e0346b8b' and '9335e6559861d8cef4214b09234d1f588ff07f74' diff -r d70aad03b491 -r ec227bab07b6 COPYRIGHT --- a/COPYRIGHT Wed Jul 23 05:36:12 2008 +0000 +++ b/COPYRIGHT Wed Jul 23 05:44:56 2008 +0000 @@ -157,6 +157,7 @@ Konrad Gräfe Miah Gregory David Grohmann +Vladislav Guberinić Gideon N. Guillen Christian Hammond Erick Hamness diff -r d70aad03b491 -r ec227bab07b6 ChangeLog --- a/ChangeLog Wed Jul 23 05:36:12 2008 +0000 +++ b/ChangeLog Wed Jul 23 05:44:56 2008 +0000 @@ -10,6 +10,9 @@ we don't install our SSL CA certs, so it's important that the libpurple package depend on the CA certificates. + IRC: + * /ctcp command (Vladislav Guberinić) + MSN: * Update MSN support to protocol 15 (Elliott Sales de Andrade, Jorge Villaseñor, Mike Ruprecht, Carlos Silva, Ma Yuan, Daniel Ljungborg diff -r d70aad03b491 -r ec227bab07b6 ChangeLog.win32 --- a/ChangeLog.win32 Wed Jul 23 05:36:12 2008 +0000 +++ b/ChangeLog.win32 Wed Jul 23 05:44:56 2008 +0000 @@ -1,3 +1,6 @@ +version 2.5.0 (??/??/2008): + * Don't install the GSSAPI SASL plugin on NT4 to avoid an error popup. + version 2.4.3 (07/01/2008): * No changes diff -r d70aad03b491 -r ec227bab07b6 libpurple/protocols/irc/cmds.c --- a/libpurple/protocols/irc/cmds.c Wed Jul 23 05:36:12 2008 +0000 +++ b/libpurple/protocols/irc/cmds.c Wed Jul 23 05:44:56 2008 +0000 @@ -68,6 +68,31 @@ return 0; } +int irc_cmd_ctcp(struct irc_conn *irc, const char *cmd, const char *target, const char **args) +{ + /* we have defined args as args[0] is target and args[1] is ctcp command */ + char *buf; + GString *string; + + /* check if we have args */ + if (!args || !args[0] || !args[1]) + return 0; + + /* TODO:strip newlines or send each line as separate ctcp or something + * actually, this shouldn't be done here but somewhere else since irc should support escaping newlines */ + + string = g_string_new(args[1]); + g_string_prepend_c (string,'\001'); + g_string_append_c (string,'\001'); + buf = irc_format(irc, "vn:", "PRIVMSG", args[0], string->str); + g_string_free(string,TRUE); + + irc_send(irc, buf); + g_free(buf); + + return 1; +} + int irc_cmd_ctcp_action(struct irc_conn *irc, const char *cmd, const char *target, const char **args) { PurpleConnection *gc = purple_account_get_connection(irc->account); diff -r d70aad03b491 -r ec227bab07b6 libpurple/protocols/irc/irc.h --- a/libpurple/protocols/irc/irc.h Wed Jul 23 05:36:12 2008 +0000 +++ b/libpurple/protocols/irc/irc.h Wed Jul 23 05:44:56 2008 +0000 @@ -164,6 +164,7 @@ int irc_cmd_default(struct irc_conn *irc, const char *cmd, const char *target, const char **args); int irc_cmd_away(struct irc_conn *irc, const char *cmd, const char *target, const char **args); +int irc_cmd_ctcp(struct irc_conn *irc, const char *cmd, const char *target, const char **args); int irc_cmd_ctcp_action(struct irc_conn *irc, const char *cmd, const char *target, const char **args); int irc_cmd_ctcp_version(struct irc_conn *irc, const char *cmd, const char *target, const char **args); int irc_cmd_invite(struct irc_conn *irc, const char *cmd, const char *target, const char **args); diff -r d70aad03b491 -r ec227bab07b6 libpurple/protocols/irc/parse.c --- a/libpurple/protocols/irc/parse.c Wed Jul 23 05:36:12 2008 +0000 +++ b/libpurple/protocols/irc/parse.c Wed Jul 23 05:44:56 2008 +0000 @@ -123,6 +123,7 @@ } _irc_cmds[] = { { "action", ":", irc_cmd_ctcp_action, N_("action <action to perform>: Perform an action.") }, { "away", ":", irc_cmd_away, N_("away [message]: Set an away message, or use no message to return from being away.") }, + { "ctcp", "t:", irc_cmd_ctcp, N_("ctcp : sends ctcp msg to nick.") }, { "chanserv", ":", irc_cmd_service, N_("chanserv: Send a command to chanserv") }, { "deop", ":", irc_cmd_op, N_("deop <nick1> [nick2] ...: Remove channel operator status from someone. You must be a channel operator to do this.") }, { "devoice", ":", irc_cmd_op, N_("devoice <nick1> [nick2] ...: Remove channel voice status from someone, preventing them from speaking if the channel is moderated (+m). You must be a channel operator to do this.") }, diff -r d70aad03b491 -r ec227bab07b6 libpurple/protocols/oscar/family_icq.c --- a/libpurple/protocols/oscar/family_icq.c Wed Jul 23 05:36:12 2008 +0000 +++ b/libpurple/protocols/oscar/family_icq.c Wed Jul 23 05:44:56 2008 +0000 @@ -36,6 +36,8 @@ if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ))) return -EINVAL; + purple_debug_info("oscar", "Requesting offline messages from %s", od->sn); + bslen = 2 + 4 + 2 + 2; byte_stream_new(&bs, 4 + bslen); @@ -68,6 +70,8 @@ if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ))) return -EINVAL; + purple_debug_info("oscar", "Acknowledged receipt of offline messages from %s", od->sn); + bslen = 2 + 4 + 2 + 2; byte_stream_new(&bs, 4 + bslen); @@ -214,7 +218,7 @@ byte_stream_putle16(&bs, 0x04b2); /* shrug. */ byte_stream_putle32(&bs, atoi(uin)); - flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x0000, snacid, &bs); + flap_connection_send_snac_with_priority(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x0000, snacid, &bs, FALSE); byte_stream_destroy(&bs); @@ -242,6 +246,8 @@ if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ))) return -EINVAL; + purple_debug_info("oscar", "Requesting ICQ alias for %s", uin); + bslen = 2 + 4 + 2 + 2 + 2 + 4; byte_stream_new(&bs, 4 + bslen); @@ -259,7 +265,7 @@ byte_stream_putle16(&bs, 0x04ba); /* shrug. */ byte_stream_putle32(&bs, atoi(uin)); - flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x0000, snacid, &bs); + flap_connection_send_snac_with_priority(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x0000, snacid, &bs, FALSE); byte_stream_destroy(&bs); @@ -303,7 +309,7 @@ byte_stream_putle16(&bs, 0x051f); /* shrug. */ byte_stream_putle32(&bs, atoi(uin)); - flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x0000, snacid, &bs); + flap_connection_send_snac_with_priority(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x0000, snacid, &bs, FALSE); byte_stream_destroy(&bs); @@ -497,7 +503,7 @@ byte_stream_put16(&bs, strlen(uin)); byte_stream_putstr(&bs, uin); - flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x000, snacid, &bs); + flap_connection_send_snac_with_priority(od, conn, SNAC_FAMILY_ICQ, 0x0002, 0x000, snacid, &bs, FALSE); byte_stream_destroy(&bs); @@ -877,7 +883,7 @@ info->next = od->icq_info; od->icq_info = info; - flap_connection_send_snac(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs); + flap_connection_send_snac_with_priority(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs, FALSE); byte_stream_destroy(&bs); } diff -r d70aad03b491 -r ec227bab07b6 libpurple/protocols/oscar/family_locate.c --- a/libpurple/protocols/oscar/family_locate.c Wed Jul 23 05:36:12 2008 +0000 +++ b/libpurple/protocols/oscar/family_locate.c Wed Jul 23 05:44:56 2008 +0000 @@ -1386,7 +1386,7 @@ byte_stream_putstr(&bs, sn); snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0015, 0x0000, sn, strlen(sn)+1); - flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x0015, 0x0000, snacid, &bs); + flap_connection_send_snac_with_priority(od, conn, SNAC_FAMILY_LOCATE, 0x0015, 0x0000, snacid, &bs, FALSE); byte_stream_destroy(&bs); diff -r d70aad03b491 -r ec227bab07b6 libpurple/protocols/oscar/flap_connection.c --- a/libpurple/protocols/oscar/flap_connection.c Wed Jul 23 05:36:12 2008 +0000 +++ b/libpurple/protocols/oscar/flap_connection.c Wed Jul 23 05:44:56 2008 +0000 @@ -107,21 +107,21 @@ return MIN(((rateclass->current * (rateclass->windowsize - 1)) + timediff) / rateclass->windowsize, rateclass->max); } -static gboolean flap_connection_send_queued(gpointer data) +/* + * Attempt to send the contents of a given queue + * + * @return TRUE if the queue was completely emptied or was initially + * empty; FALSE if rate limiting prevented it from being + * emptied. + */ +static gboolean flap_connection_send_snac_queue(FlapConnection *conn, struct timeval now, GQueue *queue) { - FlapConnection *conn; - struct timeval now; - - conn = data; - gettimeofday(&now, NULL); - - purple_debug_info("oscar", "Attempting to send %u queued SNACs for %p\n", g_queue_get_length(conn->queued_snacs), conn); - while (!g_queue_is_empty(conn->queued_snacs)) + while (!g_queue_is_empty(queue)) { QueuedSnac *queued_snac; struct rateclass *rateclass; - queued_snac = g_queue_peek_head(conn->queued_snacs); + queued_snac = g_queue_peek_head(queue); rateclass = flap_connection_get_rateclass(conn, queued_snac->family, queued_snac->subtype); if (rateclass != NULL) @@ -133,7 +133,7 @@ /* (Add 100ms padding to account for inaccuracies in the calculation) */ if (new_current < rateclass->alert + 100) /* Not ready to send this SNAC yet--keep waiting. */ - return TRUE; + return FALSE; rateclass->current = new_current; rateclass->last.tv_sec = now.tv_sec; @@ -142,11 +142,35 @@ flap_connection_send(conn, queued_snac->frame); g_free(queued_snac); - g_queue_pop_head(conn->queued_snacs); + g_queue_pop_head(queue); } - conn->queued_timeout = 0; - return FALSE; + /* We emptied the queue */ + return TRUE; +} + +static gboolean flap_connection_send_queued(gpointer data) +{ + FlapConnection *conn; + struct timeval now; + + conn = data; + gettimeofday(&now, NULL); + + purple_debug_info("oscar", "Attempting to send %u queued SNACs and %u queued low-priority SNACs for %p\n", + (conn->queued_snacs ? g_queue_get_length(conn->queued_snacs) : 0), + (conn->queued_lowpriority_snacs ? g_queue_get_length(conn->queued_lowpriority_snacs) : 0), + conn); + if (!conn->queued_snacs || flap_connection_send_snac_queue(conn, now, conn->queued_snacs)) { + if (!conn->queued_lowpriority_snacs || flap_connection_send_snac_queue(conn, now, conn->queued_lowpriority_snacs)) { + /* Both queues emptied. */ + conn->queued_timeout = 0; + return FALSE; + } + } + + /* We couldn't send all our SNACs. Keep trying */ + return TRUE; } /** @@ -157,9 +181,12 @@ * * @param data The optional bytestream that makes up the data portion * of this SNAC. For empty SNACs this should be NULL. + * @param high_priority If TRUE, the SNAC will be queued normally if + * needed. If FALSE, it wil be queued separately, to be sent + * only if all high priority SNACs have been sent. */ void -flap_connection_send_snac(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, guint16 flags, aim_snacid_t snacid, ByteStream *data) +flap_connection_send_snac_with_priority(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, guint16 flags, aim_snacid_t snacid, ByteStream *data, gboolean high_priority) { FlapFrame *frame; guint32 length; @@ -213,7 +240,16 @@ queued_snac->family = family; queued_snac->subtype = subtype; queued_snac->frame = frame; - g_queue_push_tail(conn->queued_snacs, queued_snac); + + if (high_priority) { + if (!conn->queued_snacs) + conn->queued_snacs = g_queue_new(); + g_queue_push_tail(conn->queued_snacs, queued_snac); + } else { + if (!conn->queued_lowpriority_snacs) + conn->queued_lowpriority_snacs = g_queue_new(); + g_queue_push_tail(conn->queued_lowpriority_snacs, queued_snac); + } if (conn->queued_timeout == 0) conn->queued_timeout = purple_timeout_add(500, flap_connection_send_queued, conn); @@ -224,6 +260,12 @@ flap_connection_send(conn, frame); } +void +flap_connection_send_snac(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, guint16 flags, aim_snacid_t snacid, ByteStream *data) +{ + flap_connection_send_snac_with_priority(od, conn, family, subtype, flags, snacid, data, TRUE); +} + /** * This sends an empty channel 4 FLAP. This is sent to signify * that we're logging off. This shouldn't really be necessary-- @@ -275,7 +317,6 @@ conn->fd = -1; conn->subtype = -1; conn->type = type; - conn->queued_snacs = g_queue_new(); od->oscar_connections = g_slist_prepend(od->oscar_connections, conn); @@ -434,14 +475,28 @@ conn->rateclasses = g_slist_delete_link(conn->rateclasses, conn->rateclasses); } - while (!g_queue_is_empty(conn->queued_snacs)) - { - QueuedSnac *queued_snac; - queued_snac = g_queue_pop_head(conn->queued_snacs); - flap_frame_destroy(queued_snac->frame); - g_free(queued_snac); + if (conn->queued_snacs) { + while (!g_queue_is_empty(conn->queued_snacs)) + { + QueuedSnac *queued_snac; + queued_snac = g_queue_pop_head(conn->queued_snacs); + flap_frame_destroy(queued_snac->frame); + g_free(queued_snac); + } + g_queue_free(conn->queued_snacs); } - g_queue_free(conn->queued_snacs); + + if (conn->queued_lowpriority_snacs) { + while (!g_queue_is_empty(conn->queued_lowpriority_snacs)) + { + QueuedSnac *queued_snac; + queued_snac = g_queue_pop_head(conn->queued_lowpriority_snacs); + flap_frame_destroy(queued_snac->frame); + g_free(queued_snac); + } + g_queue_free(conn->queued_lowpriority_snacs); + } + if (conn->queued_timeout > 0) purple_timeout_remove(conn->queued_timeout); @@ -998,4 +1053,3 @@ sendframe_flap(conn, frame); flap_frame_destroy(frame); } - diff -r d70aad03b491 -r ec227bab07b6 libpurple/protocols/oscar/oscar.c --- a/libpurple/protocols/oscar/oscar.c Wed Jul 23 05:36:12 2008 +0000 +++ b/libpurple/protocols/oscar/oscar.c Wed Jul 23 05:44:56 2008 +0000 @@ -1893,6 +1893,38 @@ return 1; } +static gboolean purple_requesticqstatusnote(gpointer data) +{ + PurpleConnection *gc = data; + OscarData *od = gc->proto_data; + + while (od->statusnotes_queue != NULL) + { + char *sn; + struct aim_ssi_item *ssi_item; + aim_tlv_t *note_hash; + + sn = od->statusnotes_queue->data; + + ssi_item = aim_ssi_itemlist_finditem(od->ssi.local, + NULL, sn, AIM_SSI_TYPE_BUDDY); + if (ssi_item != NULL) + { + note_hash = aim_tlv_gettlv(ssi_item->data, 0x015c, 1); + if (note_hash != NULL) { + aim_icq_getstatusnote(od, sn, note_hash->value, note_hash->length); + } + } + + od->statusnotes_queue = g_slist_remove(od->statusnotes_queue, sn); + g_free(sn); + } + + od->statusnotes_queue_timer = 0; + return FALSE; +} + + static int purple_parse_oncoming(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { PurpleConnection *gc; @@ -2074,8 +2106,28 @@ if (ssi_item != NULL) { note_hash = aim_tlv_gettlv(ssi_item->data, 0x015c, 1); - if (note_hash != NULL) - aim_icq_getstatusnote(od, info->sn, note_hash->value, note_hash->length); + if (note_hash != NULL) { + /* We do automatic rate limiting at the FLAP level, so + * a flood of requests won't disconnect us. However, + * it WOULD mean that we would have to wait a + * potentially long time to be able to message in real + * time again. Also, since we're requesting with every + * purple_parse_oncoming() call, which often come in + * groups, we should coalesce to do only one lookup per + * buddy. + */ + if (od->statusnotes_queue == NULL || + g_slist_find_custom(od->statusnotes_queue, info->sn, (GCompareFunc)strcmp) == NULL) + { + od->statusnotes_queue = g_slist_prepend(od->statusnotes_queue, + g_strdup(info->sn)); + + if (od->statusnotes_queue_timer > 0) + purple_timeout_remove(od->statusnotes_queue_timer); + od->statusnotes_queue_timer = purple_timeout_add_seconds(3, + purple_requesticqstatusnote, gc); + } + } } } diff -r d70aad03b491 -r ec227bab07b6 libpurple/protocols/oscar/oscar.h --- a/libpurple/protocols/oscar/oscar.h Wed Jul 23 05:36:12 2008 +0000 +++ b/libpurple/protocols/oscar/oscar.h Wed Jul 23 05:44:56 2008 +0000 @@ -433,6 +433,7 @@ GSList *rateclasses; /* Contains nodes of struct rateclass. */ GQueue *queued_snacs; /**< Contains QueuedSnacs. */ + GQueue *queued_lowpriority_snacs; /**< Contains QueuedSnacs to send only once queued_snacs is empty */ guint queued_timeout; void *internal; /* internal conn-specific libfaim data */ @@ -543,6 +544,10 @@ /** A linked list containing PeerConnections. */ GSList *peer_connections; + + /** Queue of ICQ Status Notes to request. */ + GSList *statusnotes_queue; + guint statusnotes_queue_timer; }; /* Valid for calling aim_icq_setstatus() and for aim_userinfo_t->icqinfo.status */ @@ -625,6 +630,7 @@ void flap_connection_send_version(OscarData *od, FlapConnection *conn); void flap_connection_send_version_with_cookie(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy); void flap_connection_send_snac(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, guint16 flags, aim_snacid_t snacid, ByteStream *data); +void flap_connection_send_snac_with_priority(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, guint16 flags, aim_snacid_t snacid, ByteStream *data, gboolean high_priority); void flap_connection_send_keepalive(OscarData *od, FlapConnection *conn); FlapFrame *flap_frame_new(OscarData *od, guint16 channel, int datalen); diff -r d70aad03b491 -r ec227bab07b6 libpurple/protocols/oscar/oscar_data.c --- a/libpurple/protocols/oscar/oscar_data.c Wed Jul 23 05:36:12 2008 +0000 +++ b/libpurple/protocols/oscar/oscar_data.c Wed Jul 23 05:44:56 2008 +0000 @@ -88,10 +88,17 @@ while (od->requesticon) { - gchar *sn = od->requesticon->data; - od->requesticon = g_slist_remove(od->requesticon, sn); - g_free(sn); + g_free(od->requesticon->data); + od->requesticon = g_slist_delete_link(od->requesticon, od->requesticon); } + while (od->statusnotes_queue) + { + g_free(od->statusnotes_queue->data); + od->statusnotes_queue = g_slist_delete_link(od->statusnotes_queue, + od->statusnotes_queue); + } + if (od->statusnotes_queue_timer > 0) + purple_timeout_remove(od->statusnotes_queue_timer); g_free(od->email); g_free(od->newp); g_free(od->oldp); diff -r d70aad03b491 -r ec227bab07b6 pidgin/pidgintooltip.c --- a/pidgin/pidgintooltip.c Wed Jul 23 05:36:12 2008 +0000 +++ b/pidgin/pidgintooltip.c Wed Jul 23 05:44:56 2008 +0000 @@ -59,6 +59,7 @@ destroy_tooltip_data(PidginTooltipData *data) { gtk_tree_path_free(data->common.treeview.path); + pidgin_tooltip_destroy(); g_free(data); } diff -r d70aad03b491 -r ec227bab07b6 pidgin/win32/nsis/pidgin-installer.nsi --- a/pidgin/win32/nsis/pidgin-installer.nsi Wed Jul 23 05:36:12 2008 +0000 +++ b/pidgin/win32/nsis/pidgin-installer.nsi Wed Jul 23 05:44:56 2008 +0000 @@ -505,11 +505,20 @@ ; If this is under NT4, delete the SILC support stuff ; there is a bug that will prevent any account from connecting ; See https://lists.silcnet.org/pipermail/silc-devel/2005-January/001588.html + ; Also, remove the GSSAPI SASL plugin and associated files as they aren't + ; compatible with NT4. ${If} ${IsNT} ${AndIf} ${IsWinNT4} + ;SILC Delete "$INSTDIR\plugins\libsilc.dll" Delete "$INSTDIR\libsilcclient-1-1-2.dll" Delete "$INSTDIR\libsilc-1-1-2.dll" + ;GSSAPI + Delete "$INSTDIR\sasl2\saslGSSAPI.dll" + Delete "$INSTDIR\gssapi32.dll" + Delete "$INSTDIR\k5sprt32.dll" + Delete "$INSTDIR\krb5_32.dll" + Delete "$INSTDIR\comerr32.dll" ${EndIf} SetOutPath "$INSTDIR" @@ -704,6 +713,8 @@ Push "ymsgr" Call un.UnregisterURIHandler + Delete "$INSTDIR\ca-certs\CAcert_Class3.pem" + Delete "$INSTDIR\ca-certs\CAcert_Root.pem" Delete "$INSTDIR\ca-certs\Equifax_Secure_CA.pem" Delete "$INSTDIR\ca-certs\GTE_CyberTrust_Global_Root.pem" Delete "$INSTDIR\ca-certs\Microsoft_Secure_Server_Authority.pem"