00001 #include <string.h>
00002 #include <stdlib.h>
00003 #include <stdio.h>
00004 #include <time.h>
00005 #include "queue.h"
00006
00007 #define COPGUARD 0x00000001
00008 #define CKTOPIC 0x00000002
00009 #define CLEAVEOPS 0x00000004
00010 #define CQUIET 0x00000008
00011 #define CCSJOIN 0x00000010
00012 #define CIDENT 0x00000020
00013 #define CHOLD 0x00000040
00014 #define CREG 0x00000080
00015 #define CBANISH 0x00000100
00016 #define CPROTOP 0x00000200
00017 #define CMARK 0x00000400
00018 #define CCLOSE 0x00000800
00019
00020 #define strncpyzt(dd,ff,nn) \
00021 do { \
00022 strncpy(dd,ff,nn); \
00023 dd[nn - 1] = '\0'; \
00024 } while(0)
00025
00026 #define MIN(x,y) ((x)<(y)?(x):(y))
00027 #define MAX(x,y) ((x)>(y)?(x):(y))
00028
00029 #define NBANISH 0x0100
00030 #define NHOLD 0x0004
00031 #define NVACATION 0x0002
00032 #define GNUPLOT_DAT
00033 #define MAILSTAT_WRITE
00034 #define NZERO(x) ((x)?(x):1)
00035
00036 int main(void);
00037 char *sfgets(char *, int, FILE *);
00038 void *oalloc(size_t);
00039
00040 int email=0, email_valid=0;
00041 int nicks=0, usernicks=0;
00042 int urls=0;
00043 int access=0;
00044 int held=0;
00045 time_t CTime;
00046
00047 typedef struct emaillist_struct EmailList;
00048
00049 struct emaillist_struct {
00050 char email[128];
00051 LIST_ENTRY(emaillist_struct) emails;
00052 };
00053
00054 typedef struct
00055 {
00056 char *current;
00057 char *start;
00058 } ParseState;
00059
00060 typedef struct akill Akill;
00061
00062 struct akill
00063 {
00064 time_t setat, unset;
00065 int type;
00066 LIST_ENTRY(akill) ak_lst;
00067
00068 char nick[80], user[20], host[80];
00069 char setby[80], reason[255];
00070 };
00071
00072 typedef struct urllist_struct UrlList;
00073
00074 struct urllist_struct {
00075 char url[128];
00076 LIST_ENTRY(urllist_struct) urls;
00077 };
00078
00079 typedef struct regnicklist RegNickList;
00080
00081 struct regnicklist {
00082 char nick[33];
00083 unsigned long reged;
00084 char realname[128];
00085 u_int32_t flags;
00086 LIST_ENTRY(regnicklist) users;
00087 };
00088
00089
00090 typedef struct regchanlist RegChanList;
00091
00092 struct regchanlist {
00093 char chan[255];
00094 time_t ts;
00095 u_int32_t flags, mlock;
00096 int ops, akicks;
00097
00098 LIST_ENTRY(regchanlist) chans;
00099 };
00100
00101 char *get_arg(ParseState *);
00102
00103 LIST_HEAD(,regnicklist) firstUser;
00104 LIST_HEAD(,regnicklist) heldNick;
00105 LIST_HEAD(,urllist_struct) firstUrl;
00106 LIST_HEAD(,emaillist_struct) firstEmail;
00107 LIST_HEAD(,regchanlist) chanList;
00108 LIST_HEAD(,akill) akList;
00109
00110 int chanstats()
00111 {
00112 FILE *fp;
00113 u_int thechans[33], theakicks[100], theops[200];
00114 u_int theflags[32], themlocks[32];
00115 u_int thedays[50];
00116 u_int opitems = 0, akitems = 0;
00117 u_int chans = 0, urls = 0;
00118 u_int descs = 0, munged = 0;
00119
00120 char *command;
00121 char line[1024];
00122 ParseState *state = (ParseState *)oalloc(sizeof(ParseState));
00123 int a, done = 0;
00124 RegChanList *cp = NULL;
00125
00126 for (a = 0; a < 33; a++)
00127 thechans[a] = 0;
00128
00129 for (a = 0; a < 32; a++) {
00130 theflags[a] = 0;
00131 themlocks[a] = 0;
00132 }
00133
00134 for(a = 0; a < 50; a++)
00135 thedays[a] = 0;
00136
00137 for(a = 0; a < 100; a++)
00138 theakicks[a] = 0;
00139
00140 for(a = 0; a < 200; a++)
00141 theops[a] = 0;
00142
00143 fp = fopen("chanserv/chanserv.db", "r");
00144 if(!fp)
00145 exit(-1);
00146 while(!done) {
00147 if (!(sfgets(line, 1024, fp))) {
00148 done = 1;
00149 break;
00150 }
00151 state->current = state->start = line;
00152 command = get_arg(state);
00153 if(!strcmp(command, "channel")) {
00154 cp = oalloc(sizeof(RegChanList));
00155 command = get_arg(state);
00156
00157 strncpy(cp->chan, command, 255);
00158 cp->chan[254] = '\0';
00159
00160 thechans[MAX(0, MIN(32, strlen(cp->chan) - 1))]++;
00161
00162
00163 command = get_arg(state);
00164 if (command && command[0] == '-')
00165 munged++;
00166
00167 command = get_arg(state);
00168 cp->mlock = strtoul(command, (char **)0, 10);
00169
00170 command = get_arg(state);
00171 cp->flags = strtoul(command, (char **)0, 10);
00172
00173 get_arg(state);
00174 get_arg(state);
00175 command = get_arg(state);
00176 get_arg(state);
00177 get_arg(state);
00178 get_arg(state);
00179 get_arg(state);
00180 get_arg(state);
00181 command = get_arg(state);
00182 if (command && *command && command[1])
00183 descs++;
00184
00185 cp->ts = atoi(command);
00186
00187 LIST_INSERT_HEAD(&chanList, cp, chans);
00188 chans++;
00189 }
00190 else if (!strcmp(command, "url")) {
00191 urls++;
00192 }
00193 else if (!strcmp(command, "desc")) {
00194 descs++;
00195 }
00196 else if(!strcmp(command, "op")) {
00197 if (cp)
00198 cp->ops++;
00199 opitems++;
00200 }
00201 else if(!strcmp(command, "akick")) {
00202 if (cp)
00203 cp->akicks++;
00204 akitems++;
00205 }
00206 }
00207
00208 for(cp = LIST_FIRST(&chanList); cp; cp = LIST_NEXT(cp, chans))
00209 {
00210 time_t workingtime = (CTime - cp->ts);
00211 int dayssince = ((3600*24*15) - workingtime) / (3600*24);
00212
00213 thedays[MIN(15, MAX(0, dayssince))]++;
00214 theops[MIN(199, cp->ops)]++;
00215 theakicks[MIN(99, cp->akicks)]++;
00216 for(a = 0; a < 32; a++) {
00217 if (cp->flags & (1 << a))
00218 theflags[a]++;
00219 if (cp->mlock & (1 << a))
00220 themlocks[a]++;
00221 }
00222 }
00223
00224 printf("<chanstats time=\"%ld\" total=\"%i\"\n numurls=\"%i\" numdescs=\"%i\" opitems=\"%i\" akitems=\"%i\" munged=\"%i\">\n", CTime, chans,
00225 urls, descs, opitems, akitems, munged);
00226
00227 printf(" <expirelens>\n ");
00228 for(a = 0; a < 15; a++)
00229 {
00230 printf(" <explen i=\"%i\" val=\"%i\" />", a, thedays[a]);
00231 if (((a+1) % 2) == 0)
00232 printf("\n ");
00233
00234 }
00235 printf("\n </expirelens>\n");
00236
00237 printf(" <opcts>\n ");
00238 for(a = 0; a < 200; a++)
00239 {
00240 printf(" <opct i=\"%i\" val=\"%i\" />", a, theops[a]);
00241 if (((a+1) % 2) == 0)
00242 printf("\n ");
00243
00244 }
00245 if (((a) % 2) != 0)
00246 printf("\n ");
00247 printf("</opcts>\n");
00248
00249 printf(" <bancts>\n ");
00250 for(a = 0; a < 100; a++)
00251 {
00252 printf(" <banct i=\"%i\" val=\"%i\" />", a, theakicks[a]);
00253 if (((a+1) % 2) == 0)
00254 printf("\n ");
00255
00256 }
00257 if (((a) % 2) != 0)
00258 printf("\n ");
00259 printf("</bancts>\n");
00260
00261
00262 printf(" <flagcts>\n ");
00263 for(a = 0; a < 32; a++)
00264 {
00265 printf(" <flagct i=\"%i\" val=\"%i\" />", a, theflags[a]);
00266 if (((a+1) % 2) == 0)
00267 printf("\n ");
00268
00269 }
00270 if (((a) % 2) != 0)
00271 printf("\n ");
00272 printf("</flagcts>\n");
00273
00274
00275 printf(" <mlockcts>\n ");
00276 for(a = 0; a < 32; a++)
00277 {
00278 printf(" <mlockct i=\"%i\" val=\"%i\" />", a, themlocks[a]);
00279 if (((a+1) % 2) == 0)
00280 printf("\n ");
00281
00282 }
00283 if (((a) % 2) != 0)
00284 printf("\n ");
00285 printf("</mlockcts>\n");
00286
00287 for(cp = LIST_FIRST(&chanList); cp; cp = LIST_NEXT(cp, chans))
00288 {
00289 if ( cp->flags & CBANISH)
00290 printf("<banchan>%s</banchan>\n", cp->chan);
00291 else if ( cp->flags & CCLOSE )
00292 printf("<closedchan>%s</closedchan>\n", cp->chan);
00293 if ( cp->flags & CHOLD)
00294 printf("<heldchan>%s</heldchan>\n", cp->chan);
00295 }
00296
00297 printf("</chanstats>\n");
00298 fclose(fp);
00299 }
00300
00301 int hasWild(char *s)
00302 {
00303 while(*s) {
00304 if (*s == '?' || *s == '*')
00305 return 1;
00306 s++;
00307 }
00308 return 0;
00309 }
00310
00311 int hasNonWild(char *s)
00312 {
00313 while(*s) {
00314 if (*s != '?' || *s != '*')
00315 return 1;
00316 s++;
00317 }
00318 return 0;
00319 }
00320
00321 char *knock(char *h)
00322 {
00323 return (h = strchr(h, '.')) ? h + 1 : NULL;
00324 }
00325
00326 char *domain(char *h)
00327 {
00328 char *htmp;
00329
00330 while((htmp = knock(h)) != NULL)
00331 h = htmp;
00332 return h;
00333 }
00334
00335 int countDots(char *x)
00336 {
00337 int dots = 0;
00338
00339 while(*x)
00340 {
00341 if (*x == '.')
00342 dots++;
00343 x++;
00344 }
00345 return dots;
00346 }
00347
00348 int banType(char *n, char *u, char *h)
00349 {
00350 if (!hasWild(n))
00351 return 1;
00352 if (hasNonWild(u))
00353 return 2;
00354 if (!hasWild(h) && *h == '*' && countDots(h) <= 3)
00355 return 3;
00356 return 4;
00357 }
00358
00359 int akillstats(void)
00360 {
00361 int bans[4][10] = {0}, i = 0, a = 0;
00362 int mm[] = { 0,0,1,2,2,3,3,3,3,4 };
00363 char *xx[] = { "akill", "ignore", "ahurt" };
00364
00365 char line[1024];
00366 Akill *ak;
00367 FILE *fp;
00368
00369 fp = fopen("operserv/akill.db", "r");
00370
00371 if (!fp)
00372 return -1;
00373
00374 while(sfgets(line, 256, fp))
00375 {
00376 i++;
00377
00378 if (strcmp(line, "-") != 0)
00379 return -1;
00380 ak = (struct akill*)oalloc(sizeof(Akill));
00381 sfgets(line, 256, fp);
00382 if (*line == '#')
00383 sfgets(line, 256, fp);
00384 strncpyzt(ak->nick, line, sizeof(ak->nick));
00385
00386 sfgets(line, 256, fp);
00387 strncpyzt(ak->user, line, sizeof(ak->user));
00388
00389 sfgets(line, 256, fp);
00390 strncpyzt(ak->host, line, sizeof(ak->host));
00391
00392 sfgets(line, 256, fp);
00393 sscanf(line, "%d %d", &ak->setat, &ak->unset);
00394
00395 sfgets(line, 256, fp);
00396 strncpyzt(ak->setby, line, sizeof(ak->setby));
00397
00398 sfgets(line, 256, fp);
00399 strncpyzt(ak->reason, line, sizeof(ak->reason));
00400
00401 sfgets(line, 256, fp);
00402 ak->type = atoi(line);
00403 LIST_INSERT_HEAD(&akList, ak, ak_lst);
00404 }
00405
00406 for(ak = LIST_FIRST(&akList); ak; ak = LIST_NEXT(ak, ak_lst))
00407 {
00408 bans[mm[ak->type]][0]++;
00409 bans[mm[ak->type]][banType(ak->nick,ak->user,ak->host)]++;
00410 }
00411
00412 printf("<akillstats akills=\"%i\" ignores=\"%i\" ahurts=\"%i\">\n",
00413 bans[0][0], bans[1][0], bans[2][0]);
00414 for(i = 0; i < 3; i++) {
00415 printf("<s-%s-site count=\"%i\" />", xx[i], bans[i][4]);
00416 printf("<s-%s-host count=\"%i\" />\n", xx[i], bans[i][3]);
00417 printf("<s-%s-user count=\"%i\" />", xx[i], bans[i][2]);
00418 printf("<s-%s-nick count=\"%i\" />\n", xx[i], bans[i][1]);
00419 }
00420
00421 printf("</akillstats>\n");
00422
00423 fclose(fp);
00424 }
00425
00426 int nickstats(void)
00427 {
00428 RegNickList *read;
00429 RegNickList *read2;
00430 u_long totalnicklen=0;
00431 u_long totalurllen=0;
00432 u_long totalemail=0;
00433 u_long totalrn=0;
00434 time_t workingtime;
00435 time_t dayssince;
00436 u_int longestnick=0;
00437 u_int longesturl=0;
00438 u_int longestemail=0;
00439 u_int longestrn=0;
00440 u_int averagenick=0;
00441 u_int averageurl=0;
00442 u_int averageemail=0;
00443 u_int averagern=0;
00444 u_int thenicks[33];
00445 u_int thedays[50];
00446 UrlList *url;
00447 EmailList *email2;
00448 ParseState *state = (ParseState *)oalloc(sizeof(ParseState));
00449 char *command;
00450 char line[1024];
00451 FILE *fp;
00452 int done = 0;
00453 int a, i = 0;
00454
00455 for (a = 0; a < 33; a++)
00456 thenicks[a] = 0;
00457
00458 for(a = 0; a < 50; a++)
00459 thedays[a] = 0;
00460
00461 fp = fopen("nickserv/nickserv.db", "r");
00462 if(!fp)
00463 exit(-1);
00464 while(!done) {
00465 if (!(sfgets(line, 1024, fp))) {
00466 done = 1;
00467 break;
00468 }
00469
00470 state->current = state->start = line;
00471 command = get_arg(state);
00472 if(!strcmp(command, "nick")) {
00473 read = (RegNickList *)oalloc(sizeof(RegNickList));
00474 LIST_INSERT_HEAD(&firstUser, read, users);
00475 strcpy(read->nick, get_arg(state));
00476 get_arg(state);
00477 get_arg(state);
00478 get_arg(state);
00479 read->reged = atol(get_arg(state));
00480 get_arg(state);
00481 read->flags = atoi(get_arg(state));
00482 strcpy(read->realname, state->current);
00483 if (!(read->flags & (NBANISH|NHOLD)))
00484 usernicks++;
00485 nicks++;
00486 }
00487 else if(!strcmp(command, "url")) {
00488 url = (UrlList *)oalloc(sizeof(UrlList));
00489 LIST_INSERT_HEAD(&firstUrl, url, urls);
00490 get_arg(state);
00491 strncpy(url->url, get_arg(state), 128);
00492 urls++;
00493 }
00494 else if(!strcmp(command, "access")) {
00495 access++;
00496 }
00497 else if(!strcmp(command, "email")) {
00498 if (!(read->flags & (NBANISH|NHOLD))) {
00499 email2 = (EmailList *)oalloc(sizeof(EmailList));
00500 LIST_INSERT_HEAD(&firstEmail, email2, emails);
00501 get_arg(state);
00502 strcpy(email2->email, get_arg(state));
00503 email++;
00504 if (strncmp(email2->email, "(none)", 6))
00505 email_valid++;
00506 }
00507 }
00508 else if(!strcmp(command, "done"))
00509 done = 1;
00510 }
00511
00512 fclose(fp);
00513 printf("<nickstats time=\"%ld\" total=\"%i\"\n numurls=\"%i\" accitems=\"%i\" numemails=\"%i\">\n", CTime, nicks, urls, access, email);
00514 for(read = firstUser.lh_first;read;read = read->users.le_next) {
00515 if(read->flags & NBANISH || read->flags & NHOLD) {
00516 read2 = (RegNickList *)oalloc(sizeof(RegNickList));
00517 LIST_INSERT_HEAD(&heldNick, read2, users);
00518 strcpy(read2->nick, read->nick);
00519 read2->flags = read->flags;
00520
00521 held++;
00522 }
00523 else {
00524 if(read->flags & NVACATION)
00525 workingtime = (CTime - read->reged)/2;
00526 else
00527 workingtime=CTime - read->reged;
00528 dayssince = ((60*60*24*25) - workingtime) / (60*60*24);
00529 thedays[dayssince]++;
00530 }
00531 thenicks[strlen(read->nick) - 1]++;
00532 totalnicklen = totalnicklen + strlen(read->nick);
00533 if (strlen(read->nick) > longestnick)
00534 longestnick = strlen(read->nick);
00535 if (strlen(read->realname) > longestrn)
00536 longestrn = strlen(read->realname);
00537 totalrn = totalrn + strlen(read->realname);
00538 }
00539
00540 for(email2 = firstEmail.lh_first;email2;email2 = email2->emails.le_next) {
00541 if(strlen(email2->email) > longestemail)
00542 longestemail = strlen(email2->email);
00543 totalemail = totalemail + strlen(email2->email);
00544 }
00545 for(url = firstUrl.lh_first;url;url = url->urls.le_next) {
00546 totalurllen = totalurllen + strlen(url->url);
00547 if (strlen(url->url) > longesturl)
00548 longesturl = strlen(url->url);
00549 }
00550
00551 averagenick = totalnicklen / NZERO(nicks);
00552 averageurl = totalurllen / NZERO(urls);
00553 averageemail = totalemail / NZERO(email);
00554 averagern = totalrn / NZERO(nicks);
00555 printf(" <emails valid=\"%i\" none=\"%i\" count=\"%i\" />\n", email_valid, email - email_valid, nicks - email);
00556 printf(" <nicklength longest=\"%i\" average=\"%i\" />\n", longestnick, averagenick);
00557 printf(" <urllength longest=\"%i\" average=\"%i\" />\n", longesturl, averageurl);
00558 printf(" <emaillength longest=\"%i\" average=\"%i\" />\n", longestemail, averageemail);
00559 printf(" <reallen longest=\"%i\" average=\"%i\" />\n", longestrn, averagern);
00560 printf(" <nicklens>\n");
00561 for(i = 0; i < 17; i++) {
00562 printf(" <nicklen i=\"%i\" val=\"%i\" /> ", i, thenicks[i]);
00563 if (((i+1) % 2) == 0)
00564 printf("\n");
00565 }
00566 printf(" </nicklens>\n");
00567 printf(" <expirelens>\n");
00568 for(i = 0; i < 25; i++) {
00569 printf(" <explen i=\"%i\" val=\"%i\" /> ", i, thedays[i]);
00570 if (((i+1) % 2) == 0)
00571 printf("\n");
00572 }
00573 printf(" </expirelens>\n");
00574
00575 for(read = heldNick.lh_first;read;read = read->users.le_next) {
00576 if (!(read->flags & NBANISH))
00577 printf(" <heldnick>%s</heldnick>\n", read->nick);
00578 }
00579 for(read = heldNick.lh_first;read;read = read->users.le_next) {
00580 if ((read->flags & NBANISH))
00581 printf(" <bannick>%s</bannick>\n", read->nick);
00582 }
00583 printf("\n");
00584
00585 #ifdef MAILSTAT_WRITE
00586 if (nicks && (fp = fopen("emailstats", "a")))
00587 {
00588
00589 #define PC(x, y) (((100*(x))/y) + (((100*(x))%y > (y/2)) ? 1 : 0))
00590 fprintf(fp, "[%ld]\n", CTime);
00591 fprintf(fp, "E-mail addies : %5i(%3d%%) * Elected to set none : %5i(%3d%%)\n", email_valid, PC(email_valid, usernicks), email - email_valid, PC(email - email_valid, usernicks));
00592 fprintf(fp, "Neglected e-mail field : %5i(%3d%%) * Nicks : %5i/%5i\n", usernicks - email, PC(usernicks - email, usernicks), usernicks, nicks - usernicks);
00593 fflush(fp);
00594 fclose(fp);
00595 }
00596 #endif
00597
00598 #ifdef GNUPLOT_DAT
00599 fp = fopen("NickExpire.dat", "w");
00600 for (a = 0; a < 25 ; a++) {
00601 fprintf(fp, "%d %d\n", a+1, thedays[a]);
00602 fflush(fp);
00603 }
00604 fclose(fp);
00605 fp = fopen("NickLength.dat", "w");
00606 for(a = 0; a < 17; a++) {
00607 fprintf(fp, "%d %d\n", a+1, thenicks[a]);
00608 fflush(fp);
00609 }
00610 fclose(fp);
00611 #endif
00612 printf("</nickstats>\n");
00613
00614 }
00615
00616 int
00617 main(void)
00618 {
00619 CTime = time(NULL);
00620
00621 printf("<statsrun time=\"%ld\">\n", CTime);
00622 nickstats();
00623 chanstats();
00624 akillstats();
00625 printf("</statsrun>\n");
00626
00627 return 0;
00628 }
00629
00630 char *
00631 sfgets(char *str, int len, FILE *fp)
00632 {
00633 if(!fgets(str, len, fp))
00634 return NULL;
00635 else {
00636 if(str[0])
00637 str[strlen(str) - 1] = 0;
00638 return str;
00639 }
00640 }
00641
00642
00643
00644
00645
00646
00647
00648
00649 void *oalloc(size_t size)
00650 {
00651 void *alloctmp = 0;
00652
00653 if (size < 1) {
00654 printf("oalloc: Error, requested size is less than 1");
00655 exit(1);
00656 }
00657
00658 alloctmp = malloc(size);
00659
00660 if (alloctmp == NULL) {
00661 printf("oalloc: Error allocating memory, terminating services\n");
00662 exit(1);
00663 }
00664
00665 memset(alloctmp, 0, size);
00666
00667 return alloctmp;
00668 }
00669
00670 char *
00671 get_arg (ParseState * state)
00672 {
00673 state->current = strsep (&state->start, " ");
00674 return state->current;
00675 }
00676
00677 char *
00678 curr_arg (ParseState * state)
00679 {
00680 return state->current;
00681 }
00682