2 * libyahoo2: libyahoo2.c
4 * Some code copyright (C) 2002-2004, Philip S Tellis <philip.tellis AT gmx.net>
6 * Yahoo Search copyright (C) 2003, Konstantin Klyagin <konst AT konst.org.ua>
8 * Much of this code was taken and adapted from the yahoo module for
9 * gaim released under the GNU GPL. This code is also released under the
12 * This code is derivitive of Gaim <http://gaim.sourceforge.net>
13 * copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
14 * 1998-1999, Adam Fritzler <afritz@marko.net>
15 * 1998-2002, Rob Flynn <rob@marko.net>
16 * 2000-2002, Eric Warmenhoven <eric@warmenhoven.org>
17 * 2001-2002, Brian Macke <macke@strangelove.net>
18 * 2001, Anand Biligiri S <abiligiri@users.sf.net>
19 * 2001, Valdis Kletnieks
20 * 2002, Sean Egan <bj91704@binghamton.edu>
21 * 2002, Toby Gray <toby.gray@ntlworld.com>
23 * This library also uses code from other libraries, namely:
24 * Portions from libfaim copyright 1998, 1999 Adam Fritzler
26 * Portions of Sylpheed copyright 2000-2002 Hiroyuki Yamamoto
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
40 * You should have received a copy of the GNU General Public License
41 * along with this program; if not, write to the Free Software
42 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
54 #include <curl/curl.h>
61 # define strrchr rindex
63 char *strchr (), *strrchr ();
65 # define memcpy(d, s, n) bcopy ((s), (d), (n))
66 # define memmove(d, s, n) bcopy ((s), (d), (n))
70 #include <sys/types.h>
73 # include <winsock2.h>
74 # define write(a,b,c) send(a,b,c,0)
75 # define read(a,b,c) recv(a,b,c,0)
84 #include "yahoo_httplib.h"
85 #include "yahoo_util.h"
86 #include "yahoo_auth.h"
88 #include "yahoo2_callbacks.h"
89 #include "yahoo_debug.h"
91 #define snprintf _snprintf
92 #define vsnprintf _vsnprintf
95 #ifdef USE_STRUCT_CALLBACKS
96 struct yahoo_callbacks
*yc
=NULL
;
98 static int yahoo_send_data(int fd
, void *data
, int len
);
100 void yahoo_register_callbacks(struct yahoo_callbacks
* tyc
)
105 #define YAHOO_CALLBACK(x) yc->x
107 #define YAHOO_CALLBACK(x) x
110 char *curl_buffer
= NULL
;
111 size_t curl_buffer_size
= 0;
113 size_t yahoo_handle_curl_write(void *ptr
, size_t size
, size_t nmemb
, void *stream
)
115 if (curl_buffer
== NULL
)
117 curl_buffer
= malloc(size
*nmemb
);
118 curl_buffer_size
= 0;
122 curl_buffer
= realloc(curl_buffer
, curl_buffer_size
+ size
*nmemb
);
124 memcpy(curl_buffer
+ curl_buffer_size
, ptr
, size
*nmemb
);
125 curl_buffer_size
+= size
*nmemb
;
129 int yahoo_log_message(char * fmt
, ...)
134 vsnprintf(out
, sizeof(out
), fmt
, ap
);
136 return YAHOO_CALLBACK(ext_yahoo_log
)("%s", out
);
139 int yahoo_connect(char * host
, int port
)
141 return YAHOO_CALLBACK(ext_yahoo_connect
)(host
, port
);
144 static enum yahoo_log_level log_level
= YAHOO_LOG_WARNING
;
146 enum yahoo_log_level
yahoo_get_log_level()
151 int yahoo_set_log_level(enum yahoo_log_level level
)
153 enum yahoo_log_level l
= log_level
;
158 /* default values for servers */
159 static char pager_host
[] = "scs.msg.yahoo.com";
160 static int pager_port
= 5050;
161 static int fallback_ports
[]={23, 25, 80, 20, 119, 8001, 8002, 5050, 0};
162 static char filetransfer_host
[]="filetransfer.msg.yahoo.com";
163 static int filetransfer_port
=80;
164 static char webcam_host
[]="webcam.yahoo.com";
165 static int webcam_port
=5100;
166 static char webcam_description
[]="";
167 static char local_host
[]="";
168 static int conn_type
=Y_WCM_DSL
;
170 static char profile_url
[] = "http://profiles.yahoo.com/";
172 enum yahoo_service
{ /* these are easier to see in hex */
173 YAHOO_SERVICE_LOGON
= 1,
174 YAHOO_SERVICE_LOGOFF
,
175 YAHOO_SERVICE_ISAWAY
,
176 YAHOO_SERVICE_ISBACK
,
177 YAHOO_SERVICE_IDLE
, /* 5 (placemarker) */
178 YAHOO_SERVICE_MESSAGE
,
180 YAHOO_SERVICE_IDDEACT
,
181 YAHOO_SERVICE_MAILSTAT
,
182 YAHOO_SERVICE_USERSTAT
, /* 0xa */
183 YAHOO_SERVICE_NEWMAIL
,
184 YAHOO_SERVICE_CHATINVITE
,
185 YAHOO_SERVICE_CALENDAR
,
186 YAHOO_SERVICE_NEWPERSONALMAIL
,
187 YAHOO_SERVICE_NEWCONTACT
,
188 YAHOO_SERVICE_ADDIDENT
, /* 0x10 */
189 YAHOO_SERVICE_ADDIGNORE
,
191 YAHOO_SERVICE_GOTGROUPRENAME
, /* < 1, 36(old), 37(new) */
192 YAHOO_SERVICE_SYSMESSAGE
= 0x14,
193 YAHOO_SERVICE_PASSTHROUGH2
= 0x16,
194 YAHOO_SERVICE_CONFINVITE
= 0x18,
195 YAHOO_SERVICE_CONFLOGON
,
196 YAHOO_SERVICE_CONFDECLINE
,
197 YAHOO_SERVICE_CONFLOGOFF
,
198 YAHOO_SERVICE_CONFADDINVITE
,
199 YAHOO_SERVICE_CONFMSG
,
200 YAHOO_SERVICE_CHATLOGON
,
201 YAHOO_SERVICE_CHATLOGOFF
,
202 YAHOO_SERVICE_CHATMSG
= 0x20,
203 YAHOO_SERVICE_GAMELOGON
= 0x28,
204 YAHOO_SERVICE_GAMELOGOFF
,
205 YAHOO_SERVICE_GAMEMSG
= 0x2a,
206 YAHOO_SERVICE_FILETRANSFER
= 0x46,
207 YAHOO_SERVICE_VOICECHAT
= 0x4A,
208 YAHOO_SERVICE_NOTIFY
,
209 YAHOO_SERVICE_VERIFY
,
210 YAHOO_SERVICE_P2PFILEXFER
,
211 YAHOO_SERVICE_PEERTOPEER
= 0x4F, /* Checks if P2P possible */
212 YAHOO_SERVICE_WEBCAM
,
213 YAHOO_SERVICE_AUTHRESP
= 0x54,
215 YAHOO_SERVICE_AUTH
= 0x57,
216 YAHOO_SERVICE_ADDBUDDY
= 0x83,
217 YAHOO_SERVICE_REMBUDDY
,
218 YAHOO_SERVICE_IGNORECONTACT
, /* > 1, 7, 13 < 1, 66, 13, 0*/
219 YAHOO_SERVICE_REJECTCONTACT
,
220 YAHOO_SERVICE_GROUPRENAME
= 0x89, /* > 1, 65(new), 66(0), 67(old) */
221 YAHOO_SERVICE_CHATONLINE
= 0x96, /* > 109(id), 1, 6(abcde) < 0,1*/
222 YAHOO_SERVICE_CHATGOTO
,
223 YAHOO_SERVICE_CHATJOIN
, /* > 1 104-room 129-1600326591 62-2 */
224 YAHOO_SERVICE_CHATLEAVE
,
225 YAHOO_SERVICE_CHATEXIT
= 0x9b,
226 YAHOO_SERVICE_CHATLOGOUT
= 0xa0,
227 YAHOO_SERVICE_CHATPING
,
228 YAHOO_SERVICE_COMMENT
= 0xa8,
229 YAHOO_SERVICE_STEALTH
= 0xb9,
230 YAHOO_SERVICE_PICTURE_CHECKSUM
= 0xbd,
231 YAHOO_SERVICE_PICTURE
= 0xbe,
232 YAHOO_SERVICE_PICTURE_UPDATE
= 0xc1,
233 YAHOO_SERVICE_PICTURE_UPLOAD
= 0xc2,
234 YAHOO_SERVICE_Y6_STATUS_UPDATE
= 0xc6,
235 YAHOO_SERVICE_AUTH_REQ_15
= 0xd6,
236 YAHOO_SERVICE_STATUS_15
= 0xf0,
237 YAHOO_SERVICE_LIST_15
= 0xf1
245 struct yahoo_packet
{
246 unsigned short int service
;
252 struct yahoo_search_state
{
256 int lsearch_agerange
;
258 int lsearch_yahoo_only
;
265 unsigned char *queue
;
269 struct yahoo_input_data
{
270 struct yahoo_data
*yd
;
271 struct yahoo_webcam
*wcm
;
272 struct yahoo_webcam_data
*wcd
;
273 struct yahoo_search_state
*ys
;
276 enum yahoo_connection_type type
;
278 unsigned char *rxqueue
;
286 struct yahoo_server_settings
{
289 char *filetransfer_host
;
290 int filetransfer_port
;
293 char *webcam_description
;
298 struct yahoo_add_request
{
304 static void * _yahoo_default_server_settings()
306 struct yahoo_server_settings
*yss
= y_new0(struct yahoo_server_settings
, 1);
308 yss
->pager_host
= strdup(pager_host
);
309 yss
->pager_port
= pager_port
;
310 yss
->filetransfer_host
= strdup(filetransfer_host
);
311 yss
->filetransfer_port
= filetransfer_port
;
312 yss
->webcam_host
= strdup(webcam_host
);
313 yss
->webcam_port
= webcam_port
;
314 yss
->webcam_description
= strdup(webcam_description
);
315 yss
->local_host
= strdup(local_host
);
316 yss
->conn_type
= conn_type
;
321 static void * _yahoo_assign_server_settings(va_list ap
)
323 struct yahoo_server_settings
*yss
= _yahoo_default_server_settings();
329 key
= va_arg(ap
, char *);
333 if(!strcmp(key
, "pager_host")) {
334 svalue
= va_arg(ap
, char *);
335 free(yss
->pager_host
);
336 yss
->pager_host
= strdup(svalue
);
337 } else if(!strcmp(key
, "pager_port")) {
338 nvalue
= va_arg(ap
, int);
339 yss
->pager_port
= nvalue
;
340 } else if(!strcmp(key
, "filetransfer_host")) {
341 svalue
= va_arg(ap
, char *);
342 free(yss
->filetransfer_host
);
343 yss
->filetransfer_host
= strdup(svalue
);
344 } else if(!strcmp(key
, "filetransfer_port")) {
345 nvalue
= va_arg(ap
, int);
346 yss
->filetransfer_port
= nvalue
;
347 } else if(!strcmp(key
, "webcam_host")) {
348 svalue
= va_arg(ap
, char *);
349 free(yss
->webcam_host
);
350 yss
->webcam_host
= strdup(svalue
);
351 } else if(!strcmp(key
, "webcam_port")) {
352 nvalue
= va_arg(ap
, int);
353 yss
->webcam_port
= nvalue
;
354 } else if(!strcmp(key
, "webcam_description")) {
355 svalue
= va_arg(ap
, char *);
356 free(yss
->webcam_description
);
357 yss
->webcam_description
= strdup(svalue
);
358 } else if(!strcmp(key
, "local_host")) {
359 svalue
= va_arg(ap
, char *);
360 free(yss
->local_host
);
361 yss
->local_host
= strdup(svalue
);
362 } else if(!strcmp(key
, "conn_type")) {
363 nvalue
= va_arg(ap
, int);
364 yss
->conn_type
= nvalue
;
366 WARNING(("Unknown key passed to yahoo_init, "
367 "perhaps you didn't terminate the list "
375 static void yahoo_free_server_settings(struct yahoo_server_settings
*yss
)
380 free(yss
->pager_host
);
381 free(yss
->filetransfer_host
);
382 free(yss
->webcam_host
);
383 free(yss
->webcam_description
);
384 free(yss
->local_host
);
389 static YList
*conns
=NULL
;
390 static YList
*inputs
=NULL
;
391 static int last_id
=0;
393 static void add_to_list(struct yahoo_data
*yd
)
395 conns
= y_list_prepend(conns
, yd
);
397 static struct yahoo_data
* find_conn_by_id(int id
)
400 for(l
= conns
; l
; l
= y_list_next(l
)) {
401 struct yahoo_data
*yd
= l
->data
;
402 if(yd
->client_id
== id
)
407 static void del_from_list(struct yahoo_data
*yd
)
409 conns
= y_list_remove(conns
, yd
);
412 /* call repeatedly to get the next one */
414 static struct yahoo_input_data * find_input_by_id(int id)
417 for(l = inputs; l; l = y_list_next(l)) {
418 struct yahoo_input_data *yid = l->data;
419 if(yid->yd->client_id == id)
426 static struct yahoo_input_data
* find_input_by_id_and_webcam_user(int id
, const char * who
)
429 LOG(("find_input_by_id_and_webcam_user"));
430 for(l
= inputs
; l
; l
= y_list_next(l
)) {
431 struct yahoo_input_data
*yid
= l
->data
;
432 if(yid
->type
== YAHOO_CONNECTION_WEBCAM
&& yid
->yd
->client_id
== id
434 ((who
&& yid
->wcm
->user
&& !strcmp(who
, yid
->wcm
->user
)) ||
435 !(yid
->wcm
->user
&& !who
)))
441 static struct yahoo_input_data
* find_input_by_id_and_type(int id
, enum yahoo_connection_type type
)
444 LOG(("find_input_by_id_and_type"));
445 for(l
= inputs
; l
; l
= y_list_next(l
)) {
446 struct yahoo_input_data
*yid
= l
->data
;
447 if(yid
->type
== type
&& yid
->yd
->client_id
== id
)
453 static struct yahoo_input_data
* find_input_by_id_and_fd(int id
, int fd
)
456 LOG(("find_input_by_id_and_fd"));
457 for(l
= inputs
; l
; l
= y_list_next(l
)) {
458 struct yahoo_input_data
*yid
= l
->data
;
459 if(yid
->fd
== fd
&& yid
->yd
->client_id
== id
)
465 static int count_inputs_with_id(int id
)
469 LOG(("counting %d", id
));
470 for(l
= inputs
; l
; l
= y_list_next(l
)) {
471 struct yahoo_input_data
*yid
= l
->data
;
472 if(yid
->yd
->client_id
== id
)
480 extern char *yahoo_crypt(char *, char *);
482 /* Free a buddy list */
483 static void yahoo_free_buddies(YList
* list
)
487 for(l
= list
; l
; l
= l
->next
)
489 struct yahoo_buddy
*bud
= l
->data
;
495 FREE(bud
->real_name
);
497 FREE(bud
->yab_entry
->fname
);
498 FREE(bud
->yab_entry
->lname
);
499 FREE(bud
->yab_entry
->nname
);
500 FREE(bud
->yab_entry
->id
);
501 FREE(bud
->yab_entry
->email
);
502 FREE(bud
->yab_entry
->hphone
);
503 FREE(bud
->yab_entry
->wphone
);
504 FREE(bud
->yab_entry
->mphone
);
505 FREE(bud
->yab_entry
);
508 l
->data
= bud
= NULL
;
514 /* Free an identities list */
515 static void yahoo_free_identities(YList
* list
)
520 list
= y_list_remove_link(list
, list
);
525 /* Free webcam data */
526 static void yahoo_free_webcam(struct yahoo_webcam
*wcm
)
532 FREE(wcm
->description
);
538 static void yahoo_free_data(struct yahoo_data
*yd
)
545 FREE(yd
->login_cookie
);
548 yahoo_free_buddies(yd
->buddies
);
549 yahoo_free_buddies(yd
->ignore
);
550 yahoo_free_identities(yd
->identities
);
552 yahoo_free_server_settings(yd
->server_settings
);
557 #define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4)
559 static struct yahoo_packet
*yahoo_packet_new(enum yahoo_service service
,
560 enum yahoo_status status
, int id
)
562 struct yahoo_packet
*pkt
= y_new0(struct yahoo_packet
, 1);
564 pkt
->service
= service
;
565 pkt
->status
= status
;
571 static void yahoo_packet_hash(struct yahoo_packet
*pkt
, int key
, const char *value
)
573 struct yahoo_pair
*pair
= y_new0(struct yahoo_pair
, 1);
575 pair
->value
= strdup(value
);
576 pkt
->hash
= y_list_append(pkt
->hash
, pair
);
579 static int yahoo_packet_length(struct yahoo_packet
*pkt
)
585 for (l
= pkt
->hash
; l
; l
= l
->next
) {
586 struct yahoo_pair
*pair
= l
->data
;
593 len
+= strlen(pair
->value
);
600 #define yahoo_put16(buf, data) ( \
601 (*(buf) = (unsigned char)((data)>>8)&0xff), \
602 (*((buf)+1) = (unsigned char)(data)&0xff), \
604 #define yahoo_get16(buf) ((((*(buf))&0xff)<<8) + ((*((buf)+1)) & 0xff))
605 #define yahoo_put32(buf, data) ( \
606 (*((buf)) = (unsigned char)((data)>>24)&0xff), \
607 (*((buf)+1) = (unsigned char)((data)>>16)&0xff), \
608 (*((buf)+2) = (unsigned char)((data)>>8)&0xff), \
609 (*((buf)+3) = (unsigned char)(data)&0xff), \
611 #define yahoo_get32(buf) ((((*(buf) )&0xff)<<24) + \
612 (((*((buf)+1))&0xff)<<16) + \
613 (((*((buf)+2))&0xff)<< 8) + \
614 (((*((buf)+3))&0xff)))
616 static void yahoo_packet_read(struct yahoo_packet
*pkt
, unsigned char *data
, int len
)
620 while (pos
+ 1 < len
) {
621 char *key
, *value
= NULL
;
625 struct yahoo_pair
*pair
= y_new0(struct yahoo_pair
, 1);
627 key
= malloc(len
+ 1);
629 while (pos
+ 1 < len
) {
630 if (data
[pos
] == 0xc0 && data
[pos
+ 1] == 0x80)
632 key
[x
++] = data
[pos
++];
636 pair
->key
= strtol(key
, NULL
, 10);
640 /* if x is 0 there was no key, so don't accept it */
642 value
= malloc(len
- pos
+ 2);
644 while (pos
+ 1 < len
) {
645 if (data
[pos
] == 0xc0 && data
[pos
+ 1] == 0x80)
648 value
[x
++] = data
[pos
++];
654 pair
->value
= strdup(value
);
656 pkt
->hash
= y_list_append(pkt
->hash
, pair
);
657 DEBUG_MSG(("Key: %d \tValue: %s", pair
->key
, pair
->value
));
664 static void yahoo_packet_write(struct yahoo_packet
*pkt
, unsigned char *data
)
669 for (l
= pkt
->hash
; l
; l
= l
->next
) {
670 struct yahoo_pair
*pair
= l
->data
;
671 unsigned char buf
[100];
673 snprintf((char *)buf
, sizeof(buf
), "%d", pair
->key
);
674 strcpy((char *)data
+ pos
, (char *)buf
);
675 pos
+= strlen((char *)buf
);
679 strcpy((char *)data
+ pos
, pair
->value
);
680 pos
+= strlen(pair
->value
);
686 static void yahoo_dump_unhandled(struct yahoo_packet
*pkt
)
690 NOTICE(("Service: 0x%02x\tStatus: %d", pkt
->service
, pkt
->status
));
691 for (l
= pkt
->hash
; l
; l
= l
->next
) {
692 struct yahoo_pair
*pair
= l
->data
;
693 NOTICE(("\t%d => %s", pair
->key
, pair
->value
));
698 static void yahoo_packet_dump(unsigned char *data
, int len
)
700 if(yahoo_get_log_level() >= YAHOO_LOG_DEBUG
) {
702 for (i
= 0; i
< len
; i
++) {
703 if ((i
% 8 == 0) && i
)
704 YAHOO_CALLBACK(ext_yahoo_log
)(" ");
705 if ((i
% 16 == 0) && i
)
706 YAHOO_CALLBACK(ext_yahoo_log
)("\n");
707 YAHOO_CALLBACK(ext_yahoo_log
)("%02x ", data
[i
]);
709 YAHOO_CALLBACK(ext_yahoo_log
)("\n");
710 for (i
= 0; i
< len
; i
++) {
711 if ((i
% 8 == 0) && i
)
712 YAHOO_CALLBACK(ext_yahoo_log
)(" ");
713 if ((i
% 16 == 0) && i
)
714 YAHOO_CALLBACK(ext_yahoo_log
)("\n");
715 if (isprint(data
[i
]))
716 YAHOO_CALLBACK(ext_yahoo_log
)(" %c ", data
[i
]);
718 YAHOO_CALLBACK(ext_yahoo_log
)(" . ");
720 YAHOO_CALLBACK(ext_yahoo_log
)("\n");
724 static char base64digits
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
725 "abcdefghijklmnopqrstuvwxyz"
727 static void to_y64(unsigned char *out
, const unsigned char *in
, int inlen
)
728 /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
730 for (; inlen
>= 3; inlen
-= 3)
732 *out
++ = base64digits
[in
[0] >> 2];
733 *out
++ = base64digits
[((in
[0]<<4) & 0x30) | (in
[1]>>4)];
734 *out
++ = base64digits
[((in
[1]<<2) & 0x3c) | (in
[2]>>6)];
735 *out
++ = base64digits
[in
[2] & 0x3f];
740 unsigned char fragment
;
742 *out
++ = base64digits
[in
[0] >> 2];
743 fragment
= (in
[0] << 4) & 0x30;
745 fragment
|= in
[1] >> 4;
746 *out
++ = base64digits
[fragment
];
747 *out
++ = (inlen
< 2) ? '-'
748 : base64digits
[(in
[1] << 2) & 0x3c];
754 static void yahoo_add_to_send_queue(struct yahoo_input_data
*yid
, void *data
, int length
)
756 struct data_queue
*tx
= y_new0(struct data_queue
, 1);
757 tx
->queue
= y_new0(unsigned char, length
);
759 memcpy(tx
->queue
, data
, length
);
761 yid
->txqueues
= y_list_append(yid
->txqueues
, tx
);
764 yid
->write_tag
=YAHOO_CALLBACK(ext_yahoo_add_handler
)(yid
->yd
->client_id
, yid
->fd
, YAHOO_INPUT_WRITE
, yid
);
767 static void yahoo_send_packet(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
, int extra_pad
)
769 int pktlen
= yahoo_packet_length(pkt
);
770 int len
= YAHOO_PACKET_HDRLEN
+ pktlen
;
778 data
= y_new0(unsigned char, len
+ 1);
780 memcpy(data
+ pos
, "YMSG", 4); pos
+= 4;
781 pos
+= yahoo_put16(data
+ pos
, 0x000f);
782 pos
+= yahoo_put16(data
+ pos
, 0x0000);
783 pos
+= yahoo_put16(data
+ pos
, pktlen
+ extra_pad
);
784 pos
+= yahoo_put16(data
+ pos
, pkt
->service
);
785 pos
+= yahoo_put32(data
+ pos
, pkt
->status
);
786 pos
+= yahoo_put32(data
+ pos
, pkt
->id
);
788 yahoo_packet_write(pkt
, data
+ pos
);
790 yahoo_packet_dump(data
, len
);
792 if( yid
->type
== YAHOO_CONNECTION_FT
)
793 yahoo_send_data(yid
->fd
, data
, len
);
795 yahoo_add_to_send_queue(yid
, data
, len
);
799 static void yahoo_packet_free(struct yahoo_packet
*pkt
)
802 struct yahoo_pair
*pair
= pkt
->hash
->data
;
807 pkt
->hash
= y_list_remove_link(pkt
->hash
, pkt
->hash
);
813 static int yahoo_send_data(int fd
, void *data
, int len
)
821 yahoo_packet_dump(data
, len
);
824 ret
= write(fd
, data
, len
);
825 } while(ret
== -1 && errno
==EINTR
);
829 LOG(("wrote data: ERR %s", strerror(errno
)));
831 LOG(("wrote data: OK"));
838 void yahoo_close(int id
)
840 struct yahoo_data
*yd
= find_conn_by_id(id
);
851 static void yahoo_input_close(struct yahoo_input_data
*yid
)
853 inputs
= y_list_remove(inputs
, yid
);
855 LOG(("yahoo_input_close(read)"));
856 YAHOO_CALLBACK(ext_yahoo_remove_handler
)(yid
->yd
->client_id
, yid
->read_tag
);
857 LOG(("yahoo_input_close(write)"));
858 YAHOO_CALLBACK(ext_yahoo_remove_handler
)(yid
->yd
->client_id
, yid
->write_tag
);
859 yid
->read_tag
= yid
->write_tag
= 0;
864 if(count_inputs_with_id(yid
->yd
->client_id
) == 0) {
865 LOG(("closing %d", yid
->yd
->client_id
));
866 yahoo_close(yid
->yd
->client_id
);
868 yahoo_free_webcam(yid
->wcm
);
872 FREE(yid
->ys
->lsearch_text
);
878 static int is_same_bud(const void * a
, const void * b
) {
879 const struct yahoo_buddy
*subject
= a
;
880 const struct yahoo_buddy
*object
= b
;
882 return strcmp(subject
->id
, object
->id
);
885 static YList
* bud_str2list(char *rawlist
)
894 lines
= y_strsplit(rawlist
, "\n", -1);
895 for (tmp
= lines
; *tmp
; tmp
++) {
896 struct yahoo_buddy
*newbud
;
898 split
= y_strsplit(*tmp
, ":", 2);
901 if (!split
[0] || !split
[1]) {
905 buddies
= y_strsplit(split
[1], ",", -1);
907 for (bud
= buddies
; bud
&& *bud
; bud
++) {
908 newbud
= y_new0(struct yahoo_buddy
, 1);
909 newbud
->id
= strdup(*bud
);
910 newbud
->group
= strdup(split
[0]);
912 if(y_list_find_custom(l
, newbud
, is_same_bud
)) {
919 newbud
->real_name
= NULL
;
921 l
= y_list_append(l
, newbud
);
923 NOTICE(("Added buddy %s to group %s", newbud
->id
, newbud
->group
));
934 static char * getcookie(char *rawcookie
)
940 if (strlen(rawcookie
) < 2)
943 tmpcookie
= strdup(rawcookie
+2);
944 cookieend
= strchr(tmpcookie
, ';');
949 cookie
= strdup(tmpcookie
);
951 /* cookieend=NULL; not sure why this was there since the value is not preserved in the stack -dd */
956 static char * getlcookie(char *cookie
)
960 char *login_cookie
= NULL
;
962 tmpend
= strstr(cookie
, "n=");
964 tmp
= strdup(tmpend
+2);
965 tmpend
= strchr(tmp
, '&');
968 login_cookie
= strdup(tmp
);
975 static void yahoo_process_notify(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
977 struct yahoo_data
*yd
= yid
->yd
;
985 for (l
= pkt
->hash
; l
; l
= l
->next
) {
986 struct yahoo_pair
*pair
= l
->data
;
994 stat
= atoi(pair
->value
);
997 if (pair
->key
== 16) { /* status == -1 */
998 NOTICE((pair
->value
));
1007 if (!strncasecmp(msg
, "TYPING", strlen("TYPING")))
1008 YAHOO_CALLBACK(ext_yahoo_typing_notify
)(yd
->client_id
, to
, from
, stat
);
1009 else if (!strncasecmp(msg
, "GAME", strlen("GAME")))
1010 YAHOO_CALLBACK(ext_yahoo_game_notify
)(yd
->client_id
, to
, from
, stat
);
1011 else if (!strncasecmp(msg
, "WEBCAMINVITE", strlen("WEBCAMINVITE")))
1013 if (!strcmp(ind
, " ")) {
1014 YAHOO_CALLBACK(ext_yahoo_webcam_invite
)(yd
->client_id
, to
, from
);
1017 /* accept the invitation (-1 = deny 1 = accept) */
1020 YAHOO_CALLBACK(ext_yahoo_webcam_invite_reply
)(yd
->client_id
, to
, from
, accept
);
1024 LOG(("Got unknown notification: %s", msg
));
1027 static void yahoo_process_filetransfer(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1029 struct yahoo_data
*yd
= yid
->yd
;
1038 char *filename
=NULL
;
1039 unsigned long filesize
=0L;
1042 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1043 struct yahoo_pair
*pair
= l
->data
;
1048 if (pair
->key
== 14)
1050 if (pair
->key
== 20)
1052 if (pair
->key
== 38)
1053 expires
= atol(pair
->value
);
1055 if (pair
->key
== 27)
1056 filename
= pair
->value
;
1057 if (pair
->key
== 28)
1058 filesize
= atol(pair
->value
);
1060 if (pair
->key
== 49)
1061 service
= pair
->value
;
1064 if(pkt
->service
== YAHOO_SERVICE_P2PFILEXFER
) {
1065 if(strcmp("FILEXFER", service
) != 0) {
1066 WARNING(("unhandled service 0x%02x", pkt
->service
));
1067 yahoo_dump_unhandled(pkt
);
1074 tmp
= strchr(msg
, '\006');
1079 YAHOO_CALLBACK(ext_yahoo_got_file
)(yd
->client_id
, to
, from
, url
, expires
, msg
, filename
, filesize
);
1083 static void yahoo_process_conference(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1085 struct yahoo_data
*yd
= yid
->yd
;
1092 YList
*members
= NULL
;
1095 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1096 struct yahoo_pair
*pair
= l
->data
;
1097 if (pair
->key
== 50)
1100 if (pair
->key
== 52) { /* invite */
1101 members
= y_list_append(members
, strdup(pair
->value
));
1103 if (pair
->key
== 53) /* logon */
1105 if (pair
->key
== 54) /* decline */
1107 if (pair
->key
== 55) /* unavailable (status == 2) */
1109 if (pair
->key
== 56) /* logoff */
1112 if (pair
->key
== 57)
1115 if (pair
->key
== 58) /* join message */
1117 if (pair
->key
== 14) /* decline/conf message */
1120 if (pair
->key
== 13)
1122 if (pair
->key
== 16) /* error */
1125 if (pair
->key
== 1) /* my id */
1127 if (pair
->key
== 3) /* message sender */
1130 if (pair
->key
== 97)
1131 utf8
= atoi(pair
->value
);
1138 for(l
= members
; l
; l
= l
->next
) {
1140 if(!strcmp(w
, host
))
1144 members
= y_list_append(members
, strdup(host
));
1146 /* invite, decline, join, left, message -> status == 1 */
1148 switch(pkt
->service
) {
1149 case YAHOO_SERVICE_CONFINVITE
:
1150 if(pkt
->status
== 2)
1153 YAHOO_CALLBACK(ext_yahoo_got_conf_invite
)(yd
->client_id
, host
, room
, msg
, members
);
1155 YAHOO_CALLBACK(ext_yahoo_error
)(yd
->client_id
, msg
, 0, E_CONFNOTAVAIL
);
1157 case YAHOO_SERVICE_CONFADDINVITE
:
1158 if(pkt
->status
== 2)
1161 YAHOO_CALLBACK(ext_yahoo_got_conf_invite
)(yd
->client_id
, host
, room
, msg
, members
);
1163 case YAHOO_SERVICE_CONFDECLINE
:
1165 YAHOO_CALLBACK(ext_yahoo_conf_userdecline
)(yd
->client_id
, who
, room
, msg
);
1167 case YAHOO_SERVICE_CONFLOGON
:
1169 YAHOO_CALLBACK(ext_yahoo_conf_userjoin
)(yd
->client_id
, who
, room
);
1171 case YAHOO_SERVICE_CONFLOGOFF
:
1173 YAHOO_CALLBACK(ext_yahoo_conf_userleave
)(yd
->client_id
, who
, room
);
1175 case YAHOO_SERVICE_CONFMSG
:
1177 YAHOO_CALLBACK(ext_yahoo_conf_message
)(yd
->client_id
, who
, room
, msg
, utf8
);
1182 static void yahoo_process_chat(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1188 YList
*members
= NULL
;
1189 struct yahoo_chat_member
*currentmember
= NULL
;
1193 int membercount
= 0;
1197 yahoo_dump_unhandled(pkt
);
1198 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1199 struct yahoo_pair
*pair
= l
->data
;
1201 if (pair
->key
== 104) {
1206 if (pair
->key
== 105) {
1208 topic
= pair
->value
;
1211 if (pair
->key
== 108) {
1212 /* Number of members in this packet */
1213 membercount
= atoi(pair
->value
);
1216 if (pair
->key
== 109) {
1217 /* message sender */
1220 if (pkt
->service
== YAHOO_SERVICE_CHATJOIN
) {
1221 currentmember
= y_new0(struct yahoo_chat_member
, 1);
1222 currentmember
->id
= strdup(pair
->value
);
1223 members
= y_list_append(members
, currentmember
);
1227 if (pair
->key
== 110) {
1229 if (pkt
->service
== YAHOO_SERVICE_CHATJOIN
)
1230 currentmember
->age
= atoi(pair
->value
);
1233 if (pair
->key
== 113) {
1235 if (pkt
->service
== YAHOO_SERVICE_CHATJOIN
)
1236 currentmember
->attribs
= atoi(pair
->value
);
1239 if (pair
->key
== 141) {
1241 if (pkt
->service
== YAHOO_SERVICE_CHATJOIN
)
1242 currentmember
->alias
= strdup(pair
->value
);
1245 if (pair
->key
== 142) {
1247 if (pkt
->service
== YAHOO_SERVICE_CHATJOIN
)
1248 currentmember
->location
= strdup(pair
->value
);
1252 if (pair
->key
== 130) {
1257 if (pair
->key
== 117) {
1262 if (pair
->key
== 124) {
1264 msgtype
= atoi(pair
->value
);
1266 if (pair
->key
== 114) {
1267 /* message error not sure what all the pair values mean */
1268 /* but -1 means no session in room */
1269 chaterr
= atoi(pair
->value
);
1274 if (pkt
->service
== YAHOO_SERVICE_CHATLOGOUT
) { /* yahoo originated chat logout */
1275 YAHOO_CALLBACK(ext_yahoo_chat_yahoologout
)(yid
->yd
->client_id
);
1278 if (pkt
->service
== YAHOO_SERVICE_COMMENT
&& chaterr
) {
1279 YAHOO_CALLBACK(ext_yahoo_chat_yahooerror
)(yid
->yd
->client_id
);
1283 WARNING(("We didn't get a room name, ignoring packet"));
1287 switch(pkt
->service
) {
1288 case YAHOO_SERVICE_CHATJOIN
:
1289 if(y_list_length(members
) != membercount
) {
1290 WARNING(("Count of members doesn't match No. of members we got"));
1292 if(firstjoin
&& members
) {
1293 YAHOO_CALLBACK(ext_yahoo_chat_join
)(yid
->yd
->client_id
, room
, topic
, members
, yid
->fd
);
1295 if(y_list_length(members
) != 1) {
1296 WARNING(("Got more than 1 member on a normal join"));
1298 /* this should only ever have one, but just in case */
1300 YList
*n
= members
->next
;
1301 currentmember
= members
->data
;
1302 YAHOO_CALLBACK(ext_yahoo_chat_userjoin
)(yid
->yd
->client_id
, room
, currentmember
);
1303 y_list_free_1(members
);
1308 case YAHOO_SERVICE_CHATEXIT
:
1310 YAHOO_CALLBACK(ext_yahoo_chat_userleave
)(yid
->yd
->client_id
, room
, who
);
1313 case YAHOO_SERVICE_COMMENT
:
1315 YAHOO_CALLBACK(ext_yahoo_chat_message
)(yid
->yd
->client_id
, who
, room
, msg
, msgtype
, utf8
);
1321 static void yahoo_process_message(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1323 struct yahoo_data
*yd
= yid
->yd
;
1325 YList
* messages
= NULL
;
1335 } *message
= y_new0(struct m
, 1);
1337 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1338 struct yahoo_pair
*pair
= l
->data
;
1339 if (pair
->key
== 1 || pair
->key
== 4)
1342 message
->from
= pair
->value
;
1344 else if (pair
->key
== 5)
1345 message
->to
= pair
->value
;
1346 else if (pair
->key
== 15)
1347 message
->tm
= strtol(pair
->value
, NULL
, 10);
1348 else if (pair
->key
== 97)
1349 message
->utf8
= atoi(pair
->value
);
1350 /* user message */ /* sys message */
1351 else if (pair
->key
== 14 || pair
->key
== 16)
1352 message
->msg
= pair
->value
;
1353 else if (pair
->key
== 31) {
1355 messages
= y_list_append(messages
, message
);
1356 message
= y_new0(struct m
, 1);
1358 message
->i_31
= atoi(pair
->value
);
1360 else if (pair
->key
== 32)
1361 message
->i_32
= atoi(pair
->value
);
1363 LOG(("yahoo_process_message: status: %d, key: %d, value: %s",
1364 pkt
->status
, pair
->key
, pair
->value
));
1367 messages
= y_list_append(messages
, message
);
1369 for (l
= messages
; l
; l
=l
->next
) {
1371 if (pkt
->service
== YAHOO_SERVICE_SYSMESSAGE
) {
1372 YAHOO_CALLBACK(ext_yahoo_system_message
)(yd
->client_id
, message
->msg
);
1373 } else if (pkt
->status
<= 2 || pkt
->status
== 5) {
1374 YAHOO_CALLBACK(ext_yahoo_got_im
)(yd
->client_id
, message
->to
, message
->from
, message
->msg
, message
->tm
, pkt
->status
, message
->utf8
);
1375 } else if (pkt
->status
== 0xffffffff) {
1376 YAHOO_CALLBACK(ext_yahoo_error
)(yd
->client_id
, message
->msg
, 0, E_SYSTEM
);
1381 y_list_free(messages
);
1385 static void yahoo_process_status(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1388 struct yahoo_data
*yd
= yid
->yd
;
1392 char *name
; /* 7 name */
1393 int state
; /* 10 state */
1394 int flags
; /* 13 flags, bit 0 = pager, bit 1 = chat, bit 2 = game */
1395 int mobile
; /* 60 mobile */
1396 char *msg
; /* 19 custom status message */
1397 int away
; /* 47 away (or invisible)*/
1398 int buddy_session
; /* 11 state */
1399 int f17
; /* 17 in chat? then what about flags? */
1400 int idle
; /* 137 seconds idle */
1401 int f138
; /* 138 state */
1402 char *f184
; /* 184 state */
1403 int f192
; /* 192 state */
1404 int f10001
; /* 10001 state */
1405 int f10002
; /* 10002 state */
1406 int f198
; /* 198 state */
1407 char *f197
; /* 197 state */
1408 char *f205
; /* 205 state */
1409 int f213
; /* 213 state */
1414 if (pkt
->service
== YAHOO_SERVICE_LOGOFF
&& pkt
->status
== -1) {
1415 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_DUPL
, NULL
);
1419 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1420 struct yahoo_pair
*pair
= l
->data
;
1422 switch (pair
->key
) {
1423 case 0: /* we won't actually do anything with this */
1424 NOTICE(("key %d:%s", pair
->key
, pair
->value
));
1426 case 1: /* we don't get the full buddy list here. */
1427 if (!yd
->logged_in
) {
1428 yd
->logged_in
= TRUE
;
1429 if(yd
->current_status
< 0)
1430 yd
->current_status
= yd
->initial_status
;
1431 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_OK
, NULL
);
1434 case 8: /* how many online buddies we have */
1435 NOTICE(("key %d:%s", pair
->key
, pair
->value
));
1437 case 7: /* the current buddy */
1438 u
= y_new0(struct user
, 1);
1439 u
->name
= pair
->value
;
1440 users
= y_list_prepend(users
, u
);
1442 case 10: /* state */
1444 ((struct user
*)users
->data
)->state
= strtol(pair
->value
, NULL
, 10);
1446 case 19: /* custom status message */
1448 ((struct user
*)users
->data
)->msg
= pair
->value
;
1450 case 47: /* is it an away message or not */
1452 ((struct user
*)users
->data
)->away
= atoi(pair
->value
);
1454 case 137: /* seconds idle */
1456 ((struct user
*)users
->data
)->idle
= atoi(pair
->value
);
1458 case 11: /* this is the buddy's session id */
1460 ((struct user
*)users
->data
)->buddy_session
= atoi(pair
->value
);
1462 case 17: /* in chat? */
1464 ((struct user
*)users
->data
)->f17
= atoi(pair
->value
);
1466 case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */
1468 ((struct user
*)users
->data
)->flags
= atoi(pair
->value
);
1470 case 60: /* SMS -> 1 MOBILE USER */
1471 /* sometimes going offline makes this 2, but invisible never sends it */
1473 ((struct user
*)users
->data
)->mobile
= atoi(pair
->value
);
1477 ((struct user
*)users
->data
)->f138
= atoi(pair
->value
);
1481 ((struct user
*)users
->data
)->f184
= pair
->value
;
1485 ((struct user
*)users
->data
)->f192
= atoi(pair
->value
);
1489 ((struct user
*)users
->data
)->f10001
= atoi(pair
->value
);
1493 ((struct user
*)users
->data
)->f10002
= atoi(pair
->value
);
1497 ((struct user
*)users
->data
)->f198
= atoi(pair
->value
);
1501 ((struct user
*)users
->data
)->f197
= pair
->value
;
1505 ((struct user
*)users
->data
)->f205
= pair
->value
;
1509 ((struct user
*)users
->data
)->f213
= atoi(pair
->value
);
1511 case 16: /* Custom error message */
1512 YAHOO_CALLBACK(ext_yahoo_error
)(yd
->client_id
, pair
->value
, 0, E_CUSTOM
);
1515 WARNING(("unknown status key %d:%s", pair
->key
, pair
->value
));
1522 struct user
*u
= users
->data
;
1524 if (u
->name
!= NULL
) {
1525 if (pkt
->service
== YAHOO_SERVICE_LOGOFF
|| u
->flags
== 0) {
1526 YAHOO_CALLBACK(ext_yahoo_status_changed
)(yd
->client_id
, u
->name
, YAHOO_STATUS_OFFLINE
, NULL
, 1, 0, 0);
1528 YAHOO_CALLBACK(ext_yahoo_status_changed
)(yd
->client_id
, u
->name
, u
->state
, u
->msg
, u
->away
, u
->idle
, u
->mobile
);
1532 users
= y_list_remove_link(users
, users
);
1538 static void yahoo_process_list(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1540 struct yahoo_data
*yd
= yid
->yd
;
1543 if (!yd
->logged_in
) {
1544 struct yahoo_packet
*pkt2
;
1546 yd
->logged_in
= TRUE
;
1547 if(yd
->current_status
< 0)
1548 yd
->current_status
= yd
->initial_status
;
1549 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_OK
, NULL
);
1551 pkt2
= yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE
, YAHOO_STATUS_AVAILABLE
, 0);
1553 snprintf(buff
, sizeof(buff
)-1, "%d", yd
->current_status
);
1554 yahoo_packet_hash(pkt2
, 10, buff
);
1555 yahoo_packet_hash(pkt2
, 19, "");
1556 yahoo_send_packet(yid
, pkt2
, 0);
1558 yahoo_packet_free(pkt2
);
1561 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1562 struct yahoo_pair
*pair
= l
->data
;
1565 case 87: /* buddies */
1566 if(!yd
->rawbuddylist
)
1567 yd
->rawbuddylist
= strdup(pair
->value
);
1569 yd
->rawbuddylist
= y_string_append(yd
->rawbuddylist
, pair
->value
);
1573 case 88: /* ignore list */
1575 yd
->ignorelist
= strdup("Ignore:");
1576 yd
->ignorelist
= y_string_append(yd
->ignorelist
, pair
->value
);
1579 case 89: /* identities */
1581 char **identities
= y_strsplit(pair
->value
, ",", -1);
1583 for(i
=0; identities
[i
]; i
++)
1584 yd
->identities
= y_list_append(yd
->identities
,
1585 strdup(identities
[i
]));
1586 y_strfreev(identities
);
1588 YAHOO_CALLBACK(ext_yahoo_got_identities
)(yd
->client_id
, yd
->identities
);
1590 case 59: /* cookies */
1591 if(yd
->ignorelist
) {
1592 yd
->ignore
= bud_str2list(yd
->ignorelist
);
1593 FREE(yd
->ignorelist
);
1594 YAHOO_CALLBACK(ext_yahoo_got_ignore
)(yd
->client_id
, yd
->ignore
);
1596 if(yd
->rawbuddylist
) {
1597 yd
->buddies
= bud_str2list(yd
->rawbuddylist
);
1598 FREE(yd
->rawbuddylist
);
1599 YAHOO_CALLBACK(ext_yahoo_got_buddies
)(yd
->client_id
, yd
->buddies
);
1602 if(pair
->value
[0]=='Y') {
1604 FREE(yd
->login_cookie
);
1606 yd
->cookie_y
= getcookie(pair
->value
);
1607 yd
->login_cookie
= getlcookie(yd
->cookie_y
);
1609 } else if(pair
->value
[0]=='T') {
1611 yd
->cookie_t
= getcookie(pair
->value
);
1613 } else if(pair
->value
[0]=='C') {
1615 yd
->cookie_c
= getcookie(pair
->value
);
1618 if(yd
->cookie_y
&& yd
->cookie_t
&& yd
->cookie_c
)
1619 YAHOO_CALLBACK(ext_yahoo_got_cookies
)(yd
->client_id
);
1625 case 101: /* NULL */
1626 case 102: /* NULL */
1627 case 93: /* 86400/1440 */
1634 static void yahoo_process_list_15(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1637 struct yahoo_data
*yd
= yid
->yd
;
1639 char *grp
= 0, *bud
= 0;
1643 struct yahoo_pair
*pair
= l
->data
;
1645 switch (pair
->key
) {
1647 /* This is always 318 before a group, 319 before the first s/n in a group, 320 before any ignored s/n.
1648 * It is not sent for s/n's in a group after the first.
1649 * All ignored s/n's are listed last, so when we see a 320 we clear the group and begin marking the
1650 * s/n's as ignored. It is always followed by an identical 300 key.
1652 if (pair
->value
&& !strcmp(pair
->value
, "320")) {
1653 /* No longer in any group; this indicates the start of the ignore list. */
1658 case 65: /* This is the group */
1660 grp
= strdup(pair
->value
);
1663 case 7: /* buddy's s/n */
1664 bud
= strdup(pair
->value
);
1668 /* This buddy is in a group */
1669 struct yahoo_buddy
*buddy
= y_new0(struct yahoo_buddy
, 1);
1670 buddy
->id
= strdup(bud
);
1671 buddy
->group
= strdup(grp
);
1672 buddy
->real_name
= 0;
1673 buddy
->yab_entry
= 0;
1674 yd
->buddies
= y_list_append(yd
->buddies
, buddy
);
1676 /* This buddy is on the ignore list (and therefore in no group) */
1677 //purple_privacy_deny_add(account, norm_bud, 1);
1686 YAHOO_CALLBACK(ext_yahoo_got_buddies
)(yd
->client_id
, yd
->buddies
);
1689 static void yahoo_process_auth_15(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1692 struct yahoo_data
*yd
= yid
->yd
;
1693 const char *msg
= NULL
;
1695 if (pkt
->status
== 1) {
1696 const char *who
= NULL
;
1701 struct yahoo_pair
*pair
= l
->data
;
1703 switch (pair
->key
) {
1708 response
= strtol(pair
->value
, NULL
, 10);
1717 if (response
== 1) {/* Authorized */
1718 NOTICE(("Received authorization from buddy '%s'.\n", who
? who
: "(Unknown Buddy)"));
1719 YAHOO_CALLBACK(ext_yahoo_got_auth_response
)(yd
->client_id
, who
? who
: "(Unknown Buddy)", 1, NULL
);
1721 else if (response
== 2) { /* Declined */
1722 WARNING(("Received authorization decline from buddy '%s'.\n", who
? who
: "(Unknown Buddy)"));
1723 YAHOO_CALLBACK(ext_yahoo_got_auth_response
)(yd
->client_id
, who
? who
: "(Unknown Buddy)", 0, msg
);
1725 WARNING(("Received unknown authorization response of %d from buddy '%s'.\n", response
, who
? who
: "(Unknown Buddy)"));
1728 /* Buddy requested authorization to add us. */
1729 else if (pkt
->status
== 3) {
1730 struct yahoo_add_request
*add_req
;
1731 const char *firstname
= NULL
, *lastname
= NULL
;
1735 add_req
= y_new0(struct yahoo_add_request
, 1);
1738 struct yahoo_pair
*pair
= l
->data
;
1740 switch (pair
->key
) {
1742 add_req
->who
= strdup(pair
->value
);
1745 add_req
->id
= strdup(pair
->value
);
1751 firstname
= pair
->value
;
1754 add_req
->protocol
= strtol(pair
->value
, NULL
, 10);
1757 lastname
= pair
->value
;
1764 if (add_req
->id
&& add_req
->who
) {
1765 char *alias
= NULL
, *dec_msg
= NULL
;
1768 dec_msg = yahoo_string_decode(msg, FALSE);*/
1770 dec_msg
= strdup(msg
);
1772 /*if (firstname && lastname)
1773 alias = g_strdup_printf("%s %s", firstname, lastname);
1775 alias = g_strdup(firstname);
1777 alias = g_strdup(lastname);*/
1779 YAHOO_CALLBACK(ext_yahoo_got_auth_request
)(yd
->client_id
, add_req
->who
, dec_msg
);
1791 WARNING(("Received authorization of unknown status (%d).\n", pkt
->status
));
1795 static void yahoo_process_verify(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1797 struct yahoo_data
*yd
= yid
->yd
;
1799 if(pkt
->status
!= 0x01) {
1800 DEBUG_MSG(("expected status: 0x01, got: %d", pkt
->status
));
1801 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_LOCK
, "");
1805 pkt
= yahoo_packet_new(YAHOO_SERVICE_AUTH
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
1807 yahoo_packet_hash(pkt
, 1, yd
->user
);
1808 yahoo_send_packet(yid
, pkt
, 0);
1810 yahoo_packet_free(pkt
);
1814 static void yahoo_process_picture_checksum( struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1816 struct yahoo_data
*yd
= yid
->yd
;
1822 for(l
= pkt
->hash
; l
; l
= l
->next
)
1824 struct yahoo_pair
*pair
= l
->data
;
1837 checksum
= atoi( pair
->value
);
1842 // YAHOO_CALLBACK(ext_yahoo_got_buddyicon_checksum)(yd->client_id,to,from,checksum);
1845 static void yahoo_process_picture(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1847 struct yahoo_data
*yd
= yid
->yd
;
1857 for(l
= pkt
->hash
; l
; l
= l
->next
)
1859 struct yahoo_pair
*pair
= l
->data
;
1864 case 4: /* sender */
1870 case 13: /* request / sending */
1871 status
= atoi( pair
->value
);
1876 case 192: /*checksum */
1877 checksum
= atoi( pair
->value
);
1884 case 1: /* this is a request, ignore for now */
1885 YAHOO_CALLBACK(ext_yahoo_got_buddyicon_request
)(yd
->client_id
, to
, from
);
1887 case 2: /* this is cool - we get a picture :) */
1888 YAHOO_CALLBACK(ext_yahoo_got_buddyicon
)(yd
->client_id
,to
, from
, url
, checksum
);
1893 static void yahoo_process_picture_upload(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1895 struct yahoo_data
*yd
= yid
->yd
;
1901 if ( pkt
->status
!= 1 )
1902 return; /* something went wrong */
1904 for(l
= pkt
->hash
; l
; l
= l
->next
)
1906 struct yahoo_pair
*pair
= l
->data
;
1915 case 27: /* local filename */
1922 YAHOO_CALLBACK(ext_yahoo_buddyicon_uploaded
)(yd
->client_id
, url
);
1925 static void yahoo_process_auth_pre_0x0b(struct yahoo_input_data
*yid
,
1926 const char *seed
, const char *sn
)
1928 struct yahoo_data
*yd
= yid
->yd
;
1930 /* So, Yahoo has stopped supporting its older clients in India, and
1931 * undoubtedly will soon do so in the rest of the world.
1933 * The new clients use this authentication method. I warn you in
1934 * advance, it's bizzare, convoluted, inordinately complicated.
1935 * It's also no more secure than crypt() was. The only purpose this
1936 * scheme could serve is to prevent third part clients from connecting
1942 struct yahoo_packet
*pack
;
1944 md5_byte_t result
[16];
1947 unsigned char *password_hash
= malloc(25);
1948 unsigned char *crypt_hash
= malloc(25);
1949 unsigned char *hash_string_p
= malloc(50 + strlen(sn
));
1950 unsigned char *hash_string_c
= malloc(50 + strlen(sn
));
1956 unsigned char *result6
= malloc(25);
1957 unsigned char *result96
= malloc(25);
1963 md5_append(&ctx
, (md5_byte_t
*)yd
->password
, strlen(yd
->password
));
1964 md5_finish(&ctx
, result
);
1965 to_y64(password_hash
, result
, 16);
1968 crypt_result
= yahoo_crypt(yd
->password
, "$1$_2S43d5f$");
1969 md5_append(&ctx
, (md5_byte_t
*)crypt_result
, strlen(crypt_result
));
1970 md5_finish(&ctx
, result
);
1971 to_y64(crypt_hash
, result
, 16);
1976 checksum
= seed
[seed
[7] % 16];
1977 snprintf((char *)hash_string_p
, strlen(sn
) + 50,
1978 "%c%s%s%s", checksum
, password_hash
, yd
->user
, seed
);
1979 snprintf((char *)hash_string_c
, strlen(sn
) + 50,
1980 "%c%s%s%s", checksum
, crypt_hash
, yd
->user
, seed
);
1983 checksum
= seed
[seed
[9] % 16];
1984 snprintf((char *)hash_string_p
, strlen(sn
) + 50,
1985 "%c%s%s%s", checksum
, yd
->user
, seed
, password_hash
);
1986 snprintf((char *)hash_string_c
, strlen(sn
) + 50,
1987 "%c%s%s%s", checksum
, yd
->user
, seed
, crypt_hash
);
1990 checksum
= seed
[seed
[15] % 16];
1991 snprintf((char *)hash_string_p
, strlen(sn
) + 50,
1992 "%c%s%s%s", checksum
, seed
, password_hash
, yd
->user
);
1993 snprintf((char *)hash_string_c
, strlen(sn
) + 50,
1994 "%c%s%s%s", checksum
, seed
, crypt_hash
, yd
->user
);
1997 checksum
= seed
[seed
[1] % 16];
1998 snprintf((char *)hash_string_p
, strlen(sn
) + 50,
1999 "%c%s%s%s", checksum
, yd
->user
, password_hash
, seed
);
2000 snprintf((char *)hash_string_c
, strlen(sn
) + 50,
2001 "%c%s%s%s", checksum
, yd
->user
, crypt_hash
, seed
);
2004 checksum
= seed
[seed
[3] % 16];
2005 snprintf((char *)hash_string_p
, strlen(sn
) + 50,
2006 "%c%s%s%s", checksum
, password_hash
, seed
, yd
->user
);
2007 snprintf((char *)hash_string_c
, strlen(sn
) + 50,
2008 "%c%s%s%s", checksum
, crypt_hash
, seed
, yd
->user
);
2013 md5_append(&ctx
, (md5_byte_t
*)hash_string_p
, strlen((char *)hash_string_p
));
2014 md5_finish(&ctx
, result
);
2015 to_y64(result6
, result
, 16);
2018 md5_append(&ctx
, (md5_byte_t
*)hash_string_c
, strlen((char *)hash_string_c
));
2019 md5_finish(&ctx
, result
);
2020 to_y64(result96
, result
, 16);
2022 pack
= yahoo_packet_new(YAHOO_SERVICE_AUTHRESP
, yd
->initial_status
, yd
->session_id
);
2023 yahoo_packet_hash(pack
, 0, yd
->user
);
2024 yahoo_packet_hash(pack
, 6, (char *)result6
);
2025 yahoo_packet_hash(pack
, 96, (char *)result96
);
2026 yahoo_packet_hash(pack
, 1, yd
->user
);
2028 yahoo_send_packet(yid
, pack
, 0);
2032 FREE(password_hash
);
2034 FREE(hash_string_p
);
2035 FREE(hash_string_c
);
2037 yahoo_packet_free(pack
);
2041 int split_lines(char *s
, char *lines
[], int max
)
2044 char *b
= strdup(s
);
2048 while (p
&& (pos
<max
))
2050 tok
= strsep(&p
, "\r\n");
2051 if (strlen(tok
) == 0)
2053 lines
[pos
] = strdup(tok
);
2062 * New new auth protocol
2064 static void yahoo_process_auth_0x10(struct yahoo_input_data
*yid
, const char *seed
, const char *sn
)
2069 struct yahoo_data
*yd
= yid
->yd
;
2070 LOG(("CURL init..."));
2071 curl
= curl_easy_init();
2073 if (!curl
) // CURL init failed
2075 WARNING(("Yahoo: curl init error"));
2078 LOG(("CURL inited"));
2080 snprintf(url
, sizeof(url
), "https://login.yahoo.com/config/pwtoken_get?src=ymsgr&ts=&login=%s&passwd=%s&chal=%s",yd
->user
, yd
->password
, seed
);
2081 curl_easy_setopt(curl
, CURLOPT_URL
, url
);
2082 curl_easy_setopt(curl
, CURLOPT_WRITEFUNCTION
, &yahoo_handle_curl_write
);
2086 LOG(("Downloading token"));
2087 ret
= curl_easy_perform(curl
);
2089 if (ret
) // there was error
2091 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_LOGOFF
, NULL
);
2092 WARNING(("Yahoo: curl error %d", ret
));
2093 curl_easy_cleanup(curl
);
2094 return; // deallocate curl data buffer?
2097 if (!curl_buffer
) // no data was read
2099 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_LOGOFF
, NULL
);
2100 WARNING(("Yahoo: no data read"));
2101 curl_easy_cleanup(curl
);
2105 LOG(("Token downloaded"));
2109 char *buff
= malloc(curl_buffer_size
+ 1);
2110 memcpy(buff
, curl_buffer
, curl_buffer_size
);
2111 buff
[curl_buffer_size
] = '\0';
2116 int n
= split_lines(buff
, lines
, 6);
2120 if (n
>= 2) // there's some error
2122 ret_code
= strtol(lines
[0], NULL
, 10);
2123 token
= strdup(lines
[1]+6);
2127 ret_code
= strtol(lines
[0], NULL
, 10);
2133 if (ret_code
) // error
2138 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_PASSWD
, NULL
);
2141 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_LOCK
, "Yahoo! website. Too many failed logins.");
2144 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_UNAME
, NULL
);
2148 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_LOCK
, "Yahoo! website.");
2151 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_LOGOFF
, NULL
);
2153 WARNING(("Yahoo: wrong token response - %d (%d lines: '%s')", ret_code
, n
, buff
));
2156 curl_easy_cleanup(curl
);
2161 LOG(("Token parsed, downloading cookies"));
2162 snprintf(url
, sizeof(url
), "https://login.yahoo.com/config/pwtoken_login?src=ymsgr&ts=&token=%s", token
);
2164 curl_easy_setopt(curl
, CURLOPT_URL
, url
);
2165 curl_easy_setopt(curl
, CURLOPT_WRITEFUNCTION
, &yahoo_handle_curl_write
);
2167 ret
= curl_easy_perform(curl
);
2169 if (ret
) // error with curl
2171 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_LOGOFF
, NULL
);
2172 WARNING(("Yahoo: curl error %d", ret
));
2175 curl_easy_cleanup(curl
);
2178 LOG(("Cookies downloaded"));
2179 buff
= malloc(curl_buffer_size
+1);
2180 memcpy(buff
, curl_buffer
, curl_buffer_size
);
2181 buff
[curl_buffer_size
] = '\0';
2185 n
= split_lines(buff
, lines
, 6);
2191 yd
->cookie_y
= yd
->cookie_t
= NULL
;
2195 ret_code
= strtol(lines
[0], NULL
, 10);
2196 crumb
= strdup(lines
[1] + 6);
2197 yd
->cookie_y
= strdup(lines
[2] + 2);
2198 yd
->cookie_t
= strdup(lines
[3] + 2);
2202 ret_code
= strtol(lines
[0], NULL
, 10);
2210 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_LOGOFF
, NULL
);
2211 WARNING(("Yahoo: wrong crumb response - %d", ret_code
));
2215 yd
->cookie_y
= yd
->cookie_t
= NULL
;
2216 curl_easy_cleanup(curl
);
2219 char crypt
[strlen(crumb
) + strlen(seed
) + 1];
2220 strcpy(crypt
, crumb
);
2221 strcat(crypt
, seed
);
2225 md5_byte_t result
[16];
2227 char crypt_hash
[30];
2228 LOG(("Computing MD5"));
2230 md5_append(&ctx
, (md5_byte_t
*)crypt
, strlen(crypt
));
2231 md5_finish(&ctx
, result
);
2232 to_y64(crypt_hash
, result
, 16);
2234 LOG(("Constructing packet"));
2235 struct yahoo_packet
*pack
= yahoo_packet_new(YAHOO_SERVICE_AUTHRESP
, yd
->initial_status
, yd
->session_id
);
2236 yahoo_packet_hash(pack
, 1, yd
->user
);
2237 yahoo_packet_hash(pack
, 0, yd
->user
);
2238 yahoo_packet_hash(pack
, 277, yd
->cookie_y
);
2239 yahoo_packet_hash(pack
, 278, yd
->cookie_t
);
2240 yahoo_packet_hash(pack
, 307, crypt_hash
);
2241 yahoo_packet_hash(pack
, 244, YAHOO_CLIENT_VERSION_ID
);
2242 yahoo_packet_hash(pack
, 2, yd
->user
);
2243 yahoo_packet_hash(pack
, 2, "1");
2244 yahoo_packet_hash(pack
, 135, YAHOO_CLIENT_VERSION
);
2246 LOG(("Sending login packet"));
2247 yahoo_send_packet(yid
, pack
, 0);
2248 yahoo_packet_free(pack
);
2249 LOG(("Auth 0x10 finished"));
2253 * New auth protocol cracked by Cerulean Studios and sent in to Gaim
2255 static void yahoo_process_auth_0x0b(struct yahoo_input_data
*yid
, const char *seed
, const char *sn
)
2257 struct yahoo_packet
*pack
= NULL
;
2258 struct yahoo_data
*yd
= yid
->yd
;
2260 md5_byte_t result
[16];
2266 char *alphabet1
= "FBZDWAGHrJTLMNOPpRSKUVEXYChImkwQ";
2267 char *alphabet2
= "F0E1D2C3B4A59687abcdefghijklmnop";
2269 char *challenge_lookup
= "qzec2tb3um1olpar8whx4dfgijknsvy5";
2270 char *operand_lookup
= "+|&%/*^-";
2271 char *delimit_lookup
= ",;";
2273 unsigned char *password_hash
= malloc(25);
2274 unsigned char *crypt_hash
= malloc(25);
2275 char *crypt_result
= NULL
;
2277 unsigned char pass_hash_xor1
[64];
2278 unsigned char pass_hash_xor2
[64];
2279 unsigned char crypt_hash_xor1
[64];
2280 unsigned char crypt_hash_xor2
[64];
2284 unsigned char digest1
[20];
2285 unsigned char digest2
[20];
2286 unsigned char comparison_src
[20];
2287 unsigned char magic_key_char
[4];
2288 const char *magic_ptr
;
2290 unsigned int magic
[64];
2291 unsigned int magic_work
=0;
2292 unsigned int magic_4
= 0;
2300 memset(password_hash
, 0, 25);
2301 memset(crypt_hash
, 0, 25);
2302 memset(&pass_hash_xor1
, 0, 64);
2303 memset(&pass_hash_xor2
, 0, 64);
2304 memset(&crypt_hash_xor1
, 0, 64);
2305 memset(&crypt_hash_xor2
, 0, 64);
2306 memset(&digest1
, 0, 20);
2307 memset(&digest2
, 0, 20);
2308 memset(&magic
, 0, 64);
2309 memset(&resp_6
, 0, 100);
2310 memset(&resp_96
, 0, 100);
2311 memset(&magic_key_char
, 0, 4);
2312 memset(&comparison_src
, 0, 20);
2315 * Magic: Phase 1. Generate what seems to be a 30
2316 * byte value (could change if base64
2317 * ends up differently? I don't remember and I'm
2318 * tired, so use a 64 byte buffer.
2323 while (*magic_ptr
!= (int)NULL
) {
2326 /* Ignore parentheses. */
2328 if (*magic_ptr
== '(' || *magic_ptr
== ')') {
2333 /* Characters and digits verify against
2334 the challenge lookup.
2337 if (isalpha(*magic_ptr
) || isdigit(*magic_ptr
)) {
2338 loc
= strchr(challenge_lookup
, *magic_ptr
);
2340 /* This isn't good */
2344 /* Get offset into lookup table and lsh 3. */
2346 magic_work
= loc
- challenge_lookup
;
2352 unsigned int local_store
;
2354 loc
= strchr(operand_lookup
, *magic_ptr
);
2356 /* Also not good. */
2360 local_store
= loc
- operand_lookup
;
2362 /* Oops; how did this happen? */
2363 if (magic_cnt
>= 64)
2366 magic
[magic_cnt
++] = magic_work
| local_store
;
2372 magic_len
= magic_cnt
;
2375 /* Magic: Phase 2. Take generated magic value and
2376 * sprinkle fairy dust on the values. */
2378 for (magic_cnt
= magic_len
-2; magic_cnt
>= 0; magic_cnt
--) {
2379 unsigned char byte1
;
2380 unsigned char byte2
;
2383 if ((magic_cnt
>= magic_len
)) {
2384 WARNING(("magic_cnt(%d) magic_len(%d)", magic_cnt
, magic_len
))
2388 byte1
= magic
[magic_cnt
];
2389 byte2
= magic
[magic_cnt
+1];
2394 magic
[magic_cnt
+1] = byte1
;
2398 * Magic: Phase 3. This computes 20 bytes. The first 4 bytes are used as our magic
2399 * key (and may be changed later); the next 16 bytes are an MD5 sum of the magic key
2400 * plus 3 bytes. The 3 bytes are found by looping, and they represent the offsets
2401 * into particular functions we'll later call to potentially alter the magic key.
2410 unsigned int bl
= 0;
2411 unsigned int cl
= magic
[magic_cnt
++];
2413 if (magic_cnt
>= magic_len
)
2418 bl
= cl
= (cl
& 0x1f) << 6;
2420 bl
= magic
[magic_cnt
++];
2421 cl
= (cl
& 0x0f) << 6;
2422 bl
= ((bl
& 0x3f) + cl
) << 6;
2425 cl
= magic
[magic_cnt
++];
2426 bl
= (cl
& 0x3f) + bl
;
2430 comparison_src
[x
++] = (bl
& 0xff00) >> 8;
2431 comparison_src
[x
++] = bl
& 0xff;
2434 /* First four bytes are magic key. */
2435 memcpy(&magic_key_char
[0], comparison_src
, 4);
2436 magic_4
= magic_key_char
[0] | (magic_key_char
[1] << 8) |
2437 (magic_key_char
[2] << 16) | (magic_key_char
[3] << 24);
2440 * Magic: Phase 4. Determine what function to use later by getting outside/inside
2441 * loop values until we match our previous buffer.
2443 for (x
= 0; x
< 65535; x
++) {
2446 for (y
= 0; y
< 5; y
++) {
2447 unsigned char test
[3];
2449 /* Calculate buffer. */
2455 md5_append( &ctx
, magic_key_char
, 4 );
2456 md5_append( &ctx
, test
, 3 );
2457 md5_finish( &ctx
, result
);
2460 if( memcmp( comparison_src
+ 4, result
, 16 ) == 0 ) {
2470 /* If y != 0, we need some help. */
2472 unsigned int updated_key
;
2474 /* Update magic stuff.
2475 * Call it twice because Yahoo's encryption is super bad ass.
2477 updated_key
= yahoo_auth_finalCountdown(magic_4
, 0x60, y
, x
);
2478 updated_key
= yahoo_auth_finalCountdown(updated_key
, 0x60, y
, x
);
2480 magic_key_char
[0] = updated_key
& 0xff;
2481 magic_key_char
[1] = (updated_key
>> 8) & 0xff;
2482 magic_key_char
[2] = (updated_key
>> 16) & 0xff;
2483 magic_key_char
[3] = (updated_key
>> 24) & 0xff;
2486 /* Get password and crypt hashes as per usual. */
2488 md5_append(&ctx
, (md5_byte_t
*)yd
->password
, strlen(yd
->password
));
2489 md5_finish(&ctx
, result
);
2491 to_y64(password_hash
, result
, 16);
2493 crypt_result
= yahoo_crypt(yd
->password
, "$1$_2S43d5f$");
2496 md5_append(&ctx
, (md5_byte_t
*)crypt_result
, strlen(crypt_result
));
2497 md5_finish(&ctx
, result
);
2498 to_y64(crypt_hash
, result
, 16);
2501 /* Our first authentication response is based off
2502 * of the password hash. */
2504 for (x
= 0; x
< (int)strlen((char *)password_hash
); x
++)
2505 pass_hash_xor1
[cnt
++] = password_hash
[x
] ^ 0x36;
2508 memset(&(pass_hash_xor1
[cnt
]), 0x36, 64-cnt
);
2512 for (x
= 0; x
< (int)strlen((char *)password_hash
); x
++)
2513 pass_hash_xor2
[cnt
++] = password_hash
[x
] ^ 0x5c;
2516 memset(&(pass_hash_xor2
[cnt
]), 0x5c, 64-cnt
);
2521 /* The first context gets the password hash XORed
2522 * with 0x36 plus a magic value
2523 * which we previously extrapolated from our
2526 SHA1Update(&ctx1
, pass_hash_xor1
, 64);
2528 ctx1
.totalLength
= 0x1ff;
2529 SHA1Update(&ctx1
, magic_key_char
, 4);
2530 SHA1Final(&ctx1
, digest1
);
2532 /* The second context gets the password hash XORed
2533 * with 0x5c plus the SHA-1 digest
2534 * of the first context. */
2536 SHA1Update(&ctx2
, pass_hash_xor2
, 64);
2537 SHA1Update(&ctx2
, digest1
, 20);
2538 SHA1Final(&ctx2
, digest2
);
2540 /* Now that we have digest2, use it to fetch
2541 * characters from an alphabet to construct
2542 * our first authentication response. */
2544 for (x
= 0; x
< 20; x
+= 2) {
2545 unsigned int val
= 0;
2546 unsigned int lookup
= 0;
2550 memset(&byte
, 0, 6);
2552 /* First two bytes of digest stuffed
2558 val
+= digest2
[x
+1];
2560 lookup
= (val
>> 0x0b);
2562 if (lookup
>= strlen(alphabet1
))
2564 sprintf(byte
, "%c", alphabet1
[lookup
]);
2565 strcat(resp_6
, byte
);
2566 strcat(resp_6
, "=");
2568 lookup
= (val
>> 0x06);
2570 if (lookup
>= strlen(alphabet2
))
2572 sprintf(byte
, "%c", alphabet2
[lookup
]);
2573 strcat(resp_6
, byte
);
2575 lookup
= (val
>> 0x01);
2577 if (lookup
>= strlen(alphabet2
))
2579 sprintf(byte
, "%c", alphabet2
[lookup
]);
2580 strcat(resp_6
, byte
);
2582 lookup
= (val
& 0x01);
2583 if (lookup
>= strlen(delimit_lookup
))
2585 sprintf(byte
, "%c", delimit_lookup
[lookup
]);
2586 strcat(resp_6
, byte
);
2589 /* Our second authentication response is based off
2590 * of the crypto hash. */
2593 memset(&digest1
, 0, 20);
2594 memset(&digest2
, 0, 20);
2596 for (x
= 0; x
< (int)strlen((char *)crypt_hash
); x
++)
2597 crypt_hash_xor1
[cnt
++] = crypt_hash
[x
] ^ 0x36;
2600 memset(&(crypt_hash_xor1
[cnt
]), 0x36, 64-cnt
);
2604 for (x
= 0; x
< (int)strlen((char *)crypt_hash
); x
++)
2605 crypt_hash_xor2
[cnt
++] = crypt_hash
[x
] ^ 0x5c;
2608 memset(&(crypt_hash_xor2
[cnt
]), 0x5c, 64-cnt
);
2613 /* The first context gets the password hash XORed
2614 * with 0x36 plus a magic value
2615 * which we previously extrapolated from our
2618 SHA1Update(&ctx1
, crypt_hash_xor1
, 64);
2620 ctx1
.totalLength
= 0x1ff;
2621 SHA1Update(&ctx1
, magic_key_char
, 4);
2622 SHA1Final(&ctx1
, digest1
);
2624 /* The second context gets the password hash XORed
2625 * with 0x5c plus the SHA-1 digest
2626 * of the first context. */
2628 SHA1Update(&ctx2
, crypt_hash_xor2
, 64);
2629 SHA1Update(&ctx2
, digest1
, 20);
2630 SHA1Final(&ctx2
, digest2
);
2632 /* Now that we have digest2, use it to fetch
2633 * characters from an alphabet to construct
2634 * our first authentication response. */
2636 for (x
= 0; x
< 20; x
+= 2) {
2637 unsigned int val
= 0;
2638 unsigned int lookup
= 0;
2642 memset(&byte
, 0, 6);
2644 /* First two bytes of digest stuffed
2649 val
+= digest2
[x
+1];
2651 lookup
= (val
>> 0x0b);
2653 if (lookup
>= strlen(alphabet1
))
2655 sprintf(byte
, "%c", alphabet1
[lookup
]);
2656 strcat(resp_96
, byte
);
2657 strcat(resp_96
, "=");
2659 lookup
= (val
>> 0x06);
2661 if (lookup
>= strlen(alphabet2
))
2663 sprintf(byte
, "%c", alphabet2
[lookup
]);
2664 strcat(resp_96
, byte
);
2666 lookup
= (val
>> 0x01);
2668 if (lookup
>= strlen(alphabet2
))
2670 sprintf(byte
, "%c", alphabet2
[lookup
]);
2671 strcat(resp_96
, byte
);
2673 lookup
= (val
& 0x01);
2674 if (lookup
>= strlen(delimit_lookup
))
2676 sprintf(byte
, "%c", delimit_lookup
[lookup
]);
2677 strcat(resp_96
, byte
);
2680 pack
= yahoo_packet_new(YAHOO_SERVICE_AUTHRESP
, yd
->initial_status
, yd
->session_id
);
2681 yahoo_packet_hash(pack
, 0, sn
);
2682 yahoo_packet_hash(pack
, 6, resp_6
);
2683 yahoo_packet_hash(pack
, 96, resp_96
);
2684 yahoo_packet_hash(pack
, 1, sn
);
2685 yahoo_packet_hash(pack
, 244, YAHOO_CLIENT_VERSION_ID
);
2686 yahoo_packet_hash(pack
, 135, YAHOO_CLIENT_VERSION
);
2688 yahoo_send_packet(yid
, pack
, 0);
2689 yahoo_packet_free(pack
);
2691 free(password_hash
);
2695 static void yahoo_process_auth(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2699 YList
*l
= pkt
->hash
;
2703 struct yahoo_pair
*pair
= l
->data
;
2704 if (pair
->key
== 94)
2708 if (pair
->key
== 13)
2709 m
= atoi(pair
->value
);
2718 /*yahoo_process_auth_pre_0x0b(yid, seed, sn);
2722 //yahoo_process_auth_0x0b(yid, seed, sn);
2723 yahoo_process_auth_0x10(yid
, seed
, sn
);
2727 WARNING(("unknown auth type %d", m
));
2728 //yahoo_process_auth_0x0b(yid, seed, sn);
2729 yahoo_process_auth_0x10(yid
, seed
, sn
);
2734 static void yahoo_process_auth_resp(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2736 struct yahoo_data
*yd
= yid
->yd
;
2744 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2745 struct yahoo_pair
*pair
= l
->data
;
2747 login_id
= pair
->value
;
2748 else if (pair
->key
== 1)
2749 handle
= pair
->value
;
2750 else if (pair
->key
== 20)
2752 else if (pair
->key
== 66)
2753 login_status
= atoi(pair
->value
);
2756 if(pkt
->status
== 0xffffffff) {
2757 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, login_status
, url
);
2758 /* yahoo_logoff(yd->client_id);*/
2762 static void yahoo_process_mail(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2764 struct yahoo_data
*yd
= yid
->yd
;
2771 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2772 struct yahoo_pair
*pair
= l
->data
;
2774 count
= strtol(pair
->value
, NULL
, 10);
2775 else if (pair
->key
== 43)
2777 else if (pair
->key
== 42)
2778 email
= pair
->value
;
2779 else if (pair
->key
== 18)
2782 LOG(("key: %d => value: %s", pair
->key
, pair
->value
));
2785 if (who
&& email
&& subj
) {
2787 snprintf(from
, sizeof(from
), "%s (%s)", who
, email
);
2788 YAHOO_CALLBACK(ext_yahoo_mail_notify
)(yd
->client_id
, from
, subj
, count
);
2789 } else if(count
> 0)
2790 YAHOO_CALLBACK(ext_yahoo_mail_notify
)(yd
->client_id
, NULL
, NULL
, count
);
2793 static void yahoo_process_contact(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2795 struct yahoo_data
*yd
= yid
->yd
;
2801 int state
= YAHOO_STATUS_AVAILABLE
;
2809 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2810 struct yahoo_pair
*pair
= l
->data
;
2813 else if (pair
->key
== 3)
2815 else if (pair
->key
== 14)
2817 else if (pair
->key
== 7)
2819 else if (pair
->key
== 10)
2820 state
= strtol(pair
->value
, NULL
, 10);
2821 else if (pair
->key
== 15)
2822 tm
= strtol(pair
->value
, NULL
, 10);
2823 else if (pair
->key
== 13)
2824 online
= strtol(pair
->value
, NULL
, 10);
2825 else if (pair
->key
== 47)
2826 away
= strtol(pair
->value
, NULL
, 10);
2827 else if (pair
->key
== 137)
2828 idle
= strtol(pair
->value
, NULL
, 10);
2829 else if (pair
->key
== 60)
2830 mobile
= strtol(pair
->value
, NULL
, 10);
2835 YAHOO_CALLBACK(ext_yahoo_contact_added
)(yd
->client_id
, id
, who
, msg
);
2837 YAHOO_CALLBACK(ext_yahoo_status_changed
)(yd
->client_id
, name
, state
, msg
, away
, idle
, mobile
);
2838 else if(pkt
->status
== 0x07)
2839 YAHOO_CALLBACK(ext_yahoo_rejected
)(yd
->client_id
, who
, msg
);
2842 static void yahoo_process_buddyadd(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2844 struct yahoo_data
*yd
= yid
->yd
;
2850 struct yahoo_buddy
*bud
=NULL
;
2853 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2854 struct yahoo_pair
*pair
= l
->data
;
2859 if (pair
->key
== 65)
2860 where
= pair
->value
;
2861 if (pair
->key
== 66)
2862 status
= strtol(pair
->value
, NULL
, 10);
2865 yahoo_dump_unhandled(pkt
);
2872 bud
= y_new0(struct yahoo_buddy
, 1);
2873 bud
->id
= strdup(who
);
2874 bud
->group
= strdup(where
);
2875 bud
->real_name
= NULL
;
2877 yd
->buddies
= y_list_append(yd
->buddies
, bud
);
2879 /* YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, who, status, NULL, (status==YAHOO_STATUS_AVAILABLE?0:1)); */
2882 static void yahoo_process_buddydel(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2884 struct yahoo_data
*yd
= yid
->yd
;
2889 struct yahoo_buddy
*bud
;
2894 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2895 struct yahoo_pair
*pair
= l
->data
;
2898 else if (pair
->key
== 7)
2900 else if (pair
->key
== 65)
2901 where
= pair
->value
;
2902 else if (pair
->key
== 66)
2903 unk_66
= strtol(pair
->value
, NULL
, 10);
2905 DEBUG_MSG(("unknown key: %d = %s", pair
->key
, pair
->value
));
2911 bud
= y_new0(struct yahoo_buddy
, 1);
2912 bud
->id
= strdup(who
);
2913 bud
->group
= strdup(where
);
2915 buddy
= y_list_find_custom(yd
->buddies
, bud
, is_same_bud
);
2923 yd
->buddies
= y_list_remove_link(yd
->buddies
, buddy
);
2924 y_list_free_1(buddy
);
2928 FREE(bud
->real_name
);
2935 static void yahoo_process_ignore(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2943 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2944 struct yahoo_pair
*pair
= l
->data
;
2949 if (pair
->key
== 13) /* 1 == ignore, 2 == unignore */
2950 un_ignore
= strtol(pair
->value
, NULL
, 10);
2951 if (pair
->key
== 66)
2952 status
= strtol(pair
->value
, NULL
, 10);
2959 * 2 - already in ignore list, could not add
2960 * 3 - not in ignore list, could not delete
2961 * 12 - is a buddy, could not add
2965 YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, who, 0, status);
2969 static void yahoo_process_voicechat(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2974 char *voice_room
= NULL
;
2977 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2978 struct yahoo_pair
*pair
= l
->data
;
2983 if (pair
->key
== 13)
2984 voice_room
=pair
->value
;
2985 if (pair
->key
== 57)
2989 NOTICE(("got voice chat invite from %s in %s to identity %s", who
, room
, me
));
2991 * send: s:0 1:me 5:who 57:room 13:1
2992 * ???? s:4 5:who 10:99 19:-1615114531
2993 * gotr: s:4 5:who 10:99 19:-1615114615
2994 * ???? s:1 5:me 4:who 57:room 13:3room
2995 * got: s:1 5:me 4:who 57:room 13:1room
2996 * rej: s:0 1:me 5:who 57:room 13:3
2997 * rejr: s:4 5:who 10:99 19:-1617114599
3001 static void yahoo_process_ping(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
3003 char *errormsg
= NULL
;
3006 for (l
= pkt
->hash
; l
; l
= l
->next
) {
3007 struct yahoo_pair
*pair
= l
->data
;
3008 if (pair
->key
== 16)
3009 errormsg
= pair
->value
;
3012 NOTICE(("got ping packet"));
3013 //YAHOO_CALLBACK(ext_yahoo_got_ping)(yid->yd->client_id, errormsg);
3016 static void _yahoo_webcam_get_server_connected(int fd
, int error
, void *d
)
3018 struct yahoo_input_data
*yid
= d
;
3019 char *who
= yid
->wcm
->user
;
3021 char *packet
= NULL
;
3022 unsigned char magic_nr
[] = {0, 1, 0};
3023 unsigned char header_len
= 8;
3024 unsigned int len
= 0;
3025 unsigned int pos
= 0;
3027 if(error
|| fd
<= 0) {
3034 inputs
= y_list_prepend(inputs
, yid
);
3036 /* send initial packet */
3038 data
= strdup("<RVWCFG>");
3040 data
= strdup("<RUPCFG>");
3041 yahoo_add_to_send_queue(yid
, data
, strlen(data
));
3047 data
= strdup("g=");
3048 data
= y_string_append(data
, who
);
3049 data
= y_string_append(data
, "\r\n");
3051 data
= strdup("f=1\r\n");
3054 packet
= y_new0(char, header_len
+ len
);
3055 packet
[pos
++] = header_len
;
3056 memcpy(packet
+ pos
, magic_nr
, sizeof(magic_nr
));
3057 pos
+= sizeof(magic_nr
);
3058 pos
+= yahoo_put32(packet
+ pos
, len
);
3059 memcpy(packet
+ pos
, data
, len
);
3061 yahoo_add_to_send_queue(yid
, packet
, pos
);
3065 yid
->read_tag
=YAHOO_CALLBACK(ext_yahoo_add_handler
)(yid
->yd
->client_id
, fd
, YAHOO_INPUT_READ
, yid
);
3068 static void yahoo_webcam_get_server(struct yahoo_input_data
*y
, char *who
, char *key
)
3070 struct yahoo_input_data
*yid
= y_new0(struct yahoo_input_data
, 1);
3071 struct yahoo_server_settings
*yss
= y
->yd
->server_settings
;
3073 yid
->type
= YAHOO_CONNECTION_WEBCAM_MASTER
;
3075 yid
->wcm
= y_new0(struct yahoo_webcam
, 1);
3076 yid
->wcm
->user
= who
?strdup(who
):NULL
;
3077 yid
->wcm
->direction
= who
?YAHOO_WEBCAM_DOWNLOAD
:YAHOO_WEBCAM_UPLOAD
;
3078 yid
->wcm
->key
= strdup(key
);
3080 YAHOO_CALLBACK(ext_yahoo_connect_async
)(yid
->yd
->client_id
, yss
->webcam_host
, yss
->webcam_port
,
3081 _yahoo_webcam_get_server_connected
, yid
);
3085 static YList
*webcam_queue
=NULL
;
3086 static void yahoo_process_webcam_key(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
3093 yahoo_dump_unhandled(pkt
);
3094 for (l
= pkt
->hash
; l
; l
= l
->next
) {
3095 struct yahoo_pair
*pair
= l
->data
;
3098 if (pair
->key
== 61)
3106 webcam_queue
= y_list_remove_link(webcam_queue
, webcam_queue
);
3108 yahoo_webcam_get_server(yid
, who
, key
);
3112 static void yahoo_packet_process(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
3114 DEBUG_MSG(("yahoo_packet_process: 0x%02x", pkt
->service
));
3115 switch (pkt
->service
)
3117 case YAHOO_SERVICE_USERSTAT
:
3118 case YAHOO_SERVICE_LOGON
:
3119 case YAHOO_SERVICE_LOGOFF
:
3120 case YAHOO_SERVICE_ISAWAY
:
3121 case YAHOO_SERVICE_ISBACK
:
3122 case YAHOO_SERVICE_GAMELOGON
:
3123 case YAHOO_SERVICE_GAMELOGOFF
:
3124 case YAHOO_SERVICE_IDACT
:
3125 case YAHOO_SERVICE_IDDEACT
:
3126 case YAHOO_SERVICE_STATUS_15
:
3127 yahoo_process_status(yid
, pkt
);
3129 case YAHOO_SERVICE_NOTIFY
:
3130 yahoo_process_notify(yid
, pkt
);
3132 case YAHOO_SERVICE_MESSAGE
:
3133 case YAHOO_SERVICE_GAMEMSG
:
3134 case YAHOO_SERVICE_SYSMESSAGE
:
3135 yahoo_process_message(yid
, pkt
);
3137 case YAHOO_SERVICE_NEWMAIL
:
3138 yahoo_process_mail(yid
, pkt
);
3140 case YAHOO_SERVICE_NEWCONTACT
:
3141 yahoo_process_contact(yid
, pkt
);
3143 case YAHOO_SERVICE_LIST
:
3144 yahoo_process_list(yid
, pkt
);
3146 case YAHOO_SERVICE_VERIFY
:
3147 yahoo_process_verify(yid
, pkt
);
3149 case YAHOO_SERVICE_AUTH
:
3150 yahoo_process_auth(yid
, pkt
);
3152 case YAHOO_SERVICE_AUTHRESP
:
3153 yahoo_process_auth_resp(yid
, pkt
);
3155 case YAHOO_SERVICE_CONFINVITE
:
3156 case YAHOO_SERVICE_CONFADDINVITE
:
3157 case YAHOO_SERVICE_CONFDECLINE
:
3158 case YAHOO_SERVICE_CONFLOGON
:
3159 case YAHOO_SERVICE_CONFLOGOFF
:
3160 case YAHOO_SERVICE_CONFMSG
:
3161 yahoo_process_conference(yid
, pkt
);
3163 case YAHOO_SERVICE_CHATONLINE
:
3164 case YAHOO_SERVICE_CHATGOTO
:
3165 case YAHOO_SERVICE_CHATJOIN
:
3166 case YAHOO_SERVICE_CHATLEAVE
:
3167 case YAHOO_SERVICE_CHATEXIT
:
3168 case YAHOO_SERVICE_CHATLOGOUT
:
3169 case YAHOO_SERVICE_CHATPING
:
3170 case YAHOO_SERVICE_COMMENT
:
3171 yahoo_process_chat(yid
, pkt
);
3173 case YAHOO_SERVICE_P2PFILEXFER
:
3174 case YAHOO_SERVICE_FILETRANSFER
:
3175 yahoo_process_filetransfer(yid
, pkt
);
3177 case YAHOO_SERVICE_ADDBUDDY
:
3178 yahoo_process_buddyadd(yid
, pkt
);
3180 case YAHOO_SERVICE_REMBUDDY
:
3181 yahoo_process_buddydel(yid
, pkt
);
3183 case YAHOO_SERVICE_IGNORECONTACT
:
3184 yahoo_process_ignore(yid
, pkt
);
3186 case YAHOO_SERVICE_VOICECHAT
:
3187 yahoo_process_voicechat(yid
, pkt
);
3189 case YAHOO_SERVICE_WEBCAM
:
3190 yahoo_process_webcam_key(yid
, pkt
);
3192 case YAHOO_SERVICE_PING
:
3193 yahoo_process_ping(yid
, pkt
);
3195 case YAHOO_SERVICE_IDLE
:
3196 case YAHOO_SERVICE_MAILSTAT
:
3197 case YAHOO_SERVICE_CHATINVITE
:
3198 case YAHOO_SERVICE_CALENDAR
:
3199 case YAHOO_SERVICE_NEWPERSONALMAIL
:
3200 case YAHOO_SERVICE_ADDIDENT
:
3201 case YAHOO_SERVICE_ADDIGNORE
:
3202 case YAHOO_SERVICE_GOTGROUPRENAME
:
3203 case YAHOO_SERVICE_GROUPRENAME
:
3204 case YAHOO_SERVICE_PASSTHROUGH2
:
3205 case YAHOO_SERVICE_CHATLOGON
:
3206 case YAHOO_SERVICE_CHATLOGOFF
:
3207 case YAHOO_SERVICE_CHATMSG
:
3208 case YAHOO_SERVICE_REJECTCONTACT
:
3209 case YAHOO_SERVICE_PEERTOPEER
:
3210 WARNING(("unhandled service 0x%02x", pkt
->service
));
3211 yahoo_dump_unhandled(pkt
);
3213 case YAHOO_SERVICE_PICTURE
:
3214 yahoo_process_picture(yid
, pkt
);
3216 case YAHOO_SERVICE_PICTURE_CHECKSUM
:
3217 yahoo_process_picture_checksum(yid
, pkt
);
3219 case YAHOO_SERVICE_PICTURE_UPLOAD
:
3220 yahoo_process_picture_upload(yid
, pkt
);
3222 case YAHOO_SERVICE_LIST_15
:
3223 yahoo_process_list_15(yid
, pkt
);
3225 case YAHOO_SERVICE_AUTH_REQ_15
:
3226 yahoo_process_auth_15(yid
, pkt
);
3229 WARNING(("unknown service 0x%02x", pkt
->service
));
3230 yahoo_dump_unhandled(pkt
);
3235 static struct yahoo_packet
* yahoo_getdata(struct yahoo_input_data
* yid
)
3237 struct yahoo_packet
*pkt
;
3238 struct yahoo_data
*yd
= yid
->yd
;
3245 DEBUG_MSG(("rxlen is %d", yid
->rxlen
));
3246 if (yid
->rxlen
< YAHOO_PACKET_HDRLEN
) {
3247 DEBUG_MSG(("len < YAHOO_PACKET_HDRLEN"));
3251 pos
+= 4; /* YMSG */
3255 pktlen
= yahoo_get16(yid
->rxqueue
+ pos
); pos
+= 2;
3256 DEBUG_MSG(("%d bytes to read, rxlen is %d",
3257 pktlen
, yid
->rxlen
));
3259 if (yid
->rxlen
< (YAHOO_PACKET_HDRLEN
+ pktlen
)) {
3260 DEBUG_MSG(("len < YAHOO_PACKET_HDRLEN + pktlen"));
3264 LOG(("reading packet"));
3265 yahoo_packet_dump(yid
->rxqueue
, YAHOO_PACKET_HDRLEN
+ pktlen
);
3267 pkt
= yahoo_packet_new(0, 0, 0);
3269 pkt
->service
= yahoo_get16(yid
->rxqueue
+ pos
); pos
+= 2;
3270 pkt
->status
= yahoo_get32(yid
->rxqueue
+ pos
); pos
+= 4;
3271 DEBUG_MSG(("Yahoo Service: 0x%02x Status: %d", pkt
->service
,
3273 pkt
->id
= yahoo_get32(yid
->rxqueue
+ pos
); pos
+= 4;
3275 yd
->session_id
= pkt
->id
;
3277 yahoo_packet_read(pkt
, yid
->rxqueue
+ pos
, pktlen
);
3279 yid
->rxlen
-= YAHOO_PACKET_HDRLEN
+ pktlen
;
3280 DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
3282 unsigned char *tmp
= y_memdup(yid
->rxqueue
+ YAHOO_PACKET_HDRLEN
3283 + pktlen
, yid
->rxlen
);
3286 DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
3288 DEBUG_MSG(("freed rxqueue == %p", yid
->rxqueue
));
3295 static void yahoo_yab_read(struct yab
*yab
, unsigned char *d
, int len
)
3298 char *data
= (char *)d
;
3301 DEBUG_MSG(("Got yab: %s", data
));
3302 st
= en
= strstr(data
, "userid=\"");
3304 st
+= strlen("userid=\"");
3305 en
= strchr(st
, '"'); *en
++ = '\0';
3306 yab
->id
= yahoo_xmldecode(st
);
3309 st
= strstr(en
, "fname=\"");
3311 st
+= strlen("fname=\"");
3312 en
= strchr(st
, '"'); *en
++ = '\0';
3313 yab
->fname
= yahoo_xmldecode(st
);
3316 st
= strstr(en
, "lname=\"");
3318 st
+= strlen("lname=\"");
3319 en
= strchr(st
, '"'); *en
++ = '\0';
3320 yab
->lname
= yahoo_xmldecode(st
);
3323 st
= strstr(en
, "nname=\"");
3325 st
+= strlen("nname=\"");
3326 en
= strchr(st
, '"'); *en
++ = '\0';
3327 yab
->nname
= yahoo_xmldecode(st
);
3330 st
= strstr(en
, "email=\"");
3332 st
+= strlen("email=\"");
3333 en
= strchr(st
, '"'); *en
++ = '\0';
3334 yab
->email
= yahoo_xmldecode(st
);
3337 st
= strstr(en
, "hphone=\"");
3339 st
+= strlen("hphone=\"");
3340 en
= strchr(st
, '"'); *en
++ = '\0';
3341 yab
->hphone
= yahoo_xmldecode(st
);
3344 st
= strstr(en
, "wphone=\"");
3346 st
+= strlen("wphone=\"");
3347 en
= strchr(st
, '"'); *en
++ = '\0';
3348 yab
->wphone
= yahoo_xmldecode(st
);
3351 st
= strstr(en
, "mphone=\"");
3353 st
+= strlen("mphone=\"");
3354 en
= strchr(st
, '"'); *en
++ = '\0';
3355 yab
->mphone
= yahoo_xmldecode(st
);
3358 st
= strstr(en
, "dbid=\"");
3360 st
+= strlen("dbid=\"");
3361 en
= strchr(st
, '"'); *en
++ = '\0';
3362 yab
->dbid
= atoi(st
);
3366 static struct yab
* yahoo_getyab(struct yahoo_input_data
*yid
)
3368 struct yab
*yab
= NULL
;
3370 struct yahoo_data
*yd
= yid
->yd
;
3375 DEBUG_MSG(("rxlen is %d", yid
->rxlen
));
3377 if(yid
->rxlen
<= strlen("<record"))
3380 /* start with <record */
3381 while(pos
< yid
->rxlen
-strlen("<record")+1
3382 && memcmp(yid
->rxqueue
+ pos
, "<record", strlen("<record")))
3385 if(pos
>= yid
->rxlen
-1)
3390 while(end
< yid
->rxlen
-strlen("/>")+1 && memcmp(yid
->rxqueue
+ end
, "/>", strlen("/>")))
3393 if(end
>= yid
->rxlen
-1)
3396 yab
= y_new0(struct yab
, 1);
3397 yahoo_yab_read(yab
, yid
->rxqueue
+ pos
, end
+2-pos
);
3400 yid
->rxlen
-= end
+1;
3401 DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
3403 unsigned char *tmp
= y_memdup(yid
->rxqueue
+ end
+ 1, yid
->rxlen
);
3406 DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
3408 DEBUG_MSG(("freed rxqueue == %p", yid
->rxqueue
));
3416 static char * yahoo_getwebcam_master(struct yahoo_input_data
*yid
)
3420 unsigned int status
=0;
3422 struct yahoo_data
*yd
= yid
->yd
;
3427 DEBUG_MSG(("rxlen is %d", yid
->rxlen
));
3429 len
= yid
->rxqueue
[pos
++];
3430 if (yid
->rxlen
< len
)
3433 /* extract status (0 = ok, 6 = webcam not online) */
3434 status
= yid
->rxqueue
[pos
++];
3438 pos
+= 2; /* skip next 2 bytes */
3439 server
= y_memdup(yid
->rxqueue
+pos
, 16);
3442 else if (status
== 6)
3444 YAHOO_CALLBACK(ext_yahoo_webcam_closed
)
3445 (yd
->client_id
, yid
->wcm
->user
, 4);
3448 /* skip rest of the data */
3451 DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
3453 unsigned char *tmp
= y_memdup(yid
->rxqueue
+ pos
, yid
->rxlen
);
3456 DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
3458 DEBUG_MSG(("freed rxqueue == %p", yid
->rxqueue
));
3465 static int yahoo_get_webcam_data(struct yahoo_input_data
*yid
)
3467 unsigned char reason
=0;
3469 unsigned int begin
=0;
3471 unsigned int closed
=0;
3472 unsigned char header_len
=0;
3475 struct yahoo_data
*yd
= yid
->yd
;
3480 if(!yid
->wcm
|| !yid
->wcd
|| !yid
->rxlen
)
3483 DEBUG_MSG(("rxlen is %d", yid
->rxlen
));
3485 /* if we are not reading part of image then read header */
3486 if (!yid
->wcd
->to_read
)
3488 header_len
=yid
->rxqueue
[pos
++];
3489 yid
->wcd
->packet_type
=0;
3491 if (yid
->rxlen
< header_len
)
3494 if (header_len
>= 8)
3496 reason
= yid
->rxqueue
[pos
++];
3497 /* next 2 bytes should always be 05 00 */
3499 yid
->wcd
->data_size
= yahoo_get32(yid
->rxqueue
+ pos
);
3501 yid
->wcd
->to_read
= yid
->wcd
->data_size
;
3503 if (header_len
>= 13)
3505 yid
->wcd
->packet_type
= yid
->rxqueue
[pos
++];
3506 yid
->wcd
->timestamp
= yahoo_get32(yid
->rxqueue
+ pos
);
3510 /* skip rest of header */
3515 pos
+= yid
->wcd
->to_read
;
3516 if (pos
> yid
->rxlen
) pos
= yid
->rxlen
;
3518 /* if it is not an image then make sure we have the whole packet */
3519 if (yid
->wcd
->packet_type
!= 0x02) {
3520 if ((pos
- begin
) != yid
->wcd
->data_size
) {
3521 yid
->wcd
->to_read
= 0;
3524 yahoo_packet_dump(yid
->rxqueue
+ begin
, pos
- begin
);
3528 DEBUG_MSG(("packet type %.2X, data length %d", yid
->wcd
->packet_type
,
3529 yid
->wcd
->data_size
));
3531 /* find out what kind of packet we got */
3532 switch (yid
->wcd
->packet_type
)
3535 /* user requests to view webcam (uploading) */
3536 if (yid
->wcd
->data_size
&&
3537 yid
->wcm
->direction
== YAHOO_WEBCAM_UPLOAD
) {
3539 while (end
<= yid
->rxlen
&&
3540 yid
->rxqueue
[end
++] != 13);
3543 who
= y_memdup(yid
->rxqueue
+ begin
, end
- begin
);
3544 who
[end
- begin
- 1] = 0;
3545 YAHOO_CALLBACK(ext_yahoo_webcam_viewer
)(yd
->client_id
, who
+ 2, 2);
3550 if (yid
->wcm
->direction
== YAHOO_WEBCAM_DOWNLOAD
) {
3551 /* timestamp/status field */
3552 /* 0 = declined viewing permission */
3553 /* 1 = accepted viewing permission */
3554 if (yid
->wcd
->timestamp
== 0) {
3555 YAHOO_CALLBACK(ext_yahoo_webcam_closed
)(yd
->client_id
, yid
->wcm
->user
, 3);
3559 case 0x01: /* status packets?? */
3560 /* timestamp contains status info */
3561 /* 00 00 00 01 = we have data?? */
3563 case 0x02: /* image data */
3564 YAHOO_CALLBACK(ext_yahoo_got_webcam_image
)(yd
->client_id
,
3565 yid
->wcm
->user
, yid
->rxqueue
+ begin
,
3566 yid
->wcd
->data_size
, pos
- begin
,
3567 yid
->wcd
->timestamp
);
3569 case 0x05: /* response packets when uploading */
3570 if (!yid
->wcd
->data_size
) {
3571 YAHOO_CALLBACK(ext_yahoo_webcam_data_request
)(yd
->client_id
, yid
->wcd
->timestamp
);
3574 case 0x07: /* connection is closing */
3577 case 0x01: /* user closed connection */
3580 case 0x0F: /* user cancelled permission */
3584 YAHOO_CALLBACK(ext_yahoo_webcam_closed
)(yd
->client_id
, yid
->wcm
->user
, closed
);
3586 case 0x0C: /* user connected */
3587 case 0x0D: /* user disconnected */
3588 if (yid
->wcd
->data_size
) {
3589 who
= y_memdup(yid
->rxqueue
+ begin
, pos
- begin
+ 1);
3590 who
[pos
- begin
] = 0;
3591 if (yid
->wcd
->packet_type
== 0x0C)
3595 YAHOO_CALLBACK(ext_yahoo_webcam_viewer
)(yd
->client_id
, who
, connect
);
3599 case 0x13: /* user data */
3600 /* i=user_ip (ip of the user we are viewing) */
3601 /* j=user_ext_ip (external ip of the user we */
3607 yid
->wcd
->to_read
-= pos
- begin
;
3610 DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
3612 unsigned char *tmp
= y_memdup(yid
->rxqueue
+ pos
, yid
->rxlen
);
3615 DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
3617 DEBUG_MSG(("freed rxqueue == %p", yid
->rxqueue
));
3621 /* If we read a complete packet return success */
3622 if (!yid
->wcd
->to_read
)
3628 int yahoo_write_ready(int id
, int fd
, void *data
)
3630 struct yahoo_input_data
*yid
= data
;
3632 struct data_queue
*tx
;
3634 LOG(("write callback: id=%d fd=%d data=%p", id
, fd
, data
));
3635 if(!yid
|| !yid
->txqueues
)
3638 tx
= yid
->txqueues
->data
;
3639 LOG(("writing %d bytes", tx
->len
));
3640 len
= yahoo_send_data(fd
, tx
->queue
, MIN(1024, tx
->len
));
3642 if(len
== -1 && errno
== EAGAIN
)
3647 DEBUG_MSG(("len == %d (<= 0)", len
));
3648 while(yid
->txqueues
) {
3649 YList
*l
=yid
->txqueues
;
3653 yid
->txqueues
= y_list_remove_link(yid
->txqueues
, yid
->txqueues
);
3656 LOG(("yahoo_write_ready(%d, %d) len < 0", id
, fd
));
3657 YAHOO_CALLBACK(ext_yahoo_remove_handler
)(id
, yid
->write_tag
);
3666 unsigned char *tmp
= y_memdup(tx
->queue
+ len
, tx
->len
);
3670 YList
*l
=yid
->txqueues
;
3673 yid
->txqueues
= y_list_remove_link(yid
->txqueues
, yid
->txqueues
);
3677 LOG(("yahoo_write_ready(%d, %d) !yxqueues", id, fd));
3679 if(!yid
->txqueues
) {
3680 LOG(("yahoo_write_ready(%d, %d) !yxqueues", id
, fd
));
3681 YAHOO_CALLBACK(ext_yahoo_remove_handler
)(id
, yid
->write_tag
);
3689 static void yahoo_process_pager_connection(struct yahoo_input_data
*yid
, int over
)
3691 struct yahoo_packet
*pkt
;
3692 struct yahoo_data
*yd
= yid
->yd
;
3693 int id
= yd
->client_id
;
3698 while (find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
)
3699 && (pkt
= yahoo_getdata(yid
)) != NULL
) {
3701 yahoo_packet_process(yid
, pkt
);
3703 yahoo_packet_free(pkt
);
3707 static void yahoo_process_ft_connection(struct yahoo_input_data
*yid
, int over
)
3711 static void yahoo_process_chatcat_connection(struct yahoo_input_data
*yid
, int over
)
3716 if (strstr((char*)yid
->rxqueue
+(yid
->rxlen
-20), "</content>")) {
3717 YAHOO_CALLBACK(ext_yahoo_chat_cat_xml
)(yid
->yd
->client_id
, (char*)yid
->rxqueue
);
3721 static void yahoo_process_yab_connection(struct yahoo_input_data
*yid
, int over
)
3723 struct yahoo_data
*yd
= yid
->yd
;
3727 int id
= yd
->client_id
;
3732 while(find_input_by_id_and_type(id
, YAHOO_CONNECTION_YAB
)
3733 && (yab
= yahoo_getyab(yid
)) != NULL
) {
3737 for(buds
= yd
->buddies
; buds
; buds
=buds
->next
) {
3738 struct yahoo_buddy
* bud
= buds
->data
;
3739 if(!strcmp(bud
->id
, yab
->id
)) {
3740 bud
->yab_entry
= yab
;
3742 bud
->real_name
= strdup(yab
->nname
);
3743 } else if(yab
->fname
&& yab
->lname
) {
3744 bud
->real_name
= y_new0(char,
3746 strlen(yab
->lname
)+2
3748 sprintf(bud
->real_name
, "%s %s",
3749 yab
->fname
, yab
->lname
);
3750 } else if(yab
->fname
) {
3751 bud
->real_name
= strdup(yab
->fname
);
3759 YAHOO_CALLBACK(ext_yahoo_got_buddies
)(yd
->client_id
, yd
->buddies
);
3762 static void yahoo_process_search_connection(struct yahoo_input_data
*yid
, int over
)
3764 struct yahoo_found_contact
*yct
=NULL
;
3765 char *p
= (char *)yid
->rxqueue
, *np
, *cp
;
3767 int start
=0, found
=0, total
=0;
3768 YList
*contacts
=NULL
;
3769 struct yahoo_input_data
*pyid
= find_input_by_id_and_type(yid
->yd
->client_id
, YAHOO_CONNECTION_PAGER
);
3774 if(p
&& (p
=strstr(p
, "\r\n\r\n"))) {
3777 for(k
= 0; (p
= strchr(p
, 4)) && (k
< 4); k
++) {
3781 case 0: found
= pyid
->ys
->lsearch_nfound
= n
; break;
3782 case 2: start
= pyid
->ys
->lsearch_nstart
= n
; break;
3783 case 3: total
= pyid
->ys
->lsearch_ntotal
= n
; break;
3802 if(strlen(cp
) > 2 && y_list_length(contacts
) < total
) {
3803 yct
= y_new0(struct yahoo_found_contact
, 1);
3804 contacts
= y_list_append(contacts
, yct
);
3811 yct
->online
= !strcmp(cp
, "2") ? 1 : 0;
3817 yct
->age
= atoi(cp
);
3820 if( strcmp(cp
,"\005") != 0)
3828 YAHOO_CALLBACK(ext_yahoo_got_search_result
)(yid
->yd
->client_id
, found
, start
, total
, contacts
);
3831 YList
*node
= contacts
;
3832 contacts
= y_list_remove_link(contacts
, node
);
3834 y_list_free_1(node
);
3838 static void _yahoo_webcam_connected(int fd
, int error
, void *d
)
3840 struct yahoo_input_data
*yid
= d
;
3841 struct yahoo_webcam
*wcm
= yid
->wcm
;
3842 struct yahoo_data
*yd
= yid
->yd
;
3843 char conn_type
[100];
3846 unsigned char magic_nr
[] = {1, 0, 0, 0, 1};
3847 unsigned header_len
=0;
3851 if(error
|| fd
<= 0) {
3857 inputs
= y_list_prepend(inputs
, yid
);
3860 /* send initial packet */
3861 switch (wcm
->direction
)
3863 case YAHOO_WEBCAM_DOWNLOAD
:
3864 data
= strdup("<REQIMG>");
3866 case YAHOO_WEBCAM_UPLOAD
:
3867 data
= strdup("<SNDIMG>");
3872 yahoo_add_to_send_queue(yid
, data
, strlen(data
));
3876 switch (wcm
->direction
)
3878 case YAHOO_WEBCAM_DOWNLOAD
:
3880 data
= strdup("a=2\r\nc=us\r\ne=21\r\nu=");
3881 data
= y_string_append(data
, yd
->user
);
3882 data
= y_string_append(data
, "\r\nt=");
3883 data
= y_string_append(data
, wcm
->key
);
3884 data
= y_string_append(data
, "\r\ni=");
3885 data
= y_string_append(data
, wcm
->my_ip
);
3886 data
= y_string_append(data
, "\r\ng=");
3887 data
= y_string_append(data
, wcm
->user
);
3888 data
= y_string_append(data
, "\r\no=w-2-5-1\r\np=");
3889 snprintf(conn_type
, sizeof(conn_type
), "%d", wcm
->conn_type
);
3890 data
= y_string_append(data
, conn_type
);
3891 data
= y_string_append(data
, "\r\n");
3893 case YAHOO_WEBCAM_UPLOAD
:
3895 data
= strdup("a=2\r\nc=us\r\nu=");
3896 data
= y_string_append(data
, yd
->user
);
3897 data
= y_string_append(data
, "\r\nt=");
3898 data
= y_string_append(data
, wcm
->key
);
3899 data
= y_string_append(data
, "\r\ni=");
3900 data
= y_string_append(data
, wcm
->my_ip
);
3901 data
= y_string_append(data
, "\r\no=w-2-5-1\r\np=");
3902 snprintf(conn_type
, sizeof(conn_type
), "%d", wcm
->conn_type
);
3903 data
= y_string_append(data
, conn_type
);
3904 data
= y_string_append(data
, "\r\nb=");
3905 data
= y_string_append(data
, wcm
->description
);
3906 data
= y_string_append(data
, "\r\n");
3911 packet
= y_new0(char, header_len
+ len
);
3912 packet
[pos
++] = header_len
;
3914 switch (wcm
->direction
)
3916 case YAHOO_WEBCAM_DOWNLOAD
:
3920 case YAHOO_WEBCAM_UPLOAD
:
3926 pos
+= yahoo_put32(packet
+ pos
, len
);
3927 if (wcm
->direction
== YAHOO_WEBCAM_UPLOAD
)
3929 memcpy(packet
+ pos
, magic_nr
, sizeof(magic_nr
));
3930 pos
+= sizeof(magic_nr
);
3932 memcpy(packet
+ pos
, data
, len
);
3933 yahoo_add_to_send_queue(yid
, packet
, header_len
+ len
);
3937 yid
->read_tag
=YAHOO_CALLBACK(ext_yahoo_add_handler
)(yid
->yd
->client_id
, yid
->fd
, YAHOO_INPUT_READ
, yid
);
3940 static void yahoo_webcam_connect(struct yahoo_input_data
*y
)
3942 struct yahoo_webcam
*wcm
= y
->wcm
;
3943 struct yahoo_input_data
*yid
;
3944 struct yahoo_server_settings
*yss
;
3946 if (!wcm
|| !wcm
->server
|| !wcm
->key
)
3949 yid
= y_new0(struct yahoo_input_data
, 1);
3950 yid
->type
= YAHOO_CONNECTION_WEBCAM
;
3953 /* copy webcam data to new connection */
3957 yss
= y
->yd
->server_settings
;
3959 yid
->wcd
= y_new0(struct yahoo_webcam_data
, 1);
3961 LOG(("Connecting to: %s:%d", wcm
->server
, wcm
->port
));
3962 YAHOO_CALLBACK(ext_yahoo_connect_async
)(y
->yd
->client_id
, wcm
->server
, wcm
->port
,
3963 _yahoo_webcam_connected
, yid
);
3967 static void yahoo_process_webcam_master_connection(struct yahoo_input_data
*yid
, int over
)
3970 struct yahoo_server_settings
*yss
;
3975 server
= yahoo_getwebcam_master(yid
);
3979 yss
= yid
->yd
->server_settings
;
3980 yid
->wcm
->server
= strdup(server
);
3981 yid
->wcm
->port
= yss
->webcam_port
;
3982 yid
->wcm
->conn_type
= yss
->conn_type
;
3983 yid
->wcm
->my_ip
= strdup(yss
->local_host
);
3984 if (yid
->wcm
->direction
== YAHOO_WEBCAM_UPLOAD
)
3985 yid
->wcm
->description
= strdup(yss
->webcam_description
);
3986 yahoo_webcam_connect(yid
);
3991 static void yahoo_process_webcam_connection(struct yahoo_input_data
*yid
, int over
)
3993 int id
= yid
->yd
->client_id
;
3999 /* as long as we still have packets available keep processing them */
4000 while (find_input_by_id_and_fd(id
, fd
)
4001 && yahoo_get_webcam_data(yid
) == 1);
4004 static void (*yahoo_process_connection
[])(struct yahoo_input_data
*, int over
) = {
4005 yahoo_process_pager_connection
,
4006 yahoo_process_ft_connection
,
4007 yahoo_process_yab_connection
,
4008 yahoo_process_webcam_master_connection
,
4009 yahoo_process_webcam_connection
,
4010 yahoo_process_chatcat_connection
,
4011 yahoo_process_search_connection
4014 int yahoo_read_ready(int id
, int fd
, void *data
)
4016 struct yahoo_input_data
*yid
= data
;
4020 LOG(("read callback: id=%d fd=%d data=%p", id
, fd
, data
));
4026 len
= read(fd
, buf
, sizeof(buf
));
4027 } while(len
== -1 && errno
== EINTR
);
4029 if(len
== -1 && errno
== EAGAIN
) /* we'll try again later */
4034 DEBUG_MSG(("len == %d (<= 0)", len
));
4036 if(yid
->type
== YAHOO_CONNECTION_PAGER
) {
4037 YAHOO_CALLBACK(ext_yahoo_error
)(yid
->yd
->client_id
, "Connection closed by server", 1, E_CONNECTION
);
4040 yahoo_process_connection
[yid
->type
](yid
, 1);
4041 yahoo_input_close(yid
);
4043 /* no need to return an error, because we've already fixed it */
4048 LOG(("read error: %s", strerror(errno
)));
4052 yid
->rxqueue
= y_renew(unsigned char, yid
->rxqueue
, len
+ yid
->rxlen
);
4053 memcpy(yid
->rxqueue
+ yid
->rxlen
, buf
, len
);
4056 yahoo_process_connection
[yid
->type
](yid
, 0);
4061 int yahoo_init_with_attributes(const char *username
, const char *password
, ...)
4064 struct yahoo_data
*yd
;
4066 yd
= y_new0(struct yahoo_data
, 1);
4071 yd
->user
= strdup(username
);
4072 yd
->password
= strdup(password
);
4074 yd
->initial_status
= -1;
4075 yd
->current_status
= -1;
4077 yd
->client_id
= ++last_id
;
4081 va_start(ap
, password
);
4082 yd
->server_settings
= _yahoo_assign_server_settings(ap
);
4085 return yd
->client_id
;
4088 int yahoo_init(const char *username
, const char *password
)
4090 return yahoo_init_with_attributes(username
, password
, (char *)NULL
);
4093 struct connect_callback_data
{
4094 struct yahoo_data
*yd
;
4099 static void yahoo_connected(int fd
, int error
, void *data
)
4101 struct connect_callback_data
*ccd
= data
;
4102 struct yahoo_data
*yd
= ccd
->yd
;
4103 struct yahoo_packet
*pkt
;
4104 struct yahoo_input_data
*yid
;
4105 struct yahoo_server_settings
*yss
= yd
->server_settings
;
4108 if(fallback_ports
[ccd
->i
]) {
4110 yss
->pager_port
= fallback_ports
[ccd
->i
++];
4111 tag
= YAHOO_CALLBACK(ext_yahoo_connect_async
)(yd
->client_id
, yss
->pager_host
,
4112 yss
->pager_port
, yahoo_connected
, ccd
);
4118 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_SOCK
, NULL
);
4125 /* fd < 0 && error == 0 means connect was cancelled */
4129 pkt
= yahoo_packet_new(YAHOO_SERVICE_AUTH
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4130 NOTICE(("Sending initial packet"));
4132 yahoo_packet_hash(pkt
, 1, yd
->user
);
4134 yid
= y_new0(struct yahoo_input_data
, 1);
4137 inputs
= y_list_prepend(inputs
, yid
);
4139 yahoo_send_packet(yid
, pkt
, 0);
4141 yahoo_packet_free(pkt
);
4143 yid
->read_tag
=YAHOO_CALLBACK(ext_yahoo_add_handler
)(yid
->yd
->client_id
, yid
->fd
, YAHOO_INPUT_READ
, yid
);
4146 void yahoo_login(int id
, int initial
)
4148 struct yahoo_data
*yd
= find_conn_by_id(id
);
4149 struct connect_callback_data
*ccd
;
4150 struct yahoo_server_settings
*yss
;
4156 yss
= yd
->server_settings
;
4158 yd
->initial_status
= initial
;
4160 ccd
= y_new0(struct connect_callback_data
, 1);
4162 tag
= YAHOO_CALLBACK(ext_yahoo_connect_async
)(yd
->client_id
, yss
->pager_host
, yss
->pager_port
,
4163 yahoo_connected
, ccd
);
4166 * if tag <= 0, then callback has already been called
4167 * so ccd will have been freed
4172 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_SOCK
, NULL
);
4176 int yahoo_get_fd(int id
)
4178 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4185 void yahoo_send_im(int id
, const char *from
, const char *who
, const char *what
, int utf8
, int picture
)
4187 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4188 struct yahoo_packet
*pkt
= NULL
;
4189 struct yahoo_data
*yd
;
4197 pkt
= yahoo_packet_new(YAHOO_SERVICE_MESSAGE
, YAHOO_STATUS_OFFLINE
, yd
->session_id
);
4199 snprintf(pic_str
, sizeof(pic_str
), "%d", picture
);
4201 if(from
&& strcmp(from
, yd
->user
))
4202 yahoo_packet_hash(pkt
, 0, yd
->user
);
4203 yahoo_packet_hash(pkt
, 1, from
?from
:yd
->user
);
4204 yahoo_packet_hash(pkt
, 5, who
);
4205 yahoo_packet_hash(pkt
, 14, what
);
4208 yahoo_packet_hash(pkt
, 97, "1");
4210 yahoo_packet_hash(pkt
, 63, ";0"); /* imvironment name; or ;0 */
4211 yahoo_packet_hash(pkt
, 64, "0");
4212 yahoo_packet_hash(pkt
, 206, pic_str
);
4215 yahoo_send_packet(yid
, pkt
, 0);
4217 yahoo_packet_free(pkt
);
4220 void yahoo_send_typing(int id
, const char *from
, const char *who
, int typ
)
4222 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4223 struct yahoo_data
*yd
;
4224 struct yahoo_packet
*pkt
= NULL
;
4229 pkt
= yahoo_packet_new(YAHOO_SERVICE_NOTIFY
, YAHOO_STATUS_NOTIFY
, yd
->session_id
);
4231 yahoo_packet_hash(pkt
, 5, who
);
4232 yahoo_packet_hash(pkt
, 4, from
?from
:yd
->user
);
4233 yahoo_packet_hash(pkt
, 14, " ");
4234 yahoo_packet_hash(pkt
, 13, typ
? "1" : "0");
4235 yahoo_packet_hash(pkt
, 49, "TYPING");
4237 yahoo_send_packet(yid
, pkt
, 0);
4239 yahoo_packet_free(pkt
);
4242 void yahoo_set_away(int id
, enum yahoo_status state
, const char *msg
, int away
)
4244 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4245 struct yahoo_data
*yd
;
4246 struct yahoo_packet
*pkt
= NULL
;
4256 yd
->current_status
= YAHOO_STATUS_CUSTOM
;
4258 yd
->current_status
= state
;
4261 if (yd
->current_status
== YAHOO_STATUS_AVAILABLE
)
4262 service
= YAHOO_SERVICE_ISBACK
;
4264 service
= YAHOO_SERVICE_ISAWAY
;
4266 if ((away
== 2) && (yd
->current_status
== YAHOO_STATUS_AVAILABLE
)) {
4267 pkt
= yahoo_packet_new(YAHOO_SERVICE_ISAWAY
, YAHOO_STATUS_BRB
, yd
->session_id
);
4268 yahoo_packet_hash(pkt
, 10, "999");
4269 yahoo_packet_hash(pkt
, 47, "2");
4271 pkt
= yahoo_packet_new(service
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4272 snprintf(s
, sizeof(s
), "%d", yd
->current_status
);
4273 yahoo_packet_hash(pkt
, 10, s
);
4274 if (yd
->current_status
== YAHOO_STATUS_CUSTOM
) {
4275 yahoo_packet_hash(pkt
, 19, msg
);
4276 yahoo_packet_hash(pkt
, 47, (away
== 2)? "2": (away
) ?"1":"0");
4278 yahoo_packet_hash(pkt
, 47, (away
== 2)? "2": (away
) ?"1":"0");
4285 yahoo_send_packet(yid
, pkt
, 0);
4286 yahoo_packet_free(pkt
);
4289 void yahoo_logoff(int id
)
4291 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4292 struct yahoo_data
*yd
;
4293 struct yahoo_packet
*pkt
= NULL
;
4299 LOG(("yahoo_logoff: current status: %d", yd
->current_status
));
4301 if(yd
->current_status
!= -1) {
4302 pkt
= yahoo_packet_new(YAHOO_SERVICE_LOGOFF
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4303 yd
->current_status
= -1;
4306 yahoo_send_packet(yid
, pkt
, 0);
4307 yahoo_packet_free(pkt
);
4313 yahoo_input_close(yid);
4314 } while((yid = find_input_by_id(id)));*/
4318 void yahoo_get_list(int id
)
4320 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4321 struct yahoo_data
*yd
;
4322 struct yahoo_packet
*pkt
= NULL
;
4328 pkt
= yahoo_packet_new(YAHOO_SERVICE_LIST
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4329 yahoo_packet_hash(pkt
, 1, yd
->user
);
4331 yahoo_send_packet(yid
, pkt
, 0);
4332 yahoo_packet_free(pkt
);
4336 static void _yahoo_http_connected(int id
, int fd
, int error
, void *data
)
4338 struct yahoo_input_data
*yid
= data
;
4340 inputs
= y_list_remove(inputs
, yid
);
4346 yid
->read_tag
=YAHOO_CALLBACK(ext_yahoo_add_handler
)(yid
->yd
->client_id
, fd
, YAHOO_INPUT_READ
, yid
);
4349 void yahoo_get_yab(int id
)
4351 struct yahoo_data
*yd
= find_conn_by_id(id
);
4352 struct yahoo_input_data
*yid
;
4359 yid
= y_new0(struct yahoo_input_data
, 1);
4361 yid
->type
= YAHOO_CONNECTION_YAB
;
4363 snprintf(url
, 1024, "http://insider.msg.yahoo.com/ycontent/?ab2=0");
4365 snprintf(buff
, sizeof(buff
), "Y=%s; T=%s",
4366 yd
->cookie_y
, yd
->cookie_t
);
4368 inputs
= y_list_prepend(inputs
, yid
);
4370 yahoo_http_get(yid
->yd
->client_id
, url
, buff
,
4371 _yahoo_http_connected
, yid
);
4374 void yahoo_set_yab(int id
, struct yab
* yab
)
4376 struct yahoo_data
*yd
= find_conn_by_id(id
);
4377 struct yahoo_input_data
*yid
;
4381 int size
= sizeof(url
)-1;
4386 yid
= y_new0(struct yahoo_input_data
, 1);
4387 yid
->type
= YAHOO_CONNECTION_YAB
;
4390 strncpy(url
, "http://insider.msg.yahoo.com/ycontent/?addab2=0", size
);
4393 /* change existing yab */
4395 strncat(url
, "&ee=1&ow=1&id=", size
- strlen(url
));
4396 snprintf(tmp
, sizeof(tmp
), "%d", yab
->dbid
);
4397 strncat(url
, tmp
, size
- strlen(url
));
4401 strncat(url
, "&fn=", size
- strlen(url
));
4402 temp
= yahoo_urlencode(yab
->fname
);
4403 strncat(url
, temp
, size
- strlen(url
));
4407 strncat(url
, "&ln=", size
- strlen(url
));
4408 temp
= yahoo_urlencode(yab
->lname
);
4409 strncat(url
, temp
, size
- strlen(url
));
4412 strncat(url
, "&yid=", size
- strlen(url
));
4413 temp
= yahoo_urlencode(yab
->id
);
4414 strncat(url
, temp
, size
- strlen(url
));
4417 strncat(url
, "&nn=", size
- strlen(url
));
4418 temp
= yahoo_urlencode(yab
->nname
);
4419 strncat(url
, temp
, size
- strlen(url
));
4423 strncat(url
, "&e=", size
- strlen(url
));
4424 temp
= yahoo_urlencode(yab
->email
);
4425 strncat(url
, temp
, size
- strlen(url
));
4429 strncat(url
, "&hp=", size
- strlen(url
));
4430 temp
= yahoo_urlencode(yab
->hphone
);
4431 strncat(url
, temp
, size
- strlen(url
));
4435 strncat(url
, "&wp=", size
- strlen(url
));
4436 temp
= yahoo_urlencode(yab
->wphone
);
4437 strncat(url
, temp
, size
- strlen(url
));
4441 strncat(url
, "&mp=", size
- strlen(url
));
4442 temp
= yahoo_urlencode(yab
->mphone
);
4443 strncat(url
, temp
, size
- strlen(url
));
4446 strncat(url
, "&pp=0", size
- strlen(url
));
4448 snprintf(buff
, sizeof(buff
), "Y=%s; T=%s",
4449 yd
->cookie_y
, yd
->cookie_t
);
4451 inputs
= y_list_prepend(inputs
, yid
);
4453 yahoo_http_get(yid
->yd
->client_id
, url
, buff
,
4454 _yahoo_http_connected
, yid
);
4457 void yahoo_set_identity_status(int id
, const char * identity
, int active
)
4459 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4460 struct yahoo_data
*yd
;
4461 struct yahoo_packet
*pkt
= NULL
;
4467 pkt
= yahoo_packet_new(active
?YAHOO_SERVICE_IDACT
:YAHOO_SERVICE_IDDEACT
,
4468 YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4469 yahoo_packet_hash(pkt
, 3, identity
);
4471 yahoo_send_packet(yid
, pkt
, 0);
4472 yahoo_packet_free(pkt
);
4476 void yahoo_refresh(int id
)
4478 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4479 struct yahoo_data
*yd
;
4480 struct yahoo_packet
*pkt
= NULL
;
4486 pkt
= yahoo_packet_new(YAHOO_SERVICE_USERSTAT
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4488 yahoo_send_packet(yid
, pkt
, 0);
4489 yahoo_packet_free(pkt
);
4493 void yahoo_keepalive(int id
)
4495 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4496 struct yahoo_data
*yd
;
4497 struct yahoo_packet
*pkt
=NULL
;
4502 pkt
= yahoo_packet_new(YAHOO_SERVICE_PING
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4503 yahoo_send_packet(yid
, pkt
, 0);
4504 yahoo_packet_free(pkt
);
4507 void yahoo_chat_keepalive (int id
)
4509 struct yahoo_input_data
*yid
= find_input_by_id_and_type (id
, YAHOO_CONNECTION_PAGER
);
4510 struct yahoo_data
*yd
;
4511 struct yahoo_packet
*pkt
= NULL
;
4518 pkt
= yahoo_packet_new (YAHOO_SERVICE_CHATPING
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4519 yahoo_send_packet (yid
, pkt
, 0);
4520 yahoo_packet_free (pkt
);
4523 void yahoo_add_buddy(int id
, const char *who
, const char *group
, const char *msg
)
4525 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4526 struct yahoo_data
*yd
;
4527 struct yahoo_packet
*pkt
;
4536 pkt
= yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4538 yahoo_packet_hash(pkt
, 14, msg
);
4539 yahoo_packet_hash(pkt
, 65, group
);
4540 yahoo_packet_hash(pkt
, 97, "1");
4541 yahoo_packet_hash(pkt
, 1, yd
->user
);
4542 yahoo_packet_hash(pkt
, 302, "319");
4543 yahoo_packet_hash(pkt
, 300, "319");
4544 yahoo_packet_hash(pkt
, 7, who
);
4545 yahoo_packet_hash(pkt
, 334, "0");
4546 yahoo_packet_hash(pkt
, 301, "319");
4547 yahoo_packet_hash(pkt
, 303, "319");
4549 yahoo_send_packet(yid
, pkt
, 0);
4550 yahoo_packet_free(pkt
);
4553 void yahoo_remove_buddy(int id
, const char *who
, const char *group
)
4555 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4556 struct yahoo_data
*yd
;
4557 struct yahoo_packet
*pkt
= NULL
;
4563 pkt
= yahoo_packet_new(YAHOO_SERVICE_REMBUDDY
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4565 yahoo_packet_hash(pkt
, 1, yd
->user
);
4566 yahoo_packet_hash(pkt
, 7, who
);
4567 yahoo_packet_hash(pkt
, 65, group
);
4568 yahoo_send_packet(yid
, pkt
, 0);
4569 yahoo_packet_free(pkt
);
4572 void yahoo_reject_buddy(int id
, const char *who
, const char *msg
)
4574 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4575 struct yahoo_data
*yd
;
4576 struct yahoo_packet
*pkt
;
4585 pkt
= yahoo_packet_new(YAHOO_SERVICE_REJECTCONTACT
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4586 yahoo_packet_hash(pkt
, 1, yd
->user
);
4587 yahoo_packet_hash(pkt
, 7, who
);
4588 yahoo_packet_hash(pkt
, 14, msg
);
4589 yahoo_send_packet(yid
, pkt
, 0);
4590 yahoo_packet_free(pkt
);
4593 void yahoo_auth_deny(int id
, const char *who
)
4595 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4596 struct yahoo_data
*yd
;
4597 struct yahoo_packet
*pkt
;
4606 pkt
= yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4607 yahoo_packet_hash(pkt
, 1, yd
->user
);
4608 yahoo_packet_hash(pkt
, 5, who
);
4609 yahoo_packet_hash(pkt
, 13, "2");
4610 yahoo_packet_hash(pkt
, 334, "0");
4611 yahoo_packet_hash(pkt
, 97, "1");
4612 yahoo_packet_hash(pkt
, 14, "");
4613 yahoo_send_packet(yid
, pkt
, 0);
4614 yahoo_packet_free(pkt
);
4618 void yahoo_auth_grant(int id
, const char *who
)
4620 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4621 struct yahoo_data
*yd
;
4622 struct yahoo_packet
*pkt
;
4631 pkt
= yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4632 yahoo_packet_hash(pkt
, 1, yd
->user
);
4633 yahoo_packet_hash(pkt
, 5, who
);
4634 // yahoo_packet_hash(pkt, 241, 0);
4635 yahoo_packet_hash(pkt
, 13, "1");
4636 yahoo_packet_hash(pkt
, 334, "0");
4637 yahoo_send_packet(yid
, pkt
, 0);
4638 yahoo_packet_free(pkt
);
4642 void yahoo_ignore_buddy(int id
, const char *who
, int unignore
)
4644 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4645 struct yahoo_data
*yd
;
4646 struct yahoo_packet
*pkt
;
4655 pkt
= yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4656 yahoo_packet_hash(pkt
, 1, yd
->user
);
4657 yahoo_packet_hash(pkt
, 7, who
);
4658 yahoo_packet_hash(pkt
, 13, unignore
?"2":"1");
4659 yahoo_send_packet(yid
, pkt
, 0);
4660 yahoo_packet_free(pkt
);
4663 void yahoo_stealth_buddy(int id
, const char *who
, int unstealth
)
4665 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4666 struct yahoo_data
*yd
;
4667 struct yahoo_packet
*pkt
;
4676 pkt
= yahoo_packet_new(YAHOO_SERVICE_STEALTH
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4677 yahoo_packet_hash(pkt
, 1, yd
->user
);
4678 yahoo_packet_hash(pkt
, 7, who
);
4679 yahoo_packet_hash(pkt
, 31, unstealth
?"2":"1");
4680 yahoo_packet_hash(pkt
, 13, "2");
4681 yahoo_send_packet(yid
, pkt
, 0);
4682 yahoo_packet_free(pkt
);
4685 void yahoo_change_buddy_group(int id
, const char *who
, const char *old_group
, const char *new_group
)
4687 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4688 struct yahoo_data
*yd
;
4689 struct yahoo_packet
*pkt
= NULL
;
4695 pkt
= yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4696 yahoo_packet_hash(pkt
, 1, yd
->user
);
4697 yahoo_packet_hash(pkt
, 7, who
);
4698 yahoo_packet_hash(pkt
, 65, new_group
);
4699 yahoo_packet_hash(pkt
, 14, " ");
4701 yahoo_send_packet(yid
, pkt
, 0);
4702 yahoo_packet_free(pkt
);
4704 pkt
= yahoo_packet_new(YAHOO_SERVICE_REMBUDDY
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4705 yahoo_packet_hash(pkt
, 1, yd
->user
);
4706 yahoo_packet_hash(pkt
, 7, who
);
4707 yahoo_packet_hash(pkt
, 65, old_group
);
4708 yahoo_send_packet(yid
, pkt
, 0);
4709 yahoo_packet_free(pkt
);
4712 void yahoo_group_rename(int id
, const char *old_group
, const char *new_group
)
4714 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4715 struct yahoo_data
*yd
;
4716 struct yahoo_packet
*pkt
= NULL
;
4722 pkt
= yahoo_packet_new(YAHOO_SERVICE_GROUPRENAME
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4723 yahoo_packet_hash(pkt
, 1, yd
->user
);
4724 yahoo_packet_hash(pkt
, 65, old_group
);
4725 yahoo_packet_hash(pkt
, 67, new_group
);
4727 yahoo_send_packet(yid
, pkt
, 0);
4728 yahoo_packet_free(pkt
);
4731 void yahoo_conference_addinvite(int id
, const char * from
, const char *who
, const char *room
, const YList
* members
, const char *msg
)
4733 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4734 struct yahoo_data
*yd
;
4735 struct yahoo_packet
*pkt
;
4741 pkt
= yahoo_packet_new(YAHOO_SERVICE_CONFADDINVITE
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4743 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4744 yahoo_packet_hash(pkt
, 51, who
);
4745 yahoo_packet_hash(pkt
, 57, room
);
4746 yahoo_packet_hash(pkt
, 58, msg
);
4747 yahoo_packet_hash(pkt
, 13, "0");
4748 for(; members
; members
= members
->next
) {
4749 yahoo_packet_hash(pkt
, 52, (char *)members
->data
);
4750 yahoo_packet_hash(pkt
, 53, (char *)members
->data
);
4752 /* 52, 53 -> other members? */
4754 yahoo_send_packet(yid
, pkt
, 0);
4756 yahoo_packet_free(pkt
);
4759 void yahoo_conference_invite(int id
, const char * from
, YList
*who
, const char *room
, const char *msg
)
4761 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4762 struct yahoo_data
*yd
;
4763 struct yahoo_packet
*pkt
;
4769 pkt
= yahoo_packet_new(YAHOO_SERVICE_CONFINVITE
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4771 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4772 yahoo_packet_hash(pkt
, 50, yd
->user
);
4773 for(; who
; who
= who
->next
) {
4774 yahoo_packet_hash(pkt
, 52, (char *)who
->data
);
4776 yahoo_packet_hash(pkt
, 57, room
);
4777 yahoo_packet_hash(pkt
, 58, msg
);
4778 yahoo_packet_hash(pkt
, 13, "0");
4780 yahoo_send_packet(yid
, pkt
, 0);
4782 yahoo_packet_free(pkt
);
4785 void yahoo_conference_logon(int id
, const char *from
, YList
*who
, const char *room
)
4787 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4788 struct yahoo_data
*yd
;
4789 struct yahoo_packet
*pkt
;
4795 pkt
= yahoo_packet_new(YAHOO_SERVICE_CONFLOGON
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4797 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4798 for(; who
; who
= who
->next
) {
4799 yahoo_packet_hash(pkt
, 3, (char *)who
->data
);
4801 yahoo_packet_hash(pkt
, 57, room
);
4803 yahoo_send_packet(yid
, pkt
, 0);
4805 yahoo_packet_free(pkt
);
4808 void yahoo_conference_decline(int id
, const char * from
, YList
*who
, const char *room
, const char *msg
)
4810 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4811 struct yahoo_data
*yd
;
4812 struct yahoo_packet
*pkt
;
4818 pkt
= yahoo_packet_new(YAHOO_SERVICE_CONFDECLINE
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4820 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4821 for(; who
; who
= who
->next
) {
4822 yahoo_packet_hash(pkt
, 3, (char *)who
->data
);
4824 yahoo_packet_hash(pkt
, 57, room
);
4825 yahoo_packet_hash(pkt
, 14, msg
);
4827 yahoo_send_packet(yid
, pkt
, 0);
4829 yahoo_packet_free(pkt
);
4832 void yahoo_conference_logoff(int id
, const char * from
, YList
*who
, const char *room
)
4834 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4835 struct yahoo_data
*yd
;
4836 struct yahoo_packet
*pkt
;
4842 pkt
= yahoo_packet_new(YAHOO_SERVICE_CONFLOGOFF
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4844 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4845 for(; who
; who
= who
->next
) {
4846 yahoo_packet_hash(pkt
, 3, (char *)who
->data
);
4848 yahoo_packet_hash(pkt
, 57, room
);
4850 yahoo_send_packet(yid
, pkt
, 0);
4852 yahoo_packet_free(pkt
);
4855 void yahoo_conference_message(int id
, const char * from
, YList
*who
, const char *room
, const char *msg
, int utf8
)
4857 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4858 struct yahoo_data
*yd
;
4859 struct yahoo_packet
*pkt
;
4865 pkt
= yahoo_packet_new(YAHOO_SERVICE_CONFMSG
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4867 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4868 for(; who
; who
= who
->next
) {
4869 yahoo_packet_hash(pkt
, 53, (char *)who
->data
);
4871 yahoo_packet_hash(pkt
, 57, room
);
4872 yahoo_packet_hash(pkt
, 14, msg
);
4875 yahoo_packet_hash(pkt
, 97, "1");
4877 yahoo_send_packet(yid
, pkt
, 0);
4879 yahoo_packet_free(pkt
);
4882 void yahoo_get_chatrooms(int id
, int chatroomid
)
4884 struct yahoo_data
*yd
= find_conn_by_id(id
);
4885 struct yahoo_input_data
*yid
;
4892 yid
= y_new0(struct yahoo_input_data
, 1);
4894 yid
->type
= YAHOO_CONNECTION_CHATCAT
;
4896 if (chatroomid
== 0) {
4897 snprintf(url
, 1024, "http://insider.msg.yahoo.com/ycontent/?chatcat=0");
4899 snprintf(url
, 1024, "http://insider.msg.yahoo.com/ycontent/?chatroom_%d=0",chatroomid
);
4902 snprintf(buff
, sizeof(buff
), "Y=%s; T=%s", yd
->cookie_y
, yd
->cookie_t
);
4904 inputs
= y_list_prepend(inputs
, yid
);
4906 yahoo_http_get(yid
->yd
->client_id
, url
, buff
, _yahoo_http_connected
, yid
);
4909 void yahoo_chat_logon(int id
, const char *from
, const char *room
, const char *roomid
)
4911 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4912 struct yahoo_data
*yd
;
4913 struct yahoo_packet
*pkt
;
4920 pkt
= yahoo_packet_new(YAHOO_SERVICE_CHATONLINE
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4922 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4923 yahoo_packet_hash(pkt
, 109, yd
->user
);
4924 yahoo_packet_hash(pkt
, 6, "abcde");
4926 yahoo_send_packet(yid
, pkt
, 0);
4928 yahoo_packet_free(pkt
);
4930 pkt
= yahoo_packet_new(YAHOO_SERVICE_CHATJOIN
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4932 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4933 yahoo_packet_hash(pkt
, 104, room
);
4934 yahoo_packet_hash(pkt
, 129, roomid
);
4935 yahoo_packet_hash(pkt
, 62, "2"); /* ??? */
4937 yahoo_send_packet(yid
, pkt
, 0);
4939 yahoo_packet_free(pkt
);
4943 void yahoo_chat_message(int id
, const char *from
, const char *room
, const char *msg
, const int msgtype
, const int utf8
)
4945 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4946 struct yahoo_data
*yd
;
4947 struct yahoo_packet
*pkt
;
4955 pkt
= yahoo_packet_new(YAHOO_SERVICE_COMMENT
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4957 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4958 yahoo_packet_hash(pkt
, 104, room
);
4959 yahoo_packet_hash(pkt
, 117, msg
);
4961 snprintf(buf
, sizeof(buf
), "%d", msgtype
);
4962 yahoo_packet_hash(pkt
, 124, buf
);
4965 yahoo_packet_hash(pkt
, 97, "1");
4967 yahoo_send_packet(yid
, pkt
, 0);
4969 yahoo_packet_free(pkt
);
4973 void yahoo_chat_logoff(int id
, const char *from
)
4975 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4976 struct yahoo_data
*yd
;
4977 struct yahoo_packet
*pkt
;
4984 pkt
= yahoo_packet_new(YAHOO_SERVICE_CHATLOGOUT
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4986 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4988 yahoo_send_packet(yid
, pkt
, 0);
4990 yahoo_packet_free(pkt
);
4993 void yahoo_buddyicon_request(int id
, const char *who
)
4995 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4996 struct yahoo_data
*yd
;
4997 struct yahoo_packet
*pkt
;
5004 pkt
= yahoo_packet_new(YAHOO_SERVICE_PICTURE
, YAHOO_STATUS_AVAILABLE
, 0);
5005 yahoo_packet_hash(pkt
, 4, yd
->user
);
5006 yahoo_packet_hash(pkt
, 5, who
);
5007 yahoo_packet_hash(pkt
, 13, "1");
5008 yahoo_send_packet(yid
, pkt
, 0);
5010 yahoo_packet_free(pkt
);
5013 void yahoo_send_picture_info(int id
, const char *who
, const char *url
, int checksum
)
5015 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
5016 struct yahoo_data
*yd
;
5017 struct yahoo_packet
*pkt
;
5018 char checksum_str
[10];
5025 snprintf(checksum_str
, sizeof(checksum_str
), "%d", checksum
);
5027 pkt
= yahoo_packet_new(YAHOO_SERVICE_PICTURE
, YAHOO_STATUS_AVAILABLE
, 0);
5028 yahoo_packet_hash(pkt
, 1, yd
->user
);
5029 yahoo_packet_hash(pkt
, 4, yd
->user
);
5030 yahoo_packet_hash(pkt
, 5, who
);
5031 yahoo_packet_hash(pkt
, 13, "2");
5032 yahoo_packet_hash(pkt
, 20, url
);
5033 yahoo_packet_hash(pkt
, 192, checksum_str
);
5034 yahoo_send_packet(yid
, pkt
, 0);
5036 yahoo_packet_free(pkt
);
5039 void yahoo_send_picture_update(int id
, const char *who
, int type
)
5041 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
5042 struct yahoo_data
*yd
;
5043 struct yahoo_packet
*pkt
;
5051 snprintf(type_str
, sizeof(type_str
), "%d", type
);
5053 pkt
= yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPDATE
, YAHOO_STATUS_AVAILABLE
, 0);
5054 yahoo_packet_hash(pkt
, 1, yd
->user
);
5055 yahoo_packet_hash(pkt
, 5, who
);
5056 yahoo_packet_hash(pkt
, 206, type_str
);
5057 yahoo_send_packet(yid
, pkt
, 0);
5059 yahoo_packet_free(pkt
);
5062 void yahoo_send_picture_checksum(int id
, const char *who
, int checksum
)
5064 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
5065 struct yahoo_data
*yd
;
5066 struct yahoo_packet
*pkt
;
5067 char checksum_str
[10];
5074 snprintf(checksum_str
, sizeof(checksum_str
), "%d", checksum
);
5076 pkt
= yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM
, YAHOO_STATUS_AVAILABLE
, 0);
5077 yahoo_packet_hash(pkt
, 1, yd
->user
);
5079 yahoo_packet_hash(pkt
, 5, who
);
5080 yahoo_packet_hash(pkt
, 192, checksum_str
);
5081 yahoo_packet_hash(pkt
, 212, "1");
5082 yahoo_send_packet(yid
, pkt
, 0);
5084 yahoo_packet_free(pkt
);
5087 void yahoo_webcam_close_feed(int id
, const char *who
)
5089 struct yahoo_input_data
*yid
= find_input_by_id_and_webcam_user(id
, who
);
5092 yahoo_input_close(yid
);
5095 void yahoo_webcam_get_feed(int id
, const char *who
)
5097 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
5098 struct yahoo_data
*yd
;
5099 struct yahoo_packet
*pkt
;
5105 * add the user to the queue. this is a dirty hack, since
5106 * the yahoo server doesn't tell us who's key it's returning,
5107 * we have to just hope that it sends back keys in the same
5108 * order that we request them.
5109 * The queue is popped in yahoo_process_webcam_key
5111 webcam_queue
= y_list_append(webcam_queue
, who
?strdup(who
):NULL
);
5115 pkt
= yahoo_packet_new(YAHOO_SERVICE_WEBCAM
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
5117 yahoo_packet_hash(pkt
, 1, yd
->user
);
5119 yahoo_packet_hash(pkt
, 5, who
);
5120 yahoo_send_packet(yid
, pkt
, 0);
5122 yahoo_packet_free(pkt
);
5125 void yahoo_webcam_send_image(int id
, unsigned char *image
, unsigned int length
, unsigned int timestamp
)
5127 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_WEBCAM
);
5128 unsigned char *packet
;
5129 unsigned char header_len
= 13;
5130 unsigned int pos
= 0;
5135 packet
= y_new0(unsigned char, header_len
);
5137 packet
[pos
++] = header_len
;
5139 packet
[pos
++] = 5; /* version byte?? */
5141 pos
+= yahoo_put32(packet
+ pos
, length
);
5142 packet
[pos
++] = 2; /* packet type, image */
5143 pos
+= yahoo_put32(packet
+ pos
, timestamp
);
5144 yahoo_add_to_send_queue(yid
, packet
, header_len
);
5148 yahoo_add_to_send_queue(yid
, image
, length
);
5151 void yahoo_webcam_accept_viewer(int id
, const char* who
, int accept
)
5153 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_WEBCAM
);
5154 char *packet
= NULL
;
5156 unsigned char header_len
= 13;
5157 unsigned int pos
= 0;
5158 unsigned int len
= 0;
5163 data
= strdup("u=");
5164 data
= y_string_append(data
, (char*)who
);
5165 data
= y_string_append(data
, "\r\n");
5168 packet
= y_new0(char, header_len
+ len
);
5169 packet
[pos
++] = header_len
;
5171 packet
[pos
++] = 5; /* version byte?? */
5173 pos
+= yahoo_put32(packet
+ pos
, len
);
5174 packet
[pos
++] = 0; /* packet type */
5175 pos
+= yahoo_put32(packet
+ pos
, accept
);
5176 memcpy(packet
+ pos
, data
, len
);
5178 yahoo_add_to_send_queue(yid
, packet
, header_len
+ len
);
5182 void yahoo_webcam_invite(int id
, const char *who
)
5184 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
5185 struct yahoo_packet
*pkt
;
5190 pkt
= yahoo_packet_new(YAHOO_SERVICE_NOTIFY
, YAHOO_STATUS_NOTIFY
, yid
->yd
->session_id
);
5192 yahoo_packet_hash(pkt
, 49, "WEBCAMINVITE");
5193 yahoo_packet_hash(pkt
, 14, " ");
5194 yahoo_packet_hash(pkt
, 13, "0");
5195 yahoo_packet_hash(pkt
, 1, yid
->yd
->user
);
5196 yahoo_packet_hash(pkt
, 5, who
);
5197 yahoo_send_packet(yid
, pkt
, 0);
5199 yahoo_packet_free(pkt
);
5202 static void yahoo_search_internal(int id
, int t
, const char *text
, int g
, int ar
, int photo
, int yahoo_only
, int startpos
, int total
)
5204 struct yahoo_data
*yd
= find_conn_by_id(id
);
5205 struct yahoo_input_data
*yid
;
5213 yid
= y_new0(struct yahoo_input_data
, 1);
5215 yid
->type
= YAHOO_CONNECTION_SEARCH
;
5219 .ar=1 - 13-18, 2 - 18-25, 3 - 25-35, 4 - 35-50, 5 - 50-70, 6 - 70+
5222 snprintf(buff
, sizeof(buff
), "&.sq=%%20&.tt=%d&.ss=%d", total
, startpos
);
5224 ctext
= strdup(text
);
5225 while((p
= strchr(ctext
, ' ')))
5228 snprintf(url
, 1024, "http://members.yahoo.com/interests?.oc=m&.kw=%s&.sb=%d&.g=%d&.ar=0%s%s%s",
5229 ctext
, t
, g
, photo
? "&.p=y" : "", yahoo_only
? "&.pg=y" : "",
5230 startpos
? buff
: "");
5234 snprintf(buff
, sizeof(buff
), "Y=%s; T=%s", yd
->cookie_y
, yd
->cookie_t
);
5236 inputs
= y_list_prepend(inputs
, yid
);
5237 yahoo_http_get(yid
->yd
->client_id
, url
, buff
, _yahoo_http_connected
, yid
);
5240 void yahoo_search(int id
, enum yahoo_search_type t
, const char *text
, enum yahoo_search_gender g
, enum yahoo_search_agerange ar
,
5241 int photo
, int yahoo_only
)
5243 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
5244 struct yahoo_search_state
*yss
;
5250 yid
->ys
= y_new0(struct yahoo_search_state
, 1);
5254 FREE(yss
->lsearch_text
);
5255 yss
->lsearch_type
= t
;
5256 yss
->lsearch_text
= strdup(text
);
5257 yss
->lsearch_gender
= g
;
5258 yss
->lsearch_agerange
= ar
;
5259 yss
->lsearch_photo
= photo
;
5260 yss
->lsearch_yahoo_only
= yahoo_only
;
5262 yahoo_search_internal(id
, t
, text
, g
, ar
, photo
, yahoo_only
, 0, 0);
5265 void yahoo_search_again(int id
, int start
)
5267 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
5268 struct yahoo_search_state
*yss
;
5270 if(!yid
|| !yid
->ys
)
5276 start
= yss
->lsearch_nstart
+ yss
->lsearch_nfound
;
5278 yahoo_search_internal(id
, yss
->lsearch_type
, yss
->lsearch_text
,
5279 yss
->lsearch_gender
, yss
->lsearch_agerange
,
5280 yss
->lsearch_photo
, yss
->lsearch_yahoo_only
,
5281 start
, yss
->lsearch_ntotal
);
5284 struct send_file_data
{
5285 struct yahoo_packet
*pkt
;
5286 yahoo_get_fd_callback callback
;
5290 static void _yahoo_send_picture_connected(int id
, int fd
, int error
, void *data
)
5292 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_FT
);
5293 struct send_file_data
*sfd
= data
;
5294 struct yahoo_packet
*pkt
= sfd
->pkt
;
5295 unsigned char buff
[1024];
5298 sfd
->callback(id
, fd
, error
, sfd
->user_data
);
5300 yahoo_packet_free(pkt
);
5301 inputs
= y_list_remove(inputs
, yid
);
5307 yahoo_send_packet(yid
, pkt
, 8);
5308 yahoo_packet_free(pkt
);
5310 snprintf((char *)buff
, sizeof(buff
), "29");
5314 write(yid
->fd
, buff
, 4);
5316 /* YAHOO_CALLBACK(ext_yahoo_add_handler)(nyd->fd, YAHOO_INPUT_READ); */
5318 sfd
->callback(id
, fd
, error
, sfd
->user_data
);
5320 inputs
= y_list_remove(inputs
, yid
);
5322 while(yahoo_tcp_readline(buff, sizeof(buff), nyd->fd) > 0) {
5323 if(!strcmp(buff, ""))
5328 yahoo_input_close(yid
);
5331 void yahoo_send_picture(int id
, const char *name
, unsigned long size
,
5332 yahoo_get_fd_callback callback
, void *data
)
5334 struct yahoo_data
*yd
= find_conn_by_id(id
);
5335 struct yahoo_input_data
*yid
;
5336 struct yahoo_server_settings
*yss
;
5337 struct yahoo_packet
*pkt
= NULL
;
5339 char expire_str
[10];
5340 long content_length
=0;
5341 unsigned char buff
[1024];
5343 struct send_file_data
*sfd
;
5348 yss
= yd
->server_settings
;
5350 yid
= y_new0(struct yahoo_input_data
, 1);
5352 yid
->type
= YAHOO_CONNECTION_FT
;
5354 pkt
= yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPLOAD
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
5356 snprintf(size_str
, sizeof(size_str
), "%ld", size
);
5357 snprintf(expire_str
, sizeof(expire_str
), "%ld", (long)604800);
5359 yahoo_packet_hash(pkt
, 0, yd
->user
);
5360 yahoo_packet_hash(pkt
, 1, yd
->user
);
5361 yahoo_packet_hash(pkt
, 14, "");
5362 yahoo_packet_hash(pkt
, 27, name
);
5363 yahoo_packet_hash(pkt
, 28, size_str
);
5364 yahoo_packet_hash(pkt
, 38, expire_str
);
5367 content_length
= YAHOO_PACKET_HDRLEN
+ yahoo_packet_length(pkt
);
5369 snprintf(url
, sizeof(url
), "http://%s:%d/notifyft",
5370 yss
->filetransfer_host
, yss
->filetransfer_port
);
5371 snprintf((char *)buff
, sizeof(buff
), "Y=%s; T=%s",
5372 yd
->cookie_y
, yd
->cookie_t
);
5373 inputs
= y_list_prepend(inputs
, yid
);
5375 sfd
= y_new0(struct send_file_data
, 1);
5377 sfd
->callback
= callback
;
5378 sfd
->user_data
= data
;
5379 yahoo_http_post(yid
->yd
->client_id
, url
, (char *)buff
, content_length
+4+size
,
5380 _yahoo_send_picture_connected
, sfd
);
5383 static void _yahoo_send_file_connected(int id
, int fd
, int error
, void *data
)
5385 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_FT
);
5386 struct send_file_data
*sfd
= data
;
5387 struct yahoo_packet
*pkt
= sfd
->pkt
;
5388 unsigned char buff
[1024];
5391 sfd
->callback(id
, fd
, error
, sfd
->user_data
);
5393 yahoo_packet_free(pkt
);
5394 inputs
= y_list_remove(inputs
, yid
);
5400 yahoo_send_packet(yid
, pkt
, 8);
5401 yahoo_packet_free(pkt
);
5403 snprintf((char *)buff
, sizeof(buff
), "29");
5407 write(yid
->fd
, buff
, 4);
5409 /* YAHOO_CALLBACK(ext_yahoo_add_handler)(nyd->fd, YAHOO_INPUT_READ); */
5411 sfd
->callback(id
, fd
, error
, sfd
->user_data
);
5413 inputs
= y_list_remove(inputs
, yid
);
5415 while(yahoo_tcp_readline(buff, sizeof(buff), nyd->fd) > 0) {
5416 if(!strcmp(buff, ""))
5421 yahoo_input_close(yid
);
5424 void yahoo_send_file(int id
, const char *who
, const char *msg
,
5425 const char *name
, unsigned long size
,
5426 yahoo_get_fd_callback callback
, void *data
)
5428 struct yahoo_data
*yd
= find_conn_by_id(id
);
5429 struct yahoo_input_data
*yid
;
5430 struct yahoo_server_settings
*yss
;
5431 struct yahoo_packet
*pkt
= NULL
;
5433 long content_length
=0;
5434 unsigned char buff
[1024];
5436 struct send_file_data
*sfd
;
5441 yss
= yd
->server_settings
;
5443 yid
= y_new0(struct yahoo_input_data
, 1);
5445 yid
->type
= YAHOO_CONNECTION_FT
;
5447 pkt
= yahoo_packet_new(YAHOO_SERVICE_FILETRANSFER
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
5449 snprintf(size_str
, sizeof(size_str
), "%ld", size
);
5451 yahoo_packet_hash(pkt
, 0, yd
->user
);
5452 yahoo_packet_hash(pkt
, 5, who
);
5453 yahoo_packet_hash(pkt
, 14, msg
);
5454 yahoo_packet_hash(pkt
, 27, name
);
5455 yahoo_packet_hash(pkt
, 28, size_str
);
5457 content_length
= YAHOO_PACKET_HDRLEN
+ yahoo_packet_length(pkt
);
5459 snprintf(url
, sizeof(url
), "http://%s:%d/notifyft",
5460 yss
->filetransfer_host
, yss
->filetransfer_port
);
5461 snprintf((char *)buff
, sizeof(buff
), "Y=%s; T=%s",
5462 yd
->cookie_y
, yd
->cookie_t
);
5463 inputs
= y_list_prepend(inputs
, yid
);
5465 sfd
= y_new0(struct send_file_data
, 1);
5467 sfd
->callback
= callback
;
5468 sfd
->user_data
= data
;
5469 yahoo_http_post(yid
->yd
->client_id
, url
, (char *)buff
, content_length
+4+size
,
5470 _yahoo_send_file_connected
, sfd
);
5474 enum yahoo_status
yahoo_current_status(int id
)
5476 struct yahoo_data
*yd
= find_conn_by_id(id
);
5478 return YAHOO_STATUS_OFFLINE
;
5479 return yd
->current_status
;
5482 const YList
* yahoo_get_buddylist(int id
)
5484 struct yahoo_data
*yd
= find_conn_by_id(id
);
5490 const YList
* yahoo_get_ignorelist(int id
)
5492 struct yahoo_data
*yd
= find_conn_by_id(id
);
5498 const YList
* yahoo_get_identities(int id
)
5500 struct yahoo_data
*yd
= find_conn_by_id(id
);
5503 return yd
->identities
;
5506 const char * yahoo_get_cookie(int id
, const char *which
)
5508 struct yahoo_data
*yd
= find_conn_by_id(id
);
5511 if(!strncasecmp(which
, "y", 1))
5512 return yd
->cookie_y
;
5513 if(!strncasecmp(which
, "t", 1))
5514 return yd
->cookie_t
;
5515 if(!strncasecmp(which
, "c", 1))
5516 return yd
->cookie_c
;
5517 if(!strncasecmp(which
, "login", 5))
5518 return yd
->login_cookie
;
5522 void yahoo_get_url_handle(int id
, const char *url
,
5523 yahoo_get_url_handle_callback callback
, void *data
)
5525 struct yahoo_data
*yd
= find_conn_by_id(id
);
5529 yahoo_get_url_fd(id
, url
, yd
, callback
, data
);
5532 const char * yahoo_get_profile_url( void )