/*

oer - IRC bot

See ftp://nic.funet.fi/pub/unix/irc/docs/FAQ.gz section 11 for the
definition of the word bot.

Copyright (C) 2000-2001 EQU <equ@equnet.org>

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 "oer-common.h"
#include "oer.h"

/* prototype definitions */
int emptyline(char *);
int iscomment(char *);
int isnumber(char *);
int isserver(char *);
int isvaliduserhost(char *);
int isansi(char *);
int isaction(char *);
int isctcp(char *);
int wordcount(char *);
int parse(char *, int, char *, char *, int, int);
int issamenickandhost(char *, char *, char *, char *);
void striplf(char *);
void stripchars(char *, char *);
void stripcntrl(char *);
void stripansi(char *);
void stripmirc(char *);
void safequote(char *);
void oer_debug(int, const char *, ...);
void secondstostring(time_t, char *, int);
void sortstring(char *);

#ifndef HAVE_SNPRINTF
int snprintf(char *, size_t, const char *, ...);
#endif

#ifndef HAVE_SNPRINTF
int snprintf(char *str, size_t size, const char *format, ...)
{
	int slen;
        va_list ap;
	char *ptr;

	/* what would be a "safe" size, beats me */
	if((ptr = malloc(TXT_BUFFER * 10)) == NULL) {
		return -1;
	}
	va_start(ap, format);
	vsprintf(ptr, format, ap);
	va_end(ap);
	strncpy(str, ptr, size);
	if(strlen(ptr) > size) {
		free(ptr);
		return -1;
	}
	slen = strlen(ptr);
	free(ptr);
	return slen;
}
#endif

void oer_debug(int level, const char *fmt, ...)
{
        va_list ap;

	if(do_tempoutput) {
		va_start(ap, fmt);
		vfprintf(stdout, fmt, ap);
		va_end(ap);
		return;
	}
	if(!do_console && !do_output) {
		return;
	}
        if(level <= do_debug) {
                va_start(ap, fmt);
                if(do_output) {
                        vfprintf(mystate->logto, fmt, ap);
		}
		if(do_console) {
                        vfprintf(stdout, fmt, ap);
                }
                va_end(ap);
        }
}

int wordcount(char *line)
{
	int ppos;
	int nppos;
	int words;
	char word[STRINGLEN + 1];

	ppos = 0;
	words = 0;
	while(1) {
		nppos = parse(line, ppos, " ", word, STRINGLEN, 0);
		if(nppos == ppos || nppos < 0) {
			break;
		}
		ppos = nppos;
		words++;
	}
	return words;
}

int isansi(char *line)
{
        int i;
        int length;
	char stringbuffer[WRITE_BUFFER_LENGTH + 1];

	strncpy(stringbuffer, line, WRITE_BUFFER_LENGTH);
	stripansi(stringbuffer);
	for(i = 0, length = strlen(stringbuffer); i < length; i++) {
                if(iscntrl((int)stringbuffer[i])) {
			return 1;
		}
        }
	return 0;
}

int isctcp(char *line)
{
	int i;
	int length;

	/* The first char has to be ^A */
	if(line[0] != 1) {
		return 0;
	}
	for(i = 1, length = strlen(line); i < length; i++) {
		if(line[i] == 1) {
			return 1;
		}
	}
	return 0;
}

int isaction(char *line)
{
	char chars[STRINGLEN + 1];

	snprintf(chars, STRINGLEN, "%cACTION", 1);
	if(!strncasecmp(line, chars, strlen(chars))) {
		return 1;
	} else {
		return 0;
	}
}

void stripcntrl(char *source)
{
	int i;
	int k;
	int length;
        char stringbuffer[WRITE_BUFFER_LENGTH + 1];
	
	for(i = 0, k = 0, length = strlen(source); i < length && k < WRITE_BUFFER_LENGTH; i++) {
		if(!iscntrl((int)source[i])) {
			stringbuffer[k++] = source[i];
		}
	}
	stringbuffer[k] = 0;
	/* the outstring is at max. equal length to the
	   original source string */
	strcpy(source, stringbuffer);
}

