void cs_log(nick *np, char *event, ... ) { char buf[512]; char buf2[1024]; char userbuf[512]; va_list va; char timebuf[TIMELEN]; int len; time_t now; if (logfd<0) return; va_start(va,event); vsnprintf(buf,512,event,va); va_end(va); if (np) { snprintf(userbuf,511,"%s!%s@%s [%s%s]",np->nick,np->ident,np->host->name->content, getreguserfromnick(np)?"auth ":"noauth",getreguserfromnick(np)?getreguserfromnick(np)->username:""); } else { userbuf[0]='\0'; } now=time(NULL); strftime(timebuf,sizeof(timebuf),Q9_LOG_FORMAT_TIME, gmtime(&now)); len=snprintf(buf2,sizeof(buf2),"[%s] %s %s\n",timebuf,userbuf,buf); write(logfd, buf2, len); }
void csdb_accounthistory_insert(nick *np, char *oldpass, char *newpass, char *oldemail, char *newemail) { reguser *rup=getreguserfromnick(np); char escoldpass[PASSLEN*2+5]; char escnewpass[PASSLEN*2+5]; char escoldemail[EMAILLEN*2+5]; char escnewemail[EMAILLEN*2+5]; if (!rup || UHasOperPriv(rup)) return; if (oldpass) dbescapestring(escoldpass, oldpass, CSMIN(strlen(oldpass), PASSLEN)); else escoldpass[0]='\0'; if (newpass) dbescapestring(escnewpass, newpass, CSMIN(strlen(newpass), PASSLEN)); else escnewpass[0]='\0'; if (oldemail) dbescapestring(escoldemail, oldemail, CSMIN(strlen(oldemail), EMAILLEN)); else escoldemail[0]='\0'; if (newemail) dbescapestring(escnewemail, newemail, CSMIN(strlen(newemail), EMAILLEN)); else escnewemail[0]='\0'; dbquery("INSERT INTO chanserv.accounthistory (userID, changetime, authtime, oldpassword, newpassword, oldemail, " "newemail) VALUES (%u, %lu, %lu, '%s', '%s', '%s', '%s')", rup->ID, getnettime(), np->accountts, escoldpass, escnewpass, escoldemail, escnewemail); }
int cs_privcheck(int privnum, nick *np) { reguser *rup=NULL; if (np) rup=getreguserfromnick(np); switch(privnum) { case QPRIV_SUSPENDBYPASS: case QPRIV_VIEWCHANFLAGS: case QPRIV_VIEWFULLCHANLEV: case QPRIV_VIEWFULLWHOIS: case QPRIV_VIEWCHANMODES: case QPRIV_VIEWAUTOLIMIT: case QPRIV_VIEWBANTIMER: case QPRIV_VIEWUSERFLAGS: case QPRIV_VIEWCHANSUSPENSION: return (rup && UHasHelperPriv(rup)); case QPRIV_VIEWCOMMENTS: case QPRIV_VIEWEMAIL: case QPRIV_CHANGECHANLEV: case QPRIV_CHANGECHANFLAGS: case QPRIV_CHANGECHANMODES: case QPRIV_CHANGEAUTOLIMIT: case QPRIV_CHANGEBANTIMER: case QPRIV_CHANGEUSERFLAGS: case QPRIV_VIEWSUSPENDEDBY: case QPRIV_VIEWWALLMESSAGE: /* if you change VIEWWALLMESSAGE alter chanservwallmessage too */ case QPRIV_VIEWREALHOST: return (np && rup && IsOper(np) && UHasOperPriv(rup)); default: /* By default opers can override anything */ return (np && rup && IsOper(np) && UHasOperPriv(rup)); } }
void csdb_chanlevhistory_insert(regchan *rcp, nick *np, reguser *trup, flag_t oldflags, flag_t newflags) { reguser *rup=getreguserfromnick(np); assert(rup != NULL); dbquery("INSERT INTO chanserv.chanlevhistory (userID, channelID, targetID, changetime, authtime, " "oldflags, newflags) VALUES (%u, %u, %u, %lu, %lu, %u, %u)", rup->ID, rcp->ID, trup->ID, getnettime(), np->accountts, oldflags, newflags); }
int csc_dorecover(void *source, int cargc, char **cargv) { nick *sender=source,*np; reguser *rup; regchanuser *rcup; regchan *rcp; chanindex *cip; unsigned long *lp; int i; modechanges changes; if (cargc<1) { chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "recover"); return CMD_ERROR; } if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "recover",0, 0))) return CMD_ERROR; rcp=cip->exts[chanservext]; if (cip->channel) { localsetmodeinit(&changes, cip->channel, chanservnick); /* clearchan */ localdosetmode_key(&changes, NULL, MCB_DEL); localdosetmode_simple(&changes, 0, cip->channel->flags); cs_docheckchanmodes(cip->channel, &changes); /* unbanall */ while (cip->channel->bans) { localdosetmode_ban(&changes, bantostring(cip->channel->bans), MCB_DEL); } /* remove the registered bans that match on me */ cs_unbanfn(sender, cip, nickmatchban_peerthroughhidehost, sender, 1, 0); /* deopall */ for (i=0,lp=cip->channel->users->content; i<cip->channel->users->hashsize;i++,lp++) { if (*lp!=nouser && (*lp & CUMODE_OP)) { if (!(np=getnickbynumeric(*lp)) || (!IsService(np) && (!(rup=getreguserfromnick(np)) || !(rcup=findreguseronchannel(rcp, rup)) || !(CUHasOpPriv(rcup)) || !(CUIsProtect(rcup) || CIsProtect(rcp))))) { localdosetmode_nick(&changes, np, MC_DEOP); } } } localsetmodeflush(&changes, 1); } cs_log(sender,"RECOVER %s",cip->name->content); chanservstdmessage(sender, QM_DONE); return CMD_OK; }
void csdb_doaccounthistory_real(DBConn *dbconn, void *arg) { nick *np=getnickbynumeric((unsigned long)arg); reguser *rup; char *oldpass, *newpass, *oldemail, *newemail; time_t changetime; DBResult *pgres; int count=0; char tbuf[TIMELEN]; if(!dbconn) return; pgres=dbgetresult(dbconn); if (!dbquerysuccessful(pgres)) { Error("chanserv", ERR_ERROR, "Error loading account history data."); return; } if (dbnumfields(pgres) != 7) { Error("chanserv", ERR_ERROR, "Account history data format error."); dbclear(pgres); return; } if (!np) { dbclear(pgres); return; } if (!(rup=getreguserfromnick(np)) || !UHasOperPriv(rup)) { Error("chanserv", ERR_ERROR, "No reguser pointer or oper privs in account history."); dbclear(pgres); return; } /* @TIMELEN */ chanservsendmessage(np, "Number: Time: Old password: New password: Old email: New email:"); while(dbfetchrow(pgres)) { /*userID=strtoul(dbgetvalue(pgres, 0), NULL, 10);*/ changetime=strtoul(dbgetvalue(pgres, 1), NULL, 10); /*authtime=strtoul(dbgetvalue(pgres, 2), NULL, 10);*/ oldpass=dbgetvalue(pgres, 3); newpass=dbgetvalue(pgres, 4); oldemail=dbgetvalue(pgres, 5); newemail=dbgetvalue(pgres, 6); q9strftime(tbuf, sizeof(tbuf), changetime); chanservsendmessage(np, "#%-6d %-19s %-14s %-14s %-30s %s", ++count, tbuf, oldpass, newpass, oldemail, newemail); /* @TIMELEN */ } chanservstdmessage(np, QM_ENDOFLIST); dbclear(pgres); }
int csa_doaddchan(void *source, int cargc, char **cargv) { nick *sender=(nick *)source; reguser *rup = getreguserfromnick(sender), *founder; chanindex *cip; short type; regchan *rcp; if(cargc<3) { controlreply(sender, "ADDCHAN FALSE args"); return CMD_ERROR; } if (*cargv[0] != '#' || strlen(cargv[0]) > CHANNELLEN) { controlreply(sender, "ADDCHAN FALSE invalidchannel"); return CMD_ERROR; } if (!(cip=findorcreatechanindex(cargv[0]))) { controlreply(sender, "ADDCHAN FALSE invalidchannel"); return CMD_ERROR; } founder = findreguserbyID(atoi(cargv[1])); if(founder == NULL) { controlreply(sender, "ADDCHAN FALSE useridnotexist"); return CMD_ERROR; } if(UIsInactive(founder)) { controlreply(sender, "ADDCHAN FALSE accountinactive"); return CMD_ERROR; } for(type=CHANTYPES-1;type;type--) if(!ircd_strcmp(chantypes[type]->content, cargv[2])) break; if(!type) { controlreply(sender, "ADDCHAN FALSE invalidchantype"); return CMD_ERROR; } rcp = cs_addchan(cip, sender, rup, founder, QCFLAG_JOINED | QCFLAG_AUTOOP | QCFLAG_BITCH | QCFLAG_FORCETOPIC | QCFLAG_PROTECT | QCFLAG_TOPICSAVE, CHANMODE_NOCTCP | CHANMODE_DELJOINS | CHANMODE_MODNOAUTH | CHANMODE_NONOTICE | CHANMODE_NOEXTMSG | CHANMODE_SINGLETARG | CHANMODE_TOPICLIMIT | CHANMODE_NOQUITMSG, 0, type); if(!rcp) { controlreply(sender, "ADDCHAN FALSE alreadyregistered"); return CMD_ERROR; } cs_log(sender, "ADDCHAN %s #%s %s %s", cip->name->content, founder->username, printflags(rcp->flags, rcflags), chantypes[type]->content); controlreply(sender, "ADDCHAN TRUE %u", rcp->ID); return CMD_OK; }
int csc_dodeopall(void *source, int cargc, char **cargv) { nick *sender=source,*np; reguser *rup; regchanuser *rcup; regchan *rcp; chanindex *cip; unsigned long *lp; int i; modechanges changes; if (cargc<1) { chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "deopall"); return CMD_ERROR; } if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "deopall",0, 0))) return CMD_ERROR; rcp=cip->exts[chanservext]; if (cip->channel) { localsetmodeinit(&changes, cip->channel, chanservnick); for (i=0,lp=cip->channel->users->content; i<cip->channel->users->hashsize;i++,lp++) { if (*lp!=nouser && (*lp & CUMODE_OP)) { if (!(np=getnickbynumeric(*lp)) || (!IsService(np) && (!(rup=getreguserfromnick(np)) || !(rcup=findreguseronchannel(rcp, rup)) || !(CUHasOpPriv(rcup)) || !(CUIsProtect(rcup) || CIsProtect(rcp))))) { localdosetmode_nick(&changes, np, MC_DEOP); } } } localsetmodeflush(&changes, 1); } cs_log(sender,"DEOPALL %s",cip->name->content); chanservstdmessage(sender, QM_DONE); return CMD_OK; }
int csc_dorollbackchan(void *source, int cargc, char **cargv) { nick *sender=source; chanindex *cip; reguser *rup, *trup=NULL; regchan *rcp; time_t starttime=getnettime(); long duration; if (!(rup=getreguserfromnick(sender))) return CMD_ERROR; if (cargc < 2) { chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "rollbackchan"); return CMD_ERROR; } if (!(cip=cs_checkaccess(sender, cargv[0], 0, NULL, NULL, 0, 0))) return CMD_ERROR; rcp=(regchan*)cip->exts[chanservext]; if (cargc > 2) { duration=durationtolong(cargv[2]); if (!(trup=findreguser(sender, cargv[1]))) return CMD_ERROR; } else duration=durationtolong(cargv[1]); if (!duration) { chanservsendmessage(sender, "Invalid duration."); return CMD_ERROR; } starttime-=duration; cs_log(sender,"ROLLBACKCHAN %s #%s %s", cip->name->content, rup->username, cargv[1]); csdb_rollbackchanlevhistory(sender, rcp, trup, starttime); return CMD_OK; }
int csu_dodeluser(void *source, int cargc, char **cargv) { nick *sender=source; reguser *rup=getreguserfromnick(sender), *target; char *reason; if (!rup) return CMD_ERROR; if (cargc<2) { chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "deluser"); return CMD_ERROR; } reason = cargv[1]; if(!checkreason(sender, reason)) return CMD_ERROR; if (!(target=findreguser(sender, cargv[0]))) return CMD_ERROR; if(target->ID == lastuserID) { chanservsendmessage(sender, "Sorry, can't delete last user -- wait a while and try again."); return CMD_ERROR; } if(UHasStaffPriv(target)) { cs_log(sender,"DELUSER FAILED username %s (reason: %s)",target->username,reason); chanservwallmessage("%s (%s) just FAILED using DELUSER on %s (reason: %s)", sender->nick, rup->username, target->username, reason); chanservsendmessage(sender, "Sorry, that user is privileged."); return CMD_ERROR; } cs_log(sender,"DELUSER OK username %s (reason: %s)",target->username,reason); chanservwallmessage("%s (%s) just used DELUSER on %s (reason: %s)", sender->nick, rup->username, target->username, reason); cs_removeuser(target); chanservstdmessage(sender, QM_DONE); return CMD_OK; }
int csc_dodelchan(void *source, int cargc, char **cargv) { nick *sender=source; reguser *rup=getreguserfromnick(sender); chanindex *cip; regchan *rcp; char *reason; char buf[512]; if (!rup) return CMD_ERROR; if (cargc<2) { chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "delchan"); return CMD_ERROR; } reason = cargv[1]; if(!checkreason(sender, reason)) return CMD_ERROR; if (!(cip=findchanindex(cargv[0])) || !(rcp=cip->exts[chanservext])) { chanservstdmessage(sender, QM_UNKNOWNCHAN, cargv[0]); return CMD_ERROR; } if (rcp->ID == lastchannelID) { chanservsendmessage(sender, "Sorry, can't delete last channel -- wait a while and try again."); return CMD_ERROR; } cs_log(sender,"DELCHAN %s (%s)",cip->name->content,reason); chanservwallmessage("%s (%s) just used DELCHAN on %s (reason: %s)", sender->nick, rup->username, cip->name->content, reason); snprintf(buf, sizeof(buf), "Channel deleted: %s", reason); cs_removechannel(rcp, buf); chanservstdmessage(sender, QM_DONE); return CMD_OK; }
int csa_doaccounthistory(void *source, int cargc, char **cargv) { reguser *rup, *trup; nick *sender=source; if (!(rup=getreguserfromnick(sender))) return CMD_ERROR; if (cargc < 1) { chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "accounthistory"); return CMD_ERROR; } if (!(trup=findreguser(sender, cargv[0]))) return CMD_ERROR; if ((rup != trup) && UHasOperPriv(trup) && !UHasAdminPriv(rup)) { chanservstdmessage(sender, QM_NOACCESS, "accounthistory", cargv[0]); return CMD_ERROR; } csdb_retreiveaccounthistory(sender, trup, 10); return CMD_OK; }
int csa_donewpw(void *source, int cargc, char **cargv) { reguser *rup; nick *sender=source; unsigned int same=0; time_t t; int pq; if (cargc<3) { chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "newpass"); return CMD_ERROR; } if (!(rup=getreguserfromnick(sender))) return CMD_ERROR; if (!checkpassword(rup, cargv[0])) { chanservstdmessage(sender, QM_AUTHFAIL); cs_log(sender,"NEWPASS FAIL username %s bad password %s",rup->username,cargv[0]); return CMD_ERROR; } if (strcmp(cargv[1],cargv[2])) { chanservstdmessage(sender, QM_PWDONTMATCH); /* Sorry, passwords do not match */ cs_log(sender,"NEWPASS FAIL username %s new passwords don't match (%s vs %s)",rup->username,cargv[1],cargv[2]); return CMD_ERROR; } if (!strcmp(cargv[0],cargv[1])) { /* If they are the same then continue anyway but don't send the hook later. */ same=1; } pq = csa_checkpasswordquality(cargv[1]); if(pq == QM_PWTOSHORT) { chanservstdmessage(sender, QM_PWTOSHORT); /* new password too short */ cs_log(sender,"NEWPASS FAIL username %s password too short %s (%zu characters)",rup->username,cargv[1],strlen(cargv[1])); return CMD_ERROR; } else if(pq == QM_PWTOWEAK) { chanservstdmessage(sender, QM_PWTOWEAK); /* new password is weak */ cs_log(sender,"NEWPASS FAIL username %s password too weak %s",rup->username,cargv[1]); return CMD_ERROR; } else if(pq == QM_PWTOLONG) { chanservstdmessage(sender, QM_PWTOLONG); /* new password too long */ cs_log(sender,"NEWPASS FAIL username %s password too long %s",rup->username,cargv[1]); return CMD_ERROR; } else if(pq == QM_PWINVALID) { chanservstdmessage(sender, QM_PWINVALID); cs_log(sender,"NEWPASS FAIL username %s password invalid %s",rup->username,cargv[1]); return CMD_ERROR; } else if(pq == -1) { /* all good */ } else { chanservsendmessage(sender, "unknown error in newpass.c... contact #help"); return CMD_ERROR; } t=time(NULL); if(!UHasStaffPriv(rup)) { if(rup->lockuntil && rup->lockuntil > t) { chanservstdmessage(sender, QM_ACCOUNTLOCKED, rup->lockuntil); return CMD_ERROR; } rup->lockuntil=t+7*24*3600; } else { rup->lockuntil=0; } if(rup->lastemail) { freesstring(rup->lastemail); rup->lastemail=NULL; } rup->lastpasschange=t; csdb_accounthistory_insert(sender, rup->password, cargv[1], NULL, NULL); setpassword(rup, cargv[1]); rup->lastauth=time(NULL); chanservstdmessage(sender, QM_PWCHANGED); cs_log(sender,"NEWPASS OK username %s", rup->username); #ifdef AUTHGATE_WARNINGS if(UHasOperPriv(rup)) chanservsendmessage(sender, "WARNING FOR PRIVILEGED USERS: you MUST go to https://auth.quakenet.org and login successfully to update the cache, if you do not your old password will still be usable in certain circumstances."); #endif csdb_updateuser(rup); csdb_createmail(rup, QMAIL_NEWPW); if (!same) triggerhook(HOOK_CHANSERV_PWCHANGE, sender); return CMD_OK; }
void csc_dorollbackchan_real(DBConn *dbconn, void *arg) { nick *np=getnickbynumeric((unsigned long)arg); reguser *rup, *crup1, *crup2; chanindex *cip = NULL; regchan *rcp=NULL; regchanuser *rcup; unsigned int userID, channelID, targetID; time_t changetime, authtime; flag_t oldflags, newflags; DBResult *pgres; int j, newuser; char fbuf[18]; if(!dbconn) return; pgres=dbgetresult(dbconn); if (!dbquerysuccessful(pgres)) { Error("chanserv", ERR_ERROR, "Error loading chanlev history data."); return; } if (dbnumfields(pgres) != 7) { Error("chanserv", ERR_ERROR, "Chanlev history data format error."); dbclear(pgres); return; } if (!np) { Error("chanserv", ERR_ERROR, "No nick pointer in rollback."); dbclear(pgres); return; } if (!(rup=getreguserfromnick(np)) || !UHasOperPriv(rup)) { Error("chanserv", ERR_ERROR, "No reguser pointer or oper privs in rollback."); dbclear(pgres); return; } while(dbfetchrow(pgres)) { userID=strtoul(dbgetvalue(pgres, 0), NULL, 10); channelID=strtoul(dbgetvalue(pgres, 1), NULL, 10); if (!rcp) { for (j=0; j<CHANNELHASHSIZE && !rcp; j++) { for (cip=chantable[j]; cip && !rcp; cip=cip->next) { if (!cip->exts[chanservext]) continue; if (((regchan*)cip->exts[chanservext])->ID == channelID) rcp=(regchan*)cip->exts[chanservext]; } } if (!rcp) { Error("chanserv", ERR_ERROR, "No regchan pointer or oper privs in rollback."); dbclear(pgres); return; } cip=rcp->index; chanservsendmessage(np, "Attempting to roll back %s:", cip->name->content); } targetID=strtoul(dbgetvalue(pgres, 2), NULL, 10); changetime=strtoul(dbgetvalue(pgres, 3), NULL, 10); authtime=strtoul(dbgetvalue(pgres, 4), NULL, 10); oldflags=strtoul(dbgetvalue(pgres, 5), NULL, 10); newflags=strtoul(dbgetvalue(pgres, 6), NULL, 10); strncpy(fbuf, printflags(newflags, rcuflags), 17); fbuf[17]='\0'; crup1=findreguserbyID(userID); crup2=findreguserbyID(targetID); if (!crup2) { chanservsendmessage(np, "Affected user (ID: %d) is no longer in database, continuing...", targetID); continue; } if (!(rcup=findreguseronchannel(rcp, crup2))) { rcup=getregchanuser(); rcup->user=crup2; rcup->chan=rcp; rcup->flags=0; rcup->changetime=time(NULL); rcup->usetime=0; rcup->info=NULL; newuser=1; } else newuser=0; csdb_chanlevhistory_insert(rcp, np, rcup->user, rcup->flags, oldflags); rcup->flags=oldflags; chanservsendmessage(np, "%s user flags for %s (%s -> %s)", newflags?oldflags?"Restoring":"Deleting":"Readding", crup2->username, fbuf, printflags(oldflags, rcuflags)); if (rcup->flags) { if (newuser) { addregusertochannel(rcup); csdb_createchanuser(rcup); } else csdb_updatechanuser(rcup); } else { if (!newuser) { csdb_deletechanuser(rcup); delreguserfromchannel(rcp, crup2); } freesstring(rcup->info); freeregchanuser(rcup); rcup=NULL; for (j=0; j<REGCHANUSERHASHSIZE; j++) if (rcp->regusers[j]) break; if (j==REGCHANUSERHASHSIZE) { cs_log(np, "DELCHAN %s (Cleared chanlev from rollback)", cip->name->content); chanservsendmessage(np, "Rollback cleared chanlev list, channel deleted."); rcp=NULL; } } } chanservstdmessage(np, QM_DONE); dbclear(pgres); }
int csu_dosuspenduserlist(void *source, int cargc, char **cargv) { nick *sender=source; reguser *rup=getreguserfromnick(sender); reguser *dbrup, *trup; int i, seewhom; unsigned int count=0; char buf[TIMELEN], buf2[TIMELEN], *bywhom; time_t now=time(NULL); if (!rup) return CMD_ERROR; if (cargc < 1) { chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "suspenduserlist"); return CMD_ERROR; } seewhom = cs_privcheck(QPRIV_VIEWSUSPENDEDBY, sender); if(!seewhom) bywhom = "(hidden)"; /* @TIMELEN */ chanservstdmessage(sender, QM_SUSPENDUSERLISTHEADER); for (i=0;i<REGUSERHASHSIZE;i++) { for (dbrup=regusernicktable[i]; dbrup; dbrup=dbrup->nextbyname) { if (!UHasSuspension(dbrup)) continue; if (!match(cargv[0], dbrup->username)) { char suspendtype[100]; if (UIsDelayedGline(dbrup)) strcpy(suspendtype, "delayed gline"); else if (UIsGline(dbrup)) strcpy(suspendtype, "instant gline"); else if (UIsSuspended(dbrup)) strcpy(suspendtype, "suspended"); else strcpy(suspendtype, "not used"); if(seewhom) { trup=findreguserbyID(dbrup->suspendby); if (trup) bywhom=trup->username; else bywhom="(unknown)"; } if (dbrup->suspendexp) q9strftime(buf,sizeof(buf),dbrup->suspendexp); q9strftime(buf2,sizeof(buf2),dbrup->suspendtime); count++; /* @TIMELEN */ chanservsendmessage(sender, "%-15s %-13s %-15s %-19s %-19s %s", dbrup->username, suspendtype, bywhom, buf2, (dbrup->suspendexp)?((now >= dbrup->suspendexp)?"next auth":buf):"never", dbrup->suspendreason?dbrup->suspendreason->content:"(none)"); if (count >= 2000) { chanservstdmessage(sender, QM_TOOMANYRESULTS, 2000, "users"); return CMD_ERROR; } } } } chanservstdmessage(sender, QM_RESULTCOUNT, count, "user", (count==1)?"":"s"); return CMD_OK; }
chanindex *cs_checkaccess(nick *np, const char *chan, unsigned int flags, chanindex *cip, const char *cmdname, int priv, int quiet) { reguser *rup=getreguserfromnick(np); regchan *rcp; regchanuser *rcup=NULL; unsigned long *lp; if ((flags & CA_AUTHED) && !rup) return NULL; if (!cip && !(cip=findchanindex(chan))) { if (!quiet) chanservstdmessage(np, QM_UNKNOWNCHAN, chan); return NULL; } if (!(rcp=cip->exts[chanservext])) { if (!quiet) chanservstdmessage(np, QM_UNKNOWNCHAN, cip->name->content); return NULL; } if (CIsSuspended(rcp)) { if (cs_privcheck(QPRIV_SUSPENDBYPASS, np)) { if (!quiet) chanservstdmessage(np, QM_BYPASSINGSUSPEND, cip->name->content); } else { if (!quiet) chanservstdmessage(np, QM_UNKNOWNCHAN, cip->name->content); return NULL; } } if (rcp && rup) rcup=findreguseronchannel(rcp, rup); if (!cs_privcheck(priv,np)) { if ((flags & CA_VOICEPRIV) && !(rcp && CIsVoiceAll(rcp) && !(rcup && CUIsQuiet(rcup)) && !(cip->channel && (nickbanned(np, cip->channel, 1) || IsInviteOnly(cip->channel)))) && !(rcup && CUHasVoicePriv(rcup))) { if (!quiet) chanservstdmessage(np, QM_NOACCESSONCHAN, cip->name->content, cmdname); return NULL; } if ((flags & CA_NEEDKNOWN) && !rup) { if (!quiet) chanservstdmessage(np, QM_NOACCESSONCHAN, cip->name->content, cmdname); return NULL; } if ((flags & CA_NEEDKNOWN) && (!rcup || !CUKnown(rcup))) { if (!quiet) chanservstdmessage(np, QM_NOACCESSONCHAN, cip->name->content, cmdname); return NULL; } if (((flags & CA_OPPRIV ) && !CUHasOpPriv(rcup)) || ((flags & CA_MASTERPRIV) && !CUHasMasterPriv(rcup)) || ((flags & CA_OWNERPRIV) && !CUIsOwner(rcup)) || ((flags & CA_TOPICPRIV ) && !CUHasTopicPriv(rcup))) { if (!quiet) chanservstdmessage(np, QM_NOACCESSONCHAN, cip->name->content, cmdname); return NULL; } } if ((flags & CA_ONCHANREQ) && !(cip->channel)) { if (!quiet) chanservstdmessage(np, QM_NOTONCHAN, cip->name->content); return NULL; } if (cip->channel) { lp=getnumerichandlefromchanhash(cip->channel->users, np->numeric); if ((flags & CA_ONCHANREQ) && !lp) { if (!quiet) chanservstdmessage(np, QM_NOTONCHAN, cip->name->content); return NULL; } if ((flags & CA_OPPED) && !(*lp & CUMODE_OP)) { if (!quiet) chanservstdmessage(np, QM_NOTOPPED, cip->name->content); return NULL; } if ((flags & CA_DEOPPED) && (*lp & CUMODE_OP)) { if (!quiet) chanservstdmessage(np, QM_ALREADYOPPED, cip->name->content); return NULL; } if ((flags & CA_VOICED) && !(*lp & CUMODE_VOICE)) { if (!quiet) chanservstdmessage(np, QM_NOTVOICED, cip->name->content); return NULL; } if ((flags & CA_DEVOICED) && (*lp & CUMODE_VOICE)) { if (!quiet) chanservstdmessage(np, QM_ALREADYVOICED, cip->name->content); return NULL; } if ((flags & CA_OFFCHAN) && lp) { if (!quiet) chanservstdmessage(np, QM_ALREADYONCHAN, cip->name->content); return NULL; } } return cip; }