www.pudn.com > simplec++codeforp2p.rar > sys.cpp


// ------------------------------------------------
// File : sys.cpp
// Date: 4-apr-2002
// Author: giles
// Desc: 
//		Sys is a base class for all things systemy, like starting threads, creating sockets etc..
//		Lock is a very basic cross platform CriticalSection class		 
//		SJIS-UTF8 conversion by ????
//
// (c) 2002 peercast.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.
// ------------------------------------------------

#include "common.h"
#include "sys.h"
#include "socket.h"
#include "gnutella.h"
#include 
#include  
#include "jis.h" 
 
// ----------------------------------- 
#define isSJIS(a,b) ((a >= 0x81 && a <= 0x9f || a >= 0xe0 && a<=0xfc) && (b >= 0x40 && b <= 0x7e || b >= 0x80 && b<=0xfc)) 
#define isEUC(a) (a >= 0xa1 && a <= 0xfe) 
#define isASCII(a) (a <= 0x7f)  
#define isPLAINASCII(a) (((a >= '0') && (a <= '9')) || ((a >= 'a') && (a <= 'z')) || ((a >= 'A') && (a <= 'Z'))) 
#define isUTF8(a,b) ((a & 0xc0) == 0xc0 && (b & 0x80) == 0x80 ) 
#define isESCAPE(a,b) ((a == '&') && (b == '#')) 
#define isHTMLSPECIAL(a) ((a == '&') || (a == '\"') || (a == '\'') || (a == '<') || (a == '>')) 
 
 
 
// -----------------------------------
const char *LogBuffer::logTypes[]=
{
	"",
	"DBUG",
	"EROR",
	"GNET",
	"CHAN",
};

// -----------------------------------
// base64 encode/decode taken from ices2 source.. 
static char base64table[64] = {
    'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
    'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
    'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
    'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
};
#if 0
// -----------------------------------
static char *util_base64_encode(char *data)
{
    int len = strlen(data);
    char *out = malloc(len*4/3 + 4);
    char *result = out;
    int chunk;

    while(len > 0) {
        chunk = (len >3)?3:len;
        *out++ = base64table[(*data & 0xFC)>>2];
        *out++ = base64table[((*data & 0x03)<<4) | ((*(data+1) & 0xF0) >> 4)];
        switch(chunk) {
            case 3:
                *out++ = base64table[((*(data+1) & 0x0F)<<2) | ((*(data+2) & 0xC0)>>6)];
                *out++ = base64table[(*(data+2)) & 0x3F];
                break;
            case 2:
                *out++ = base64table[((*(data+1) & 0x0F)<<2)];
                *out++ = '=';
                break;
            case 1:
                *out++ = '=';
                *out++ = '=';
                break;
        }
        data += chunk;
        len -= chunk;
    }

    return result;
}
#endif

// -----------------------------------
static int base64chartoval(char input)
{
    if(input >= 'A' && input <= 'Z')
        return input - 'A';
    else if(input >= 'a' && input <= 'z')
        return input - 'a' + 26;
    else if(input >= '0' && input <= '9')
        return input - '0' + 52;
    else if(input == '+')
        return 62;
    else if(input == '/')
        return 63;
    else if(input == '=')
        return -1;
    else
        return -2;
}

// -----------------------------------
static char *util_base64_decode(char *input)
{
	return NULL;
}





// ------------------------------------------
Sys::Sys()
{
	idleSleepTime = 10;
	logBuf = new LogBuffer(1000,100); 
	numThreads=0;
}

// ------------------------------------------
void Sys::sleepIdle()
{
	sleep(idleSleepTime);
}

// ------------------------------------------
void Host::toResolvedName(char *str)
{
	char hostName[128];

	if (ClientSocket::getHostname(hostName,ip))
		sprintf(str,"%s:%d",hostName,port);
	else
		toStr(str);
}

