source: skype/skype.c @ fc26bcb

Last change on this file since fc26bcb was 5652d43, checked in by Miklos Vajna <vmiklos@…>, at 2007-11-23T23:46:20Z

warning fix in skype_chat_with()
fix "when you start a group chat, a warning is shown saying creating the
group chat is failed, but in fact it is created"

  • Property mode set to 100644
File size: 19.6 KB
Line 
1/*
2 *  skype.c - Skype plugin for BitlBee
3 *
4 *  Copyright (c) 2007 by Miklos Vajna <vmiklos@frugalware.org>
5 *
6 *  Several ideas are used from the BitlBee Jabber plugin, which is
7 *
8 *  Copyright (c) 2006 by Wilmer van der Gaast <wilmer@gaast.net>
9 *
10 *  This program is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License as published by
12 *  the Free Software Foundation; either version 2 of the License, or
13 *  (at your option) any later version.
14 *
15 *  This program is distributed in the hope that it will be useful,
16 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 *  GNU General Public License for more details.
19 *
20 *  You should have received a copy of the GNU General Public License
21 *  along with this program; if not, write to the Free Software
22 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
23 *  USA.
24 */
25
26#include <stdio.h>
27#include <poll.h>
28#include <bitlbee.h>
29#include <glib.h>
30
31#define SKYPE_PORT_DEFAULT "2727"
32
33/*
34 * Enumerations
35 */
36
37typedef enum
38{
39        SKYPE_CALL_RINGING = 1,
40        SKYPE_CALL_MISSED
41} skype_call_status;
42
43typedef enum
44{
45        SKYPE_FILETRANSFER_NEW = 1,
46        SKYPE_FILETRANSFER_FAILED
47} skype_filetransfer_status;
48
49/*
50 * Structures
51 */
52
53struct skype_data
54{
55        struct im_connection *ic;
56        char *username;
57        /* The effective file descriptor. We store it here so any function can
58         * write() to it. */
59        int fd;
60        /* File descriptor returned by bitlbee. we store it so we know when
61         * we're connected and when we aren't. */
62        int bfd;
63        /* When we receive a new message id, we query the properties, finally
64         * the chatname. Store the properties here so that we can use
65         * imcb_buddy_msg() when we got the chatname. */
66        char *handle;
67        /* List, because of multiline messages. */
68        GList *body;
69        char *type;
70        /* This is necessary because we send a notification when we get the
71         * handle. So we store the state here and then we can send a
72         * notification about the handle is in a given status. */
73        skype_call_status call_status;
74        /* Same for file transfers. */
75        skype_filetransfer_status filetransfer_status;
76        /* Using /j #nick we want to have a groupchat with two people. Usually
77         * not (default). */
78        char* groupchat_with;
79        /* The user who invited us to the chat. */
80        char* adder;
81        /* If we are waiting for a confirmation about we changed the topic. */
82        int topic_wait;
83};
84
85struct skype_away_state
86{
87        char *code;
88        char *full_name;
89};
90
91struct skype_buddy_ask_data
92{
93        struct im_connection *ic;
94        char *handle;
95};
96
97/*
98 * Tables
99 */
100
101const struct skype_away_state skype_away_state_list[] =
102{
103        { "ONLINE",  "Online" },
104        { "SKYPEME",  "Skype Me" },
105        { "AWAY",   "Away" },
106        { "NA",    "Not available" },
107        { "DND",      "Do Not Disturb" },
108        { "INVISIBLE",      "Invisible" },
109        { "OFFLINE",      "Offline" },
110        { NULL, NULL}
111};
112
113/*
114 * Functions
115 */
116
117static void skype_init( account_t *acc )
118{
119        set_t *s;
120
121        s = set_add( &acc->set, "port", SKYPE_PORT_DEFAULT, set_eval_int, acc );
122        s->flags |= ACC_SET_OFFLINE_ONLY;
123
124        s = set_add( &acc->set, "server", NULL, set_eval_account, acc );
125        s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY;
126}
127
128int skype_write( struct im_connection *ic, char *buf, int len )
129{
130        struct skype_data *sd = ic->proto_data;
131        struct pollfd pfd[1];
132
133        pfd[0].fd = sd->fd;
134        pfd[0].events = POLLOUT;
135
136        /* This poll is necessary or we'll get a SIGPIPE when we write() to
137         * sd->fd. */
138        poll(pfd, 1, 1000);
139        if(pfd[0].revents & POLLHUP)
140        {
141                imcb_error( ic, "Could not connect to server" );
142                imc_logout( ic, TRUE );
143                return FALSE;
144        }
145        write( sd->fd, buf, len );
146
147        return TRUE;
148}
149
150static void skype_buddy_ask_yes( gpointer w, struct skype_buddy_ask_data *bla )
151{
152        char *buf = g_strdup_printf("SET USER %s ISAUTHORIZED TRUE", bla->handle);
153        skype_write( bla->ic, buf, strlen( buf ) );
154        g_free(buf);
155        g_free(bla->handle);
156        g_free(bla);
157}
158
159static void skype_buddy_ask_no( gpointer w, struct skype_buddy_ask_data *bla )
160{
161        char *buf = g_strdup_printf("SET USER %s ISAUTHORIZED FALSE", bla->handle);
162        skype_write( bla->ic, buf, strlen( buf ) );
163        g_free(buf);
164        g_free(bla->handle);
165        g_free(bla);
166}
167
168void skype_buddy_ask( struct im_connection *ic, char *handle, char *message)
169{
170        struct skype_buddy_ask_data *bla = g_new0( struct skype_buddy_ask_data, 1 );
171        char *buf;
172
173        bla->ic = ic;
174        bla->handle = g_strdup(handle);
175
176        buf = g_strdup_printf( "The user %s wants to add you to his/her buddy list, saying: '%s'.", handle, message);
177        imcb_ask( ic, buf, bla, skype_buddy_ask_yes, skype_buddy_ask_no );
178        g_free( buf );
179}
180
181struct groupchat *skype_chat_by_name( struct im_connection *ic, char *name )
182{
183        struct groupchat *ret;
184
185        for( ret = ic->groupchats; ret; ret = ret->next )
186        {
187                if(strcmp(name, ret->title ) == 0 )
188                        break;
189        }
190
191        return ret;
192}
193
194static gboolean skype_read_callback( gpointer data, gint fd, b_input_condition cond )
195{
196        struct im_connection *ic = data;
197        struct skype_data *sd = ic->proto_data;
198        char buf[1024];
199        int st;
200        char **lines, **lineptr, *line, *ptr;
201
202        if( !sd || sd->fd == -1 )
203                return FALSE;
204        /* Read the whole data. */
205        st = read( sd->fd, buf, sizeof( buf ) );
206        if( st > 0 )
207        {
208                buf[st] = '\0';
209                /* Then split it up to lines. */
210                lines = g_strsplit(buf, "\n", 0);
211                lineptr = lines;
212                while((line = *lineptr))
213                {
214                        if(!strlen(line))
215                                break;
216                        if(!strncmp(line, "USERS ", 6))
217                        {
218                                char **i;
219                                char **nicks;
220
221                                nicks = g_strsplit(line + 6, ", ", 0);
222                                i = nicks;
223                                while(*i)
224                                {
225                                        g_snprintf(buf, 1024, "GET USER %s ONLINESTATUS\n", *i);
226                                        skype_write( ic, buf, strlen( buf ) );
227                                        i++;
228                                }
229                                g_strfreev(nicks);
230                        }
231                        else if(!strncmp(line, "USER ", 5))
232                        {
233                                int flags = 0;
234                                char *status = strrchr(line, ' ');
235                                char *user = strchr(line, ' ');
236                                status++;
237                                ptr = strchr(++user, ' ');
238                                *ptr = '\0';
239                                ptr++;
240                                if(!strncmp(ptr, "ONLINESTATUS ", 13) &&
241                                                strcmp(user, sd->username) != 0
242                                                && strcmp(user, "echo123") != 0)
243                                {
244                                        ptr = g_strdup_printf("%s@skype.com", user);
245                                        imcb_add_buddy(ic, ptr, NULL);
246                                        if(strcmp(status, "OFFLINE") != 0)
247                                                flags |= OPT_LOGGED_IN;
248                                        if(strcmp(status, "ONLINE") != 0 && strcmp(status, "SKYPEME") != 0)
249                                                flags |= OPT_AWAY;
250                                        imcb_buddy_status(ic, ptr, flags, NULL, NULL);
251                                        g_free(ptr);
252                                }
253                                else if(!strncmp(ptr, "RECEIVEDAUTHREQUEST ", 20))
254                                {
255                                        char *message = ptr + 20;
256                                        if(strlen(message))
257                                                skype_buddy_ask(ic, user, message);
258                                }
259                                else if(!strncmp(ptr, "BUDDYSTATUS ", 12))
260                                {
261                                        char *st = ptr + 12;
262                                        if(!strcmp(st, "3"))
263                                        {
264                                                char *buf = g_strdup_printf("%s@skype.com", user);
265                                                imcb_add_buddy(ic, buf, NULL);
266                                                g_free(buf);
267                                        }
268                                }
269                        }
270                        else if(!strncmp(line, "CHATMESSAGE ", 12))
271                        {
272                                char *id = strchr(line, ' ');
273                                if(++id)
274                                {
275                                        char *info = strchr(id, ' ');
276                                        *info = '\0';
277                                        info++;
278                                        if(!strcmp(info, "STATUS RECEIVED"))
279                                        {
280                                                /* New message ID:
281                                                 * (1) Request its from field
282                                                 * (2) Request its body
283                                                 * (3) Request its type
284                                                 * (4) Query chatname
285                                                 */
286                                                g_snprintf(buf, 1024, "GET CHATMESSAGE %s FROM_HANDLE\n", id);
287                                                skype_write( ic, buf, strlen( buf ) );
288                                                g_snprintf(buf, 1024, "GET CHATMESSAGE %s BODY\n", id);
289                                                skype_write( ic, buf, strlen( buf ) );
290                                                g_snprintf(buf, 1024, "GET CHATMESSAGE %s TYPE\n", id);
291                                                skype_write( ic, buf, strlen( buf ) );
292                                                g_snprintf(buf, 1024, "GET CHATMESSAGE %s CHATNAME\n", id);
293                                                skype_write( ic, buf, strlen( buf ) );
294                                        }
295                                        else if(!strncmp(info, "FROM_HANDLE ", 12))
296                                        {
297                                                info += 12;
298                                                /* New from field value. Store
299                                                 * it, then we can later use it
300                                                 * when we got the message's
301                                                 * body. */
302                                                g_free(sd->handle);
303                                                sd->handle = g_strdup_printf("%s@skype.com", info);
304                                        }
305                                        else if(!strncmp(info, "EDITED_BY ", 10))
306                                        {
307                                                info += 10;
308                                                /* This is the same as
309                                                 * FROM_HANDLE, except that we
310                                                 * never request these lines
311                                                 * from Skype, we just get
312                                                 * them. */
313                                                g_free(sd->handle);
314                                                sd->handle = g_strdup_printf("%s@skype.com", info);
315                                        }
316                                        else if(!strncmp(info, "BODY ", 5))
317                                        {
318                                                info += 5;
319                                                sd->body = g_list_append(sd->body, g_strdup(info));
320                                        }
321                                        else if(!strncmp(info, "TYPE ", 5))
322                                        {
323                                                info += 5;
324                                                g_free(sd->type);
325                                                sd->type = g_strdup(info);
326                                        }
327                                        else if(!strncmp(info, "CHATNAME ", 9))
328                                        {
329                                                info += 9;
330                                                if(sd->handle && sd->body && sd->type)
331                                                {
332                                                        struct groupchat *gc = skype_chat_by_name(ic, info);
333                                                        int i;
334                                                        for(i=0;i<g_list_length(sd->body);i++)
335                                                        {
336                                                                char *body = g_list_nth_data(sd->body, i);
337                                                                if(!strcmp(sd->type, "SAID"))
338                                                                {
339                                                                        if(!gc)
340                                                                                /* Private message */
341                                                                                imcb_buddy_msg(ic, sd->handle, body, 0, 0);
342                                                                        else
343                                                                                /* Groupchat message */
344                                                                                imcb_chat_msg(gc, sd->handle, body, 0, 0);
345                                                                }
346                                                                else if(!strcmp(sd->type, "SETTOPIC"))
347                                                                {
348                                                                        if(gc)
349                                                                                imcb_chat_topic(gc, sd->handle, body, 0);
350                                                                }
351                                                                else if(!strcmp(sd->type, "LEFT"))
352                                                                {
353                                                                        if(gc)
354                                                                                imcb_chat_remove_buddy(gc, sd->handle, NULL);
355                                                                }
356                                                        }
357                                                        g_list_free(sd->body);
358                                                        sd->body = NULL;
359                                                }
360                                        }
361                                }
362                        }
363                        else if(!strncmp(line, "CALL ", 5))
364                        {
365                                char *id = strchr(line, ' ');
366                                if(++id)
367                                {
368                                        char *info = strchr(id, ' ');
369                                        *info = '\0';
370                                        info++;
371                                        if(!strcmp(info, "STATUS RINGING"))
372                                        {
373                                                g_snprintf(buf, 1024, "GET CALL %s PARTNER_HANDLE\n", id);
374                                                skype_write( ic, buf, strlen( buf ) );
375                                                sd->call_status = SKYPE_CALL_RINGING;
376                                        }
377                                        else if(!strcmp(info, "STATUS MISSED"))
378                                        {
379                                                g_snprintf(buf, 1024, "GET CALL %s PARTNER_HANDLE\n", id);
380                                                skype_write( ic, buf, strlen( buf ) );
381                                                sd->call_status = SKYPE_CALL_MISSED;
382                                        }
383                                        else if(!strncmp(info, "PARTNER_HANDLE ", 15))
384                                        {
385                                                info += 15;
386                                                if(sd->call_status) {
387                                                        switch(sd->call_status)
388                                                        {
389                                                                case SKYPE_CALL_RINGING:
390                                                                        imcb_log(ic, "The user %s is currently ringing you.", info);
391                                                                        break;
392                                                                case SKYPE_CALL_MISSED:
393                                                                        imcb_log(ic, "You have missed a call from user %s.", info);
394                                                                        break;
395                                                        }
396                                                        sd->call_status = 0;
397                                                }
398                                        }
399                                }
400                        }
401                        else if(!strncmp(line, "FILETRANSFER ", 13))
402                        {
403                                char *id = strchr(line, ' ');
404                                if(++id)
405                                {
406                                        char *info = strchr(id, ' ');
407                                        *info = '\0';
408                                        info++;
409                                        if(!strcmp(info, "STATUS NEW"))
410                                        {
411                                                g_snprintf(buf, 1024, "GET FILETRANSFER %s PARTNER_HANDLE\n", id);
412                                                skype_write( ic, buf, strlen( buf ) );
413                                                sd->filetransfer_status = SKYPE_FILETRANSFER_NEW;
414                                        }
415                                        else if(!strcmp(info, "STATUS FAILED"))
416                                        {
417                                                g_snprintf(buf, 1024, "GET FILETRANSFER %s PARTNER_HANDLE\n", id);
418                                                skype_write( ic, buf, strlen( buf ) );
419                                                sd->filetransfer_status = SKYPE_FILETRANSFER_FAILED;
420                                        }
421                                        else if(!strncmp(info, "PARTNER_HANDLE ", 15))
422                                        {
423                                                info += 15;
424                                                if(sd->filetransfer_status) {
425                                                        switch(sd->filetransfer_status)
426                                                        {
427                                                                case SKYPE_FILETRANSFER_NEW:
428                                                                        imcb_log(ic, "The user %s offered a new file for you.", info);
429                                                                        break;
430                                                                case SKYPE_FILETRANSFER_FAILED:
431                                                                        imcb_log(ic, "Failed to transfer file from user %s.", info);
432                                                                        break;
433                                                        }
434                                                        sd->filetransfer_status = 0;
435                                                }
436                                        }
437                                }
438                        }
439                        else if(!strncmp(line, "CHAT ", 5))
440                        {
441                                char *id = strchr(line, ' ');
442                                if(++id)
443                                {
444                                        char *info = strchr(id, ' ');
445                                        if(info)
446                                                *info = '\0';
447                                        info++;
448                                        /* Remove fake chat if we created one in skype_chat_with() */
449                                        struct groupchat *gc = skype_chat_by_name(ic, "");
450                                        if(gc)
451                                                imcb_chat_free(gc);
452                                        if(!strcmp(info, "STATUS MULTI_SUBSCRIBED"))
453                                        {
454                                                imcb_chat_new( ic, id );
455                                                g_snprintf(buf, 1024, "GET CHAT %s ADDER\n", id);
456                                                skype_write(ic, buf, strlen(buf));
457                                                g_snprintf(buf, 1024, "GET CHAT %s TOPIC\n", id);
458                                                skype_write(ic, buf, strlen(buf));
459                                        }
460                                        else if(!strcmp(info, "STATUS DIALOG") && sd->groupchat_with)
461                                        {
462                                                gc = imcb_chat_new( ic, id );
463                                                /* According to the docs this
464                                                 * is necessary. However it
465                                                 * does not seem the situation
466                                                 * and it would open an extra
467                                                 * window on our client, so
468                                                 * just leave it out. */
469                                                /*g_snprintf(buf, 1024, "OPEN CHAT %s\n", id);
470                                                skype_write(ic, buf, strlen(buf));*/
471                                                g_snprintf(buf, 1024, "%s@skype.com", sd->groupchat_with);
472                                                imcb_chat_add_buddy(gc, buf);
473                                                imcb_chat_add_buddy(gc, sd->username);
474                                                g_free(sd->groupchat_with);
475                                                sd->groupchat_with = NULL;
476                                                g_snprintf(buf, 1024, "GET CHAT %s ADDER\n", id);
477                                                skype_write(ic, buf, strlen(buf));
478                                                g_snprintf(buf, 1024, "GET CHAT %s TOPIC\n", id);
479                                                skype_write(ic, buf, strlen(buf));
480                                        }
481                                        else if(!strcmp(info, "STATUS UNSUBSCRIBED"))
482                                        {
483                                                gc = skype_chat_by_name(ic, id);
484                                                if(gc)
485                                                        gc->data = (void*)FALSE;
486                                        }
487                                        else if(!strncmp(info, "ADDER ", 6))
488                                        {
489                                                info += 6;
490                                                g_free(sd->adder);
491                                                sd->adder = g_strdup_printf("%s@skype.com", info);
492                                        }
493                                        else if(!strncmp(info, "TOPIC ", 6))
494                                        {
495                                                info += 6;
496                                                gc = skype_chat_by_name(ic, id);
497                                                if(gc && (sd->adder || sd->topic_wait))
498                                                {
499                                                        if(sd->topic_wait)
500                                                        {
501                                                                sd->adder = g_strdup(sd->username);
502                                                                sd->topic_wait = 0;
503                                                        }
504                                                        imcb_chat_topic(gc, sd->adder, info, 0);
505                                                        g_free(sd->adder);
506                                                        sd->adder = NULL;
507                                                }
508                                        }
509                                        else if(!strncmp(info, "ACTIVEMEMBERS ", 14))
510                                        {
511                                                info += 14;
512                                                gc = skype_chat_by_name(ic, id);
513                                                /* Hack! We set ->data to TRUE
514                                                 * while we're on the channel
515                                                 * so that we won't rejoin
516                                                 * after a /part. */
517                                                if(gc && !gc->data)
518                                                {
519                                                        char **members = g_strsplit(info, " ", 0);
520                                                        int i;
521                                                        for(i=0;members[i];i++)
522                                                        {
523                                                                if(!strcmp(members[i], sd->username))
524                                                                        continue;
525                                                                g_snprintf(buf, 1024, "%s@skype.com", members[i]);
526                                                                if(!g_list_find_custom(gc->in_room, buf, (GCompareFunc)strcmp))
527                                                                        imcb_chat_add_buddy(gc, buf);
528                                                        }
529                                                        imcb_chat_add_buddy(gc, sd->username);
530                                                        g_strfreev(members);
531                                                }
532                                        }
533                                }
534                        }
535                        lineptr++;
536                }
537                g_strfreev(lines);
538        }
539        else if( st == 0 || ( st < 0 && !sockerr_again() ) )
540        {
541                closesocket( sd->fd );
542                sd->fd = -1;
543
544                imcb_error( ic, "Error while reading from server" );
545                imc_logout( ic, TRUE );
546                return FALSE;
547        }
548        return TRUE;
549}
550
551gboolean skype_start_stream( struct im_connection *ic )
552{
553        struct skype_data *sd = ic->proto_data;
554        char *buf;
555        int st;
556
557        if(!sd)
558                return FALSE;
559
560        if( sd->bfd <= 0 )
561                sd->bfd = b_input_add( sd->fd, GAIM_INPUT_READ, skype_read_callback, ic );
562
563        /* This will download all buddies. */
564        buf = g_strdup_printf("SEARCH FRIENDS\n");
565        st = skype_write( ic, buf, strlen( buf ) );
566        g_free(buf);
567        buf = g_strdup_printf("SET USERSTATUS ONLINE\n");
568        skype_write( ic, buf, strlen( buf ) );
569        g_free(buf);
570        return st;
571}
572
573gboolean skype_connected( gpointer data, gint source, b_input_condition cond )
574{
575        struct im_connection *ic = data;
576        imcb_connected(ic);
577        return skype_start_stream(ic);
578}
579
580static void skype_login( account_t *acc )
581{
582        struct im_connection *ic = imcb_new( acc );
583        struct skype_data *sd = g_new0( struct skype_data, 1 );
584
585        ic->proto_data = sd;
586
587        imcb_log( ic, "Connecting" );
588        sd->fd = proxy_connect(acc->server, set_getint( &acc->set, "port" ), skype_connected, ic );
589        sd->username = g_strdup( acc->user );
590
591        sd->ic = ic;
592}
593
594static void skype_logout( struct im_connection *ic )
595{
596        struct skype_data *sd = ic->proto_data;
597        char *buf;
598
599        buf = g_strdup_printf("SET USERSTATUS OFFLINE\n");
600        skype_write( ic, buf, strlen( buf ) );
601        g_free(buf);
602
603        g_free(sd->username);
604        g_free(sd->handle);
605        g_free(sd);
606        ic->proto_data = NULL;
607}
608
609static int skype_buddy_msg( struct im_connection *ic, char *who, char *message, int flags )
610{
611        char *buf, *ptr, *nick;
612        int st;
613
614        nick = g_strdup(who);
615        ptr = strchr(nick, '@');
616        if(ptr)
617                *ptr = '\0';
618
619        buf = g_strdup_printf("MESSAGE %s %s\n", nick, message);
620        g_free(nick);
621        st = skype_write( ic, buf, strlen( buf ) );
622        g_free(buf);
623
624        return st;
625}
626
627const struct skype_away_state *skype_away_state_by_name( char *name )
628{
629        int i;
630
631        for( i = 0; skype_away_state_list[i].full_name; i ++ )
632                if( g_strcasecmp( skype_away_state_list[i].full_name, name ) == 0 )
633                        return( skype_away_state_list + i );
634
635        return NULL;
636}
637
638static void skype_set_away( struct im_connection *ic, char *state_txt, char *message )
639{
640        const struct skype_away_state *state;
641        char *buf;
642
643        if( strcmp( state_txt, GAIM_AWAY_CUSTOM ) == 0 )
644                state = skype_away_state_by_name( "Away" );
645        else
646                state = skype_away_state_by_name( state_txt );
647        buf = g_strdup_printf("SET USERSTATUS %s\n", state->code);
648        skype_write( ic, buf, strlen( buf ) );
649        g_free(buf);
650}
651
652static GList *skype_away_states( struct im_connection *ic )
653{
654        static GList *l = NULL;
655        int i;
656       
657        if( l == NULL )
658                for( i = 0; skype_away_state_list[i].full_name; i ++ )
659                        l = g_list_append( l, (void*) skype_away_state_list[i].full_name );
660       
661        return l;
662}
663
664static void skype_add_buddy( struct im_connection *ic, char *who, char *group )
665{
666        char *buf, *nick, *ptr;
667
668        nick = g_strdup(who);
669        ptr = strchr(nick, '@');
670        if(ptr)
671                *ptr = '\0';
672        buf = g_strdup_printf("SET USER %s BUDDYSTATUS 2 Please authorize me\n", nick);
673        skype_write( ic, buf, strlen( buf ) );
674        g_free(nick);
675}
676
677static void skype_remove_buddy( struct im_connection *ic, char *who, char *group )
678{
679        char *buf, *nick, *ptr;
680
681        nick = g_strdup(who);
682        ptr = strchr(nick, '@');
683        if(ptr)
684                *ptr = '\0';
685        buf = g_strdup_printf("SET USER %s BUDDYSTATUS 1\n", nick);
686        skype_write( ic, buf, strlen( buf ) );
687        g_free(nick);
688}
689
690void skype_chat_msg( struct groupchat *gc, char *message, int flags )
691{
692        struct im_connection *ic = gc->ic;
693        char *buf;
694        buf = g_strdup_printf("CHATMESSAGE %s %s\n", gc->title, message);
695        skype_write( ic, buf, strlen( buf ) );
696        g_free(buf);
697}
698
699void skype_chat_leave( struct groupchat *gc )
700{
701        struct im_connection *ic = gc->ic;
702        char *buf;
703        buf = g_strdup_printf("ALTER CHAT %s LEAVE\n", gc->title);
704        skype_write( ic, buf, strlen( buf ) );
705        g_free(buf);
706        gc->data = (void*)TRUE;
707}
708
709void skype_chat_invite(struct groupchat *gc, char *who, char *message)
710{
711        struct im_connection *ic = gc->ic;
712        char *buf, *ptr, *nick;
713        nick = g_strdup(message);
714        ptr = strchr(nick, '@');
715        if(ptr)
716                *ptr = '\0';
717        buf = g_strdup_printf("ALTER CHAT %s ADDMEMBERS %s\n", gc->title, nick);
718        skype_write( ic, buf, strlen( buf ) );
719        g_free(buf);
720        g_free(nick);
721}
722
723void skype_chat_topic(struct groupchat *gc, char *message)
724{
725        struct im_connection *ic = gc->ic;
726        struct skype_data *sd = ic->proto_data;
727        char *buf;
728        buf = g_strdup_printf("ALTER CHAT %s SETTOPIC %s\n", gc->title, message);
729        skype_write( ic, buf, strlen( buf ) );
730        g_free(buf);
731        sd->topic_wait = 1;
732}
733
734struct groupchat *skype_chat_with(struct im_connection *ic, char *who)
735{
736        struct skype_data *sd = ic->proto_data;
737        char *ptr, *nick, *buf;
738        nick = g_strdup(who);
739        ptr = strchr(nick, '@');
740        if(ptr)
741                *ptr = '\0';
742        buf = g_strdup_printf("CHAT CREATE %s\n", nick);
743        skype_write(ic, buf, strlen(buf));
744        g_free(buf);
745        sd->groupchat_with = g_strdup(nick);
746        g_free(nick);
747        /* We create a fake chat for now. We will replace it with a real one in
748         * the real callback. */
749        return(imcb_chat_new( ic, "" ));
750}
751
752void init_plugin(void)
753{
754        struct prpl *ret = g_new0( struct prpl, 1 );
755
756        ret->name = "skype";
757        ret->login = skype_login;
758        ret->init = skype_init;
759        ret->logout = skype_logout;
760        ret->buddy_msg = skype_buddy_msg;
761        ret->away_states = skype_away_states;
762        ret->set_away = skype_set_away;
763        ret->add_buddy = skype_add_buddy;
764        ret->remove_buddy = skype_remove_buddy;
765        ret->chat_msg = skype_chat_msg;
766        ret->chat_leave = skype_chat_leave;
767        ret->chat_invite = skype_chat_invite;
768        ret->chat_with = skype_chat_with;
769        ret->handle_cmp = g_strcasecmp;
770        ret->chat_topic = skype_chat_topic;
771        register_protocol( ret );
772}
Note: See TracBrowser for help on using the repository browser.