#include "uirc.h"


int low_level_quote(char *input, int in_length, char *output)
{
#define M_QUOTE		16

int i;

for(i = 0; i < in_length; i++)
	{
	if(*input == 0)
		{
		*output = M_QUOTE;
		output++;
		*output = '0';
		}
	else if(*input == '\n')
		{
		*output = M_QUOTE;
		output++;
		*output = 'n';
		}
	else if(*input == '\r')
		{
		*output = M_QUOTE;
		output++;
		*output = 'r';
		}
	else if(*input == M_QUOTE)
		{
		*output = M_QUOTE;
		output++;
		*output = M_QUOTE;
		}
	else 
		{
		*output = *input;
		}
	input++;
	output++;
	}
*output = 0;/* string termination */
}


int medium_level_quote(\
char *input, int in_length, char *output, int *out_length)
{
#define X_QUOTE 	92
#define X_DELIM 	1
int i;
int j;

j = 0;
for(i = 0; i < in_length; i++)
	{
	if(*input == X_DELIM)
		{
		*output = X_QUOTE;
		output++;
		j++;
		*output = 'a';
		}
	else if(*input == X_QUOTE)
		{
		*output = X_QUOTE;
		output++;
		j++;
		*output = X_QUOTE;
		}
	else 
		{
		*output = *input;
		}
	input++;
	output++;
	j++;
	}
*out_length = j;
}


int medium_level_dequote(\
char input[], int in_length, char output[], int *out_length)
{
int i, j;
int error_flag;

error_flag = 0;
j = 0;
for(i = 0; i < in_length; i++)
	{
	if(*input == X_QUOTE)
		{
		input++;
		i++;
		if(*input == 'a') *output = X_DELIM;
		else if(*input == X_QUOTE) *output = X_QUOTE;
		else
			{
			*output = *input;
			error_flag = 1;
			}
		}
	else
		{
		*output = *input;
		}
	input++;
	output++;
	j++;
	}
*out_length = j;
if(error_flag) return(0);
return(1);/* ok */
}


int low_level_dequote(\
char *input, int in_length, char *output, int *out_length)
{
int i, j;
int error_flag;

error_flag = 0;
j = 0;
for(i = 0; i < in_length; i++)
	{
	if(*input == M_QUOTE)
		{
		input++;
		i++;
		if(*input == 'o')*output = 0;
		else if(*input == 'r')*output = '\r';
		else if(*input == 'n') *output = '\n';
		else if(*input == M_QUOTE)*output = M_QUOTE;
		else
			{
			*output = *input;
			error_flag = 1;
			}
		}
	else
		{
		*output = *input;
		}
	input++;
	output++;
	j++;
	}
*out_length = j;
if(error_flag) return(0);
return(1);/* ok */
}


int ctcp_quote(char *input, int in_length, char *output)
{
char temp[512];
int temp_length;

medium_level_quote(input, in_length, temp, &temp_length);
low_level_quote(temp, temp_length, output); 
}


int ctcp_dequote(\
char *input, char in_length, char *output, int *out_length, char *from)
{
char temp[512];
int temp_length;
int a, b;

a = low_level_dequote(input, in_length, temp, &temp_length);
if(!a) to_screen("error in low level dequoting detected and ignored\n", from);
/*
fprintf(stdout, "\nto_medium: %s", temp);
*/
b = medium_level_dequote(temp, temp_length, output, out_length);
if(!b) to_screen("error in medium level dequoting detected and ignored\n",\
from);

if(!a) return(0);/* error */
if(!b) return(0);/* error */
return(1);/* ok */
}


int extract_and_handle_ctcp(\
char *from, char *to, char *text, char *no_ctcp, int socketfd, char *prefix)
{
int  a, c, i, j;
int flag, old_flag;
char temp[512];
char output[512];
int out_length;


j = 0;
old_flag = 0;
flag = 0;
while(1)
	{
	if(*text ==0)break;
	if(*text == 1)/* ctcp start or end */
		{
		flag = 1 - flag;/* toggle flag */
		text++;
		}
	if(flag)/* in ctcp */
		{ 
		temp[j] = *text;/* copy */
		j++;
		text++;
		}
	else /* outside ctcp */
		{
		*no_ctcp = *text;
		no_ctcp++;
		text++;
		}
	if( (old_flag == 1) && (flag == 0) )
		{
		temp[j] = 0;
		a = ctcp_dequote(temp, j, output, &out_length, from);
/*
		fprintf(stdout, "\n");
		fprintf(stdout, "\neahc: extract_dequote="); 
		for(i = 0; i < out_length; i++)
			{
			fprintf(stdout, "%c", output[i]);
			}
		fprintf(stdout, "\neahc: out_length=%d", out_length);
		fprintf(stdout, "\neahc: from=%s, to=%s", from, to);
*/
		/* test for ignore ctcp */
		if(get_ignore_nick(prefix) & CTCP)return(1);

		ctcp_handle(from, to, output, out_length, socketfd); 
		j = 0;
		}
	old_flag = flag;
	}
*no_ctcp = 0;
if(!a) return(0);
return(1);/* ok */
}


