/*
 * EveryBuddy 
 *
 * Copyright (C) 1999, Torrey Searle <tsearle@uci.edu>
 *
 * 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
 *
 */

/*
 * util.c
 * just some handy functions to have around
 *
 */

#include <gtk/gtk.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <stdio.h>
#include <ctype.h>
#include "util.h"
#include "status.h"
#include "account.h"
#include "globals.h"
#include "contact.h"
#include "service.h"
#include "contact.h"
#include "chat_window.h"
#include "dialog.h"

#ifndef NAME_MAX
#define NAME_MAX 4096
#endif

gint clean_pid(void * dummy)
{
    int status;
    pid_t pid;

    pid = waitpid(-1, &status, WNOHANG);

    if (pid == 0)
        return TRUE;

    return FALSE;
}

char * get_local_addresses()
{
	static char addresses[1024];
	char buff[1024];
	char gateway[16];
	char  * c;
	struct hostent * hn;
	int i;
		FILE * f;
		//system("getip.pl > myip");
		f = popen("netstat -nr", "r");
		if((int)f < 1)
				goto IP_TEST_2;
		while( fgets(buff, 1024, f)  > 0 )
		{
				c = strtok( buff, " " );
				if( (strstr(c, "default") || strstr(c,"0.0.0.0") ) &&
								!strstr(c, "127.0.0" ) )
						break;
		}
		c = strtok( NULL, " " );
		pclose(f);

		strncpy(gateway,c, 16);

		
		
		for(i = strlen(gateway); gateway[i] != '.'; i-- )
		{
			gateway[i] = 0;
		}

		gateway[i] = 0;

		for(i = strlen(gateway); gateway[i] != '.'; i-- )
		{
			gateway[i] = 0;
		}

		//g_snprintf(buff, 1024, "/sbin/ifconfig -a|grep inet|grep %s", gateway );
		f = popen("/sbin/ifconfig -a", "r");
		if((int)f < 1)
				goto IP_TEST_2;
		
		while( fgets(buff, 1024, f)  > 0 )
		{
				if( strstr(buff, "inet") && strstr(buff,gateway) )
						break;
		}
		pclose(f);
		
		c = strtok( buff, " " );
		c = strtok( NULL, " " );

		strncpy ( addresses, c,1024 );
		c = strtok(addresses, ":" );
		strncpy ( buff, c, 1024 );
		if((c=strtok(NULL, ":")))
		{
			strncpy( buff, c, 1024 );
		}

		
		strncpy(addresses, buff, 1024);

		return addresses;
		
		
IP_TEST_2:

		gethostname(buff,1024);
		
		hn = gethostbyname(buff);
		if(hn)
				strncpy(addresses, inet_ntoa( *((struct in_addr*)hn->h_addr)), 1024 );
		else
				addresses[0] = 0;
		return addresses;
}


#if 0
void move_to_word_end(GtkWidget *widget, gint pos){
  int i;
  gchar *string=gtk_editable_get_chars(GTK_EDITABLE(widget),0, -1);
  int length=strlen(string);
  int end=length;

  if(isspace(string[pos])){
    pos--;
  }


  for(i=pos; i<=length; i++){
    if(isspace(string[i])){
      end=i;
      break;
    }
  }
  
  gtk_text_set_point(GTK_TEXT(widget), end);
}

gchar * find_word(GtkWidget *widget, gint pos){
  int i;
  int start=0;
  gchar *string=gtk_editable_get_chars(GTK_EDITABLE(widget),0, -1);
  int length=strlen(string);
  int end=length;
  g_print("cursor @ %d\n length of text is %d\n string is: %s\n\n", pos, length, string);

  if(isspace(string[pos])){
    pos--;
  }

  for(i=pos; i>=0; i--){
    if(isspace(string[i])){
      start=i;
      break;
    }
  }

  for(i=pos; i<=length; i++){
    if(isspace(string[i])){
      end=i;
      break;
    }
  }
  
  g_print("The word you click on is hopefully %s\n", gtk_editable_get_chars(GTK_EDITABLE(widget), start, end));
  return gtk_editable_get_chars(GTK_EDITABLE(widget), start, end);
}
  
