OSDN Git Service

VP27マージ
[peercast-im/PeerCastIM.git] / PeerCast.root / PeerCast / core / common / sys.cpp
1 // ------------------------------------------------
2 // File : sys.cpp
3 // Date: 4-apr-2002
4 // Author: giles
5 // Desc: 
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 ????
9 //
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.
16
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 // ------------------------------------------------
22
23 #include "common.h"
24 #include "sys.h"
25 #include "socket.h"
26 #include "gnutella.h"
27 #include "servmgr.h" //JP-EX
28 #ifdef WIN32
29 #include "utf8.h" //JP-Patch
30 #endif
31 #include <stdlib.h>
32 #include <time.h>
33 #include "jis.h"
34 #ifdef _DEBUG
35 #include "chkMemoryLeak.h"
36 #define DEBUG_NEW new(__FILE__, __LINE__)
37 #define new DEBUG_NEW
38 #endif
39
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 == '>'))
48
49
50
51 // -----------------------------------
52 const char *LogBuffer::logTypes[]=
53 {
54         "",
55         "DBUG",
56         "EROR",
57         "GNET",
58         "CHAN",
59 };
60
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','+','/'
68 };
69 #if 0
70 // -----------------------------------
71 static char *util_base64_encode(char *data)
72 {
73     int len = strlen(data);
74     char *out = malloc(len*4/3 + 4);
75     char *result = out;
76     int chunk;
77
78     while(len > 0) {
79         chunk = (len >3)?3:len;
80         *out++ = base64table[(*data & 0xFC)>>2];
81         *out++ = base64table[((*data & 0x03)<<4) | ((*(data+1) & 0xF0) >> 4)];
82         switch(chunk) {
83             case 3:
84                 *out++ = base64table[((*(data+1) & 0x0F)<<2) | ((*(data+2) & 0xC0)>>6)];
85                 *out++ = base64table[(*(data+2)) & 0x3F];
86                 break;
87             case 2:
88                 *out++ = base64table[((*(data+1) & 0x0F)<<2)];
89                 *out++ = '=';
90                 break;
91             case 1:
92                 *out++ = '=';
93                 *out++ = '=';
94                 break;
95         }
96         data += chunk;
97         len -= chunk;
98     }
99
100     return result;
101 }
102 #endif
103
104 // -----------------------------------
105 static int base64chartoval(char input)
106 {
107     if(input >= 'A' && input <= 'Z')
108         return input - 'A';
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 == '+')
114         return 62;
115     else if(input == '/')
116         return 63;
117     else if(input == '=')
118         return -1;
119     else
120         return -2;
121 }
122
123 // -----------------------------------
124 static char *util_base64_decode(char *input)
125 {
126         return NULL;
127 }
128
129
130
131
132
133 // ------------------------------------------
134 Sys::Sys()
135 {
136         idleSleepTime = 10;
137         logBuf = new LogBuffer(1000,100);
138         numThreads=0;
139 }
140
141 // ------------------------------------------
142 void Sys::sleepIdle()
143 {
144         sleep(idleSleepTime);
145 }
146
147 // ------------------------------------------
148 bool Host::isLocalhost()
149 {
150         return loopbackIP() || (ip == ClientSocket::getIP(NULL)); 
151 }
152 // ------------------------------------------
153 void Host::fromStrName(const char *str, int p)
154 {
155         if (!strlen(str))
156         {
157                 port = 0;
158                 ip = 0;
159                 return;
160         }
161
162         char name[128];
163         strncpy(name,str,sizeof(name)-1);
164         name[127] = '\0';
165         port = p;
166         char *pp = strstr(name,":");
167         if (pp)
168         {
169                 port = atoi(pp+1);
170                 pp[0] = 0;
171         }
172
173         ip = ClientSocket::getIP(name);
174 }
175 // ------------------------------------------
176 void Host::fromStrIP(const char *str, int p)
177 {
178         unsigned int ipb[4];
179         unsigned int ipp;
180
181
182         if (strstr(str,":"))
183         {
184                 if (sscanf(str,"%03d.%03d.%03d.%03d:%d",&ipb[0],&ipb[1],&ipb[2],&ipb[3],&ipp) == 5)
185                 {
186                         ip = ((ipb[0]&0xff) << 24) | ((ipb[1]&0xff) << 16) | ((ipb[2]&0xff) << 8) | ((ipb[3]&0xff));
187                         port = ipp;
188                 }else
189                 {
190                         ip = 0;
191                         port = 0;
192                 }
193         }else{
194                 port = p;
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));
197                 else
198                         ip = 0;
199         }
200 }
201 // -----------------------------------
202 bool Host::isMemberOf(Host &h)
203 {
204         if (h.ip==0)
205                 return false;
206
207     if( h.ip0() != 255 && ip0() != h.ip0() )
208         return false;
209     if( h.ip1() != 255 && ip1() != h.ip1() )
210         return false;
211     if( h.ip2() != 255 && ip2() != h.ip2() )
212         return false;
213     if( h.ip3() != 255 && ip3() != h.ip3() )
214         return false;
215
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])
220                                 return false;
221 */
222         return true;
223 }
224
225 // -----------------------------------
226 char *trimstr(char *s1)
227 {
228         while (*s1)
229         {
230                 if ((*s1 == ' ') || (*s1 == '\t'))
231                         s1++;
232                 else
233                         break;
234
235         }
236
237         char *s = s1;
238
239         if(strlen(s1) > 0) {
240 /*      s1 = s1+strlen(s1);
241
242         while (*--s1)
243                 if ((*s1 != ' ') && (*s1 != '\t'))
244                         break;*/
245
246                 s1 = s1+strlen(s1);
247
248 //      s1[1] = 0;
249
250                 while (*--s1)
251                         if ((*s1 != ' ') && (*s1 != '\t'))
252                                 break;
253  
254                 s1[1] = 0;
255         }
256         return s;
257 }
258
259 // -----------------------------------
260 char *stristr(const char *s1, const char *s2)
261 {
262         while (*s1)
263         {
264                 if (TOUPPER(*s1) == TOUPPER(*s2))
265                 {
266                         const char *c1 = s1;
267                         const char *c2 = s2;
268
269                         while (*c1 && *c2)
270                         {
271                                 if (TOUPPER(*c1) != TOUPPER(*c2))
272                                         break;
273                                 c1++;
274                                 c2++;
275                         }
276                         if (*c2==0)
277                                 return (char *)s1;
278                 }
279
280                 s1++;
281         }
282         return NULL;
283 }
284 // -----------------------------------
285 bool String::isValidURL()
286 {
287         return (strnicmp(data,"http://",7)==0) || (strnicmp(data,"mailto:",7)==0);
288 }
289
290 // -----------------------------------
291 void String::setFromTime(unsigned int t)
292 {
293 //      char *p = ctime((time_t*)&t);
294         time_t tmp = t;
295         char *p = ctime(&tmp);
296         if (p)
297                 strcpy(data,p);
298         else
299                 strcpy(data,"-");
300         type = T_ASCII;
301 }
302 // -----------------------------------
303 void String::setFromStopwatch(unsigned int t)
304 {
305         unsigned int sec,min,hour,day;
306
307         sec = t%60;
308         min = (t/60)%60;
309         hour = (t/3600)%24;
310         day = (t/86400);
311
312         if (day)
313                 sprintf(data,"%d day, %d hour",day,hour);
314         else if (hour)
315                 sprintf(data,"%d hour, %d min",hour,min);
316         else if (min)
317                 sprintf(data,"%d min, %d sec",min,sec);
318         else if (sec)
319                 sprintf(data,"%d sec",sec);
320         else
321                 sprintf(data,"-");
322
323         type = T_ASCII;
324 }
325 // -----------------------------------
326 void String::setFromString(const char *str, TYPE t)
327 {
328         int cnt=0;
329         bool quote=false;
330         while (*str)
331         {
332                 bool add=true;
333                 if (*str == '\"')
334                 {
335                         if (quote) 
336                                 break;
337                         else 
338                                 quote = true;
339                         add = false;
340                 }else if (*str == ' ')
341                 {
342                         if (!quote)
343                         {
344                                 if (cnt)
345                                         break;
346                                 else
347                                         add = false;
348                         }
349                 }
350
351                 if (add)
352                 {
353                         data[cnt++] = *str++;
354                         if (cnt >= (MAX_LEN-1))
355                                 break;
356                 }else
357                         str++;
358         }
359         data[cnt] = 0;
360         type = t;
361 }
362
363 // -----------------------------------
364 int String::base64WordToChars(char *out,const char *input)
365 {
366         char *start = out;
367         signed char vals[4];
368
369     vals[0] = base64chartoval(*input++);
370     vals[1] = base64chartoval(*input++);
371     vals[2] = base64chartoval(*input++);
372     vals[3] = base64chartoval(*input++);
373
374     if(vals[0] < 0 || vals[1] < 0 || vals[2] < -1 || vals[3] < -1) 
375                 return 0;
376
377     *out++ = vals[0]<<2 | vals[1]>>4;
378     if(vals[2] >= 0)
379         *out++ = ((vals[1]&0x0F)<<4) | (vals[2]>>2);
380     else
381         *out++ = 0;
382
383     if(vals[3] >= 0)
384         *out++ = ((vals[2]&0x03)<<6) | (vals[3]);
385     else
386         *out++ = 0;
387
388         return out-start;
389 }
390
391 // -----------------------------------
392 void String::BASE642ASCII(const char *input)
393 {
394         char *out = data;
395     int len = strlen(input);
396
397     while(len >= 4) 
398         {
399                 out += base64WordToChars(out,input);
400                 input += 4;
401         len -= 4;
402     }
403     *out = 0;
404 }
405
406
407
408 // -----------------------------------
409 void String::UNKNOWN2UNICODE(const char *in,bool safe)
410 {
411         MemoryStream utf8(data,MAX_LEN-1);
412
413         unsigned char c;
414         unsigned char d;
415
416         while (c = *in++)
417         {
418                 d = *in;
419
420                 if (isUTF8(c,d))                // utf8 encoded 
421                 {
422                         int numChars=0;
423                         int i;
424
425                         for(i=0; i<6; i++)
426                         {
427                                 if (c & (0x80>>i))
428                                         numChars++;
429                                 else
430                                         break;
431                         }
432
433                         utf8.writeChar(c);
434                         for(i=0; i<numChars-1; i++)
435                                 utf8.writeChar(*in++);
436
437                 }
438                 else if(isSJIS(c,d))                    // shift_jis
439                 {
440                         utf8.writeUTF8(JISConverter::sjisToUnicode((c<<8 | d)));
441                         in++;
442
443                 }
444                 else if(isEUC(c) && isEUC(d))           // euc-jp
445                 {
446                         utf8.writeUTF8(JISConverter::eucToUnicode((c<<8 | d)));
447                         in++;
448
449                 }
450                 else if (isESCAPE(c,d))         // html escape tags &#xx;
451                 {
452                         in++;
453                         char code[16];
454                         char *cp = code;
455                         while (c=*in++) 
456                         {
457                                 if (c!=';')
458                                         *cp++ = c;
459                                 else
460                                         break;
461                         }
462                         *cp = 0;
463
464                         utf8.writeUTF8(strtoul(code,NULL,10));
465
466                 }
467                 else if (isPLAINASCII(c))       // plain ascii : a-z 0-9 etc..
468                 {
469                         utf8.writeUTF8(c);
470
471                 }
472                 else if (isHTMLSPECIAL(c) && safe)                      
473                 {
474                         const char *str = NULL;
475                         if (c == '&') str = "&amp;";
476                         else if (c == '\"') str = "&quot;";
477                         else if (c == '\'') str = "&#039;";
478                         else if (c == '<') str = "&lt;";
479                         else if (c == '>') str = "&gt;";
480                         else str = "?";
481
482                         utf8.writeString(str);
483                 }
484                 else
485                 {
486                         utf8.writeUTF8(c);
487                 }
488
489                 if (utf8.pos >= (MAX_LEN-10))
490                         break;
491
492
493         }
494
495         utf8.writeChar(0);      // null terminate
496
497 }
498
499 // -----------------------------------
500 void String::ASCII2HTML(const char *in)
501 {
502         char *op = data;
503         char *oe = data+MAX_LEN-10;
504         unsigned char c;
505         const char *p = in;
506         while (c = *p++)
507         {
508                 
509                 if (((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')))
510                 {
511                         *op++ = c;
512                 }else
513                 {
514                         sprintf(op,"&#x%02X;",(int)c);
515                         op+=6;
516                 }
517                 if (op >= oe)
518                         break;
519         }
520         *op = 0;
521 }
522 // -----------------------------------
523 void String::ASCII2ESC(const char *in, bool safe)
524 {
525         char *op = data;
526         char *oe = data+MAX_LEN-10;
527         const char *p = in;
528         unsigned char c;
529         while (c = *p++)
530         {
531                 if (((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')))
532                         *op++ = c;
533                 else
534                 {
535                         *op++ = '%';
536                         if (safe)
537                                 *op++ = '%';
538                         *op=0;
539                         sprintf(op,"%02X",(int)c);
540                         op+=2;
541                 }
542                 if (op >= oe)
543                         break;
544         }
545         *op=0;
546 }
547 // -----------------------------------
548 void String::HTML2ASCII(const char *in)
549 {
550         unsigned char c;
551         char *o = data;
552         char *oe = data+MAX_LEN-10;
553         const char *p = in;
554         while (c = *p++)
555         {
556                 if ((c == '&') && (p[0] == '#'))
557                 {
558                         p++;
559                         char code[8];
560                         char *cp = code;
561                         char ec = *p++;         // hex/dec
562                         while (c=*p++) 
563                         {
564                                 if (c!=';')
565                                         *cp++ = c;
566                                 else
567                                         break;
568                         }
569                         *cp = 0;
570                         c = (unsigned char)strtoul(code,NULL,ec=='x'?16:10);
571                 }
572                 *o++ = c;
573                 if (o >= oe)
574                         break;
575         }
576
577         *o=0;
578 }
579 // -----------------------------------
580 void String::HTML2UNICODE(const char *in)
581 {
582         MemoryStream utf8(data,MAX_LEN-1);
583
584         unsigned char c;
585         while (c = *in++)
586         {
587                 if ((c == '&') && (*in == '#'))
588                 {
589                         in++;
590                         char code[16];
591                         char *cp = code;
592                         char ec = *in++;                // hex/dec
593                         while (c=*in++) 
594                         {
595                                 if (c!=';')
596                                         *cp++ = c;
597                                 else
598                                         break;
599                         }
600                         *cp = 0;
601                         utf8.writeUTF8(strtoul(code,NULL,ec=='x'?16:10));
602                 }else
603                         utf8.writeUTF8(c);
604
605                 if (utf8.pos >= (MAX_LEN-10))
606                         break;
607         }
608
609         utf8.writeUTF8(0);
610 }
611
612 // -----------------------------------
613 void String::ESC2ASCII(const char *in)
614 {
615         unsigned char c;
616         char *o = data;
617         char *oe = data+MAX_LEN-10;
618         const char *p = in;
619         while (c = *p++)
620         {
621                 if (c == '+')
622                         c = ' ';
623                 else if (c == '%')
624                 {
625                         if (p[0] == '%')
626                                 p++;
627
628                         char hi = TOUPPER(p[0]);
629                         char lo = TOUPPER(p[1]);
630                         c = (TONIBBLE(hi)<<4) | TONIBBLE(lo);
631                         p+=2;
632                 }
633                 *o++ = c;
634                 if (o >= oe)
635                         break;
636         }
637
638         *o=0;
639 }
640 // -----------------------------------
641 void String::ASCII2META(const char *in, bool safe)
642 {
643         char *op = data;
644         char *oe = data+MAX_LEN-10;
645         const char *p = in;
646         unsigned char c;
647         while (c = *p++)
648         {
649                 switch (c)
650                 {
651                         case '%':
652                                 if (safe)
653                                         *op++='%';
654                                 break;
655                         case ';':
656                                 c = ':';
657                                 break;
658                 }
659
660                 *op++=c;
661                 if (op >= oe)
662                         break;
663         }
664         *op=0;
665 }
666 #ifdef WIN32
667 // -----------------------------------
668 void String::ASCII2SJIS(const char *in) //JP-EX
669 {
670         char *op = data;
671         char *p;
672         if (utf8_decode(in,&p)<0)
673         {
674                 strcpy(op,in);
675                 return;
676         }
677         strcpy(op,p);
678         free(p);
679 }
680 #endif
681 // -----------------------------------
682 void String::convertTo(TYPE t)
683 {
684         if (t != type)
685         {
686                 String tmp = *this;
687
688                 // convert to ASCII
689                 switch (type)
690                 {
691                         case T_UNKNOWN:
692                         case T_ASCII:
693                                 break;
694                         case T_HTML:
695                                 tmp.HTML2ASCII(data);
696                                 break;
697                         case T_ESC:
698                         case T_ESCSAFE:
699                                 tmp.ESC2ASCII(data);
700                                 break;
701                         case T_META:
702                         case T_METASAFE:
703                                 break;
704                         case T_BASE64:
705                                 tmp.BASE642ASCII(data);
706                                 break;
707                 }
708
709                 // convert to new format
710                 switch (t)
711                 {
712                         case T_UNKNOWN:
713                         case T_ASCII:
714                                 strcpy(data,tmp.data);
715                                 break;
716                         case T_UNICODE:
717                                 UNKNOWN2UNICODE(tmp.data,false);
718                                 break;
719                         case T_UNICODESAFE:
720                                 UNKNOWN2UNICODE(tmp.data,true);
721                                 break;
722                         case T_HTML:
723                                 ASCII2HTML(tmp.data);
724                                 break;
725                         case T_ESC:
726                                 ASCII2ESC(tmp.data,false);
727                                 break;
728                         case T_ESCSAFE:
729                                 ASCII2ESC(tmp.data,true);
730                                 break;
731                         case T_META:
732                                 ASCII2META(tmp.data,false);
733                                 break;
734                         case T_METASAFE:
735                                 ASCII2META(tmp.data,true);
736                                 break;
737 #ifdef WIN32
738                         case T_SJIS: //JP-EX
739                                 ASCII2SJIS(tmp.data);
740                                 break;
741 #endif
742                 }
743
744                 type = t;
745         }
746 }
747 // -----------------------------------
748 void LogBuffer::write(const char *str, TYPE t)
749 {
750         lock.on();
751
752         size_t len = strlen(str);
753         int cnt=0;
754         while (len)
755         {
756                 size_t rlen = len;
757                 if (rlen > (lineLen-1))
758                         rlen = lineLen-1;
759
760                 int i = currLine % maxLines;
761                 int bp = i*lineLen;
762                 strncpy(&buf[bp],str,rlen);
763                 buf[bp+rlen] = 0;
764                 if (cnt==0)
765                 {
766                         times[i] = sys->getTime();
767                         types[i] = t;
768                 }else
769                 {
770                         times[i] = 0;
771                         types[i] = T_NONE;
772                 }
773                 currLine++;
774
775                 str += rlen;
776                 len -= rlen;
777                 cnt++;
778         }
779
780         lock.off();
781 }
782
783 // -----------------------------------
784 char *getCGIarg(const char *str, const char *arg)
785 {
786         if (!str)
787                 return NULL;
788
789 //      char *s = strstr(str,arg);
790         char *s = (char*)strstr(str,arg);
791
792         if (!s)
793                 return NULL;
794
795         s += strlen(arg);
796
797         return s;
798 }
799
800 // -----------------------------------
801 bool cmpCGIarg(char *str, char *arg, char *value)
802 {
803         if ((!str) || (!strlen(value)))
804                 return false;
805
806         if (strnicmp(str,arg,strlen(arg)) == 0)
807         {
808
809                 str += strlen(arg);
810
811                 return strncmp(str,value,strlen(value))==0;
812         }else
813                 return false;
814 }
815 // -----------------------------------
816 bool hasCGIarg(char *str, char *arg)
817 {
818         if (!str)
819                 return false;
820
821         char *s = strstr(str,arg);
822
823         if (!s)
824                 return false;
825
826         return true;
827 }
828
829
830 // ---------------------------
831 void GnuID::encode(Host *h, const char *salt1, const char *salt2, unsigned char salt3)
832 {
833         int s1=0,s2=0;
834         for(int i=0; i<16; i++)
835         {
836                 unsigned char ipb = id[i];
837
838                 // encode with IP address 
839                 if (h)
840                         ipb ^= ((unsigned char *)&h->ip)[i&3];
841
842                 // add a bit of salt 
843                 if (salt1)
844                 {
845                         if (salt1[s1])
846                                 ipb ^= salt1[s1++];
847                         else
848                                 s1=0;
849                 }
850
851                 // and some more
852                 if (salt2)
853                 {
854                         if (salt2[s2])
855                                 ipb ^= salt2[s2++];
856                         else
857                                 s2=0;
858                 }
859
860                 // plus some pepper
861                 ipb ^= salt3;
862
863                 id[i] = ipb;
864         }
865
866 }
867 // ---------------------------
868 void GnuID::toStr(char *str)
869 {
870
871         str[0] = 0;
872         for(int i=0; i<16; i++)
873         {
874                 char tmp[8];
875                 unsigned char ipb = id[i];
876
877                 sprintf(tmp,"%02X",ipb);
878                 strcat(str,tmp);
879         }
880
881 }
882 // ---------------------------
883 void GnuID::fromStr(const char *str)
884 {
885         clear();
886
887         if (strlen(str) < 32)
888                 return;
889
890         char buf[8];
891
892         buf[2] = 0;
893
894         for(int i=0; i<16; i++)
895         {
896                 buf[0] = str[i*2];
897                 buf[1] = str[i*2+1];
898                 id[i] = (unsigned char)strtoul(buf,NULL,16);
899         }
900
901 }
902
903 // ---------------------------
904 void GnuID::generate(unsigned char flags)
905 {
906         clear();
907
908         for(int i=0; i<16; i++)
909                 id[i] = sys->rnd();
910
911         id[0] = flags;
912 }
913
914 // ---------------------------
915 unsigned char GnuID::getFlags()
916 {
917         return id[0];
918 }
919
920 // ---------------------------
921 GnuIDList::GnuIDList(int max)
922 :ids(new GnuID[max])
923 {
924         maxID = max;
925         for(int i=0; i<maxID; i++)
926                 ids[i].clear();
927 }
928 // ---------------------------
929 GnuIDList::~GnuIDList()
930 {
931         delete [] ids;
932 }
933 // ---------------------------
934 bool GnuIDList::contains(GnuID &id)
935 {
936         for(int i=0; i<maxID; i++)
937                 if (ids[i].isSame(id))
938                         return true;
939         return false;
940 }
941 // ---------------------------
942 int GnuIDList::numUsed()
943 {
944         int cnt=0;
945         for(int i=0; i<maxID; i++)
946                 if (ids[i].storeTime)
947                         cnt++;
948         return cnt;
949 }
950 // ---------------------------
951 unsigned int GnuIDList::getOldest()
952 {
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;
958         return t;
959 }
960 // ---------------------------
961 void GnuIDList::add(GnuID &id)
962 {
963         unsigned int minTime = (unsigned int) -1;
964         int minIndex = 0;
965
966         // find same or oldest
967         for(int i=0; i<maxID; i++)
968         {
969                 if (ids[i].isSame(id))
970                 {
971                         ids[i].storeTime = sys->getTime();
972                         return;
973                 }
974                 if (ids[i].storeTime <= minTime)
975                 {
976                         minTime = ids[i].storeTime;
977                         minIndex = i;
978                 }
979         }
980
981         ids[minIndex] = id;
982         ids[minIndex].storeTime = sys->getTime();
983 }
984 // ---------------------------
985 void GnuIDList::clear()
986 {
987         for(int i=0; i<maxID; i++)
988                 ids[i].clear();
989 }
990         
991 // ---------------------------
992 void LogBuffer::dumpHTML(Stream &out)
993 {
994         WLockBlock lb(&lock);
995         lb.on();
996
997         unsigned int nl = currLine;
998         unsigned int sp = 0;
999         if (nl > maxLines)
1000         {
1001                 nl = maxLines-1;
1002                 sp = (currLine+1)%maxLines;
1003         }
1004
1005         String tim,str;
1006         if (nl)
1007         {
1008                 for(unsigned int i=0; i<nl; i++)
1009                 {
1010                         unsigned int bp = sp*lineLen;
1011
1012                         if (types[sp])
1013                         {
1014                                 tim.setFromTime(times[sp]);
1015
1016                                 out.writeString(tim.cstr());
1017                                 out.writeString(" <b>[");
1018                                 out.writeString(getTypeStr(types[sp]));
1019                                 out.writeString("]</b> ");
1020                         }
1021                         str.set(&buf[bp]);
1022                         str.convertTo(String::T_HTML);
1023
1024                         out.writeString(str.cstr());
1025                         out.writeString("<br>");
1026
1027                         sp++;
1028                         sp %= maxLines;
1029                 }
1030         }
1031
1032         lb.off();
1033
1034 }
1035
1036 // ---------------------------
1037 void    ThreadInfo::shutdown()
1038 {
1039         active = false;
1040         //sys->waitThread(this);
1041 }