source: skype/skype.c @ a7af5f0

Last change on this file since a7af5f0 was a7af5f0, checked in by Miklos Vajna <vmiklos@…>, at 2007-10-17T22:59:41Z

fix incoming multiline messages - again
i broke it when adding groupchat support

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