bool CIRCNetwork::AddChan(const CString& sName, bool bInConfig) { if (sName.empty() || FindChan(sName)) { return false; } CChan* pChan = new CChan(sName, this, bInConfig); m_vChans.push_back(pChan); return true; }
int ReloadData() { #ifdef NICKSERVICES struct NickInfo *temp, *newnick, *nnext; int ii; #ifdef CHANNELSERVICES struct ChanInfo *ctemp, *cnext; #endif #ifdef MEMOSERVICES struct MemoInfo *mtemp, *mnext; #endif #endif /* NICKSERVICES */ #ifdef NICKSERVICES for (ii = 0; ii < NICKLIST_MAX; ++ii) for (temp = nicklist[ii]; temp; temp = temp->next) temp->flags |= NS_DELETE; if (ns_loaddata() == (-2)) { /* * Reload had fatal errors, so use the old database - * go through and KEEP all structures marked for deletion * and DELETE structures not marked, because they are the * ones that were just added in the failed reload */ for (ii = 0; ii < NICKLIST_MAX; ++ii) { for (temp = nicklist[ii]; temp; temp = nnext) { nnext = temp->next; if (!(temp->flags & NS_DELETE)) DeleteNick(temp); else { /* remove the deletion flag */ temp->flags &= ~NS_DELETE; } } } return 0; } else { /* * Reload was ok - now go through and remove the old nick * structures marked for deletion */ for (ii = 0; ii < NICKLIST_MAX; ++ii) { for (temp = nicklist[ii]; temp; temp = nnext) { nnext = temp->next; if (temp->flags & NS_DELETE) { /* * We should try to preserve the old identification * data. Before deleting this nickname, attempt * to find the corresponding one that was just * read from the configuration file, and set it's * ident/collide/split_ts variables correctly. * It is safe to use FindNick() because it will * return the most current entry. If the entry * was deleted, FindNick() will return 'temp' * so we're still not losing anything. */ if ((newnick = FindNick(temp->nick))) { newnick->flags |= (temp->flags & NS_IDENTIFIED); newnick->collide_ts = temp->collide_ts; #ifdef RECORD_SPLIT_TS newnick->split_ts = temp->split_ts; newnick->whensplit = temp->whensplit; #endif /* RECORD_SPLIT_TS */ } DeleteNick(temp); } /* if (temp->flags & NS_DELETE) */ } /* for (temp = nicklist[ii]; temp; temp = nnext) */ } /* for (ii = 0; ii < NICKLIST_MAX; ++ii) */ } #ifdef CHANNELSERVICES for (ii = 0; ii < CHANLIST_MAX; ++ii) for (ctemp = chanlist[ii]; ctemp; ctemp = ctemp->next) ctemp->flags |= CS_DELETE; if (cs_loaddata() == (-2)) { /* * Reload had fatal errors, so use the old database - * go through and KEEP all structures marked for deletion * and DELETE structures not marked, because they are the * ones that were just added in the failed reload */ for (ii = 0; ii < CHANLIST_MAX; ++ii) { for (ctemp = chanlist[ii]; ctemp; ctemp = cnext) { cnext = ctemp->next; if (!(ctemp->flags & CS_DELETE)) DeleteChan(ctemp); else { /* remove the deletion flag */ ctemp->flags &= ~CS_DELETE; } } } return 0; } else { struct Channel *cptr; /* * Reload was ok - now go through and remove the old chan * structures marked for deletion */ for (ii = 0; ii < CHANLIST_MAX; ++ii) { for (ctemp = chanlist[ii]; ctemp; ctemp = cnext) { cnext = ctemp->next; if (ctemp->flags & CS_DELETE) DeleteChan(ctemp); else { /* * It must be a new channel entry, have ChanServ * join the channel */ cptr = FindChannel(ctemp->name); if (cptr && !IsChannelMember(cptr, Me.csptr)) cs_join(ctemp); } } } /* * Now go through the list and have ChanServ part any old chans */ if (Me.csptr) { struct UserChannel *uc, *ucprev; ucprev = NULL; for (uc = Me.csptr->firstchan; uc; ) { if (!FindChan(uc->chptr->name)) { if (ucprev) { ucprev->next = uc->next; cs_part(uc->chptr); uc = ucprev; } else { Me.csptr->firstchan = uc->next; cs_part(uc->chptr); uc = NULL; } } ucprev = uc; if (uc) uc = uc->next; else uc = Me.csptr->firstchan; } } } /* if (Me.csptr) */ #endif /* CHANNELSERVICES */ #ifdef MEMOSERVICES for (ii = 0; ii < MEMOLIST_MAX; ++ii) for (mtemp = memolist[ii]; mtemp; mtemp = mtemp->next) mtemp->flags |= MS_RDELETE; if (ms_loaddata() == (-2)) { /* * Reload had fatal errors, so use the old database - * go through and KEEP all structures marked for deletion * and DELETE structures not marked, because they are the * ones that were just added in the failed reload */ for (ii = 0; ii < MEMOLIST_MAX; ++ii) { for (mtemp = memolist[ii]; mtemp; mtemp = mnext) { mnext = mtemp->next; if (!(mtemp->flags & MS_RDELETE)) DeleteMemoList(mtemp); else { /* remove the deletion flag */ mtemp->flags &= ~MS_RDELETE; } } } return 0; } else { /* * Reload was ok - now go through and remove the old memo * structures marked for deletion */ for (ii = 0; ii < MEMOLIST_MAX; ++ii) { for (mtemp = memolist[ii]; mtemp; mtemp = mnext) { mnext = mtemp->next; if (mtemp->flags & MS_RDELETE) DeleteMemoList(mtemp); } } } #endif /* MEMOSERVICES */ #endif /* NICKSERVICES */ #ifdef STATSERVICES if (ss_loaddata() == (-2)) return 0; #endif /* STATSERVICES */ #ifdef SEENSERVICES if (es_loaddata() == (-2)) return 0; #endif /* SEENSERVICES */ if (os_loaddata() == (-2)) return 0; return 1; } /* ReloadData() */
void CIRCNetwork::Clone(const CIRCNetwork& Network) { m_sName = Network.GetName(); SetNick(Network.GetNick()); SetAltNick(Network.GetAltNick()); SetIdent(Network.GetIdent()); SetRealName(Network.GetRealName()); // Servers const vector<CServer*>& vServers = Network.GetServers(); CString sServer; CServer* pCurServ = GetCurrentServer(); if (pCurServ) { sServer = pCurServ->GetName(); } DelServers(); unsigned int a; for (a = 0; a < vServers.size(); a++) { CServer* pServer = vServers[a]; AddServer(pServer->GetName(), pServer->GetPort(), pServer->GetPass(), pServer->IsSSL()); } m_uServerIdx = 0; for (a = 0; a < m_vServers.size(); a++) { if (sServer.Equals(m_vServers[a]->GetName())) { m_uServerIdx = a + 1; break; } } if (m_uServerIdx == 0) { m_uServerIdx = m_vServers.size(); CIRCSock* pSock = GetIRCSock(); if (pSock) { PutStatus("Jumping servers because this server is no longer in the list"); pSock->Quit(); } } // !Servers // Chans const vector<CChan*>& vChans = Network.GetChans(); for (a = 0; a < vChans.size(); a++) { CChan* pNewChan = vChans[a]; CChan* pChan = FindChan(pNewChan->GetName()); if (pChan) { pChan->SetInConfig(pNewChan->InConfig()); } else { AddChan(pNewChan->GetName(), pNewChan->InConfig()); } } for (a = 0; a < m_vChans.size(); a++) { CChan* pChan = m_vChans[a]; CChan* pNewChan = Network.FindChan(pChan->GetName()); if (!pNewChan) { pChan->SetInConfig(false); } else { pChan->Clone(*pNewChan); } } // !Chans // Modules set<CString> ssUnloadMods; CModules& vCurMods = GetModules(); const CModules& vNewMods = Network.GetModules(); for (a = 0; a < vNewMods.size(); a++) { CString sModRet; CModule* pNewMod = vNewMods[a]; CModule* pCurMod = vCurMods.FindModule(pNewMod->GetModName()); if (!pCurMod) { vCurMods.LoadModule(pNewMod->GetModName(), pNewMod->GetArgs(), CModInfo::NetworkModule, m_pUser, this, sModRet); } else if (pNewMod->GetArgs() != pCurMod->GetArgs()) { vCurMods.ReloadModule(pNewMod->GetModName(), pNewMod->GetArgs(), m_pUser, this, sModRet); } } for (a = 0; a < vCurMods.size(); a++) { CModule* pCurMod = vCurMods[a]; CModule* pNewMod = vNewMods.FindModule(pCurMod->GetModName()); if (!pNewMod) { ssUnloadMods.insert(pCurMod->GetModName()); } } for (set<CString>::iterator it = ssUnloadMods.begin(); it != ssUnloadMods.end(); ++it) { vCurMods.UnloadModule(*it); } // !Modules SetIRCConnectEnabled(Network.GetIRCConnectEnabled()); }
static void m_list(struct Luser *lptr, struct NickInfo *nptr, int ac, char **av) { struct MemoInfo *mi = NULL; struct Memo *memoptr; char status[4]; if (!nptr) return; if (ac >= 2) { if (av[1][0] == '#') { #ifdef CHANNELSERVICES struct ChanInfo *ci; #endif #ifndef CHANNELSERVICES notice(n_MemoServ, lptr->nick, "Channel services are disabled"); return; #else if (!(ci = FindChan(av[1]))) { notice(n_MemoServ, lptr->nick, ERR_CH_NOT_REGGED, av[1]); return; } if (!HasAccess(ci, lptr, CA_AUTOOP)) { notice(n_MemoServ, lptr->nick, "AutoOp access is required to list memos for [\002%s\002]", ci->name); return; } mi = FindMemoList(ci->name); if (!mi) { notice(n_MemoServ, lptr->nick, "There are no recorded memos for [\002%s\002]", ci->name); return; } #endif /* CHANNELSERVICES */ } } if (!mi) { if (!(mi = FindMemoList(nptr->nick))) { notice(n_MemoServ, lptr->nick, "You have no recorded memos"); return; } } notice(n_MemoServ, lptr->nick, "-- Listing memos for [\002%s\002] --", mi->name); notice(n_MemoServ, lptr->nick, " Idx Sender Time Sent"); for (memoptr = mi->memos; memoptr; memoptr = memoptr->next) { if (memoptr->flags & MS_DELETE) strcpy(status, "(D)"); else if (mi->name[0] != '#') { if (memoptr->flags & MS_READ) strcpy(status, "(R)"); else strcpy(status, "(N)"); } else status[0] = '\0'; notice(n_MemoServ, lptr->nick, "%3s %-3d %-18s %s ago", status, memoptr->index, memoptr->sender, timeago(memoptr->sent, 1)); } notice(n_MemoServ, lptr->nick, "-- End of list --"); } /* m_list() */
bool CUser::Clone(const CUser& User, CString& sErrorRet, bool bCloneChans) { unsigned int a = 0; sErrorRet.clear(); if (!User.IsValid(sErrorRet, true)) { return false; } // user names can only specified for the constructor, changing it later // on breaks too much stuff (e.g. lots of paths depend on the user name) if (GetUserName() != User.GetUserName()) { DEBUG("Ignoring username in CUser::Clone(), old username [" << GetUserName() << "]; New username [" << User.GetUserName() << "]"); } if (!User.GetPass().empty()) { SetPass(User.GetPass(), User.GetPassHashType(), User.GetPassSalt()); } SetNick(User.GetNick(false)); SetAltNick(User.GetAltNick(false)); SetIdent(User.GetIdent(false)); SetRealName(User.GetRealName()); SetStatusPrefix(User.GetStatusPrefix()); SetBindHost(User.GetBindHost()); SetDCCBindHost(User.GetDCCBindHost()); SetQuitMsg(User.GetQuitMsg()); SetSkinName(User.GetSkinName()); SetDefaultChanModes(User.GetDefaultChanModes()); SetBufferCount(User.GetBufferCount(), true); SetJoinTries(User.JoinTries()); SetMaxJoins(User.MaxJoins()); // Allowed Hosts m_ssAllowedHosts.clear(); const set<CString>& ssHosts = User.GetAllowedHosts(); for (set<CString>::const_iterator it = ssHosts.begin(); it != ssHosts.end(); ++it) { AddAllowedHost(*it); } for (a = 0; a < m_vClients.size(); a++) { CClient* pSock = m_vClients[a]; if (!IsHostAllowed(pSock->GetRemoteIP())) { pSock->PutStatusNotice("You are being disconnected because your IP is no longer allowed to connect to this user"); pSock->Close(); } } // !Allowed Hosts // Servers const vector<CServer*>& vServers = User.GetServers(); CString sServer; CServer* pCurServ = GetCurrentServer(); if (pCurServ) { sServer = pCurServ->GetName(); } DelServers(); for (a = 0; a < vServers.size(); a++) { CServer* pServer = vServers[a]; AddServer(pServer->GetName(), pServer->GetPort(), pServer->GetPass(), pServer->IsSSL()); } m_uServerIdx = 0; for (a = 0; a < m_vServers.size(); a++) { if (sServer.Equals(m_vServers[a]->GetName())) { m_uServerIdx = a + 1; break; } } if (m_uServerIdx == 0) { m_uServerIdx = m_vServers.size(); CIRCSock* pSock = GetIRCSock(); if (pSock) { PutStatus("Jumping servers because this server is no longer in the list"); pSock->Quit(); } } // !Servers // Chans const vector<CChan*>& vChans = User.GetChans(); for (a = 0; a < vChans.size(); a++) { CChan* pNewChan = vChans[a]; CChan* pChan = FindChan(pNewChan->GetName()); if (pChan) { pChan->SetInConfig(pNewChan->InConfig()); } else { AddChan(pNewChan->GetName(), pNewChan->InConfig()); } } for (a = 0; a < m_vChans.size(); a++) { CChan* pChan = m_vChans[a]; CChan* pNewChan = User.FindChan(pChan->GetName()); if (!pNewChan) { pChan->SetInConfig(false); } else { if (bCloneChans) pChan->Clone(*pNewChan); } } // !Chans // CTCP Replies m_mssCTCPReplies.clear(); const MCString& msReplies = User.GetCTCPReplies(); for (MCString::const_iterator it = msReplies.begin(); it != msReplies.end(); ++it) { AddCTCPReply(it->first, it->second); } // !CTCP Replies // Flags SetIRCConnectEnabled(User.GetIRCConnectEnabled()); SetKeepBuffer(User.KeepBuffer()); SetMultiClients(User.MultiClients()); SetBounceDCCs(User.BounceDCCs()); SetUseClientIP(User.UseClientIP()); SetDenyLoadMod(User.DenyLoadMod()); SetAdmin(User.IsAdmin()); SetDenySetBindHost(User.DenySetBindHost()); SetTimestampAppend(User.GetTimestampAppend()); SetTimestampPrepend(User.GetTimestampPrepend()); SetTimestampFormat(User.GetTimestampFormat()); SetTimezoneOffset(User.GetTimezoneOffset()); // !Flags // Modules set<CString> ssUnloadMods; CModules& vCurMods = GetModules(); const CModules& vNewMods = User.GetModules(); for (a = 0; a < vNewMods.size(); a++) { CString sModRet; CModule* pNewMod = vNewMods[a]; CModule* pCurMod = vCurMods.FindModule(pNewMod->GetModName()); if (!pCurMod) { vCurMods.LoadModule(pNewMod->GetModName(), pNewMod->GetArgs(), this, sModRet); } else if (pNewMod->GetArgs() != pCurMod->GetArgs()) { vCurMods.ReloadModule(pNewMod->GetModName(), pNewMod->GetArgs(), this, sModRet); } } for (a = 0; a < vCurMods.size(); a++) { CModule* pCurMod = vCurMods[a]; CModule* pNewMod = vNewMods.FindModule(pCurMod->GetModName()); if (!pNewMod) { ssUnloadMods.insert(pCurMod->GetModName()); } } for (set<CString>::iterator it = ssUnloadMods.begin(); it != ssUnloadMods.end(); ++it) { vCurMods.UnloadModule(*it); } // !Modules return true; }
static void m_purge(struct Luser *lptr, struct NickInfo *nptr, int ac, char **av) { struct MemoInfo *mi; int cnt; if (!nptr) return; if (ac >= 2) { #ifdef CHANNELSERVICES struct ChanInfo *ci; #endif #ifndef CHANNELSERVICES notice(n_MemoServ, lptr->nick, "Channel services are disabled"); return; #else if (!(ci = FindChan(av[1]))) { notice(n_MemoServ, lptr->nick, ERR_CH_NOT_REGGED, av[1]); return; } if (!HasAccess(ci, lptr, CA_SUPEROP)) { notice(n_MemoServ, lptr->nick, "SuperOp access is required to purge memos for [\002%s\002]", ci->name); return; } if (!(mi = FindMemoList(ci->name))) { notice(n_MemoServ, lptr->nick, "There are no recorded memos for [\002%s\002]", ci->name); return; } cnt = PurgeMemos(mi); notice(n_MemoServ, lptr->nick, "Memos marked for deletion on [\002%s\002] have been purged (%d found)", ci->name, cnt); return; #endif /* CHANNELSERVICES */ } else if (!(mi = FindMemoList(nptr->nick))) { notice(n_MemoServ, lptr->nick, "You have no recorded memos"); return; } cnt = PurgeMemos(mi); notice(n_MemoServ, lptr->nick, "Your memos marked for deletion have been purged (%d found)", cnt); } /* m_purge() */
static void m_send(struct Luser *lptr, struct NickInfo *nptr, int ac, char **av) { char *memotext, /* memo text */ *to; /* who the memo is sent to */ int index; struct NickInfo *master = NULL, *realptr = NULL; #ifdef CHANNELSERVICES struct ChanInfo *ci = NULL; #endif if (ac < 3) { notice(n_MemoServ, lptr->nick, "Syntax: SEND <nick/channel> <text>"); notice(n_MemoServ, lptr->nick, ERR_MORE_INFO, n_MemoServ, "SEND"); return; } if (*av[1] == '#') { #ifndef CHANNELSERVICES notice(n_MemoServ, lptr->nick, "Channel services are disabled"); return; #else if (!(ci = FindChan(av[1]))) { notice(n_MemoServ, lptr->nick, ERR_CH_NOT_REGGED, av[1]); return; } if (!HasAccess(ci, lptr, CA_AUTOOP)) { notice(n_MemoServ, lptr->nick, "AutoOp access is required to send a memo to [\002%s\002]", ci->name); return; } to = ci->name; #endif /* CHANNELSERVICES */ } else { /* it was sent to a nickname */ if (!(realptr = FindNick(av[1]))) { notice(n_MemoServ, lptr->nick, ERR_NOT_REGGED, av[1]); return; } master = GetMaster(realptr); assert(master != 0); if (!(master->flags & NS_MEMOS)) { notice(n_MemoServ, lptr->nick, "[\002%s\002] is rejecting all memos", av[1]); return; } to = master->nick; } /* get the actual memo text now */ if (ac < 3) memotext = MyStrdup(""); else memotext = GetString(ac - 2, av + 2); index = StoreMemo(to, memotext, lptr); if (index) { notice(n_MemoServ, lptr->nick, "Memo has been recorded for [\002%s\002]", realptr ? realptr->nick : to); if (realptr && master) { /* * It was sent to a nickname - check if they are online * and identified and optionally notify them * * we should have here linklist traversal and notifying all clients. * however, that could be a bit cpu intensitive to do for every * memo, so i haven't done it so far. -kre */ if ((master->flags & NS_MEMONOTIFY) && (realptr->flags & NS_IDENTIFIED) && FindClient(realptr->nick)) { notice(n_MemoServ, realptr->nick, "You have a new memo from \002%s\002 (#%d)", lptr->nick, index); notice(n_MemoServ, realptr->nick, "Type \002/msg %s READ %d\002 to read it", n_MemoServ, index); } } /* if (ni) */ #ifdef CHANNELSERVICES else { struct Channel *chptr; struct ChanAccess *ca; char *newtext; /* * It was sent to a channel - notify every AOP or higher */ if ((ci) && (chptr = FindChannel(to))) { struct ChannelUser *cu; struct NickInfo *tmpn; for (cu = chptr->firstuser; cu; cu = cu->next) { if (FindService(cu->lptr)) continue; tmpn = GetLink(cu->lptr->nick); if (HasAccess(ci, cu->lptr, CA_AUTOOP)) { if (tmpn) { /* don't notify people who don't want memos */ if (!(tmpn->flags & NS_MEMOS) || !(tmpn->flags & NS_MEMONOTIFY)) continue; } notice(n_MemoServ, cu->lptr->nick, "New channel memo from \002%s\002 (#%d)", lptr->nick, index); notice(n_MemoServ, cu->lptr->nick, "Type \002/msg %s READ %s %d\002 to read it", n_MemoServ, chptr->name, index); } } } newtext = (char *) MyMalloc(strlen(memotext) + strlen(ci->name) + 4); ircsprintf(newtext, "(%s) %s", ci->name, memotext); for (ca = ci->access; ca; ca = ca->next) { if (ca->nptr) StoreMemo(ca->nptr->nick, newtext, lptr); } MyFree(newtext); } /* else */ #endif /* CHANNELSERVICES */ } /* if (index) */ MyFree (memotext); } /* m_send() */
static void m_forward(struct Luser *lptr, struct NickInfo *nptr, int ac, char **av) { struct MemoInfo *from, *target; struct Memo *memoptr = NULL; struct Memo *fromptr; char *to; /* who the memo is sent to */ int index, cnt; char buf[MAXLINE]; struct NickInfo *master, *realptr; #ifdef CHANNELSERVICES struct ChanInfo *ci = NULL; #endif if (!nptr) return; if (ac < 3) { notice(n_MemoServ, lptr->nick, "Syntax: FORWARD <index|ALL> <nick/channel>"); notice(n_MemoServ, lptr->nick, ERR_MORE_INFO, n_MemoServ, "FORWARD"); return; } if (!(from = FindMemoList(nptr->nick))) { notice(n_MemoServ, lptr->nick, "You have no recorded memos"); return; } index = IsNum(av[1]); if ((index < 0) || (index > from->memocnt) || (!index && (irccmp(av[1], "ALL") != 0))) { notice(n_MemoServ, lptr->nick, "[\002%s\002] is an invalid index", av[1]); return; } master = realptr = NULL; if (*av[2] == '#') { #ifndef CHANNELSERVICES notice(n_MemoServ, lptr->nick, "Channel services are disabled"); return; #else if (!(ci = FindChan(av[2]))) { notice(n_MemoServ, lptr->nick, ERR_CH_NOT_REGGED, av[2]); return; } if (!HasAccess(ci, lptr, CA_AUTOOP)) { notice(n_MemoServ, lptr->nick, "AutoOp access is required to forward a memo to [\002%s\002]", ci->name); return; } to = ci->name; #endif } else { /* it was sent to a nickname */ if (!(realptr = FindNick(av[2]))) { notice(n_MemoServ, lptr->nick, ERR_NOT_REGGED, av[2]); return; } master = GetMaster(realptr); assert(master != 0); if (!(master->flags & NS_MEMOS)) { notice(n_MemoServ, lptr->nick, "[\002%s\002] is rejecting all memos", realptr->nick); return; } to = master->nick; } if (!(target = FindMemoList(to))) { target = MakeMemoList(); target->name = MyStrdup(to); AddMemoList(target); } else if (from == target) { /* * If we let someone forward memos to themselves, * the below loop will never end, eventually malloc()'ing too * much and crashing - head it off at the pass */ notice(n_MemoServ, lptr->nick, "You cannot forward memos to yourself"); return; } if (MaxMemos && (target->memocnt >= MaxMemos)) { notice(n_MemoServ, lptr->nick, "%s has reached the maximum memo limit, and cannot receive more", to); return; } cnt = 0; for (fromptr = from->memos; fromptr; fromptr = fromptr->next) { if (!index || (fromptr->index == index)) { memset(&buf, 0, MAXLINE); target->memocnt++; target->newmemos++; cnt++; memoptr = MakeMemo(); memoptr->sender = MyStrdup(lptr->nick); memoptr->sent = current_ts; memoptr->index = target->memocnt; strcpy(buf, "[Fwd]: "); strncat(buf, fromptr->text, MAXLINE - 8); memoptr->text = MyStrdup(buf); AddMemo(target, memoptr); if (MaxMemos && (target->memocnt >= MaxMemos)) break; } } if (!index) ircsprintf(buf, "All memos have"); else ircsprintf(buf, "Memo #%d has", index); notice(n_MemoServ, lptr->nick, "%s been forwarded to [\002%s\002]", buf, target->name); if (master && realptr) { /* * It was sent to a nickname - check if they are online * and notify them */ if ((master->flags & NS_MEMONOTIFY) && (realptr->flags & NS_IDENTIFIED) && FindClient(realptr->nick)) { notice(n_MemoServ, realptr->nick, "You have %d new forwarded memo%s from \002%s\002", cnt, (cnt == 1) ? "" : "s", memoptr->sender); notice(n_MemoServ, realptr->nick, "Type \002/msg %s LIST\002 to view %s", n_MemoServ, (cnt == 1) ? "it" : "them"); } } /* if (master && realptr) */ #ifdef CHANNELSERVICES else { struct Channel *chptr; /* * It was sent to a channel - notify every AOP or higher */ if ((ci) && (chptr = FindChannel(target->name))) { struct ChannelUser *cu; struct NickInfo *tmpn; for (cu = chptr->firstuser; cu; cu = cu->next) { if (FindService(cu->lptr)) continue; tmpn = GetLink(cu->lptr->nick); if (HasAccess(ci, cu->lptr, CA_AUTOOP)) { if (tmpn) { if (!(tmpn->flags & NS_MEMOS) || !(tmpn->flags & NS_MEMONOTIFY)) continue; } notice(n_MemoServ, cu->lptr->nick, "%d new forwarded channel memo%s from \002%s\002", cnt, (cnt == 1) ? "" : "s", memoptr->sender); notice(n_MemoServ, cu->lptr->nick, "Type \002/msg %s LIST %s\002 to view %s", n_MemoServ, chptr->name, (cnt == 1) ? "it" : "them"); } } } } /* else */ #endif /* CHANNELSERVICES */ } /* m_forward() */
static void m_undel(struct Luser *lptr, struct NickInfo *nptr, int ac, char **av) { struct MemoInfo *mi; struct Memo *memoptr; char istr[MAXLINE]; int index; if (!nptr) return; if (ac < 2) { notice(n_MemoServ, lptr->nick, "Syntax: UNDEL [channel] <index|all>"); notice(n_MemoServ, lptr->nick, ERR_MORE_INFO, n_MemoServ, "UNDEL"); return; } if (ac >= 3) { #ifdef CHANNELSERVICES struct ChanInfo *ci; #endif #ifndef CHANNELSERVICES notice(n_MemoServ, lptr->nick, "Channel services are disabled"); return; #else if (!(ci = FindChan(av[1]))) { notice(n_MemoServ, lptr->nick, ERR_CH_NOT_REGGED, av[1]); return; } if (!HasAccess(ci, lptr, CA_SUPEROP)) { notice(n_MemoServ, lptr->nick, "SuperOp access is required to undelete memos for [\002%s\002]", ci->name); return; } if (!(mi = FindMemoList(ci->name))) { notice(n_MemoServ, lptr->nick, "There are no recorded memos for [\002%s\002]", ci->name); return; } index = IsNum(av[2]); #endif /* CHANNELSERVICES */ } else { if (!(mi = FindMemoList(nptr->nick))) { notice(n_MemoServ, lptr->nick, "You have no recorded memos"); return; } index = IsNum(av[1]); } if ((index < 0) || (index > mi->memocnt) || (!index && (irccmp(av[(ac >= 3) ? 2 : 1], "ALL") != 0))) { notice(n_MemoServ, lptr->nick, "[\002%s\002] is an invalid index", av[(ac >= 3) ? 2 : 1]); return; } for (memoptr = mi->memos; memoptr; memoptr = memoptr->next) { if (!index || (memoptr->index == index)) memoptr->flags &= ~MS_DELETE; } if (index) ircsprintf(istr, "Memo #%d has", index); else strcpy(istr, "All memos have"); if (ac >= 3) notice(n_MemoServ, lptr->nick, "%s been unmarked for deletion for [\002%s\002]", istr, av[1]); else notice(n_MemoServ, lptr->nick, "%s been unmarked for deletion", istr); } /* m_undel() */
static void m_read(struct Luser *lptr, struct NickInfo *nptr, int ac, char **av) { struct MemoInfo *mi; int index; struct Memo *memoptr; char istr[10]; if (!nptr) return; if (ac < 2) { notice(n_MemoServ, lptr->nick, "Syntax: READ [channel] <index|all>"); notice(n_MemoServ, lptr->nick, ERR_MORE_INFO, n_MemoServ, "READ"); return; } if (ac >= 3) { #ifdef CHANNELSERVICES struct ChanInfo *ci; #endif #ifndef CHANNELSERVICES notice(n_MemoServ, lptr->nick, "Channel services are disabled"); return; #else if (!(ci = FindChan(av[1]))) { notice(n_MemoServ, lptr->nick, ERR_CH_NOT_REGGED, av[1]); return; } if (!HasAccess(ci, lptr, CA_AUTOOP)) { notice(n_MemoServ, lptr->nick, "AutoOp access is required to read memos for [\002%s\002]", ci->name); return; } if (!(mi = FindMemoList(ci->name))) { notice(n_MemoServ, lptr->nick, "There are no recorded memos for [\002%s\002]", ci->name); return; } index = IsNum(av[2]); #endif /* CHANNELSERVICES */ } else { if (!(mi = FindMemoList(nptr->nick))) { notice(n_MemoServ, lptr->nick, "You have no recorded memos"); return; } index = IsNum(av[1]); } if ((index < 0) || (index > mi->memocnt) || (!index && (irccmp(av[(ac >= 3) ? 2 : 1], "ALL") != 0))) { notice(n_MemoServ, lptr->nick, "[\002%s\002] is an invalid index", av[(ac >= 3) ? 2 : 1]); return; } for (memoptr = mi->memos; memoptr; memoptr = memoptr->next) { if (!index || (memoptr->index == index)) { notice(n_MemoServ, lptr->nick, "Memo #%d from %s (sent %s ago):", memoptr->index, memoptr->sender, timeago(memoptr->sent, 1)); notice(n_MemoServ, lptr->nick, memoptr->text); if (ac < 3) { /* only mark nickname memos as read - not channel memos */ if (!(memoptr->flags & MS_READ)) mi->newmemos--; memoptr->flags |= MS_READ; } } } if (index) ircsprintf(istr, "%d", index); else strcpy(istr, "ALL"); if (ac >= 3) notice(n_MemoServ, lptr->nick, "To delete, type \002/msg %s DEL %s %s", n_MemoServ, av[1], istr); else notice(n_MemoServ, lptr->nick, "To delete, type \002/msg %s DEL %s", n_MemoServ, istr); } /* m_read() */
void UpdateChanModes(struct Luser *lptr, char *who, struct Channel *cptr, char *modes) { int add; char *tmp, *p; register char ch; struct Luser *userptr; #if defined(NICKSERVICES) && defined(CHANNELSERVICES) int cs_deoped = 0; /* was chanserv deoped? */ #endif char **modeargs; /* arguements to +l/k/o/v modes */ char tempargs[MAXLINE]; int argcnt; /* number of arguements */ int argidx; /* current index in modeargs[] */ #ifndef SAVE_TS char sendstr[MAXLINE]; #endif if (!cptr) return; assert(lptr || who); if (lptr) { SendUmode(OPERUMODE_M, "*** %s: Mode [%s] by %s!%s@%s", cptr->name, modes, lptr->nick, lptr->username, lptr->hostname); putlog(LOG3, "%s: mode change \"%s\" by %s!%s@%s", cptr->name, modes, lptr->nick, lptr->username, lptr->hostname); } else { SendUmode(OPERUMODE_M, "*** %s: Mode [%s] by %s", cptr->name, modes, who); putlog(LOG3, "%s: mode change \"%s\" by %s", cptr->name, modes, who); } if ((tmp = strchr(modes, ' '))) strcpy(tempargs, *(tmp + 1) ? tmp + 1 : ""); else tempargs[0] = '\0'; argcnt = SplitBuf(tempargs, &modeargs); /* * This routine parses the given channel modes and keeps * the corresponding lists correctly updated - also make * sure OperServ and ChanServ remain opped */ add = 0; argidx = (-1); for (tmp = modes; *tmp; ++tmp) { ch = *tmp; if (IsSpace(ch)) break; switch (ch) { case ' ': case '\n': case '\r': break; case '-': { add = 0; break; } case '+': { add = 1; break; } /* * Op/DeOp */ case 'o': { ++argidx; if (argidx >= argcnt) { /* * there are more 'o' flags than there are nicknames, * just break */ break; } if (!(userptr = FindClient(modeargs[argidx]))) break; SetChannelMode(cptr, add, MODE_O, userptr, 0); if (add) { #ifdef STATSERVICES if (lptr) ++lptr->numops; #endif } /* if (add) */ else { if (userptr == Me.osptr) { if (!FloodCheck(cptr, lptr, Me.osptr, 0)) { #ifdef SAVE_TS os_part(cptr); os_join(cptr); #else toserv(":%s MODE %s +o %s\n", n_OperServ, cptr->name, n_OperServ); #endif } if (!lptr) { putlog(LOG1, "%s: %s attempted to deop %s", cptr->name, who, n_OperServ); } else { putlog(LOG1, "%s: %s!%s@%s attempted to deop %s", cptr->name, lptr->nick, lptr->username, lptr->hostname, n_OperServ); } } #if defined(NICKSERVICES) && defined(CHANNELSERVICES) else if (userptr == Me.csptr) { cs_deoped = 1; } #endif /* defined(NICKSERVICES) && defined(CHANNELSERVICES) */ #ifdef STATSERVICES if (lptr) ++lptr->numdops; #endif } /* else if (!add) */ #if defined(NICKSERVICES) && defined(CHANNELSERVICES) cs_CheckModes(lptr, FindChan(cptr->name), !add, MODE_O, userptr); #endif break; } /* case 'o' */ /* * Voice/DeVoice */ case 'v': { ++argidx; if (argidx >= argcnt) break; if (!(userptr = FindClient(modeargs[argidx]))) break; SetChannelMode(cptr, add, MODE_V, userptr, 0); if (add) { #ifdef STATSERVICES if (lptr) ++lptr->numvoices; #endif } else { #ifdef STATSERVICES if (lptr) ++lptr->numdvoices; #endif } /* else if (!add) */ #if defined(NICKSERVICES) && defined(CHANNELSERVICES) cs_CheckModes(lptr, FindChan(cptr->name), !add, MODE_V, userptr); #endif break; } /* case 'v' */ #ifdef HYBRID7 /* HalfOp/DeHalfOp -Janos */ case 'h': { ++argidx; if (argidx >= argcnt) break; if (!(userptr = FindClient(modeargs[argidx]))) break; SetChannelMode(cptr, add, MODE_H, userptr, 0); if (add) { #ifdef STATSERVICES if (lptr) ++lptr->numhops; #endif } else { #ifdef STATSERVICES if (lptr) ++lptr->numdhops; #endif } /* else if (!add) */ #if defined(NICKSERVICES) && defined(CHANNELSERVICES) cs_CheckModes(lptr, FindChan(cptr->name), !add, MODE_H, userptr); #endif break; } /* case 'h'*/ #endif /* HYBRID7 */ /* * Channel limit */ case 'l': { if (add) { ++argidx; if (argidx >= argcnt) break; cptr->limit = atoi(modeargs[argidx]); } else cptr->limit = 0; #if defined(NICKSERVICES) && defined(CHANNELSERVICES) cs_CheckModes(lptr, FindChan(cptr->name), !add, MODE_L, 0); #endif break; } /* case 'l' */ /* * Channel key */ case 'k': { ++argidx; if (argidx >= argcnt) break; #ifndef BLOCK_ALLOCATION if (cptr->key) MyFree(cptr->key); #endif if (add) { #ifdef BLOCK_ALLOCATION strncpy(cptr->key, modeargs[argidx], KEYLEN); cptr->key[KEYLEN] = '\0'; #else cptr->key = MyStrdup(modeargs[argidx]); #endif /* BLOCK_ALLOCATION */ } else { #ifdef BLOCK_ALLOCATION cptr->key[0] = '\0'; #else cptr->key = 0; #endif /* BLOCK_ALLOCATION */ } #if defined(NICKSERVICES) && defined(CHANNELSERVICES) cs_CheckModes(lptr, FindChan(cptr->name), !add, MODE_K, 0); #endif break; } /* case 'k' */ /* * Channel forwarding target */ case 'f': { ++argidx; if (argidx >= argcnt) break; #ifndef BLOCK_ALLOCATION if (cptr->forward) MyFree(cptr->forward); #endif if (add) { #ifdef BLOCK_ALLOCATION strncpy(cptr->forward, modeargs[argidx], CHANNELLEN); cptr->forward[CHANNELLEN] = '\0'; #else cptr->forward = MyStrdup(modeargs[argidx]); #endif /* BLOCK_ALLOCATION */ } else { #ifdef BLOCK_ALLOCATION cptr->forward[0] = '\0'; #else cptr->forward = 0; #endif /* BLOCK_ALLOCATION */ } #if defined(NICKSERVICES) && defined(CHANNELSERVICES) cs_CheckModes(lptr, FindChan(cptr->name), !add, MODE_F, 0); #endif break; } /* case 'f' */ /* * Channel ban */ case 'b': { ++argidx; if (argidx >= argcnt) break; /* if it's a forwarding ban like nick!ident@host!#channel * just drop the forward channel * found by CheeToS -- jilles */ p = strchr(modeargs[argidx], '!'); if (p != NULL) { p = strchr(p + 1, '!'); if (p != NULL) *p = '\0'; } if (add) AddBan(who, cptr, modeargs[argidx]); else DeleteBan(cptr, modeargs[argidx]); if (p != NULL) *p = '!'; break; } /* case 'b' */ #ifdef GECOSBANS /* * Channel deny */ case 'd': { ++argidx; if (argidx >= argcnt) break; if (add) AddGecosBan(who, cptr, modeargs[argidx]); else DeleteGecosBan(cptr, modeargs[argidx]); break; } /* case 'd' */ #endif /* GECOSBANS */ /* * Channel exception */ case 'e': { ++argidx; if (argidx >= argcnt) break; if (add) AddException(who, cptr, modeargs[argidx]); else DeleteException(cptr, modeargs[argidx]); break; } /* case 'e' */ #ifdef HYBRID7 /* Channel invite exception -Janos */ case 'I': { ++argidx; if (argidx >= argcnt) break; if (add) AddInviteException(who, cptr, modeargs[argidx]); else DeleteInviteException(cptr, modeargs[argidx]); break; } /* case 'I' */ #endif /* HYBRID7 */ default: { int modeflag = 0; if (ch == 's') modeflag = MODE_S; else if (ch == 'p') modeflag = MODE_P; else if (ch == 'n') modeflag = MODE_N; else if (ch == 't') modeflag = MODE_T; else if (ch == 'm') modeflag = MODE_M; else if (ch == 'i') modeflag = MODE_I; else if (ch == 'r') modeflag = MODE_R; else if (ch == 'z') modeflag = MODE_Z; else if (ch == 'P') modeflag = MODE_CAPP; #if 0 /* doesn't exist in 1.0.34 */ else if (ch == 'F') modeflag = MODE_CAPF; #endif else if (ch == 'Q') modeflag = MODE_CAPQ; #ifdef HYBRID7 else if (ch == 'a') modeflag = MODE_A; #endif else if (ch == 'c') modeflag = MODE_C; else if (ch == 'g') modeflag = MODE_G; else if (ch == 'L') modeflag = MODE_CAPL; else if (ch == 'R') modeflag = MODE_CAPR; if (modeflag) { if (add) cptr->modes |= modeflag; else cptr->modes &= ~modeflag; } #if defined(NICKSERVICES) && defined(CHANNELSERVICES) if (modeflag) cs_CheckModes(lptr, FindChan(cptr->name), !add, modeflag, 0); #endif break; } /* default: */ } /* switch (*tmp) */ } /* for (tmp = modes; *tmp; ++tmp) */ MyFree(modeargs); #if defined(NICKSERVICES) && defined(CHANNELSERVICES) if ((cs_deoped) && (!FloodCheck(cptr, lptr, Me.csptr, 0))) { /* reop ChanServ */ #ifdef SAVE_TS cs_part(cptr); cs_join(FindChan(cptr->name)); #else toserv(":%s MODE %s +o %s\n", n_ChanServ, cptr->name, n_ChanServ); #endif if (!lptr) putlog(LOG1, "%s: %s attempted to deop %s", cptr->name, who, n_ChanServ); else putlog(LOG1, "%s: %s!%s@%s attempted to deop %s", cptr->name, lptr->nick, lptr->username, lptr->hostname, n_ChanServ); } #endif /* defined(NICKSERVICES) && defined(CHANNELSERVICES) */ } /* UpdateChanModes() */
void RemoveFromChannel(struct Channel *cptr, struct Luser *lptr) { struct UserChannel *tempchan, *prev = NULL; struct ChannelUser *tempuser, *prev2 = NULL; if (!cptr || !lptr) return; SendUmode(OPERUMODE_P, "*** Channel part: %s (%s)", lptr->nick, cptr->name); /* Is this the contact? */ #ifdef CHANNELSERVICES { struct NickInfo *nptr; struct ChanInfo *ciptr; if ((nptr = FindNick(lptr->nick)) && (ciptr = FindChan(cptr->name))) { if (nptr->flags & NS_IDENTIFIED) { if (ciptr->contact && irccmp(lptr->nick, ciptr->contact) == 0) /* That's the contact joining. Update activity timer */ ciptr->last_contact_active = current_ts; if (ciptr->alternate && irccmp(lptr->nick, ciptr->alternate) == 0) ciptr->last_alternate_active = current_ts; } } } #endif /* remove cptr from lptr's chan list */ for (tempchan = lptr->firstchan; tempchan; tempchan = tempchan->next) { if (cptr == tempchan->chptr) { if (prev) prev->next = tempchan->next; else lptr->firstchan = tempchan->next; MyFree(tempchan); tempchan = NULL; break; } prev = tempchan; } /* remove lptr from cptr's nick list */ for (tempuser = cptr->firstuser; tempuser; tempuser = tempuser->next) { if (lptr == tempuser->lptr) { if (prev2) prev2->next = tempuser->next; else cptr->firstuser = tempuser->next; MyFree(tempuser); tempuser = NULL; --cptr->numusers; break; } prev2 = tempuser; } if (cptr->numusers == 0) DeleteChannel(cptr); /* the last nick left the chan, erase it */ } /* RemoveFromChannel() */