void replace_word(GtkWidget *widget, GtkWidget * data)
{
  gchar *before;
  gchar *after;
  int pos = gtk_editable_get_position(GTK_EDITABLE(data));
  g_print("got into callback");
  before = find_word(data, pos);
  g_print("Replace %s\n", before);
  gtk_label_get(GTK_LABEL(GTK_BIN(widget)->child), &after);
  g_print("with %s\n", after);
  move_to_word_end(data, pos);
  gtk_text_backward_delete(GTK_TEXT(data), strlen(before));
  gtk_text_insert( GTK_TEXT(data), NULL, &(data->style->fg[0]), NULL,
				   after, strlen(after) );
  
}

gboolean spell_menu(gchar *word, GdkEvent * event, GtkWidget *widget){
  int i=0; 
  int word_buff_count=0;  
  int length; 
  char word_buff[20];  
  char buff[1024];
  FILE *file;
  GtkWidget *spell_menu, *spell_button;
  
  if(event->type == GDK_BUTTON_PRESS){
    GdkEventButton *buttonevent = (GdkEventButton *) event;
    g_print("mouse_cb button press\n");
    if(buttonevent->button ==3){
      

  
  spell_menu = gtk_menu_new();
  
  g_snprintf(buff, 1024, "echo \"%s\" | ispell -a", word );
  file = popen(buff, "r");
  buff[0] = 0;
  fgets(buff, 255, file);
  fgets(buff, 255, file);
  length=strlen(buff);

  g_print("word is : %s\n", word);  
  
  if(buff[0] != '*' && buff[0] != '+' && strlen(buff) > 0)
  {
      g_print("Ispell's output %s", buff);
      while(buff[i]!=':')
	  {
		i++;
      }
      i++;
      g_print("past while #1");
      
      while(i<length)
	  {
			if(buff[i]==',')
			{ 
	  			word_buff[word_buff_count]='\0';
	  			g_print("done with word: %s\n", word_buff);
	  			spell_button=gtk_menu_item_new_with_label(word_buff);
	  			gtk_menu_append(GTK_MENU(spell_menu), spell_button);
	  
	  		/*	  g_print("%s\n",word);*/
	  		/*	  g_print("%s\n",my_struct->word);*/
	  
	  			gtk_signal_connect(GTK_OBJECT(spell_button), "activate",
			    	 GTK_SIGNAL_FUNC(replace_word),
			     	 widget);
	  
	  			gtk_widget_show(spell_button);
	  			word_buff_count=0;
			}
			else
			{
	  			word_buff[word_buff_count++]=buff[i];
			}
			i++;
      }
      word_buff[word_buff_count-1]='\0';
      g_print("done with word: %s\n", word_buff);
      spell_button=gtk_menu_item_new_with_label(word_buff);
      gtk_menu_append(GTK_MENU(spell_menu), spell_button);
	  gtk_signal_connect(GTK_OBJECT(spell_button), "activate",
			    	 GTK_SIGNAL_FUNC(replace_word),
			     	 widget);
      gtk_widget_show(spell_button);
      word_buff_count=0;
      gtk_widget_show(spell_menu);
      gtk_menu_popup(GTK_MENU(spell_menu),  NULL, NULL, NULL, NULL,
		     buttonevent->button, 0);
      
    }
  else{
    g_print("checked ok: Ispell's output %s", buff);
  }
  pclose(file);
    }
    return TRUE;
  }
  return FALSE;
}

