Initial commit, version 2.6.3a
[tropbot.git] / tblib.cc
1 //-----------------------------------------------------------------------------
2
3 #include "tblib.h"
4
5 //-----------------------------------------------------------------------------
6
7 char *cut_nick_from_prefix(char *name)
8 {
9   char *s, *nick;
10   s = name;
11   while((*s != '!') && (*s != '\0')) s++;
12   nick = new char[s-name+1];
13   strncpy(nick, name, s-name);
14   *(nick+(s-name)) = '\0';
15   return nick;
16 };
17
18 //-----------------------------------------------------------------------------
19
20 int is_weird_login(char *login)
21 {
22   char *s;
23   s = login;
24   while((*s != '\0') && (*s != '!') &&
25         ((*s & 128) == 0) && (*s >= 32) && (*s != 127)) s++;
26   return (*s != '\0') || (*s == '!');
27 }
28
29 //-----------------------------------------------------------------------------
30
31 int is_pattern(char *s)
32 {
33   while((*s != '\0') && (*s != '!') && (*s != '*')) s++;
34   return (*s == '*') || (*s == '!');
35 }
36
37 //-----------------------------------------------------------------------------
38
39 char *clean_banid(char *banid)
40 {
41   char *result, *s, *t;
42   int joker_mode, min_car, k;
43
44   result = new char[strlen(banid)+1];
45
46   s = banid;
47   t = result;
48
49   joker_mode = 0;
50   while(*s != '\0')
51     {
52       if(*s == '*')
53         {
54           if(!joker_mode) min_car = 0;
55           joker_mode = 1;
56         }
57       else
58         {
59           if(*s == '?')
60             {
61               if(joker_mode) min_car++;
62               else *t++ = *s;
63             }
64           else
65             {
66               if(joker_mode)
67                 {
68                   *t++ = '*';
69                   for(k=0; k<min_car; k++) *t++ = '?';
70                   joker_mode = 0;
71                 }
72
73               if(((*s & 128) != 0) || (*s < 32) || (*s == 127)) *t++ = '?';
74               else *t++ = *s;
75             }
76         }
77       s++;
78     }
79
80   if(joker_mode)
81     {
82       *t++ = '*';
83       for(k=0; k<min_car; k++) *t++ = '?';
84     }
85   
86   *t++ = '\0';
87
88   return result;
89 }
90
91 //-----------------------------------------------------------------------------
92
93 char *next_word(char *buffer, char *r, int buffer_size)
94 {
95   char *s;
96   s = buffer;
97   if(r != NULL)
98     {
99       while((*r != '\0') && (*r != ' ') && (s<buffer+buffer_size-1))
100         *s++ = *r++;
101       while(*r == ' ') r++;
102       if(*r == '\0') r = NULL;
103     };
104   *s = '\0';
105   return r;
106 };
107
108 //-----------------------------------------------------------------------------
109
110 int is_hostname(char *host)
111 {
112   char *s;
113   s = host;
114   while((*s != '!') && (*s != '\0')) s++;
115   return *s == '\0';
116 };
117
118 int is_numeric(char *host)
119 {
120   int r;
121   char *c;
122
123   r = 1;
124   for(c = host; *c != '\0'; c++)
125     {
126       r &= (((*c >='0') && (*c <= '9')) || (*c == '.'));
127       r |= (*c == '@');
128     };
129
130   return r;
131 };
132
133 int are_same_site(char *u1, char *u2)
134 {
135   int n1, n2;
136   char *c1, *c2;
137
138   n1 = is_numeric(u1);
139   n2 = is_numeric(u2);
140
141   if(n1 && n2)
142     {
143       c1 = u1; c2 = u2;
144       while(*c1 != '\0') c1++; while((c1 > u1) && (*c1 != '.')) c1--;
145       while(*c2 != '\0') c2++; while((c2 > u2) && (*c2 != '.')) c2--;
146       if((c1-u1) == (c2-u2)) return strncmp(u1, u2, c1-u1) == 0;
147       else return 0;
148     };
149
150   if(!n1 && !n2)
151     {
152       while(*u1 != '.') u1++;
153       while(*u2 != '.') u2++;
154       return strcmp(u1, u2) == 0;
155     };
156
157   return 0;
158 };
159
160 // :CISMhp.Univ-Lyon1.FR 311 chose Johnkee gponcet@bi bi@192.93.80.208 * :Gael
161 // :sil.polytechnique.fr 311 chose Johnkee gponcet bi@192.93.80.208 * :Gael 
162
163 void concat_pattern_from_host(char *result, char *host)
164 {
165   int r;
166   if(is_numeric(host))
167     {
168       r = 0;
169       while((*host != '\0') && (r<3))
170         {
171           *result++ = *host++;
172           if(*host == '.') r++;
173         };
174       concat(result, ".*");
175     }
176   else
177     {
178       *result++ = '*';
179       while((*host != '.') && (*host != '\0')) host++;
180       concat(result, host);
181     };
182   *result++ = '\0';
183 };
184
185 char *pattern_from_prefix(char *prefix, int site_pattern)
186 {
187   char small_buffer[SMALL_BUFFER_SIZE];
188   int l;
189   char *c, *d, *pattern;
190
191   c = small_buffer;
192   d = prefix;
193   concat(c, "*!*");
194
195   // Skip the nickname
196   while((*d != '!') && (*d != '\0')) d++;
197
198   if(*d == '!')
199     if(site_pattern)
200       {
201         while((*d != '@') && (*d != '\0')) d++;
202       }
203     else
204       {
205         // Copy the login
206         d++;
207         if((*d == '~') || (*d == '+') ||
208            (*d == '-') || (*d=='^')) d++;
209         l = 0;
210         while((*d != '@') && (*d != '\0') &&
211               ((l<7) || *(d+1) == '\0')) { *c++ = *d++; l++; }
212         if((*d != '\0') && (*d != '@')) *c++ = '*';
213         while(*d != '@') d++;
214       };
215   *c++ = *d++;
216
217   concat_pattern_from_host(c, d);
218
219   pattern = new char[strlen(small_buffer)+1];
220   strcpy(pattern, small_buffer);
221
222   return pattern;
223 };
224
225 //-----------------------------------------------------------------------------
226
227 int Contains(char *string, char c)
228 {
229   while((*string != '\0') && (*string != c)) string++;
230   return *string == c;
231 };
232
233 int find_substring(char *&sub, char *&str)
234 {
235   char *s, *u;
236   u = sub;
237   s = str;
238
239   if(*u == '\0') while(*s != '\0') s++;
240   else
241     while((*u != '\0') && (*u != '*') && (*s != '\0') &&
242           ((*u == *s) || (*u == '?'))) { u++; s++; };
243
244   if((*u == '\0') || (*u == '*'))
245     {
246       sub = u;
247       str = s;
248       return 1;
249     }
250   else
251     {
252       str++;
253       return 0;
254     };
255 };
256
257 int match_pattern(char *pattern, char *string)
258 {
259   char *p, *s;
260   int ok;
261
262   if(pattern == NULL) return -1;
263   if(string == NULL) return 0;
264
265   p = pattern; s = string;
266
267   if(*p != '*') ok = find_substring(p, s);
268   else ok = 1;
269
270   while((*s != '\0') && (*p != '\0') && ok)
271     {
272       while(*p == '*') p++;
273       ok = 0;
274       while((*s != '\0') && !ok) ok = find_substring(p, s);
275     };
276
277   if((*p == '\0') && (*s != '\0') && ok)
278     {
279       while(*s != '\0') s++;
280       while((p>=pattern) && (s>=string) && ok && (*p != '*'))
281         {
282           ok = (*p == '?') || (*p == *s);
283           p--; s--;
284         }
285       return (*p == '*') || (p == pattern-1);
286     }
287   else return (*p == '\0') && (*s == '\0') && ok;
288 };
289
290 void uncap(char *string)
291 {
292   char *s;
293   if(string != NULL)
294     {
295       s = string;
296       for(s = string; *s != '\0'; s++)
297         if((*s >= 'A') && (*s <= 'Z')) *s -= 'A'-'a';
298     };
299 };
300
301 char *strdup(char *s)
302 {
303   char *t;
304   if(s == NULL) return NULL;
305   else
306     {
307       t = new char[strlen(s)+1];
308       strcpy(t, s);
309       return t;
310     };
311 };
312
313 int eq(char *s, char *t)
314 {
315   return strcmp(s, t) == 0;
316 };
317
318 //-----------------------------------------------------------------------------
319
320 char *seconds_to_string(int time)
321 {
322   char buffer[128];
323   char *t, *u, *result;
324   int d, h, m, s;
325   int before;
326
327   s = time%60;
328   m = (time/60)%60;
329   h = (time/3600)%24;
330   d = time/86400;
331
332   t = buffer;
333
334   before = 0;
335   if(s>0)
336     {
337       before = 1;
338       *t++ = 's';
339       *t++ = (s%10)+'0';
340       if(s/10>0) *t++ = (s/10)+'0';
341     };
342   
343   if(m>0)
344     {
345       if(before) *t++ = ' ';
346       else before = 1;
347       concat(t, "nim");
348       *t++ = (m%10)+'0';
349       if(m/10>0) *t++ = (m/10)+'0';
350     };
351
352   if(h>0)
353     {
354       if(before) *t++ = ' ';
355       else before = 1;
356       *t++ = 'h';
357       *t++ = (h%10)+'0';
358       if(h/10>0) *t++ = (h/10)+'0';
359     };
360   
361   if(d>0)
362     {
363       if(before) *t++ = ' ';
364       else before = 1;
365       *t++ = 'd';
366       while(d>0)
367         {
368           *t++ = (d%10)+'0';
369           d /= 10;
370         };
371     };
372   
373   result = new char[(t-buffer)+1];
374   u = result;
375
376   t--;
377   while(t>=buffer) *u++ = *t--;
378   *u = '\0';
379
380   return result;
381 };
382
383 int string_to_seconds(char *string)
384 {
385   int total;
386   int acc;
387   total = 0; acc = 0;
388   while(*string != '\0')
389     {
390       if((*string >= '0') && (*string <= '9')) acc = 10*acc + (*string - '0');
391       if(*string == 'd') { total = total+86400*acc; acc = 0; };
392       if(*string == 'h') { total = total+3600*acc; acc = 0; };
393       if(*string == 'm') { total = total+60*acc; acc = 0; }
394       if((*string == 's') || (*string == '\0')) { total = total+acc; acc = 0; }
395       string++;
396     };
397   return total;
398 };
399
400 //-----------------------------------------------------------------------------
401
402 int call_socket(char *hostname, unsigned short portnum)
403 {
404   struct sockaddr_in sa;
405   struct hostent     *hp;
406   int s;
407
408   if ((sa.sin_addr.s_addr = inet_addr(hostname)) == -1)
409     {
410       if ((hp = gethostbyname(hostname)) != NULL)
411         {
412           bzero((char *) &sa, sizeof(sa));
413           bcopy(hp->h_addr, (char *) &sa.sin_addr,
414                 hp->h_length);
415           sa.sin_family = hp->h_addrtype;
416         }
417       else
418         return (-2);
419     }
420   else sa.sin_family = AF_INET;
421
422   sa.sin_port = (unsigned short) htons(portnum);
423
424
425
426 /*
427   if(is_numeric(hostname))
428     {
429 //      if ((hp = gethostbyaddr(hostname)) == NULL)
430       cerr<<"*** Can't use numeric IP ***\n";
431       return -1;
432     }
433   else
434     {
435       if ((hp = gethostbyname(hostname)) == NULL)
436         return -1;
437     };
438
439   cout<<"HP->H_ADDR >";
440   for(int k=0; k<hp->h_length; k++) cout<<"["<<hp->h_addr[k]<<"]";
441   cout<<"<\n";
442
443   memset(&sa,0,sizeof(sa));
444   memcpy((char *)&sa.sin_addr,hp->h_addr,hp->h_length);
445   sa.sin_family= hp->h_addrtype;
446   sa.sin_port= htons((u_short)portnum);
447 */
448
449   if ((s= socket(AF_INET, SOCK_STREAM, 0)) < 0)   /* get socket */
450     return(-1);
451
452   if (connect(s, (struct sockaddr *) &sa, sizeof sa) < 0)      /* connect */
453     {
454       close(s);
455       return(-1);
456     }
457   return(s);
458 }
459
460 //-----------------------------------------------------------------------------
461
462 int establish(unsigned short portnum)
463 {
464   char   myname[MAXHOSTNAME+1];
465   int    s;
466   struct sockaddr_in sa;
467   struct hostent *hp;
468
469   memset(&sa, 0, sizeof(struct sockaddr_in)); /* clear our address */
470   gethostname(myname, MAXHOSTNAME);           /* who are we? */
471   hp= gethostbyname(myname);                  /* get our address info */
472   if (hp == NULL)                             /* we don't exist !? */
473     return(-1);
474   sa.sin_family= hp->h_addrtype;              /* this is our host address */
475   sa.sin_port= htons(portnum);                /* this is our port number */
476
477   if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) /* create socket */
478     return(-1);
479
480   if (bind(s,(struct sockaddr *)&sa,sizeof(struct sockaddr_in)) < 0)
481     {
482       close(s);
483       return(-1);                               /* bind address to socket */
484     }
485
486   listen(s, NB_QUEUE_CONNECTS);               /* max # of queued connects */
487   return(s);
488 }
489
490 //-----------------------------------------------------------------------------
491
492 int get_connection(int s)
493 {
494   int t;                  /* socket of connection */
495   if ((t = accept(s,NULL,NULL)) < 0)   /* accept connection if there is one */
496     return(-1);
497   return(t);
498 }
499
500 //-----------------------------------------------------------------------------
501
502 int slice_buffer(char *&src, char *endsrc,
503                  char *&prefix,
504                  char *&dest_cmd,
505                  char **slice_cmd, int &n_cmd,
506                  char *&dest_ctcp,
507                  char **slice_ctcp, int &n_ctcp)
508 {
509   int end;
510   int ctcp, queue;
511
512   char *s;
513
514   s = src;
515   while((*s != '\r') && (*s != '\n') && (s<endsrc)) s++;
516   
517   if(s<endsrc)
518     {
519       end = 0;
520
521       n_cmd = 0;
522       n_ctcp = 0;
523       ctcp = 0;
524       queue = 0;
525       
526       if(*src == ':')
527         {
528           src++;
529           prefix = dest_ctcp;
530           while((src<endsrc) && (*src != ' '))
531             {
532               *dest_ctcp = *src;
533               dest_ctcp++;
534               src++;
535             };
536           *dest_ctcp = '\0';
537           dest_ctcp++;
538         }
539       else prefix = NULL;
540       
541       while((src < endsrc) && !end)
542         {
543           if((*src == ' ') || (*src == '\r') || (*src == '\n')
544              || (*src == '\001'))
545             {
546               if(*src == '\001')
547                 {
548                   src++;
549                   slice_ctcp[n_ctcp++] = dest_ctcp;
550                   while((src<endsrc) && (*src != '\r') && (*src != '\001'))
551                     *dest_ctcp++ = *src++;
552                   *dest_ctcp = '\0';
553                   dest_ctcp++;
554                   if(src<endsrc)
555                     {
556                       end = (*src == '\r') || (*src == '\n');
557                       src++;
558                     }
559                   else end = 1;
560                 }
561               else
562                 {
563                   *dest_cmd = '\0';
564                   dest_cmd++;
565                   end = (*src == '\r') || (*src == '\n');
566                   src++;
567                 };
568             }
569           else
570             {
571               if(!ctcp) slice_cmd[n_cmd++] = dest_cmd;
572               if(*src == ':')
573                 {
574                   queue = 1;
575                   src++;
576                 };
577               ctcp = 0;
578               while((src<endsrc) &&
579                 ((*src != ' ') || queue) && (*src != '\r') && (*src != '\n') 
580                     && (*src != '\001'))
581                 *dest_cmd++ = *src++;
582               ctcp = (*src == '\001');
583             };
584         };
585       if(src < endsrc) if(*src == '\n') src++; // Loose the '\n'
586       return 0;
587     }
588   else return 1;
589 };
590
591 //-----------------------------------------------------------------------------
592
593 void ListChar::Print()
594 {
595   NodeList<char *> *node;
596   for(node = first; node != NULL; node = node->next)
597     cout<<node->body<<"\n";
598 };
599
600 void ListChar::Clear()
601 {
602   NodeList<char *> *node, *next;
603   node = first;
604   while(node != NULL)
605     {
606       next = node->next;
607       delete node->body;
608       delete node;
609       node = next;
610     };
611   first = NULL;
612 };
613
614 void ListChar::Add(char *s)
615 {
616   char *p;
617   p = strdup(s);
618   uncap(p);
619   Insert(p);
620 };
621
622 void ListChar::Remove(char *s)
623 {
624   NodeList<char *> *node, *pred, *next;
625
626   pred = NULL;
627   node = first;
628   while(node != NULL)
629     {
630       next = node->next;
631       if(strcmp(node->body, s) == 0)
632         {
633           if(pred == NULL) first = next;
634           else pred->next = next;
635           delete node->body;
636           delete node;
637         }
638       else pred = node;
639       node = next;
640     };
641 };
642
643 int ListChar::Matches(char *s)
644 {
645   NodeList<char *> *node;
646   int yep;
647   yep = 0;
648   for(node = first; (node != NULL) && !yep; node = node->next)
649     yep = match_pattern(node->body, s);
650   return yep;
651 };
652
653 int ListChar::IsMatchedBy(char *s)
654 {
655   NodeList<char *> *node;
656   int yep;
657   yep = 0;
658   for(node = first; (node != NULL) && !yep; node = node->next)
659     yep = match_pattern(s, node->body);
660   return yep;
661 };
662
663 int ListChar::Contains(char *s)
664 {
665   NodeList<char *> *node;
666   int yep;
667   yep = 0;
668   for(node = first; (node != NULL) && !yep; node = node->next)
669     yep = (strcmp(node->body, s) == 0);
670   return yep;
671 };
672