source: protocols/yahoo/yahoo.c @ 7320610

Last change on this file since 7320610 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
Line 
1/*
2 * libyahoo2 wrapper to BitlBee
3 *
4 * Mostly Copyright 2004-2012 Wilmer van der Gaast <wilmer@gaast.net>
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
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
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 */
37struct byahoo_buddygroups {
38        char *buddy;
39        char *group;
40};
41
42struct byahoo_data {
43        int y2_id;
44        int current_status;
45        gboolean logged_in;
46        GSList *buddygroups;
47};
48
49struct byahoo_input_data {
50        int h;
51        void *d;
52};
53
54struct byahoo_conf_invitation {
55        char *name;
56        struct groupchat *c;
57        int yid;
58        YList *members;
59        struct im_connection *ic;
60};
61
62static GSList *byahoo_inputs = NULL;
63static int byahoo_chat_id = 0;
64
65static char *byahoo_strip(const char *in)
66{
67        int len;
68
69        /* This should get rid of the markup noise at the beginning of the string. */
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) {
76                                break;
77                        }
78
79                        in = s + 1;
80                } else if (strncmp(in, "\e[", 2) == 0) {
81                        const char *s;
82
83                        for (s = in + 2; *s && *s != 'm'; s++) {
84                                ;
85                        }
86
87                        if (*s != 'm') {
88                                break;
89                        }
90
91                        in = s + 1;
92                } else {
93                        break;
94                }
95        }
96
97        /* This is supposed to get rid of the noise at the end of the line. */
98        len = strlen(in);
99        while (len > 0 && (in[len - 1] == '>' || in[len - 1] == 'm')) {
100                int blen = len;
101                const char *search;
102
103                if (in[len - 1] == '>') {
104                        search = "</";
105                } else {
106                        search = "\e[";
107                }
108
109                len -= 3;
110                while (len > 0 && strncmp(in + len, search, 2) != 0) {
111                        len--;
112                }
113
114                if (len <= 0 && strncmp(in, search, 2) != 0) {
115                        len = blen;
116                        break;
117                }
118        }
119
120        return(g_strndup(in, len));
121}
122
123static void byahoo_init(account_t *acc)
124{
125        set_add(&acc->set, "mail_notifications", "false", set_eval_bool, acc);
126
127        acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE;
128}
129
130static void byahoo_login(account_t *acc)
131{
132        struct im_connection *ic = imcb_new(acc);
133        struct byahoo_data *yd = ic->proto_data = g_new0(struct byahoo_data, 1);
134        char *s;
135
136        yd->logged_in = FALSE;
137        yd->current_status = YAHOO_STATUS_AVAILABLE;
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);
147}
148
149static void byahoo_logout(struct im_connection *ic)
150{
151        struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
152        GSList *l;
153
154        while (ic->groupchats) {
155                imcb_chat_free(ic->groupchats->data);
156        }
157
158        for (l = yd->buddygroups; l; l = l->next) {
159                struct byahoo_buddygroups *bg = l->data;
160
161                g_free(bg->buddy);
162                g_free(bg->group);
163                g_free(bg);
164        }
165        g_slist_free(yd->buddygroups);
166
167        yahoo_logoff(yd->y2_id);
168
169        g_free(yd);
170}
171
172static void byahoo_get_info(struct im_connection *ic, char *who)
173{
174        /* Just make an URL and let the user fetch the info */
175        imcb_log(ic, "%s\n%s: %s%s", _("User Info"),
176                 _("For now, fetch yourself"), yahoo_get_profile_url(),
177                 who);
178}
179
180static int byahoo_buddy_msg(struct im_connection *ic, char *who, char *what, int flags)
181{
182        struct byahoo_data *yd = ic->proto_data;
183
184        yahoo_send_im(yd->y2_id, NULL, who, what, 1, 0);
185
186        return 1;
187}
188
189static int byahoo_send_typing(struct im_connection *ic, char *who, int typing)
190{
191        struct byahoo_data *yd = ic->proto_data;
192
193        yahoo_send_typing(yd->y2_id, NULL, who, (typing & OPT_TYPING) != 0);
194
195        return 1;
196}
197
198static void byahoo_set_away(struct im_connection *ic, char *state, char *msg)
199{
200        struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
201
202        if (state && msg == NULL) {
203                /* Use these states only if msg doesn't contain additional
204                   info since away messages are only supported with CUSTOM. */
205                if (g_strcasecmp(state, "Be Right Back") == 0) {
206                        yd->current_status = YAHOO_STATUS_BRB;
207                } else if (g_strcasecmp(state, "Busy") == 0) {
208                        yd->current_status = YAHOO_STATUS_BUSY;
209                } else if (g_strcasecmp(state, "Not At Home") == 0) {
210                        yd->current_status = YAHOO_STATUS_NOTATHOME;
211                } else if (g_strcasecmp(state, "Not At Desk") == 0) {
212                        yd->current_status = YAHOO_STATUS_NOTATDESK;
213                } else if (g_strcasecmp(state, "Not In Office") == 0) {
214                        yd->current_status = YAHOO_STATUS_NOTINOFFICE;
215                } else if (g_strcasecmp(state, "On Phone") == 0) {
216                        yd->current_status = YAHOO_STATUS_ONPHONE;
217                } else if (g_strcasecmp(state, "On Vacation") == 0) {
218                        yd->current_status = YAHOO_STATUS_ONVACATION;
219                } else if (g_strcasecmp(state, "Out To Lunch") == 0) {
220                        yd->current_status = YAHOO_STATUS_OUTTOLUNCH;
221                } else if (g_strcasecmp(state, "Stepped Out") == 0) {
222                        yd->current_status = YAHOO_STATUS_STEPPEDOUT;
223                } else if (g_strcasecmp(state, "Invisible") == 0) {
224                        yd->current_status = YAHOO_STATUS_INVISIBLE;
225                } else {
226                        yd->current_status = YAHOO_STATUS_CUSTOM;
227                }
228        } else if (msg) {
229                yd->current_status = YAHOO_STATUS_CUSTOM;
230        } else {
231                yd->current_status = YAHOO_STATUS_AVAILABLE;
232        }
233
234        yahoo_set_away(yd->y2_id, yd->current_status, msg, state ? 2 : 0);
235}
236
237static GList *byahoo_away_states(struct im_connection *ic)
238{
239        static GList *m = NULL;
240
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
254        return m;
255}
256
257static void byahoo_keepalive(struct im_connection *ic)
258{
259        struct byahoo_data *yd = ic->proto_data;
260
261        yahoo_keepalive(yd->y2_id);
262}
263
264static void byahoo_add_buddy(struct im_connection *ic, char *who, char *group)
265{
266        struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
267        bee_user_t *bu;
268
269        if (group && (bu = bee_user_by_handle(ic->bee, ic, who)) && bu->group) {
270                GSList *bgl;
271
272                /* If the person is in our list already, this is a group change. */
273                yahoo_change_buddy_group(yd->y2_id, who, bu->group->name, group);
274
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. */
278                for (bgl = yd->buddygroups; bgl; bgl = bgl->next) {
279                        struct byahoo_buddygroups *bg = bgl->data;
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);
285                        }
286                }
287        } else {
288                yahoo_add_buddy(yd->y2_id, who, group ? group : BYAHOO_DEFAULT_GROUP, NULL);
289        }
290}
291
292static void byahoo_remove_buddy(struct im_connection *ic, char *who, char *group)
293{
294        struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
295        GSList *bgl;
296
297        yahoo_remove_buddy(yd->y2_id, who, BYAHOO_DEFAULT_GROUP);
298
299        for (bgl = yd->buddygroups; bgl; bgl = bgl->next) {
300                struct byahoo_buddygroups *bg = bgl->data;
301
302                if (g_strcasecmp(bg->buddy, who) == 0) {
303                        yahoo_remove_buddy(yd->y2_id, who, bg->group);
304                }
305        }
306}
307
308static void byahoo_chat_msg(struct groupchat *c, char *message, int flags)
309{
310        struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data;
311
312        yahoo_conference_message(yd->y2_id, NULL, c->data, c->title, message, 1);
313}
314
315static void byahoo_chat_invite(struct groupchat *c, char *who, char *msg)
316{
317        struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data;
318
319        yahoo_conference_invite(yd->y2_id, NULL, c->data, c->title, msg ? msg : "");
320}
321
322static void byahoo_chat_leave(struct groupchat *c)
323{
324        struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data;
325
326        yahoo_conference_logoff(yd->y2_id, NULL, c->data, c->title);
327        imcb_chat_free(c);
328}
329
330static struct groupchat *byahoo_chat_with(struct im_connection *ic, char *who)
331{
332        struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
333        struct groupchat *c;
334        char *roomname;
335        YList *members;
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
342        /* FIXME: Free this thing when the chat's destroyed. We can't *always*
343                  do this because it's not always created here. */
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
351        return c;
352}
353
354static void byahoo_auth_allow(struct im_connection *ic, const char *who)
355{
356        struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
357
358        yahoo_confirm_buddy(yd->y2_id, who, 0, "");
359}
360
361static void byahoo_auth_deny(struct im_connection *ic, const char *who)
362{
363        struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
364
365        yahoo_confirm_buddy(yd->y2_id, who, 1, "");
366}
367
368void byahoo_initmodule()
369{
370        struct prpl *ret = g_new0(struct prpl, 1);
371
372        ret->name = "yahoo";
373        ret->mms = 832;       /* this guess taken from libotr UPGRADING file */
374        ret->init = byahoo_init;
375
376        ret->login = byahoo_login;
377        ret->keepalive = byahoo_keepalive;
378        ret->logout = byahoo_logout;
379
380        ret->buddy_msg = byahoo_buddy_msg;
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;
386        ret->send_typing = byahoo_send_typing;
387
388        ret->chat_msg = byahoo_chat_msg;
389        ret->chat_invite = byahoo_chat_invite;
390        ret->chat_leave = byahoo_chat_leave;
391        ret->chat_with = byahoo_chat_with;
392
393        ret->handle_cmp = g_strcasecmp;
394
395        ret->auth_allow = byahoo_auth_allow;
396        ret->auth_deny = byahoo_auth_deny;
397
398        register_protocol(ret);
399}
400
401static struct im_connection *byahoo_get_ic_by_id(int id)
402{
403        GSList *l;
404        struct im_connection *ic;
405        struct byahoo_data *yd;
406
407        for (l = get_connections(); l; l = l->next) {
408                ic = l->data;
409                yd = ic->proto_data;
410
411                if (strcmp(ic->acc->prpl->name, "yahoo") == 0 && yd->y2_id == id) {
412                        return(ic);
413                }
414        }
415
416        return(NULL);
417}
418
419
420/* Now it's callback time! */
421
422struct byahoo_connect_callback_data {
423        int fd;
424        yahoo_connect_callback callback;
425        gpointer data;
426        int id;
427};
428
429void byahoo_connect_callback(gpointer data, gint source, b_input_condition cond)
430{
431        struct byahoo_connect_callback_data *d = data;
432
433        if (!byahoo_get_ic_by_id(d->id)) {
434                g_free(d);
435                return;
436        }
437
438        d->callback(NULL + d->fd, 0, d->data);
439        g_free(d);
440}
441
442struct byahoo_read_ready_data {
443        int id;
444        int fd;
445        int tag;
446        gpointer data;
447};
448
449gboolean byahoo_read_ready_callback(gpointer data, gint source, b_input_condition cond)
450{
451        struct byahoo_read_ready_data *d = data;
452
453        if (!byahoo_get_ic_by_id(d->id)) {
454                /* WTF doesn't libyahoo clean this up? */
455                return FALSE;
456        }
457
458        yahoo_read_ready(d->id, NULL + d->fd, d->data);
459
460        return TRUE;
461}
462
463struct byahoo_write_ready_data {
464        int id;
465        int fd;
466        int tag;
467        gpointer data;
468};
469
470gboolean byahoo_write_ready_callback(gpointer data, gint source, b_input_condition cond)
471{
472        struct byahoo_write_ready_data *d = data;
473
474        return yahoo_write_ready(d->id, NULL + d->fd, d->data);
475}
476
477void ext_yahoo_login_response(int id, int succ, const char *url)
478{
479        struct im_connection *ic = byahoo_get_ic_by_id(id);
480        struct byahoo_data *yd = NULL;
481
482        if (ic == NULL) {
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. */
487
488                return;
489        }
490
491        yd = (struct byahoo_data *) ic->proto_data;
492
493        if (succ == YAHOO_LOGIN_OK) {
494                imcb_connected(ic);
495
496                yd->logged_in = TRUE;
497        } else {
498                char *errstr;
499                int allow_reconnect = FALSE;
500
501                yd->logged_in = FALSE;
502
503                if (succ == YAHOO_LOGIN_UNAME) {
504                        errstr = "Incorrect Yahoo! username";
505                } else if (succ == YAHOO_LOGIN_PASSWD) {
506                        errstr = "Incorrect Yahoo! password";
507                } else if (succ == YAHOO_LOGIN_LOCK) {
508                        errstr = "Yahoo! account locked";
509                } else if (succ == 1236) {
510                        errstr = "Yahoo! account locked or machine temporarily banned";
511                } else if (succ == YAHOO_LOGIN_DUPL) {
512                        errstr = "Logged in on a different machine or device";
513                } else if (succ == YAHOO_LOGIN_SOCK) {
514                        errstr = "Socket problem";
515                        allow_reconnect = TRUE;
516                } else {
517                        errstr = "Unknown error";
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);
527        }
528}
529
530void ext_yahoo_got_buddies(int id, YList *buds)
531{
532        struct im_connection *ic = byahoo_get_ic_by_id(id);
533        struct byahoo_data *yd = ic->proto_data;
534        YList *bl = buds;
535
536        while (bl) {
537                struct yahoo_buddy *b = bl->data;
538                struct byahoo_buddygroups *bg;
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);
546                }
547
548                imcb_add_buddy(ic, b->id, b->group);
549                imcb_rename_buddy(ic, b->id, b->real_name);
550
551                bl = bl->next;
552        }
553}
554
555void ext_yahoo_got_identities(int id, YList *ids)
556{
557}
558
559void ext_yahoo_got_cookies(int id)
560{
561}
562
563void ext_yahoo_status_changed(int id, const char *who, int stat, const char *msg, int away, int idle, int mobile)
564{
565        struct im_connection *ic = byahoo_get_ic_by_id(id);
566        char *state_string = NULL;
567        int flags = OPT_LOGGED_IN;
568
569        if (away) {
570                flags |= OPT_AWAY;
571        }
572        if (mobile) {
573                flags |= OPT_MOBILE;
574        }
575
576        switch (stat) {
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        }
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        }
624}
625
626void ext_yahoo_got_buzz(int id, const char *me, const char *who, long tm)
627{
628}
629
630void ext_yahoo_got_im(int id, const char *me, const char *who, const char *msg, long tm, int stat, int utf8)
631{
632        struct im_connection *ic = byahoo_get_ic_by_id(id);
633        char *m;
634
635        if (msg) {
636                m = byahoo_strip(msg);
637                imcb_buddy_msg(ic, (char *) who, (char *) m, 0, 0);
638                g_free(m);
639        }
640}
641
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)
644{
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);
648}
649
650void ext_yahoo_got_ft_data(int id, const unsigned char *in, int len, void *data)
651{
652}
653
654void ext_yahoo_file_transfer_done(int id, int result, void *data)
655{
656}
657
658void ext_yahoo_typing_notify(int id, const char *ignored, const char *who, int stat)
659{
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        }
667}
668
669void ext_yahoo_system_message(int id, const char *me, const char *who, const char *msg)
670{
671        struct im_connection *ic = byahoo_get_ic_by_id(id);
672
673        imcb_log(ic, "Yahoo! system message: %s", msg);
674}
675
676void ext_yahoo_webcam_invite(int id, const char *ignored, const char *from)
677{
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);
681}
682
683void ext_yahoo_error(int id, const char *err, int fatal, int num)
684{
685        struct im_connection *ic = byahoo_get_ic_by_id(id);
686
687        imcb_error(ic, "%s", err);
688}
689
690/* TODO: Clear up the mess of inp and d structures */
691int ext_yahoo_add_handler(int id, void *fd_, yahoo_input_condition cond, void *data)
692{
693        struct byahoo_input_data *inp = g_new0(struct byahoo_input_data, 1);
694        int fd = (long) fd_;
695
696        if (cond == YAHOO_INPUT_READ) {
697                struct byahoo_read_ready_data *d = g_new0(struct byahoo_read_ready_data, 1);
698
699                d->id = id;
700                d->fd = fd;
701                d->data = data;
702
703                inp->d = d;
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
709                d->id = id;
710                d->fd = fd;
711                d->data = data;
712
713                inp->d = d;
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);
719                return -1;
720                /* Panic... */
721        }
722
723        byahoo_inputs = g_slist_append(byahoo_inputs, inp);
724        return inp->h;
725}
726
727void ext_yahoo_remove_handler(int id, int tag)
728{
729        struct byahoo_input_data *inp;
730        GSList *l = byahoo_inputs;
731
732        while (l) {
733                inp = l->data;
734                if (inp->h == tag) {
735                        byahoo_inputs = g_slist_remove(byahoo_inputs, inp);
736                        g_free(inp->d);
737                        g_free(inp);
738                        break;
739                }
740                l = l->next;
741        }
742
743        b_event_remove(tag);
744}
745
746int ext_yahoo_connect_async(int id, const char *host, int port, yahoo_connect_callback callback, void *data,
747                            int use_ssl)
748{
749        struct byahoo_connect_callback_data *d;
750        int fd;
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);
756        }
757        d->fd = fd;
758        d->callback = callback;
759        d->data = data;
760        d->id = id;
761
762        return fd;
763}
764
765char *ext_yahoo_get_ip_addr(const char *domain)
766{
767        return NULL;
768}
769
770int ext_yahoo_write(void *fd, char *buf, int len)
771{
772        return write((long) fd, buf, len);
773}
774
775int ext_yahoo_read(void *fd, char *buf, int len)
776{
777        return read((long) fd, buf, len);
778}
779
780void ext_yahoo_close(void *fd)
781{
782        close((long) fd);
783}
784
785void ext_yahoo_got_buddy_change_group(int id, const char *me, const char *who,
786                                      const char *old_group, const char *new_group)
787{
788        struct im_connection *ic = byahoo_get_ic_by_id(id);
789
790        imcb_add_buddy(ic, who, new_group);
791}
792
793static void byahoo_accept_conf(void *data)
794{
795        struct byahoo_conf_invitation *inv = data;
796        struct groupchat *b = NULL;
797        GSList *l;
798
799        for (l = inv->ic->groupchats; l; l = l->next) {
800                b = l->data;
801                if (b == inv->c) {
802                        break;
803                }
804        }
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);
811        }
812
813        g_free(inv->name);
814        g_free(inv);
815}
816
817static void byahoo_reject_conf(void *data)
818{
819        struct byahoo_conf_invitation *inv = data;
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);
825}
826
827void ext_yahoo_got_conf_invite(int id, const char *ignored,
828                               const char *who, const char *room, const char *msg, YList *members)
829{
830        struct im_connection *ic = byahoo_get_ic_by_id(id);
831        struct byahoo_conf_invitation *inv;
832        char txt[1024];
833        YList *m;
834
835        if (g_strcasecmp(who, ic->acc->user) == 0) {
836                /* WTF, Yahoo! seems to echo these now? */
837                return;
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);
844        inv->c->data = members;
845        inv->yid = id;
846        inv->members = members;
847        inv->ic = ic;
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);
858}
859
860void ext_yahoo_conf_userdecline(int id, const char *ignored, const char *who, const char *room, const char *msg)
861{
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);
865}
866
867void ext_yahoo_conf_userjoin(int id, const char *ignored, const char *who, const char *room)
868{
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        }
875}
876
877void ext_yahoo_conf_userleave(int id, const char *ignored, const char *who, const char *room)
878
879{
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        }
886}
887
888void ext_yahoo_conf_message(int id, const char *ignored, const char *who, const char *room, const char *msg, int utf8)
889{
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);
898}
899
900void ext_yahoo_chat_cat_xml(int id, const char *xml)
901{
902}
903
904void ext_yahoo_chat_join(int id, const char *who, const char *room, const char *topic, YList *members, void *fd)
905{
906}
907
908void ext_yahoo_chat_userjoin(int id, const char *me, const char *room, struct yahoo_chat_member *who)
909{
910        free(who->id);
911        free(who->alias);
912        free(who->location);
913        free(who);
914}
915
916void ext_yahoo_chat_userleave(int id, const char *me, const char *room, const char *who)
917{
918}
919
920void ext_yahoo_chat_message(int id, const char *me, const char *who, const char *room, const char *msg, int msgtype,
921                            int utf8)
922{
923}
924
925void ext_yahoo_chat_yahoologout(int id, const char *me)
926{
927}
928
929void ext_yahoo_chat_yahooerror(int id, const char *me)
930{
931}
932
933void ext_yahoo_contact_added(int id, const char *myid, const char *who, const char *msg)
934{
935        struct im_connection *ic = byahoo_get_ic_by_id(id);
936
937        imcb_ask_auth(ic, who, msg);
938}
939
940void ext_yahoo_rejected(int id, const char *who, const char *msg)
941{
942}
943
944void ext_yahoo_game_notify(int id, const char *me, const char *who, int stat, const char *msg)
945{
946}
947
948void ext_yahoo_mail_notify(int id, const char *from, const char *subj, int cnt)
949{
950        struct im_connection *ic = byahoo_get_ic_by_id(id);
951
952        if (!set_getbool(&ic->acc->set, "mail_notifications")) {
953                ; /* The user doesn't care. */
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        }
959}
960
961void ext_yahoo_webcam_invite_reply(int id, const char *me, const char *from, int accept)
962{
963}
964
965void ext_yahoo_webcam_closed(int id, const char *who, int reason)
966{
967}
968
969void ext_yahoo_got_search_result(int id, int found, int start, int total, YList *contacts)
970{
971}
972
973void ext_yahoo_webcam_viewer(int id, const char *who, int connect)
974{
975}
976
977void ext_yahoo_webcam_data_request(int id, int send)
978{
979}
980
981int ext_yahoo_log(const char *fmt, ...)
982{
983        return(0);
984}
985
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)
988{
989}
990
991void ext_yahoo_got_ping(int id, const char *msg)
992{
993}
994
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}
1001
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.