3 * centerim MSN protocol handling class
4 * $Id: msnhook.cc,v 1.91 2005/02/03 02:02:37 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"
32 #include "icqcontacts.h"
33 #include "accountmanager.h"
34 #include "eventmanager.h"
37 #include "icqgroups.h"
40 #include <sys/types.h>
41 #include <sys/socket.h>
42 #include <netinet/in.h>
44 #include <arpa/inet.h>
48 static string
nicknormalize(const string
&nick
) {
49 if(nick
.find("@") == -1) return nick
+ "@hotmail.com";
53 static string
nicktodisp(const string
&nick
) {
57 if((pos
= r
.find("@")) != -1)
58 if(r
.substr(pos
+1) == "hotmail.com")
64 static map
<MSN::BuddyStatus
, imstatus
> convstat
;
66 static imstatus
buddy2stat(MSN::BuddyStatus bst
) {
67 map
<MSN::BuddyStatus
, imstatus
>::const_iterator i
= convstat
.find(bst
);
68 if(i
!= convstat
.end())
74 static MSN::BuddyStatus
stat2buddy(imstatus st
) {
75 map
<MSN::BuddyStatus
, imstatus
>::const_iterator i
= convstat
.begin();
76 while(i
!= convstat
.end()) {
82 return MSN::STATUS_AVAILABLE
;
85 // ----------------------------------------------------------------------------
87 msnhook::msnhook(): abstracthook(msn
), conn(cb
) {
92 fcapabs
.insert(hookcapab::changedetails
);
93 fcapabs
.insert(hookcapab::directadd
);
97 if(conn
.connectionState() != MSN::NotificationServerConnection::NS_DISCONNECTED
) {
103 void msnhook::init() {
104 manualstatus
= conf
->getstatus(msn
);
106 convstat
[MSN::STATUS_AVAILABLE
] = available
;
107 convstat
[MSN::STATUS_INVISIBLE
] = invisible
;
108 convstat
[MSN::STATUS_BUSY
] = dontdisturb
;
109 convstat
[MSN::STATUS_ONTHEPHONE
] = occupied
;
110 convstat
[MSN::STATUS_AWAY
] = notavail
;
111 convstat
[MSN::STATUS_BERIGHTBACK
] = away
;
112 convstat
[MSN::STATUS_OUTTOLUNCH
] = outforlunch
;
113 convstat
[MSN::STATUS_IDLE
] = away
;
116 void msnhook::connect() {
117 icqconf::imaccount account
= conf
->getourid(msn
);
121 readinfo
= flogged
= false;
125 if(conn
.connectionState() != MSN::NotificationServerConnection::NS_DISCONNECTED
)
131 conn
.connect(account
.server
, account
.port
, nicknormalize(account
.nickname
), account
.password
);
136 void msnhook::disconnect() {
138 if(conn
.connectionState() != MSN::NotificationServerConnection::NS_DISCONNECTED
)
140 clist
.setoffline(mhook
.proto
);
141 log(logDisconnected
);
144 void msnhook::exectimers() {
146 if(timer_current
-timer_ping
> conn
.nextPing()) {
149 timer_ping
= timer_current
;
156 void msnhook::main() {
157 vector
<int>::const_iterator i
;
167 getsockets(rs
, ws
, es
, hsock
);
168 tv
.tv_sec
= tv
.tv_usec
= 0;
171 if(select(hsock
+1, &rs
, &ws
, &es
, &tv
) > 0) {
172 for(i
= rfds
.begin(); i
!= rfds
.end(); ++i
)
173 if(FD_ISSET(*i
, &rs
)) {
174 c
= conn
.connectionWithSocket(*i
);
175 if(c
) c
->dataArrivedOnSocket();
179 for(i
= wfds
.begin(); i
!= wfds
.end(); ++i
)
180 if(FD_ISSET(*i
, &ws
)) {
181 c
= conn
.connectionWithSocket(*i
);
184 if(!c
->isConnected()) {
185 c
->socketConnectionCompleted();
187 c
->socketIsWritable();
198 void msnhook::getsockets(fd_set
&rf
, fd_set
&wf
, fd_set
&efds
, int &hsocket
) const {
199 vector
<int>::const_iterator i
;
201 for(i
= rfds
.begin(); i
!= rfds
.end(); ++i
) {
202 hsocket
= max(hsocket
, *i
);
206 for(i
= wfds
.begin(); i
!= wfds
.end(); ++i
) {
207 hsocket
= max(hsocket
, *i
);
212 bool msnhook::isoursocket(fd_set
&rf
, fd_set
&wf
, fd_set
&efds
) const {
213 vector
<int>::const_iterator i
;
215 for(i
= rfds
.begin(); i
!= rfds
.end(); ++i
)
216 if(FD_ISSET(*i
, &rf
))
219 for(i
= wfds
.begin(); i
!= wfds
.end(); ++i
)
220 if(FD_ISSET(*i
, &wf
))
226 bool msnhook::online() const {
230 bool msnhook::logged() const {
231 return fonline
&& flogged
;
234 bool msnhook::isconnecting() const {
235 return fonline
&& !flogged
;
238 bool msnhook::enabled() const {
242 bool msnhook::send(const imevent
&ev
) {
244 string rcpt
= nicknormalize(ev
.getcontact().nickname
);
246 if(ev
.gettype() == imevent::message
) {
247 const immessage
*m
= static_cast<const immessage
*>(&ev
);
248 if(m
) text
= m
->gettext();
250 } else if(ev
.gettype() == imevent::url
) {
251 const imurl
*m
= static_cast<const imurl
*>(&ev
);
252 if(m
) text
= m
->geturl() + "\n\n" + m
->getdescription();
254 } else if(ev
.gettype() == imevent::file
) {
255 const imfile
*m
= static_cast<const imfile
*>(&ev
);
256 vector
<imfile::record
> files
= m
->getfiles();
257 vector
<imfile::record
>::const_iterator ir
;
259 for(ir
= files
.begin(); ir
!= files
.end(); ++ir
) {
265 imfile
fr(ev
.getcontact(), imevent::outgoing
, "", vector
<imfile::record
>(1, r
));
268 qevent
*ctx
= new qevent(qevent::qeFile
, rcpt
, ir
->fname
);
270 if(lconn
.find(rcpt
) != lconn
.end()) sendmsn(lconn
[rcpt
], ctx
);
271 else conn
.requestSwitchboardConnection(ctx
);
280 icqcontact
*c
= clist
.get(ev
.getcontact());
281 text
= rusconv("ku", text
);
284 if(c
->getstatus() != offline
|| !c
->inlist()) {
286 qevent
*ctx
= new qevent(qevent::qeMsg
, rcpt
, text
);
288 if(lconn
.find(rcpt
) != lconn
.end()) sendmsn(lconn
[rcpt
], ctx
);
289 else conn
.requestSwitchboardConnection(ctx
);
300 int msnhook::findgroup(const imcontact
&ic
, string
&gname
) const {
304 if(c
= clist
.get(ic
)) {
305 vector
<icqgroup
>::const_iterator ig
= find(groups
.begin(), groups
.end(), c
->getgroupid());
306 if(ig
!= groups
.end()) {
307 gname
= ig
->getname();
308 map
<int, string
>::const_iterator im
= mgroups
.begin();
309 while(im
!= mgroups
.end() && gid
== -1) {
310 if(im
->second
== ig
->getname())
320 void msnhook::sendnewuser(const imcontact
&ic
) {
321 if(logged() && !readinfo
) {
323 imcontact
icc(nicktodisp(ic
.nickname
), msn
);
325 if(icc
.nickname
!= ic
.nickname
)
326 if(c
= clist
.get(ic
)) {
328 c
->setnick(icc
.nickname
);
329 c
->setdispnick(icc
.nickname
);
335 gid
= findgroup(ic
, gname
);
341 conn
.addToGroup(nicknormalize(ic
.nickname
), gid
);
349 void msnhook::setautostatus(imstatus st
) {
354 logger
.putourstatus(msn
, ourstatus
, st
);
356 conn
.setState(stat2buddy(ourstatus
= st
));
361 if(getstatus() != offline
) {
367 imstatus
msnhook::getstatus() const {
368 return online() ? ourstatus
: offline
;
371 void msnhook::removeuser(const imcontact
&ic
) {
372 removeuser(ic
, true);
375 void msnhook::removeuser(const imcontact
&ic
, bool report
) {
378 vector
<msnbuddy
>::const_iterator ib
= find(slst
["FL"].begin(), slst
["FL"].end(), nicknormalize(ic
.nickname
));
380 if(online() && ib
!= slst
["FL"].end()) {
382 log(logContactRemove
, ic
.nickname
.c_str());
385 conn
.removeFromGroup(nicknormalize(ic
.nickname
), ib
->gid
);
387 for(i
= 0, found
= false; i
< clist
.count
&& !found
; i
++) {
388 icqcontact
*c
= (icqcontact
*) clist
.at(i
);
389 found
= c
->getdesc().pname
== msn
390 && groups
.getname(c
->getgroupid()) == mgroups
[ib
->gid
];
393 if(!found
&& ib
->gid
> 0)
394 conn
.removeGroup(ib
->gid
);
400 void msnhook::requestinfo(const imcontact
&ic
) {
401 icqcontact
*c
= clist
.get(ic
);
402 if(!c
) c
= clist
.get(contactroot
);
404 icqcontact::moreinfo m
= c
->getmoreinfo();
405 icqcontact::basicinfo b
= c
->getbasicinfo();
407 b
.email
= nicknormalize(ic
.nickname
);
408 m
.homepage
= "http://members.msn.com/" + b
.email
;
410 if(ic
.nickname
== conf
->getourid(msn
).nickname
)
411 c
->setnick(friendlynicks
[ic
.nickname
]);
417 void msnhook::lookup(const imsearchparams
¶ms
, verticalmenu
&dest
) {
419 vector
<msnbuddy
>::const_iterator i
= slst
["RL"].begin();
421 while(i
!= slst
["RL"].end()) {
422 icqcontact
*c
= new icqcontact(imcontact(nicktodisp(i
->nick
), msn
));
423 c
->setnick(i
->friendly
);
425 dest
.additem(conf
->getcolor(cp_clist_msn
), c
, (string
) " " + i
->nick
);
430 face
.log(_("+ [msn] reverse users listing finished, %d found"),
437 vector
<icqcontact
*> msnhook::getneedsync() {
439 vector
<icqcontact
*> r
;
442 for(i
= 0; i
< clist
.count
; i
++) {
443 icqcontact
*c
= (icqcontact
*) clist
.at(i
);
445 if(c
->getdesc().pname
== msn
) {
446 vector
<msnbuddy
>::const_iterator fi
= slst
["FL"].begin();
448 for(found
= false; fi
!= slst
["FL"].end() && !found
; ++fi
)
449 found
= c
->getdesc().nickname
== fi
->nick
;
459 void msnhook::sendupdateuserinfo(const icqcontact
&c
) {
461 conn
.setFriendlyName(c
.getnick());
466 void msnhook::checkfriendly(icqcontact
*c
, const string friendlynick
, bool forcefetch
) {
467 string oldnick
= c
->getnick();
468 string newnick
= unmime(friendlynick
);
472 if(forcefetch
|| (oldnick
!= newnick
&& c
->getdispnick() == oldnick
) || oldnick
.empty()) {
473 c
->setdispnick(newnick
);
474 face
.relaxedupdate();
478 void msnhook::checkinlist(imcontact ic
) {
479 icqcontact
*c
= clist
.get(ic
);
480 vector
<icqcontact
*> notremote
= getneedsync();
484 if(find(notremote
.begin(), notremote
.end(), c
) != notremote
.end())
485 mhook
.sendnewuser(ic
);
488 bool msnhook::knowntransfer(const imfile
&fr
) const {
489 return transferinfo
.find(fr
) != transferinfo
.end();
492 void msnhook::replytransfer(const imfile
&fr
, bool accept
, const string
&localpath
) {
494 transferinfo
[fr
].second
= localpath
;
496 if(transferinfo
[fr
].second
.substr(transferinfo
[fr
].second
.size()-1) != "/")
497 transferinfo
[fr
].second
+= "/";
499 transferinfo
[fr
].second
+= justfname(fr
.getfiles().begin()->fname
);
500 // msn_filetrans_accept(transferinfo[fr].first, transferinfo[fr].second.c_str());
503 // msn_filetrans_reject(transferinfo[fr].first);
504 transferinfo
.erase(fr
);
509 void msnhook::aborttransfer(const imfile
&fr
) {
510 // msn_filetrans_reject(transferinfo[fr].first);
512 face
.transferupdate(fr
.getfiles().begin()->fname
, fr
,
513 icqface::tsCancel
, 0, 0);
515 transferinfo
.erase(fr
);
518 bool msnhook::getfevent(MSN::FileTransferInvitation
*fhandle
, imfile
&fr
) {
519 map
<imfile
, pair
<MSN::FileTransferInvitation
*, string
> >::const_iterator i
= transferinfo
.begin();
521 while(i
!= transferinfo
.end()) {
522 if(i
->second
.first
== fhandle
) {
532 void msnhook::updatecontact(icqcontact
*c
) {
533 string gname
, nick
= nicknormalize(c
->getdesc().nickname
);
534 vector
<msnbuddy
>::const_iterator ib
= find(slst
["FL"].begin(), slst
["FL"].end(), nick
);
536 if(ib
!= slst
["FL"].end() && logged() && conf
->getgroupmode() != icqconf::nogroups
)
537 if(mhook
.findgroup(c
->getdesc(), gname
) != ib
->gid
) {
539 conn
.removeFromList("FL", nick
.c_str());
543 sendnewuser(c
->getdesc());
547 void msnhook::renamegroup(const string
&oldname
, const string
&newname
) {
549 map
<int, string
>::const_iterator im
= mgroups
.begin();
550 while(im
!= mgroups
.end()) {
551 if(im
->second
== oldname
) {
553 conn
.renameGroup(im
->first
, newname
);
564 // ----------------------------------------------------------------------------
566 void msnhook::statusupdate(string buddy
, string friendlyname
, imstatus status
) {
567 imcontact
ic(nicktodisp(buddy
), msn
);
568 icqcontact
*c
= clist
.get(ic
);
572 c
= clist
.addnew(ic
, false);
574 if(!friendlyname
.empty())
575 checkfriendly(c
, friendlyname
, forcefetch
);
577 logger
.putonline(ic
, c
->getstatus(), status
);
578 c
->setstatus(status
);
581 // ----------------------------------------------------------------------------
583 void msnhook::sendmsn(MSN::SwitchboardServerConnection
*conn
, const qevent
*ctx
) {
584 MSN::FileTransferInvitation
*inv
;
587 case msnhook::qevent::qeMsg
:
588 conn
->sendMessage(ctx
->text
);
591 case msnhook::qevent::qeFile
:
592 inv
= conn
->sendFile(ctx
->text
);
593 // if(inv) mhook.transferinfo[] = inv;
600 // ----------------------------------------------------------------------------
602 static void log(const string
&s
) {
607 void msncallbacks::log(int writing
, const char* buf
) {
608 string pref
= writing
? "OUT" : "IN";
609 ::log((string
) "[" + pref
+ "] " + buf
);
612 void msncallbacks::registerSocket(int s
, int reading
, int writing
) {
613 ::log("msncallbacks::registerSocket");
614 if(reading
) mhook
.rfds
.push_back(s
);
615 if(writing
) mhook
.wfds
.push_back(s
);
618 void msncallbacks::unregisterSocket(int s
) {
619 ::log("msncallbacks::unregisterSocket");
620 vector
<int>::iterator i
;
622 i
= find(mhook
.rfds
.begin(), mhook
.rfds
.end(), s
);
623 if(i
!= mhook
.rfds
.end()) mhook
.rfds
.erase(i
);
625 i
= find(mhook
.wfds
.begin(), mhook
.wfds
.end(), s
);
626 if(i
!= mhook
.wfds
.end()) mhook
.wfds
.erase(i
);
629 void msncallbacks::gotFriendlyName(MSN::Connection
* conn
, string friendlyname
) {
630 ::log("msncallbacks::gotFriendlyName");
631 if(!friendlyname
.empty())
632 mhook
.friendlynicks
[conf
->getourid(msn
).nickname
] = friendlyname
;
635 void msncallbacks::gotBuddyListInfo(MSN::NotificationServerConnection
* conn
, MSN::ListSyncInfo
* data
) {
636 ::log("msncallbacks::gotBuddyListInfo");
640 mhook
.readinfo
= true;
642 std::map
<int, MSN::Group
>::iterator ig
;
644 for(ig
= data
->groups
.begin(); ig
!= data
->groups
.end(); ig
++) {
645 mhook
.mgroups
[ig
->second
.groupID
] = ig
->second
.name
;
648 std::list
<MSN::Buddy
> &lst
= data
->forwardList
;
649 std::list
<MSN::Buddy
>::iterator i
;
651 for(i
= lst
.begin(); i
!= lst
.end(); i
++) {
653 if(!i
->groups
.empty()) gid
= (*i
->groups
.begin())->groupID
;
654 mhook
.slst
["FL"].push_back(msnbuddy(i
->userName
, i
->friendlyName
, gid
));
656 ic
= imcontact(nicktodisp(i
->userName
), msn
);
657 icqcontact
*c
= clist
.get(ic
);
658 if(!c
) c
= clist
.addnew(ic
, false);
660 icqcontact::basicinfo bi
= c
->getbasicinfo();
661 icqcontact::workinfo wi
= c
->getworkinfo();
663 list
<MSN::Buddy::PhoneNumber
>::iterator ip
= i
->phoneNumbers
.begin();
664 for(; ip
!= i
->phoneNumbers
.end(); ip
++) {
665 if(ip
->title
== "PHH") bi
.phone
= ip
->number
; else
666 if(ip
->title
== "PHW") wi
.phone
= ip
->number
; else
667 if(ip
->title
== "PHM") bi
.cellular
= ip
->number
;
673 for(found
= false, ig
= data
->groups
.begin(); ig
!= data
->groups
.end() && !found
; ++ig
) {
674 found
= ig
->second
.groupID
== gid
;
675 if(found
) clist
.updateEntry(ic
, ig
->second
.name
);
679 for(lst
= data
->reverseList
, i
= lst
.begin(); i
!= lst
.end(); ++i
)
680 mhook
.slst
["RL"].push_back(msnbuddy(i
->userName
, i
->friendlyName
));
682 mhook
.readinfo
= false;
683 mhook
.flogged
= true;
685 mhook
.setautostatus(mhook
.manualstatus
);
686 mhook
.timer_ping
= timer_current
;
687 mhook
.log(abstracthook::logLogged
);
691 void msncallbacks::gotLatestListSerial(MSN::Connection
* conn
, int serial
) {
692 ::log("msncallbacks::gotLatestListSerial");
695 void msncallbacks::gotGTC(MSN::Connection
* conn
, char c
) {
696 ::log("msncallbacks::gotGTC");
699 void msncallbacks::gotBLP(MSN::Connection
* conn
, char c
) {
700 ::log("msncallbacks::gotBLP");
703 void msncallbacks::gotNewReverseListEntry(MSN::Connection
* conn
, MSN::Passport buddy
, std::string friendlyname
) {
704 ::log("msncallbacks::gotNewReverseListEntry");
707 mhook
.conn
.addToList("AL", buddy
);
711 imcontact
ic(nicktodisp(buddy
), msn
);
712 mhook
.checkinlist(ic
);
713 em
.store(imnotification(ic
, _("The user has added you to his/her contact list")));
716 void msncallbacks::addedListEntry(MSN::Connection
* conn
, string lst
, MSN::Passport buddy
, int groupID
) {
717 ::log("msncallbacks::addedListEntry");
718 mhook
.slst
[lst
].push_back(msnbuddy(buddy
, "", groupID
));
721 void msncallbacks::removedListEntry(MSN::Connection
* conn
, string lst
, MSN::Passport buddy
, int groupID
) {
722 ::log("msncallbacks::removedListEntry");
723 vector
<msnbuddy
>::iterator i
= mhook
.slst
[lst
].begin();
724 while(i
!= mhook
.slst
[lst
].end()) {
725 if(i
->nick
== buddy
) {
726 mhook
.slst
[lst
].erase(i
);
727 i
= mhook
.slst
[lst
].begin();
734 void msncallbacks::showError(MSN::Connection
* conn
, string msg
) {
738 void msncallbacks::buddyChangedStatus(MSN::Connection
* conn
, MSN::Passport buddy
, string friendlyname
, MSN::BuddyStatus state
) {
739 ::log("msncallbacks::buddyChangedStatus");
740 mhook
.statusupdate(buddy
, friendlyname
, buddy2stat(state
));
743 void msncallbacks::buddyOffline(MSN::Connection
* conn
, MSN::Passport buddy
) {
744 ::log("msncallbacks::buddyOffline");
745 mhook
.statusupdate(buddy
, "", offline
);
748 void msncallbacks::gotSwitchboard(MSN::SwitchboardServerConnection
* conn
, const void * tag
) {
749 ::log("msncallbacks::gotSwitchboard");
752 const msnhook::qevent
*ctx
= static_cast<const msnhook::qevent
*>(tag
);
753 conn
->inviteUser(ctx
->nick
);
757 void msncallbacks::buddyJoinedConversation(MSN::SwitchboardServerConnection
* conn
, MSN::Passport buddy
, std::string friendlyname
, int is_initial
) {
758 ::log("msncallbacks::buddyJoinedConversation");
760 const msnhook::qevent
*ctx
= static_cast<const msnhook::qevent
*>(conn
->auth
.tag
);
761 mhook
.lconn
[ctx
->nick
] = conn
;
762 mhook
.sendmsn(conn
, ctx
);
767 void msncallbacks::buddyLeftConversation(MSN::SwitchboardServerConnection
* conn
, MSN::Passport buddy
) {
768 ::log("msncallbacks::buddyLeftConversation");
771 void msncallbacks::gotInstantMessage(MSN::SwitchboardServerConnection
* conn
, MSN::Passport buddy
, std::string friendlyname
, MSN::Message
* msg
) {
772 ::log("msncallbacks::gotInstantMessage");
773 imcontact
ic(nicktodisp(buddy
), msn
);
775 mhook
.checkinlist(ic
);
777 string text
= mhook
.rusconv("uk", msg
->getBody());
778 em
.store(immessage(ic
, imevent::incoming
, text
));
781 void msncallbacks::failedSendingMessage(MSN::Connection
* conn
) {
782 ::log("msncallbacks::failedSendingMessage");
785 void msncallbacks::buddyTyping(MSN::Connection
* conn
, MSN::Passport buddy
, std::string friendlyname
) {
786 ::log("msncallbacks::buddyTyping");
787 icqcontact
*c
= clist
.get(imcontact(nicktodisp(buddy
), msn
));
788 if(c
) c
->setlasttyping(timer_current
);
791 void msncallbacks::gotInitialEmailNotification(MSN::Connection
* conn
, int unread_inbox
, int unread_folders
) {
792 ::log("msncallbacks::gotInitialEmailNotification");
793 face
.log(_("+ [msn] unread e-mail: %d in inbox, %d in folders"),
794 unread_inbox
, unread_folders
);
797 void msncallbacks::gotNewEmailNotification(MSN::Connection
* conn
, string from
, string subject
) {
798 ::log("msncallbacks::gotNewEmailNotification");
799 face
.log(_("+ [msn] e-mail from %s, %s"), from
.c_str(), subject
.c_str());
800 clist
.get(contactroot
)->playsound(imevent::email
);
803 void msncallbacks::gotFileTransferInvitation(MSN::Connection
* conn
, MSN::Passport buddy
, std::string friendlyname
, MSN::FileTransferInvitation
* inv
) {
804 ::log("msncallbacks::gotFileTransferInvitation");
805 if(!mhook
.fcapabs
.count(hookcapab::files
))
809 r
.fname
= inv
->fileName
;
810 r
.size
= inv
->fileSize
;
812 imcontact
ic(nicktodisp(buddy
), msn
);
813 mhook
.checkinlist(ic
);
815 imfile
fr(ic
, imevent::incoming
, "", vector
<imfile::record
>(1, r
));
817 mhook
.transferinfo
[fr
].first
= inv
;
820 face
.transferupdate(inv
->fileName
, fr
, icqface::tsInit
, inv
->fileSize
, 0);
823 void msncallbacks::fileTransferProgress(MSN::FileTransferInvitation
* inv
, string status
, unsigned long recv
, unsigned long total
) {
824 ::log("msncallbacks::fileTransferProgress");
827 if(mhook
.getfevent(inv
, fr
)) {
828 face
.transferupdate(fr
.getfiles().begin()->fname
, fr
,
829 icqface::tsProgress
, total
, recv
);
833 void msncallbacks::fileTransferFailed(MSN::FileTransferInvitation
* inv
, int error
, string message
) {
834 ::log("msncallbacks::fileTransferFailed");
837 if(mhook
.getfevent(inv
, fr
)) {
838 face
.transferupdate(fr
.getfiles().begin()->fname
, fr
, icqface::tsError
, 0, 0);
839 mhook
.transferinfo
.erase(fr
);
843 void msncallbacks::fileTransferSucceeded(MSN::FileTransferInvitation
* inv
) {
844 ::log("msncallbacks::fileTransferSucceeded");
847 if(mhook
.getfevent(inv
, fr
)) {
848 face
.transferupdate(fr
.getfiles().begin()->fname
, fr
, icqface::tsFinish
, 0, 0);
849 mhook
.transferinfo
.erase(fr
);
853 void msncallbacks::gotNewConnection(MSN::Connection
* conn
) {
854 ::log("msncallbacks::gotNewConnection");
855 if(dynamic_cast<MSN::NotificationServerConnection
*>(conn
))
856 dynamic_cast<MSN::NotificationServerConnection
*>(conn
)->synchronizeLists();
859 void msncallbacks::closingConnection(MSN::Connection
* conn
) {
860 ::log("msncallbacks::closingConnection");
862 MSN::SwitchboardServerConnection
*swc
;
864 if(swc
= dynamic_cast<MSN::SwitchboardServerConnection
*>(conn
)) {
865 map
<string
, MSN::SwitchboardServerConnection
*>::const_iterator ic
= mhook
.lconn
.begin();
866 while(ic
!= mhook
.lconn
.end()) {
867 if(swc
== ic
->second
) {
868 mhook
.lconn
.erase(ic
->first
);
874 } else if(conn
== &mhook
.conn
) {
875 if(!mhook
.destroying
) {
882 logger
.putourstatus(msn
, mhook
.getstatus(), mhook
.ourstatus
= offline
);
883 clist
.setoffline(msn
);
885 mhook
.fonline
= false;
886 mhook
.log(abstracthook::logDisconnected
);
893 unregisterSocket(conn
->sock
);
896 void msncallbacks::changedStatus(MSN::Connection
* conn
, MSN::BuddyStatus state
) {
897 ::log("msncallbacks::changedStatus");
900 int msncallbacks::connectToServer(string server
, int port
, bool *connected
) {
901 ::log("msncallbacks::connectToServer");
902 struct sockaddr_in sa
;
905 string msgerr
= _("+ [msn] cannot connect: ");
907 hp
= gethostbyname(server
.c_str());
909 face
.log(msgerr
+ _("could not resolve hostname"));
910 errno
= ECONNREFUSED
;
914 memset(&sa
, 0, sizeof(sa
));
915 memcpy((char *) &sa
.sin_addr
, hp
->h_addr
, hp
->h_length
);
916 sa
.sin_family
= hp
->h_addrtype
;
917 sa
.sin_port
= htons((u_short
) port
);
919 if((s
= socket(hp
->h_addrtype
, SOCK_STREAM
, 0)) < 0)
922 int oldfdArgs
= fcntl(s
, F_GETFL
, 0);
923 fcntl(s
, F_SETFL
, oldfdArgs
| O_NONBLOCK
);
927 if(cw_connect(s
, (struct sockaddr
*) &sa
, sizeof sa
, 0) < 0) {
928 if(errno
!= EINPROGRESS
) {
929 face
.log(msgerr
+ _("verify the hostname and port"));
938 int msncallbacks::listenOnPort(int port
) {
939 ::log("msncallbacks::listenOnPort");
941 struct sockaddr_in addr
;
943 if((s
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0)
946 memset(&addr
, 0, sizeof(addr
));
947 addr
.sin_family
= AF_INET
;
948 addr
.sin_port
= htons(port
);
950 if(bind(s
, (sockaddr
*) &addr
, sizeof(addr
)) < 0 || listen(s
, 1) < 0) {
958 string
msncallbacks::getOurIP() {
959 ::log("msncallbacks::getOurIP");
963 gethostname(buf2
, 1024);
964 hn
= gethostbyname(buf2
);
966 return inet_ntoa(*((struct in_addr
*) hn
->h_addr
));
969 string
msncallbacks::getSecureHTTPProxy() {
970 ::log("msncallbacks::getSecureHTTPProxy");
974 void msncallbacks::addedGroup(MSN::Connection
* conn
, string groupName
, int groupID
) {
975 ::log("msncallbacks::addedGroup");
979 mhook
.mgroups
[groupID
] = groupName
;
981 vector
<icqgroup
>::const_iterator ig
= groups
.begin();
983 while(ig
!= groups
.end()) {
984 if(ig
->getname() == groupName
) {
985 for(i
= 0; i
< clist
.count
; i
++) {
986 c
= (icqcontact
*) clist
.at(i
);
987 if(c
->getgroupid() == ig
->getid())
988 mhook
.sendnewuser(c
->getdesc());
996 void msncallbacks::renamedGroup(MSN::Connection
* conn
, int groupID
, string newGroupName
) {
997 ::log("msncallbacks::renamedGroup");
998 mhook
.mgroups
[groupID
] = newGroupName
;
1001 void msncallbacks::removedGroup(MSN::Connection
* conn
, int groupID
) {
1002 ::log("msncallbacks::removedGroup");
1003 mhook
.mgroups
.erase(groupID
);