1 /* 2 SPDX-License-Identifier: GPL-2.0-or-later 3 4 SPDX-FileCopyrightText: 2002 Dario Abatianni <eisfuchs@tigress.com> 5 SPDX-FileCopyrightText: 2005 Ismail Donmez <ismail@kde.org> 6 SPDX-FileCopyrightText: 2005-2016 Peter Simonsson <peter.simonsson@gmail.com> 7 SPDX-FileCopyrightText: 2006-2008 Eli J. MacKenzie <argonel at gmail.com> 8 SPDX-FileCopyrightText: 2005-2008 Eike Hein <hein@kde.org> 9 */ 10 11 #ifndef SERVER_H 12 #define SERVER_H 13 14 #include "common.h" 15 #include "channelnick.h" 16 #include "inputfilter.h" 17 #include "outputfilter.h" 18 #include "nickinfo.h" 19 #include "serversettings.h" 20 #include "servergroupsettings.h" 21 #include "connectionsettings.h" 22 #include "statuspanel.h" 23 #include "invitedialog.h" 24 #include <config-konversation.h> 25 26 #ifdef HAVE_QCA2 27 #include "cipher.h" 28 #endif 29 30 #include <QElapsedTimer> 31 #include <QTimer> 32 #include <QPointer> 33 34 #include <QHostInfo> 35 #include <QSslSocket> 36 37 #include <QExplicitlySharedDataPointer> 38 #include <KProcess> 39 #include <preferences.h> 40 41 class QAbstractItemModel; 42 class QStringListModel; 43 class Channel; 44 class Query; 45 class Identity; 46 class RawLog; 47 class ChannelListPanel; 48 class ServerISON; 49 class ChatWindow; 50 class ViewContainer; 51 52 class IRCQueue; 53 54 namespace Konversation 55 { 56 namespace DCC 57 { 58 class Transfer; 59 class Chat; 60 } 61 } 62 63 class Server : public QObject 64 { 65 Q_OBJECT 66 friend class IRCQueue; 67 friend class QueueTuner; 68 friend class ViewContainer; 69 70 public: 71 enum QueuePriority 72 { 73 LowPriority, ///<slow queue, for automatic info gathering 74 StandardPriority, ///<regular queue, for chat and user initiated commands 75 HighPriority, ///<for pongs and quits 76 77 _QueueListSize, 78 79 HiPriority=HighPriority, 80 LoPriority=LowPriority, 81 NormalPriorty=StandardPriority, 82 RegularPriority=StandardPriority 83 }; 84 85 enum CapModifier { 86 NoModifiers = 0x0, 87 DisMod = 0x1, 88 StickyMod = 0x2, 89 AckMod = 0x4 90 }; 91 Q_DECLARE_FLAGS(CapModifiers, CapModifier) 92 93 enum CapabilityFlag { 94 NoCapabilies = 0x00, 95 AwayNotify = 0x01, 96 ExtendedJoin = 0x02, 97 WHOX = 0x04, 98 ServerTime = 0x08, 99 UserHostInNames = 0x10, 100 SASL = 0x20, 101 MultiPrefix = 0x40, 102 AccountNotify = 0x80, 103 SelfMessage = 0x100, 104 ChgHost = 0x200, 105 CapNofify = 0x400, 106 }; 107 Q_DECLARE_FLAGS(CapabilityFlags, CapabilityFlag) 108 109 Server(QObject* parent, ConnectionSettings& settings); 110 ~Server() override; 111 112 void cycle(); abortScheduledRecreation()113 void abortScheduledRecreation() { m_recreationScheduled = false; } 114 connectionId()115 int connectionId() const { return m_connectionId; } 116 getConnectionSettings()117 ConnectionSettings& getConnectionSettings() { return m_connectionSettings; } getConnectionSettings()118 const ConnectionSettings& getConnectionSettings() const { return m_connectionSettings; } setConnectionSettings(ConnectionSettings & settings)119 void setConnectionSettings(ConnectionSettings& settings) { m_connectionSettings = settings; } 120 getDisplayName()121 QString getDisplayName() const { return m_connectionSettings.name(); } getServerName()122 QString getServerName() const { return m_connectionSettings.server().host(); } 123 getServerGroup()124 Konversation::ServerGroupSettingsPtr getServerGroup() const { return m_connectionSettings.serverGroup(); } getIdentity()125 IdentityPtr getIdentity() const { return m_connectionSettings.identity(); } 126 getConnectionState()127 Konversation::ConnectionState getConnectionState() const { return m_connectionState; } 128 isConnected()129 bool isConnected() const { return (m_connectionState == Konversation::SSConnected); } isConnecting()130 bool isConnecting() const { return (m_connectionState == Konversation::SSConnecting); } isScheduledToConnect()131 bool isScheduledToConnect() const { return (m_connectionState == Konversation::SSScheduledToConnect); } 132 133 bool getUseSSL() const; 134 QString getSSLInfo() const; 135 int getPort() const; 136 int getLag() const; 137 138 void updateAutoJoin(Konversation::ChannelList channels = Konversation::ChannelList()); 139 140 /** 141 * Generates the JOIN commands for the given channel list. 142 * This takes care of splitting too long commands into mutliple ones and 143 * filtering out invalid channels (because they are not prefixed with any of the 144 * CHANTYPES). 145 * 146 * @param tmpList The list of channels for which the JOIN command(s) will be generated. 147 * @return A list of QStrings with the JOIN commands. 148 */ 149 QStringList generateJoinCommand(const Konversation::ChannelList &tmpList); 150 151 QAbstractItemModel* nickListModel() const; 152 void resetNickSelection(); 153 void queueNicks(const QString& channelName, const QStringList& nicknameList); 154 void addHostmaskToNick(const QString &sourceNick, const QString &sourceHostmask); 155 Channel* nickJoinsChannel(const QString &channelName, const QString &nickname, const QString &hostmask, const QString &account, 156 const QString &realName, const QHash<QString, QString> &messageTags); 157 void renameNick(const QString &nickname, const QString &newNick, const QHash<QString, QString> &messageTags); 158 Channel* removeNickFromChannel(const QString &channelName, const QString &nickname, const QString &reason, const QHash<QString, QString> &messageTags, bool quit=false); 159 void nickWasKickedFromChannel(const QString &channelName, const QString &nickname, const QString &kicker, const QString &reason, const QHash<QString, QString> &messageTags); 160 void removeNickFromServer(const QString &nickname, const QString &reason, const QHash<QString, QString> &messageTags); 161 162 void setChannelTypes(const QString &types); 163 QString getChannelTypes() const; 164 165 void setModesCount(int count); 166 int getModesCount() const; 167 168 // extended user modes support 169 void setChanModes(const QString&); //grab modes types from RPL_ISUPPORT CHANMODES banAddressListModes()170 QString banAddressListModes() const { return m_banAddressListModes; } // aka "TYPE A" modes https://tools.ietf.org/html/draft-brocklesby-irc-isupport-03#section-3.3 171 172 void setPrefixes(const QString &modes, const QString& prefixes); 173 QString getServerNickPrefixes() const; 174 175 void mangleNicknameWithModes(QString &nickname,bool& isAdmin,bool& isOwner,bool &isOp, 176 bool& isHalfop,bool &hasVoice); 177 178 bool isAChannel(const QString &channel) const; 179 bool isNickname(const QString& compare) const; 180 181 QString getNickname() const; 182 QString loweredNickname() const; 183 184 QString getNextNickname(); 185 getInputFilter()186 InputFilter* getInputFilter() { return &m_inputFilter; } getOutputFilter()187 Konversation::OutputFilter* getOutputFilter() const { return m_outputFilter; } 188 189 Channel* joinChannel(const QString& name, const QString& hostmask, const QHash<QString, QString> &messageTags); 190 void removeChannel(Channel* channel); 191 void appendServerMessageToChannel(const QString& channel, const QString& type, const QString& message, const QHash<QString, QString> &messageTags); 192 void appendCommandMessageToChannel(const QString& channel, const QString& command, const QString& message, const QHash<QString, QString> &messageTags, 193 bool highlight = true, bool parseURL = true); 194 void appendStatusMessage(const QString& type,const QString& message, const QHash<QString, QString> &messageTags); 195 void appendMessageToFrontmost(const QString& type,const QString& message, const QHash<QString, QString> &messageTags = QHash<QString, QString>(), bool parseURL = true); 196 197 int getPreLength(const QString& command, const QString& dest) const; 198 199 void dbusRaw(const QString& command); 200 void dbusSay(const QString& target,const QString& command); 201 void dbusInfo(const QString& string); 202 void ctcpReply(const QString& receiver, const QString& text); 203 204 void setChannelTopic(const QString& channel, const QString& topic, const QHash<QString, QString> &messageTags); 205 // Overloaded 206 void setChannelTopic(const QString& nickname, const QString& channel, const QString& topic, const QHash<QString, QString> &messageTags); 207 void updateChannelMode(const QString& nick, const QString& channel, char mode, bool plus, const QString& parameter, const QHash<QString, QString> &messageTags); 208 void updateChannelModeWidgets(const QString& channel, char mode, const QString& parameter); 209 210 Channel* getChannelByName(const QString& name) const; 211 Query* getQueryByName(const QString& name) const; 212 ChatWindow* getChannelOrQueryByName(const QString& name) const; 213 QString parseWildcards(const QString& toParse, ChatWindow* context = nullptr, const QStringList &nicks = QStringList()); 214 QString parseWildcards(const QString& toParse, const QString& nickname, const QString& channelName, const QString &channelKey, const QStringList &nickList, const QString& inputLineText); 215 QString parseWildcards(const QString& toParse, const QString& nickname, const QString& channelName, const QString &channelKey, const QString& nick, const QString& inputLineText); 216 217 void autoCommandsAndChannels(); 218 219 void sendURIs(const QList<QUrl>& uris, const QString& nick); 220 221 void notifyAction(const QString& nick); 222 ChannelListPanel* getChannelListPanel() const; 223 getStatusView()224 StatusPanel* getStatusView() const { return m_statusView; } 225 virtual bool closeYourself(bool askForConfirmation=true); 226 227 QString getOwnIpByNetworkInterface() const; 228 QString getOwnIpByServerMessage() const; 229 isAway()230 bool isAway() const { return m_away; } 231 void setAway(bool away, const QHash<QString, QString> &messageTags); 232 QString awayTime() const; 233 setAwayReason(const QString & reason)234 void setAwayReason(const QString& reason) { m_awayReason = reason; } 235 236 /** 237 * Returns true if the given nickname is known to be online. 238 * @param nickname The nickname. Case insensitive. 239 * @return True if the nickname is known to be online by the server. 240 * Note that a nick that is not in any of the joined channels and is not on the 241 * notify list, and has not initiated a query with you, may well be online, 242 * but server doesn't know if it is or not, in which case False is returned. 243 */ 244 bool isNickOnline(const QString &nickname) const; 245 /** Given a nickname, returns NickInfo object. 246 * @param nickname The desired nickname. Case insensitive. 247 * @return Pointer to the nickinfo for this nickname if one exists. 248 * 0 if not known to be online. 249 * 250 * A NickInfo pointer will only be returned if the nickname is known to the Konvi 251 * Server object. A nick will be known if: 252 * - It is in one of the server's channels user has joined. 253 * - It is on the notify list and is known to be online. 254 * - The nick initiated a query with the user. 255 * A NickInfo is destroyed when it is offline. 256 */ 257 NickInfoPtr getNickInfo(const QString& nickname) const; 258 /** Given a nickname, returns an existing NickInfo object, or creates a new NickInfo object. 259 * Guaranteed to return a nickinfo. 260 * @param nickname The desired nickname. Case sensitive. 261 * @return Pointer to the found or created NickInfo object. 262 */ 263 NickInfoPtr obtainNickInfo(const QString& nickname); 264 /** Returns a list of all the NickInfos that are online and known to the server. 265 * Caller should not modify the list. 266 * A nick will be known if: 267 * - It is in one of the server's channels user has joined. 268 * - It is on the notify list and is known to be online. 269 * - The nick initiated a query with the user. 270 * 271 * @return A QMap of NickInfoPtrs indexed by lowercase nickname. 272 */ 273 const NickInfoMap* getAllNicks() const; 274 /** Returns the list of members for a channel in the joinedChannels list. 275 * A joinedChannel is one that you are in, as opposed to a channel that you aren't in, 276 * but one of your watched nicks is in. 277 * Code that calls this must not modify the list. 278 * @param channelName Name of desired channel. Case insensitive. 279 * @return A map of all the nicks in the channel. 280 * 0 if channel is not in the joinedChannels list. 281 */ 282 const ChannelNickMap *getJoinedChannelMembers(const QString& channelName) const; 283 /** Returns the list of members for a channel in the unjoinedChannels list. 284 * An unjoinedChannel is a channel you aren't in. As such, this is only going to return 285 * nicks that you know are in that channel because a /whois has been done against them. 286 * This could be done automatically if they are on the watch list. 287 * Code that calls this must not modify the list. 288 * @param channelName Name of desired channel. Case insensitive. 289 * @return A map of only the nicks that we know that are in the channel. 290 * 0 if channel is not in the unjoinedChannels list. 291 */ 292 const ChannelNickMap *getUnjoinedChannelMembers(const QString& channelName) const; 293 /** Searches the Joined and Unjoined lists for the given channel and returns the member list. 294 * Code that calls this must not modify the list. 295 * @param channelName Name of desired channel. Case insensitive. 296 * @return A map of nicks in that channel. 0 if channel is not in either list. 297 * 298 * @see getJoinedChannelMembers(const QString& channelName) 299 * @see getUnjoinedChannelMembers(const QString& channelName) 300 */ 301 const ChannelNickMap *getChannelMembers(const QString& channelName) const; 302 /** Returns a list of all the joined channels that a nick is in. 303 * @param nickname The desired nickname. Case insensitive. 304 * @return A list of joined channels the nick is in. Empty if none. 305 */ 306 QStringList getNickJoinedChannels(const QString& nickname) const; 307 /** Returns a list of all the channels (joined or unjoined) that a nick is in. 308 * @param nickname The desired nickname. Case insensitive. 309 * @return A list of channels the nick is in. Empty if none. 310 * 311 * A nick will not appear in the Unjoined channels list unless a WHOIS 312 * has been performed on it. 313 */ 314 QStringList getNickChannels(const QString& nickname) const; 315 /** Returns a list of all the channels we're in that nickname is also in. 316 * @param nickname The desired nickname. Case insensitive. 317 * @return A list of channels the nick is in that we're also in. Empty if none. 318 */ 319 QStringList getSharedChannels(const QString& nickname) const; 320 /** Returns pointer to the ChannelNick (mode and pointer to NickInfo) for a 321 * given channel and nickname. 322 * @param channelName The desired channel name. Case insensitive. 323 * @param nickname The desired nickname. Case insensitive. 324 * @return Pointer to ChannelNick structure containing a pointer 325 * to the NickInfo and the mode of the nick in the channel. 326 * 0 if not found. 327 */ 328 ChannelNickPtr getChannelNick(const QString& channelName, const QString& nickname) const; 329 /** Updates a nickname in a channel. If not on the joined or unjoined lists, and nick 330 * is in the watch list, adds the channel and nick to the unjoinedChannels list. 331 * If mode != 99, sets the mode for the nick in the channel. 332 * Returns the NickInfo object if nick is on any lists, otherwise 0. 333 * @param channelName The channel name. Case sensitive. 334 * @param nickname The nickname. Case sensitive. 335 * @param mode Bit mask containing the modes the nick has in the channel, 336 * or 99 if not known. See channelnick.cpp for bit definitions. 337 */ 338 ChannelNickPtr setChannelNick(const QString& channelName, const QString& nickname, unsigned int mode = 99); 339 340 /** 341 * Returns a QList of all channels 342 */ getChannelList()343 const QList<Channel *>& getChannelList() const { return m_channelList; } 344 345 /** 346 * Returns a lower case list of all the nicks on the user watch list. 347 */ 348 QStringList getWatchList() const; 349 /** 350 * Return true if the given nickname is on the watch list. 351 */ 352 bool isWatchedNick(const QString& nickname) const; 353 /** 354 * Returns a list of all the nicks on the watch list that are not in joined 355 * channels. ISON command is sent for these nicks. 356 */ 357 QStringList getISONList() const; 358 QString getISONListString() const; 359 360 ViewContainer* getViewContainer() const; 361 362 /** Adds a nickname to the joinedChannels list. 363 * Creates new NickInfo if necessary. 364 * If needed, moves the channel from the unjoined list to the joined list. 365 * If needed, moves the nickname from the Offline to Online lists. 366 * If mode != 99 sets the mode for this nick in this channel. 367 * @param channelName The channel name. Case sensitive. 368 * @param nickname The nickname. Case sensitive. 369 * @return The NickInfo for the nickname. 370 */ 371 ChannelNickPtr addNickToJoinedChannelsList(const QString& channelName, const QString& nickname); 372 setAllowedChannelModes(const QString & modes)373 void setAllowedChannelModes(const QString& modes) { m_allowedChannelModes = modes; } allowedChannelModes()374 QString allowedChannelModes() const { return m_allowedChannelModes; } 375 setTopicLength(int topicLength)376 void setTopicLength(int topicLength) { m_topicLength = topicLength; } topicLength()377 int topicLength() const { return m_topicLength; } 378 379 void registerWithServices(); 380 381 // Blowfish stuff 382 QByteArray getKeyForRecipient(const QString& recipient) const; 383 void setKeyForRecipient(const QString& recipient, const QByteArray& key); 384 identifyMsg()385 bool identifyMsg() const { return m_identifyMsg; } getLastAuthenticateCommand()386 QString getLastAuthenticateCommand() const { return m_lastAuthenticateCommand; } 387 388 ChannelListPanel* addChannelListPanel(); 389 390 // invoked by DCC::TransferSend 391 void dccSendRequest(const QString& recipient,const QString& fileName,const QString& address,quint16 port,quint64 size); 392 void dccPassiveSendRequest(const QString& recipient,const QString& fileName,const QString& address,quint64 size,const QString& token); 393 // invoked by DCC::TransferRecv 394 void dccPassiveResumeGetRequest(const QString& sender,const QString& fileName,quint16 port,KIO::filesize_t startAt,const QString &token); 395 void dccResumeGetRequest(const QString& sender,const QString& fileName,quint16 port,KIO::filesize_t startAt); 396 void dccReverseSendAck(const QString& partnerNick,const QString& fileName,const QString& ownAddress,quint16 ownPort,quint64 size,const QString& reverseToken); 397 void dccRejectSend(const QString& partnerNick, const QString& fileName); 398 // invoked by DCC::Chat 399 void dccRejectChat(const QString& partnerNick, const QString& extension); 400 void dccPassiveChatRequest(const QString& recipient, const QString& extension, const QString& address, const QString& token); 401 void dccReverseChatAck(const QString& partnerNick, const QString& extension, const QString& ownAddress, quint16 ownPort, const QString& reverseToken); 402 capEndDelayed()403 bool capEndDelayed() const { return m_capEndDelayed; } 404 setHasWHOX(bool state)405 void setHasWHOX(bool state) { m_capabilities.setFlag(WHOX, state); } capabilities()406 CapabilityFlags capabilities() const { return m_capabilities; } whoRequestsDisabled()407 bool whoRequestsDisabled() const { return m_whoRequestsDisabled; } 408 409 // IRCQueueManager 410 bool validQueue(QueuePriority priority); ///< is this queue index valid? 411 void resetQueues(); ///< Tell all of the queues to reset 412 413 /** Forces the queued data to be sent in sequence of age, without pause. 414 415 This could flood you off but since you're quitting, we probably don't care. This is done 416 here instead of in the queues themselves so we can interleave the queues without having to 417 zip the queues together. If you want to quit the server normally without sending, reset the queues 418 first. 419 */ 420 void flushQueues(); 421 422 //These are really only here to limit where ircqueue.h is included 423 424 Q_SIGNALS: 425 void destroyed(int connectionId); 426 void nicknameChanged(const QString&); 427 void serverLag(Server* server,int msec); /// will be connected to KonversationMainWindow::updateLag() 428 void tooLongLag(Server* server, int msec);/// will be connected to KonversationMainWindow::updateLag() 429 void resetLag(Server* server); ///< will be emitted when new 303 came in 430 void nicksNowOnline(Server* server,const QStringList& list,bool changed); 431 void awayState(bool away); /// will be connected to any user input panel; 432 void multiServerCommand(const QString& command, const QString& parameter); 433 434 /** 435 * Emitted when the server gains/loses connection. 436 * Will be connected to all server dependant tabs. 437 */ 438 void serverOnline(bool state); 439 440 /** 441 * Emitted every time something gets sent. 442 * 443 * @param bytes The count of bytes sent to the server, before re-encoding. 444 * @param encodedBytes The count of bytes sent to the server after re-encoding. 445 */ 446 void sentStat(int bytes, int encodedBytes, IRCQueue *whichQueue); 447 448 //Note that these signals haven't been implemented yet. 449 /// Fires when the information in a NickInfo object changes. 450 void nickInfoChanged(Server* server, const NickInfoPtr nickInfo); 451 /// Emitted once if one or more NickInfo has been changed. 452 void nickInfoChanged(); 453 /// Emitted once if one or more ChannelNick has been changed in @p channel. 454 void channelNickChanged(const QString& channel); 455 456 /// Fires when a nick leaves or joins a channel. Based on joined flag, receiver could 457 /// call getJoinedChannelMembers or getUnjoinedChannelMembers, or just 458 /// getChannelMembers to get a list of all the nicks now in the channel. 459 /// parted indicates whether the nick joined or left the channel. 460 void channelMembersChanged(Server* server, const QString& channelName, bool joined, bool parted, const QString& nickname); 461 462 /// Fires when a channel is moved to/from the Joinied/Unjoined lists. 463 /// joined indicates which list it is now on. Note that if joined is False, it is 464 /// possible the channel does not exist in any list anymore. 465 void channelJoinedOrUnjoined(Server* server, const QString& channelName, bool joined); 466 467 /// Fires when a nick on the watch list goes online or offline. 468 void watchedNickChanged(Server* server, const QString& nickname, bool online); 469 ///Fires when the user switches his state to away and has enabled "Insert Remember Line on away" in his identity. 470 void awayInsertRememberLine(Server* server); 471 void sslInitFailure(); 472 void sslConnected(Server* server); 473 474 void connectionStateChanged(Server* server, Konversation::ConnectionState state); 475 476 void showView(ChatWindow* view); 477 void addDccPanel(); 478 void addDccChat(Konversation::DCC::Chat *chat); 479 480 public Q_SLOTS: 481 void connectToIRCServer(); 482 void connectToIRCServerIn(uint delay); 483 484 /** Adds line to queue if non-empty. */ 485 bool queue(const QString& line, QueuePriority priority=StandardPriority); 486 //TODO this should be an overload, not a separate name. ambiguous cases need QString() around the cstring 487 bool queueList(const QStringList& buffer, QueuePriority priority=StandardPriority); 488 489 void setNickname(const QString &newNickname); 490 /** This is called when we want to open a new query, or focus an existing one. 491 * @param nickInfo The nickinfo we want to open the query to. Must exist. 492 * @param weinitiated This is whether we initiated this - did we do /query, or somebody else sending us a message. 493 * @return A pointer to a new or already-existing query. Guaranteed to be non-null 494 */ 495 Query *addQuery(const NickInfoPtr & nickInfo, bool weinitiated); 496 void closeQuery(const QString &name); 497 void closeChannel(const QString &name); 498 void reconnectServer(const QString& quitMessage = QString()); 499 void disconnectServer(const QString& quitMessage = QString()); 500 void quitServer(const QString& quitMessage = QString()); 501 void openDccChat(const QString& nickname); 502 void openDccWBoard(const QString& nickname); 503 void requestDccChat(const QString& partnerNick, const QString& extension, const QString& numericalOwnIp, quint16 ownPort); 504 void acceptDccGet(const QString& nick, const QString& file); 505 void requestBan(const QStringList& users,const QString& channel,const QString& option); 506 void requestUnban(const QString& mask,const QString& channel); 507 508 void addDccSend(const QString &recipient, const QUrl &fileURL, bool passive = Preferences::self()->dccPassiveSend(), const QString &altFileName = QString(), quint64 fileSize = 0); 509 void removeQuery(Query *query); 510 void notifyListStarted(int serverGroupId); 511 void startNotifyTimer(int msec=0); 512 void notifyTimeout(); 513 void sendJoinCommand(const QString& channelName, const QString& password = QString()); 514 void requestAway(const QString& reason = QString()); 515 void requestUnaway(); 516 void requestChannelList(); 517 void requestWhois(const QString& nickname); 518 void requestWho(const QString& channel); 519 void requestUserhost(const QString& nicks); 520 void requestTopic(const QString& channel); 521 void resolveUserhost(const QString& nickname); 522 void addRawLog(bool show); 523 void closeRawLog(); 524 void addToChannelList(const QString& channel, int users, const QString& topic); 525 void closeChannelListPanel(); 526 void sendMultiServerCommand(const QString& command, const QString& parameter); 527 void executeMultiServerCommand(const QString& command, const QString& parameter); 528 void showSSLDialog(); 529 void sendToAllChannels(const QString& text); 530 void sendToAllChannelsAndQueries(const QString& text); 531 532 void enableIdentifyMsg(bool enabled); 533 bool identifyMsgEnabled(); 534 void addBan(const QString &channel, const QString &ban); 535 void removeBan(const QString &channel, const QString &ban); 536 537 /// Called when we received a PONG from the server 538 void pongReceived(); 539 540 #ifdef HAVE_QCA2 541 void initKeyExchange(const QString &receiver); 542 void parseInitKeyX(const QString &sender, const QString &pubKey); 543 void parseFinishKeyX(const QString &sender, const QString &pubKey); 544 #endif 545 546 /// Start the NickInfo changed timer if it isn't started already 547 void startNickInfoChangedTimer(); 548 /// Start the ChannelNick changed timer if it isn't started already 549 void startChannelNickChangedTimer(const QString& channel); 550 551 /// Called when the system wants to close the connection due to network going down etc. 552 void involuntaryQuit(); 553 /// Will only reconnect if the connection state is involuntary disconnected. 554 void reconnectInvoluntary(); 555 556 void requestAvailableCapabilies (); 557 void capInitiateNegotiation(const QString &availableCaps); 558 void capReply(); 559 void capEndNegotiation(); 560 void capCheckIgnored(); 561 void capAcknowledged(const QString& name, CapModifiers modifiers); 562 void capDenied(const QString& name); 563 void sendAuthenticate(const QString& message); 564 void capDel(const QString &unavailableCaps); 565 566 private Q_SLOTS: 567 void hostFound(); 568 void preShellCommandExited(int exitCode, QProcess::ExitStatus exitStatus); 569 void preShellCommandError(QProcess::ProcessError eror); 570 void socketConnected(); 571 void startAwayTimer(); 572 void incoming(); 573 void processIncomingData(); 574 /// Sends the QString to the socket. No longer has any internal concept of queueing 575 void toServer(const QString&, IRCQueue *); 576 /// Because KBufferedSocket has no closed(int) signal we use this slot to call broken(0) 577 void closed(); 578 void broken(QAbstractSocket::SocketError error); 579 /** This is connected to the SSLSocket failed. 580 * @param reason The reason why this failed. This is already translated, ready to show the user. 581 */ 582 void sslError(const QList<QSslError>&); 583 void connectionEstablished(const QString& ownHost); 584 void notifyResponse(const QString& nicksOnline); 585 586 void slotNewDccTransferItemQueued(Konversation::DCC::Transfer* transfer); 587 void startReverseDccSendTransfer(const QString& sourceNick,const QStringList& dccArguments); 588 void startReverseDccChat(const QString &sourceNick, const QStringList &dccArgument); 589 void addDccGet(const QString& sourceNick,const QStringList& dccArguments); 590 void requestDccSend(); // -> to outputFilter, dccPanel 591 // -> to outputFilter 592 void requestDccSend(const QString& recipient); 593 // -> to inputFilter 594 void resumeDccGetTransfer(const QString& sourceNick,const QStringList& dccArguments); 595 // -> to inputFilter 596 void resumeDccSendTransfer(const QString& sourceNick,const QStringList& dccArguments); 597 void rejectDccSendTransfer(const QString& sourceNick,const QStringList& dccArguments); 598 void dccGetDone(Konversation::DCC::Transfer* item); 599 void dccSendDone(Konversation::DCC::Transfer* item); 600 void dccStatusChanged(Konversation::DCC::Transfer* item, int newStatus, int oldStatus); 601 void addDccChat(const QString& sourceNick,const QStringList& arguments); 602 void rejectDccChat(const QString& sourceNick); 603 604 void scriptNotFound(const QString& name); 605 void scriptExecutionError(const QString& name); 606 void userhost(const QString& nick,const QString& hostmask,bool away,bool ircOp); 607 void setTopicAuthor(const QString& channel,const QString& author, const QDateTime &t); 608 void endOfWho(const QString& target); 609 void endOfNames(const QString& target); 610 void invitation(const QString& nick,const QString& channel); 611 void gotOwnResolvedHostByWelcome(const QHostInfo& res); 612 void gotOwnResolvedHostByUserhost(const QHostInfo& res); 613 614 /// Send a PING to the server so we can meassure the lag 615 void sendPing(); 616 /// Updates GUI when the lag gets high 617 void updateLongPongLag(); 618 619 /// Update the encoding shown in the mainwindow's actions 620 void updateEncoding(); 621 622 /** Called when the NickInfo changed timer times out. 623 * Emits the nickInfoChanged() signal for all changed NickInfos 624 */ 625 void sendNickInfoChangedSignals(); 626 /** Called when the ChannelNick changed timer times out. 627 * Emits the channelNickChanged() signal for each channel with changed nicks. 628 */ 629 void sendChannelNickChangedSignals(); 630 631 void requestOpenChannelListPanel(const QString& filter); 632 633 /** Called in the server constructor if the preferences are set to run a command on a new server instance. 634 * This sets up the kprocess, runs it, and connects the signals to call preShellCommandExited when done. */ 635 void doPreShellCommand(); 636 637 private: 638 /// Initialize the timers 639 void initTimers(); 640 641 /// Connect to the signals used in this class. 642 void connectSignals(); 643 644 int _send_internal(QString outputline); ///< Guts of old send, isn't a slot. 645 646 /** Adds a nickname to the unjoinedChannels list. 647 * Creates new NickInfo if necessary. 648 * If needed, moves the channel from the joined list to the unjoined list. 649 * If needed, moves the nickname from the Offline to the Online list. 650 * If mode != 99 sets the mode for this nick in this channel. 651 * @param channelName The channel name. Case sensitive. 652 * @param nickname The nickname. Case sensitive. 653 * @return The NickInfo for the nickname. 654 */ 655 ChannelNickPtr addNickToUnjoinedChannelsList(const QString& channelName, const QString& nickname); 656 657 /** 658 * If not already online, changes a nick to the online state by creating 659 * a NickInfo for it and emits various signals and messages for it. 660 * This method should only be called for nicks on the watch list. 661 * @param nickname The nickname that is online. 662 * @return Pointer to NickInfo for nick. 663 */ 664 NickInfoPtr setWatchedNickOnline(const QString& nickname); 665 666 /** 667 * Display offline notification for a certain nickname. The function doesn't change NickInfo objects. 668 * @param nickname The nickname that is offline 669 * @param nickInfo Pointer to NickInfo for nick 670 */ 671 void setWatchedNickOffline(const QString& nickname, const NickInfoPtr &nickInfo); 672 673 /** 674 * If nickname is no longer on any channel list, or the query list, delete it altogether. 675 * Call this routine only if the nick is not on the notify list or is on the notify 676 * list but is known to be offline. 677 * @param nickname The nickname to be deleted. Case insensitive. 678 * @return True if the nickname is deleted. 679 */ 680 bool deleteNickIfUnlisted(const QString &nickname); 681 682 /** 683 * If not already offline, changes a nick to the offline state. 684 * Removes it from all channels on the joined and unjoined lists. 685 * If the nick is in the watch list, and went offline, emits a signal, 686 * posts a Notify message, and posts a KNotify. 687 * If the nick goes offline, the NickInfo is deleted. 688 * 689 * @param nickname The nickname. Case sensitive. 690 * @return True if the nick was online. 691 */ 692 bool setNickOffline(const QString& nickname); 693 694 /** Remove nickname from a channel (on joined or unjoined lists). 695 * @param channelName The channel name. Case insensitive. 696 * @param nickname The nickname. Case insensitive. 697 */ 698 void removeChannelNick(const QString& channelName, const QString& nickname); 699 700 /** Remove channel from the joined list. 701 * Nicknames in the channel are added to the unjoined list if they are in the watch list. 702 * @param channelName The channel name. Case insensitive. 703 */ 704 void removeJoinedChannel(const QString& channelName); 705 706 /** Renames a nickname in all NickInfo lists. 707 * @param nickInfo Pointer to existing NickInfo object. 708 * @param newname New nickname for the nick. Case sensitive. 709 */ 710 void renameNickInfo(NickInfoPtr nickInfo, const QString& newname); 711 712 bool getAutoJoin() const; 713 void setAutoJoin(bool on); 714 getAutoJoinCommands()715 QStringList getAutoJoinCommands() const { return m_autoJoinCommands; } setAutoJoinCommands(const QStringList & commands)716 void setAutoJoinCommands(const QStringList& commands) { m_autoJoinCommands = commands; } 717 718 void rebuildTargetPrefixMatcher(); ///< updates the regexp when prefixes change 719 720 void updateConnectionState(Konversation::ConnectionState state); 721 bool isSocketConnected() const; 722 723 void purgeData(); 724 725 /// Recovers the filename from the dccArguments list from pos 0 to size-offset-1 726 /// joining with a space and cleans the filename using cleanDccFileName. 727 /// The filename only needs to be recovered if it contains a space, in case 728 /// it does not, the cleaned string at pos 0 is returned. 729 /// "offset" states how many fixed arguments the dcc command has, where the 730 /// filename is variable. For example "filename ip port filesize", offset is 3. 731 inline QString recoverDccFileName(const QStringList& dccArguments, int offset) const; 732 733 /// Cleans the filename from extra '"'. We just remove '"' if it is the first 734 /// and last char, if the filename really contains a '"' it comes as two chars, 735 /// escaped "\"", and is not affected. 736 /// Some clients return the filename with multiple '"' around the filename 737 /// but all we want is the plain filename. 738 inline QString cleanDccFileName(const QString& filename) const; 739 740 /// Checks if the port is in a valid range 741 inline quint16 stringToPort(const QString &port, bool *ok = nullptr); 742 743 /// Creates a list of known users and returns the one chosen by the user 744 inline QString recipientNick() const; 745 746 void collectStats(int bytes, int encodedBytes); 747 748 void initCapablityNames(); 749 750 private: 751 // constants 752 static const int BUFFER_LEN=513; 753 754 unsigned int m_completeQueryPosition; 755 QList<int> m_nickIndices; 756 QStringList m_referenceNicklist; 757 QStringListModel* m_nickListModel; 758 759 // TODO roll these into a QMap. 760 QString m_serverNickPrefixes; ///< Nickname prefixes used by the server to indicate a mode 761 QString m_serverNickPrefixModes; ///< if supplied: mode flags related to nickname prefixes 762 763 QRegularExpression m_targetMatcher; ///< a character set composed of m_serverNickPrefixes and m_channelPrefixes 764 765 QString m_banAddressListModes; // "TYPE A" modes from RPL_ISUPPORT CHANMODES=A,B,C,D 766 767 QString m_channelPrefixes; // prefixes that indicate channel names. defaults to RFC1459 "#&" 768 int m_modesCount; // Maximum number of channel modes with parameter allowed per MODE command. 769 770 bool m_autoJoin; 771 772 QStringList m_autoJoinCommands; 773 774 QSslSocket *m_socket; 775 776 QTimer m_incomingTimer; 777 QTimer m_notifyTimer; 778 QStringList m_notifyCache; // List of users found with ISON 779 int m_currentLag; 780 781 QStringList m_inputBuffer; 782 QByteArray m_lineBuffer; 783 784 QList<IRCQueue *> m_queues; 785 // Stats used in QueueTuner 786 int m_bytesSent, m_encodedBytesSent, m_linesSent, m_bytesReceived; 787 788 QString m_nickname; 789 QString m_loweredNickname; 790 QString m_ownIpByUserhost; // RPL_USERHOST 791 QString m_ownIpByWelcome; // RPL_WELCOME 792 793 QList<Channel*> m_channelList; 794 QHash<QString, Channel*> m_loweredChannelNameHash; 795 796 QList<Query*> m_queryList; 797 798 InputFilter m_inputFilter; 799 Konversation::OutputFilter* m_outputFilter; 800 801 QPointer<StatusPanel> m_statusView; 802 QPointer<RawLog> m_rawLog; 803 QPointer<ChannelListPanel> m_channelListPanel; 804 805 bool m_away; 806 QString m_awayReason; 807 QString m_nonAwayNick; 808 int m_awayTime; 809 810 Konversation::ConnectionState m_connectionState; 811 812 KProcess m_preShellCommand; 813 814 /// Helper object to construct ISON (notify) list. 815 ServerISON* m_serverISON; 816 /// All nicks known to this server. Note this is NOT a list of all nicks on the server. 817 /// Any nick appearing in this list is online, but may not necessarily appear in 818 /// any of the joined or unjoined channel lists because a WHOIS has not yet been 819 /// performed on the nick. 820 NickInfoMap m_allNicks; 821 /// List of membership lists for joined channels. A "joined" channel is a channel 822 /// that user has joined, i.e., a tab appears for the channel in the main window. 823 ChannelMembershipMap m_joinedChannels; 824 /// List of membership lists for unjoined channels. These come from WHOIS responses. 825 /// Note that this is NOT a list of all channels on the server, just those we are 826 /// interested in because of nicks in the Nick Watch List. 827 ChannelMembershipMap m_unjoinedChannels; 828 /// List of nicks in Queries. 829 NickInfoMap m_queryNicks; 830 831 QString m_allowedChannelModes; 832 833 int m_topicLength; 834 835 // Blowfish key map 836 QHash<QString, QByteArray> m_keyHash; 837 838 bool m_identifyMsg; 839 840 bool m_sslErrorLock; 841 842 /// Used to lock incomingTimer while processing message. 843 bool m_processingIncoming; 844 845 /// Measures the lag between PING and PONG 846 QElapsedTimer m_lagTime; 847 /// Updates the gui when the lag gets too high 848 QTimer m_pingResponseTimer; 849 /// Wait before sending the next PING 850 QTimer m_pingSendTimer; 851 852 /// Previous ISON reply of the server, needed for comparison with the next reply 853 QStringList m_prevISONList; 854 855 int m_capRequested; 856 int m_capAnswered; 857 bool m_capEndDelayed; 858 QString m_lastAuthenticateCommand; 859 860 ConnectionSettings m_connectionSettings; 861 862 /// Used by ConnectionManager to schedule a reconnect; stopped by /disconnect 863 /// and /quit. 864 QTimer* m_delayedConnectTimer; 865 866 bool m_reconnectImmediately; 867 868 static int m_availableConnectionId; 869 int m_connectionId; 870 871 QPointer<InviteDialog> m_inviteDialog; 872 873 QTimer* m_nickInfoChangedTimer; 874 QTimer* m_channelNickChangedTimer; 875 QStringList m_changedChannels; 876 877 bool m_recreationScheduled; 878 879 CapabilityFlags m_capabilities; 880 QHash<QString, CapabilityFlag> m_capabilityNames; 881 882 bool m_whoRequestsDisabled; 883 884 Q_DISABLE_COPY(Server) 885 }; 886 887 Q_DECLARE_OPERATORS_FOR_FLAGS(Server::CapModifiers) 888 Q_DECLARE_OPERATORS_FOR_FLAGS(Server::CapabilityFlags) 889 890 #endif 891