3 * centerim yahoo! protocol handling class
4 * $Id: yahoohook.cc,v 1.112 2004/12/20 00:54:02 konst Exp $
6 * Copyright (C) 2003-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"
29 #include "yahoohook.h"
34 #include "icqcontacts.h"
35 #include "icqgroups.h"
37 #include "accountmanager.h"
38 #include "eventmanager.h"
44 #include <sys/socket.h>
45 #include <netinet/in.h>
47 #define PERIOD_REFRESH 60
48 #define PERIOD_CLOSE 6
52 int yahoohook::yfd::connection_tags
= 0;
54 char pager_host
[255], pager_port
[255], filetransfer_host
[255],
55 filetransfer_port
[255], webcam_host
[255], webcam_port
[255],
56 local_host
[255], webcam_description
[255];
62 static int stat2int
[imstatus_size
] = {
64 YAHOO_STATUS_AVAILABLE
,
65 YAHOO_STATUS_INVISIBLE
,
68 YAHOO_STATUS_NOTATDESK
,
69 YAHOO_STATUS_NOTATHOME
,
71 YAHOO_STATUS_OUTTOLUNCH
,
74 yahoohook::yahoohook() : abstracthook(yahoo
), fonline(false), cid(0) {
75 fcapabs
.insert(hookcapab::setaway
);
76 fcapabs
.insert(hookcapab::fetchaway
);
77 fcapabs
.insert(hookcapab::directadd
);
78 fcapabs
.insert(hookcapab::files
);
79 fcapabs
.insert(hookcapab::conferencing
);
80 fcapabs
.insert(hookcapab::conferencesaretemporary
);
81 fcapabs
.insert(hookcapab::ssl
);
83 pager_host
[0] = pager_port
[0] = filetransfer_host
[0] =
84 filetransfer_port
[0] = webcam_host
[0] = webcam_port
[0] =
88 yahoohook::~yahoohook() {
91 void yahoohook::init() {
92 manualstatus
= conf
->getstatus(proto
);
94 static struct yahoo_callbacks c
;
96 memset(&c
, 0, sizeof(c
));
98 c
.ext_yahoo_login_response
= &login_response
;
99 c
.ext_yahoo_got_buddies
= &got_buddies
;
100 c
.ext_yahoo_status_changed
= &status_changed
;
101 c
.ext_yahoo_got_im
= &got_im
;
102 c
.ext_yahoo_got_conf_invite
= &got_conf_invite
;
103 c
.ext_yahoo_conf_userdecline
= &conf_userdecline
;
104 c
.ext_yahoo_conf_userjoin
= &conf_userjoin
;
105 c
.ext_yahoo_conf_userleave
= &conf_userleave
;
106 c
.ext_yahoo_conf_message
= &conf_message
;
107 c
.ext_yahoo_got_file
= &got_file
;
108 c
.ext_yahoo_contact_added
= &contact_added
;
109 c
.ext_yahoo_game_notify
= &game_notify
;
110 c
.ext_yahoo_mail_notify
= &mail_notify
;
111 c
.ext_yahoo_system_message
= &system_message
;
112 c
.ext_yahoo_error
= &error
;
113 c
.ext_yahoo_add_handler
= &add_handler
;
114 c
.ext_yahoo_remove_handler
= &remove_handler
;
115 c
.ext_yahoo_connect_async
= &connect_async
;
116 c
.ext_yahoo_read
= &y_read
;
117 c
.ext_yahoo_write
= &y_write
;
118 c
.ext_yahoo_close
= &y_close
;
119 c
.ext_yahoo_got_identities
= &got_identities
;
120 c
.ext_yahoo_got_ignore
= &got_ignore
;
121 c
.ext_yahoo_got_cookies
= &got_cookies
;
122 c
.ext_yahoo_chat_cat_xml
= &chat_cat_xml
;
123 c
.ext_yahoo_chat_join
= &chat_join
;
124 c
.ext_yahoo_chat_userjoin
= &chat_userjoin
;
125 c
.ext_yahoo_chat_userleave
= &chat_userleave
;
126 c
.ext_yahoo_chat_message
= &chat_message
;
127 c
.ext_yahoo_rejected
= &rejected
;
128 c
.ext_yahoo_typing_notify
= &typing_notify
;
129 c
.ext_yahoo_got_webcam_image
= &got_webcam_image
;
130 c
.ext_yahoo_webcam_invite
= &webcam_invite
;
131 c
.ext_yahoo_webcam_invite_reply
= &webcam_invite_reply
;
132 c
.ext_yahoo_webcam_closed
= &webcam_closed
;
133 c
.ext_yahoo_webcam_viewer
= &webcam_viewer
;
134 c
.ext_yahoo_webcam_data_request
= &webcam_data_request
;
135 c
.ext_yahoo_got_search_result
= &got_search_result
;
136 c
.ext_yahoo_got_ping
= &got_ping
;
137 c
.ext_yahoo_log
= &ylog
;
138 c
.ext_yahoo_got_buddyicon_request
= &got_buddyicon_request
;
139 c
.ext_yahoo_got_buddyicon
= &got_buddyicon
;
140 c
.ext_yahoo_buddyicon_uploaded
= &buddyicon_uploaded
;
141 c
.ext_yahoo_chat_yahooerror
= &chat_yahooerror
;
142 c
.ext_yahoo_chat_yahoologout
= &chat_yahoologout
;
143 c
.ext_yahoo_connect
= &yahoo_connect
;
144 c
.ext_yahoo_file_transfer_done
= &file_transfer_done
;
145 c
.ext_yahoo_get_ip_addr
= &get_ip_addr
;
146 c
.ext_yahoo_got_buddy_change_group
= &got_buddy_change_group
;
147 c
.ext_yahoo_got_buddyicon_checksum
= &got_buddyicon_checksum
;
148 c
.ext_yahoo_got_buzz
= &got_buzz
;
149 c
.ext_yahoo_got_ft_data
= &got_ft_data
;
151 yahoo_register_callbacks(&c
);
154 void yahoohook::connect() {
155 icqconf::imaccount acc
= conf
->getourid(proto
);
165 cid
= yahoo_init_with_attributes(acc
.nickname
.c_str(), acc
.password
.c_str(),
166 "pager_host", acc
.server
.c_str(),
167 "pager_port", acc
.port
,
170 yahoo_login(cid
, stat2int
[manualstatus
]);
173 string msg
= _("+ [yahoo] cannot connect: ");
176 case -1: msg
+= _("could not resolve hostname"); break;
177 case -2: msg
+= _("could not create socket"); break;
178 default: msg
+= _("verify the pager host and port entered"); break;
188 void yahoohook::main() {
189 vector
<yfd
>::iterator i
;
198 tv
.tv_sec
= tv
.tv_usec
= 0;
201 for(i
= fds
.begin(); i
!= fds
.end(); ++i
) {
202 struct y_c ic
= i
->con
;
203 if (i
->cond
& YAHOO_INPUT_READ
)
205 if (i
->cond
& YAHOO_INPUT_WRITE
)
207 hsock
= max(hsock
, ic
.fd
);
210 if(select(hsock
+1, &rs
, &ws
, 0, &tv
) > 0) {
211 for(i
= fds
.begin(); i
!= fds
.end(); ++i
) {
213 if (!cw_nb_connect(i
->con
.fd
, NULL
, 0, i
->con
.ssl
, &i
->con
.state
))
215 if (i
->con
.state
& CW_CONNECT_WANT_SOMETHING
)
223 struct y_c tc
= i
->con
;
224 connect_complete(i
->data
, &tc
);
228 if(FD_ISSET(i
->con
.fd
, &rs
)) {
229 yahoo_read_ready(cid
, &i
->con
, i
->data
);
232 if(FD_ISSET(i
->con
.fd
, &ws
)) {
233 yahoo_write_ready(cid
, &i
->con
, i
->data
);
240 void yahoohook::getsockets(fd_set
&rs
, fd_set
&ws
, fd_set
&es
, int &hsocket
) const {
242 vector
<yfd
>::const_iterator i
;
244 for(i
= fds
.begin(); i
!= fds
.end(); ++i
) {
245 if (i
->cond
& YAHOO_INPUT_READ
)
246 FD_SET(i
->con
.fd
, &rs
);
247 if (i
->cond
& YAHOO_INPUT_WRITE
)
248 FD_SET(i
->con
.fd
, &ws
);
249 hsocket
= max(hsocket
, i
->con
.fd
);
254 bool yahoohook::isoursocket(fd_set
&rs
, fd_set
&ws
, fd_set
&es
) const {
255 vector
<yfd
>::const_iterator i
;
257 for(i
= fds
.begin(); i
!= fds
.end(); ++i
)
259 if(i
->cond
& YAHOO_INPUT_READ
&& FD_ISSET(i
->con
.fd
, &rs
))
262 if(i
->cond
& YAHOO_INPUT_WRITE
&& FD_ISSET(i
->con
.fd
, &ws
))
268 void yahoohook::disconnect() {
275 void yahoohook::disconnected() {
277 vector
<yfd
>::const_iterator i
;
278 for(i
= fds
.begin(); i
!= fds
.end(); ++i
)
285 logger
.putourstatus(proto
, getstatus(), ourstatus
= offline
);
286 clist
.setoffline(proto
);
288 log(logDisconnected
);
293 void yahoohook::exectimers() {
294 vector
<pair
<Action
, string
> >::iterator it
;
296 for(it
= tobedone
.begin(); it
!= tobedone
.end(); ++it
) {
299 /* TODO: investigate if copy is really needed here */
300 char *room
= strdup(it
->second
.c_str());
301 yahoo_conference_logon(cid
, 0, getmembers(it
->second
), room
);
310 if(timer_current
-timer_refresh
> PERIOD_REFRESH
) {
312 yahoo_keepalive(cid
);
313 timer_refresh
= timer_current
;
315 } else if(timer_close
&& timer_current
-timer_close
> PERIOD_CLOSE
) {
323 struct tm
*yahoohook::timestamp() {
324 return localtime(&timer_current
);
327 bool yahoohook::send(const imevent
&ev
) {
328 icqcontact
*c
= clist
.get(ev
.getcontact());
332 if(ev
.gettype() == imevent::message
) {
333 const immessage
*m
= static_cast<const immessage
*>(&ev
);
334 if(m
) text
= rushtmlconv("ku", m
->gettext());
336 } else if(ev
.gettype() == imevent::url
) {
337 const imurl
*m
= static_cast<const imurl
*>(&ev
);
338 if(m
) text
= rushtmlconv("ku", m
->geturl()) + "\n\n" + rusconv("kw", m
->getdescription());
340 } else if(ev
.gettype() == imevent::file
) {
341 const imfile
*m
= static_cast<const imfile
*>(&ev
);
342 vector
<imfile::record
> files
= m
->getfiles();
343 vector
<imfile::record
>::const_iterator ir
;
345 for(ir
= files
.begin(); ir
!= files
.end(); ++ir
) {
346 sfiles
.push_back(strdup(ir
->fname
.c_str()));
347 srfiles
[sfiles
.back()] = *m
;
349 yahoo_send_file(cid
, ev
.getcontact().nickname
.c_str(),
350 m
->getmessage().c_str(), justfname(ir
->fname
).c_str(),
351 ir
->size
, &get_fd
, sfiles
.back());
355 } else if (ev
.gettype() == imevent::authorization
) {
356 const imauthorization
*m
= static_cast<const imauthorization
*> (&ev
);
358 switch(m
->getauthtype()) {
359 case imauthorization::Granted
:
360 yahoo_confirm_buddy(cid
, ev
.getcontact().nickname
.c_str(), 0, 0);
363 case imauthorization::Rejected
:
364 yahoo_confirm_buddy(cid
, ev
.getcontact().nickname
.c_str(), 1, 0);
372 yahoo_send_im(cid
, 0, ev
.getcontact().nickname
.c_str(), text
.c_str(), 0, 0);
374 yahoo_conference_message(cid
, 0, getmembers(ev
.getcontact().nickname
.substr(1)),
375 ev
.getcontact().nickname
.c_str()+1, text
.c_str(), 0);
384 bool yahoohook::online() const {
388 bool yahoohook::logged() const {
389 return fonline
&& flogged
;
392 bool yahoohook::isconnecting() const {
393 return fonline
&& !flogged
;
396 void yahoohook::sendnewuser(const imcontact
&ic
) {
397 sendnewuser(ic
, true);
400 void yahoohook::sendnewuser(const imcontact
&ic
, bool report
) {
401 if(online() && !ischannel(ic
)) {
404 const YList
*buddies
= yahoo_get_buddylist(cid
);
405 const YList
*bud
= 0;
407 for(bud
= buddies
; bud
&& !found
; bud
= y_list_next(bud
))
408 found
= ic
.nickname
== static_cast<yahoo_buddy
*>(bud
->data
)->id
;
411 if(report
) log(logContactAdd
, ic
.nickname
.c_str());
414 vector
<icqgroup
>::const_iterator ig
= find(groups
.begin(), groups
.end(), clist
.get(ic
)->getgroupid());
415 if (ig
== groups
.end())
417 yahoo_add_buddy(cid
, ic
.nickname
.c_str(), ig
->getname().c_str(), "");
426 void yahoohook::removeuser(const imcontact
&ic
) {
427 removeuser(ic
, true);
430 void yahoohook::removeuser(const imcontact
&ic
, bool report
) {
433 if(report
) log(logContactRemove
, ic
.nickname
.c_str());
435 const YList
*buddies
= yahoo_get_buddylist(cid
);
436 const YList
*bud
= 0;
438 for(bud
= buddies
; bud
; bud
= y_list_next(bud
)) {
439 if(ic
.nickname
== ((yahoo_buddy
*) bud
->data
)->id
)
440 yahoo_remove_buddy(cid
,
441 ((yahoo_buddy
*) bud
->data
)->id
,
442 ((yahoo_buddy
*) bud
->data
)->group
);
446 face
.log(_("+ [yahoo] leaving the %s conference"),
447 ic
.nickname
.c_str());
449 yahoo_conference_logoff(cid
, 0, getmembers(ic
.nickname
.substr(1)), ic
.nickname
.c_str()+1);
454 imstatus
yahoohook::yahoo2imstatus(int status
) {
455 imstatus st
= offline
;
458 case YAHOO_STATUS_AVAILABLE
:
461 case YAHOO_STATUS_BUSY
:
464 case YAHOO_STATUS_CUSTOM
:
465 case YAHOO_STATUS_BRB
:
466 case YAHOO_STATUS_IDLE
:
467 case YAHOO_STATUS_ONPHONE
:
470 case YAHOO_STATUS_NOTATDESK
:
473 case YAHOO_STATUS_NOTATHOME
:
474 case YAHOO_STATUS_NOTINOFFICE
:
475 case YAHOO_STATUS_ONVACATION
:
476 case YAHOO_STATUS_STEPPEDOUT
:
479 case YAHOO_STATUS_OUTTOLUNCH
:
482 case YAHOO_STATUS_INVISIBLE
:
493 bool yahoohook::enabled() const {
497 void yahoohook::setautostatus(imstatus st
) {
499 if(getstatus() != offline
) {
503 if(getstatus() == offline
) {
507 logger
.putourstatus(proto
, getstatus(), ourstatus
= st
);
509 if(st
== freeforchat
) {
510 /* TODO copy should not be needed here ?*/
511 char *msg
= strdup("free for chat");
512 yahoo_set_away(cid
, (yahoo_status
) stat2int
[st
], msg
, 0);
515 } else if(st
!= away
) {
516 yahoo_set_away(cid
, (yahoo_status
) stat2int
[st
], 0, 0);
519 char *msg
= strdup(rusconv("ku", conf
->getawaymsg(proto
)).c_str());
520 yahoo_set_away(cid
, (yahoo_status
) stat2int
[st
], msg
, 1);
528 imstatus
yahoohook::getstatus() const {
529 return online() ? ourstatus
: offline
;
532 void yahoohook::requestinfo(const imcontact
&ic
) {
533 requestfromfound(ic
);
535 icqcontact
*c
= clist
.get(ic
);
536 if(!c
) c
= clist
.get(contactroot
);
538 icqcontact::moreinfo m
= c
->getmoreinfo();
539 icqcontact::basicinfo b
= c
->getbasicinfo();
541 m
.homepage
= "http://profiles.yahoo.com/" + ic
.nickname
;
542 b
.email
= ic
.nickname
+ "@yahoo.com";
548 void yahoohook::userstatus(const string
&nick
, int st
, const string
&message
, bool away
) {
549 imcontact
ic(nick
, proto
);
550 icqcontact
*c
= clist
.get(ic
);
552 awaymessages
[nick
] = rusconv("wk", message
);
555 c
= clist
.addnew(ic
, false);
559 logger
.putonline(ic
, c
->getstatus(), yahoo2imstatus(st
));
560 c
->setstatus(yahoo2imstatus(st
));
564 YList
*yahoohook::getmembers(const string
&room
) {
566 static YList
*smemb
= 0;
567 vector
<string
>::iterator ic
;
568 map
<string
, vector
<string
> >::iterator im
;
571 for(YList
*n
= smemb
; n
; n
= y_list_next(n
))
578 if((im
= confmembers
.find(room
)) != confmembers
.end())
579 for(ic
= im
->second
.begin(); ic
!= im
->second
.end(); ++ic
)
580 smemb
= y_list_append(smemb
, strdup(ic
->c_str()));
585 string
yahoohook::decode(string text
, bool utf
) {
588 text
= rushtmlconv(utf
? "uk" : "wk", text
);
590 while((npos
= text
.find("\e[")) != -1) {
591 if((mpos
= text
.substr(npos
).find("m")) == -1)
592 mpos
= text
.size()-npos
-1;
594 text
.erase(npos
, mpos
+1);
600 bool yahoohook::knowntransfer(const imfile
&fr
) const {
601 return fvalid
.find(fr
) != fvalid
.end();
604 void yahoohook::replytransfer(const imfile
&fr
, bool accept
, const string
&localpath
) {
606 string localname = localpath + "/";
607 localname += fr.getfiles()[0].fname;
608 sfiles.push_back(strdup(localname.c_str()));
609 srfiles[sfiles.back()] = fr;
610 yahoo_get_url_handle(cid, fvalid[fr].c_str(), &get_url, sfiles.back());
618 void yahoohook::aborttransfer(const imfile
&fr
) {
619 face
.transferupdate(fr
.getfiles().begin()->fname
, fr
, icqface::tsCancel
, 0, 0);
623 void yahoohook::lookup(const imsearchparams
¶ms
, verticalmenu
&dest
) {
626 vector
<string
>::const_iterator i
;
628 while(!foundguys
.empty()) {
629 delete foundguys
.back();
630 foundguys
.pop_back();
633 yahoo_search_gender gender
= YAHOO_GENDER_NONE
;
635 switch(params
.gender
) {
636 case genderMale
: gender
= YAHOO_GENDER_MALE
; break;
637 case genderFemale
: gender
= YAHOO_GENDER_FEMALE
; break;
640 searchonlineonly
= params
.onlineonly
;
643 if(!params
.kwords
.empty()) {
644 yahoo_search(cid
, YAHOO_SEARCH_KEYWORD
, decode(params
.kwords
, false).c_str(),
645 gender
, YAHOO_AGERANGE_NONE
, params
.photo
? 1 : 0, 1);
647 } else if(!params
.firstname
.empty()) {
648 yahoo_search(cid
, YAHOO_SEARCH_NAME
, decode(params
.firstname
, false).c_str(),
649 gender
, YAHOO_AGERANGE_NONE
, params
.photo
? 1 : 0, 1);
651 } else if(!params
.room
.empty()) {
652 room
= params
.room
.substr(1);
653 i
= confmembers
[room
].begin();
655 while(i
!= confmembers
[room
].end()) {
656 if(c
= clist
.get(imcontact(*i
, proto
)))
657 searchdest
->additem(conf
->getcolor(cp_clist_yahoo
),
658 c
, (string
) " " + *i
);
664 log(logConfMembers
, searchdest
->getcount());
666 searchdest
->redraw();
672 void yahoohook::conferencecreate(const imcontact
&confid
, const vector
<imcontact
> &lst
) {
674 string room
= confid
.nickname
.substr(1);
678 vector
<imcontact
>::const_iterator il
= lst
.begin();
679 while(il
!= lst
.end()) {
680 who
= y_list_append(who
, strdup(il
->nickname
.c_str()));
684 yahoo_conference_invite(cid
, 0, who
, room
.c_str(), _("Please join my conference."));
686 for(YList
*w
= who
; w
; w
= y_list_next(w
))
692 void yahoohook::requestawaymsg(const imcontact
&ic
) {
693 icqcontact
*c
= clist
.get(ic
);
696 if(awaymessages
.find(ic
.nickname
) != awaymessages
.end()) {
697 em
.store(imnotification(ic
, string() + _("Custom status message:") + "\n\n" +
698 awaymessages
[ic
.nickname
]));
701 face
.log(_("+ [yahoo] cannot fetch away msg from %s, %s (maybe no away msg set)"),
702 c
->getdispnick().c_str(), ic
.totext().c_str());
708 void yahoohook::checkinlist(imcontact ic
) {
710 icqcontact
*c
= clist
.get(ic
);
714 const YList
*buddies
= yahoo_get_buddylist(cid
);
716 for(const YList
*bud
= buddies
; bud
&& !found
; ) {
717 yahoo_buddy
*yb
= (yahoo_buddy
*) bud
->data
;
718 found
= (c
->getdesc().nickname
== yb
->id
);
719 bud
= y_list_next(bud
);
722 if(!found
) sendnewuser(ic
, false);
726 void yahoohook::updatecontact(icqcontact
*c
) {
727 if(logged() && conf
->getgroupmode() != icqconf::nogroups
) {
729 const YList
*buddies
= yahoo_get_buddylist(cid
);
730 string newgroupname
= groups
.getname(c
->getgroupid());
732 for(const YList
*bud
= buddies
; bud
; ) {
733 yahoo_buddy
*yb
= (yahoo_buddy
*) bud
->data
;
735 if(c
->getdesc().nickname
== yb
->id
) {
737 if(newgroupname
!= yb
->group
)
738 yahoo_change_buddy_group(cid
, yb
->id
, yb
->group
, newgroupname
.c_str());
742 yahoo_remove_buddy(cid
, yb
->id
, yb
->group
);
746 bud
= y_list_next(bud
);
751 void yahoohook::renamegroup(const string
&oldname
, const string
&newname
) {
753 string tempname
= oldname
+ "___" + i2str(getpid()) + "_temp";
754 yahoo_group_rename(cid
, oldname
.c_str(), tempname
.c_str());
755 yahoo_group_rename(cid
, tempname
.c_str(), newname
.c_str());
759 // ----------------------------------------------------------------------------
761 void yahoohook::login_response(int id
, int succ
, const char *url
) {
762 vector
<string
>::iterator in
;
766 yhook
.flogged
= true;
767 logger
.putourstatus(yahoo
, offline
, yhook
.ourstatus
= yhook
.manualstatus
);
768 yhook
.log(logLogged
);
769 time(&yhook
.timer_refresh
);
770 yhook
.setautostatus(yhook
.manualstatus
);
771 yhook
.timer_close
= 0;
774 case YAHOO_LOGIN_LOGOFF
:
775 yhook
.fonline
= yhook
.fonline
= false;
776 yahoo_close(yhook
.cid
);
777 face
.log(_("+ [yahoo] cannot login"));
780 case YAHOO_LOGIN_PASSWD
:
781 yhook
.fonline
= yhook
.fonline
= false;
782 yahoo_close(yhook
.cid
);
783 face
.log(_("+ [yahoo] cannot login: username and password mismatch"));
786 case YAHOO_LOGIN_UNAME
:
787 yhook
.fonline
= yhook
.fonline
= false;
788 yahoo_close(yhook
.cid
);
789 face
.log(_("+ [yahoo] cannot login: username doesn't exist"));
792 case YAHOO_LOGIN_LOCK
:
793 yhook
.fonline
= yhook
.fonline
= false;
794 yahoo_close(yhook
.cid
);
795 face
.log(_("+ [yahoo] cannot login: the account has been blocked"));
796 face
.log(_("+ to reactivate visit %s"), url
);
799 case YAHOO_LOGIN_DUPL
:
800 face
.log(_("+ [yahoo] another logon detected"));
801 yahoo_logoff(yhook
.cid
);
802 yhook
.manualstatus
= offline
;
805 case YAHOO_LOGIN_UNKNOWN
:
806 case YAHOO_LOGIN_SOCK
:
807 face
.log(_("+ [yahoo] server closed socket"));
808 yhook
.disconnected();
815 void yahoohook::got_buddies(int id
, YList
*buds
) {
818 for(buddy
= buds
; buddy
; buddy
= y_list_next(buddy
)) {
819 yahoo_buddy
*bud
= static_cast<yahoo_buddy
*>(buddy
->data
);
821 clist
.updateEntry(imcontact(bud
->id
, yahoo
), bud
->group
? bud
->group
: "");
825 void yahoohook::got_identities(int id
, YList
*buds
) {
828 void yahoohook::status_changed(int id
, const char *who
, int stat
, const char *msg
, int away
, int idle
, int mobile
) {
829 yhook
.userstatus(who
, stat
, msg
? msg
: "", (bool) away
);
832 void yahoohook::got_im(int id
, const char *me
, const char *who
, const char *msg
, long tm
, int stat
, int utf8
) {
833 imcontact
ic(who
, yahoo
);
834 string text
= cuthtml(msg
, chCutBR
| chLeaveLinks
);
836 yhook
.checkinlist(ic
);
837 text
= yhook
.decode(text
, utf8
);
840 em
.store(immessage(ic
, imevent::incoming
, text
, tm
));
844 void yahoohook::got_search_result(int id
, int found
, int start
, int total
, YList
*contacts
) {
845 yahoo_found_contact
*fc
;
850 if(!yhook
.searchdest
)
853 for(ir
= contacts
; ir
; ir
= ir
->next
) {
854 fc
= (yahoo_found_contact
*) ir
->data
;
856 if(yhook
.searchonlineonly
&& !fc
->online
)
859 c
= new icqcontact(imcontact(fc
->id
, yahoo
));
861 icqcontact::basicinfo binfo
= c
->getbasicinfo();
862 icqcontact::moreinfo minfo
= c
->getmoreinfo();
864 if(!fc
->id
|| !fc
->gender
)
868 c
->setdispnick(c
->getnick());
871 if(sg
== "MALE") minfo
.gender
= genderMale
;
872 else if(sg
== "FEMALE") minfo
.gender
= genderFemale
;
875 if(fc
->location
) binfo
.street
= fc
->location
;
877 line
= (fc
->online
? "o " : " ") + c
->getnick();
879 if(fc
->age
|| fc
->location
|| strlen(fc
->gender
) >= 4) {
881 if(fc
->age
) line
+= i2str(fc
->age
);
883 if(strlen(fc
->gender
) >= 4) {
884 if(fc
->age
) line
+= ", ";
888 if(fc
->location
&& strlen(fc
->location
)) {
889 if(fc
->age
|| strlen(fc
->gender
) >= 4) line
+= ", ";
890 line
+= fc
->location
;
896 c
->setbasicinfo(binfo
);
897 c
->setmoreinfo(minfo
);
899 yhook
.foundguys
.push_back(c
);
900 yhook
.searchdest
->additem(conf
->getcolor(cp_clist_yahoo
), c
, line
);
903 yhook
.searchdest
->redraw();
905 if(start
+ found
>= total
) {
907 yhook
.log(logSearchFinished
, yhook
.foundguys
.size());
908 yhook
.searchdest
= 0;
910 yahoo_search_again(yhook
.cid
, -1);
914 void yahoohook::got_conf_invite(int id
, const char *me
, const char *who
, const char *room
, const char *msg
, YList
*members
) {
915 icqconf::imaccount acc
= conf
->getourid(yahoo
);
916 string confname
= (string
) "#" + room
, inviter
, text
;
917 vector
<string
>::iterator ic
;
921 imcontact
cont(confname
, yahoo
);
922 icqcontact
*c
= clist
.get(cont
);
923 if(!c
) c
= clist
.addnew(cont
);
925 inviter
= confname
.substr(1);
926 if((i
= inviter
.rfind("-")) != -1) {
930 snprintf(buf
, NOTIFBUF
, _("The user %s has invited you to the %s conference, the topic there is: %s"),
931 yhook
.rusconv("wk", inviter
).c_str(),
932 yhook
.rusconv("wk", room
).c_str(),
933 yhook
.rusconv("wk", msg
).c_str());
935 text
= (string
) buf
+ "\n\n" + _("Current conference members are: ");
936 yhook
.confmembers
[room
].push_back(inviter
);
938 for(YList
*m
= members
; m
; m
= y_list_next(m
)) {
939 string id
= (char *) m
->data
;
941 if(id
!= acc
.nickname
)
942 if(find(yhook
.confmembers
[room
].begin(), yhook
.confmembers
[room
].end(), id
) == yhook
.confmembers
[room
].end()) {
943 yhook
.confmembers
[room
].push_back(id
);
947 for(ic
= yhook
.confmembers
[room
].begin(); ic
!= yhook
.confmembers
[room
].end(); ) {
949 if(++ic
!= yhook
.confmembers
[room
].end())
953 c
->setstatus(available
);
954 em
.store(imnotification(cont
, text
));
955 em
.store(imnotification(cont
, _("Auto-joined the conference")));
957 yhook
.tobedone
.push_back(make_pair(tbdConfLogon
, room
));
960 void yahoohook::conf_userdecline(int id
, const char *me
, const char *who
, const char *room
, const char *msg
) {
961 icqcontact
*c
= clist
.get(imcontact((string
) "#" + room
, yahoo
));
965 snprintf(buf
, NOTIFBUF
, _("The user %s has declined your invitation to join the conference"), who
);
966 em
.store(imnotification(c
, buf
));
970 void yahoohook::conf_userjoin(int id
, const char *me
, const char *who
, const char *room
) {
971 icqcontact
*c
= clist
.get(imcontact((string
) "#" + room
, yahoo
));
975 snprintf(buf
, NOTIFBUF
, _("The user %s has joined the conference"), who
);
977 if(find(yhook
.confmembers
[room
].begin(), yhook
.confmembers
[room
].end(), who
) == yhook
.confmembers
[room
].end())
978 yhook
.confmembers
[room
].push_back(who
);
980 em
.store(imnotification(c
, buf
));
984 void yahoohook::conf_userleave(int id
, const char *me
, const char *who
, const char *room
) {
985 icqcontact
*c
= clist
.get(imcontact((string
) "#" + room
, yahoo
));
987 vector
<string
>::iterator im
;
990 snprintf(buf
, NOTIFBUF
, _("The user %s has left the conference"), who
);
991 em
.store(imnotification(c
, buf
));
993 im
= find(yhook
.confmembers
[room
].begin(), yhook
.confmembers
[room
].end(), who
);
994 if(im
!= yhook
.confmembers
[room
].end()) yhook
.confmembers
[room
].erase(im
);
998 void yahoohook::conf_message(int id
, const char *me
, const char *who
, const char *room
, const char *msg
, int utf8
) {
999 icqcontact
*c
= clist
.get(imcontact((string
) "#" + room
, yahoo
));
1001 string text
= (string
) who
+ ": " + cuthtml(msg
, chCutBR
| chLeaveLinks
);
1002 text
= yhook
.decode(text
, utf8
);
1004 if(c
) em
.store(immessage(c
, imevent::incoming
, text
));
1007 void yahoohook::got_file(int id
, const char *me
, const char *who
, const char *msg
, const char *fname
, unsigned long fesize
, char *trid
) {
1008 if(!who
|| !fname
|| !trid
)
1015 if(!fesize
) r
.size
= -1;
1017 if((pos
= r
.fname
.find('?')) != -1)
1020 imfile
fr(imcontact(who
, yahoo
), imevent::incoming
, "",
1021 vector
<imfile::record
>(1, r
));
1023 yhook
.fvalid
[fr
] = trid
;
1026 face
.transferupdate(fname
, fr
, icqface::tsInit
, fesize
, 0);
1029 void yahoohook::contact_added(int id
, const char *myid
, const char *who
, const char *msg
) {
1030 string text
= _("The user has added you to his/her contact list");
1034 text
+= (string
) ", " + _("the message was: ") + msg
;
1037 em
.store(imnotification(imcontact(who
, yahoo
), text
));
1040 void yahoohook::typing_notify(int id
, const char *me
, const char *who
, int stat
) {
1041 icqcontact
*c
= clist
.get(imcontact(who
, yahoo
));
1042 if(c
) c
->setlasttyping(stat
? timer_current
: 0);
1045 void yahoohook::game_notify(int id
, const char *me
, const char *who
, int stat
, const char *msg
) {
1048 void yahoohook::mail_notify(int id
, const char *from
, const char *subj
, int cnt
) {
1052 snprintf(buf
, NOTIFBUF
, _("+ [yahoo] e-mail from %s, %s"), from
, subj
);
1054 clist
.get(contactroot
)->playsound(imevent::email
);
1058 void yahoohook::system_message(int id
, const char *me
, const char *who
, const char *msg
) {
1059 face
.log(_("+ [yahoo] system (%s): %s"), who
, msg
);
1062 void yahoohook::got_ping(int id
, const char *msg
) {
1063 // face.log(_("+ [yahoo] ping: %s"), msg);
1066 void yahoohook::error(int id
, const char *err
, int fatal
, int num
) {
1068 face
.log(_("+ [yahoo] fatal error: %s"), err
);
1069 yhook
.disconnected();
1072 face
.log(_("[yahoo] error %s"), err
);
1076 int yahoohook::add_handler(int id
, void *fd
, yahoo_input_condition cond
, void *data
) {
1078 struct y_c
*con
= (struct y_c
*)fd
;
1080 yhook
.fds
.push_back(yfd(con
->fd
, data
, con
->ssl
, cond
));
1081 tag
= yhook
.fds
.back().tag
;
1086 void yahoohook::remove_handler(int id
, int tag
) {
1087 vector
<yfd
>::iterator i
;
1089 i
= find(yhook
.fds
.begin(), yhook
.fds
.end(), tag
);
1090 if(i
!= yhook
.fds
.end())
1094 int yahoohook::connect_async(int id
, const char *host
, int port
, yahoo_connect_callback callback
, void *data
, int use_ssl
) {
1095 struct sockaddr_in serv_addr
;
1096 static struct hostent
*server
;
1098 struct connect_callback_data
* ccd
;
1101 if(!(server
= gethostbyname(host
))) {
1106 if((servfd
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0) {
1110 memset(&serv_addr
, 0, sizeof(serv_addr
));
1111 serv_addr
.sin_family
= AF_INET
;
1112 memcpy(&serv_addr
.sin_addr
.s_addr
, *server
->h_addr_list
, server
->h_length
);
1113 serv_addr
.sin_port
= htons(port
);
1117 struct y_c
*con
= new struct y_c(servfd
, use_ssl
, state
);
1118 error
= cw_nb_connect(servfd
, (struct sockaddr
*) &serv_addr
, sizeof(serv_addr
), use_ssl
, &state
);
1121 if(!error
&& !state
) {
1122 int f
= fcntl(servfd
, F_GETFL
);
1123 fcntl(servfd
, F_SETFL
, f
| O_NONBLOCK
);
1124 callback(con
, 0, data
);
1126 } else if((error
== -1 && errno
== EINPROGRESS
) || (state
& CW_CONNECT_STARTED
)){
1127 ccd
= new connect_callback_data
;
1128 ccd
->callback
= callback
;
1129 ccd
->callback_data
= data
;
1132 ccd
->tag
= add_handler(id
, con
, YAHOO_INPUT_WRITE
, ccd
);
1137 callback(NULL
, 0, data
);
1144 void yahoohook::connect_complete(void *data
, struct y_c
*con
) {
1145 connect_callback_data
*ccd
= (connect_callback_data
*) data
;
1147 socklen_t err_size
= sizeof(so_error
);
1149 remove_handler(0, ccd
->tag
);
1150 if(getsockopt(con
->fd
, SOL_SOCKET
, SO_ERROR
, (char *) &so_error
, &err_size
) == -1 || so_error
!= 0) {
1152 face
.log(_("+ [yahoo] direct connection failed"));
1156 ccd
->callback(con
, so_error
, ccd
->callback_data
);
1162 int yahoohook::y_write(void *fd
, char *buf
, int len
)
1166 struct y_c
*con
= (struct y_c
*)fd
;
1167 return cw_write(con
->fd
, buf
, len
, con
->ssl
);
1170 int yahoohook::y_read(void *fd
, char *buf
, int len
)
1174 struct y_c
*con
= (struct y_c
*)fd
;
1175 return cw_read(con
->fd
, buf
, len
, con
->ssl
);
1179 void yahoohook::y_close(void *fd
)
1181 struct y_c
*con
= (struct y_c
*)fd
;
1186 void yahoohook::got_ignore(int id
, YList
* igns
) {
1189 void yahoohook::got_cookies(int id
) {
1192 void yahoohook::chat_cat_xml(int id
, const char *xml
) {
1193 face
.log(_("+ [yahoo] chat_cat_xml"));
1196 void yahoohook::chat_join(int id
, const char *me
, const char *room
, const char *topic
, YList
*members
, void *fd
) {
1197 face
.log(_("+ [yahoo] chat_join"));
1200 void yahoohook::chat_userjoin(int id
, const char *me
, const char *room
, struct yahoo_chat_member
*who
) {
1201 face
.log(_("+ [yahoo] chat_userjoin"));
1204 void yahoohook::chat_userleave(int id
, const char *me
, const char *room
, const char *who
) {
1205 face
.log(_("+ [yahoo] chat_userleave"));
1208 void yahoohook::chat_message(int id
, const char *me
, const char *who
, const char *room
, const char *msg
, int msgtype
, int utf8
) {
1209 face
.log(_("+ [yahoo] chat_message from %s"), who
);
1212 void yahoohook::rejected(int id
, const char *who
, const char *msg
) {
1213 face
.log(_("+ [yahoo] rejected by %s: %s"), who
, msg
);
1216 void yahoohook::got_webcam_image(int id
, const char * who
, const unsigned char *image
, unsigned int image_size
, unsigned int real_size
, unsigned int timestamp
) {
1219 void yahoohook::webcam_invite(int id
, const char *me
, const char *from
) {
1222 void yahoohook::webcam_invite_reply(int id
, const char *me
, const char *from
, int accept
) {
1225 void yahoohook::webcam_closed(int id
, const char *who
, int reason
) {
1228 void yahoohook::webcam_viewer(int id
, const char *who
, int connect
) {
1231 void yahoohook::webcam_data_request(int id
, int send
) {
1234 void yahoohook::got_buddyicon_request(int id
, const char *me
, const char *who
) {
1237 void yahoohook::got_buddyicon(int id
, const char *me
, const char *who
, const char *url
, int checksum
) {
1240 void yahoohook::buddyicon_uploaded(int id
, const char *url
) {
1243 void yahoohook::chat_yahooerror(int id
, const char *me
) {
1244 face
.log(_("+ [yahoo] chat_yahooerror"));
1247 void yahoohook::chat_yahoologout(int id
, const char *me
) {
1248 face
.log(_("+ [yahoo] chat_yahoologout"));
1251 int yahoohook::yahoo_connect(const char *host
, int port
) {
1252 face
.log(_("+ [yahoo] yahoo connect"));
1256 void yahoohook::file_transfer_done(int id
, int result
, void *data
) {
1259 char *yahoohook::get_ip_addr(const char *domain
) {
1260 face
.log(_("+ [yahoo] get_ip_addr %s"), domain
);
1264 void yahoohook::got_buddy_change_group(int id
, const char *me
, const char *who
, const char *old_group
, const char *new_group
) {
1265 face
.log(_("+ [yahoo] yahoo buddy_change_group %s from %s to %s"), who
, old_group
, new_group
);
1268 void yahoohook::got_buddyicon_checksum(int id
, char const *me
, const char *who
, int checksum
) {
1271 void yahoohook::got_buzz(int id
, const char *me
, const char *who
, long tm
) {
1272 face
.log(_("+ [yahoo] got buzz from %s"), who
);
1275 void yahoohook::got_ft_data(int id
, const unsigned char *in
, int len
, void *data
) {
1278 void yahoohook::auth_request(int id
, char *who
, char *msg
) {
1279 imcontact
ic(who
, yahoo
);
1280 string text
= cuthtml(msg
?msg
: "", chCutBR
| chLeaveLinks
);
1282 yhook
.checkinlist(ic
);
1283 text
= yhook
.decode(text
, true);
1285 em
.store(imauthorization(ic
, imevent::incoming
, imauthorization::Request
, text
));
1288 void yahoohook::auth_response(int id
, const char *who
, char granted
, const char *msg
) {
1289 imcontact
ic(who
, yahoo
);
1290 string text
= cuthtml(msg
?msg
:"", chCutBR
| chLeaveLinks
);
1292 //yhook.checkinlist(ic);
1293 text
= yhook
.decode(text
, true);
1296 message
= "The user has accepted your authorization request";
1299 message
= "The user has rejected your authorization request";
1308 em
.store(imnotification(ic
, message
));
1311 int yahoohook::ylog(const char *fmt
, ...) {
1312 if(conf
->getdebug()) {
1317 vsnprintf(buf
, NOTIFBUF
, fmt
, ap
);
1326 void yahoohook::get_fd(int id
, void *fd
, int error
, void *data
) {
1327 const char *fname
= (const char *) data
;
1328 struct y_c
*con
= (struct y_c
*)fd
;
1338 cw_write(con
->fd
, buf
, f
.tellg(), con
->ssl
);
1345 map
<const char *, imfile
>::iterator ir
= yhook
.srfiles
.find(fname
);
1346 if(ir
!= yhook
.srfiles
.end()) {
1347 face
.transferupdate(fname
, ir
->second
,
1348 error
? icqface::tsError
: icqface::tsFinish
,
1351 yhook
.srfiles
.erase(ir
);
1354 vector
<char *>::iterator i
= find(yhook
.sfiles
.begin(), yhook
.sfiles
.end(), fname
);
1355 if(i
!= yhook
.sfiles
.end()) {
1357 yhook
.sfiles
.erase(i
);
1361 void yahoohook::get_url(int id
, int fd
, int error
, const char *filename
, unsigned long size
, void *data
) {
1363 const char *localname
= (const char *) data
;
1366 vector
<char *>::iterator i
= find(yhook
.sfiles
.begin(), yhook
.sfiles
.end(), localname
);
1367 if(i
!= yhook
.sfiles
.end()) {
1368 ofstream
f(localname
);
1373 FILE *fp
= fdopen(fd
, "r");
1376 r
= fread(buf
, 1, 1024, fp
);
1377 if(r
> 0) f
.write(buf
, r
);
1388 yhook
.sfiles
.erase(i
);
1392 map
<const char *, imfile
>::iterator ir
= yhook
.srfiles
.find(localname
);
1393 if(ir
!= yhook
.srfiles
.end()) {
1394 face
.transferupdate(justfname(localname
), ir
->second
,
1395 error
? icqface::tsError
: icqface::tsFinish
,
1398 yhook
.srfiles
.erase(ir
);