/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ /* Copyright (C) 2002 Dario Abatianni Copyright (C) 2005 Ismail Donmez Copyright (C) 2005-2006 Peter Simonsson Copyright (C) 2006-2008 Eli J. MacKenzie Copyright (C) 2005-2008 Eike Hein */ #ifndef SERVER_H #define SERVER_H #include "common.h" #include "channelnick.h" #include "inputfilter.h" #include "outputfilter.h" #include "nickinfo.h" #include "sslsocket.h" #include "serversettings.h" #include "servergroupsettings.h" #include "connectionsettings.h" #include #include #include #include #include #include #include #include class Channel; class DccTransfer; class DccTransferPanelItem; class Query; class StatusPanel; class Identity; class RawLog; class ChannelListPanel; class ScriptLauncher; class ServerISON; class TQStrList; class ChatWindow; class ViewContainer; using namespace KNetwork; class IRCQueue; class Server : public TQObject { Q_OBJECT friend class IRCQueue; friend class QueueTuner; void resetNickSelection(); public: enum QueuePriority { LowPriority, ///& getChannelList() const { return m_channelList; } void emitChannelNickChanged(const ChannelNickPtr channelNick); void emitNickInfoChanged(const NickInfoPtr nickInfo); /** * Returns a list of all the nicks on the user watch list plus nicks in the addressbook. */ TQStringList getWatchList(); TQString getWatchListString(); /** * Return true if the given nickname is on the watch list. */ bool isWatchedNick(const TQString& nickname); /** * Returns a list of all the nicks on the watch list that are not in joined * channels. ISON command is sent for these nicks. */ TQStringList getISONList(); TQString getISONListString(); ViewContainer* getViewContainer() const; /** Adds a nickname to the joinedChannels list. * Creates new NickInfo if necessary. * If needed, moves the channel from the unjoined list to the joined list. * If needed, moves the nickname from the Offline to Online lists. * If mode != 99 sets the mode for this nick in this channel. * @param channelName The channel name. Case sensitive. * @param nickname The nickname. Case sensitive. * @return The NickInfo for the nickname. */ ChannelNickPtr addNickToJoinedChannelsList(const TQString& channelName, const TQString& nickname); void setAllowedChannelModes(const TQString& modes) { m_allowedChannelModes = modes; } TQString allowedChannelModes() const { return m_allowedChannelModes; } void registerWithServices(); // Blowfish stuff TQCString getKeyForRecipient(const TQString& recipient) const; void setKeyForRecipient(const TQString& recipient, const TQCString& key); bool identifyMsg() const { return m_identifyMsg; } ChannelListPanel* addChannelListPanel(); // invoked by DccTransferSend void dccSendRequest(const TQString& recipient,const TQString& fileName,const TQString& address,const TQString& port,unsigned long size); void dccPassiveSendRequest(const TQString& recipient,const TQString& fileName,const TQString& address,unsigned long size,const TQString& token); // invoked by DccTransferRecv void dccResumeGetRequest(const TQString& sender,const TQString& fileName,const TQString& port,TDEIO::filesize_t startAt); void dccReverseSendAck(const TQString& partnerNick,const TQString& fileName,const TQString& ownAddress,const TQString& ownPort,unsigned long size,const TQString& reverseToken); // IRCQueueManager bool validQueue(QueuePriority priority); ///< is this queue index valid? void resetQueues(); ///< Tell all of the queues to reset static int _max_queue() { return Howmanyqueuesdoweneedanywayquestionmark-1; } /** Forces the queued data to be sent in sequence of age, without pause. This could flood you off but since you're quitting, we probably don't care. This is done here instead of in the queues themselves so we can interleave the queues without having to zip the queues together. If you want to quit the server normally without sending, reset the queues first. */ void flushQueues(); //These are really only here to limit where ircqueue.h is included static void _fetchRates(); ///< on server construction static void _stashRates(); ///< on application exit static void _resetRates(); ///< when QueueTuner says to signals: void destroyed(int connectionId); void nicknameChanged(const TQString&); void serverLag(Server* server,int msec); /// will be connected to KonversationMainWindow::updateLag() void tooLongLag(Server* server, int msec);/// will be connected to KonversationMainWindow::updateLag() void resetLag(); ///< will be emitted when new 303 came in void nicksNowOnline(Server* server,const TQStringList& list,bool changed); void awayState(bool away); /// will be connected to any user input panel; void multiServerCommand(const TQString& command, const TQString& parameter); /** * Emitted when the server gains/loses connection. * Will be connected to all server dependant tabs. */ void serverOnline(bool state); /** * Emitted every time something gets sent. * * @param bytes The count of bytes sent to the server, before re-encoding. * @param encodedBytes The count of bytes sent to the server after re-encoding. */ void sentStat(int bytes, int encodedBytes, IRCQueue *whichQueue); //FIXME can anyone who can connect to a Server signal not know about an IRCQueue? void sentStat(int bytes, int encodedBytes); //Note that these signals haven't been implemented yet. /// Fires when the information in a NickInfo object changes. void nickInfoChanged(Server* server, const NickInfoPtr nickInfo); /// Fires when the mode of a nick in a channel changes. void channelNickChanged(Server* server, const ChannelNickPtr channelNick); /// Fires when a nick leaves or joins a channel. Based on joined flag, receiver could /// call getJoinedChannelMembers or getUnjoinedChannelMembers, or just /// getChannelMembers to get a list of all the nicks now in the channel. /// parted indicates whether the nick joined or left the channel. void channelMembersChanged(Server* server, const TQString& channelName, bool joined, bool parted, const TQString& nickname); /// Fires when a channel is moved to/from the Joinied/Unjoined lists. /// joined indicates which list it is now on. Note that if joined is False, it is /// possible the channel does not exist in any list anymore. void channelJoinedOrUnjoined(Server* server, const TQString& channelName, bool joined); /// Fires when a nick on the watch list goes online or offline. void watchedNickChanged(Server* server, const TQString& nickname, bool online); ///Fires when the user switches his state to away and has enabled "Insert Remember Line on away" in his identity. void awayInsertRememberLine(Server* server); void sslInitFailure(); void sslConnected(Server* server); void connectionStateChanged(Server* server, Konversation::ConnectionState state); void showView(ChatWindow* view); void addDccPanel(); void addDccChat(const TQString& myNick,const TQString& nick,const TQStringList& arguments,bool listen); public slots: void connectToIRCServer(); /** Adds line to queue if non-empty. */ bool queue(const TQString& line, QueuePriority priority=StandardPriority); //TODO this should be an overload, not a separate name. ambiguous cases need TQString() around the cstring bool queueList(const TQStringList& buffer, QueuePriority priority=StandardPriority); void setNickname(const TQString &newNickname); /** This is called when we want to open a new query, or focus an existing one. * @param nickInfo The nickinfo we want to open the query to. Must exist. * @param weinitiated This is whether we initiated this - did we do /query, or somebody else sending us a message. * @return A pointer to a new or already-existing query. Guaranteed to be non-null */ Query *addQuery(const NickInfoPtr & nickInfo, bool weinitiated); void closeQuery(const TQString &name); void closeChannel(const TQString &name); void quitServer(); void openDccChat(const TQString& nickname); void requestDccChat(const TQString& partnerNick, const TQString& numericalOwnIp, const TQString& ownPort); void requestBan(const TQStringList& users,const TQString& channel,const TQString& option); void requestUnban(const TQString& mask,const TQString& channel); void addDccSend(const TQString &recipient,KURL fileURL, const TQString &altFileName = TQString(), uint fileSize = 0); void removeQuery(Query *query); void startNotifyTimer(int msec=0); void sendJoinCommand(const TQString& channelName, const TQString& password = TQString()); void requestChannelList(); void requestWhois(const TQString& nickname); void requestWho(const TQString& channel); void requestUserhost(const TQString& nicks); void requestTopic(const TQString& channel); void resolveUserhost(const TQString& nickname); void addRawLog(bool show); void closeRawLog(); void addToChannelList(const TQString& channel, int users, const TQString& topic); void closeChannelListPanel(); void updateChannelQuickButtons(); void sendMultiServerCommand(const TQString& command, const TQString& parameter); void executeMultiServerCommand(const TQString& command, const TQString& parameter); void reconnect(); void disconnect(); //FIXME is this overriding a qobject method? do we care? void showSSLDialog(); void sendToAllChannels(const TQString& text); void notifyTimeout(); void enableIdentifyMsg(bool enabled); bool identifyMsgEnabled(); void addBan(const TQString &channel, const TQString &ban); void removeBan(const TQString &channel, const TQString &ban); /// Called when we received a PONG from the server void pongReceived(); protected slots: void lookupFinished(); void preShellCommandExited(TDEProcess*); void ircServerConnectionSuccess(); void startAwayTimer(); void incoming(); void processIncomingData(); /// Sends the TQString to the socket. No longer has any internal concept of queueing void toServer(TQString&, IRCQueue *); /// Because TDEBufferedSocket has no closed(int) signal we use this slot to call broken(0) void closed(); void broken(int state); /** This is connected to the SSLSocket failed. * @param reason The reason why this failed. This is already translated, ready to show the user. */ void sslError(const TQString& reason); void connectionEstablished(const TQString& ownHost); void notifyResponse(const TQString& nicksOnline); void slotNewDccTransferItemQueued(DccTransfer* transfer); void startReverseDccSendTransfer(const TQString& sourceNick,const TQStringList& dccArguments); void addDccGet(const TQString& sourceNick,const TQStringList& dccArguments); void requestDccSend(); // -> to outputFilter, dccPanel // -> to outputFilter void requestDccSend(const TQString& recipient); // -> to inputFilter void resumeDccGetTransfer(const TQString& sourceNick,const TQStringList& dccArguments); // -> to inputFilter void resumeDccSendTransfer(const TQString& sourceNick,const TQStringList& dccArguments); void dccGetDone(DccTransfer* item); void dccSendDone(DccTransfer* item); void dccStatusChanged(DccTransfer* item, int newStatus, int oldStatus); void scriptNotFound(const TQString& name); void scriptExecutionError(const TQString& name); void userhost(const TQString& nick,const TQString& hostmask,bool away,bool ircOp); void setTopicAuthor(const TQString& channel,const TQString& author, TQDateTime t); void endOfWho(const TQString& target); void invitation(const TQString& nick,const TQString& channel); void sendToAllChannelsAndQueries(const TQString& text); void gotOwnResolvedHostByWelcome(KResolverResults res); void gotOwnResolvedHostByUserhost(KResolverResults res); /// Send a PING to the server so we can meassure the lag void sendPing(); /// Updates GUI when the lag gets high void updateLongPongLag(); /// Update the encoding shown in the mainwindow's actions void updateEncoding(); private slots: void collectStats(int bytes, int encodedBytes); /** Called in the server constructor if the preferences are set to run a command on a new server instance. * This sets up the kprocess, runs it, and connects the signals to call preShellCommandExited when done. */ void doPreShellCommand(); protected: // constants static const int BUFFER_LEN=513; /// Initialize the timers void initTimers(); /// Connect to the signals used in this class. void connectSignals(); int _send_internal(TQString outputline); ///< Guts of old send, isn't a slot. /** Adds a nickname to the unjoinedChannels list. * Creates new NickInfo if necessary. * If needed, moves the channel from the joined list to the unjoined list. * If needed, moves the nickname from the Offline to the Online list. * If mode != 99 sets the mode for this nick in this channel. * @param channelName The channel name. Case sensitive. * @param nickname The nickname. Case sensitive. * @return The NickInfo for the nickname. */ ChannelNickPtr addNickToUnjoinedChannelsList(const TQString& channelName, const TQString& nickname); /** * If not already online, changes a nick to the online state by creating * a NickInfo for it and emits various signals and messages for it. * This method should only be called for nicks on the watch list. * @param nickname The nickname that is online. * @return Pointer to NickInfo for nick. */ NickInfoPtr setWatchedNickOnline(const TQString& nickname); /** * Display offline notification for a certain nickname. The function doesn't change NickInfo objects. * If NickInfoPtr is given, then also the integration with KAddressBook is engaged (i.e. the * nick is marked as away) * @param nickname The nickname that is offline * @param nickInfo Pointer to NickInfo for nick */ void setWatchedNickOffline(const TQString& nickname, const NickInfoPtr nickInfo); /** * If nickname is no longer on any channel list, or the query list, delete it altogether. * Call this routine only if the nick is not on the notify list or is on the notify * list but is known to be offline. * @param nickname The nickname to be deleted. Case insensitive. * @return True if the nickname is deleted. */ bool deleteNickIfUnlisted(const TQString &nickname); /** * If not already offline, changes a nick to the offline state. * Removes it from all channels on the joined and unjoined lists. * If the nick is in the watch list, and went offline, emits a signal, * posts a Notify message, and posts a KNotify. * If the nick is in the addressbook, and went offline, informs addressbook of change. * If the nick goes offline, the NickInfo is deleted. * * @param nickname The nickname. Case sensitive. * @return True if the nick was online. */ bool setNickOffline(const TQString& nickname); /** Remove nickname from a channel (on joined or unjoined lists). * @param channelName The channel name. Case insensitive. * @param nickname The nickname. Case insensitive. */ void removeChannelNick(const TQString& channelName, const TQString& nickname); /** Remove channel from the joined list. * Nicknames in the channel are added to the unjoined list if they are in the watch list. * @param channelName The channel name. Case insensitive. */ void removeJoinedChannel(const TQString& channelName); /** Renames a nickname in all NickInfo lists. * @param nickInfo Pointer to existing NickInfo object. * @param newname New nickname for the nick. Case sensitive. */ void renameNickInfo(NickInfoPtr nickInfo, const TQString& newname); bool getAutoJoin() const; void setAutoJoin(bool on); TQStringList getAutoJoinCommands() const { return m_autoJoinCommands; } void setAutoJoinCommands(const TQStringList& commands) { m_autoJoinCommands = commands; } unsigned int m_completeQueryPosition; TQValueList m_nickIndices; TQStringList m_referenceNicklist; // TODO roll these into a TQMap. TQString m_serverNickPrefixes; // Prefixes used by the server to indicate a mode TQString m_serverNickPrefixModes; // if supplied: modes related to those prefixes TQString m_channelPrefixes; // prefixes that indicate channel names. defaults to RFC1459 "#&" bool m_autoJoin; TQStringList m_autoJoinCommands; KNetwork::KStreamSocket* m_socket; TQTimer m_reconnectTimer; TQTimer m_incomingTimer; TQTimer m_notifyTimer; TQStringList m_notifyCache; // List of users found with ISON int m_checkTime; // Time elapsed while waiting for server 303 response int m_currentLag; TQCString m_inputBufferIncomplete; TQStringList m_inputBuffer; TQValueVector m_queues; int m_bytesSent, m_encodedBytesSent, m_linesSent, m_bytesReceived; TQString m_nickname; TQString m_loweredNickname; TQString m_ownIpByUserhost; // RPL_USERHOST TQString m_ownIpByWelcome; // RPL_WELCOME TQPtrList m_channelList; TQPtrList m_queryList; InputFilter m_inputFilter; Konversation::OutputFilter* m_outputFilter; TQGuardedPtr m_statusView; TQGuardedPtr m_rawLog; TQGuardedPtr m_channelListPanel; bool m_away; TQString m_awayReason; TQString m_nonAwayNick; int m_awayTime; Konversation::ConnectionState m_connectionState; void updateConnectionState(Konversation::ConnectionState state); bool isSocketConnected() const; ScriptLauncher* m_scriptLauncher; TDEProcess m_preShellCommand; private: /// Helper object to construct ISON (notify) list and map offline nicks to /// addressbook. ServerISON* m_serverISON; /// All nicks known to this server. Note this is NOT a list of all nicks on the server. /// Any nick appearing in this list is online, but may not necessarily appear in /// any of the joined or unjoined channel lists because a WHOIS has not yet been /// performed on the nick. NickInfoMap m_allNicks; /// List of membership lists for joined channels. A "joined" channel is a channel /// that user has joined, i.e., a tab appears for the channel in the main window. ChannelMembershipMap m_joinedChannels; /// List of membership lists for unjoined channels. These come from WHOIS responses. /// Note that this is NOT a list of all channels on the server, just those we are /// interested in because of nicks in the Nick Watch List. ChannelMembershipMap m_unjoinedChannels; /// List of nicks in Queries. NickInfoMap m_queryNicks; TQString m_allowedChannelModes; // Blowfish key map TQMap m_keyMap; bool m_identifyMsg; bool m_autoIdentifyLock; /// Used to lock incomingTimer while processing message. bool m_processingIncoming; /// Meassures the lag between PING and PONG TQTime m_lagTime; /// Updates the gui when the lag gets too high TQTimer m_pingResponseTimer; /// Previous ISON reply of the server, needed for comparison with the next reply TQStringList m_prevISONList; ConnectionSettings m_connectionSettings; static int m_availableConnectionId; int m_connectionId; }; #endif