aboutsummaryrefslogtreecommitdiffstats
path: root/protocols/skype/skype.c
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/skype/skype.c')
-rw-r--r--protocols/skype/skype.c176
1 files changed, 117 insertions, 59 deletions
diff --git a/protocols/skype/skype.c b/protocols/skype/skype.c
index 8638b5c1..7ce562d4 100644
--- a/protocols/skype/skype.c
+++ b/protocols/skype/skype.c
@@ -1,7 +1,7 @@
/*
* skype.c - Skype plugin for BitlBee
*
- * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012 by Miklos Vajna <vmiklos@frugalware.org>
+ * Copyright (c) 2007-2013 by Miklos Vajna <vmiklos@vmiklos.hu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@
#define SKYPE_DEFAULT_SERVER "localhost"
#define SKYPE_DEFAULT_PORT "2727"
-#define IRC_LINE_SIZE 1024
+#define IRC_LINE_SIZE 16384
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
/*
@@ -45,6 +45,8 @@ enum {
enum {
SKYPE_FILETRANSFER_NEW = 1,
+ SKYPE_FILETRANSFER_TRANSFERRING,
+ SKYPE_FILETRANSFER_COMPLETED,
SKYPE_FILETRANSFER_FAILED
};
@@ -80,6 +82,8 @@ struct skype_data {
int call_out;
/* Same for file transfers. */
int filetransfer_status;
+ /* Path of the file being transferred. */
+ char *filetransfer_path;
/* Using /j #nick we want to have a groupchat with two people. Usually
* not (default). */
char *groupchat_with;
@@ -113,6 +117,8 @@ struct skype_data {
/* Pending user which has to be added to the next group which is
* created. */
char *pending_user;
+ /* If the info command was used, to determine what to do with FULLNAME result. */
+ int is_info;
};
struct skype_away_state {
@@ -189,7 +195,7 @@ int skype_printf(struct im_connection *ic, char *fmt, ...)
static void skype_buddy_ask_yes(void *data)
{
struct skype_buddy_ask_data *bla = data;
- skype_printf(bla->ic, "SET USER %s ISAUTHORIZED TRUE",
+ skype_printf(bla->ic, "SET USER %s ISAUTHORIZED TRUE\n",
bla->handle);
g_free(bla->handle);
g_free(bla);
@@ -198,7 +204,7 @@ static void skype_buddy_ask_yes(void *data)
static void skype_buddy_ask_no(void *data)
{
struct skype_buddy_ask_data *bla = data;
- skype_printf(bla->ic, "SET USER %s ISAUTHORIZED FALSE",
+ skype_printf(bla->ic, "SET USER %s ISAUTHORIZED FALSE\n",
bla->handle);
g_free(bla->handle);
g_free(bla);
@@ -213,8 +219,7 @@ void skype_buddy_ask(struct im_connection *ic, char *handle, char *message)
bla->ic = ic;
bla->handle = g_strdup(handle);
- buf = g_strdup_printf("The user %s wants to add you to "
- "his/her buddy list, saying: '%s'.", handle, message);
+ buf = g_strdup_printf("The user %s wants to add you to his/her buddy list, saying: '%s'.", handle, message);
imcb_ask(ic, buf, bla, skype_buddy_ask_yes, skype_buddy_ask_no);
g_free(buf);
}
@@ -222,7 +227,7 @@ void skype_buddy_ask(struct im_connection *ic, char *handle, char *message)
static void skype_call_ask_yes(void *data)
{
struct skype_buddy_ask_data *bla = data;
- skype_printf(bla->ic, "SET CALL %s STATUS INPROGRESS",
+ skype_printf(bla->ic, "SET CALL %s STATUS INPROGRESS\n",
bla->handle);
g_free(bla->handle);
g_free(bla);
@@ -231,7 +236,7 @@ static void skype_call_ask_yes(void *data)
static void skype_call_ask_no(void *data)
{
struct skype_buddy_ask_data *bla = data;
- skype_printf(bla->ic, "SET CALL %s STATUS FINISHED",
+ skype_printf(bla->ic, "SET CALL %s STATUS FINISHED\n",
bla->handle);
g_free(bla->handle);
g_free(bla);
@@ -316,8 +321,10 @@ static void skype_parse_users(struct im_connection *ic, char *line)
char **i, **nicks;
nicks = g_strsplit(line + 6, ", ", 0);
- for (i = nicks; *i; i++)
+ for (i = nicks; *i; i++) {
skype_printf(ic, "GET USER %s ONLINESTATUS\n", *i);
+ skype_printf(ic, "GET USER %s FULLNAME\n", *i);
+ }
g_strfreev(nicks);
}
@@ -371,9 +378,17 @@ static void skype_parse_user(struct im_connection *ic, char *line)
*buf ? buf : NULL);
if (set_getbool(&ic->acc->set, "show_moods"))
imcb_log(ic, "User `%s' changed mood text to `%s'", user, buf);
- } else if (!strncmp(ptr, "FULLNAME ", 9))
- sd->info_fullname = g_strdup(ptr + 9);
- else if (!strncmp(ptr, "PHONE_HOME ", 11))
+ } else if (!strncmp(ptr, "FULLNAME ", 9)) {
+ char *name = ptr + 9;
+ if (sd->is_info) {
+ sd->is_info = FALSE;
+ sd->info_fullname = g_strdup(name);
+ } else {
+ char *buf = g_strdup_printf("%s@skype.com", user);
+ imcb_rename_buddy(ic, buf, name);
+ g_free(buf);
+ }
+ } else if (!strncmp(ptr, "PHONE_HOME ", 11))
sd->info_phonehome = g_strdup(ptr + 11);
else if (!strncmp(ptr, "PHONE_OFFICE ", 13))
sd->info_phoneoffice = g_strdup(ptr + 13);
@@ -408,8 +423,7 @@ static void skype_parse_user(struct im_connection *ic, char *line)
sd->info_about = g_strdup(st->str);
g_string_free(st, TRUE);
}
- }
- else if (!strncmp(ptr, "BIRTHDAY ", 9)) {
+ } else if (!strncmp(ptr, "BIRTHDAY ", 9)) {
sd->info_birthday = g_strdup(ptr + 9);
GString *st = g_string_new("Contact Information\n");
@@ -565,10 +579,30 @@ static void skype_parse_user(struct im_connection *ic, char *line)
}
}
-static void skype_parse_chatmessage(struct im_connection *ic, char *line)
+static void skype_parse_chatmessage_said_emoted(struct im_connection *ic, struct groupchat *gc, char *body)
{
struct skype_data *sd = ic->proto_data;
char buf[IRC_LINE_SIZE];
+ if (!strcmp(sd->type, "SAID")) {
+ if (!sd->is_edit)
+ g_snprintf(buf, IRC_LINE_SIZE, "%s", body);
+ else {
+ g_snprintf(buf, IRC_LINE_SIZE, "%s %s", set_getstr(&ic->acc->set, "edit_prefix"), body);
+ sd->is_edit = 0;
+ }
+ } else
+ g_snprintf(buf, IRC_LINE_SIZE, "/me %s", body);
+ if (!gc)
+ /* Private message */
+ imcb_buddy_msg(ic, sd->handle, buf, 0, 0);
+ else
+ /* Groupchat message */
+ imcb_chat_msg(gc, sd->handle, buf, 0, 0);
+}
+
+static void skype_parse_chatmessage(struct im_connection *ic, char *line)
+{
+ struct skype_data *sd = ic->proto_data;
char *id = strchr(line, ' ');
if (!++id)
@@ -626,27 +660,7 @@ static void skype_parse_chatmessage(struct im_connection *ic, char *line)
char *body = g_list_nth_data(sd->body, i);
if (!strcmp(sd->type, "SAID") ||
!strcmp(sd->type, "EMOTED")) {
- if (!strcmp(sd->type, "SAID")) {
- if (!sd->is_edit)
- g_snprintf(buf, IRC_LINE_SIZE, "%s",
- body);
- else {
- g_snprintf(buf, IRC_LINE_SIZE, "%s %s",
- set_getstr(&ic->acc->set, "edit_prefix"),
- body);
- sd->is_edit = 0;
- }
- } else
- g_snprintf(buf, IRC_LINE_SIZE, "/me %s",
- body);
- if (!gc)
- /* Private message */
- imcb_buddy_msg(ic,
- sd->handle, buf, 0, 0);
- else
- /* Groupchat message */
- imcb_chat_msg(gc,
- sd->handle, buf, 0, 0);
+ skype_parse_chatmessage_said_emoted(ic, gc, body);
} else if (!strcmp(sd->type, "SETTOPIC") && gc)
imcb_chat_topic(gc,
sd->handle, body, 0);
@@ -715,8 +729,7 @@ static void skype_parse_call(struct im_connection *ic, char *line)
switch (sd->call_status) {
case SKYPE_CALL_RINGING:
if (sd->call_out)
- imcb_log(ic, "You are currently ringing "
- "the user %s.", info);
+ imcb_log(ic, "You are currently ringing the user %s.", info);
else {
g_snprintf(buf, IRC_LINE_SIZE,
"The user %s is currently ringing you.",
@@ -785,6 +798,15 @@ static void skype_parse_filetransfer(struct im_connection *ic, char *line)
skype_printf(ic, "GET FILETRANSFER %s PARTNER_HANDLE\n",
id);
sd->filetransfer_status = SKYPE_FILETRANSFER_FAILED;
+ } else if (!strcmp(info, "STATUS COMPLETED")) {
+ skype_printf(ic, "GET FILETRANSFER %s PARTNER_HANDLE\n", id);
+ sd->filetransfer_status = SKYPE_FILETRANSFER_COMPLETED;
+ } else if (!strcmp(info, "STATUS TRANSFERRING")) {
+ skype_printf(ic, "GET FILETRANSFER %s PARTNER_HANDLE\n", id);
+ sd->filetransfer_status = SKYPE_FILETRANSFER_TRANSFERRING;
+ } else if (!strncmp(info, "FILEPATH ", 9)) {
+ info += 9;
+ sd->filetransfer_path = g_strdup(info);
} else if (!strncmp(info, "PARTNER_HANDLE ", 15)) {
info += 15;
if (!sd->filetransfer_status)
@@ -798,6 +820,16 @@ static void skype_parse_filetransfer(struct im_connection *ic, char *line)
imcb_log(ic, "Failed to transfer file from user %s.",
info);
break;
+ case SKYPE_FILETRANSFER_COMPLETED:
+ imcb_log(ic, "File transfer from user %s completed.", info);
+ break;
+ case SKYPE_FILETRANSFER_TRANSFERRING:
+ if (sd->filetransfer_path) {
+ imcb_log(ic, "File transfer from user %s started, saving to %s.", info, sd->filetransfer_path);
+ g_free(sd->filetransfer_path);
+ sd->filetransfer_path = NULL;
+ }
+ break;
}
sd->filetransfer_status = 0;
}
@@ -897,7 +929,7 @@ static void skype_parse_group(struct im_connection *ic, char *line)
if (!sd->pending_user) {
/* Number of users changed in this group, query its type to see
* if it's a custom one we should care about. */
- skype_printf(ic, "GET GROUP %s TYPE", id);
+ skype_printf(ic, "GET GROUP %s TYPE\n", id);
return;
}
@@ -906,7 +938,7 @@ static void skype_parse_group(struct im_connection *ic, char *line)
struct skype_group *sg = skype_group_by_id(ic, atoi(id));
if (sg) {
- skype_printf(ic, "ALTER GROUP %d ADDUSER %s", sg->id, sd->pending_user);
+ skype_printf(ic, "ALTER GROUP %d ADDUSER %s\n", sg->id, sd->pending_user);
g_free(sd->pending_user);
sd->pending_user = NULL;
} else
@@ -914,7 +946,7 @@ static void skype_parse_group(struct im_connection *ic, char *line)
"No skype group with id %s. That's probably a bug.", id);
} else if (!strcmp(info, "TYPE CUSTOM_GROUP"))
/* This one is interesting, query its users. */
- skype_printf(ic, "GET GROUP %s USERS", id);
+ skype_printf(ic, "GET GROUP %s USERS\n", id);
}
static void skype_parse_chat(struct im_connection *ic, char *line)
@@ -982,8 +1014,8 @@ static void skype_parse_chat(struct im_connection *ic, char *line)
g_free(sd->adder);
sd->adder = NULL;
}
- } else if (!strncmp(info, "ACTIVEMEMBERS ", 14)) {
- info += 14;
+ } else if (!strncmp(info, "MEMBERS ", 8) || !strncmp(info, "ACTIVEMEMBERS ", 14) ) {
+ info += 8;
gc = bee_chat_by_title(ic->bee, ic, id);
/* Hack! We set ->data to TRUE
* while we're on the channel
@@ -1045,6 +1077,9 @@ static void skype_parse_chats(struct im_connection *ic, char *line)
static void skype_parse_groups(struct im_connection *ic, char *line)
{
+ if (!set_getbool(&ic->acc->set, "read_groups"))
+ return;
+
char **i;
char **groups = g_strsplit(line + 7, ", ", 0);
@@ -1123,6 +1158,13 @@ static gboolean skype_read_callback(gpointer data, gint fd,
return FALSE;
/* Read the whole data. */
st = ssl_read(sd->ssl, buf, sizeof(buf));
+ if (st >= IRC_LINE_SIZE-1) {
+ /* As we don't buffer incoming data, if IRC_LINE_SIZE amount of bytes
+ * were received, there's a good chance last message was truncated
+ * and the next recv() will yield garbage. */
+ imcb_error(ic, "Unable to handle incoming data from skyped");
+ st = 0;
+ }
if (st > 0) {
buf[st] = '\0';
/* Then split it up to lines. */
@@ -1177,8 +1219,12 @@ gboolean skype_start_stream(struct im_connection *ic)
skype_printf(ic, "SET USERSTATUS ONLINE\n");
/* Auto join to bookmarked chats if requested.*/
- if (set_getbool(&ic->acc->set, "auto_join"))
+ if (set_getbool(&ic->acc->set, "auto_join")) {
skype_printf(ic, "SEARCH BOOKMARKEDCHATS\n");
+ skype_printf(ic, "SEARCH ACTIVECHATS\n");
+ skype_printf(ic, "SEARCH MISSEDCHATS\n");
+ skype_printf(ic, "SEARCH RECENTCHATS\n");
+ }
return st;
}
@@ -1227,7 +1273,7 @@ static void skype_logout(struct im_connection *ic)
skype_printf(ic, "SET USERSTATUS OFFLINE\n");
- while( ic->groupchats )
+ while (ic->groupchats)
imcb_chat_free(ic->groupchats->data);
for (i = 0; i < g_list_length(sd->groups); i++) {
@@ -1314,7 +1360,16 @@ static char *skype_set_display_name(set_t *set, char *value)
account_t *acc = set->data;
struct im_connection *ic = acc->ic;
- skype_printf(ic, "SET PROFILE FULLNAME %s", value);
+ skype_printf(ic, "SET PROFILE FULLNAME %s\n", value);
+ return value;
+}
+
+static char *skype_set_mood_text(set_t *set, char *value)
+{
+ account_t *acc = set->data;
+ struct im_connection *ic = acc->ic;
+
+ skype_printf(ic, "SET PROFILE MOOD_TEXT %s\n", value);
return value;
}
@@ -1323,7 +1378,7 @@ static char *skype_set_balance(set_t *set, char *value)
account_t *acc = set->data;
struct im_connection *ic = acc->ic;
- skype_printf(ic, "GET PROFILE PSTN_BALANCE");
+ skype_printf(ic, "GET PROFILE PSTN_BALANCE\n");
return value;
}
@@ -1334,7 +1389,7 @@ static void skype_call(struct im_connection *ic, char *value)
if (ptr)
*ptr = '\0';
- skype_printf(ic, "CALL %s", nick);
+ skype_printf(ic, "CALL %s\n", nick);
g_free(nick);
}
@@ -1343,7 +1398,7 @@ static void skype_hangup(struct im_connection *ic)
struct skype_data *sd = ic->proto_data;
if (sd->call_id) {
- skype_printf(ic, "SET CALL %s STATUS FINISHED",
+ skype_printf(ic, "SET CALL %s STATUS FINISHED\n",
sd->call_id);
g_free(sd->call_id);
sd->call_id = 0;
@@ -1383,10 +1438,10 @@ static void skype_add_buddy(struct im_connection *ic, char *who, char *group)
if (!sg) {
/* No such group, we need to create it, then have to
* add the user once it's created. */
- skype_printf(ic, "CREATE GROUP %s", group);
+ skype_printf(ic, "CREATE GROUP %s\n", group);
sd->pending_user = g_strdup(nick);
} else {
- skype_printf(ic, "ALTER GROUP %d ADDUSER %s", sg->id, nick);
+ skype_printf(ic, "ALTER GROUP %d ADDUSER %s\n", sg->id, nick);
}
}
}
@@ -1463,11 +1518,13 @@ struct groupchat *skype_chat_with(struct im_connection *ic, char *who)
static void skype_get_info(struct im_connection *ic, char *who)
{
+ struct skype_data *sd = ic->proto_data;
char *ptr, *nick;
nick = g_strdup(who);
ptr = strchr(nick, '@');
if (ptr)
*ptr = '\0';
+ sd->is_info = TRUE;
skype_printf(ic, "GET USER %s FULLNAME\n", nick);
skype_printf(ic, "GET USER %s PHONE_HOME\n", nick);
skype_printf(ic, "GET USER %s PHONE_OFFICE\n", nick);
@@ -1490,11 +1547,6 @@ static void skype_get_info(struct im_connection *ic, char *who)
skype_printf(ic, "GET USER %s BIRTHDAY\n", nick);
}
-static void skype_set_my_name(struct im_connection *ic, char *info)
-{
- skype_set_display_name(set_find(&ic->acc->set, "display_name"), info);
-}
-
static void skype_init(account_t *acc)
{
set_t *s;
@@ -1510,6 +1562,9 @@ static void skype_init(account_t *acc)
acc);
s->flags |= SET_NOSAVE | ACC_SET_ONLINE_ONLY;
+ s = set_add(&acc->set, "mood_text", NULL, skype_set_mood_text, acc);
+ s->flags |= ACC_SET_NOSAVE | ACC_SET_ONLINE_ONLY;
+
s = set_add(&acc->set, "call", NULL, skype_set_call, acc);
s->flags |= SET_NOSAVE | ACC_SET_ONLINE_ONLY;
@@ -1535,6 +1590,8 @@ static void skype_init(account_t *acc)
s = set_add(&acc->set, "edit_prefix", "EDIT:",
NULL, acc);
+
+ s = set_add(&acc->set, "read_groups", "false", set_eval_bool, acc);
}
#if BITLBEE_VERSION_CODE > BITLBEE_VER(3, 0, 1)
@@ -1546,12 +1603,14 @@ GList *skype_buddy_action_list(bee_user_t *bu)
bu = bu;
if (ret == NULL) {
- static const struct buddy_action ba[3] = {
+ static const struct buddy_action ba[2] = {
{"CALL", "Initiate a call" },
{"HANGUP", "Hang up a call" },
};
+ int i;
- ret = g_list_prepend(ret, (void *) ba + 0);
+ for (i = 0; i < ARRAY_SIZE(ba); i++)
+ ret = g_list_prepend(ret, (void *)(ba + i));
}
return ret;
@@ -1582,7 +1641,6 @@ void init_plugin(void)
ret->logout = skype_logout;
ret->buddy_msg = skype_buddy_msg;
ret->get_info = skype_get_info;
- ret->set_my_name = skype_set_my_name;
ret->away_states = skype_away_states;
ret->set_away = skype_set_away;
ret->add_buddy = skype_add_buddy;