void SetChan(const CString& sLine) {
        const CString sVar = sLine.Token(1).AsLower();
        CString sUsername = sLine.Token(2);
        CString sNetwork = sLine.Token(3);
        CString sChan = sLine.Token(4);
        CString sValue = sLine.Token(5, true);

        if (sValue.empty()) {
            PutModule(
                t_s("Usage: SetChan <variable> <username> <network> <chan> "
                    "<value>"));
            return;
        }

        CUser* pUser = FindUser(sUsername);
        if (!pUser) return;

        CIRCNetwork* pNetwork = FindNetwork(pUser, sNetwork);
        if (!pNetwork) {
            return;
        }

        std::vector<CChan*> vChans = pNetwork->FindChans(sChan);
        if (vChans.empty()) {
            PutModule(t_f("Error: No channels matching [{1}] found.")(sChan));
            return;
        }

        for (CChan* pChan : vChans) {
            if (sVar == "defmodes") {
                pChan->SetDefaultModes(sValue);
                PutModule(pChan->GetName() + ": DefModes = " + sValue);
            } else if (sVar == "buffersize" || sVar == "buffer") {
                unsigned int i = sValue.ToUInt();
                if (sValue.Equals("-")) {
                    pChan->ResetBufferCount();
                    PutModule(pChan->GetName() + ": BufferSize = " +
                              CString(pChan->GetBufferCount()));
                } else if (pChan->SetBufferCount(i, GetUser()->IsAdmin())) {
                    // Admins don't have to honour the buffer limit
                    PutModule(pChan->GetName() + ": BufferSize = " + sValue);
                } else {
                    PutModule(
                        t_f("Setting failed, limit for buffer size is {1}")(
                            CString(CZNC::Get().GetMaxBufferSize())));
                    return;
                }
            } else if (sVar == "inconfig") {
                bool b = sValue.ToBool();
                pChan->SetInConfig(b);
                PutModule(pChan->GetName() + ": InConfig = " + CString(b));
            } else if (sVar == "keepbuffer") {
                // XXX compatibility crap, added in 0.207
                bool b = !sValue.ToBool();
                pChan->SetAutoClearChanBuffer(b);
                PutModule(pChan->GetName() + ": AutoClearChanBuffer = " +
                          CString(b));
            } else if (sVar == "autoclearchanbuffer") {
                if (sValue.Equals("-")) {
                    pChan->ResetAutoClearChanBuffer();
                } else {
                    bool b = sValue.ToBool();
                    pChan->SetAutoClearChanBuffer(b);
                }
                PutModule(pChan->GetName() + ": AutoClearChanBuffer = " +
                          CString(pChan->AutoClearChanBuffer()));
            } else if (sVar == "detached") {
                bool b = sValue.ToBool();
                if (pChan->IsDetached() != b) {
                    if (b)
                        pChan->DetachUser();
                    else
                        pChan->AttachUser();
                }
                PutModule(pChan->GetName() + ": Detached = " + CString(b));
            } else if (sVar == "key") {
                pChan->SetKey(sValue);
                PutModule(pChan->GetName() + ": Key = " + sValue);
            } else {
                PutModule(t_s("Error: Unknown variable"));
                return;
            }
        }
    }