/* sunone-util.c
 *
 * Copyright (C) 2002-2004 Sun Microsystems, Inc
 *
 * AUTHORS
 *     Jack Jia <jack.jia@sun.com>
 *     Harry Lu <harry.lu@sun.com>
 *     Alfred Peng <alfred.peng@sun.com>
 *     Jedy Wang <jedy.wang@sun.com>
 *     Rodrigo Moya <rodrigo@ximian.com>
 *
 */

#include <string.h>
#include <glib.h>
#include "sunone-util.h"

#ifdef ENABLE_IDN
#define IDN_DECD ( IDN_DELIMMAP | IDN_NAMEPREP | IDN_IDNCONV | IDN_RTCHECK \
		| IDN_ASCCHECK )
#define IDN_ENCD ( IDN_DELIMMAP | IDN_LOCALMAP | IDN_NAMEPREP | IDN_IDNCONV  \
		| IDN_LENCHECK | IDN_ASCCHECK )
#endif

icalcomponent *
sunone_util_icalparser_parse_string (const char *str, int len)
{
    icalcomponent *ical;
    char *string;

	if (!str)
		return NULL;

    string = g_strndup (str, len);
    ical = icalparser_parse_string (string);
    g_free (string);

    return ical;
}

char *
sunone_util_get_calid_from_uri (const char *uristr)
{
	return sunone_util_get_parameter_from_uri (uristr, "calid");
}

char *
sunone_util_get_parameter_from_uri (const char *uristr, const char *name)
{
	char *s;
	char **arr;
	char *param = NULL;

	s = strchr (uristr, '?');
	if (!s || !*s)
		return NULL;

	arr = g_strsplit (s + 1, "&", 0);
	if (arr) {
		gint n = 0;

		while (arr[n]) {
			if (!strncmp (arr[n], name, strlen (name))) {
				param = strchr (arr[n], '=');
				if (param) {
					param = g_strdup (param + 1);
					break;
				}
			}

			n++;
		}

		g_strfreev (arr);
	}

	return param;
}

char *
sunone_util_fix_calid (const char *calid)
{
	char *fixed, *p;
	
	fixed = g_strdup (calid);
	for (p = fixed; *p; p++) {
		if (*p == '/')
			*p = '\\';
	}

	return fixed;
}

void
sunone_util_mangle_uid (ECalComponent *comp)
{
	const char *uid;
	ECalComponentRange rid;
	char *new_uid;
	char *tstr;
	
	e_cal_component_get_recurid (comp, &rid);	
	if (!rid.datetime.value)
		return;
	tstr = icaltime_as_ical_string (*rid.datetime.value);
	e_cal_component_get_uid (comp, &uid);

	new_uid = g_strconcat (uid, tstr, NULL);
	e_cal_component_set_uid (comp, new_uid);
	g_free (tstr);
	g_free (new_uid);

	e_cal_component_free_range (&rid);
}

void
sunone_util_unmangle_uid (ECalComponent *comp)
{
	const char *uid;
	ECalComponentRange rid;
	char *new_uid;
	char *rid_string;
	
	e_cal_component_get_recurid (comp, &rid);	
	if (!rid.datetime.value)
		return;
	e_cal_component_get_uid (comp, &uid);
	
	new_uid = g_strdup (uid);
	rid_string = icaltime_as_ical_string (*rid.datetime.value);
	new_uid[strlen (uid) - strlen (rid_string)] = '\0';	
	g_free (rid_string);
	e_cal_component_set_uid (comp, new_uid);
	g_free (new_uid);

	e_cal_component_free_range (&rid);
}

