source: protocols/yahoo/yahoo.c @ 72d661e

Last change on this file since 72d661e was 72d661e, checked in by dequis <dx@…>, at 2015-10-21T08:46:02Z

yahoo: Fix handling of proxy connection failures

Fixes trac ticket 135, https://bugs.bitlbee.org/bitlbee/ticket/135

The ticket mentions 100% cpu usage when failing to connect to a socks
proxy. It also provides a patch that just checks source == -1 and
disconnects cleanly instead of trying to continue logging in.

This commit is pretty much the same thing, adapted to the API we're
currently using, since the original patch was for bitlbee 1.0.1 and it
looks like the old api was terrible back then.

That ticket was almost 10 years old. The yahoo code didn't change a lot
in that time.

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