source: skype/skype.c @ a5f4040

Last change on this file since a5f4040 was a5f4040, checked in by Miklos Vajna <vmiklos@…>, at 2008-12-21T20:08:44Z

remove the 'len' parameter of skype_write()

  • Property mode set to 100644
File size: 34.9 KB
Line 
1/*
2 *  skype.c - Skype plugin for BitlBee
3 *
4 *  Copyright (c) 2007, 2008 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#define _XOPEN_SOURCE
27#include <stdio.h>
28#include <poll.h>
29#include <bitlbee.h>
30#include <bitlbee/ssl_client.h>
31#include <glib.h>
32
33#define SKYPE_DEFAULT_SERVER "localhost"
34#define SKYPE_DEFAULT_PORT "2727"
35
36/*
37 * Enumerations
38 */
39
40typedef enum
41{
42        SKYPE_CALL_RINGING = 1,
43        SKYPE_CALL_MISSED,
44        SKYPE_CALL_CANCELLED,
45        SKYPE_CALL_FINISHED,
46        SKYPE_CALL_REFUSED
47} skype_call_status;
48
49typedef enum
50{
51        SKYPE_FILETRANSFER_NEW = 1,
52        SKYPE_FILETRANSFER_FAILED
53} skype_filetransfer_status;
54
55/*
56 * Structures
57 */
58
59struct skype_data
60{
61        struct im_connection *ic;
62        char *username;
63        /* The effective file descriptor. We store it here so any function can
64         * write() to it. */
65        int fd;
66        /* File descriptor returned by bitlbee. we store it so we know when
67         * we're connected and when we aren't. */
68        int bfd;
69        /* ssl_getfd() uses this to get the file desciptor. */
70        void *ssl;
71        /* When we receive a new message id, we query the properties, finally
72         * the chatname. Store the properties here so that we can use
73         * imcb_buddy_msg() when we got the chatname. */
74        char *handle;
75        /* List, because of multiline messages. */
76        GList *body;
77        char *type;
78        /* This is necessary because we send a notification when we get the
79         * handle. So we store the state here and then we can send a
80         * notification about the handle is in a given status. */
81        skype_call_status call_status;
82        char *call_id;
83        char *call_duration;
84        /* If the call is outgoing or not */
85        int call_out;
86        /* Same for file transfers. */
87        skype_filetransfer_status filetransfer_status;
88        /* Using /j #nick we want to have a groupchat with two people. Usually
89         * not (default). */
90        char* groupchat_with;
91        /* The user who invited us to the chat. */
92        char* adder;
93        /* If we are waiting for a confirmation about we changed the topic. */
94        int topic_wait;
95        /* These are used by the info command. */
96        char *info_fullname;
97        char *info_phonehome;
98        char *info_phoneoffice;
99        char *info_phonemobile;
100        char *info_nrbuddies;
101        char *info_tz;
102        char *info_seen;
103        char *info_birthday;
104        char *info_sex;
105        char *info_language;
106        char *info_country;
107        char *info_province;
108        char *info_city;
109        char *info_homepage;
110        char *info_about;
111        /* When a call fails, we get the reason and later we get the failure
112         * event, so store the failure code here till then */
113        int failurereason;
114};
115
116struct skype_away_state
117{
118        char *code;
119        char *full_name;
120};
121
122struct skype_buddy_ask_data
123{
124        struct im_connection *ic;
125        /* This is also used for call IDs for simplicity */
126        char *handle;
127};
128
129/*
130 * Tables
131 */
132
133const struct skype_away_state skype_away_state_list[] =
134{
135        { "ONLINE",  "Online" },
136        { "SKYPEME",  "Skype Me" },
137        { "AWAY",   "Away" },
138        { "NA",    "Not available" },
139        { "DND",      "Do Not Disturb" },
140        { "INVISIBLE",      "Invisible" },
141        { "OFFLINE",      "Offline" },
142        { NULL, NULL}
143};
144
145/*
146 * Functions
147 */
148
149int skype_write( struct im_connection *ic, char *buf )
150{
151        struct skype_data *sd = ic->proto_data;
152        struct pollfd pfd[1];
153        int len = strlen(buf);
154
155        pfd[0].fd = sd->fd;
156        pfd[0].events = POLLOUT;
157
158        /* This poll is necessary or we'll get a SIGPIPE when we write() to
159         * sd->fd. */
160        poll(pfd, 1, 1000);
161        if(pfd[0].revents & POLLHUP)
162        {
163                imc_logout( ic, TRUE );
164                return FALSE;
165        }
166        ssl_write( sd->ssl, buf, len );
167
168        return TRUE;
169}
170
171static void skype_buddy_ask_yes( void *data )
172{
173        struct skype_buddy_ask_data *bla = data;
174        char *buf = g_strdup_printf("SET USER %s ISAUTHORIZED TRUE", bla->handle);
175        skype_write( bla->ic, buf );
176        g_free(buf);
177        g_free(bla->handle);
178        g_free(bla);
179}
180
181static void skype_buddy_ask_no( void *data )
182{
183        struct skype_buddy_ask_data *bla = data;
184        char *buf = g_strdup_printf("SET USER %s ISAUTHORIZED FALSE", bla->handle);
185        skype_write( bla->ic, buf );
186        g_free(buf);
187        g_free(bla->handle);
188        g_free(bla);
189}
190
191void skype_buddy_ask( struct im_connection *ic, char *handle, char *message)
192{
193        struct skype_buddy_ask_data *bla = g_new0( struct skype_buddy_ask_data, 1 );
194        char *buf;
195
196        bla->ic = ic;
197        bla->handle = g_strdup(handle);
198
199        buf = g_strdup_printf( "The user %s wants to add you to his/her buddy list, saying: '%s'.", handle, message);
200        imcb_ask( ic, buf, bla, skype_buddy_ask_yes, skype_buddy_ask_no );
201        g_free( buf );
202}
203
204static void skype_call_ask_yes( void *data )
205{
206        struct skype_buddy_ask_data *bla = data;
207        char *buf = g_strdup_printf("SET CALL %s STATUS INPROGRESS", bla->handle);
208        skype_write( bla->ic, buf );
209        g_free(buf);
210        g_free(bla->handle);
211        g_free(bla);
212}
213
214static void skype_call_ask_no( void *data )
215{
216        struct skype_buddy_ask_data *bla = data;
217        char *buf = g_strdup_printf("SET CALL %s STATUS FINISHED", bla->handle);
218        skype_write( bla->ic, buf );
219        g_free(buf);
220        g_free(bla->handle);
221        g_free(bla);
222}
223
224void skype_call_ask( struct im_connection *ic, char *call_id, char *message)
225{
226        struct skype_buddy_ask_data *bla = g_new0( struct skype_buddy_ask_data, 1 );
227
228        bla->ic = ic;
229        bla->handle = g_strdup(call_id);
230
231        imcb_ask( ic, message, bla, skype_call_ask_yes, skype_call_ask_no );
232}
233struct groupchat *skype_chat_by_name( struct im_connection *ic, char *name )
234{
235        struct groupchat *ret;
236
237        for( ret = ic->groupchats; ret; ret = ret->next )
238        {
239                if(strcmp(name, ret->title ) == 0 )
240                        break;
241        }
242
243        return ret;
244}
245
246static char *skype_call_strerror(int err)
247{
248        switch(err) {
249                case 1:
250                        return "Miscellaneous error";
251                case 2:
252                        return "User or phone number does not exist.";
253                case 3:
254                        return "User is offline";
255                case 4:
256                        return "No proxy found";
257                case 5:
258                        return "Session terminated.";
259                case 6:
260                        return "No common codec found.";
261                case 7:
262                        return "Sound I/O error.";
263                case 8:
264                        return "Problem with remote sound device.";
265                case 9:
266                        return "Call blocked by recipient.";
267                case 10:
268                        return "Recipient not a friend.";
269                case 11:
270                        return "Current user not authorized by recipient.";
271                case 12:
272                        return "Sound recording error.";
273                default:
274                        return "Unknown error";
275        }
276}
277
278static gboolean skype_read_callback( gpointer data, gint fd, b_input_condition cond )
279{
280        struct im_connection *ic = data;
281        struct skype_data *sd = ic->proto_data;
282        char buf[1024];
283        int st;
284        char **lines, **lineptr, *line, *ptr;
285
286        if( !sd || sd->fd == -1 )
287                return FALSE;
288        /* Read the whole data. */
289        st = ssl_read( sd->ssl, buf, sizeof( buf ) );
290        if( st > 0 )
291        {
292                buf[st] = '\0';
293                /* Then split it up to lines. */
294                lines = g_strsplit(buf, "\n", 0);
295                lineptr = lines;
296                while((line = *lineptr))
297                {
298                        if(!strlen(line))
299                                break;
300                        if(!strncmp(line, "USERS ", 6))
301                        {
302                                char **i;
303                                char **nicks;
304
305                                nicks = g_strsplit(line + 6, ", ", 0);
306                                i = nicks;
307                                while(*i)
308                                {
309                                        g_snprintf(buf, 1024, "GET USER %s ONLINESTATUS\n", *i);
310                                        skype_write( ic, buf );
311                                        i++;
312                                }
313                                g_strfreev(nicks);
314                        }
315                        else if(!strncmp(line, "USER ", 5))
316                        {
317                                int flags = 0;
318                                char *status = strrchr(line, ' ');
319                                char *user = strchr(line, ' ');
320                                status++;
321                                ptr = strchr(++user, ' ');
322                                *ptr = '\0';
323                                ptr++;
324                                if(!strncmp(ptr, "ONLINESTATUS ", 13) &&
325                                                strcmp(user, sd->username) != 0
326                                                && strcmp(user, "echo123") != 0)
327                                {
328                                        ptr = g_strdup_printf("%s@skype.com", user);
329                                        imcb_add_buddy(ic, ptr, NULL);
330                                        if(strcmp(status, "OFFLINE") && (strcmp(status, "SKYPEOUT") || !set_getbool(&ic->acc->set, "skypeout_offline")))
331                                                flags |= OPT_LOGGED_IN;
332                                        if(strcmp(status, "ONLINE") != 0 && strcmp(status, "SKYPEME") != 0)
333                                                flags |= OPT_AWAY;
334                                        imcb_buddy_status(ic, ptr, flags, NULL, NULL);
335                                        g_free(ptr);
336                                }
337                                else if(!strncmp(ptr, "RECEIVEDAUTHREQUEST ", 20))
338                                {
339                                        char *message = ptr + 20;
340                                        if(strlen(message))
341                                                skype_buddy_ask(ic, user, message);
342                                }
343                                else if(!strncmp(ptr, "BUDDYSTATUS ", 12))
344                                {
345                                        char *st = ptr + 12;
346                                        if(!strcmp(st, "3"))
347                                        {
348                                                char *buf = g_strdup_printf("%s@skype.com", user);
349                                                imcb_add_buddy(ic, buf, NULL);
350                                                g_free(buf);
351                                        }
352                                }
353                                else if(!strncmp(ptr, "FULLNAME ", 9))
354                                        sd->info_fullname = g_strdup_printf("%s", ptr + 9);
355                                else if(!strncmp(ptr, "PHONE_HOME ", 11))
356                                        sd->info_phonehome = g_strdup_printf("%s", ptr + 11);
357                                else if(!strncmp(ptr, "PHONE_OFFICE ", 13))
358                                        sd->info_phoneoffice = g_strdup_printf("%s", ptr + 13);
359                                else if(!strncmp(ptr, "PHONE_MOBILE ", 13))
360                                        sd->info_phonemobile = g_strdup_printf("%s", ptr + 13);
361                                else if(!strncmp(ptr, "NROF_AUTHED_BUDDIES ", 20))
362                                        sd->info_nrbuddies = g_strdup_printf("%s", ptr + 20);
363                                else if(!strncmp(ptr, "TIMEZONE ", 9))
364                                        sd->info_tz = g_strdup_printf("%s", ptr + 9);
365                                else if(!strncmp(ptr, "LASTONLINETIMESTAMP ", 20))
366                                        sd->info_seen = g_strdup_printf("%s", ptr + 20);
367                                else if(!strncmp(ptr, "BIRTHDAY ", 9))
368                                        sd->info_birthday = g_strdup_printf("%s", ptr + 9);
369                                else if(!strncmp(ptr, "SEX ", 4))
370                                        sd->info_sex = g_strdup_printf("%s", ptr + 4);
371                                else if(!strncmp(ptr, "LANGUAGE ", 9))
372                                        sd->info_language = g_strdup_printf("%s", ptr + 9);
373                                else if(!strncmp(ptr, "COUNTRY ", 8))
374                                        sd->info_country = g_strdup_printf("%s", ptr + 8);
375                                else if(!strncmp(ptr, "PROVINCE ", 9))
376                                        sd->info_province = g_strdup_printf("%s", ptr + 9);
377                                else if(!strncmp(ptr, "CITY ", 5))
378                                        sd->info_city = g_strdup_printf("%s", ptr + 5);
379                                else if(!strncmp(ptr, "HOMEPAGE ", 9))
380                                        sd->info_homepage = g_strdup_printf("%s", ptr + 9);
381                                else if(!strncmp(ptr, "ABOUT ", 6))
382                                {
383                                        sd->info_about = g_strdup_printf("%s", ptr + 6);
384
385                                        GString *st = g_string_new("Contact Information\n");
386                                        g_string_append_printf(st, "Skype Name: %s\n", user);
387                                        if(sd->info_fullname)
388                                        {
389                                                if(strlen(sd->info_fullname))
390                                                        g_string_append_printf(st, "Full Name: %s\n", sd->info_fullname);
391                                                g_free(sd->info_fullname);
392                                        }
393                                        if(sd->info_phonehome)
394                                        {
395                                                if(strlen(sd->info_phonehome))
396                                                        g_string_append_printf(st, "Home Phone: %s\n", sd->info_phonehome);
397                                                g_free(sd->info_phonehome);
398                                        }
399                                        if(sd->info_phoneoffice)
400                                        {
401                                                if(strlen(sd->info_phoneoffice))
402                                                        g_string_append_printf(st, "Office Phone: %s\n", sd->info_phoneoffice);
403                                                g_free(sd->info_phoneoffice);
404                                        }
405                                        if(sd->info_phonemobile)
406                                        {
407                                                if(strlen(sd->info_phonemobile))
408                                                        g_string_append_printf(st, "Mobile Phone: %s\n", sd->info_phonemobile);
409                                                g_free(sd->info_phonemobile);
410                                        }
411                                        g_string_append_printf(st, "Personal Information\n");
412                                        if(sd->info_nrbuddies)
413                                        {
414                                                if(strlen(sd->info_nrbuddies))
415                                                        g_string_append_printf(st, "Contacts: %s\n", sd->info_nrbuddies);
416                                                g_free(sd->info_nrbuddies);
417                                        }
418                                        if(sd->info_tz)
419                                        {
420                                                if(strlen(sd->info_tz))
421                                                {
422                                                        char ib[256];
423                                                        time_t t = time(NULL);
424                                                        t += atoi(sd->info_tz)-(60*60*24);
425                                                        struct tm *gt = gmtime(&t);
426                                                        strftime(ib, 256, "%H:%M:%S", gt);
427                                                        g_string_append_printf(st, "Local Time: %s\n", ib);
428                                                }
429                                                g_free(sd->info_tz);
430                                        }
431                                        if(sd->info_seen)
432                                        {
433                                                if(strlen(sd->info_seen))
434                                                {
435                                                        char ib[256];
436                                                        time_t it = atoi(sd->info_seen);
437                                                        struct tm *tm = localtime(&it);
438                                                        strftime(ib, 256, ("%Y. %m. %d. %H:%M"), tm);
439                                                        g_string_append_printf(st, "Last Seen: %s\n", ib);
440                                                }
441                                                g_free(sd->info_seen);
442                                        }
443                                        if(sd->info_birthday)
444                                        {
445                                                if(strlen(sd->info_birthday) && strcmp(sd->info_birthday, "0"))
446                                                {
447                                                        char ib[256];
448                                                        struct tm tm;
449                                                        strptime(sd->info_birthday, "%Y%m%d", &tm);
450                                                        strftime(ib, 256, "%B %d, %Y", &tm);
451                                                        g_string_append_printf(st, "Birthday: %s\n", ib);
452
453                                                        strftime(ib, 256, "%Y", &tm);
454                                                        int year = atoi(ib);
455                                                        time_t t = time(NULL);
456                                                        struct tm *lt = localtime(&t);
457                                                        g_string_append_printf(st, "Age: %d\n", lt->tm_year+1900-year);
458                                                }
459                                                g_free(sd->info_birthday);
460                                        }
461                                        if(sd->info_sex)
462                                        {
463                                                if(strlen(sd->info_sex))
464                                                {
465                                                        char *iptr = sd->info_sex;
466                                                        while(*iptr++)
467                                                                *iptr = tolower(*iptr);
468                                                        g_string_append_printf(st, "Gender: %s\n", sd->info_sex);
469                                                }
470                                                g_free(sd->info_sex);
471                                        }
472                                        if(sd->info_language)
473                                        {
474                                                if(strlen(sd->info_language))
475                                                {
476                                                        char *iptr = strchr(sd->info_language, ' ');
477                                                        if(iptr)
478                                                                iptr++;
479                                                        else
480                                                                iptr = sd->info_language;
481                                                        g_string_append_printf(st, "Language: %s\n", iptr);
482                                                }
483                                                g_free(sd->info_language);
484                                        }
485                                        if(sd->info_country)
486                                        {
487                                                if(strlen(sd->info_country))
488                                                {
489                                                        char *iptr = strchr(sd->info_country, ' ');
490                                                        if(iptr)
491                                                                iptr++;
492                                                        else
493                                                                iptr = sd->info_country;
494                                                        g_string_append_printf(st, "Country: %s\n", iptr);
495                                                }
496                                                g_free(sd->info_country);
497                                        }
498                                        if(sd->info_province)
499                                        {
500                                                if(strlen(sd->info_province))
501                                                        g_string_append_printf(st, "Region: %s\n", sd->info_province);
502                                                g_free(sd->info_province);
503                                        }
504                                        if(sd->info_city)
505                                        {
506                                                if(strlen(sd->info_city))
507                                                        g_string_append_printf(st, "City: %s\n", sd->info_city);
508                                                g_free(sd->info_city);
509                                        }
510                                        if(sd->info_homepage)
511                                        {
512                                                if(strlen(sd->info_homepage))
513                                                        g_string_append_printf(st, "Homepage: %s\n", sd->info_homepage);
514                                                g_free(sd->info_homepage);
515                                        }
516                                        if(sd->info_about)
517                                        {
518                                                if(strlen(sd->info_about))
519                                                        g_string_append_printf(st, "%s\n", sd->info_about);
520                                                g_free(sd->info_about);
521                                        }
522                                        imcb_log(ic, "%s", st->str);
523                                        g_string_free(st, TRUE);
524                                }
525                        }
526                        else if(!strncmp(line, "CHATMESSAGE ", 12))
527                        {
528                                char *id = strchr(line, ' ');
529                                if(++id)
530                                {
531                                        char *info = strchr(id, ' ');
532                                        *info = '\0';
533                                        info++;
534                                        if(!strcmp(info, "STATUS RECEIVED"))
535                                        {
536                                                /* New message ID:
537                                                 * (1) Request its from field
538                                                 * (2) Request its body
539                                                 * (3) Request its type
540                                                 * (4) Query chatname
541                                                 */
542                                                g_snprintf(buf, 1024, "GET CHATMESSAGE %s FROM_HANDLE\n", id);
543                                                skype_write( ic, buf );
544                                                g_snprintf(buf, 1024, "GET CHATMESSAGE %s BODY\n", id);
545                                                skype_write( ic, buf );
546                                                g_snprintf(buf, 1024, "GET CHATMESSAGE %s TYPE\n", id);
547                                                skype_write( ic, buf );
548                                                g_snprintf(buf, 1024, "GET CHATMESSAGE %s CHATNAME\n", id);
549                                                skype_write( ic, buf );
550                                        }
551                                        else if(!strncmp(info, "FROM_HANDLE ", 12))
552                                        {
553                                                info += 12;
554                                                /* New from field value. Store
555                                                 * it, then we can later use it
556                                                 * when we got the message's
557                                                 * body. */
558                                                g_free(sd->handle);
559                                                sd->handle = g_strdup_printf("%s@skype.com", info);
560                                        }
561                                        else if(!strncmp(info, "EDITED_BY ", 10))
562                                        {
563                                                info += 10;
564                                                /* This is the same as
565                                                 * FROM_HANDLE, except that we
566                                                 * never request these lines
567                                                 * from Skype, we just get
568                                                 * them. */
569                                                g_free(sd->handle);
570                                                sd->handle = g_strdup_printf("%s@skype.com", info);
571                                        }
572                                        else if(!strncmp(info, "BODY ", 5))
573                                        {
574                                                info += 5;
575                                                sd->body = g_list_append(sd->body, g_strdup(info));
576                                        }
577                                        else if(!strncmp(info, "TYPE ", 5))
578                                        {
579                                                info += 5;
580                                                g_free(sd->type);
581                                                sd->type = g_strdup(info);
582                                        }
583                                        else if(!strncmp(info, "CHATNAME ", 9))
584                                        {
585                                                info += 9;
586                                                if(sd->handle && sd->body && sd->type)
587                                                {
588                                                        struct groupchat *gc = skype_chat_by_name(ic, info);
589                                                        int i;
590                                                        for(i=0;i<g_list_length(sd->body);i++)
591                                                        {
592                                                                char *body = g_list_nth_data(sd->body, i);
593                                                                if(!strcmp(sd->type, "SAID") || !strcmp(sd->type, "EMOTED"))
594                                                                {
595                                                                        char *st;
596                                                                        if(!strcmp(sd->type, "SAID"))
597                                                                                st = g_strdup(body);
598                                                                        else
599                                                                        {
600                                                                                st = g_strdup_printf("/me %s", body);
601                                                                        }
602                                                                        if(!gc)
603                                                                                /* Private message */
604                                                                                imcb_buddy_msg(ic, sd->handle, st, 0, 0);
605                                                                        else
606                                                                                /* Groupchat message */
607                                                                                imcb_chat_msg(gc, sd->handle, st, 0, 0);
608                                                                        g_free(st);
609                                                                }
610                                                                else if(!strcmp(sd->type, "SETTOPIC"))
611                                                                {
612                                                                        if(gc)
613                                                                                imcb_chat_topic(gc, sd->handle, body, 0);
614                                                                }
615                                                                else if(!strcmp(sd->type, "LEFT"))
616                                                                {
617                                                                        if(gc)
618                                                                                imcb_chat_remove_buddy(gc, sd->handle, NULL);
619                                                                }
620                                                        }
621                                                        g_list_free(sd->body);
622                                                        sd->body = NULL;
623                                                }
624                                        }
625                                }
626                        }
627                        else if(!strncmp(line, "CALL ", 5))
628                        {
629                                char *id = strchr(line, ' ');
630                                if(++id)
631                                {
632                                        char *info = strchr(id, ' ');
633                                        *info = '\0';
634                                        info++;
635                                        if(!strncmp(info, "FAILUREREASON ", 14))
636                                                sd->failurereason = atoi(strchr(info, ' '));
637                                        else if(!strcmp(info, "STATUS RINGING"))
638                                        {
639                                                if(sd->call_id)
640                                                        g_free(sd->call_id);
641                                                sd->call_id = g_strdup(id);
642                                                g_snprintf(buf, 1024, "GET CALL %s PARTNER_HANDLE\n", id);
643                                                skype_write( ic, buf );
644                                                sd->call_status = SKYPE_CALL_RINGING;
645                                        }
646                                        else if(!strcmp(info, "STATUS MISSED"))
647                                        {
648                                                g_snprintf(buf, 1024, "GET CALL %s PARTNER_HANDLE\n", id);
649                                                skype_write( ic, buf );
650                                                sd->call_status = SKYPE_CALL_MISSED;
651                                        }
652                                        else if(!strcmp(info, "STATUS CANCELLED"))
653                                        {
654                                                        g_snprintf(buf, 1024, "GET CALL %s PARTNER_HANDLE\n", id);
655                                                        skype_write( ic, buf );
656                                                        sd->call_status = SKYPE_CALL_CANCELLED;
657                                        }
658                                        else if(!strcmp(info, "STATUS FINISHED"))
659                                        {
660                                                g_snprintf(buf, 1024, "GET CALL %s PARTNER_HANDLE\n", id);
661                                                skype_write( ic, buf );
662                                                sd->call_status = SKYPE_CALL_FINISHED;
663                                        }
664                                        else if(!strcmp(info, "STATUS REFUSED"))
665                                        {
666                                                g_snprintf(buf, 1024, "GET CALL %s PARTNER_HANDLE\n", id);
667                                                skype_write( ic, buf );
668                                                sd->call_status = SKYPE_CALL_REFUSED;
669                                        }
670                                        else if(!strcmp(info, "STATUS UNPLACED"))
671                                        {
672                                                if(sd->call_id)
673                                                        g_free(sd->call_id);
674                                                /* Save the ID for later usage (Cancel/Finish). */
675                                                sd->call_id = g_strdup(id);
676                                                sd->call_out = TRUE;
677                                        }
678                                        else if(!strcmp(info, "STATUS FAILED"))
679                                        {
680                                                imcb_error(ic, "Call failed: %s", skype_call_strerror(sd->failurereason));
681                                                sd->call_id = NULL;
682                                        }
683                                        else if(!strncmp(info, "DURATION ", 9))
684                                        {
685                                                if(sd->call_duration)
686                                                        g_free(sd->call_duration);
687                                                sd->call_duration = g_strdup(info+9);
688                                        }
689                                        else if(!strncmp(info, "PARTNER_HANDLE ", 15))
690                                        {
691                                                info += 15;
692                                                if(sd->call_status) {
693                                                        switch(sd->call_status)
694                                                        {
695                                                                case SKYPE_CALL_RINGING:
696                                                                        if(sd->call_out)
697                                                                                imcb_log(ic, "You are currently ringing the user %s.", info);
698                                                                        else
699                                                                        {
700                                                                                g_snprintf(buf, 1024, "The user %s is currently ringing you.", info);
701                                                                                skype_call_ask(ic, sd->call_id, buf);
702                                                                        }
703                                                                        break;
704                                                                case SKYPE_CALL_MISSED:
705                                                                        imcb_log(ic, "You have missed a call from user %s.", info);
706                                                                        break;
707                                                                case SKYPE_CALL_CANCELLED:
708                                                                        imcb_log(ic, "You cancelled the call to the user %s.", info);
709                                                                        sd->call_status = 0;
710                                                                        sd->call_out = FALSE;
711                                                                        break;
712                                                                case SKYPE_CALL_REFUSED:
713                                                                        if(sd->call_out)
714                                                                                imcb_log(ic, "The user %s refused the call.", info);
715                                                                        else
716                                                                                imcb_log(ic, "You refused the call from user %s.", info);
717                                                                        sd->call_out = FALSE;
718                                                                        break;
719                                                                case SKYPE_CALL_FINISHED:
720                                                                        if(sd->call_duration)
721                                                                                imcb_log(ic, "You finished the call to the user %s (duration: %s seconds).", info, sd->call_duration);
722                                                                        else
723                                                                                imcb_log(ic, "You finished the call to the user %s.", info);
724                                                                        sd->call_out = FALSE;
725                                                                        break;
726                                                                default:
727                                                                        /* Don't be noisy, ignore other statuses for now. */
728                                                                        break;
729                                                        }
730                                                        sd->call_status = 0;
731                                                }
732                                        }
733                                }
734                        }
735                        else if(!strncmp(line, "FILETRANSFER ", 13))
736                        {
737                                char *id = strchr(line, ' ');
738                                if(++id)
739                                {
740                                        char *info = strchr(id, ' ');
741                                        *info = '\0';
742                                        info++;
743                                        if(!strcmp(info, "STATUS NEW"))
744                                        {
745                                                g_snprintf(buf, 1024, "GET FILETRANSFER %s PARTNER_HANDLE\n", id);
746                                                skype_write( ic, buf );
747                                                sd->filetransfer_status = SKYPE_FILETRANSFER_NEW;
748                                        }
749                                        else if(!strcmp(info, "STATUS FAILED"))
750                                        {
751                                                g_snprintf(buf, 1024, "GET FILETRANSFER %s PARTNER_HANDLE\n", id);
752                                                skype_write( ic, buf );
753                                                sd->filetransfer_status = SKYPE_FILETRANSFER_FAILED;
754                                        }
755                                        else if(!strncmp(info, "PARTNER_HANDLE ", 15))
756                                        {
757                                                info += 15;
758                                                if(sd->filetransfer_status) {
759                                                        switch(sd->filetransfer_status)
760                                                        {
761                                                                case SKYPE_FILETRANSFER_NEW:
762                                                                        imcb_log(ic, "The user %s offered a new file for you.", info);
763                                                                        break;
764                                                                case SKYPE_FILETRANSFER_FAILED:
765                                                                        imcb_log(ic, "Failed to transfer file from user %s.", info);
766                                                                        break;
767                                                        }
768                                                        sd->filetransfer_status = 0;
769                                                }
770                                        }
771                                }
772                        }
773                        else if(!strncmp(line, "CHAT ", 5))
774                        {
775                                char *id = strchr(line, ' ');
776                                if(++id)
777                                {
778                                        char *info = strchr(id, ' ');
779                                        if(info)
780                                                *info = '\0';
781                                        info++;
782                                        /* Remove fake chat if we created one in skype_chat_with() */
783                                        struct groupchat *gc = skype_chat_by_name(ic, "");
784                                        if(gc)
785                                                imcb_chat_free(gc);
786                                        if(!strcmp(info, "STATUS MULTI_SUBSCRIBED"))
787                                        {
788                                                imcb_chat_new( ic, id );
789                                                g_snprintf(buf, 1024, "GET CHAT %s ADDER\n", id);
790                                                skype_write(ic, buf);
791                                                g_snprintf(buf, 1024, "GET CHAT %s TOPIC\n", id);
792                                                skype_write(ic, buf);
793                                        }
794                                        else if(!strcmp(info, "STATUS DIALOG") && sd->groupchat_with)
795                                        {
796                                                gc = imcb_chat_new( ic, id );
797                                                /* According to the docs this
798                                                 * is necessary. However it
799                                                 * does not seem the situation
800                                                 * and it would open an extra
801                                                 * window on our client, so
802                                                 * just leave it out. */
803                                                /*g_snprintf(buf, 1024, "OPEN CHAT %s\n", id);
804                                                skype_write(ic, buf);*/
805                                                g_snprintf(buf, 1024, "%s@skype.com", sd->groupchat_with);
806                                                imcb_chat_add_buddy(gc, buf);
807                                                imcb_chat_add_buddy(gc, sd->username);
808                                                g_free(sd->groupchat_with);
809                                                sd->groupchat_with = NULL;
810                                                g_snprintf(buf, 1024, "GET CHAT %s ADDER\n", id);
811                                                skype_write(ic, buf);
812                                                g_snprintf(buf, 1024, "GET CHAT %s TOPIC\n", id);
813                                                skype_write(ic, buf);
814                                        }
815                                        else if(!strcmp(info, "STATUS UNSUBSCRIBED"))
816                                        {
817                                                gc = skype_chat_by_name(ic, id);
818                                                if(gc)
819                                                        gc->data = (void*)FALSE;
820                                        }
821                                        else if(!strncmp(info, "ADDER ", 6))
822                                        {
823                                                info += 6;
824                                                g_free(sd->adder);
825                                                sd->adder = g_strdup_printf("%s@skype.com", info);
826                                        }
827                                        else if(!strncmp(info, "TOPIC ", 6))
828                                        {
829                                                info += 6;
830                                                gc = skype_chat_by_name(ic, id);
831                                                if(gc && (sd->adder || sd->topic_wait))
832                                                {
833                                                        if(sd->topic_wait)
834                                                        {
835                                                                sd->adder = g_strdup(sd->username);
836                                                                sd->topic_wait = 0;
837                                                        }
838                                                        imcb_chat_topic(gc, sd->adder, info, 0);
839                                                        g_free(sd->adder);
840                                                        sd->adder = NULL;
841                                                }
842                                        }
843                                        else if(!strncmp(info, "ACTIVEMEMBERS ", 14))
844                                        {
845                                                info += 14;
846                                                gc = skype_chat_by_name(ic, id);
847                                                /* Hack! We set ->data to TRUE
848                                                 * while we're on the channel
849                                                 * so that we won't rejoin
850                                                 * after a /part. */
851                                                if(gc && !gc->data)
852                                                {
853                                                        char **members = g_strsplit(info, " ", 0);
854                                                        int i;
855                                                        for(i=0;members[i];i++)
856                                                        {
857                                                                if(!strcmp(members[i], sd->username))
858                                                                        continue;
859                                                                g_snprintf(buf, 1024, "%s@skype.com", members[i]);
860                                                                if(!g_list_find_custom(gc->in_room, buf, (GCompareFunc)strcmp))
861                                                                        imcb_chat_add_buddy(gc, buf);
862                                                        }
863                                                        imcb_chat_add_buddy(gc, sd->username);
864                                                        g_strfreev(members);
865                                                }
866                                        }
867                                }
868                        }
869                        else if(!strncmp(line, "PASSWORD ", 9))
870                        {
871                                if(!strncmp(line+9, "OK", 2))
872                                        imcb_connected(ic);
873                                else
874                                {
875                                        imcb_error(ic, "Authentication Failed");
876                                        imc_logout( ic, TRUE );
877                                }
878                        }
879                        else if(!strncmp(line, "PROFILE PSTN_BALANCE ", 21))
880                        {
881                                imcb_log(ic, "SkypeOut balance value is '%s'.", line+21);
882                        }
883                        else if(!strncmp(line, "PING", 4))
884                        {
885                                g_snprintf(buf, 1024, "PONG\n");
886                                skype_write(ic, buf);
887                        }
888                        else if(!strncmp(line, "CHATS ", 6))
889                        {
890                                char **i;
891                                char **chats = g_strsplit(line + 6, ", ", 0);
892
893                                i = chats;
894                                while (*i)
895                                {
896                                        g_snprintf(buf, 1024, "GET CHAT %s STATUS\n", *i);
897                                        skype_write( ic, buf );
898                                        g_snprintf(buf, 1024, "GET CHAT %s ACTIVEMEMBERS\n", *i);
899                                        skype_write( ic, buf );
900                                        i++;
901                                }
902                                g_strfreev(chats);
903                        }
904                        lineptr++;
905                }
906                g_strfreev(lines);
907        }
908        else if( st == 0 || ( st < 0 && !sockerr_again() ) )
909        {
910                closesocket( sd->fd );
911                sd->fd = -1;
912
913                imcb_error( ic, "Error while reading from server" );
914                imc_logout( ic, TRUE );
915                return FALSE;
916        }
917        return TRUE;
918}
919
920gboolean skype_start_stream( struct im_connection *ic )
921{
922        struct skype_data *sd = ic->proto_data;
923        char *buf;
924        int st;
925
926        if(!sd)
927                return FALSE;
928
929        if( sd->bfd <= 0 )
930                sd->bfd = b_input_add( sd->fd, GAIM_INPUT_READ, skype_read_callback, ic );
931
932        /* Log in */
933        buf = g_strdup_printf("USERNAME %s\n", ic->acc->user);
934        st = skype_write( ic, buf );
935        g_free(buf);
936        buf = g_strdup_printf("PASSWORD %s\n", ic->acc->pass);
937        st = skype_write( ic, buf );
938        g_free(buf);
939
940        /* This will download all buddies. */
941        buf = g_strdup_printf("SEARCH FRIENDS\n");
942        st = skype_write( ic, buf );
943        g_free(buf);
944        buf = g_strdup_printf("SET USERSTATUS ONLINE\n");
945        skype_write( ic, buf );
946        g_free(buf);
947
948        /* Auto join to bookmarked chats if requested.*/
949        if (set_getbool(&ic->acc->set, "auto_join")) {
950                buf = g_strdup_printf("SEARCH BOOKMARKEDCHATS\n");
951                skype_write( ic, buf );
952                g_free(buf);
953        }
954        return st;
955}
956
957gboolean skype_connected( gpointer data, void *source, b_input_condition cond )
958{
959        struct im_connection *ic = data;
960        struct skype_data *sd = ic->proto_data;
961        if(!source)
962        {
963                sd->ssl = NULL;
964                imcb_error( ic, "Could not connect to server" );
965                imc_logout( ic, TRUE );
966                return FALSE;
967        }
968        imcb_log( ic, "Connected to server, logging in" );
969        return skype_start_stream(ic);
970}
971
972static void skype_login( account_t *acc )
973{
974        struct im_connection *ic = imcb_new( acc );
975        struct skype_data *sd = g_new0( struct skype_data, 1 );
976
977        ic->proto_data = sd;
978
979        imcb_log( ic, "Connecting" );
980        sd->ssl = ssl_connect(set_getstr( &acc->set, "server" ), set_getint( &acc->set, "port" ), skype_connected, ic );
981        sd->fd = sd->ssl ? ssl_getfd( sd->ssl ) : -1;
982        sd->username = g_strdup( acc->user );
983
984        sd->ic = ic;
985
986        if (set_getbool(&acc->set, "skypeconsole"))
987                imcb_add_buddy(ic, "skypeconsole", NULL);
988}
989
990static void skype_logout( struct im_connection *ic )
991{
992        struct skype_data *sd = ic->proto_data;
993        char *buf;
994
995        buf = g_strdup_printf("SET USERSTATUS OFFLINE\n");
996        skype_write( ic, buf );
997        g_free(buf);
998
999        g_free(sd->username);
1000        g_free(sd->handle);
1001        g_free(sd);
1002        ic->proto_data = NULL;
1003}
1004
1005static int skype_buddy_msg( struct im_connection *ic, char *who, char *message, int flags )
1006{
1007        char *buf, *ptr, *nick;
1008        int st;
1009
1010        nick = g_strdup(who);
1011        ptr = strchr(nick, '@');
1012        if(ptr)
1013                *ptr = '\0';
1014
1015        if (!strncmp(who, "skypeconsole", 12))
1016                buf = g_strdup_printf("%s\n", message);
1017        else
1018                buf = g_strdup_printf("MESSAGE %s %s\n", nick, message);
1019        g_free(nick);
1020        st = skype_write( ic, buf );
1021        g_free(buf);
1022
1023        return st;
1024}
1025
1026const struct skype_away_state *skype_away_state_by_name( char *name )
1027{
1028        int i;
1029
1030        for( i = 0; skype_away_state_list[i].full_name; i ++ )
1031                if( g_strcasecmp( skype_away_state_list[i].full_name, name ) == 0 )
1032                        return( skype_away_state_list + i );
1033
1034        return NULL;
1035}
1036
1037static void skype_set_away( struct im_connection *ic, char *state_txt, char *message )
1038{
1039        const struct skype_away_state *state;
1040        char *buf;
1041
1042        if( strcmp( state_txt, GAIM_AWAY_CUSTOM ) == 0 )
1043                state = skype_away_state_by_name( "Away" );
1044        else
1045                state = skype_away_state_by_name( state_txt );
1046        buf = g_strdup_printf("SET USERSTATUS %s\n", state->code);
1047        skype_write( ic, buf );
1048        g_free(buf);
1049}
1050
1051static GList *skype_away_states( struct im_connection *ic )
1052{
1053        static GList *l = NULL;
1054        int i;
1055       
1056        if( l == NULL )
1057                for( i = 0; skype_away_state_list[i].full_name; i ++ )
1058                        l = g_list_append( l, (void*) skype_away_state_list[i].full_name );
1059       
1060        return l;
1061}
1062
1063static char *skype_set_display_name( set_t *set, char *value )
1064{
1065        account_t *acc = set->data;
1066        struct im_connection *ic = acc->ic;
1067        char *buf;
1068
1069        buf = g_strdup_printf("SET PROFILE FULLNAME %s", value);
1070        skype_write( ic, buf );
1071        g_free(buf);
1072        return(value);
1073}
1074
1075static char *skype_set_balance( set_t *set, char *value )
1076{
1077        account_t *acc = set->data;
1078        struct im_connection *ic = acc->ic;
1079        char *buf;
1080
1081        buf = g_strdup_printf("GET PROFILE PSTN_BALANCE");
1082        skype_write( ic, buf );
1083        g_free(buf);
1084        return(value);
1085}
1086
1087static char *skype_set_call( set_t *set, char *value )
1088{
1089        account_t *acc = set->data;
1090        struct im_connection *ic = acc->ic;
1091        struct skype_data *sd = ic->proto_data;
1092        char *nick, *ptr, *buf;
1093
1094        if(value)
1095        {
1096                user_t *u = user_find(acc->irc, value);
1097                /* We are starting a call */
1098                if(!u)
1099                        nick = g_strdup(value);
1100                else
1101                        nick = g_strdup(u->handle);
1102                ptr = strchr(nick, '@');
1103                if(ptr)
1104                        *ptr = '\0';
1105
1106                buf = g_strdup_printf("CALL %s", nick);
1107                skype_write( ic, buf );
1108                g_free(buf);
1109                g_free(nick);
1110        }
1111        else
1112        {
1113                /* We are ending a call */
1114                if(sd->call_id)
1115                {
1116                        buf = g_strdup_printf("SET CALL %s STATUS FINISHED", sd->call_id);
1117                        skype_write( ic, buf );
1118                        g_free(buf);
1119                        g_free(sd->call_id);
1120                        sd->call_id = NULL;
1121                }
1122                else
1123                {
1124                        imcb_error(ic, "There are no active calls currently.");
1125                }
1126        }
1127        return(value);
1128}
1129
1130static void skype_add_buddy( struct im_connection *ic, char *who, char *group )
1131{
1132        char *buf, *nick, *ptr;
1133
1134        nick = g_strdup(who);
1135        ptr = strchr(nick, '@');
1136        if(ptr)
1137                *ptr = '\0';
1138        buf = g_strdup_printf("SET USER %s BUDDYSTATUS 2 Please authorize me\n", nick);
1139        skype_write( ic, buf );
1140        g_free(nick);
1141}
1142
1143static void skype_remove_buddy( struct im_connection *ic, char *who, char *group )
1144{
1145        char *buf, *nick, *ptr;
1146
1147        nick = g_strdup(who);
1148        ptr = strchr(nick, '@');
1149        if(ptr)
1150                *ptr = '\0';
1151        buf = g_strdup_printf("SET USER %s BUDDYSTATUS 1\n", nick);
1152        skype_write( ic, buf );
1153        g_free(nick);
1154}
1155
1156void skype_chat_msg( struct groupchat *gc, char *message, int flags )
1157{
1158        struct im_connection *ic = gc->ic;
1159        char *buf;
1160        buf = g_strdup_printf("CHATMESSAGE %s %s\n", gc->title, message);
1161        skype_write( ic, buf );
1162        g_free(buf);
1163}
1164
1165void skype_chat_leave( struct groupchat *gc )
1166{
1167        struct im_connection *ic = gc->ic;
1168        char *buf;
1169        buf = g_strdup_printf("ALTER CHAT %s LEAVE\n", gc->title);
1170        skype_write( ic, buf );
1171        g_free(buf);
1172        gc->data = (void*)TRUE;
1173}
1174
1175void skype_chat_invite(struct groupchat *gc, char *who, char *message)
1176{
1177        struct im_connection *ic = gc->ic;
1178        char *buf, *ptr, *nick;
1179        nick = g_strdup(message);
1180        ptr = strchr(nick, '@');
1181        if(ptr)
1182                *ptr = '\0';
1183        buf = g_strdup_printf("ALTER CHAT %s ADDMEMBERS %s\n", gc->title, nick);
1184        skype_write( ic, buf );
1185        g_free(buf);
1186        g_free(nick);
1187}
1188
1189void skype_chat_topic(struct groupchat *gc, char *message)
1190{
1191        struct im_connection *ic = gc->ic;
1192        struct skype_data *sd = ic->proto_data;
1193        char *buf;
1194        buf = g_strdup_printf("ALTER CHAT %s SETTOPIC %s\n", gc->title, message);
1195        skype_write( ic, buf );
1196        g_free(buf);
1197        sd->topic_wait = 1;
1198}
1199
1200struct groupchat *skype_chat_with(struct im_connection *ic, char *who)
1201{
1202        struct skype_data *sd = ic->proto_data;
1203        char *ptr, *nick, *buf;
1204        nick = g_strdup(who);
1205        ptr = strchr(nick, '@');
1206        if(ptr)
1207                *ptr = '\0';
1208        buf = g_strdup_printf("CHAT CREATE %s\n", nick);
1209        skype_write(ic, buf);
1210        g_free(buf);
1211        sd->groupchat_with = g_strdup(nick);
1212        g_free(nick);
1213        /* We create a fake chat for now. We will replace it with a real one in
1214         * the real callback. */
1215        return(imcb_chat_new( ic, "" ));
1216}
1217
1218static void skype_get_info(struct im_connection *ic, char *who)
1219{
1220        char *ptr, *nick, *buf;
1221        nick = g_strdup(who);
1222        ptr = strchr(nick, '@');
1223        if(ptr)
1224                *ptr = '\0';
1225        buf = g_strdup_printf("GET USER %s FULLNAME\n", nick);
1226        skype_write(ic, buf);
1227        g_free(buf);
1228        buf = g_strdup_printf("GET USER %s PHONE_HOME\n", nick);
1229        skype_write(ic, buf);
1230        g_free(buf);
1231        buf = g_strdup_printf("GET USER %s PHONE_OFFICE\n", nick);
1232        skype_write(ic, buf);
1233        g_free(buf);
1234        buf = g_strdup_printf("GET USER %s PHONE_MOBILE\n", nick);
1235        skype_write(ic, buf);
1236        g_free(buf);
1237        buf = g_strdup_printf("GET USER %s NROF_AUTHED_BUDDIES\n", nick);
1238        skype_write(ic, buf);
1239        g_free(buf);
1240        buf = g_strdup_printf("GET USER %s TIMEZONE\n", nick);
1241        skype_write(ic, buf);
1242        g_free(buf);
1243        buf = g_strdup_printf("GET USER %s LASTONLINETIMESTAMP\n", nick);
1244        skype_write(ic, buf);
1245        g_free(buf);
1246        buf = g_strdup_printf("GET USER %s BIRTHDAY\n", nick);
1247        skype_write(ic, buf);
1248        g_free(buf);
1249        buf = g_strdup_printf("GET USER %s SEX\n", nick);
1250        skype_write(ic, buf);
1251        g_free(buf);
1252        buf = g_strdup_printf("GET USER %s LANGUAGE\n", nick);
1253        skype_write(ic, buf);
1254        g_free(buf);
1255        buf = g_strdup_printf("GET USER %s COUNTRY\n", nick);
1256        skype_write(ic, buf);
1257        g_free(buf);
1258        buf = g_strdup_printf("GET USER %s PROVINCE\n", nick);
1259        skype_write(ic, buf);
1260        g_free(buf);
1261        buf = g_strdup_printf("GET USER %s CITY\n", nick);
1262        skype_write(ic, buf);
1263        g_free(buf);
1264        buf = g_strdup_printf("GET USER %s HOMEPAGE\n", nick);
1265        skype_write(ic, buf);
1266        g_free(buf);
1267        buf = g_strdup_printf("GET USER %s ABOUT\n", nick);
1268        skype_write(ic, buf);
1269        g_free(buf);
1270}
1271
1272static void skype_set_my_name( struct im_connection *ic, char *info )
1273{
1274        skype_set_display_name( set_find( &ic->acc->set, "display_name" ), info );
1275}
1276
1277static void skype_init( account_t *acc )
1278{
1279        set_t *s;
1280
1281        s = set_add( &acc->set, "server", SKYPE_DEFAULT_SERVER, set_eval_account, acc );
1282        s->flags |= ACC_SET_OFFLINE_ONLY;
1283
1284        s = set_add( &acc->set, "port", SKYPE_DEFAULT_PORT, set_eval_int, acc );
1285        s->flags |= ACC_SET_OFFLINE_ONLY;
1286
1287        s = set_add( &acc->set, "display_name", NULL, skype_set_display_name, acc );
1288        s->flags |= ACC_SET_NOSAVE | ACC_SET_ONLINE_ONLY;
1289
1290        s = set_add( &acc->set, "call", NULL, skype_set_call, acc );
1291        s->flags |= ACC_SET_NOSAVE | ACC_SET_ONLINE_ONLY;
1292
1293        s = set_add( &acc->set, "balance", NULL, skype_set_balance, acc );
1294        s->flags |= ACC_SET_NOSAVE | ACC_SET_ONLINE_ONLY;
1295
1296        s = set_add( &acc->set, "skypeout_offline", "true", set_eval_bool, acc );
1297
1298        s = set_add( &acc->set, "skypeconsole", "false", set_eval_bool, acc );
1299        s->flags |= ACC_SET_OFFLINE_ONLY;
1300
1301        s = set_add( &acc->set, "auto_join", "false", set_eval_bool, acc );
1302        s->flags |= ACC_SET_OFFLINE_ONLY;
1303}
1304
1305void init_plugin(void)
1306{
1307        struct prpl *ret = g_new0( struct prpl, 1 );
1308
1309        ret->name = "skype";
1310        ret->login = skype_login;
1311        ret->init = skype_init;
1312        ret->logout = skype_logout;
1313        ret->buddy_msg = skype_buddy_msg;
1314        ret->get_info = skype_get_info;
1315        ret->set_my_name = skype_set_my_name;
1316        ret->away_states = skype_away_states;
1317        ret->set_away = skype_set_away;
1318        ret->add_buddy = skype_add_buddy;
1319        ret->remove_buddy = skype_remove_buddy;
1320        ret->chat_msg = skype_chat_msg;
1321        ret->chat_leave = skype_chat_leave;
1322        ret->chat_invite = skype_chat_invite;
1323        ret->chat_with = skype_chat_with;
1324        ret->handle_cmp = g_strcasecmp;
1325        ret->chat_topic = skype_chat_topic;
1326        register_protocol( ret );
1327}
1328
1329/* vim: set ts=2 sw=2 noet: */
Note: See TracBrowser for help on using the repository browser.