Mercurial > pidgin.yaz
changeset 27864:e81f0d1966db
propagate from branch 'im.pidgin.pidgin' (head fedb7de8d5fe70aa0cd0ee66f32050b68f5fd230)
to branch 'im.pidgin.pidgin.yaz' (head 408cc507c692410048dc0b6fd409bb65b04b45cd)
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Mon, 28 Jul 2008 06:18:51 +0000 |
parents | 57727a140609 (current diff) d1d32f318ce9 (diff) |
children | 86e7e2b5e59a |
files | configure.ac libpurple/protocols/irc/irc.c libpurple/protocols/irc/parse.c libpurple/protocols/jabber/jabber.c libpurple/protocols/jabber/si.c libpurple/protocols/msn/switchboard.c libpurple/protocols/oscar/oscar.c libpurple/protocols/oscar/oscar.h libpurple/protocols/yahoo/yahoo_profile.c libpurple/server.c |
diffstat | 41 files changed, 700 insertions(+), 263 deletions(-) [+] |
line wrap: on
line diff
--- a/COPYRIGHT Fri Jul 18 08:45:31 2008 +0000 +++ b/COPYRIGHT Mon Jul 28 06:18:51 2008 +0000 @@ -157,6 +157,7 @@ Konrad Gräfe Miah Gregory David Grohmann +Vladislav Guberinić Gideon N. Guillen Christian Hammond Erick Hamness
--- a/ChangeLog Fri Jul 18 08:45:31 2008 +0000 +++ b/ChangeLog Mon Jul 28 06:18:51 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
--- a/ChangeLog.win32 Fri Jul 18 08:45:31 2008 +0000 +++ b/ChangeLog.win32 Mon Jul 28 06:18:51 2008 +0000 @@ -1,3 +1,8 @@ +version 2.5.0 (??/??/2008): + * Don't install the GSSAPI SASL plugin on NT4 to avoid an error popup. + * Upgrade to Perl 5.10 (System Perl runtime must be upgraded for Perl + plugins to continue to work). + version 2.4.3 (07/01/2008): * No changes
--- a/configure.ac Fri Jul 18 08:45:31 2008 +0000 +++ b/configure.ac Mon Jul 28 06:18:51 2008 +0000 @@ -47,7 +47,7 @@ m4_define([purple_major_version], [2]) m4_define([purple_minor_version], [5]) m4_define([purple_micro_version], [0]) -m4_define([purple_version_suffix], []) +m4_define([purple_version_suffix], [devel]) m4_define([purple_version], [purple_major_version.purple_minor_version.purple_micro_version]) m4_define([purple_display_version], purple_version[]m4_ifdef([purple_version_suffix],[purple_version_suffix])) @@ -56,7 +56,7 @@ m4_define([gnt_major_version], [2]) m4_define([gnt_minor_version], [5]) m4_define([gnt_micro_version], [0]) -m4_define([gnt_version_suffix], []) +m4_define([gnt_version_suffix], [devel]) m4_define([gnt_version], [gnt_major_version.gnt_minor_version.gnt_micro_version]) m4_define([gnt_display_version], gnt_version[]m4_ifdef([gnt_version_suffix],[gnt_version_suffix]))
--- a/doc/funniest_home_convos.txt Fri Jul 18 08:45:31 2008 +0000 +++ b/doc/funniest_home_convos.txt Mon Jul 28 06:18:51 2008 +0000 @@ -510,3 +510,8 @@ 12:58 <staggered_ranks> why hasn't support for napster been removed? 12:58 <deryni> It has. 12:59 <staggered_ranks> oh.. ok + + +14:39 <rrobbertt> Does anyone know a way to get text to speech with pidgin? +14:41 <elb> do you want to be rooted sooner, or later? +14:42 <seanegan> good question"; rm -rf ~
--- a/libpurple/plugins/perl/Makefile.mingw Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/plugins/perl/Makefile.mingw Mon Jul 28 06:18:51 2008 +0000 @@ -47,7 +47,7 @@ -lws2_32 \ -lintl \ -lpurple \ - -lperl58 + -lperl510 include $(PIDGIN_COMMON_RULES)
--- a/libpurple/plugins/perl/common/Makefile.mingw Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/plugins/perl/common/Makefile.mingw Mon Jul 28 06:18:51 2008 +0000 @@ -5,6 +5,7 @@ # PIDGIN_TREE_TOP := ../../../.. +GCCWARNINGS := -Wno-comment -Waggregate-return -Wcast-align -Wdeclaration-after-statement -Werror-implicit-function-declaration -Wextra -Wno-sign-compare -Wno-unused-parameter -Winit-self -Wmissing-declarations -Wmissing-prototypes -Wpointer-arith -Wundef -Wno-unused include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak TARGET = Purple @@ -12,8 +13,6 @@ EXTUTILS ?= C:/perl/lib/ExtUtils PERL_PLUGIN_TOP := .. -CFLAGS += -Wno-comment -Wno-unused - ## ## INCLUDE PATHS ## @@ -77,7 +76,7 @@ ## ## LIBRARIES ## -LIBS = -lperl58 \ +LIBS = -lperl510 \ -lperl \ -lpurple \ -lglib-2.0
--- a/libpurple/plugins/perl/perl-common.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/plugins/perl/perl-common.c Mon Jul 28 06:18:51 2008 +0000 @@ -32,7 +32,10 @@ static MGVTBL vtbl_free_object = { - NULL, NULL, NULL, NULL, magic_free_object, NULL, NULL + 0, 0, 0, 0, magic_free_object, 0, 0 +#if PERL_API_REVISION > 5 || (PERL_API_REVISION == 5 && PERL_API_VERSION >= 10) + , 0 +#endif }; static SV *
--- a/libpurple/plugins/perl/perl-common.h Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/plugins/perl/perl-common.h Mon Jul 28 06:18:51 2008 +0000 @@ -5,9 +5,9 @@ #ifdef _WIN32 #undef pipe #endif -#include <XSUB.h> #include <EXTERN.h> #include <perl.h> +#include <XSUB.h> /* XXX: perl defines it's own _ but I think it's safe to undef it */ #undef _
--- a/libpurple/plugins/perl/perl.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/plugins/perl/perl.c Mon Jul 28 06:18:51 2008 +0000 @@ -67,6 +67,10 @@ #undef group /* perl module support */ +#ifdef _WIN32 +EXTERN_C void boot_Win32CORE (pTHX_ CV* cv); +#endif + #ifdef OLD_PERL extern void boot_DynaLoader _((CV * cv)); #else @@ -127,10 +131,14 @@ #endif { char *file = __FILE__; + dXSUB_SYS; /* This one allows dynamic loading of perl modules in perl scripts by * the 'use perlmod;' construction */ newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file); +#ifdef _WIN32 + newXS("Win32CORE::bootstrap", boot_Win32CORE, file); +#endif } static void @@ -240,18 +248,44 @@ static gboolean probe_perl_plugin(PurplePlugin *plugin) { - /* XXX This would be much faster if I didn't create a new - * PerlInterpreter every time I probed a plugin */ - PerlInterpreter *prober = perl_alloc(); - char *argv[] = {"", plugin->path }; + char *args[] = {"", plugin->path }; + char **argv = args; + int argc = 2; + PerlInterpreter *prober; gboolean status = TRUE; HV *plugin_info; + + PERL_SYS_INIT(&argc, &argv); + + /* XXX This would be much faster if we didn't create a new + * PerlInterpreter every time we probe a plugin */ + prober = perl_alloc(); + PERL_SET_CONTEXT(prober); + PL_perl_destruct_level = 1; perl_construct(prober); - perl_parse(prober, xs_init, 2, argv, NULL); +/* Fix IO redirection to match where pidgin's is going. + * Without this, we lose stdout/stderr unless we redirect to a file */ +#ifdef _WIN32 +{ + PerlIO* newprlIO = PerlIO_open("CONOUT$", "w"); + if (newprlIO) { + int stdout_fd = PerlIO_fileno(PerlIO_stdout()); + int stderr_fd = PerlIO_fileno(PerlIO_stderr()); + PerlIO_close(PerlIO_stdout()); + PerlIO_close(PerlIO_stderr()); + PerlLIO_dup2(PerlIO_fileno(newprlIO), stdout_fd); + PerlLIO_dup2(PerlIO_fileno(newprlIO), stderr_fd); + + PerlIO_close(newprlIO); + } +} +#endif + + perl_parse(prober, xs_init, argc, argv, NULL); perl_run(prober); @@ -578,7 +612,7 @@ load_perl_plugin, /**< load */ unload_perl_plugin, /**< unload */ destroy_perl_plugin, /**< destroy */ - + /* padding */ NULL, NULL,
--- a/libpurple/protocols/bonjour/jabber.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/bonjour/jabber.c Mon Jul 28 06:18:51 2008 +0000 @@ -672,7 +672,6 @@ bonjour_jabber_start(BonjourJabber *jdata) { struct sockaddr_in my_addr; - int yes = 1; int i; gboolean bind_successful; @@ -686,16 +685,6 @@ return -1; } - /* Make the socket reusable */ - if (setsockopt(jdata->socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0) - { - purple_debug_error("bonjour", "Error setting socket options: %s\n", g_strerror(errno)); - purple_connection_error_reason (jdata->account->gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Error setting socket options")); - return -1; - } - memset(&my_addr, 0, sizeof(struct sockaddr_in)); my_addr.sin_family = AF_INET; @@ -709,6 +698,8 @@ bind_successful = TRUE; break; } + + purple_debug_info("bonjour", "Unable to bind to port %u.(%s)\n", jdata->port, g_strerror(errno)); jdata->port++; }
--- a/libpurple/protocols/irc/cmds.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/irc/cmds.c Mon Jul 28 06:18:51 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);
--- a/libpurple/protocols/irc/irc.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/irc/irc.c Mon Jul 28 06:18:51 2008 +0000 @@ -360,7 +360,8 @@ static gboolean do_login(PurpleConnection *gc) { char *buf, *tmp = NULL; - const char *hostname; + char *hostname, *server; + const char *hosttmp; const char *username, *realname; struct irc_conn *irc = gc->proto_data; const char *pass = purple_connection_get_password(gc); @@ -374,7 +375,6 @@ g_free(buf); } - hostname = purple_get_host_name(); realname = purple_account_get_string(irc->account, "realname", ""); username = purple_account_get_string(irc->account, "username", ""); @@ -389,9 +389,29 @@ } } - buf = irc_format(irc, "vvvv:", "USER", tmp ? tmp : username, hostname, irc->server, - strlen(realname) ? realname : IRC_DEFAULT_ALIAS); + hosttmp = purple_get_host_name(); + if (*hosttmp == ':') { + /* This is either an IPv6 address, or something which + * doesn't belong here. Either way, we need to escape + * it. */ + hostname = g_strdup_printf("0%s", hosttmp); + } else { + /* Ugly, I know. */ + hostname = g_strdup(hosttmp); + } + + if (*irc->server == ':') { + /* Same as hostname, above. */ + server = g_strdup_printf("0%s", irc->server); + } else { + server = g_strdup(irc->server); + } + + buf = irc_format(irc, "vvvv:", "USER", tmp ? tmp : username, hostname, server, + strlen(realname) ? realname : IRC_DEFAULT_ALIAS); g_free(tmp); + g_free(hostname); + g_free(server); if (irc_send(irc, buf) < 0) { g_free(buf); return FALSE;
--- a/libpurple/protocols/irc/irc.h Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/irc/irc.h Mon Jul 28 06:18:51 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);
--- a/libpurple/protocols/irc/parse.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/irc/parse.c Mon Jul 28 06:18:51 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 <nick> <msg>: 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.") },
--- a/libpurple/protocols/jabber/disco.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/jabber/disco.c Mon Jul 28 06:18:51 2008 +0000 @@ -73,6 +73,15 @@ "jid='%s' host='%s' port='%d' zeroconf='%s'\n", from ? from : "", sh->host ? sh->host : "", sh->port, sh->zeroconf ? sh->zeroconf : ""); + + /* TODO: When we support zeroconf proxies, fix this to handle them */ + if (!(sh->jid && sh->host && sh->port > 0)) { + g_free(sh->jid); + g_free(sh->host); + g_free(sh->zeroconf); + g_free(sh); + js->bs_proxies = g_list_remove(js->bs_proxies, sh); + } } @@ -329,6 +338,7 @@ static void jabber_disco_finish_server_info_result_cb(JabberStream *js) { + const char *ft_proxies; jabber_vcard_fetch_mine(js); @@ -339,11 +349,44 @@ /* Send initial presence; this will trigger receipt of presence for contacts on the roster */ jabber_presence_send(js->gc->account, NULL); - + if (js->server_caps & JABBER_CAP_ADHOC) { /* The server supports ad-hoc commands, so let's request the list */ jabber_adhoc_server_get_list(js); } + + /* If there are manually specified bytestream proxies, query them */ + ft_proxies = purple_account_get_string(js->gc->account, "ft_proxies", NULL); + if (ft_proxies) { + JabberIq *iq; + JabberBytestreamsStreamhost *sh; + int i; + char *tmp; + gchar **ft_proxy_list = g_strsplit(ft_proxies, ",", 0); + + for(i = 0; ft_proxy_list[i]; i++) { + g_strstrip(ft_proxy_list[i]); + if(!(*ft_proxy_list[i])) + continue; + + /* We used to allow specifying a port directly here; get rid of it */ + if((tmp = strchr(ft_proxy_list[i], ':'))) + *tmp = '\0'; + + sh = g_new0(JabberBytestreamsStreamhost, 1); + sh->jid = g_strdup(ft_proxy_list[i]); + js->bs_proxies = g_list_prepend(js->bs_proxies, sh); + + iq = jabber_iq_new_query(js, JABBER_IQ_GET, + "http://jabber.org/protocol/bytestreams"); + xmlnode_set_attrib(iq->node, "to", sh->jid); + jabber_iq_set_callback(iq, jabber_disco_bytestream_server_cb, sh); + jabber_iq_send(iq); + } + + g_strfreev(ft_proxy_list); + } + } static void
--- a/libpurple/protocols/jabber/jabber.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/jabber/jabber.c Mon Jul 28 06:18:51 2008 +0000 @@ -63,6 +63,7 @@ GList *jabber_features = NULL; static void jabber_unregister_account_cb(JabberStream *js); +static void try_srv_connect(JabberStream *js); static void jabber_stream_init(JabberStream *js) { @@ -522,15 +523,23 @@ JabberStream *js = gc->proto_data; if (source < 0) { - gchar *tmp; - tmp = g_strdup_printf(_("Could not establish a connection with the server:\n%s"), - error); - purple_connection_error_reason (gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); - g_free(tmp); + if (js->srv_rec != NULL) { + purple_debug_error("jabber", "Unable to connect to server: %s. Trying next SRV record.\n", error); + try_srv_connect(js); + } else { + gchar *tmp; + tmp = g_strdup_printf(_("Could not establish a connection with the server:\n%s"), + error); + purple_connection_error_reason(gc, + PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); + g_free(tmp); + } return; } + g_free(js->srv_rec); + js->srv_rec = NULL; + js->fd = source; if(js->state == JABBER_STREAM_CONNECTING) @@ -565,37 +574,62 @@ jabber_login_callback_ssl, jabber_ssl_connect_failure, js->certificate_CN, js->gc); } -static void jabber_login_connect(JabberStream *js, const char *domain, const char *host, int port) +static gboolean jabber_login_connect(JabberStream *js, const char *domain, const char *host, int port, + gboolean fatal_failure) { /* host should be used in preference to domain to * allow SASL authentication to work with FQDN of the server, * but we use domain as fallback for when users enter IP address * in connect server */ + g_free(js->serverFQDN); if (purple_ip_address_is_valid(host)) js->serverFQDN = g_strdup(domain); else js->serverFQDN = g_strdup(host); if (purple_proxy_connect(js->gc, js->gc->account, host, - port, jabber_login_callback, js->gc) == NULL) - purple_connection_error_reason (js->gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Unable to create socket")); + port, jabber_login_callback, js->gc) == NULL) { + if (fatal_failure) { + purple_connection_error_reason (js->gc, + PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("Unable to create socket")); + } + + return FALSE; + } + + return TRUE; +} + +static void try_srv_connect(JabberStream *js) +{ + while (js->srv_rec != NULL && js->srv_rec_idx < js->max_srv_rec_idx) { + PurpleSrvResponse *tmp_resp = js->srv_rec + (js->srv_rec_idx++); + if (jabber_login_connect(js, tmp_resp->hostname, tmp_resp->hostname, tmp_resp->port, FALSE)) + return; + } + + g_free(js->srv_rec); + js->srv_rec = NULL; + + /* Fall back to the defaults (I'm not sure if we should actually do this) */ + jabber_login_connect(js, js->user->domain, js->user->domain, + purple_account_get_int(js->gc->account, "port", 5222), TRUE); } static void srv_resolved_cb(PurpleSrvResponse *resp, int results, gpointer data) { - JabberStream *js; - - js = data; + JabberStream *js = data; js->srv_query_data = NULL; if(results) { - jabber_login_connect(js, resp->hostname, resp->hostname, resp->port); - g_free(resp); + js->srv_rec = resp; + js->srv_rec_idx = 0; + js->max_srv_rec_idx = results; + try_srv_connect(js); } else { jabber_login_connect(js, js->user->domain, js->user->domain, - purple_account_get_int(js->gc->account, "port", 5222)); + purple_account_get_int(js->gc->account, "port", 5222), TRUE); } } @@ -677,7 +711,7 @@ * invoke the magic of SRV lookups, to figure out host and port */ if(!js->gsc) { if(connect_server[0]) { - jabber_login_connect(js, js->user->domain, connect_server, purple_account_get_int(account, "port", 5222)); + jabber_login_connect(js, js->user->domain, connect_server, purple_account_get_int(account, "port", 5222), TRUE); } else { js->srv_query_data = purple_srv_resolve("xmpp-client", "tcp", js->user->domain, srv_resolved_cb, js); @@ -1158,7 +1192,7 @@ if (connect_server[0]) { jabber_login_connect(js, js->user->domain, server, purple_account_get_int(account, - "port", 5222)); + "port", 5222), TRUE); } else { js->srv_query_data = purple_srv_resolve("xmpp-client", "tcp", @@ -1329,7 +1363,10 @@ if (js->keepalive_timeout != -1) purple_timeout_remove(js->keepalive_timeout); - + + g_free(js->srv_rec); + js->srv_rec = NULL; + g_free(js); gc->proto_data = NULL;
--- a/libpurple/protocols/jabber/jabber.h Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/jabber/jabber.h Mon Jul 28 06:18:51 2008 +0000 @@ -201,6 +201,10 @@ /* A purple timeout tag for the keepalive */ int keepalive_timeout; + + PurpleSrvResponse *srv_rec; + guint srv_rec_idx; + guint max_srv_rec_idx; }; typedef gboolean (JabberFeatureEnabled)(JabberStream *js, const gchar *shortname, const gchar *namespace);
--- a/libpurple/protocols/jabber/libxmpp.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/jabber/libxmpp.c Mon Jul 28 06:18:51 2008 +0000 @@ -236,7 +236,7 @@ option = purple_account_option_string_new(_("File transfer proxies"), "ft_proxies", /* TODO: Is this an acceptable default? */ - "proxy.jabber.org:7777"); + "proxy.jabber.org"); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--- a/libpurple/protocols/jabber/si.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/jabber/si.c Mon Jul 28 06:18:51 2008 +0000 @@ -723,7 +723,6 @@ JabberSIXfer *jsx; JabberIq *iq; xmlnode *query, *streamhost; - const char *ft_proxies; char port[6]; GList *tmp; JabberBytestreamsStreamhost *sh, *sh2; @@ -787,52 +786,6 @@ jabber_si_xfer_bytestreams_send_connected_cb, xfer); } - /* insert proxies here */ - ft_proxies = purple_account_get_string(xfer->account, "ft_proxies", NULL); - if (ft_proxies) { - int i, portnum; - char *tmp; - gchar **ft_proxy_list = g_strsplit(ft_proxies, ",", 0); - - g_list_foreach(jsx->streamhosts, jabber_si_free_streamhost, NULL); - g_list_free(jsx->streamhosts); - jsx->streamhosts = NULL; - - for(i = 0; ft_proxy_list[i]; i++) { - g_strstrip(ft_proxy_list[i]); - if(!(*ft_proxy_list[i])) - continue; - - if((tmp = strchr(ft_proxy_list[i], ':'))) { - portnum = atoi(tmp + 1); - *tmp = '\0'; - } else - portnum = 7777; - - g_snprintf(port, sizeof(port), "%hu", portnum); - - purple_debug_info("jabber", "jabber_si_xfer_bytestreams_listen_cb() will be looking at jsx %p: jsx->streamhosts %p and ft_proxy_list[%i] %p\n", - jsx, jsx->streamhosts, i, ft_proxy_list[i]); - if(g_list_find_custom(jsx->streamhosts, ft_proxy_list[i], jabber_si_compare_jid) != NULL) - continue; - - streamhost_count++; - streamhost = xmlnode_new_child(query, "streamhost"); - xmlnode_set_attrib(streamhost, "jid", ft_proxy_list[i]); - xmlnode_set_attrib(streamhost, "host", ft_proxy_list[i]); - xmlnode_set_attrib(streamhost, "port", port); - - sh = g_new0(JabberBytestreamsStreamhost, 1); - sh->jid = g_strdup(ft_proxy_list[i]); - sh->host = g_strdup(ft_proxy_list[i]); - sh->port = portnum; - - jsx->streamhosts = g_list_prepend(jsx->streamhosts, sh); - } - - g_strfreev(ft_proxy_list); - } - for (tmp = jsx->js->bs_proxies; tmp; tmp = tmp->next) { sh = tmp->data;
--- a/libpurple/protocols/msn/notification.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/msn/notification.c Mon Jul 28 06:18:51 2008 +0000 @@ -989,7 +989,8 @@ PurpleConnection *gc; MsnUserList *userlist; char *who = NULL, *text = NULL; - xmlnode *payloadNode, *from, *textNode; + const char *id = NULL; + xmlnode *payloadNode, *from, *msg, *textNode; purple_debug_misc("msn", "Incoming Page: {%s}\n", payload); @@ -1014,9 +1015,27 @@ </NOTIFICATION> */ + /* This is the payload if your message was too long: + <NOTIFICATION id="TrID" siteid="111100400" siteurl="http://mobile.msn.com/"> + <TO name="passport@example.com"> + <VIA agent="mobile"/> + </TO> + <FROM name="tel:+XXXXXXXXXXX"/> + <MSG pri="1" id="407"> + <CAT Id="110110001"/> + <ACTION url="2wayIM.asp"/> + <SUBSCR url="2wayIM.asp"/> + <BODY lcid="1033"> + <TEXT></TEXT> + </BODY> + </MSG> + </NOTIFICATION> + */ + if (!(payloadNode = xmlnode_from_str(payload, len)) || !(from = xmlnode_get_child(payloadNode, "FROM")) || - !(textNode = xmlnode_get_child(payloadNode, "MSG/BODY/TEXT"))) + !(msg = xmlnode_get_child(payloadNode, "MSG")) || + !(textNode = xmlnode_get_child(msg, "BODY/TEXT"))) return; who = g_strdup(xmlnode_get_attrib(from, "name")); @@ -1026,7 +1045,7 @@ /* Match number to user's mobile number, FROM is a phone number if the other side page you using your phone number */ - if(!strncmp(who, "tel:+", 5)) { + if (!strncmp(who, "tel:+", 5)) { MsnUser *user = msn_userlist_find_user_with_mobile_phone(userlist, who + 4); @@ -1036,7 +1055,20 @@ } } - serv_got_im(gc, who, text, 0, time(NULL)); + id = xmlnode_get_attrib(msg, "id"); + + if (id && !strcmp(id, "407")) { + /* TODO: Use this to NAK the transaction, maybe print the text, too. + unsigned int trId; + id = xmlnode_get_attrib(payloadNode, "id"); + trId = atol(id); + */ + purple_conv_present_error(who, gc->account, + _("Mobile message was not sent because it was too long.")); + + } else { + serv_got_im(gc, who, text, 0, time(NULL)); + } g_free(text); g_free(who);
--- a/libpurple/protocols/msn/oim.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/msn/oim.c Mon Jul 28 06:18:51 2008 +0000 @@ -381,11 +381,11 @@ } else if (g_str_equal(faultcode_str, "q0:InvalidContent")) { str_reason = _("Message was not sent because an unknown " - "encoding error occured."); + "encoding error occurred."); } else { str_reason = _("Message was not sent because an unknown " - "error occured."); + "error occurred."); } msn_session_report_user(oim->session, msg->to_member,
--- a/libpurple/protocols/msn/page.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/msn/page.c Mon Jul 28 06:18:51 2008 +0000 @@ -53,9 +53,9 @@ g_return_val_if_fail(page != NULL, NULL); - str = - g_strdup_printf("<TEXT xml:space=\"preserve\" enc=\"utf-8\">%s</TEXT>", - msn_page_get_body(page)); + str = g_markup_printf_escaped( + "<TEXT xml:space=\"preserve\" enc=\"utf-8\">%s</TEXT>", + msn_page_get_body(page)); if (ret_size != NULL) *ret_size = strlen(str);
--- a/libpurple/protocols/msn/switchboard.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/msn/switchboard.c Mon Jul 28 06:18:51 2008 +0000 @@ -982,7 +982,13 @@ account = cmdproc->session->account; user = msg->remote_user; - serv_got_attention(account->gc, user, MSN_NUDGE); + if (swboard->current_users > 1 || + ((swboard->conv != NULL) && + purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT)) + purple_prpl_got_attention_in_chat(account->gc, swboard->chat_id, user, MSN_NUDGE); + + else + purple_prpl_got_attention(account->gc, user, MSN_NUDGE); } else if (!strcmp(id, "2")) { /* Wink */
--- a/libpurple/protocols/oscar/family_icq.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/oscar/family_icq.c Mon Jul 28 06:18:51 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); }
--- a/libpurple/protocols/oscar/family_locate.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/oscar/family_locate.c Mon Jul 28 06:18:51 2008 +0000 @@ -53,10 +53,9 @@ * These are in ascending numerical order. */ - /* - * Perhaps better called OSCAR_CAPABILITY_SHORTCAPS - */ - {OSCAR_CAPABILITY_ICHAT, + /* Client understands short caps, a UUID of the form + * 0946XXYY-4C7F-11D1-8222-444553540000 where XXYY is the short cap. */ + {OSCAR_CAPABILITY_SHORTCAPS, {0x09, 0x46, 0x00, 0x00, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, @@ -64,11 +63,15 @@ {0x09, 0x46, 0x00, 0x01, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, + {OSCAR_CAPABILITY_XHTML_IM, + {0x09, 0x46, 0x00, 0x02, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, + {OSCAR_CAPABILITY_VIDEO, {0x09, 0x46, 0x01, 0x00, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - /* "Live Video" support in Windows AIM 5.5.3501 and newer */ + /* "Live Video" (SIP/RTC Video) support in Windows AIM 5.5.3501 and newer */ {OSCAR_CAPABILITY_LIVEVIDEO, {0x09, 0x46, 0x01, 0x01, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, @@ -78,9 +81,15 @@ {0x09, 0x46, 0x01, 0x02, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - /* In Windows AIM 5.5.3501 and newer */ + /* "Microphone" support in Windows AIM 5.5.3501 and newer */ + {OSCAR_CAPABILITY_MICROPHONE, + {0x09, 0x46, 0x01, 0x03, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, + + /* Supports RTC Audio */ + /* OSCAR_CAPABILITY_RTCAUDIO */ {OSCAR_CAPABILITY_GENERICUNKNOWN, - {0x09, 0x46, 0x01, 0x03, 0x4c, 0x7f, 0x11, 0xd1, + {0x09, 0x46, 0x01, 0x04, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, /* In iChatAV (version numbers...?) */ @@ -88,12 +97,21 @@ {0x09, 0x46, 0x01, 0x05, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x45, 0x53, 0x54, 0x00}}, - /* - * Not really sure about this one. In an email from - * 26 Sep 2003, Matthew Sachs suggested that, "this - * is probably the capability for the SMS features." - */ - {OSCAR_CAPABILITY_SMS, + /* Supports "new status message features" (Who advertises this one?) */ + /* OSCAR_CAPABILITY_HOST_STATUS_TEXT_AWARE */ + {OSCAR_CAPABILITY_GENERICUNKNOWN, + {0x09, 0x46, 0x01, 0x0a, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, + + /* Supports "see as I type" (Who advertises this one?) */ + /* OSCAR_CAPABILITY_SEE_AS_I_TYPE */ + {OSCAR_CAPABILITY_GENERICUNKNOWN, + {0x09, 0x46, 0x01, 0x0b, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, + + /* Client only asserts caps for services in which it is participating */ + /* OSCAR_CAPABILITY_SMARTCAPS */ + {OSCAR_CAPABILITY_GENERICUNKNOWN, {0x09, 0x46, 0x01, 0xff, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, @@ -1386,7 +1404,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);
--- a/libpurple/protocols/oscar/flap_connection.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/oscar/flap_connection.c Mon Jul 28 06:18:51 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); } -
--- a/libpurple/protocols/oscar/oscar.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/oscar/oscar.c Mon Jul 28 06:18:51 2008 +0000 @@ -66,7 +66,9 @@ #define OSCAR_CONNECT_STEPS 6 -static OscarCapability purple_caps = OSCAR_CAPABILITY_CHAT | OSCAR_CAPABILITY_BUDDYICON | OSCAR_CAPABILITY_DIRECTIM | OSCAR_CAPABILITY_SENDFILE | OSCAR_CAPABILITY_UNICODE | OSCAR_CAPABILITY_INTEROPERATE | OSCAR_CAPABILITY_ICHAT; +static OscarCapability purple_caps = (OSCAR_CAPABILITY_CHAT | OSCAR_CAPABILITY_BUDDYICON | OSCAR_CAPABILITY_DIRECTIM | + OSCAR_CAPABILITY_SENDFILE | OSCAR_CAPABILITY_UNICODE | OSCAR_CAPABILITY_INTEROPERATE | + OSCAR_CAPABILITY_SHORTCAPS); static guint8 features_aim[] = {0x01, 0x01, 0x01, 0x02}; static guint8 features_icq[] = {0x01, 0x06}; @@ -1538,6 +1540,7 @@ /* Suspended account */ purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Your account is currently suspended.")); break; + case 0x02: case 0x14: /* service temporarily unavailable */ purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("The AOL Instant Messenger service is temporarily unavailable.")); @@ -1921,6 +1924,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; @@ -2102,8 +2137,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); + } + } } } @@ -3115,7 +3170,7 @@ oscar_user_info_append_status(gc, user_info, /* PurpleBuddy */ NULL, userinfo, /* strip_html_tags */ FALSE); - if (userinfo->present & AIM_USERINFO_PRESENT_IDLE) { + if ((userinfo->present & AIM_USERINFO_PRESENT_IDLE) && userinfo->idletime != 0) { tmp = purple_str_seconds_to_string(userinfo->idletime*60); oscar_user_info_add_pair(user_info, _("Idle"), tmp); g_free(tmp);
--- a/libpurple/protocols/oscar/oscar.h Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/oscar/oscar.h Mon Jul 28 06:18:51 2008 +0000 @@ -353,17 +353,19 @@ OSCAR_CAPABILITY_TRILLIANCRYPT = 0x00010000, OSCAR_CAPABILITY_UNICODE = 0x00020000, OSCAR_CAPABILITY_INTEROPERATE = 0x00040000, - OSCAR_CAPABILITY_ICHAT = 0x00080000, + OSCAR_CAPABILITY_SHORTCAPS = 0x00080000, OSCAR_CAPABILITY_HIPTOP = 0x00100000, OSCAR_CAPABILITY_SECUREIM = 0x00200000, OSCAR_CAPABILITY_SMS = 0x00400000, - OSCAR_CAPABILITY_GENERICUNKNOWN = 0x00800000, + OSCAR_CAPABILITY_MICROPHONE = 0x00800000, OSCAR_CAPABILITY_VIDEO = 0x01000000, OSCAR_CAPABILITY_ICHATAV = 0x02000000, OSCAR_CAPABILITY_LIVEVIDEO = 0x04000000, OSCAR_CAPABILITY_CAMERA = 0x08000000, - OSCAR_CAPABILITY_ICHAT_SCREENSHARE = 0x10000000, - OSCAR_CAPABILITY_LAST = 0x20000000 + OSCAR_CAPABILITY_ICHAT_SCREENSHARE = 0x10000000, + OSCAR_CAPABILITY_XHTML_IM = 0x20000000, + OSCAR_CAPABILITY_GENERICUNKNOWN = 0x40000000, + OSCAR_CAPABILITY_LAST = 0x80000000 } OscarCapability; /* @@ -433,6 +435,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 +546,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 +632,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);
--- a/libpurple/protocols/oscar/oscar_data.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/oscar/oscar_data.c Mon Jul 28 06:18:51 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);
--- a/libpurple/protocols/yahoo/yahoo_profile.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo_profile.c Mon Jul 28 06:18:51 2008 +0000 @@ -1291,6 +1291,10 @@ url_data = purple_util_fetch_url(url, TRUE, NULL, FALSE, yahoo_got_info, data); if (url_data != NULL) yd->url_datas = g_slist_prepend(yd->url_datas, url_data); + else { + g_free(data->name); + g_free(data); + } g_free(url); }
--- a/libpurple/prpl.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/prpl.c Mon Jul 28 06:18:51 2008 +0000 @@ -389,6 +389,110 @@ return statuses; } +void +purple_prpl_send_attention(PurpleConnection *gc, const char *who, guint type_code) +{ + PurpleAttentionType *attn; + PurpleMessageFlags flags; + PurplePlugin *prpl; + PurpleConversation *conv; + gboolean (*send_attention)(PurpleConnection *, const char *, guint); + PurpleBuddy *buddy; + const char *alias; + gchar *description; + time_t mtime; + + g_return_if_fail(gc != NULL); + g_return_if_fail(who != NULL); + + prpl = purple_find_prpl(purple_account_get_protocol_id(gc->account)); + send_attention = PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->send_attention; + g_return_if_fail(send_attention != NULL); + + mtime = time(NULL); + + attn = purple_get_attention_type_from_code(gc->account, type_code); + + if ((buddy = purple_find_buddy(purple_connection_get_account(gc), who)) != NULL) + alias = purple_buddy_get_contact_alias(buddy); + else + alias = who; + + if (attn && purple_attention_type_get_outgoing_desc(attn)) { + description = g_strdup_printf(purple_attention_type_get_outgoing_desc(attn), alias); + } else { + description = g_strdup_printf(_("Requesting %s's attention..."), alias); + } + + flags = PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_NOTIFY | PURPLE_MESSAGE_SYSTEM; + + purple_debug_info("server", "serv_send_attention: sending '%s' to %s\n", + description, who); + + if (!send_attention(gc, who, type_code)) + return; + + conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, gc->account, who); + purple_conv_im_write(PURPLE_CONV_IM(conv), NULL, description, flags, mtime); + + g_free(description); +} + +static void +got_attention(PurpleConnection *gc, int id, const char *who, guint type_code) +{ + PurpleMessageFlags flags; + PurpleAttentionType *attn; + PurpleBuddy *buddy; + const char *alias; + gchar *description; + time_t mtime; + + mtime = time(NULL); + + attn = purple_get_attention_type_from_code(gc->account, type_code); + + /* PURPLE_MESSAGE_NOTIFY is for attention messages. */ + flags = PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NOTIFY | PURPLE_MESSAGE_RECV; + + /* TODO: if (attn->icon_name) is non-null, use it to lookup an emoticon and display + * it next to the attention command. And if it is null, display a generic icon. */ + + if ((buddy = purple_find_buddy(purple_connection_get_account(gc), who)) != NULL) + alias = purple_buddy_get_contact_alias(buddy); + else + alias = who; + + if (attn && purple_attention_type_get_incoming_desc(attn)) { + description = g_strdup_printf(purple_attention_type_get_incoming_desc(attn), alias); + } else { + description = g_strdup_printf(_("%s has requested your attention!"), alias); + } + + purple_debug_info("server", "got_attention: got '%s' from %s\n", + description, who); + + if (id == -1) + serv_got_im(gc, who, description, flags, mtime); + else + serv_got_chat_in(gc, id, who, flags, description, mtime); + + /* TODO: sounds (depending on PurpleAttentionType), shaking, etc. */ + + g_free(description); +} + +void +purple_prpl_got_attention(PurpleConnection *gc, const char *who, guint type_code) +{ + got_attention(gc, -1, who, type_code); +} + +void +purple_prpl_got_attention_in_chat(PurpleConnection *gc, int id, const char *who, guint type_code) +{ + got_attention(gc, id, who, type_code); +} /************************************************************************** * Protocol Plugin Subsystem API
--- a/libpurple/prpl.h Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/prpl.h Mon Jul 28 06:18:51 2008 +0000 @@ -693,6 +693,41 @@ */ GList *purple_prpl_get_statuses(PurpleAccount *account, PurplePresence *presence); +/** Send an attention request message. + * + * @param gc The connection to send the message on. + * @param who Whose attention to request. + * @param type_code An index into the prpl's attention_types list determining the type + * of the attention request command to send. 0 if prpl only defines one + * (for example, Yahoo and MSN), but some protocols define more (MySpaceIM). + * + * Note that you can't send arbitrary PurpleAttentionType's, because there is + * only a fixed set of attention commands. + * @since 2.5.0 + */ +void purple_prpl_send_attention(PurpleConnection *gc, const char *who, guint type_code); + +/** Process an incoming attention message. + * + * @param gc The connection that received the attention message. + * @param who Who requested your attention. + * @param type_code An index into the prpl's attention_types list determining the type + * of the attention request command to send. + * @since 2.5.0 + */ +void purple_prpl_got_attention(PurpleConnection *gc, const char *who, guint type_code); + +/** Process an incoming attention message in a chat. + * + * @param gc The connection that received the attention message. + * @param id The chat id. + * @param who Who requested your attention. + * @param type_code An index into the prpl's attention_types list determining the type + * of the attention request command to send. + * @since 2.5.0 + */ +void purple_prpl_got_attention_in_chat(PurpleConnection *gc, int id, const char *who, guint type_code); + /*@}*/ /**************************************************************************/
--- a/libpurple/server.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/server.c Mon Jul 28 06:18:51 2008 +0000 @@ -335,91 +335,13 @@ void serv_send_attention(PurpleConnection *gc, const char *who, guint type_code) { - PurpleAttentionType *attn; - PurpleMessageFlags flags; - PurplePlugin *prpl; - PurpleConversation *conv; - gboolean (*send_attention)(PurpleConnection *, const char *, guint); - PurpleBuddy *buddy; - const char *alias; - gchar *description; - time_t mtime; - - g_return_if_fail(gc != NULL); - g_return_if_fail(who != NULL); - - prpl = purple_find_prpl(purple_account_get_protocol_id(gc->account)); - send_attention = PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->send_attention; - g_return_if_fail(send_attention != NULL); - - mtime = time(NULL); - - attn = purple_get_attention_type_from_code(gc->account, type_code); - - if ((buddy = purple_find_buddy(purple_connection_get_account(gc), who)) != NULL) - alias = purple_buddy_get_contact_alias(buddy); - else - alias = who; - - if (attn && purple_attention_type_get_outgoing_desc(attn)) { - description = g_strdup_printf(purple_attention_type_get_outgoing_desc(attn), alias); - } else { - description = g_strdup_printf(_("Requesting %s's attention..."), alias); - } - - flags = PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_NOTIFY | PURPLE_MESSAGE_SYSTEM; - - purple_debug_info("server", "serv_send_attention: sending '%s' to %s\n", - description, who); - - if (!send_attention(gc, who, type_code)) - return; - - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, gc->account, who); - purple_conv_im_write(PURPLE_CONV_IM(conv), NULL, description, flags, mtime); - - g_free(description); + purple_prpl_send_attention(gc, who, type_code); } void serv_got_attention(PurpleConnection *gc, const char *who, guint type_code) { - PurpleMessageFlags flags; - PurpleAttentionType *attn; - PurpleBuddy *buddy; - const char *alias; - gchar *description; - time_t mtime; - - mtime = time(NULL); - - attn = purple_get_attention_type_from_code(gc->account, type_code); - - /* PURPLE_MESSAGE_NOTIFY is for attention messages. */ - flags = PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NOTIFY | PURPLE_MESSAGE_RECV; - - /* TODO: if (attn->icon_name) is non-null, use it to lookup an emoticon and display - * it next to the attention command. And if it is null, display a generic icon. */ - - if ((buddy = purple_find_buddy(purple_connection_get_account(gc), who)) != NULL) - alias = purple_buddy_get_contact_alias(buddy); - else - alias = who; - - if (attn && purple_attention_type_get_incoming_desc(attn)) { - description = g_strdup_printf(purple_attention_type_get_incoming_desc(attn), alias); - } else { - description = g_strdup_printf(_("%s has requested your attention!"), alias); - } - - purple_debug_info("server", "serv_got_attention: got '%s' from %s\n", - description, who); - - serv_got_im(gc, who, description, flags, mtime); - - /* TODO: sounds (depending on PurpleAttentionType), shaking, etc. */ - - g_free(description); + purple_prpl_got_attention(gc, who, type_code); }
--- a/libpurple/server.h Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/server.h Mon Jul 28 06:18:51 2008 +0000 @@ -63,6 +63,8 @@ /** Send an attention request message. * + * @deprecated Use purple_prpl_send_attention() instead. + * * @param gc The connection to send the message on. * @param who Whose attention to request. * @param type_code An index into the prpl's attention_types list determining the type @@ -76,6 +78,8 @@ /** Process an incoming attention message. * + * @deprecated Use purple_prpl_got_attention() instead. + * * @param gc The connection that received the attention message. * @param who Who requested your attention. * @param type_code An index into the prpl's attention_types list determining the type
--- a/libpurple/win32/global.mak Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/win32/global.mak Mon Jul 28 06:18:51 2008 +0000 @@ -19,7 +19,7 @@ MEANWHILE_TOP ?= $(WIN32_DEV_TOP)/meanwhile-1.0.2_daa1 NSPR_TOP ?= $(WIN32_DEV_TOP)/nspr-4.6.4 NSS_TOP ?= $(WIN32_DEV_TOP)/nss-3.11.4 -PERL_LIB_TOP ?= $(WIN32_DEV_TOP)/perl58 +PERL_LIB_TOP ?= $(WIN32_DEV_TOP)/perl-5.10.0 SILC_TOOLKIT ?= $(WIN32_DEV_TOP)/silc-toolkit-1.1.5 TCL_LIB_TOP ?= $(WIN32_DEV_TOP)/tcl-8.4.5 GSTREAMER_TOP ?= $(WIN32_DEV_TOP)/gstreamer-0.10.13 @@ -56,7 +56,7 @@ PIDGIN_EXE := $(PIDGIN_TOP)/pidgin.exe PIDGIN_PORTABLE_EXE := $(PIDGIN_TOP)/pidgin-portable.exe -GCCWARNINGS := -Waggregate-return -Wcast-align -Wdeclaration-after-statement -Werror-implicit-function-declaration -Wextra -Wno-sign-compare -Wno-unused-parameter -Winit-self -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wundef +GCCWARNINGS ?= -Waggregate-return -Wcast-align -Wdeclaration-after-statement -Werror-implicit-function-declaration -Wextra -Wno-sign-compare -Wno-unused-parameter -Winit-self -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wundef # parse the version number from the configure.ac file if it is newer #m4_define([purple_major_version], [2])
--- a/libpurple/win32/libc_interface.c Fri Jul 18 08:45:31 2008 +0000 +++ b/libpurple/win32/libc_interface.c Mon Jul 28 06:18:51 2008 +0000 @@ -327,9 +327,12 @@ case WSAETIMEDOUT: /* 10060 */ g_snprintf(errbuf, sizeof(errbuf), _("Connection timed out.")); break; - case WSAECONNREFUSED: /*10061 */ + case WSAECONNREFUSED: /* 10061 */ g_snprintf(errbuf, sizeof(errbuf), _("Connection refused.")); break; + case WSAEADDRINUSE: /* 10048 */ + g_snprintf(errbuf, sizeof(errbuf), _("Address already in use.")); + break; default: g_snprintf(errbuf, sizeof(errbuf), "Windows socket error #%d", errornum); }
--- a/pidgin/pidgintooltip.c Fri Jul 18 08:45:31 2008 +0000 +++ b/pidgin/pidgintooltip.c Mon Jul 28 06:18:51 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); }
--- a/pidgin/plugins/perl/common/Makefile.mingw Fri Jul 18 08:45:31 2008 +0000 +++ b/pidgin/plugins/perl/common/Makefile.mingw Mon Jul 28 06:18:51 2008 +0000 @@ -5,13 +5,12 @@ # PIDGIN_TREE_TOP := ../../../.. +GCCWARNINGS := -Wno-comment -Waggregate-return -Wcast-align -Wdeclaration-after-statement -Werror-implicit-function-declaration -Wextra -Wno-sign-compare -Wno-unused-parameter -Winit-self -Wmissing-declarations -Wmissing-prototypes -Wpointer-arith -Wundef -Wno-unused include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak TARGET = Pidgin EXTUTILS ?= C:/perl/lib/ExtUtils -CFLAGS += -Wno-comment -Wno-unused - ## ## INCLUDE PATHS ## @@ -72,7 +71,7 @@ ## ## LIBRARIES ## -LIBS = -lperl58 \ +LIBS = -lperl510 \ -lperl \ -lpurple \ -lpidgin \
--- a/pidgin/win32/nsis/pidgin-installer.nsi Fri Jul 18 08:45:31 2008 +0000 +++ b/pidgin/win32/nsis/pidgin-installer.nsi Mon Jul 28 06:18:51 2008 +0000 @@ -72,7 +72,7 @@ !define GTK_MIN_VERSION "2.6.10" !define GTK_REG_KEY "SOFTWARE\GTK\2.0" !define PERL_REG_KEY "SOFTWARE\Perl" -!define PERL_DLL "perl58.dll" +!define PERL_DLL "perl510.dll" !define GTK_DEFAULT_INSTALL_PATH "$COMMONFILES\GTK\2.0" !define GTK_RUNTIME_INSTALLER "..\..\..\..\gtk_installer\gtk-runtime*.exe" @@ -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"
--- a/pidgin/win32/winpidgin.c Fri Jul 18 08:45:31 2008 +0000 +++ b/pidgin/win32/winpidgin.c Mon Jul 28 06:18:51 2008 +0000 @@ -89,9 +89,8 @@ const char *err_msg = get_win32_error_message(retv); printf("Could not read reg key '%s' subkey '%s' value: '%s'.\nMessage: (%ld) %s\n", - ((key == HKEY_LOCAL_MACHINE) ? "HKLM" : - (key == HKEY_CURRENT_USER) ? "HKCU" : - "???"), + (key == HKEY_LOCAL_MACHINE) ? "HKLM" + : ((key == HKEY_CURRENT_USER) ? "HKCU" : "???"), sub_key, val_name, retv, err_msg); } RegCloseKey(hkey); @@ -216,13 +215,13 @@ /* Set up the settings dir base to be \\path\to * The actual settings dir will be \\path\to\.purple */ - snprintf(path2, sizeof(path2), "PURPLEHOME=%s", path); + _snprintf(path2, sizeof(path2), "PURPLEHOME=%s", path); printf("Setting settings dir: %s\n", path2); - putenv(path2); + _putenv(path2); - snprintf(path2, sizeof(path2), "PIDGIN_ASPELL_DIR=%s\\Aspell\\bin", path); + _snprintf(path2, sizeof(path2), "PIDGIN_ASPELL_DIR=%s\\Aspell\\bin", path); printf("%s\n", path2); - putenv(path2); + _putenv(path2); /* set the GTK+ path to be \\path\to\GTK\bin */ strcat(path, "\\GTK\\bin"); @@ -437,9 +436,50 @@ locale = winpidgin_get_locale(); - snprintf(envstr, 25, "LANG=%s", locale); + _snprintf(envstr, 25, "LANG=%s", locale); printf("Setting locale: %s\n", envstr); - putenv(envstr); + _putenv(envstr); +} + +static void winpidgin_add_perl_to_path() { + char perl_path[MAX_PATH + 1]; + DWORD plen = sizeof(perl_path); + + printf("%s", "Looking for Perl... "); + + if (read_reg_string(HKEY_LOCAL_MACHINE, "SOFTWARE\\Perl", "", + (LPBYTE) &perl_path, &plen)) { + const char *path = getenv("PATH"); + /* Enough to add "PATH=" + ";" + perl_path + "\\bin" + \0 */ + + /* We *could* check for perl510.dll, but it seems unnecessary. */ + + printf("found in '%s'.\n", perl_path); + + if (perl_path[strlen(perl_path) - 1] != '\\') { + strcat(perl_path, "\\"); + } + strcat(perl_path, "bin"); + + if (!strstr(path, perl_path)) { + int newlen = (path ? strlen(path) : 0) + strlen(perl_path) + 10; + char *newpath = malloc(newlen); + *newpath = '\0'; + + _snprintf(newpath, newlen, "PATH=%s%s%s", + path ? path : "", + path ? ";" : "", + perl_path); + + printf("Adding Perl to PATH: %s\n", newpath); + + _putenv(newpath); + free(newpath); + } else + printf("%s\n", "Perl already in PATH."); + } else + printf("%s", "not found.\n"); + } #define PIDGIN_WM_FOCUS_REQUEST (WM_APP + 13) @@ -598,10 +638,10 @@ } else { DWORD dw = GetLastError(); const char *err_msg = get_win32_error_message(dw); - snprintf(errbuf, 512, + _snprintf(errbuf, 512, "Error getting module filename.\nError: (%u) %s", (UINT) dw, err_msg); - printf("%s", errbuf); + printf("%s\n", errbuf); MessageBox(NULL, errbuf, NULL, MB_OK | MB_TOPMOST); pidgin_dir[0] = '\0'; } @@ -631,6 +671,9 @@ dll_prep(); winpidgin_set_locale(); + + winpidgin_add_perl_to_path(); + /* If help, version or multiple flag used, do not check Mutex */ if (!strstr(lpszCmdLine, "-h") && !strstr(lpszCmdLine, "-v")) if (!winpidgin_set_running(getenv("PIDGIN_MULTI_INST") == NULL && strstr(lpszCmdLine, "-m") == NULL)) @@ -645,11 +688,11 @@ BOOL mod_not_found = (dw == ERROR_MOD_NOT_FOUND || dw == ERROR_DLL_NOT_FOUND); const char *err_msg = get_win32_error_message(dw); - snprintf(errbuf, 512, "Error loading pidgin.dll.\nError: (%u) %s%s%s", + _snprintf(errbuf, 512, "Error loading pidgin.dll.\nError: (%u) %s%s%s", (UINT) dw, err_msg, mod_not_found ? "\n" : "", mod_not_found ? "This probably means that GTK+ can't be found." : ""); - printf("%s", errbuf); + printf("%s\n", errbuf); MessageBox(NULL, errbuf, TEXT("Error"), MB_OK | MB_TOPMOST); return 0;