void stripmirc(char *source)
{
	int i;
	int k;
	int iscolor;
	int incolor;
	int length;
        char stringbuffer[WRITE_BUFFER_LENGTH + 1];
	
	for(i = 0, k = 0, iscolor = 0, incolor = 0, length = strlen(source); i < length && k < WRITE_BUFFER_LENGTH; i++) {
		if(source[i] == 3) {
			iscolor = (iscolor) ? 0 : 1;
			incolor = (incolor) ? 0 : 1;
			continue;
		}
		if(iscolor && incolor && (isdigit((int)source[i]) || source[i] == ',')) {
			continue;
		}
		incolor = 0;
		stringbuffer[k++] = source[i];
	}
	stringbuffer[k] = 0;
	/* the outstring is at max. equal length to the
	   original source string */
	strcpy(source, stringbuffer);
}

void stripchars(char *source, char *what)
{
	int i;
	int j;
	int k;
	int length;
	int length2;
        char stringbuffer[WRITE_BUFFER_LENGTH + 1];

	for(i = 0, length = strlen(what); i < length; i++) {
		for(k = 0, j = 0, length2 = strlen(source); k < length2; k++) {
			if(source[k] != what[i]) {
				stringbuffer[j++] = source[k];
			}
		}
		/* the outstring is at max. equal length to the
		   original source string */
		stringbuffer[j] = 0;
		strcpy(source, stringbuffer);
	}
}

void safequote(char *source)
{
	int j;
	int k;
	int length;
        char stringbuffer[WRITE_BUFFER_LENGTH + 1];

	for(k = 0, j = 0, length = strlen(source); k < length; k++) {
		if(source[k] == ':') {
			if((k + 1 < length) && source[k + 1] == ':') {
				/* skip to next sequent char */
				k++;
			}
		}
		stringbuffer[j++] = source[k];
	}
	/* the outstring is at max. equal length to the
	   original source string */
	stringbuffer[j] = 0;
	strcpy(source, stringbuffer);
}

void stripansi(char *source)
{
	char chars[STRINGLEN + 1];

	/* strip ^A which is for ctcp actions */
	chars[0] = 1;
	/* strip ^B which is normal bold */
	chars[1] = 2;
	/* strip ^G which is bell */
	chars[2] = 7;
	/* strip ^V which is normal reverse */
	chars[3] = 22;
	/* strip ^_ which is normal underline */
	chars[4] = 31;
	/* strip ^O which is normal ansi toggle */
	chars[5] = 15;
	/* eol */
	chars[6] = 0;
	stripchars(source, chars);
}

int emptyline(char *line)
{
        int length;
        int i;

        for(i = 0, length = strlen(line); i < length; i++) {
                if(!isspace((int)line[i])) {
                        return 0;
		}
	}
        return 1;
}

int iscomment(char *line)
{
        int length;
        int i;

        for(i = 0, length = strlen(line); i < length && isspace((int)line[i]); i++) {
		;
	}
	if(line[i] == '#') {
		return 1;
	}
        return 0;
}

void striplf(char *line)
{
        int i;

        for(i = strlen(line) - 1; isspace((int)line[i]) && i >= 0; i--) {
                line[i] = '\0';
	}
}

int isnumber(char *line)
{
	int length;
	int i;

	for(i = 0, length = strlen(line); line[i] != '\0' && i < length; i++) {
		if(!isdigit((int)line[i])) {
			return 0;
		}
	}
	return 1;
}

int isserver(char *line)
{
	int i;
	int length;
	int dots;

	for(i = 0, length = strlen(line), dots = 0; i < length; i++) {
		if(line[i] == '.') {
			dots++;
		}
	}
	if(wordcount(line) >= 2 && dots >= 2) {
		return 1;
	} else {
		return 0;
	}
}

int isvaliduserhost(char *line)
{
	int c;
	int c2;
	char *ptr;
	char *ptr2;

        if((ptr = index(line, '@')) == NULL) {
		return 0;
	}
	ptr2 = ptr + strlen(line);
	c = *(ptr - 1);
	c2 = *(ptr + 1);
	if(ptr == line || ptr == ptr2 || !isgraph(c) || !isgraph(c2)) {
		return 0;
	}
	return 1;
}