ctcp_handle(\
char *from, char *to, char *trailing, int trail_length, int socketfd,\
char *out)
{
char tag[512];
char message[512];
int b, i, j;
char temp[512];
char temp2[512];
int o_length;
char *ti;
time_t now;
extern time_t idletimer;
extern char *strchr();
extern char addressed_channel[];
char decoded[512];
int decoded_length;
extern time_t ctcp_ping_timer;

ctcp_dequote(trailing, trail_length, decoded, &decoded_length, from);
 
/* get the present time */
now = time(0);
ti = ctime(&now);
*strchr(ti, '\n') = 0;
 
/* for ctcp fixed requests the format is: \1FINGER\1,
/* VERSION, PID, CLIENT INFO, ECHO, DCC */
/* for ACTION \1ACTION\1 */ 
/* only auto reply to a PRIVMSG, NOT to a NOTICE */
/* (ACTION is not really ctcp, but can take form \1ACTION text\1)*/

/* extract the tag */
for(i = 0; i < decoded_length; i++)
	{
	tag[i] = decoded[i];
	if(tag[i] == ' ')break;
 	}
tag[i] = 0;/* string termination */
/* extract the rest (if any) */
j = 0;
for(i = i; i < decoded_length; i++)	
	{
	message[j] = decoded[i];
	j++;
	}
message[j] = 0;

/*
sprintf(temp, "\nmessage=%s", message);
to_screen(temp, "");
*/

/* alert user */
if(strcmp(tag, "ACTION") != 0)/* action will show itself */
	{
	sprintf(temp, "CTCP %s from %s to %s %s", tag, from, to, message);  
/*	to_screen(temp, from);/* this would cause a seperate logfile */
	/* it is better to send these things to the channel or nick 'to' */
	to_screen(temp, to);
	}

if(strcmp(tag, "PING") == 0)
	{
	sprintf(temp,\
	"NOTICE %s :\1PING%s\1\n", from, message);
	if(! send_to_server(socketfd, temp) )return(0);	

	sprintf(temp, "CTCP PING reply from %s: %d seconds",\
	from, time(0) - ctcp_ping_timer);
	to_screen(temp, addressed_channel);
	return(1);
	}
else if(strcmp(tag, "ACTION") == 0)
	{
	get_event("ACTION", to, from, message, socketfd);
	sprintf(temp, "<%s> ACTION %s", from, message); 
	color_to_text(temp, INTENSIFIED, temp2, 1);
	to_screen(temp2, addressed_channel);
	return(1);
	}
else if(strcmp(tag, "VERSION") == 0)
	{
	sprintf(temp,\
	"NOTICE %s :\1VERSION uirc 0.017 color experimental, working on it :)\1\n",\
	from);
	if( !send_to_server(socketfd, temp) )return(0);	
	}		
else if(strcmp(tag, "FINGER") == 0)
	{
	sprintf(temp,\
	"NOTICE %s :\1FINGER panteltje pante@pi.net %d seconds idle\1\n",\
	from, time(0) - idletimer);
	if(! send_to_server(socketfd, temp) )return(0);	
	return(1);
	}
else if(strcmp(tag, "CLIENTINFO") == 0)
	{
	sprintf(temp,\
"NOTICE %s :\1CLIENTINFO FINGER ACTION PING ECHO VERSION TIME DCC CHAT DCC SEND/RECEIVE\1\n",\
	from);
	if(! send_to_server(socketfd, temp) )return(0);	
	return(1);
	}
else if(strcmp(tag, "TIME") == 0)
	{
	sprintf(temp, "NOTICE %s :\1TIME %s\1\n", from, ti);
/* ctcp_quote(temp, strlen(temp), temp2, &o_length);*/
	if(! send_to_server(socketfd, temp) )return(0);	
	return(1);
	}
else if(strcmp(tag, "ERRMSG") == 0)/* same as ECHO in ircii */
	{
	/* removed the trailing \1, else ircii sees this as a separate
	/* line */
	sprintf(temp, "NOTICE %s :\1ERRMSG%s\1\n", from, message);
	if(! send_to_server(socketfd, temp) )return(0);	
	return(1);
	}
else if(strcmp(tag, "ECHO") == 0)
	{
	/* removed the trailing \1, else ircii sees this as a separate
	/* line */
	sprintf(temp, "NOTICE %s :\1ECHO%s\1\n", from, message);
	if(! send_to_server(socketfd, temp) )return(0);	
	return(1);
	}
else if(strcmp(tag, "SOURCE") == 0)
	{
	sprintf(temp,\
"NOTICE %s :\1SOURCE experimental executable only availeble by DCC from me :)\1\n",
	from);
	if(! send_to_server(socketfd, temp) )return(0);	
	return(1);
	}
else if(strcmp(tag, "DCC") == 0)
	{
	/* rxbuf=:ircii!root@panteltje.255.255 PRIVMSG grep :DCC SEND
	/* seeflop 3266534217 1338 64 1c302f5f
	*/
	/* DCC type chat_or_filename  address    port filelength checksum
	/* DCC CHAT chat 3266534217 1042
	*/
	handle_dcc_request(from, message, socketfd);
	return(1);
	}		
else/* send error message if command not found */
	{
	sprintf(temp,"NOTICE %s ERRMSG\n", from);
/*	if(! send_to_server(socketfd, temp) )return(0);	
*/
	return(1);
	}

}/* end function ctcp_handle */

/*
int ctcp_send(int socketfd, char *to, char *message)
{
char temp[512];
char temp2[512];

ctcp_quote(message, length, temp);

sprintf(temp2, "NOTICE %s :\1%s\1\n", to, temp);
if(! send_to_server(socketfd, temp2) )return(0);	
return(1);
}
*/