added ModeBuffer to tools.c
[NeonServV5.git] / tools.c
1 #include "tools.h"
2 #include "UserNode.h"
3 #include "lang.h"
4
5 static const struct default_language_entry msgtab[] = {
6     {"TIME_MASK_2_ITEMS", "%s and %s"},
7     {"TIME_MASK_3_ITEMS", "%s, %s and %s"},
8     {"TIME_YEAR", "year"},
9     {"TIME_YEARS", "years"},
10     {"TIME_MONTH", "month"},
11     {"TIME_MONTHS", "months"},
12     {"TIME_WEEK", "week"},
13     {"TIME_WEEKS", "weeks"},
14     {"TIME_DAY", "day"},
15     {"TIME_DAYS", "days"},
16     {"TIME_HOUR", "hour"},
17     {"TIME_HOURS", "hours"},
18     {"TIME_MINUTE", "minute"},
19     {"TIME_MINUTES", "minutes"},
20     {"TIME_SECOND", "second"},
21     {"TIME_SECONDS", "seconds"},
22     {NULL, NULL}
23 };
24
25 /* copied from IRCU 2.10.12 match.c */
26 /*
27  * Compare if a given string (name) matches the given
28  * mask (which can contain wild cards: '*' - match any
29  * number of chars, '?' - match any single character.
30  *
31  * return  0, if match
32  *         1, if no match
33  *
34  *  Originally by Douglas A Lewis (dalewis@acsu.buffalo.edu)
35  *  Rewritten by Timothy Vogelsang (netski), net@astrolink.org
36  */
37 int match(const char *mask, const char *name)
38 {
39   const char *m = mask, *n = name;
40   const char *m_tmp = mask, *n_tmp = name;
41   int star_p;
42
43   for (;;) switch (*m) {
44   case '\0':
45     if (!*n)
46       return 0;
47   backtrack:
48     if (m_tmp == mask)
49       return 1;
50     m = m_tmp;
51     n = ++n_tmp;
52     if (*n == '\0')
53       return 1;
54     break;
55   case '\\':
56     m++;
57     /* allow escaping to force capitalization */
58     if (*m++ != *n++)
59       goto backtrack;
60     break;
61   case '*': case '?':
62     for (star_p = 0; ; m++) {
63       if (*m == '*')
64         star_p = 1;
65       else if (*m == '?') {
66         if (!*n++)
67           goto backtrack;
68       } else break;
69     }
70     if (star_p) {
71       if (!*m)
72         return 0;
73       else if (*m == '\\') {
74         m_tmp = ++m;
75         if (!*m)
76           return 1;
77         for (n_tmp = n; *n && *n != *m; n++) ;
78       } else {
79         m_tmp = m;
80         for (n_tmp = n; *n && tolower(*n) != tolower(*m); n++) ;
81       }
82     }
83     /* and fall through */
84   default:
85     if (!*n)
86       return *m != '\0';
87     if (tolower(*m) != tolower(*n))
88       goto backtrack;
89     m++;
90     n++;
91     break;
92   }
93 }
94
95
96 //TABLES
97 struct Table *table_init(int width, int length, int flags) {
98     int row;
99     struct Table *table = malloc(sizeof(*table));
100     table->contents = malloc(length * sizeof(*table->contents));
101     for(row = 0; row < length; row++) {
102         table->contents[row] = calloc(width, sizeof(*table->contents[row]));
103     }
104     table->length = length;
105     table->width = width;
106     table->flags = flags;
107     table->col_flags = calloc(length, sizeof(int));
108     table->entrys = 0;
109     table->maxwidth = calloc(length, sizeof(int));
110     table->table_lines = NULL;
111     return table;
112 }
113
114 int table_add(struct Table *table, char **entry) {
115     int col;
116     if(table->entrys == table->length) return 0;
117     for(col = 0; col < table->width; col++) {
118         table->contents[table->entrys][col] = ((table->flags & TABLE_FLAG_USE_POINTER) ? entry[col] : strdup(entry[col]));
119         if(strlen(entry[col]) > table->maxwidth[col])
120             table->maxwidth[col] = strlen(entry[col]);
121     }
122     table->entrys++;
123     return 1;
124 }
125
126 int table_set_bold(struct Table *table, int collum, int bold) {
127     if(bold)
128         table->col_flags[collum] |= TABLE_FLAG_COL_BOLD;
129     else
130         table->col_flags[collum] &= ~TABLE_FLAG_COL_BOLD;
131     return 1;
132 }
133
134 char **table_end(struct Table *table) {
135     int row, col, tablewidth = 0, pos,i;
136     if(!table->entrys) return NULL;
137     for(col = 0; col < table->width; col++) {
138         tablewidth += table->maxwidth[col]+1;
139         if(table->col_flags[col] & TABLE_FLAG_COL_BOLD)
140             tablewidth += 2;
141     }
142     table->table_lines = malloc(table->entrys * sizeof(table->table_lines));
143     for(row = 0; row < table->entrys; row++) {
144         table->table_lines[row] = malloc(tablewidth * sizeof(*table->table_lines[row]));
145         pos = 0;
146         for(col = 0; col < table->width; col++) {
147             if(table->col_flags[col] & TABLE_FLAG_COL_BOLD)
148                 table->table_lines[row][pos++] = '\002';
149             for(i = 0; i < strlen(table->contents[row][col]); i++) {
150                 table->table_lines[row][pos++] = table->contents[row][col][i];
151             }
152             if(col < table->width-1) {
153                 for(;i < table->maxwidth[col]; i++) {
154                     table->table_lines[row][pos++] = ' ';
155                 }
156                 table->table_lines[row][pos++] = ' ';
157             } else
158                 table->table_lines[row][pos++] = '\0';
159             
160             if(table->col_flags[col] & TABLE_FLAG_COL_BOLD)
161                 table->table_lines[row][pos++] = '\002';
162         }
163     }
164     return table->table_lines;
165 }
166
167 void table_free(struct Table *table) {
168     int row, col;
169     for(row = 0; row < table->length; row++) {
170         if(!(table->flags & TABLE_FLAG_USE_POINTER) && table->entrys > row) {
171             for(col = 0; col < table->width; col++) {
172                 free(table->contents[row][col]);
173             }
174         }
175         free(table->contents[row]);
176     }
177     free(table->contents);
178     free(table->col_flags);
179     free(table->maxwidth);
180     if(table->table_lines) {
181         for(row = 0; row < table->entrys; row++) {
182             free(table->table_lines[row]);
183         }
184         free(table->table_lines);
185     }
186     free(table);
187 }
188
189 char* timeToStr(struct UserNode *user, int seconds, int items, char *buf) {
190     char item[items][MAXLEN];
191     int tmp, citem = 0;
192     if(citem != items && seconds >= 31536000) { //60*60*24*365 = 31536000
193         
194         tmp = seconds / 31536000;
195         sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_YEAR" : "TIME_YEARS"));
196         seconds -= tmp * 31536000;
197     }
198     if(citem != items && seconds >= 86400) { //60*60*24 = 86400
199         tmp = seconds / 86400;
200         sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_DAY" : "TIME_DAYS"));
201         seconds -= tmp * 86400;
202     }
203     if(citem != items && seconds >= 3600) { //60*60 = 3600
204         tmp = seconds / 3600;
205         sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_HOUR" : "TIME_HOURS"));
206         seconds -= tmp * 3600;
207     }
208     if(citem != items && seconds >= 60) {
209         tmp = seconds / 60;
210         sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_MINUTE" : "TIME_MINUTES"));
211         seconds -= tmp * 60;
212     }
213     if(citem != items && seconds >= 1) {
214         sprintf(item[citem++], "%d %s", seconds, get_language_string(user, seconds == 1 ? "TIME_SECOND" : "TIME_SECONDS"));
215     }
216     if(citem == 2) {
217         build_language_string(user, buf, "TIME_MASK_2_ITEMS", item[0], item[1]);
218     } else if(citem == 3) {
219         build_language_string(user, buf, "TIME_MASK_3_ITEMS", item[0], item[1], item[2]);
220     } else {
221         int i, ii, p = 0;
222         for(i = 0; i < citem; i++) {
223             for(ii = 0; ii < strlen(item[i]); ii++) {
224                 buf[p++] = item[i][ii];
225             }
226             buf[p++] = ' ';
227         }
228         buf[p-1] = '\0';
229     }
230     return buf;
231 }
232
233 int strToTime(struct UserNode *user, char *str) {
234     /*
235     * y = year = 365 days
236     * M = month = 30 days
237     * w = week = 7 days
238     * d = day
239     * h = hour
240     * m = minute
241     * (s) = second
242     */
243     int total_time = 0, cvalue;
244     char *p, tmpchar;
245     int unit_multiplikator;
246     while(*str) {
247         p = str;
248         while(*p && isdigit(*p)) //get the value
249             p++;
250         tmpchar = *p;
251         *p = '\0';
252         cvalue = isdigit(*str) ? atoi(str) : 0;
253         *p = tmpchar;
254         str = p;
255         while(*p && !isdigit(*p)) //get the unit
256             p++;
257         tmpchar = *p;
258         *p = '\0';
259         if(p - str > 1) { //unit has more than one char
260             if(!stricmp(str, "year") || !stricmp(str, "year") || !stricmp(str, get_language_string(user, "TIME_YEAR")) || !stricmp(str, get_language_string(user, "TIME_YEARS")))
261                 unit_multiplikator = 31536000; //60*60*24*365 = 31536000
262             else if(!stricmp(str, "month") || !stricmp(str, "months") || !stricmp(str, get_language_string(user, "TIME_MONTH")) || !stricmp(str, get_language_string(user, "TIME_MONTHS")))
263                 unit_multiplikator = 2592000; //60*60*24*30 = 2592000
264             else if(!stricmp(str, "week") || !stricmp(str, "weeks") || !stricmp(str, get_language_string(user, "TIME_WEEK")) || !stricmp(str, get_language_string(user, "TIME_WEEKS")))
265                 unit_multiplikator = 604800; //60*60*24*7 = 604800
266             else if(!stricmp(str, "day") || !stricmp(str, "days") || !stricmp(str, get_language_string(user, "TIME_DAY")) || !stricmp(str, get_language_string(user, "TIME_DAYS")))
267                 unit_multiplikator = 86400; //60*60*24 = 86400
268             else if(!stricmp(str, "hour") || !stricmp(str, "hours") || !stricmp(str, get_language_string(user, "TIME_HOUR")) || !stricmp(str, get_language_string(user, "TIME_HOURS")))
269                 unit_multiplikator = 3600; //60*60 = 3600
270             else if(!stricmp(str, "minute") || !stricmp(str, "minutes") || !stricmp(str, "min") || !stricmp(str, "mins") || !stricmp(str, get_language_string(user, "TIME_MINUTE")) || !stricmp(str, get_language_string(user, "TIME_MINUTES")))
271                 unit_multiplikator = 60;
272             else
273                 unit_multiplikator = 1;
274         } else {
275             switch(*str) {
276                 case 'y':
277                     unit_multiplikator = 31536000; //60*60*24*365 = 31536000
278                     break;
279                 case 'M':
280                     unit_multiplikator = 2592000; //60*60*24*30 = 2592000
281                     break;
282                 case 'w':
283                     unit_multiplikator = 604800; //60*60*24*7 = 604800
284                     break;
285                 case 'd':
286                     unit_multiplikator = 86400; //60*60*24 = 86400
287                     break;
288                 case 'h':
289                     unit_multiplikator = 3600; //60*60 = 3600
290                     break;
291                 case 'm':
292                     unit_multiplikator = 60;
293                     break;
294                 default:
295                     unit_multiplikator = 1;
296                     break;
297             }
298         }
299         total_time += (cvalue * unit_multiplikator);
300         *p = tmpchar;
301         str = p;
302     }
303     return total_time;
304 }
305
306 struct ModeBuffer* initModeBuffer(struct ClientSocket *client, struct ChanNode *chan) {
307     struct ModeBuffer *modeBuf = malloc(sizeof(*modeBuf));
308     if(!modeBuf) {
309         perror("malloc() failed");
310         return;
311     }
312     modeBuf->client = client;
313     modeBuf->chan = chan;
314     modeBuf->addCount = 0;
315     modeBuf->delCount = 0;
316     return modeBuf;
317 }
318
319 void modeBufferSet(struct ModeBuffer *modeBuf, int add, char mode, char *param) {
320     if(add) {
321         modeBuf->addModes[modeBuf->addCount] = mode;
322         modeBuf->addModesParams[modeBuf->addCount] = (param ? strdup(param) : NULL);
323         modeBuf->addCount++;
324         modeBuf->addModes[modeBuf->addCount] = '\0';
325     } else {
326         modeBuf->delModes[modeBuf->delCount] = mode;
327         modeBuf->delModesParams[modeBuf->delCount] = (param ? strdup(param) : NULL);
328         modeBuf->delCount++;
329         modeBuf->delModes[modeBuf->delCount] = '\0';
330     }
331     if(modeBuf->addCount + modeBuf->delCount == MAXMODES)
332         flushModeBuffer(modeBuf);
333 }
334
335 void flushModeBuffer(struct ModeBuffer *modeBuf) {
336     char modeStr[MAXMODES+3];
337     int modePos = 0;
338     char paramStr[MAXLEN];
339     int paramPos = 0;
340     int i;
341     if(modeBuf->addCount) {
342         modeStr[modePos++] = '+';
343         for(i = 0; i < modeBuf->addCount; i++) {
344             modeStr[modePos++] = modeBuf->addModes[i];
345             if(modeBuf->addModesParams[i]) {
346                 paramPos += sprintf(paramStr + paramPos, " %s", modeBuf->addModesParams[i]);
347             }
348         }
349         modeBuf->addCount = 0;
350     }
351     if(modeBuf->delCount) {
352         modeStr[modePos++] = '-';
353         for(i = 0; i < modeBuf->delCount; i++) {
354             modeStr[modePos++] = modeBuf->delModes[i];
355             if(modeBuf->delModesParams[i]) {
356                 paramPos += sprintf(paramStr + paramPos, " %s", modeBuf->delModesParams[i]);
357             }
358         }
359         modeBuf->delCount = 0;
360     }
361     modeStr[modePos++] = '\0';
362     putsock(modeBuf->client, "MODE %s %s%s", modeBuf->chan->name, modeStr, paramStr);
363 }
364
365 void freeModeBuffer(struct ModeBuffer *modeBuf) {
366     if(modeBuf->addCount + modeBuf->delCount)
367         flushModeBuffer(modeBuf);
368     free(modeBuf);
369 }
370
371 void init_tools() {
372     register_default_language_table(msgtab);
373 }