int parse(char *from, int pos, char *delim, char *to, int to_length, int fixed)
{
        int i;
        int j;
        int k;
        int len;
	int found_delim;

        memset(to, 0, to_length + 1);
	i = pos;
	k = 0;
	j = strlen(delim);
	len = strlen(from);
	found_delim = 0;
	while(i < len && k < to_length) {
		/* loop until delim found, respecting 
		   length constraints */
		if(fixed && !strncasecmp(from + i, delim, j)) {
			found_delim = 1;
			break;
		}
		if(!fixed && from[i] == delim[0]) {
			found_delim = 1;
			break;
		}
                to[k++] = from[i++];
	}
	if(found_delim) {
		/* advance until next non-delim character */
		if(fixed) {
			i += j;
		} else {
			while((from[i] == delim[0]) && (i < len)) {
				i++;
			}
		}
	}
        if(k >= to_length) {
		/* insufficient buffer space */
                return -1;
        }
        to[k] = '\0';
	return i;
}

void secondstostring(time_t seconds, char *string, int maxlen)
{
	int fields;
        time_t safe;
        time_t days;
        time_t hours;
        time_t minutes;
        char stringbuffer[STRINGLEN + 1];

        safe = seconds;
        days = seconds / 3600 / 24;
        seconds -= days * (3600 * 24);
        hours = seconds / 3600;
        seconds -= hours * (3600);
        minutes = seconds / 60;
        seconds -= minutes * 60;
	memset(string, 0, maxlen);
	fields = 0;
        if(days > 0) {
                snprintf(string, maxlen, "%lu %s ", days, (days == 1) ? "day" : "days");
		fields++;
		fields++;
        }
        if(hours > 0) {
                snprintf(stringbuffer, STRINGLEN, "%lu %s ", hours, (hours == 1) ? "hour" : "hours");
                strncat(string, stringbuffer, maxlen - strlen(string));
		fields++;
        }
        if(minutes > 0) {
                snprintf(stringbuffer, STRINGLEN, "%lu %s ", minutes, (minutes == 1) ? "minute" : "minutes");
                strncat(string, stringbuffer, maxlen - strlen(string));
		fields++;
        }
        if(seconds > 0) {
		if(fields > 0) {
			snprintf(stringbuffer, STRINGLEN, "and %lu %s", seconds, (seconds == 1) ? "second" : "seconds");
		} else {
			snprintf(stringbuffer, STRINGLEN, "%lu %s", seconds, (seconds == 1) ? "second" : "seconds");
		}
                strncat(string, stringbuffer, maxlen - strlen(string));
		fields++;
        }
}

int issamenickandhost(char *n1, char *n2, char *h1, char *h2)
{
        if(n1 == NULL || n2 == NULL || h1 == NULL || h2 == NULL) {
		return 0;
	}
	if(!strcasecmp(n1, n2) && !strcasecmp(n1, n2) && !strcasecmp(h1, h2)) {
		return 1;
	}
	return 0;
}

void sortstring(char *string)
{
	int times;
	int pos;
	int u1;
	int u2;
	int c1;
	int c2;
	int c;

	for(times = strlen(string) - 1; times >= 0; times--) {
		for(pos = strlen(string) - 1; pos > 0; pos--) {
			u1 = 0;
			u2 = 0;
			c1 = string[pos - 1];
			c2 = string[pos];
			if(isupper(c1)) {
				u1 = 1;
				c1 = tolower(c1);
			}
			if(isupper(c2)) {
				u2 = 1;
				c2 = tolower(c2);
			}
			if(c1 < c2) {
				continue;
			}
			if(c1 == c2 && u1) {
				continue;
			}
			if(u1) {
				c1 = toupper(c1);
			}
			if(u2) {
				c2 = toupper(c2);
			}
			c = c2;
			string[pos] = c1;
			string[pos - 1] = c;
		}
	}
}
