File:  [Coherent Logic Development] / ChivanetAimPidgin / oscarprpl / src / c / userinfo.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Mon Jan 27 19:48:25 2025 UTC (6 months ago) by snw
Branches: MAIN, CoherentLogicDevelopment
CVS tags: test-tag, start, HEAD
Pidgin AIM Plugin for ChivaNet

    1: /*
    2:  * Purple's oscar protocol plugin
    3:  * This file is the legal property of its developers.
    4:  * Please see the AUTHORS file distributed alongside this file.
    5:  *
    6:  * This library is free software; you can redistribute it and/or
    7:  * modify it under the terms of the GNU Lesser General Public
    8:  * License as published by the Free Software Foundation; either
    9:  * version 2 of the License, or (at your option) any later version.
   10:  *
   11:  * This library is distributed in the hope that it will be useful,
   12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14:  * Lesser General Public License for more details.
   15:  *
   16:  * You should have received a copy of the GNU Lesser General Public
   17:  * License along with this library; if not, write to the Free Software
   18:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
   19: */
   20: 
   21: /*
   22:  * Displaying various information about buddies.
   23:  */
   24: 
   25: #include "encoding.h"
   26: #include "oscar.h"
   27: 
   28: static gchar *
   29: oscar_caps_to_string(guint64 caps)
   30: {
   31: 	GString *str;
   32: 	const gchar *tmp;
   33: 	guint64 bit = 1;
   34: 
   35: 	str = g_string_new("");
   36: 
   37: 	if (!caps) {
   38: 		return NULL;
   39: 	} else while (bit <= OSCAR_CAPABILITY_LAST) {
   40: 		if (bit & caps) {
   41: 			switch (bit) {
   42: 			case OSCAR_CAPABILITY_BUDDYICON:
   43: 				tmp = _("Buddy Icon");
   44: 				break;
   45: 			case OSCAR_CAPABILITY_TALK:
   46: 				tmp = _("Voice");
   47: 				break;
   48: 			case OSCAR_CAPABILITY_DIRECTIM:
   49: 				tmp = _("AIM Direct IM");
   50: 				break;
   51: 			case OSCAR_CAPABILITY_CHAT:
   52: 				tmp = _("Chat");
   53: 				break;
   54: 			case OSCAR_CAPABILITY_GETFILE:
   55: 				tmp = _("Get File");
   56: 				break;
   57: 			case OSCAR_CAPABILITY_SENDFILE:
   58: 				tmp = _("Send File");
   59: 				break;
   60: 			case OSCAR_CAPABILITY_GAMES:
   61: 			case OSCAR_CAPABILITY_GAMES2:
   62: 				tmp = _("Games");
   63: 				break;
   64: 			case OSCAR_CAPABILITY_XTRAZ:
   65: 			case OSCAR_CAPABILITY_NEWCAPS:
   66: 				tmp = _("ICQ Xtraz");
   67: 				break;
   68: 			case OSCAR_CAPABILITY_ADDINS:
   69: 				tmp = _("Add-Ins");
   70: 				break;
   71: 			case OSCAR_CAPABILITY_SENDBUDDYLIST:
   72: 				tmp = _("Send Buddy List");
   73: 				break;
   74: 			case OSCAR_CAPABILITY_ICQ_DIRECT:
   75: 				tmp = _("ICQ Direct Connect");
   76: 				break;
   77: 			case OSCAR_CAPABILITY_APINFO:
   78: 				tmp = _("AP User");
   79: 				break;
   80: 			case OSCAR_CAPABILITY_ICQRTF:
   81: 				tmp = _("ICQ RTF");
   82: 				break;
   83: 			case OSCAR_CAPABILITY_EMPTY:
   84: 				tmp = _("Nihilist");
   85: 				break;
   86: 			case OSCAR_CAPABILITY_ICQSERVERRELAY:
   87: 				tmp = _("ICQ Server Relay");
   88: 				break;
   89: 			case OSCAR_CAPABILITY_UNICODEOLD:
   90: 				tmp = _("Old ICQ UTF8");
   91: 				break;
   92: 			case OSCAR_CAPABILITY_TRILLIANCRYPT:
   93: 				tmp = _("Trillian Encryption");
   94: 				break;
   95: 			case OSCAR_CAPABILITY_UNICODE:
   96: 				tmp = _("ICQ UTF8");
   97: 				break;
   98: 			case OSCAR_CAPABILITY_HIPTOP:
   99: 				tmp = _("Hiptop");
  100: 				break;
  101: 			case OSCAR_CAPABILITY_SECUREIM:
  102: 				tmp = _("Security Enabled");
  103: 				break;
  104: 			case OSCAR_CAPABILITY_VIDEO:
  105: 				tmp = _("Video Chat");
  106: 				break;
  107: 			/* Not actually sure about this one... WinAIM doesn't show anything */
  108: 			case OSCAR_CAPABILITY_ICHATAV:
  109: 				tmp = _("iChat AV");
  110: 				break;
  111: 			case OSCAR_CAPABILITY_LIVEVIDEO:
  112: 				tmp = _("Live Video");
  113: 				break;
  114: 			case OSCAR_CAPABILITY_CAMERA:
  115: 				tmp = _("Camera");
  116: 				break;
  117: 			case OSCAR_CAPABILITY_ICHAT_SCREENSHARE:
  118: 				tmp = _("Screen Sharing");
  119: 				break;
  120: 			default:
  121: 				tmp = NULL;
  122: 				break;
  123: 			}
  124: 			if (tmp)
  125: 				g_string_append_printf(str, "%s%s", (*(str->str) == '\0' ? "" : ", "), tmp);
  126: 		}
  127: 		bit <<= 1;
  128: 	}
  129: 
  130: 	return g_string_free(str, FALSE);
  131: }
  132: 
  133: static void
  134: oscar_user_info_add_pair(PurpleNotifyUserInfo *user_info, const char *name, const char *value)
  135: {
  136: 	if (value && value[0]) {
  137: 		purple_notify_user_info_add_pair(user_info, name, value);
  138: 	}
  139: }
  140: 
  141: static void
  142: oscar_user_info_convert_and_add(PurpleAccount *account, OscarData *od, PurpleNotifyUserInfo *user_info,
  143: 					const char *name, const char *value)
  144: {
  145: 	gchar *utf8;
  146: 
  147: 	if (value && value[0] && (utf8 = oscar_utf8_try_convert(account, od, value))) {
  148: 		purple_notify_user_info_add_pair(user_info, name, utf8);
  149: 		g_free(utf8);
  150: 	}
  151: }
  152: 
  153: static void
  154: oscar_user_info_convert_and_add_hyperlink(PurpleAccount *account, OscarData *od, PurpleNotifyUserInfo *user_info,
  155: 						const char *name, const char *value, const char *url_prefix)
  156: {
  157: 	gchar *utf8;
  158: 
  159: 	if (value && value[0] && (utf8 = oscar_utf8_try_convert(account, od, value))) {
  160: 		gchar *tmp = g_strdup_printf("<a href=\"%s%s\">%s</a>", url_prefix, utf8, utf8);
  161: 		purple_notify_user_info_add_pair(user_info, name, tmp);
  162: 		g_free(utf8);
  163: 		g_free(tmp);
  164: 	}
  165: }
  166: 
  167: /**
  168:  * @brief Append the status information to a user_info struct
  169:  *
  170:  * The returned information is HTML-ready, appropriately escaped, as all information in a user_info struct should be HTML.
  171:  *
  172:  * @param gc The PurpleConnection
  173:  * @param user_info A PurpleNotifyUserInfo object to which status information will be added
  174:  * @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().
  175:  * @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().
  176:  * @param use_html_status If TRUE, prefer HTML-formatted away message over plaintext available message.
  177:  */
  178: void
  179: oscar_user_info_append_status(PurpleConnection *gc, PurpleNotifyUserInfo *user_info, PurpleBuddy *b, aim_userinfo_t *userinfo, gboolean use_html_status)
  180: {
  181: 	PurpleAccount *account = purple_connection_get_account(gc);
  182: 	OscarData *od;
  183: 	PurplePresence *presence = NULL;
  184: 	PurpleStatus *status = NULL;
  185: 	gchar *message = NULL, *itmsurl = NULL, *tmp;
  186: 	gboolean escaping_needed = TRUE;
  187: 
  188: 	od = purple_connection_get_protocol_data(gc);
  189: 
  190: 	if (b == NULL && userinfo == NULL)
  191: 		return;
  192: 
  193: 	if (b == NULL)
  194: 		b = purple_find_buddy(purple_connection_get_account(gc), userinfo->bn);
  195: 	else
  196: 		userinfo = aim_locate_finduserinfo(od, purple_buddy_get_name(b));
  197: 
  198: 	if (b) {
  199: 		presence = purple_buddy_get_presence(b);
  200: 		status = purple_presence_get_active_status(presence);
  201: 	}
  202: 
  203: 	/* If we have both b and userinfo we favor userinfo, because if we're
  204: 	   viewing someone's profile then we want the HTML away message, and
  205: 	   the "message" attribute of the status contains only the plaintext
  206: 	   message. */
  207: 	if (userinfo) {
  208: 		if ((userinfo->flags & AIM_FLAG_AWAY) && use_html_status && userinfo->away_len > 0 && userinfo->away != NULL && userinfo->away_encoding != NULL) {
  209: 			/* Away message */
  210: 			message = oscar_encoding_to_utf8(userinfo->away_encoding, userinfo->away, userinfo->away_len);
  211: 			escaping_needed = FALSE;
  212: 		} else {
  213: 			/*
  214: 			 * Available message or non-HTML away message (because that's
  215: 			 * all we have right now.
  216: 			 */
  217: 			if ((userinfo->status != NULL) && userinfo->status[0] != '\0') {
  218: 				message = oscar_encoding_to_utf8(userinfo->status_encoding, userinfo->status, userinfo->status_len);
  219: 			}
  220: #if defined (_WIN32) || defined (__APPLE__)
  221: 			if (userinfo->itmsurl && (userinfo->itmsurl[0] != '\0')) {
  222: 				itmsurl = oscar_encoding_to_utf8(userinfo->itmsurl_encoding, userinfo->itmsurl, userinfo->itmsurl_len);
  223: 			}
  224: #endif
  225: 		}
  226: 	} else {
  227: 		message = g_strdup(purple_status_get_attr_string(status, "message"));
  228: 		itmsurl = g_strdup(purple_status_get_attr_string(status, "itmsurl"));
  229: 	}
  230: 
  231: 	if (message) {
  232: 		tmp = oscar_util_format_string(message, purple_account_get_username(account));
  233: 		g_free(message);
  234: 		message = tmp;
  235: 		if (escaping_needed) {
  236: 			tmp = purple_markup_escape_text(message, -1);
  237: 			g_free(message);
  238: 			message = tmp;
  239: 		}
  240: 	}
  241: 
  242: 	if (use_html_status && itmsurl) {
  243: 		tmp = g_strdup_printf("<a href=\"%s\">%s</a>", itmsurl, message);
  244: 		g_free(message);
  245: 		message = tmp;
  246: 	}
  247: 
  248: 	if (b) {
  249: 		if (purple_presence_is_online(presence)) {
  250: 			gboolean is_away = ((status && !purple_status_is_available(status)) || (userinfo && (userinfo->flags & AIM_FLAG_AWAY)));
  251: 			if (oscar_util_valid_name_icq(purple_buddy_get_name(b)) || is_away || !message || !(*message)) {
  252: 				/* Append the status name for online ICQ statuses, away AIM statuses, and for all buddies with no message.
  253: 				 * If the status name and the message are the same, only show one. */
  254: 				const char *status_name = purple_status_get_name(status);
  255: 				if (status_name && message && purple_strequal(status_name, message))
  256: 					status_name = NULL;
  257: 
  258: 				tmp = g_strdup_printf("%s%s%s",
  259: 									   status_name ? status_name : "",
  260: 									   ((status_name && message) && *message) ? ": " : "",
  261: 									   (message && *message) ? message : "");
  262: 				g_free(message);
  263: 				message = tmp;
  264: 			}
  265: 
  266: 		} else if (aim_ssi_waitingforauth(od->ssi.local,
  267: 			aim_ssi_itemlist_findparentname(od->ssi.local, purple_buddy_get_name(b)),
  268: 			purple_buddy_get_name(b)))
  269: 		{
  270: 			/* Note if an offline buddy is not authorized */
  271: 			tmp = g_strdup_printf("%s%s%s",
  272: 					_("Not Authorized"),
  273: 					(message && *message) ? ": " : "",
  274: 					(message && *message) ? message : "");
  275: 			g_free(message);
  276: 			message = tmp;
  277: 		} else {
  278: 			g_free(message);
  279: 			message = g_strdup(_("Offline"));
  280: 		}
  281: 	}
  282: 
  283: 	if (presence) {
  284: 		const char *mood;
  285: 		const char *comment;
  286: 		char *description;
  287: 		status = purple_presence_get_status(presence, "mood");
  288: 		mood = icq_get_custom_icon_description(purple_status_get_attr_string(status, PURPLE_MOOD_NAME));
  289: 		if (mood) {
  290: 			comment = purple_status_get_attr_string(status, PURPLE_MOOD_COMMENT);
  291: 			if (comment) {
  292: 				char *escaped_comment = purple_markup_escape_text(comment, -1);
  293: 				description = g_strdup_printf("%s (%s)", _(mood), escaped_comment);
  294: 				g_free(escaped_comment);
  295: 			} else {
  296: 				description = g_strdup(_(mood));
  297: 			}
  298: 			purple_notify_user_info_add_pair(user_info, _("Mood"), description);
  299: 			g_free(description);
  300: 		}
  301: 	}
  302: 
  303: 	purple_notify_user_info_add_pair(user_info, _("Status"), message);
  304: 	g_free(message);
  305: }
  306: 
  307: void
  308: oscar_user_info_append_extra_info(PurpleConnection *gc, PurpleNotifyUserInfo *user_info, PurpleBuddy *b, aim_userinfo_t *userinfo)
  309: {
  310: 	OscarData *od;
  311: 	PurpleAccount *account;
  312: 	PurpleGroup *g = NULL;
  313: 	struct buddyinfo *bi = NULL;
  314: 	char *tmp;
  315: 	const char *bname = NULL, *gname = NULL;
  316: 
  317: 	od = purple_connection_get_protocol_data(gc);
  318: 	account = purple_connection_get_account(gc);
  319: 
  320: 	if ((user_info == NULL) || ((b == NULL) && (userinfo == NULL)))
  321: 		return;
  322: 
  323: 	if (userinfo == NULL)
  324: 		userinfo = aim_locate_finduserinfo(od, purple_buddy_get_name(b));
  325: 
  326: 	if (b == NULL)
  327: 		b = purple_find_buddy(account, userinfo->bn);
  328: 
  329: 	if (b != NULL) {
  330: 		bname = purple_buddy_get_name(b);
  331: 		g = purple_buddy_get_group(b);
  332: 		gname = purple_group_get_name(g);
  333: 	}
  334: 
  335: 	if (userinfo != NULL)
  336: 		bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, userinfo->bn));
  337: 
  338: 	if ((bi != NULL) && (bi->ipaddr != 0)) {
  339: 		tmp =  g_strdup_printf("%u.%u.%u.%u",
  340: 			0xFF & ((bi->ipaddr & 0xff000000) >> 24),
  341: 			0xFF & ((bi->ipaddr & 0x00ff0000) >> 16),
  342: 			0xFF & ((bi->ipaddr & 0x0000ff00) >> 8),
  343: 			0xFF & (bi->ipaddr & 0x000000ff));
  344: 		oscar_user_info_add_pair(user_info, _("IP Address"), tmp);
  345: 		g_free(tmp);
  346: 	}
  347: 
  348: 	if ((userinfo != NULL) && (userinfo->warnlevel != 0)) {
  349: 		tmp = g_strdup_printf("%d", (int)(userinfo->warnlevel/10.0 + .5));
  350: 		oscar_user_info_add_pair(user_info, _("Warning Level"), tmp);
  351: 		g_free(tmp);
  352: 	}
  353: 
  354: 	if ((b != NULL) && (bname != NULL) && (g != NULL) && (gname != NULL)) {
  355: 		tmp = aim_ssi_getcomment(od->ssi.local, gname, bname);
  356: 		if (tmp != NULL) {
  357: 			char *tmp2 = g_markup_escape_text(tmp, strlen(tmp));
  358: 			g_free(tmp);
  359: 
  360: 			oscar_user_info_convert_and_add(account, od, user_info, _("Buddy Comment"), tmp2);
  361: 			g_free(tmp2);
  362: 		}
  363: 	}
  364: }
  365: 
  366: void
  367: oscar_user_info_display_error(OscarData *od, guint16 error_reason, gchar *buddy)
  368: {
  369: 	PurpleNotifyUserInfo *user_info = purple_notify_user_info_new();
  370: 	gchar *buf = g_strdup_printf(_("User information not available: %s"), oscar_get_msgerr_reason(error_reason));
  371: 	purple_notify_user_info_add_pair(user_info, NULL, buf);
  372: 	purple_notify_userinfo(od->gc, buddy, user_info, NULL, NULL);
  373: 	purple_notify_user_info_destroy(user_info);
  374: 	if (!purple_conv_present_error(buddy, purple_connection_get_account(od->gc), buf))
  375: 		purple_notify_error(od->gc, NULL, buf, NULL);
  376: 	g_free(buf);
  377: }
  378: 
  379: void
  380: oscar_user_info_display_icq(OscarData *od, struct aim_icq_info *info)
  381: {
  382: 	PurpleConnection *gc = od->gc;
  383: 	PurpleAccount *account = purple_connection_get_account(gc);
  384: 	PurpleBuddy *buddy;
  385: 	struct buddyinfo *bi;
  386: 	gchar who[16];
  387: 	PurpleNotifyUserInfo *user_info;
  388: 
  389: 	if (!info->uin)
  390: 		return;
  391: 
  392: 	user_info = purple_notify_user_info_new();
  393: 
  394: 	g_snprintf(who, sizeof(who), "%u", info->uin);
  395: 	buddy = purple_find_buddy(account, who);
  396: 	if (buddy != NULL)
  397: 		bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, purple_buddy_get_name(buddy)));
  398: 	else
  399: 		bi = NULL;
  400: 
  401: 	purple_notify_user_info_add_pair(user_info, _("UIN"), who);
  402: 	oscar_user_info_convert_and_add(account, od, user_info, _("Nick"), info->nick);
  403: 	if ((bi != NULL) && (bi->ipaddr != 0)) {
  404: 		char *tstr =  g_strdup_printf("%u.%u.%u.%u",
  405: 			0xFF & ((bi->ipaddr & 0xff000000) >> 24),
  406: 			0xFF & ((bi->ipaddr & 0x00ff0000) >> 16),
  407: 			0xFF & ((bi->ipaddr & 0x0000ff00) >> 8),
  408: 			0xFF & (bi->ipaddr & 0x000000ff));
  409: 		purple_notify_user_info_add_pair(user_info, _("IP Address"), tstr);
  410: 		g_free(tstr);
  411: 	}
  412: 	oscar_user_info_convert_and_add(account, od, user_info, _("First Name"), info->first);
  413: 	oscar_user_info_convert_and_add(account, od, user_info, _("Last Name"), info->last);
  414: 	oscar_user_info_convert_and_add_hyperlink(account, od, user_info, _("Email Address"), info->email, "mailto:");
  415: 	if (info->numaddresses && info->email2) {
  416: 		int i;
  417: 		for (i = 0; i < info->numaddresses; i++) {
  418: 			oscar_user_info_convert_and_add_hyperlink(account, od, user_info, _("Email Address"), info->email2[i], "mailto:");
  419: 		}
  420: 	}
  421: 	oscar_user_info_convert_and_add(account, od, user_info, _("Mobile Phone"), info->mobile);
  422: 
  423: 	if (info->gender != 0)
  424: 		purple_notify_user_info_add_pair(user_info, _("Gender"), (info->gender == 1 ? _("Female") : _("Male")));
  425: 
  426: 	if ((info->birthyear > 1900) && (info->birthmonth > 0) && (info->birthday > 0)) {
  427: 		/* Initialize the struct properly or strftime() will crash
  428: 		 * under some conditions (e.g. Debian sarge w/ LANG=en_HK). */
  429: 		time_t t = time(NULL);
  430: 		struct tm *tm = localtime(&t);
  431: 
  432: 		tm->tm_mday = (int)info->birthday;
  433: 		tm->tm_mon  = (int)info->birthmonth - 1;
  434: 		tm->tm_year = (int)info->birthyear - 1900;
  435: 
  436: 		/* Ignore dst setting of today to avoid timezone shift between
  437: 		 * dates in summer and winter time. */
  438: 		tm->tm_isdst = -1;
  439: 
  440: 		/* To be 100% sure that the fields are re-normalized.
  441: 		 * If you're sure strftime() ALWAYS does this EVERYWHERE,
  442: 		 * feel free to remove it.  --rlaager */
  443: 		mktime(tm);
  444: 
  445: 		oscar_user_info_convert_and_add(account, od, user_info, _("Birthday"), purple_date_format_short(tm));
  446: 	}
  447: 	if ((info->age > 0) && (info->age < 255)) {
  448: 		char age[5];
  449: 		snprintf(age, sizeof(age), "%hhd", info->age);
  450: 		purple_notify_user_info_add_pair(user_info, _("Age"), age);
  451: 	}
  452: 	oscar_user_info_convert_and_add_hyperlink(account, od, user_info, _("Personal Web Page"), info->email, "");
  453: 	if (buddy != NULL)
  454: 		oscar_user_info_append_status(gc, user_info, buddy, /* aim_userinfo_t */ NULL, /* use_html_status */ TRUE);
  455: 
  456: 	oscar_user_info_convert_and_add(account, od, user_info, _("Additional Information"), info->info);
  457: 	purple_notify_user_info_add_section_break(user_info);
  458: 
  459: 	if ((info->homeaddr && (info->homeaddr[0])) || (info->homecity && info->homecity[0]) || (info->homestate && info->homestate[0]) || (info->homezip && info->homezip[0])) {
  460: 		purple_notify_user_info_add_section_header(user_info, _("Home Address"));
  461: 
  462: 		oscar_user_info_convert_and_add(account, od, user_info, _("Address"), info->homeaddr);
  463: 		oscar_user_info_convert_and_add(account, od, user_info, _("City"), info->homecity);
  464: 		oscar_user_info_convert_and_add(account, od, user_info, _("State"), info->homestate);
  465: 		oscar_user_info_convert_and_add(account, od, user_info, _("Zip Code"), info->homezip);
  466: 	}
  467: 	if ((info->workaddr && info->workaddr[0]) || (info->workcity && info->workcity[0]) || (info->workstate && info->workstate[0]) || (info->workzip && info->workzip[0])) {
  468: 		purple_notify_user_info_add_section_header(user_info, _("Work Address"));
  469: 
  470: 		oscar_user_info_convert_and_add(account, od, user_info, _("Address"), info->workaddr);
  471: 		oscar_user_info_convert_and_add(account, od, user_info, _("City"), info->workcity);
  472: 		oscar_user_info_convert_and_add(account, od, user_info, _("State"), info->workstate);
  473: 		oscar_user_info_convert_and_add(account, od, user_info, _("Zip Code"), info->workzip);
  474: 	}
  475: 	if ((info->workcompany && info->workcompany[0]) || (info->workdivision && info->workdivision[0]) || (info->workposition && info->workposition[0]) || (info->workwebpage && info->workwebpage[0])) {
  476: 		purple_notify_user_info_add_section_header(user_info, _("Work Information"));
  477: 
  478: 		oscar_user_info_convert_and_add(account, od, user_info, _("Company"), info->workcompany);
  479: 		oscar_user_info_convert_and_add(account, od, user_info, _("Division"), info->workdivision);
  480: 		oscar_user_info_convert_and_add(account, od, user_info, _("Position"), info->workposition);
  481: 		oscar_user_info_convert_and_add_hyperlink(account, od, user_info, _("Web Page"), info->email, "");
  482: 	}
  483: 
  484: 	purple_notify_userinfo(gc, who, user_info, NULL, NULL);
  485: 	purple_notify_user_info_destroy(user_info);
  486: }
  487: 
  488: void
  489: oscar_user_info_display_aim(OscarData *od, aim_userinfo_t *userinfo)
  490: {
  491: 	PurpleConnection *gc = od->gc;
  492: 	PurpleAccount *account = purple_connection_get_account(gc);
  493: 	PurpleNotifyUserInfo *user_info = purple_notify_user_info_new();
  494: 	gchar *tmp = NULL, *info_utf8 = NULL, *base_profile_url = NULL;
  495: 
  496: 	oscar_user_info_append_status(gc, user_info, /* PurpleBuddy */ NULL, userinfo, /* use_html_status */ TRUE);
  497: 
  498: 	if ((userinfo->present & AIM_USERINFO_PRESENT_IDLE) && userinfo->idletime != 0) {
  499: 		tmp = purple_str_seconds_to_string(userinfo->idletime*60);
  500: 		oscar_user_info_add_pair(user_info, _("Idle"), tmp);
  501: 		g_free(tmp);
  502: 	}
  503: 
  504: 	oscar_user_info_append_extra_info(gc, user_info, NULL, userinfo);
  505: 
  506: 	if ((userinfo->present & AIM_USERINFO_PRESENT_ONLINESINCE) && !oscar_util_valid_name_sms(userinfo->bn)) {
  507: 		/* An SMS contact is always online; its Online Since value is not useful */
  508: 		time_t t = userinfo->onlinesince;
  509: 		oscar_user_info_add_pair(user_info, _("Online Since"), purple_date_format_full(localtime(&t)));
  510: 	}
  511: 
  512: 	if (userinfo->present & AIM_USERINFO_PRESENT_MEMBERSINCE) {
  513: 		time_t t = userinfo->membersince;
  514: 		oscar_user_info_add_pair(user_info, _("Member Since"), purple_date_format_full(localtime(&t)));
  515: 	}
  516: 
  517: 	if (userinfo->capabilities != 0) {
  518: 		tmp = oscar_caps_to_string(userinfo->capabilities);
  519: 		oscar_user_info_add_pair(user_info, _("Capabilities"), tmp);
  520: 		g_free(tmp);
  521: 	}
  522: 
  523: 	/* Info */
  524: 	if ((userinfo->info_len > 0) && (userinfo->info != NULL) && (userinfo->info_encoding != NULL)) {
  525: 		info_utf8 = oscar_encoding_to_utf8(userinfo->info_encoding, userinfo->info, userinfo->info_len);
  526: 		tmp = oscar_util_format_string(info_utf8, purple_account_get_username(account));
  527: 		purple_notify_user_info_add_section_break(user_info);
  528: 		oscar_user_info_add_pair(user_info, _("Profile"), tmp);
  529: 		g_free(tmp);
  530: 		g_free(info_utf8);
  531: 	}
  532: 
  533: 	purple_notify_user_info_add_section_break(user_info);
  534: 	base_profile_url = oscar_util_valid_name_icq(userinfo->bn) ? "http://www.icq.com/people" : "http://profiles.aim.com";
  535: 	tmp = g_strdup_printf("<a href=\"%s/%s\">%s</a>",
  536: 			base_profile_url, purple_normalize(account, userinfo->bn), _("View web profile"));
  537: 	purple_notify_user_info_add_pair(user_info, NULL, tmp);
  538: 	g_free(tmp);
  539: 
  540: 	purple_notify_userinfo(gc, userinfo->bn, user_info, NULL, NULL);
  541: 	purple_notify_user_info_destroy(user_info);
  542: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>