void spell_check(GtkWidget * text)
{

#ifdef HAVE_ISPELL
	int start = 0;
	int end = 0;
	static GdkColor * color = NULL;
	int ignore = 0;
	int point = gtk_editable_get_position(GTK_EDITABLE(text));

	GString * string;

	if( color == NULL )
	{
		GdkColormap * gc = gtk_widget_get_colormap( text );
		color = g_new0(GdkColor, 1);
		color->red = 255 * 256;
		gdk_colormap_alloc_color(gc, color, FALSE, TRUE);
	}



	end = point-1;
	for( start = end-1; start >= 0; start-- )
	{
		if((isspace(GTK_TEXT_INDEX(GTK_TEXT(text), start)) 
					|| start == 0
					||GTK_TEXT_INDEX(GTK_TEXT(text), start) == '"') 
				
				&& !ignore)
		{
			char * word = NULL; 
			FILE * file = NULL;
			char buff[1024];
			buff[0] = 0;
			if((GTK_TEXT_INDEX(GTK_TEXT(text), start) == '"')
				|| isspace(GTK_TEXT_INDEX(GTK_TEXT(text), start))
				||	start != 0)
			{
				start++;
			}
			if(start <= end)
			{
				word = gtk_editable_get_chars( GTK_EDITABLE(text), start, end );
				g_snprintf(buff, 1024, "echo \"%s\" | ispell -l", word );
 				file = popen(buff, "r");
				memset(buff, 0, 255);

				fgets(buff, 255, file);
			}
			
			if(word && strlen(buff) > 0 )
			{
				string = g_string_new(word);
				gtk_text_set_point(GTK_TEXT(text), end);
				gtk_text_backward_delete(GTK_TEXT(text), end-start);
				gtk_text_insert( GTK_TEXT(text), NULL, color, NULL,
								 string->str, string->len );
				g_string_free( string, TRUE );
			}
			else if(word)
			{
				string = g_string_new(word);
				gtk_text_set_point(GTK_TEXT(text), end);
				gtk_text_backward_delete(GTK_TEXT(text), end-start);
				gtk_text_insert( GTK_TEXT(text), NULL, &(text->style->fg[0]), NULL,
								 string->str, string->len );
				g_string_free( string, TRUE );
			}
			if(file)
			{
				pclose( file);
			}
			break;
		}
		else if(!isalpha(GTK_TEXT_INDEX(GTK_TEXT(text), start)))
		{
			ignore = 1;
		}
	}
	gtk_text_set_point(GTK_TEXT(text), point);

#endif

}
#endif
/* a valid domain name is one that contains only alphanumeric, - and . 
 * if it has anything else, then it can't be a domain name
 */

gint is_valid_domain( gchar * name )
{
	int i;
	int dot_count = 0;
	if( name[0] == '-' || name[0] == '.' )
	{
		return FALSE;
	}
	for( i = 0; name[i] && name[i] != '/' && name[i] != ':'; i++ )
	{
		if( !isalnum(name[i]) && name[i] != '.' && name[i] != '-' )
		{
			return FALSE;
		}
		if( name[i] == '.' )
		{
			if( name[i-1] == '.' ||
				name[i-1] == '-' ||
				name[i+1] == '.' ||
				name[i+1] == '-' )
			{
				return FALSE;
			}
			dot_count++;
		}

	}
	if( name[i] == ':' )
	{
		for( i = i+1; name[i] && name[i] != '/'; i++ )
		{
			if(!isdigit(name[i]))
			{
				return FALSE;
			}
		}
	}
	return dot_count > 0;
}

/* this function will be used to determine if a given token is a link */

gint is_link( gchar * token )
{
	int i;
	int len = strlen(token);
	
	if( token[0] == '<' )
	{
		return TOKEN_NORMAL;
	}
	if(!strncasecmp( token, "http://", 7 ) )
	{
		if(is_valid_domain(token+7))
		{
			return TOKEN_HTTP;
		}
		else
		{
			return TOKEN_NORMAL;
		}
	}
	if(!strncasecmp( token, "ftp://", 6))
	{
		return TOKEN_FTP;
	}
	if(!strncasecmp( token, "mailto:", 7))
	{
		return TOKEN_EMAIL;
	}
	if(!strncasecmp( token, "www.", 4) && is_valid_domain(token))
	{
		return TOKEN_HTTP;
	}
	if(!strncasecmp( token, "ftp.", 4) && is_valid_domain(token))
	{
		return TOKEN_FTP;
	}
	if(strstr(token, "://") && !ispunct(token[0]) && !ispunct(token[strlen(token)]) )
	{
		return TOKEN_CUSTOM;
	}

	for(i = 0; i < len; i++ )
	{
		if(token[i] == '@' )
		{
			if( !ispunct(token[0]) && !ispunct(token[len-1]) )
			{
				if(is_valid_domain(token+i+1))
				{
						return TOKEN_EMAIL;
				}
				break;
			}
		}
	}
	
	for(i=len; i >= 0; i-- )
	{
		if( token[i] == '.' )
		{
			if(!strcasecmp(token+i, ".edu") && is_valid_domain(token))
			{
				return TOKEN_HTTP;
			}
			if(!strcasecmp(token+i, ".com") && is_valid_domain(token))
			{
				return TOKEN_HTTP;
			}
			if(!strcasecmp(token+i, ".net") && is_valid_domain(token))
			{
				return TOKEN_HTTP;
			}
			if(!strcasecmp(token+i, ".org") && is_valid_domain(token))
			{
				return TOKEN_HTTP;
			}
			if(!strcasecmp(token+i, ".gov") && is_valid_domain(token))
			{
				return TOKEN_HTTP;
			}
			break;
		}
	}
	return TOKEN_NORMAL;
}

