123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- #ifndef HTTPSERVER_H
- #define HTTPSERVER_H
- #include <QObject>
- #include <QTcpServer>
- #include <QDateTime>
- #include <QTimer>
- #include <map>
- #include <queue>
- constexpr int MSECS_TO_AUTOREMOVE_MESSAGES_FROM_BUFFER {15000}; // 15 secs
- constexpr int MAX_MESSAGE_LENGTH_WITHOUT_WBR = 30;
- constexpr int MAX_NICKNAME_LENGTH_WITHOUT_WBR = 20;
- constexpr int BUFFER_SIZE = 2048;
- const QString HTTP_ACTUAL_ETAG {__DATE__ __TIME__}; // Change it if svg, css or ico was modified
- class Message : public QObject
- {
- Q_OBJECT
- public:
- Message(const QString& s, const QString& t, qint64 timestamp, QObject *parent = nullptr);
- const QString getSender();
- const QString getText();
- private:
- QString m_sender;
- QString m_text;
- qint64 m_timestamp;
- QTimer m_selfKiller;
- signals:
- void outDated(qint64);
- };
- class MessagePool : public QObject
- {
- Q_OBJECT
- public:
- MessagePool(QObject *parent = nullptr);
- void saveNewMessage(const QString& nick, const QString& text);
- const std::multimap<qint64, Message*>* getMessages();
- qint64 getLastPing();
- private:
- qint64 m_lastPing;
- std::multimap<qint64, Message*> m_messages; // timestamp, message
- public slots:
- void messageToDelete(qint64 timestamp);
- };
- //////////////////////////////////////////////////
- class HttpServer : public QObject
- {
- Q_OBJECT
- public:
- explicit HttpServer(const QString& address, quint16 port,
- const QString& logFolder, const QString& mainChannel,
- bool ajaxIsDisabled, QObject *parent = nullptr);
- ~HttpServer();
- private:
- QString convertToClickableLink(const QString &httpLine);
- std::pair<QString,QString> splitUserNameAndMessage(const QString& rawLine);
- QString getRequestPath(const QString &req);
- QString getWordFromPath(const QString& path);
- void writeMainPage(QTcpSocket* socket, QString& urlPath, bool isHeadRequest);
- void writeRealTimeChatPage(QTcpSocket* socket, QString& urlPath, bool isHeadRequest);
- void writeAboutServerPage(QTcpSocket* socket, QString& urlPath, bool isHeadRequest);
- void writeAjaxAnswer(QTcpSocket* socket, QString& urlPath, bool isHeadRequest);
- void writeErrorPage(QTcpSocket*, const QString& text = "NOT FOUND");
- void writeErrorJson(QTcpSocket*, const QString& text = "");
- void removeBrakelineSymbols(QString& line);
- inline void replaceTag(QString& page, const QString& tag, const QString& payload);
- void consoleLog(const QString &message);
- void debugLog(const QString &url);
- QTcpServer* m_TcpServer;
- QString m_mainChannel;
- QString m_logFolder;
- bool m_ajaxIsDisabled;
- std::map<QString, std::map<QString, QStringList>> m_servers; // server, {channel, users}
- std::map<QString, std::map<QString, QString>> m_channelsTopic; // server, {channel, topic}
- std::map<QString, bool> m_serversOnline;
- std::map<QString, QString> m_botNick;
- QMap<QString, MessagePool*> m_messageCache; // server+channel
- const QString HEADER_HTML = "\
- HTTP/1.1 200 OK\r\n\
- Content-Type: text/html; charset=utf-8\r\n\
- Content-Length: {{SIZE}}\r\n\r\n";
- const QString HEADER_TEXT = "\
- HTTP/1.1 200 OK\r\n\
- Content-Type: text/plain; charset=utf-8\r\n\
- Content-Length: {{SIZE}}\r\n\r\n";
- const QString HEADER_CSS = "\
- HTTP/1.1 200 OK\r\n\
- Content-Type: text/css\r\n\
- Cache-Control: public, max-age=31536000\r\n\
- ETag: \""+HTTP_ACTUAL_ETAG+"\"\r\n\
- Content-Length: {{SIZE}}\r\n\r\n";
- const QString HEADER_SVG = "\
- HTTP/1.1 200 OK\r\n\
- Content-Type: image/svg+xml\r\n\
- Cache-Control: public, max-age=31536000\r\n\
- ETag: \""+HTTP_ACTUAL_ETAG+"\"\r\n\
- Content-Length: {{SIZE}}\r\n\r\n";
- const QString HEADER_ICO = "\
- HTTP/1.1 200 OK\r\n\
- Content-Type: image/ico\r\n\
- Cache-Control: public, max-age=31536000\r\n\
- ETag: \""+HTTP_ACTUAL_ETAG+"\"\r\n\
- Content-Length: {{SIZE}}\r\n\r\n";
- const QString HEADER_JS = "\
- HTTP/1.1 200 OK\r\n\
- Content-Type: text/javascript; charset=utf-8\r\n\
- Cache-Control: public, max-age=31536000\r\n\
- ETag: \""+HTTP_ACTUAL_ETAG+"\"\r\n\
- Content-Length: {{SIZE}}\r\n\r\n";
- const QString HEADER_JSON = "\
- HTTP/1.1 200 OK\r\n\
- Content-Type: application/json; charset=utf-8\r\n\
- Content-Length: {{SIZE}}\r\n\r\n";
- const QString HEADER_MP3 = "\
- HTTP/1.1 200 OK\r\n\
- Content-Type: audio/mpeg;\r\n\
- ETag: \""+HTTP_ACTUAL_ETAG+"\"\r\n\
- Content-Length: {{SIZE}}\r\n\r\n";
- const QString HEADER_304 = "HTTP/1.1 304 Not Modified\r\nContent-Length: 0\r\n\r\n";
- const QString HEADER_404 = "HTTP/1.1 404 Not found\r\n\r\n";
- const QString HTML_SERVER_SECTION = "\
- <div class=\"left_menu__item\">\n\
- <div class=\"left_menu__item_title\">\n\
- <span style=\"font-size: 17px;\">{{ONLINE_STATUS}}</span>\n\
- <a class=\"left_menu__item_title_name\" href=\"{{ABOUT_SERVER}}\">{{SERVER_NAME}}</a>\n\
- </div>\n\
- <div class=\"left_menu__item_rooms\">\n\
- {{CHANNELS}}\
- </div>\n\
- </div>\n";
- const QString HTML_SERVER_ONLINE_MARKER = "✅";
- const QString HTML_SERVER_OFFLINE_MARKER = "❌";
- const QString HTML_SERVER_SECTION_CHANNEL = "\
- <a href=\"{{CHANNEL_LINK}}\" class=\"left_menu__item_link\">{{CHANNEL_NAME}}</a>\n";
- const QString HTML_SERVER_SECTION_CHANNEL_SELECTED = "\
- <a href=\"{{CHANNEL_LINK}}\" class=\"left_menu__item_link__selected\">{{CHANNEL_NAME}}</a>\n";
- const QString HTML_ONLINE_POINT = "\
- <div class=\"main_middle__online_point\">\n\
- {{NICKNAME}}\n\
- </div>\n";
- const QString HTML_PAYLOAD_LIST_POINT_FOLDER = "\
- <a href=\"{{POINT_LINK}}\" class=\"main_payload__block\">\n\
- <div class=\"main_payload__block_folder\">\n\
- </div>\n\
- <div class=\"main_payload__block_text\">\n\
- {{POINT_CONTENT}}\n\
- </div>\n\
- </a>\n";
- const QString HTML_PAYLOAD_LIST_POINT_MESSAGE = "\
- <a href=\"{{POINT_LINK}}\" class=\"main_payload__block\">\n\
- <div class=\"main_payload__block_message\">\n\
- </div>\n\
- <div class=\"main_payload__block_text\">\n\
- {{POINT_CONTENT}}\n\
- </div>\n\
- </a>\n";
- const QString HTML_PAYLOAD_LIST_CHAT_MESSAGE = "\
- <div class=\"main_payload__chat\">\n\
- <span class=\"main_payload__chat_username\">\n\
- {{USERNAME}}\n\
- </span>\n\
- <span class=\"main_payload__chat_mail\">\n\
- {{MESSAGE_TEXT}}\n\
- </span>\n\
- </div>\n";
- const QString HTML_PAYLOAD_ADDITIONAL_ARROWS = "\
- <a href=\"{{CURRENT_DATA_LOG}}\" title=\"Jump to today logs\" class=\"main_header__title_arrows\"></a>\n";
- const QString HTML_PAYLOAD_ADDITIONAL_NOTIFY = "\
- <div onclick=\"sound()\" id=\"musicanotes\" class=\"main_header__title_notify\"></div>\n";
- const QString HTML_PAYLOAD_ERROR = "\
- <div class=\"main_payload__error\">\n\
- <span style=\"color: red; display: block; font-size: 24px;\">{{ERROR_TITLE}}</span><br>\n\
- {{ERROR_TEXT}}\n\
- </div>";
- const QString HTML_PAYLOAD_ABOUT = "\
- <div class=\"main_payload__about\">\n\
- <span style=\"color: green; display: block; font-size: 24px; text-align: center;\">{{ABOUT_TITLE}}</span><br>\n\
- {{ABOUT_TEXT}}\n\
- </div>";
- private slots:
- void acceptor();
- void reader();
- public slots:
- void ircBotFirstInfo(QString server, QStringList channels); // needed for permanent offline servers
- void ircUsersOnline(QString server, QString channel, QStringList users);
- void ircChannelTopic(QString server, QString channel, QString topic);
- void ircServerOnline(QString server, quint8 status /*0 or 1*/);
- void ircBotNick(QString server, QString nickname);
- void ircMessageCache(QString server, QString channel, QString nick, QString text);
- };
- #endif // HTTPSERVER_H
|