ParseEvents.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. /*
  2. * The contents of this file are subject to the Mozilla Public
  3. * License Version 1.1 (the "License"); you may not use this file
  4. * except in compliance with the License. You may obtain a copy of
  5. * the License at http://www.mozilla.org/MPL/
  6. *
  7. * Software distributed under the License is distributed on an "AS
  8. * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9. * implied. See the License for the specific language governing
  10. * rights and limitations under the License.
  11. *
  12. * The Original Code is Vision.
  13. *
  14. * The Initial Developer of the Original Code is The Vision Team.
  15. * Portions created by The Vision Team are
  16. * Copyright (C) 1999, 2000, 2001 The Vision Team. All Rights
  17. * Reserved.
  18. *
  19. * Contributor(s): Wade Majors <wade@ezri.org>
  20. * Rene Gollent
  21. * Todd Lair
  22. * Andrew Bazan
  23. * Jamie Wilkinson
  24. * Bjorn Oksholen
  25. * Alan Ellis <alan@cgsoftware.org>
  26. */
  27. #include "Vision.h"
  28. #include "Utilities.h"
  29. #include "StatusView.h"
  30. #include "ServerAgent.h"
  31. #include "ChannelAgent.h"
  32. #include "MessageAgent.h"
  33. #include "ClientWindow.h"
  34. #include "WindowList.h"
  35. #include <stdio.h>
  36. /* #6502 was here --
  37. <kurros> regurg, amiyumi?
  38. <regurg> Let's discuss further why your pizza NOW.
  39. <kurros> uh
  40. <slaad> ?
  41. <kurros> yeah
  42. */
  43. bool
  44. ServerAgent::ParseEvents (const char *data)
  45. {
  46. BString firstWord = GetWord(data, 1).ToUpper();
  47. BString secondWord = GetWord(data, 2).ToUpper();
  48. if (secondWord == "PRIVMSG")
  49. {
  50. BString theNick (GetNick (data)),
  51. ident (GetIdent (data)),
  52. address (GetAddress (data)),
  53. addy;
  54. addy += ident;
  55. addy += "@";
  56. addy += address;
  57. BString theTarget (GetWord (data, 3).ToUpper()),
  58. theTargetOrig (GetWord (data, 3)),
  59. theMsg (RestOfString (data, 4));
  60. ClientAgent *client (0);
  61. theMsg.RemoveFirst(":");
  62. if (theMsg.Length() == 0)
  63. return true;
  64. if (theMsg[0] == '\1' && GetWord (theMsg.String(), 1) != "\1ACTION")
  65. {
  66. // CTCP Request
  67. ParseCTCP (theNick, theTargetOrig, theMsg);
  68. return true;
  69. }
  70. if (theTarget[0] == '#'
  71. || theTarget[0] == '!'
  72. || theTarget[0] == '&'
  73. || theTarget[0] == '+')
  74. client = Client (theTarget.String());
  75. else if (!(client = Client (theNick.String())))
  76. {
  77. BString msgident (GetIdent (data)),
  78. msgaddress (GetAddress (data));
  79. client = new MessageAgent (
  80. *vision_app->pClientWin()->AgentRect(),
  81. theNick.String(),
  82. fId.String(),
  83. fSMsgr,
  84. fMyNick.String(),
  85. addy.String()),
  86. vision_app->pClientWin()->pWindowList()->AddAgent (client,
  87. theNick.String(),
  88. WIN_MESSAGE_TYPE,
  89. false);
  90. fClients.AddItem (client);
  91. }
  92. if (client)
  93. {
  94. BString msgident (GetIdent (data)),
  95. msgaddress (GetAddress (data));
  96. client->ChannelMessage (
  97. theMsg.String(),
  98. theNick.String(),
  99. msgident.String(),
  100. msgaddress.String());
  101. }
  102. return true;
  103. }
  104. if (firstWord == "NOTICE")
  105. {
  106. BString theNotice (RestOfString(data, 3));
  107. theNotice.RemoveFirst(":");
  108. BString tempString;
  109. const char *expansions[2];
  110. expansions[0] = fServerHostName.String();
  111. expansions[1] = theNotice.String();
  112. tempString = ExpandKeyed (fEvents[E_SNOTICE].String(), "NR", expansions);
  113. Display (tempString.String(), C_NOTICE);
  114. return true;
  115. }
  116. if (secondWord == "NOTICE")
  117. {
  118. BString theNotice (RestOfString(data, 4));
  119. theNotice.RemoveFirst(":");
  120. BString tempString;
  121. firstWord.RemoveFirst (":");
  122. if (firstWord.ICompare (fServerHostName) == 0)
  123. {
  124. const char *expansions[2];
  125. expansions[0] = fServerHostName.String();
  126. expansions[1] = theNotice.String();
  127. tempString = ExpandKeyed (fEvents[E_SNOTICE].String(), "NR", expansions);
  128. Display (tempString.String(), C_NOTICE);
  129. return true;
  130. }
  131. else
  132. {
  133. BString theNick (GetNick (data)),
  134. ident (GetIdent (data)),
  135. address (GetAddress (data));
  136. if ((theNotice.Length() > 0) && theNotice[0] == '\1')
  137. {
  138. // CTCP reply
  139. ParseCTCPResponse (theNick, theNotice);
  140. return true;
  141. }
  142. const char *expansions[4];
  143. expansions[0] = theNick.String();
  144. expansions[1] = theNotice.String();
  145. expansions[2] = ident.String();
  146. expansions[3] = address.String();
  147. tempString = ExpandKeyed (fEvents[E_UNOTICE].String(), "NRIA", expansions);
  148. BMessage display (M_DISPLAY);
  149. PackDisplay (&display, tempString.String(), C_NOTICE);
  150. PostActive (&display);
  151. return true;
  152. }
  153. }
  154. if (secondWord == "JOIN")
  155. {
  156. BString nick (GetNick (data)),
  157. channel (GetWord (data, 3));
  158. channel.RemoveFirst (":");
  159. ClientAgent *client (Client (channel.String()));
  160. if (nick == fMyNick)
  161. {
  162. bool activateChan (true);
  163. int32 chanCount (0);
  164. if ((chanCount = fStartupChannels.CountItems()) > 0)
  165. {
  166. for (int32 i = 0; i < chanCount; i++)
  167. if ((fStartupChannels.ItemAt (i)->ICompare (channel)) == 0)
  168. {
  169. delete fStartupChannels.RemoveItemAt (i);
  170. activateChan = false;
  171. break;
  172. }
  173. }
  174. if (!client)
  175. {
  176. ChannelAgent *newAgent (new ChannelAgent (
  177. channel.String(),
  178. fId.String(),
  179. fIrcdtype,
  180. fMyNick.String(),
  181. fSMsgr,
  182. *vision_app->pClientWin()->AgentRect()));
  183. vision_app->pClientWin()->pWindowList()->AddAgent (newAgent,
  184. channel.String(),
  185. WIN_CHANNEL_TYPE,
  186. activateChan);
  187. fClients.AddItem (newAgent);
  188. }
  189. BString tempString ("MODE ");
  190. tempString += channel;
  191. SendData (tempString.String());
  192. }
  193. else if (client)
  194. {
  195. // someone else
  196. BString ident (GetIdent (data)),
  197. address (GetAddress (data)),
  198. tempString;
  199. const char *expansions[3];
  200. expansions[0] = nick.String();
  201. expansions[1] = ident.String();
  202. expansions[2] = address.String();
  203. tempString = ExpandKeyed (fEvents[E_JOIN].String(), "NIA", expansions);
  204. BMessage display (M_DISPLAY);
  205. PackDisplay (
  206. &display,
  207. tempString.String(),
  208. C_JOIN);
  209. // add ignore code here
  210. bool ignored (false);
  211. BMessage msg (M_USER_ADD);
  212. msg.AddString ("nick", nick.String());
  213. msg.AddBool ("ignore", ignored);
  214. // don't bother displaying if the user puts an empty string
  215. if (tempString.Length() > 1)
  216. {
  217. msg.AddMessage ("display", &display);
  218. }
  219. client->fMsgr.SendMessage (&msg);
  220. }
  221. return true;
  222. }
  223. if (secondWord == "PART")
  224. {
  225. BString nick (GetNick (data)),
  226. channel (GetWord (data, 3)),
  227. reason (RestOfString(data, 4));
  228. // some servers seem to add this, shouldn't be there though
  229. channel.RemoveFirst(":");
  230. reason.RemoveFirst(":");
  231. if (reason == "-9z99")
  232. {
  233. reason = "";
  234. }
  235. ClientAgent *client;
  236. if ((client = Client (channel.String())) != 0)
  237. {
  238. BString ident (GetIdent (data)),
  239. address (GetAddress (data)),
  240. buffer;
  241. const char *expansions[4];
  242. expansions[0] = nick.String();
  243. expansions[1] = ident.String();
  244. expansions[2] = address.String();
  245. expansions[3] = reason.String();
  246. buffer = ExpandKeyed (fEvents[E_PART].String(), "NIAR", expansions);
  247. BMessage display (M_DISPLAY);
  248. PackDisplay (&display, buffer.String(), C_JOIN);
  249. BMessage msg (M_USER_QUIT);
  250. msg.AddString ("nick", nick.String());
  251. if (buffer.Length() > 1)
  252. {
  253. msg.AddMessage ("display", &display);
  254. }
  255. client->fMsgr.SendMessage (&msg);
  256. }
  257. return true;
  258. }
  259. if (secondWord == "NICK")
  260. {
  261. BString oldNick (GetNick (data)),
  262. ident (GetIdent (data)),
  263. address (GetAddress (data)),
  264. newNick (GetWord (data, 3)),
  265. buffer;
  266. newNick.RemoveFirst (":");
  267. const char *expansions[4];
  268. expansions[0] = oldNick.String();
  269. expansions[1] = newNick.String();
  270. expansions[2] = ident.String();
  271. expansions[3] = address.String();
  272. buffer = ExpandKeyed (fEvents[E_NICK].String(), "NnIA", expansions);
  273. BMessage display (M_DISPLAY);
  274. PackDisplay (&display, buffer.String(), C_NICK);
  275. BMessage msg (M_CHANGE_NICK);
  276. msg.AddString ("oldnick", oldNick.String());
  277. msg.AddString ("newnick", newNick.String());
  278. msg.AddString ("ident", ident.String());
  279. msg.AddString ("address", address.String());
  280. msg.AddMessage ("display", &display);
  281. Broadcast (&msg);
  282. // Gotta change the server as well!
  283. if (fMyNick.ICompare (oldNick) == 0)
  284. {
  285. fMyNick = newNick;
  286. if (!fReacquiredNick && (fMyNick == fReconNick))
  287. fReacquiredNick = true;
  288. if (!IsHidden())
  289. vision_app->pClientWin()->pStatusView()->SetItemValue (STATUS_NICK,
  290. newNick.String());
  291. }
  292. return true;
  293. }
  294. if (secondWord == "QUIT")
  295. {
  296. BString theNick (GetNick (data).String()),
  297. theRest (RestOfString (data, 3)),
  298. ident (GetIdent (data)),
  299. address (GetAddress (data)),
  300. theMsg,
  301. firstNick;
  302. theRest.RemoveFirst (":");
  303. const char *expansions[4];
  304. expansions[0] = theNick.String();
  305. expansions[1] = theRest.String();
  306. expansions[2] = ident.String();
  307. expansions[3] = address.String();
  308. theMsg = ExpandKeyed (fEvents[E_QUIT].String(), "NRIA", expansions);
  309. BMessage display (M_DISPLAY);
  310. PackDisplay (&display, theMsg.String(), C_QUIT);
  311. BMessage msg (M_USER_QUIT);
  312. if (theMsg.Length() > 1)
  313. {
  314. msg.AddMessage ("display", &display);
  315. }
  316. msg.AddString ("nick", theNick.String());
  317. Broadcast (&msg);
  318. // see if we had this nickname previously.
  319. // (we might have been disconnected and this could be a
  320. // connection waiting to time out)
  321. if (theNick == fReconNick)
  322. {
  323. BString tempCmd ("/nick ");
  324. tempCmd += fReconNick;
  325. ParseCmd (tempCmd.String());
  326. }
  327. return true;
  328. }
  329. if (firstWord == "PING")
  330. {
  331. BString tempString,
  332. theServer (GetWord(data, 2));
  333. theServer.RemoveFirst(":");
  334. tempString += "PONG ";
  335. tempString += fMyNick;
  336. tempString += " ";
  337. tempString += theServer;
  338. SendData (tempString.String());
  339. // some noncompliant servers dont like the above (correct) reply,
  340. // so we send this one, too.
  341. // this can't be contained in an ircdtype if because the first reply
  342. // is sent before we receive the server version.
  343. tempString = "";
  344. tempString += "PONG ";
  345. tempString += theServer;
  346. SendData (tempString.String());
  347. return true;
  348. }
  349. if (secondWord == "KICK")
  350. {
  351. BString kicker (GetNick (data)),
  352. kickee (GetWord (data, 4)),
  353. rest (RestOfString (data, 5)),
  354. channel (GetWord (data, 3));
  355. ClientAgent *client (Client (channel.String()));
  356. rest.RemoveFirst (":");
  357. if ((client = Client (channel.String())) != 0
  358. && kickee == fMyNick)
  359. {
  360. BMessage msg (M_CHANNEL_GOT_KICKED);
  361. msg.AddString ("channel", channel.String());
  362. msg.AddString ("kicker", kicker.String());
  363. msg.AddString ("rest", rest.String());
  364. client->fMsgr.SendMessage (&msg);
  365. }
  366. if (client && kickee != fMyNick)
  367. {
  368. BMessage display (M_DISPLAY);
  369. const char *expansions[4];
  370. BString buffer;
  371. expansions[0] = kickee.String();
  372. expansions[1] = channel.String();
  373. expansions[2] = kicker.String();
  374. expansions[3] = rest.String();
  375. buffer = ExpandKeyed (fEvents[E_KICK].String(), "NCnR", expansions);
  376. PackDisplay (&display, buffer.String(), C_QUIT);
  377. BMessage msg (M_USER_QUIT);
  378. msg.AddString ("nick", kickee.String());
  379. msg.AddMessage ("display", &display);
  380. client->fMsgr.SendMessage (&msg);
  381. }
  382. return true;
  383. }
  384. if (secondWord == "TOPIC")
  385. {
  386. BString theNick (GetNick (data)),
  387. theChannel (GetWord (data, 3)),
  388. theTopic (RestOfString (data, 4));
  389. ClientAgent *client (Client (theChannel.String()));
  390. theTopic.RemoveFirst (":");
  391. if (client)
  392. {
  393. BString ident (GetIdent (data)),
  394. address (GetAddress (data)),
  395. buffer;
  396. const char *expansions[5];
  397. expansions[0] = theNick.String();
  398. expansions[1] = theTopic.String();
  399. expansions[2] = client->Id().String();
  400. expansions[3] = ident.String();
  401. expansions[4] = address.String();
  402. BMessage topic (M_CHANNEL_TOPIC);
  403. topic.AddString("topic", theTopic.String());
  404. BMessage display (M_DISPLAY);
  405. buffer = ExpandKeyed (fEvents[E_TOPIC].String(), "NTCIA", expansions);
  406. PackDisplay (&display, buffer.String(), C_WHOIS);
  407. topic.AddMessage("display", &display);
  408. client->fMsgr.SendMessage (&topic);
  409. }
  410. return true;
  411. }
  412. if (secondWord == "MODE")
  413. {
  414. BString theNick (GetNick (data)),
  415. theChannel (GetWord (data, 3)),
  416. theMode (GetWord (data, 4)),
  417. theTarget (RestOfString (data, 5));
  418. ClientAgent *client (Client (theChannel.String()));
  419. if (client)
  420. {
  421. BMessage msg (M_CHANNEL_MODE);
  422. msg.AddString("nick", theNick.String());
  423. msg.AddString("mode", theMode.String());
  424. msg.AddString("target", theTarget.String());
  425. client->fMsgr.SendMessage (&msg);
  426. }
  427. else
  428. {
  429. BMessage msg (M_DISPLAY);
  430. BString buffer;
  431. theMode.RemoveFirst(":");
  432. buffer += S_PEVENTS_UMODE_CHANGE;
  433. buffer += theMode;
  434. buffer += "\n";
  435. PackDisplay (&msg, buffer.String());
  436. PostActive (&msg);
  437. }
  438. return true;
  439. }
  440. if (firstWord == "ERROR") // server error (on connect?)
  441. {
  442. BString theError (RestOfString (data, 2));
  443. theError.RemoveFirst (":");
  444. theError.Append ("\n");
  445. Display (theError.String(), C_QUIT);
  446. return true;
  447. }
  448. if (secondWord == "WALLOPS")
  449. {
  450. BString theNick (GetNick (data)),
  451. theWall (RestOfString (data, 3)),
  452. tempString;
  453. theWall.RemoveFirst (":");
  454. theWall.Append ("\n");
  455. tempString += "!";
  456. tempString += theNick;
  457. tempString += "! ";
  458. tempString += theWall;
  459. if (IsHidden())
  460. {
  461. BMessage statusMsg (M_CW_UPDATE_STATUS);
  462. statusMsg.AddPointer ("item", fAgentWinItem);
  463. statusMsg.AddInt32 ("status", WIN_NEWS_BIT);
  464. Window()->PostMessage (&statusMsg);
  465. }
  466. Display (tempString.String(), C_WALLOPS);
  467. return true;
  468. }
  469. if (secondWord == "INVITE")
  470. {
  471. BString tempString,
  472. theChannel (GetWord(data, 4));
  473. theChannel.RemoveFirst(":");
  474. tempString += S_PEVENTS_INVITE1;
  475. tempString += theChannel;
  476. tempString += S_PEVENTS_INVITE2;
  477. tempString += GetNick(data);
  478. tempString += ".\n";
  479. BMessage msg (M_DISPLAY);
  480. PackDisplay (&msg, tempString.String(), C_WHOIS);
  481. PostActive (&msg);
  482. return true;
  483. }
  484. if (secondWord == "SILENCE")
  485. {
  486. BString tempString,
  487. theHostmask (GetWord(data, 3)); // Could be a hostmask, a nick, whatever
  488. const char *hostmask = theHostmask.String();
  489. if (hostmask[0] == '+') {
  490. tempString += S_PEVENTS_SILENCE_ADDED;
  491. theHostmask.RemoveFirst("+");
  492. } else {
  493. tempString += S_PEVENTS_SILENCE_REMOVED;
  494. theHostmask.RemoveFirst("-");
  495. }
  496. tempString += theHostmask;
  497. tempString += ".\n";
  498. BMessage msg (M_DISPLAY);
  499. PackDisplay (&msg, tempString.String(), C_WHOIS);
  500. PostActive (&msg);
  501. return true;
  502. }
  503. // ship off to parse numerics
  504. return ParseENums (data, secondWord.String());
  505. }