GString * get_next_token(char * input)
{
	int i = 0;
	int len = strlen(input);
	GString * string = g_string_sized_new(20);

	if(!strncasecmp(input, "<A", 2))
	{
		g_string_assign(string, "<A");
		for( i = 2; i < len; i++ )
		{
			g_string_append_c(string, input[i]);
			if( input[i] != '<' )
			{
				continue;
			}
			g_string_append_c(string, input[++i]);
			if( input[i] != '/' )
			{
				continue;
			}
			g_string_append_c(string, input[++i]);
			if( tolower(input[i]) != 'a' )
			{
				continue;
			}
			g_string_append_c(string, input[++i]);
			break;
		}
		return string;
	}
	if(input[0] == '<')
	{
		for(i=0; i < len; i++)
		{
			g_string_append_c(string, input[i]);
			if(input[i] == '>')
			{
				break;
			}
		}
		return string;
	}

	if( ispunct(input[0]) )
	{
		for( i=0; i < len; i++ )
		{
			if( ispunct(input[i]) && input[i] != '<' )
			{
				g_string_append_c(string, input[i]);
			}
			else
			{
				break;
			}
		}
		return string;
	}

	/*
	 * now that we have covered prior html
	 * we can do an (almost) simple word tokenization
	 */

	for( i = 0; i < len; i++ )
	{
		if(!isspace(input[i]) && input[i] != '<' )
		{
			if(!ispunct(input[i]) || input[i] == '/' )
			{
				g_string_append_c(string, input[i]);
			}
			else
			{
				int j;
#if 0
				if( (i < len - 1 && !isspace(input[i+1])) || i==0 )
				{
					g_string_append_c(string, input[i]);
				}
				else
				{
					return string;
				}
#endif
				for(j = i+1; j < len; j++ )
				{
					if( isspace(input[j] ) )
					{
						return string;
					}
					if( isalpha( input[j] ) || isdigit(input[j] ) ) 
					{
						break;
					}
				}
				if( j == len )
				{
					return string;
				}
				else
				{
					g_string_append_c(string, input[i]);
				}
							
							
			}
		}
		else
		{
			return string;
		}
	}
	return string;
}
			
void linkify_token( GString * token )
{
	GString * g;
	GString * g2;
	int type = is_link(token->str);

	if(type == TOKEN_NORMAL)
		return;

	g = g_string_sized_new(token->len);
	g2 = g_string_sized_new(token->len);

	g_string_assign(g, token->str);
	g_string_assign(g2, token->str);
	

		
	if(type == TOKEN_HTTP && strncasecmp(token->str, "http://", 7))
	{
		g_string_prepend(g2, "http://");
	}
	else if( type == TOKEN_FTP && strncasecmp(token->str, "ftp://", 6))
	{
		g_string_prepend(g2, "ftp://");
	}
	else if( type == TOKEN_EMAIL && strncasecmp(token->str, "mailto:", 7))
	{
		g_string_prepend(g2, "mailto:");
	}

#ifdef DEBUG
	printf("TOKEN: %s\n", token->str);
#endif
	g_string_sprintf(token, "<A HREF=\"%s\">%s</A>", g2->str, g->str);

	g_string_free(g,TRUE);
	g_string_free(g2,TRUE);
}

gchar * linkify( gchar * input )
{
	int i = 0;
	int len = strlen(input);
	gchar * result;
	GString * temp_result;
	GString * temp = NULL;

	temp_result = g_string_sized_new(2048);

	while( i < len )
	{
		if( isspace(input[i]) )
		{
			g_string_append_c(temp_result, input[i]);
			i++;
		}
		else
		{
			temp = get_next_token(input+i);
#ifdef DEBUG 
			printf("%s\t%s\t%d\t%d\n", input, input+i, i, temp->len);
#endif
			i += temp->len;
			linkify_token(temp);
			g_string_append(temp_result, temp->str);
			g_string_free(temp, TRUE);
		}
	}

	result = temp_result->str;
	g_string_free(temp_result, FALSE);
	return result;
}
			

