The complete source code of IdealIRC
http://www.idealirc.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
71 lines
2.0 KiB
71 lines
2.0 KiB
/*
|
|
* IdealIRC Core - Internet Relay Chat API
|
|
* Copyright (C) 2021 Tom-Andre Barstad.
|
|
* This software is licensed under the Software Attribution License.
|
|
* See LICENSE for more information.
|
|
*/
|
|
|
|
#include "IRCMemberEntry.h"
|
|
#include "IRCBase.h"
|
|
#include <algorithm>
|
|
|
|
IRCMemberEntry::IRCMemberEntry(std::shared_ptr<IRCMember> member, IRCBase& owner)
|
|
: m_member(member)
|
|
, m_owner(&owner)
|
|
{}
|
|
|
|
std::shared_ptr<IRCMember> IRCMemberEntry::member() const
|
|
{
|
|
return m_member;
|
|
}
|
|
|
|
const std::string& IRCMemberEntry::modes() const
|
|
{
|
|
return m_modes;
|
|
}
|
|
|
|
void IRCMemberEntry::addMode(char m)
|
|
{
|
|
// Note: "PREFIX" is always present.
|
|
// Value example: (ohv)@%+
|
|
// Value is ordered with most significant first.
|
|
const std::string& prefix = m_owner->isupport().find("PREFIX")->second;
|
|
|
|
// Just interested in the mode letters (ie. ohv)
|
|
const std::string validModes(prefix.begin() + 1, std::find(prefix.begin(), prefix.end(), ')'));
|
|
auto order = [validModes](const char m) -> int {
|
|
auto ret = validModes.find(m);
|
|
return ret != std::string::npos ? static_cast<int>(ret)
|
|
: -1;
|
|
};
|
|
|
|
auto mOrd = order(m);
|
|
if (mOrd < 0)
|
|
return;
|
|
|
|
auto it = m_modes.begin();
|
|
for (auto& mode : m_modes) {
|
|
if (mode == m)
|
|
return;
|
|
else if (order(mode) >= mOrd)
|
|
break;
|
|
else
|
|
++it;
|
|
}
|
|
m_modes.insert(it, m);
|
|
}
|
|
|
|
void IRCMemberEntry::delMode(char m)
|
|
{
|
|
auto pos = m_modes.find_first_of(m);
|
|
|
|
/*
|
|
* Out-of-bounds can happen due to an IRC protocol bug. For example, where you join a channel which has
|
|
* members that got both op (@) and voice (+) but only one of the symbols is visible from NAMES message
|
|
* meaning that the client only picks up the "most significant" mode.
|
|
* IRCv3 implements a fix for this which this client support, but not all servers do.
|
|
* When a member then removes the unknown mode, we get this situation below;
|
|
*/
|
|
if (pos != std::string::npos)
|
|
m_modes.erase(pos, 1);
|
|
}
|
|
|