summaryrefslogtreecommitdiff
path: root/libpurple/protocols/oscar/oscar.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpurple/protocols/oscar/oscar.c')
-rw-r--r--libpurple/protocols/oscar/oscar.c272
1 files changed, 256 insertions, 16 deletions
diff --git a/libpurple/protocols/oscar/oscar.c b/libpurple/protocols/oscar/oscar.c
index c4c59e4d39..9eb30bd942 100644
--- a/libpurple/protocols/oscar/oscar.c
+++ b/libpurple/protocols/oscar/oscar.c
@@ -61,6 +61,11 @@
#define OSCAR_STATUS_ID_FREE4CHAT "free4chat"
#define OSCAR_STATUS_ID_CUSTOM "custom"
#define OSCAR_STATUS_ID_MOBILE "mobile"
+#define OSCAR_STATUS_ID_EVIL "evil"
+#define OSCAR_STATUS_ID_DEPRESSION "depression"
+#define OSCAR_STATUS_ID_ATHOME "athome"
+#define OSCAR_STATUS_ID_ATWORK "atwork"
+#define OSCAR_STATUS_ID_LUNCH "lunch"
#define AIMHASHDATA "http://pidgin.im/aim_data.php3"
@@ -68,7 +73,7 @@
static OscarCapability purple_caps = (OSCAR_CAPABILITY_CHAT | OSCAR_CAPABILITY_BUDDYICON | OSCAR_CAPABILITY_DIRECTIM |
OSCAR_CAPABILITY_SENDFILE | OSCAR_CAPABILITY_UNICODE | OSCAR_CAPABILITY_INTEROPERATE |
- OSCAR_CAPABILITY_SHORTCAPS | OSCAR_CAPABILITY_TYPING);
+ OSCAR_CAPABILITY_SHORTCAPS | OSCAR_CAPABILITY_TYPING | OSCAR_CAPABILITY_ICQSERVERRELAY | OSCAR_CAPABILITY_NEWCAPS | OSCAR_CAPABILITY_XTRAZ);
static guint8 features_aim[] = {0x01, 0x01, 0x01, 0x02};
static guint8 features_icq[] = {0x01, 0x06};
@@ -180,6 +185,7 @@ static int purple_parse_incoming_im(OscarData *, FlapConnection *, FlapFrame *,
static int purple_parse_misses (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_parse_clientauto (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_parse_userinfo (OscarData *, FlapConnection *, FlapFrame *, ...);
+static int purple_got_infoblock (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_parse_motd (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_chatnav_info (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_conv_chat_join (OscarData *, FlapConnection *, FlapFrame *, ...);
@@ -190,6 +196,7 @@ static int purple_email_parseupdate(OscarData *, FlapConnection *, FlapFrame *,
static int purple_icon_parseicon (OscarData *, FlapConnection *, FlapFrame *, ...);
static int oscar_icon_req (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_parse_msgack (OscarData *, FlapConnection *, FlapFrame *, ...);
+static int purple_parse_ratechange (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_parse_evilnotify (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_parse_searcherror(OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_parse_searchreply(OscarData *, FlapConnection *, FlapFrame *, ...);
@@ -672,7 +679,7 @@ static gchar *oscar_caps_to_string(OscarCapability caps)
{
GString *str;
const gchar *tmp;
- guint bit = 1;
+ guint64 bit = 1;
str = g_string_new("");
@@ -703,6 +710,10 @@ static gchar *oscar_caps_to_string(OscarCapability caps)
case OSCAR_CAPABILITY_GAMES2:
tmp = _("Games");
break;
+ case OSCAR_CAPABILITY_XTRAZ:
+ case OSCAR_CAPABILITY_NEWCAPS:
+ tmp = _("ICQ Xtraz");
+ break;
case OSCAR_CAPABILITY_ADDINS:
tmp = _("Add-Ins");
break;
@@ -784,6 +795,16 @@ static char *oscar_icqstatus(int state) {
return g_strdup(_("Web Aware"));
else if (state & AIM_ICQ_STATE_INVISIBLE)
return g_strdup(_("Invisible"));
+ else if (state & AIM_ICQ_STATE_EVIL)
+ return g_strdup(_("Evil"));
+ else if (state & AIM_ICQ_STATE_DEPRESSION)
+ return g_strdup(_("Depression"));
+ else if (state & AIM_ICQ_STATE_ATHOME)
+ return g_strdup(_("At home"));
+ else if (state & AIM_ICQ_STATE_ATWORK)
+ return g_strdup(_("At work"));
+ else if (state & AIM_ICQ_STATE_LUNCH)
+ return g_strdup(_("At lunch"));
else
return g_strdup(_("Online"));
}
@@ -961,6 +982,16 @@ static void oscar_user_info_append_status(PurpleConnection *gc, PurpleNotifyUser
}
}
+ if (presence) {
+ const char *mood;
+ const char *description;
+ status = purple_presence_get_status(presence, "mood");
+ mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
+ description = icq_get_custom_icon_description(mood);
+ if (description && *description)
+ purple_notify_user_info_add_pair(user_info, _("Mood"), _(description));
+ }
+
purple_notify_user_info_add_pair(user_info, _("Status"), message);
g_free(message);
}
@@ -2240,6 +2271,16 @@ static int purple_parse_oncoming(OscarData *od, FlapConnection *conn, FlapFrame
status_id = OSCAR_STATUS_ID_AWAY;
else if (type & AIM_ICQ_STATE_INVISIBLE)
status_id = OSCAR_STATUS_ID_INVISIBLE;
+ else if (type & AIM_ICQ_STATE_EVIL)
+ status_id = OSCAR_STATUS_ID_EVIL;
+ else if (type & AIM_ICQ_STATE_DEPRESSION)
+ status_id = OSCAR_STATUS_ID_DEPRESSION;
+ else if (type & AIM_ICQ_STATE_ATHOME)
+ status_id = OSCAR_STATUS_ID_ATHOME;
+ else if (type & AIM_ICQ_STATE_ATWORK)
+ status_id = OSCAR_STATUS_ID_ATWORK;
+ else if (type & AIM_ICQ_STATE_LUNCH)
+ status_id = OSCAR_STATUS_ID_LUNCH;
else
status_id = OSCAR_STATUS_ID_AVAILABLE;
} else {
@@ -2552,7 +2593,9 @@ incomingim_chan2(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo,
{
PurpleConnection *gc;
PurpleAccount *account;
+ PurpleMessageFlags flags = 0;
char *message = NULL;
+ char *rtfmsg = NULL;
g_return_val_if_fail(od != NULL, 0);
g_return_val_if_fail(od->gc != NULL, 0);
@@ -2582,6 +2625,20 @@ incomingim_chan2(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo,
}
}
+ if (args->info.rtfmsg.rtfmsg != NULL)
+ {
+ if (args->encoding != NULL)
+ {
+ char *encoding = NULL;
+ encoding = oscar_encoding_extract(args->encoding);
+ rtfmsg = oscar_encoding_to_utf8(account, encoding, args->info.rtfmsg.rtfmsg,
+ strlen(args->info.rtfmsg.rtfmsg));
+ g_free(encoding);
+ } else {
+ if (g_utf8_validate(args->info.rtfmsg.rtfmsg, strlen(args->info.rtfmsg.rtfmsg), NULL))
+ rtfmsg = g_strdup(args->info.rtfmsg.rtfmsg);
+ }
+ }
if (args->type & OSCAR_CAPABILITY_CHAT)
{
char *encoding, *utf8name, *tmp;
@@ -2667,10 +2724,28 @@ incomingim_chan2(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo,
else if (args->type & OSCAR_CAPABILITY_ICQSERVERRELAY)
{
- purple_debug_error("oscar", "Got an ICQ Server Relay message of "
+ purple_debug_info("oscar", "Got an ICQ Server Relay message of "
"type %d\n", args->info.rtfmsg.msgtype);
- }
+ purple_debug_info("oscar", "Sending X-Status Reply\n");
+ if(args->info.rtfmsg.msgtype == 26)
+ icq_relay_xstatus(od, userinfo->bn, args->cookie);
+
+ if(args->info.rtfmsg.msgtype == 1)
+ {
+ if(rtfmsg)
+ {
+ serv_got_im(gc, userinfo->bn, rtfmsg, flags,
+ time(NULL));
+ }
+ else
+ {
+ serv_got_im(gc, userinfo->bn,
+ args->info.rtfmsg.rtfmsg, flags,
+ time(NULL));
+ }
+ }
+ }
else
{
purple_debug_error("oscar", "Unknown request class %hu\n",
@@ -3250,6 +3325,29 @@ static int purple_parse_clientauto_ch4(OscarData *od, char *who, guint16 reason,
} break;
+ case 0x0006: { /* Reply from an ICQ status message request */
+ char *statusmsg, **splitmsg;
+ PurpleNotifyUserInfo *user_info;
+
+ /* Split at (carriage return/newline)'s, then rejoin later with BRs between. */
+ statusmsg = oscar_icqstatus(state);
+ splitmsg = g_strsplit(msg, "\r\n", 0);
+
+ user_info = purple_notify_user_info_new();
+
+ purple_notify_user_info_add_pair(user_info, _("UIN"), who);
+ purple_notify_user_info_add_pair(user_info, _("Status"), statusmsg);
+ purple_notify_user_info_add_section_break(user_info);
+ purple_notify_user_info_add_pair(user_info, NULL, g_strjoinv("<BR>", splitmsg));
+
+ g_free(statusmsg);
+ g_strfreev(splitmsg);
+
+ purple_notify_userinfo(gc, who, user_info, NULL, NULL);
+ purple_notify_user_info_destroy(user_info);
+
+ } break;
+
default: {
purple_debug_warning("oscar",
"Received an unknown client auto-response from %s. "
@@ -3497,6 +3595,55 @@ static int purple_parse_userinfo(OscarData *od, FlapConnection *conn, FlapFrame
return 1;
}
+static int purple_got_infoblock(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
+{
+ PurpleConnection *gc = od->gc;
+ PurpleAccount *account = purple_connection_get_account(gc);
+ PurpleBuddy *b;
+ PurplePresence *presence;
+ PurpleStatus *status;
+ gchar *message = NULL;
+
+ va_list ap;
+ aim_userinfo_t *userinfo;
+
+ va_start(ap, fr);
+ userinfo = va_arg(ap, aim_userinfo_t *);
+ va_end(ap);
+
+ b = purple_find_buddy(account, userinfo->bn);
+ if (b == NULL)
+ return 1;
+
+ if (!oscar_util_valid_name_icq(userinfo->bn))
+ {
+ if (strcmp(purple_buddy_get_name(b), userinfo->bn) != 0)
+ serv_got_alias(gc, purple_buddy_get_name(b), userinfo->bn);
+ else
+ serv_got_alias(gc, purple_buddy_get_name(b), NULL);
+ }
+
+ presence = purple_buddy_get_presence(b);
+ status = purple_presence_get_active_status(presence);
+
+ if (purple_status_is_online(status) && !purple_status_is_available(status) &&
+ userinfo->flags & AIM_FLAG_AWAY && userinfo->away_len > 0 &&
+ userinfo->away != NULL && userinfo->away_encoding != NULL)
+ {
+ gchar *charset = oscar_encoding_extract(userinfo->away_encoding);
+ message = oscar_encoding_to_utf8(account, charset,
+ userinfo->away,
+ userinfo->away_len);
+ g_free(charset);
+ purple_prpl_got_user_status(account, userinfo->bn,
+ purple_status_get_id(status),
+ "message", message, NULL);
+ g_free(message);
+ }
+
+ return 1;
+}
+
static int purple_parse_motd(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
{
char *msg;
@@ -4848,6 +4995,16 @@ oscar_set_extendedstatus(PurpleConnection *gc)
data |= AIM_ICQ_STATE_CHAT;
else if (!strcmp(status_id, OSCAR_STATUS_ID_INVISIBLE))
data |= AIM_ICQ_STATE_INVISIBLE;
+ else if (!strcmp(status_id, OSCAR_STATUS_ID_EVIL))
+ data |= AIM_ICQ_STATE_EVIL;
+ else if (!strcmp(status_id, OSCAR_STATUS_ID_DEPRESSION))
+ data |= AIM_ICQ_STATE_DEPRESSION;
+ else if (!strcmp(status_id, OSCAR_STATUS_ID_ATWORK))
+ data |= AIM_ICQ_STATE_ATWORK;
+ else if (!strcmp(status_id, OSCAR_STATUS_ID_ATHOME))
+ data |= AIM_ICQ_STATE_ATHOME;
+ else if (!strcmp(status_id, OSCAR_STATUS_ID_LUNCH))
+ data |= AIM_ICQ_STATE_LUNCH;
else if (!strcmp(status_id, OSCAR_STATUS_ID_CUSTOM))
data |= AIM_ICQ_STATE_OUT | AIM_ICQ_STATE_AWAY;
@@ -5009,6 +5166,12 @@ oscar_set_status(PurpleAccount *account, PurpleStatus *status)
pc = purple_account_get_connection(account);
od = purple_connection_get_protocol_data(pc);
+ /* There's no need to do the stuff below for mood updates. */
+ if (purple_status_type_get_primitive(purple_status_get_type(status)) == PURPLE_STATUS_MOOD) {
+ aim_locate_setcaps(od, purple_caps);
+ return;
+ }
+
/* Set the AIM-style away message for both AIM and ICQ accounts */
oscar_set_info_and_status(account, FALSE, NULL, TRUE, status);
@@ -5961,6 +6124,11 @@ int oscar_send_chat(PurpleConnection *gc, int id, const char *message, PurpleMes
return 0;
}
+PurpleMood* oscar_get_purple_moods(PurpleAccount *account)
+{
+ return icq_get_purple_moods(account);
+}
+
const char *oscar_list_icon_icq(PurpleAccount *a, PurpleBuddy *b)
{
const char *name = b ? purple_buddy_get_name(b) : NULL;
@@ -6031,12 +6199,17 @@ const char *oscar_list_emblem(PurpleBuddy *b)
return "admin";
if (userinfo->flags & AIM_FLAG_ACTIVEBUDDY)
return "bot";
- if (userinfo->capabilities & OSCAR_CAPABILITY_HIPTOP)
- return "hiptop";
if (userinfo->capabilities & OSCAR_CAPABILITY_SECUREIM)
return "secure";
if (userinfo->icqinfo.status & AIM_ICQ_STATE_BIRTHDAY)
return "birthday";
+
+ /* Make the mood icon override anything below this. */
+ if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_MOOD))
+ return NULL;
+
+ if (userinfo->capabilities & OSCAR_CAPABILITY_HIPTOP)
+ return "hiptop";
}
return NULL;
}
@@ -6259,9 +6432,53 @@ oscar_status_types(PurpleAccount *account)
purple_value_new(PURPLE_TYPE_STRING), NULL);
status_types = g_list_prepend(status_types, type);
- type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE,
+ type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
OSCAR_STATUS_ID_FREE4CHAT,
- _("Free For Chat"), TRUE, is_icq, FALSE);
+ _("Free For Chat"), TRUE, is_icq, FALSE,
+ "message", _("Message"),
+ purple_value_new(PURPLE_TYPE_STRING), NULL);
+
+ status_types = g_list_prepend(status_types, type);
+
+ type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+ OSCAR_STATUS_ID_EVIL,
+ _("Evil"), TRUE, is_icq, FALSE,
+ "message", _("Message"),
+ purple_value_new(PURPLE_TYPE_STRING), NULL);
+ status_types = g_list_prepend(status_types, type);
+
+
+ type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+ OSCAR_STATUS_ID_DEPRESSION,
+ _("Depression"), TRUE, is_icq, FALSE,
+ "message", _("Message"),
+ purple_value_new(PURPLE_TYPE_STRING), NULL);
+ status_types = g_list_prepend(status_types, type);
+
+
+ type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+ OSCAR_STATUS_ID_ATHOME,
+ _("At home"), TRUE, is_icq, FALSE,
+ "message", _("Message"),
+ purple_value_new(PURPLE_TYPE_STRING), NULL);
+ status_types = g_list_prepend(status_types, type);
+
+
+ type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+ OSCAR_STATUS_ID_ATWORK,
+ _("At work"), TRUE, is_icq, FALSE,
+ "message", _("Message"),
+ purple_value_new(PURPLE_TYPE_STRING), NULL);
+
+ status_types = g_list_prepend(status_types, type);
+
+
+ type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+ OSCAR_STATUS_ID_LUNCH,
+ _("Lunch"), TRUE, is_icq, FALSE,
+ "message", _("Message"),
+ purple_value_new(PURPLE_TYPE_STRING), NULL);
+
status_types = g_list_prepend(status_types, type);
type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY,
@@ -6271,9 +6488,12 @@ oscar_status_types(PurpleAccount *account)
purple_value_new(PURPLE_TYPE_STRING), NULL);
status_types = g_list_prepend(status_types, type);
- type = purple_status_type_new_full(PURPLE_STATUS_INVISIBLE,
+ type = purple_status_type_new_with_attrs(PURPLE_STATUS_INVISIBLE,
OSCAR_STATUS_ID_INVISIBLE,
- NULL, TRUE, TRUE, FALSE);
+ NULL, TRUE, TRUE, FALSE,
+ "message", _("Message"),
+ purple_value_new(PURPLE_TYPE_STRING), NULL);
+
status_types = g_list_prepend(status_types, type);
type = purple_status_type_new_full(PURPLE_STATUS_MOBILE, OSCAR_STATUS_ID_MOBILE, NULL, FALSE, FALSE, TRUE);
@@ -6306,9 +6526,14 @@ oscar_status_types(PurpleAccount *account)
NULL, TRUE, TRUE, FALSE);
status_types = g_list_prepend(status_types, type);
- status_types = g_list_reverse(status_types);
+ type = purple_status_type_new_with_attrs(PURPLE_STATUS_MOOD,
+ "mood", NULL, TRUE, is_icq, TRUE,
+ PURPLE_MOOD_NAME, _("Mood Name"), purple_value_new(PURPLE_TYPE_STRING),
+ PURPLE_MOOD_COMMENT, _("Mood Comment"), purple_value_new(PURPLE_TYPE_STRING),
+ NULL);
+ status_types = g_list_prepend(status_types, type);
- return status_types;
+ return g_list_reverse(status_types);
}
static void oscar_ssi_editcomment(struct name_data *data, const char *text) {
@@ -6480,6 +6705,23 @@ oscar_close_directim(gpointer object, gpointer ignored)
}
}
+static void oscar_get_icqxstatusmsg (PurpleBlistNode *node, gpointer ignore)
+{
+ PurpleBuddy *buddy;
+ PurpleConnection *gc;
+ PurpleAccount *account;
+
+
+ g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+
+ buddy = (PurpleBuddy *)node;
+ gc = purple_account_get_connection(buddy->account);
+ account = purple_connection_get_account(gc);
+ purple_debug_info("oscar", "Manual X-Status Get From %s to %s:\n", purple_buddy_get_name(buddy), account->username);
+
+ icq_im_xstatus_request(gc->proto_data, purple_buddy_get_name(buddy));
+}
+
static void
oscar_get_aim_info_cb(PurpleBlistNode *node, gpointer ignore)
{
@@ -6529,15 +6771,13 @@ oscar_buddy_menu(PurpleBuddy *buddy) {
menu = g_list_prepend(menu, act);
}
-#if 0
if (od->icq)
{
- act = purple_menu_action_new(_("Get Status Msg"),
- PURPLE_CALLBACK(oscar_get_icqstatusmsg),
+ act = purple_menu_action_new(_("Get X-Status Msg"),
+ PURPLE_CALLBACK(oscar_get_icqxstatusmsg),
NULL, NULL);
menu = g_list_prepend(menu, act);
}
-#endif
if (userinfo &&
oscar_util_name_compare(purple_account_get_username(account), bname) &&