static gboolean
has_perm (GList *acls, const char *user, SunOneACEContext context, SunOneACEPermission perm, gboolean is_owner)
{
	SunOneACE *ace;
	GList *l;
	
	for (l = acls; l != NULL; l = l->next) {
		gboolean has;
		
		ace = (SunOneACE *) l->data;
		
		if (sunone_ace_get_context (ace) != SUNONE_ACE_CONTEXT_ENTIRE_CALENDAR &&
		    sunone_ace_get_context (ace) != context)
			continue;		

		has = (sunone_ace_get_access_type (ace) == SUNONE_ACE_ACCESSTYPE_GRANT);
		
		switch (sunone_ace_get_user_type (ace)) {
		case SUNONE_ACE_USERTYPE_USER :
			if (!user || !sunone_ace_get_user_name (ace))
				continue;
			
			if (!strcasecmp (user, sunone_ace_get_user_name (ace)) && (sunone_ace_get_permissions (ace) & perm))
				return has;				
			break;
		case SUNONE_ACE_USERTYPE_OWNERS:
			if (!is_owner)
				continue;
			
			if (sunone_ace_get_permissions (ace) & perm)
				return has;
			break;
		case SUNONE_ACE_USERTYPE_ALL_USERS :
		case SUNONE_ACE_USERTYPE_NONOWNERS :
			if (sunone_ace_get_permissions (ace) & perm)
				return has;
			break;
		default :
			break;
		}
	}

	return FALSE;
}

gboolean
sunone_util_has_permissions (SunOneCalendarProperties *props, const char *user, 
			     SunOneACEContext context, SunOneACEPermission perms)
{
	SunOneACEPermission perm;
	gboolean is_owner;
	GList *l;
	int i;
	
	g_return_val_if_fail (props != NULL, FALSE);
	g_return_val_if_fail (props->primary_owner != NULL, FALSE);
	
	if (!user)
		return FALSE;

	/* if we're the primary owner, we can do whatever */
	if (!strcasecmp (props->primary_owner, user))
		return TRUE;

	/* check to see if we are an owner at all */
	is_owner = FALSE;	
	for (l = props->owners; l; l = l->next) {
		g_return_val_if_fail (l->data != NULL, FALSE);
		if (!strcasecmp (l->data, user)) {
			is_owner = TRUE;
			break;
		}		
	}

	perm = SUNONE_ACE_PERMISSION_NONE;
	for (i = 0; perm <= SUNONE_ACE_PERMISSION_WRITE; i++, perm = SUNONE_ACE_PERMISSION_CANCEL << i) {
		if (!(perm & perms))
			continue;
		
		if (!has_perm (props->acls, user, context, perm, is_owner))
			return FALSE;
	}
	
	return TRUE;
}

#ifdef ENABLE_IDN

char *
sunone_util_get_encoded_server_port_name (const char *server_port) 
{
	char *server = NULL;
	char ace_name[1024];
	idn_result_t r;
	char *colon = NULL;

	g_return_val_if_fail (server_port != NULL, NULL);

	colon = strchr (server_port,':');

	if (colon) {
		server = g_strndup (server_port, colon - server_port);
	} 

	if (server) {
		r = idn_encodename (IDN_ENCD, server, ace_name, sizeof (ace_name));
		g_free (server);
		if (r == idn_success) {
			char *s = (char *) g_malloc (strlen (ace_name) + (colon ? strlen (colon) : 0 ) + 1);
			sprintf(s, "%s%s", ace_name, colon ? colon: "");
			return (s);
		}
	} 

	return ((char *)g_strdup(server_port));
}

char *
sunone_util_get_decoded_server_port_name (const char *server_port)
{
	char *server = NULL;
	char *colon = NULL;

	colon = strchr (server_port,':');

	if ((server = sunone_util_get_decoded_server_name (server_port)) != NULL) {
		char *s = (char *) g_malloc (strlen (server) + (colon ? strlen (colon) : 0 ) + 1);
		sprintf(s, "%s%s", server, colon ? colon: "");
		g_free (server);
		return (s);
	} else {
		return ((char *)g_strdup(server_port));
	}
}

char *
sunone_util_get_decoded_server_name (const char *server_port)
{
	char *server = NULL;
	char local_name[1024];
	idn_result_t r;
	char *colon = NULL;

	g_return_val_if_fail (server_port != NULL, NULL);

	colon = strchr (server_port,':');

	if (colon) {
		server = g_strndup (server_port, colon - server_port);
	} 

	if (server) {
		r = idn_decodename (IDN_DECD, server, local_name, sizeof (local_name));
		g_free (server);
		if (r == idn_success) {
			return (g_strdup(local_name));
		}
	};

	return ((char *)g_strdup(server_port));
}
#endif

