diff options
author | certus certus@31f1291d-b8d6-0310-a050-a5561fc1590b <certus certus@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864> | 2006-07-04 19:50:00 +0000 |
---|---|---|
committer | certus certus@31f1291d-b8d6-0310-a050-a5561fc1590b <certus certus@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864> | 2006-07-04 19:50:00 +0000 |
commit | 3323816264fc01ccfb455b61bf43cbe8621532cf (patch) | |
tree | 340e92d5519851b254900fe997a577b34002ca2e /src | |
parent | 7ceb358ec4c7ceb8d202ca18c1572804400b4a31 (diff) |
# BUILD : 1.7.14 (1080) # BUGS : 491? # NOTES : rewrote exception system due to a bug we couldn't track down.
git-svn-id: svn://svn.anope.org/anope/trunk@1080 31f1291d-b8d6-0310-a050-a5561fc1590b
git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@804 5417fbe8-f217-4b02-8779-1006273d7864
Diffstat (limited to 'src')
-rw-r--r-- | src/mysql.c | 29 | ||||
-rw-r--r-- | src/sessions.c | 472 |
2 files changed, 209 insertions, 292 deletions
diff --git a/src/mysql.c b/src/mysql.c index af319d5b6..889dcd40d 100644 --- a/src/mysql.c +++ b/src/mysql.c @@ -983,10 +983,13 @@ void db_mysql_load_news(void) mysql_free_result(mysql_res); } +#define HASH(host) (((host)[0]&31)<<5 | ((host)[1]&31)) + void db_mysql_load_exceptions(void) { char sqlcmd[MAX_SQL_BUF]; - int j; + Exception *exception; + int index; if (!do_mysql) return; @@ -1000,20 +1003,26 @@ void db_mysql_load_exceptions(void) } mysql_res = mysql_store_result(mysql); nexceptions = mysql_num_rows(mysql_res); - exceptions = scalloc(sizeof(Exception) * nexceptions, 1); - j = 0; + exception = scalloc(sizeof(Exception), 1); while ((mysql_row = mysql_fetch_row(mysql_res))) { - exceptions[j].mask = sstrdup(mysql_row[0]); - exceptions[j].limit = atoi(mysql_row[1]); - snprintf(exceptions[j].who, NICKMAX, "%s", mysql_row[2]); - exceptions[j].reason = sstrdup(mysql_row[3]); - exceptions[j].time = atoi(mysql_row[4]); - exceptions[j].expires = atoi(mysql_row[5]); - j++; + exception->mask = sstrdup(mysql_row[0]); + exception->limit = atoi(mysql_row[1]); + snprintf(exception->who, NICKMAX, "%s", mysql_row[2]); + exception->reason = sstrdup(mysql_row[3]); + exception->time = atoi(mysql_row[4]); + exception->expires = atoi(mysql_row[5]); + index = HASH(exception->mask); + exception->prev = NULL; + exception->next = exceptionlist[index]; + if (exception->next) + exception->next->prev = exception; + exceptionlist[index] = exception; } mysql_free_result(mysql_res); } +#undef HASH + #define HASH(host) ((tolower((host)[0])&31)<<5 | (tolower((host)[1])&31)) void db_mysql_load_os_dbase(void) diff --git a/src/sessions.c b/src/sessions.c index 2bf0605ea..29bb4b5f4 100644 --- a/src/sessions.c +++ b/src/sessions.c @@ -47,6 +47,12 @@ * exceptions. Comments and suggestions are more than welcome! * * -TheShadow (02 April 1999) + * + * The whole exception system has been rewritten to use linked list instead of + * an array due to a bug we couldn't track down. We don't need the numerical + * system anymore, it's not necessary to delete ranges. + * + * -Certus (04 July 2006) */ /*************************************************************************/ @@ -60,10 +66,82 @@ Session *sessionlist[1024]; int32 nsessions = 0; -Exception *exceptions = NULL; +Exception *exceptionlist[1024]; int16 nexceptions = 0; /*************************************************************************/ +/************************ Exception Manipulation *************************/ +/*************************************************************************/ + +Exception *exception_add(User * u, const char *mask, const int limit, + const char *reason, const char *who, + const time_t expires) +{ + int i, index; + Exception *exception, *ptr, *prev; + + /* Check if an exception already exists for this mask */ + for (i = 0; i < 1024; i++) { + for (exception = exceptionlist[i]; exception; exception = exception->next) { + if (!stricmp(mask, exception->mask)) { + if (exception->limit != limit) { + exception->limit = limit; + if (u) + notice_lang(s_OperServ, u, OPER_EXCEPTION_CHANGED, + mask, exception->limit); + return NULL; + } else { + if (u) + notice_lang(s_OperServ, u, OPER_EXCEPTION_EXISTS, + mask); + return NULL; + } + } + } + } + + nexceptions++; + exception = scalloc(sizeof(Exception), 1); + + exception->mask = sstrdup(mask); + exception->limit = limit; + exception->reason = sstrdup(reason); + exception->time = time(NULL); + strscpy(exception->who, who, NICKMAX); + exception->expires = expires; + + index = HASH(mask); /* bang! into the list! */ + + exception->prev = NULL; + exception->next = exceptionlist[index]; + if (exception->next) + exception->next->prev = exception; + exceptionlist[index] = exception; + + return exception; +} + +/*************************************************************************/ + +static int exception_del(Exception *exception) +{ + /* Remove the exception from the list */ + if (exception->next) + exception->next->prev = exception->prev; + if (exception->prev) + exception->prev->next = exception->next; + else + exceptionlist[HASH(exception->mask)] = exception->next; + + free(exception->mask); + free(exception->reason); + free(exception); + nexceptions--; + + return 1; +} + +/*************************************************************************/ /****************************** Statistics *******************************/ /*************************************************************************/ @@ -86,14 +164,18 @@ void get_session_stats(long *nrec, long *memuse) void get_exception_stats(long *nrec, long *memuse) { + Exception *exception; long mem; int i; mem = sizeof(Exception) * nexceptions; - for (i = 0; i < nexceptions; i++) { - mem += strlen(exceptions[i].mask) + 1; - mem += strlen(exceptions[i].reason) + 1; + for (i = 0; i < 1024; i++) { + for (exception = exceptionlist[i]; exception; exception = exception->next) { + mem += strlen(exception->mask) + 1; + mem += strlen(exception->reason) + 1; + } } + *nrec = nexceptions; *memuse = mem; } @@ -328,22 +410,20 @@ void del_session(const char *host) void expire_exceptions(void) { int i; + Exception *exception, *tmpexc; time_t now = time(NULL); - for (i = 0; i < nexceptions; i++) { - if (exceptions[i].expires == 0 || exceptions[i].expires > now) - continue; - if (WallExceptionExpire) - anope_cmd_global(s_OperServ, - "Session limit exception for %s has expired.", - exceptions[i].mask); - free(exceptions[i].mask); - free(exceptions[i].reason); - nexceptions--; - memmove(exceptions + i, exceptions + i + 1, - sizeof(Exception) * (nexceptions - i)); - exceptions = srealloc(exceptions, sizeof(Exception) * nexceptions); - i--; + for (i = 0; i < 1024; i++) { + for (exception = exceptionlist[i]; exception; exception = tmpexc) { + tmpexc = exception->next; + if (exception->expires == 0 || exception->expires > now) + continue; + if (WallExceptionExpire) + anope_cmd_global(s_OperServ, + "Session limit exception for %s has expired.", + exception->mask); + exception_del(exception); + } } } @@ -352,10 +432,12 @@ void expire_exceptions(void) Exception *find_host_exception(const char *host) { int i; + Exception *exception; - for (i = 0; i < nexceptions; i++) { - if (match_wild_nocase(exceptions[i].mask, host)) { - return &exceptions[i]; + for (i = 0; i < 1024; i++) { + for (exception = exceptionlist[i]; exception; exception = exception->next) { + if (match_wild_nocase(exception->mask, host)) + return exception; } } @@ -378,7 +460,7 @@ Exception *find_host_exception(const char *host) void load_exceptions() { dbFILE *f; - int i; + int i, index; uint16 n; uint16 tmp16; uint32 tmp32; @@ -392,21 +474,31 @@ void load_exceptions() case 7: SAFE(read_int16(&n, f)); nexceptions = n; - exceptions = scalloc(sizeof(Exception) * nexceptions, 1); if (!nexceptions) { close_db(f); return; } for (i = 0; i < nexceptions; i++) { - SAFE(read_string(&exceptions[i].mask, f)); + + Exception *exception = scalloc(sizeof(Exception), 1); + + SAFE(read_string(&exception->mask, f)); SAFE(read_int16(&tmp16, f)); - exceptions[i].limit = tmp16; - SAFE(read_buffer(exceptions[i].who, f)); - SAFE(read_string(&exceptions[i].reason, f)); + exception->limit = tmp16; + SAFE(read_buffer(exception->who, f)); + SAFE(read_string(&exception->reason, f)); SAFE(read_int32(&tmp32, f)); - exceptions[i].time = tmp32; + exception->time = tmp32; SAFE(read_int32(&tmp32, f)); - exceptions[i].expires = tmp32; + exception->expires = tmp32; + + index = HASH(exception->mask); + + exception->prev = NULL; + exception->next = exceptionlist[index]; + if (exception->next) + exception->next->prev = exception; + exceptionlist[index] = exception; } break; @@ -438,19 +530,22 @@ void save_exceptions() { dbFILE *f; int i; + Exception *exception; static time_t lastwarn = 0; if (! (f = open_db(s_OperServ, ExceptionDBName, "w", EXCEPTION_VERSION))) return; SAFE(write_int16(nexceptions, f)); - for (i = 0; i < nexceptions; i++) { - SAFE(write_string(exceptions[i].mask, f)); - SAFE(write_int16(exceptions[i].limit, f)); - SAFE(write_buffer(exceptions[i].who, f)); - SAFE(write_string(exceptions[i].reason, f)); - SAFE(write_int32(exceptions[i].time, f)); - SAFE(write_int32(exceptions[i].expires, f)); + for (i = 0; i < 1024; i++) { + for (exception = exceptionlist[i]; exception; exception = exception->next) { + SAFE(write_string(exception->mask, f)); + SAFE(write_int16(exception->limit, f)); + SAFE(write_buffer(exception->who, f)); + SAFE(write_string(exception->reason, f)); + SAFE(write_int32(exception->time, f)); + SAFE(write_int32(exception->expires, f)); + } } close_db(f); } @@ -463,156 +558,20 @@ void save_rdb_exceptions() { #ifdef USE_RDB int i; - Exception *e; + Exception *exception; if (!rdb_open()) return; rdb_clear_table("anope_os_exceptions"); - for (i = 0; i < nexceptions; i++) { - e = &exceptions[i]; - rdb_save_exceptions(e); + for (i = 0; i < 1024; i++) { + for (exception = exceptionlist[i]; exception; exception = exception->next) { + rdb_save_exceptions(exception); + } } rdb_close(); #endif } -/*************************************************************************/ -/************************ Exception Manipulation *************************/ -/*************************************************************************/ - -int exception_add(User * u, const char *mask, const int limit, - const char *reason, const char *who, - const time_t expires) -{ - int i; - - /* Check if an exception already exists for this mask */ - for (i = 0; i < nexceptions; i++) { - if (!stricmp(mask, exceptions[i].mask)) { - if (exceptions[i].limit != limit) { - exceptions[i].limit = limit; - if (u) - notice_lang(s_OperServ, u, OPER_EXCEPTION_CHANGED, - mask, exceptions[i].limit); - return -2; - } else { - if (u) - notice_lang(s_OperServ, u, OPER_EXCEPTION_EXISTS, - mask); - return -1; - } - } - } - - nexceptions++; - exceptions = srealloc(exceptions, sizeof(Exception) * nexceptions); - - exceptions[nexceptions - 1].mask = sstrdup(mask); - exceptions[nexceptions - 1].limit = limit; - exceptions[nexceptions - 1].reason = sstrdup(reason); - exceptions[nexceptions - 1].time = time(NULL); - strscpy(exceptions[nexceptions - 1].who, who, NICKMAX); - exceptions[nexceptions - 1].expires = expires; - exceptions[nexceptions - 1].num = nexceptions - 1; - - return 1; -} - -/*************************************************************************/ - -static int exception_del(const int index) -{ - if (index < 0 || index >= nexceptions) - return 0; - - free(exceptions[index].mask); - free(exceptions[index].reason); - nexceptions--; - memmove(exceptions + index, exceptions + index + 1, - sizeof(Exception) * (nexceptions - index)); - exceptions = srealloc(exceptions, sizeof(Exception) * nexceptions); - - return 1; -} - -/* We use the "num" property to keep track of the position of each exception - * when deleting using ranges. This is because an exception's position changes - * as others are deleted. The positions will be recalculated once the process - * is complete. -TheShadow - */ - -static int exception_del_callback(User * u, int num, va_list args) -{ - int i; - int *last = va_arg(args, int *); - - *last = num; - for (i = 0; i < nexceptions; i++) { - if (num - 1 == exceptions[i].num) - break; - } - if (i < nexceptions) - return exception_del(i); - else - return 0; -} - -static int exception_list(User * u, const int index, int *sent_header) -{ - if (index < 0 || index >= nexceptions) - return 0; - if (!*sent_header) { - notice_lang(s_OperServ, u, OPER_EXCEPTION_LIST_HEADER); - notice_lang(s_OperServ, u, OPER_EXCEPTION_LIST_COLHEAD); - *sent_header = 1; - } - notice_lang(s_OperServ, u, OPER_EXCEPTION_LIST_FORMAT, index + 1, - exceptions[index].limit, exceptions[index].mask); - return 1; -} - -static int exception_list_callback(User * u, int num, va_list args) -{ - int *sent_header = va_arg(args, int *); - - return exception_list(u, num - 1, sent_header); -} - -static int exception_view(User * u, const int index, int *sent_header) -{ - char timebuf[32], expirebuf[256]; - struct tm tm; - time_t t = time(NULL); - - if (index < 0 || index >= nexceptions) - return 0; - if (!*sent_header) { - notice_lang(s_OperServ, u, OPER_EXCEPTION_LIST_HEADER); - *sent_header = 1; - } - - tm = *localtime(exceptions[index].time ? &exceptions[index].time : &t); - strftime_lang(timebuf, sizeof(timebuf), - u, STRFTIME_SHORT_DATE_FORMAT, &tm); - - expire_left(u->na, expirebuf, sizeof(expirebuf), - exceptions[index].expires); - - notice_lang(s_OperServ, u, OPER_EXCEPTION_VIEW_FORMAT, - index + 1, exceptions[index].mask, - *exceptions[index].who ? - exceptions[index].who : "<unknown>", - timebuf, expirebuf, exceptions[index].limit, - exceptions[index].reason); - return 1; -} - -static int exception_view_callback(User * u, int num, va_list args) -{ - int *sent_header = va_arg(args, int *); - - return exception_view(u, num - 1, sent_header); -} /*************************************************************************/ @@ -629,9 +588,6 @@ static int exception_view_callback(User * u, int num, va_list args) * Syntax: EXCEPTION VIEW [mask] * Displays detailed information about each exception or those matching * mask. - * - * Syntax: EXCEPTION MOVE num position - * Moves the exception at position num to position. */ int do_exception(User * u) @@ -651,11 +607,11 @@ int do_exception(User * u) cmd = ""; if (stricmp(cmd, "ADD") == 0) { + /* gotta keep this check because of the dbs :( -Certus */ if (nexceptions >= 32767) { notice_lang(s_OperServ, u, OPER_EXCEPTION_TOO_MANY); return MOD_CONT; } - mask = strtok(NULL, " "); if (mask && *mask == '+') { expiry = mask; @@ -687,24 +643,27 @@ int do_exception(User * u) MaxSessionLimit); return MOD_CONT; - } else { + } else { /* finally when can add it */ + Exception *exception; + if (strchr(mask, '!') || strchr(mask, '@')) { notice_lang(s_OperServ, u, OPER_EXCEPTION_INVALID_HOSTMASK); return MOD_CONT; } - x = exception_add(u, mask, limit, reason, u->nick, expires); + exception = exception_add(u, mask, limit, reason, u->nick, expires); - if (x == 1) { - notice_lang(s_OperServ, u, OPER_EXCEPTION_ADDED, mask, - limit); - } + if (exception) + notice_lang(s_OperServ, u, OPER_EXCEPTION_ADDED, mask, limit); if (readonly) notice_lang(s_OperServ, u, READ_ONLY_MODE); } } else if (stricmp(cmd, "DEL") == 0) { + Exception *exception; + int deleted = 0; + mask = strtok(NULL, " "); if (!mask) { @@ -713,127 +672,76 @@ int do_exception(User * u) return MOD_CONT; } - if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) { - int count, deleted, last = -1; - deleted = - process_numlist(mask, &count, exception_del_callback, u, - &last); - if (!deleted) { - if (count == 1) { - notice_lang(s_OperServ, u, - OPER_EXCEPTION_NO_SUCH_ENTRY, last); - } else { - notice_lang(s_OperServ, u, OPER_EXCEPTION_NO_MATCH); - } - } else if (deleted == 1) { - notice_lang(s_OperServ, u, OPER_EXCEPTION_DELETED_ONE); - } else { - notice_lang(s_OperServ, u, OPER_EXCEPTION_DELETED_SEVERAL, - deleted); - } - } else { - int deleted = 0; - - for (i = 0; i < nexceptions; i++) { - if (stricmp(mask, exceptions[i].mask) == 0) { - exception_del(i); - notice_lang(s_OperServ, u, OPER_EXCEPTION_DELETED, - mask); + for (i = 0; i < 1024; i++) { + for (exception = exceptionlist[i]; exception; exception = exception->next) { + if (!stricmp(mask, exception->mask)) { + exception_del(exception); + notice_lang(s_OperServ, u, OPER_EXCEPTION_DELETED, mask); deleted = 1; break; } } - if (!deleted && i == nexceptions) - notice_lang(s_OperServ, u, OPER_EXCEPTION_NOT_FOUND, mask); } - /* Renumber the exception list. I don't believe in having holes in - * lists - it makes code more complex, harder to debug and we end up - * with huge index numbers. Imho, fixed numbering is only beneficial - * when one doesn't have range capable manipulation. -TheShadow */ - - for (i = 0; i < nexceptions; i++) - exceptions[i].num = i; + if (!deleted) + notice_lang(s_OperServ, u, OPER_EXCEPTION_NOT_FOUND, mask); if (readonly) notice_lang(s_OperServ, u, READ_ONLY_MODE); - } else if (stricmp(cmd, "MOVE") == 0) { - Exception *exception; - char *n1str = strtok(NULL, " "); /* From position */ - char *n2str = strtok(NULL, " "); /* To position */ - int n1, n2; - - if (!n2str) { - syntax_error(s_OperServ, u, "EXCEPTION", - OPER_EXCEPTION_MOVE_SYNTAX); - return MOD_CONT; - } - - n1 = atoi(n1str) - 1; - n2 = atoi(n2str) - 1; - - if ((n1 >= 0 && n1 < nexceptions) && (n2 >= 0 && n2 < nexceptions) - && (n1 != n2)) { - exception = scalloc(sizeof(Exception), 1); - memcpy(exception, &exceptions[n1], sizeof(Exception)); - - if (n1 < n2) { - /* Shift upwards */ - memmove(&exceptions[n1], &exceptions[n1 + 1], - sizeof(Exception) * (n2 - n1)); - memmove(&exceptions[n2], exception, sizeof(Exception)); - } else { - /* Shift downwards */ - memmove(&exceptions[n2 + 1], &exceptions[n2], - sizeof(Exception) * (n1 - n2)); - memmove(&exceptions[n2], exception, sizeof(Exception)); - } - - free(exception); - notice_lang(s_OperServ, u, OPER_EXCEPTION_MOVED, - exceptions[n1].mask, n1 + 1, n2 + 1); - - /* Renumber the exception list. See the DEL block above for why. */ - for (i = 0; i < nexceptions; i++) - exceptions[i].num = i; - - if (readonly) - notice_lang(s_OperServ, u, READ_ONLY_MODE); - } else { - syntax_error(s_OperServ, u, "EXCEPTION", - OPER_EXCEPTION_MOVE_SYNTAX); - } } else if (stricmp(cmd, "LIST") == 0) { int sent_header = 0; + Exception *exception; + expire_exceptions(); mask = strtok(NULL, " "); - if (mask && strspn(mask, "1234567890,-") == strlen(mask)) { - process_numlist(mask, NULL, exception_list_callback, u, - &sent_header); - } else { - for (i = 0; i < nexceptions; i++) { - if (!mask || match_wild_nocase(mask, exceptions[i].mask)) - exception_list(u, i, &sent_header); + + for (i = 0; i < 1024; i++) { + for (exception = exceptionlist[i]; exception; exception = exception->next) { + if (!mask || match_wild_nocase(mask, exception->mask)) { + if (!sent_header) { + notice_lang(s_OperServ, u, OPER_EXCEPTION_LIST_HEADER); + notice_lang(s_OperServ, u, OPER_EXCEPTION_LIST_COLHEAD); + sent_header = 1; + } + notice_lang(s_OperServ, u, OPER_EXCEPTION_LIST_FORMAT, + exception->limit, exception->mask); + } } } + if (!sent_header) notice_lang(s_OperServ, u, OPER_EXCEPTION_NO_MATCH); } else if (stricmp(cmd, "VIEW") == 0) { int sent_header = 0; + Exception *exception; + char timebuf[32], expirebuf[256]; + struct tm tm; + time_t t = time(NULL); + expire_exceptions(); mask = strtok(NULL, " "); - if (mask && strspn(mask, "1234567890,-") == strlen(mask)) { - process_numlist(mask, NULL, exception_view_callback, u, - &sent_header); - } else { - for (i = 0; i < nexceptions; i++) { - if (!mask || match_wild_nocase(mask, exceptions[i].mask)) - exception_view(u, i, &sent_header); + + for (i = 0; i < 1024; i++) { + for (exception = exceptionlist[i]; exception; exception = exception->next) { + if (!mask || match_wild_nocase(mask, exception->mask)) { + if (!sent_header) { + notice_lang(s_OperServ, u, OPER_EXCEPTION_LIST_HEADER); + sent_header = 1; + } + tm = *localtime(exception->time ? &exception->time : &t); + strftime_lang(timebuf, sizeof(timebuf), u, + STRFTIME_SHORT_DATE_FORMAT, &tm); + expire_left(u->na, expirebuf, sizeof(expirebuf), exception->expires); + notice_lang(s_OperServ, u, OPER_EXCEPTION_VIEW_FORMAT, exception->mask, + exception->who ? exception->who : "<unknown>", timebuf, expirebuf, + exception->limit, exception->reason); + } } } + if (!sent_header) notice_lang(s_OperServ, u, OPER_EXCEPTION_NO_MATCH); |