eb_local_account * find_suitable_local_account( eb_local_account * first,
												gint second )
{
	GList * node;
	GList * states;
	
	/*The last state in the list of states will be the OFFLINE state*
	 *The first state in the list will be the ONLINE states			*
	 *The rest of the states are the various AWAY states 			*/
	
	states = eb_services[second].sc->get_states();
	
	g_list_free(states);
	
	if( first && first->connected )
	{
		/* hurrah, we got our first choice */
		return first;
	}
			
	/*dang, we are out of luck with our first choice, do we have something
	  else that uses the same service? */

	for( node = accounts; node; node = node->next )
	{
		eb_local_account * ela = (eb_local_account *)(node->data);
#ifdef DEBUG
		g_warning("%s %s", eb_services[ela->service_id].name, ela->handle);
#endif
		
		if( ela->service_id == second && ela->connected )
		{
			return ela;
		}
		else if( !ela->connected )
		{
#ifdef DEBUG
			g_warning("%s is offline!", ela->handle );
#endif
		}
			
	}
	
	/*We can't find anything, let's bail*/
	return NULL;
}

/* if contact can offline message, return the account,
   otherwise, return null 
*/

eb_account * can_offline_message( struct contact * con )
{
	GList * node;
	for(node = con->accounts; node; node=node->next)
	{
		eb_account * ea = (eb_account*)node->data;
		
		if( eb_services[ea->service_id].offline_messaging )
			return ea;
	}
	return 0;
}	
	
eb_account * find_suitable_remote_account( eb_account * first, 
										   struct contact * rest )
{
	GList * node;
	eb_account * possibility = NULL;

	if( first && eb_services[first->service_id].sc->query_connected(first) )
	{
		return first;
	}
	
	for(node = rest->accounts; node; node=node->next)
	{
		eb_account * ea = (eb_account*)node->data;
		
		if( eb_services[ea->service_id].sc->query_connected(ea) )
		{
			if(ea->service_id == rest->default_chatb )
			{
				return ea;
			}
			else
			{
				possibility = ea;
			}
		}
	}
	return possibility;
}
	
eb_account * find_suitable_file_transfer_account( eb_account * first, 
										   struct contact * rest )
{
	GList * node;
	eb_account * possibility = NULL;

    if ( first == NULL )
        return NULL;

	if( first && eb_services[first->service_id].sc->query_connected(first)
			&& eb_services[first->service_id].file_transfer )
	{
		return first;
	}
	
	for(node = rest->accounts; node; node=node->next)
	{
		eb_account * ea = (eb_account*)node->data;
		
		if( eb_services[ea->service_id].sc->query_connected(ea)
				&& eb_services[first->service_id].file_transfer )
		{
			if(ea->service_id == rest->default_chatb )
			{
				return ea;
			}
			else
			{
				possibility = ea;
			}
		}
	}
	return possibility;
}
	
eb_chat_room * find_chat_room_by_id( gchar * id )
{
	GList * node = chat_rooms;
	for( node= chat_rooms; node; node=node->next)
	{
		eb_chat_room * ecr = node->data;
		fprintf(stderr, "Comparing %s to %s\n", id, ecr->id );
		if(!strcmp(id, ecr->id))
			return ecr;
	}
	return NULL;

}

eb_chat_room * find_chat_room_by_name( gchar * name, gint service_id )
{
	GList * node = chat_rooms;
	for( node= chat_rooms; node; node=node->next)
	{
		eb_chat_room * ecr = node->data;
		if(!strcmp(name, ecr->room_name)  && (ecr->chat_room_account->service_id == service_id) )
			return ecr;
	}
	return NULL;

}

grouplist * find_grouplist_by_name(gchar * name)
{
    GList * l1;

    if (name == NULL) {
	return NULL;
    }
    for(l1 = groups; l1; l1=l1->next )
    {
		if(!g_strncasecmp(((grouplist *)l1->data)->name, name, strlen(name)+1))
        {
             return (grouplist*)l1->data;
        }
    }
    return NULL;
}

grouplist * find_grouplist_by_nick(gchar * nick)
{
    GList * l1;
    GList * l2;

    if (nick == NULL) {
	return NULL;
    }
    for(l1 = groups; l1; l1=l1->next )
    {
        for(l2 = ((grouplist*)l1->data)->members; l2; l2=l2->next )
        {
			if(!strcmp(((struct contact*)l2->data)->nick, nick))
            {
                    return (grouplist*)l1->data;
            }
        }
    }
    return NULL;
}

struct contact * find_contact_by_handle( gchar * handle )
{
    GList * l1;
    GList * l2;
    GList * l3;

    if (handle == NULL) {
	return NULL;
    }
    for(l1 = groups; l1; l1=l1->next )
    {
        for(l2 = ((grouplist*)l1->data)->members; l2; l2=l2->next )
        {
            for(l3 = ((struct contact*)l2->data)->accounts; l3; l3=l3->next)
            {
                eb_account * account = (eb_account*)l3->data;
                if(!strcmp(account->handle, handle))
                    return (struct contact*)l2->data;
            }
        }
    }
    return NULL;
}

