view src/protocols/jabber/jutil.c @ 10138:5fb5c447eb4f

[gaim-migrate @ 11208] Bring back the old smiley selection dialog for gtk<2.4 and play around with the signals for both of them. We're not explicitly freeing the smiley menu in gtk2.4 anymore... can someone verify that gtk is freeing it for us? Or write a patch to free it, if not? This would probably be a pretty big memleak if gtk isn't taking care of it... committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Mon, 25 Oct 2004 02:48:38 +0000
parents a9fb4493ae22
children 17142948653e
line wrap: on
line source

/*
 * gaim - Jabber Protocol Plugin
 *
 * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
 *
 * 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
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
#include "internal.h"
#include "server.h"
#include "util.h"

#include "chat.h"
#include "presence.h"
#include "jutil.h"

gboolean jabber_nodeprep_validate(const char *str)
{
	const char *c;

	if(!str)
		return TRUE;

	if(strlen(str) > 1023)
		return FALSE;

	c = str;
	while(c && *c) {
		gunichar ch = g_utf8_get_char(c);
		if(ch == '\"' || ch == '&' || ch == '\'' || ch == '/' || ch == ':' ||
				ch == '<' || ch == '>' || ch == '@' || !g_unichar_isgraph(ch)) {
			return FALSE;
		}
		c = g_utf8_next_char(c);
	}

	return TRUE;
}

gboolean jabber_nameprep_validate(const char *str)
{
	const char *c;

	if(!str)
		return TRUE;

	if(strlen(str) > 1023)
		return FALSE;

	c = str;
	while(c && *c) {
		gunichar ch = g_utf8_get_char(c);
		if(!g_unichar_isgraph(ch))
			return FALSE;

		c = g_utf8_next_char(c);
	}


	return TRUE;
}

gboolean jabber_resourceprep_validate(const char *str)
{
	const char *c;

	if(!str)
		return TRUE;

	if(strlen(str) > 1023)
		return FALSE;

	c = str;
	while(c && *c) {
		gunichar ch = g_utf8_get_char(c);
		if(!g_unichar_isgraph(ch) && ch != ' ')
			return FALSE;

		c = g_utf8_next_char(c);
	}

	return TRUE;
}


JabberID*
jabber_id_new(const char *str)
{
	char *at;
	char *slash;
	JabberID *jid;

	if(!str || !g_utf8_validate(str, -1, NULL))
		return NULL;

	jid = g_new0(JabberID, 1);

	at = g_utf8_strchr(str, -1, '@');
	slash = g_utf8_strchr(str, -1, '/');

	if(at) {
		jid->node = g_utf8_normalize(str, at-str, G_NORMALIZE_NFKC);
		if(slash) {
			jid->domain = g_utf8_normalize(at+1, slash-(at+1), G_NORMALIZE_NFKC);
			jid->resource = g_utf8_normalize(slash+1, -1, G_NORMALIZE_NFKC);
		} else {
			jid->domain = g_utf8_normalize(at+1, -1, G_NORMALIZE_NFKC);
		}
	} else {
		if(slash) {
			jid->domain = g_utf8_normalize(str, slash-str, G_NORMALIZE_NFKC);
			jid->resource = g_utf8_normalize(slash+1, -1, G_NORMALIZE_NFKC);
		} else {
			jid->domain = g_utf8_normalize(str, -1, G_NORMALIZE_NFKC);
		}
	}


	if(!jabber_nodeprep_validate(jid->node) ||
			!jabber_nameprep_validate(jid->domain) ||
			!jabber_resourceprep_validate(jid->resource)) {
		jabber_id_free(jid);
		return NULL;
	}

	return jid;
}

void
jabber_id_free(JabberID *jid)
{
	if(jid) {
		if(jid->node)
			g_free(jid->node);
		if(jid->domain)
			g_free(jid->domain);
		if(jid->resource)
			g_free(jid->resource);
		g_free(jid);
	}
}


char *jabber_get_resource(const char *in)
{
	JabberID *jid = jabber_id_new(in);
	char *out;

	if(!jid)
		return NULL;

	out = g_strdup(jid->resource);
	jabber_id_free(jid);

	return out;
}

char *jabber_get_bare_jid(const char *in)
{
	JabberID *jid = jabber_id_new(in);
	char *out;

	if(!jid)
		return NULL;

	out = g_strdup_printf("%s%s%s", jid->node ? jid->node : "",
			jid->node ? "@" : "", jid->domain);
	jabber_id_free(jid);

	return out;
}

const char *jabber_normalize(const GaimAccount *account, const char *in)
{
	GaimConnection *gc = account ? account->gc : NULL;
	JabberStream *js = gc ? gc->proto_data : NULL;
	static char buf[3072]; /* maximum legal length of a jabber jid */
	JabberID *jid;
	char *node, *domain;

	jid = jabber_id_new(in);

	if(!jid)
		return NULL;

	node = jid->node ? g_utf8_strdown(jid->node, -1) : NULL;
	domain = g_utf8_strdown(jid->domain, -1);


	if(js && node && jid->resource &&
			jabber_chat_find(js, node, domain))
		g_snprintf(buf, sizeof(buf), "%s@%s/%s", node, domain,
				jid->resource);
	else
		g_snprintf(buf, sizeof(buf), "%s%s%s", node ? node : "",
				node ? "@" : "", domain);

	jabber_id_free(jid);
	g_free(node);
	g_free(domain);

	return buf;
}

GaimConversation *
jabber_find_unnormalized_conv(const char *name, GaimAccount *account)
{
	GaimConversation *c = NULL;
	GList *cnv;

	g_return_val_if_fail(name != NULL, NULL);

	for(cnv = gaim_get_conversations(); cnv; cnv = cnv->next) {
		c = (GaimConversation*)cnv->data;
		if(gaim_conversation_get_type(c) == GAIM_CONV_IM &&
				!gaim_utf8_strcasecmp(name, gaim_conversation_get_name(c)) &&
				account == gaim_conversation_get_account(c))
			return c;
	}

	return NULL;
}