// ------------------------------------------
bool Host::isLocalhost()
{ 
	return loopbackIP() || (ip == ClientSocket::getIP(NULL)); 
}
// ------------------------------------------
void Host::fromStrName(const char *str, int p)
{
	if (!strlen(str))
	{
		port = 0;
		ip = 0;
		return;
	}

	char name[128];
	strcpy(name,str);
	port = p;
	char *pp = strstr(name,":");
	if (pp)
	{
		port = atoi(pp+1);
		pp[0] = 0;
	}

	ip = ClientSocket::getIP(name);
}
// ------------------------------------------
void Host::fromStrIP(const char *str, int p)
{
	unsigned int ipb[4];
	unsigned int ipp;


	if (strstr(str,":"))
	{
		if (sscanf(str,"%03d.%03d.%03d.%03d:%d",&ipb[0],&ipb[1],&ipb[2],&ipb[3],&ipp) == 5)
		{
			ip = ((ipb[0]&0xff) << 24) | ((ipb[1]&0xff) << 16) | ((ipb[2]&0xff) << 8) | ((ipb[3]&0xff));
			port = ipp;
		}else
		{
			ip = 0;
			port = 0;
		}
	}else{
		port = p;
		if (sscanf(str,"%03d.%03d.%03d.%03d",&ipb[0],&ipb[1],&ipb[2],&ipb[3]) == 4)
			ip = ((ipb[0]&0xff) << 24) | ((ipb[1]&0xff) << 16) | ((ipb[2]&0xff) << 8) | ((ipb[3]&0xff));
		else
			ip = 0;
	}
}
// -----------------------------------
bool Host::isMemberOf(Host &h)
{
	if (h.ip==0)
		return false;

    if( h.ip0() != 255 && ip0() != h.ip0() )
        return false;
    if( h.ip1() != 255 && ip1() != h.ip1() )
        return false;
    if( h.ip2() != 255 && ip2() != h.ip2() )
        return false;
    if( h.ip3() != 255 && ip3() != h.ip3() )
        return false;

/* removed for endieness compatibility
	for(int i=0; i<4; i++)
		if (h.ipByte[i] != 255)
			if (ipByte[i] != h.ipByte[i])
				return false;
*/
	return true;
}

// -----------------------------------
char *trimstr(char *s1)
{
	while (*s1)
	{
		if ((*s1 == ' ') || (*s1 == '\t'))
			s1++;
		else
			break;

	}

	char *s = s1;

	s1 = s1+strlen(s1);

	while (*--s1)
		if ((*s1 != ' ') && (*s1 != '\t'))
			break;

	s1[1] = 0;

	return s;
}

// -----------------------------------
char *stristr(const char *s1, const char *s2)
{
	while (*s1)
	{
		if (TOUPPER(*s1) == TOUPPER(*s2))
		{
			const char *c1 = s1;
			const char *c2 = s2;

			while (*c1 && *c2)
			{
				if (TOUPPER(*c1) != TOUPPER(*c2))
					break;
				c1++;
				c2++;
			}
			if (*c2==0)
				return (char *)s1;
		}

		s1++;
	}
	return NULL;
}
// -----------------------------------
bool String::isValidURL()
{
	return (strnicmp(data,"http://",7)==0) || (strnicmp(data,"mailto:",7)==0);
}

// -----------------------------------
void String::setFromTime(unsigned int t)
{
	char *p = ctime((time_t*)&t);
	if (p)
		strcpy(data,p);
	else
		strcpy(data,"-");
	type = T_ASCII;
}
// -----------------------------------
void String::setFromStopwatch(unsigned int t)
{
	unsigned int sec,min,hour,day;

	sec = t%60;
	min = (t/60)%60;
	hour = (t/3600)%24;
	day = (t/86400);

	if (day)
		sprintf(data,"%d day, %d hour",day,hour);
	else if (hour)
		sprintf(data,"%d hour, %d min",hour,min);
	else if (min)
		sprintf(data,"%d min, %d sec",min,sec);
	else if (sec)
		sprintf(data,"%d sec",sec);
	else
		sprintf(data,"-");

	type = T_ASCII;
}
// -----------------------------------
void String::setFromString(const char *str, TYPE t)
{
	int cnt=0;
	bool quote=false;
	while (*str)
	{
		bool add=true;
		if (*str == '\"')
		{
			if (quote) 
				break;
			else 
				quote = true;
			add = false;
		}else if (*str == ' ')
		{
			if (!quote)
			{
				if (cnt)
					break;
				else
					add = false;
			}
		}

		if (add)
		{
			data[cnt++] = *str++;
			if (cnt >= (MAX_LEN-1))
				break;
		}else
			str++;
	}
	data[cnt] = 0;
	type = t;
}