struct contact * find_contact_by_nick( gchar * nick )
{
    GList * l1;
    GList * l2;

    if (nick == NULL){
	return NULL;
    }
    for(l1 = groups; l1; l1=l1->next )
    {
        for(l2 = ((grouplist*)l1->data)->members; l2; l2=l2->next )
        {
            if(!g_strncasecmp(((struct contact*)l2->data)->nick, nick, strlen(nick)+1))
            {
                return (struct contact*)l2->data;
            }
        }
    }
    return NULL;
}

eb_account * find_account_by_handle( gchar * handle, gint type )
{
    GList * l1;
    GList * l2;
    GList * l3;

    if (handle == NULL) {
	return NULL;
    }
    for(l1 = groups; l1; l1=l1->next )
    {
        for(l2 = ((grouplist*)l1->data)->members; l2; l2=l2->next )
        {
            for(l3 = ((struct contact*)l2->data)->accounts; l3; l3=l3->next)
            {
                eb_account * account = (eb_account*)l3->data;
                if(!g_strncasecmp(account->handle, handle,strlen(account->handle)+1)
						&& account->service_id == type )
                    return account;
            }
        }
    }
    return NULL;
}

extern char *aim_normalize(char *s);
eb_account * find_account_by_handle_normalized( gchar * handle, gint type )
{
    GList * l1;
    GList * l2;
    GList * l3;
 
    if (handle == NULL) {
        return NULL;
    }
    for(l1 = groups; l1; l1=l1->next )
    {
        for(l2 = ((grouplist*)l1->data)->members; l2; l2=l2->next )
        {
            for(l3 = ((struct contact*)l2->data)->accounts; l3; l3=l3->next)
            {
                eb_account * account = (eb_account*)l3->data;
                if(!g_strncasecmp(aim_normalize(account->handle), handle,strlen(handle)+1)
                                                && account->service_id == type )
                    return account;
            }
        }
    }
    return NULL;
}

eb_local_account * find_local_account_by_handle( gchar * handle )
{
    GList * l1;

    for(l1 = accounts; l1; l1=l1->next )
    {
         eb_local_account * account = (eb_local_account*)l1->data;
         if(!g_strncasecmp(account->handle, handle, strlen(handle)+1))
              return account;
    }
    return NULL;
}

void strip_html(gchar * text)
{
	int i, j;
	int visible = 1;
	
	for( i=0, j=0; text[i]; i++ )
	{
		if(text[i]=='<')
		{
			switch(text[i+1])
			{
				case 'a':
				case 'A':
					if(isspace(text[i+2]) || text[i+2] == '>')
					{
						visible = 0;
					}
					break;

				case 'i':
				case 'I':
				case 'u':
				case 'U':
					if(text[i+2] == '>')
					{
						visible = 0;
					}
					break;
				case 'b':
				case 'B':
					if(text[i+2] == '>')
					{
						visible = 0;
					}
					else if(text[i+2] == 'O' || text[i+2] == 'o')
					{
						if(text[i+3] == 'D' || text[i+3] == 'd' )
						{
							if(text[i+4] == 'Y' || text[i+4] == 'y' )
							{
								if(isspace(text[i+5]) || text[i+5] == '>')
								{
									visible = 0;
								}
							}
						}
					}
					break;
				case 'h':
				case 'H':
					if(text[i+2] == 'T' || text[i+2] == 't')
					{
						if(text[i+3] == 'M' || text[i+3] == 'm')
						{
							if(text[i+4] == 'L' || text[i+4] == 'l')
							{
								if(isspace(text[i+5]) || text[i+5] == '>')
								{
									visible = 0;
								}
							}
						}
					}
					break;
								
				case 'F':
				case 'f':
					if(text[i+2] == 'o' || text[i+2] == 'O')
					{
						if(text[i+3] == 'n' || text[i+3] == 'N')
						{
							if(text[i+4] == 't' || text[i+4] == 'T')
							{
								if(isspace(text[i+5]) || text[i+5] == '>')
								{
									visible = 0;
								}
							}
						}
					}
					break;
				case '/':
					visible = 0;
					break;
			}
		}
		else if(text[i] == '>')
		{
			if(!visible)
			{
				visible = 1;
				continue;
			}
		}
		if(visible)
		{
			text[j++] = text[i];
		}
	}
	text[j] = '\0';
}


