예제 #1
0
/*
 * Subtype 0x0002
 *
 * This is the initial login request packet.
 *
 * NOTE!! If you want/need to make use of the aim_sendmemblock() function,
 * then the client information you send here must exactly match the
 * executable that you're pulling the data from.
 *
 * Java AIM 1.1.19:
 *   clientstring = "AOL Instant Messenger (TM) version 1.1.19 for Java built 03/24/98, freeMem 215871 totalMem 1048567, i686, Linus, #2 SMP Sun Feb 11 03:41:17 UTC 2001 2.4.1-ac9, IBM Corporation, 1.1.8, 45.3, Tue Mar 27 12:09:17 PST 2001"
 *   clientid = 0x0001
 *   major  = 0x0001
 *   minor  = 0x0001
 *   point = (not sent)
 *   build  = 0x0013
 *   unknown= (not sent)
 *
 * AIM for Linux 1.1.112:
 *   clientstring = "AOL Instant Messenger (SM)"
 *   clientid = 0x1d09
 *   major  = 0x0001
 *   minor  = 0x0001
 *   point = 0x0001
 *   build  = 0x0070
 *   unknown= 0x0000008b
 *   serverstore = 0x01
 *
 * @param truncate_pass Truncate the password to 8 characters.  This
 *        usually happens for AOL accounts.  We are told that we
 *        should truncate it if the 0x0017/0x0007 SNAC contains
 *        a TLV of type 0x0026 with data 0x0000.
 * @param allow_multiple_logins Allow multiple logins? If TRUE, the AIM
 *        server will prompt the user when multiple logins occur. If
 *        FALSE, existing connections (on other clients) will be
 *        disconnected automatically as we connect.
 */
int
aim_send_login(OscarData *od, FlapConnection *conn, const char *sn, const char *password, gboolean truncate_pass, ClientInfo *ci, const char *key, gboolean allow_multiple_logins)
{
	FlapFrame *frame;
	GSList *tlvlist = NULL;
	guint8 digest[16];
	aim_snacid_t snacid;
	size_t password_len;
	guint32 distrib;

	if (!ci || !sn || !password)
		return -EINVAL;

#ifdef USE_XOR_FOR_ICQ
	/* If we're signing on an ICQ account then use the older, XOR login method */
	if (aim_snvalid_icq(sn))
		return goddamnicq2(od, conn, sn, password, ci);
#endif

	frame = flap_frame_new(od, 0x02, 1152);

	snacid = aim_cachesnac(od, SNAC_FAMILY_AUTH, 0x0002, 0x0000, NULL, 0);
	aim_putsnac(&frame->data, SNAC_FAMILY_AUTH, 0x0002, 0x0000, snacid);

	aim_tlvlist_add_str(&tlvlist, 0x0001, sn);

	/* Truncate ICQ and AOL passwords, if necessary */
	password_len = strlen(password);
	if (oscar_util_valid_name_icq(sn) && (password_len > MAXICQPASSLEN))
		password_len = MAXICQPASSLEN;
	else if (truncate_pass && password_len > 8)
		password_len = 8;

	aim_encode_password_md5(password, password_len, key, digest);

	distrib = oscar_get_ui_info_int(
			od->icq ? "prpl-icq-distid" : "prpl-aim-distid",
			ci->distrib);

	aim_tlvlist_add_raw(&tlvlist, 0x0025, 16, digest);

#ifndef USE_OLD_MD5
	aim_tlvlist_add_noval(&tlvlist, 0x004c);
#endif

	if (ci->clientstring != NULL)
		aim_tlvlist_add_str(&tlvlist, 0x0003, ci->clientstring);
	else {
		gchar *clientstring = oscar_get_clientstring();
		aim_tlvlist_add_str(&tlvlist, 0x0003, clientstring);
		g_free(clientstring);
	}
	aim_tlvlist_add_16(&tlvlist, 0x0016, (guint16)ci->clientid);
	aim_tlvlist_add_16(&tlvlist, 0x0017, (guint16)ci->major);
	aim_tlvlist_add_16(&tlvlist, 0x0018, (guint16)ci->minor);
	aim_tlvlist_add_16(&tlvlist, 0x0019, (guint16)ci->point);
	aim_tlvlist_add_16(&tlvlist, 0x001a, (guint16)ci->build);
	aim_tlvlist_add_32(&tlvlist, 0x0014, distrib);
	aim_tlvlist_add_str(&tlvlist, 0x000f, ci->lang);
	aim_tlvlist_add_str(&tlvlist, 0x000e, ci->country);

	/*
	 * If set, old-fashioned buddy lists will not work. You will need
	 * to use SSI.
	 */
	aim_tlvlist_add_8(&tlvlist, 0x004a, (allow_multiple_logins ? 0x01 : 0x03));

	aim_tlvlist_write(&frame->data, &tlvlist);

	aim_tlvlist_free(tlvlist);

	flap_connection_send(conn, frame);

	return 0;
}
예제 #2
0
파일: userinfo.c 프로젝트: Lilitana/Pidgin
/**
 * @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);
}