Update to version 2.9.2d
[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   if ((s= socket(AF_INET, SOCK_STREAM, 0)) < 0)   /* get socket */
425     return(-1);
426
427   if (connect(s, (struct sockaddr *) &sa, sizeof sa) < 0)      /* connect */
428     {
429       close(s);
430       return(-1);
431     }
432   return(s);
433 }
434
435 //-----------------------------------------------------------------------------
436
437 int establish(unsigned short portnum)
438 {
439   char   myname[MAXHOSTNAME+1];
440   int    s;
441   struct sockaddr_in sa;
442   struct hostent *hp;
443
444   memset(&sa, 0, sizeof(struct sockaddr_in)); /* clear our address */
445   gethostname(myname, MAXHOSTNAME);           /* who are we? */
446   hp= gethostbyname(myname);                  /* get our address info */
447   if (hp == NULL)                             /* we don't exist !? */
448     return(-1);
449   sa.sin_family= hp->h_addrtype;              /* this is our host address */
450   sa.sin_port= htons(portnum);                /* this is our port number */
451
452   if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) /* create socket */
453     return(-1);
454
455   if (bind(s,(struct sockaddr *) &sa,sizeof(struct sockaddr_in)) < 0)
456     {
457       close(s);
458       return(-1);                               /* bind address to socket */
459     }
460
461   listen(s, NB_QUEUE_CONNECTS);               /* max # of queued connects */
462   return(s);
463 }
464
465 //-----------------------------------------------------------------------------
466
467 int get_connection(int s)
468 {
469   int t;                  /* socket of connection */
470   if ((t = accept(s,NULL,NULL)) < 0)   /* accept connection if there is one */
471     return(-1);
472   return(t);
473 }
474
475 //-----------------------------------------------------------------------------
476
477 int slice_buffer(char *&src, char *endsrc,
478                  char *&prefix,
479                  char *&dest_cmd,
480                  char **slice_cmd, int &n_cmd,
481                  char *&dest_ctcp,
482                  char **slice_ctcp, int &n_ctcp)
483 {
484   int end;
485   int ctcp, queue;
486
487   char *s;
488
489   s = src; while((*s != '\r') && (*s != '\n') && (s<endsrc)) s++;
490   
491   if(s == endsrc) return 1;
492
493   end = 0;
494
495   n_cmd = 0;
496   n_ctcp = 0;
497   ctcp = 0;
498   queue = 0;
499       
500   if(*src == ':')
501     {
502       src++;
503       prefix = dest_ctcp;
504       while((src<endsrc) && (*src != ' ')) *dest_ctcp++ = *src++;
505       *dest_ctcp++ = '\0';
506     }
507   else prefix = NULL;
508       
509   while((src < endsrc) && !end)
510     {
511       if((*src == ' ') || (*src == '\r') || (*src == '\n') || (*src == '\001'))
512         {
513           if(*src == '\001')
514             {
515               src++;
516               slice_ctcp[n_ctcp++] = dest_ctcp;
517
518               while((src<endsrc) && (*src != '\r') &&
519                     (*src != '\n') && (*src != '\001')) *dest_ctcp++ = *src++;
520
521               *dest_ctcp++ = '\0';
522
523               if(src<endsrc)
524                 {
525                   end = (*src == '\r') || (*src == '\n');
526                   src++;
527                 }
528               else end = 1;
529             }
530           else
531             {
532               *dest_cmd++ = '\0';
533               end = (*src == '\r') || (*src == '\n');
534               src++;
535             };
536         }
537       else
538         {
539           if(!ctcp) slice_cmd[n_cmd++] = dest_cmd;
540           if(*src == ':') { queue = 1; src++; };
541
542           ctcp = 0;
543           while((src<endsrc) &&
544                 ((*src != ' ') || queue) && (*src != '\r') && (*src != '\n') 
545                 && (*src != '\001'))
546             *dest_cmd++ = *src++;
547
548           ctcp = (*src == '\001');
549         };
550     };
551
552   if(src < endsrc) if(*src == '\n') src++;
553
554   return 0;
555 };
556
557 //-----------------------------------------------------------------------------
558
559 void ListChar::Clear()
560 {
561   NodeList<char *> *node, *next;
562   node = first;
563   while(node != NULL)
564     {
565       next = node->next;
566       delete[] node->body;
567       delete node;
568       node = next;
569     };
570   first = NULL;
571 };
572
573 void ListChar::Add(char *s)
574 {
575   char *p;
576   p = strdup(s);
577   uncap(p);
578   Insert(p);
579 };
580
581 void ListChar::Remove(char *s)
582 {
583   NodeList<char *> *node, *pred, *next;
584
585   pred = NULL;
586   node = first;
587   while(node != NULL)
588     {
589       next = node->next;
590
591       if(strcmp(node->body, s) == 0)
592         {
593           if(pred == NULL) first = next;
594           else pred->next = next;
595
596           delete[] node->body;
597           delete node;
598         }
599       else pred = node;
600
601       node = next;
602     };
603 };
604
605 int ListChar::Matches(char *s)
606 {
607   NodeList<char *> *node;
608   int yep;
609   yep = 0;
610   for(node = first; (node != NULL) && !yep; node = node->next)
611     yep = match_pattern(node->body, s);
612   return yep;
613 };
614
615 int ListChar::IsMatchedBy(char *s)
616 {
617   NodeList<char *> *node;
618   int yep;
619   yep = 0;
620   for(node = first; (node != NULL) && !yep; node = node->next)
621     yep = match_pattern(s, node->body);
622   return yep;
623 };
624
625 int ListChar::Contains(char *s)
626 {
627   NodeList<char *> *node;
628   int yep;
629   yep = 0;
630   for(node = first; (node != NULL) && !yep; node = node->next)
631     yep = (strcmp(node->body, s) == 0);
632   return yep;
633 };
634