void remove_account( eb_account * a )
{
    struct contact * c = a->account_contact;
	buddy_logoff(a);
	remove_account_line(a);
    c->accounts = g_list_remove(c->accounts, a);
    RUN_SERVICE(a)->del_user(a);
    g_free(a);
}
void remove_contact( struct contact * c )
{
    grouplist * g = c->group;
    if(c->chatwindow)
        gtk_widget_destroy(c->chatwindow->window);
    while(c->accounts)
    {
        remove_account(c->accounts->data);
    }
	remove_contact_line(c);
    g->members = g_list_remove(g->members, c);
    g_free(c);

}
void remove_group( grouplist * g )
{
    while(g->members)
    {
        remove_contact(g->members->data);
    }
	remove_group_line(g);
    groups = g_list_remove(groups,g);
    g_free(g);
}

void add_group( gchar * name )
{
    grouplist g, *eg;
    strncpy(g.name, name,255);
    g.members = NULL;
	g.list_item = NULL;
   
    groups = g_list_append( groups, eg = g_memdup(&g, sizeof(grouplist)));
	add_group_line(eg);
}


struct contact * add_new_contact( gchar * group, gchar * con, gint type )
{
    grouplist * g = find_grouplist_by_name( group);
    struct contact * c = g_new0( struct contact, 1);
	c->online = 0;
    if (con != NULL) {		// don't copy from null pointers !!
    strncpy(c->nick, con, 255);
    }
    c->default_chatb = c->default_filetransb = type;
   
    if(g)
    {
        g->members = g_list_append(g->members, c);
        c->group = g;
    }
    return c;
}

void add_account( gchar * contact, eb_account * account )
{
    struct contact * c = find_contact_by_nick( contact );
	eb_account * ea = find_account_by_handle(account->handle, account->service_id);
	if(ea)
	{
		if(!strcasecmp(ea->account_contact->nick, "Unknown"))
		{
			struct contact * c2 = ea->account_contact;
			remove_account(ea);
			if(g_list_length(c2->accounts) == 0)
			{
				remove_contact(c2);
			}
		}
		else
		{
			char buff[2048];
			g_snprintf(buff, 2048, "The account already exists on your\ncontact list at the following location\nGroup: %s\nContact: %s\nPlease delete this account before\nadding it elsewhere.", ea->account_contact->group->name, ea->account_contact->nick );

			if( c && g_list_length(c->accounts) == 0)
			{
				remove_contact(c);
			}

			do_error_dialog(buff, "Error: account exists");
			return;
		}
	}
   
    if( c )
    {
        c->accounts = g_list_append( c->accounts, account );
        account->account_contact = c;
    		RUN_SERVICE(account)->add_user(account);
    }
}


void add_contact( gchar * group, struct contact * user )
{
    GList * l1;
    grouplist * grp;
    for( l1 = groups; l1; l1=l1->next )
    {
        if(!g_strcasecmp(((grouplist*)(l1->data))->name, group) )
        {
            ((grouplist*)(l1->data))->members =
                g_list_append(((grouplist*)(l1->data))->members, user);
            user->group = l1->data;
            return;
        }
    }
    grp = g_new0(grouplist, 1);
    strncpy(grp->name, group, 255);
    grp->members = g_list_append(grp->members, user );
    groups = g_list_append(groups, grp);
    user->group = grp;
}

void add_unknown( eb_account * ea )
{
    struct contact * con = g_new0(struct contact, 1);
    strncpy(con->nick, ea->handle, 255);
    con->accounts = g_list_append( con->accounts, ea );
    con->default_chatb = ea->service_id;
    con->default_filetransb = ea->service_id;
    ea->account_contact = con;
    add_contact("Unknown", con);
	ea->icon_handler = -1;
	ea->status_handler = -1;
    RUN_SERVICE(ea)->add_user(ea);
	write_contact_list();
}


void move_contact (gchar * group, struct contact * c)
{
	grouplist * g = c->group;
	
	g->members = g_list_remove(g->members, c);
	remove_contact_line(c);
	g = find_grouplist_by_name(group);
	
	if(!g)
	{
		add_group(group);
	}
	g = find_grouplist_by_name(group);
	add_group_line(g);

	g->members = g_list_append(g->members, c);
	c->group = g;
	
	add_contact_and_accounts(c);
}

