#include "tools.h"
+#include "UserNode.h"
+#include "ChanNode.h"
+#include "lang.h"
+#include "ClientSocket.h"
+
+static const struct default_language_entry msgtab[] = {
+ {"TIME_MASK_2_ITEMS", "%s and %s"}, /* {ARGS: "2 days", "1 hour"} */
+ {"TIME_MASK_3_ITEMS", "%s, %s and %s"}, /* {ARGS: "2 days", "1 hour", "20 minutes"} */
+ {"TIME_YEAR", "year"},
+ {"TIME_YEARS", "years"},
+ {"TIME_MONTH", "month"},
+ {"TIME_MONTHS", "months"},
+ {"TIME_WEEK", "week"},
+ {"TIME_WEEKS", "weeks"},
+ {"TIME_DAY", "day"},
+ {"TIME_DAYS", "days"},
+ {"TIME_HOUR", "hour"},
+ {"TIME_HOURS", "hours"},
+ {"TIME_MINUTE", "minute"},
+ {"TIME_MINUTES", "minutes"},
+ {"TIME_SECOND", "second"},
+ {"TIME_SECONDS", "seconds"},
+ {NULL, NULL}
+};
/* copied from IRCU 2.10.12 match.c */
/*
for (n_tmp = n; *n && *n != *m; n++) ;
} else {
m_tmp = m;
- for (n_tmp = n; *n && ToLower(*n) != ToLower(*m); n++) ;
+ for (n_tmp = n; *n && tolower(*n) != tolower(*m); n++) ;
}
}
/* and fall through */
default:
if (!*n)
return *m != '\0';
- if (ToLower(*m) != ToLower(*n))
+ if (tolower(*m) != tolower(*n))
goto backtrack;
m++;
n++;
break;
}
-}
\ No newline at end of file
+}
+
+
+//TABLES
+struct Table *table_init(int width, int length, int flags) {
+ int row;
+ struct Table *table = malloc(sizeof(*table));
+ table->contents = malloc(length * sizeof(*table->contents));
+ for(row = 0; row < length; row++) {
+ table->contents[row] = calloc(width, sizeof(*table->contents[row]));
+ }
+ table->length = length;
+ table->width = width;
+ table->flags = flags;
+ table->col_flags = calloc(length, sizeof(int));
+ table->entrys = 0;
+ table->maxwidth = calloc(length, sizeof(int));
+ table->table_lines = NULL;
+ return table;
+}
+
+int table_add(struct Table *table, char **entry) {
+ int col;
+ if(table->entrys == table->length) return 0;
+ for(col = 0; col < table->width; col++) {
+ table->contents[table->entrys][col] = ((table->flags & TABLE_FLAG_USE_POINTER) || !entry[col] ? entry[col] : strdup(entry[col]));
+ if(table->contents[table->entrys][col])
+ table->col_flags[col] |= TABLE_FLAG_COL_CONTENTS;
+ if(entry[col] && strlen(entry[col]) > table->maxwidth[col])
+ table->maxwidth[col] = strlen(entry[col]);
+ }
+ table->entrys++;
+ return 1;
+}
+
+int table_change(struct Table *table, int row, char **entry) {
+ int col;
+ if(row >= table->length) return 0;
+ for(col = 0; col < table->width; col++) {
+ if(table->contents[row][col] && !(table->flags & TABLE_FLAG_USE_POINTER))
+ free(table->contents[row][col]);
+ table->contents[row][col] = ((table->flags & TABLE_FLAG_USE_POINTER) || !entry[col] ? entry[col] : strdup(entry[col]));
+ if(table->contents[row][col])
+ table->col_flags[col] |= TABLE_FLAG_COL_CONTENTS;
+ if(entry[col] && strlen(entry[col]) > table->maxwidth[col])
+ table->maxwidth[col] = strlen(entry[col]);
+ }
+ return 1;
+}
+
+int table_change_field(struct Table *table, int row, int col, char *entry) {
+ if(row >= table->length) return 0;
+ if(col >= table->width) return 0;
+ if(table->contents[row][col] && !(table->flags & TABLE_FLAG_USE_POINTER))
+ free(table->contents[row][col]);
+ table->contents[row][col] = (((table->flags & TABLE_FLAG_USE_POINTER) || !entry) ? entry : strdup(entry));
+ if(table->contents[row][col])
+ table->col_flags[col] |= TABLE_FLAG_COL_CONTENTS;
+ if(entry && strlen(entry) > table->maxwidth[col])
+ table->maxwidth[col] = strlen(entry);
+ return 1;
+}
+
+int table_set_bold(struct Table *table, int collum, int bold) {
+ if(bold)
+ table->col_flags[collum] |= TABLE_FLAG_COL_BOLD;
+ else
+ table->col_flags[collum] &= ~TABLE_FLAG_COL_BOLD;
+ return 1;
+}
+
+char **table_end(struct Table *table) {
+ int row, col, tablewidth = 0, pos,i;
+ if(!table->entrys) return NULL;
+ for(col = 0; col < table->width; col++) {
+ tablewidth += table->maxwidth[col]+1;
+ if(table->col_flags[col] & TABLE_FLAG_COL_BOLD)
+ tablewidth += 2;
+ }
+ table->table_lines = malloc(table->entrys * sizeof(table->table_lines));
+ for(row = 0; row < table->entrys; row++) {
+ table->table_lines[row] = malloc(tablewidth * sizeof(*table->table_lines[row]));
+ pos = 0;
+ for(col = 0; col < table->width; col++) {
+ if(!(table->col_flags[col] & TABLE_FLAG_COL_CONTENTS)) continue;
+ if(table->col_flags[col] & TABLE_FLAG_COL_BOLD)
+ table->table_lines[row][pos++] = '\002';
+ for(i = 0; i < strlen(table->contents[row][col]); i++) {
+ table->table_lines[row][pos++] = table->contents[row][col][i];
+ }
+ if(col < table->width-1) {
+ for(;i < table->maxwidth[col]; i++) {
+ table->table_lines[row][pos++] = ' ';
+ }
+ table->table_lines[row][pos++] = ' ';
+ } else
+ table->table_lines[row][pos++] = '\0';
+
+ if(table->col_flags[col] & TABLE_FLAG_COL_BOLD)
+ table->table_lines[row][pos++] = '\002';
+ }
+ }
+ return table->table_lines;
+}
+
+void table_free(struct Table *table) {
+ int row, col;
+ for(row = 0; row < table->length; row++) {
+ if(!(table->flags & TABLE_FLAG_USE_POINTER) && table->entrys > row) {
+ for(col = 0; col < table->width; col++) {
+ if(table->contents[row][col])
+ free(table->contents[row][col]);
+ }
+ }
+ free(table->contents[row]);
+ }
+ free(table->contents);
+ free(table->col_flags);
+ free(table->maxwidth);
+ if(table->table_lines) {
+ for(row = 0; row < table->entrys; row++) {
+ free(table->table_lines[row]);
+ }
+ free(table->table_lines);
+ }
+ free(table);
+}
+
+char* timeToStr(struct UserNode *user, int seconds, int items, char *buf) {
+ char item[items][MAXLEN];
+ int tmp, citem = 0;
+ if(citem != items && seconds >= 31536000) { //60*60*24*365 = 31536000
+
+ tmp = seconds / 31536000;
+ sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_YEAR" : "TIME_YEARS"));
+ seconds -= tmp * 31536000;
+ }
+ if(citem != items && seconds >= 86400) { //60*60*24 = 86400
+ tmp = seconds / 86400;
+ sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_DAY" : "TIME_DAYS"));
+ seconds -= tmp * 86400;
+ }
+ if(citem != items && seconds >= 3600) { //60*60 = 3600
+ tmp = seconds / 3600;
+ sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_HOUR" : "TIME_HOURS"));
+ seconds -= tmp * 3600;
+ }
+ if(citem != items && seconds >= 60) {
+ tmp = seconds / 60;
+ sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_MINUTE" : "TIME_MINUTES"));
+ seconds -= tmp * 60;
+ }
+ if(citem != items && seconds >= 1) {
+ sprintf(item[citem++], "%d %s", seconds, get_language_string(user, seconds == 1 ? "TIME_SECOND" : "TIME_SECONDS"));
+ }
+ if(citem == 2) {
+ build_language_string(user, buf, "TIME_MASK_2_ITEMS", item[0], item[1]);
+ } else if(citem == 3) {
+ build_language_string(user, buf, "TIME_MASK_3_ITEMS", item[0], item[1], item[2]);
+ } else {
+ int i, ii, p = 0;
+ for(i = 0; i < citem; i++) {
+ for(ii = 0; ii < strlen(item[i]); ii++) {
+ buf[p++] = item[i][ii];
+ }
+ buf[p++] = ' ';
+ }
+ buf[(p ? p-1 : 0)] = '\0';
+ }
+ return buf;
+}
+
+int strToTime(struct UserNode *user, char *str) {
+ /*
+ * y = year = 365 days
+ * M = month = 30 days
+ * w = week = 7 days
+ * d = day
+ * h = hour
+ * m = minute
+ * (s) = second
+ */
+ int total_time = 0, cvalue;
+ char *p, tmpchar;
+ int unit_multiplikator;
+ while(*str) {
+ p = str;
+ while(*p && !isdigit(*p)) //skip leading chars
+ p++;
+ str = p;
+ while(*p && isdigit(*p)) //get the value
+ p++;
+ tmpchar = *p;
+ *p = '\0';
+ cvalue = isdigit(*str) ? atoi(str) : 0;
+ *p = tmpchar;
+ while(*p == ' ') //skip spaces
+ p++;
+ str = p;
+ while(*p && !isdigit(*p)) //get the unit
+ p++;
+ tmpchar = *p;
+ *p = '\0';
+ if(p - str > 1) { //unit has more than one char
+ if(!stricmp(str, "year") || !stricmp(str, "year") || !stricmp(str, get_language_string(user, "TIME_YEAR")) || !stricmp(str, get_language_string(user, "TIME_YEARS")))
+ unit_multiplikator = 31536000; //60*60*24*365 = 31536000
+ else if(!stricmp(str, "month") || !stricmp(str, "months") || !stricmp(str, get_language_string(user, "TIME_MONTH")) || !stricmp(str, get_language_string(user, "TIME_MONTHS")))
+ unit_multiplikator = 2592000; //60*60*24*30 = 2592000
+ else if(!stricmp(str, "week") || !stricmp(str, "weeks") || !stricmp(str, get_language_string(user, "TIME_WEEK")) || !stricmp(str, get_language_string(user, "TIME_WEEKS")))
+ unit_multiplikator = 604800; //60*60*24*7 = 604800
+ else if(!stricmp(str, "day") || !stricmp(str, "days") || !stricmp(str, get_language_string(user, "TIME_DAY")) || !stricmp(str, get_language_string(user, "TIME_DAYS")))
+ unit_multiplikator = 86400; //60*60*24 = 86400
+ else if(!stricmp(str, "hour") || !stricmp(str, "hours") || !stricmp(str, get_language_string(user, "TIME_HOUR")) || !stricmp(str, get_language_string(user, "TIME_HOURS")))
+ unit_multiplikator = 3600; //60*60 = 3600
+ 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")))
+ unit_multiplikator = 60;
+ else
+ unit_multiplikator = 1;
+ } else {
+ switch(*str) {
+ case 'y':
+ unit_multiplikator = 31536000; //60*60*24*365 = 31536000
+ break;
+ case 'M':
+ unit_multiplikator = 2592000; //60*60*24*30 = 2592000
+ break;
+ case 'w':
+ unit_multiplikator = 604800; //60*60*24*7 = 604800
+ break;
+ case 'd':
+ unit_multiplikator = 86400; //60*60*24 = 86400
+ break;
+ case 'h':
+ unit_multiplikator = 3600; //60*60 = 3600
+ break;
+ case 'm':
+ unit_multiplikator = 60;
+ break;
+ default:
+ unit_multiplikator = 1;
+ break;
+ }
+ }
+ total_time += (cvalue * unit_multiplikator);
+ *p = tmpchar;
+ str = p;
+ }
+ return total_time;
+}
+
+struct ModeBuffer* initModeBuffer(struct ClientSocket *client, struct ChanNode *chan) {
+ struct ModeBuffer *modeBuf = malloc(sizeof(*modeBuf));
+ if(!modeBuf) {
+ perror("malloc() failed");
+ return NULL;
+ }
+ modeBuf->client = client;
+ modeBuf->chan = chan;
+ modeBuf->addCount = 0;
+ modeBuf->delCount = 0;
+ return modeBuf;
+}
+
+void modeBufferSet(struct ModeBuffer *modeBuf, int add, char mode, char *param) {
+ if(add) {
+ modeBuf->addModes[modeBuf->addCount] = mode;
+ modeBuf->addModesParams[modeBuf->addCount] = (param ? strdup(param) : NULL);
+ modeBuf->addCount++;
+ modeBuf->addModes[modeBuf->addCount] = '\0';
+ } else {
+ modeBuf->delModes[modeBuf->delCount] = mode;
+ modeBuf->delModesParams[modeBuf->delCount] = (param ? strdup(param) : NULL);
+ modeBuf->delCount++;
+ modeBuf->delModes[modeBuf->delCount] = '\0';
+ }
+ if(modeBuf->addCount + modeBuf->delCount == MAXMODES)
+ flushModeBuffer(modeBuf);
+}
+
+void flushModeBuffer(struct ModeBuffer *modeBuf) {
+ char modeStr[MAXMODES+3];
+ int modePos = 0;
+ char paramStr[MAXLEN];
+ int paramPos = 0;
+ int i;
+ if(modeBuf->addCount) {
+ modeStr[modePos++] = '+';
+ for(i = 0; i < modeBuf->addCount; i++) {
+ modeStr[modePos++] = modeBuf->addModes[i];
+ if(modeBuf->addModesParams[i]) {
+ paramPos += sprintf(paramStr + paramPos, " %s", modeBuf->addModesParams[i]);
+ }
+ }
+ modeBuf->addCount = 0;
+ }
+ if(modeBuf->delCount) {
+ modeStr[modePos++] = '-';
+ for(i = 0; i < modeBuf->delCount; i++) {
+ modeStr[modePos++] = modeBuf->delModes[i];
+ if(modeBuf->delModesParams[i]) {
+ paramPos += sprintf(paramStr + paramPos, " %s", modeBuf->delModesParams[i]);
+ }
+ }
+ modeBuf->delCount = 0;
+ }
+ modeStr[modePos++] = '\0';
+ putsock(modeBuf->client, "MODE %s %s%s", modeBuf->chan->name, modeStr, paramStr);
+}
+
+void freeModeBuffer(struct ModeBuffer *modeBuf) {
+ if(modeBuf->addCount + modeBuf->delCount)
+ flushModeBuffer(modeBuf);
+ free(modeBuf);
+}
+
+int is_ircmask(const char *text) {
+ while (*text && (isalnum((char)*text) || strchr("-_[]|\\`^{}?*", *text)))
+ text++;
+ if (*text++ != '!')
+ return 0;
+ while (*text && *text != '@' && !isspace((char)*text))
+ text++;
+ if (*text++ != '@')
+ return 0;
+ while (*text && !isspace((char)*text))
+ text++;
+ return !*text;
+}
+
+char* generate_banmask(struct UserNode *user, char *buffer) {
+ char *userhost = user->host;
+
+ if(isFakeHost(user->host)) {
+ sprintf(buffer, "*!*@%s", userhost);
+ return buffer;
+ }
+
+ //check if the hostname has more than 4 connections (trusted host)
+ if(countUsersWithHost(userhost) > 4) {
+ sprintf(buffer, "*!%s@%s", user->ident, userhost);
+ return buffer;
+ } else {
+ sprintf(buffer, "*!*@%s", userhost);
+ return buffer;
+ }
+}
+
+char* make_banmask(char *input, char* buffer) {
+ char *nick = NULL, *ident = NULL, *host = NULL;
+ char tmp[HOSTLEN];
+ char *p;
+ if((p = strstr(input, "!"))) {
+ nick = input;
+ *p = '\0';
+ ident = p+1;
+ if((p = strstr(ident, "@"))) {
+ *p = '\0';
+ host = p+1;
+ }
+ } else if((p = strstr(input, "@"))) {
+ ident = input;
+ *p = '\0';
+ host = p+1;
+ } else if((p = strstr(input, "."))) {
+ host = input;
+ } else if(*input == '*' && input[1] != '\0' && !strstr(input+1, "*")) {
+ //AUTH MASK
+ p = getAuthFakehost(input+1);
+ if(p)
+ host = p;
+ else {
+ sprintf(tmp, "%s.*", input+1);
+ host = tmp;
+ }
+ } else {
+ struct UserNode *user = searchUserByNick(input);
+ if(user)
+ return generate_banmask(user, buffer);
+ else
+ nick = input;
+ }
+ if(nick && *nick == '\0') nick = NULL;
+ if(ident && *ident == '\0') ident = NULL;
+ if(host && *host == '\0') host = NULL;
+ sprintf(buffer, "%s!%s@%s", (nick ? nick : "*"), (ident ? ident : "*"), (host ? host : "*"));
+ return buffer;
+}
+
+int isFakeHost(char *host) {
+ char *p1, *p2 = host;
+
+ //find the last dot to identify if the hostmask is a fake host
+ while((p1 = strstr(p2, "."))) {
+ p2 = p1 + 1;
+ }
+ //TLD database: http://www.iana.org/domains/root/db/
+ //the longest TLD i found was 6 chars long (ignoring the stange exotic ones :D)
+ //but we even ignore '.museum' and '.travel' so we can say that the TLD of our mask needs to be less than 4 chars to be a real domain
+ return (strlen(p2+1) > 4);
+}
+
+void init_tools() {
+ register_default_language_table(msgtab);
+}