/*
    NewsCoaster
    Copyright (C) 1999-2002 Mark Harman

    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

    NewsCoaster Homepage :
        http://newscoaster.tripod.com/

    Mailing List to hear about announcements of new releases etc at:
        http://groups.yahoo.com/group/newscoaster-announce/
*/

#include "mui_headers.h"
#include <exec/types.h>
#include <string.h>
#include <ctype.h>

#include "Vector.h"
#include "various.h"
#include "misc.h"
#include "strings.h"

/* Strips a newline from the end of 'line'.
 */
void StripNewLine(char * line) {
	for(;;) {
		if(*line==13 || *line==10) {
			*line=0;
			return;
		}
		if(*line==0)
			return;
		line++;
	}
}

/* Replaces a string ending in CRLF with a string that just ends in LF.
 */
void convert13to10(char * text) {
	for(;;) {
		if(*text==13) {
			text++;
			if(*text==10) {
				*(text-1)=10;
				*text=0;
				return;
			}
		}
		if(*text==0)
			break;
		text++;
	}
}

/* Copys 'src' to 'dest', but replaces the CRLF with just a LF.
 * Returns the length of the copied string.
 */
int strcpy_13to10(char *dest,char *src) {
	int p = (int)dest;
	while(*src!=NULL) {
		if(*src == 13) {
			src++;
			if(*src == 10) {
				*dest++ = 10;
				break;
			}
			src--;
		}
		*dest = *src;
		dest++;
		src++;
	}
	*dest = '\0';
	return (int)dest - p;
}

/* Terminates 'text' at the first occurance of 'ch'.
 */
void StripChar(char * text,char ch) {
	char *str=strchr(text,ch);
	if(str != NULL)
		*str= '\0';
}

/* Removes trailing characters from 'text' so that last character is not
 * 'ch'.
 */
void StripTrail(char * text,char ch) {
	char *ptr = &text[strlen(text)-1];
	while(ptr>=text) {
		if(*ptr == ch)
			*ptr=0;
		else
			break;
		ptr--;
	}
}

/* Returns TRUE iff the strings 'str1' and 'str2' are equal (case
 * sensitive).
 */
BOOL equals(char *str1,char *str2) {
	if(*str1 == NULL || *str2 == NULL)
		return FALSE;
	while(*str1 == *str2) {
		if(*str1==0)
			return TRUE;
		str1++;
		str2++;
	}
	return FALSE;
}

/* Returns TRUE iff the strings 'str1' and 'str2' are equal (case
 * insensitive).
 */
BOOL iequals(char *str1,char *str2) {
	if(*str1 == NULL || *str2 == NULL)
		return FALSE;
	while(toupper(*str1) == toupper(*str2)) {
		if(*str1 == '\0')
			return TRUE;
		str1++;
		str2++;
	}
	return FALSE;
}

/* Unless otherwise specified, the following functions use 'word' to mean a
 * sequence of non-whitespace characters seperated by one or more
 * whitespace (as defined by isspace()) characters.
 */

/* Copies the first word of 'buffer' to 'dest'.
 */
void wordFirst(char * dest,char * buffer) {
	while(*buffer!=NULL && isspace(*buffer))
		buffer++;
	if(*buffer==NULL) {
		*dest = '\0';
		return;
	}
	while(*buffer!=NULL && !isspace(*buffer)) {
		*dest = *buffer;
		dest++;
		buffer++;
	}
	*dest= '\0';
}

/* Copies the first word of 'buffer' to 'dest'.
 * Returns the length of 'dest'.
 */
int wordFirstAndLen(char * dest,char * buffer) {
	//nLog("wordFirstAndLen((char *)%d,(char *)%s) called\n",dest,buffer);
	char * ptr = dest;
	while(*buffer!=NULL && isspace(*buffer))
		buffer++;
	if(*buffer==NULL) {
		*dest = '\0';
		return 0;
	}
	while(*buffer!=NULL && !isspace(*buffer)) {
		*dest = *buffer;
		dest++;
		buffer++;
	}
	*dest = '\0';
	return ((int)dest - (int)ptr);
}

/* Copies the first word of 'buffer' to 'dest', converting it to upper
 * case.
 */
void wordFirstUpper(char * dest,char * buffer) {
	while(*buffer!=NULL && isspace(*buffer))
		buffer++;
	if(*buffer==NULL) {
		*dest = '\0';
		return;
	}
	while(*buffer!=NULL && !isspace(*buffer)) {
		*dest = toupper(*buffer);
		dest++;
		buffer++;
	}
	*dest = '\0';
}

/* Copies the first word of 'buffer' to 'dest', converting it to upper
 * case.
 * Returns the length of 'dest'.
 */
