-
-typedef std::vector<userrec *> UserList;
-UserList listusers; /* vector of people doing a /list */
-class ListTimer *timer;
-
-/** To create a timer which recurs every second, we inherit from InspTimer.
- * InspTimer is only one-shot however, so at the end of each Tick() we simply
- * insert another of ourselves into the pending queue :)
- */
-class ListTimer : public InspTimer
-{
- private:
-
- char buffer[MAXBUF];
- chanrec *chan;
- InspIRCd* ServerInstance;
- const std::string glob;
- size_t ServerNameSize;
-
- public:
-
- ListTimer(InspIRCd* Instance, long interval) : InspTimer(interval,Instance->Time()), ServerInstance(Instance)
- {
- ServerNameSize = 4 + strlen(ServerInstance->Config->ServerName);
- }
-
- virtual void Tick(time_t TIME)
- {
- bool go_again = true;
-
- while (go_again)
- {
- go_again = false;
- for (UserList::iterator iter = listusers.begin(); iter != listusers.end(); iter++)
- {
- /*
- * What we do here:
- * - Get where they are up to
- * - If it's more than total number of channels, erase
- * them from the iterator, set go_again to true
- * - If not, spool more channels
- */
- userrec* u = (userrec*)(*iter);
- ListData* ld;
- u->GetExt("safelist_cache", ld);
- if ((size_t)ld->list_position > ServerInstance->chanlist->size())
- {
- u->Shrink("safelist_cache");
- DELETE(ld);
- listusers.erase(iter);
- go_again = true;
- break;
- }
- chan = NULL;
- /* Attempt to fill up to 25% the user's sendq with /LIST output */
- long amount_sent = 0;
- do
- {
- if (!ld->list_position)
- u->WriteServ("321 %s Channel :Users Name",u->nick);
- chan = ServerInstance->GetChannelIndex(ld->list_position);
- /* spool details */
- bool has_user = (chan && chan->HasUser(u));
- if ((chan) && (chan->modes[CM_PRIVATE]))
- {
- bool display = match(chan->name, ld->glob.c_str());
- long users = chan->GetUserCounter();
- if ((users) && (display))
- {
- int counter = snprintf(buffer, MAXBUF, "322 %s *", u->nick);
- amount_sent += counter + ServerNameSize;
- u->WriteServ(std::string(buffer));
- }
- }
- else if ((chan) && (((!(chan->modes[CM_PRIVATE])) && (!(chan->modes[CM_SECRET]))) || (has_user)))
- {
- bool display = match(chan->name, ld->glob.c_str());
- long users = chan->GetUserCounter();
-
- if ((users) && (display))
- {
- int counter = snprintf(buffer, MAXBUF, "322 %s %s %ld :[+%s] %s",u->nick, chan->name, users, chan->ChanModes(has_user), chan->topic);
- /* Increment total plus linefeed */
- amount_sent += counter + ServerNameSize;
- u->WriteServ(std::string(buffer));
- }
- }
- else
- {
- if (!chan)
- {
- if (!ld->list_ended)
- {
- ld->list_ended = true;
- u->WriteServ("323 %s :End of channel list.",u->nick);
- }
- }
- }
-
- ld->list_position++;
- }
- while ((chan != NULL) && (amount_sent < (u->sendqmax / 4)));
- }
- }
-
- if (listusers.size())
- {
- timer = new ListTimer(ServerInstance,1);
- ServerInstance->Timers->AddTimer(timer);
- }
- else
- {
- timer = NULL;
- }
- }
-};