void import_gaim_accounts()
{
    gchar buff[1024];
    gchar c[1024];
    gchar group[1024];
    FILE * fp;
    g_snprintf(buff, 1024, "%s/gaim.buddy", getenv("HOME"));
    if( !(fp = fopen(buff, "r")) )
        return;
    while(!feof(fp))
    {
        fgets(c, 1024, fp);
        g_strchomp(c);
        if (*c == 'g') {
            strncpy(group,c+2, 1024);
            if(!find_grouplist_by_name(group))
            {
                add_group(group);
            }
        } else if (*c == 'b') {
            if(find_account_by_handle(c+2, AIM_SERVICE_ID))
            {
                continue;
            }
            if(!find_contact_by_nick(c+2))
            {
                add_new_contact( group, c+2, AIM_SERVICE_ID );
            }
            if(!find_account_by_handle(c+2, AIM_SERVICE_ID))
            {
                eb_account * ea = eb_services[AIM_SERVICE_ID].sc->new_account(c+2);
                add_account( c+2, ea );
//                RUN_SERVICE(ea)->add_user(ea);
            }
        } else if (*c == 'p') {
            /*no need*/
        } else if (*c == 'd') {
            /*no need*/
        } else if (*c == 'm') {
            /*no need*/
        }
    }


}

typedef struct _invite_request
{
	eb_local_account * ela;
	void * id;
} invite_request;

static void process_invite( GtkWidget * widget, gpointer data )
{
	invite_request * invite = data;
	int result = (int)gtk_object_get_user_data( GTK_OBJECT(widget));

	if( result )
	{
		RUN_SERVICE(invite->ela)->accept_invite( invite->ela, invite->id );
	}
	else
	{
		RUN_SERVICE(invite->ela)->decline_invite( invite->ela, invite->id);
	}

	g_free(invite);
}


void invite_dialog( eb_local_account * ela, char * user, char * chat_room,
					void * id )
{
	char * message = g_strdup_printf(
			"User %s wants to invite you to\n%s\nWould you like to accept?",
			user, chat_room);
	invite_request * invite = g_new0( invite_request, 1 );

	invite->ela = ela;
	invite->id = id;
	do_dialog( message, "Chat Invite", process_invite, invite );
	g_free(message);
}
	
		

void import_gnomeicu_accounts()
{
    gchar buff[1024];
    gchar c[1024];
    gchar ** tokens = NULL;
    gchar * uin = NULL, * nick = NULL;
    FILE * fp;

    g_snprintf(buff, 1024, "%s/.gnome/GnomeICU", getenv("HOME"));
    if( !(fp = fopen(buff, "r")) )
        return;
	while(!feof(fp))
	{
		fgets(c, 1024, fp);
		g_strchomp(c);
		if(!g_strncasecmp( c, "[NewContacts]", strlen("[NewContacts]")+1))
			break;
	}
	if(feof(fp))
	{
		fclose(fp);
		return;
	}
	if(!find_grouplist_by_name("GnomeICU Users"))
		add_group("GnomeICU Users");
    while(!feof(fp))
    {
        fgets(c, 1024, fp);
		if(feof(fp))
			break;
        g_strchomp(c);

	tokens = g_strsplit(c,"=",2);
	uin = *tokens;
	nick = *(tokens+1);
		
            if(find_account_by_handle(uin, ICQ_SERVICE_ID))
            {
                continue;
            }
            if(!find_contact_by_nick(nick))
            {
                add_new_contact( "GnomeICU Users", nick, ICQ_SERVICE_ID );
            }
            if(!find_account_by_handle(uin, ICQ_SERVICE_ID))
            {
                eb_account * ea = eb_services[ICQ_SERVICE_ID].sc->new_account(uin);
				ea->service_id = ICQ_SERVICE_ID;
                add_account( nick, ea );
//                RUN_SERVICE(ea)->add_user(ea);
            }
	g_strfreev (tokens);
    }
	fclose(fp);


}

void make_safe_filename(gchar *buff, gchar *name)  {
	
	/* i'm pretty sure the only illegal character is '/', but maybe 
	 * there are others i'm forgetting */
	char *bad_chars="/";
	char *p;
	char holder[NAME_MAX];

	strncpy(holder, name, NAME_MAX);

	for (p=holder; *p; p++) {
		if ( strchr(bad_chars, *p) )
			*p='_';
	}
	g_snprintf(buff, NAME_MAX, "%s/.everybuddy/logs/%s", 
				getenv("HOME"), holder);
}
					

