3 * centerim icq protocol handling class
4 * $Id: icqhook.cc,v 1.159 2004/12/20 00:54:02 konst Exp $
6 * Copyright (C) 2001-2004 by Konstantin Klyagin <k@thekonst.net>
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.
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.
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
25 #include "icqcommon.h"
33 #include "icqgroups.h"
34 #include "icqcontacts.h"
37 #include "accountmanager.h"
38 #include "eventmanager.h"
40 #include "src/Capabilities.h"
42 #define PERIOD_ICQPOLL 5
43 #define PERIOD_RESOLVE 10
44 #define DELAY_SENDNEW 5
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
51 static const Status stat2int
[imstatus_size
] = {
54 STATUS_ONLINE
, /* invisible */
63 icqhook::icqhook(): abstracthook(icq
) {
67 fcapabs
.insert(hookcapab::urls
);
68 fcapabs
.insert(hookcapab::setaway
);
69 fcapabs
.insert(hookcapab::fetchaway
);
70 fcapabs
.insert(hookcapab::changenick
);
71 // fcapabs.insert(hookcapab::changepassword);
72 fcapabs
.insert(hookcapab::changedetails
);
73 fcapabs
.insert(hookcapab::authrequests
);
74 fcapabs
.insert(hookcapab::authreqwithmessages
);
75 fcapabs
.insert(hookcapab::contacts
);
76 fcapabs
.insert(hookcapab::visibility
);
77 fcapabs
.insert(hookcapab::cltemporary
);
78 fcapabs
.insert(hookcapab::changeabout
);
81 fcapabs
.insert(hookcapab::pgp
);
84 cli
.connected
.connect(this, &icqhook::connected_cb
);
85 cli
.disconnected
.connect(this, &icqhook::disconnected_cb
);
86 cli
.socket
.connect(this, &icqhook::socket_cb
);
87 cli
.messaged
.connect(this, &icqhook::messaged_cb
);
88 cli
.messageack
.connect(this, &icqhook::messageack_cb
);
89 cli
.contactlist
.connect(this, &icqhook::contactlist_cb
);
90 cli
.contact_userinfo_change_signal
.connect(this, &icqhook::contact_userinfo_change_signal_cb
);
91 cli
.contact_status_change_signal
.connect(this, &icqhook::contact_status_change_signal_cb
);
92 cli
.contact_typing_signal
.connect(this, &icqhook::contact_typing_signal_cb
);
93 cli
.newuin
.connect(this, &icqhook::newuin_cb
);
94 cli
.rate
.connect(this, &icqhook::rate_cb
);
95 // cli.password_changed.connect(this, &icqhook::password_changed_cb);
96 cli
.want_auto_resp
.connect(this, &icqhook::want_auto_resp_cb
);
97 cli
.search_result
.connect(this, &icqhook::search_result_cb
);
98 cli
.self_contact_userinfo_change_signal
.connect(this, &icqhook::self_contact_userinfo_change_cb
);
99 cli
.self_contact_status_change_signal
.connect(this, &icqhook::self_contact_status_change_cb
);
100 cli
.sbl_received
.connect(this, &icqhook::sbl_received_cb
);
103 icqhook::~icqhook() {
104 cli
.logger
.disconnect(this);
105 cli
.connected
.disconnect(this);
106 cli
.disconnected
.disconnect(this);
107 cli
.socket
.disconnect(this);
108 cli
.messaged
.disconnect(this);
109 cli
.messageack
.disconnect(this);
110 cli
.contactlist
.disconnect(this);
111 cli
.contact_userinfo_change_signal
.disconnect(this);
112 cli
.contact_status_change_signal
.disconnect(this);
113 cli
.newuin
.disconnect(this);
114 cli
.rate
.disconnect(this);
115 cli
.search_result
.disconnect(this);
116 cli
.want_auto_resp
.disconnect(this);
117 cli
.self_contact_userinfo_change_signal
.disconnect(this);
118 cli
.self_contact_status_change_signal
.disconnect(this);
119 // cli.password_changed.disconnect(this);
122 void icqhook::init() {
123 manualstatus
= conf
->getstatus(proto
);
126 cli
.logger
.connect(this, &icqhook::logger_cb
);
129 void icqhook::connect() {
130 icqconf::imaccount acc
= conf
->getourid(proto
);
131 int i
, ptpmin
, ptpmax
;
134 if(acc
.additional
["webaware"].empty()) acc
.additional
["webaware"] = "1";
137 if(!acc
.server
.empty()) cli
.setLoginServerHost(acc
.server
);
138 if(acc
.port
) cli
.setLoginServerPort(acc
.port
);
140 if(!conf
->getsmtphost().empty()) cli
.setSMTPServerHost(conf
->getsmtphost());
141 if(conf
->getsmtpport()) cli
.setSMTPServerPort(conf
->getsmtpport());
143 if(!conf
->getbindhost().empty()) cli
.setClientBindHost(conf
->getbindhost());
145 conf
->getpeertopeer(ptpmin
, ptpmax
);
147 cli
.setAcceptInDC(true);
148 cli
.setPortRangeLowerBound(ptpmin
);
149 cli
.setPortRangeUpperBound(ptpmax
);
150 cli
.setUsePortRange(true);
152 cli
.setAcceptInDC(false);
157 cli
.self_contact_userinfo_change_signal
.disconnect(this);
160 cli
.setPassword(acc
.password
);
161 cli
.setWebAware(acc
.additional
["webaware"] == "1");
163 cli
.setStatus(stat2int
[manualstatus
], manualstatus
== invisible
);
164 cli
.self_contact_userinfo_change_signal
.connect(this, &icqhook::self_contact_userinfo_change_cb
);
166 for(i
= 0; i
< clist
.count
; i
++) {
167 c
= (icqcontact
*) clist
.at(i
);
169 if(c
->getdesc().pname
== proto
&& c
->getdesc().uin
) {
170 icqcontact::basicinfo bi
= c
->getbasicinfo();
174 addContact(c
->getdesc().uin
, groups
.getname(c
->getgroupid()));
184 void icqhook::disconnect() {
185 cli
.setStatus(STATUS_OFFLINE
);
186 fonline
= flogged
= false;
189 void icqhook::resolve() {
191 vector
<icqcontact
*> toresolve
;
193 for(int i
= 0; i
< clist
.count
; i
++) {
194 c
= (icqcontact
*) clist
.at(i
);
196 if(c
->getdesc().pname
== proto
)
197 if(c
->getdispnick() == i2str(c
->getdesc().uin
))
198 toresolve
.push_back(c
);
201 if(toresolve
.size()) {
202 c
= toresolve
[randlimit(0, toresolve
.size()-1)];
207 void icqhook::sendinvisible() {
208 vector
<visInfo
> todo
, nvislist
;
209 vector
<visInfo
>::iterator iv
, it
;
212 for(i
= lst
.begin(); i
!= lst
.end(); ++i
) {
213 if(i
->getdesc().pname
== proto
) {
214 switch(i
->getstatus()) {
217 todo
.push_back(pair
<unsigned int, contactstatus
>
218 (i
->getdesc().uin
, i
->getstatus()));
226 for(iv
= vislist
.begin(); iv
!= vislist
.end(); ++iv
) {
227 it
= find(todo
.begin(), todo
.end(), *iv
);
229 if(it
!= todo
.end()) {
233 case csvisible
: cli
.removeVisible(iv
->first
); break;
234 case csinvisible
: cli
.removeInvisible(iv
->first
); break;
239 for(it
= todo
.begin(); it
!= todo
.end(); ++it
) {
241 case csvisible
: cli
.addVisible(new Contact(it
->first
)); break;
242 case csinvisible
: cli
.addInvisible(new Contact(it
->first
)); break;
249 void icqhook::exectimers() {
251 if(timer_current
-timer_poll
> PERIOD_ICQPOLL
) {
254 timer_poll
= timer_current
;
258 * Will to the mass-adding stuff here too..
262 vector
<imcontact
>::iterator ic
= uinstosend
.begin();
264 if(ic
!= uinstosend
.end()) {
266 uinstosend
.erase(ic
);
268 ContactRef icont
= cli
.getContact(imc
.uin
);
269 if(!icont
.get()) sendnewuser(imc
);
273 if(timer_current
-timer_resolve
> PERIOD_RESOLVE
) {
275 timer_resolve
= timer_current
;
280 void icqhook::main() {
281 vector
<int>::iterator i
;
290 tv
.tv_sec
= tv
.tv_usec
= 0;
293 for(i
= rfds
.begin(); i
!= rfds
.end(); ++i
) {
295 hsock
= max(hsock
, *i
);
298 for(i
= wfds
.begin(); i
!= wfds
.end(); ++i
) {
300 hsock
= max(hsock
, *i
);
303 for(i
= efds
.begin(); i
!= efds
.end(); ++i
) {
305 hsock
= max(hsock
, *i
);
308 if(select(hsock
+1, &rs
, &ws
, &es
, &tv
) > 0) {
309 for(i
= rfds
.begin(); i
!= rfds
.end(); ++i
) {
310 if(FD_ISSET(*i
, &rs
)) {
311 cli
.socket_cb(*i
, SocketEvent::READ
);
316 for(i
= wfds
.begin(); i
!= wfds
.end(); ++i
) {
317 if(FD_ISSET(*i
, &ws
)) {
318 cli
.socket_cb(*i
, SocketEvent::WRITE
);
323 for(i
= efds
.begin(); i
!= efds
.end(); ++i
) {
324 if(FD_ISSET(*i
, &es
)) {
325 cli
.socket_cb(*i
, SocketEvent::EXCEPTION
);
332 void icqhook::getsockets(fd_set
&rs
, fd_set
&ws
, fd_set
&es
, int &hsocket
) const {
333 vector
<int>::const_iterator i
;
335 for(i
= rfds
.begin(); i
!= rfds
.end(); ++i
) {
336 hsocket
= max(hsocket
, *i
);
340 for(i
= wfds
.begin(); i
!= wfds
.end(); ++i
) {
341 hsocket
= max(hsocket
, *i
);
345 for(i
= efds
.begin(); i
!= efds
.end(); ++i
) {
346 hsocket
= max(hsocket
, *i
);
351 bool icqhook::isoursocket(fd_set
&rs
, fd_set
&ws
, fd_set
&es
) const {
352 vector
<int>::const_iterator i
;
354 for(i
= rfds
.begin(); i
!= rfds
.end(); ++i
)
355 if(FD_ISSET(*i
, &rs
))
358 for(i
= wfds
.begin(); i
!= wfds
.end(); ++i
)
359 if(FD_ISSET(*i
, &ws
))
362 for(i
= efds
.begin(); i
!= efds
.end(); ++i
)
363 if(FD_ISSET(*i
, &es
))
369 bool icqhook::online() const {
373 bool icqhook::logged() const {
374 return fonline
&& flogged
;
377 bool icqhook::isconnecting() const {
378 return fonline
&& !flogged
;
381 bool icqhook::enabled() const {
385 bool icqhook::send(const imevent
&ev
) {
386 unsigned int uin
= ev
.getcontact().uin
;
387 ContactRef ic
= cli
.getContact(uin
);
388 MessageEvent
*sev
= 0;
389 ICQMessageEvent
*iev
;
390 icqcontact
*c
=clist
.get(ev
.getcontact());
392 if(ev
.getcontact().pname
!= proto
)
396 ic
= cli
.getSelfContact();
401 if(ev
.gettype() == imevent::message
) {
402 const immessage
*m
= static_cast<const immessage
*> (&ev
);
403 string text
= m
->gettext(), sub
;
406 if ( (c
!=NULL
) && (pgp
.enabled(ev
.getcontact())) ) {
407 text
= pgp
.encrypt(text
, c
->getpgpkey(), proto
);
408 text
= "-----BEGIN PGP MESSAGE-----\n\n" + text
+ "\n-----END PGP MESSAGE-----\n";
412 if(ic
->getStatus() == STATUS_OFFLINE
)
413 if(text
.size() > 450) {
414 while(!text
.empty()) {
415 if(text
.size() > 450) {
416 sub
= text
.substr(0, 450);
423 cli
.SendEvent(new NormalMessageEvent(ic
, ruscrlfconv("kw", sub
)));
429 sev
= new NormalMessageEvent(ic
, ruscrlfconv("kw", text
));
431 } else if(ev
.gettype() == imevent::url
) {
432 const imurl
*m
= static_cast<const imurl
*> (&ev
);
433 sev
= new URLMessageEvent(ic
,
434 ruscrlfconv("kw", m
->getdescription()),
435 ruscrlfconv("kw", m
->geturl()));
437 } else if(ev
.gettype() == imevent::sms
) {
438 const imsms
*m
= static_cast<const imsms
*> (&ev
);
441 if(m
->getphone().empty()) {
442 if(ic
->getMainHomeInfo().getMobileNo().empty()) {
443 cli
.fetchSelfDetailContactInfo();
447 ic
= new Contact(m
->getphone());
448 ic
->setMobileNo(m
->getphone());
450 ContactTree
&ct
= cli
.getContactTree();
451 ContactTree::Group
&g
= ct
.group_size() ? *ct
.begin() : ct
.add_group("New");
456 cli
.contact_userinfo_change_signal
.disconnect(this);
457 ic
->setMobileNo(clist
.get(ev
.getcontact())->getbasicinfo().cellular
);
458 cli
.contact_userinfo_change_signal
.connect(this, &icqhook::contact_userinfo_change_signal_cb
);
461 sev
= new SMSMessageEvent(ic
, rusconv("ku", m
->getmessage()), true);
463 } else if(ev
.gettype() == imevent::authorization
) {
464 const imauthorization
*m
= static_cast<const imauthorization
*> (&ev
);
466 switch(m
->getauthtype()) {
467 case imauthorization::Granted
:
468 case imauthorization::Rejected
:
469 sev
= new AuthAckEvent(ic
, ruscrlfconv("kw", m
->getmessage()),
470 m
->getauthtype() == imauthorization::Granted
);
473 case imauthorization::Request
:
474 sev
= new AuthReqEvent(ic
, ruscrlfconv("kw", m
->getmessage()));
476 icqcontact::basicinfo bi
= c
->getbasicinfo();
483 } else if(ev
.gettype() == imevent::contacts
) {
484 const imcontacts
*m
= static_cast<const imcontacts
*> (&ev
);
485 vector
< pair
<unsigned int, string
> >::const_iterator icc
;
486 list
<ContactRef
> slst
;
488 for(icc
= m
->getcontacts().begin(); icc
!= m
->getcontacts().end(); ++icc
) {
489 ContactRef
ct(new Contact(icc
->first
));
490 ct
->setAlias(ruscrlfconv("kw", icc
->second
));
494 sev
= new ContactMessageEvent(ic
, slst
);
501 if(ic
->getStatus() == STATUS_DND
|| ic
->getStatus() == STATUS_OCCUPIED
)
502 if(iev
= dynamic_cast<ICQMessageEvent
*>(sev
))
503 iev
->setUrgent(true);
511 void icqhook::sendnewuser(const imcontact
&ic
) {
512 static time_t lastadd
= 0;
513 icqcontact
*cc
= clist
.get(ic
);
515 if(logged() && ic
.uin
&& cc
) {
516 if(timer_current
-lastadd
> DELAY_SENDNEW
) {
517 ContactRef cont
= addContact(ic
.uin
, groups
.getname(cc
->getgroupid()));
518 cli
.fetchSimpleContactInfo(cont
);
519 cli
.fetchDetailContactInfo(cont
);
521 if(sblrecv
&& cc
->inlist()) {
522 ContactTree::Group
&g
= cli
.getContactTree().lookup_group_containing_contact(cont
);
524 cont
->setServerSideInfo(g
.get_id(), 0);
525 cont
->setServerBased(true);
526 cont
->setAuthAwait(cc
->getbasicinfo().authawait
);
528 //cli.uploadServerBasedContact(cont);
531 lastadd
= timer_current
;
534 uinstosend
.push_back(ic
);
540 void icqhook::removeuser(const imcontact
&c
) {
541 ContactRef ic
= cli
.getContact(c
.uin
);
544 icqcontact
*cc
= clist
.get(c
);
548 if(ic
->getServerBased()) {
549 ic
->setAlias(cc
->getnick());
550 ic
->setAuthAwait(cc
->getbasicinfo().authawait
);
551 //cli.removeServerBasedContact(ic);
555 ContactTree
& ct
= cli
.getContactTree();
556 ContactTree::Group
&gr
= ct
.lookup_group_containing_contact(ic
);
561 void icqhook::setautostatus(imstatus st
) {
563 if(getstatus() == offline
) {
567 logger
.putourstatus(icq
, getstatus(), st
);
568 cli
.setStatus(stat2int
[st
], st
== invisible
);
571 if(getstatus() != offline
) {
577 imstatus
icqhook::getstatus() const {
580 } else if(cli
.getInvisible()) {
583 return icq2imstatus(cli
.getStatus());
587 bool icqhook::regconnect(const string
&aserv
) {
590 if((pos
= aserv
.find(":")) != -1) {
591 cli
.setLoginServerHost(aserv
.substr(0, pos
));
592 cli
.setLoginServerPort(strtoul(aserv
.substr(pos
+1).c_str(), 0, 0));
598 bool icqhook::regattempt(unsigned int &auin
, const string
&apassword
, const string
&email
) {
599 fd_set srfds
, swfds
, sefds
;
602 time_t regtimeout
= time(0);
606 cli
.setPassword(apassword
);
609 while(!reguin
&& (time(0)-regtimeout
< 60)) {
616 getsockets(srfds
, swfds
, sefds
, hsockfd
);
621 select(hsockfd
+1, &srfds
, &swfds
, &sefds
, &tv
);
623 if(isoursocket(srfds
, swfds
, sefds
)) {
629 return (bool) reguin
;
632 imstatus
icqhook::icq2imstatus(const Status st
) const {
638 case STATUS_OCCUPIED
:
642 case STATUS_FREEFORCHAT
:
652 void icqhook::requestinfo(const imcontact
&c
) {
653 if(logged() && c
.uin
) {
654 if(c
== imcontact(conf
->getourid(icq
).uin
, icq
)) {
655 // Our info is requested
656 cli
.fetchSelfDetailContactInfo();
658 ContactRef icont
= cli
.getContact(c
.uin
);
661 addContact(c
.uin
, "");
663 cli
.fetchSimpleContactInfo(icont
);
664 cli
.fetchDetailContactInfo(icont
);
670 void icqhook::lookup(const imsearchparams
¶ms
, verticalmenu
&dest
) {
673 while(!foundguys
.empty()) {
674 delete foundguys
.back();
675 foundguys
.pop_back();
680 sex
= params
.gender
== genderMale
? ICQ2000::SEX_MALE
:
681 params
.gender
== genderFemale
? ICQ2000::SEX_FEMALE
:
682 ICQ2000::SEX_UNKNOWN
;
685 searchevent
= cli
.searchForContacts(params
.uin
);
687 } else if(!params
.kwords
.empty()) {
688 searchevent
= cli
.searchForContacts(rusconv("kw", params
.kwords
));
690 } else if(params
.randomgroup
) {
691 searchevent
= cli
.searchForContacts((ICQ2000::RandomChatGroup
) params
.randomgroup
);
693 } else if(!params
.email
.empty() || params
.minage
|| params
.maxage
||
694 !params
.city
.empty() || !params
.state
.empty() ||
695 !params
.company
.empty() || !params
.department
.empty() ||
696 !params
.position
.empty() || params
.onlineonly
||
697 params
.country
|| params
.language
||
698 (sex
!= SEX_UNKNOWN
) || (params
.agerange
!= RANGE_NORANGE
)) {
699 searchevent
= cli
.searchForContacts(rusconv("kw", params
.nick
),
700 rusconv("kw", params
.firstname
), rusconv("kw", params
.lastname
),
701 rusconv("kw", params
.email
), params
.agerange
, sex
,
702 params
.language
, rusconv("kw", params
.city
),
703 rusconv("kw", params
.state
), params
.country
,
704 rusconv("kw", params
.company
), rusconv("kw", params
.department
),
705 rusconv("kw", params
.position
), params
.onlineonly
);
708 searchevent
= cli
.searchForContacts(rusconv("kw", params
.nick
),
709 rusconv("kw", params
.firstname
), rusconv("kw", params
.lastname
));
714 void icqhook::sendupdateuserinfo(const icqcontact
&c
) {
715 ContactRef ic
= cli
.getSelfContact();
717 cli
.self_contact_userinfo_change_signal
.disconnect(this);
719 Contact::MainHomeInfo
&home
= ic
->getMainHomeInfo();
720 Contact::HomepageInfo
&hpage
= ic
->getHomepageInfo();
721 Contact::WorkInfo
&work
= ic
->getWorkInfo();
723 const icqcontact::basicinfo
&cbinfo
= c
.getbasicinfo();
724 const icqcontact::moreinfo
&cminfo
= c
.getmoreinfo();
725 const icqcontact::workinfo
&cwinfo
= c
.getworkinfo();
727 /* basic information */
729 ic
->setAlias(rusconv("kw", c
.getnick()));
730 ic
->setFirstName(rusconv("kw", cbinfo
.fname
));
731 ic
->setLastName(rusconv("kw", cbinfo
.lname
));
732 ic
->setEmail(rusconv("kw", cbinfo
.email
));
733 ic
->setAuthReq(cbinfo
.requiresauth
);
735 ic
->setAboutInfo(rusconv("kw", c
.getabout()));
737 home
.city
= rusconv("kw", cbinfo
.city
);
738 home
.state
= rusconv("kw", cbinfo
.state
);
739 home
.phone
= rusconv("kw", cbinfo
.phone
);
740 home
.fax
= rusconv("kw", cbinfo
.fax
);
741 home
.street
= rusconv("kw", cbinfo
.street
);
742 home
.setMobileNo(rusconv("kw", cbinfo
.cellular
));
744 home
.zip
= cbinfo
.zip
;
745 home
.country
= (Country
) cbinfo
.country
;
746 home
.timezone
= (Timezone
) getSystemTimezone();
748 /* more information */
750 hpage
.age
= cminfo
.age
;
753 cminfo
.gender
== genderFemale
? SEX_FEMALE
:
754 cminfo
.gender
== genderMale
? SEX_MALE
:
757 hpage
.homepage
= rusconv("kw", cminfo
.homepage
);
758 hpage
.birth_day
= cminfo
.birth_day
;
759 hpage
.birth_month
= cminfo
.birth_month
;
760 hpage
.birth_year
= cminfo
.birth_year
;
762 hpage
.lang1
= (Language
) cminfo
.lang1
;
763 hpage
.lang2
= (Language
) cminfo
.lang2
;
764 hpage
.lang3
= (Language
) cminfo
.lang3
;
766 /* work information */
768 work
.city
= rusconv("kw", cwinfo
.city
);
769 work
.state
= rusconv("kw", cwinfo
.state
);
770 work
.street
= rusconv("kw", cwinfo
.street
);
771 work
.company_name
= rusconv("kw", cwinfo
.company
);
772 work
.company_dept
= rusconv("kw", cwinfo
.dept
);
773 work
.company_position
= rusconv("kw", cwinfo
.position
);
774 work
.company_web
= rusconv("kw", cwinfo
.homepage
);
776 work
.zip
= cwinfo
.zip
;
777 work
.country
= cwinfo
.country
;
779 ic
->setMainHomeInfo(home
);
780 ic
->setHomepageInfo(hpage
);
781 ic
->setWorkInfo(work
);
782 ic
->setAuthReq(cbinfo
.requiresauth
);
784 icqconf::imaccount acc
= conf
->getourid(icq
);
785 acc
.additional
["webaware"] = cbinfo
.webaware
? "1" : "0";
786 acc
.additional
["randomgroup"] = i2str(cbinfo
.randomgroup
);
789 cli
.setWebAware(cbinfo
.webaware
);
790 cli
.setRandomChatGroup(cbinfo
.randomgroup
);
792 cli
.uploadSelfDetails();
793 cli
.self_contact_userinfo_change_signal
.connect(this, &icqhook::self_contact_userinfo_change_cb
);
795 if(!c.getreginfo().password.empty())
796 cli.changePassword(c.getreginfo().password);*/
799 void icqhook::requestawaymsg(const imcontact
&c
) {
800 ContactRef ic
= cli
.getContact(c
.uin
);
803 cli
.SendEvent(new AwayMessageEvent(ic
));
807 void icqhook::updateinforecord(ContactRef ic
, icqcontact
*c
) {
809 vector
<string
> pintinfo
, backginfo
;
810 list
<Contact::PersonalInterestInfo::Interest
>::iterator ii
;
811 list
<Contact::BackgroundInfo::School
>::iterator isc
;
812 icqcontact::basicinfo cbinfo
;
813 icqcontact::moreinfo cminfo
;
814 icqcontact::workinfo cwinfo
;
817 Contact::MainHomeInfo
&home
= ic
->getMainHomeInfo();
818 Contact::HomepageInfo
&hpage
= ic
->getHomepageInfo();
819 Contact::WorkInfo
&work
= ic
->getWorkInfo();
820 Contact::PersonalInterestInfo
&pint
= ic
->getPersonalInterestInfo();
821 Contact::BackgroundInfo
&backg
= ic
->getBackgroundInfo();
822 Contact::EmailInfo
&email
= ic
->getEmailInfo();
824 cbinfo
= c
->getbasicinfo();
825 cminfo
= c
->getmoreinfo();
826 cwinfo
= c
->getworkinfo();
828 /* basic information */
830 cbinfo
.fname
= rusconv("wk", ic
->getFirstName());
831 cbinfo
.lname
= rusconv("wk", ic
->getLastName());
832 if(!ic
->getEmail().empty()) cbinfo
.email
= rusconv("wk", ic
->getEmail());
833 cbinfo
.city
= rusconv("wk", home
.city
);
834 cbinfo
.state
= rusconv("wk", home
.state
);
835 cbinfo
.phone
= rusconv("wk", home
.phone
);
836 cbinfo
.fax
= rusconv("wk", home
.fax
);
837 cbinfo
.street
= rusconv("wk", home
.street
);
838 cbinfo
.requiresauth
= ic
->getAuthReq();
840 if(!home
.getMobileNo().empty())
841 cbinfo
.cellular
= rusconv("wk", home
.getMobileNo());
843 cbinfo
.zip
= home
.zip
;
844 cbinfo
.country
= home
.country
;
846 /* more information */
848 cminfo
.age
= hpage
.age
;
851 hpage
.sex
== 1 ? genderFemale
:
852 hpage
.sex
== 2 ? genderMale
:
855 cminfo
.homepage
= rusconv("wk", hpage
.homepage
);
856 cminfo
.birth_day
= hpage
.birth_day
;
857 cminfo
.birth_month
= hpage
.birth_month
;
858 cminfo
.birth_year
= hpage
.birth_year
;
860 cminfo
.lang1
= hpage
.lang1
;
861 cminfo
.lang2
= hpage
.lang2
;
862 cminfo
.lang3
= hpage
.lang3
;
864 cminfo
.timezone
= home
.timezone
;
866 /* work information */
868 cwinfo
.city
= rusconv("wk", work
.city
);
869 cwinfo
.state
= rusconv("wk", work
.state
);
870 cwinfo
.street
= rusconv("wk", work
.street
);
871 cwinfo
.company
= rusconv("wk", work
.company_name
);
872 cwinfo
.dept
= rusconv("wk", work
.company_dept
);
873 cwinfo
.position
= rusconv("wk", work
.company_position
);
874 cwinfo
.homepage
= rusconv("wk", work
.company_web
);
876 cwinfo
.zip
= work
.zip
;
877 cwinfo
.country
= work
.country
;
879 /* personal interests */
881 for(ii
= pint
.interests
.begin(); ii
!= pint
.interests
.end(); ++ii
) {
882 sbuf
= getInterestsIDtoString(ii
->first
);
884 if(!ii
->second
.empty()) {
885 if(!sbuf
.empty()) sbuf
+= ": ";
886 sbuf
+= rusconv("wk", ii
->second
);
889 if(!sbuf
.empty()) pintinfo
.push_back(sbuf
);
892 /* education background */
894 for(isc
= backg
.schools
.begin(); isc
!= backg
.schools
.end(); ++isc
) {
895 sbuf
= getBackgroundIDtoString(isc
->first
);
896 if(!sbuf
.empty()) sbuf
+= ": ";
897 sbuf
+= rusconv("wk", isc
->second
);
898 if(!sbuf
.empty()) backginfo
.push_back(sbuf
);
901 /* nicknames stuff */
903 string nick
= rusconv("wk", ic
->getAlias());
905 if((c
->getnick() == c
->getdispnick())
906 || (c
->getdispnick() == i2str(c
->getdesc().uin
))) {
907 c
->setdispnick(nick
);
911 c
->setbasicinfo(cbinfo
);
912 c
->setmoreinfo(cminfo
);
913 c
->setworkinfo(cwinfo
);
914 c
->setinterests(pintinfo
);
915 c
->setbackground(backginfo
);
916 c
->setabout(rusconv("wk", ic
->getAboutInfo()));
918 face
.relaxedupdate();
922 void icqhook::processemailevent(const string
&sender
, const string
&email
, const string
&message
) {
923 if(email
.empty() && sender
.empty() && message
.empty())
926 icqcontact
*c
= clist
.getemail(email
);
929 if(c
= clist
.addnew(imcontact(0, infocard
), true)) {
930 c
->setdispnick(email
);
933 icqcontact::basicinfo b
= c
->getbasicinfo();
935 if(sender
!= email
) {
936 int pos
= sender
.find(" ");
939 b
.fname
= sender
.substr(0, pos
);
940 b
.lname
= sender
.substr(pos
+1);
951 em
.store(imemail(c
, imevent::incoming
,
952 rusconv("wk", message
)));
956 void icqhook::updatecontact(icqcontact
*c
) {
958 ContactTree
&tree
= cli
.getContactTree();
959 ContactRef ic
= tree
[c
->getdesc().uin
];
962 string gname
= groups
.getname(c
->getgroupid());
963 ContactTree::Group
&oldg
= tree
.lookup_group_containing_contact(ic
);
964 ContactTree::Group
*newg
= 0;
966 if(oldg
.get_label() != gname
) {
967 ContactTree::iterator curr
= tree
.begin();
968 while(curr
!= tree
.end()) {
969 if((*curr
).get_label() == gname
) {
976 //cli.removeServerBasedContact(ic);
978 if(!newg
) newg
= &(tree
.add_group(gname
));
979 tree
.relocate_contact(ic
, oldg
, *newg
);
981 ic
->setServerSideInfo(newg
->get_id(), ic
->getServerSideID());
982 ic
->setAuthAwait(c
->getbasicinfo().authawait
);
984 //cli.uploadServerBasedContact(ic);
990 void icqhook::renamegroup(const string
&oldname
, const string
&newname
) {
993 ContactTree::Group *gp = 0;
994 ContactTree &ct = cli.getContactTree();
996 ContactTree::iterator curr = ct.begin();
997 while(curr != ct.end()) {
998 if((*curr).get_label() == oldname) {
1006 gp->set_label(newname);
1007 cli.uploadServerBasedGroup(*gp);
1013 // ----------------------------------------------------------------------------
1015 void icqhook::connected_cb(ConnectedEvent
*ev
) {
1018 timer_poll
= timer_current
;
1019 timer_resolve
= timer_poll
-PERIOD_RESOLVE
+3;
1021 logger
.putourstatus(icq
, offline
, manualstatus
);
1023 cli
.setRandomChatGroup(strtoul(conf
->getourid(icq
).additional
["randomgroup"].c_str(), 0, 0));
1029 ifstream
f(conf
->getconfigfname("icq-infoset").c_str());
1032 getstring(f
, buf
); cli
.getSelfContact()->setAlias(buf
);
1033 getstring(f
, buf
); cli
.getSelfContact()->setEmail(buf
);
1034 getstring(f
, buf
); cli
.getSelfContact()->setFirstName(buf
);
1035 getstring(f
, buf
); cli
.getSelfContact()->setLastName(buf
);
1038 cli
.getSelfContact()->getMainHomeInfo().timezone
= (Timezone
) getSystemTimezone();
1039 cli
.uploadSelfDetails();
1041 unlink(conf
->getconfigfname("icq-infoset").c_str());
1044 cli
.fetchServerBasedContactList();
1047 void icqhook::disconnected_cb(DisconnectedEvent
*ev
) {
1050 static const string reasons
[DisconnectedEvent::FAILED_UNKNOWN
+1] = {
1052 _("socket problems"),
1056 _("username and password mismatch"),
1057 _("dual login detected"),
1065 msg
= isconnecting() ? _("+ [icq] cannot connect") : _("+ [icq] disconnected");
1067 logger
.putourstatus(icq
, getstatus(), offline
);
1069 clist
.setoffline(icq
);
1072 if(!reasons
[ev
->getReason()].empty()) {
1074 msg
+= reasons
[ev
->getReason()];
1076 logger
.putmessage((string
) _("icq disconnection reason") + ": " +
1077 reasons
[ev
->getReason()]);
1079 if(ev
->getReason() == DisconnectedEvent::FAILED_DUALLOGIN
)
1080 manualstatus
= offline
;
1087 static string
fixicqrtf(string msg
) {
1091 static char *emoticons
[] = {
1092 ":-)", ":-O", ":-|", ":-\\", ":-(", ":-*", "8-/", ":~(",
1093 ";-)", ">:-O", ":`(", ":-X", ":-P", "B-)", "O:-)", ":-D",
1094 "*ANNOYED*", "*DISGUSTED*", "*DROOLING*", "*GIGGLING*",
1095 "*JOKINGLY*", "*SHOCKED*", "*WHINNING*", "*SURPRISED*",
1096 "*SURPRISED*", "*IN LOVE*"
1099 for(pos
= 0; (pos
= msg
.find("<##icqimage", pos
)) != -1; ) {
1100 if((bpos
= msg
.find(">", pos
)) != -1) {
1101 sub
= msg
.substr(pos
, bpos
-pos
);
1103 if(sub
.size() > 2) sub
.erase(0, sub
.size()-2);
1106 if(n
>= 0 && n
<= 25) {
1107 msg
.erase(pos
, bpos
-pos
+1);
1108 msg
.insert(pos
, emoticons
[n
]);
1118 void icqhook::messaged_cb(MessageEvent
*ev
) {
1122 ic
= imcontact(ev
->getContact()->getUIN(), icq
);
1124 if(ev
->getType() == MessageEvent::Normal
) {
1125 NormalMessageEvent
*r
= static_cast<NormalMessageEvent
*>(ev
);
1127 bool converted
= false;
1129 // check for UCS-2BE encoding in message
1130 if (r
->getEncoding() == (unsigned int)0x0002) {
1131 string msg
= r
->getMessage();
1132 text
= rusconv("ck", msg
);
1136 text
= r
->getMessage();
1137 if(text
.substr(0, 6) == "{\\rtf1")
1138 text
= fixicqrtf(striprtf(text
, converted
?conf
->getconvertto(proto
):conf
->getconvertfrom(proto
)));
1140 text
= converted
? text
: rusconv("wk", text
);
1143 const string pgpBlockBegin
= "-----BEGIN PGP MESSAGE-----";
1144 const string pgpBlockEnd
= "-----END PGP MESSAGE-----";
1146 int pgpDataBegin
= text
.find(pgpBlockBegin
);
1147 int pgpDataEnd
= text
.find(pgpBlockEnd
);
1149 // find where actual PGP data starts
1150 if (pgpDataBegin
!= string::npos
) {
1151 int a
= text
.find("\n\n", pgpDataBegin
+1);
1152 int b
= text
.find("\r\n\r\n", pgpDataBegin
+1);
1154 if(a
!= string::npos
) {
1155 if(b
!= string::npos
) {
1156 // if we found both, take the smaller value
1163 // we didn't find second match, so just take first
1167 // we didn't find first, so take whatever is in second
1172 if((pgpDataBegin
!= string::npos
) && (pgpDataEnd
!= string::npos
)) {
1174 enc
=text
.substr(pgpDataBegin
, pgpDataEnd
-pgpDataBegin
);
1176 icqcontact
*c
= clist
.get(ic
);
1180 c
->setusepgpkey(true);
1181 if(pgp
.enabled(proto
)) {
1182 string dec
= pgp
.decrypt(enc
, proto
);
1185 if(dec
.length() != 0) {
1186 logMsg
="+ "+ic
.totext()+" ("+c
->getdispnick()+") PGP message decoded";
1189 // if we fail to decode message,
1190 // just display it as it is
1191 logMsg
="+ "+ic
.totext()+" ("+c
->getdispnick()+") FAILED to decode PGP message";
1193 logger
.putmessage(logMsg
);
1196 c
->setusepgpkey(false);
1199 c
->setusepgpkey(false);
1205 em
.store(immessage(ic
, imevent::incoming
, text
, r
->getTime()));
1207 } else if(ev
->getType() == MessageEvent::URL
) {
1208 URLMessageEvent
*r
= static_cast<URLMessageEvent
*>(ev
);
1209 em
.store(imurl(ic
, imevent::incoming
,
1210 rusconv("wk", r
->getURL()),
1211 rusconv("wk", r
->getMessage())));
1213 } else if(ev
->getType() == MessageEvent::SMS
) {
1214 SMSMessageEvent
*r
= static_cast<SMSMessageEvent
*>(ev
);
1215 icqcontact
*c
= clist
.getmobile(r
->getSender());
1218 if(c
= clist
.addnew(imcontact(0, infocard
), true)) {
1219 icqcontact::basicinfo b
= c
->getbasicinfo();
1220 b
.cellular
= r
->getSender();
1223 c
->setdispnick(b
.cellular
);
1224 c
->setnick(b
.cellular
);
1228 em
.store(imsms(c
, imevent::incoming
, rusconv("uk", r
->getMessage())));
1231 } else if(ev
->getType() == MessageEvent::AuthReq
) {
1232 AuthReqEvent
*r
= static_cast<AuthReqEvent
*>(ev
);
1233 em
.store(imauthorization(ic
, imevent::incoming
, imauthorization::Request
,
1234 rusconv("wk", r
->getMessage())));
1236 } else if(ev
->getType() == MessageEvent::AuthAck
) {
1237 AuthAckEvent
*r
= static_cast<AuthAckEvent
*>(ev
);
1238 icqcontact
*c
= clist
.get(ic
);
1241 icqcontact::basicinfo bi
= c
->getbasicinfo();
1242 bi
.authawait
= false;
1243 c
->setbasicinfo(bi
);
1245 ContactRef cr
= cli
.getContactTree()[ic
.uin
];
1247 cr
->setAuthAwait(false);
1248 //cli.removeServerBasedContact(cr);
1249 //cli.uploadServerBasedContact(cr);
1253 if(r
->isGranted()) {
1254 em
.store(imnotification(ic
, _("The user has accepted your authorization request")));
1257 em
.store(imnotification(ic
, (string
)
1258 _("The user has rejected your authorization request; the message was: ") + r
->getMessage()));
1262 } else if(ev
->getType() == MessageEvent::EmailEx
) {
1263 EmailExEvent
*r
= static_cast<EmailExEvent
*>(ev
);
1264 processemailevent(r
->getSender(), r
->getEmail(), r
->getMessage());
1266 } else if(ev
->getType() == MessageEvent::WebPager
) {
1267 WebPagerEvent
*r
= static_cast<WebPagerEvent
*>(ev
);
1268 processemailevent(r
->getSender(), r
->getEmail(), r
->getMessage());
1270 } else if(ev
->getType() == MessageEvent::UserAdd
) {
1271 UserAddEvent
*r
= static_cast<UserAddEvent
*>(ev
);
1272 em
.store(imnotification(ic
,
1273 _("The user has added you to his/her contact list")));
1275 } else if(ev
->getType() == MessageEvent::Contacts
) {
1276 ContactMessageEvent
*r
= static_cast<ContactMessageEvent
*>(ev
);
1277 vector
< pair
<unsigned int, string
> > lst
;
1279 list
<ContactRef
> clst
= r
->getContacts();
1280 list
<ContactRef
>::iterator il
;
1282 for(il
= clst
.begin(); il
!= clst
.end(); ++il
) {
1283 lst
.push_back(make_pair((*il
)->getUIN(), (*il
)->getAlias()));
1286 em
.store(imcontacts(ic
, imevent::incoming
, lst
));
1290 ev
->setDelivered(true);
1293 void icqhook::messageack_cb(MessageEvent
*ev
) {
1296 ICQMessageEvent
*me
;
1298 ic
= imcontact(ev
->getContact()->getUIN(), icq
);
1302 c
= clist
.get(contactroot
);
1303 c
->setdispnick(cli
.getSelfContact()->getAlias());
1306 if(ev
->isFinished()) {
1307 // The FINAL decision.
1309 switch(ev
->getType()) {
1310 case MessageEvent::SMS
:
1311 if(!ev
->isDelivered()) {
1312 if(ev
->getContact()->getUIN()) {
1313 face
.log(_("+ [icq] failed SMS to %s, %s"),
1314 c
->getdispnick().c_str(), ic
.totext().c_str());
1316 face
.log(_("+ [icq] failed SMS to %s"),
1317 ev
->getContact()->getAlias().c_str());
1322 case MessageEvent::AwayMessage
:
1323 if(ev
->isDelivered()) {
1324 AwayMessageEvent
*r
;
1326 if(r
= dynamic_cast<AwayMessageEvent
*>(ev
)) {
1327 em
.store(imnotification(ic
, string() + _("Away message:") + "\n\n" +
1328 rusconv("wk", r
->getAwayMessage())));
1331 face
.log(_("+ [icq] cannot fetch away msg from %s, %s (maybe no away msg set)"),
1332 c
->getdispnick().c_str(), ic
.totext().c_str());
1339 * Rejected, but there is still something to be done.
1345 void icqhook::contactlist_cb(ContactListEvent
*ev
) {
1348 void icqhook::contact_status_change_signal_cb(StatusChangeEvent
*ev
) {
1349 icqcontact
*c
= clist
.get(imcontact(ev
->getUIN(), icq
));
1352 ContactRef ic
= ev
->getContact();
1353 StatusChangeEvent
*tev
= dynamic_cast<StatusChangeEvent
*>(ev
);
1354 imstatus nst
= icq2imstatus(tev
->getStatus());
1356 if(ic
->isInvisible()) nst
= invisible
;
1358 c
->setidlefor(ic
->getExtPort());
1359 logger
.putonline(c
, c
->getstatus(), nst
);
1362 if (ic
->get_signon_time())
1363 c
->setonlinesince(ic
->get_signon_time());
1366 c
->setlasttyping(0);
1370 void icqhook::contact_userinfo_change_signal_cb(UserInfoChangeEvent
*ev
) {
1371 icqcontact
*c
= clist
.get(imcontact(ev
->getUIN(), icq
));
1372 ContactRef ic
= ev
->getContact();
1375 c
= clist
.get(contactroot
);
1378 * In case we wanna look up info about a user which
1379 * is not on our contact list.
1384 if(!ev
->isTransientDetail()) {
1385 updateinforecord(ic
, c
);
1389 string lastip
, sbuf
, oldip
;
1390 struct in_addr addr
;
1392 oldip
= c
->getlastip();
1393 addr
.s_addr
= ntohl(ic
->getExtIP());
1394 if(p
= inet_ntoa(addr
)) lastip
= p
;
1396 if(lastip
.find_first_not_of(".0") != -1) {
1397 addr
.s_addr
= ntohl(ic
->getLanIP());
1398 if(p
= inet_ntoa(addr
)) {
1401 if(sbuf
.find_first_not_of(".0") != -1 && lastip
!= sbuf
) {
1402 if(!lastip
.empty()) lastip
+= " ";
1407 c
->setlastip(lastip
);
1411 if ((c
->getstatus() != offline
) && (oldip
.find_first_of("*")))
1413 oldip
.insert(0, "* ");
1414 c
->setlastip(oldip
);
1420 void icqhook::contact_typing_signal_cb(UserTypingNotificationEvent
*ev
) {
1421 icqcontact
*c
= clist
.get(imcontact(ev
->getUIN(), icq
));
1424 time_t when
= ev
->isTyping() ? (time(NULL
) + 300) : 0; // nobody should type for more than five minutes without a break...
1425 c
->setlasttyping(when
);
1426 face
.relaxedupdate();
1430 void icqhook::newuin_cb(NewUINEvent
*ev
) {
1431 reguin
= ev
->getUIN();
1434 void icqhook::rate_cb(RateInfoChangeEvent
*ev
) {
1437 void icqhook::logger_cb(LogEvent
*ev
) {
1438 switch(ev
->getType()) {
1439 case LogEvent::PACKET
:
1440 case LogEvent::DIRECTPACKET
:
1441 face
.log(ev
->getMessage());
1445 face
.log(ev
->getMessage());
1450 void icqhook::socket_cb(SocketEvent
*ev
) {
1451 vector
<int>::iterator i
;
1453 if(dynamic_cast<AddSocketHandleEvent
*>(ev
)) {
1454 AddSocketHandleEvent
*cev
= dynamic_cast<AddSocketHandleEvent
*>(ev
);
1456 if(cev
->isRead()) rfds
.push_back(cev
->getSocketHandle());
1457 if(cev
->isWrite()) wfds
.push_back(cev
->getSocketHandle());
1458 if(cev
->isException()) efds
.push_back(cev
->getSocketHandle());
1460 } else if(dynamic_cast<RemoveSocketHandleEvent
*>(ev
)) {
1461 RemoveSocketHandleEvent
*cev
= dynamic_cast<RemoveSocketHandleEvent
*>(ev
);
1463 i
= find(rfds
.begin(), rfds
.end(), cev
->getSocketHandle());
1467 i
= find(wfds
.begin(), wfds
.end(), cev
->getSocketHandle());
1471 i
= find(efds
.begin(), efds
.end(), cev
->getSocketHandle());
1477 void icqhook::want_auto_resp_cb(ICQMessageEvent
*ev
) {
1478 /* TODO: something should probably be logged here, but
1479 * logging an UNITIALIZED BUFFER seems pretty stupid to me
1481 /* char buf[128]; */
1484 imcontact cont
= imcontact(ev
->getSenderUIN(), icq
);
1485 icqcontact
*c
= clist
.get(cont
);
1487 ident
= cont
.totext();
1488 if(c
) ident
+= " (" + c
->getdispnick() + ")";
1490 /* logger.putmessage(buf); */
1491 ev
->setAwayMessage(rusconv("kw", conf
->getawaymsg(icq
)));
1494 void icqhook::search_result_cb(SearchResultEvent
*ev
) {
1495 if(ev
== searchevent
) {
1496 ContactRef cont
= ev
->getLastContactAdded();
1498 if(searchdest
&& cont
.get()) {
1499 icqcontact
*c
= new icqcontact(imcontact(cont
->getUIN(), icq
));
1500 icqcontact::basicinfo binfo
= c
->getbasicinfo();
1502 if(ev
->getSearchType() == SearchResultEvent::RandomChat
) {
1503 binfo
.fname
= _("Random Chat User");
1506 c
->setnick(rusconv("wk", cont
->getAlias()));
1507 c
->setdispnick(c
->getnick());
1509 binfo
.fname
= rusconv("wk", cont
->getFirstName());
1510 binfo
.lname
= rusconv("wk", cont
->getLastName());
1511 binfo
.email
= rusconv("wk", cont
->getEmail());
1515 string line
= (cont
->getStatus() == STATUS_ONLINE
? "o " : " ") + c
->getnick();
1517 if(line
.size() > 12) line
.resize(12);
1518 else line
+= string(12-line
.size(), ' ');
1520 line
+= " " + binfo
.fname
+ " " + binfo
.lname
;
1521 if(!binfo
.email
.empty()) line
+= " <" + binfo
.email
+ ">";
1523 binfo
.requiresauth
= cont
->getAuthReq();
1524 binfo
.authawait
= cont
->getAuthAwait();
1526 c
->setbasicinfo(binfo
);
1528 foundguys
.push_back(c
);
1529 searchdest
->additem(conf
->getcolor(cp_clist_icq
), c
, line
);
1530 searchdest
->redraw();
1533 if(ev
->isFinished() && searchdest
) {
1535 log(logSearchFinished
, ev
->getContactList().size());
1541 void icqhook::self_contact_userinfo_change_cb(UserInfoChangeEvent
*ev
) {
1542 if(!ev
->isTransientDetail()) {
1543 icqcontact
*c
= clist
.get(contactroot
);
1545 updateinforecord(cli
.getSelfContact(), c
);
1546 updateinforecord(cli
.getSelfContact(), clist
.get(imcontact(cli
.getUIN(), icq
)));
1550 * Fill in the locally stored parts now.
1554 icqconf::imaccount im
= conf
->getourid(icq
);
1555 icqcontact::basicinfo cbinfo
= c
->getbasicinfo();
1556 cbinfo
.webaware
= im
.additional
["webaware"] == "1";
1557 cbinfo
.randomgroup
= strtoul(im
.additional
["randomgroup"].c_str(), 0, 0);
1558 c
->setbasicinfo(cbinfo
);
1562 void icqhook::self_contact_status_change_cb(StatusChangeEvent
*ev
) {
1568 void icqhook::password_changed_cb(PasswordChangeEvent *ev) {
1569 if(ev->isSuccess()) {
1570 icqconf::imaccount acc = conf->getourid(icq);
1571 acc.password = ev->getPassword();
1572 conf->setourid(acc);
1573 log(logPasswordChanged);
1579 void icqhook::sbl_received_cb(SBLReceivedEvent
*ev
) {
1581 ContactTree
&tree
= cli
.getContactTree();
1582 ContactTree::iterator curr
= ev
->tree
.begin();
1586 while(curr
!= ev
->tree
.end()) {
1587 ContactTree::Group
*lg
= 0;
1589 ContactTree::iterator igl
= tree
.begin();
1590 while(igl
!= tree
.end()) {
1591 if((*igl
).get_label() == (*curr
).get_label()) {
1599 lg
= &(tree
.add_group((*curr
).get_label(), (*curr
).get_id()));
1601 lg
->set_id((*curr
).get_id());
1604 ContactTree::Group::iterator ig
= curr
->begin();
1605 while(ig
!= curr
->end()) {
1606 imcontact
ic((*ig
)->getUIN(), proto
);
1607 clist
.updateEntry(ic
, (*curr
).get_label());
1609 ContactRef nc
= tree
[ic
.uin
];
1611 ContactTree::Group
&cg
= tree
.lookup_group_containing_contact(nc
);
1612 tree
.relocate_contact(nc
, cg
, *lg
);
1614 nc
= lg
->add(new Contact(ic
.uin
));
1616 nc
->setAuthAwait((*ig
)->getAuthAwait());
1618 if(cc
= clist
.get(ic
)) {
1619 icqcontact::basicinfo bi
= cc
->getbasicinfo();
1620 bi
.authawait
= nc
->getAuthAwait();
1621 bi
.serverbased
= true;
1622 cc
->setbasicinfo(bi
);
1625 nc
->setServerBased(true);
1626 nc
->setServerSideInfo((*ig
)->getServerSideGroupID(), (*ig
)->getServerSideID());
1636 ContactRef
icqhook::addContact(unsigned int uin
, const string
&groupname
) {
1637 ContactTree
& ct
= cli
.getContactTree();
1638 ContactTree::Group
*gp
= 0;
1640 ContactTree::iterator curr
= ct
.begin();
1641 while(curr
!= ct
.end()) {
1642 if((*curr
).get_label() == groupname
) {
1649 if(!gp
) gp
= &(ct
.add_group(groupname
));
1651 ContactRef
cont(new Contact(uin
));
1657 #endif /* BUILD_ICQ */