int wordFirstAndLenUpper(char * dest,char * buffer) {
	//nLog("wordFirstAndLenUpper((char *)%d,(char *)%d:%s) called\n",dest,buffer,buffer);
	char *ptr = dest;
	while(*buffer != '\0' && isspace(*buffer))
		buffer++;
	/*if(*buffer == '\0') {
		*dest = '\0';
		return 0;
	}*/
	while(*buffer != '\0' && !isspace(*buffer)) {
		*dest = toupper(*buffer);
		dest++;
		buffer++;
	}
	*dest = '\0';
	return ((int)dest - (int)ptr);
}

/* Returns a pointer to the last word.
 */
char *wordLast(char *buffer) {
	if( *buffer == '\0' )
		return buffer;
	char *last = buffer;
	char *ptr = buffer;
	ptr++;
	while( *ptr != '\0' ) {
		if( isspace(ptr[-1]) && !isspace(ptr[0]) )
			last = ptr;
		ptr++;
	}
	return last;
}

/* Copies the 'n'th word (ie, starting from n==1) in 'str' to 'word'.
 */
void word(char *word,char *str,int n) {
	for(int i=1;i<n;i++) {
		while( *str!=NULL && isspace(*str) ) // spaces
			str++;
		while( *str!=NULL && !isspace(*str) ) // non-spaces
			str++;
		if( *str == NULL ) {
			*word = '\0';
			return;
		}
	}
	while( *str!=NULL && isspace(*str) ) // spaces
		str++;
	while( *str!=NULL && !isspace(*str) ) { // copy word
		*word = *str;
		word++;
		str++;
	}
	*word = '\0';
}

/* Copies the 'n'th "word" (ie, starting from n==1) in 'str' to 'word',
 * where words are considered to be strings seperated by characters 'ws'.
 */
void word(char *word,char *str,int n,char ws) {
	nLog("%d::%s\n",n,str);
	char *tptr = word;
	for(int i=1;i<n;i++) {
		while( *str!=NULL && *str==ws ) // spaces
			str++;
		while( *str!=NULL && *str!=ws ) // non-spaces
			str++;
		if( *str == NULL ) {
			*word = '\0';
			return;
		}
	}
	while( *str!=NULL && *str==ws ) // spaces
		str++;
	while( *str!=NULL && *str!=ws ) { // copy word
		*word = *str;
		word++;
		str++;
	}
	*word = '\0';
	nLog("%s\n",tptr);
}

/* Returns a pointer to the start of the 'n'th word (ie, starting from
 * n==1) in 'str'.
 * Returns NULL if there are less than 'n' words.
 */
char * wordStart(char *str,int n) {
	for(int i=1;i<n;i++) {
		while( *str!=NULL && isspace(*str) ) // spaces
			str++;
		while( *str!=NULL && !isspace(*str) ) // non-spaces
			str++;
		if( *str == NULL ) {
			return NULL;
		}
	}
	while( *str!=NULL && isspace(*str) ) // spaces
		str++;
	return str;
}

/* Extract either the name or email from 'email' and copy to 'out'. 'type'
 * can be:
 * GETEMAIL_NAME      - return the name
 * GETEMAIL_NAMEEMAIL - return the name, or if there is no name, return the email
 * GETEMAIL_EMAIL     - return the email
 */
void get_email(char * out,char * email,GetEmailType type) {
	STRPTR t1 = NULL;
	char word1[256] = "";
	int t2 = 0;
	if(type==GETEMAIL_NAME || type==GETEMAIL_NAMEEMAIL) {
		if(email[0]=='<' || email[1]=='<') {
			if(email[strlen(email)-1]=='>') {
				// no name
				if(type==GETEMAIL_NAME) {
					out[0] = '\0';
					return;
				}
			}
			else {
				// email is first
				t1=strchr(email,'>');
				if(t1==NULL) {
					out[0]= '\0';
					return;
				}
				t2=strlen(email)+(int)email-(int)t1+3;
				strncpy(out,t1+2,t2);
				out[t2]= '\0';
				return;
			}
		}
		else {
			t1=strchr(email,'<');
			if(t1==NULL)
				t2=strlen(email)+1;
			else
				t2=(int)t1-(int)email;
			strncpy(out,email,t2-1);
			out[t2-1]= '\0';
			return;
		}
	}
	// get email
	t1=strchr(email,'<');
	if(t1==NULL) {
		wordFirst(word1,email);
		strcpy(out,word1);
		return;
	}
	t2=(int)t1-(int)email;
	int t3 = strlen(email) - t2 - 2;
	if(t3 > 0) {
		strncpy(out,t1+1,t3);
		out[t3]= '\0';
	}
	else
		*out = '\0';
	return;
}

/* Converts 'text' to upper case.
 */
void toUpper(char *text) {
	while( (*text = toupper(*text)) != '\0')
		text++;
}

/* This function is provided when compiling with StormC.
 */
