CConfig CUser::ToConfig() const {
    CConfig config;
    CConfig passConfig;

    CString sHash;
    switch (m_eHashType) {
        case HASH_NONE:
            sHash = "Plain";
            break;
        case HASH_MD5:
            sHash = "MD5";
            break;
        case HASH_SHA256:
            sHash = "SHA256";
            break;
    }
    passConfig.AddKeyValuePair("Salt", m_sPassSalt);
    passConfig.AddKeyValuePair("Method", sHash);
    passConfig.AddKeyValuePair("Hash", GetPass());
    config.AddSubConfig("Pass", "password", passConfig);

    config.AddKeyValuePair("Nick", GetNick());
    config.AddKeyValuePair("AltNick", GetAltNick());
    config.AddKeyValuePair("Ident", GetIdent());
    config.AddKeyValuePair("RealName", GetRealName());
    config.AddKeyValuePair("BindHost", GetBindHost());
    config.AddKeyValuePair("DCCBindHost", GetDCCBindHost());
    config.AddKeyValuePair("QuitMsg", GetQuitMsg());
    if (CZNC::Get().GetStatusPrefix() != GetStatusPrefix())
        config.AddKeyValuePair("StatusPrefix", GetStatusPrefix());
    config.AddKeyValuePair("Skin", GetSkinName());
    config.AddKeyValuePair("ChanModes", GetDefaultChanModes());
    config.AddKeyValuePair("ChanBufferSize", CString(GetChanBufferSize()));
    config.AddKeyValuePair("QueryBufferSize", CString(GetQueryBufferSize()));
    config.AddKeyValuePair("AutoClearChanBuffer",
                           CString(AutoClearChanBuffer()));
    config.AddKeyValuePair("AutoClearQueryBuffer",
                           CString(AutoClearQueryBuffer()));
    config.AddKeyValuePair("MultiClients", CString(MultiClients()));
    config.AddKeyValuePair("DenyLoadMod", CString(DenyLoadMod()));
    config.AddKeyValuePair("Admin", CString(IsAdmin()));
    config.AddKeyValuePair("DenySetBindHost", CString(DenySetBindHost()));
    config.AddKeyValuePair("TimestampFormat", GetTimestampFormat());
    config.AddKeyValuePair("AppendTimestamp", CString(GetTimestampAppend()));
    config.AddKeyValuePair("PrependTimestamp", CString(GetTimestampPrepend()));
    config.AddKeyValuePair("AuthOnlyViaModule", CString(AuthOnlyViaModule()));
    config.AddKeyValuePair("Timezone", m_sTimezone);
    config.AddKeyValuePair("JoinTries", CString(m_uMaxJoinTries));
    config.AddKeyValuePair("MaxNetworks", CString(m_uMaxNetworks));
    config.AddKeyValuePair("MaxQueryBuffers", CString(m_uMaxQueryBuffers));
    config.AddKeyValuePair("MaxJoins", CString(m_uMaxJoins));
    config.AddKeyValuePair("ClientEncoding", GetClientEncoding());
    config.AddKeyValuePair("Language", GetLanguage());
    config.AddKeyValuePair("NoTrafficTimeout", CString(GetNoTrafficTimeout()));

    // Allow Hosts
    if (!m_ssAllowedHosts.empty()) {
        for (const CString& sHost : m_ssAllowedHosts) {
            config.AddKeyValuePair("Allow", sHost);
        }
    }

    // CTCP Replies
    if (!m_mssCTCPReplies.empty()) {
        for (const auto& itb : m_mssCTCPReplies) {
            config.AddKeyValuePair("CTCPReply",
                                   itb.first.AsUpper() + " " + itb.second);
        }
    }

    // Modules
    const CModules& Mods = GetModules();

    if (!Mods.empty()) {
        for (CModule* pMod : Mods) {
            CString sArgs = pMod->GetArgs();

            if (!sArgs.empty()) {
                sArgs = " " + sArgs;
            }

            config.AddKeyValuePair("LoadModule", pMod->GetModName() + sArgs);
        }
    }

    // Networks
    for (CIRCNetwork* pNetwork : m_vIRCNetworks) {
        config.AddSubConfig("Network", pNetwork->GetName(),
                            pNetwork->ToConfig());
    }

    return config;
}