chanservnick=registerlocaluser(csnick->content,csuser->content,cshost->content,
csrealname->content,NULL,
- UMODE_INV|UMODE_SERVICE|UMODE_DEAF,
+ UMODE_INV|UMODE_SERVICE|UMODE_DEAF|UMODE_OPER,
&chanservuserhandler);
freesstring(csnick);
if (!(rcp=cp->index->exts[chanservext]))
return;
- /* Check for a new timestamp */
- if ((!rcp->ltimestamp) || (cp->timestamp < rcp->ltimestamp)) {
+ /* Check for a new timestamp. But don't do anything stupid if the incoming timestamp is 0 */
+ if (cp->timestamp && ((!rcp->ltimestamp) || (cp->timestamp < rcp->ltimestamp))) {
rcp->ltimestamp=cp->timestamp;
csdb_updatechanneltimestamp(rcp);
}
lastuserID=rup->ID;
strncpy(rup->username,np->authname,NICKLEN); rup->username[NICKLEN]='\0';
rup->created=time(NULL);
- rup->lastauth=time(NULL); /* questionable */
+ rup->lastauth=0;
rup->lastemailchange=0;
rup->flags=QUFLAG_NOTICE;
rup->languageid=0;
rup->suspendby=0;
rup->suspendexp=0;
rup->suspendtime=0;
+ rup->lockuntil=0;
rup->password[0]='\0';
rup->email=NULL;
+ rup->lastemail=NULL;
rup->localpart=NULL;
rup->domain=NULL;
rup->info=NULL;
(rcup && CUIsDeny(rcup)))
localdosetmode_nick(changes, np, MC_DEOP);
} else {
- if (rcup && (CUIsProtect(rcup) || CIsProtect(rcp)) && CUIsOp(rcup) && !CUIsDeny(rcup))
+ if (rcup && (CUIsProtect(rcup) || CIsProtect(rcp)) && CUIsOp(rcup) && !CUIsDeny(rcup)) {
localdosetmode_nick(changes, np, MC_OP);
+ cs_logchanop(rcp, np->nick, rcup->user);
+ }
}
if (cp->users->content[i] & CUMODE_VOICE) {
localdosetmode_nick(&changes, np, MC_DEOP);
} else {
if (!CUIsDeny(rcup) && CUIsOp(rcup) &&
- (CUIsProtect(rcup) || CIsProtect(rcup->chan) || CUIsAutoOp(rcup)))
+ (CUIsProtect(rcup) || CIsProtect(rcup->chan) || CUIsAutoOp(rcup))) {
localdosetmode_nick(&changes, np, MC_OP);
+ cs_logchanop(rcup->chan, np->nick, rup);
+ }
}
if (*lp & CUMODE_VOICE) {
releasechanindex(cip);
}
+/* Sender is who the DELCHAN is attributed to.. */
+int cs_removechannelifempty(nick *sender, regchan *rcp) {
+ unsigned int i;
+ regchanuser *rcup;
+
+ for (i=0;i<REGCHANUSERHASHSIZE;i++) {
+ for (rcup=rcp->regusers[i];rcup;rcup=rcup->nextbychan) {
+ if (rcup->flags & ~(QCUFLAG_BANNED | QCUFLAG_DENY | QCUFLAG_QUIET))
+ return 0;
+ }
+ }
+
+ cs_log(sender,"DELCHAN %s (Empty)",rcp->index->name->content);
+ cs_removechannel(rcp);
+
+ return 1;
+}
+
void cs_removeuser(reguser *rup) {
- int i;
regchanuser *rcup, *nrcup;
regchan *rcp;
struct authname *anp;
rcp=rcup->chan;
delreguserfromchannel(rcp, rup);
-
- for (i=0;i<REGCHANUSERHASHSIZE;i++) {
- if (rcp->regusers[i])
- break;
- }
-
- if (i==REGCHANUSERHASHSIZE) {
- /* There are no users left on this channel! */
- cs_log(NULL, "DELCHAN %s (last user removed)",rcp->index->name->content);
- cs_removechannel(rcp);
- }
-
- freeregchanuser(rcup);
+ cs_removechannelifempty(NULL, rcp);
}
if(rup->domain)
delreguserfrommaildomain(rup,rup->domain);
freesstring(rup->localpart);
freesstring(rup->email);
+ freesstring(rup->lastemail);
freesstring(rup->lastuserhost);
freesstring(rup->suspendreason);
freesstring(rup->comment);
if (!(flags & (QCUFLAG_VOICE | QCUFLAG_OP)))
flags &= ~QCUFLAG_PROTECT;
- /* The personal flags require one of +mnovk */
+ /* The personal flags require one of +mnovk, as does +t */
if (!(flags & (QCUFLAG_OWNER | QCUFLAG_MASTER | QCUFLAG_OP | QCUFLAG_VOICE | QCUFLAG_KNOWN)))
- flags &= ~QCUFLAGS_PERSONAL;
+ flags &= ~(QCUFLAGS_PERSONAL | QCUFLAG_TOPIC);
return flags;
}
/*
* Unbans a mask from a channel, including permbans if user has correct privs.
+ *
+ * Return 0 if it works, 1 if it don't.
*/
-void cs_unbanfn(nick *sender, chanindex *cip, UnbanFN fn, void *arg, int removepermbans) {
+int cs_unbanfn(nick *sender, chanindex *cip, UnbanFN fn, void *arg, int removepermbans, int abortonfailure) {
regban **rbh, *rbp;
chanban **cbh, *cbp;
regchan *rcp;
rbh=&(rbp->next);
} else if (!cs_checkaccess(sender, NULL, CA_MASTERPRIV, cip, NULL, 0, 1)) {
chanservstdmessage(sender, QM_NOTREMOVEDPERMBAN, banstr, cip->name->content);
+ if (abortonfailure) return 1; /* Just give up... */
rbh=&(rbp->next);
} else {
chanservstdmessage(sender, QM_REMOVEDPERMBAN, banstr, cip->name->content);
}
localsetmodeflush(&changes,1);
}
+
+ return 0;
+}
+
+/* Add entry to channel op history when someone gets ops. */
+void cs_logchanop(regchan *rcp, char *nick, reguser *rup) {
+ strncpy(rcp->chanopnicks[rcp->chanoppos], nick, NICKLEN);
+ rcp->chanopnicks[rcp->chanoppos][NICKLEN]='\0';
+ rcp->chanopaccts[rcp->chanoppos]=rup->ID;
+ rcp->chanoppos=(rcp->chanoppos+1)%CHANOPHISTORY;
}