1 /*
2 *
3 * centerim IRC protocol handling class
4 * $Id: irchook.cc,v 1.80 2004/12/20 00:54:02 konst Exp $
5 *
6 * Copyright (C) 2001-2004 by Konstantin Klyagin <k@thekonst.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 * USA
22 *
23 */
24
25 #include "irchook.h"
26
27 #ifdef BUILD_IRC
28
29 #include "icqgroups.h"
30 #include "icqface.h"
31 #include "icqcontacts.h"
32 #include "imlogger.h"
33
34 #include "accountmanager.h"
35 #include "eventmanager.h"
36
37 #include "centerim.h"
38
39 #include <iterator>
40 #include <sstream>
41
42 #define NOTIFBUF 512
43
44 // ----------------------------------------------------------------------------
45
46 irchook irhook;
47
irchook()48 irchook::irchook()
49 : abstracthook(irc), handle(firetalk_create_handle(firetalk_find_protocol("IRC"), 0)),
50 fonline(false), flogged(false), ourstatus(offline)
51 {
52 fcapabs.insert(hookcapab::setaway);
53 fcapabs.insert(hookcapab::fetchaway);
54 fcapabs.insert(hookcapab::changenick);
55 fcapabs.insert(hookcapab::optionalpassword);
56 fcapabs.insert(hookcapab::ping);
57 fcapabs.insert(hookcapab::version);
58 fcapabs.insert(hookcapab::files);
59 fcapabs.insert(hookcapab::cltemporary);
60 fcapabs.insert(hookcapab::directadd);
61 fcapabs.insert(hookcapab::conferencing);
62 fcapabs.insert(hookcapab::channelpasswords);
63 }
64
~irchook()65 irchook::~irchook() {
66 }
67
init()68 void irchook::init() {
69 int i;
70
71 manualstatus = conf->getstatus(irc);
72
73 for(i = 0; i < clist.count; i++) {
74 icqcontact *c = (icqcontact *) clist.at(i);
75
76 if(c->getdesc().pname == irc)
77 if(ischannel(c))
78 if(c->getbasicinfo().requiresauth) {
79 channels.push_back(channelInfo(c->getdesc().nickname));
80 channels.back().joined = true;
81 channels.back().passwd = c->getbasicinfo().zip;
82 }
83 }
84
85 firetalk_register_callback(handle, FC_CONNECTED, &connected);
86 firetalk_register_callback(handle, FC_CONNECTFAILED, &connectfailed);
87 firetalk_register_callback(handle, FC_DISCONNECT, &disconnected);
88 firetalk_register_callback(handle, FC_NEWNICK, &newnick);
89 firetalk_register_callback(handle, FC_IM_GOTINFO, &gotinfo);
90 firetalk_register_callback(handle, FC_IM_GOTCHANNELS, &gotchannels);
91 firetalk_register_callback(handle, FC_IM_GETMESSAGE, &getmessage);
92 firetalk_register_callback(handle, FC_IM_GETACTION, &getaction);
93 firetalk_register_callback(handle, FC_IM_BUDDYONLINE, &buddyonline);
94 firetalk_register_callback(handle, FC_IM_BUDDYOFFLINE, &buddyoffline);
95 firetalk_register_callback(handle, FC_IM_BUDDYAWAY, &buddyaway);
96 firetalk_register_callback(handle, FC_IM_BUDDYUNAWAY, &buddyonline);
97 firetalk_register_callback(handle, FC_CHAT_LISTMEMBER, &listmember);
98 firetalk_register_callback(handle, FC_CHAT_LIST_EXTENDED, &listextended);
99 firetalk_register_callback(handle, FC_CHAT_END_EXTENDED, &endextended);
100 firetalk_register_callback(handle, FC_CHAT_NAMES, &chatnames);
101 firetalk_register_callback(handle, FC_CHAT_GETMESSAGE, &chatmessage);
102 firetalk_register_callback(handle, FC_CHAT_GETACTION, &chataction);
103 firetalk_register_callback(handle, FC_CHAT_JOINED, &chatjoined);
104 firetalk_register_callback(handle, FC_CHAT_LEFT, &chatleft);
105 firetalk_register_callback(handle, FC_CHAT_KICKED, &chatkicked);
106 firetalk_register_callback(handle, FC_CHAT_OPPED, &chatopped);
107 firetalk_register_callback(handle, FC_CHAT_DEOPPED, &chatdeopped);
108 firetalk_register_callback(handle, FC_ERROR, &errorhandler);
109 firetalk_register_callback(handle, FC_IM_USER_NICKCHANGED, &nickchanged);
110 firetalk_register_callback(handle, FC_NEEDPASS, &needpass);
111 firetalk_register_callback(handle, FC_FILE_OFFER, &fileoffer);
112 firetalk_register_callback(handle, FC_FILE_START, &filestart);
113 firetalk_register_callback(handle, FC_FILE_PROGRESS, &fileprogress);
114 firetalk_register_callback(handle, FC_FILE_FINISH, &filefinish);
115 firetalk_register_callback(handle, FC_FILE_ERROR, &fileerror);
116 firetalk_register_callback(handle, FC_CHAT_USER_JOINED, &chatuserjoined);
117 firetalk_register_callback(handle, FC_CHAT_USER_LEFT, &chatuserleft);
118 firetalk_register_callback(handle, FC_CHAT_USER_KICKED, &chatuserkicked);
119 firetalk_register_callback(handle, FC_CHAT_GOTTOPIC, &chatgottopic);
120 firetalk_register_callback(handle, FC_CHAT_USER_OPPED, &chatuseropped);
121 firetalk_register_callback(handle, FC_CHAT_USER_DEOPPED, &chatuserdeopped);
122
123 firetalk_subcode_register_request_callback(handle, "VERSION", &subrequest);
124
125 firetalk_subcode_register_reply_callback(handle, "PING", &subreply);
126 firetalk_subcode_register_reply_callback(handle, "VERSION", &subreply);
127
128 if(conf->getdebug())
129 firetalk_register_callback(handle, FC_LOG, &fclog);
130 }
131
connect()132 void irchook::connect() {
133 icqconf::imaccount acc = conf->getourid(irc);
134 log(logConnecting);
135
136 firetalk_register_callback(handle, FC_DISCONNECT, 0);
137 firetalk_disconnect(handle);
138 firetalk_register_callback(handle, FC_DISCONNECT, &disconnected);
139
140 fonline = firetalk_signon(handle, acc.server.c_str(),
141 acc.port, acc.nickname.c_str()) == FE_SUCCESS;
142
143 if(fonline) {
144 flogged = false;
145 } else {
146 face.log(_("+ [irc] unable to connect to the server"));
147 }
148 }
149
disconnect()150 void irchook::disconnect() {
151 if(fonline) {
152 firetalk_disconnect(handle);
153 }
154 }
155
exectimers()156 void irchook::exectimers() {
157 }
158
main()159 void irchook::main() {
160 firetalk_select();
161 }
162
getsockets(fd_set & rfds,fd_set & wfds,fd_set & efds,int & hsocket) const163 void irchook::getsockets(fd_set &rfds, fd_set &wfds, fd_set &efds, int &hsocket) const {
164 int *r, *w, *e, *sr, *sw, *se;
165
166 firetalk_getsockets(firetalk_find_protocol("IRC"), &sr, &sw, &se);
167
168 for(r = sr; *r; r++) {
169 if(*r > hsocket) hsocket = *r;
170 FD_SET(*r, &rfds);
171 }
172
173 for(w = sw; *w; w++) {
174 if(*w > hsocket) hsocket = *w;
175 FD_SET(*w, &wfds);
176 }
177
178 for(e = se; *e; e++) {
179 if(*e > hsocket) hsocket = *e;
180 FD_SET(*e, &efds);
181 }
182
183 delete sr;
184 delete sw;
185 delete se;
186 }
187
isoursocket(fd_set & rfds,fd_set & wfds,fd_set & efds) const188 bool irchook::isoursocket(fd_set &rfds, fd_set &wfds, fd_set &efds) const {
189 bool res = false;
190 int *r, *w, *e, *sr, *sw, *se;
191
192 if(online()) {
193 firetalk_getsockets(firetalk_find_protocol("IRC"), &sr, &sw, &se);
194
195 for(r = sr; *r; r++) res = res || FD_ISSET(*r, &rfds);
196 for(w = sw; *w; w++) res = res || FD_ISSET(*w, &wfds);
197 for(e = se; *e; e++) res = res || FD_ISSET(*e, &efds);
198
199 delete sr;
200 delete sw;
201 delete se;
202 }
203
204 return res;
205 }
206
online() const207 bool irchook::online() const {
208 return fonline;
209 }
210
logged() const211 bool irchook::logged() const {
212 return flogged && fonline;
213 }
214
enabled() const215 bool irchook::enabled() const {
216 return true;
217 }
218
isconnecting() const219 bool irchook::isconnecting() const {
220 return fonline && !flogged;
221 }
222
send(const imevent & ev)223 bool irchook::send(const imevent &ev) {
224 icqcontact *c = clist.get(ev.getcontact());
225 string text, cmd;
226 bool result = true;
227
228 if(c) {
229 if(ev.gettype() == imevent::message) {
230 const immessage *m = static_cast<const immessage *>(&ev);
231 text = rusconv("kw", m->gettext());
232
233 } else if(ev.gettype() == imevent::url) {
234 const imurl *m = static_cast<const imurl *>(&ev);
235 text = rushtmlconv("kw", m->geturl()) + "\n\n" + rushtmlconv("kw", m->getdescription());
236
237 } else if(ev.gettype() == imevent::file) {
238 const imfile *m = static_cast<const imfile *>(&ev);
239 vector<imfile::record> files = m->getfiles();
240 vector<imfile::record>::const_iterator ir;
241
242 for(ir = files.begin(); ir != files.end(); ++ir) {
243 imfile::record r;
244 r.fname = ir->fname;
245 r.size = ir->size;
246
247 imfile fr(c->getdesc(), imevent::outgoing, "",
248 vector<imfile::record>(1, r));
249
250 firetalk_file_offer(handle, c->getdesc().nickname.c_str(),
251 ir->fname.c_str(), &transferinfo[fr].first);
252 }
253
254 return true;
255 }
256
257 string original = text;
258 int pos = -1;
259
260 while (original.length()>0)
261 {
262 if ((pos = original.find("\n")) != -1) // split by newlines into separate commands, drop empty ones
263 {
264 if (pos>1)
265 {
266 text = original.substr(0, pos-1);
267 original.erase(0, pos+1);
268 }
269 else
270 {
271 original.erase(0, pos+1);
272 continue;
273 }
274 }
275 else
276 {
277 text = original;
278 original.erase();
279 }
280 if(text.substr(0, 1) == "/") {
281 text.erase(0, 1);
282 cmd = up(getword(text));
283
284 if(cmd == "ME") {
285 if(ischannel(c)) return firetalk_chat_send_action(handle,
286 c->getdesc().nickname.c_str(), text.c_str(), 0) == FE_SUCCESS;
287 else return firetalk_im_send_action(handle,
288 c->getdesc().nickname.c_str(), text.c_str(), 0) == FE_SUCCESS;
289
290 } else if(cmd == "KICK") {
291 text = cmd + " " + c->getdesc().nickname + " " + text;
292
293 } else if(cmd == "OP") {
294 text = (string) "mode " + c->getdesc().nickname + " +o " + text;
295
296 } else if(cmd == "DEOP") {
297 text = (string) "mode " + c->getdesc().nickname + " -o " + text;
298
299 } else if(cmd == "RAW") {
300 // leave text intact
301
302 } else {
303 text.insert(0, cmd + " ");
304
305 }
306
307 rawcommand(text);
308 }
309
310 if(ischannel(c)) {
311 if (firetalk_chat_send_message(handle,
312 c->getdesc().nickname.c_str(), text.c_str(), 0) != FE_SUCCESS)
313 result = false;
314
315 } else {
316 if (firetalk_im_send_message(handle,
317 c->getdesc().nickname.c_str(), text.c_str(), 0) != FE_SUCCESS)
318 result = false;
319
320 }
321 }
322 return result;
323 }
324
325 return false;
326 }
327
sendnewuser(const imcontact & ic)328 void irchook::sendnewuser(const imcontact &ic) {
329 icqcontact *c;
330
331 if(online()) {
332 if(!ischannel(ic)) {
333 vector<icqgroup>::const_iterator ig = find(groups.begin(), groups.end(), clist.get(ic)->getgroupid());
334 if(ig != groups.end()) {
335 firetalk_im_add_buddy(handle, ic.nickname.c_str(), ig->getname().c_str(), "");
336 }
337 requestinfo(ic);
338 } else {
339 vector<channelInfo> ch = getautochannels();
340 if(find(ch.begin(), ch.end(), ic.nickname) == ch.end()) {
341 ch.push_back(ic.nickname);
342 ch.back().joined = true;
343 if(c = clist.get(ic)) {
344 ch.back().passwd = c->getbasicinfo().zip;
345 }
346 setautochannels(ch);
347 }
348 }
349 }
350 }
351
removeuser(const imcontact & ic)352 void irchook::removeuser(const imcontact &ic) {
353 if(online()) {
354 if(!ischannel(ic)) {
355 firetalk_im_remove_buddy(handle, ic.nickname.c_str());
356 } else {
357 vector<channelInfo> ch = getautochannels();
358 vector<channelInfo>::iterator ich = find(ch.begin(), ch.end(), ic.nickname);
359 if(ich != ch.end()) {
360 ch.erase(ich);
361 setautochannels(ch);
362 }
363 }
364 }
365 }
366
setautostatus(imstatus st)367 void irchook::setautostatus(imstatus st) {
368 if(st != offline) {
369 if(getstatus() == offline) {
370 connect();
371 } else {
372 if(getstatus() != st) {
373 logger.putourstatus(irc, getstatus(), ourstatus = st);
374
375 switch(st) {
376 case away:
377 case notavail:
378 case outforlunch:
379 case occupied:
380 firetalk_set_away(handle, conf->getawaymsg(irc).c_str(), 0);
381 break;
382
383 default:
384 firetalk_set_away(handle, 0, 0);
385 break;
386 }
387 }
388 }
389 } else {
390 if(getstatus() != offline) {
391 disconnect();
392 }
393 }
394
395 face.update();
396 }
397
getstatus() const398 imstatus irchook::getstatus() const {
399 return (flogged && fonline) ? ourstatus : offline;
400 }
401
requestinfo(const imcontact & c)402 void irchook::requestinfo(const imcontact &c) {
403 firetalk_im_get_info(handle, c.nickname.c_str());
404 }
405
sendupdateuserinfo(icqcontact & c,const string & newpass)406 void irchook::sendupdateuserinfo(icqcontact &c, const string &newpass) {
407 const icqcontact::basicinfo &b = c.getbasicinfo();
408
409 ircname = b.fname;
410 if(!b.lname.empty()) {
411 if(!ircname.empty()) ircname += " ";
412 ircname += b.lname;
413 }
414 }
415
lookup(const imsearchparams & params,verticalmenu & dest)416 void irchook::lookup(const imsearchparams ¶ms, verticalmenu &dest) {
417 string rooms = params.room, room;
418 bool ready = true;
419 vector<channelInfo>::iterator ic;
420
421 searchdest = &dest;
422
423 emailsub = params.email;
424 namesub = params.firstname;
425 searchsincelast = params.sincelast && !params.room.empty();
426
427 searchchannels.clear();
428 extlisted.clear();
429
430 while(!foundguys.empty()) {
431 delete foundguys.back();
432 foundguys.pop_back();
433 }
434
435 if(!params.room.empty()) {
436 smode = Channel;
437
438 while(!(room = getword(rooms)).empty()) {
439 if(room[0] != '#') room.insert(0, "#");
440 searchchannels.push_back(room);
441 ic = find(irhook.channels.begin(), irhook.channels.end(), room);
442
443 if(ic == irhook.channels.end()) {
444 irhook.channels.push_back(channelInfo(room));
445 ic = irhook.channels.end()-1;
446 }
447
448 if(!ic->joined) {
449 firetalk_chat_join(handle, room.c_str());
450 ready = false;
451 }
452
453 if(emailsub.empty() && namesub.empty()) {
454 /* if(ic->fetched) {*/
455 ic->nicks.clear();
456 firetalk_chat_listmembers(handle, room.c_str());
457 /* } else {
458 ready = false;
459 }*/
460
461 } else {
462 ready = false;
463 if(ic->joined) {
464 ic->nicks.clear();
465 firetalk_chat_requestextended(handle, params.room.c_str());
466 }
467
468 }
469 }
470
471 if(ready)
472 processnicks();
473
474 } else if(!params.email.empty()) {
475 smode = Email;
476 searchchannels.push_back("");
477 firetalk_im_searchemail(handle, ("*" + params.email + "*").c_str());
478
479 }
480 }
481
processnicks()482 void irchook::processnicks() {
483 string dnick;
484 char *nick;
485 vector<string> foundnicks;
486 static vector<string> lastfoundnicks;
487 vector<string>::iterator in, isn;
488 vector<channelInfo>::iterator ir;
489 bool remove;
490 icqcontact *c;
491 int npos;
492
493 if(!searchdest)
494 return;
495
496 ir = find(channels.begin(), channels.end(), *searchchannels.begin());
497 if(ir != channels.end())
498 foundnicks = ir->nicks;
499
500 sort(foundnicks.begin(), foundnicks.end());
501
502 if(searchchannels.size() > 1) {
503 for(in = foundnicks.begin(); in != foundnicks.end(); ) {
504 remove = false;
505
506 for(ir = channels.begin(); !remove && (ir != channels.end()); ++ir) {
507 if(find(searchchannels.begin(), searchchannels.end(), ir->name) == searchchannels.end())
508 continue;
509 if(ir->name == *searchchannels.begin())
510 continue;
511
512 if(find(ir->nicks.begin(), ir->nicks.end(), *in) == ir->nicks.end()) {
513 /*
514 *
515 * Not found in one of other channels. Remove it from the
516 * first channel's list.
517 *
518 */
519 remove = true;
520 }
521 }
522
523 if(remove) {
524 foundnicks.erase(in);
525 in = foundnicks.begin();
526 } else {
527 in++;
528 }
529 }
530 }
531
532 if(searchsincelast) {
533 vector<string> tnicks;
534 insert_iterator< vector<string> > tins(tnicks, tnicks.begin());
535
536 set_difference(foundnicks.begin(), foundnicks.end(),
537 lastfoundnicks.begin(), lastfoundnicks.end(), tins);
538
539 lastfoundnicks = foundnicks;
540 foundnicks = tnicks;
541
542 } else {
543 lastfoundnicks = foundnicks;
544
545 }
546
547 for(in = foundnicks.begin(); in != foundnicks.end(); ++in) {
548 dnick = *in;
549
550 npos = 0;
551
552 if(!emailsub.empty()) npos = dnick.rfind("<"); else
553 if(!namesub.empty()) npos = dnick.rfind("[");
554
555 if(npos > 0) dnick.erase(npos-1);
556
557 c = new icqcontact(imcontact(dnick, irc));
558 c->setdispnick(dnick);
559
560 searchdest->additem(conf->getcolor(cp_clist_irc), c, (string) " " + *in);
561 foundguys.push_back(c);
562 }
563
564 face.findready();
565 log(logConfMembers, foundguys.size());
566
567 searchdest->redraw();
568 searchdest = 0;
569 }
570
getautochannels() const571 vector<irchook::channelInfo> irchook::getautochannels() const {
572 vector<channelInfo> r;
573 vector<channelInfo>::const_iterator ic;
574
575 for(ic = channels.begin(); ic != channels.end(); ++ic) {
576 if(find(searchchannels.begin(), searchchannels.end(), ic->name) != searchchannels.end())
577 if(!ic->joined)
578 // A channel used for search
579 continue;
580
581 r.push_back(*ic);
582 }
583
584 return r;
585 }
586
setautochannels(vector<channelInfo> & achannels)587 void irchook::setautochannels(vector<channelInfo> &achannels) {
588 bool r;
589 vector<channelInfo>::iterator ic, iac;
590
591 /*
592 *
593 * First, let's leave the channels we are not on anymore.
594 *
595 */
596
597 for(ic = channels.begin(); ic != channels.end(); ++ic) {
598 iac = find(achannels.begin(), achannels.end(), ic->name);
599
600 if(ic->joined) {
601 r = iac == achannels.end();
602 if(!r) r = !iac->joined;
603 if(r) firetalk_chat_part(irhook.handle, ic->name.c_str());
604 }
605 }
606
607 /*
608 *
609 * Now, let's see if there are any new channels we
610 * gotta join to.
611 *
612 */
613
614 for(iac = achannels.begin(); iac != achannels.end(); ++iac) {
615 ic = find(channels.begin(), channels.end(), iac->name);
616
617 if(iac->joined) {
618 r = ic == channels.end();
619 if(!r) r = !ic->joined;
620 string passname = iac->name;
621 if (!iac->passwd.empty())
622 passname += " " + iac->passwd;
623 if(r) firetalk_chat_join(irhook.handle, passname.c_str());
624 }
625 }
626
627 channels = achannels;
628 }
629
requestawaymsg(const imcontact & ic)630 void irchook::requestawaymsg(const imcontact &ic) {
631 em.store(imnotification(ic, string() +
632 _("Away message:") + "\n\n" + awaymessages[ic.nickname]));
633 }
634
rawcommand(const string & cmd)635 void irchook::rawcommand(const string &cmd) {
636 int *r, *w, *e, sock;
637 if(online()) {
638 firetalk_getsockets(firetalk_find_protocol("IRC"), &r, &w, &e);
639
640 if(*r) {
641 write(*r, cmd.c_str(), cmd.size());
642 write(*r, "\n", 1);
643 }
644
645 delete r;
646 delete w;
647 delete e;
648 }
649 }
650
channelfatal(string room,const char * fmt,...)651 void irchook::channelfatal(string room, const char *fmt, ...) {
652 va_list ap;
653 char buf[NOTIFBUF];
654 vector<channelInfo>::iterator i;
655
656 va_start(ap, fmt);
657 vsnprintf(buf, NOTIFBUF, fmt, ap);
658 va_end(ap);
659
660 if(room.substr(0, 1) != "#")
661 room.insert(0, "#");
662
663 i = find(channels.begin(), channels.end(), room);
664
665 if(i != channels.end()) {
666 imcontact cont(room, irc);
667 icqcontact *c = clist.get(cont);
668 if(!c) c = clist.addnew(cont);
669 c->setstatus(offline);
670 i->joined = i->fetched = false;
671 em.store(imnotification(cont, buf));
672 }
673 }
674
ouridchanged(const icqconf::imaccount & ia)675 void irchook::ouridchanged(const icqconf::imaccount &ia) {
676 if(logged()) {
677 firetalk_set_nickname(handle, ia.nickname.c_str());
678 }
679 }
680
requestversion(const imcontact & c)681 void irchook::requestversion(const imcontact &c) {
682 if(logged()) {
683 firetalk_subcode_send_request(handle, c.nickname.c_str(), "VERSION", 0);
684 }
685 }
686
ping(const imcontact & c)687 void irchook::ping(const imcontact &c) {
688 if(logged()) {
689 firetalk_subcode_send_request(handle, c.nickname.c_str(), "PING", 0);
690 time(&pingtime[up(c.nickname)]);
691 }
692 }
693
knowntransfer(const imfile & fr) const694 bool irchook::knowntransfer(const imfile &fr) const {
695 return transferinfo.find(fr) != transferinfo.end();
696 }
697
replytransfer(const imfile & fr,bool accept,const string & localpath)698 void irchook::replytransfer(const imfile &fr, bool accept, const string &localpath) {
699 if(accept) {
700 transferinfo[fr].second = localpath;
701
702 if(transferinfo[fr].second.substr(transferinfo[fr].second.size()-1) != "/")
703 transferinfo[fr].second += "/";
704
705 transferinfo[fr].second += justfname(fr.getfiles().begin()->fname);
706
707 firetalk_file_accept(handle, transferinfo[fr].first, 0,
708 transferinfo[fr].second.c_str());
709
710 } else {
711 firetalk_file_refuse(handle, transferinfo[fr].first);
712 transferinfo.erase(fr);
713
714 }
715 }
716
aborttransfer(const imfile & fr)717 void irchook::aborttransfer(const imfile &fr) {
718 firetalk_file_cancel(handle, transferinfo[fr].first);
719
720 face.transferupdate(fr.getfiles().begin()->fname, fr,
721 icqface::tsCancel, 0, 0);
722
723 irhook.transferinfo.erase(fr);
724 }
725
getfevent(void * fhandle,imfile & fr)726 bool irchook::getfevent(void *fhandle, imfile &fr) {
727 map<imfile, pair<void *, string> >::const_iterator i = transferinfo.begin();
728
729 while(i != transferinfo.end()) {
730 if(i->second.first == fhandle) {
731 fr = i->first;
732 return true;
733 }
734 ++i;
735 }
736
737 return false;
738 }
739
740 // ----------------------------------------------------------------------------
741
userstatus(const string & nickname,imstatus st)742 void irchook::userstatus(const string &nickname, imstatus st) {
743 if(!nickname.empty()) {
744 imcontact ic(nickname, irc);
745 icqcontact *c = clist.get(ic);
746
747 if(c)
748 if(st != c->getstatus()) {
749 logger.putonline(ic, c->getstatus(), st);
750 c->setstatus(st);
751 }
752 }
753 }
754
connected(void * conn,void * cli,...)755 void irchook::connected(void *conn, void *cli, ...) {
756 irhook.flogged = true;
757 irhook.log(logLogged);
758 face.update();
759
760 int i;
761 vector<channelInfo>::iterator ic;
762 icqcontact *c;
763
764 for(i = 0; i < clist.count; i++) {
765 c = (icqcontact *) clist.at(i);
766
767 if(c->getdesc().pname == irc)
768 if(!ischannel(c)) {
769 vector<icqgroup>::const_iterator ig = find(groups.begin(), groups.end(), clist.get(c)->getgroupid());
770 if(ig != groups.end()) {
771 firetalk_im_add_buddy(irhook.handle, c->getdesc().nickname.c_str() , ig->getname().c_str(), "");
772 }
773 }
774 }
775
776 for(ic = irhook.channels.begin(); ic != irhook.channels.end(); ++ic) {
777 if(ic->joined) {
778 string passname = ic->name;
779 if (!ic->passwd.empty())
780 passname += " " + ic->passwd;
781 firetalk_chat_join(irhook.handle, passname.c_str());
782 }
783 }
784
785 irhook.ourstatus = available;
786 irhook.setautostatus(irhook.manualstatus);
787 irhook.awaymessages.clear();
788 irhook.sentpass = false;
789 }
790
disconnected(void * conn,void * cli,...)791 void irchook::disconnected(void *conn, void *cli, ...) {
792 irhook.fonline = false;
793
794 logger.putourstatus(irc, irhook.getstatus(), offline);
795 clist.setoffline(irc);
796
797 vector<channelInfo>::iterator ic;
798 for(ic = irhook.channels.begin(); ic != irhook.channels.end(); ++ic)
799 ic->fetched = false;
800
801 irhook.log(logDisconnected);
802 face.update();
803 }
804
connectfailed(void * connection,void * cli,...)805 void irchook::connectfailed(void *connection, void *cli, ...) {
806 va_list ap;
807
808 va_start(ap, cli);
809 int err = va_arg(ap, int);
810 char *reason = va_arg(ap, char *);
811 va_end(ap);
812
813 irhook.fonline = false;
814
815 face.log(_("+ [irc] connect failed: %s"), reason);
816 face.update();
817 }
818
newnick(void * conn,void * cli,...)819 void irchook::newnick(void *conn, void *cli, ...) {
820 va_list ap;
821
822 va_start(ap, cli);
823 char *nick = va_arg(ap, char *);
824 va_end(ap);
825
826 if(nick)
827 if(strlen(nick)) {
828 icqconf::imaccount acc = conf->getourid(irc);
829 acc.nickname = nick;
830 conf->setourid(acc);
831
832 face.log(_("+ [irc] nickname was changed successfully"));
833 }
834 }
835
gotinfo(void * conn,void * cli,...)836 void irchook::gotinfo(void *conn, void *cli, ...) {
837 int pos;
838 va_list ap;
839 string about, email;
840 icqcontact::basicinfo cbinfo;
841
842 va_start(ap, cli);
843 char *nick = va_arg(ap, char *);
844 char *info = va_arg(ap, char *);
845 int warning = va_arg(ap, int);
846 int idle = va_arg(ap, int);
847 va_end(ap);
848
849 if(nick && info)
850 if(strlen(nick) && strlen(info)) {
851 icqcontact *c = clist.get(imcontact(nick, irc));
852
853 if(!c) c = clist.get(contactroot);
854
855 about = info;
856 cbinfo = c->getbasicinfo();
857
858 if((pos = about.find(":")) != -1) {
859 email = about.substr(0, pos);
860 about.erase(0, pos);
861
862 if(email.substr(0, 1) == "~") email.erase(0, 1);
863 if((pos = about.find_first_not_of(" :")) > 0) about.erase(0, pos);
864 }
865
866 cbinfo.lname = "";
867 cbinfo.email = irhook.rushtmlconv("wk", email);
868
869 if((pos = about.find(" ")) != -1) {
870 cbinfo.lname = irhook.rushtmlconv("wk", about.substr(pos+1));
871 about.erase(pos);
872 }
873
874 cbinfo.fname = irhook.rushtmlconv("wk", about);
875
876 c->setnick(nick);
877 c->setbasicinfo(cbinfo);
878
879 if(c->getstatus() == offline)
880 c->setstatus(available);
881 }
882 }
883
gotchannels(void * conn,void * cli,...)884 void irchook::gotchannels(void *conn, void *cli, ...) {
885 va_list ap;
886 string info;
887 icqcontact *c;
888
889 va_start(ap, cli);
890 char *nick = va_arg(ap, char *);
891 char *channels = va_arg(ap, char *);
892 va_end(ap);
893
894 if(nick && channels)
895 if(strlen(nick) && strlen(channels)) {
896 c = clist.get(imcontact(nick, irc));
897 if(!c) c = clist.get(contactroot);
898
899 c->setabout((string) _("On channels: ") + channels);
900
901 if(c->getstatus() == offline)
902 c->setstatus(available);
903 }
904 }
905
getmessage(void * conn,void * cli,...)906 void irchook::getmessage(void *conn, void *cli, ...) {
907 va_list ap;
908
909 va_start(ap, cli);
910 char *sender = va_arg(ap, char *);
911 int automessage_flag = va_arg(ap, int);
912 char *message = va_arg(ap, char *);
913 va_end(ap);
914
915 if(sender && message)
916 if(strlen(sender) && strlen(message)) {
917 /*if(!irhook.sentpass) // NickServ identify should be handled by firetalk and needpass callback
918 if(up(sender) == "NICKSERV") {
919 firetalk_im_send_message(irhook.handle, "NickServ",
920 ((string) "identify " + conf->getourid(irc).additional["nickpass"]).c_str(), 0);
921
922 irhook.sentpass = true;
923 }*/
924
925 em.store(immessage(imcontact(sender, irc),
926 imevent::incoming, irhook.rushtmlconv("wk", cuthtml(message, chCutBR | chLeaveLinks))));
927 }
928 }
929
getaction(void * conn,void * cli,...)930 void irchook::getaction(void *conn, void *cli, ...) {
931 va_list ap;
932
933 va_start(ap, cli);
934 char *sender = va_arg(ap, char *);
935 int automessage_flag = va_arg(ap, int);
936 char *message = va_arg(ap, char *);
937 va_end(ap);
938
939 if(sender && message)
940 if(strlen(sender) && strlen(message)) {
941 em.store(immessage(imcontact(sender, irc), imevent::incoming,
942 ((string) "* " + sender + " " +
943 irhook.rushtmlconv("wk", cuthtml(message, chCutBR | chLeaveLinks))).c_str()));
944 }
945 }
946
buddyonline(void * conn,void * cli,...)947 void irchook::buddyonline(void *conn, void *cli, ...) {
948 va_list ap;
949
950 va_start(ap, cli);
951 char *nick = va_arg(ap, char *);
952 va_end(ap);
953
954 if(nick)
955 if(strlen(nick)) {
956 irhook.userstatus(nick, available);
957 }
958 }
959
buddyoffline(void * conn,void * cli,...)960 void irchook::buddyoffline(void *conn, void *cli, ...) {
961 va_list ap;
962
963 va_start(ap, cli);
964 char *nick = va_arg(ap, char *);
965 va_end(ap);
966
967 if(nick)
968 if(strlen(nick)) {
969 irhook.userstatus(nick, offline);
970 }
971 }
972
buddyaway(void * conn,void * cli,...)973 void irchook::buddyaway(void *conn, void *cli, ...) {
974 va_list ap;
975
976 va_start(ap, cli);
977 char *nick = va_arg(ap, char *);
978 char *msg = va_arg(ap, char *);
979 va_end(ap);
980
981 if(nick)
982 if(strlen(nick)) {
983 irhook.userstatus(nick, away);
984 if(msg) irhook.awaymessages[nick] = irhook.rushtmlconv("wk", msg);
985 }
986 }
987
listmember(void * connection,void * cli,...)988 void irchook::listmember(void *connection, void *cli, ...) {
989 va_list ap;
990 vector<channelInfo>::iterator ir;
991
992 va_start(ap, cli);
993 char *room = va_arg(ap, char *);
994 char *membername = va_arg(ap, char *);
995 int opped = va_arg(ap, int);
996 va_end(ap);
997
998 if(membername)
999 if(strlen(membername)) {
1000 ir = find(irhook.channels.begin(), irhook.channels.end(), room);
1001
1002 if(ir != irhook.channels.end()) {
1003 ir->nicks.push_back(/*(string) (opped ? "@": "") +*/ membername);
1004 }
1005 }
1006 }
1007
fclog(void * connection,void * cli,...)1008 void irchook::fclog(void *connection, void *cli, ...) {
1009 va_list ap;
1010
1011 va_start(ap, cli);
1012 char *msg = va_arg(ap, char *);
1013 va_end(ap);
1014
1015 face.log("irc: %s", msg);
1016 }
1017
chatnames(void * connection,void * cli,...)1018 void irchook::chatnames(void *connection, void *cli, ...) {
1019 va_list ap;
1020 vector<channelInfo>::iterator ic;
1021 vector<string>::iterator is;
1022 bool ready = true;
1023
1024 va_start(ap, cli);
1025 char *croom = va_arg(ap, char *);
1026 va_end(ap);
1027
1028 ic = find(irhook.channels.begin(), irhook.channels.end(), croom);
1029
1030 if(ic != irhook.channels.end()) {
1031 ic->fetched = true;
1032 ic->nicks.clear();
1033
1034 if(irhook.searchdest) {
1035 if(irhook.emailsub.empty() && irhook.namesub.empty()) {
1036 firetalk_chat_listmembers(irhook.handle, croom);
1037 if(!ic->joined) firetalk_chat_part(irhook.handle, croom);
1038 } else {
1039 firetalk_chat_requestextended(irhook.handle, croom);
1040 }
1041 }
1042 }
1043
1044 if(irhook.searchdest && irhook.emailsub.empty() && irhook.namesub.empty()) {
1045 for(is = irhook.searchchannels.begin(); is != irhook.searchchannels.end(); ++is) {
1046 ic = find(irhook.channels.begin(), irhook.channels.end(), *is);
1047
1048 if(ic != irhook.channels.end())
1049 if(!ic->fetched) {
1050 ready = false;
1051 break;
1052 }
1053 }
1054
1055 if(ready) {
1056 irhook.processnicks();
1057 }
1058 }
1059 }
1060
listextended(void * connection,void * cli,...)1061 void irchook::listextended(void *connection, void *cli, ...) {
1062 va_list ap;
1063 string text, email, name;
1064 vector<channelInfo>::iterator ir;
1065 vector<string>::iterator is;
1066 int npos;
1067
1068 va_start(ap, cli);
1069 char *nickname = va_arg(ap, char *);
1070 char *room = va_arg(ap, char *);
1071 char *login = va_arg(ap, char *);
1072 char *hostname = va_arg(ap, char *);
1073 char *net = va_arg(ap, char *);
1074 char *description = va_arg(ap, char *);
1075 va_end(ap);
1076
1077 ir = find(irhook.channels.begin(), irhook.channels.end(), room);
1078
1079 if(irhook.smode == Email) {
1080 ir = find(irhook.channels.begin(), irhook.channels.end(), "");
1081
1082 if(ir == irhook.channels.end()) {
1083 irhook.channels.push_back(channelInfo(""));
1084 ir = irhook.channels.end()-1;
1085 }
1086 }
1087
1088 if(ir != irhook.channels.end()) {
1089 name = description;
1090 if((npos = name.find(" ")) != -1)
1091 name.erase(0, npos+1);
1092
1093 email = (string) login + "@" + hostname;
1094
1095 if(irhook.emailsub.empty() || email.find(irhook.emailsub) != -1 || irhook.smode == Email) {
1096 if(irhook.namesub.empty() || name.find(irhook.namesub) != -1) {
1097 text = nickname;
1098
1099 if(!irhook.emailsub.empty()) {
1100 text += " <" + email + ">";
1101 } else if(!irhook.namesub.empty()) {
1102 text += " [" + name + "]";
1103 }
1104
1105 ir->nicks.push_back(text);
1106 }
1107 }
1108 }
1109
1110 if(find(irhook.extlisted.begin(), irhook.extlisted.end(), room) == irhook.extlisted.end())
1111 irhook.extlisted.push_back(room);
1112 }
1113
endextended(void * connection,void * cli,...)1114 void irchook::endextended(void *connection, void *cli, ...) {
1115 bool ready = true;
1116 vector<string>::iterator is;
1117 vector<channelInfo>::iterator ic;
1118
1119 if(irhook.smode == Channel && !irhook.extlisted.empty()) {
1120 ic = find(irhook.channels.begin(), irhook.channels.end(), irhook.extlisted.back());
1121
1122 if(ic != irhook.channels.end()) {
1123 if(!ic->joined)
1124 firetalk_chat_part(irhook.handle, irhook.extlisted.back().c_str());
1125
1126 for(is = irhook.searchchannels.begin(); ready && is != irhook.searchchannels.end(); ++is)
1127 ready = find(irhook.extlisted.begin(), irhook.extlisted.end(), *is) != irhook.extlisted.end();
1128 }
1129 }
1130
1131 ready = ready || irhook.smode == Email;
1132
1133 if(ready) {
1134 irhook.processnicks();
1135
1136 if(irhook.smode == Email) {
1137 ic = find(irhook.channels.begin(), irhook.channels.end(), "");
1138 if(ic != irhook.channels.end()) irhook.channels.erase(ic);
1139 }
1140 }
1141 }
1142
chatmessage(void * connection,void * cli,...)1143 void irchook::chatmessage(void *connection, void *cli, ...) {
1144 va_list ap;
1145 string imsg;
1146
1147 va_start(ap, cli);
1148 char *room = va_arg(ap, char *);
1149 char *from = va_arg(ap, char *);
1150 int automessage = va_arg(ap, int);
1151 char *msg = va_arg(ap, char *);
1152 va_end(ap);
1153
1154 if(clist.get(imcontact(room, irc))) {
1155 imsg = (string) from + ": " + msg;
1156 getmessage(connection, cli, room, automessage, imsg.c_str());
1157 }
1158 }
1159
chataction(void * connection,void * cli,...)1160 void irchook::chataction(void *connection, void *cli, ...) {
1161 va_list ap;
1162 string imsg;
1163
1164 va_start(ap, cli);
1165 char *room = va_arg(ap, char *);
1166 char *from = va_arg(ap, char *);
1167 int automessage = va_arg(ap, int);
1168 char *msg = va_arg(ap, char *);
1169 va_end(ap);
1170
1171 if(from && msg)
1172 if(strlen(from) && strlen(msg))
1173 if(clist.get(imcontact(room, irc))) {
1174 em.store(immessage(imcontact(room, irc), imevent::incoming,
1175 ((string) "* " + from + " " +
1176 irhook.rushtmlconv("wk", cuthtml(msg, chCutBR | chLeaveLinks))).c_str()));
1177 }
1178 }
1179
1180
chatjoined(void * connection,void * cli,...)1181 void irchook::chatjoined(void *connection, void *cli, ...) {
1182 va_list ap;
1183
1184 va_start(ap, cli);
1185 char *room = va_arg(ap, char *);
1186 va_end(ap);
1187
1188 icqcontact *c = clist.get(imcontact(room, irc));
1189 if(c) c->setstatus(available, false);
1190 }
1191
chatleft(void * connection,void * cli,...)1192 void irchook::chatleft(void *connection, void *cli, ...) {
1193 va_list ap;
1194
1195 va_start(ap, cli);
1196 char *room = va_arg(ap, char *);
1197 va_end(ap);
1198
1199 icqcontact *c = clist.get(imcontact(room, irc));
1200 if(c) c->setstatus(offline, false);
1201 }
1202
chatkicked(void * connection,void * cli,...)1203 void irchook::chatkicked(void *connection, void *cli, ...) {
1204 va_list ap;
1205
1206 va_start(ap, cli);
1207 char *room = va_arg(ap, char *);
1208 char *by = va_arg(ap, char *);
1209 char *reason = va_arg(ap, char *);
1210 va_end(ap);
1211
1212 irhook.channelfatal(room, _("Kicked by %s; reason: %s"),
1213 by, irhook.rushtmlconv("wk", reason).c_str());
1214 }
1215
errorhandler(void * connection,void * cli,...)1216 void irchook::errorhandler(void *connection, void *cli, ...) {
1217 va_list ap;
1218 icqcontact *c;
1219
1220 va_start(ap, cli);
1221 int error = va_arg(ap, int);
1222 char *subject = va_arg(ap, char *);
1223 char *description = va_arg(ap, char *);
1224 va_end(ap);
1225
1226 switch(error) {
1227 case FE_ROOMUNAVAILABLE:
1228 // Cannot join channel
1229 if(subject)
1230 if(strlen(subject))
1231 irhook.channelfatal(subject, "%s", description);
1232 break;
1233 case FE_BADUSER:
1234 // Cannot fetch user's info
1235 if(subject)
1236 if(strlen(subject))
1237 if(c = clist.get(imcontact(subject, irc)))
1238 c->setstatus(offline);
1239 break;
1240 }
1241 }
1242
nickchanged(void * connection,void * cli,...)1243 void irchook::nickchanged(void *connection, void *cli, ...) {
1244 va_list ap;
1245 icqcontact *c;
1246 char buf[NOTIFBUF];
1247
1248 va_start(ap, cli);
1249 char *oldnick = va_arg(ap, char *);
1250 char *newnick = va_arg(ap, char *);
1251 va_end(ap);
1252
1253 if(oldnick && newnick)
1254 if(strcmp(oldnick, newnick)) {
1255 if(c = clist.get(imcontact(oldnick, irc))) {
1256 if(!clist.get(imcontact(newnick, irc))) {
1257 if(!c->inlist()) {
1258 if(c->getdispnick() == oldnick) c->setdispnick(newnick);
1259 c->setdesc(imcontact(newnick, irc));
1260 c->setnick(newnick);
1261 }
1262
1263 } else {
1264 c->setstatus(offline);
1265
1266 }
1267
1268 snprintf(buf, NOTIFBUF, _("The user has changed their nick from %s to %s"), oldnick, newnick);
1269 em.store(imnotification(c, buf));
1270 }
1271 }
1272 }
1273
needpass(void * conn,void * cli,...)1274 void irchook::needpass(void *conn, void *cli, ...) {
1275 va_list ap;
1276
1277 va_start(ap, cli);
1278 char *pass = va_arg(ap, char *);
1279 int size = va_arg(ap, int);
1280 va_end(ap);
1281
1282 if(pass) {
1283 icqconf::imaccount acc = conf->getourid(irc);
1284
1285 if (size == 129) // signon password
1286 {
1287 if(!acc.password.empty()) {
1288 strncpy(pass, acc.password.c_str(), size-1);
1289 pass[size-1] = 0;
1290 face.log(_("+ [irc] password sent"));
1291 }
1292 }
1293 else // NickServ password
1294 {
1295 irhook.sentpass = true;
1296 if(!acc.additional["nickpass"].empty()) {
1297 strncpy(pass, acc.additional["nickpass"].c_str(), size-1);
1298 pass[size-1] = 0;
1299 face.log(_("+ [irc] nick password sent"));
1300 }
1301 }
1302 }
1303 }
1304
subrequest(void * conn,void * cli,const char * const nick,const char * const command,const char * const args)1305 void irchook::subrequest(void *conn, void *cli, const char * const nick,
1306 const char * const command, const char * const args) {
1307
1308 if(!strcmp(command, "VERSION")) {
1309 ostringstream args_stream;
1310 args_stream << PACKAGE << " " << centerim::version;
1311 firetalk_subcode_send_reply(conn, nick, "VERSION", args_stream.str().c_str());
1312 }
1313 }
1314
subreply(void * conn,void * cli,const char * const nick,const char * const command,const char * const args)1315 void irchook::subreply(void *conn, void *cli, const char * const nick,
1316 const char * const command, const char * const args) {
1317 char buf[NOTIFBUF];
1318
1319 if(!strcmp(command, "PING")) {
1320 map<string, time_t>::iterator i = irhook.pingtime.find(up(nick));
1321
1322 if(i != irhook.pingtime.end()) {
1323 snprintf(buf, NOTIFBUF, _("PING reply from the user: %d second(s)"), time(0)-i->second);
1324 em.store(imnotification(imcontact(nick, irc), buf));
1325 }
1326
1327 } else if(!strcmp(command, "VERSION")) {
1328 snprintf(buf, NOTIFBUF, _("The remote is using %s"), args);
1329 em.store(imnotification(imcontact(nick, irc), buf));
1330
1331 }
1332 }
1333
fileoffer(void * conn,void * cli,...)1334 void irchook::fileoffer(void *conn, void *cli, ...) {
1335 va_list ap;
1336
1337 va_start(ap, cli);
1338 void *filehandle = va_arg(ap, void *);
1339 char *from = va_arg(ap, char *);
1340 char *filename = va_arg(ap, char *);
1341 long size = va_arg(ap, long);
1342 va_end(ap);
1343
1344 imfile::record r;
1345 r.fname = filename;
1346 r.size = size;
1347
1348 imfile fr(imcontact(from, irc), imevent::incoming, "",
1349 vector<imfile::record>(1, r));
1350
1351 irhook.transferinfo[fr].first = filehandle;
1352 em.store(fr);
1353
1354 face.transferupdate(filename, fr, icqface::tsInit, size, 0);
1355 }
1356
filestart(void * conn,void * cli,...)1357 void irchook::filestart(void *conn, void *cli, ...) {
1358 va_list ap;
1359 imfile fr;
1360
1361 va_start(ap, cli);
1362 void *filehandle = va_arg(ap, void *);
1363 void *clientfilestruct = va_arg(ap, void *);
1364 va_end(ap);
1365
1366 if(irhook.getfevent(filehandle, fr)) {
1367 face.transferupdate(fr.getfiles().begin()->fname, fr,
1368 icqface::tsStart, 0, 0);
1369 }
1370 }
1371
fileprogress(void * conn,void * cli,...)1372 void irchook::fileprogress(void *conn, void *cli, ...) {
1373 va_list ap;
1374 imfile fr;
1375
1376 va_start(ap, cli);
1377 void *filehandle = va_arg(ap, void *);
1378 void *clientfilestruct = va_arg(ap, void *);
1379 long bytes = va_arg(ap, long);
1380 long size = va_arg(ap, long);
1381 va_end(ap);
1382
1383 if(irhook.getfevent(filehandle, fr)) {
1384 face.transferupdate(fr.getfiles().begin()->fname, fr,
1385 icqface::tsProgress, size, bytes);
1386 }
1387 }
1388
filefinish(void * conn,void * cli,...)1389 void irchook::filefinish(void *conn, void *cli, ...) {
1390 va_list ap;
1391 imfile fr;
1392
1393 va_start(ap, cli);
1394 void *filehandle = va_arg(ap, void *);
1395 void *clientfilestruct = va_arg(ap, void *);
1396 long size = va_arg(ap, long);
1397 va_end(ap);
1398
1399 if(irhook.getfevent(filehandle, fr)) {
1400 face.transferupdate(fr.getfiles().begin()->fname, fr,
1401 icqface::tsFinish, size, 0);
1402
1403 irhook.transferinfo.erase(fr);
1404 }
1405 }
1406
fileerror(void * conn,void * cli,...)1407 void irchook::fileerror(void *conn, void *cli, ...) {
1408 va_list ap;
1409 imfile fr;
1410
1411 va_start(ap, cli);
1412 void *filehandle = va_arg(ap, void *);
1413 void *clientfilestruct = va_arg(ap, void *);
1414 int error = va_arg(ap, int);
1415 va_end(ap);
1416
1417 if(irhook.getfevent(filehandle, fr)) {
1418 face.transferupdate(fr.getfiles().begin()->fname, fr,
1419 icqface::tsError, 0, 0);
1420
1421 irhook.transferinfo.erase(fr);
1422 }
1423 }
1424
chatuserjoined(void * conn,void * cli,...)1425 void irchook::chatuserjoined(void *conn, void *cli, ...) {
1426 va_list ap;
1427
1428 va_start(ap, cli);
1429 char *room = va_arg(ap, char *);
1430 char *who = va_arg(ap, char *);
1431 char *email = va_arg(ap, char *);
1432 va_end(ap);
1433
1434 if(conf->getourid(irc).nickname != who) {
1435 string uname = who;
1436
1437 if(email)
1438 if(strlen(email))
1439 uname += (string) " (" + email + ")";
1440
1441 char buf[NOTIFBUF];
1442 snprintf(buf, NOTIFBUF, _("%s has joined."), uname.c_str());
1443 em.store(imnotification(imcontact(room, irc), buf));
1444 }
1445 }
1446
chatuserleft(void * conn,void * cli,...)1447 void irchook::chatuserleft(void *conn, void *cli, ...) {
1448 va_list ap;
1449
1450 va_start(ap, cli);
1451 char *room = va_arg(ap, char *);
1452 char *who = va_arg(ap, char *);
1453 char *reason = va_arg(ap, char *);
1454 va_end(ap);
1455
1456 if(conf->getourid(irc).nickname != who) {
1457 string text;
1458 string text2;
1459 char buf[NOTIFBUF];
1460
1461 snprintf(buf, NOTIFBUF, _("%s has left"), who); text = buf;
1462
1463 if(reason)
1464 if(strlen(reason)) {
1465 if(strlen(reason) > 450) reason[450] = 0;
1466 text2 = irhook.rushtmlconv( "wk", reason );
1467 snprintf(buf, NOTIFBUF, _("reason: %s"), reason);
1468 text += (string) "; " + buf + ".";
1469 }
1470
1471 em.store(imnotification(imcontact(room, irc), text));
1472 }
1473 }
1474
chatuserkicked(void * conn,void * cli,...)1475 void irchook::chatuserkicked(void *conn, void *cli, ...) {
1476 va_list ap;
1477
1478 va_start(ap, cli);
1479 char *room = va_arg(ap, char *);
1480 char *who = va_arg(ap, char *);
1481 char *by = va_arg(ap, char *);
1482 char *reason = va_arg(ap, char *);
1483 va_end(ap);
1484
1485 if(conf->getourid(irc).nickname != who) {
1486 string text;
1487 char buf[NOTIFBUF];
1488
1489 snprintf(buf, NOTIFBUF, _("%s has been kicked by %s"), who, by); text = buf;
1490
1491 if(reason)
1492 if(strlen(reason)) {
1493 snprintf(buf, NOTIFBUF, _("reason: %s"), reason);
1494 text += (string) "; " + buf + ".";
1495 }
1496
1497 em.store(imnotification(imcontact(room, irc), text));
1498 }
1499 }
1500
chatgottopic(void * conn,void * cli,...)1501 void irchook::chatgottopic(void *conn, void *cli, ...) {
1502 va_list ap;
1503
1504 va_start(ap, cli);
1505 char *room = va_arg(ap, char *);
1506 char *topic = va_arg(ap, char *);
1507 char *author = va_arg(ap, char *);
1508 va_end(ap);
1509
1510 vector<channelInfo>::const_iterator ic = find(irhook.channels.begin(), irhook.channels.end(), room);
1511
1512 if(ic == irhook.channels.end() || !ic->joined)
1513 return;
1514
1515 string text;
1516 char buf[NOTIFBUF];
1517 text = irhook.rushtmlconv( "wk", topic );
1518 snprintf(buf, NOTIFBUF, _("Channel topic now is: %s"), text.c_str());
1519 text = buf;
1520
1521 if(author)
1522 if(strlen(author)) {
1523 snprintf(buf, NOTIFBUF, _("set by %s"), author);
1524 text += (string) "; " + buf + ".";
1525 }
1526
1527 em.store(imnotification(imcontact(room, irc), text));
1528 }
1529
chatuseropped(void * conn,void * cli,...)1530 void irchook::chatuseropped(void *conn, void *cli, ...) {
1531 va_list ap;
1532
1533 va_start(ap, cli);
1534 char *room = va_arg(ap, char *);
1535 char *who = va_arg(ap, char *);
1536 char *by = va_arg(ap, char *);
1537 va_end(ap);
1538
1539 if(by) {
1540 char buf[NOTIFBUF];
1541 snprintf(buf, NOTIFBUF, _("%s has been opped by %s."), who, by);
1542 em.store(imnotification(imcontact(room, irc), buf));
1543 }
1544 }
1545
chatuserdeopped(void * conn,void * cli,...)1546 void irchook::chatuserdeopped(void *conn, void *cli, ...) {
1547 va_list ap;
1548
1549 va_start(ap, cli);
1550 char *room = va_arg(ap, char *);
1551 char *who = va_arg(ap, char *);
1552 char *by = va_arg(ap, char *);
1553 va_end(ap);
1554
1555 if(by) {
1556 char buf[NOTIFBUF];
1557 snprintf(buf, NOTIFBUF, _("%s has been deopped by %s."), who, by);
1558 em.store(imnotification(imcontact(room, irc), buf));
1559 }
1560 }
1561
chatopped(void * conn,void * cli,...)1562 void irchook::chatopped(void *conn, void *cli, ...) {
1563 va_list ap;
1564
1565 va_start(ap, cli);
1566 char *room = va_arg(ap, char *);
1567 char *by = va_arg(ap, char *);
1568 va_end(ap);
1569
1570 char buf[NOTIFBUF];
1571 if(by) snprintf(buf, NOTIFBUF, _("%s has opped us."), by);
1572 else snprintf(buf, NOTIFBUF, _("you are an op here"));
1573 em.store(imnotification(imcontact(room, irc), buf));
1574 }
1575
chatdeopped(void * conn,void * cli,...)1576 void irchook::chatdeopped(void *conn, void *cli, ...) {
1577 va_list ap;
1578
1579 va_start(ap, cli);
1580 char *room = va_arg(ap, char *);
1581 char *by = va_arg(ap, char *);
1582 va_end(ap);
1583
1584 char buf[NOTIFBUF];
1585 snprintf(buf, NOTIFBUF, _("%s has deopped us."), by);
1586 em.store(imnotification(imcontact(room, irc), buf));
1587 }
1588
1589 // ----------------------------------------------------------------------------
1590
operator !=(const string & aname) const1591 bool irchook::channelInfo::operator != (const string &aname) const {
1592 return up(aname) != up(name);
1593 }
1594
operator ==(const string & aname) const1595 bool irchook::channelInfo::operator == (const string &aname) const {
1596 return up(aname) == up(name);
1597 }
1598
1599 #endif
1600