- ModeHandler* mh = NULL;
- unsigned long paramptr = 3;
- std::string to_bounce = "";
- std::string to_keep = "";
- std::vector<std::string> params_to_keep;
- std::string params_to_bounce = "";
- bool adding = true;
- char cur_change = 1;
- char old_change = 0;
- char old_bounce_change = 0;
- /* Merge modes, basically do special stuff to mode with params */
- for (std::string::iterator x = params[2].begin(); x != params[2].end(); x++)
- {
- switch (*x)
- {
- case '-':
- adding = false;
- break;
- case '+':
- adding = true;
- break;
- default:
- if (adding)
- {
- /* We only care about whats being set,
- * not whats being unset
- */
- mh = this->Instance->Modes->FindMode(*x, chan ? MODETYPE_CHANNEL : MODETYPE_USER);
- if ((mh) && (mh->GetNumParams(adding) > 0) && (!mh->IsListMode()))
- {
- /* We only want to do special things to
- * modes with parameters, we are going to rewrite
- * those parameters
- */
- ModePair ret;
- adding ? cur_change = '+' : cur_change = '-';
- ret = mh->ModeSet(smode ? NULL : who, dst, chan, params[paramptr]);
- /* The mode is set here, check which we should keep */
- if (ret.first)
- {
- bool which_to_keep = mh->CheckTimeStamp(TS, ourTS, params[paramptr], ret.second, chan);
- if (which_to_keep == true)
- {
- /* Keep ours, bounce theirs:
- * Send back ours to them and
- * drop their mode changs
- */
- adding ? cur_change = '+' : cur_change = '-';
- if (cur_change != old_bounce_change)
- to_bounce += cur_change;
- to_bounce += *x;
- old_bounce_change = cur_change;
- if ((mh->GetNumParams(adding) > 0) && (paramptr < params.size()))
- params_to_bounce.append(" ").append(ret.second);
- }
- else
- {
- /* Keep theirs: Accept their mode change,
- * do nothing else
- */
- adding ? cur_change = '+' : cur_change = '-';
- if (cur_change != old_change)
- to_keep += cur_change;
- to_keep += *x;
- old_change = cur_change;
- if ((mh->GetNumParams(adding) > 0) && (paramptr < params.size()))
- params_to_keep.push_back(params[paramptr]);
- }
- }
- else
- {
- /* Mode isnt set here, we want it */
- adding ? cur_change = '+' : cur_change = '-';
- if (cur_change != old_change)
- to_keep += cur_change;
- to_keep += *x;
- old_change = cur_change;
- if ((mh->GetNumParams(adding) > 0) && (paramptr < params.size()))
- params_to_keep.push_back(params[paramptr]);
- }
- paramptr++;
- }
- else
- {
- mh = this->Instance->Modes->FindMode(*x, chan ? MODETYPE_CHANNEL : MODETYPE_USER);
- if (mh)
- {
- adding ? cur_change = '+' : cur_change = '-';
-
- /* Just keep this, safe to merge with no checks
- * it has no parameters
- */
-
- if (cur_change != old_change)
- to_keep += cur_change;
- to_keep += *x;
- old_change = cur_change;
-
- if ((mh->GetNumParams(adding) > 0) && (paramptr < params.size()))
- {
- params_to_keep.push_back(params[paramptr++]);
- }
- }
- }
- }
- else
- {
- mh = this->Instance->Modes->FindMode(*x, chan ? MODETYPE_CHANNEL : MODETYPE_USER);
- if (mh)
- {
- /* Taking a mode away */
- adding ? cur_change = '+' : cur_change = '-';
- if (cur_change != old_change)
- to_keep += cur_change;
- to_keep += *x;
- old_change = cur_change;
- if ((mh->GetNumParams(adding) > 0) && (paramptr < params.size()))
- params_to_keep.push_back(params[paramptr++]);
- }
- }
- break;
- }
- }
- if (to_bounce.length())
- {
- std::deque<std::string> newparams;
- newparams.push_back(params[0]);
- newparams.push_back(ConvToStr(ourTS));
- newparams.push_back(to_bounce+params_to_bounce);
- Utils->DoOneToOne(this->Instance->Config->ServerName,"FMODE",newparams,sourceserv);
- }
- if (to_keep.length())
- {
- unsigned int n = 2;
- unsigned int q = 0;
- modelist[0] = params[0].c_str();
- modelist[1] = to_keep.c_str();
- if (params_to_keep.size() > 0)
- {
- for (q = 0; (q < params_to_keep.size()) && (q < 64); q++)
- {
- modelist[n++] = params_to_keep[q].c_str();
- }
- }