source: protocols/yahoo/yahoo.c @ faeb521

Last change on this file since faeb521 was dd43c62, checked in by dequis <dx@…>, at 2015-05-28T05:26:24Z

Gmail notifications support through new imcb_notify_email() API

  • 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, "notify_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, "notify_handle")) {
155                imcb_add_buddy(ic, set_getstr(&acc->set, "notify_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
443        if (!byahoo_get_ic_by_id(d->id)) {
444                g_free(d);
445                return;
446        }
447
448        d->callback(NULL + d->fd, 0, d->data);
449        g_free(d);
450}
451
452struct byahoo_read_ready_data {
453        int id;
454        int fd;
455        int tag;
456        gpointer data;
457};
458
459gboolean byahoo_read_ready_callback(gpointer data, gint source, b_input_condition cond)
460{
461        struct byahoo_read_ready_data *d = data;
462
463        if (!byahoo_get_ic_by_id(d->id)) {
464                /* WTF doesn't libyahoo clean this up? */
465                return FALSE;
466        }
467
468        yahoo_read_ready(d->id, NULL + d->fd, d->data);
469
470        return TRUE;
471}
472
473struct byahoo_write_ready_data {
474        int id;
475        int fd;
476        int tag;
477        gpointer data;
478};
479
480gboolean byahoo_write_ready_callback(gpointer data, gint source, b_input_condition cond)
481{
482        struct byahoo_write_ready_data *d = data;
483
484        return yahoo_write_ready(d->id, NULL + d->fd, d->data);
485}
486
487void ext_yahoo_login_response(int id, int succ, const char *url)
488{
489        struct im_connection *ic = byahoo_get_ic_by_id(id);
490        struct byahoo_data *yd = NULL;
491
492        if (ic == NULL) {
493                /* libyahoo2 seems to call this one twice when something
494                   went wrong sometimes. Don't know why. Because we clean
495                   up the connection on the first failure, the second
496                   should be ignored. */
497
498                return;
499        }
500
501        yd = (struct byahoo_data *) ic->proto_data;
502
503        if (succ == YAHOO_LOGIN_OK) {
504                imcb_connected(ic);
505
506                yd->logged_in = TRUE;
507        } else {
508                char *errstr;
509                int allow_reconnect = FALSE;
510
511                yd->logged_in = FALSE;
512
513                if (succ == YAHOO_LOGIN_UNAME) {
514                        errstr = "Incorrect Yahoo! username";
515                } else if (succ == YAHOO_LOGIN_PASSWD) {
516                        errstr = "Incorrect Yahoo! password";
517                } else if (succ == YAHOO_LOGIN_LOCK) {
518                        errstr = "Yahoo! account locked";
519                } else if (succ == 1236) {
520                        errstr = "Yahoo! account locked or machine temporarily banned";
521                } else if (succ == YAHOO_LOGIN_DUPL) {
522                        errstr = "Logged in on a different machine or device";
523                } else if (succ == YAHOO_LOGIN_SOCK) {
524                        errstr = "Socket problem";
525                        allow_reconnect = TRUE;
526                } else {
527                        errstr = "Unknown error";
528                }
529
530                if (url && *url) {
531                        imcb_error(ic, "Error %d (%s). See %s for more information.", succ, errstr, url);
532                } else {
533                        imcb_error(ic, "Error %d (%s)", succ, errstr);
534                }
535
536                imc_logout(ic, allow_reconnect);
537        }
538}
539
540void ext_yahoo_got_buddies(int id, YList *buds)
541{
542        struct im_connection *ic = byahoo_get_ic_by_id(id);
543        struct byahoo_data *yd = ic->proto_data;
544        YList *bl = buds;
545
546        while (bl) {
547                struct yahoo_buddy *b = bl->data;
548                struct byahoo_buddygroups *bg;
549
550                if (strcmp(b->group, BYAHOO_DEFAULT_GROUP) != 0) {
551                        bg = g_new0(struct byahoo_buddygroups, 1);
552
553                        bg->buddy = g_strdup(b->id);
554                        bg->group = g_strdup(b->group);
555                        yd->buddygroups = g_slist_append(yd->buddygroups, bg);
556                }
557
558                imcb_add_buddy(ic, b->id, b->group);
559                imcb_rename_buddy(ic, b->id, b->real_name);
560
561                bl = bl->next;
562        }
563}
564
565void ext_yahoo_got_identities(int id, YList *ids)
566{
567}
568
569void ext_yahoo_got_cookies(int id)
570{
571}
572
573void ext_yahoo_status_changed(int id, const char *who, int stat, const char *msg, int away, int idle, int mobile)
574{
575        struct im_connection *ic = byahoo_get_ic_by_id(id);
576        char *state_string = NULL;
577        int flags = OPT_LOGGED_IN;
578
579        if (away) {
580                flags |= OPT_AWAY;
581        }
582        if (mobile) {
583                flags |= OPT_MOBILE;
584        }
585
586        switch (stat) {
587        case YAHOO_STATUS_BRB:
588                state_string = "Be Right Back";
589                break;
590        case YAHOO_STATUS_BUSY:
591                state_string = "Busy";
592                break;
593        case YAHOO_STATUS_NOTATHOME:
594                state_string = "Not At Home";
595                break;
596        case YAHOO_STATUS_NOTATDESK:
597                state_string = "Not At Desk";
598                break;
599        case YAHOO_STATUS_NOTINOFFICE:
600                state_string = "Not In Office";
601                break;
602        case YAHOO_STATUS_ONPHONE:
603                state_string = "On Phone";
604                break;
605        case YAHOO_STATUS_ONVACATION:
606                state_string = "On Vacation";
607                break;
608        case YAHOO_STATUS_OUTTOLUNCH:
609                state_string = "Out To Lunch";
610                break;
611        case YAHOO_STATUS_STEPPEDOUT:
612                state_string = "Stepped Out";
613                break;
614        case YAHOO_STATUS_INVISIBLE:
615                state_string = "Invisible";
616                break;
617        case YAHOO_STATUS_CUSTOM:
618                state_string = "Away";
619                break;
620        case YAHOO_STATUS_IDLE:
621                state_string = "Idle";
622                break;
623        case YAHOO_STATUS_OFFLINE:
624                state_string = "Offline";
625                flags = 0;
626                break;
627        }
628
629        imcb_buddy_status(ic, who, flags, state_string, msg);
630
631        if (stat == YAHOO_STATUS_IDLE) {
632                imcb_buddy_times(ic, who, 0, idle);
633        }
634}
635
636void ext_yahoo_got_buzz(int id, const char *me, const char *who, long tm)
637{
638}
639
640void ext_yahoo_got_im(int id, const char *me, const char *who, const char *msg, long tm, int stat, int utf8)
641{
642        struct im_connection *ic = byahoo_get_ic_by_id(id);
643        char *m;
644
645        if (msg) {
646                m = byahoo_strip(msg);
647                imcb_buddy_msg(ic, (char *) who, (char *) m, 0, 0);
648                g_free(m);
649        }
650}
651
652void ext_yahoo_got_file(int id, const char *ignored, const char *who, const char *msg,
653                        const char *fname, unsigned long fesize, char *trid)
654{
655        struct im_connection *ic = byahoo_get_ic_by_id(id);
656
657        imcb_log(ic, "Got a file transfer (file = %s) from %s. Ignoring for now due to lack of support.", fname, who);
658}
659
660void ext_yahoo_got_ft_data(int id, const unsigned char *in, int len, void *data)
661{
662}
663
664void ext_yahoo_file_transfer_done(int id, int result, void *data)
665{
666}
667
668void ext_yahoo_typing_notify(int id, const char *ignored, const char *who, int stat)
669{
670        struct im_connection *ic = byahoo_get_ic_by_id(id);
671
672        if (stat == 1) {
673                imcb_buddy_typing(ic, (char *) who, OPT_TYPING);
674        } else {
675                imcb_buddy_typing(ic, (char *) who, 0);
676        }
677}
678
679void ext_yahoo_system_message(int id, const char *me, const char *who, const char *msg)
680{
681        struct im_connection *ic = byahoo_get_ic_by_id(id);
682
683        imcb_log(ic, "Yahoo! system message: %s", msg);
684}
685
686void ext_yahoo_webcam_invite(int id, const char *ignored, const char *from)
687{
688        struct im_connection *ic = byahoo_get_ic_by_id(id);
689
690        imcb_log(ic, "Got a webcam invitation from %s. IRC+webcams is a no-no though...", from);
691}
692
693void ext_yahoo_error(int id, const char *err, int fatal, int num)
694{
695        struct im_connection *ic = byahoo_get_ic_by_id(id);
696
697        imcb_error(ic, "%s", err);
698}
699
700/* TODO: Clear up the mess of inp and d structures */
701int ext_yahoo_add_handler(int id, void *fd_, yahoo_input_condition cond, void *data)
702{
703        struct byahoo_input_data *inp = g_new0(struct byahoo_input_data, 1);
704        int fd = (long) fd_;
705
706        if (cond == YAHOO_INPUT_READ) {
707                struct byahoo_read_ready_data *d = g_new0(struct byahoo_read_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 = b_input_add(fd, B_EV_IO_READ, (b_event_handler) byahoo_read_ready_callback,
715                                              (gpointer) d);
716        } else if (cond == YAHOO_INPUT_WRITE) {
717                struct byahoo_write_ready_data *d = g_new0(struct byahoo_write_ready_data, 1);
718
719                d->id = id;
720                d->fd = fd;
721                d->data = data;
722
723                inp->d = d;
724                d->tag = inp->h =
725                                 b_input_add(fd, B_EV_IO_WRITE, (b_event_handler) byahoo_write_ready_callback,
726                                             (gpointer) d);
727        } else {
728                g_free(inp);
729                return -1;
730                /* Panic... */
731        }
732
733        byahoo_inputs = g_slist_append(byahoo_inputs, inp);
734        return inp->h;
735}
736
737void ext_yahoo_remove_handler(int id, int tag)
738{
739        struct byahoo_input_data *inp;
740        GSList *l = byahoo_inputs;
741
742        while (l) {
743                inp = l->data;
744                if (inp->h == tag) {
745                        byahoo_inputs = g_slist_remove(byahoo_inputs, inp);
746                        g_free(inp->d);
747                        g_free(inp);
748                        break;
749                }
750                l = l->next;
751        }
752
753        b_event_remove(tag);
754}
755
756int ext_yahoo_connect_async(int id, const char *host, int port, yahoo_connect_callback callback, void *data,
757                            int use_ssl)
758{
759        struct byahoo_connect_callback_data *d;
760        int fd;
761
762        d = g_new0(struct byahoo_connect_callback_data, 1);
763        if ((fd = proxy_connect(host, port, (b_event_handler) byahoo_connect_callback, (gpointer) d)) < 0) {
764                g_free(d);
765                return(fd);
766        }
767        d->fd = fd;
768        d->callback = callback;
769        d->data = data;
770        d->id = id;
771
772        return fd;
773}
774
775char *ext_yahoo_get_ip_addr(const char *domain)
776{
777        return NULL;
778}
779
780int ext_yahoo_write(void *fd, char *buf, int len)
781{
782        return write((long) fd, buf, len);
783}
784
785int ext_yahoo_read(void *fd, char *buf, int len)
786{
787        return read((long) fd, buf, len);
788}
789
790void ext_yahoo_close(void *fd)
791{
792        close((long) fd);
793}
794
795void ext_yahoo_got_buddy_change_group(int id, const char *me, const char *who,
796                                      const char *old_group, const char *new_group)
797{
798        struct im_connection *ic = byahoo_get_ic_by_id(id);
799
800        imcb_add_buddy(ic, who, new_group);
801}
802
803static void byahoo_accept_conf(void *data)
804{
805        struct byahoo_conf_invitation *inv = data;
806        struct groupchat *b = NULL;
807        GSList *l;
808
809        for (l = inv->ic->groupchats; l; l = l->next) {
810                b = l->data;
811                if (b == inv->c) {
812                        break;
813                }
814        }
815
816        if (b != NULL) {
817                yahoo_conference_logon(inv->yid, NULL, inv->members, inv->name);
818                imcb_chat_add_buddy(inv->c, inv->ic->acc->user);
819        } else {
820                imcb_log(inv->ic, "Duplicate/corrupted invitation to `%s'.", inv->name);
821        }
822
823        g_free(inv->name);
824        g_free(inv);
825}
826
827static void byahoo_reject_conf(void *data)
828{
829        struct byahoo_conf_invitation *inv = data;
830
831        yahoo_conference_decline(inv->yid, NULL, inv->members, inv->name, "User rejected groupchat");
832        imcb_chat_free(inv->c);
833        g_free(inv->name);
834        g_free(inv);
835}
836
837void ext_yahoo_got_conf_invite(int id, const char *ignored,
838                               const char *who, const char *room, const char *msg, YList *members)
839{
840        struct im_connection *ic = byahoo_get_ic_by_id(id);
841        struct byahoo_conf_invitation *inv;
842        char txt[1024];
843        YList *m;
844
845        if (g_strcasecmp(who, ic->acc->user) == 0) {
846                /* WTF, Yahoo! seems to echo these now? */
847                return;
848        }
849
850        inv = g_malloc(sizeof(struct byahoo_conf_invitation));
851        memset(inv, 0, sizeof(struct byahoo_conf_invitation));
852        inv->name = g_strdup(room);
853        inv->c = imcb_chat_new(ic, (char *) room);
854        inv->c->data = members;
855        inv->yid = id;
856        inv->members = members;
857        inv->ic = ic;
858
859        for (m = members; m; m = m->next) {
860                if (g_strcasecmp(m->data, ic->acc->user) != 0) {
861                        imcb_chat_add_buddy(inv->c, m->data);
862                }
863        }
864
865        g_snprintf(txt, 1024, "Got an invitation to chatroom %s from %s: %s", room, who, msg);
866
867        imcb_ask(ic, txt, inv, byahoo_accept_conf, byahoo_reject_conf);
868}
869
870void ext_yahoo_conf_userdecline(int id, const char *ignored, const char *who, const char *room, const char *msg)
871{
872        struct im_connection *ic = byahoo_get_ic_by_id(id);
873
874        imcb_log(ic, "Invite to chatroom %s rejected by %s: %s", room, who, msg);
875}
876
877void ext_yahoo_conf_userjoin(int id, const char *ignored, const char *who, const char *room)
878{
879        struct im_connection *ic = byahoo_get_ic_by_id(id);
880        struct groupchat *c = bee_chat_by_title(ic->bee, ic, room);
881
882        if (c) {
883                imcb_chat_add_buddy(c, (char *) who);
884        }
885}
886
887void ext_yahoo_conf_userleave(int id, const char *ignored, const char *who, const char *room)
888
889{
890        struct im_connection *ic = byahoo_get_ic_by_id(id);
891        struct groupchat *c = bee_chat_by_title(ic->bee, ic, room);
892
893        if (c) {
894                imcb_chat_remove_buddy(c, (char *) who, "");
895        }
896}
897
898void ext_yahoo_conf_message(int id, const char *ignored, const char *who, const char *room, const char *msg, int utf8)
899{
900        struct im_connection *ic = byahoo_get_ic_by_id(id);
901        char *m = byahoo_strip(msg);
902        struct groupchat *c = bee_chat_by_title(ic->bee, ic, room);
903
904        if (c) {
905                imcb_chat_msg(c, (char *) who, (char *) m, 0, 0);
906        }
907        g_free(m);
908}
909
910void ext_yahoo_chat_cat_xml(int id, const char *xml)
911{
912}
913
914void ext_yahoo_chat_join(int id, const char *who, const char *room, const char *topic, YList *members, void *fd)
915{
916}
917
918void ext_yahoo_chat_userjoin(int id, const char *me, const char *room, struct yahoo_chat_member *who)
919{
920        free(who->id);
921        free(who->alias);
922        free(who->location);
923        free(who);
924}
925
926void ext_yahoo_chat_userleave(int id, const char *me, const char *room, const char *who)
927{
928}
929
930void ext_yahoo_chat_message(int id, const char *me, const char *who, const char *room, const char *msg, int msgtype,
931                            int utf8)
932{
933}
934
935void ext_yahoo_chat_yahoologout(int id, const char *me)
936{
937}
938
939void ext_yahoo_chat_yahooerror(int id, const char *me)
940{
941}
942
943void ext_yahoo_contact_added(int id, const char *myid, const char *who, const char *msg)
944{
945        struct im_connection *ic = byahoo_get_ic_by_id(id);
946
947        imcb_ask_auth(ic, who, msg);
948}
949
950void ext_yahoo_rejected(int id, const char *who, const char *msg)
951{
952}
953
954void ext_yahoo_game_notify(int id, const char *me, const char *who, int stat, const char *msg)
955{
956}
957
958void ext_yahoo_mail_notify(int id, const char *from, const char *subj, int cnt)
959{
960        struct im_connection *ic = byahoo_get_ic_by_id(id);
961        char *msg;
962
963        if (set_getbool(&ic->acc->set, "mail_notifications")) {
964                if (from && subj) {
965                        msg = g_strdup_printf("Received e-mail message from %s with subject `%s'", from, subj);
966                } else if (cnt > 0) {
967                        msg = g_strdup_printf("Received %d new e-mails", cnt);
968                }
969
970                imcb_notify_email(ic, set_getstr(&ic->acc->set, "notify_handle"), msg, 0, 0);
971                g_free(msg);
972        }
973}
974
975void ext_yahoo_webcam_invite_reply(int id, const char *me, const char *from, int accept)
976{
977}
978
979void ext_yahoo_webcam_closed(int id, const char *who, int reason)
980{
981}
982
983void ext_yahoo_got_search_result(int id, int found, int start, int total, YList *contacts)
984{
985}
986
987void ext_yahoo_webcam_viewer(int id, const char *who, int connect)
988{
989}
990
991void ext_yahoo_webcam_data_request(int id, int send)
992{
993}
994
995int ext_yahoo_log(const char *fmt, ...)
996{
997        return(0);
998}
999
1000void ext_yahoo_got_webcam_image(int id, const char * who, const unsigned char *image, unsigned int image_size,
1001                                unsigned int real_size, unsigned int timestamp)
1002{
1003}
1004
1005void ext_yahoo_got_ping(int id, const char *msg)
1006{
1007}
1008
1009void ext_yahoo_got_buddyicon(int id, const char *me, const char *who, const char *url, int checksum)
1010{
1011}
1012void ext_yahoo_got_buddyicon_checksum(int id, const char *me, const char *who, int checksum)
1013{
1014}
1015
1016void ext_yahoo_got_buddyicon_request(int id, const char *me, const char *who)
1017{
1018}
1019void ext_yahoo_buddyicon_uploaded(int id, const char *url)
1020{
1021}
Note: See TracBrowser for help on using the repository browser.