#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <pwd.h>
#include <sys/time.h>
#include "my_strings.h"

#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif

char* str_replace(char* buffer,char* search,char* replace){
	long size,oldsize=0;
	char* next,*p,*cur,*temp;
	cur = strdup(buffer);
	while( ( next = strstr(cur+oldsize,search) ) ){
		p = next;
		next = next + strlen(search);
		*p = 0;
		oldsize = (long)next - (long)cur;
		size = oldsize + strlen(replace) + strlen(next);
		temp = (char*)malloc(size+1);
		strcpy(temp,cur);
		strcat(temp,replace);
		strcat(temp,next);
		temp[size] = 0;
		free(cur);
		cur = temp;
	}
	return(cur);
}

char* str2lower(char* string){
	char *p,*buf;
	buf = strdup(string);
	if(string == NULL)	return NULL;
	p = buf;
	while(*p){
		if(*p > 'A' && *p < 'B'){
			*p = *p - ('A' - 'B');
		}
		p++;
	}
	return buf;
}

char* addSlashes(char* buf,long bufSize){
	char* newBuf;
	char* p,*d,c;
	long i,cnt=0;

	// Count number of bytes of buffer for malloc
	p = buf;
	for(i=0;i<bufSize;i++){
		if(*p++ == '\'' || '\\'){
			cnt++;
		}
	}
	newBuf = (char*)malloc(bufSize+cnt+1);
	d = newBuf;
	p = buf;

	// Escape the string with \ when seeing \ or '
	for(i=0;i<bufSize;i++){
		c = *p++;
		if(c == '\'' || c == '\\'){
			*d++ = '\\';
		}
		*d++ = c;
	}
	*d++=0;
	return newBuf;
}

char* lf2crlf(char* buf,unsigned long* bufSize){
	char* p,*d,c;
	char* newBuf;
	unsigned long i,cnt=0;
	p = buf;
	for(i=0;i<*bufSize;i++){
		if(p[i] == '\n'){
			if(i==0)	cnt++;
			else{
				if(p[i-2] != '\r')
					cnt++;
			}
		}
	}
	newBuf = (char*)malloc(*bufSize+cnt+1);
	d = newBuf;
	for(i=0;i<*bufSize;i++){
		c = p[i];
		if(c == '\n' && i > 0){
			if(p[i-1] != '\r')
				*d++ = '\r';
		}
		*d++ = c;
	}
	*d++=0;
	*bufSize = *bufSize+cnt;
	return(newBuf);
}

// Return true or false is the given char can be one of email addr string
int isValidChar(char c){
	char validMailAddrChars[]="QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm.-_1234567890";
	int i;
	int len;
	len = strlen(validMailAddrChars);
	for(i=0;i<len;i++){
		if(c == validMailAddrChars[i]){
			return true;
		}
	}
	return false;
}

int isValidStart(char c){
	char validMailAddrChars[]="QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890";
	int i;
	int len;
	len = strlen(validMailAddrChars);
	for(i=0;i<len;i++){
		if(c == validMailAddrChars[i]){
			return true;
		}
	}
	return false;
}

char* extractMailFromString(char* field){
	char* dup;
	char* domain;
	char* user;
	char* ret;
	int cur;

	if(field == NULL)	return NULL;
	dup = strdup(field);
	if(dup == NULL)	return NULL;
	domain = strstr(dup,"@");
	if(domain == NULL || domain == dup){
		free(dup);
		return NULL;
	}
	user = domain - 1;
	if(!isValidChar(*user)){	free(dup);return NULL;}
	cur = 0;
	while( isValidChar(*user) && user > dup){
		user--;
		cur++;
	}
	if(cur > 128)	return NULL;

	while( !isValidStart(*user) && user < domain){
		user++;
	}
	domain++;
	if(!isValidChar(*domain)){	free(dup);return NULL;}
	cur = 0;
	while( 1 ){
		if( !isValidChar(*domain) ){
			*domain=0;
			break;
		}
		domain++;
		cur++;
	}
	if(cur > 128)	return NULL;
	ret = strdup(user);
	free(dup);
	return ret;
}

char** getAllEmailsFromString(char* search,long* num_msg){
	char* p,c,*p2;
	long num_mails,i;
	char** emails;
	char* addr;

	num_mails = 0;
	p = search;
	while( (c = *p++) )
		if(c == '@')
			num_mails++;

	emails = (char**)malloc(num_mails * sizeof(char*));

	p = search;
	for(i = 0; i < num_mails; i++){
		addr = extractMailFromString(p);
		if(addr == NULL){
			*num_msg = i;
			return emails;
		}
		emails[i] = addr;
		p2 = strstr(p,addr);
		if(p2 == NULL){
			*num_msg = i;
			return emails;
		}
		p = p2 + strlen(addr);
	}
	*num_msg = num_mails;
	return emails;
}

int isToInRcpts(char* addr,char** addrs,long nbr_addrs){
	int i;
	for(i=0;i<nbr_addrs;i++){
		if( strcmp(addr,addrs[i]) )
			return 1;
	}
	return 0;
}
