source: protocols/yahoo/yahoo.c @ a880e34

Last change on this file since a880e34 was 05816dd, checked in by dequis <dx@…>, at 2015-02-22T22:44:40Z

coverity: Fix some (harmless?) use-after-free with g_slist_remove()

These were passing a pointer to a variable right after it was g_free()'d

They are most likely harmless as g_slist_remove() probably just needs
the pointer location, but fixing it anyway.

  • Property mode set to 100644
File size: 24.2 KB
RevLine 
[b7d3cc34]1/*
2 * libyahoo2 wrapper to BitlBee
3 *
[0e788f5]4 * Mostly Copyright 2004-2012 Wilmer van der Gaast <wilmer@gaast.net>
[b7d3cc34]5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
[6f10697]18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
[b7d3cc34]19 *
20 */
21
22
23#include <errno.h>
24#include <string.h>
25#include <stdlib.h>
26#include <stdio.h>
27#include <time.h>
28#include <sys/stat.h>
29#include <ctype.h>
30#include "nogaim.h"
31#include "yahoo2.h"
32#include "yahoo2_callbacks.h"
33
34#define BYAHOO_DEFAULT_GROUP "Buddies"
35
36/* A hack to handle removal of buddies not in the group "Buddies" correctly */
[5ebff60]37struct byahoo_buddygroups {
[b7d3cc34]38        char *buddy;
39        char *group;
40};
41
[5ebff60]42struct byahoo_data {
[b7d3cc34]43        int y2_id;
44        int current_status;
45        gboolean logged_in;
46        GSList *buddygroups;
47};
48
[5ebff60]49struct byahoo_input_data {
[b7d3cc34]50        int h;
51        void *d;
52};
53
[5ebff60]54struct byahoo_conf_invitation {
[b7d3cc34]55        char *name;
[0da65d5]56        struct groupchat *c;
[b7d3cc34]57        int yid;
58        YList *members;
[0da65d5]59        struct im_connection *ic;
[b7d3cc34]60};
61
62static GSList *byahoo_inputs = NULL;
63static int byahoo_chat_id = 0;
64
[5ebff60]65static char *byahoo_strip(const char *in)
[b7d3cc34]66{
67        int len;
[5ebff60]68
[717e3bf]69        /* This should get rid of the markup noise at the beginning of the string. */
[5ebff60]70        while (*in) {
71                if (g_strncasecmp(in, "<font", 5) == 0 ||
72                    g_strncasecmp(in, "<fade", 5) == 0 ||
73                    g_strncasecmp(in, "<alt", 4) == 0) {
74                        char *s = strchr(in, '>');
75                        if (!s) {
[b7d3cc34]76                                break;
[5ebff60]77                        }
78
[b7d3cc34]79                        in = s + 1;
[5ebff60]80                } else if (strncmp(in, "\e[", 2) == 0) {
[cfc8d58]81                        const char *s;
[5ebff60]82
83                        for (s = in + 2; *s && *s != 'm'; s++) {
84                                ;
85                        }
86
87                        if (*s != 'm') {
[b7d3cc34]88                                break;
[5ebff60]89                        }
90
[b7d3cc34]91                        in = s + 1;
[5ebff60]92                } else {
[b7d3cc34]93                        break;
94                }
95        }
[5ebff60]96
[717e3bf]97        /* This is supposed to get rid of the noise at the end of the line. */
[5ebff60]98        len = strlen(in);
99        while (len > 0 && (in[len - 1] == '>' || in[len - 1] == 'm')) {
[b7d3cc34]100                int blen = len;
[717e3bf]101                const char *search;
[5ebff60]102
103                if (in[len - 1] == '>') {
[717e3bf]104                        search = "</";
[5ebff60]105                } else {
[717e3bf]106                        search = "\e[";
[5ebff60]107                }
108
[717e3bf]109                len -= 3;
[5ebff60]110                while (len > 0 && strncmp(in + len, search, 2) != 0) {
111                        len--;
112                }
113
114                if (len <= 0 && strncmp(in, search, 2) != 0) {
[b7d3cc34]115                        len = blen;
116                        break;
117                }
118        }
[5ebff60]119
120        return(g_strndup(in, len));
[b7d3cc34]121}
122
[5ebff60]123static void byahoo_init(account_t *acc)
[1febf5c]124{
[5ebff60]125        set_add(&acc->set, "mail_notifications", "false", set_eval_bool, acc);
126
[4049061]127        acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE;
[1febf5c]128}
129
[5ebff60]130static void byahoo_login(account_t *acc)
[b7d3cc34]131{
[5ebff60]132        struct im_connection *ic = imcb_new(acc);
133        struct byahoo_data *yd = ic->proto_data = g_new0(struct byahoo_data, 1);
[6e6b3d7]134        char *s;
[5ebff60]135
[b7d3cc34]136        yd->logged_in = FALSE;
137        yd->current_status = YAHOO_STATUS_AVAILABLE;
[5ebff60]138
139        if ((s = strchr(acc->user, '@')) && g_strcasecmp(s, "@yahoo.com") == 0) {
140                imcb_error(ic, "Your Yahoo! username should just be a username. "
141                           "Do not include any @domain part.");
142        }
143
144        imcb_log(ic, "Connecting");
145        yd->y2_id = yahoo_init(acc->user, acc->pass);
146        yahoo_login(yd->y2_id, yd->current_status);
[b7d3cc34]147}
148
[5ebff60]149static void byahoo_logout(struct im_connection *ic)
[b7d3cc34]150{
[0da65d5]151        struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
[b7d3cc34]152        GSList *l;
[5ebff60]153
154        while (ic->groupchats) {
155                imcb_chat_free(ic->groupchats->data);
156        }
157
158        for (l = yd->buddygroups; l; l = l->next) {
[b7d3cc34]159                struct byahoo_buddygroups *bg = l->data;
[5ebff60]160
161                g_free(bg->buddy);
162                g_free(bg->group);
163                g_free(bg);
[b7d3cc34]164        }
[5ebff60]165        g_slist_free(yd->buddygroups);
166
167        yahoo_logoff(yd->y2_id);
168
169        g_free(yd);
[b7d3cc34]170}
171
[5ebff60]172static void byahoo_get_info(struct im_connection *ic, char *who)
[b7d3cc34]173{
174        /* Just make an URL and let the user fetch the info */
[5ebff60]175        imcb_log(ic, "%s\n%s: %s%s", _("User Info"),
176                 _("For now, fetch yourself"), yahoo_get_profile_url(),
177                 who);
[b7d3cc34]178}
179
[5ebff60]180static int byahoo_buddy_msg(struct im_connection *ic, char *who, char *what, int flags)
[b7d3cc34]181{
[0da65d5]182        struct byahoo_data *yd = ic->proto_data;
[5ebff60]183
184        yahoo_send_im(yd->y2_id, NULL, who, what, 1, 0);
185
[b7d3cc34]186        return 1;
187}
188
[5ebff60]189static int byahoo_send_typing(struct im_connection *ic, char *who, int typing)
[b7d3cc34]190{
[0da65d5]191        struct byahoo_data *yd = ic->proto_data;
[5ebff60]192
193        yahoo_send_typing(yd->y2_id, NULL, who, (typing & OPT_TYPING) != 0);
194
[b7d3cc34]195        return 1;
196}
197
[5ebff60]198static void byahoo_set_away(struct im_connection *ic, char *state, char *msg)
[b7d3cc34]199{
[0da65d5]200        struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
[5ebff60]201
202        if (state && msg == NULL) {
[be915f5]203                /* Use these states only if msg doesn't contain additional
204                   info since away messages are only supported with CUSTOM. */
[5ebff60]205                if (g_strcasecmp(state, "Be Right Back") == 0) {
[b7d3cc34]206                        yd->current_status = YAHOO_STATUS_BRB;
[5ebff60]207                } else if (g_strcasecmp(state, "Busy") == 0) {
[b7d3cc34]208                        yd->current_status = YAHOO_STATUS_BUSY;
[5ebff60]209                } else if (g_strcasecmp(state, "Not At Home") == 0) {
[b7d3cc34]210                        yd->current_status = YAHOO_STATUS_NOTATHOME;
[5ebff60]211                } else if (g_strcasecmp(state, "Not At Desk") == 0) {
[b7d3cc34]212                        yd->current_status = YAHOO_STATUS_NOTATDESK;
[5ebff60]213                } else if (g_strcasecmp(state, "Not In Office") == 0) {
[b7d3cc34]214                        yd->current_status = YAHOO_STATUS_NOTINOFFICE;
[5ebff60]215                } else if (g_strcasecmp(state, "On Phone") == 0) {
[b7d3cc34]216                        yd->current_status = YAHOO_STATUS_ONPHONE;
[5ebff60]217                } else if (g_strcasecmp(state, "On Vacation") == 0) {
[b7d3cc34]218                        yd->current_status = YAHOO_STATUS_ONVACATION;
[5ebff60]219                } else if (g_strcasecmp(state, "Out To Lunch") == 0) {
[b7d3cc34]220                        yd->current_status = YAHOO_STATUS_OUTTOLUNCH;
[5ebff60]221                } else if (g_strcasecmp(state, "Stepped Out") == 0) {
[b7d3cc34]222                        yd->current_status = YAHOO_STATUS_STEPPEDOUT;
[5ebff60]223                } else if (g_strcasecmp(state, "Invisible") == 0) {
[b7d3cc34]224                        yd->current_status = YAHOO_STATUS_INVISIBLE;
[5ebff60]225                } else {
[4049061]226                        yd->current_status = YAHOO_STATUS_CUSTOM;
[5ebff60]227                }
228        } else if (msg) {
[be915f5]229                yd->current_status = YAHOO_STATUS_CUSTOM;
[5ebff60]230        } else {
[b7d3cc34]231                yd->current_status = YAHOO_STATUS_AVAILABLE;
[5ebff60]232        }
233
234        yahoo_set_away(yd->y2_id, yd->current_status, msg, state ? 2 : 0);
[b7d3cc34]235}
236
[5ebff60]237static GList *byahoo_away_states(struct im_connection *ic)
[b7d3cc34]238{
[99c8f13]239        static GList *m = NULL;
[b7d3cc34]240
[5ebff60]241        if (m == NULL) {
242                m = g_list_append(m, "Be Right Back");
243                m = g_list_append(m, "Busy");
244                m = g_list_append(m, "Not At Home");
245                m = g_list_append(m, "Not At Desk");
246                m = g_list_append(m, "Not In Office");
247                m = g_list_append(m, "On Phone");
248                m = g_list_append(m, "On Vacation");
249                m = g_list_append(m, "Out To Lunch");
250                m = g_list_append(m, "Stepped Out");
251                m = g_list_append(m, "Invisible");
252        }
253
[b7d3cc34]254        return m;
255}
256
[5ebff60]257static void byahoo_keepalive(struct im_connection *ic)
[b7d3cc34]258{
[0da65d5]259        struct byahoo_data *yd = ic->proto_data;
[5ebff60]260
261        yahoo_keepalive(yd->y2_id);
[b7d3cc34]262}
263
[5ebff60]264static void byahoo_add_buddy(struct im_connection *ic, char *who, char *group)
[b7d3cc34]265{
[0da65d5]266        struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
[ccc595b]267        bee_user_t *bu;
[5ebff60]268
269        if (group && (bu = bee_user_by_handle(ic->bee, ic, who)) && bu->group) {
[ccc595b]270                GSList *bgl;
[5ebff60]271
[ccc595b]272                /* If the person is in our list already, this is a group change. */
[5ebff60]273                yahoo_change_buddy_group(yd->y2_id, who, bu->group->name, group);
274
[ccc595b]275                /* No idea how often people have people in multiple groups and
276                   BitlBee doesn't currently support this anyway .. but keep
277                   this struct up-to-date for now. */
[5ebff60]278                for (bgl = yd->buddygroups; bgl; bgl = bgl->next) {
[ccc595b]279                        struct byahoo_buddygroups *bg = bgl->data;
[5ebff60]280
281                        if (g_strcasecmp(bg->buddy, who) == 0 &&
282                            g_strcasecmp(bg->group, bu->group->name) == 0) {
283                                g_free(bg->group);
284                                bg->group = g_strdup(group);
[ccc595b]285                        }
286                }
[5ebff60]287        } else {
288                yahoo_add_buddy(yd->y2_id, who, group ? group : BYAHOO_DEFAULT_GROUP, NULL);
[ccc595b]289        }
[b7d3cc34]290}
291
[5ebff60]292static void byahoo_remove_buddy(struct im_connection *ic, char *who, char *group)
[b7d3cc34]293{
[0da65d5]294        struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
[b7d3cc34]295        GSList *bgl;
[5ebff60]296
297        yahoo_remove_buddy(yd->y2_id, who, BYAHOO_DEFAULT_GROUP);
298
299        for (bgl = yd->buddygroups; bgl; bgl = bgl->next) {
[b7d3cc34]300                struct byahoo_buddygroups *bg = bgl->data;
[5ebff60]301
302                if (g_strcasecmp(bg->buddy, who) == 0) {
303                        yahoo_remove_buddy(yd->y2_id, who, bg->group);
304                }
[b7d3cc34]305        }
306}
307
[5ebff60]308static void byahoo_chat_msg(struct groupchat *c, char *message, int flags)
[b7d3cc34]309{
[0da65d5]310        struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data;
[5ebff60]311
312        yahoo_conference_message(yd->y2_id, NULL, c->data, c->title, message, 1);
[b7d3cc34]313}
314
[5ebff60]315static void byahoo_chat_invite(struct groupchat *c, char *who, char *msg)
[b7d3cc34]316{
[0da65d5]317        struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data;
[5ebff60]318
319        yahoo_conference_invite(yd->y2_id, NULL, c->data, c->title, msg ? msg : "");
[b7d3cc34]320}
321
[5ebff60]322static void byahoo_chat_leave(struct groupchat *c)
[b7d3cc34]323{
[0da65d5]324        struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data;
[5ebff60]325
326        yahoo_conference_logoff(yd->y2_id, NULL, c->data, c->title);
327        imcb_chat_free(c);
[b7d3cc34]328}
329
[5ebff60]330static struct groupchat *byahoo_chat_with(struct im_connection *ic, char *who)
[b7d3cc34]331{
[0da65d5]332        struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
333        struct groupchat *c;
[b7d3cc34]334        char *roomname;
335        YList *members;
[5ebff60]336
337        roomname = g_strdup_printf("%s-Bee-%d", ic->acc->user, byahoo_chat_id);
338
339        c = imcb_chat_new(ic, roomname);
340        imcb_chat_add_buddy(c, ic->acc->user);
341
[b7d3cc34]342        /* FIXME: Free this thing when the chat's destroyed. We can't *always*
343                  do this because it's not always created here. */
[5ebff60]344        c->data = members = g_new0(YList, 1);
345        members->data = g_strdup(who);
346
347        yahoo_conference_invite(yd->y2_id, NULL, members, roomname, "Please join my groupchat...");
348
349        g_free(roomname);
350
[fa29d093]351        return c;
[b7d3cc34]352}
353
[5ebff60]354static void byahoo_auth_allow(struct im_connection *ic, const char *who)
[ba16895]355{
356        struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
[5ebff60]357
358        yahoo_confirm_buddy(yd->y2_id, who, 0, "");
[ba16895]359}
360
[5ebff60]361static void byahoo_auth_deny(struct im_connection *ic, const char *who)
[ba16895]362{
363        struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
[5ebff60]364
365        yahoo_confirm_buddy(yd->y2_id, who, 1, "");
[ba16895]366}
367
[5ebff60]368void byahoo_initmodule()
[b7d3cc34]369{
[7b23afd]370        struct prpl *ret = g_new0(struct prpl, 1);
[5ebff60]371
[7b23afd]372        ret->name = "yahoo";
[5ebff60]373        ret->mms = 832;       /* this guess taken from libotr UPGRADING file */
[1febf5c]374        ret->init = byahoo_init;
[5ebff60]375
[b7d3cc34]376        ret->login = byahoo_login;
[0da65d5]377        ret->keepalive = byahoo_keepalive;
378        ret->logout = byahoo_logout;
[5ebff60]379
[f6c963b]380        ret->buddy_msg = byahoo_buddy_msg;
[b7d3cc34]381        ret->get_info = byahoo_get_info;
382        ret->away_states = byahoo_away_states;
383        ret->set_away = byahoo_set_away;
384        ret->add_buddy = byahoo_add_buddy;
385        ret->remove_buddy = byahoo_remove_buddy;
[7b23afd]386        ret->send_typing = byahoo_send_typing;
[5ebff60]387
[f6c963b]388        ret->chat_msg = byahoo_chat_msg;
[b7d3cc34]389        ret->chat_invite = byahoo_chat_invite;
390        ret->chat_leave = byahoo_chat_leave;
[0da65d5]391        ret->chat_with = byahoo_chat_with;
[5b52a48]392
393        ret->handle_cmp = g_strcasecmp;
[5ebff60]394
[ba16895]395        ret->auth_allow = byahoo_auth_allow;
396        ret->auth_deny = byahoo_auth_deny;
[5ebff60]397
[7b23afd]398        register_protocol(ret);
[b7d3cc34]399}
400
[5ebff60]401static struct im_connection *byahoo_get_ic_by_id(int id)
[b7d3cc34]402{
403        GSList *l;
[0da65d5]404        struct im_connection *ic;
[b7d3cc34]405        struct byahoo_data *yd;
[5ebff60]406
407        for (l = get_connections(); l; l = l->next) {
[0da65d5]408                ic = l->data;
409                yd = ic->proto_data;
[5ebff60]410
411                if (strcmp(ic->acc->prpl->name, "yahoo") == 0 && yd->y2_id == id) {
412                        return(ic);
413                }
[b7d3cc34]414        }
[5ebff60]415
416        return(NULL);
[b7d3cc34]417}
418
419
420/* Now it's callback time! */
421
[5ebff60]422struct byahoo_connect_callback_data {
[b7d3cc34]423        int fd;
424        yahoo_connect_callback callback;
425        gpointer data;
426        int id;
427};
428
[5ebff60]429void byahoo_connect_callback(gpointer data, gint source, b_input_condition cond)
[b7d3cc34]430{
431        struct byahoo_connect_callback_data *d = data;
[5ebff60]432
433        if (!byahoo_get_ic_by_id(d->id)) {
434                g_free(d);
[b7d3cc34]435                return;
436        }
[5ebff60]437
438        d->callback(NULL + d->fd, 0, d->data);
439        g_free(d);
[b7d3cc34]440}
441
[5ebff60]442struct byahoo_read_ready_data {
[b7d3cc34]443        int id;
444        int fd;
445        int tag;
446        gpointer data;
447};
448
[5ebff60]449gboolean byahoo_read_ready_callback(gpointer data, gint source, b_input_condition cond)
[b7d3cc34]450{
451        struct byahoo_read_ready_data *d = data;
[5ebff60]452
453        if (!byahoo_get_ic_by_id(d->id)) {
[b7d3cc34]454                /* WTF doesn't libyahoo clean this up? */
[ba9edaa]455                return FALSE;
[5ebff60]456        }
457
458        yahoo_read_ready(d->id, NULL + d->fd, d->data);
459
[7a685f1]460        return TRUE;
[b7d3cc34]461}
462
[5ebff60]463struct byahoo_write_ready_data {
[b7d3cc34]464        int id;
465        int fd;
466        int tag;
467        gpointer data;
468};
469
[5ebff60]470gboolean byahoo_write_ready_callback(gpointer data, gint source, b_input_condition cond)
[b7d3cc34]471{
472        struct byahoo_write_ready_data *d = data;
[5ebff60]473
474        return yahoo_write_ready(d->id, NULL + d->fd, d->data);
[b7d3cc34]475}
476
[5ebff60]477void ext_yahoo_login_response(int id, int succ, const char *url)
[b7d3cc34]478{
[5ebff60]479        struct im_connection *ic = byahoo_get_ic_by_id(id);
[b7d3cc34]480        struct byahoo_data *yd = NULL;
[5ebff60]481
482        if (ic == NULL) {
[b7d3cc34]483                /* libyahoo2 seems to call this one twice when something
484                   went wrong sometimes. Don't know why. Because we clean
485                   up the connection on the first failure, the second
486                   should be ignored. */
[5ebff60]487
[b7d3cc34]488                return;
489        }
[5ebff60]490
[0da65d5]491        yd = (struct byahoo_data *) ic->proto_data;
[5ebff60]492
493        if (succ == YAHOO_LOGIN_OK) {
494                imcb_connected(ic);
495
[b7d3cc34]496                yd->logged_in = TRUE;
[5ebff60]497        } else {
[b7d3cc34]498                char *errstr;
[c495217]499                int allow_reconnect = FALSE;
[5ebff60]500
[b7d3cc34]501                yd->logged_in = FALSE;
[5ebff60]502
503                if (succ == YAHOO_LOGIN_UNAME) {
[b7d3cc34]504                        errstr = "Incorrect Yahoo! username";
[5ebff60]505                } else if (succ == YAHOO_LOGIN_PASSWD) {
[b7d3cc34]506                        errstr = "Incorrect Yahoo! password";
[5ebff60]507                } else if (succ == YAHOO_LOGIN_LOCK) {
[b7d3cc34]508                        errstr = "Yahoo! account locked";
[5ebff60]509                } else if (succ == 1236) {
[c495217]510                        errstr = "Yahoo! account locked or machine temporarily banned";
[5ebff60]511                } else if (succ == YAHOO_LOGIN_DUPL) {
[b7d3cc34]512                        errstr = "Logged in on a different machine or device";
[5ebff60]513                } else if (succ == YAHOO_LOGIN_SOCK) {
[b7d3cc34]514                        errstr = "Socket problem";
[c495217]515                        allow_reconnect = TRUE;
[5ebff60]516                } else {
[b7d3cc34]517                        errstr = "Unknown error";
[5ebff60]518                }
519
520                if (url && *url) {
521                        imcb_error(ic, "Error %d (%s). See %s for more information.", succ, errstr, url);
522                } else {
523                        imcb_error(ic, "Error %d (%s)", succ, errstr);
524                }
525
526                imc_logout(ic, allow_reconnect);
[b7d3cc34]527        }
528}
529
[5ebff60]530void ext_yahoo_got_buddies(int id, YList *buds)
[b7d3cc34]531{
[5ebff60]532        struct im_connection *ic = byahoo_get_ic_by_id(id);
[0da65d5]533        struct byahoo_data *yd = ic->proto_data;
[b7d3cc34]534        YList *bl = buds;
[5ebff60]535
536        while (bl) {
[b7d3cc34]537                struct yahoo_buddy *b = bl->data;
538                struct byahoo_buddygroups *bg;
[5ebff60]539
540                if (strcmp(b->group, BYAHOO_DEFAULT_GROUP) != 0) {
541                        bg = g_new0(struct byahoo_buddygroups, 1);
542
543                        bg->buddy = g_strdup(b->id);
544                        bg->group = g_strdup(b->group);
545                        yd->buddygroups = g_slist_append(yd->buddygroups, bg);
[b7d3cc34]546                }
[5ebff60]547
548                imcb_add_buddy(ic, b->id, b->group);
549                imcb_rename_buddy(ic, b->id, b->real_name);
550
[b7d3cc34]551                bl = bl->next;
552        }
553}
554
[5ebff60]555void ext_yahoo_got_identities(int id, YList *ids)
[b7d3cc34]556{
557}
558
[5ebff60]559void ext_yahoo_got_cookies(int id)
[b7d3cc34]560{
561}
562
[5ebff60]563void ext_yahoo_status_changed(int id, const char *who, int stat, const char *msg, int away, int idle, int mobile)
[b7d3cc34]564{
[5ebff60]565        struct im_connection *ic = byahoo_get_ic_by_id(id);
[6bbb939]566        char *state_string = NULL;
567        int flags = OPT_LOGGED_IN;
[5ebff60]568
569        if (away) {
[6bbb939]570                flags |= OPT_AWAY;
[5ebff60]571        }
572        if (mobile) {
[c00dd71]573                flags |= OPT_MOBILE;
[5ebff60]574        }
575
576        switch (stat) {
[6bbb939]577        case YAHOO_STATUS_BRB:
578                state_string = "Be Right Back";
579                break;
580        case YAHOO_STATUS_BUSY:
581                state_string = "Busy";
582                break;
583        case YAHOO_STATUS_NOTATHOME:
584                state_string = "Not At Home";
585                break;
586        case YAHOO_STATUS_NOTATDESK:
587                state_string = "Not At Desk";
588                break;
589        case YAHOO_STATUS_NOTINOFFICE:
590                state_string = "Not In Office";
591                break;
592        case YAHOO_STATUS_ONPHONE:
593                state_string = "On Phone";
594                break;
595        case YAHOO_STATUS_ONVACATION:
596                state_string = "On Vacation";
597                break;
598        case YAHOO_STATUS_OUTTOLUNCH:
599                state_string = "Out To Lunch";
600                break;
601        case YAHOO_STATUS_STEPPEDOUT:
602                state_string = "Stepped Out";
603                break;
604        case YAHOO_STATUS_INVISIBLE:
605                state_string = "Invisible";
606                break;
607        case YAHOO_STATUS_CUSTOM:
608                state_string = "Away";
609                break;
610        case YAHOO_STATUS_IDLE:
611                state_string = "Idle";
612                break;
613        case YAHOO_STATUS_OFFLINE:
614                state_string = "Offline";
615                flags = 0;
616                break;
617        }
[5ebff60]618
619        imcb_buddy_status(ic, who, flags, state_string, msg);
620
621        if (stat == YAHOO_STATUS_IDLE) {
622                imcb_buddy_times(ic, who, 0, idle);
623        }
[b7d3cc34]624}
625
[5ebff60]626void ext_yahoo_got_buzz(int id, const char *me, const char *who, long tm)
[9034ba0]627{
628}
629
[5ebff60]630void ext_yahoo_got_im(int id, const char *me, const char *who, const char *msg, long tm, int stat, int utf8)
[b7d3cc34]631{
[5ebff60]632        struct im_connection *ic = byahoo_get_ic_by_id(id);
[ac4adf9]633        char *m;
[5ebff60]634
635        if (msg) {
636                m = byahoo_strip(msg);
637                imcb_buddy_msg(ic, (char *) who, (char *) m, 0, 0);
638                g_free(m);
[ac4adf9]639        }
[b7d3cc34]640}
641
[5ebff60]642void ext_yahoo_got_file(int id, const char *ignored, const char *who, const char *msg,
643                        const char *fname, unsigned long fesize, char *trid)
[b7d3cc34]644{
[5ebff60]645        struct im_connection *ic = byahoo_get_ic_by_id(id);
646
647        imcb_log(ic, "Got a file transfer (file = %s) from %s. Ignoring for now due to lack of support.", fname, who);
[b7d3cc34]648}
649
[5ebff60]650void ext_yahoo_got_ft_data(int id, const unsigned char *in, int len, void *data)
[9034ba0]651{
652}
653
[5ebff60]654void ext_yahoo_file_transfer_done(int id, int result, void *data)
[9034ba0]655{
656}
657
[5ebff60]658void ext_yahoo_typing_notify(int id, const char *ignored, const char *who, int stat)
[b7d3cc34]659{
[5ebff60]660        struct im_connection *ic = byahoo_get_ic_by_id(id);
661
662        if (stat == 1) {
663                imcb_buddy_typing(ic, (char *) who, OPT_TYPING);
664        } else {
665                imcb_buddy_typing(ic, (char *) who, 0);
666        }
[b7d3cc34]667}
668
[5ebff60]669void ext_yahoo_system_message(int id, const char *me, const char *who, const char *msg)
[b7d3cc34]670{
[5ebff60]671        struct im_connection *ic = byahoo_get_ic_by_id(id);
672
673        imcb_log(ic, "Yahoo! system message: %s", msg);
[b7d3cc34]674}
675
[5ebff60]676void ext_yahoo_webcam_invite(int id, const char *ignored, const char *from)
[b7d3cc34]677{
[5ebff60]678        struct im_connection *ic = byahoo_get_ic_by_id(id);
679
680        imcb_log(ic, "Got a webcam invitation from %s. IRC+webcams is a no-no though...", from);
[b7d3cc34]681}
682
[5ebff60]683void ext_yahoo_error(int id, const char *err, int fatal, int num)
[b7d3cc34]684{
[5ebff60]685        struct im_connection *ic = byahoo_get_ic_by_id(id);
686
687        imcb_error(ic, "%s", err);
[b7d3cc34]688}
689
690/* TODO: Clear up the mess of inp and d structures */
[5ebff60]691int ext_yahoo_add_handler(int id, void *fd_, yahoo_input_condition cond, void *data)
[b7d3cc34]692{
[5ebff60]693        struct byahoo_input_data *inp = g_new0(struct byahoo_input_data, 1);
[bce2014]694        int fd = (long) fd_;
[5ebff60]695
696        if (cond == YAHOO_INPUT_READ) {
697                struct byahoo_read_ready_data *d = g_new0(struct byahoo_read_ready_data, 1);
698
[b7d3cc34]699                d->id = id;
700                d->fd = fd;
701                d->data = data;
[5ebff60]702
[b7d3cc34]703                inp->d = d;
[5ebff60]704                d->tag = inp->h = b_input_add(fd, B_EV_IO_READ, (b_event_handler) byahoo_read_ready_callback,
705                                              (gpointer) d);
706        } else if (cond == YAHOO_INPUT_WRITE) {
707                struct byahoo_write_ready_data *d = g_new0(struct byahoo_write_ready_data, 1);
708
[b7d3cc34]709                d->id = id;
710                d->fd = fd;
711                d->data = data;
[5ebff60]712
[b7d3cc34]713                inp->d = d;
[5ebff60]714                d->tag = inp->h =
715                                 b_input_add(fd, B_EV_IO_WRITE, (b_event_handler) byahoo_write_ready_callback,
716                                             (gpointer) d);
717        } else {
718                g_free(inp);
[9034ba0]719                return -1;
[b7d3cc34]720                /* Panic... */
721        }
[5ebff60]722
723        byahoo_inputs = g_slist_append(byahoo_inputs, inp);
[9034ba0]724        return inp->h;
[b7d3cc34]725}
726
[5ebff60]727void ext_yahoo_remove_handler(int id, int tag)
[b7d3cc34]728{
729        struct byahoo_input_data *inp;
730        GSList *l = byahoo_inputs;
[5ebff60]731
732        while (l) {
[b7d3cc34]733                inp = l->data;
[5ebff60]734                if (inp->h == tag) {
[05816dd]735                        byahoo_inputs = g_slist_remove(byahoo_inputs, inp);
[5ebff60]736                        g_free(inp->d);
737                        g_free(inp);
[b7d3cc34]738                        break;
739                }
740                l = l->next;
741        }
[5ebff60]742
743        b_event_remove(tag);
[b7d3cc34]744}
745
[5ebff60]746int ext_yahoo_connect_async(int id, const char *host, int port, yahoo_connect_callback callback, void *data,
747                            int use_ssl)
[b7d3cc34]748{
749        struct byahoo_connect_callback_data *d;
750        int fd;
[5ebff60]751
752        d = g_new0(struct byahoo_connect_callback_data, 1);
753        if ((fd = proxy_connect(host, port, (b_event_handler) byahoo_connect_callback, (gpointer) d)) < 0) {
754                g_free(d);
755                return(fd);
[b7d3cc34]756        }
757        d->fd = fd;
758        d->callback = callback;
759        d->data = data;
760        d->id = id;
[5ebff60]761
[9034ba0]762        return fd;
[b7d3cc34]763}
764
[5ebff60]765char *ext_yahoo_get_ip_addr(const char *domain)
[b7d3cc34]766{
[9034ba0]767        return NULL;
768}
[b7d3cc34]769
[5ebff60]770int ext_yahoo_write(void *fd, char *buf, int len)
[9034ba0]771{
[5ebff60]772        return write((long) fd, buf, len);
[9034ba0]773}
[b7d3cc34]774
[5ebff60]775int ext_yahoo_read(void *fd, char *buf, int len)
[9034ba0]776{
[5ebff60]777        return read((long) fd, buf, len);
[9034ba0]778}
[b7d3cc34]779
[5ebff60]780void ext_yahoo_close(void *fd)
[9034ba0]781{
[5ebff60]782        close((long) fd);
[9034ba0]783}
784
[5ebff60]785void ext_yahoo_got_buddy_change_group(int id, const char *me, const char *who,
786                                      const char *old_group, const char *new_group)
[9034ba0]787{
[5ebff60]788        struct im_connection *ic = byahoo_get_ic_by_id(id);
789
790        imcb_add_buddy(ic, who, new_group);
[ccc595b]791}
[b7d3cc34]792
[5ebff60]793static void byahoo_accept_conf(void *data)
[b7d3cc34]794{
[9143aeb]795        struct byahoo_conf_invitation *inv = data;
[f7d12f7]796        struct groupchat *b = NULL;
[eaaa986]797        GSList *l;
[5ebff60]798
799        for (l = inv->ic->groupchats; l; l = l->next) {
[eaaa986]800                b = l->data;
[5ebff60]801                if (b == inv->c) {
[2bebe15]802                        break;
[5ebff60]803                }
[eaaa986]804        }
[5ebff60]805
806        if (b != NULL) {
807                yahoo_conference_logon(inv->yid, NULL, inv->members, inv->name);
808                imcb_chat_add_buddy(inv->c, inv->ic->acc->user);
809        } else {
810                imcb_log(inv->ic, "Duplicate/corrupted invitation to `%s'.", inv->name);
[2bebe15]811        }
[5ebff60]812
813        g_free(inv->name);
814        g_free(inv);
[b7d3cc34]815}
816
[5ebff60]817static void byahoo_reject_conf(void *data)
[b7d3cc34]818{
[9143aeb]819        struct byahoo_conf_invitation *inv = data;
[5ebff60]820
821        yahoo_conference_decline(inv->yid, NULL, inv->members, inv->name, "User rejected groupchat");
822        imcb_chat_free(inv->c);
823        g_free(inv->name);
824        g_free(inv);
[b7d3cc34]825}
826
[5ebff60]827void ext_yahoo_got_conf_invite(int id, const char *ignored,
828                               const char *who, const char *room, const char *msg, YList *members)
[b7d3cc34]829{
[5ebff60]830        struct im_connection *ic = byahoo_get_ic_by_id(id);
[b7d3cc34]831        struct byahoo_conf_invitation *inv;
832        char txt[1024];
833        YList *m;
[5ebff60]834
835        if (g_strcasecmp(who, ic->acc->user) == 0) {
[aa7ce1b]836                /* WTF, Yahoo! seems to echo these now? */
837                return;
[5ebff60]838        }
839
840        inv = g_malloc(sizeof(struct byahoo_conf_invitation));
841        memset(inv, 0, sizeof(struct byahoo_conf_invitation));
842        inv->name = g_strdup(room);
843        inv->c = imcb_chat_new(ic, (char *) room);
[b7d3cc34]844        inv->c->data = members;
845        inv->yid = id;
846        inv->members = members;
[0da65d5]847        inv->ic = ic;
[5ebff60]848
849        for (m = members; m; m = m->next) {
850                if (g_strcasecmp(m->data, ic->acc->user) != 0) {
851                        imcb_chat_add_buddy(inv->c, m->data);
852                }
853        }
854
855        g_snprintf(txt, 1024, "Got an invitation to chatroom %s from %s: %s", room, who, msg);
856
857        imcb_ask(ic, txt, inv, byahoo_accept_conf, byahoo_reject_conf);
[b7d3cc34]858}
859
[5ebff60]860void ext_yahoo_conf_userdecline(int id, const char *ignored, const char *who, const char *room, const char *msg)
[b7d3cc34]861{
[5ebff60]862        struct im_connection *ic = byahoo_get_ic_by_id(id);
863
864        imcb_log(ic, "Invite to chatroom %s rejected by %s: %s", room, who, msg);
[b7d3cc34]865}
866
[5ebff60]867void ext_yahoo_conf_userjoin(int id, const char *ignored, const char *who, const char *room)
[b7d3cc34]868{
[5ebff60]869        struct im_connection *ic = byahoo_get_ic_by_id(id);
870        struct groupchat *c = bee_chat_by_title(ic->bee, ic, room);
871
872        if (c) {
873                imcb_chat_add_buddy(c, (char *) who);
874        }
[b7d3cc34]875}
876
[5ebff60]877void ext_yahoo_conf_userleave(int id, const char *ignored, const char *who, const char *room)
[cfc8d58]878
[b7d3cc34]879{
[5ebff60]880        struct im_connection *ic = byahoo_get_ic_by_id(id);
881        struct groupchat *c = bee_chat_by_title(ic->bee, ic, room);
882
883        if (c) {
884                imcb_chat_remove_buddy(c, (char *) who, "");
885        }
[b7d3cc34]886}
887
[5ebff60]888void ext_yahoo_conf_message(int id, const char *ignored, const char *who, const char *room, const char *msg, int utf8)
[b7d3cc34]889{
[5ebff60]890        struct im_connection *ic = byahoo_get_ic_by_id(id);
891        char *m = byahoo_strip(msg);
892        struct groupchat *c = bee_chat_by_title(ic->bee, ic, room);
893
894        if (c) {
895                imcb_chat_msg(c, (char *) who, (char *) m, 0, 0);
896        }
897        g_free(m);
[b7d3cc34]898}
899
[5ebff60]900void ext_yahoo_chat_cat_xml(int id, const char *xml)
[b7d3cc34]901{
902}
903
[5ebff60]904void ext_yahoo_chat_join(int id, const char *who, const char *room, const char *topic, YList *members, void *fd)
[b7d3cc34]905{
906}
907
[5ebff60]908void ext_yahoo_chat_userjoin(int id, const char *me, const char *room, struct yahoo_chat_member *who)
[b7d3cc34]909{
[cfc8d58]910        free(who->id);
911        free(who->alias);
912        free(who->location);
[5ebff60]913        free(who);
[b7d3cc34]914}
915
[5ebff60]916void ext_yahoo_chat_userleave(int id, const char *me, const char *room, const char *who)
[b7d3cc34]917{
918}
919
[5ebff60]920void ext_yahoo_chat_message(int id, const char *me, const char *who, const char *room, const char *msg, int msgtype,
921                            int utf8)
[b7d3cc34]922{
923}
924
[5ebff60]925void ext_yahoo_chat_yahoologout(int id, const char *me)
[b7d3cc34]926{
927}
928
[5ebff60]929void ext_yahoo_chat_yahooerror(int id, const char *me)
[b7d3cc34]930{
931}
932
[5ebff60]933void ext_yahoo_contact_added(int id, const char *myid, const char *who, const char *msg)
[b7d3cc34]934{
[5ebff60]935        struct im_connection *ic = byahoo_get_ic_by_id(id);
936
937        imcb_ask_auth(ic, who, msg);
[b7d3cc34]938}
939
[5ebff60]940void ext_yahoo_rejected(int id, const char *who, const char *msg)
[b7d3cc34]941{
942}
943
[5ebff60]944void ext_yahoo_game_notify(int id, const char *me, const char *who, int stat, const char *msg)
[b7d3cc34]945{
946}
947
[5ebff60]948void ext_yahoo_mail_notify(int id, const char *from, const char *subj, int cnt)
[b7d3cc34]949{
[5ebff60]950        struct im_connection *ic = byahoo_get_ic_by_id(id);
951
952        if (!set_getbool(&ic->acc->set, "mail_notifications")) {
[1febf5c]953                ; /* The user doesn't care. */
[5ebff60]954        } else if (from && subj) {
955                imcb_log(ic, "Received e-mail message from %s with subject `%s'", from, subj);
956        } else if (cnt > 0) {
957                imcb_log(ic, "Received %d new e-mails", cnt);
958        }
[b7d3cc34]959}
960
[5ebff60]961void ext_yahoo_webcam_invite_reply(int id, const char *me, const char *from, int accept)
[b7d3cc34]962{
963}
964
[5ebff60]965void ext_yahoo_webcam_closed(int id, const char *who, int reason)
[b7d3cc34]966{
967}
968
[5ebff60]969void ext_yahoo_got_search_result(int id, int found, int start, int total, YList *contacts)
[b7d3cc34]970{
971}
972
[5ebff60]973void ext_yahoo_webcam_viewer(int id, const char *who, int connect)
[b7d3cc34]974{
975}
976
[5ebff60]977void ext_yahoo_webcam_data_request(int id, int send)
[b7d3cc34]978{
979}
980
[5ebff60]981int ext_yahoo_log(const char *fmt, ...)
[b7d3cc34]982{
[5ebff60]983        return(0);
[b7d3cc34]984}
985
[5ebff60]986void ext_yahoo_got_webcam_image(int id, const char * who, const unsigned char *image, unsigned int image_size,
987                                unsigned int real_size, unsigned int timestamp)
[b7d3cc34]988{
989}
[cfc8d58]990
[5ebff60]991void ext_yahoo_got_ping(int id, const char *msg)
[cfc8d58]992{
993}
994
[5ebff60]995void ext_yahoo_got_buddyicon(int id, const char *me, const char *who, const char *url, int checksum)
996{
997}
998void ext_yahoo_got_buddyicon_checksum(int id, const char *me, const char *who, int checksum)
999{
1000}
[cfc8d58]1001
[5ebff60]1002void ext_yahoo_got_buddyicon_request(int id, const char *me, const char *who)
1003{
1004}
1005void ext_yahoo_buddyicon_uploaded(int id, const char *url)
1006{
1007}
Note: See TracBrowser for help on using the repository browser.