/* Subtype 0x0006 */ static int userinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; aim_userinfo_t *userinfo, *userinfo2; GSList *tlvlist; aim_tlv_t *tlv = NULL; int was_explicit; userinfo = (aim_userinfo_t *)g_malloc(sizeof(aim_userinfo_t)); aim_info_extract(od, bs, userinfo); tlvlist = aim_tlvlist_read(bs); /* Profile will be 1 and 2 */ userinfo->info_encoding = aim_tlv_getstr(tlvlist, 0x0001, 1); if ((tlv = aim_tlv_gettlv(tlvlist, 0x0002, 1))) { userinfo->info = (char *)g_malloc(tlv->length); memcpy(userinfo->info, tlv->value, tlv->length); userinfo->info_len = tlv->length; } /* Away message will be 3 and 4 */ userinfo->away_encoding = aim_tlv_getstr(tlvlist, 0x0003, 1); if ((tlv = aim_tlv_gettlv(tlvlist, 0x0004, 1))) { userinfo->away = (char *)g_malloc(tlv->length); memcpy(userinfo->away, tlv->value, tlv->length); userinfo->away_len = tlv->length; } /* Caps will be 5 */ if ((tlv = aim_tlv_gettlv(tlvlist, 0x0005, 1))) { ByteStream cbs; byte_stream_init(&cbs, tlv->value, tlv->length); userinfo->capabilities = aim_locate_getcaps(od, &cbs, tlv->length); userinfo->present = AIM_USERINFO_PRESENT_CAPABILITIES; } aim_tlvlist_free(tlvlist); aim_locate_adduserinfo(od, userinfo); userinfo2 = aim_locate_finduserinfo(od, userinfo->sn); aim_info_free(userinfo); g_free(userinfo); /* * Remove this screen name from our queue. If the client requested * this buddy's info explicitly, then notify them that we have info * for this buddy. */ if (userinfo2 != NULL) { was_explicit = aim_locate_gotuserinfo(od, conn, userinfo2->sn); if (was_explicit == TRUE) if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) ret = userfunc(od, conn, frame, userinfo2); } return ret; }
/* Subtype 0x0006 */ static int userinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_userinfo_t *userinfo, *userinfo2; GSList *tlvlist; aim_tlv_t *tlv = NULL; userinfo = (aim_userinfo_t *)g_malloc(sizeof(aim_userinfo_t)); aim_info_extract(od, bs, userinfo); tlvlist = aim_tlvlist_read(bs); /* Profile will be 1 and 2 */ userinfo->info_encoding = aim_tlv_getstr(tlvlist, 0x0001, 1); if ((tlv = aim_tlv_gettlv(tlvlist, 0x0002, 1))) { userinfo->info = (char *)g_malloc(tlv->length); memcpy(userinfo->info, tlv->value, tlv->length); userinfo->info_len = tlv->length; } /* Away message will be 3 and 4 */ userinfo->away_encoding = aim_tlv_getstr(tlvlist, 0x0003, 1); if ((tlv = aim_tlv_gettlv(tlvlist, 0x0004, 1))) { userinfo->away = (char *)g_malloc(tlv->length); memcpy(userinfo->away, tlv->value, tlv->length); userinfo->away_len = tlv->length; } /* Caps will be 5 */ if ((tlv = aim_tlv_gettlv(tlvlist, 0x0005, 1))) { ByteStream cbs; PurpleAccount *account = purple_connection_get_account(od->gc); const char *mood; byte_stream_init(&cbs, tlv->value, tlv->length); userinfo->capabilities = aim_locate_getcaps(od, &cbs, tlv->length); byte_stream_rewind(&cbs); userinfo->present = AIM_USERINFO_PRESENT_CAPABILITIES; mood = aim_receive_custom_icon(od, &cbs, tlv->length); if (mood) purple_prpl_got_user_status(account, userinfo->bn, "mood", PURPLE_MOOD_NAME, mood, NULL); else purple_prpl_got_user_status_deactive(account, userinfo->bn, "mood"); } aim_tlvlist_free(tlvlist); aim_locate_adduserinfo(od, userinfo); userinfo2 = aim_locate_finduserinfo(od, userinfo->bn); aim_info_free(userinfo); g_free(userinfo); /* Show the info to the user */ oscar_user_info_display_aim(od, userinfo2); return ret; }
/* Subtype 0x0006 */ static int userinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { int ret = 0; aim_rxcallback_t userfunc; aim_userinfo_t *userinfo, *userinfo2; GSList *tlvlist; aim_tlv_t *tlv = NULL; userinfo = (aim_userinfo_t *)g_malloc(sizeof(aim_userinfo_t)); aim_info_extract(od, bs, userinfo); tlvlist = aim_tlvlist_read(bs); /* Profile will be 1 and 2 */ userinfo->info_encoding = aim_tlv_getstr(tlvlist, 0x0001, 1); if ((tlv = aim_tlv_gettlv(tlvlist, 0x0002, 1))) { userinfo->info = (char *)g_malloc(tlv->length); memcpy(userinfo->info, tlv->value, tlv->length); userinfo->info_len = tlv->length; } /* Away message will be 3 and 4 */ userinfo->away_encoding = aim_tlv_getstr(tlvlist, 0x0003, 1); if ((tlv = aim_tlv_gettlv(tlvlist, 0x0004, 1))) { userinfo->away = (char *)g_malloc(tlv->length); memcpy(userinfo->away, tlv->value, tlv->length); userinfo->away_len = tlv->length; } /* Caps will be 5 */ if ((tlv = aim_tlv_gettlv(tlvlist, 0x0005, 1))) { ByteStream cbs; byte_stream_init(&cbs, tlv->value, tlv->length); userinfo->capabilities = aim_locate_getcaps(od, &cbs, tlv->length); userinfo->present = AIM_USERINFO_PRESENT_CAPABILITIES; } aim_tlvlist_free(tlvlist); aim_locate_adduserinfo(od, userinfo); userinfo2 = aim_locate_finduserinfo(od, userinfo->bn); aim_info_free(userinfo); g_free(userinfo); /* Show the info to the user */ if (userinfo2 != NULL && ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))) ret = userfunc(od, conn, frame, userinfo2); return ret; }
void oscar_user_info_append_extra_info(PurpleConnection *gc, PurpleNotifyUserInfo *user_info, PurpleBuddy *b, aim_userinfo_t *userinfo) { OscarData *od; PurpleAccount *account; PurplePresence *presence = NULL; PurpleStatus *status = NULL; PurpleGroup *g = NULL; struct buddyinfo *bi = NULL; char *tmp; const char *bname = NULL, *gname = NULL; od = purple_connection_get_protocol_data(gc); account = purple_connection_get_account(gc); if ((user_info == NULL) || ((b == NULL) && (userinfo == NULL))) return; if (userinfo == NULL) userinfo = aim_locate_finduserinfo(od, purple_buddy_get_name(b)); if (b == NULL) b = purple_find_buddy(account, userinfo->bn); if (b != NULL) { bname = purple_buddy_get_name(b); g = purple_buddy_get_group(b); gname = purple_group_get_name(g); presence = purple_buddy_get_presence(b); status = purple_presence_get_active_status(presence); } if (userinfo != NULL) bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, userinfo->bn)); if ((bi != NULL) && (bi->ipaddr != 0)) { tmp = g_strdup_printf("%hhu.%hhu.%hhu.%hhu", (bi->ipaddr & 0xff000000) >> 24, (bi->ipaddr & 0x00ff0000) >> 16, (bi->ipaddr & 0x0000ff00) >> 8, (bi->ipaddr & 0x000000ff)); oscar_user_info_add_pair(user_info, _("IP Address"), tmp); g_free(tmp); }
/* * Add the userinfo to our linked list. If we already have userinfo * for this buddy, then just overwrite parts of the old data. * * @param userinfo Contains the new information for the buddy. */ static void aim_locate_adduserinfo(OscarData *od, aim_userinfo_t *userinfo) { aim_userinfo_t *cur; cur = aim_locate_finduserinfo(od, userinfo->bn); if (cur == NULL) { cur = (aim_userinfo_t *)g_new0(aim_userinfo_t, 1); cur->bn = g_strdup(userinfo->bn); cur->next = od->locate.userinfo; od->locate.userinfo = cur; } cur->warnlevel = userinfo->warnlevel; cur->idletime = userinfo->idletime; if (userinfo->flags != 0) cur->flags = userinfo->flags; if (userinfo->createtime != 0) cur->createtime = userinfo->createtime; if (userinfo->membersince != 0) cur->membersince = userinfo->membersince; if (userinfo->onlinesince != 0) cur->onlinesince = userinfo->onlinesince; if (userinfo->sessionlen != 0) cur->sessionlen = userinfo->sessionlen; if (userinfo->capabilities != 0) cur->capabilities = userinfo->capabilities; cur->present |= userinfo->present; if (userinfo->iconcsumlen > 0) { g_free(cur->iconcsum); cur->iconcsum = (guint8 *)g_malloc(userinfo->iconcsumlen); memcpy(cur->iconcsum, userinfo->iconcsum, userinfo->iconcsumlen); cur->iconcsumlen = userinfo->iconcsumlen; } if (userinfo->info != NULL) { g_free(cur->info); g_free(cur->info_encoding); if (userinfo->info_len > 0) { cur->info = (char *)g_malloc(userinfo->info_len); memcpy(cur->info, userinfo->info, userinfo->info_len); } else cur->info = NULL; cur->info_encoding = g_strdup(userinfo->info_encoding); cur->info_len = userinfo->info_len; } if (userinfo->status != NULL) { g_free(cur->status); g_free(cur->status_encoding); if (userinfo->status_len > 0) { cur->status = (char *)g_malloc(userinfo->status_len); memcpy(cur->status, userinfo->status, userinfo->status_len); } else cur->status = NULL; if (userinfo->status_encoding != NULL) cur->status_encoding = g_strdup(userinfo->status_encoding); else cur->status_encoding = NULL; cur->status_len = userinfo->status_len; } if (userinfo->itmsurl != NULL) { g_free(cur->itmsurl); g_free(cur->itmsurl_encoding); if (userinfo->itmsurl_len > 0) { cur->itmsurl = (char *)g_malloc(userinfo->itmsurl_len); memcpy(cur->itmsurl, userinfo->itmsurl, userinfo->itmsurl_len); } else cur->itmsurl = NULL; if (userinfo->itmsurl_encoding != NULL) cur->itmsurl_encoding = g_strdup(userinfo->itmsurl_encoding); else cur->itmsurl_encoding = NULL; cur->itmsurl_len = userinfo->itmsurl_len; } if (userinfo->away != NULL) { g_free(cur->away); g_free(cur->away_encoding); if (userinfo->away_len > 0) { cur->away = (char *)g_malloc(userinfo->away_len); memcpy(cur->away, userinfo->away, userinfo->away_len); } else cur->away = NULL; cur->away_encoding = g_strdup(userinfo->away_encoding); cur->away_len = userinfo->away_len; } else { /* * We don't have an away message specified in this user_info * block, so clear any cached away message now. */ if (cur->away) { g_free(cur->away); cur->away = NULL; } if (cur->away_encoding) { g_free(cur->away_encoding); cur->away_encoding = NULL; } cur->away_len = 0; } }
/* * Add the userinfo to our linked list. If we already have userinfo * for this buddy, then just overwrite parts of the old data. * * @param userinfo Contains the new information for the buddy. */ static void aim_locate_adduserinfo(OscarData *od, aim_userinfo_t *userinfo) { aim_userinfo_t *cur; FlapConnection *conn; aim_rxcallback_t userfunc; cur = aim_locate_finduserinfo(od, userinfo->sn); if (cur == NULL) { cur = (aim_userinfo_t *)g_new0(aim_userinfo_t, 1); cur->sn = g_strdup(userinfo->sn); cur->next = od->locate.userinfo; od->locate.userinfo = cur; } cur->warnlevel = userinfo->warnlevel; cur->idletime = userinfo->idletime; if (userinfo->flags != 0) cur->flags = userinfo->flags; if (userinfo->createtime != 0) cur->createtime = userinfo->createtime; if (userinfo->membersince != 0) cur->membersince = userinfo->membersince; if (userinfo->onlinesince != 0) cur->onlinesince = userinfo->onlinesince; if (userinfo->sessionlen != 0) cur->sessionlen = userinfo->sessionlen; if (userinfo->capabilities != 0) cur->capabilities = userinfo->capabilities; cur->present |= userinfo->present; if (userinfo->iconcsumlen > 0) { g_free(cur->iconcsum); cur->iconcsum = (guint8 *)g_malloc(userinfo->iconcsumlen); memcpy(cur->iconcsum, userinfo->iconcsum, userinfo->iconcsumlen); cur->iconcsumlen = userinfo->iconcsumlen; } if (userinfo->info != NULL) { g_free(cur->info); g_free(cur->info_encoding); if (userinfo->info_len > 0) { cur->info = (char *)g_malloc(userinfo->info_len); memcpy(cur->info, userinfo->info, userinfo->info_len); } else cur->info = NULL; cur->info_encoding = g_strdup(userinfo->info_encoding); cur->info_len = userinfo->info_len; } if (userinfo->status != NULL) { g_free(cur->status); g_free(cur->status_encoding); if (userinfo->status_len > 0) { cur->status = (char *)g_malloc(userinfo->status_len); memcpy(cur->status, userinfo->status, userinfo->status_len); } else cur->status = NULL; if (userinfo->status_encoding != NULL) cur->status_encoding = g_strdup(userinfo->status_encoding); else cur->status_encoding = NULL; cur->status_len = userinfo->status_len; } if (userinfo->itmsurl != NULL) { g_free(cur->itmsurl); g_free(cur->itmsurl_encoding); if (userinfo->itmsurl_len > 0) { cur->itmsurl = (char *)g_malloc(userinfo->itmsurl_len); memcpy(cur->itmsurl, userinfo->itmsurl, userinfo->itmsurl_len); } else cur->itmsurl = NULL; if (userinfo->itmsurl_encoding != NULL) cur->itmsurl_encoding = g_strdup(userinfo->itmsurl_encoding); else cur->itmsurl_encoding = NULL; cur->itmsurl_len = userinfo->itmsurl_len; } if (userinfo->away != NULL) { g_free(cur->away); g_free(cur->away_encoding); if (userinfo->away_len > 0) { cur->away = (char *)g_malloc(userinfo->away_len); memcpy(cur->away, userinfo->away, userinfo->away_len); } else cur->away = NULL; cur->away_encoding = g_strdup(userinfo->away_encoding); cur->away_len = userinfo->away_len; } else if (!(userinfo->flags & AIM_FLAG_AWAY)) { /* * We don't have an away message specified in this user_info block. * If the user is not away, clear any cached away message now. */ if (cur->away) { g_free(cur->away); cur->away = NULL; } if (cur->away_encoding) { g_free(cur->away_encoding); cur->away_encoding = NULL; } cur->away_len = 0; } /* * This callback can be used by a client if they want to know whenever * info for a buddy is updated. For example, if a client shows away * messages in its buddy list, then it would need to know if a user's * away message changes. */ conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE); if ((userfunc = aim_callhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_GOTINFOBLOCK))) userfunc(od, conn, NULL, cur); }
/** * @brief Append the status information to a user_info struct * * The returned information is HTML-ready, appropriately escaped, as all information in a user_info struct should be HTML. * * @param gc The PurpleConnection * @param user_info A PurpleNotifyUserInfo object to which status information will be added * @param b The PurpleBuddy whose status is desired. This or the aim_userinfo_t (or both) must be passed to oscar_user_info_append_status(). * @param userinfo The aim_userinfo_t of the buddy whose status is desired. This or the PurpleBuddy (or both) must be passed to oscar_user_info_append_status(). * @param use_html_status If TRUE, prefer HTML-formatted away message over plaintext available message. */ void oscar_user_info_append_status(PurpleConnection *gc, PurpleNotifyUserInfo *user_info, PurpleBuddy *b, aim_userinfo_t *userinfo, gboolean use_html_status) { PurpleAccount *account = purple_connection_get_account(gc); OscarData *od; PurplePresence *presence = NULL; PurpleStatus *status = NULL; gchar *message = NULL, *itmsurl = NULL, *tmp; gboolean escaping_needed = TRUE; od = purple_connection_get_protocol_data(gc); if (b == NULL && userinfo == NULL) return; if (b == NULL) b = purple_find_buddy(purple_connection_get_account(gc), userinfo->bn); else userinfo = aim_locate_finduserinfo(od, purple_buddy_get_name(b)); if (b) { presence = purple_buddy_get_presence(b); status = purple_presence_get_active_status(presence); } /* If we have both b and userinfo we favor userinfo, because if we're viewing someone's profile then we want the HTML away message, and the "message" attribute of the status contains only the plaintext message. */ if (userinfo) { if ((userinfo->flags & AIM_FLAG_AWAY) && use_html_status && userinfo->away_len > 0 && userinfo->away != NULL && userinfo->away_encoding != NULL) { /* Away message */ message = oscar_encoding_to_utf8(userinfo->away_encoding, userinfo->away, userinfo->away_len); escaping_needed = FALSE; } else { /* * Available message or non-HTML away message (because that's * all we have right now. */ if ((userinfo->status != NULL) && userinfo->status[0] != '\0') { message = oscar_encoding_to_utf8(userinfo->status_encoding, userinfo->status, userinfo->status_len); } #if defined (_WIN32) || defined (__APPLE__) if (userinfo->itmsurl && (userinfo->itmsurl[0] != '\0')) { itmsurl = oscar_encoding_to_utf8(userinfo->itmsurl_encoding, userinfo->itmsurl, userinfo->itmsurl_len); } #endif } } else { message = g_strdup(purple_status_get_attr_string(status, "message")); itmsurl = g_strdup(purple_status_get_attr_string(status, "itmsurl")); } if (message) { tmp = oscar_util_format_string(message, purple_account_get_username(account)); g_free(message); message = tmp; if (escaping_needed) { tmp = purple_markup_escape_text(message, -1); g_free(message); message = tmp; } } if (use_html_status && itmsurl) { tmp = g_strdup_printf("<a href=\"%s\">%s</a>", itmsurl, message); g_free(message); message = tmp; } if (b) { if (purple_presence_is_online(presence)) { gboolean is_away = ((status && !purple_status_is_available(status)) || (userinfo && (userinfo->flags & AIM_FLAG_AWAY))); if (oscar_util_valid_name_icq(purple_buddy_get_name(b)) || is_away || !message || !(*message)) { /* Append the status name for online ICQ statuses, away AIM statuses, and for all buddies with no message. * If the status name and the message are the same, only show one. */ const char *status_name = purple_status_get_name(status); if (status_name && message && !strcmp(status_name, message)) status_name = NULL; tmp = g_strdup_printf("%s%s%s", status_name ? status_name : "", ((status_name && message) && *message) ? ": " : "", (message && *message) ? message : ""); g_free(message); message = tmp; } } else if (aim_ssi_waitingforauth(od->ssi.local, aim_ssi_itemlist_findparentname(od->ssi.local, purple_buddy_get_name(b)), purple_buddy_get_name(b))) { /* Note if an offline buddy is not authorized */ tmp = g_strdup_printf("%s%s%s", _("Not Authorized"), (message && *message) ? ": " : "", (message && *message) ? message : ""); g_free(message); message = tmp; } else { g_free(message); message = g_strdup(_("Offline")); } } if (presence) { const char *mood; const char *comment; char *description; status = purple_presence_get_status(presence, "mood"); mood = icq_get_custom_icon_description(purple_status_get_attr_string(status, PURPLE_MOOD_NAME)); if (mood) { comment = purple_status_get_attr_string(status, PURPLE_MOOD_COMMENT); if (comment) { char *escaped_comment = purple_markup_escape_text(comment, -1); description = g_strdup_printf("%s (%s)", _(mood), escaped_comment); g_free(escaped_comment); } else { description = g_strdup(_(mood)); } purple_notify_user_info_add_pair(user_info, _("Mood"), description); g_free(description); } } purple_notify_user_info_add_pair(user_info, _("Status"), message); g_free(message); }