# HG changeset patch # User Richard Laager # Date 1188781748 0 # Node ID f96cceb75fbb14e327b80b25e79df1c9d3c39392 # Parent 0eff4257d55b602d5d4206fef6d1e5918cd72685# Parent 6e08084a27aaf78a46eb03b18b1aab17f33ff82f merge of '3f25aaeb59668d0654c46b32af65735a2aa35fb9' and '97d7ebae82d528f45307b69c9b2510dfb2542c92' diff -r 0eff4257d55b -r f96cceb75fbb COPYRIGHT --- a/COPYRIGHT Mon Sep 03 01:07:47 2007 +0000 +++ b/COPYRIGHT Mon Sep 03 01:09:08 2007 +0000 @@ -348,6 +348,7 @@ Sony Computer Entertainment America, Inc. Andy Spencer Mark Spencer +Peter Speybrouck Lex Spoon Chris Stafford Kevin Stange diff -r 0eff4257d55b -r f96cceb75fbb ChangeLog.API --- a/ChangeLog.API Mon Sep 03 01:07:47 2007 +0000 +++ b/ChangeLog.API Mon Sep 03 01:09:08 2007 +0000 @@ -6,6 +6,9 @@ * PURPLE_MESSAGE_INVISIBLE flag, which can be used by purple_conv_im_send_with_flags to send a message, but not display it in the conversation + * serv_send_attention(), serv_got_attention(), as well as send_attention + and attention_types in PurplePluginProtocolInfo. This new API is used + for zapping in MySpaceIM, buzzing in Yahoo, and nudging in MSN. Changed: * purple_prefs_load is now called within purple_prefs_init. The UI no longer needs to call it. @@ -14,6 +17,9 @@ Added: * pidgin_set_accessible_relations, sets up label-for and labelled-by ATK relations (broken out from pidgin_set_accessible_label) + * pidgin_conv_attach_to_conversation, to reattach the Pidgin UI to a + conversation + * conversation-hiding and conversation-displayed signals. Finch: Added: diff -r 0eff4257d55b -r f96cceb75fbb ChangeLog.win32 --- a/ChangeLog.win32 Mon Sep 03 01:07:47 2007 +0000 +++ b/ChangeLog.win32 Mon Sep 03 01:09:08 2007 +0000 @@ -1,4 +1,5 @@ version 2.2.0 (??/??/2007): + * Updated gtkspell to 2.0.11 * Upgrade SILC to use the 1.1.2 toolkit version 2.1.1 (08/20/2007): diff -r 0eff4257d55b -r f96cceb75fbb doc/gtkconv-signals.dox --- a/doc/gtkconv-signals.dox Mon Sep 03 01:07:47 2007 +0000 +++ b/doc/gtkconv-signals.dox Mon Sep 03 01:09:08 2007 +0000 @@ -8,6 +8,8 @@ @signal displaying-chat-msg @signal displayed-chat-msg @signal conversation-switched + @signal conversation-hiding + @signal conversation-displayed @endsignals
@@ -116,5 +118,23 @@ @param new_conv The now active conversation. @endsignaldef + @signaldef conversation-hiding + @signalproto +void (*conversation_hiding)(PidginConversation *gtkconv); + @endsignalproto + @signaldesc + Emitted immediately before an existing conversation is hidden. + @param gtkconv The PidginConversation + @endsignaldef + + @signaldef conversation-displayed + @signalproto +void (*conversation_displayed)(PidginConversation *gtkconv); + @endsignalproto + @signaldesc + Emitted right after the Pidgin UI is reattached to a conversation. + @param gtkconv The PidginConversation + @endsignaldef + */ // vim: syntax=c tw=75 et diff -r 0eff4257d55b -r f96cceb75fbb finch/plugins/gntclipboard.c --- a/finch/plugins/gntclipboard.c Mon Sep 03 01:07:47 2007 +0000 +++ b/finch/plugins/gntclipboard.c Mon Sep 03 01:09:08 2007 +0000 @@ -38,10 +38,12 @@ #include #include #include +#include #include #include +#ifdef HAVE_X11 static pid_t child = 0; static gulong sig_handle; @@ -49,7 +51,6 @@ static void set_clip(gchar *string) { -#ifdef HAVE_X11 Window w; XEvent e, respond; XSelectionRequestEvent *req; @@ -89,14 +90,12 @@ return; } } -#endif return; } static void clipboard_changed(GntWM *wm, gchar *string) { -#ifdef HAVE_X11 if (child) { kill(child, SIGTERM); } @@ -104,8 +103,8 @@ set_clip(string); _exit(0); } +} #endif -} static gboolean plugin_load(PurplePlugin *plugin) @@ -113,25 +112,35 @@ #ifdef HAVE_X11 if (!XOpenDisplay(NULL)) { purple_debug_warning("gntclipboard", "Couldn't find X display\n"); + purple_notify_error(NULL, _("Error"), _("Error loading the plugin."), + _("Couldn't find X display")); return FALSE; } -#endif if (!getenv("WINDOWID")) { purple_debug_warning("gntclipboard", "Couldn't find window\n"); + purple_notify_error(NULL, _("Error"), _("Error loading the plugin."), + _("Couldn't find window")); return FALSE; } sig_handle = g_signal_connect(G_OBJECT(gnt_get_clipboard()), "clipboard_changed", G_CALLBACK(clipboard_changed), NULL); return TRUE; +#else + purple_notify_error(NULL, _("Error"), _("Error loading the plugin."), + _("This plugin cannot be loaded because it was not built with X11 support.")); + return FALSE; +#endif } static gboolean plugin_unload(PurplePlugin *plugin) { +#ifdef HAVE_X11 if (child) { kill(child, SIGTERM); child = 0; } g_signal_handler_disconnect(G_OBJECT(gnt_get_clipboard()), sig_handle); +#endif return TRUE; } diff -r 0eff4257d55b -r f96cceb75fbb libpurple/certificate.c --- a/libpurple/certificate.c Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/certificate.c Mon Sep 03 01:09:08 2007 +0000 @@ -1083,11 +1083,14 @@ x509_tls_cached_show_cert(x509_tls_cached_ua_ctx *c, gint id) { PurpleCertificate *disp_crt = c->vrq->cert_chain->data; - purple_certificate_display_x509(disp_crt); /* Since clicking a button closes the request, show it again */ x509_tls_cached_user_auth(c->vrq, c->reason); + /* Show the certificate AFTER re-opening the dialog so that this + appears above the other */ + purple_certificate_display_x509(disp_crt); + x509_tls_cached_ua_ctx_free(c); } @@ -1205,7 +1208,14 @@ /* Load up the cached certificate */ cached_crt = purple_certificate_pool_retrieve( tls_peers, vrq->subject_name); - g_assert(cached_crt); + if ( !cached_crt ) { + purple_debug_error("certificate/x509/tls_cached", + "Lookup failed on cached certificate!\n" + "It was here just a second ago. Forwarding " + "to cert_changed.\n"); + /* vrq now becomes the problem of cert_changed */ + x509_tls_cached_peer_cert_changed(vrq); + } /* Now get SHA1 sums for both and compare them */ /* TODO: This is not an elegant way to compare certs */ @@ -1338,7 +1348,14 @@ ca_crt = purple_certificate_pool_retrieve(ca, ca_id); g_free(ca_id); - g_assert(ca_crt); + if (!ca_crt) { + purple_debug_error("certificate/x509/tls_cached", + "Certificate authority disappeared out " + "underneath me!\n"); + purple_certificate_verify_complete(vrq, + PURPLE_CERTIFICATE_INVALID); + return; + } /* Check the signature */ if ( !purple_certificate_signed_by(end_crt, ca_crt) ) { @@ -1375,9 +1392,11 @@ "tls_peers"); if (tls_peers) { - g_assert(purple_certificate_pool_store(tls_peers, - vrq->subject_name, - peer_crt) ); + if (!purple_certificate_pool_store(tls_peers,vrq->subject_name, + peer_crt) ) { + purple_debug_error("certificate/x509/tls_cached", + "FAILED to cache peer certificate\n"); + } } else { purple_debug_error("certificate/x509/tls_cached", "Unable to locate tls_peers certificate " @@ -1790,7 +1809,6 @@ GByteArray *sha_bin; gchar *cn; time_t activation, expiration; - /* Length of these buffers is dictated by 'man ctime_r' */ gchar *activ_str, *expir_str; gchar *secondary; @@ -1807,7 +1825,11 @@ /* Get the certificate times */ /* TODO: Check the times against localtime */ /* TODO: errorcheck? */ - g_assert(purple_certificate_get_times(crt, &activation, &expiration)); + if (!purple_certificate_get_times(crt, &activation, &expiration)) { + purple_debug_error("certificate", + "Failed to get certificate times!\n"); + activation = expiration = 0; + } activ_str = g_strdup(ctime(&activation)); expir_str = g_strdup(ctime(&expiration)); diff -r 0eff4257d55b -r f96cceb75fbb libpurple/example/nullclient.c --- a/libpurple/example/nullclient.c Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/example/nullclient.c Mon Sep 03 01:09:08 2007 +0000 @@ -197,7 +197,7 @@ purple_util_set_user_dir(CUSTOM_USER_DIRECTORY); /* We do not want any debugging for now to keep the noise to a minimum. */ - purple_debug_set_enabled(TRUE); + purple_debug_set_enabled(FALSE); /* Set the core-uiops, which is used to * - initialize the ui specific preferences. @@ -257,24 +257,6 @@ PURPLE_CALLBACK(signed_on), NULL); } - - - -void signedOn( PurpleConnection *gc, gpointer dummy ) { - - - if( gc ) { - - PurpleAccount* a = purple_connection_get_account( gc ); - - if( a ) { - - purple_presence_set_idle( purple_account_get_presence( a ), TRUE, time( NULL ) ); - } - } -} - - int main() { GList *iter; @@ -300,26 +282,30 @@ names = g_list_append(names, info->id); } } + printf("Select the protocol [0-%d]: ", i-1); + fgets(name, sizeof(name), stdin); + sscanf(name, "%d", &num); + prpl = g_list_nth_data(names, num); + + printf("Username: "); + fgets(name, sizeof(name), stdin); + name[strlen(name) - 1] = 0; /* strip the \n at the end */ /* Create the account */ - account = purple_account_new("msimprpl@xyzzy.cjb.net", "prpl-myspace" ); - purple_account_set_password(account, "4224jc" ); + account = purple_account_new(name, prpl); + + /* Get the password for the account */ + password = getpass("Password: "); + purple_account_set_password(account, password); /* It's necessary to enable the account first. */ purple_account_set_enabled(account, UI_ID, TRUE); -#if 0 - static int handle; - purple_signal_connect( purple_connections_get_handle(), - "signed-on", &handle, - PURPLE_CALLBACK( signedOn ), - NULL ); - /* Now, to connect the account(s), create a status and activate it. */ - purple_savedstatus_activate( purple_savedstatus_get_default() ); + status = purple_savedstatus_new(NULL, PURPLE_STATUS_AVAILABLE); + purple_savedstatus_activate(status); connect_to_signals_for_demonstration_purposes_only(); -#endif g_main_loop_run(loop); diff -r 0eff4257d55b -r f96cceb75fbb libpurple/internal.h --- a/libpurple/internal.h Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/internal.h Mon Sep 03 01:09:08 2007 +0000 @@ -29,6 +29,10 @@ # include #endif +/* for SIOCGIFCONF in SKYOS */ +#ifdef SKYOS +#include +#endif /* * If we're using NLS, make sure gettext works. If not, then define * dummy macros in place of the normal gettext macros. diff -r 0eff4257d55b -r f96cceb75fbb libpurple/plugins/ssl/ssl-gnutls.c --- a/libpurple/plugins/ssl/ssl-gnutls.c Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/plugins/ssl/ssl-gnutls.c Mon Sep 03 01:09:08 2007 +0000 @@ -60,7 +60,7 @@ (gnutls_realloc_function) g_realloc, /* realloc */ (gnutls_free_function) g_free /* free */ ); - + gnutls_global_init(); gnutls_certificate_allocate_credentials(&xcred); @@ -73,7 +73,7 @@ static gboolean ssl_gnutls_init(void) { - return TRUE; + return TRUE; } static void @@ -130,17 +130,18 @@ purple_ssl_close(gsc); } else { - purple_debug_info("gnutls", "Handshake complete\n"); - - /* TODO: Remove all this debugging babble */ /* Now we are cooking with gas! */ PurpleSslOps *ops = purple_ssl_get_ops(); GList * peers = ops->get_peer_certificates(gsc); - + PurpleCertificateScheme *x509 = purple_certificate_find_scheme("x509"); GList * l; + + /* TODO: Remove all this debugging babble */ + purple_debug_info("gnutls", "Handshake complete\n"); + for (l=peers; l; l = l->next) { PurpleCertificate *crt = l->data; GByteArray *z = @@ -155,71 +156,71 @@ /* Kill the cert! */ x509->destroy_certificate(crt); - + g_free(fpr); g_byte_array_free(z, TRUE); } g_list_free(peers); - + { - const gnutls_datum_t *cert_list; - unsigned int cert_list_size = 0; - gnutls_session_t session=gnutls_data->session; - - cert_list = - gnutls_certificate_get_peers(session, &cert_list_size); - - purple_debug_info("gnutls", - "Peer provided %d certs\n", - cert_list_size); - int i; - for (i=0; isession; + int i; + + cert_list = + gnutls_certificate_get_peers(session, &cert_list_size); + + purple_debug_info("gnutls", + "Peer provided %d certs\n", + cert_list_size); + for (i=0; isession) == GNUTLS_CRT_X509, NULL); @@ -425,12 +426,14 @@ static void x509_crtdata_delref(x509_crtdata_t *cd) { - g_assert(cd->refcount > 0); - (cd->refcount)--; + if (cd->refcount < 0) + g_critical("Refcount of x509_crtdata_t is %d, which is less " + "than zero!\n", cd->refcount); + /* If the refcount reaches zero, kill the structure */ - if (cd->refcount == 0) { + if (cd->refcount <= 0) { purple_debug_info("gnutls/x509", "Freeing unused cert data at %p\n", cd); @@ -465,11 +468,11 @@ certdat = g_new0(x509_crtdata_t, 1); gnutls_x509_crt_init(&(certdat->crt)); certdat->refcount = 0; - + /* Perform the actual certificate parse */ /* Yes, certdat->crt should be passed as-is */ gnutls_x509_crt_import(certdat->crt, &dt, mode); - + /* Allocate the certificate and load it with data */ crt = g_new0(PurpleCertificate, 1); crt->scheme = &x509_gnutls; @@ -494,7 +497,7 @@ purple_debug_info("gnutls", "Attempting to load X.509 certificate from %s\n", filename); - + /* Next, we'll simply yank the entire contents of the file into memory */ /* TODO: Should I worry about very large files here? */ @@ -505,7 +508,7 @@ NULL /* No error checking for now */ ), NULL); - + /* Load the datum struct */ dt.data = (unsigned char *) buf; dt.size = buf_sz; @@ -513,7 +516,7 @@ /* Perform the conversion */ crt = x509_import_from_datum(dt, GNUTLS_X509_FMT_PEM); // files should be in PEM format - + /* Cleanup */ g_free(buf); @@ -570,7 +573,6 @@ success = purple_util_write_data_to_file_absolute(filename, out_buf, out_size); - g_free(out_buf); g_return_val_if_fail(success, FALSE); return success; @@ -595,10 +597,10 @@ } /** Frees a Certificate * - * Destroys a Certificate's internal data structures and frees the pointer - * given. - * @param crt Certificate instance to be destroyed. It WILL NOT be destroyed - * if it is not of the correct CertificateScheme. Can be NULL + * Destroys a Certificate's internal data structures and frees the pointer + * given. + * @param crt Certificate instance to be destroyed. It WILL NOT be destroyed + * if it is not of the correct CertificateScheme. Can be NULL * */ static void @@ -621,7 +623,7 @@ /* Use the reference counting system to free (or not) the underlying data */ x509_crtdata_delref((x509_crtdata_t *)crt->data); - + /* Kill the structure itself */ g_free(crt); } @@ -642,7 +644,7 @@ gnutls_x509_crt_t issuer_dat; unsigned int verify; /* used to store result from GnuTLS verifier */ int ret; - + g_return_val_if_fail(crt, FALSE); g_return_val_if_fail(issuer, FALSE); @@ -684,7 +686,7 @@ /* The issuer is not correct, or there were errors */ return FALSE; } - + /* Now, check the signature */ /* The second argument is a ptr to an array of "trusted" issuer certs, but we're only using one trusted one */ @@ -695,7 +697,7 @@ current standard) */ GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT, &verify); - + if (ret != 0) { purple_debug_error("gnutls/x509", "Attempted certificate verification caused a GnuTLS error code %d. I will just say the signature is bad, but you should look into this.\n", ret); @@ -712,7 +714,7 @@ issuer_id, crt_id); g_free(crt_id); g_free(issuer_id); - + return FALSE; } /* if (ret, etc.) */ @@ -741,7 +743,7 @@ /* This shouldn't happen */ g_return_val_if_fail(tmpsz == hashlen, NULL); - + /* Okay, now create and fill hash array */ hash = g_byte_array_new(); g_byte_array_append(hash, hashbuf, hashlen); @@ -775,7 +777,7 @@ g_free(dn); return NULL; } - + return dn; } @@ -806,7 +808,7 @@ g_free(dn); return NULL; } - + return dn; } @@ -847,7 +849,6 @@ return NULL; } - return cn; } @@ -892,7 +893,7 @@ if (*activation == errval || *expiration == errval) { return FALSE; } - + return TRUE; } diff -r 0eff4257d55b -r f96cceb75fbb libpurple/plugins/tcl/tcl_cmds.c --- a/libpurple/plugins/tcl/tcl_cmds.c Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/plugins/tcl/tcl_cmds.c Mon Sep 03 01:09:08 2007 +0000 @@ -544,12 +544,16 @@ int tcl_cmd_cmd(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - const char *cmds[] = { "register", "unregister", NULL }; - enum { CMD_CMD_REGISTER, CMD_CMD_UNREGISTER } cmd; + const char *cmds[] = { "do", "help", "list", "register", "unregister", NULL }; + enum { CMD_CMD_DO, CMD_CMD_HELP, CMD_CMD_LIST, CMD_CMD_REGISTER, CMD_CMD_UNREGISTER } cmd; struct tcl_cmd_handler *handler; - Tcl_Obj *result = Tcl_GetObjResult(interp); + Tcl_Obj *list, *elem, *result = Tcl_GetObjResult(interp); + PurpleConversation *convo; PurpleCmdId id; + PurpleCmdStatus status; int error; + GList *l, *cur; + gchar *escaped, *errstr = NULL; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?"); @@ -560,6 +564,57 @@ return error; switch (cmd) { + case CMD_CMD_DO: + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "conversation command"); + return TCL_ERROR; + } + if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL) + return TCL_ERROR; + escaped = g_markup_escape_text(Tcl_GetString(objv[3]), -1); + status = purple_cmd_do_command(convo, Tcl_GetString(objv[3]), + escaped, &errstr); + g_free(escaped); + Tcl_SetStringObj(result, errstr ? (char *)errstr : "", -1); + g_free(errstr); + if (status != PURPLE_CMD_STATUS_OK) { + return TCL_ERROR; + } + break; + case CMD_CMD_HELP: + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "conversation name"); + return TCL_ERROR; + } + if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL) + return TCL_ERROR; + l = cur = purple_cmd_help(convo, Tcl_GetString(objv[3])); + list = Tcl_NewListObj(0, NULL); + while (cur != NULL) { + elem = Tcl_NewStringObj((char *)cur->data, -1); + Tcl_ListObjAppendElement(interp, list, elem); + cur = g_list_next(cur); + } + g_list_free(l); + Tcl_SetObjResult(interp, list); + break; + case CMD_CMD_LIST: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "conversation"); + return TCL_ERROR; + } + if ((convo = tcl_validate_conversation(objv[2], interp)) == NULL) + return TCL_ERROR; + l = cur = purple_cmd_list(convo); + list = Tcl_NewListObj(0, NULL); + while (cur != NULL) { + elem = Tcl_NewStringObj((char *)cur->data, -1); + Tcl_ListObjAppendElement(interp, list, elem); + cur = g_list_next(cur); + } + g_list_free(l); + Tcl_SetObjResult(interp, list); + break; case CMD_CMD_REGISTER: if (objc != 9) { Tcl_WrongNumArgs(interp, 2, objv, "cmd arglist priority flags prpl_id proc helpstr"); diff -r 0eff4257d55b -r f96cceb75fbb libpurple/protocols/bonjour/bonjour.c --- a/libpurple/protocols/bonjour/bonjour.c Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/protocols/bonjour/bonjour.c Mon Sep 03 01:09:08 2007 +0000 @@ -235,6 +235,13 @@ g_free(stripped); } +static void bonjour_remove_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group) { + if (buddy->proto_data) { + bonjour_buddy_delete(buddy->proto_data); + buddy->proto_data = NULL; + } +} + static GList * bonjour_status_types(PurpleAccount *account) { @@ -395,7 +402,7 @@ NULL, /* change_passwd */ NULL, /* add_buddy */ NULL, /* add_buddies */ - NULL, /* remove_buddy */ + bonjour_remove_buddy, /* remove_buddy */ NULL, /* remove_buddies */ NULL, /* add_permit */ NULL, /* add_deny */ diff -r 0eff4257d55b -r f96cceb75fbb libpurple/protocols/bonjour/buddy.c --- a/libpurple/protocols/bonjour/buddy.c Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/protocols/bonjour/buddy.c Mon Sep 03 01:09:08 2007 +0000 @@ -121,9 +121,8 @@ * the buddy. */ void -bonjour_buddy_add_to_purple(BonjourBuddy *bonjour_buddy) +bonjour_buddy_add_to_purple(BonjourBuddy *bonjour_buddy, PurpleBuddy *buddy) { - PurpleBuddy *buddy; PurpleGroup *group; PurpleAccount *account = bonjour_buddy->account; const char *status_id, *old_hash, *new_hash; @@ -147,7 +146,8 @@ } /* Make sure the buddy exists in our buddy list */ - buddy = purple_find_buddy(account, bonjour_buddy->name); + if (buddy == NULL) + buddy = purple_find_buddy(account, bonjour_buddy->name); if (buddy == NULL) { buddy = purple_buddy_new(account, bonjour_buddy->name, NULL); diff -r 0eff4257d55b -r f96cceb75fbb libpurple/protocols/bonjour/buddy.h --- a/libpurple/protocols/bonjour/buddy.h Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/protocols/bonjour/buddy.h Mon Sep 03 01:09:08 2007 +0000 @@ -92,8 +92,9 @@ /** * If the buddy doesn't previoulsy exists, it is created. Else, its data is changed (???) + * purple_buddy is optional; it saves an additional lookup if we already have it */ -void bonjour_buddy_add_to_purple(BonjourBuddy *buddy); +void bonjour_buddy_add_to_purple(BonjourBuddy *bonjour_buddy, PurpleBuddy *purple_buddy); /** * We got the buddy icon data; deal with it diff -r 0eff4257d55b -r f96cceb75fbb libpurple/protocols/bonjour/issues.txt --- a/libpurple/protocols/bonjour/issues.txt Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/protocols/bonjour/issues.txt Mon Sep 03 01:09:08 2007 +0000 @@ -2,6 +2,5 @@ ============= Known issues =============== ========================================== -* Status changes don't work * File transfers * Typing notifications diff -r 0eff4257d55b -r f96cceb75fbb libpurple/protocols/bonjour/jabber.c --- a/libpurple/protocols/bonjour/jabber.c Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/protocols/bonjour/jabber.c Mon Sep 03 01:09:08 2007 +0000 @@ -373,17 +373,19 @@ g_return_if_fail(bb != NULL); - /* Close the socket, clear the watcher and free memory */ - bonjour_jabber_close_conversation(bb->conversation); - bb->conversation = NULL; + /* Inform the user that the conversation has been closed */ + if (bb->conversation != NULL) { + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, pb->name, pb->account); + if (conv != NULL) { + char *tmp = g_strdup_printf(_("%s has closed the conversation."), pb->name); + purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); + g_free(tmp); + } + /* Close the socket, clear the watcher and free memory */ + bonjour_jabber_close_conversation(bb->conversation); + bb->conversation = NULL; + } - /* Inform the user that the conversation has been closed */ - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, pb->name, pb->account); - if (conv != NULL) { - char *tmp = g_strdup_printf(_("%s has closed the conversation."), pb->name); - purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); - g_free(tmp); - } } void bonjour_jabber_stream_started(PurpleBuddy *pb) { diff -r 0eff4257d55b -r f96cceb75fbb libpurple/protocols/bonjour/mdns_avahi.c --- a/libpurple/protocols/bonjour/mdns_avahi.c Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_avahi.c Mon Sep 03 01:09:08 2007 +0000 @@ -33,7 +33,7 @@ #include #include -/* For some reason, this is missing from the Avahi type defines */ +/* Avahi only defines the types that it actually uses (which at this time doesn't include NULL) */ #ifndef AVAHI_DNS_TYPE_NULL #define AVAHI_DNS_TYPE_NULL 0x0A #endif @@ -58,7 +58,8 @@ const char *host_name, const AvahiAddress *a, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void *userdata) { - BonjourBuddy *buddy; + PurpleBuddy *pb; + BonjourBuddy *bb; PurpleAccount *account = userdata; AvahiStringList *l; size_t size; @@ -67,44 +68,62 @@ g_return_if_fail(r != NULL); + pb = purple_find_buddy(account, name); + bb = (pb != NULL) ? pb->proto_data : NULL; + switch (event) { case AVAHI_RESOLVER_FAILURE: purple_debug_error("bonjour", "_resolve_callback - Failure: %s\n", avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r)))); + avahi_service_resolver_free(r); + if (bb != NULL) { + /* We've already freed the resolver */ + if (r == ((AvahiBuddyImplData *)bb->mdns_impl_data)->resolver) + ((AvahiBuddyImplData *)bb->mdns_impl_data)->resolver = NULL; + purple_blist_remove_buddy(pb); + } break; case AVAHI_RESOLVER_FOUND: /* create a buddy record */ - buddy = bonjour_buddy_new(name, account); + if (bb == NULL) + bb = bonjour_buddy_new(name, account); - ((AvahiBuddyImplData *)buddy->mdns_impl_data)->resolver = r; + /* If we're reusing an existing buddy, make sure if it is a different resolver to clean up the old one. + * I don't think this should ever happen, but I'm afraid we might get events out of sequence. */ + if (((AvahiBuddyImplData *)bb->mdns_impl_data)->resolver != NULL + && ((AvahiBuddyImplData *)bb->mdns_impl_data)->resolver != r) { + avahi_service_resolver_free(((AvahiBuddyImplData *)bb->mdns_impl_data)->resolver); + } + ((AvahiBuddyImplData *)bb->mdns_impl_data)->resolver = r; + g_free(bb->ip); /* Get the ip as a string */ - buddy->ip = g_malloc(AVAHI_ADDRESS_STR_MAX); - avahi_address_snprint(buddy->ip, AVAHI_ADDRESS_STR_MAX, a); + bb->ip = g_malloc(AVAHI_ADDRESS_STR_MAX); + avahi_address_snprint(bb->ip, AVAHI_ADDRESS_STR_MAX, a); - buddy->port_p2pj = port; + bb->port_p2pj = port; /* Obtain the parameters from the text_record */ - clear_bonjour_buddy_values(buddy); - l = txt; - while (l != NULL) { - ret = avahi_string_list_get_pair(l, &key, &value, &size); - l = l->next; - if (ret < 0) + clear_bonjour_buddy_values(bb); + for(l = txt; l != NULL; l = l->next) { + if ((ret = avahi_string_list_get_pair(l, &key, &value, &size)) < 0) continue; - set_bonjour_buddy_value(buddy, key, value, size); + set_bonjour_buddy_value(bb, key, value, size); /* TODO: Since we're using the glib allocator, I think we * can use the values instead of re-copying them */ avahi_free(key); avahi_free(value); } - if (!bonjour_buddy_check(buddy)) - bonjour_buddy_delete(buddy); - else + if (!bonjour_buddy_check(bb)) { + if (pb != NULL) + purple_blist_remove_buddy(pb); + else + bonjour_buddy_delete(bb); + } else /* Add or update the buddy in our buddy list */ - bonjour_buddy_add_to_purple(buddy); + bonjour_buddy_add_to_purple(bb, pb); break; default: @@ -120,7 +139,7 @@ AvahiLookupResultFlags flags, void *userdata) { PurpleAccount *account = userdata; - PurpleBuddy *gb = NULL; + PurpleBuddy *pb = NULL; switch (event) { case AVAHI_BROWSER_FAILURE: @@ -132,7 +151,7 @@ /* A new peer has joined the network and uses iChat bonjour */ purple_debug_info("bonjour", "_browser_callback - new service\n"); /* Make sure it isn't us */ - if (g_ascii_strcasecmp(name, account->username) != 0) { + if (purple_utf8_strcasecmp(name, account->username) != 0) { if (!avahi_service_resolver_new(avahi_service_browser_get_client(b), interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, _resolver_callback, account)) { @@ -143,16 +162,12 @@ break; case AVAHI_BROWSER_REMOVE: purple_debug_info("bonjour", "_browser_callback - Remove service\n"); - gb = purple_find_buddy(account, name); - if (gb != NULL) { - bonjour_buddy_delete(gb->proto_data); - purple_blist_remove_buddy(gb); - } + pb = purple_find_buddy(account, name); + if (pb != NULL) + purple_blist_remove_buddy(pb); break; case AVAHI_BROWSER_ALL_FOR_NOW: case AVAHI_BROWSER_CACHE_EXHAUSTED: - purple_debug_warning("bonjour", "(Browser) %s\n", - event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW"); break; default: purple_debug_info("bonjour", "Unrecognized Service browser event: %d.\n", event); diff -r 0eff4257d55b -r f96cceb75fbb libpurple/protocols/bonjour/mdns_howl.c --- a/libpurple/protocols/bonjour/mdns_howl.c Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_howl.c Mon Sep 03 01:09:08 2007 +0000 @@ -71,6 +71,7 @@ char value[SW_TEXT_RECORD_MAX_LEN]; sw_uint32 value_length; + /* TODO: We want to keep listening for updates*/ sw_discovery_cancel(discovery, oid); /* create a buddy record */ @@ -100,7 +101,7 @@ } /* Add or update the buddy in our buddy list */ - bonjour_buddy_add_to_purple(buddy); + bonjour_buddy_add_to_purple(buddy, NULL); return SW_OKAY; } @@ -149,10 +150,7 @@ purple_debug_info("bonjour", "_browser_reply --> Remove service\n"); gb = purple_find_buddy(account, name); if (gb != NULL) - { - bonjour_buddy_delete(gb->proto_data); purple_blist_remove_buddy(gb); - } break; case SW_DISCOVERY_BROWSE_RESOLVED: purple_debug_info("bonjour", "_browse_reply --> Resolved\n"); diff -r 0eff4257d55b -r f96cceb75fbb libpurple/protocols/bonjour/mdns_win32.c --- a/libpurple/protocols/bonjour/mdns_win32.c Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_win32.c Mon Sep 03 01:09:08 2007 +0000 @@ -79,23 +79,23 @@ uint32_t ttl, void *context) { - if (kDNSServiceErr_NoError != errorCode) + if (kDNSServiceErr_NoError != errorCode) { purple_debug_error("bonjour", "record query - callback error.\n"); - else if (flags & kDNSServiceFlagsAdd) - { + /* TODO: Probably should remove the buddy when this happens */ + } else if (flags & kDNSServiceFlagsAdd) { if (rrtype == kDNSServiceType_TXT) { /* New Buddy */ - BonjourBuddy *buddy = (BonjourBuddy*) context; - _mdns_parse_text_record(buddy, rdata, rdlen); - bonjour_buddy_add_to_purple(buddy); + BonjourBuddy *bb = (BonjourBuddy*) context; + _mdns_parse_text_record(bb, rdata, rdlen); + bonjour_buddy_add_to_purple(bb, NULL); } else if (rrtype == kDNSServiceType_NULL) { /* Buddy Icon response */ - BonjourBuddy *buddy = (BonjourBuddy*) context; - Win32BuddyImplData *idata = buddy->mdns_impl_data; + BonjourBuddy *bb = (BonjourBuddy*) context; + Win32BuddyImplData *idata = bb->mdns_impl_data; g_return_if_fail(idata != NULL); - bonjour_buddy_got_buddy_icon(buddy, rdata, rdlen); + bonjour_buddy_got_buddy_icon(bb, rdata, rdlen); /* We've got what we need; stop listening */ purple_input_remove(idata->null_query_handler); @@ -110,32 +110,34 @@ _mdns_resolve_host_callback(GSList *hosts, gpointer data, const char *error_message) { ResolveCallbackArgs* args = (ResolveCallbackArgs*)data; + BonjourBuddy* bb = args->buddy; - if (!hosts || !hosts->data) + if (!hosts || !hosts->data) { purple_debug_error("bonjour", "host resolution - callback error.\n"); - else { + bonjour_buddy_delete(bb); + } else { struct sockaddr_in *addr = (struct sockaddr_in*)g_slist_nth_data(hosts, 1); - BonjourBuddy* buddy = args->buddy; - Win32BuddyImplData *idata = buddy->mdns_impl_data; + Win32BuddyImplData *idata = bb->mdns_impl_data; g_return_if_fail(idata != NULL); - buddy->ip = g_strdup(inet_ntoa(addr->sin_addr)); + g_free(bb->ip); + bb->ip = g_strdup(inet_ntoa(addr->sin_addr)); /* finally, set up the continuous txt record watcher, and add the buddy to purple */ if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&idata->txt_query, kDNSServiceFlagsLongLivedQuery, kDNSServiceInterfaceIndexAny, args->full_service_name, kDNSServiceType_TXT, - kDNSServiceClass_IN, _mdns_record_query_callback, buddy)) { + kDNSServiceClass_IN, _mdns_record_query_callback, bb)) { - purple_debug_info("bonjour", "Found buddy %s at %s:%d\n", buddy->name, buddy->ip, buddy->port_p2pj); + purple_debug_info("bonjour", "Found buddy %s at %s:%d\n", bb->name, bb->ip, bb->port_p2pj); idata->txt_query_handler = purple_input_add(DNSServiceRefSockFD(idata->txt_query), PURPLE_INPUT_READ, _mdns_handle_event, idata->txt_query); - bonjour_buddy_add_to_purple(buddy); + bonjour_buddy_add_to_purple(bb, NULL); } else - bonjour_buddy_delete(buddy); + bonjour_buddy_delete(bb); } @@ -202,18 +204,19 @@ DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context) { PurpleAccount *account = (PurpleAccount*)context; - PurpleBuddy *gb = NULL; + PurpleBuddy *pb = NULL; if (kDNSServiceErr_NoError != errorCode) purple_debug_error("bonjour", "service browser - callback error"); else if (flags & kDNSServiceFlagsAdd) { /* A presence service instance has been discovered... check it isn't us! */ - if (g_ascii_strcasecmp(serviceName, account->username) != 0) { + if (purple_utf8_strcasecmp(serviceName, account->username) != 0) { /* OK, lets go ahead and resolve it to add to the buddy list */ ResolveCallbackArgs *args = g_new0(ResolveCallbackArgs, 1); args->buddy = bonjour_buddy_new(serviceName, account); - if (kDNSServiceErr_NoError != DNSServiceResolve(&args->resolver, 0, 0, serviceName, regtype, replyDomain, _mdns_service_resolve_callback, args)) { + if (kDNSServiceErr_NoError != DNSServiceResolve(&args->resolver, 0, 0, serviceName, regtype, + replyDomain, _mdns_service_resolve_callback, args)) { bonjour_buddy_delete(args->buddy); g_free(args); purple_debug_error("bonjour", "service browser - failed to resolve service.\n"); @@ -226,11 +229,9 @@ } else { /* A peer has sent a goodbye packet, remove them from the buddy list */ purple_debug_info("bonjour", "service browser - remove notification\n"); - gb = purple_find_buddy(account, serviceName); - if (gb != NULL) { - bonjour_buddy_delete(gb->proto_data); - purple_blist_remove_buddy(gb); - } + pb = purple_find_buddy(account, serviceName); + if (pb != NULL) + purple_blist_remove_buddy(pb); } } diff -r 0eff4257d55b -r f96cceb75fbb libpurple/protocols/myspace/CHANGES --- a/libpurple/protocols/myspace/CHANGES Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/protocols/myspace/CHANGES Mon Sep 03 01:09:08 2007 +0000 @@ -1,3 +1,13 @@ +2007-08-28 Jeff Connelly - 0.17 +* Get server-side contact list from server on sign-on (partly implements + server-side contacts, ticket #2658). +* Set local alias to username on sign-on, if not already set. This fixes + #2793, though this may not be the best way, other fixes under consideration. +* Support myim:sendIM and addContact URLs with cID and uID parameters. +* Fix #2722, only check for mail if "New mail notifications" is enabled. +* Modularize msimprpl. + + 2007-08-23 Jeff Connelly - 0.16 * Add option to add all friends from myspace.com to your buddy list (#2660) * If a user doesn't have a picture, don't display an icon (instead of @@ -6,6 +16,7 @@ * Fix #2752, which led to duplicate groups * Fix #2720, crash/disconnect when adding a buddy that doesn't exist (You'll now receive an error when looking up invalid usernames). +* Source-code release only. 2007-08-22 Jeff Connelly - 0.15 * Incomplete implementation of adding friends from myspace.com. diff -r 0eff4257d55b -r f96cceb75fbb libpurple/protocols/myspace/myspace.c --- a/libpurple/protocols/myspace/myspace.c Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/protocols/myspace/myspace.c Mon Sep 03 01:09:08 2007 +0000 @@ -683,6 +683,7 @@ msim_incoming_im(MsimSession *session, MsimMessage *msg) { gchar *username, *msg_msim_markup, *msg_purple_markup; + time_t time_received; g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); g_return_val_if_fail(msg != NULL, FALSE); @@ -696,8 +697,12 @@ msg_purple_markup = msim_markup_to_html(session, msg_msim_markup); g_free(msg_msim_markup); - serv_got_im(session->gc, username, msg_purple_markup, - PURPLE_MESSAGE_RECV, time(NULL)); + time_received = msim_msg_get_integer(msg, "date"); + if (!time_received) { + time_received = time(NULL); + } + + serv_got_im(session->gc, username, msg_purple_markup, PURPLE_MESSAGE_RECV, time_received); g_free(username); g_free(msg_purple_markup); diff -r 0eff4257d55b -r f96cceb75fbb libpurple/protocols/oscar/oscarcommon.h --- a/libpurple/protocols/oscar/oscarcommon.h Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/protocols/oscar/oscarcommon.h Mon Sep 03 01:09:08 2007 +0000 @@ -30,7 +30,7 @@ #include "version.h" #include "notify.h" -#define OSCAR_DEFAULT_LOGIN_SERVER "login.oscar.aol.com" +#define OSCAR_DEFAULT_LOGIN_SERVER "login.messaging.aol.com" #define OSCAR_DEFAULT_LOGIN_PORT 5190 #ifndef _WIN32 #define OSCAR_DEFAULT_CUSTOM_ENCODING "ISO-8859-1" diff -r 0eff4257d55b -r f96cceb75fbb libpurple/protocols/yahoo/yahoo.c --- a/libpurple/protocols/yahoo/yahoo.c Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Mon Sep 03 01:09:08 2007 +0000 @@ -969,7 +969,6 @@ PurpleConnection *gc; char *id; char *who; - char *msg; int protocol; }; @@ -987,7 +986,6 @@ g_free(add_req->id); g_free(add_req->who); - g_free(add_req->msg); g_free(add_req); } @@ -1018,7 +1016,6 @@ g_free(add_req->id); g_free(add_req->who); - g_free(add_req->msg); g_free(add_req); } @@ -1132,10 +1129,18 @@ l = l->next; } - if (add_req->id) { - char *alias = NULL; + if (add_req->id && add_req->who) { + char *alias = NULL, *dec_msg = NULL; + + if (!yahoo_privacy_check(gc, add_req->who)) { + purple_debug_misc("yahoo", "Auth. request from %s dropped and automatically denied due to privacy settings!\n", + add_req->who); + yahoo_buddy_add_deny_cb(add_req, NULL); + return; + } + if (msg) - add_req->msg = yahoo_string_decode(gc, msg, FALSE); + dec_msg = yahoo_string_decode(gc, msg, FALSE); if (firstname && lastname) alias = g_strdup_printf("%s %s", firstname, lastname); @@ -1144,20 +1149,19 @@ else if (lastname) alias = g_strdup(lastname); - /* DONE! this is almost exactly the same as what MSN does, * this should probably be moved to the core. */ purple_account_request_authorization(purple_connection_get_account(gc), add_req->who, add_req->id, - alias, add_req->msg, purple_find_buddy(purple_connection_get_account(gc),add_req->who) != NULL, + alias, dec_msg, purple_find_buddy(purple_connection_get_account(gc), add_req->who) != NULL, yahoo_buddy_add_authorize_cb, yahoo_buddy_add_deny_reason_cb, add_req); g_free(alias); + g_free(dec_msg); } else { g_free(add_req->id); g_free(add_req->who); - /*g_free(add_req->msg);*/ g_free(add_req); } } else { @@ -1165,6 +1169,7 @@ } } +/* I don't think this happens anymore in Version 15 */ static void yahoo_buddy_added_us(PurpleConnection *gc, struct yahoo_packet *pkt) { struct yahoo_add_request *add_req; char *msg = NULL; @@ -1192,22 +1197,31 @@ l = l->next; } - if (add_req->id) { + if (add_req->id && add_req->who) { + char *dec_msg = NULL; + + if (!yahoo_privacy_check(gc, add_req->who)) { + purple_debug_misc("yahoo", "Auth. request from %s dropped and automatically denied due to privacy settings!\n", + add_req->who); + yahoo_buddy_add_deny_cb(add_req, NULL); + return; + } + if (msg) - add_req->msg = yahoo_string_decode(gc, msg, FALSE); + dec_msg = yahoo_string_decode(gc, msg, FALSE); /* DONE! this is almost exactly the same as what MSN does, * this should probably be moved to the core. */ purple_account_request_authorization(purple_connection_get_account(gc), add_req->who, add_req->id, - NULL, add_req->msg, purple_find_buddy(purple_connection_get_account(gc),add_req->who) != NULL, + NULL, dec_msg, purple_find_buddy(purple_connection_get_account(gc),add_req->who) != NULL, yahoo_buddy_add_authorize_cb, yahoo_buddy_add_deny_reason_cb, add_req); + g_free(dec_msg); } else { g_free(add_req->id); g_free(add_req->who); - /*g_free(add_req->msg);*/ g_free(add_req); } } @@ -3016,6 +3030,11 @@ if (yd->ycht) ycht_connection_close(yd->ycht); + g_free(yd->pending_chat_room); + g_free(yd->pending_chat_id); + g_free(yd->pending_chat_topic); + g_free(yd->pending_chat_goto); + g_free(yd); gc->proto_data = NULL; } diff -r 0eff4257d55b -r f96cceb75fbb libpurple/protocols/yahoo/yahoo.h --- a/libpurple/protocols/yahoo/yahoo.h Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo.h Mon Sep 03 01:09:08 2007 +0000 @@ -130,6 +130,10 @@ gboolean chat_online; gboolean in_chat; char *chat_name; + char *pending_chat_room; + char *pending_chat_id; + char *pending_chat_topic; + char *pending_chat_goto; char *auth; gsize auth_written; char *cookie_y; diff -r 0eff4257d55b -r f96cceb75fbb libpurple/protocols/yahoo/yahoochat.c --- a/libpurple/protocols/yahoo/yahoochat.c Mon Sep 03 01:07:47 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoochat.c Mon Sep 03 01:09:08 2007 +0000 @@ -55,16 +55,24 @@ { struct yahoo_data *yd = gc->proto_data; struct yahoo_packet *pkt; + const char *rll; if (yd->wm) { ycht_connection_open(gc); return; } + rll = purple_account_get_string(purple_connection_get_account(gc), + "room_list_locale", YAHOO_ROOMLIST_LOCALE); + pkt = yahoo_packet_new(YAHOO_SERVICE_CHATONLINE, YAHOO_STATUS_AVAILABLE,0); - yahoo_packet_hash(pkt, "ssss", 1, purple_connection_get_display_name(gc), - 109, purple_connection_get_display_name(gc), 6, "abcde", - 135, "ym8.1.0.415"); + yahoo_packet_hash(pkt, "sssss", + 109, purple_connection_get_display_name(gc), + 1, purple_connection_get_display_name(gc), + 6, "abcde", + /* I'm not sure this is the correct way to set this. */ + 98, rll, + 135, "ym8.1.0.415"); yahoo_packet_send_and_free(pkt, yd); } @@ -125,6 +133,7 @@ case 1: /* us, but we already know who we are */ break; case 57: + g_free(room); room = yahoo_string_decode(gc, pair->value, FALSE); break; case 50: /* inviter */ @@ -136,6 +145,7 @@ g_string_append_printf(members, "%s\n", pair->value); break; case 58: + g_free(msg); msg = yahoo_string_decode(gc, pair->value, FALSE); break; case 13: /* ? */ @@ -145,6 +155,17 @@ if (!room) { g_string_free(members, TRUE); + g_free(msg); + return; + } + + if (!yahoo_privacy_check(gc, who) || + (purple_account_get_bool(purple_connection_get_account(gc), "ignore_invites", FALSE))) { + purple_debug_info("yahoo", + "Invite to conference %s from %s has been dropped.\n", room, who); + g_free(room); + g_free(msg); + g_string_free(members, TRUE); return; } @@ -153,19 +174,9 @@ if (msg) g_hash_table_replace(components, g_strdup("topic"), msg); g_hash_table_replace(components, g_strdup("type"), g_strdup("Conference")); - if (members) { - g_hash_table_replace(components, g_strdup("members"), g_strdup(members->str)); - } - if (!yahoo_privacy_check(gc, who) || - (purple_account_get_bool(purple_connection_get_account(gc), "ignore_invites", FALSE))) { - purple_debug_info("yahoo", - "Invite to conference %s from %s has been dropped.\n", room, who); - g_string_free(members, TRUE); - return; - } + g_hash_table_replace(components, g_strdup("members"), g_string_free(members, FALSE)); serv_got_chat_invite(gc, room, who, msg, components); - g_string_free(members, TRUE); } void yahoo_process_conference_decline(PurpleConnection *gc, struct yahoo_packet *pkt) @@ -180,20 +191,21 @@ switch (pair->key) { case 57: + g_free(room); room = yahoo_string_decode(gc, pair->value, FALSE); break; case 54: who = pair->value; break; case 14: + g_free(msg); msg = yahoo_string_decode(gc, pair->value, FALSE); break; } } if (!yahoo_privacy_check(gc, who)) { g_free(room); - if (msg != NULL) - g_free(msg); + g_free(msg); return; } @@ -209,8 +221,7 @@ } g_free(room); - if (msg) - g_free(msg); + g_free(msg); } } @@ -226,6 +237,7 @@ switch (pair->key) { case 57: + g_free(room); room = yahoo_string_decode(gc, pair->value, FALSE); break; case 53: @@ -254,6 +266,7 @@ switch (pair->key) { case 57: + g_free(room); room = yahoo_string_decode(gc, pair->value, FALSE); break; case 56: @@ -276,7 +289,6 @@ char *room = NULL; char *who = NULL; char *msg = NULL; - char *msg2; int utf8 = 0; PurpleConversation *c; @@ -285,6 +297,7 @@ switch (pair->key) { case 57: + g_free(room); room = yahoo_string_decode(gc, pair->value, FALSE); break; case 3: @@ -299,28 +312,82 @@ } } - if (room && who && msg) { - msg2 = yahoo_string_decode(gc, msg, utf8); - c = yahoo_find_conference(gc, room); - if (!c) - return; - msg = yahoo_codes_to_html(msg2); - serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)), who, 0, msg, time(NULL)); - g_free(msg); - g_free(msg2); + if (room && who && msg) { + char *msg2; + + c = yahoo_find_conference(gc, room); + if (!c) { + g_free(room); + return; } - if (room) - g_free(room); + + msg2 = yahoo_string_decode(gc, msg, utf8); + msg = yahoo_codes_to_html(msg2); + serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)), who, 0, msg, time(NULL)); + g_free(msg); + g_free(msg2); + } + + g_free(room); } +static void yahoo_chat_join(PurpleConnection *gc, const char *dn, const char *room, const char *topic, const char *id) +{ + struct yahoo_data *yd = gc->proto_data; + struct yahoo_packet *pkt; + char *room2; + gboolean utf8 = TRUE; + + if (yd->wm) { + g_return_if_fail(yd->ycht != NULL); + ycht_chat_join(yd->ycht, room); + return; + } + + /* apparently room names are always utf8, or else always not utf8, + * so we don't have to actually pass the flag in the packet. Or something. */ + room2 = yahoo_string_encode(gc, room, &utf8); + + pkt = yahoo_packet_new(YAHOO_SERVICE_CHATJOIN, YAHOO_STATUS_AVAILABLE, 0); + yahoo_packet_hash(pkt, "ssss", + 1, purple_connection_get_display_name(gc), + 104, room2, + 62, "2", + 129, id ? id : "0"); + yahoo_packet_send_and_free(pkt, yd); + g_free(room2); +} /* this is a confirmation of yahoo_chat_online(); */ void yahoo_process_chat_online(PurpleConnection *gc, struct yahoo_packet *pkt) { struct yahoo_data *yd = (struct yahoo_data *) gc->proto_data; - if (pkt->status == 1) + if (pkt->status == 1) { yd->chat_online = 1; + + /* We need to goto a user in chat */ + if (yd->pending_chat_goto) { + struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_CHATGOTO, YAHOO_STATUS_AVAILABLE, 0); + yahoo_packet_hash(pkt, "sss", + 109, yd->pending_chat_goto, + 1, purple_connection_get_display_name(gc), + 62, "2"); + yahoo_packet_send_and_free(pkt, yd); + } else if (yd->pending_chat_room) { + yahoo_chat_join(gc, purple_connection_get_display_name(gc), yd->pending_chat_room, + yd->pending_chat_topic, yd->pending_chat_id); + } + + g_free(yd->pending_chat_room); + yd->pending_chat_room = NULL; + g_free(yd->pending_chat_id); + yd->pending_chat_id = NULL; + g_free(yd->pending_chat_topic); + yd->pending_chat_topic = NULL; + g_free(yd->pending_chat_goto); + yd->pending_chat_goto = NULL; + } } /* this is basicly the opposite of chat_online */ @@ -340,6 +407,14 @@ if (pkt->status == 1) { yd->chat_online = 0; + g_free(yd->pending_chat_room); + yd->pending_chat_room = NULL; + g_free(yd->pending_chat_id); + yd->pending_chat_id = NULL; + g_free(yd->pending_chat_topic); + yd->pending_chat_topic = NULL; + g_free(yd->pending_chat_goto); + yd->pending_chat_goto = NULL; if (yd->in_chat) yahoo_c_leave(gc, YAHOO_CHAT_ID); } @@ -384,9 +459,11 @@ switch (pair->key) { case 104: + g_free(room); room = yahoo_string_decode(gc, pair->value, TRUE); break; case 105: + g_free(topic); topic = yahoo_string_decode(gc, pair->value, TRUE); break; case 128: @@ -445,8 +522,11 @@ purple_conversation_set_name(c, room); c = serv_got_joined_chat(gc, YAHOO_CHAT_ID, room); - if (topic) + if (topic) { purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic); + /* Also print the topic to the backlog so that the captcha link is clickable */ + purple_conv_chat_write(PURPLE_CONV_CHAT(c), "", topic, PURPLE_MESSAGE_SYSTEM, time(NULL)); + } yd->in_chat = 1; yd->chat_name = g_strdup(room); purple_conv_chat_add_users(PURPLE_CONV_CHAT(c), members, NULL, flags, FALSE); @@ -456,14 +536,22 @@ g_free(tmpmsg); } else { c = serv_got_joined_chat(gc, YAHOO_CHAT_ID, room); - if (topic) + if (topic) { purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic); + /* Also print the topic to the backlog so that the captcha link is clickable */ + purple_conv_chat_write(PURPLE_CONV_CHAT(c), "", topic, PURPLE_MESSAGE_SYSTEM, time(NULL)); + } yd->in_chat = 1; yd->chat_name = g_strdup(room); purple_conv_chat_add_users(PURPLE_CONV_CHAT(c), members, NULL, flags, FALSE); } g_list_free(flags); } else if (c) { + if (topic) { + const char *cur_topic = purple_conv_chat_get_topic(PURPLE_CONV_CHAT(c)); + if (cur_topic == NULL || strcmp(cur_topic, topic) != 0) + purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic); + } yahoo_chat_add_users(PURPLE_CONV_CHAT(c), members); } @@ -497,8 +585,10 @@ for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; - if (pair->key == 104) + if (pair->key == 104) { + g_free(room); room = yahoo_string_decode(gc, pair->value, TRUE); + } if (pair->key == 109) who = pair->value; } @@ -529,6 +619,7 @@ utf8 = strtol(pair->value, NULL, 10); break; case 104: + g_free(room); room = yahoo_string_decode(gc, pair->value, TRUE); break; case 109: @@ -583,6 +674,7 @@ switch (pair->key) { case 104: + g_free(room); room = yahoo_string_decode(gc, pair->value, TRUE); break; case 129: /* room id? */ @@ -590,6 +682,7 @@ case 126: /* ??? */ break; case 117: + g_free(msg); msg = yahoo_string_decode(gc, pair->value, FALSE); break; case 119: @@ -603,24 +696,21 @@ if (room && who) { GHashTable *components; + if (!yahoo_privacy_check(gc, who) || + (purple_account_get_bool(purple_connection_get_account(gc), "ignore_invites", FALSE))) { + purple_debug_info("yahoo", "Invite to room %s from %s has been dropped.\n", room, who); + g_free(room); + g_free(msg); + return; + } + components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); g_hash_table_replace(components, g_strdup("room"), g_strdup(room)); - if (!yahoo_privacy_check(gc, who) || - (purple_account_get_bool(purple_connection_get_account(gc), "ignore_invites", FALSE))) { - purple_debug_info("yahoo", - "Invite to room %s from %s has been dropped.\n", room, who); - if (room != NULL) - g_free(room); - if (msg != NULL) - g_free(msg); - return; - } serv_got_chat_invite(gc, room, who, msg, components); } - if (room) - g_free(room); - if (msg) - g_free(msg); + + g_free(room); + g_free(msg); } void yahoo_process_chat_goto(PurpleConnection *gc, struct yahoo_packet *pkt) @@ -783,6 +873,14 @@ yahoo_packet_send_and_free(pkt, yd); yd->chat_online = 0; + g_free(yd->pending_chat_room); + yd->pending_chat_room = NULL; + g_free(yd->pending_chat_id); + yd->pending_chat_id = NULL; + g_free(yd->pending_chat_topic); + yd->pending_chat_topic = NULL; + g_free(yd->pending_chat_goto); + yd->pending_chat_goto = NULL; g_free(eroom); } @@ -829,29 +927,6 @@ return 0; } -static void yahoo_chat_join(PurpleConnection *gc, const char *dn, const char *room, const char *topic) -{ - struct yahoo_data *yd = gc->proto_data; - struct yahoo_packet *pkt; - char *room2; - gboolean utf8 = TRUE; - - if (yd->wm) { - g_return_if_fail(yd->ycht != NULL); - ycht_chat_join(yd->ycht, room); - return; - } - - /* apparently room names are always utf8, or else always not utf8, - * so we don't have to actually pass the flag in the packet. Or something. */ - room2 = yahoo_string_encode(gc, room, &utf8); - - pkt = yahoo_packet_new(YAHOO_SERVICE_CHATJOIN, YAHOO_STATUS_AVAILABLE, 0); - yahoo_packet_hash(pkt, "ssss", 1, purple_connection_get_display_name(gc), - 62, "2", 104, room2, 129, "0"); - yahoo_packet_send_and_free(pkt, yd); - g_free(room2); -} static void yahoo_chat_invite(PurpleConnection *gc, const char *dn, const char *buddy, const char *room, const char *msg) @@ -892,8 +967,18 @@ return; } - if (!yd->chat_online) + if (!yd->chat_online) { yahoo_chat_online(gc); + g_free(yd->pending_chat_room); + yd->pending_chat_room = NULL; + g_free(yd->pending_chat_id); + yd->pending_chat_id = NULL; + g_free(yd->pending_chat_topic); + yd->pending_chat_topic = NULL; + g_free(yd->pending_chat_goto); + yd->pending_chat_goto = g_strdup(name); + return; + } pkt = yahoo_packet_new(YAHOO_SERVICE_CHATGOTO, YAHOO_STATUS_AVAILABLE, 0); yahoo_packet_hash(pkt, "sss", 109, name, 1, purple_connection_get_display_name(gc), 62, "2"); @@ -988,8 +1073,7 @@ void yahoo_c_join(PurpleConnection *gc, GHashTable *data) { struct yahoo_data *yd; - char *room, *topic, *members, *type; - int id; + char *room, *topic, *type; PurpleConversation *c; yd = (struct yahoo_data *) gc->proto_data; @@ -1004,9 +1088,9 @@ if (!topic) topic = ""; - members = g_hash_table_lookup(data, "members"); - if ((type = g_hash_table_lookup(data, "type")) && !strcmp(type, "Conference")) { + int id; + const char *members = g_hash_table_lookup(data, "members"); id = yd->conf_id++; c = serv_got_joined_chat(gc, id, room); yd->confs = g_slist_prepend(yd->confs, c); @@ -1014,13 +1098,27 @@ yahoo_conf_join(yd, c, purple_connection_get_display_name(gc), room, topic, members); return; } else { - if (yd->in_chat) + const char *id; + /*if (yd->in_chat) yahoo_chat_leave(gc, room, purple_connection_get_display_name(gc), - FALSE); - if (!yd->chat_online) + FALSE);*/ + + id = g_hash_table_lookup(data, "id"); + + if (!yd->chat_online) { yahoo_chat_online(gc); - yahoo_chat_join(gc, purple_connection_get_display_name(gc), room, topic); + g_free(yd->pending_chat_room); + yd->pending_chat_room = g_strdup(room); + g_free(yd->pending_chat_id); + yd->pending_chat_id = g_strdup(id); + g_free(yd->pending_chat_topic); + yd->pending_chat_topic = g_strdup(topic); + g_free(yd->pending_chat_goto); + yd->pending_chat_goto = NULL; + } else { + yahoo_chat_join(gc, purple_connection_get_display_name(gc), room, topic, id); + } return; } } @@ -1148,16 +1246,13 @@ for (i = 0; anames[i]; i++) { if (!strcmp(anames[i], "id")) { - if (s->room.id) - g_free(s->room.id); + g_free(s->room.id); s->room.id = g_strdup(avalues[i]); } else if (!strcmp(anames[i], "name")) { - if (s->room.name) - g_free(s->room.name); + g_free(s->room.name); s->room.name = g_strdup(avalues[i]); } else if (!strcmp(anames[i], "topic")) { - if (s->room.topic) - g_free(s->room.topic); + g_free(s->room.topic); s->room.topic = g_strdup(avalues[i]); } else if (!strcmp(anames[i], "type")) { if (!strcmp("yahoo", avalues[i])) diff -r 0eff4257d55b -r f96cceb75fbb pidgin/gtkblist.c --- a/pidgin/gtkblist.c Mon Sep 03 01:07:47 2007 +0000 +++ b/pidgin/gtkblist.c Mon Sep 03 01:09:08 2007 +0000 @@ -125,7 +125,7 @@ static PidginBuddyList *gtkblist = NULL; static gboolean pidgin_blist_refresh_timer(PurpleBuddyList *list); -static void pidgin_blist_update_buddy(PurpleBuddyList *list, PurpleBlistNode *node, gboolean statusChange); +static void pidgin_blist_update_buddy(PurpleBuddyList *list, PurpleBlistNode *node, gboolean status_change); static void pidgin_blist_selection_changed(GtkTreeSelection *selection, gpointer data); static void pidgin_blist_update(PurpleBuddyList *list, PurpleBlistNode *node); static void pidgin_blist_update_group(PurpleBuddyList *list, PurpleBlistNode *node); @@ -614,6 +614,8 @@ static void pidgin_blist_update_privacy_cb(PurpleBuddy *buddy) { + if (buddy->node.ui_data == NULL || ((struct _pidgin_blist_node*)buddy->node.ui_data)->row == NULL) + return; pidgin_blist_update_buddy(purple_get_blist(), (PurpleBlistNode*)(buddy), TRUE); } @@ -2620,6 +2622,7 @@ struct _pidgin_blist_node *gtknode; GdkRectangle mon_size; int sig; + const char *name; if (node == NULL) return; @@ -2677,7 +2680,9 @@ gtknode = node->ui_data; + name = gtk_window_get_title(GTK_WINDOW(gtk_widget_get_toplevel(widget))); gtk_widget_set_app_paintable(gtkblist->tipwindow, TRUE); + gtk_window_set_title(GTK_WINDOW(gtkblist->tipwindow), name ? name : _("Buddy List")); gtk_window_set_resizable(GTK_WINDOW(gtkblist->tipwindow), FALSE); gtk_widget_set_name(gtkblist->tipwindow, "gtk-tooltips"); g_signal_connect(G_OBJECT(gtkblist->tipwindow), "expose_event", @@ -3207,6 +3212,7 @@ { GdkPixbuf *ret; const char *protoname = NULL; + const char *icon = NULL; struct _pidgin_blist_node *gtknode = node->ui_data; struct _pidgin_blist_node *gtkbuddynode = NULL; PurpleBuddy *buddy = NULL; @@ -3255,62 +3261,54 @@ purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); PurplePresence *p; + gboolean trans; + if(conv != NULL) { PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); - if(gtkconv != NULL && pidgin_conv_is_hidden(gtkconv) && size == PIDGIN_STATUS_ICON_SMALL) { + if((gtkconv == NULL || pidgin_conv_is_hidden(gtkconv)) && size == PIDGIN_STATUS_ICON_SMALL) { return gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_MESSAGE, icon_size, "GtkTreeView"); } } + p = purple_buddy_get_presence(buddy); + trans = (purple_presence_is_idle(p) && size == PIDGIN_STATUS_ICON_SMALL); if (PURPLE_BUDDY_IS_ONLINE(buddy) && gtkbuddynode && gtkbuddynode->recent_signonoff) - ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_LOGIN, - icon_size, "GtkTreeView"); + icon = PIDGIN_STOCK_STATUS_LOGIN; else if (gtkbuddynode && gtkbuddynode->recent_signonoff) - ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_LOGOUT, - icon_size, "GtkTreeView"); + icon = PIDGIN_STOCK_STATUS_LOGOUT; else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_UNAVAILABLE)) - if (purple_presence_is_idle(p) && size == PIDGIN_STATUS_ICON_SMALL) - ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_BUSY_I, - icon_size, "GtkTreeView"); + if (trans) + icon = PIDGIN_STOCK_STATUS_BUSY_I; else - ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_BUSY, - icon_size, "GtkTreeView"); + icon = PIDGIN_STOCK_STATUS_BUSY; else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AWAY)) - if (purple_presence_is_idle(p) && size == PIDGIN_STATUS_ICON_SMALL) - ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_AWAY_I, - icon_size, "GtkTreeView"); + if (trans) + icon = PIDGIN_STOCK_STATUS_AWAY_I; else - ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_AWAY, - icon_size, "GtkTreeView"); + icon = PIDGIN_STOCK_STATUS_AWAY; else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_EXTENDED_AWAY)) - if (purple_presence_is_idle(p) && size == PIDGIN_STATUS_ICON_SMALL) - ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_XA_I, - icon_size, "GtkTreeView"); + if (trans) + icon = PIDGIN_STOCK_STATUS_XA_I; else - ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_XA, - icon_size, "GtkTreeView"); + icon = PIDGIN_STOCK_STATUS_XA; else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_OFFLINE)) - ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_OFFLINE, - icon_size, "GtkTreeView"); - else if (purple_presence_is_idle(p) && size == PIDGIN_STATUS_ICON_SMALL) - ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_AVAILABLE_I, - icon_size, "GtkTreeView"); + icon = PIDGIN_STOCK_STATUS_OFFLINE; + else if (trans) + icon = PIDGIN_STOCK_STATUS_AVAILABLE_I; else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_INVISIBLE)) - ret = gtk_widget_render_icon(GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_INVISIBLE, - icon_size, "GtkTreeView"); + icon = PIDGIN_STOCK_STATUS_INVISIBLE; else - ret = gtk_widget_render_icon(GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_AVAILABLE, - icon_size, "GtkTreeView"); + icon = PIDGIN_STOCK_STATUS_AVAILABLE; } else if (chat) { - ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_CHAT, - icon_size, "GtkTreeView"); + icon = PIDGIN_STOCK_STATUS_CHAT; } else { - ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_PERSON, - icon_size, "GtkTreeView"); - } - + icon = PIDGIN_STOCK_STATUS_PERSON; + } + + ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), icon, + icon_size, "GtkTreeView"); return ret; } @@ -3333,7 +3331,7 @@ if(conv != NULL) { gtkconv = PIDGIN_CONVERSATION(conv); - if(gtkconv != NULL && pidgin_conv_is_hidden(gtkconv)) { + if(gtkconv == NULL || pidgin_conv_is_hidden(gtkconv)) { hidden_conv = TRUE; } } @@ -5158,7 +5156,7 @@ -static void pidgin_blist_update_buddy(PurpleBuddyList *list, PurpleBlistNode *node, gboolean statusChange) +static void pidgin_blist_update_buddy(PurpleBuddyList *list, PurpleBlistNode *node, gboolean status_change) { PurpleBuddy *buddy; struct _pidgin_blist_node *gtkparentnode; @@ -5211,6 +5209,10 @@ GdkPixbuf *emblem; char *mark; gboolean showicons = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"); + const char *name = purple_chat_get_name(chat); + PurpleConversation *conv = + purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, name, chat->account); + gboolean hidden = (conv && !PIDGIN_CONVERSATION(conv)); if(!insert_node(list, node, &iter)) return; @@ -5226,15 +5228,20 @@ avatar = NULL; mark = g_markup_escape_text(purple_chat_get_name(chat), -1); + if (hidden) { + char *bold = g_strdup_printf("%s", mark); + g_free(mark); + mark = bold; + } gtk_tree_store_set(gtkblist->treemodel, &iter, STATUS_ICON_COLUMN, status, STATUS_ICON_VISIBLE_COLUMN, TRUE, BUDDY_ICON_COLUMN, avatar ? avatar : gtkblist->empty_avatar, BUDDY_ICON_VISIBLE_COLUMN, purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"), - EMBLEM_COLUMN, emblem, + EMBLEM_COLUMN, emblem, EMBLEM_VISIBLE_COLUMN, emblem != NULL, - PROTOCOL_ICON_COLUMN, pidgin_create_prpl_icon(chat->account, PIDGIN_PRPL_ICON_SMALL), + PROTOCOL_ICON_COLUMN, pidgin_create_prpl_icon(chat->account, PIDGIN_PRPL_ICON_SMALL), PROTOCOL_ICON_VISIBLE_COLUMN, purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons"), NAME_COLUMN, mark, GROUP_EXPANDER_VISIBLE_COLUMN, FALSE, diff -r 0eff4257d55b -r f96cceb75fbb pidgin/gtkconv.c --- a/pidgin/gtkconv.c Mon Sep 03 01:07:47 2007 +0000 +++ b/pidgin/gtkconv.c Mon Sep 03 01:09:08 2007 +0000 @@ -1303,7 +1303,10 @@ menu_hide_conv_cb(gpointer data, guint action, GtkWidget *widget) { PidginWindow *win = data; + PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(win); PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); + purple_signal_emit(pidgin_conversations_get_handle(), + "conversation-hiding", gtkconv); purple_conversation_set_ui_ops(conv, NULL); } @@ -5622,6 +5625,7 @@ account, name, displaying, conv, flags); g_free(displaying); } + static void pidgin_conv_chat_add_users(PurpleConversation *conv, GList *cbuddies, gboolean new_arrivals) { @@ -7206,6 +7210,8 @@ if (gtkconv->attach.current) return TRUE; + purple_signal_emit(pidgin_conversations_get_handle(), + "conversation-displayed", gtkconv); g_source_remove(gtkconv->attach.timer); gtkconv->attach.timer = 0; return FALSE; @@ -7228,12 +7234,15 @@ list = g_list_last(list); gtkconv->attach.current = list; gtkconv->attach.timer = g_idle_add(add_message_history_to_gtkconv, gtkconv); - } - - /* XXX: If this is a chat: - * - populate the userlist - * - set the topic - */ + } else { + purple_signal_emit(pidgin_conversations_get_handle(), + "conversation-displayed", gtkconv); + } + + if (conv->type == PURPLE_CONV_TYPE_CHAT) { + pidgin_conv_update_fields(conv, PIDGIN_CONV_TOPIC); + pidgin_conv_chat_add_users(conv, PURPLE_CONV_CHAT(conv)->in_room, TRUE); + } return TRUE; } @@ -7415,6 +7424,16 @@ purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_CONVERSATION)); + purple_signal_register(handle, "conversation-hiding", + purple_marshal_VOID__POINTER_POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_BOXED, + "PidginConversation *")); + + purple_signal_register(handle, "conversation-displayed", + purple_marshal_VOID__POINTER_POINTER, NULL, 1, + purple_value_new(PURPLE_TYPE_BOXED, + "PidginConversation *")); + /********************************************************************** * Register commands **********************************************************************/ diff -r 0eff4257d55b -r f96cceb75fbb pidgin/gtkconv.h --- a/pidgin/gtkconv.h Mon Sep 03 01:07:47 2007 +0000 +++ b/pidgin/gtkconv.h Mon Sep 03 01:09:08 2007 +0000 @@ -245,6 +245,13 @@ */ void pidgin_conv_present_conversation(PurpleConversation *conv); +/** + * Reattach Pidgin UI to a conversation. + * + * @param conv The conversation. + * + * @return Wheter Pidgin UI was successfully attached. + */ gboolean pidgin_conv_attach_to_conversation(PurpleConversation *conv); PidginWindow *pidgin_conv_get_window(PidginConversation *gtkconv); diff -r 0eff4257d55b -r f96cceb75fbb pidgin/gtkimhtmltoolbar.c --- a/pidgin/gtkimhtmltoolbar.c Mon Sep 03 01:07:47 2007 +0000 +++ b/pidgin/gtkimhtmltoolbar.c Mon Sep 03 01:09:08 2007 +0000 @@ -786,6 +786,7 @@ gtk_widget_set_sensitive(GTK_WIDGET(toolbar->bold), buttons & GTK_IMHTML_BOLD); gtk_widget_set_sensitive(GTK_WIDGET(toolbar->italic), buttons & GTK_IMHTML_ITALIC); gtk_widget_set_sensitive(GTK_WIDGET(toolbar->underline), buttons & GTK_IMHTML_UNDERLINE); + gtk_widget_set_sensitive(GTK_WIDGET(toolbar->strikethrough), buttons & GTK_IMHTML_STRIKE); gtk_widget_set_sensitive(GTK_WIDGET(toolbar->larger_size), buttons & GTK_IMHTML_GROW); gtk_widget_set_sensitive(GTK_WIDGET(toolbar->smaller_size), buttons & GTK_IMHTML_SHRINK); @@ -798,6 +799,7 @@ (buttons & GTK_IMHTML_BOLD || buttons & GTK_IMHTML_ITALIC || buttons & GTK_IMHTML_UNDERLINE || + buttons & GTK_IMHTML_STRIKE || buttons & GTK_IMHTML_GROW || buttons & GTK_IMHTML_SHRINK || buttons & GTK_IMHTML_FACE || @@ -831,7 +833,7 @@ static void update_buttons(GtkIMHtmlToolbar *toolbar) { - gboolean bold, italic, underline; + gboolean bold, italic, underline, strike; char *tmp; char *tmp2; GtkLabel *label = g_object_get_data(G_OBJECT(toolbar), "font_label"); @@ -840,6 +842,7 @@ gtk_imhtml_get_current_format(GTK_IMHTML(toolbar->imhtml), &bold, &italic, &underline); + strike = GTK_IMHTML(toolbar->imhtml)->edit.strike; if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->bold)) != bold) toggle_button_set_active_block(GTK_TOGGLE_BUTTON(toolbar->bold), bold, @@ -847,10 +850,12 @@ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->italic)) != italic) toggle_button_set_active_block(GTK_TOGGLE_BUTTON(toolbar->italic), italic, toolbar); - if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->underline)) != underline) toggle_button_set_active_block(GTK_TOGGLE_BUTTON(toolbar->underline), underline, toolbar); + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->strikethrough)) != strike) + toggle_button_set_active_block(GTK_TOGGLE_BUTTON(toolbar->strikethrough), + strike, toolbar); /* These buttons aren't ever "active". */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toolbar->smaller_size), FALSE); @@ -874,6 +879,12 @@ gtk_label_set_markup_with_mnemonic(label, markup); g_free(markup); } + if (strike) { + gchar *markup = g_strdup_printf("%s", + gtk_label_get_label(label)); + gtk_label_set_markup_with_mnemonic(label, markup); + g_free(markup); + } tmp = gtk_imhtml_get_current_fontface(GTK_IMHTML(toolbar->imhtml)); toggle_button_set_active_block(GTK_TOGGLE_BUTTON(toolbar->font), diff -r 0eff4257d55b -r f96cceb75fbb pidgin/gtksourceundomanager.c --- a/pidgin/gtksourceundomanager.c Mon Sep 03 01:07:47 2007 +0000 +++ b/pidgin/gtksourceundomanager.c Mon Sep 03 01:09:08 2007 +0000 @@ -677,8 +677,6 @@ if (um->priv->running_not_undoable_actions > 0) return; - g_return_if_fail (strlen (text) >= (guint)length); - undo_action.action_type = GTK_SOURCE_UNDO_ACTION_INSERT; undo_action.action.insert.pos = gtk_text_iter_get_offset (pos); @@ -774,7 +772,7 @@ *action = *undo_action; if (action->action_type == GTK_SOURCE_UNDO_ACTION_INSERT) - action->action.insert.text = g_strdup (undo_action->action.insert.text); + action->action.insert.text = g_strndup (undo_action->action.insert.text, undo_action->action.insert.length); else if (action->action_type == GTK_SOURCE_UNDO_ACTION_DELETE) action->action.delete.text = g_strdup (undo_action->action.delete.text); else diff -r 0eff4257d55b -r f96cceb75fbb pidgin/plugins/notify.c --- a/pidgin/plugins/notify.c Mon Sep 03 01:07:47 2007 +0000 +++ b/pidgin/plugins/notify.c Mon Sep 03 01:09:08 2007 +0000 @@ -167,7 +167,7 @@ gboolean has_focus; PidginWindow *purplewin = NULL; - if (conv == NULL) + if (conv == NULL || PIDGIN_CONVERSATION(conv) == NULL) return 0; /* We want to remove the notifications, but not reset the counter */ @@ -224,6 +224,8 @@ PidginWindow *purplewin = NULL; g_return_if_fail(conv != NULL); + if (PIDGIN_CONVERSATION(conv) == NULL) + return; purplewin = PIDGIN_CONVERSATION(conv)->win; active_conv = pidgin_conv_window_get_active_conversation(purplewin); @@ -417,10 +419,14 @@ deleting_conv(PurpleConversation *conv) { PidginWindow *purplewin = NULL; + PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); + + if (gtkconv == NULL) + return; detach_signals(conv); - purplewin = PIDGIN_CONVERSATION(conv)->win; + purplewin = gtkconv->win; handle_urgent(purplewin, FALSE); purple_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(0)); diff -r 0eff4257d55b -r f96cceb75fbb pidgin/win32/nsis/pidgin-installer.nsi --- a/pidgin/win32/nsis/pidgin-installer.nsi Mon Sep 03 01:07:47 2007 +0000 +++ b/pidgin/win32/nsis/pidgin-installer.nsi Mon Sep 03 01:09:08 2007 +0000 @@ -693,6 +693,8 @@ ; Remove Language preference info (TODO: check if NSIS removes this) Delete "$INSTDIR\ca-certs\Equifax_Secure_CA.pem" + Delete "$INSTDIR\ca-certs\GTE_CyberTrust_Global_Root.pem" + Delete "$INSTDIR\ca-certs\Verisign_Class3_Primary_CA.pem" Delete "$INSTDIR\ca-certs\Verisign_RSA_Secure_Server_CA.pem" RMDir "$INSTDIR\ca-certs" RMDir /r "$INSTDIR\locale" diff -r 0eff4257d55b -r f96cceb75fbb share/ca-certs/Makefile.am --- a/share/ca-certs/Makefile.am Mon Sep 03 01:07:47 2007 +0000 +++ b/share/ca-certs/Makefile.am Mon Sep 03 01:09:08 2007 +0000 @@ -5,6 +5,7 @@ Verisign_RSA_Secure_Server_CA.pem \ Verisign_Class3_Primary_CA.pem -EXTRA_DIST = \ - $(cacerts_DATA) +EXTRA_DIST = \ + Makefile.mingw \ + $(cacerts_DATA)