// -----------------------------------
int String::base64WordToChars(char *out,const char *input)
{
	char *start = out;
	signed char vals[4];

    vals[0] = base64chartoval(*input++);
    vals[1] = base64chartoval(*input++);
    vals[2] = base64chartoval(*input++);
    vals[3] = base64chartoval(*input++);

    if(vals[0] < 0 || vals[1] < 0 || vals[2] < -1 || vals[3] < -1) 
		return 0;

    *out++ = vals[0]<<2 | vals[1]>>4;
    if(vals[2] >= 0)
        *out++ = ((vals[1]&0x0F)<<4) | (vals[2]>>2);
    else
        *out++ = 0;

    if(vals[3] >= 0)
        *out++ = ((vals[2]&0x03)<<6) | (vals[3]);
    else
        *out++ = 0;

	return out-start;
}

// -----------------------------------
void String::BASE642ASCII(const char *input)
{
	char *out = data;
    int len = strlen(input);

    while(len >= 4) 
	{
		out += base64WordToChars(out,input);
		input += 4;
        len -= 4;
    }
    *out = 0;
}
 
 
 
// ----------------------------------- 
void String::UNKNOWN2UNICODE(const char *in,bool safe) 
{ 
	MemoryStream utf8(data,MAX_LEN-1); 
 
	unsigned char c; 
	unsigned char d; 
 
	while (c = *in++) 
	{ 
		d = *in; 
 
		if (isUTF8(c,d))		// utf8 encoded  
		{ 
			int numChars=0; 
			int i; 
 
			for(i=0; i<6; i++) 
			{ 
				if (c & (0x80>>i)) 
					numChars++; 
				else 
					break; 
			} 
 
			utf8.writeChar(c); 
			for(i=0; i') str = ">"; 
			else str = "?"; 
 
			utf8.writeString(str); 
		} 
		else 
		{ 
			utf8.writeUTF8(c); 
		} 
 
		if (utf8.pos >= (MAX_LEN-10)) 
			break; 
 
 
	} 
 
	utf8.writeChar(0);	// null terminate 
 
} 
 
// ----------------------------------- 
void String::ASCII2HTML(const char *in) 
{ 
	char *op = data; 
	char *oe = data+MAX_LEN-10; 
	unsigned char c; 
	const char *p = in; 
	while (c = *p++) 
	{ 
		 
		if (((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))) 
		{ 
			*op++ = c; 
		}else 
		{ 
			sprintf(op,"&#x%02X;",(int)c); 
			op+=6; 
		} 
		if (op >= oe) 
			break; 
	} 
	*op = 0; 
} 
// -----------------------------------
void String::ASCII2ESC(const char *in, bool safe)
{
	char *op = data;
	char *oe = data+MAX_LEN-10;
	const char *p = in;
	unsigned char c;
	while (c = *p++)
	{
		if (((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')))
			*op++ = c;
		else
		{
			*op++ = '%';
			if (safe)
				*op++ = '%';
			*op=0;
			sprintf(op,"%02X",(int)c);
			op+=2;
		}
		if (op >= oe)
			break;
	}
	*op=0;
}
// -----------------------------------
void String::HTML2ASCII(const char *in)
{
	unsigned char c;
	char *o = data;
	char *oe = data+MAX_LEN-10;
	const char *p = in;
	while (c = *p++)
	{
		if ((c == '&') && (p[0] == '#'))
		{
			p++;
			char code[8];
			char *cp = code;
			char ec = *p++;		// hex/dec
			while (c=*p++) 
			{
				if (c!=';')
					*cp++ = c;
				else
					break;
			}
			*cp = 0;
			c = (unsigned char)strtoul(code,NULL,ec=='x'?16:10);
		}
		*o++ = c;
		if (o >= oe)
			break;
	}

	*o=0;
}
// ----------------------------------- 
void String::HTML2UNICODE(const char *in) 
{ 
	MemoryStream utf8(data,MAX_LEN-1); 
 
	unsigned char c; 
	while (c = *in++) 
	{ 
		if ((c == '&') && (*in == '#')) 
		{ 
			in++; 
			char code[16]; 
			char *cp = code; 
			char ec = *in++;		// hex/dec 
			while (c=*in++)  
			{ 
				if (c!=';') 
					*cp++ = c; 
				else 
					break; 
			} 
			*cp = 0; 
			utf8.writeUTF8(strtoul(code,NULL,ec=='x'?16:10)); 
		}else 
			utf8.writeUTF8(c); 
 
		if (utf8.pos >= (MAX_LEN-10)) 
			break; 
	} 
 
	utf8.writeUTF8(0); 
} 

// -----------------------------------
void String::ESC2ASCII(const char *in)
{
	unsigned char c;
	char *o = data;
	char *oe = data+MAX_LEN-10;
	const char *p = in;
	while (c = *p++)
	{
		if (c == '+')
			c = ' ';
		else if (c == '%')
		{
			if (p[0] == '%')
				p++;

			char hi = TOUPPER(p[0]);
			char lo = TOUPPER(p[1]);
			c = (TONIBBLE(hi)<<4) | TONIBBLE(lo);
			p+=2;
		}
		*o++ = c;
		if (o >= oe)
			break;
	}

	*o=0;
}
// -----------------------------------
void String::ASCII2META(const char *in, bool safe)
{
	char *op = data;
	char *oe = data+MAX_LEN-10;
	const char *p = in;
	unsigned char c;
	while (c = *p++)
	{
		switch (c)
		{
			case '%':
				if (safe)
					*op++='%';
				break;
			case ';':
				c = ':';
				break;
		}

		*op++=c;
		if (op >= oe)
			break;
	}
	*op=0;
}
// -----------------------------------
void String::convertTo(TYPE t)
{
	if (t != type)
	{
		String tmp = *this;

		// convert to ASCII
		switch (type)
		{
			case T_UNKNOWN:
			case T_ASCII:
				break;
			case T_HTML:
				tmp.HTML2ASCII(data);
				break;
			case T_ESC:
			case T_ESCSAFE:
				tmp.ESC2ASCII(data);
				break;
			case T_META:
			case T_METASAFE:
				break;
			case T_BASE64:
				tmp.BASE642ASCII(data);
				break;
		}

		// convert to new format
		switch (t)
		{
			case T_UNKNOWN:
			case T_ASCII:
				strcpy(data,tmp.data);
				break;
			case T_UNICODE: 
				UNKNOWN2UNICODE(tmp.data,false); 
				break; 
			case T_UNICODESAFE: 
				UNKNOWN2UNICODE(tmp.data,true); 
				break; 
			case T_HTML:
				ASCII2HTML(tmp.data);
				break;
			case T_ESC:
				ASCII2ESC(tmp.data,false);
				break;
			case T_ESCSAFE:
				ASCII2ESC(tmp.data,true);
				break;
			case T_META:
				ASCII2META(tmp.data,false);
				break;
			case T_METASAFE:
				ASCII2META(tmp.data,true);
				break;
		}

		type = t;
	}
}
// -----------------------------------
void LogBuffer::write(const char *str, TYPE t)
{
	lock.on();

	unsigned int len = strlen(str);
	int cnt=0;
	while (len)
	{
		unsigned int rlen = len;
		if (rlen > (lineLen-1))
			rlen = lineLen-1;

		int i = currLine % maxLines;
		int bp = i*lineLen;
		strncpy(&buf[bp],str,rlen);
		buf[bp+rlen] = 0;
		if (cnt==0)
		{
			times[i] = sys->getTime();
			types[i] = t;
		}else
		{
			times[i] = 0;
			types[i] = T_NONE;
		}
		currLine++;

		str += rlen;
		len -= rlen;
		cnt++;
	}

	lock.off();
}

// -----------------------------------
char *getCGIarg(const char *str, const char *arg)
{
	if (!str)
		return NULL;

	char *s = strstr(str,arg);

	if (!s)
		return NULL;

	s += strlen(arg);

	return s;
}

// -----------------------------------
bool cmpCGIarg(char *str, char *arg, char *value)
{
	if ((!str) || (!strlen(value)))
		return false;

	if (strnicmp(str,arg,strlen(arg)) == 0) 
	{

		str += strlen(arg);

		return strncmp(str,value,strlen(value))==0; 
	}else 
		return false;
}
// -----------------------------------
bool hasCGIarg(char *str, char *arg)
{
	if (!str)
		return false;

	char *s = strstr(str,arg);

	if (!s)
		return false;

	return true;
}


// ---------------------------
void GnuID::encode(Host *h, const char *salt1, const char *salt2, unsigned char salt3)
{
	int s1=0,s2=0;
	for(int i=0; i<16; i++)
	{
		unsigned char ipb = id[i];

		// encode with IP address 
		if (h)
			ipb ^= ((unsigned char *)&h->ip)[i&3];

		// add a bit of salt 
		if (salt1)
		{
			if (salt1[s1])
				ipb ^= salt1[s1++];
			else
				s1=0;
		}

		// and some more
		if (salt2)
		{
			if (salt2[s2])
				ipb ^= salt2[s2++];
			else
				s2=0;
		}

		// plus some pepper
		ipb ^= salt3;

		id[i] = ipb;
	}

}
// ---------------------------
void GnuID::toStr(char *str)
{

	str[0] = 0;
	for(int i=0; i<16; i++)
	{
		char tmp[8];
		unsigned char ipb = id[i];

		sprintf(tmp,"%02X",ipb);
		strcat(str,tmp);
	}

}
// ---------------------------
void GnuID::fromStr(const char *str)
{
	clear();

	if (strlen(str) < 32)
		return;

	char buf[8];

	buf[2] = 0;

	for(int i=0; i<16; i++)
	{
		buf[0] = str[i*2];
		buf[1] = str[i*2+1];
		id[i] = (unsigned char)strtoul(buf,NULL,16);
	}

}

// ---------------------------
void GnuID::generate(unsigned char flags)
{
	clear();

	for(int i=0; i<16; i++)
		id[i] = sys->rnd();
 
	id[0] = flags;
}

// ---------------------------
unsigned char GnuID::getFlags()
{
	return id[0];
}

// ---------------------------
GnuIDList::GnuIDList(int max)
:ids(new GnuID[max])
{
	maxID = max;
	for(int i=0; igetTime(); 
			return; 
		}
		if (ids[i].storeTime <= minTime)
		{
			minTime = ids[i].storeTime;
			minIndex = i;
		} 
	}

	ids[minIndex] = id;
	ids[minIndex].storeTime = sys->getTime();
}
// ---------------------------
void GnuIDList::clear()
{
	for(int i=0; i maxLines) 
	{ 
		nl = maxLines-1; 
		sp = (currLine+1)%maxLines; 
	} 
 
	String tim,str; 
	if (nl) 
	{ 
		for(unsigned int i=0; i["); 
				out.writeString(getTypeStr(types[sp])); 
				out.writeString("] "); 
			} 
			str.set(&buf[bp]); 
			str.convertTo(String::T_HTML); 
 
			out.writeString(str.cstr()); 
			out.writeString("
"); sp++; sp %= maxLines; } } lock.off(); } // --------------------------- void ThreadInfo::shutdown() { active = false; //sys->waitThread(this); }