/* user data manipulation -- separated from old 'chanprog' cos it was getting way too big */ #include #include #include #include "eggdrop.h" extern char botname[]; extern char botuser[]; extern char bothost[]; /* where the user records are stored */ char userfile[121]=""; /* are we still loading config file? (don't autosave) */ int nosave=1; /* old-style queue, still used by server list */ struct queue { char *item; struct queue *next; }; /* new-style userlist */ struct userrec { char handle[10]; struct queue *host; char pass[10]; unsigned int flags; time_t laston; struct userrec *next; char *email; char *dccdir; char *comment; char *info; } *userlist=NULL; /* flags are in eggdrop.h */ struct queue *addq(); struct queue *delq(); /* memory we should be using */ int expmem_users() { int tot; struct userrec *u=userlist; struct queue *s; tot=0; while (u!=NULL) { if (u->email!=NULL) tot+=strlen(u->email)+1; if (u->dccdir!=NULL) tot+=strlen(u->dccdir)+1; if (u->comment!=NULL) tot+=strlen(u->comment)+1; if (u->info!=NULL) tot+=strlen(u->info)+1; s=u->host; while (s!=NULL) { tot+=strlen(s->item)+1; tot+=sizeof(struct queue); s=s->next; } tot+=sizeof(struct userrec); u=u->next; } return tot; } struct userrec *get_user_by_handle(handle) char *handle; { struct userrec *u=userlist; while (u!=NULL) { if (strcasecmp(u->handle,handle)==0) return u; u=u->next; } return NULL; } void clear_userlist() { struct userrec *u=userlist,*v; while (u!=NULL) { clearq(u->host); if (u->email!=NULL) nfree(u->email); if (u->dccdir!=NULL) nfree(u->dccdir); if (u->comment!=NULL) nfree(u->comment); if (u->info!=NULL) nfree(u->info); v=u->next; nfree(u); u=v; } userlist=NULL; } /* find CLOSEST host match */ /* (if "*!*@*" and "*!*@*clemson.edu" both match, use the latter!) */ struct userrec *get_user_by_host(host) char *host; { struct userrec *u=userlist,*ret; struct queue *q; int cnt,i; ret=NULL; cnt=0; while (u!=NULL) { q=u->host; while (q!=NULL) { i=wild_match(q->item,host); if (i>cnt) { ret=u; cnt=i; } q=q->next; } u=u->next; } return ret; } void get_handle_by_host(nick,host) char *nick,*host; { struct userrec *u; u=get_user_by_host(host); if (u==NULL) { nick[0]='*'; nick[1]=0; return; } strcpy(nick,u->handle); } struct userrec *get_user_by_equal_host(host) char *host; { struct userrec *u=userlist; struct queue *q; while (u!=NULL) { q=u->host; while (q!=NULL) { if (strcasecmp(q->item,host)==0) return u; q=q->next; } u=u->next; } return NULL; } /* try: pass_match_by_host("nopass",host) will return 1 if no password is set for that host */ int pass_match_by_host(pass,host) char *pass,*host; { struct userrec *u; u=get_user_by_host(host); if (u==NULL) return 0; if (strcasecmp(u->pass,"nopass")==0) return 1; if (strcasecmp(u->pass,pass)!=0) return 0; else return 1; } int pass_match_by_handle(pass,handle) char *pass,*handle; { struct userrec *u; u=get_user_by_handle(handle); if (u==NULL) return 0; if (strcasecmp(u->pass,"nopass")==0) return 1; if (strcasecmp(u->pass,pass)!=0) return 0; else return 1; } void write_user(u,f) struct userrec *u; FILE *f; { char host[81],s[121]; struct queue *q; if (u->flags&USER_PURGE) { u->flags&=(~USER_PURGE); return; } s[0]=0; if (u->flags&USER_OP) strcat(s,"o"); if (u->flags&USER_DEOP) strcat(s,"d"); if (u->flags&USER_BAN) strcat(s,"b"); if (u->flags&USER_KICK) strcat(s,"k"); if (u->flags&USER_MASTER) strcat(s,"m"); if (u->flags&USER_FRIEND) strcat(s,"f"); if (u->flags&USER_XFER) strcat(s,"x"); if (u->flags&USER_IGNORE) strcat(s,"i"); if (u->flags&USER_TANDEM) strcat(s,"t"); if (s[0]==0) strcat(s,"-"); strcpy(host,u->host->item); fprintf(f,"%-10s%-40s%-10s%-10s%lu\n",u->handle,host,u->pass,s,u->laston); s[0]=0; q=u->host->next; while (q!=NULL) { if (!s[0]) sprintf(s,"%-10s%s","-",q->item); else { if (strlen(s)+strlen(q->item)+2>70) { fprintf(f,"%s\n",s); sprintf(s,"%-10s%s","-",q->item); } else { strcat(s,", "); strcat(s,q->item); } } q=q->next; } if (s[0]) fprintf(f,"%s\n",s); if (u->email!=NULL) fprintf(f,"%-10s%s\n","+",u->email); if (u->dccdir!=NULL) fprintf(f,"%-10s%s\n","*",u->dccdir); if (u->comment!=NULL) fprintf(f,"%-10s%s\n","=",u->comment); if (u->info!=NULL) fprintf(f,"%-10s%s\n",":",u->info); } void save_user(u) struct userrec *u; { FILE *fi,*fo; char s[121],handle[20]; int wrote=0,usec=0; sprintf(s,"%s~new",userfile); fi=fopen(userfile,"r"); fo=fopen(s,"w"); if (fo==NULL) { console("ERROR in writing save file."); return; } if (fi==NULL) { /* create new data file */ fprintf(fo,"# users data file\n\n"); write_user(u,fo); fclose(fo); sprintf(s,"mv %s~new %s",userfile,userfile); system(s); return; } /* now find the right user */ while (!feof(fi)) { fgets(s,120,fi); if (s[strlen(s)-1]=='\n') s[strlen(s)-1]=0; if (!feof(fi)) { if ((s[0]=='#') || (s[0]==';')) fprintf(fo,"%s\n",s); else { split(handle,s); rmspace(handle); rmspace(s); if (strcasecmp(u->handle,handle)==0) { /* this is us! */ wrote=2; write_user(u,fo); } else if ((handle[0]=='-') || (handle[0]=='+') || (handle[0]=='*') || (handle[0]=='=') || (handle[0]==':')) { if (wrote!=2) fprintf(fo,"%-10s%s\n",handle,s); } else { if (wrote==2) wrote=1; fprintf(fo,"%-10s%s\n",handle,s); } } } } if (!wrote) write_user(u,fo); if (!feof(fi)) { while (!feof(fi)) { fgets(s,120,fi); if (s[strlen(s)-1]=='\n') s[strlen(s)-1]=0; if (!feof(fi)) fprintf(fo,"%s\n",s); } } fclose(fi); fclose(fo); sprintf(s,"mv %s~new %s",userfile,userfile); system(s); } void purge_user(u) struct userrec *u; { u->flags|=USER_PURGE; save_user(u); } void change_pass_by_handle(handle,pass) char *handle,*pass; { struct userrec *u; u=get_user_by_handle(handle); if (u==NULL) return; strcpy(u->pass,pass); save_user(u); } void change_pass_by_host(host,pass) char *host,*pass; { struct userrec *u; u=get_user_by_host(host); if (u==NULL) return; strcpy(u->pass,pass); save_user(u); } void change_handle(oldh,newh) char *oldh,*newh; { struct userrec *u; u=get_user_by_handle(oldh); if (u==NULL) return; purge_user(u); strcpy(u->handle,newh); save_user(u); } void adduser(handle,host,pass,flags) char *handle,*host,*pass; int flags; { struct userrec *u; u=(struct userrec *)nmalloc(sizeof(struct userrec)); u->next=userlist; userlist=u; strcpy(u->handle,handle); strcpy(u->pass,pass); u->host=addq(host,NULL); u->flags=flags; u->laston=0L; u->email=NULL; u->dccdir=NULL; u->comment=NULL; if (!nosave) save_user(u); } int deluser(handle) char *handle; { struct userrec *u=userlist,*prev=NULL; int fnd=0; while ((u!=NULL) && (!fnd)) { if (strcasecmp(u->handle,handle)==0) fnd=1; else { prev=u; u=u->next; } } if (!fnd) return 0; if (prev==NULL) userlist=u->next; else prev->next=u->next; if (!nosave) purge_user(u); clearq(u->host); if (u->email!=NULL) nfree(u->email); if (u->dccdir!=NULL) nfree(u->dccdir); if (u->comment!=NULL) nfree(u->comment); nfree(u); return 1; } int delhost_by_handle(handle,host) char *handle,*host; { struct userrec *u; int i; u=get_user_by_handle(handle); if (u==NULL) return 0; u->host=delq(host,u->host,&i); if ((!nosave) && (i)) save_user(u); return i; } void addhost_by_handle(handle,host) char *handle,*host; { struct userrec *u; u=get_user_by_handle(handle); if (u==NULL) return; u->host=addq(host,u->host); if (!nosave) save_user(u); } void addhost_by_host(matchhost,host) char *matchhost,*host; { struct userrec *u; u=get_user_by_host(matchhost); if (u==NULL) return; u->host=addq(host,u->host); if (!nosave) save_user(u); } void set_handle_email(handle,email) char *handle,*email; { struct userrec *u; u=get_user_by_handle(handle); if (u==NULL) return; if (u->email!=NULL) nfree(u->email); if (email[0]) { u->email=(char *)nmalloc(strlen(email)+1); strcpy(u->email,email); } else u->email=NULL; if (!nosave) save_user(u); } void get_handle_email(handle,s) char *handle; char *s; { struct userrec *u; u=get_user_by_handle(handle); if (u==NULL) { s[0]=0; return; } if (u->email==NULL) { s[0]=0; return; } strcpy(s,u->email); return; } void get_handle_dccdir(handle,s) char *handle; char *s; { struct userrec *u; u=get_user_by_handle(handle); if (u==NULL) { s[0]=0; return; } if (u->dccdir==NULL) { s[0]=0; return; } strcpy(s,u->dccdir); return; } void get_handle_comment(handle,s) char *handle; char *s; { struct userrec *u; u=get_user_by_handle(handle); if (u==NULL) { s[0]=0; return; } if (u->comment==NULL) { s[0]=0; return; } strcpy(s,u->comment); return; } void get_handle_info(handle,s) char *handle; char *s; { struct userrec *u; u=get_user_by_handle(handle); if (u==NULL) { s[0]=0; return; } if (u->info==NULL) { s[0]=0; return; } strcpy(s,u->info); return; } void set_handle_dccdir(handle,dir) char *handle,*dir; { struct userrec *u; if (strlen(dir)>80) dir[80]=0; u=get_user_by_handle(handle); if (u==NULL) return; if (u->dccdir!=NULL) nfree(u->dccdir); u->dccdir=(char *)nmalloc(strlen(dir)+1); strcpy(u->dccdir,dir); if (!nosave) save_user(u); } void set_handle_comment(handle,comment) char *handle,*comment; { struct userrec *u; if (strlen(comment)>80) comment[80]=0; u=get_user_by_handle(handle); if (u==NULL) return; if (u->comment!=NULL) nfree(u->comment); if (comment[0]) { u->comment=(char *)nmalloc(strlen(comment)+1); strcpy(u->comment,comment); } else u->comment=NULL; if (!nosave) save_user(u); } void set_handle_info(handle,info) char *handle,*info; { struct userrec *u; if (strlen(info)>80) info[80]=0; u=get_user_by_handle(handle); if (u==NULL) return; if (u->info!=NULL) nfree(u->info); if (info[0]) { u->info=(char *)nmalloc(strlen(info)+1); strcpy(u->info,info); } else u->info=NULL; if (!nosave) save_user(u); } int chg_attr_u(u,chg,which) struct userrec *u; char chg; int which; { if (u==NULL) return 0; if (chg=='+') { if (u->flags&which) return 0; u->flags |= which; if (!nosave) save_user(u); return 1; } else { if (!(u->flags&which)) return 0; u->flags &= ~which; if (!nosave) save_user(u); return 1; } } int chg_attr_by_handle(handle,chg,which) char *handle,chg; int which; { struct userrec *u; u=get_user_by_handle(handle); return chg_attr_u(u,chg,which); } int chg_attr_by_host(host,chg,which) char *host,chg; int which; { struct userrec *u; u=get_user_by_host(host); return chg_attr_u(u,chg,which); } /* return 1 if it was successful */ /* change attr by handle or host (depending on whether ident has '@') */ int change_attr(ident,chg,which) char *ident,chg; int which; { if (strchr(ident,'@')==NULL) { /* handle? */ return chg_attr_by_handle(ident,chg,which); } else return chg_attr_by_host(ident,chg,which); } int prog_deop(s) char *s; { return chg_attr_by_host(s,'+',USER_DEOP); } int unprog_deop(s) char *s; { return chg_attr_by_host(s,'-',USER_DEOP); } int prog_op(s) char *s; { return chg_attr_by_host(s,'+',USER_OP); } int unprog_op(s) char *s; { return chg_attr_by_host(s,'-',USER_OP); } int prog_master(s) char *s; { return chg_attr_by_host(s,'+',USER_MASTER); } int unprog_master(s) char *s; { return chg_attr_by_host(s,'-',USER_MASTER); } int prog_kick(s) char *s; { return chg_attr_by_host(s,'+',USER_KICK); } int unprog_kick(s) char *s; { return chg_attr_by_host(s,'-',USER_KICK); } int prog_friend(s) char *s; { return chg_attr_by_host(s,'+',USER_FRIEND); } int unprog_friend(s) char *s; { return chg_attr_by_host(s,'-',USER_FRIEND); } int match_attr_handle(handle,which) char *handle; int which; { struct userrec *u; u=get_user_by_handle(handle); if (u==NULL) return 0; if (u->flags&which) return 1; else return 0; } int match_attr(host,which) char *host; int which; { struct userrec *u; u=get_user_by_host(host); if (u==NULL) return 0; if (u->flags&which) return 1; else return 0; } int match_op(user) char *user; { return match_attr(user,USER_OP); } int match_deop(user) char *user; { return match_attr(user,USER_DEOP); } int match_ban(user) char *user; { return match_attr(user,USER_BAN); } int match_kick(user) char *user; { return match_attr(user,USER_KICK); } int match_master(user) char *user; { return match_attr(user,USER_MASTER); } int match_friend(user) char *user; { return match_attr(user,USER_FRIEND); } int match_xfer(user) char *user; { return match_attr(user,USER_XFER); } int match_tandem(user) char *user; { return match_tandem(user,USER_TANDEM); } int match_ignore(user) char *user; { struct userrec *u; struct queue *q; u=get_user_by_handle("ignore"); if (u==NULL) return 0; q=u->host; while (q!=NULL) { if (wild_match(q->item,user)) return 1; q=q->next; } return 0; } int equals_ban(user) char *user; { struct userrec *u; u=get_user_by_equal_host(user); if (u==NULL) return 0; if (u->flags&USER_BAN) return 1; else return 0; } void prog_ban(who) char *who; { struct userrec *u; char s[121]; sprintf(s,"%s!%s@%s",botname,botuser,bothost); if (wild_match(who,s)) { console("Wanted to deop myself: deflected."); return; } u=get_user_by_handle("ban"); if (u==NULL) { adduser("ban",who,"nopass",USER_BAN); return; } u->host=addq(who,u->host); save_user(u); } void prog_ignore(who) char *who; { struct userrec *u; char s[121]; u=get_user_by_handle("ignore"); if (u==NULL) { adduser("ignore",who,"nopass",USER_IGNORE); return; } u->host=addq(who,u->host); save_user(u); } int unprog_ban(who) char *who; { struct userrec *u; int i,j; struct queue *q; u=get_user_by_handle("ban"); if (u==NULL) return 0; if (atoi(who)) { j=atoi(who)-1; q=u->host; while (j>0) { if (q!=NULL) q=q->next; j--; } if (q!=NULL) { strcpy(who,q->item); u->host=delq(q->item,u->host,&i); } } else u->host=delq(who,u->host,&i); if (i) { if (u->host!=NULL) save_user(u); else deluser("ban"); } return i; } int unprog_ignore(who) char *who; { struct userrec *u; int i,j; struct queue *q; u=get_user_by_handle("ignore"); if (u==NULL) return 0; if (atoi(who)) { j=atoi(who)-1; q=u->host; while (j>0) { if (q!=NULL) q=q->next; j--; } if (q!=NULL) { strcpy(who,q->item); u->host=delq(q->item,u->host,&i); } } else u->host=delq(who,u->host,&i); if (i) { if (u->host != NULL) save_user(u); else deluser("ignore"); } return i; } void tell_bans(z) { struct userrec *u; struct queue *q; int i=1; u=get_user_by_handle("ban"); if (u==NULL) { tprintf(z,"No permanent bans.\n"); return; } q=u->host; if (q==NULL) tprintf(z,"No bans.\n"); while (q!=NULL) { tprintf(z,"Ban[%2d]: %s\n",i++,q->item); q=q->next; } } void tell_ignores(z) { struct userrec *u; struct queue *q; int i=1; u=get_user_by_handle("ignore"); if (u==NULL) { tprintf(z,"No ignores.\n"); return; } q=u->host; if (q==NULL) tprintf(z,"No ignores.\n"); while (q!=NULL) { tprintf(z,"Ignore[%2d]: %s\n",i++,q->item); q=q->next; } } /* update a user's last signon, by host */ void update_laston(host) char *host; { struct userrec *u; u=get_user_by_host(host); if (u==NULL) return; u->laston=time(NULL); if (!nosave) save_user(u); } void touch_user(nick,n) char *nick; time_t n; { struct userrec *u; u=get_user_by_handle(nick); if (u==NULL) return; u->laston=n; if (!nosave) save_user(u); } /* since i was getting a ban list, i assume i'm chop */ /* recheck_bans makes sure that all who are 'banned' on the userlist are actually in fact banned on the channel */ void recheck_bans() { struct userrec *u=userlist; struct queue *q; while (u!=NULL) { if (u->flags&USER_BAN) { q=u->host; while (q!=NULL) { if (!isbanned(q->item)) add_ban(q->item); q=q->next; } } u=u->next; } flush_ban(); } void tell_user(z,u) int z; struct userrec *u; { char s[81],s1[81]; struct queue *q; time_t now; s[0]=0; if (u->flags&USER_OP) strcat(s,"o"); if (u->flags&USER_DEOP) strcat(s,"d"); if (u->flags&USER_BAN) strcat(s,"b"); if (u->flags&USER_KICK) strcat(s,"k"); if (u->flags&USER_MASTER) strcat(s,"m"); if (u->flags&USER_FRIEND) strcat(s,"f"); if (u->flags&USER_XFER) strcat(s,"x"); if (u->flags&USER_IGNORE) strcat(s,"i"); if (u->flags&USER_TANDEM) strcat(s,"t"); if (u->laston == 0L) strcpy(s1,"never"); else { now=time(NULL)-(u->laston); strcpy(s1,ctime(&(u->laston))); if (now>86400) { s1[7]=0; strcpy(&s1[11],&s1[4]); strcpy(s1,&s1[8]); } else { s1[16]=0; strcpy(s1,&s1[11]); } } tprintf(z,"%-10s%-40s%-10s%-10s%s\n",u->handle,u->host->item,u->pass, s,s1); s[0]=0; q=u->host->next; while (q!=NULL) { if (!s[0]) sprintf(s," %s",q->item); else { if (strlen(s)+strlen(q->item)+2>70) { tprintf(z,"%s\n",s); sprintf(s," %s",q->item); } else { strcat(s,", "); strcat(s,q->item); } } q=q->next; } if (s[0]) tprintf(z,"%s\n",s); if (u->comment!=NULL) tprintf(z," COMMENT: %s\n",u->comment); if (u->email!=NULL) tprintf(z," EMAIL: %s\n",u->email); if (u->info!=NULL) tprintf(z," INFO: %s\n",u->info); } /* show user by ident */ void tell_user_ident(z,id) int z; char *id; { struct userrec *u; u=get_user_by_handle(id); if (u==NULL) u=get_user_by_host(id); if (u==NULL) { tprintf(z,"Can't find anyone matching that.\n"); return; } tprintf(z,"%-10s%-40s%-10s%-10s%-10s\n","HANDLE","HOSTMASK(S)","PASS", "ATTR","LAST"); tell_user(z,u); } /* show all the lists to a dcc-chat person */ /* under new format: give user list */ void tell_lists(z) int z; { struct userrec *u=userlist; tprintf(z,"%-10s%-40s%-10s%-10s%-10s\n","HANDLE","HOSTMASK(S)","PASS", "ATTR","LAST"); while (u!=NULL) { tell_user(z,u); u=u->next; } tprintf(z,"--- End of user list.\n"); } /* show the list of masters */ /* match string: wildcard to match nickname or hostmasks */ /* +attr to find all with attr */ void tell_users_match(z,mtch) int z; char *mtch; { struct userrec *u=userlist; int fnd=0,i,cnt; struct queue *q; tprintf(z,"*** Matching '%s':\n",mtch); cnt=0; tprintf(z,"%-10s%-40s%-10s%-10s%-10s\n","HANDLE","HOSTMASK(S)","PASS", "ATTR","LAST"); while (u!=NULL) { if (mtch[0]=='+') { fnd=0; for (i=1; mtch[i]!=0; i++) { if (mtch[i]=='o') fnd|=USER_OP; if (mtch[i]=='d') fnd|=USER_DEOP; if (mtch[i]=='b') fnd|=USER_BAN; if (mtch[i]=='k') fnd|=USER_KICK; if (mtch[i]=='m') fnd|=USER_MASTER; if (mtch[i]=='f') fnd|=USER_FRIEND; if (mtch[i]=='x') fnd|=USER_XFER; if (mtch[i]=='i') fnd|=USER_IGNORE; if (mtch[i]=='t') fnd|=USER_TANDEM; } if (u->flags&fnd) { tell_user(z,u); cnt++; } } else if (wild_match(mtch,u->handle)) { tell_user(z,u); cnt++; } else { fnd=0; q=u->host; while (q!=NULL) { if ((wild_match(mtch,q->item)) && (!fnd)) { tell_user(z,u); fnd=1; cnt++; } q=q->next; } } u=u->next; } tprintf(z,"--- Found %d match%s.\n",cnt,cnt==1?"":"es"); } int readuserfile(file) char *file; { char *p,s[121],lasthand[20],host[41],attr[20],pass[20],code[41]; FILE *f; int flags,i; lasthand[0]=0; f=fopen(file,"r"); if (f==NULL) return 0; nosave=1; while (!feof(f)) { fgets(s,120,f); if (!feof(f)) { p=strchr(s,';'); if (p!=NULL) *p=0; rmspace(s); if ((s[0]!='#') && (s[0]!=';') && (s[0])) { split(code,s); rmspace(code); rmspace(s); if (strcasecmp(code,"-")==0) { if (lasthand[0]) { p=strchr(s,','); while (p!=NULL) { splitc(code,s,','); rmspace(code); rmspace(s); if (code[0]) addhost_by_handle(lasthand,code); p=strchr(s,','); } if (s[0]) addhost_by_handle(lasthand,s); } } else if (strcasecmp(code,"+")==0) { if (lasthand[0]) { set_handle_email(lasthand,s); } } else if (strcasecmp(code,"*")==0) { if (lasthand[0]) { set_handle_dccdir(lasthand,s); } } else if (strcasecmp(code,"=")==0) { if (lasthand[0]) { set_handle_comment(lasthand,s); } } else if (strcasecmp(code,":")==0) { if (lasthand[0]) { set_handle_info(lasthand,s); } } else { split(host,s); rmspace(s); split(pass,s); rmspace(s); if (pass[0]==0) { strcpy(pass,s); s[0]=0; } split(attr,s); if (attr[0]==0) { strcpy(attr,s); s[0]=0; } rmspace(attr); rmspace(pass); rmspace(host); rmspace(s); flags=0; for (i=0; i