mirror of https://notabug.org/acetone/ircabot.git
646 lines
24 KiB
C++
646 lines
24 KiB
C++
#include "httpserver.h"
|
|
#include "ircclient.h"
|
|
#include "connectiondata.h"
|
|
#include "global.h"
|
|
#include "version.h"
|
|
|
|
#include <QRegularExpression>
|
|
#include <QDirIterator>
|
|
#include <QHostAddress>
|
|
#include <QTcpSocket>
|
|
#include <QDebug>
|
|
#include <QFile>
|
|
#include <QDir>
|
|
|
|
HttpServer::HttpServer(const QString &address, quint16 port, const QString& logFolder,
|
|
const QString& mainChannel, QObject *parent) :
|
|
QObject(parent),
|
|
m_TcpServer(new QTcpServer),
|
|
m_mainChannel(mainChannel),
|
|
m_logFolder(logFolder)
|
|
{
|
|
if (not m_TcpServer->listen(QHostAddress(address), port)) {
|
|
throw std::runtime_error("HttpServer not binded at " +
|
|
address.toStdString() + " : " + QString::number(port).toStdString());
|
|
}
|
|
else {
|
|
consoleLog(address + " : " + QString::number(port));
|
|
}
|
|
|
|
connect (m_TcpServer, &QTcpServer::newConnection, this, &HttpServer::acceptor);
|
|
}
|
|
|
|
HttpServer::~HttpServer()
|
|
{
|
|
m_TcpServer->close();
|
|
m_TcpServer->deleteLater();
|
|
}
|
|
|
|
void HttpServer::consoleLog(const QString &message)
|
|
{
|
|
qInfo().noquote() << "[WEBINTERFACE]" << message;
|
|
}
|
|
|
|
void HttpServer::acceptor()
|
|
{
|
|
QTcpSocket* socket = m_TcpServer->nextPendingConnection();
|
|
connect(socket, &QTcpSocket::readyRead, this, &HttpServer::reader);
|
|
connect(socket, &QTcpSocket::disconnected, socket, &QTcpSocket::deleteLater);
|
|
}
|
|
|
|
void HttpServer::reader()
|
|
{
|
|
QTcpSocket* socket = static_cast<QTcpSocket*>(sender());
|
|
QString request = socket->readAll();
|
|
QString urlPath = getRequestPath(request);
|
|
|
|
// static files
|
|
if (urlPath == "/favicon.ico") {
|
|
QFile icon("://html/favicon.ico");
|
|
if (icon.open(QIODevice::ReadOnly)) {
|
|
socket->write(HEADER_ICO.toUtf8());
|
|
socket->write(icon.readAll());
|
|
icon.close();
|
|
}
|
|
}
|
|
else if (urlPath == "/style.css") {
|
|
QFile css("://html/style.css");
|
|
if (css.open(QIODevice::ReadOnly)) {
|
|
socket->write(HEADER_CSS.toUtf8());
|
|
socket->write(css.readAll());
|
|
css.close();
|
|
}
|
|
}
|
|
else if (urlPath == "/robots.txt") {
|
|
socket->write(HEADER_HTML.toUtf8());
|
|
socket->write("Go out, mr.Robot.");
|
|
}
|
|
else if (urlPath.endsWith(".svg")) {
|
|
QFile svg("://html"+urlPath);
|
|
if (svg.open(QIODevice::ReadOnly)) {
|
|
socket->write(HEADER_SVG.toUtf8());
|
|
socket->write(svg.readAll());
|
|
svg.close();
|
|
}
|
|
else {
|
|
socket->write(HEADER_404.toUtf8());
|
|
socket->write("<center><h1>NOT FOUND</H1></center>");
|
|
}
|
|
}
|
|
|
|
// dynamic page
|
|
else {
|
|
writeMainPage(socket, urlPath);
|
|
}
|
|
socket->disconnectFromHost();
|
|
}
|
|
|
|
void HttpServer::ircBotFirstInfo(QString server, QStringList channels)
|
|
{
|
|
for (const auto &c: channels) {
|
|
m_backendInfo[server][c] = QStringList();
|
|
}
|
|
}
|
|
|
|
void HttpServer::ircClientAction(QString server, QString channel, QStringList users)
|
|
{
|
|
if (server.isEmpty()) return;
|
|
m_backendInfo[server][channel] = users;
|
|
}
|
|
|
|
void HttpServer::ircServerOnline(QString server, quint8 status)
|
|
{
|
|
if (server.isEmpty()) return;
|
|
bool online = status;
|
|
m_serversOnline[server] = online;
|
|
}
|
|
|
|
void HttpServer::ircBotNic(QString server, QString nickname)
|
|
{
|
|
m_botsNick[server] = nickname;
|
|
}
|
|
|
|
QString HttpServer::getRequestPath(const QString &req)
|
|
{
|
|
if (req.isEmpty()) return QString();
|
|
|
|
QString result(req);
|
|
int begin = result.indexOf(' ');
|
|
if (begin == -1) return QString();
|
|
|
|
result.remove(0, begin+1);
|
|
|
|
int space = result.indexOf(' ');
|
|
int size = result.size();
|
|
result.remove(space, size-space);
|
|
result = QByteArray::fromPercentEncoding(result.toUtf8());
|
|
|
|
return result;
|
|
}
|
|
|
|
QString HttpServer::getWordFromPath(const QString &path)
|
|
{
|
|
QString result {path};
|
|
if (result.startsWith('/')) {
|
|
result.remove(QRegularExpression("^/"));
|
|
}
|
|
result.remove(QRegularExpression("/.*$"));
|
|
return result;
|
|
}
|
|
|
|
void HttpServer::writeErrorPage(QTcpSocket *socket)
|
|
{
|
|
socket->write(HEADER_404.toUtf8());
|
|
socket->write("<title>404</title><center><h1>NOT FOUND</H1></center>");
|
|
}
|
|
|
|
void HttpServer::replaceTag(QString &page, const QString &tag, const QString &payload)
|
|
{
|
|
page.replace("{{"+tag+"}}", payload);
|
|
}
|
|
|
|
void HttpServer::writeMainPage(QTcpSocket *socket, QString &urlPath)
|
|
{
|
|
if (urlPath == "/") {
|
|
urlPath += m_mainChannel;
|
|
}
|
|
|
|
QFile main("://html/main.html");
|
|
QString page;
|
|
if (main.open(QIODevice::ReadOnly)) {
|
|
page = main.readAll();
|
|
main.close();
|
|
}
|
|
else {
|
|
socket->write(HEADER_404.toUtf8());
|
|
socket->write("<title>Critical error</title><center><h1>NOT FOUND</H1><p>Maybe it is compilation error</p></center>");
|
|
}
|
|
|
|
QString server = getWordFromPath(urlPath);
|
|
QDir fsPath(m_logFolder+server);
|
|
if (not fsPath.exists()) {
|
|
writeErrorPage(socket);
|
|
return;
|
|
}
|
|
|
|
urlPath.remove(QRegularExpression("^.*/"+server));
|
|
QString channel = getWordFromPath(urlPath);
|
|
channel.remove(QRegularExpression("\\?.*$"));
|
|
if (channel.isEmpty()){
|
|
// First channel if not passed directly
|
|
QDirIterator it(fsPath.path());
|
|
while (it.hasNext()) {
|
|
channel = it.next();
|
|
if (channel.endsWith(".") or channel.endsWith("..")) continue; // QDir::NoDotAndNoDotDot not works!
|
|
while(channel.contains('/')) {
|
|
channel.remove(QRegularExpression("^.*/"));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (not fsPath.cd(channel)) {
|
|
writeErrorPage(socket);
|
|
return;
|
|
}
|
|
|
|
QString originalServerName;
|
|
for (const auto &s: m_backendInfo) {
|
|
if (global::toLowerAndNoSpaces(s.first) == server) {
|
|
originalServerName = s.first;
|
|
}
|
|
}
|
|
QString originalChannelName;
|
|
for (const auto &server: m_backendInfo) {
|
|
for (const auto &channel_users: server.second) {
|
|
if (global::toLowerAndNoSpaces(channel_users.first) == "#"+channel) {
|
|
originalChannelName = global::toLowerAndNoSpaces(channel_users.first);
|
|
}
|
|
}
|
|
}
|
|
|
|
urlPath.remove(QRegularExpression("^.*/"+channel));
|
|
QString year = getWordFromPath(urlPath);
|
|
year.remove(QRegularExpression("\\?.*$"));
|
|
QString month;
|
|
QString day;
|
|
if (not year.isEmpty() and fsPath.cd(year)) {
|
|
urlPath.remove(QRegularExpression("^.*/"+year));
|
|
month = getWordFromPath(urlPath);
|
|
month.remove(QRegularExpression("\\?.*$"));
|
|
if (not month.isEmpty() and fsPath.cd(month)) {
|
|
urlPath.remove(QRegularExpression("^.*/"+month));
|
|
day = getWordFromPath(urlPath);
|
|
day.remove(QRegularExpression("\\?.*$"));
|
|
if (not QFile::exists(fsPath.path()+global::slash+day+".txt")) {
|
|
day.clear();
|
|
}
|
|
}
|
|
else { month.clear(); }
|
|
}
|
|
else { year.clear(); }
|
|
|
|
//// Left menu compilation
|
|
QString htmlServersSectionS;
|
|
for (const auto &s: m_backendInfo) {
|
|
if (s.first.isEmpty()) continue; // empty server name?
|
|
|
|
QString htmlServersSection = HTML_SERVER_SECTION;
|
|
replaceTag(htmlServersSection, "SERVER_NAME", s.first);
|
|
|
|
QString htmlChannelLineS;
|
|
for (const auto &c: s.second) {
|
|
QString htmlChannelLine;
|
|
if (originalServerName == s.first and originalChannelName == c.first) {
|
|
htmlChannelLine = HTML_SERVER_SECTION_CHANNEL_SELECTED;
|
|
} else {
|
|
htmlChannelLine = HTML_SERVER_SECTION_CHANNEL;
|
|
}
|
|
replaceTag(htmlChannelLine, "CHANNEL_NAME", c.first);
|
|
|
|
QString channelNameForUrl {c.first};
|
|
channelNameForUrl.remove('#');
|
|
QString channelLink = "/" + global::toLowerAndNoSpaces(s.first) + "/" + channelNameForUrl;
|
|
replaceTag(htmlChannelLine, "CHANNEL_LINK", channelLink);
|
|
|
|
htmlChannelLineS += htmlChannelLine;
|
|
}
|
|
replaceTag(htmlServersSection, "CHANNELS", htmlChannelLineS);
|
|
|
|
bool online {false};
|
|
for (const auto &srv: m_serversOnline) {
|
|
if (srv.first == s.first) {
|
|
online = srv.second;
|
|
break;
|
|
}
|
|
}
|
|
if (online) {
|
|
replaceTag(htmlServersSection, "ONLINE_STATUS", HTML_SERVER_ONLINE_MARKER);
|
|
} else {
|
|
replaceTag(htmlServersSection, "ONLINE_STATUS", HTML_SERVER_OFFLINE_MARKER);
|
|
}
|
|
|
|
htmlServersSectionS += htmlServersSection;
|
|
}
|
|
replaceTag(page, "SERVERS_SECTION", htmlServersSectionS);
|
|
|
|
//// Main section header compilation
|
|
if (m_backendInfo.size() > 1) {
|
|
replaceTag(page, "PAGE_TITLE", originalChannelName + " ("+originalServerName+") | IRCaBot");
|
|
} else {
|
|
replaceTag(page, "PAGE_TITLE", originalChannelName + " | IRCaBot");
|
|
}
|
|
|
|
replaceTag(page, "MAIN_HEADER", originalChannelName);
|
|
|
|
QString middlePath = "/";
|
|
if (not year.isEmpty()) {
|
|
middlePath += "<a style=\"text-decoration: none\" href=\"/"+server+"/"+channel+"/"+year+"\">" + year + "</a>";
|
|
if (not month.isEmpty()) {
|
|
middlePath += "/<a style=\"text-decoration: none\" href=\"/"+server+"/"+channel+"/"+year+"/"+month+"\">" + month + "</a>";
|
|
if (not day.isEmpty()) {
|
|
middlePath += "/" + day;
|
|
}
|
|
}
|
|
}
|
|
|
|
int currentOnline = m_backendInfo[originalServerName][originalChannelName].size();
|
|
if (currentOnline > 0) currentOnline -= 1;
|
|
replaceTag(page, "ONLINE", QString::number(currentOnline));
|
|
|
|
QString onlineUserS;
|
|
for (const auto &user: m_backendInfo[originalServerName][originalChannelName]) {
|
|
if (QRegularExpression("^.?"+m_botsNick[originalServerName]+"$").match(user).hasMatch()) {
|
|
continue;
|
|
}
|
|
QString onlineUser = HTML_ONLINE_POINT;
|
|
replaceTag(onlineUser, "NICKNAME", user);
|
|
onlineUserS += onlineUser;
|
|
}
|
|
replaceTag(page, "ONLINE_LIST", onlineUserS);
|
|
|
|
if (middlePath == "/") {
|
|
replaceTag(page, "SEARCH_PLACEHOLDER", originalChannelName);
|
|
} else if (month.isEmpty()) {
|
|
replaceTag(page, "SEARCH_PLACEHOLDER", originalChannelName + "/" + year);
|
|
} else {
|
|
replaceTag(page, "SEARCH_PLACEHOLDER", originalChannelName + "/" + year + "/" + month);
|
|
}
|
|
|
|
//// Main section body compilation
|
|
QString payloadBlock;
|
|
|
|
QString searchRequest = global::getValue(urlPath, "toSearch", global::eForWeb);
|
|
// Search request
|
|
if (not searchRequest.isEmpty()) {
|
|
QRegularExpression userRgx(searchRequest);
|
|
bool rgxIsValid = false;
|
|
if (userRgx.isValid()) rgxIsValid = true;
|
|
consoleLog("Search request (" + server + "): " + searchRequest);
|
|
|
|
if (not day.isEmpty()) {
|
|
middlePath.remove(QRegularExpression("/[0-9]{2}$"));
|
|
}
|
|
middlePath += " ("+searchRequest+")";
|
|
|
|
QStringList paths;
|
|
QDirIterator it(fsPath.path());
|
|
while (it.hasNext()) {
|
|
QString currentPath = it.next();
|
|
if (currentPath.endsWith(".") or currentPath.endsWith("..")) continue;
|
|
QString logFolder = m_logFolder;
|
|
#ifdef WIN32
|
|
logFolder.replace('\\', '/');
|
|
#endif
|
|
|
|
QString server {currentPath}; // Folder wich is not server folder is ignored
|
|
server.remove(QRegularExpression("^"+logFolder));
|
|
server.remove(QRegularExpression("/.*$"));
|
|
|
|
bool serverIsOk = false;
|
|
for (const auto &srv: m_backendInfo) {
|
|
if (global::toLowerAndNoSpaces(srv.first) == server) {
|
|
serverIsOk = true;
|
|
break;
|
|
}
|
|
}
|
|
if (not serverIsOk) continue;
|
|
|
|
QString currentChannel {currentPath}; // Folder wich is not channel folder is ignored
|
|
currentChannel.remove(QRegularExpression("^"+logFolder+"[^/]*/"));
|
|
currentChannel.remove(QRegularExpression("/.*$"));
|
|
|
|
bool channelIsOk = false;
|
|
for (const auto &ch: m_backendInfo[originalServerName]) {
|
|
QString searchChan {ch.first};
|
|
searchChan.remove('#');
|
|
if (searchChan == currentChannel) {
|
|
channelIsOk = true;
|
|
break;
|
|
}
|
|
}
|
|
if (not channelIsOk) continue;
|
|
|
|
paths.push_back(currentPath);
|
|
}
|
|
|
|
if (paths.isEmpty()) {
|
|
payloadBlock = HTML_PAYLOAD_ERROR;
|
|
replaceTag(payloadBlock, "ERROR_TITLE", "Not found");
|
|
replaceTag(payloadBlock, "ERROR_TEXT", "");
|
|
}
|
|
else {
|
|
QStringList matchedPaths;
|
|
|
|
if (not month.isEmpty()) {
|
|
for (const auto& path: paths) {
|
|
if (not QRegularExpression("^.*[0-9]{2}\\.txt$").match(path).hasMatch()) continue;
|
|
|
|
QFile file(path);
|
|
if (not file.open(QIODevice::ReadOnly)) {
|
|
consoleLog("Error! I can't open log file " + fsPath.path());
|
|
continue;
|
|
}
|
|
QString buffer {file.readAll()};
|
|
file.close();
|
|
if (rgxIsValid) {
|
|
if (QRegularExpression(searchRequest).match(buffer).hasMatch()) {
|
|
matchedPaths.push_back(path);
|
|
}
|
|
} else {
|
|
if (buffer.contains(searchRequest, Qt::CaseInsensitive)) {
|
|
matchedPaths.push_back(path);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (month.isEmpty() and not year.isEmpty()){
|
|
for (const auto &p: paths) {
|
|
QStringList slavePaths;
|
|
|
|
QDirIterator it(p);
|
|
while (it.hasNext()) {
|
|
QString fileName = it.next();
|
|
if (fileName.endsWith(".") or fileName.endsWith("..")) continue;
|
|
if (not QRegularExpression("\\.txt$").match(fileName).hasMatch()) continue;
|
|
slavePaths.push_back(fileName);
|
|
}
|
|
for (const auto &path: slavePaths) {
|
|
if (not QRegularExpression("^.*[0-9]{2}\\.txt$").match(path).hasMatch()) continue;
|
|
|
|
QFile file(path);
|
|
if (not file.open(QIODevice::ReadOnly)) {
|
|
consoleLog("Error! I can't open log file " + fsPath.path());
|
|
continue;
|
|
}
|
|
QString buffer {file.readAll()};
|
|
file.close();
|
|
if (rgxIsValid) {
|
|
if (QRegularExpression(searchRequest).match(buffer).hasMatch()) {
|
|
matchedPaths.push_back(path);
|
|
}
|
|
} else {
|
|
if (buffer.contains(searchRequest, Qt::CaseInsensitive)) {
|
|
matchedPaths.push_back(path);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else { // root directory
|
|
QStringList yearPaths;
|
|
for (const auto& p: paths) {
|
|
if (not QRegularExpression("/2[0-9]{3}$").match(p).hasMatch()) continue;
|
|
yearPaths.push_back(p);
|
|
}
|
|
|
|
/* If you are reading this code, maybe you are crying now.
|
|
* Sorry me, man (woman/forgot/etc). Maybe I'll refactor this hell in the future.
|
|
* acetone.
|
|
*/
|
|
|
|
QStringList fileNameS;
|
|
for (const auto& p: yearPaths) {
|
|
QStringList slavePaths;
|
|
|
|
QDirIterator it(p);
|
|
while (it.hasNext()) {
|
|
QString folderName = it.next();
|
|
if (folderName.endsWith(".") or folderName.endsWith("..")) continue;
|
|
if (not QRegularExpression("/[0-9]{2}$").match(folderName).hasMatch()) continue;
|
|
slavePaths.push_back(folderName);
|
|
}
|
|
|
|
for (const auto &path: slavePaths) {
|
|
QDirIterator itMonth(path);
|
|
while (itMonth.hasNext()) {
|
|
QString fileName = itMonth.next();
|
|
if (fileName.endsWith(".") or fileName.endsWith("..")) continue;
|
|
if (not QRegularExpression("^.*[0-9]{2}\\.txt$").match(fileName).hasMatch()) continue;
|
|
fileNameS.push_back(fileName);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (const auto& path: fileNameS) {
|
|
QFile file(path);
|
|
if (not file.open(QIODevice::ReadOnly)) {
|
|
consoleLog("Error! I can't open log file " + fsPath.path());
|
|
continue;
|
|
}
|
|
QString buffer {file.readAll()};
|
|
file.close();
|
|
if (rgxIsValid) {
|
|
if (QRegularExpression(searchRequest).match(buffer).hasMatch()) {
|
|
matchedPaths.push_back(path);
|
|
}
|
|
} else {
|
|
if (buffer.contains(searchRequest, Qt::CaseInsensitive)) {
|
|
matchedPaths.push_back(path);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (matchedPaths.isEmpty()) {
|
|
payloadBlock = HTML_PAYLOAD_ERROR;
|
|
replaceTag(payloadBlock, "ERROR_TITLE", "Not found");
|
|
replaceTag(payloadBlock, "ERROR_TEXT", "");
|
|
|
|
}
|
|
else {
|
|
for (auto& point: matchedPaths) {
|
|
QString logFolder {m_logFolder};
|
|
logFolder.remove(QRegularExpression(".$"));
|
|
point.remove(logFolder);
|
|
point.remove(QRegularExpression("\\.txt$"));
|
|
|
|
QString finded = HTML_PAYLOAD_LIST_POINT_MESSAGE;
|
|
replaceTag(finded, "POINT_LINK", point);
|
|
point.remove(QRegularExpression("^.*"+channel));
|
|
replaceTag(finded, "POINT_CONTENT", point);
|
|
payloadBlock += finded;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Simple log explorer
|
|
else {
|
|
if (year.isEmpty()) { // /
|
|
QStringList folderNameS;
|
|
QDirIterator it(fsPath.path());
|
|
while (it.hasNext()) {
|
|
QString folderName = it.next();
|
|
if (folderName.endsWith(".") or folderName.endsWith("..")) continue;
|
|
while(folderName.contains('/')) {
|
|
folderName.remove(QRegularExpression("^.*/"));
|
|
}
|
|
folderName.remove(QRegularExpression("\\.txt$"));
|
|
folderNameS << folderName;
|
|
}
|
|
if (not folderNameS.isEmpty()) {
|
|
for (const auto &f: folderNameS) {
|
|
QString onePoint = HTML_PAYLOAD_LIST_POINT_FOLDER;
|
|
replaceTag(onePoint, "POINT_CONTENT", f);
|
|
replaceTag(onePoint, "POINT_LINK", "/"+server+"/"+channel+"/"+f);
|
|
payloadBlock += onePoint;
|
|
}
|
|
}
|
|
}
|
|
else if (not year.isEmpty() and month.isEmpty()) { // /YYYY
|
|
QStringList folderNameS;
|
|
QDirIterator it(fsPath.path());
|
|
while (it.hasNext()) {
|
|
QString folderName = it.next();
|
|
if (folderName.endsWith(".") or folderName.endsWith("..")) continue;
|
|
while(folderName.contains('/')) {
|
|
folderName.remove(QRegularExpression("^.*/"));
|
|
}
|
|
folderName.remove(QRegularExpression("\\.txt$"));
|
|
folderNameS << folderName;
|
|
}
|
|
if (not folderNameS.isEmpty()) {
|
|
for (const auto &f: folderNameS) {
|
|
QString onePoint = HTML_PAYLOAD_LIST_POINT_FOLDER;
|
|
replaceTag(onePoint, "POINT_CONTENT", f);
|
|
replaceTag(onePoint, "POINT_LINK", "/"+server+"/"+channel+"/"+year+"/"+f);
|
|
payloadBlock += onePoint;
|
|
}
|
|
}
|
|
}
|
|
else if (not month.isEmpty() and day.isEmpty()) { // /YYYY/MM
|
|
QStringList fileNameS;
|
|
QDirIterator it(fsPath.path());
|
|
while (it.hasNext()) {
|
|
QString fileName = it.next();
|
|
if (fileName.endsWith(".") or fileName.endsWith("..")) continue; // QDir::NoDotAndNoDotDot not works!
|
|
while(fileName.contains('/')) {
|
|
fileName.remove(QRegularExpression("^.*/"));
|
|
}
|
|
fileName.remove(QRegularExpression("\\.txt$"));
|
|
fileNameS << fileName;
|
|
}
|
|
if (not fileNameS.isEmpty()) {
|
|
for (const auto &a: fileNameS) {
|
|
QString onePoint = HTML_PAYLOAD_LIST_POINT_MESSAGE;
|
|
replaceTag(onePoint, "POINT_CONTENT", a);
|
|
replaceTag(onePoint, "POINT_LINK", "/"+server+"/"+channel+"/"+year+"/"+month+"/"+a);
|
|
payloadBlock += onePoint;
|
|
}
|
|
}
|
|
}
|
|
else if (not day.isEmpty()) { // /YYYY/MM/dd
|
|
|
|
QFile file(fsPath.path()+global::slash+day+".txt");
|
|
if (not file.open(QIODevice::ReadOnly)) {
|
|
consoleLog("Error! I can't open log file " + fsPath.path());
|
|
payloadBlock = HTML_PAYLOAD_ERROR;
|
|
replaceTag(payloadBlock, "ERROR_TITLE", "Internal error");
|
|
replaceTag(payloadBlock, "ERROR_TEXT", "Requested log file openning failed");
|
|
}
|
|
else {
|
|
QString buffer = file.readLine();
|
|
while (not buffer.isEmpty()) {
|
|
buffer.remove('\n');
|
|
buffer.remove('\r'); // perebzdel
|
|
buffer.remove('\t'); //
|
|
|
|
QString nick {buffer};
|
|
nick.remove(QRegularExpression("\\]\\s.*$"));
|
|
nick.remove(QRegularExpression("^\\["));
|
|
if (nick.isEmpty()) continue;
|
|
|
|
QString text {buffer};
|
|
text.remove(QRegularExpression("^\\[.*\\]\\s"));
|
|
text.replace(' ', " "); // for long spaces (code examples, etc)
|
|
|
|
if (text.isEmpty()) continue;
|
|
|
|
QString message = HTML_PAYLOAD_LIST_CHAT_MESSAGE;
|
|
for (const auto &user: m_backendInfo[originalServerName][originalChannelName]) {
|
|
if (QRegularExpression("^.?"+nick+"$").match(user).hasMatch()) {
|
|
message.replace("<div class=\"main_payload__chat_username\">",
|
|
"<div class=\"main_payload__chat_username\" style=\"color: green\">");
|
|
break;
|
|
}
|
|
}
|
|
replaceTag(message, "USERNAME", nick);
|
|
replaceTag(message, "MESSAGE_TEXT", text);
|
|
payloadBlock += message;
|
|
buffer = file.readLine();
|
|
}
|
|
file.close();
|
|
}
|
|
}
|
|
}
|
|
replaceTag(page, "MIDDLE_PATH", middlePath);
|
|
replaceTag(page, "PAYLOAD_BLOCK", payloadBlock);
|
|
|
|
//// Footer
|
|
replaceTag(page, "VERSION", IRCABOT_VERSION);
|
|
replaceTag(page, "COPYRIGHT_YEAR", COPYRIGHT_YEAR);
|
|
|
|
socket->write(HEADER_HTML.toUtf8());
|
|
socket->write(page.toUtf8());
|
|
}
|