ParseCmd.cpp 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289
  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. * Alan Ellis <alan@cgsoftware.org>
  25. */
  26. #include <File.h>
  27. #include <FilePanel.h>
  28. #include <Path.h>
  29. #include <Roster.h>
  30. #include <FindDirectory.h>
  31. #include <arpa/inet.h>
  32. #include <ctype.h>
  33. #include <netdb.h>
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <sys/socket.h>
  37. #include <map>
  38. #include "Vision.h"
  39. #include "VisionBase.h"
  40. #include "ServerAgent.h"
  41. #include "ChannelAgent.h"
  42. #include "MessageAgent.h"
  43. #include "Names.h"
  44. #include "Utilities.h"
  45. #include "ClientAgent.h"
  46. #include "ClientWindow.h"
  47. #include "RunView.h"
  48. #include "WindowList.h"
  49. bool
  50. ClientAgent::ParseCmd (const char *data)
  51. {
  52. BString firstWord (GetWord(data, 1).ToUpper());
  53. BMessage sendMsg (M_SERVER_SEND);
  54. if (vision_app->HasAlias(firstWord))
  55. {
  56. return ParseCmd(vision_app->ParseAlias(data, fId).String());
  57. }
  58. if (firstWord == "/ADDALIAS")
  59. {
  60. vision_app->AddAlias(GetWord(data, 2).ToUpper(), RestOfString(data, 3));
  61. return true;
  62. }
  63. if (firstWord == "/DELALIAS")
  64. {
  65. vision_app->RemoveAlias(GetWord(data, 2).ToUpper());
  66. return true;
  67. }
  68. if (firstWord == "/WALLOPS" // we need to insert a ':' before parm2
  69. || firstWord == "/SQUIT" // for the user
  70. || firstWord == "/PRIVMSG")
  71. {
  72. BString theCmd (firstWord.RemoveAll ("/")),
  73. theRest (RestOfString (data, 2));
  74. AddSend (&sendMsg, theCmd);
  75. if (theRest != "-9z99")
  76. {
  77. AddSend (&sendMsg, " :");
  78. AddSend (&sendMsg, theRest);
  79. }
  80. AddSend (&sendMsg, endl);
  81. return true;
  82. }
  83. if (firstWord == "/KILL") // we need to insert a ':' before parm3
  84. { // for the user
  85. BString theCmd (firstWord.RemoveAll ("/")),
  86. theTarget (GetWord (data, 2)),
  87. theRest (RestOfString (data, 3));
  88. AddSend (&sendMsg, theCmd);
  89. AddSend (&sendMsg, " ");
  90. AddSend (&sendMsg, theTarget);
  91. if (theRest != "-9z99")
  92. {
  93. AddSend (&sendMsg, " :");
  94. AddSend (&sendMsg, theRest);
  95. }
  96. AddSend (&sendMsg, endl);
  97. return true;
  98. }
  99. // some quick aliases for scripts, these will of course be
  100. // moved to an aliases section eventually
  101. if (firstWord == "/SOUNDPLAY"
  102. || firstWord == "/CL-AMP")
  103. {
  104. app_info ai;
  105. be_app->GetAppInfo (&ai);
  106. BEntry entry (&ai.ref);
  107. if (entry.InitCheck() != B_OK)
  108. return true;
  109. BPath path;
  110. entry.GetPath (&path);
  111. path.GetParent (&path);
  112. path.Append ("scripts");
  113. if (firstWord == "/SOUNDPLAY")
  114. path.Append ("soundplay-hey");
  115. else
  116. path.Append ("cl-amp-clr");
  117. BString *theCmd (new BString (path.Path()));
  118. BMessage *execmsg (new BMessage);
  119. execmsg->AddPointer ("exec", theCmd);
  120. execmsg->AddPointer ("agent", this);
  121. thread_id execThread = spawn_thread (
  122. ExecPipe,
  123. "exec_thread",
  124. B_LOW_PRIORITY,
  125. execmsg);
  126. resume_thread (execThread);
  127. return true;
  128. }
  129. if (firstWord == "/ABOUT")
  130. {
  131. vision_app->PostMessage (B_ABOUT_REQUESTED);
  132. return true;
  133. }
  134. if (firstWord == "/GAWAY")
  135. {
  136. BString theReason (RestOfString (data, 2)),
  137. tempString;
  138. if (theReason == "-9z99")
  139. theReason = "BRB"; // Todo: make a default away msg option
  140. BString theCmd ("/AWAY ");
  141. theCmd += theReason;
  142. BMessage cmdMsg (M_SUBMIT);
  143. cmdMsg.AddBool("clear", true);
  144. cmdMsg.AddBool("history", true);
  145. cmdMsg.AddString("input", theCmd.String());
  146. vision_app->pClientWin()->ServerBroadcast(&cmdMsg);
  147. return true;
  148. }
  149. if (firstWord == "/AWAY")
  150. {
  151. BString theReason (RestOfString (data, 2)),
  152. tempString;
  153. if (theReason == "-9z99")
  154. theReason = "BRB"; // Todo: make a default away msg option
  155. const char *expansions[1];
  156. expansions[0] = theReason.String();
  157. tempString = ExpandKeyed (vision_app->GetCommand (CMD_AWAY).String(), "R",
  158. expansions);
  159. tempString.RemoveFirst("\n");
  160. AddSend (&sendMsg, "AWAY");
  161. AddSend (&sendMsg, " :");
  162. AddSend (&sendMsg, theReason.String());
  163. AddSend (&sendMsg, endl);
  164. if (fId != fServerName)
  165. ActionMessage (tempString.String(), fMyNick.String());
  166. return true;
  167. }
  168. if (firstWord == "/GBACK")
  169. {
  170. BString theCmd ("/BACK");
  171. BMessage cmdMsg (M_SUBMIT);
  172. cmdMsg.AddBool("clear", true);
  173. cmdMsg.AddBool("history", true);
  174. cmdMsg.AddString("input", theCmd.String());
  175. vision_app->pClientWin()->ServerBroadcast(&cmdMsg);
  176. return true;
  177. }
  178. if (firstWord == "/BACK")
  179. {
  180. AddSend (&sendMsg, "AWAY");
  181. AddSend (&sendMsg, endl);
  182. if (fId != fServerName)
  183. ActionMessage (vision_app->GetCommand (CMD_BACK).String(), fMyNick.String());
  184. return true;
  185. }
  186. if (firstWord == "/CLEAR")
  187. {
  188. fText->Clear ();
  189. return true;
  190. }
  191. if (firstWord == "/NETCLEAR")
  192. {
  193. BLooper *looper (NULL);
  194. ServerAgent *currentserver (dynamic_cast<ServerAgent *>(fSMsgr.Target(&looper)));
  195. if (currentserver != NULL)
  196. {
  197. BMessage msg (M_SUBMIT);
  198. msg.AddString("input", "/clear");
  199. msg.AddBool("clear", true);
  200. msg.AddBool("history", false);
  201. currentserver->Broadcast(&msg, true);
  202. }
  203. return true;
  204. }
  205. if (firstWord == "/ACLEAR")
  206. {
  207. BMessage msg (M_SUBMIT);
  208. msg.AddString("input", "/netclear");
  209. msg.AddBool("clear", true);
  210. msg.AddBool("history", true);
  211. vision_app->pClientWin()->ServerBroadcast(&msg);
  212. return true;
  213. }
  214. if (firstWord == "/FIND" || firstWord == "/SEARCH")
  215. {
  216. BString buffer (RestOfString(data, 2));
  217. if (buffer != "-9z99")
  218. {
  219. fText->FindText(buffer.String());
  220. }
  221. return true;
  222. }
  223. if (firstWord == "/CTCP")
  224. {
  225. BString theTarget (GetWord (data, 2)),
  226. theAction (RestOfString (data, 3));
  227. if (theAction != "-9z99")
  228. {
  229. theAction.ToUpper();
  230. if (theAction.ICompare ("PING") == 0)
  231. {
  232. time_t now (time (0));
  233. theAction << " " << now;
  234. }
  235. CTCPAction (theTarget, theAction);
  236. AddSend (&sendMsg, "PRIVMSG ");
  237. AddSend (&sendMsg, theTarget << " :\1" << theAction << "\1");
  238. AddSend (&sendMsg, endl);
  239. }
  240. else
  241. Display ("[x] /ctcp: " S_PCMD_PARAMETER_ERROR "\n", C_ERROR);
  242. return true;
  243. }
  244. if (firstWord == "/DCC")
  245. {
  246. BString secondWord (GetWord (data, 2)),
  247. theNick (GetWord (data, 3)),
  248. theFile (RestOfString(data, 4));
  249. if (secondWord.ICompare ("SEND") == 0
  250. && theNick != "-9z99")
  251. {
  252. BMessage *msg (new BMessage (M_CHOSE_FILE));
  253. msg->AddString ("nick", theNick.String());
  254. BPath sendPath;
  255. if (theFile != "-9z99")
  256. {
  257. if (theFile.ByteAt (0) != '/')
  258. {
  259. find_directory (B_USER_DIRECTORY, &sendPath, false);
  260. sendPath.Append (theFile.String(), true);
  261. }
  262. else
  263. sendPath.SetTo (theFile.String(), NULL, true);
  264. // the BFile is used to verify if the file exists
  265. // based off the documentation get_ref_for_path *should*
  266. // return something other than B_OK if the file doesn't exist
  267. // but that doesn't seem to be working correctly
  268. BFile sendFile (sendPath.Path(), B_READ_ONLY);
  269. // if the file exists, sendMsg, otherwise drop to the file panel
  270. if (sendFile.InitCheck() == B_OK)
  271. {
  272. sendFile.Unset();
  273. entry_ref ref;
  274. get_ref_for_path(sendPath.Path(), &ref);
  275. msg->AddRef("refs", &ref);
  276. fSMsgr.SendMessage(msg);
  277. return true;
  278. }
  279. }
  280. BFilePanel *myPanel (new BFilePanel (B_OPEN_PANEL, NULL, NULL, 0, false));
  281. BString myTitle (S_PCMD_SEND_TITLE);
  282. myTitle.Append (theNick);
  283. myPanel->Window()->SetTitle (myTitle.String());
  284. myPanel->SetTarget (fSMsgr);
  285. myPanel->SetMessage (msg);
  286. myPanel->SetButtonLabel (B_DEFAULT_BUTTON, S_PCMD_SEND_BUTTON);
  287. myPanel->Show();
  288. }
  289. if (secondWord.ICompare ("CHAT") == 0
  290. && theNick != "-9z99")
  291. {
  292. if (theNick.ICompare(fMyNick) == 0)
  293. return false;
  294. BString thePort (GetWord (data, 4));
  295. BMessage msg (M_CHAT_ACTION);
  296. msg.AddString ("nick", theNick.String());
  297. if (thePort != "-9z99")
  298. msg.AddString ("port", thePort.String());
  299. fSMsgr.SendMessage (&msg);
  300. }
  301. return true;
  302. }
  303. if (firstWord == "/DOP" || firstWord == "/DEOP" || firstWord == "/DEVOICE")
  304. {
  305. BString theNick (RestOfString (data, 2));
  306. int32 current (2),
  307. last (2);
  308. if (theNick != "-9z99")
  309. {
  310. BString command ("MODE ");
  311. command += fId;
  312. command += " -";
  313. while (GetWord(data, current) != "-9z99")
  314. {
  315. AddSend (&sendMsg, command.String());
  316. for (; GetWord(data, current) != "-9z99" && (current - last != 4); current++)
  317. AddSend (&sendMsg, ((firstWord == "/DEVOICE") ? "v" : "o"));
  318. AddSend (&sendMsg, " ");
  319. for (; last < current; last++)
  320. {
  321. BString curNick (GetWord(data, last));
  322. if (curNick != "-9z99")
  323. {
  324. AddSend (&sendMsg, curNick);
  325. AddSend (&sendMsg, " ");
  326. }
  327. }
  328. AddSend (&sendMsg, endl);
  329. sendMsg.MakeEmpty();
  330. }
  331. }
  332. else
  333. {
  334. BString dispString ("[x] ");
  335. dispString += firstWord.ToLower();
  336. dispString += ": ";
  337. dispString += S_PCMD_PARAMETER_ERROR "\n";
  338. Display (dispString.String(), C_ERROR);
  339. }
  340. return true;
  341. }
  342. if (firstWord == "/DNS")
  343. {
  344. BString parms (GetWord(data, 2));
  345. ChannelAgent *channelagent;
  346. MessageAgent *messageagent;
  347. if ((channelagent = dynamic_cast<ChannelAgent *>(this)))
  348. {
  349. const NamesView *namesList (channelagent->pNamesList());
  350. int32 count (namesList->CountItems());
  351. for (int32 i = 0; i < count; ++i)
  352. {
  353. NameItem *item ((NameItem *)(namesList->ItemAt (i)));
  354. if (!item->Name().ICompare (parms.String(), strlen (parms.String()))) //nick
  355. {
  356. AddSend (&sendMsg, "USERHOST ");
  357. AddSend (&sendMsg, item->Name().String());
  358. AddSend (&sendMsg, endl);
  359. return true;
  360. }
  361. }
  362. }
  363. else if ((messageagent = dynamic_cast<MessageAgent *>(this)))
  364. {
  365. BString eid (fId);
  366. eid.RemoveLast (" [DCC]");
  367. if (!ICompare(eid, parms) || !ICompare(fMyNick, parms))
  368. {
  369. AddSend (&sendMsg, "USERHOST ");
  370. AddSend (&sendMsg, parms.String());
  371. AddSend (&sendMsg, endl);
  372. return true;
  373. }
  374. }
  375. if (parms != "-9z99")
  376. {
  377. BMessage *lookupmsg (new BMessage);
  378. lookupmsg->AddString ("lookup", parms.String());
  379. lookupmsg->AddPointer ("agent", this);
  380. thread_id lookupThread = spawn_thread (
  381. DNSLookup,
  382. "dns_lookup",
  383. B_LOW_PRIORITY,
  384. lookupmsg);
  385. resume_thread (lookupThread);
  386. }
  387. else
  388. Display ("[x] /dns: " S_PCMD_PARAMETER_ERROR "\n", C_ERROR);
  389. return true;
  390. }
  391. if (firstWord == "/PEXEC" || firstWord == "/RRUN") // piped exec
  392. {
  393. BString *theCmd (new BString (RestOfString (data, 2)));
  394. if (*theCmd != "-9z99")
  395. {
  396. BMessage *msg (new BMessage);
  397. msg->AddPointer ("exec", theCmd);
  398. msg->AddPointer ("agent", this);
  399. thread_id execThread = spawn_thread (
  400. ExecPipe,
  401. "exec_thread",
  402. B_LOW_PRIORITY,
  403. msg);
  404. resume_thread (execThread);
  405. }
  406. else
  407. {
  408. Display ("[x] /pexec: Error: Invalid parameters\n", C_ERROR);
  409. delete theCmd;
  410. }
  411. return true;
  412. }
  413. #if 1
  414. if (firstWord == "/EXCLUDE")
  415. {
  416. {
  417. BString second (GetWord (data, 2)),
  418. rest (RestOfString (data, 3));
  419. if (rest != "-9z99" && rest != "-9z99")
  420. {
  421. BMessage msg (M_EXCLUDE_ADD);
  422. msg.AddString ("second", second.String());
  423. msg.AddString ("cmd", rest.String());
  424. msg.AddString ("server", fServerName.String());
  425. msg.AddRect ("frame", Frame());
  426. vision_app->PostMessage (&msg);
  427. }
  428. }
  429. return true;
  430. }
  431. #endif
  432. if (firstWord == "/EXIT")
  433. {
  434. Window()->PostMessage (B_QUIT_REQUESTED);
  435. return true;
  436. }
  437. if (firstWord == "/IGNORE")
  438. {
  439. BString rest (RestOfString (data, 2));
  440. // strip trailing spaces
  441. int32 count (rest.Length() - 1);
  442. while (rest[count--] == ' ')
  443. rest.RemoveLast(" ");
  444. if (rest != "-9z99")
  445. {
  446. BMessage msg (M_IGNORE_ADD);
  447. msg.AddString ("cmd", rest.String());
  448. fSMsgr.SendMessage(&msg);
  449. }
  450. return true;
  451. }
  452. if (firstWord == "/INVITE" || firstWord == "/I")
  453. {
  454. BString theUser (GetWord (data, 2));
  455. if (theUser != "-9z99")
  456. {
  457. BString theChan (GetWord (data, 3));
  458. if (theChan == "-9z99")
  459. theChan = fId;
  460. AddSend (&sendMsg, "INVITE ");
  461. AddSend (&sendMsg, theUser << " " << theChan);
  462. AddSend (&sendMsg, endl);
  463. }
  464. else
  465. Display ("[x] /invite: " S_PCMD_PARAMETER_ERROR "\n", C_ERROR);
  466. return true;
  467. }
  468. if (firstWord == "/JOIN" || firstWord == "/J")
  469. {
  470. // Bugs: Will not handle passing more than one channel key
  471. BString channel (GetWord (data, 2));
  472. if (channel != "-9z99")
  473. {
  474. if (channel[0] != '#'
  475. && channel[0] != '!'
  476. && channel[0] != '&'
  477. && channel[0] != '+')
  478. channel.Prepend ("#");
  479. AddSend (&sendMsg, "JOIN ");
  480. AddSend (&sendMsg, channel);
  481. BString key (GetWord (data, 3));
  482. if (key != "-9z99")
  483. {
  484. AddSend (&sendMsg, " ");
  485. AddSend (&sendMsg, key);
  486. }
  487. AddSend (&sendMsg, endl);
  488. if (key != "-9z99")
  489. {
  490. // used for keeping track of channel keys on u2 ircds
  491. // (not included as part of the mode reply on join)
  492. ServerAgent *fatherServer (vision_app->pClientWin()->GetTopServer (fAgentWinItem));
  493. if (fatherServer != NULL)
  494. {
  495. if (fatherServer->IRCDType() == IRCD_UNDERNET)
  496. {
  497. vision_app->pClientWin()->joinStrings.Append (",");
  498. vision_app->pClientWin()->joinStrings.Append (data);
  499. }
  500. }
  501. }
  502. }
  503. else
  504. Display ("[x] /join: " S_PCMD_PARAMETER_ERROR "\n", C_ERROR);
  505. return true;
  506. }
  507. if (firstWord == "/KICK" || firstWord == "/K")
  508. {
  509. BString theNick (GetWord (data, 2));
  510. if (theNick != "-9z99")
  511. {
  512. BString theReason (RestOfString (data, 3));
  513. if (theReason == "-9z99")
  514. {
  515. // No expansions
  516. theReason = vision_app->GetCommand (CMD_KICK);
  517. }
  518. AddSend (&sendMsg, "KICK ");
  519. AddSend (&sendMsg, fId);
  520. AddSend (&sendMsg, " ");
  521. AddSend (&sendMsg, theNick);
  522. AddSend (&sendMsg, " :");
  523. AddSend (&sendMsg, theReason);
  524. AddSend (&sendMsg, endl);
  525. }
  526. else
  527. Display ("[x] /kick: " S_PCMD_PARAMETER_ERROR "\n", C_ERROR);
  528. return true;
  529. }
  530. if (firstWord == "/LIST")
  531. {
  532. BString theArgs (RestOfString (data, 2));
  533. BMessage msg (M_LIST_COMMAND);
  534. msg.AddString ("cmd", theArgs);
  535. fSMsgr.SendMessage (&msg);
  536. return true;
  537. }
  538. if (firstWord == "/M")
  539. {
  540. BString theMode (RestOfString (data, 2));
  541. AddSend (&sendMsg, "MODE ");
  542. if (fId == fServerName)
  543. AddSend (&sendMsg, fMyNick);
  544. else if (fId[0] == '#' || fId[0] == '!' || fId[0] == '&' || fId[0] == '+')
  545. AddSend (&sendMsg, fId);
  546. else
  547. AddSend (&sendMsg, fMyNick);
  548. if (theMode != "-9z99")
  549. {
  550. AddSend (&sendMsg, " ");
  551. AddSend (&sendMsg, theMode);
  552. }
  553. AddSend (&sendMsg, endl);
  554. return true;
  555. }
  556. if (firstWord == "/ME")
  557. {
  558. BString theAction (RestOfString (data, 2));
  559. if (theAction != "-9z99")
  560. ActionMessage (theAction.String(), fMyNick.String());
  561. else
  562. Display ("[x] /me: " S_PCMD_PARAMETER_ERROR "\n", C_ERROR);
  563. return true;
  564. }
  565. if (firstWord == "/MODE")
  566. {
  567. BString theMode (RestOfString (data, 3)),
  568. theTarget (GetWord (data, 2));
  569. if (theTarget != "-9z99")
  570. {
  571. AddSend (&sendMsg, "MODE ");
  572. if (theMode == "-9z99")
  573. AddSend (&sendMsg, theTarget);
  574. else
  575. AddSend (&sendMsg, theTarget << " " << theMode);
  576. AddSend (&sendMsg, endl);
  577. }
  578. else
  579. Display ("[x] /mode: " S_PCMD_PARAMETER_ERROR "\n", C_ERROR);
  580. return true;
  581. }
  582. if (firstWord == "/MSG")
  583. {
  584. BString theRest (RestOfString (data, 3));
  585. BString theNick (GetWord (data, 2));
  586. if (theRest != "-9z99")
  587. {
  588. if (vision_app->GetBool ("queryOnMsg"))
  589. {
  590. BMessage msg (M_OPEN_MSGAGENT);
  591. BMessage buffer (M_SUBMIT);
  592. buffer.AddString ("input", theRest.String());
  593. msg.AddMessage ("msg", &buffer);
  594. msg.AddString ("nick", theNick.String());
  595. fSMsgr.SendMessage (&msg);
  596. }
  597. else
  598. {
  599. BString tempString;
  600. tempString << "[M]-> " << theNick << " > " << theRest << "\n";
  601. Display (tempString.String());
  602. AddSend (&sendMsg, "PRIVMSG ");
  603. AddSend (&sendMsg, theNick);
  604. AddSend (&sendMsg, " :");
  605. AddSend (&sendMsg, theRest);
  606. AddSend (&sendMsg, endl);
  607. }
  608. }
  609. return true;
  610. }
  611. if (firstWord == "/NICK")
  612. {
  613. BString newNick (GetWord (data, 2));
  614. if (newNick != "-9z99")
  615. {
  616. BString tempString (S_PCMD_TRY_NEW_NICK);
  617. tempString << newNick << ".\n";
  618. Display (tempString.String());
  619. AddSend (&sendMsg, "NICK ");
  620. AddSend (&sendMsg, newNick);
  621. AddSend (&sendMsg, endl);
  622. }
  623. else
  624. Display ("[x] /nick: " S_PCMD_PARAMETER_ERROR "\n", C_ERROR);
  625. return true;
  626. }
  627. if (firstWord == "/NOTICE")
  628. {
  629. BString theTarget (GetWord (data, 2)),
  630. theMsg (RestOfString (data, 3));
  631. if (theMsg != "-9z99")
  632. {
  633. AddSend (&sendMsg, "NOTICE ");
  634. AddSend (&sendMsg, theTarget);
  635. AddSend (&sendMsg, " :");
  636. AddSend (&sendMsg, theMsg);
  637. AddSend (&sendMsg, endl);
  638. BString tempString ("[N]-> ");
  639. tempString += theTarget;
  640. tempString += " -> ";
  641. tempString += theMsg;
  642. tempString += '\n';
  643. Display (tempString.String());
  644. }
  645. else
  646. Display ("[x] /notice: " S_PCMD_PARAMETER_ERROR "\n", C_ERROR);
  647. return true;
  648. }
  649. if (firstWord == "/NOTIFY")
  650. {
  651. BString rest (RestOfString (data, 2));
  652. // strip trailing spaces
  653. int32 count (rest.Length() - 1);
  654. while (rest[count--] == ' ')
  655. rest.RemoveLast(" ");
  656. if (rest != "-9z99")
  657. {
  658. BMessage msg (M_NOTIFYLIST_ADD);
  659. msg.AddString ("cmd", rest.String());
  660. fSMsgr.SendMessage(&msg);
  661. }
  662. return true;
  663. }
  664. if (firstWord == "/OP" || firstWord == "/VOICE")
  665. {
  666. BString theNick (RestOfString (data, 2));
  667. int32 current (2),
  668. last (2);
  669. if (theNick != "-9z99")
  670. {
  671. BString command ("MODE ");
  672. command += fId;
  673. command += " +";
  674. while (GetWord(data, current) != "-9z99")
  675. {
  676. AddSend (&sendMsg, command.String());
  677. for (; GetWord(data, current) != "-9z99" && (current - last != 4); current++)
  678. AddSend (&sendMsg, ((firstWord == "/OP") ? "o" : "v"));
  679. AddSend (&sendMsg, " ");
  680. for (; last < current; last++)
  681. {
  682. BString curNick (GetWord(data, last));
  683. if (curNick != "-9z99")
  684. {
  685. AddSend (&sendMsg, curNick);
  686. AddSend (&sendMsg, " ");
  687. }
  688. }
  689. AddSend (&sendMsg, endl);
  690. sendMsg.MakeEmpty();
  691. }
  692. }
  693. else
  694. {
  695. BString dispString ("[x] ");
  696. dispString += firstWord.ToLower();
  697. dispString += ": ";
  698. dispString += S_PCMD_PARAMETER_ERROR "\n";
  699. Display ( dispString.String(), C_ERROR);
  700. }
  701. return true;
  702. }
  703. if (firstWord == "/PART")
  704. {
  705. BMessage msg (M_CLIENT_QUIT);
  706. msg.AddBool ("vision:part", true);
  707. BString secondWord (GetWord(data, 2));
  708. BString partmsg;
  709. if (secondWord == fId)
  710. {
  711. partmsg = RestOfString(data, 3);
  712. }
  713. else
  714. {
  715. partmsg = RestOfString(data, 2);
  716. }
  717. if (partmsg != "-9z99")
  718. {
  719. msg.AddString("vision:partmsg", partmsg);
  720. }
  721. fMsgr.SendMessage (&msg);
  722. return true;
  723. }
  724. if (firstWord == "/PING")
  725. {
  726. BString theNick (GetWord (data, 2));
  727. if (theNick != "-9z99")
  728. {
  729. long theTime (time (0));
  730. BString tempString ("/CTCP ");
  731. tempString << theNick << " PING " << theTime;
  732. ParseCmd (tempString.String());
  733. }
  734. return true;
  735. }
  736. if (firstWord == "/QUERY" || firstWord == "/Q")
  737. {
  738. BString theNick (GetWord (data, 2)),
  739. theMsg (RestOfString (data, 3));
  740. if (theNick != "-9z99")
  741. {
  742. BMessage msg (M_OPEN_MSGAGENT);
  743. msg.AddString ("nick", theNick.String());
  744. if (theMsg != "-9z99")
  745. {
  746. BMessage buffer (M_SUBMIT);
  747. buffer.AddString ("input", theMsg.String());
  748. msg.AddMessage ("msg", &buffer);
  749. }
  750. fSMsgr.SendMessage (&msg);
  751. }
  752. return true;
  753. }
  754. if (firstWord == "/QUIT")
  755. {
  756. BString theRest (RestOfString (data, 2)),
  757. buffer;
  758. if (theRest != "-9z99")
  759. {
  760. buffer += "QUIT :";
  761. buffer += theRest;
  762. }
  763. BMessage msg (M_CLIENT_QUIT);
  764. msg.AddString ("vision:quit", buffer.String());
  765. if (fSMsgr.IsValid())
  766. fSMsgr.SendMessage (&msg);
  767. return true;
  768. }
  769. if (firstWord == "/RAW" || firstWord == "/QUOTE")
  770. {
  771. BString theRaw (RestOfString (data, 2));
  772. if (theRaw != "-9z99")
  773. {
  774. AddSend (&sendMsg, theRaw);
  775. AddSend (&sendMsg, endl);
  776. BString tempString ("[R]-> ");
  777. tempString << theRaw << '\n';
  778. Display (tempString.String());
  779. }
  780. else
  781. Display ("[x] /raw: " S_PCMD_PARAMETER_ERROR "\n", C_ERROR);
  782. return true;
  783. }
  784. if (firstWord == "/RECONNECT")
  785. {
  786. fSMsgr.SendMessage (M_SLASH_RECONNECT);
  787. return true;
  788. }
  789. if (firstWord == "/SETBOOL")
  790. {
  791. BString var (GetWord (data, 2)),
  792. value (GetWord (data, 3));
  793. bool newvalue (false),
  794. caught (false);
  795. value.ToLower();
  796. if (value != "-9z99")
  797. {
  798. if (value == "true")
  799. {
  800. caught = true;
  801. newvalue = true;
  802. }
  803. else if (value == "false")
  804. {
  805. caught = true;
  806. newvalue = false;
  807. }
  808. }
  809. if (!caught || value == "-9z99")
  810. {
  811. Display ("[x] /setbool: " S_PCMD_PARAMETER_ERROR "\n", C_ERROR);
  812. }
  813. else
  814. {
  815. status_t returned (vision_app->SetBool (var.String(), newvalue));
  816. if (returned == B_OK)
  817. Display ("[x] /setbool: " S_PCMD_SET_BOOL_SUCCESS "\n", C_ERROR);
  818. else
  819. Display ("[x] /setbool: " S_PCMD_SET_BOOL_FAILURE "\n", C_ERROR);
  820. }
  821. return true;
  822. }
  823. if (firstWord == "/SLEEP")
  824. {
  825. BString rest (RestOfString (data, 2));
  826. if (rest != "-9z99")
  827. {
  828. // this basically locks up the window its called from,
  829. // but I can't think of a better way with our current
  830. // commands implementation
  831. int32 sleeptime = atoi(rest.String());
  832. snooze (sleeptime * 1000 * 100); // deciseconds? 10 = one second
  833. }
  834. return true;
  835. }
  836. if (firstWord == "/TOPIC")
  837. {
  838. BString theChan (GetWord(data, 2));
  839. BString theTopic (RestOfString (data, 3));
  840. if (theChan != "-9z99")
  841. {
  842. AddSend (&sendMsg, "TOPIC ");
  843. AddSend (&sendMsg, theChan);
  844. if (theTopic != "-9z99")
  845. {
  846. AddSend (&sendMsg, " :");
  847. AddSend (&sendMsg, theTopic);
  848. }
  849. AddSend (&sendMsg, endl);
  850. }
  851. // TODO: print nice error message about topic parameters here
  852. return true;
  853. }
  854. if (firstWord == "/UNIGNORE")
  855. {
  856. BString rest (RestOfString (data, 2));
  857. // strip trailing spaces
  858. int32 count (rest.Length() - 1);
  859. while (rest[count--] == ' ')
  860. rest.RemoveLast(" ");
  861. if (rest != "-9z99")
  862. {
  863. BMessage msg (M_IGNORE_REMOVE);
  864. msg.AddString ("cmd", rest.String());
  865. fSMsgr.SendMessage(&msg);
  866. }
  867. return true;
  868. }
  869. if (firstWord == "/UNNOTIFY")
  870. {
  871. {
  872. BString rest (RestOfString (data, 2));
  873. // strip trailing spaces
  874. int32 count (rest.Length() - 1);
  875. while (rest[count--] == ' ')
  876. rest.RemoveLast(" ");
  877. if (rest != "-9z99")
  878. {
  879. BMessage msg (M_NOTIFYLIST_REMOVE);
  880. msg.AddString ("cmd", rest.String());
  881. fSMsgr.SendMessage (&msg);
  882. }
  883. }
  884. return true;
  885. }
  886. if (firstWord == "/VUPTIME")
  887. {
  888. BString parms (GetWord(data, 2)),
  889. clientUptime (DurationString(vision_app->VisionUptime())),
  890. expandedString (S_PCMD_VIS_UPTIME);
  891. expandedString += clientUptime;
  892. if ((fId != fServerName) && (parms == "-9z99"))
  893. {
  894. AddSend (&sendMsg, "PRIVMSG ");
  895. AddSend (&sendMsg, fId);
  896. AddSend (&sendMsg, " :");
  897. AddSend (&sendMsg, expandedString.String());
  898. AddSend (&sendMsg, endl);
  899. ChannelMessage (expandedString.String(), fMyNick.String());
  900. }
  901. else if ((parms == "-l") || (fId == fServerName)) // echo locally
  902. {
  903. BString tempString;
  904. tempString << "Vision Uptime: " << clientUptime.String() << "\n";
  905. Display (tempString.String(), C_WHOIS);
  906. }
  907. return true;
  908. }
  909. if (firstWord == "/UPTIME")
  910. {
  911. BString parms (GetWord(data, 2)),
  912. uptime (DurationString (system_time())),
  913. expandedString;
  914. const char *expansions[1];
  915. expansions[0] = uptime.String();
  916. expandedString = ExpandKeyed (vision_app->GetCommand (CMD_UPTIME).String(), "U",
  917. expansions);
  918. expandedString.RemoveFirst("\n");
  919. if ((fId != fServerName) && (parms == "-9z99"))
  920. {
  921. AddSend (&sendMsg, "PRIVMSG ");
  922. AddSend (&sendMsg, fId);
  923. AddSend (&sendMsg, " :");
  924. AddSend (&sendMsg, expandedString.String());
  925. AddSend (&sendMsg, endl);
  926. ChannelMessage (expandedString.String(), fMyNick.String());
  927. }
  928. else if ((parms == "-l") || (fId == fServerName)) // echo locally
  929. {
  930. BString tempString;
  931. tempString << "Uptime: " << expandedString << "\n";
  932. Display (tempString.String(), C_WHOIS);
  933. }
  934. return true;
  935. }
  936. if (firstWord == "/VERSION"
  937. || firstWord == "/TIME")
  938. {
  939. BString theCmd (firstWord.RemoveFirst ("/")),
  940. theNick (GetWord (data, 2));
  941. theCmd.ToUpper();
  942. // the "." check is because the user might specify a server name
  943. if (theNick != "-9z99" && theNick.FindFirst(".") < 0)
  944. {
  945. BString tempString ("/CTCP ");
  946. tempString << theNick << " " << theCmd;
  947. ParseCmd (tempString.String());
  948. }
  949. else
  950. {
  951. AddSend (&sendMsg, theCmd);
  952. if (theNick != "-9z99")
  953. {
  954. AddSend (&sendMsg, " ");
  955. AddSend (&sendMsg, theNick);
  956. }
  957. AddSend (&sendMsg, endl);
  958. }
  959. return true;
  960. }
  961. if (firstWord != "" && firstWord[0] == '/')
  962. // != "" is required to prevent a nasty crash with firstWord[0]
  963. {
  964. BString theCmd (firstWord.RemoveAll ("/")),
  965. theRest (RestOfString (data, 2));
  966. if (theCmd == "W")
  967. theCmd = "WHOIS";
  968. AddSend (&sendMsg, theCmd);
  969. if (theRest != "-9z99")
  970. {
  971. AddSend (&sendMsg, " ");
  972. AddSend (&sendMsg, theRest);
  973. }
  974. AddSend (&sendMsg, endl);
  975. return true;
  976. }
  977. return false; // we couldn't handle this message
  978. }
  979. int32
  980. ClientAgent::ExecPipe (void *arg)
  981. {
  982. BMessage *msg (reinterpret_cast<BMessage *>(arg));
  983. BString *exec;
  984. ClientAgent *agent;
  985. if ((msg->FindPointer ("exec", reinterpret_cast<void **>(&exec)) != B_OK)
  986. || (msg->FindPointer ("agent", reinterpret_cast<void **>(&agent)) != B_OK))
  987. {
  988. printf (":ERROR: couldn't find valid data in BMsg to ExecPipe() -- bailing\n");
  989. return B_ERROR;
  990. }
  991. // re use message
  992. msg->MakeEmpty();
  993. msg->what = M_SUBMIT;
  994. msg->AddString("input", "");
  995. msg->AddBool("clear", false);
  996. msg->AddBool("add2history", false);
  997. BMessenger self_destruct_in_15_seconds(agent);
  998. FILE *fp = popen (exec->String(), "r");
  999. if(fp == NULL)
  1000. {
  1001. msg->what = M_DISPLAY;
  1002. PackDisplay(msg, "[x] " S_PCMD_PEXEC_ERROR "\n", C_ERROR);
  1003. self_destruct_in_15_seconds.SendMessage(msg);
  1004. }
  1005. else
  1006. {
  1007. char data[768]; // should be long enough for any line...
  1008. // read one less just in case we need to offset by a char (prepended '/')
  1009. while (fgets(data, 767, fp))
  1010. {
  1011. data[strlen(data)-1] = '\0'; // strip termination
  1012. if (data[0] == '/')
  1013. {
  1014. memmove(data + 1, data, strlen(data));
  1015. data[0] = ' ';
  1016. }
  1017. // ship off to agent
  1018. msg->ReplaceString("input", data);
  1019. self_destruct_in_15_seconds.SendMessage(msg);
  1020. }
  1021. pclose(fp);
  1022. }
  1023. delete exec;
  1024. delete msg;
  1025. return B_OK;
  1026. }
  1027. int32
  1028. ClientAgent::DNSLookup (void *arg)
  1029. {
  1030. BMessage *msg (reinterpret_cast<BMessage *>(arg));
  1031. const char *lookup;
  1032. ClientAgent *agent;
  1033. if ((msg->FindString ("lookup", &lookup) != B_OK)
  1034. || (msg->FindPointer ("agent", reinterpret_cast<void **>(&agent)) != B_OK))
  1035. {
  1036. printf (":ERROR: couldn't find valid data in BMsg to DNSLookup() -- bailing\n");
  1037. return B_ERROR;
  1038. }
  1039. BString resolve (lookup),
  1040. output ("[x] ");
  1041. if (isalpha (resolve[0]))
  1042. {
  1043. hostent *hp = gethostbyname (resolve.String());
  1044. if (hp)
  1045. {
  1046. // ip address is in hp->h_addr_list[0];
  1047. char addr_buf[16];
  1048. in_addr *addr = (in_addr *)hp->h_addr_list[0];
  1049. strcpy(addr_buf, inet_ntoa(*addr));
  1050. output += S_PCMD_DNS1;
  1051. output += resolve.String();
  1052. output += S_PCMD_DNS2;
  1053. output += addr_buf;
  1054. }
  1055. else
  1056. {
  1057. output += S_PCMD_DNS_ERROR;
  1058. output += resolve.String();
  1059. }
  1060. }
  1061. else
  1062. {
  1063. ulong addr = inet_addr (resolve.String());
  1064. hostent *hp = gethostbyaddr ((const char *)&addr, 4, AF_INET);
  1065. if (hp)
  1066. {
  1067. output += S_PCMD_DNS1;
  1068. output += resolve.String();
  1069. output += S_PCMD_DNS2;
  1070. output += hp->h_name;
  1071. }
  1072. else
  1073. {
  1074. output += S_PCMD_DNS_ERROR;
  1075. output += resolve.String();
  1076. }
  1077. }
  1078. output += "\n";
  1079. delete msg;
  1080. BMessage dnsMsg (M_DISPLAY);
  1081. agent->PackDisplay (&dnsMsg, output.String(), C_WHOIS);
  1082. agent->fMsgr.SendMessage (&dnsMsg);
  1083. return B_OK;
  1084. }