+ *offset++ = n + 65;
+ extparam.clear();
+ switch (n)
+ {
+ case CM_KEY:
+ extparam = (showkey ? this->key : "<key>");
+ break;
+ case CM_LIMIT:
+ extparam = ConvToStr(this->limit);
+ break;
+ case CM_NOEXTERNAL:
+ case CM_TOPICLOCK:
+ case CM_INVITEONLY:
+ case CM_MODERATED:
+ case CM_SECRET:
+ case CM_PRIVATE:
+ /* We know these have no parameters */
+ break;
+ default:
+ extparam = this->GetModeParameter(n + 65);
+ break;
+ }
+ if (!extparam.empty())
+ {
+ charlcat(sparam,' ',MAXBUF);
+ strlcat(sparam,extparam.c_str(),MAXBUF);
+ }
+ }
+ }
+
+ /* Null terminate scratch */
+ *offset = '\0';
+ strlcat(scratch,sparam,MAXBUF);
+ return scratch;
+}
+
+/* compile a userlist of a channel into a string, each nick seperated by
+ * spaces and op, voice etc status shown as @ and +, and send it to 'user'
+ */
+void chanrec::UserList(userrec *user, CUList *ulist)
+{
+ char list[MAXBUF];
+ size_t dlen, curlen;
+ int MOD_RESULT = 0;
+
+ if (!IS_LOCAL(user))
+ return;
+
+ FOREACH_RESULT(I_OnUserList,OnUserList(user, this, ulist));
+ if (MOD_RESULT == 1)
+ return;
+
+ dlen = curlen = snprintf(list,MAXBUF,"353 %s = %s :", user->nick, this->name);
+
+ int numusers = 0;
+ char* ptr = list + dlen;
+
+ if (!ulist)
+ ulist = this->GetUsers();
+
+ /* Improvement by Brain - this doesnt change in value, so why was it inside
+ * the loop?
+ */
+ bool has_user = this->HasUser(user);
+
+ for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++)
+ {
+ if ((!has_user) && (i->first->IsModeSet('i')))
+ {
+ /*
+ * user is +i, and source not on the channel, does not show
+ * nick in NAMES list
+ */
+ continue;
+ }
+
+ if (i->first->Visibility && !i->first->Visibility->VisibleTo(user))
+ continue;
+
+ size_t ptrlen = snprintf(ptr, MAXBUF, "%s%s ", this->GetPrefixChar(i->first), i->second.c_str());
+ /* OnUserList can change this - reset it back to normal */
+ i->second = i->first->nick;
+
+ curlen += ptrlen;
+ ptr += ptrlen;
+
+ numusers++;
+
+ if (curlen > (480-NICKMAX))
+ {
+ /* list overflowed into multiple numerics */
+ user->WriteServ(std::string(list));
+
+ /* reset our lengths */
+ dlen = curlen = snprintf(list,MAXBUF,"353 %s = %s :", user->nick, this->name);
+ ptr = list + dlen;
+
+ ptrlen = 0;
+ numusers = 0;
+ }
+ }
+
+ /* if whats left in the list isnt empty, send it */
+ if (numusers)
+ {
+ user->WriteServ(std::string(list));
+ }
+
+ user->WriteServ("366 %s %s :End of /NAMES list.", user->nick, this->name);
+}
+
+long chanrec::GetMaxBans()
+{
+ /* Return the cached value if there is one */
+ if (this->maxbans)
+ return this->maxbans;
+
+ /* If there isnt one, we have to do some O(n) hax to find it the first time. (ick) */
+ for (std::map<std::string,int>::iterator n = ServerInstance->Config->maxbans.begin(); n != ServerInstance->Config->maxbans.end(); n++)
+ {
+ if (match(this->name,n->first.c_str()))
+ {
+ this->maxbans = n->second;
+ return n->second;
+ }
+ }
+
+ /* Screw it, just return the default of 64 */
+ this->maxbans = 64;
+ return this->maxbans;
+}
+
+void chanrec::ResetMaxBans()
+{
+ this->maxbans = 0;
+}
+
+/* returns the status character for a given user on a channel, e.g. @ for op,
+ * % for halfop etc. If the user has several modes set, the highest mode
+ * the user has must be returned.
+ */
+const char* chanrec::GetPrefixChar(userrec *user)
+{
+ static char pf[2] = {0, 0};
+
+ prefixlist::iterator n = prefixes.find(user);
+ if (n != prefixes.end())
+ {
+ if (n->second.size())
+ {
+ /* If the user has any prefixes, their highest prefix
+ * will always be at the head of the list, as the list is
+ * sorted in rank order highest first (see SetPrefix()
+ * for reasons why)
+ */
+ *pf = n->second.begin()->first;
+ return pf;
+ }
+ }
+
+ *pf = 0;
+ return pf;
+}
+
+const char* chanrec::GetAllPrefixChars(userrec* user)
+{
+ static char prefix[MAXBUF];
+ int ctr = 0;
+ *prefix = 0;
+
+ prefixlist::iterator n = prefixes.find(user);
+ if (n != prefixes.end())
+ {
+ for (std::vector<prefixtype>::iterator x = n->second.begin(); x != n->second.end(); x++)
+ {
+ prefix[ctr++] = x->first;