void lua_startbot(void *arg) { channel *cp; myureconnect = NULL; if(!luabotnick) luabotnick = getcopyconfigitem("lua", "botnick", "U", NICKLEN); lua_nick = registerlocaluser(luabotnick->content, "lua", "quakenet.department.of.corrections", LUA_FULLVERSION, "U", UMODE_ACCOUNT | UMODE_DEAF | UMODE_OPER | UMODE_SERVICE, &lua_bothandler); if(!lua_nick) { myureconnect = scheduleoneshot(time(NULL) + 1, &lua_startbot, NULL); return; } cp = findchannel(LUA_OPERCHAN); if(cp && localjoinchannel(lua_nick, cp)) { localgetops(lua_nick, cp); } else { localcreatechannel(lua_nick, LUA_OPERCHAN); } cp = findchannel(LUA_PUKECHAN); if(cp && localjoinchannel(lua_nick, cp)) { localgetops(lua_nick, cp); } else { localcreatechannel(lua_nick, LUA_PUKECHAN); } myublip = schedulerecurring(time(NULL) + 1, 0, 60, &lua_blip, NULL); myutick = schedulerecurring(time(NULL) + 1, 0, 1, &lua_tick, NULL); lua_registerevents(); }
static int pc_join(char *name) { patrolchannel *pc = NULL; channel *cp; for (pc = patrolchannels; pc; pc = pc->next) if (ircd_strcmp(pc->channel->content, name) == 0) return 0; cp = findchannel(name); if (!cp) return -1; pc = malloc(sizeof(patrolchannel)); pc->channel = getsstring(name, 512); pc->nick = NULL; pc->next = patrolchannels; patrolchannels = pc; pc_check(); return 0; }
/** * handle the MKICK command */ void cs_mkick(char *src, int ac, char **av) { if (ac < 2) { notice(cs_name, src, CS_MKICK_ERR_USAGE); notice(cs_name, src, CS_RPL_HLP, cs_name, "MKICK"); return; } char *chan = sstrdup(av[1]); char *reason = sstrdup(av[2]); user *u = finduser(src); if (!isregcs(chan)) { notice(cs_name, src, CS_ERR_NOTREG, chan); return; } ChanInfo *c = findchan(chan); if (cs_xop_get_level(u, c) < cs_mkick_access) { notice(cs_name, src, CS_XOP_ERR_HIGHERACCESS, get_opacc(cs_mkick_access)); return; } channel *channel = findchannel(chan); int relevant_count; if(channel->bot) { relevant_count = 1; } else { relevant_count = 0; } if(channel->ucnt<relevant_count) { notice(cs_name,src,CS_MKICK_RPL_NOUSERS,chan); return; } char final_reason[256]; sprintf(final_reason,"MKICK Command used by %s (%s)",src,reason); do_mkick(channel,final_reason); return; }
int ca_carrot(void *source, int cargc, char **cargv) { nick *sender=(nick *)source; nick *victim; channel *cp; if (cargc<1) return CMD_USAGE; if ((victim=getnickbynick(cargv[0]))!=NULL) { controlreply(victim,"%cACTION ger %s en morot%c",1,victim->nick,1); controlreply(sender,"Gave %s a carrot.",victim->nick); } else if ((cp=findchannel(cargv[0]))!=NULL) { if (cargc>1) { controlchanmsg(cp,"%cACTION ger %s en morot%c",1,cargv[1],1); } else { controlchanmsg(cp,"%cACTION waves a carrot around menacingly.%c",1,1); } controlreply(sender,"Used carrot in %s.",cp->index->name->content); } else { controlreply(sender,"Couldn't find %s.",cargv[0]); } return CMD_OK; }
int handlepartmsg(void *source, int cargc, char **cargv) { char *pos,*nextchan; nick *np; channel *cp; void *harg[3]; if (cargc<1) { return CMD_OK; } if (cargc>2) { Error("channel",ERR_WARNING,"PART with too many parameters (%d)",cargc); } if (cargc>1) { harg[2]=(void *)cargv[1]; } else { harg[2]=(void *)""; } /* Find out who we are talking about here */ np=getnickbynumericstr(source); if (np==NULL) { Error("channel",ERR_WARNING,"PART from non existent numeric %s",(char *)source); return CMD_OK; } harg[1]=np; nextchan=pos=cargv[0]; while (*nextchan!='\0') { /* Find the next chan position */ for (;*pos!='\0' && *pos!=',';pos++) ; /* Empty loop */ if (*pos==',') { *pos='\0'; pos++; } /* OK, pos now points at either null or the next chan * and nextchan now points at the channel name we want to parse next */ if ((cp=findchannel(nextchan))==NULL) { /* Erm, parting a channel that's not there?? */ Error("channel",ERR_WARNING,"Nick %s left non-existent channel %s",np->nick,nextchan); } else { /* Skip ghost parts (confirmation for kick from target server). */ if (getnumerichandlefromchanhash(cp->users, np->numeric)) { /* Trigger hook *FIRST* */ harg[0]=cp; triggerhook(HOOK_CHANNEL_PART,harg); delnickfromchannel(cp,np->numeric,1); } } nextchan=pos; } return CMD_OK; }
void dbl_display(variable* ch, int count, ...) { Channel* canal=findchannel(decimal2integer(ch)); va_list arg; int i; variable* field; FILE* fh; if (canal->terminal==1) fh=stdout; else fh=canal->fh; va_start(arg,count); for (i = 0; i < count; i++) { field=va_arg(arg,variable*); if (gettype(field)<=tALPHA) fwrite(getdata(field),getsize(field),1,fh); if (gettype(field)==tDECIMAL) { int64 code; code=decimal2integer(field); code%=256; fprintf(fh,"%c",code); } } fflush(fh); va_end(arg); }
void Run(CommandSource &source, const Flux::vector ¶ms) { Flux::string chan = params[1]; User *u = source.u; if(!u->IsOwner()) { source.Reply(ACCESS_DENIED); Log(u) << "attempted to make bot part " << chan; return; } if(!IsValidChannel(chan)) source.Reply(CHANNEL_X_INVALID, chan.c_str()); else { Channel *c = findchannel(chan); if(c) c->SendPart(); else source.Reply("I am not in channel \2%s\2", chan.c_str()); Log(u) << "made the bot part " << chan; } }
void spawnclones(unsigned int count) { nick *np; unsigned int i,j; char nick[11], ident[11], host[40]; channel *cp; for (i=0;i<count;i++) { if (nclones >= MAXCLONES) return; for (j=0;j<10;j++) { nick[j]=(rand()%26)+'a'; ident[j]=(rand()%26)+'a'; host[j]=(rand()%26)+'a'; host[j+11]=(rand()%26)+'a'; host[j+22]=(rand()%26)+'a'; } host[10]=host[21]='.'; host[32]=nick[10]=ident[10]='\0'; np=clones[nclones++]=registerlocaluser(nick, ident, host, host, "", 0, clonehandler); if ((cp=findchannel(HOMECHANNEL))) { localjoinchannel(np, cp); } } }
int handletopicmsg(void *source, int cargc, char **cargv) { channel *cp; nick *np; void *harg[2]; time_t topictime=0, timestamp=0; if (cargc<2) { return CMD_OK; } if (cargc>2) topictime=strtol(cargv[cargc-2], NULL, 10); if (cargc>3) timestamp=strtol(cargv[cargc-3], NULL, 10); np=getnickbynumericstr((char *)source); /* The following check removed because servers can set topics.. */ #if 0 if (np==NULL) { /* We should check the sender exists, but we still change the topic even if it doesn't */ Error("channel",ERR_WARNING,"Topic change by non-existent user %s",(char *)source); } #endif /* Grab channel pointer */ if ((cp=findchannel(cargv[0]))==NULL) { /* We're not going to create a channel for the sake of a topic.. */ return CMD_OK; } else { if (timestamp && (cp->timestamp < timestamp)) { /* Ignore topic change for younger channel * (note that topic change for OLDER channel should be impossible!) */ return CMD_OK; } if (topictime && (cp->topictime > topictime)) { /* Ignore topic change with older topic */ return CMD_OK; } if (cp->topic!=NULL) { freesstring(cp->topic); } if (cargv[cargc-1][0]=='\0') { cp->topic=NULL; cp->topictime=0; } else { cp->topic=getsstring(cargv[cargc-1],TOPICLEN); cp->topictime=topictime?topictime:getnettime(); } /* Trigger hook */ harg[0]=cp; harg[1]=np; triggerhook(HOOK_CHANNEL_TOPIC,harg); } return CMD_OK; }
void makenick(void *arg) { channel *cp; cmnick=registerlocaluser(NICK, "clone", "master", "Clone Master", "", 0, masterhandler); if ((cp=findchannel(HOMECHANNEL))) { localjoinchannel(cmnick, cp); } else { localcreatechannel(cmnick, HOMECHANNEL); } }
void join(char *chan) { channel *cp; unsigned int i; if (!(cp=findchannel(chan))) return; for(i=0;i<nclones;i++) { localjoinchannel(clones[i], cp); } }
void dbl_delete(variable *ch, variable *keyfld) { Channel *canal = findchannel(decimal2integer(ch)); if (canal->submode == INDEXED) { /* You can note that keyfld is useless */ char* query; asprintf(&query,"DELETE FROM %s WHERE id=%d",canal->filespec,canal->lastid); mysql_query(dibol->dbh,query); free(query); } }
EventResult OnLog(Log *l) { Channel *c = findchannel(Config->LogChan); if(!c) return EVENT_CONTINUE; std::stringstream logstream; Flux::string message = Flux::Sanitize(l->buffer.str()); if(l->u && !l->c) message = l->u->nick + " " + message; if(l->u && l->c) message = l->u->nick + " used " + l->c->name + " " + message; switch(l->type) { case LOG_NORMAL: logstream << message; break; case LOG_THREAD: if(protocoldebug) logstream << "[THREAD] " << message; break; case LOG_DEBUG: if(dev || protocoldebug) logstream << message; break; // case LOG_DEVEL: // if(!protocoldebug && dev) // logstream << message; // break; case LOG_RAWIO: return EVENT_CONTINUE; case LOG_CRITICAL: logstream << "\0034[CRITICAL] " << message << "\017"; break; case LOG_WARN: logstream << "\0037[WARNING]\017 " << message; break; default: break; } c->SendMessage(NoTermColor(logstream.str())); return EVENT_CONTINUE; }
void versionscan_createfakeuser(void* arg) { channel* cp; char buf[200]; vsconnect=NULL; sprintf(buf, "%s v%s", VS_RNDESC, VS_VERSION); versionscan_nick=registerlocaluser(VS_NICK, VS_IDENT, VS_HOST, buf, VS_AUTHNAME, UMODE_ACCOUNT | UMODE_DEAF | UMODE_OPER | UMODE_SERVICE, versionscan_handler); if ((cp=findchannel(OPER_CHAN))) { localjoinchannel(versionscan_nick, cp); localgetops(versionscan_nick, cp); } else { localcreatechannel(versionscan_nick, OPER_CHAN); } }
int handlekickmsg(void *source, int cargc, char **cargv) { nick *np,*kicker; channel *cp; void *harg[4]; if (cargc<3) { return CMD_OK; } /* Find out who we are talking about here */ if ((np=getnickbynumericstr(cargv[1]))==NULL) { Error("channel",ERR_DEBUG,"Non-existant numeric %s kicked from channel %s",(char *)source,cargv[0]); return CMD_OK; } /* And who did the kicking */ if (((char *)source)[2]=='\0') { /* 'Twas a server.. */ kicker=NULL; } else if ((kicker=getnickbynumericstr((char *)source))==NULL) { /* It looks strange, but we let the kick go through anyway */ Error("channel",ERR_DEBUG,"Kick from non-existant nick %s",(char *)source); } /* And find out which channel */ if ((cp=findchannel(cargv[0]))==NULL) { /* OK, not a channel that actually exists then.. */ Error("channel",ERR_DEBUG,"Nick %s kicked from non-existent channel %s",np->nick,cargv[0]); } else { /* Before we do anything else, we have to acknowledge the kick to the network */ if (homeserver(np->numeric)==mylongnum) { irc_send("%s L %s",longtonumeric(np->numeric,5),cp->index->name->content); } /* Trigger hook *FIRST* */ harg[0]=cp; harg[1]=np; harg[2]=kicker; harg[3]=cargv[2]; triggerhook(HOOK_CHANNEL_KICK,harg); /* We let delnickfromchannel() worry about whether this nick is actually on this channel */ delnickfromchannel(cp,np->numeric,1); } return CMD_OK; }
void dbl_writes (variable* ch, variable* record) { Channel* canal=findchannel(decimal2integer(ch)); if (canal==NULL) error(11); if (canal->terminal==1) { fwrite(getdata(record),getsize(record),1,stdout); printf("\n"); return; } if (canal->submode == SEQUENTIAL) { fwrite(getdata(record),getsize(record),1,canal->fh); fprintf(canal->fh,"\n"); return; } if (canal->submode == RELATIVE ) { int seqnum; char *query; MYSQL_RES *result; MYSQL_ROW row; char *data = alpha2char (record); /* Compute the next free id */ /* We iterate through the id while we found a free place */ seqnum=(canal->lastid)+1; asprintf(&query,"SELECT id FROM %s WHERE id>%d ORDER BY id",canal->filespec,canal->lastid); mysql_query(dibol->dbh,query); free(query); result=mysql_use_result(dibol->dbh); while ( (row=mysql_fetch_row(result))) { if (seqnum!=strtol(row[0],NULL,10)) break; seqnum++; } mysql_free_result(result); /* write the record */ asprintf(&query,"INSERT INTO %s (id,data) VALUES (%d,\"%s\")",canal->filespec,seqnum,data); mysql_query(dibol->dbh,query); free(query); free(data); canal->lastid=seqnum; return; } }
int versionscan_scan(void* sender, int cargc, char** cargv) { nick* np=(nick*)sender; nick* n; channel* cp; if (cargc < 1) { sendnoticetouser(versionscan_nick, np, "Syntax: scan <target>"); return CMD_ERROR; } if (versionscan_mode != VS_SCAN) { sendnoticetouser(versionscan_nick, np, "Scanning of users is currently disabled."); return CMD_ERROR; } if (cargv[0][0] == '#') { if ((cp=findchannel(cargv[0]))) { sendmessagetochannel(versionscan_nick, cp, "\001VERSION\001"); sendnoticetouser(versionscan_nick, np, "Done."); } else { sendnoticetouser(versionscan_nick, np, "No such channel."); return CMD_ERROR; } } else { if ((n=getnickbynick(cargv[0]))) { if (IsOper(n)) { sendnoticetouser(versionscan_nick, np, "Cannot scan IRC Operators."); return CMD_ERROR; } sendmessagetouser(versionscan_nick, n, "\001VERSION\001"); sendnoticetouser(versionscan_nick, np, "Done."); } else { sendnoticetouser(versionscan_nick, np, "No such nick."); return CMD_ERROR; } } return CMD_OK; }
static void pc_check(void) { patrolchannel *pc; channel *cp; for (pc = patrolchannels; pc; pc = pc->next) { if (pc->nick && pc->nick->timestamp > getnettime() - 900) continue; if (pc->nick) deregisterlocaluser(pc->nick, NULL); cp = findchannel(pc->channel->content); if (!cp) { pc->nick = NULL; continue; } pc->nick = patrol_generateclone(0, patroluserhandler); localjoinchannel(pc->nick, cp); } }
void Run(CommandSource &source, const Flux::vector ¶ms) { User *u = source.u; Flux::string chan = params[1]; if(!u->IsOwner()) { source.Reply(ACCESS_DENIED); Log(u) << "attempted to make the bot join " << chan; return; } if(!IsValidChannel(chan)) source.Reply(CHANNEL_X_INVALID, chan.c_str()); else { Log(u) << "made the bot join " << chan; Channel *c = findchannel(chan); if(!c) { ircproto->join(chan); Flux::string WelcomeMessage = Config->WelcomeMessage.replace_all_ci("{botnick}", Config->BotNick); WelcomeMessage.trim(); if(!WelcomeMessage.empty()) ircproto->privmsg(chan, WelcomeMessage); } else { Log(u) << "tried to make bot join " << c->name << " but we're already in that channel"; source.Reply("Already in \2%s\2", c->name.c_str()); } } }
hchannel *hchannel_add(const char *cname) { channel *cp; hchannel *hchan; cp = findchannel((char*)cname); if (!cp) { localcreatechannel(helpmodnick, (char*)cname); cp = findchannel((char*)cname); } else { localjoinchannel(helpmodnick, cp); localgetops(helpmodnick, cp); } hchan = (hchannel*)malloc(sizeof(hchannel)); hchan->welcome[0] = '\0'; hchan->real_channel = cp; hchan->flags = H_CHANFLAGS_DEFAULT; hchan->channel_users = NULL; hchan->channel_hterms = NULL; hchan->max_idle = 5 * HDEF_m; hchan->topic = NULL; hchan->report_to = NULL; hchan->autoqueue = 0; hchan->jf_control = time(NULL); hchan->lc_profile = NULL; hchan->censor = NULL; hchan->htickets = NULL; hchan->ticket_message = NULL; hchan->last_activity = time(NULL); hchan->last_staff_activity = time(NULL); hchan->stats = get_hstat_channel(); hchan->next = hchannels; hchannels = hchan; { int i; nick *nck; huser *husr; huser_channel *tmp; for (i=0;i < hchan->real_channel->users->hashsize;i++) { nck = getnickbynumeric(hchan->real_channel->users->content[i]); if (!nck) /* it's a hash, not an array */ continue; if ((husr = huser_get(nck)) == NULL) husr = huser_add(nck); tmp = huser_add_channel(husr, hchan); hchannel_add_user(hchan, husr); if (hchan->real_channel->users->content[i] & CUMODE_OP) tmp->flags |= HCUMODE_OP; if (hchan->real_channel->users->content[i] & CUMODE_VOICE) tmp->flags |= HCUMODE_VOICE; } } return hchan; }
int handlejoinmsg(void *source, int cargc, char **cargv) { char *pos,*nextchan; nick *np; void *harg[3]; channel *cp,**ch; long timestamp=0; int i; int newchan=0; if (cargc<1) { return CMD_OK; } if (cargc>1) { /* We must have received a timestamp too */ timestamp=strtol(cargv[1],NULL,10); } /* Find out who we are talking about here */ np=getnickbynumericstr(source); if (np==NULL) { Error("channel",ERR_WARNING,"Channel join from non existent user %s",(char *)source); return CMD_OK; } nextchan=pos=cargv[0]; while (*nextchan!='\0') { /* Find the next chan position */ for (;*pos!='\0' && *pos!=',';pos++) ; /* Empty loop */ if (*pos==',') { *pos='\0'; pos++; } /* OK, pos now points at either null or the next chan * and nextchan now points at the channel name we want to parse next */ if(nextchan[0]=='0' && nextchan[1]=='\0') { /* Leave all channels * We do this as if they were leaving the network, * then vape their channels array and start again */ ch=(channel **)(np->channels->content); for(i=0;i<np->channels->cursi;i++) { /* Send hook */ harg[0]=ch[i]; harg[1]=np; harg[2]=NULL; triggerhook(HOOK_CHANNEL_PART,harg); delnickfromchannel(ch[i],np->numeric,0); } array_free(np->channels); array_init(np->channels,sizeof(channel *)); } else { /* It's an actual channel join */ newchan=0; if ((cp=findchannel(nextchan))==NULL) { /* User joined non-existent channel - create it. Note that createchannel automatically * puts the right magic timestamp in for us */ Error("channel",ERR_DEBUG,"User %s joined non existent channel %s.",np->nick,nextchan); cp=createchannel(nextchan); newchan=1; } if (cp->timestamp==MAGIC_REMOTE_JOIN_TS && timestamp) { /* No valid timestamp on the chan and we received one -- set */ cp->timestamp=timestamp; } /* OK, this is slightly inefficient since we turn the nick * into a numeric, * and addnicktochannel then converts it back again. BUT it's fewer lines of code :) */ if (addnicktochannel(cp,np->numeric)) { /* The user wasn't added */ if (newchan) { delchannel(cp); } } else { chanindex *cip=cp->index; /* If we just created a channel, flag it */ if (newchan) { triggerhook(HOOK_CHANNEL_NEWCHANNEL,cp); } /* Don't send HOOK_CHANNEL_JOIN if the channel doesn't exist any * more (can happen if something destroys it in response to * HOOK_CHANNEL_NEWCHANNEL) */ if (cp == cip->channel) { /* send hook */ harg[0]=cp; harg[1]=np; triggerhook(HOOK_CHANNEL_JOIN,harg); } } } nextchan=pos; } return CMD_OK; }
int handleclearmodemsg(void *source, int cargc, char **cargv) { channel *cp; void *harg[4]; nick *np, *target; char *mcp; unsigned long usermask=0; int i; int changes=0; if (cargc<2) { return CMD_OK; } if ((cp=findchannel(cargv[0]))==NULL) { /* No channel, abort */ Error("channel",ERR_WARNING,"Mode change on non-existent channel %s",cargv[0]); return CMD_OK; } if (((char *)source)[2]=='\0') { /* Server mode change? (I don't think servers are allowed to do CLEARMODE) */ np=NULL; } else if ((np=getnickbynumericstr((char *)source))==NULL) { /* No sender, continue but moan */ Error("channel",ERR_WARNING,"Mode change by non-existent user %s on channel %s",(char *)source,cp->index->name->content); } harg[0]=cp; harg[1]=np; harg[3]=(void *)(long)(cp->flags); for (mcp=cargv[1];*mcp;mcp++) { switch (*mcp) { case 'o': usermask |= CUMODE_OP; changes |= MODECHANGE_USERS; break; case 'v': usermask |= CUMODE_VOICE; changes |= MODECHANGE_USERS; break; case 'n': ClearNoExtMsg(cp); changes |= MODECHANGE_MODES; break; case 't': ClearTopicLimit(cp); changes |= MODECHANGE_MODES; break; case 's': ClearSecret(cp); changes |= MODECHANGE_MODES; break; case 'p': ClearPrivate(cp); changes |= MODECHANGE_MODES; break; case 'i': ClearInviteOnly(cp); changes |= MODECHANGE_MODES; break; case 'm': ClearModerated(cp); changes |= MODECHANGE_MODES; break; case 'c': ClearNoColour(cp); changes |= MODECHANGE_MODES; break; case 'C': ClearNoCTCP(cp); changes |= MODECHANGE_MODES; break; case 'r': ClearRegOnly(cp); changes |= MODECHANGE_MODES; break; case 'D': ClearDelJoins(cp); changes |= MODECHANGE_MODES; break; case 'u': ClearNoQuitMsg(cp); changes |= MODECHANGE_MODES; break; case 'N': ClearNoNotice(cp); changes |= MODECHANGE_MODES; break; case 'M': ClearModNoAuth(cp); changes |= MODECHANGE_MODES; break; case 'T': ClearSingleTarg(cp); changes |= MODECHANGE_MODES; break; case 'b': clearallbans(cp); changes |= MODECHANGE_BANS; break; case 'k': /* This is all safe even if there is no key atm */ freesstring(cp->key); cp->key=NULL; ClearKey(cp); changes |= MODECHANGE_MODES; break; case 'l': cp->limit=0; ClearLimit(cp); changes |= MODECHANGE_MODES; break; } } if (usermask) { /* We have to strip something off each user */ for (i=0;i<cp->users->hashsize;i++) { if (cp->users->content[i]!=nouser && (cp->users->content[i] & usermask)) { /* This user exists and has at least one of the modes we're clearing */ if ((target=getnickbynumeric(cp->users->content[i]))==NULL) { /* This really is a fuckup, we found them on the channel but there isn't a user with that numeric */ /* This means there's a serious bug in the nick/channel tracking code */ Error("channel",ERR_ERROR,"CLEARMODE failed: user on channel who doesn't exist?"); } else { harg[2]=target; /* Yes, these are deliberate three way bitwise ANDs.. */ if (cp->users->content[i] & usermask & CUMODE_OP) triggerhook(HOOK_CHANNEL_DEOPPED, harg); if (cp->users->content[i] & usermask & CUMODE_VOICE) triggerhook(HOOK_CHANNEL_DEVOICED, harg); cp->users->content[i] &= ~usermask; } } } } harg[2]=(void *)((long)changes); triggerhook(HOOK_CHANNEL_MODECHANGE, harg); return CMD_OK; }
int handlecreatemsg(void *source, int cargc, char **cargv) { char *pos,*nextchan; nick *np; channel *cp; long timestamp=0; int newchan=1; void *harg[2]; if (cargc<2) { return CMD_OK; } timestamp=strtol(cargv[1],NULL,10); /* Find out who we are talking about here */ np=getnickbynumericstr(source); if (np==NULL) { Error("channel",ERR_WARNING,"Channel create from non existent user %s",(char *)source); return CMD_OK; } nextchan=pos=cargv[0]; while (*nextchan!='\0') { /* Find the next chan position */ for (;*pos!='\0' && *pos!=',';pos++) ; /* Empty loop */ if (*pos==',') { *pos='\0'; pos++; } /* OK, pos now points at either null or the next chan * and nextchan now points at the channel name we want to parse next */ /* It's a channel create */ if ((cp=findchannel(nextchan))==NULL) { /* This is the expected case -- the channel didn't exist before */ cp=createchannel(nextchan); cp->timestamp=timestamp; newchan=1; } else { Error("channel",ERR_DEBUG,"Received CREATE for already existing channel %s",cp->index->name->content); if (cp->timestamp==MAGIC_REMOTE_JOIN_TS && timestamp) { /* No valid timestamp on the chan and we received one -- set */ cp->timestamp=timestamp; } newchan=0; } /* Add the user to the channel, preopped */ if (addnicktochannel(cp,(np->numeric)|CUMODE_OP)) { if (newchan) { delchannel(cp); } } else { chanindex *cip = cp->index; /* Flag the channel as new if necessary */ if (newchan) { triggerhook(HOOK_CHANNEL_NEWCHANNEL,cp); } /* If HOOK_CHANNEL_NEWCHANNEL has caused the channel to be deleted, * don't trigger the CREATE hook. */ if (cip->channel == cp) { /* Trigger hook */ harg[0]=cp; harg[1]=np; triggerhook(HOOK_CHANNEL_CREATE,harg); } } nextchan=pos; } return CMD_OK; }
int handleburstmsg(void *source, int cargc, char **cargv) { channel *cp; time_t timestamp; int wipeout=0; int i; int arg=0; char *charp; int newlimit; int waslimit,waskeyed; char *nextnum; unsigned long currentmode; int isnewchan; /* (we don't see the first 2 params in cargc) */ /* AK B #+lod+ 1017561154 +tnk eits ATJWu:o,AiW1a,Ag3lV,AiWnl,AE6oI :%*[email protected] */ if (cargc<2) { Error("channel",ERR_WARNING,"Burst message with only %d parameters",cargc); return CMD_OK; } timestamp=strtol(cargv[1],NULL,10); if ((cp=findchannel(cargv[0]))==NULL) { /* We don't have this channel already */ cp=createchannel(cargv[0]); cp->timestamp=timestamp; isnewchan=1; } else { isnewchan=0; if (timestamp<cp->timestamp) { /* The incoming timestamp is older. Erase all our current channel modes, and the topic. */ cp->timestamp=timestamp; freesstring(cp->topic); cp->topic=NULL; cp->topictime=0; freesstring(cp->key); cp->key=NULL; cp->limit=0; cp->flags=0; clearallbans(cp); /* Remove all +v, +o we currently have */ for(i=0;i<cp->users->hashsize;i++) { if (cp->users->content[i]!=nouser) { cp->users->content[i]&=CU_NUMERICMASK; } } } else if (timestamp>cp->timestamp) { /* The incoming timestamp is greater. Ignore any incoming modes they may happen to set */ wipeout=1; } } /* OK, dealt with the name and timestamp. * Loop over the remaining args */ for (arg=2;arg<cargc;arg++) { if (cargv[arg][0]=='+') { /* Channel modes */ if (wipeout) { /* We ignore the modes, but we need to see if they include +l or +k * so that we can ignore their corresponding values */ for (charp=cargv[arg];*charp;charp++) { if (*charp=='k' || *charp=='l') { arg++; } } } else { /* Clear off the limit and key flags before calling setflags so we can see if the burst tried to set them */ /* If the burst doesn't set them, we restore them afterwards */ waslimit=IsLimit(cp); ClearLimit(cp); waskeyed=IsKey(cp); ClearKey(cp); /* We can then use the flag function for these modes */ setflags(&(cp->flags),CHANMODE_ALL,cargv[arg],cmodeflags,REJECT_NONE); /* Pick up the limit and key, if they were set. Note that the limit comes first */ if (IsLimit(cp)) { /* A limit was SET by the burst */ if (++arg>=cargc) { /* Ran out of args -- damn ircd is spewing out crap again */ Error("channel",ERR_WARNING,"Burst +l with no argument"); break; /* "break" being the operative word */ } else { newlimit=strtol(cargv[arg],NULL,10); } if (cp->limit>0 && waslimit) { /* We had a limit before -- we now have the lowest one of the two */ if (newlimit<cp->limit) { cp->limit=newlimit; } } else { /* No limit before -- we just have the new one */ cp->limit=newlimit; } } else if (waslimit) { SetLimit(cp); /* We had a limit before, but the burst didn't set one. Restore flag. */ } if (IsKey(cp)) { /* A key was SET by the burst */ if (++arg>=cargc) { /* Ran out of args -- oopsie! */ Error("channel",ERR_WARNING,"Burst +k with no argument"); break; } if (waskeyed) { /* We had a key before -- alphabetically first wins */ if (ircd_strcmp(cargv[arg],cp->key->content)<0) { /* Replace our key */ freesstring(cp->key); cp->key=getsstring(cargv[arg],KEYLEN); } } else { /* No key before -- just the new one */ cp->key=getsstring(cargv[arg],KEYLEN); } } else if (waskeyed) { SetKey(cp); /* We had a key before, but the burst didn't set one. Restore flag. */ } } } else if (cargv[arg][0]=='%') { /* We have one or more bans here */ nextnum=cargv[arg]+1; while (*nextnum) { /* Split off the next ban */ for (charp=nextnum;*charp;charp++) { if (*charp==' ') { *charp='\0'; charp++; break; } } setban(cp,nextnum); nextnum=charp; } } else { /* List of numerics */ nextnum=charp=cargv[arg]; currentmode=0; while (*nextnum!='\0') { /* Step over the next numeric */ for (i=0;i<5;i++) { if (*charp++=='\0') break; } if (i<5) { break; } if (*charp==',') { *charp='\0'; charp++; } else if (*charp==':') { *charp='\0'; charp++; currentmode=0; /* Look for modes */ for (;*charp;charp++) { if (*charp=='v') { currentmode|=CUMODE_VOICE; } else if (*charp=='o') { currentmode|=CUMODE_OP; } else if (*charp==',') { charp++; break; } } /* If we're ignore incoming modes, zap it to zero again */ if (wipeout) { currentmode=0; } } /* OK. At this point charp points to either '\0' if we're at the end, * or the start of the next numeric otherwise. nextnum points at a valid numeric * we need to add, and currentmode reflects the correct mode */ addnicktochannel(cp,(numerictolong(nextnum,5)|currentmode)); nextnum=charp; } } } if (cp->users->totalusers==0) { /* Oh dear, the channel is now empty. Perhaps one of those * charming empty burst messages you get sometimes.. */ if (!isnewchan) { /* I really don't think this can happen, can it..? */ /* Only send the LOSTCHANNEL if the channel existed before */ triggerhook(HOOK_CHANNEL_LOSTCHANNEL,cp); } delchannel(cp); } else { /* If this is a new channel, we do the NEWCHANNEL hook also */ if (isnewchan) { triggerhook(HOOK_CHANNEL_NEWCHANNEL,cp); } /* Just one hook to say "something happened to this channel" */ triggerhook(HOOK_CHANNEL_BURST,cp); } return CMD_OK; }
int handlemodemsg(void *source, int cargc, char **cargv) { channel *cp; int dir=1; int arg=2; char *modestr; unsigned long *lp; void *harg[4]; nick *np, *target; int hooknum; int changes=0; if (cargc<2) { return CMD_OK; } if (cargv[0][0]!='#' && cargv[0][0]!='+') { /* Not a channel, ignore */ return CMD_OK; } if ((cp=findchannel(cargv[0]))==NULL) { /* No channel, abort */ Error("channel",ERR_WARNING,"Mode change on non-existent channel %s",cargv[0]); return CMD_OK; } if (((char *)source)[2]=='\0') { /* Server mode change, treat as divine intervention */ np=NULL; } else if ((np=getnickbynumericstr((char *)source))==NULL) { /* No sender, continue but moan */ Error("channel",ERR_WARNING,"Mode change by non-existent user %s on channel %s",(char *)source,cp->index->name->content); } /* Set up the hook data */ harg[0]=cp; harg[1]=np; harg[3]=(void *)(long)(cp->flags); /* Process the mode string one character at a time */ /* Maybe I'll write this more intelligently one day if I can comprehend the ircu code that does this */ for (modestr=cargv[1];*modestr;modestr++) { switch(*modestr) { /* Set whether we are adding or removing modes */ case '+': dir=1; break; case '-': dir=0; break; /* Simple modes: just set or clear based on value of dir */ case 'n': if (dir) { SetNoExtMsg(cp); } else { ClearNoExtMsg(cp); } changes |= MODECHANGE_MODES; break; case 't': if (dir) { SetTopicLimit(cp); } else { ClearTopicLimit(cp); } changes |= MODECHANGE_MODES; break; case 's': if (dir) { SetSecret(cp); ClearPrivate(cp); } else { ClearSecret(cp); } changes |= MODECHANGE_MODES; break; case 'p': if (dir) { SetPrivate(cp); ClearSecret(cp); } else { ClearPrivate(cp); } changes |= MODECHANGE_MODES; break; case 'i': if (dir) { SetInviteOnly(cp); } else { ClearInviteOnly(cp); } changes |= MODECHANGE_MODES; break; case 'm': if (dir) { SetModerated(cp); } else { ClearModerated(cp); } changes |= MODECHANGE_MODES; break; case 'c': if (dir) { SetNoColour(cp); } else { ClearNoColour(cp); } changes |= MODECHANGE_MODES; break; case 'C': if (dir) { SetNoCTCP(cp); } else { ClearNoCTCP(cp); } changes |= MODECHANGE_MODES; break; case 'r': if (dir) { SetRegOnly(cp); } else { ClearRegOnly(cp); } changes |= MODECHANGE_MODES; break; case 'D': if (dir) { SetDelJoins(cp); } else { ClearDelJoins(cp); } changes |= MODECHANGE_MODES; break; case 'u': if (dir) { SetNoQuitMsg(cp); } else { ClearNoQuitMsg(cp); } changes |= MODECHANGE_MODES; break; case 'N': if (dir) { SetNoNotice(cp); } else { ClearNoNotice(cp); } changes |= MODECHANGE_MODES; break; case 'M': if (dir) { SetModNoAuth(cp); } else { ClearModNoAuth(cp); } changes |= MODECHANGE_MODES; break; case 'T': if (dir) { SetSingleTarg(cp); } else { ClearSingleTarg(cp); } changes |= MODECHANGE_MODES; break; /* Parameter modes: advance parameter and possibly read it in */ case 'l': if (dir) { /* +l uses a parameter, but -l does not. * If there is no parameter, don't set the mode. * I guess we should moan too in that case, but * they might be even nastier to us if we do ;) */ if (arg<cargc) { cp->limit=strtol(cargv[arg++],NULL,10); SetLimit(cp); } } else { ClearLimit(cp); cp->limit=0; } changes |= MODECHANGE_MODES; break; case 'k': if (dir) { /* +k uses a parameter in both directions */ if (arg<cargc) { freesstring(cp->key); /* It's probably NULL, but be safe */ cp->key=getsstring(cargv[arg++],KEYLEN); SetKey(cp); } } else { freesstring(cp->key); cp->key=NULL; ClearKey(cp); arg++; /* Eat the arg without looking at it, even if it's not there */ } changes |= MODECHANGE_MODES; break; /* Op/Voice */ case 'o': case 'v': if (arg<cargc) { if((lp=getnumerichandlefromchanhash(cp->users,numerictolong(cargv[arg++],5)))==NULL) { /* They're not on the channel; MODE crossed with part/kill/kick/blah */ Error("channel",ERR_DEBUG,"Mode change for user %s not on channel %s",cargv[arg-1],cp->index->name->content); } else { if ((target=getnickbynumeric(*lp))==NULL) { /* This really is a fuckup, we found them on the channel but there isn't a user with that numeric */ /* This means there's a serious bug in the nick/channel tracking code */ Error("channel",ERR_ERROR,"Mode change for user %s on channel %s who doesn't exist",cargv[arg-1],cp->index->name->content); } else { /* Do the mode change whilst admiring the beautiful code layout */ harg[2]=target; if (*modestr=='o') { if (dir) { *lp |= CUMODE_OP; hooknum=HOOK_CHANNEL_OPPED; } else { *lp &= ~CUMODE_OP; hooknum=HOOK_CHANNEL_DEOPPED; } } else { if (dir) { *lp |= CUMODE_VOICE; hooknum=HOOK_CHANNEL_VOICED; } else { *lp &= ~CUMODE_VOICE; hooknum=HOOK_CHANNEL_DEVOICED; } } triggerhook(hooknum,harg); } } } changes |= MODECHANGE_USERS; break; case 'b': if (arg<cargc) { if (dir) { setban(cp,cargv[arg++]); triggerhook(HOOK_CHANNEL_BANSET,harg); } else { clearban(cp,cargv[arg++],0); triggerhook(HOOK_CHANNEL_BANCLEAR,harg); } } changes |= MODECHANGE_BANS; break; default: Error("channel",ERR_DEBUG,"Unknown mode char '%c' %s on %s",*modestr,dir?"set":"cleared",cp->index->name->content); break; } } harg[2]=(void *)((long)changes); triggerhook(HOOK_CHANNEL_MODECHANGE,(void *)harg); return CMD_OK; }
int loadchandb(char *filename) { FILE *fp; channel *cp; /* Current channel will be here */ char line[1024]; /* Large buffer, just incase */ char *charp; int loaded = 0; if (!(fp = fopen(filename, "r"))) { printlog("Could not open channel file %s.", filename); return 0; } while((fgets(line, 1023, fp))) { /* Read out the line and skip any comments and empty lines too. */ /* Valid comments are: # and // */ if (line[0] == '#' || (line[0] == '/' && line[1] == '/') || line[0] == '\n' || line[0] == '\r') continue; /* Remove the end-of-line chars here */ for (charp = line; *charp; charp++) { if (*charp == '\n' || *charp == '\r') { *charp = '\0'; break; } } /* Is the line long enough? */ /* It needs to be atleast 3 chars long */ /* [#channel] or key=setting */ if (strlen(line) < 3) continue; /* Find channelname or setting */ if (line[0] == '[') { for (charp = &(line[1]); *charp; charp++) { if (*charp == ']') { *charp = '\0'; break; } } if (!(cp = findchannel(&(line[1])))) cp = addchannel(&(line[1])); loaded++; continue; } /* Next line must be a setting */ if (cp) { for (charp = line; *charp; charp++) { if (*charp == '=') { *charp = '\0'; /* Make sure the setting isn't empty */ if (!strlen(charp + 1)) break; /* Now check the input and assign accordingly */ if (!strcasecmp(line, "createdat")) { cp->createdat = (time_t)atoll(charp + 1); } else if (!strcasecmp(line, "lastjoin")) { cp->lastjoin = (time_t)atoll(charp + 1); } else if (!strcasecmp(line, "flags")) { cp->flags = atoi(charp + 1); } } } } } fclose(fp); return loaded; }
int loaduserdb(char *filename) { FILE *fp; dbuser *dup; account *ap; channel *cp = NULL; chanlevel *clp = NULL; char line[1024]; /* Large buffer, just incase */ char *charp; int loaded = 0; if (!(fp = fopen(filename, "r"))) { printlog("Could not open user file %s.", filename); return 0; } while((fgets(line, 1023, fp))) { /* Read out the line and skip any comments and empty lines too. */ /* Valid comments are: # and // */ if (line[0] == '#' || (line[0] == '/' && line[1] == '/') || line[0] == '\n' || line[0] == '\r') continue; /* Remove the end-of-line chars here */ for (charp = line; *charp; charp++) { if (*charp == '\n' || *charp == '\r') { *charp = '\0'; break; } } /* Is the line long enough? */ /* It needs to be atleast 3 chars long */ /* [#account] or <#channel> or key=setting */ if (strlen(line) < 3) continue; /* Find accountname or setting */ if (line[0] == '[') { for (charp = &(line[1]); *charp; charp++) { if (*charp == ']') { *charp = '\0'; break; } } if (!(ap = findaccount(&(line[1])))) ap = addaccount(&(line[1])); printlog("added new account: %s", ap->name); dup = newdbuser(); /* Link account with dbuser */ ap->dbuser = dup; dup->account = ap; cp = NULL; clp = NULL; loaded++; continue; } /* Next line must be a setting */ if (ap) { if (line[0] == '<') { for (charp = &(line[1]); *charp; charp++) { if (*charp == '>') { *charp = '\0'; break; } } cp = findchannel(&(line[1])); if (cp) clp = addchanlevel(cp, ap); continue; } for (charp = line; *charp; charp++) { if (*charp == '=') { *charp = '\0'; /* Make sure the setting isn't empty */ if (!strlen(charp + 1)) break; /* Now check the input and assign accordingly */ if (cp && clp) { /* This is a chanlevel entry */ if (!strcasecmp(line, "lastchanged")) { clp->lastchanged = (time_t)atoll(charp + 1); } else if (!strcasecmp(line, "lastseen")) { clp->lastseen = (time_t)atoll(charp + 1); } else if (!strcasecmp(line, "flags")) { clp->flags = atoi(charp + 1); } } else { /* This is a dbuser entry */ if (!strcasecmp(line, "flags")) { ap->dbuser->flags = atoi(charp + 1); } else if (!strcasecmp(line, "lastseen")) { ap->dbuser->lastseen = (time_t)atoll(charp + 1); } else if (!strcasecmp(line, "trigger")) { ap->dbuser->trigger = atoi(charp + 1); } } } } } } fclose(fp); return loaded; }