#ifdef __GNUC__
int stricmp(char * str1,char * str2) {
	int res = 0;
	char u1,u2;
	while(*str1!=0 && *str2!=0) {
		u1 = toupper(*str1);
		u2 = toupper(*str2);
		if(u1 != u2) {
			if( u1 > u2 )
				res = 1;
			else
				res = -1;
			break;
		}
		str1++;
		str2++;
	}
	if(res==0) {
		if(*str1!=0 && *str2==0)
			res = 1;
		else if(*str1==0 && *str2!=0)
			res = -1;
	}
	return res;
}
#endif

/* Similar to strncmp, but the comparison is case insensitive.
 */
int strincmp(char * str1,char * str2,int n) {
	int i=0;
	int res = 0;
	char u1,u2;
	while(*str1!=0 && *str2!=0 && i<n) {
		u1 = toupper(*str1);
		u2 = toupper(*str2);
		if(u1 != u2) {
			if( u1 > u2 )
				res = 1;
			else
				res = -1;
			break;
		}
		str1++;
		str2++;
		i++;
	}
	if(res==0 && i<n) {
		if(*str1!=0 && *str2==0)
			res = 1;
		else if(*str1==0 && *str2!=0)
			res = -1;
	}
	return res;
}

/* Similar to strincmp, but it assumes that 'str2' is in upper case.
 */
int strincmp_q(char * str1,char * str2,int n) {
	int i=0;
	int res = 0;
	char u1;
	while(*str1!=0 && *str2!=0 && i<n) {
		u1 = toupper(*str1);
		if(u1 != *str2) {
			if( u1 > *str2 )
				res = 1;
			else
				res = -1;
			break;
		}
		str1++;
		str2++;
		i++;
	}
	if(res==0 && i<n) {
		if(*str1!=0 && *str2==0)
			res = 1;
		else if(*str1==0 && *str2!=0)
			res = -1;
	}
	return res;
}

/* Similar to strstr, but the search is case insensitive.
 */
char * stristr(char * src,char * sub) {
	if(*sub==NULL)
		return src;

	char * pos = NULL;
	char * subptr = sub;
	for(char *p=src; *p != '\0' ;) {
		if(toupper(*p) == toupper(*subptr)) {
			p++;
			subptr++;
			if(*subptr == '\0') {
				pos = &p[ (int)sub - (int)subptr ];
				break;
			}
		}
		else if(subptr != sub)
			subptr = sub;
		else
			p++;
	}
	return pos;
}

/* Similar to stristr, but it assumes that 'sub' is in upper case.
 */
char * stristr_q(char * src,char * sub) {
	if(*sub==NULL)
		return src;

	char * pos = NULL;
	char * subptr = sub;
	for(char *p=src; *p != '\0' ;) {
		if(toupper(*p) == *subptr) {
			p++;
			subptr++;
			if(*subptr == '\0') {
				pos = &p[ (int)sub - (int)subptr ];
				break;
			}
		}
		else if(subptr != sub)
			subptr = sub;
		else
			p++;
	}
	return pos;
}

/* Replaces all Escape characters in the string with a space.
 * This is due to a security flaw when devices such as APIPE: are mounted,
 * allowing code to be executed by displaying malicious text in an MUI Text
 * object (or subclass).
 * See http://www.abraxis.com/SA-2001-11-08.html for more details.
 */
void stripEscapes(char * text) {
	while(*text != '\0') {
		if(*text == 27)
			*text = ' ';
		text++;
	}
	/*for(int i=0;i<length;i++) {
		if(*text == 27 || *text == '\0')
			*text = ' ';
		text++;
	}*/
}

void translateIso(char *dest,char *src) {
	while(*src != '\0') {
		if(src[0] == '=' && src[1] == '?') {
			char *qu_1 = strchr(&src[2],'?');
			char *qu_2 = NULL;
			char *end = NULL;
			if(qu_1 != NULL)
				qu_2 = strchr(&qu_1[1],'?');
			if(qu_2 != NULL)
				end = strstr(&qu_2[1],"?=");
			if(end != NULL) {
				char enc = qu_1[1];
				src = &qu_2[1];
				/*while(src < end) {
					*dest++ = *src++;
				}*/
				int len = (int)end - (int)src;
				if(len > 0) {
					if(enc == 'q' || enc == 'Q') {
						int dlen = decode_qprint(src, dest, len, TRUE);
						dest += dlen;
					}
					else if(enc == 'b' || enc == 'B') {
						int dlen = decode_base64(src, dest, len);
						dest += dlen;
					}
					else {
						while(src < end) {
							*dest++ = *src++;
						}
					}
				}
				src = &end[2];
			}
			else {
				*dest++ = *src++;
				*dest++ = *src++;
			}
		}
		else
			*dest++ = *src++;
	}
	*dest = '\0';
}
