source: protocols/yahoo/yahoo.c @ 80c2f3c

Last change on this file since 80c2f3c was 2b0c05c, checked in by dequis <dx@…>, at 2015-10-21T09:50:08Z

yahoo: call callback on connect error to fix memleak

Passing NULL as the "fd" and 0 as the error. The callback is
yahoo_connected() in libyahoo2.c, and with those parameters all it does
is freeing the data parameter.

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