Merge branch 'master' of https://github.com/AttorneyOnline/akashi
This commit is contained in:
commit
535c05f3e2
@ -10,4 +10,8 @@ Requires Qt >= 5.10, and Qt websockets
|
||||
make
|
||||
```
|
||||
|
||||
Copyright © scatterflower 2021
|
||||
Copyright © scatterflower 2020-2021
|
||||
|
||||
Copyright © Salanto 2021
|
||||
|
||||
Copyright © in1tiate 2021
|
||||
|
@ -42,10 +42,9 @@ class AOClient : public QObject {
|
||||
AOClient(Server* p_server, QTcpSocket* p_socket, QObject* parent = nullptr, int user_id = 0);
|
||||
~AOClient();
|
||||
|
||||
QString getHwid();
|
||||
QString getIpid();
|
||||
Server* getServer();
|
||||
void setHwid(QString p_hwid);
|
||||
QString getIpid();
|
||||
void calculateIpid();
|
||||
|
||||
int id;
|
||||
|
||||
@ -59,6 +58,7 @@ class AOClient : public QObject {
|
||||
QString ooc_name = "";
|
||||
QString showname = "";
|
||||
bool global_enabled = true;
|
||||
bool is_muted = false;
|
||||
struct ClientVersion {
|
||||
QString string;
|
||||
int release = -1;
|
||||
@ -79,6 +79,7 @@ class AOClient : public QObject {
|
||||
{"MOTD", 1ULL << 7},
|
||||
{"ANNOUNCE", 1ULL << 8},
|
||||
{"MODCHAT", 1ULL << 9},
|
||||
{"MUTE", 1ULL << 10},
|
||||
{"SUPER", ~0ULL}
|
||||
};
|
||||
|
||||
@ -221,6 +222,8 @@ class AOClient : public QObject {
|
||||
void cmdAnnounce(int argc, QStringList argv);
|
||||
void cmdM(int argc, QStringList argv);
|
||||
void cmdGM(int argc, QStringList argv);
|
||||
void cmdMute(int argc, QStringList argv);
|
||||
void cmdUnmute(int argc, QStringList argv);
|
||||
// Casing/RP
|
||||
void cmdPlay(int argc, QStringList argv);
|
||||
void cmdNeed(int argc, QStringList argv);
|
||||
@ -245,6 +248,7 @@ class AOClient : public QObject {
|
||||
QStringList buildAreaList(int area_idx);
|
||||
int genRand(int min, int max);
|
||||
void diceThrower(int argc, QStringList argv, RollType Type);
|
||||
long long parseTime(QString input);
|
||||
|
||||
// Command function global variables
|
||||
bool change_auth_started = false;
|
||||
@ -309,7 +313,9 @@ class AOClient : public QObject {
|
||||
{"motd", {ACLFlags.value("NONE"), 0, &AOClient::cmdMOTD}},
|
||||
{"announce", {ACLFlags.value("ANNOUNCE"), 1, &AOClient::cmdAnnounce}},
|
||||
{"m", {ACLFlags.value("MODCHAT"), 1, &AOClient::cmdM}},
|
||||
{"gm", {ACLFlags.value("MODCHAT"), 1, &AOClient::cmdGM}}
|
||||
{"gm", {ACLFlags.value("MODCHAT"), 1, &AOClient::cmdGM}},
|
||||
{"mute", {ACLFlags.value("MUTE"), 1, &AOClient::cmdMute}},
|
||||
{"unmute", {ACLFlags.value("MUTE"), 1, &AOClient::cmdUnmute}}
|
||||
};
|
||||
|
||||
QString partial_packet;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define BAN_MANAGER_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDateTime>
|
||||
#include <QHostAddress>
|
||||
#include <QMessageAuthenticationCode>
|
||||
#include <QString>
|
||||
@ -37,8 +38,10 @@ public:
|
||||
|
||||
QString getBanReason(QHostAddress ip);
|
||||
QString getBanReason(QString hdid);
|
||||
long long getBanDuration(QString hdid);
|
||||
long long getBanDuration(QHostAddress hdid);
|
||||
|
||||
void addBan(QString ipid, QHostAddress ip, QString hdid, unsigned long time, QString reason);
|
||||
void addBan(QString ipid, QHostAddress ip, QString hdid, unsigned long time, QString reason, long long duration);
|
||||
|
||||
bool createUser(QString username, QString salt, QString password, unsigned long long acl);
|
||||
unsigned long long getACL(QString moderator_name);
|
||||
|
@ -28,6 +28,7 @@ AOClient::AOClient(Server* p_server, QTcpSocket* p_socket, QObject* parent, int
|
||||
current_area = 0;
|
||||
current_char = "";
|
||||
remote_ip = p_socket->peerAddress();
|
||||
calculateIpid();
|
||||
is_partial = false;
|
||||
last_wtce_time = 0;
|
||||
last_message = "";
|
||||
@ -274,22 +275,17 @@ void AOClient::sendPacket(QString header)
|
||||
sendPacket(AOPacket(header, {}));
|
||||
}
|
||||
|
||||
QString AOClient::getHwid() { return hwid; }
|
||||
|
||||
void AOClient::setHwid(QString p_hwid)
|
||||
void AOClient::calculateIpid()
|
||||
{
|
||||
// TODO: add support for longer hwids?
|
||||
// TODO: add support for longer ipids?
|
||||
// This reduces the (fairly high) chance of
|
||||
// birthday paradox issues arising. However,
|
||||
// typing more than 8 characters might be a
|
||||
// bit cumbersome.
|
||||
hwid = p_hwid;
|
||||
|
||||
QCryptographicHash hash(
|
||||
QCryptographicHash::Md5); // Don't need security, just
|
||||
// hashing for uniqueness
|
||||
QString concat_ip_id = remote_ip.toString() + p_hwid;
|
||||
hash.addData(concat_ip_id.toUtf8());
|
||||
QCryptographicHash hash(QCryptographicHash::Md5); // Don't need security, just hashing for uniqueness
|
||||
|
||||
hash.addData(remote_ip.toString().toUtf8());
|
||||
|
||||
ipid = hash.result().toHex().right(8); // Use the last 8 characters (4 bytes)
|
||||
}
|
||||
|
116
src/commands.cpp
116
src/commands.cpp
@ -89,11 +89,47 @@ void AOClient::cmdGetArea(int argc, QStringList argv)
|
||||
|
||||
void AOClient::cmdBan(int argc, QStringList argv)
|
||||
{
|
||||
QString args_str = argv[1];
|
||||
if (argc > 2) {
|
||||
for (int i = 2; i < argc; i++)
|
||||
args_str += " " + argv[i];
|
||||
}
|
||||
|
||||
QRegularExpression quoteMatcher("['\"](.+?)[\"']");
|
||||
QRegularExpressionMatchIterator matches = quoteMatcher.globalMatch(args_str);
|
||||
QList<QString> unquoted_args;
|
||||
while (matches.hasNext()) {
|
||||
QRegularExpressionMatch match = matches.next();
|
||||
unquoted_args.append(match.captured(1));
|
||||
}
|
||||
|
||||
QString reason;
|
||||
QString duration = "perma";
|
||||
|
||||
if (unquoted_args.length() < 1) {
|
||||
sendServerMessage("Invalid syntax. Usage:\n/ban <ipid> \"<reason>\" \"<duration>\"");
|
||||
return;
|
||||
}
|
||||
|
||||
reason = unquoted_args.at(0);
|
||||
if (unquoted_args.length() > 1)
|
||||
duration = unquoted_args.at(1);
|
||||
|
||||
long long duration_seconds = 0;
|
||||
if (duration == "perma")
|
||||
duration_seconds = -2;
|
||||
else
|
||||
duration_seconds = parseTime(duration);
|
||||
|
||||
if (duration_seconds == -1) {
|
||||
sendServerMessage("Invalid time format. Format example: 1h30m");
|
||||
return;
|
||||
}
|
||||
|
||||
QString target_ipid = argv[0];
|
||||
QHostAddress ip;
|
||||
QString hdid;
|
||||
unsigned long time = QDateTime::currentDateTime().toTime_t();
|
||||
QString reason = argv[1];
|
||||
unsigned long time = QDateTime::currentDateTime().toSecsSinceEpoch();
|
||||
bool ban_logged = false;
|
||||
int kick_counter = 0;
|
||||
|
||||
@ -107,7 +143,7 @@ void AOClient::cmdBan(int argc, QStringList argv)
|
||||
if (!ban_logged) {
|
||||
ip = client->remote_ip;
|
||||
hdid = client->hwid;
|
||||
server->db_manager->addBan(target_ipid, ip, hdid, time, reason);
|
||||
server->db_manager->addBan(target_ipid, ip, hdid, time, reason, duration_seconds);
|
||||
sendServerMessage("Banned user with ipid " + target_ipid + " for reason: " + reason);
|
||||
ban_logged = true;
|
||||
}
|
||||
@ -903,6 +939,38 @@ void AOClient::cmdGM(int argc, QStringList argv)
|
||||
}
|
||||
}
|
||||
|
||||
void AOClient::cmdMute(int argc, QStringList argv)
|
||||
{
|
||||
bool conv_ok = false;
|
||||
int uid = argv[0].toInt(&conv_ok);
|
||||
if (!conv_ok) {
|
||||
sendServerMessage("Invalid user ID.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (server->getClientByID(uid)->is_muted)
|
||||
sendServerMessage("That player is already muted!");
|
||||
else
|
||||
sendServerMessage("Muted player.");
|
||||
server->getClientByID(uid)->is_muted = true;
|
||||
}
|
||||
|
||||
void AOClient::cmdUnmute(int argc, QStringList argv)
|
||||
{
|
||||
bool conv_ok = false;
|
||||
int uid = argv[0].toInt(&conv_ok);
|
||||
if (!conv_ok) {
|
||||
sendServerMessage("Invalid user ID.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!server->getClientByID(uid)->is_muted)
|
||||
sendServerMessage("That player is already unmuted!");
|
||||
else
|
||||
sendServerMessage("Unmuted player.");
|
||||
server->getClientByID(uid)->is_muted = false;
|
||||
}
|
||||
|
||||
QStringList AOClient::buildAreaList(int area_idx)
|
||||
{
|
||||
QStringList entries;
|
||||
@ -1019,3 +1087,45 @@ QString AOClient::getAreaTimer(int area_idx, QTimer* timer)
|
||||
}
|
||||
}
|
||||
|
||||
long long AOClient::parseTime(QString input)
|
||||
{
|
||||
QRegularExpression regex("(?:(?:(?<year>.*?)y)*(?:(?<week>.*?)w)*(?:(?<day>.*?)d)*(?:(?<hr>.*?)h)*(?:(?<min>.*?)m)*(?:(?<sec>.*?)s)*)");
|
||||
QRegularExpressionMatch match = regex.match(input);
|
||||
QString str_year, str_week, str_hour, str_day, str_minute, str_second;
|
||||
int year, week, day, hour, minute, second;
|
||||
|
||||
str_year = match.captured("year");
|
||||
str_week = match.captured("week");
|
||||
str_day = match.captured("day");
|
||||
str_hour = match.captured("hr");
|
||||
str_minute = match.captured("min");
|
||||
str_second = match.captured("sec");
|
||||
|
||||
bool is_well_formed = false;
|
||||
QString concat_str(str_year + str_week + str_day + str_hour + str_minute + str_second);
|
||||
concat_str.toInt(&is_well_formed);
|
||||
|
||||
if (!is_well_formed) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
year = str_year.toInt();
|
||||
week = str_week.toInt();
|
||||
day = str_day.toInt();
|
||||
hour = str_hour.toInt();
|
||||
minute = str_minute.toInt();
|
||||
second = str_second.toInt();
|
||||
|
||||
long long total = 0;
|
||||
total += 31622400 * year;
|
||||
total += 604800 * week;
|
||||
total += 86400 * day;
|
||||
total += 3600 * hour;
|
||||
total += 60 * minute;
|
||||
total += second;
|
||||
|
||||
if (total < 0)
|
||||
return -1;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
@ -24,32 +24,52 @@ DBManager::DBManager() :
|
||||
db.setDatabaseName("config/akashi.db");
|
||||
if (!db.open())
|
||||
qCritical() << "Database Error:" << db.lastError();
|
||||
QSqlQuery create_ban_table("CREATE TABLE IF NOT EXISTS bans ('ID' INTEGER, 'IPID' TEXT, 'HDID' TEXT, 'IP' TEXT, 'TIME' INTEGER, 'REASON' TEXT, PRIMARY KEY('ID' AUTOINCREMENT))");
|
||||
QSqlQuery create_ban_table("CREATE TABLE IF NOT EXISTS bans ('ID' INTEGER, 'IPID' TEXT, 'HDID' TEXT, 'IP' TEXT, 'TIME' INTEGER, 'REASON' TEXT, 'DURATION' INTEGER, PRIMARY KEY('ID' AUTOINCREMENT))");
|
||||
QSqlQuery create_user_table("CREATE TABLE IF NOT EXISTS users ('ID' INTEGER, 'USERNAME' TEXT, 'SALT' TEXT, 'PASSWORD' TEXT, 'ACL' TEXT, PRIMARY KEY('ID' AUTOINCREMENT))");
|
||||
}
|
||||
|
||||
bool DBManager::isIPBanned(QHostAddress ip)
|
||||
{
|
||||
QSqlQuery query;
|
||||
query.prepare("SELECT ID FROM BANS WHERE IP = ?");
|
||||
query.prepare("SELECT TIME FROM BANS WHERE IP = ? ORDER BY TIME DESC");
|
||||
query.addBindValue(ip.toString());
|
||||
query.exec();
|
||||
return query.first();
|
||||
if (query.first()) {
|
||||
long long duration = getBanDuration(ip);
|
||||
long long ban_time = query.value(0).toLongLong();
|
||||
if (duration == -2)
|
||||
return true;
|
||||
long long current_time = QDateTime::currentDateTime().toSecsSinceEpoch();
|
||||
if (ban_time + duration > current_time)
|
||||
return true;
|
||||
else return false;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
bool DBManager::isHDIDBanned(QString hdid)
|
||||
{
|
||||
QSqlQuery query;
|
||||
query.prepare("SELECT ID FROM BANS WHERE HDID = ?");
|
||||
query.prepare("SELECT TIME FROM BANS WHERE HDID = ? ORDER BY TIME DESC");
|
||||
query.addBindValue(hdid);
|
||||
query.exec();
|
||||
return query.first();
|
||||
if (query.first()) {
|
||||
long long duration = getBanDuration(hdid);
|
||||
long long ban_time = query.value(0).toLongLong();
|
||||
if (duration == -2)
|
||||
return true;
|
||||
long long current_time = QDateTime::currentDateTime().toSecsSinceEpoch();
|
||||
if (ban_time + duration > current_time)
|
||||
return true;
|
||||
else return false;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
QString DBManager::getBanReason(QHostAddress ip)
|
||||
{
|
||||
QSqlQuery query;
|
||||
query.prepare("SELECT REASON FROM BANS WHERE IP = ?");
|
||||
query.prepare("SELECT REASON FROM BANS WHERE IP = ? ORDER BY TIME DESC");
|
||||
query.addBindValue(ip.toString());
|
||||
query.exec();
|
||||
if (query.first()) {
|
||||
@ -63,7 +83,7 @@ QString DBManager::getBanReason(QHostAddress ip)
|
||||
QString DBManager::getBanReason(QString hdid)
|
||||
{
|
||||
QSqlQuery query;
|
||||
query.prepare("SELECT REASON FROM BANS WHERE HDID = ?");
|
||||
query.prepare("SELECT REASON FROM BANS WHERE HDID = ? ORDER BY TIME DESC");
|
||||
query.addBindValue(hdid);
|
||||
query.exec();
|
||||
if (query.first()) {
|
||||
@ -74,15 +94,44 @@ QString DBManager::getBanReason(QString hdid)
|
||||
}
|
||||
}
|
||||
|
||||
void DBManager::addBan(QString ipid, QHostAddress ip, QString hdid, unsigned long time, QString reason)
|
||||
long long DBManager::getBanDuration(QString hdid)
|
||||
{
|
||||
QSqlQuery query;
|
||||
query.prepare("INSERT INTO BANS(IPID, HDID, IP, TIME, REASON) VALUES(?, ?, ?, ?, ?)");
|
||||
query.prepare("SELECT DURATION FROM BANS WHERE HDID = ? ORDER BY TIME DESC");
|
||||
query.addBindValue(hdid);
|
||||
query.exec();
|
||||
if (query.first()) {
|
||||
return query.value(0).toLongLong();
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
long long DBManager::getBanDuration(QHostAddress ip)
|
||||
{
|
||||
QSqlQuery query;
|
||||
query.prepare("SELECT DURATION FROM BANS WHERE IP = ? ORDER BY TIME DESC");
|
||||
query.addBindValue(ip.toString());
|
||||
query.exec();
|
||||
if (query.first()) {
|
||||
return query.value(0).toLongLong();
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void DBManager::addBan(QString ipid, QHostAddress ip, QString hdid, unsigned long time, QString reason, long long duration)
|
||||
{
|
||||
QSqlQuery query;
|
||||
query.prepare("INSERT INTO BANS(IPID, HDID, IP, TIME, REASON, DURATION) VALUES(?, ?, ?, ?, ?, ?)");
|
||||
query.addBindValue(ipid);
|
||||
query.addBindValue(hdid);
|
||||
query.addBindValue(ip.toString());
|
||||
query.addBindValue(QString::number(time));
|
||||
query.addBindValue(reason);
|
||||
query.addBindValue(duration);
|
||||
if (!query.exec())
|
||||
qDebug() << "SQL Error:" << query.lastError().text();
|
||||
}
|
||||
|
@ -26,9 +26,9 @@ void AOClient::pktDefault(AreaData* area, int argc, QStringList argv, AOPacket p
|
||||
|
||||
void AOClient::pktHardwareId(AreaData* area, int argc, QStringList argv, AOPacket packet)
|
||||
{
|
||||
setHwid(argv[0]);
|
||||
if(server->db_manager->isHDIDBanned(getHwid())) {
|
||||
sendPacket("BD", {server->db_manager->getBanReason(getHwid())});
|
||||
hwid = argv[0];
|
||||
if(server->db_manager->isHDIDBanned(hwid)) {
|
||||
sendPacket("BD", {server->db_manager->getBanReason(hwid)});
|
||||
socket->close();
|
||||
return;
|
||||
}
|
||||
@ -88,7 +88,7 @@ void AOClient::pktRequestMusic(AreaData* area, int argc, QStringList argv, AOPac
|
||||
|
||||
void AOClient::pktLoadingDone(AreaData* area, int argc, QStringList argv, AOPacket packet)
|
||||
{
|
||||
if (getHwid() == "") {
|
||||
if (hwid == "") {
|
||||
// No early connecting!
|
||||
socket->close();
|
||||
return;
|
||||
@ -154,6 +154,11 @@ void AOClient::pktSelectChar(AreaData* area, int argc, QStringList argv, AOPacke
|
||||
|
||||
void AOClient::pktIcChat(AreaData* area, int argc, QStringList argv, AOPacket packet)
|
||||
{
|
||||
if (is_muted) {
|
||||
sendServerMessage("You cannot speak while muted.");
|
||||
return;
|
||||
}
|
||||
|
||||
AOPacket validated_packet = validateIcPacket(packet);
|
||||
if (validated_packet.header == "INVALID")
|
||||
return;
|
||||
@ -266,6 +271,7 @@ void AOClient::pktWebSocketIp(AreaData* area, int argc, QStringList argv, AOPack
|
||||
qDebug() << "ws ip set to" << argv[0];
|
||||
#endif
|
||||
remote_ip = QHostAddress(argv[0]);
|
||||
calculateIpid();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user