1 // ------------------------------------------------
6 // Sys is a base class for all things systemy, like starting threads, creating sockets etc..
7 // Lock is a very basic cross platform CriticalSection class
8 // SJIS-UTF8 conversion by ????
10 // (c) 2002 peercast.org
11 // ------------------------------------------------
12 // This program is free software; you can redistribute it and/or modify
13 // it under the terms of the GNU General Public License as published by
14 // the Free Software Foundation; either version 2 of the License, or
15 // (at your option) any later version.
17 // This program is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU General Public License for more details.
21 // ------------------------------------------------
27 #include "servmgr.h" //JP-EX
29 #include "utf8.h" //JP-Patch
35 #include "chkMemoryLeak.h"
36 #define DEBUG_NEW new(__FILE__, __LINE__)
40 // -----------------------------------
41 #define isSJIS(a,b) ((a >= 0x81 && a <= 0x9f || a >= 0xe0 && a<=0xfc) && (b >= 0x40 && b <= 0x7e || b >= 0x80 && b<=0xfc))
42 #define isEUC(a) (a >= 0xa1 && a <= 0xfe)
43 #define isASCII(a) (a <= 0x7f)
44 #define isPLAINASCII(a) (((a >= '0') && (a <= '9')) || ((a >= 'a') && (a <= 'z')) || ((a >= 'A') && (a <= 'Z')))
45 #define isUTF8(a,b) ((a & 0xc0) == 0xc0 && (b & 0x80) == 0x80 )
46 #define isESCAPE(a,b) ((a == '&') && (b == '#'))
47 #define isHTMLSPECIAL(a) ((a == '&') || (a == '\"') || (a == '\'') || (a == '<') || (a == '>'))
51 // -----------------------------------
52 const char *LogBuffer::logTypes[]=
61 // -----------------------------------
62 // base64 encode/decode taken from ices2 source..
63 static char base64table[64] = {
64 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
65 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
66 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
67 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
70 // -----------------------------------
71 static char *util_base64_encode(char *data)
73 int len = strlen(data);
74 char *out = malloc(len*4/3 + 4);
79 chunk = (len >3)?3:len;
80 *out++ = base64table[(*data & 0xFC)>>2];
81 *out++ = base64table[((*data & 0x03)<<4) | ((*(data+1) & 0xF0) >> 4)];
84 *out++ = base64table[((*(data+1) & 0x0F)<<2) | ((*(data+2) & 0xC0)>>6)];
85 *out++ = base64table[(*(data+2)) & 0x3F];
88 *out++ = base64table[((*(data+1) & 0x0F)<<2)];
104 // -----------------------------------
105 static int base64chartoval(char input)
107 if(input >= 'A' && input <= 'Z')
109 else if(input >= 'a' && input <= 'z')
110 return input - 'a' + 26;
111 else if(input >= '0' && input <= '9')
112 return input - '0' + 52;
113 else if(input == '+')
115 else if(input == '/')
117 else if(input == '=')
123 // -----------------------------------
124 static char *util_base64_decode(char *input)
133 // ------------------------------------------
137 logBuf = new LogBuffer(1000,100);
141 // ------------------------------------------
142 void Sys::sleepIdle()
144 sleep(idleSleepTime);
147 // ------------------------------------------
148 bool Host::isLocalhost()
150 return loopbackIP() || (ip == ClientSocket::getIP(NULL));
152 // ------------------------------------------
153 void Host::fromStrName(const char *str, int p)
163 strncpy(name,str,sizeof(name)-1);
166 char *pp = strstr(name,":");
173 ip = ClientSocket::getIP(name);
175 // ------------------------------------------
176 void Host::fromStrIP(const char *str, int p)
184 if (sscanf(str,"%03d.%03d.%03d.%03d:%d",&ipb[0],&ipb[1],&ipb[2],&ipb[3],&ipp) == 5)
186 ip = ((ipb[0]&0xff) << 24) | ((ipb[1]&0xff) << 16) | ((ipb[2]&0xff) << 8) | ((ipb[3]&0xff));
195 if (sscanf(str,"%03d.%03d.%03d.%03d",&ipb[0],&ipb[1],&ipb[2],&ipb[3]) == 4)
196 ip = ((ipb[0]&0xff) << 24) | ((ipb[1]&0xff) << 16) | ((ipb[2]&0xff) << 8) | ((ipb[3]&0xff));
201 // -----------------------------------
202 bool Host::isMemberOf(Host &h)
207 if( h.ip0() != 255 && ip0() != h.ip0() )
209 if( h.ip1() != 255 && ip1() != h.ip1() )
211 if( h.ip2() != 255 && ip2() != h.ip2() )
213 if( h.ip3() != 255 && ip3() != h.ip3() )
216 /* removed for endieness compatibility
217 for(int i=0; i<4; i++)
218 if (h.ipByte[i] != 255)
219 if (ipByte[i] != h.ipByte[i])
225 // -----------------------------------
226 char *trimstr(char *s1)
230 if ((*s1 == ' ') || (*s1 == '\t'))
240 /* s1 = s1+strlen(s1);
243 if ((*s1 != ' ') && (*s1 != '\t'))
251 if ((*s1 != ' ') && (*s1 != '\t'))
259 // -----------------------------------
260 char *stristr(const char *s1, const char *s2)
264 if (TOUPPER(*s1) == TOUPPER(*s2))
271 if (TOUPPER(*c1) != TOUPPER(*c2))
284 // -----------------------------------
285 bool String::isValidURL()
287 return (strnicmp(data,"http://",7)==0) || (strnicmp(data,"mailto:",7)==0);
290 // -----------------------------------
291 void String::setFromTime(unsigned int t)
293 // char *p = ctime((time_t*)&t);
295 char *p = ctime(&tmp);
302 // -----------------------------------
303 void String::setFromStopwatch(unsigned int t)
305 unsigned int sec,min,hour,day;
313 sprintf(data,"%d day, %d hour",day,hour);
315 sprintf(data,"%d hour, %d min",hour,min);
317 sprintf(data,"%d min, %d sec",min,sec);
319 sprintf(data,"%d sec",sec);
325 // -----------------------------------
326 void String::setFromString(const char *str, TYPE t)
340 }else if (*str == ' ')
353 data[cnt++] = *str++;
354 if (cnt >= (MAX_LEN-1))
363 // -----------------------------------
364 int String::base64WordToChars(char *out,const char *input)
369 vals[0] = base64chartoval(*input++);
370 vals[1] = base64chartoval(*input++);
371 vals[2] = base64chartoval(*input++);
372 vals[3] = base64chartoval(*input++);
374 if(vals[0] < 0 || vals[1] < 0 || vals[2] < -1 || vals[3] < -1)
377 *out++ = vals[0]<<2 | vals[1]>>4;
379 *out++ = ((vals[1]&0x0F)<<4) | (vals[2]>>2);
384 *out++ = ((vals[2]&0x03)<<6) | (vals[3]);
391 // -----------------------------------
392 void String::BASE642ASCII(const char *input)
395 int len = strlen(input);
399 out += base64WordToChars(out,input);
408 // -----------------------------------
409 void String::UNKNOWN2UNICODE(const char *in,bool safe)
411 MemoryStream utf8(data,MAX_LEN-1);
420 if (isUTF8(c,d)) // utf8 encoded
434 for(i=0; i<numChars-1; i++)
435 utf8.writeChar(*in++);
438 else if(isSJIS(c,d)) // shift_jis
440 utf8.writeUTF8(JISConverter::sjisToUnicode((c<<8 | d)));
444 else if(isEUC(c) && isEUC(d)) // euc-jp
446 utf8.writeUTF8(JISConverter::eucToUnicode((c<<8 | d)));
450 else if (isESCAPE(c,d)) // html escape tags &#xx;
464 utf8.writeUTF8(strtoul(code,NULL,10));
467 else if (isPLAINASCII(c)) // plain ascii : a-z 0-9 etc..
472 else if (isHTMLSPECIAL(c) && safe)
474 const char *str = NULL;
475 if (c == '&') str = "&";
476 else if (c == '\"') str = """;
477 else if (c == '\'') str = "'";
478 else if (c == '<') str = "<";
479 else if (c == '>') str = ">";
482 utf8.writeString(str);
489 if (utf8.pos >= (MAX_LEN-10))
495 utf8.writeChar(0); // null terminate
499 // -----------------------------------
500 void String::ASCII2HTML(const char *in)
503 char *oe = data+MAX_LEN-10;
509 if (((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')))
514 sprintf(op,"&#x%02X;",(int)c);
522 // -----------------------------------
523 void String::ASCII2ESC(const char *in, bool safe)
526 char *oe = data+MAX_LEN-10;
531 if (((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')))
539 sprintf(op,"%02X",(int)c);
547 // -----------------------------------
548 void String::HTML2ASCII(const char *in)
552 char *oe = data+MAX_LEN-10;
556 if ((c == '&') && (p[0] == '#'))
561 char ec = *p++; // hex/dec
570 c = (unsigned char)strtoul(code,NULL,ec=='x'?16:10);
579 // -----------------------------------
580 void String::HTML2UNICODE(const char *in)
582 MemoryStream utf8(data,MAX_LEN-1);
587 if ((c == '&') && (*in == '#'))
592 char ec = *in++; // hex/dec
601 utf8.writeUTF8(strtoul(code,NULL,ec=='x'?16:10));
605 if (utf8.pos >= (MAX_LEN-10))
612 // -----------------------------------
613 void String::ESC2ASCII(const char *in)
617 char *oe = data+MAX_LEN-10;
628 char hi = TOUPPER(p[0]);
629 char lo = TOUPPER(p[1]);
630 c = (TONIBBLE(hi)<<4) | TONIBBLE(lo);
640 // -----------------------------------
641 void String::ASCII2META(const char *in, bool safe)
644 char *oe = data+MAX_LEN-10;
667 // -----------------------------------
668 void String::ASCII2SJIS(const char *in) //JP-EX
672 if (utf8_decode(in,&p)<0)
681 // -----------------------------------
682 void String::convertTo(TYPE t)
695 tmp.HTML2ASCII(data);
705 tmp.BASE642ASCII(data);
709 // convert to new format
714 strcpy(data,tmp.data);
717 UNKNOWN2UNICODE(tmp.data,false);
720 UNKNOWN2UNICODE(tmp.data,true);
723 ASCII2HTML(tmp.data);
726 ASCII2ESC(tmp.data,false);
729 ASCII2ESC(tmp.data,true);
732 ASCII2META(tmp.data,false);
735 ASCII2META(tmp.data,true);
739 ASCII2SJIS(tmp.data);
747 // -----------------------------------
748 void LogBuffer::write(const char *str, TYPE t)
752 size_t len = strlen(str);
757 if (rlen > (lineLen-1))
760 int i = currLine % maxLines;
762 strncpy(&buf[bp],str,rlen);
766 times[i] = sys->getTime();
783 // -----------------------------------
784 char *getCGIarg(const char *str, const char *arg)
789 // char *s = strstr(str,arg);
790 char *s = (char*)strstr(str,arg);
800 // -----------------------------------
801 bool cmpCGIarg(char *str, char *arg, char *value)
803 if ((!str) || (!strlen(value)))
806 if (strnicmp(str,arg,strlen(arg)) == 0)
811 return strncmp(str,value,strlen(value))==0;
815 // -----------------------------------
816 bool hasCGIarg(char *str, char *arg)
821 char *s = strstr(str,arg);
830 // ---------------------------
831 void GnuID::encode(Host *h, const char *salt1, const char *salt2, unsigned char salt3)
834 for(int i=0; i<16; i++)
836 unsigned char ipb = id[i];
838 // encode with IP address
840 ipb ^= ((unsigned char *)&h->ip)[i&3];
867 // ---------------------------
868 void GnuID::toStr(char *str)
872 for(int i=0; i<16; i++)
875 unsigned char ipb = id[i];
877 sprintf(tmp,"%02X",ipb);
882 // ---------------------------
883 void GnuID::fromStr(const char *str)
887 if (strlen(str) < 32)
894 for(int i=0; i<16; i++)
898 id[i] = (unsigned char)strtoul(buf,NULL,16);
903 // ---------------------------
904 void GnuID::generate(unsigned char flags)
908 for(int i=0; i<16; i++)
914 // ---------------------------
915 unsigned char GnuID::getFlags()
920 // ---------------------------
921 GnuIDList::GnuIDList(int max)
925 for(int i=0; i<maxID; i++)
928 // ---------------------------
929 GnuIDList::~GnuIDList()
933 // ---------------------------
934 bool GnuIDList::contains(GnuID &id)
936 for(int i=0; i<maxID; i++)
937 if (ids[i].isSame(id))
941 // ---------------------------
942 int GnuIDList::numUsed()
945 for(int i=0; i<maxID; i++)
946 if (ids[i].storeTime)
950 // ---------------------------
951 unsigned int GnuIDList::getOldest()
953 unsigned int t=(unsigned int)-1;
954 for(int i=0; i<maxID; i++)
955 if (ids[i].storeTime)
956 if (ids[i].storeTime < t)
957 t = ids[i].storeTime;
960 // ---------------------------
961 void GnuIDList::add(GnuID &id)
963 unsigned int minTime = (unsigned int) -1;
966 // find same or oldest
967 for(int i=0; i<maxID; i++)
969 if (ids[i].isSame(id))
971 ids[i].storeTime = sys->getTime();
974 if (ids[i].storeTime <= minTime)
976 minTime = ids[i].storeTime;
982 ids[minIndex].storeTime = sys->getTime();
984 // ---------------------------
985 void GnuIDList::clear()
987 for(int i=0; i<maxID; i++)
991 // ---------------------------
992 void LogBuffer::dumpHTML(Stream &out)
994 WLockBlock lb(&lock);
997 unsigned int nl = currLine;
1002 sp = (currLine+1)%maxLines;
1008 for(unsigned int i=0; i<nl; i++)
1010 unsigned int bp = sp*lineLen;
1014 tim.setFromTime(times[sp]);
1016 out.writeString(tim.cstr());
1017 out.writeString(" <b>[");
1018 out.writeString(getTypeStr(types[sp]));
1019 out.writeString("]</b> ");
1022 str.convertTo(String::T_HTML);
1024 out.writeString(str.cstr());
1025 out.writeString("<br>");
1036 // ---------------------------
1037 void ThreadInfo::shutdown()
1040 //sys->waitThread(this);