# HG changeset patch # User Christopher O'Brien # Date 1162851772 0 # Node ID a03e74b9b257524b018df5e097500f515786e5da # Parent 390519f29a115917f94f43943f9d5b6c48d6269d [gaim-migrate @ 17685] fixing bugs 1570090, 1426401, applying patch 1526274. Starting to add support for ways to get around version-blocked sametime servers. Added fix to prevent login redirects from entering an eternal loop. Removing an unnecessary (and problematic) LDFLAG. I've been really slack for a while, so this is me getting caught up. committer: Tailor Script diff -r 390519f29a11 -r a03e74b9b257 libgaim/protocols/sametime/Makefile.am --- a/libgaim/protocols/sametime/Makefile.am Mon Nov 06 20:29:24 2006 +0000 +++ b/libgaim/protocols/sametime/Makefile.am Mon Nov 06 22:22:52 2006 +0000 @@ -27,7 +27,7 @@ endif -libsametime_la_LDFLAGS = -module -avoid-version -no-undefined +libsametime_la_LDFLAGS = -module -avoid-version libsametime_la_LIBADD = $(GLIB_LIBS) $(MEANWHILE_LIBS) diff -r 390519f29a11 -r a03e74b9b257 libgaim/protocols/sametime/sametime.c --- a/libgaim/protocols/sametime/sametime.c Mon Nov 06 20:29:24 2006 +0000 +++ b/libgaim/protocols/sametime/sametime.c Mon Nov 06 22:22:52 2006 +0000 @@ -141,14 +141,11 @@ /* keys to get/set gaim plugin information */ #define MW_KEY_HOST "server" #define MW_KEY_PORT "port" -#define MW_KEY_ACTIVE_MSG "active_msg" -#define MW_KEY_AWAY_MSG "away_msg" -#define MW_KEY_BUSY_MSG "busy_msg" -#define MW_KEY_MSG_PROMPT "msg_prompt" -#define MW_KEY_INVITE "conf_invite" -#define MW_KEY_ENCODING "encoding" #define MW_KEY_FORCE "force_login" #define MW_KEY_FAKE_IT "fake_client_id" +#define MW_KEY_CLIENT "client_id_val" +#define MW_KEY_MAJOR "client_major" +#define MW_KEY_MINOR "client_minor" /** number of seconds from the first blist change before a save to the @@ -233,6 +230,12 @@ }; +typedef struct { + GaimBuddy *buddy; + GaimGroup *group; +} BuddyAddData; + + /* blist and aware functions */ static void blist_export(GaimConnection *gc, struct mwSametimeList *stlist); @@ -486,7 +489,7 @@ GaimAccount *acct; struct mwGaimPluginData *pd; - time_t idle; + guint32 idle; guint stat; const char *id; const char *status = MW_STATE_ACTIVE; @@ -500,12 +503,39 @@ id = aware->id.user; if(idle) { + guint32 idle_len; /*< how long a client has been idle */ + guint32 ugly_idle_len; /*< how long a broken client has been idle */ + DEBUG_INFO("%s has idle value 0x%x\n", NSTR(id), idle); + idle_len = time(NULL) - idle; + ugly_idle_len = ((time(NULL) * 1000) - idle) / 1000; + + /* + what's the deal here? Well, good clients are smart enough to + publish their idle time by using an attribute to indicate that + they went idle at some time UTC, in seconds since epoch. Bad + clients use milliseconds since epoch. So we're going to compute + the idle time for either method, then figure out the lower of + the two and use that. Blame the ST 7.5 development team for + this. + */ + + DEBUG_INFO("idle time: %u, ugly idle time: %u\n", idle_len, ugly_idle_len); + +#if 1 + if(idle_len <= ugly_idle_len) { + ; /* DEBUG_INFO("sane idle value, let's use it\n"); */ + } else { + idle = time(NULL) - ugly_idle_len; + } + +#else if(idle < 0 || idle > time(NULL)) { DEBUG_INFO("hiding a messy idle value 0x%x\n", NSTR(id), idle); idle = -1; } +#endif } switch(stat) { @@ -559,7 +589,7 @@ if(aware->online) { gaim_prpl_got_user_status(acct, id, status, NULL); - gaim_prpl_got_user_idle(acct, id, !!idle, idle); + gaim_prpl_got_user_idle(acct, id, !!idle, (time_t) idle); } else { gaim_prpl_got_user_status(acct, id, MW_STATE_OFFLINE, NULL); @@ -1401,15 +1431,23 @@ GaimConnection *gc; GaimAccount *account; guint port; + const char *current_host; pd = mwSession_getClientData(session); gc = pd->gc; account = gaim_connection_get_account(gc); port = gaim_account_get_int(account, MW_KEY_PORT, MW_PLUGIN_DEFAULT_PORT); + current_host = gaim_account_get_string(account, MW_KEY_HOST, + MW_PLUGIN_DEFAULT_HOST); if(gaim_account_get_bool(account, MW_KEY_FORCE, FALSE) || + (! strcmp(current_host, host)) || (gaim_proxy_connect(NULL, account, host, port, connect_cb, pd) == NULL)) { + /* if we're configured to force logins, or if we're being + redirected to the already configured host, or if we couldn't + connect to the new host, we'll force the login instead */ + mwSession_forceLogin(session); } } @@ -3625,7 +3663,7 @@ struct mwGaimPluginData *pd; char *user, *pass, *host; - guint port, client; + guint port; gc = gaim_account_get_connection(account); pd = mwGaimPluginData_new(gc); @@ -3666,14 +3704,29 @@ mwSession_setProperty(pd->session, mwSession_AUTH_USER_ID, user, g_free); mwSession_setProperty(pd->session, mwSession_AUTH_PASSWORD, pass, g_free); - client = mwLogin_MEANWHILE; - if(gaim_account_get_bool(account, MW_KEY_FAKE_IT, FALSE)) - client = mwLogin_BINARY; - - DEBUG_INFO("client id: 0x%04x\n", client); - - mwSession_setProperty(pd->session, mwSession_CLIENT_TYPE_ID, - GUINT_TO_POINTER(client), NULL); + if(gaim_account_get_bool(account, MW_KEY_FAKE_IT, FALSE)) { + guint client, major, minor; + + /* if we're faking the login, let's also fake the version we're + reporting. Let's also allow the actual values to be specified */ + + client = gaim_account_get_int(account, MW_KEY_CLIENT, mwLogin_BINARY); + major = gaim_account_get_int(account, MW_KEY_MAJOR, 0x001e); + minor = gaim_account_get_int(account, MW_KEY_MINOR, 0x001d); + + DEBUG_INFO("client id: 0x%04x\n", client); + DEBUG_INFO("client major: 0x%04x\n", major); + DEBUG_INFO("client minor: 0x%04x\n", minor); + + mwSession_setProperty(pd->session, mwSession_CLIENT_TYPE_ID, + GUINT_TO_POINTER(client), NULL); + + mwSession_setProperty(pd->session, mwSession_CLIENT_VER_MAJOR, + GUINT_TO_POINTER(major), NULL); + + mwSession_setProperty(pd->session, mwSession_CLIENT_VER_MINOR, + GUINT_TO_POINTER(minor), NULL); + } gaim_connection_update_progress(gc, _("Connecting"), 1, MW_CONNECT_STEPS); @@ -3958,8 +4011,9 @@ } -static unsigned int mw_prpl_send_typing(GaimConnection *gc, const char *name, - GaimTypingState state) { +static unsigned int mw_prpl_send_typing(GaimConnection *gc, + const char *name, + GaimTypingState state) { struct mwGaimPluginData *pd; struct mwIdBlock who = { (char *) name, NULL }; @@ -3974,27 +4028,22 @@ conv = mwServiceIm_getConversation(pd->srvc_im, &who); - if(mwConversation_isOpen(conv)) - return ! mwConversation_send(conv, mwImSend_TYPING, t); - - if ((state == GAIM_TYPING) || (state == GAIM_TYPED)) { - /* let's only open a channel for typing, not for not-typing. - Otherwise two users in psychic mode will continually open - conversations to each other, never able to get rid of them, as - when the other person closes, it psychicaly opens again */ - + if(mwConversation_isOpen(conv)) { + mwConversation_send(conv, mwImSend_TYPING, t); + + } else if((state == GAIM_TYPING) || (state == GAIM_TYPED)) { + /* only open a channel for sending typing notification, not for + when typing has stopped. There's no point in re-opening a + channel just to tell someone that this side isn't typing. */ + convo_queue(conv, mwImSend_TYPING, t); - - if(! mwConversation_isPending(conv)) + + if(! mwConversation_isPending(conv)) { mwConversation_open(conv); + } } - /* - * TODO: This should probably be "0." When it's set to 1, the Gaim - * core will call serv_send_typing(gc, who, GAIM_TYPING) once - * every second until the Gaim user stops typing. --KingAnt - */ - return 1; + return 0; } @@ -4031,6 +4080,11 @@ case mwLogin_NOTESBUDDY_4_16: return "Alphaworks NotesBuddy"; + case 0x1305: + case 0x1306: + case 0x1307: + return "Lotus Sametime Connect 7.5"; + case mwLogin_SANITY: return "Sanity"; @@ -4228,19 +4282,28 @@ static void notify_add(GaimConnection *gc, GList *row, void *user_data) { + BuddyAddData *data = user_data; + char *group_name = NULL; + + if (data && data->group) { + group_name = data->group->name; + } + gaim_blist_request_add_buddy(gaim_connection_get_account(gc), - g_list_nth_data(row, 1), NULL, + g_list_nth_data(row, 1), group_name, g_list_nth_data(row, 0)); } static void notify_close(gpointer data) { - ; + if (data) { + g_free(data); + } } static void multi_resolved_query(struct mwResolveResult *result, - GaimConnection *gc) { + GaimConnection *gc, gpointer data) { GList *l; const char *msgA; const char *msgB; @@ -4285,7 +4348,7 @@ msg = g_strdup_printf(msgB, result->name); gaim_notify_searchresults(gc, _("Select User"), - msgA, msg, sres, notify_close, NULL); + msgA, msg, sres, notify_close, data); g_free(msg); } @@ -4296,10 +4359,15 @@ gpointer b) { struct mwResolveResult *res = NULL; - GaimBuddy *buddy = b; + BuddyAddData *data = b; + GaimBuddy *buddy = NULL; GaimConnection *gc; struct mwGaimPluginData *pd; + if (data) { + buddy = data->buddy; + } + gc = gaim_account_get_connection(buddy->account); pd = gc->proto_data; @@ -4316,7 +4384,7 @@ term, better safe then sorry, so let's make sure it's who the user meant to add */ gaim_blist_remove_buddy(buddy); - multi_resolved_query(res, gc); + multi_resolved_query(res, gc, data); } else { @@ -4329,12 +4397,14 @@ buddy_add(pd, buddy); blist_schedule(pd); + + g_free(data); } } else { /* prompt user if more than one match was returned */ gaim_blist_remove_buddy(buddy); - multi_resolved_query(res, gc); + multi_resolved_query(res, gc, data); } return; @@ -4378,6 +4448,12 @@ enum mwResolveFlag flags; guint32 req; + BuddyAddData *data; + + data = g_new0(BuddyAddData, 1); + data->buddy = buddy; + data->group = group; + pd = gc->proto_data; srvc = pd->srvc_resolve; @@ -4391,7 +4467,7 @@ flags = mwResolveFlag_FIRST | mwResolveFlag_USERS; req = mwServiceResolve_resolve(srvc, query, flags, add_buddy_resolved, - buddy, NULL); + data, NULL); g_list_free(query); if(req == SEARCH_ERROR) { @@ -4728,25 +4804,32 @@ static int mw_prpl_chat_send(GaimConnection *gc, int id, const char *message, - GaimMessageFlags flags) { + GaimMessageFlags flags) { struct mwGaimPluginData *pd; struct mwConference *conf; + char *msg; + int ret; pd = gc->proto_data; g_return_val_if_fail(pd != NULL, 0); conf = ID_TO_CONF(pd, id); + msg = gaim_markup_strip_html(message); + if(conf) { - return ! mwConference_sendText(conf, message); + ret = ! mwConference_sendText(conf, message); } else { struct mwPlace *place = ID_TO_PLACE(pd, id); g_return_val_if_fail(place != NULL, 0); - return ! mwPlace_sendText(place, message); + ret = ! mwPlace_sendText(place, message); } + + g_free(msg); + return ret; }