1 /***************************************************************************
2 * Copyright (C) 2005-2010 by the Quassel Project *
3 * devel@quassel-irc.org *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include "coresessioneventprocessor.h"
23 #include "corenetwork.h"
24 #include "coresession.h"
28 CoreSessionEventProcessor::CoreSessionEventProcessor(CoreSession *session)
35 bool CoreSessionEventProcessor::checkParamCount(IrcEvent *e, int minParams) {
36 if(e->params().count() < minParams) {
37 if(e->type() == EventManager::IrcEventNumeric) {
38 qWarning() << "Command " << static_cast<IrcEventNumeric *>(e)->number() << " requires " << minParams << "params, got: " << e->params();
40 QString name = coreSession()->eventManager()->enumName(e->type());
41 qWarning() << qPrintable(name) << "requires" << minParams << "params, got:" << e->params();
49 void CoreSessionEventProcessor::processIrcEventNumeric(IrcEventNumeric *e) {
53 case 903: case 904: case 905: case 906: case 907:
54 qobject_cast<CoreNetwork *>(e->network())->putRawLine("CAP END");
62 void CoreSessionEventProcessor::processIrcEventAuthenticate(IrcEvent *e) {
63 if(!checkParamCount(e, 1))
66 if(e->params().at(0) != "+") {
67 qWarning() << "Invalid AUTHENTICATE" << e;
71 CoreNetwork *net = coreNetwork(e);
73 QString construct = net->saslAccount();
74 construct.append(QChar(QChar::Null));
75 construct.append(net->saslAccount());
76 construct.append(QChar(QChar::Null));
77 construct.append(net->saslPassword());
78 QByteArray saslData = QByteArray(construct.toAscii().toBase64());
79 saslData.prepend("AUTHENTICATE ");
80 net->putRawLine(saslData);
83 void CoreSessionEventProcessor::processIrcEventCap(IrcEvent *e) {
84 // for SASL, there will only be a single param of 'sasl', however you can check here for
85 // additional CAP messages (ls, multi-prefix, et cetera).
87 if(e->params().count() == 3) {
88 if(e->params().at(2) == "sasl") {
90 coreNetwork(e)->putRawLine(coreNetwork(e)->serverEncode("AUTHENTICATE PLAIN")); // Only working with PLAIN atm, blowfish later
95 void CoreSessionEventProcessor::processIrcEventInvite(IrcEvent *e) {
96 if(checkParamCount(e, 2)) {
97 e->network()->updateNickFromMask(e->prefix());
101 void CoreSessionEventProcessor::processIrcEventKick(IrcEvent *e) {
102 if(checkParamCount(e, 2)) {
103 e->network()->updateNickFromMask(e->prefix());
104 IrcUser *victim = e->network()->ircUser(e->params().at(1));
106 victim->partChannel(e->params().at(0));
107 //if(e->network()->isMe(victim)) e->network()->setKickedFromChannel(channel);
112 void CoreSessionEventProcessor::processIrcEventNick(IrcEvent *e) {
113 if(checkParamCount(e, 1)) {
114 IrcUser *ircuser = e->network()->updateNickFromMask(e->prefix());
116 qWarning() << Q_FUNC_INFO << "Unknown IrcUser!";
119 QString newnick = e->params().at(0);
120 QString oldnick = ircuser->nick();
122 // the order is cruicial
123 // otherwise the client would rename the buffer, see that the assigned ircuser doesn't match anymore
124 // and remove the ircuser from the querybuffer leading to a wrong on/offline state
125 ircuser->setNick(newnick);
126 coreSession()->renameBuffer(e->networkId(), newnick, oldnick);
130 void CoreSessionEventProcessor::processIrcEventPart(IrcEvent *e) {
131 if(checkParamCount(e, 1)) {
132 IrcUser *ircuser = e->network()->updateNickFromMask(e->prefix());
134 qWarning() << Q_FUNC_INFO<< "Unknown IrcUser!";
137 QString channel = e->params().at(0);
138 ircuser->partChannel(channel);
139 if(e->network()->isMe(ircuser))
140 qobject_cast<CoreNetwork *>(e->network())->setChannelParted(channel);
144 void CoreSessionEventProcessor::processIrcEventPong(IrcEvent *e) {
145 // the server is supposed to send back what we passed as param. and we send a timestamp
146 // but using quote and whatnought one can send arbitrary pings, so we have to do some sanity checks
147 if(checkParamCount(e, 2)) {
148 QString timestamp = e->params().at(1);
149 QTime sendTime = QTime::fromString(timestamp, "hh:mm:ss.zzz");
150 if(sendTime.isValid())
151 e->network()->setLatency(sendTime.msecsTo(QTime::currentTime()) / 2);
155 void CoreSessionEventProcessor::processIrcEventTopic(IrcEvent *e) {
156 if(checkParamCount(e, 2)) {
157 e->network()->updateNickFromMask(e->prefix());
158 IrcChannel *channel = e->network()->ircChannel(e->params().at(0));
160 channel->setTopic(e->params().at(1));
165 void CoreSessionEventProcessor::processIrcEvent001(IrcEvent *e) {
166 if(!checkParamCount(e, 1))
169 QString myhostmask = e->params().at(0).section(' ', -1, -1);
170 e->network()->setCurrentServer(e->prefix());
171 e->network()->setMyNick(nickFromMask(myhostmask));
174 /* RPL_UMODEIS - "<user_modes> [<user_mode_params>]" */
175 void CoreSessionEventProcessor::processIrcEvent221(IrcEvent *) {
176 // TODO: save information in network object
179 /* RPL_STATSCONN - "Highest connection cout: 8000 (7999 clients)" */
180 void CoreSessionEventProcessor::processIrcEvent250(IrcEvent *) {
181 // TODO: save information in network object
184 /* RPL_LOCALUSERS - "Current local user: 5024 Max: 7999 */
185 void CoreSessionEventProcessor::processIrcEvent265(IrcEvent *) {
186 // TODO: save information in network object
189 /* RPL_GLOBALUSERS - "Current global users: 46093 Max: 47650" */
190 void CoreSessionEventProcessor::processIrcEvent266(IrcEvent *) {
191 // TODO: save information in network object
196 Replies 311 - 313, 317 - 319 are all replies generated in response to a WHOIS message.
198 "<nick> :<away message>"
200 Replies 352 and 315 paired are used to answer a WHO message.
203 Replies 314 and 369 are responses to a WHOWAS message.
207 /* RPL_AWAY - "<nick> :<away message>" */
208 void CoreSessionEventProcessor::processIrcEvent301(IrcEvent *e) {
209 if(!checkParamCount(e, 2))
212 IrcUser *ircuser = e->network()->ircUser(e->params().at(0));
214 ircuser->setAway(true);
215 ircuser->setAwayMessage(e->params().at(1));
216 //ircuser->setLastAwayMessage(now);
220 /* RPL_UNAWAY - ":You are no longer marked as being away" */
221 void CoreSessionEventProcessor::processIrcEvent305(IrcEvent *e) {
222 IrcUser *me = e->network()->me();
226 if(e->network()->autoAwayActive()) {
227 e->network()->setAutoAwayActive(false);
228 e->setFlag(EventManager::Silent);
232 /* RPL_NOWAWAY - ":You have been marked as being away" */
233 void CoreSessionEventProcessor::processIrcEvent306(IrcEvent *e) {
234 IrcUser *me = e->network()->me();
239 /* RPL_WHOISSERVICE - "<user> is registered nick" */
240 void CoreSessionEventProcessor::processIrcEvent307(IrcEvent *e) {
241 if(!checkParamCount(e, 1))
244 IrcUser *ircuser = e->network()->ircUser(e->params().at(0));
246 ircuser->setWhoisServiceReply(e->params().join(" "));
249 /* RPL_SUSERHOST - "<user> is available for help." */
250 void CoreSessionEventProcessor::processIrcEvent310(IrcEvent *e) {
251 if(!checkParamCount(e, 1))
254 IrcUser *ircuser = e->network()->ircUser(e->params().at(0));
256 ircuser->setSuserHost(e->params().join(" "));
259 /* RPL_WHOISUSER - "<nick> <user> <host> * :<real name>" */
260 void CoreSessionEventProcessor::processIrcEvent311(IrcEvent *e) {
261 if(!checkParamCount(e, 3))
264 IrcUser *ircuser = e->network()->ircUser(e->params().at(0));
266 ircuser->setUser(e->params().at(1));
267 ircuser->setHost(e->params().at(2));
268 ircuser->setRealName(e->params().last());
272 /* RPL_WHOISSERVER - "<nick> <server> :<server info>" */
273 void CoreSessionEventProcessor::processIrcEvent312(IrcEvent *e) {
274 if(!checkParamCount(e, 2))
277 IrcUser *ircuser = e->network()->ircUser(e->params().at(0));
279 ircuser->setServer(e->params().at(1));
282 /* RPL_WHOISOPERATOR - "<nick> :is an IRC operator" */
283 void CoreSessionEventProcessor::processIrcEvent313(IrcEvent *e) {
284 if(!checkParamCount(e, 1))
287 IrcUser *ircuser = e->network()->ircUser(e->params().at(0));
289 ircuser->setIrcOperator(e->params().last());
292 /* RPL_ENDOFWHO: "<name> :End of WHO list" */
293 void CoreSessionEventProcessor::processIrcEvent315(IrcEvent *e) {
294 if(!checkParamCount(e, 1))
297 if(coreNetwork(e)->setAutoWhoDone(e->params()[0]))
298 e->setFlag(EventManager::Silent);
301 /* RPL_WHOISIDLE - "<nick> <integer> :seconds idle"
302 (real life: "<nick> <integer> <integer> :seconds idle, signon time) */
303 void CoreSessionEventProcessor::processIrcEvent317(IrcEvent *e) {
304 if(!checkParamCount(e, 2))
309 int idleSecs = e->params()[1].toInt();
310 if(e->params().count() > 3) { // if we have more then 3 params we have the above mentioned "real life" situation
311 int logintime = e->params()[2].toInt();
312 loginTime = QDateTime::fromTime_t(logintime);
315 IrcUser *ircuser = e->network()->ircUser(e->params()[0]);
317 ircuser->setIdleTime(e->timestamp().addSecs(-idleSecs));
318 if(loginTime.isValid())
319 ircuser->setLoginTime(loginTime);
326 void CoreSessionEventProcessor::processIrcEvent(IrcEvent *e) {
327 if(!checkParamCount(e, 1))