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
60 # define strrchr rindex
62 char *strchr (), *strrchr ();
64 # define memcpy(d, s, n) bcopy ((s), (d), (n))
65 # define memmove(d, s, n) bcopy ((s), (d), (n))
69 #include <sys/types.h>
72 # include <winsock2.h>
73 # define write(a,b,c) send(a,b,c,0)
74 # define read(a,b,c) recv(a,b,c,0)
83 #include "yahoo_httplib.h"
84 #include "yahoo_util.h"
85 #include "yahoo_auth.h"
87 #include "yahoo2_callbacks.h"
88 #include "yahoo_debug.h"
90 #define snprintf _snprintf
91 #define vsnprintf _vsnprintf
94 #ifdef USE_STRUCT_CALLBACKS
95 struct yahoo_callbacks
*yc
=NULL
;
97 static int yahoo_send_data(int fd
, void *data
, int len
);
99 void yahoo_register_callbacks(struct yahoo_callbacks
* tyc
)
104 #define YAHOO_CALLBACK(x) yc->x
106 #define YAHOO_CALLBACK(x) x
109 int yahoo_log_message(char * fmt
, ...)
114 vsnprintf(out
, sizeof(out
), fmt
, ap
);
116 return YAHOO_CALLBACK(ext_yahoo_log
)("%s", out
);
119 int yahoo_connect(char * host
, int port
)
121 return YAHOO_CALLBACK(ext_yahoo_connect
)(host
, port
);
124 static enum yahoo_log_level log_level
= YAHOO_LOG_NONE
;
126 enum yahoo_log_level
yahoo_get_log_level()
131 int yahoo_set_log_level(enum yahoo_log_level level
)
133 enum yahoo_log_level l
= log_level
;
138 /* default values for servers */
139 static char pager_host
[] = "scs.msg.yahoo.com";
140 static int pager_port
= 5050;
141 static int fallback_ports
[]={23, 25, 80, 20, 119, 8001, 8002, 5050, 0};
142 static char filetransfer_host
[]="filetransfer.msg.yahoo.com";
143 static int filetransfer_port
=80;
144 static char webcam_host
[]="webcam.yahoo.com";
145 static int webcam_port
=5100;
146 static char webcam_description
[]="";
147 static char local_host
[]="";
148 static int conn_type
=Y_WCM_DSL
;
150 static char profile_url
[] = "http://profiles.yahoo.com/";
152 enum yahoo_service
{ /* these are easier to see in hex */
153 YAHOO_SERVICE_LOGON
= 1,
154 YAHOO_SERVICE_LOGOFF
,
155 YAHOO_SERVICE_ISAWAY
,
156 YAHOO_SERVICE_ISBACK
,
157 YAHOO_SERVICE_IDLE
, /* 5 (placemarker) */
158 YAHOO_SERVICE_MESSAGE
,
160 YAHOO_SERVICE_IDDEACT
,
161 YAHOO_SERVICE_MAILSTAT
,
162 YAHOO_SERVICE_USERSTAT
, /* 0xa */
163 YAHOO_SERVICE_NEWMAIL
,
164 YAHOO_SERVICE_CHATINVITE
,
165 YAHOO_SERVICE_CALENDAR
,
166 YAHOO_SERVICE_NEWPERSONALMAIL
,
167 YAHOO_SERVICE_NEWCONTACT
,
168 YAHOO_SERVICE_ADDIDENT
, /* 0x10 */
169 YAHOO_SERVICE_ADDIGNORE
,
171 YAHOO_SERVICE_GOTGROUPRENAME
, /* < 1, 36(old), 37(new) */
172 YAHOO_SERVICE_SYSMESSAGE
= 0x14,
173 YAHOO_SERVICE_PASSTHROUGH2
= 0x16,
174 YAHOO_SERVICE_CONFINVITE
= 0x18,
175 YAHOO_SERVICE_CONFLOGON
,
176 YAHOO_SERVICE_CONFDECLINE
,
177 YAHOO_SERVICE_CONFLOGOFF
,
178 YAHOO_SERVICE_CONFADDINVITE
,
179 YAHOO_SERVICE_CONFMSG
,
180 YAHOO_SERVICE_CHATLOGON
,
181 YAHOO_SERVICE_CHATLOGOFF
,
182 YAHOO_SERVICE_CHATMSG
= 0x20,
183 YAHOO_SERVICE_GAMELOGON
= 0x28,
184 YAHOO_SERVICE_GAMELOGOFF
,
185 YAHOO_SERVICE_GAMEMSG
= 0x2a,
186 YAHOO_SERVICE_FILETRANSFER
= 0x46,
187 YAHOO_SERVICE_VOICECHAT
= 0x4A,
188 YAHOO_SERVICE_NOTIFY
,
189 YAHOO_SERVICE_VERIFY
,
190 YAHOO_SERVICE_P2PFILEXFER
,
191 YAHOO_SERVICE_PEERTOPEER
= 0x4F, /* Checks if P2P possible */
192 YAHOO_SERVICE_WEBCAM
,
193 YAHOO_SERVICE_AUTHRESP
= 0x54,
195 YAHOO_SERVICE_AUTH
= 0x57,
196 YAHOO_SERVICE_ADDBUDDY
= 0x83,
197 YAHOO_SERVICE_REMBUDDY
,
198 YAHOO_SERVICE_IGNORECONTACT
, /* > 1, 7, 13 < 1, 66, 13, 0*/
199 YAHOO_SERVICE_REJECTCONTACT
,
200 YAHOO_SERVICE_GROUPRENAME
= 0x89, /* > 1, 65(new), 66(0), 67(old) */
201 YAHOO_SERVICE_CHATONLINE
= 0x96, /* > 109(id), 1, 6(abcde) < 0,1*/
202 YAHOO_SERVICE_CHATGOTO
,
203 YAHOO_SERVICE_CHATJOIN
, /* > 1 104-room 129-1600326591 62-2 */
204 YAHOO_SERVICE_CHATLEAVE
,
205 YAHOO_SERVICE_CHATEXIT
= 0x9b,
206 YAHOO_SERVICE_CHATLOGOUT
= 0xa0,
207 YAHOO_SERVICE_CHATPING
,
208 YAHOO_SERVICE_COMMENT
= 0xa8,
209 YAHOO_SERVICE_STEALTH
= 0xb9,
210 YAHOO_SERVICE_PICTURE_CHECKSUM
= 0xbd,
211 YAHOO_SERVICE_PICTURE
= 0xbe,
212 YAHOO_SERVICE_PICTURE_UPDATE
= 0xc1,
213 YAHOO_SERVICE_PICTURE_UPLOAD
= 0xc2,
214 YAHOO_SERVICE_Y6_STATUS_UPDATE
= 0xc6,
215 YAHOO_SERVICE_STATUS_15
= 0xf0
223 struct yahoo_packet
{
224 unsigned short int service
;
230 struct yahoo_search_state
{
234 int lsearch_agerange
;
236 int lsearch_yahoo_only
;
243 unsigned char *queue
;
247 struct yahoo_input_data
{
248 struct yahoo_data
*yd
;
249 struct yahoo_webcam
*wcm
;
250 struct yahoo_webcam_data
*wcd
;
251 struct yahoo_search_state
*ys
;
254 enum yahoo_connection_type type
;
256 unsigned char *rxqueue
;
264 struct yahoo_server_settings
{
267 char *filetransfer_host
;
268 int filetransfer_port
;
271 char *webcam_description
;
276 static void * _yahoo_default_server_settings()
278 struct yahoo_server_settings
*yss
= y_new0(struct yahoo_server_settings
, 1);
280 yss
->pager_host
= strdup(pager_host
);
281 yss
->pager_port
= pager_port
;
282 yss
->filetransfer_host
= strdup(filetransfer_host
);
283 yss
->filetransfer_port
= filetransfer_port
;
284 yss
->webcam_host
= strdup(webcam_host
);
285 yss
->webcam_port
= webcam_port
;
286 yss
->webcam_description
= strdup(webcam_description
);
287 yss
->local_host
= strdup(local_host
);
288 yss
->conn_type
= conn_type
;
293 static void * _yahoo_assign_server_settings(va_list ap
)
295 struct yahoo_server_settings
*yss
= _yahoo_default_server_settings();
301 key
= va_arg(ap
, char *);
305 if(!strcmp(key
, "pager_host")) {
306 svalue
= va_arg(ap
, char *);
307 free(yss
->pager_host
);
308 yss
->pager_host
= strdup(svalue
);
309 } else if(!strcmp(key
, "pager_port")) {
310 nvalue
= va_arg(ap
, int);
311 yss
->pager_port
= nvalue
;
312 } else if(!strcmp(key
, "filetransfer_host")) {
313 svalue
= va_arg(ap
, char *);
314 free(yss
->filetransfer_host
);
315 yss
->filetransfer_host
= strdup(svalue
);
316 } else if(!strcmp(key
, "filetransfer_port")) {
317 nvalue
= va_arg(ap
, int);
318 yss
->filetransfer_port
= nvalue
;
319 } else if(!strcmp(key
, "webcam_host")) {
320 svalue
= va_arg(ap
, char *);
321 free(yss
->webcam_host
);
322 yss
->webcam_host
= strdup(svalue
);
323 } else if(!strcmp(key
, "webcam_port")) {
324 nvalue
= va_arg(ap
, int);
325 yss
->webcam_port
= nvalue
;
326 } else if(!strcmp(key
, "webcam_description")) {
327 svalue
= va_arg(ap
, char *);
328 free(yss
->webcam_description
);
329 yss
->webcam_description
= strdup(svalue
);
330 } else if(!strcmp(key
, "local_host")) {
331 svalue
= va_arg(ap
, char *);
332 free(yss
->local_host
);
333 yss
->local_host
= strdup(svalue
);
334 } else if(!strcmp(key
, "conn_type")) {
335 nvalue
= va_arg(ap
, int);
336 yss
->conn_type
= nvalue
;
338 WARNING(("Unknown key passed to yahoo_init, "
339 "perhaps you didn't terminate the list "
347 static void yahoo_free_server_settings(struct yahoo_server_settings
*yss
)
352 free(yss
->pager_host
);
353 free(yss
->filetransfer_host
);
354 free(yss
->webcam_host
);
355 free(yss
->webcam_description
);
356 free(yss
->local_host
);
361 static YList
*conns
=NULL
;
362 static YList
*inputs
=NULL
;
363 static int last_id
=0;
365 static void add_to_list(struct yahoo_data
*yd
)
367 conns
= y_list_prepend(conns
, yd
);
369 static struct yahoo_data
* find_conn_by_id(int id
)
372 for(l
= conns
; l
; l
= y_list_next(l
)) {
373 struct yahoo_data
*yd
= l
->data
;
374 if(yd
->client_id
== id
)
379 static void del_from_list(struct yahoo_data
*yd
)
381 conns
= y_list_remove(conns
, yd
);
384 /* call repeatedly to get the next one */
386 static struct yahoo_input_data * find_input_by_id(int id)
389 for(l = inputs; l; l = y_list_next(l)) {
390 struct yahoo_input_data *yid = l->data;
391 if(yid->yd->client_id == id)
398 static struct yahoo_input_data
* find_input_by_id_and_webcam_user(int id
, const char * who
)
401 LOG(("find_input_by_id_and_webcam_user"));
402 for(l
= inputs
; l
; l
= y_list_next(l
)) {
403 struct yahoo_input_data
*yid
= l
->data
;
404 if(yid
->type
== YAHOO_CONNECTION_WEBCAM
&& yid
->yd
->client_id
== id
406 ((who
&& yid
->wcm
->user
&& !strcmp(who
, yid
->wcm
->user
)) ||
407 !(yid
->wcm
->user
&& !who
)))
413 static struct yahoo_input_data
* find_input_by_id_and_type(int id
, enum yahoo_connection_type type
)
416 LOG(("find_input_by_id_and_type"));
417 for(l
= inputs
; l
; l
= y_list_next(l
)) {
418 struct yahoo_input_data
*yid
= l
->data
;
419 if(yid
->type
== type
&& yid
->yd
->client_id
== id
)
425 static struct yahoo_input_data
* find_input_by_id_and_fd(int id
, int fd
)
428 LOG(("find_input_by_id_and_fd"));
429 for(l
= inputs
; l
; l
= y_list_next(l
)) {
430 struct yahoo_input_data
*yid
= l
->data
;
431 if(yid
->fd
== fd
&& yid
->yd
->client_id
== id
)
437 static int count_inputs_with_id(int id
)
441 LOG(("counting %d", id
));
442 for(l
= inputs
; l
; l
= y_list_next(l
)) {
443 struct yahoo_input_data
*yid
= l
->data
;
444 if(yid
->yd
->client_id
== id
)
452 extern char *yahoo_crypt(char *, char *);
454 /* Free a buddy list */
455 static void yahoo_free_buddies(YList
* list
)
459 for(l
= list
; l
; l
= l
->next
)
461 struct yahoo_buddy
*bud
= l
->data
;
467 FREE(bud
->real_name
);
469 FREE(bud
->yab_entry
->fname
);
470 FREE(bud
->yab_entry
->lname
);
471 FREE(bud
->yab_entry
->nname
);
472 FREE(bud
->yab_entry
->id
);
473 FREE(bud
->yab_entry
->email
);
474 FREE(bud
->yab_entry
->hphone
);
475 FREE(bud
->yab_entry
->wphone
);
476 FREE(bud
->yab_entry
->mphone
);
477 FREE(bud
->yab_entry
);
480 l
->data
= bud
= NULL
;
486 /* Free an identities list */
487 static void yahoo_free_identities(YList
* list
)
492 list
= y_list_remove_link(list
, list
);
497 /* Free webcam data */
498 static void yahoo_free_webcam(struct yahoo_webcam
*wcm
)
504 FREE(wcm
->description
);
510 static void yahoo_free_data(struct yahoo_data
*yd
)
517 FREE(yd
->login_cookie
);
520 yahoo_free_buddies(yd
->buddies
);
521 yahoo_free_buddies(yd
->ignore
);
522 yahoo_free_identities(yd
->identities
);
524 yahoo_free_server_settings(yd
->server_settings
);
529 #define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4)
531 static struct yahoo_packet
*yahoo_packet_new(enum yahoo_service service
,
532 enum yahoo_status status
, int id
)
534 struct yahoo_packet
*pkt
= y_new0(struct yahoo_packet
, 1);
536 pkt
->service
= service
;
537 pkt
->status
= status
;
543 static void yahoo_packet_hash(struct yahoo_packet
*pkt
, int key
, const char *value
)
545 struct yahoo_pair
*pair
= y_new0(struct yahoo_pair
, 1);
547 pair
->value
= strdup(value
);
548 pkt
->hash
= y_list_append(pkt
->hash
, pair
);
551 static int yahoo_packet_length(struct yahoo_packet
*pkt
)
557 for (l
= pkt
->hash
; l
; l
= l
->next
) {
558 struct yahoo_pair
*pair
= l
->data
;
565 len
+= strlen(pair
->value
);
572 #define yahoo_put16(buf, data) ( \
573 (*(buf) = (unsigned char)((data)>>8)&0xff), \
574 (*((buf)+1) = (unsigned char)(data)&0xff), \
576 #define yahoo_get16(buf) ((((*(buf))&0xff)<<8) + ((*((buf)+1)) & 0xff))
577 #define yahoo_put32(buf, data) ( \
578 (*((buf)) = (unsigned char)((data)>>24)&0xff), \
579 (*((buf)+1) = (unsigned char)((data)>>16)&0xff), \
580 (*((buf)+2) = (unsigned char)((data)>>8)&0xff), \
581 (*((buf)+3) = (unsigned char)(data)&0xff), \
583 #define yahoo_get32(buf) ((((*(buf) )&0xff)<<24) + \
584 (((*((buf)+1))&0xff)<<16) + \
585 (((*((buf)+2))&0xff)<< 8) + \
586 (((*((buf)+3))&0xff)))
588 static void yahoo_packet_read(struct yahoo_packet
*pkt
, unsigned char *data
, int len
)
592 while (pos
+ 1 < len
) {
593 char *key
, *value
= NULL
;
597 struct yahoo_pair
*pair
= y_new0(struct yahoo_pair
, 1);
599 key
= malloc(len
+ 1);
601 while (pos
+ 1 < len
) {
602 if (data
[pos
] == 0xc0 && data
[pos
+ 1] == 0x80)
604 key
[x
++] = data
[pos
++];
608 pair
->key
= strtol(key
, NULL
, 10);
612 /* if x is 0 there was no key, so don't accept it */
614 value
= malloc(len
- pos
+ 1);
616 while (pos
+ 1 < len
) {
617 if (data
[pos
] == 0xc0 && data
[pos
+ 1] == 0x80)
620 value
[x
++] = data
[pos
++];
626 pair
->value
= strdup(value
);
628 pkt
->hash
= y_list_append(pkt
->hash
, pair
);
629 DEBUG_MSG(("Key: %d \tValue: %s", pair
->key
, pair
->value
));
636 static void yahoo_packet_write(struct yahoo_packet
*pkt
, unsigned char *data
)
641 for (l
= pkt
->hash
; l
; l
= l
->next
) {
642 struct yahoo_pair
*pair
= l
->data
;
643 unsigned char buf
[100];
645 snprintf((char *)buf
, sizeof(buf
), "%d", pair
->key
);
646 strcpy((char *)data
+ pos
, (char *)buf
);
647 pos
+= strlen((char *)buf
);
651 strcpy((char *)data
+ pos
, pair
->value
);
652 pos
+= strlen(pair
->value
);
658 static void yahoo_dump_unhandled(struct yahoo_packet
*pkt
)
662 NOTICE(("Service: 0x%02x\tStatus: %d", pkt
->service
, pkt
->status
));
663 for (l
= pkt
->hash
; l
; l
= l
->next
) {
664 struct yahoo_pair
*pair
= l
->data
;
665 NOTICE(("\t%d => %s", pair
->key
, pair
->value
));
670 static void yahoo_packet_dump(unsigned char *data
, int len
)
672 if(yahoo_get_log_level() >= YAHOO_LOG_DEBUG
) {
674 for (i
= 0; i
< len
; i
++) {
675 if ((i
% 8 == 0) && i
)
676 YAHOO_CALLBACK(ext_yahoo_log
)(" ");
677 if ((i
% 16 == 0) && i
)
678 YAHOO_CALLBACK(ext_yahoo_log
)("\n");
679 YAHOO_CALLBACK(ext_yahoo_log
)("%02x ", data
[i
]);
681 YAHOO_CALLBACK(ext_yahoo_log
)("\n");
682 for (i
= 0; i
< len
; i
++) {
683 if ((i
% 8 == 0) && i
)
684 YAHOO_CALLBACK(ext_yahoo_log
)(" ");
685 if ((i
% 16 == 0) && i
)
686 YAHOO_CALLBACK(ext_yahoo_log
)("\n");
687 if (isprint(data
[i
]))
688 YAHOO_CALLBACK(ext_yahoo_log
)(" %c ", data
[i
]);
690 YAHOO_CALLBACK(ext_yahoo_log
)(" . ");
692 YAHOO_CALLBACK(ext_yahoo_log
)("\n");
696 static char base64digits
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
697 "abcdefghijklmnopqrstuvwxyz"
699 static void to_y64(unsigned char *out
, const unsigned char *in
, int inlen
)
700 /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
702 for (; inlen
>= 3; inlen
-= 3)
704 *out
++ = base64digits
[in
[0] >> 2];
705 *out
++ = base64digits
[((in
[0]<<4) & 0x30) | (in
[1]>>4)];
706 *out
++ = base64digits
[((in
[1]<<2) & 0x3c) | (in
[2]>>6)];
707 *out
++ = base64digits
[in
[2] & 0x3f];
712 unsigned char fragment
;
714 *out
++ = base64digits
[in
[0] >> 2];
715 fragment
= (in
[0] << 4) & 0x30;
717 fragment
|= in
[1] >> 4;
718 *out
++ = base64digits
[fragment
];
719 *out
++ = (inlen
< 2) ? '-'
720 : base64digits
[(in
[1] << 2) & 0x3c];
726 static void yahoo_add_to_send_queue(struct yahoo_input_data
*yid
, void *data
, int length
)
728 struct data_queue
*tx
= y_new0(struct data_queue
, 1);
729 tx
->queue
= y_new0(unsigned char, length
);
731 memcpy(tx
->queue
, data
, length
);
733 yid
->txqueues
= y_list_append(yid
->txqueues
, tx
);
736 yid
->write_tag
=YAHOO_CALLBACK(ext_yahoo_add_handler
)(yid
->yd
->client_id
, yid
->fd
, YAHOO_INPUT_WRITE
, yid
);
739 static void yahoo_send_packet(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
, int extra_pad
)
741 int pktlen
= yahoo_packet_length(pkt
);
742 int len
= YAHOO_PACKET_HDRLEN
+ pktlen
;
750 data
= y_new0(unsigned char, len
+ 1);
752 memcpy(data
+ pos
, "YMSG", 4); pos
+= 4;
753 pos
+= yahoo_put16(data
+ pos
, 0x000f);
754 pos
+= yahoo_put16(data
+ pos
, 0x0000);
755 pos
+= yahoo_put16(data
+ pos
, pktlen
+ extra_pad
);
756 pos
+= yahoo_put16(data
+ pos
, pkt
->service
);
757 pos
+= yahoo_put32(data
+ pos
, pkt
->status
);
758 pos
+= yahoo_put32(data
+ pos
, pkt
->id
);
760 yahoo_packet_write(pkt
, data
+ pos
);
762 yahoo_packet_dump(data
, len
);
764 if( yid
->type
== YAHOO_CONNECTION_FT
)
765 yahoo_send_data(yid
->fd
, data
, len
);
767 yahoo_add_to_send_queue(yid
, data
, len
);
771 static void yahoo_packet_free(struct yahoo_packet
*pkt
)
774 struct yahoo_pair
*pair
= pkt
->hash
->data
;
779 pkt
->hash
= y_list_remove_link(pkt
->hash
, pkt
->hash
);
785 static int yahoo_send_data(int fd
, void *data
, int len
)
793 yahoo_packet_dump(data
, len
);
796 ret
= write(fd
, data
, len
);
797 } while(ret
== -1 && errno
==EINTR
);
801 LOG(("wrote data: ERR %s", strerror(errno
)));
803 LOG(("wrote data: OK"));
810 void yahoo_close(int id
)
812 struct yahoo_data
*yd
= find_conn_by_id(id
);
823 static void yahoo_input_close(struct yahoo_input_data
*yid
)
825 inputs
= y_list_remove(inputs
, yid
);
827 LOG(("yahoo_input_close(read)"));
828 YAHOO_CALLBACK(ext_yahoo_remove_handler
)(yid
->yd
->client_id
, yid
->read_tag
);
829 LOG(("yahoo_input_close(write)"));
830 YAHOO_CALLBACK(ext_yahoo_remove_handler
)(yid
->yd
->client_id
, yid
->write_tag
);
831 yid
->read_tag
= yid
->write_tag
= 0;
836 if(count_inputs_with_id(yid
->yd
->client_id
) == 0) {
837 LOG(("closing %d", yid
->yd
->client_id
));
838 yahoo_close(yid
->yd
->client_id
);
840 yahoo_free_webcam(yid
->wcm
);
844 FREE(yid
->ys
->lsearch_text
);
850 static int is_same_bud(const void * a
, const void * b
) {
851 const struct yahoo_buddy
*subject
= a
;
852 const struct yahoo_buddy
*object
= b
;
854 return strcmp(subject
->id
, object
->id
);
857 static YList
* bud_str2list(char *rawlist
)
866 lines
= y_strsplit(rawlist
, "\n", -1);
867 for (tmp
= lines
; *tmp
; tmp
++) {
868 struct yahoo_buddy
*newbud
;
870 split
= y_strsplit(*tmp
, ":", 2);
873 if (!split
[0] || !split
[1]) {
877 buddies
= y_strsplit(split
[1], ",", -1);
879 for (bud
= buddies
; bud
&& *bud
; bud
++) {
880 newbud
= y_new0(struct yahoo_buddy
, 1);
881 newbud
->id
= strdup(*bud
);
882 newbud
->group
= strdup(split
[0]);
884 if(y_list_find_custom(l
, newbud
, is_same_bud
)) {
891 newbud
->real_name
= NULL
;
893 l
= y_list_append(l
, newbud
);
895 NOTICE(("Added buddy %s to group %s", newbud
->id
, newbud
->group
));
906 static char * getcookie(char *rawcookie
)
912 if (strlen(rawcookie
) < 2)
915 tmpcookie
= strdup(rawcookie
+2);
916 cookieend
= strchr(tmpcookie
, ';');
921 cookie
= strdup(tmpcookie
);
923 /* cookieend=NULL; not sure why this was there since the value is not preserved in the stack -dd */
928 static char * getlcookie(char *cookie
)
932 char *login_cookie
= NULL
;
934 tmpend
= strstr(cookie
, "n=");
936 tmp
= strdup(tmpend
+2);
937 tmpend
= strchr(tmp
, '&');
940 login_cookie
= strdup(tmp
);
947 static void yahoo_process_notify(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
949 struct yahoo_data
*yd
= yid
->yd
;
957 for (l
= pkt
->hash
; l
; l
= l
->next
) {
958 struct yahoo_pair
*pair
= l
->data
;
966 stat
= atoi(pair
->value
);
969 if (pair
->key
== 16) { /* status == -1 */
970 NOTICE((pair
->value
));
979 if (!strncasecmp(msg
, "TYPING", strlen("TYPING")))
980 YAHOO_CALLBACK(ext_yahoo_typing_notify
)(yd
->client_id
, to
, from
, stat
);
981 else if (!strncasecmp(msg
, "GAME", strlen("GAME")))
982 YAHOO_CALLBACK(ext_yahoo_game_notify
)(yd
->client_id
, to
, from
, stat
);
983 else if (!strncasecmp(msg
, "WEBCAMINVITE", strlen("WEBCAMINVITE")))
985 if (!strcmp(ind
, " ")) {
986 YAHOO_CALLBACK(ext_yahoo_webcam_invite
)(yd
->client_id
, to
, from
);
989 /* accept the invitation (-1 = deny 1 = accept) */
992 YAHOO_CALLBACK(ext_yahoo_webcam_invite_reply
)(yd
->client_id
, to
, from
, accept
);
996 LOG(("Got unknown notification: %s", msg
));
999 static void yahoo_process_filetransfer(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1001 struct yahoo_data
*yd
= yid
->yd
;
1010 char *filename
=NULL
;
1011 unsigned long filesize
=0L;
1014 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1015 struct yahoo_pair
*pair
= l
->data
;
1020 if (pair
->key
== 14)
1022 if (pair
->key
== 20)
1024 if (pair
->key
== 38)
1025 expires
= atol(pair
->value
);
1027 if (pair
->key
== 27)
1028 filename
= pair
->value
;
1029 if (pair
->key
== 28)
1030 filesize
= atol(pair
->value
);
1032 if (pair
->key
== 49)
1033 service
= pair
->value
;
1036 if(pkt
->service
== YAHOO_SERVICE_P2PFILEXFER
) {
1037 if(strcmp("FILEXFER", service
) != 0) {
1038 WARNING(("unhandled service 0x%02x", pkt
->service
));
1039 yahoo_dump_unhandled(pkt
);
1046 tmp
= strchr(msg
, '\006');
1051 YAHOO_CALLBACK(ext_yahoo_got_file
)(yd
->client_id
, to
, from
, url
, expires
, msg
, filename
, filesize
);
1055 static void yahoo_process_conference(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1057 struct yahoo_data
*yd
= yid
->yd
;
1064 YList
*members
= NULL
;
1067 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1068 struct yahoo_pair
*pair
= l
->data
;
1069 if (pair
->key
== 50)
1072 if (pair
->key
== 52) { /* invite */
1073 members
= y_list_append(members
, strdup(pair
->value
));
1075 if (pair
->key
== 53) /* logon */
1077 if (pair
->key
== 54) /* decline */
1079 if (pair
->key
== 55) /* unavailable (status == 2) */
1081 if (pair
->key
== 56) /* logoff */
1084 if (pair
->key
== 57)
1087 if (pair
->key
== 58) /* join message */
1089 if (pair
->key
== 14) /* decline/conf message */
1092 if (pair
->key
== 13)
1094 if (pair
->key
== 16) /* error */
1097 if (pair
->key
== 1) /* my id */
1099 if (pair
->key
== 3) /* message sender */
1102 if (pair
->key
== 97)
1103 utf8
= atoi(pair
->value
);
1110 for(l
= members
; l
; l
= l
->next
) {
1112 if(!strcmp(w
, host
))
1116 members
= y_list_append(members
, strdup(host
));
1118 /* invite, decline, join, left, message -> status == 1 */
1120 switch(pkt
->service
) {
1121 case YAHOO_SERVICE_CONFINVITE
:
1122 if(pkt
->status
== 2)
1125 YAHOO_CALLBACK(ext_yahoo_got_conf_invite
)(yd
->client_id
, host
, room
, msg
, members
);
1127 YAHOO_CALLBACK(ext_yahoo_error
)(yd
->client_id
, msg
, 0, E_CONFNOTAVAIL
);
1129 case YAHOO_SERVICE_CONFADDINVITE
:
1130 if(pkt
->status
== 2)
1133 YAHOO_CALLBACK(ext_yahoo_got_conf_invite
)(yd
->client_id
, host
, room
, msg
, members
);
1135 case YAHOO_SERVICE_CONFDECLINE
:
1137 YAHOO_CALLBACK(ext_yahoo_conf_userdecline
)(yd
->client_id
, who
, room
, msg
);
1139 case YAHOO_SERVICE_CONFLOGON
:
1141 YAHOO_CALLBACK(ext_yahoo_conf_userjoin
)(yd
->client_id
, who
, room
);
1143 case YAHOO_SERVICE_CONFLOGOFF
:
1145 YAHOO_CALLBACK(ext_yahoo_conf_userleave
)(yd
->client_id
, who
, room
);
1147 case YAHOO_SERVICE_CONFMSG
:
1149 YAHOO_CALLBACK(ext_yahoo_conf_message
)(yd
->client_id
, who
, room
, msg
, utf8
);
1154 static void yahoo_process_chat(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1160 YList
*members
= NULL
;
1161 struct yahoo_chat_member
*currentmember
= NULL
;
1165 int membercount
= 0;
1169 yahoo_dump_unhandled(pkt
);
1170 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1171 struct yahoo_pair
*pair
= l
->data
;
1173 if (pair
->key
== 104) {
1178 if (pair
->key
== 105) {
1180 topic
= pair
->value
;
1183 if (pair
->key
== 108) {
1184 /* Number of members in this packet */
1185 membercount
= atoi(pair
->value
);
1188 if (pair
->key
== 109) {
1189 /* message sender */
1192 if (pkt
->service
== YAHOO_SERVICE_CHATJOIN
) {
1193 currentmember
= y_new0(struct yahoo_chat_member
, 1);
1194 currentmember
->id
= strdup(pair
->value
);
1195 members
= y_list_append(members
, currentmember
);
1199 if (pair
->key
== 110) {
1201 if (pkt
->service
== YAHOO_SERVICE_CHATJOIN
)
1202 currentmember
->age
= atoi(pair
->value
);
1205 if (pair
->key
== 113) {
1207 if (pkt
->service
== YAHOO_SERVICE_CHATJOIN
)
1208 currentmember
->attribs
= atoi(pair
->value
);
1211 if (pair
->key
== 141) {
1213 if (pkt
->service
== YAHOO_SERVICE_CHATJOIN
)
1214 currentmember
->alias
= strdup(pair
->value
);
1217 if (pair
->key
== 142) {
1219 if (pkt
->service
== YAHOO_SERVICE_CHATJOIN
)
1220 currentmember
->location
= strdup(pair
->value
);
1224 if (pair
->key
== 130) {
1229 if (pair
->key
== 117) {
1234 if (pair
->key
== 124) {
1236 msgtype
= atoi(pair
->value
);
1238 if (pair
->key
== 114) {
1239 /* message error not sure what all the pair values mean */
1240 /* but -1 means no session in room */
1241 chaterr
= atoi(pair
->value
);
1246 if (pkt
->service
== YAHOO_SERVICE_CHATLOGOUT
) { /* yahoo originated chat logout */
1247 YAHOO_CALLBACK(ext_yahoo_chat_yahoologout
)(yid
->yd
->client_id
);
1250 if (pkt
->service
== YAHOO_SERVICE_COMMENT
&& chaterr
) {
1251 YAHOO_CALLBACK(ext_yahoo_chat_yahooerror
)(yid
->yd
->client_id
);
1255 WARNING(("We didn't get a room name, ignoring packet"));
1259 switch(pkt
->service
) {
1260 case YAHOO_SERVICE_CHATJOIN
:
1261 if(y_list_length(members
) != membercount
) {
1262 WARNING(("Count of members doesn't match No. of members we got"));
1264 if(firstjoin
&& members
) {
1265 YAHOO_CALLBACK(ext_yahoo_chat_join
)(yid
->yd
->client_id
, room
, topic
, members
, yid
->fd
);
1267 if(y_list_length(members
) != 1) {
1268 WARNING(("Got more than 1 member on a normal join"));
1270 /* this should only ever have one, but just in case */
1272 YList
*n
= members
->next
;
1273 currentmember
= members
->data
;
1274 YAHOO_CALLBACK(ext_yahoo_chat_userjoin
)(yid
->yd
->client_id
, room
, currentmember
);
1275 y_list_free_1(members
);
1280 case YAHOO_SERVICE_CHATEXIT
:
1282 YAHOO_CALLBACK(ext_yahoo_chat_userleave
)(yid
->yd
->client_id
, room
, who
);
1285 case YAHOO_SERVICE_COMMENT
:
1287 YAHOO_CALLBACK(ext_yahoo_chat_message
)(yid
->yd
->client_id
, who
, room
, msg
, msgtype
, utf8
);
1293 static void yahoo_process_message(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1295 struct yahoo_data
*yd
= yid
->yd
;
1297 YList
* messages
= NULL
;
1307 } *message
= y_new0(struct m
, 1);
1309 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1310 struct yahoo_pair
*pair
= l
->data
;
1311 if (pair
->key
== 1 || pair
->key
== 4)
1314 message
->from
= pair
->value
;
1316 else if (pair
->key
== 5)
1317 message
->to
= pair
->value
;
1318 else if (pair
->key
== 15)
1319 message
->tm
= strtol(pair
->value
, NULL
, 10);
1320 else if (pair
->key
== 97)
1321 message
->utf8
= atoi(pair
->value
);
1322 /* user message */ /* sys message */
1323 else if (pair
->key
== 14 || pair
->key
== 16)
1324 message
->msg
= pair
->value
;
1325 else if (pair
->key
== 31) {
1327 messages
= y_list_append(messages
, message
);
1328 message
= y_new0(struct m
, 1);
1330 message
->i_31
= atoi(pair
->value
);
1332 else if (pair
->key
== 32)
1333 message
->i_32
= atoi(pair
->value
);
1335 LOG(("yahoo_process_message: status: %d, key: %d, value: %s",
1336 pkt
->status
, pair
->key
, pair
->value
));
1339 messages
= y_list_append(messages
, message
);
1341 for (l
= messages
; l
; l
=l
->next
) {
1343 if (pkt
->service
== YAHOO_SERVICE_SYSMESSAGE
) {
1344 YAHOO_CALLBACK(ext_yahoo_system_message
)(yd
->client_id
, message
->msg
);
1345 } else if (pkt
->status
<= 2 || pkt
->status
== 5) {
1346 YAHOO_CALLBACK(ext_yahoo_got_im
)(yd
->client_id
, message
->to
, message
->from
, message
->msg
, message
->tm
, pkt
->status
, message
->utf8
);
1347 } else if (pkt
->status
== 0xffffffff) {
1348 YAHOO_CALLBACK(ext_yahoo_error
)(yd
->client_id
, message
->msg
, 0, E_SYSTEM
);
1353 y_list_free(messages
);
1357 static void yahoo_process_status(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1360 struct yahoo_data
*yd
= yid
->yd
;
1364 char *name
; /* 7 name */
1365 int state
; /* 10 state */
1366 int flags
; /* 13 flags, bit 0 = pager, bit 1 = chat, bit 2 = game */
1367 int mobile
; /* 60 mobile */
1368 char *msg
; /* 19 custom status message */
1369 int away
; /* 47 away (or invisible)*/
1370 int buddy_session
; /* 11 state */
1371 int f17
; /* 17 in chat? then what about flags? */
1372 int idle
; /* 137 seconds idle */
1373 int f138
; /* 138 state */
1374 char *f184
; /* 184 state */
1375 int f192
; /* 192 state */
1376 int f10001
; /* 10001 state */
1377 int f10002
; /* 10002 state */
1378 int f198
; /* 198 state */
1379 char *f197
; /* 197 state */
1380 char *f205
; /* 205 state */
1381 int f213
; /* 213 state */
1386 if (pkt
->service
== YAHOO_SERVICE_LOGOFF
&& pkt
->status
== -1) {
1387 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_DUPL
, NULL
);
1391 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1392 struct yahoo_pair
*pair
= l
->data
;
1394 switch (pair
->key
) {
1395 case 0: /* we won't actually do anything with this */
1396 NOTICE(("key %d:%s", pair
->key
, pair
->value
));
1398 case 1: /* we don't get the full buddy list here. */
1399 if (!yd
->logged_in
) {
1400 yd
->logged_in
= TRUE
;
1401 if(yd
->current_status
< 0)
1402 yd
->current_status
= yd
->initial_status
;
1403 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_OK
, NULL
);
1406 case 8: /* how many online buddies we have */
1407 NOTICE(("key %d:%s", pair
->key
, pair
->value
));
1409 case 7: /* the current buddy */
1410 u
= y_new0(struct user
, 1);
1411 u
->name
= pair
->value
;
1412 users
= y_list_prepend(users
, u
);
1414 case 10: /* state */
1415 ((struct user
*)users
->data
)->state
= strtol(pair
->value
, NULL
, 10);
1417 case 19: /* custom status message */
1418 ((struct user
*)users
->data
)->msg
= pair
->value
;
1420 case 47: /* is it an away message or not */
1421 ((struct user
*)users
->data
)->away
= atoi(pair
->value
);
1423 case 137: /* seconds idle */
1424 ((struct user
*)users
->data
)->idle
= atoi(pair
->value
);
1426 case 11: /* this is the buddy's session id */
1427 ((struct user
*)users
->data
)->buddy_session
= atoi(pair
->value
);
1429 case 17: /* in chat? */
1430 ((struct user
*)users
->data
)->f17
= atoi(pair
->value
);
1432 case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */
1433 ((struct user
*)users
->data
)->flags
= atoi(pair
->value
);
1435 case 60: /* SMS -> 1 MOBILE USER */
1436 /* sometimes going offline makes this 2, but invisible never sends it */
1437 ((struct user
*)users
->data
)->mobile
= atoi(pair
->value
);
1440 ((struct user
*)users
->data
)->f138
= atoi(pair
->value
);
1443 ((struct user
*)users
->data
)->f184
= pair
->value
;
1446 ((struct user
*)users
->data
)->f192
= atoi(pair
->value
);
1449 ((struct user
*)users
->data
)->f10001
= atoi(pair
->value
);
1452 ((struct user
*)users
->data
)->f10002
= atoi(pair
->value
);
1455 ((struct user
*)users
->data
)->f198
= atoi(pair
->value
);
1458 ((struct user
*)users
->data
)->f197
= pair
->value
;
1461 ((struct user
*)users
->data
)->f205
= pair
->value
;
1464 ((struct user
*)users
->data
)->f213
= atoi(pair
->value
);
1466 case 16: /* Custom error message */
1467 YAHOO_CALLBACK(ext_yahoo_error
)(yd
->client_id
, pair
->value
, 0, E_CUSTOM
);
1470 WARNING(("unknown status key %d:%s", pair
->key
, pair
->value
));
1477 struct user
*u
= users
->data
;
1479 if (u
->name
!= NULL
) {
1480 if (pkt
->service
== YAHOO_SERVICE_LOGOFF
|| u
->flags
== 0) {
1481 YAHOO_CALLBACK(ext_yahoo_status_changed
)(yd
->client_id
, u
->name
, YAHOO_STATUS_OFFLINE
, NULL
, 1, 0, 0);
1483 YAHOO_CALLBACK(ext_yahoo_status_changed
)(yd
->client_id
, u
->name
, u
->state
, u
->msg
, u
->away
, u
->idle
, u
->mobile
);
1487 users
= y_list_remove_link(users
, users
);
1493 static void yahoo_process_list(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1495 struct yahoo_data
*yd
= yid
->yd
;
1498 if (!yd
->logged_in
) {
1499 yd
->logged_in
= TRUE
;
1500 if(yd
->current_status
< 0)
1501 yd
->current_status
= yd
->initial_status
;
1502 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_OK
, NULL
);
1504 pkt
= yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE
, YAHOO_STATUS_AVAILABLE
, 0);
1508 snprintf(buff
, sizeof(buff
)-1, "%d", yd
->current_status
);
1509 yahoo_packet_hash(pkt
, 10, buff
);
1510 yahoo_packet_hash(pkt
, 19, "");
1511 yahoo_send_packet(yid
, pkt
, 0);
1513 yahoo_packet_free(pkt
);
1516 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1517 struct yahoo_pair
*pair
= l
->data
;
1520 case 87: /* buddies */
1521 if(!yd
->rawbuddylist
)
1522 yd
->rawbuddylist
= strdup(pair
->value
);
1524 yd
->rawbuddylist
= y_string_append(yd
->rawbuddylist
, pair
->value
);
1528 case 88: /* ignore list */
1530 yd
->ignorelist
= strdup("Ignore:");
1531 yd
->ignorelist
= y_string_append(yd
->ignorelist
, pair
->value
);
1534 case 89: /* identities */
1536 char **identities
= y_strsplit(pair
->value
, ",", -1);
1538 for(i
=0; identities
[i
]; i
++)
1539 yd
->identities
= y_list_append(yd
->identities
,
1540 strdup(identities
[i
]));
1541 y_strfreev(identities
);
1543 YAHOO_CALLBACK(ext_yahoo_got_identities
)(yd
->client_id
, yd
->identities
);
1545 case 59: /* cookies */
1546 if(yd
->ignorelist
) {
1547 yd
->ignore
= bud_str2list(yd
->ignorelist
);
1548 FREE(yd
->ignorelist
);
1549 YAHOO_CALLBACK(ext_yahoo_got_ignore
)(yd
->client_id
, yd
->ignore
);
1551 if(yd
->rawbuddylist
) {
1552 yd
->buddies
= bud_str2list(yd
->rawbuddylist
);
1553 FREE(yd
->rawbuddylist
);
1554 YAHOO_CALLBACK(ext_yahoo_got_buddies
)(yd
->client_id
, yd
->buddies
);
1557 if(pair
->value
[0]=='Y') {
1559 FREE(yd
->login_cookie
);
1561 yd
->cookie_y
= getcookie(pair
->value
);
1562 yd
->login_cookie
= getlcookie(yd
->cookie_y
);
1564 } else if(pair
->value
[0]=='T') {
1566 yd
->cookie_t
= getcookie(pair
->value
);
1568 } else if(pair
->value
[0]=='C') {
1570 yd
->cookie_c
= getcookie(pair
->value
);
1573 if(yd
->cookie_y
&& yd
->cookie_t
&& yd
->cookie_c
)
1574 YAHOO_CALLBACK(ext_yahoo_got_cookies
)(yd
->client_id
);
1580 case 101: /* NULL */
1581 case 102: /* NULL */
1582 case 93: /* 86400/1440 */
1588 static void yahoo_process_verify(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1590 struct yahoo_data
*yd
= yid
->yd
;
1592 if(pkt
->status
!= 0x01) {
1593 DEBUG_MSG(("expected status: 0x01, got: %d", pkt
->status
));
1594 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_LOCK
, "");
1598 pkt
= yahoo_packet_new(YAHOO_SERVICE_AUTH
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
1600 yahoo_packet_hash(pkt
, 1, yd
->user
);
1601 yahoo_send_packet(yid
, pkt
, 0);
1603 yahoo_packet_free(pkt
);
1607 static void yahoo_process_picture_checksum( struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1609 struct yahoo_data
*yd
= yid
->yd
;
1615 for(l
= pkt
->hash
; l
; l
= l
->next
)
1617 struct yahoo_pair
*pair
= l
->data
;
1630 checksum
= atoi( pair
->value
);
1635 //YAHOO_CALLBACK(ext_yahoo_got_buddyicon_checksum)(yd->client_id,to,from,checksum);
1638 static void yahoo_process_picture(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1640 struct yahoo_data
*yd
= yid
->yd
;
1648 for(l
= pkt
->hash
; l
; l
= l
->next
)
1650 struct yahoo_pair
*pair
= l
->data
;
1655 case 4: /* sender */
1661 case 13: /* request / sending */
1662 status
= atoi( pair
->value
);
1667 case 192: /*checksum */
1668 checksum
= atoi( pair
->value
);
1675 case 1: /* this is a request, ignore for now */
1676 YAHOO_CALLBACK(ext_yahoo_got_buddyicon_request
)(yd
->client_id
, to
, from
);
1678 case 2: /* this is cool - we get a picture :) */
1679 YAHOO_CALLBACK(ext_yahoo_got_buddyicon
)(yd
->client_id
,to
, from
, url
, checksum
);
1684 static void yahoo_process_picture_upload(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
1686 struct yahoo_data
*yd
= yid
->yd
;
1690 if ( pkt
->status
!= 1 )
1691 return; /* something went wrong */
1693 for(l
= pkt
->hash
; l
; l
= l
->next
)
1695 struct yahoo_pair
*pair
= l
->data
;
1704 case 27: /* local filename */
1711 YAHOO_CALLBACK(ext_yahoo_buddyicon_uploaded
)(yd
->client_id
, url
);
1714 static void yahoo_process_auth_pre_0x0b(struct yahoo_input_data
*yid
,
1715 const char *seed
, const char *sn
)
1717 struct yahoo_data
*yd
= yid
->yd
;
1719 /* So, Yahoo has stopped supporting its older clients in India, and
1720 * undoubtedly will soon do so in the rest of the world.
1722 * The new clients use this authentication method. I warn you in
1723 * advance, it's bizzare, convoluted, inordinately complicated.
1724 * It's also no more secure than crypt() was. The only purpose this
1725 * scheme could serve is to prevent third part clients from connecting
1731 struct yahoo_packet
*pack
;
1733 md5_byte_t result
[16];
1736 unsigned char *password_hash
= malloc(25);
1737 unsigned char *crypt_hash
= malloc(25);
1738 unsigned char *hash_string_p
= malloc(50 + strlen(sn
));
1739 unsigned char *hash_string_c
= malloc(50 + strlen(sn
));
1745 unsigned char *result6
= malloc(25);
1746 unsigned char *result96
= malloc(25);
1752 md5_append(&ctx
, (md5_byte_t
*)yd
->password
, strlen(yd
->password
));
1753 md5_finish(&ctx
, result
);
1754 to_y64(password_hash
, result
, 16);
1757 crypt_result
= yahoo_crypt(yd
->password
, "$1$_2S43d5f$");
1758 md5_append(&ctx
, (md5_byte_t
*)crypt_result
, strlen(crypt_result
));
1759 md5_finish(&ctx
, result
);
1760 to_y64(crypt_hash
, result
, 16);
1765 checksum
= seed
[seed
[7] % 16];
1766 snprintf((char *)hash_string_p
, strlen(sn
) + 50,
1767 "%c%s%s%s", checksum
, password_hash
, yd
->user
, seed
);
1768 snprintf((char *)hash_string_c
, strlen(sn
) + 50,
1769 "%c%s%s%s", checksum
, crypt_hash
, yd
->user
, seed
);
1772 checksum
= seed
[seed
[9] % 16];
1773 snprintf((char *)hash_string_p
, strlen(sn
) + 50,
1774 "%c%s%s%s", checksum
, yd
->user
, seed
, password_hash
);
1775 snprintf((char *)hash_string_c
, strlen(sn
) + 50,
1776 "%c%s%s%s", checksum
, yd
->user
, seed
, crypt_hash
);
1779 checksum
= seed
[seed
[15] % 16];
1780 snprintf((char *)hash_string_p
, strlen(sn
) + 50,
1781 "%c%s%s%s", checksum
, seed
, password_hash
, yd
->user
);
1782 snprintf((char *)hash_string_c
, strlen(sn
) + 50,
1783 "%c%s%s%s", checksum
, seed
, crypt_hash
, yd
->user
);
1786 checksum
= seed
[seed
[1] % 16];
1787 snprintf((char *)hash_string_p
, strlen(sn
) + 50,
1788 "%c%s%s%s", checksum
, yd
->user
, password_hash
, seed
);
1789 snprintf((char *)hash_string_c
, strlen(sn
) + 50,
1790 "%c%s%s%s", checksum
, yd
->user
, crypt_hash
, seed
);
1793 checksum
= seed
[seed
[3] % 16];
1794 snprintf((char *)hash_string_p
, strlen(sn
) + 50,
1795 "%c%s%s%s", checksum
, password_hash
, seed
, yd
->user
);
1796 snprintf((char *)hash_string_c
, strlen(sn
) + 50,
1797 "%c%s%s%s", checksum
, crypt_hash
, seed
, yd
->user
);
1802 md5_append(&ctx
, (md5_byte_t
*)hash_string_p
, strlen((char *)hash_string_p
));
1803 md5_finish(&ctx
, result
);
1804 to_y64(result6
, result
, 16);
1807 md5_append(&ctx
, (md5_byte_t
*)hash_string_c
, strlen((char *)hash_string_c
));
1808 md5_finish(&ctx
, result
);
1809 to_y64(result96
, result
, 16);
1811 pack
= yahoo_packet_new(YAHOO_SERVICE_AUTHRESP
, yd
->initial_status
, yd
->session_id
);
1812 yahoo_packet_hash(pack
, 0, yd
->user
);
1813 yahoo_packet_hash(pack
, 6, (char *)result6
);
1814 yahoo_packet_hash(pack
, 96, (char *)result96
);
1815 yahoo_packet_hash(pack
, 1, yd
->user
);
1817 yahoo_send_packet(yid
, pack
, 0);
1821 FREE(password_hash
);
1823 FREE(hash_string_p
);
1824 FREE(hash_string_c
);
1826 yahoo_packet_free(pack
);
1831 * New auth protocol cracked by Cerulean Studios and sent in to Gaim
1833 static void yahoo_process_auth_0x0b(struct yahoo_input_data
*yid
, const char *seed
, const char *sn
)
1835 struct yahoo_packet
*pack
= NULL
;
1836 struct yahoo_data
*yd
= yid
->yd
;
1838 md5_byte_t result
[16];
1844 char *alphabet1
= "FBZDWAGHrJTLMNOPpRSKUVEXYChImkwQ";
1845 char *alphabet2
= "F0E1D2C3B4A59687abcdefghijklmnop";
1847 char *challenge_lookup
= "qzec2tb3um1olpar8whx4dfgijknsvy5";
1848 char *operand_lookup
= "+|&%/*^-";
1849 char *delimit_lookup
= ",;";
1851 unsigned char *password_hash
= malloc(25);
1852 unsigned char *crypt_hash
= malloc(25);
1853 char *crypt_result
= NULL
;
1855 unsigned char pass_hash_xor1
[64];
1856 unsigned char pass_hash_xor2
[64];
1857 unsigned char crypt_hash_xor1
[64];
1858 unsigned char crypt_hash_xor2
[64];
1862 unsigned char digest1
[20];
1863 unsigned char digest2
[20];
1864 unsigned char comparison_src
[20];
1865 unsigned char magic_key_char
[4];
1866 const char *magic_ptr
;
1868 unsigned int magic
[64];
1869 unsigned int magic_work
=0;
1870 unsigned int magic_4
= 0;
1878 memset(password_hash
, 0, 25);
1879 memset(crypt_hash
, 0, 25);
1880 memset(&pass_hash_xor1
, 0, 64);
1881 memset(&pass_hash_xor2
, 0, 64);
1882 memset(&crypt_hash_xor1
, 0, 64);
1883 memset(&crypt_hash_xor2
, 0, 64);
1884 memset(&digest1
, 0, 20);
1885 memset(&digest2
, 0, 20);
1886 memset(&magic
, 0, 64);
1887 memset(&resp_6
, 0, 100);
1888 memset(&resp_96
, 0, 100);
1889 memset(&magic_key_char
, 0, 4);
1890 memset(&comparison_src
, 0, 20);
1893 * Magic: Phase 1. Generate what seems to be a 30
1894 * byte value (could change if base64
1895 * ends up differently? I don't remember and I'm
1896 * tired, so use a 64 byte buffer.
1901 while (*magic_ptr
!= (int)NULL
) {
1904 /* Ignore parentheses. */
1906 if (*magic_ptr
== '(' || *magic_ptr
== ')') {
1911 /* Characters and digits verify against
1912 the challenge lookup.
1915 if (isalpha(*magic_ptr
) || isdigit(*magic_ptr
)) {
1916 loc
= strchr(challenge_lookup
, *magic_ptr
);
1918 /* This isn't good */
1922 /* Get offset into lookup table and lsh 3. */
1924 magic_work
= loc
- challenge_lookup
;
1930 unsigned int local_store
;
1932 loc
= strchr(operand_lookup
, *magic_ptr
);
1934 /* Also not good. */
1938 local_store
= loc
- operand_lookup
;
1940 /* Oops; how did this happen? */
1941 if (magic_cnt
>= 64)
1944 magic
[magic_cnt
++] = magic_work
| local_store
;
1950 magic_len
= magic_cnt
;
1953 /* Magic: Phase 2. Take generated magic value and
1954 * sprinkle fairy dust on the values. */
1956 for (magic_cnt
= magic_len
-2; magic_cnt
>= 0; magic_cnt
--) {
1957 unsigned char byte1
;
1958 unsigned char byte2
;
1961 if ((magic_cnt
>= magic_len
)) {
1962 WARNING(("magic_cnt(%d) magic_len(%d)", magic_cnt
, magic_len
))
1966 byte1
= magic
[magic_cnt
];
1967 byte2
= magic
[magic_cnt
+1];
1972 magic
[magic_cnt
+1] = byte1
;
1976 * Magic: Phase 3. This computes 20 bytes. The first 4 bytes are used as our magic
1977 * key (and may be changed later); the next 16 bytes are an MD5 sum of the magic key
1978 * plus 3 bytes. The 3 bytes are found by looping, and they represent the offsets
1979 * into particular functions we'll later call to potentially alter the magic key.
1988 unsigned int bl
= 0;
1989 unsigned int cl
= magic
[magic_cnt
++];
1991 if (magic_cnt
>= magic_len
)
1996 bl
= cl
= (cl
& 0x1f) << 6;
1998 bl
= magic
[magic_cnt
++];
1999 cl
= (cl
& 0x0f) << 6;
2000 bl
= ((bl
& 0x3f) + cl
) << 6;
2003 cl
= magic
[magic_cnt
++];
2004 bl
= (cl
& 0x3f) + bl
;
2008 comparison_src
[x
++] = (bl
& 0xff00) >> 8;
2009 comparison_src
[x
++] = bl
& 0xff;
2012 /* First four bytes are magic key. */
2013 memcpy(&magic_key_char
[0], comparison_src
, 4);
2014 magic_4
= magic_key_char
[0] | (magic_key_char
[1] << 8) |
2015 (magic_key_char
[2] << 16) | (magic_key_char
[3] << 24);
2018 * Magic: Phase 4. Determine what function to use later by getting outside/inside
2019 * loop values until we match our previous buffer.
2021 for (x
= 0; x
< 65535; x
++) {
2024 for (y
= 0; y
< 5; y
++) {
2025 unsigned char test
[3];
2027 /* Calculate buffer. */
2033 md5_append( &ctx
, magic_key_char
, 4 );
2034 md5_append( &ctx
, test
, 3 );
2035 md5_finish( &ctx
, result
);
2038 if( memcmp( comparison_src
+ 4, result
, 16 ) == 0 ) {
2048 /* If y != 0, we need some help. */
2050 unsigned int updated_key
;
2052 /* Update magic stuff.
2053 * Call it twice because Yahoo's encryption is super bad ass.
2055 updated_key
= yahoo_auth_finalCountdown(magic_4
, 0x60, y
, x
);
2056 updated_key
= yahoo_auth_finalCountdown(updated_key
, 0x60, y
, x
);
2058 magic_key_char
[0] = updated_key
& 0xff;
2059 magic_key_char
[1] = (updated_key
>> 8) & 0xff;
2060 magic_key_char
[2] = (updated_key
>> 16) & 0xff;
2061 magic_key_char
[3] = (updated_key
>> 24) & 0xff;
2064 /* Get password and crypt hashes as per usual. */
2066 md5_append(&ctx
, (md5_byte_t
*)yd
->password
, strlen(yd
->password
));
2067 md5_finish(&ctx
, result
);
2069 to_y64(password_hash
, result
, 16);
2071 crypt_result
= yahoo_crypt(yd
->password
, "$1$_2S43d5f$");
2074 md5_append(&ctx
, (md5_byte_t
*)crypt_result
, strlen(crypt_result
));
2075 md5_finish(&ctx
, result
);
2076 to_y64(crypt_hash
, result
, 16);
2079 /* Our first authentication response is based off
2080 * of the password hash. */
2082 for (x
= 0; x
< (int)strlen((char *)password_hash
); x
++)
2083 pass_hash_xor1
[cnt
++] = password_hash
[x
] ^ 0x36;
2086 memset(&(pass_hash_xor1
[cnt
]), 0x36, 64-cnt
);
2090 for (x
= 0; x
< (int)strlen((char *)password_hash
); x
++)
2091 pass_hash_xor2
[cnt
++] = password_hash
[x
] ^ 0x5c;
2094 memset(&(pass_hash_xor2
[cnt
]), 0x5c, 64-cnt
);
2099 /* The first context gets the password hash XORed
2100 * with 0x36 plus a magic value
2101 * which we previously extrapolated from our
2104 SHA1Update(&ctx1
, pass_hash_xor1
, 64);
2106 ctx1
.totalLength
= 0x1ff;
2107 SHA1Update(&ctx1
, magic_key_char
, 4);
2108 SHA1Final(&ctx1
, digest1
);
2110 /* The second context gets the password hash XORed
2111 * with 0x5c plus the SHA-1 digest
2112 * of the first context. */
2114 SHA1Update(&ctx2
, pass_hash_xor2
, 64);
2115 SHA1Update(&ctx2
, digest1
, 20);
2116 SHA1Final(&ctx2
, digest2
);
2118 /* Now that we have digest2, use it to fetch
2119 * characters from an alphabet to construct
2120 * our first authentication response. */
2122 for (x
= 0; x
< 20; x
+= 2) {
2123 unsigned int val
= 0;
2124 unsigned int lookup
= 0;
2128 memset(&byte
, 0, 6);
2130 /* First two bytes of digest stuffed
2136 val
+= digest2
[x
+1];
2138 lookup
= (val
>> 0x0b);
2140 if (lookup
>= strlen(alphabet1
))
2142 sprintf(byte
, "%c", alphabet1
[lookup
]);
2143 strcat(resp_6
, byte
);
2144 strcat(resp_6
, "=");
2146 lookup
= (val
>> 0x06);
2148 if (lookup
>= strlen(alphabet2
))
2150 sprintf(byte
, "%c", alphabet2
[lookup
]);
2151 strcat(resp_6
, byte
);
2153 lookup
= (val
>> 0x01);
2155 if (lookup
>= strlen(alphabet2
))
2157 sprintf(byte
, "%c", alphabet2
[lookup
]);
2158 strcat(resp_6
, byte
);
2160 lookup
= (val
& 0x01);
2161 if (lookup
>= strlen(delimit_lookup
))
2163 sprintf(byte
, "%c", delimit_lookup
[lookup
]);
2164 strcat(resp_6
, byte
);
2167 /* Our second authentication response is based off
2168 * of the crypto hash. */
2171 memset(&digest1
, 0, 20);
2172 memset(&digest2
, 0, 20);
2174 for (x
= 0; x
< (int)strlen((char *)crypt_hash
); x
++)
2175 crypt_hash_xor1
[cnt
++] = crypt_hash
[x
] ^ 0x36;
2178 memset(&(crypt_hash_xor1
[cnt
]), 0x36, 64-cnt
);
2182 for (x
= 0; x
< (int)strlen((char *)crypt_hash
); x
++)
2183 crypt_hash_xor2
[cnt
++] = crypt_hash
[x
] ^ 0x5c;
2186 memset(&(crypt_hash_xor2
[cnt
]), 0x5c, 64-cnt
);
2191 /* The first context gets the password hash XORed
2192 * with 0x36 plus a magic value
2193 * which we previously extrapolated from our
2196 SHA1Update(&ctx1
, crypt_hash_xor1
, 64);
2198 ctx1
.totalLength
= 0x1ff;
2199 SHA1Update(&ctx1
, magic_key_char
, 4);
2200 SHA1Final(&ctx1
, digest1
);
2202 /* The second context gets the password hash XORed
2203 * with 0x5c plus the SHA-1 digest
2204 * of the first context. */
2206 SHA1Update(&ctx2
, crypt_hash_xor2
, 64);
2207 SHA1Update(&ctx2
, digest1
, 20);
2208 SHA1Final(&ctx2
, digest2
);
2210 /* Now that we have digest2, use it to fetch
2211 * characters from an alphabet to construct
2212 * our first authentication response. */
2214 for (x
= 0; x
< 20; x
+= 2) {
2215 unsigned int val
= 0;
2216 unsigned int lookup
= 0;
2220 memset(&byte
, 0, 6);
2222 /* First two bytes of digest stuffed
2227 val
+= digest2
[x
+1];
2229 lookup
= (val
>> 0x0b);
2231 if (lookup
>= strlen(alphabet1
))
2233 sprintf(byte
, "%c", alphabet1
[lookup
]);
2234 strcat(resp_96
, byte
);
2235 strcat(resp_96
, "=");
2237 lookup
= (val
>> 0x06);
2239 if (lookup
>= strlen(alphabet2
))
2241 sprintf(byte
, "%c", alphabet2
[lookup
]);
2242 strcat(resp_96
, byte
);
2244 lookup
= (val
>> 0x01);
2246 if (lookup
>= strlen(alphabet2
))
2248 sprintf(byte
, "%c", alphabet2
[lookup
]);
2249 strcat(resp_96
, byte
);
2251 lookup
= (val
& 0x01);
2252 if (lookup
>= strlen(delimit_lookup
))
2254 sprintf(byte
, "%c", delimit_lookup
[lookup
]);
2255 strcat(resp_96
, byte
);
2258 pack
= yahoo_packet_new(YAHOO_SERVICE_AUTHRESP
, yd
->initial_status
, yd
->session_id
);
2259 yahoo_packet_hash(pack
, 0, sn
);
2260 yahoo_packet_hash(pack
, 6, resp_6
);
2261 yahoo_packet_hash(pack
, 96, resp_96
);
2262 yahoo_packet_hash(pack
, 1, sn
);
2263 yahoo_packet_hash(pack
, 244, YAHOO_CLIENT_VERSION_ID
);
2264 yahoo_packet_hash(pack
, 135, YAHOO_CLIENT_VERSION
);
2266 yahoo_send_packet(yid
, pack
, 0);
2267 yahoo_packet_free(pack
);
2269 free(password_hash
);
2273 static void yahoo_process_auth(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2277 YList
*l
= pkt
->hash
;
2281 struct yahoo_pair
*pair
= l
->data
;
2282 if (pair
->key
== 94)
2286 if (pair
->key
== 13)
2287 m
= atoi(pair
->value
);
2296 yahoo_process_auth_pre_0x0b(yid
, seed
, sn
);
2300 yahoo_process_auth_0x0b(yid
, seed
, sn
);
2304 WARNING(("unknown auth type %d", m
));
2305 yahoo_process_auth_0x0b(yid
, seed
, sn
);
2310 static void yahoo_process_auth_resp(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2312 struct yahoo_data
*yd
= yid
->yd
;
2320 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2321 struct yahoo_pair
*pair
= l
->data
;
2323 login_id
= pair
->value
;
2324 else if (pair
->key
== 1)
2325 handle
= pair
->value
;
2326 else if (pair
->key
== 20)
2328 else if (pair
->key
== 66)
2329 login_status
= atoi(pair
->value
);
2332 if(pkt
->status
== 0xffffffff) {
2333 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, login_status
, url
);
2334 /* yahoo_logoff(yd->client_id);*/
2338 static void yahoo_process_mail(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2340 struct yahoo_data
*yd
= yid
->yd
;
2347 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2348 struct yahoo_pair
*pair
= l
->data
;
2350 count
= strtol(pair
->value
, NULL
, 10);
2351 else if (pair
->key
== 43)
2353 else if (pair
->key
== 42)
2354 email
= pair
->value
;
2355 else if (pair
->key
== 18)
2358 LOG(("key: %d => value: %s", pair
->key
, pair
->value
));
2361 if (who
&& email
&& subj
) {
2363 snprintf(from
, sizeof(from
), "%s (%s)", who
, email
);
2364 YAHOO_CALLBACK(ext_yahoo_mail_notify
)(yd
->client_id
, from
, subj
, count
);
2365 } else if(count
> 0)
2366 YAHOO_CALLBACK(ext_yahoo_mail_notify
)(yd
->client_id
, NULL
, NULL
, count
);
2369 static void yahoo_process_contact(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2371 struct yahoo_data
*yd
= yid
->yd
;
2377 int state
= YAHOO_STATUS_AVAILABLE
;
2385 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2386 struct yahoo_pair
*pair
= l
->data
;
2389 else if (pair
->key
== 3)
2391 else if (pair
->key
== 14)
2393 else if (pair
->key
== 7)
2395 else if (pair
->key
== 10)
2396 state
= strtol(pair
->value
, NULL
, 10);
2397 else if (pair
->key
== 15)
2398 tm
= strtol(pair
->value
, NULL
, 10);
2399 else if (pair
->key
== 13)
2400 online
= strtol(pair
->value
, NULL
, 10);
2401 else if (pair
->key
== 47)
2402 away
= strtol(pair
->value
, NULL
, 10);
2403 else if (pair
->key
== 137)
2404 idle
= strtol(pair
->value
, NULL
, 10);
2405 else if (pair
->key
== 60)
2406 mobile
= strtol(pair
->value
, NULL
, 10);
2411 YAHOO_CALLBACK(ext_yahoo_contact_added
)(yd
->client_id
, id
, who
, msg
);
2413 YAHOO_CALLBACK(ext_yahoo_status_changed
)(yd
->client_id
, name
, state
, msg
, away
, idle
, mobile
);
2414 else if(pkt
->status
== 0x07)
2415 YAHOO_CALLBACK(ext_yahoo_rejected
)(yd
->client_id
, who
, msg
);
2418 static void yahoo_process_buddyadd(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2420 struct yahoo_data
*yd
= yid
->yd
;
2426 struct yahoo_buddy
*bud
=NULL
;
2429 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2430 struct yahoo_pair
*pair
= l
->data
;
2435 if (pair
->key
== 65)
2436 where
= pair
->value
;
2437 if (pair
->key
== 66)
2438 status
= strtol(pair
->value
, NULL
, 10);
2441 yahoo_dump_unhandled(pkt
);
2448 bud
= y_new0(struct yahoo_buddy
, 1);
2449 bud
->id
= strdup(who
);
2450 bud
->group
= strdup(where
);
2451 bud
->real_name
= NULL
;
2453 yd
->buddies
= y_list_append(yd
->buddies
, bud
);
2455 /* YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, who, status, NULL, (status==YAHOO_STATUS_AVAILABLE?0:1)); */
2458 static void yahoo_process_buddydel(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2460 struct yahoo_data
*yd
= yid
->yd
;
2465 struct yahoo_buddy
*bud
;
2470 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2471 struct yahoo_pair
*pair
= l
->data
;
2474 else if (pair
->key
== 7)
2476 else if (pair
->key
== 65)
2477 where
= pair
->value
;
2478 else if (pair
->key
== 66)
2479 unk_66
= strtol(pair
->value
, NULL
, 10);
2481 DEBUG_MSG(("unknown key: %d = %s", pair
->key
, pair
->value
));
2487 bud
= y_new0(struct yahoo_buddy
, 1);
2488 bud
->id
= strdup(who
);
2489 bud
->group
= strdup(where
);
2491 buddy
= y_list_find_custom(yd
->buddies
, bud
, is_same_bud
);
2499 yd
->buddies
= y_list_remove_link(yd
->buddies
, buddy
);
2500 y_list_free_1(buddy
);
2504 FREE(bud
->real_name
);
2511 static void yahoo_process_ignore(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2519 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2520 struct yahoo_pair
*pair
= l
->data
;
2525 if (pair
->key
== 13) /* 1 == ignore, 2 == unignore */
2526 un_ignore
= strtol(pair
->value
, NULL
, 10);
2527 if (pair
->key
== 66)
2528 status
= strtol(pair
->value
, NULL
, 10);
2535 * 2 - already in ignore list, could not add
2536 * 3 - not in ignore list, could not delete
2537 * 12 - is a buddy, could not add
2541 YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, who, 0, status);
2545 static void yahoo_process_voicechat(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2550 char *voice_room
= NULL
;
2553 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2554 struct yahoo_pair
*pair
= l
->data
;
2559 if (pair
->key
== 13)
2560 voice_room
=pair
->value
;
2561 if (pair
->key
== 57)
2565 NOTICE(("got voice chat invite from %s in %s to identity %s", who
, room
, me
));
2567 * send: s:0 1:me 5:who 57:room 13:1
2568 * ???? s:4 5:who 10:99 19:-1615114531
2569 * gotr: s:4 5:who 10:99 19:-1615114615
2570 * ???? s:1 5:me 4:who 57:room 13:3room
2571 * got: s:1 5:me 4:who 57:room 13:1room
2572 * rej: s:0 1:me 5:who 57:room 13:3
2573 * rejr: s:4 5:who 10:99 19:-1617114599
2577 static void yahoo_process_ping(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2579 char *errormsg
= NULL
;
2582 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2583 struct yahoo_pair
*pair
= l
->data
;
2584 if (pair
->key
== 16)
2585 errormsg
= pair
->value
;
2588 NOTICE(("got ping packet"));
2589 //YAHOO_CALLBACK(ext_yahoo_got_ping)(yid->yd->client_id, errormsg);
2592 static void _yahoo_webcam_get_server_connected(int fd
, int error
, void *d
)
2594 struct yahoo_input_data
*yid
= d
;
2595 char *who
= yid
->wcm
->user
;
2597 char *packet
= NULL
;
2598 unsigned char magic_nr
[] = {0, 1, 0};
2599 unsigned char header_len
= 8;
2600 unsigned int len
= 0;
2601 unsigned int pos
= 0;
2603 if(error
|| fd
<= 0) {
2610 inputs
= y_list_prepend(inputs
, yid
);
2612 /* send initial packet */
2614 data
= strdup("<RVWCFG>");
2616 data
= strdup("<RUPCFG>");
2617 yahoo_add_to_send_queue(yid
, data
, strlen(data
));
2623 data
= strdup("g=");
2624 data
= y_string_append(data
, who
);
2625 data
= y_string_append(data
, "\r\n");
2627 data
= strdup("f=1\r\n");
2630 packet
= y_new0(char, header_len
+ len
);
2631 packet
[pos
++] = header_len
;
2632 memcpy(packet
+ pos
, magic_nr
, sizeof(magic_nr
));
2633 pos
+= sizeof(magic_nr
);
2634 pos
+= yahoo_put32(packet
+ pos
, len
);
2635 memcpy(packet
+ pos
, data
, len
);
2637 yahoo_add_to_send_queue(yid
, packet
, pos
);
2641 yid
->read_tag
=YAHOO_CALLBACK(ext_yahoo_add_handler
)(yid
->yd
->client_id
, fd
, YAHOO_INPUT_READ
, yid
);
2644 static void yahoo_webcam_get_server(struct yahoo_input_data
*y
, char *who
, char *key
)
2646 struct yahoo_input_data
*yid
= y_new0(struct yahoo_input_data
, 1);
2647 struct yahoo_server_settings
*yss
= y
->yd
->server_settings
;
2649 yid
->type
= YAHOO_CONNECTION_WEBCAM_MASTER
;
2651 yid
->wcm
= y_new0(struct yahoo_webcam
, 1);
2652 yid
->wcm
->user
= who
?strdup(who
):NULL
;
2653 yid
->wcm
->direction
= who
?YAHOO_WEBCAM_DOWNLOAD
:YAHOO_WEBCAM_UPLOAD
;
2654 yid
->wcm
->key
= strdup(key
);
2656 YAHOO_CALLBACK(ext_yahoo_connect_async
)(yid
->yd
->client_id
, yss
->webcam_host
, yss
->webcam_port
,
2657 _yahoo_webcam_get_server_connected
, yid
);
2661 static YList
*webcam_queue
=NULL
;
2662 static void yahoo_process_webcam_key(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2669 yahoo_dump_unhandled(pkt
);
2670 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2671 struct yahoo_pair
*pair
= l
->data
;
2674 if (pair
->key
== 61)
2682 webcam_queue
= y_list_remove_link(webcam_queue
, webcam_queue
);
2684 yahoo_webcam_get_server(yid
, who
, key
);
2688 static void yahoo_packet_process(struct yahoo_input_data
*yid
, struct yahoo_packet
*pkt
)
2690 DEBUG_MSG(("yahoo_packet_process: 0x%02x", pkt
->service
));
2691 switch (pkt
->service
)
2693 case YAHOO_SERVICE_USERSTAT
:
2694 case YAHOO_SERVICE_LOGON
:
2695 case YAHOO_SERVICE_LOGOFF
:
2696 case YAHOO_SERVICE_ISAWAY
:
2697 case YAHOO_SERVICE_ISBACK
:
2698 case YAHOO_SERVICE_GAMELOGON
:
2699 case YAHOO_SERVICE_GAMELOGOFF
:
2700 case YAHOO_SERVICE_IDACT
:
2701 case YAHOO_SERVICE_IDDEACT
:
2702 case YAHOO_SERVICE_STATUS_15
:
2703 yahoo_process_status(yid
, pkt
);
2705 case YAHOO_SERVICE_NOTIFY
:
2706 yahoo_process_notify(yid
, pkt
);
2708 case YAHOO_SERVICE_MESSAGE
:
2709 case YAHOO_SERVICE_GAMEMSG
:
2710 case YAHOO_SERVICE_SYSMESSAGE
:
2711 yahoo_process_message(yid
, pkt
);
2713 case YAHOO_SERVICE_NEWMAIL
:
2714 yahoo_process_mail(yid
, pkt
);
2716 case YAHOO_SERVICE_NEWCONTACT
:
2717 yahoo_process_contact(yid
, pkt
);
2719 case YAHOO_SERVICE_LIST
:
2720 yahoo_process_list(yid
, pkt
);
2722 case YAHOO_SERVICE_VERIFY
:
2723 yahoo_process_verify(yid
, pkt
);
2725 case YAHOO_SERVICE_AUTH
:
2726 yahoo_process_auth(yid
, pkt
);
2728 case YAHOO_SERVICE_AUTHRESP
:
2729 yahoo_process_auth_resp(yid
, pkt
);
2731 case YAHOO_SERVICE_CONFINVITE
:
2732 case YAHOO_SERVICE_CONFADDINVITE
:
2733 case YAHOO_SERVICE_CONFDECLINE
:
2734 case YAHOO_SERVICE_CONFLOGON
:
2735 case YAHOO_SERVICE_CONFLOGOFF
:
2736 case YAHOO_SERVICE_CONFMSG
:
2737 yahoo_process_conference(yid
, pkt
);
2739 case YAHOO_SERVICE_CHATONLINE
:
2740 case YAHOO_SERVICE_CHATGOTO
:
2741 case YAHOO_SERVICE_CHATJOIN
:
2742 case YAHOO_SERVICE_CHATLEAVE
:
2743 case YAHOO_SERVICE_CHATEXIT
:
2744 case YAHOO_SERVICE_CHATLOGOUT
:
2745 case YAHOO_SERVICE_CHATPING
:
2746 case YAHOO_SERVICE_COMMENT
:
2747 yahoo_process_chat(yid
, pkt
);
2749 case YAHOO_SERVICE_P2PFILEXFER
:
2750 case YAHOO_SERVICE_FILETRANSFER
:
2751 yahoo_process_filetransfer(yid
, pkt
);
2753 case YAHOO_SERVICE_ADDBUDDY
:
2754 yahoo_process_buddyadd(yid
, pkt
);
2756 case YAHOO_SERVICE_REMBUDDY
:
2757 yahoo_process_buddydel(yid
, pkt
);
2759 case YAHOO_SERVICE_IGNORECONTACT
:
2760 yahoo_process_ignore(yid
, pkt
);
2762 case YAHOO_SERVICE_VOICECHAT
:
2763 yahoo_process_voicechat(yid
, pkt
);
2765 case YAHOO_SERVICE_WEBCAM
:
2766 yahoo_process_webcam_key(yid
, pkt
);
2768 case YAHOO_SERVICE_PING
:
2769 yahoo_process_ping(yid
, pkt
);
2771 case YAHOO_SERVICE_IDLE
:
2772 case YAHOO_SERVICE_MAILSTAT
:
2773 case YAHOO_SERVICE_CHATINVITE
:
2774 case YAHOO_SERVICE_CALENDAR
:
2775 case YAHOO_SERVICE_NEWPERSONALMAIL
:
2776 case YAHOO_SERVICE_ADDIDENT
:
2777 case YAHOO_SERVICE_ADDIGNORE
:
2778 case YAHOO_SERVICE_GOTGROUPRENAME
:
2779 case YAHOO_SERVICE_GROUPRENAME
:
2780 case YAHOO_SERVICE_PASSTHROUGH2
:
2781 case YAHOO_SERVICE_CHATLOGON
:
2782 case YAHOO_SERVICE_CHATLOGOFF
:
2783 case YAHOO_SERVICE_CHATMSG
:
2784 case YAHOO_SERVICE_REJECTCONTACT
:
2785 case YAHOO_SERVICE_PEERTOPEER
:
2786 WARNING(("unhandled service 0x%02x", pkt
->service
));
2787 yahoo_dump_unhandled(pkt
);
2789 case YAHOO_SERVICE_PICTURE
:
2790 yahoo_process_picture(yid
, pkt
);
2792 case YAHOO_SERVICE_PICTURE_CHECKSUM
:
2793 yahoo_process_picture_checksum(yid
, pkt
);
2795 case YAHOO_SERVICE_PICTURE_UPLOAD
:
2796 yahoo_process_picture_upload(yid
, pkt
);
2799 WARNING(("unknown service 0x%02x", pkt
->service
));
2800 yahoo_dump_unhandled(pkt
);
2805 static struct yahoo_packet
* yahoo_getdata(struct yahoo_input_data
* yid
)
2807 struct yahoo_packet
*pkt
;
2808 struct yahoo_data
*yd
= yid
->yd
;
2815 DEBUG_MSG(("rxlen is %d", yid
->rxlen
));
2816 if (yid
->rxlen
< YAHOO_PACKET_HDRLEN
) {
2817 DEBUG_MSG(("len < YAHOO_PACKET_HDRLEN"));
2821 pos
+= 4; /* YMSG */
2825 pktlen
= yahoo_get16(yid
->rxqueue
+ pos
); pos
+= 2;
2826 DEBUG_MSG(("%d bytes to read, rxlen is %d",
2827 pktlen
, yid
->rxlen
));
2829 if (yid
->rxlen
< (YAHOO_PACKET_HDRLEN
+ pktlen
)) {
2830 DEBUG_MSG(("len < YAHOO_PACKET_HDRLEN + pktlen"));
2834 LOG(("reading packet"));
2835 yahoo_packet_dump(yid
->rxqueue
, YAHOO_PACKET_HDRLEN
+ pktlen
);
2837 pkt
= yahoo_packet_new(0, 0, 0);
2839 pkt
->service
= yahoo_get16(yid
->rxqueue
+ pos
); pos
+= 2;
2840 pkt
->status
= yahoo_get32(yid
->rxqueue
+ pos
); pos
+= 4;
2841 DEBUG_MSG(("Yahoo Service: 0x%02x Status: %d", pkt
->service
,
2843 pkt
->id
= yahoo_get32(yid
->rxqueue
+ pos
); pos
+= 4;
2845 yd
->session_id
= pkt
->id
;
2847 yahoo_packet_read(pkt
, yid
->rxqueue
+ pos
, pktlen
);
2849 yid
->rxlen
-= YAHOO_PACKET_HDRLEN
+ pktlen
;
2850 DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
2852 unsigned char *tmp
= y_memdup(yid
->rxqueue
+ YAHOO_PACKET_HDRLEN
2853 + pktlen
, yid
->rxlen
);
2856 DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
2858 DEBUG_MSG(("freed rxqueue == %p", yid
->rxqueue
));
2865 static void yahoo_yab_read(struct yab
*yab
, unsigned char *d
, int len
)
2868 char *data
= (char *)d
;
2871 DEBUG_MSG(("Got yab: %s", data
));
2872 st
= en
= strstr(data
, "userid=\"");
2874 st
+= strlen("userid=\"");
2875 en
= strchr(st
, '"'); *en
++ = '\0';
2876 yab
->id
= yahoo_xmldecode(st
);
2879 st
= strstr(en
, "fname=\"");
2881 st
+= strlen("fname=\"");
2882 en
= strchr(st
, '"'); *en
++ = '\0';
2883 yab
->fname
= yahoo_xmldecode(st
);
2886 st
= strstr(en
, "lname=\"");
2888 st
+= strlen("lname=\"");
2889 en
= strchr(st
, '"'); *en
++ = '\0';
2890 yab
->lname
= yahoo_xmldecode(st
);
2893 st
= strstr(en
, "nname=\"");
2895 st
+= strlen("nname=\"");
2896 en
= strchr(st
, '"'); *en
++ = '\0';
2897 yab
->nname
= yahoo_xmldecode(st
);
2900 st
= strstr(en
, "email=\"");
2902 st
+= strlen("email=\"");
2903 en
= strchr(st
, '"'); *en
++ = '\0';
2904 yab
->email
= yahoo_xmldecode(st
);
2907 st
= strstr(en
, "hphone=\"");
2909 st
+= strlen("hphone=\"");
2910 en
= strchr(st
, '"'); *en
++ = '\0';
2911 yab
->hphone
= yahoo_xmldecode(st
);
2914 st
= strstr(en
, "wphone=\"");
2916 st
+= strlen("wphone=\"");
2917 en
= strchr(st
, '"'); *en
++ = '\0';
2918 yab
->wphone
= yahoo_xmldecode(st
);
2921 st
= strstr(en
, "mphone=\"");
2923 st
+= strlen("mphone=\"");
2924 en
= strchr(st
, '"'); *en
++ = '\0';
2925 yab
->mphone
= yahoo_xmldecode(st
);
2928 st
= strstr(en
, "dbid=\"");
2930 st
+= strlen("dbid=\"");
2931 en
= strchr(st
, '"'); *en
++ = '\0';
2932 yab
->dbid
= atoi(st
);
2936 static struct yab
* yahoo_getyab(struct yahoo_input_data
*yid
)
2938 struct yab
*yab
= NULL
;
2940 struct yahoo_data
*yd
= yid
->yd
;
2945 DEBUG_MSG(("rxlen is %d", yid
->rxlen
));
2947 if(yid
->rxlen
<= strlen("<record"))
2950 /* start with <record */
2951 while(pos
< yid
->rxlen
-strlen("<record")+1
2952 && memcmp(yid
->rxqueue
+ pos
, "<record", strlen("<record")))
2955 if(pos
>= yid
->rxlen
-1)
2960 while(end
< yid
->rxlen
-strlen("/>")+1 && memcmp(yid
->rxqueue
+ end
, "/>", strlen("/>")))
2963 if(end
>= yid
->rxlen
-1)
2966 yab
= y_new0(struct yab
, 1);
2967 yahoo_yab_read(yab
, yid
->rxqueue
+ pos
, end
+2-pos
);
2970 yid
->rxlen
-= end
+1;
2971 DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
2973 unsigned char *tmp
= y_memdup(yid
->rxqueue
+ end
+ 1, yid
->rxlen
);
2976 DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
2978 DEBUG_MSG(("freed rxqueue == %p", yid
->rxqueue
));
2986 static char * yahoo_getwebcam_master(struct yahoo_input_data
*yid
)
2990 unsigned int status
=0;
2992 struct yahoo_data
*yd
= yid
->yd
;
2997 DEBUG_MSG(("rxlen is %d", yid
->rxlen
));
2999 len
= yid
->rxqueue
[pos
++];
3000 if (yid
->rxlen
< len
)
3003 /* extract status (0 = ok, 6 = webcam not online) */
3004 status
= yid
->rxqueue
[pos
++];
3008 pos
+= 2; /* skip next 2 bytes */
3009 server
= y_memdup(yid
->rxqueue
+pos
, 16);
3012 else if (status
== 6)
3014 YAHOO_CALLBACK(ext_yahoo_webcam_closed
)
3015 (yd
->client_id
, yid
->wcm
->user
, 4);
3018 /* skip rest of the data */
3021 DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
3023 unsigned char *tmp
= y_memdup(yid
->rxqueue
+ pos
, yid
->rxlen
);
3026 DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
3028 DEBUG_MSG(("freed rxqueue == %p", yid
->rxqueue
));
3035 static int yahoo_get_webcam_data(struct yahoo_input_data
*yid
)
3037 unsigned char reason
=0;
3039 unsigned int begin
=0;
3041 unsigned int closed
=0;
3042 unsigned char header_len
=0;
3045 struct yahoo_data
*yd
= yid
->yd
;
3050 if(!yid
->wcm
|| !yid
->wcd
|| !yid
->rxlen
)
3053 DEBUG_MSG(("rxlen is %d", yid
->rxlen
));
3055 /* if we are not reading part of image then read header */
3056 if (!yid
->wcd
->to_read
)
3058 header_len
=yid
->rxqueue
[pos
++];
3059 yid
->wcd
->packet_type
=0;
3061 if (yid
->rxlen
< header_len
)
3064 if (header_len
>= 8)
3066 reason
= yid
->rxqueue
[pos
++];
3067 /* next 2 bytes should always be 05 00 */
3069 yid
->wcd
->data_size
= yahoo_get32(yid
->rxqueue
+ pos
);
3071 yid
->wcd
->to_read
= yid
->wcd
->data_size
;
3073 if (header_len
>= 13)
3075 yid
->wcd
->packet_type
= yid
->rxqueue
[pos
++];
3076 yid
->wcd
->timestamp
= yahoo_get32(yid
->rxqueue
+ pos
);
3080 /* skip rest of header */
3085 pos
+= yid
->wcd
->to_read
;
3086 if (pos
> yid
->rxlen
) pos
= yid
->rxlen
;
3088 /* if it is not an image then make sure we have the whole packet */
3089 if (yid
->wcd
->packet_type
!= 0x02) {
3090 if ((pos
- begin
) != yid
->wcd
->data_size
) {
3091 yid
->wcd
->to_read
= 0;
3094 yahoo_packet_dump(yid
->rxqueue
+ begin
, pos
- begin
);
3098 DEBUG_MSG(("packet type %.2X, data length %d", yid
->wcd
->packet_type
,
3099 yid
->wcd
->data_size
));
3101 /* find out what kind of packet we got */
3102 switch (yid
->wcd
->packet_type
)
3105 /* user requests to view webcam (uploading) */
3106 if (yid
->wcd
->data_size
&&
3107 yid
->wcm
->direction
== YAHOO_WEBCAM_UPLOAD
) {
3109 while (end
<= yid
->rxlen
&&
3110 yid
->rxqueue
[end
++] != 13);
3113 who
= y_memdup(yid
->rxqueue
+ begin
, end
- begin
);
3114 who
[end
- begin
- 1] = 0;
3115 YAHOO_CALLBACK(ext_yahoo_webcam_viewer
)(yd
->client_id
, who
+ 2, 2);
3120 if (yid
->wcm
->direction
== YAHOO_WEBCAM_DOWNLOAD
) {
3121 /* timestamp/status field */
3122 /* 0 = declined viewing permission */
3123 /* 1 = accepted viewing permission */
3124 if (yid
->wcd
->timestamp
== 0) {
3125 YAHOO_CALLBACK(ext_yahoo_webcam_closed
)(yd
->client_id
, yid
->wcm
->user
, 3);
3129 case 0x01: /* status packets?? */
3130 /* timestamp contains status info */
3131 /* 00 00 00 01 = we have data?? */
3133 case 0x02: /* image data */
3134 YAHOO_CALLBACK(ext_yahoo_got_webcam_image
)(yd
->client_id
,
3135 yid
->wcm
->user
, yid
->rxqueue
+ begin
,
3136 yid
->wcd
->data_size
, pos
- begin
,
3137 yid
->wcd
->timestamp
);
3139 case 0x05: /* response packets when uploading */
3140 if (!yid
->wcd
->data_size
) {
3141 YAHOO_CALLBACK(ext_yahoo_webcam_data_request
)(yd
->client_id
, yid
->wcd
->timestamp
);
3144 case 0x07: /* connection is closing */
3147 case 0x01: /* user closed connection */
3150 case 0x0F: /* user cancelled permission */
3154 YAHOO_CALLBACK(ext_yahoo_webcam_closed
)(yd
->client_id
, yid
->wcm
->user
, closed
);
3156 case 0x0C: /* user connected */
3157 case 0x0D: /* user disconnected */
3158 if (yid
->wcd
->data_size
) {
3159 who
= y_memdup(yid
->rxqueue
+ begin
, pos
- begin
+ 1);
3160 who
[pos
- begin
] = 0;
3161 if (yid
->wcd
->packet_type
== 0x0C)
3165 YAHOO_CALLBACK(ext_yahoo_webcam_viewer
)(yd
->client_id
, who
, connect
);
3169 case 0x13: /* user data */
3170 /* i=user_ip (ip of the user we are viewing) */
3171 /* j=user_ext_ip (external ip of the user we */
3177 yid
->wcd
->to_read
-= pos
- begin
;
3180 DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
3182 unsigned char *tmp
= y_memdup(yid
->rxqueue
+ pos
, yid
->rxlen
);
3185 DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
3187 DEBUG_MSG(("freed rxqueue == %p", yid
->rxqueue
));
3191 /* If we read a complete packet return success */
3192 if (!yid
->wcd
->to_read
)
3198 int yahoo_write_ready(int id
, int fd
, void *data
)
3200 struct yahoo_input_data
*yid
= data
;
3202 struct data_queue
*tx
;
3204 LOG(("write callback: id=%d fd=%d data=%p", id
, fd
, data
));
3205 if(!yid
|| !yid
->txqueues
)
3208 tx
= yid
->txqueues
->data
;
3209 LOG(("writing %d bytes", tx
->len
));
3210 len
= yahoo_send_data(fd
, tx
->queue
, MIN(1024, tx
->len
));
3212 if(len
== -1 && errno
== EAGAIN
)
3217 DEBUG_MSG(("len == %d (<= 0)", len
));
3218 while(yid
->txqueues
) {
3219 YList
*l
=yid
->txqueues
;
3223 yid
->txqueues
= y_list_remove_link(yid
->txqueues
, yid
->txqueues
);
3226 LOG(("yahoo_write_ready(%d, %d) len < 0", id
, fd
));
3227 YAHOO_CALLBACK(ext_yahoo_remove_handler
)(id
, yid
->write_tag
);
3236 unsigned char *tmp
= y_memdup(tx
->queue
+ len
, tx
->len
);
3240 YList
*l
=yid
->txqueues
;
3243 yid
->txqueues
= y_list_remove_link(yid
->txqueues
, yid
->txqueues
);
3247 LOG(("yahoo_write_ready(%d, %d) !yxqueues", id, fd));
3249 if(!yid
->txqueues
) {
3250 LOG(("yahoo_write_ready(%d, %d) !yxqueues", id
, fd
));
3251 YAHOO_CALLBACK(ext_yahoo_remove_handler
)(id
, yid
->write_tag
);
3259 static void yahoo_process_pager_connection(struct yahoo_input_data
*yid
, int over
)
3261 struct yahoo_packet
*pkt
;
3262 struct yahoo_data
*yd
= yid
->yd
;
3263 int id
= yd
->client_id
;
3268 while (find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
)
3269 && (pkt
= yahoo_getdata(yid
)) != NULL
) {
3271 yahoo_packet_process(yid
, pkt
);
3273 yahoo_packet_free(pkt
);
3277 static void yahoo_process_ft_connection(struct yahoo_input_data
*yid
, int over
)
3281 static void yahoo_process_chatcat_connection(struct yahoo_input_data
*yid
, int over
)
3286 if (strstr((char*)yid
->rxqueue
+(yid
->rxlen
-20), "</content>")) {
3287 YAHOO_CALLBACK(ext_yahoo_chat_cat_xml
)(yid
->yd
->client_id
, (char*)yid
->rxqueue
);
3291 static void yahoo_process_yab_connection(struct yahoo_input_data
*yid
, int over
)
3293 struct yahoo_data
*yd
= yid
->yd
;
3297 int id
= yd
->client_id
;
3302 while(find_input_by_id_and_type(id
, YAHOO_CONNECTION_YAB
)
3303 && (yab
= yahoo_getyab(yid
)) != NULL
) {
3307 for(buds
= yd
->buddies
; buds
; buds
=buds
->next
) {
3308 struct yahoo_buddy
* bud
= buds
->data
;
3309 if(!strcmp(bud
->id
, yab
->id
)) {
3310 bud
->yab_entry
= yab
;
3312 bud
->real_name
= strdup(yab
->nname
);
3313 } else if(yab
->fname
&& yab
->lname
) {
3314 bud
->real_name
= y_new0(char,
3316 strlen(yab
->lname
)+2
3318 sprintf(bud
->real_name
, "%s %s",
3319 yab
->fname
, yab
->lname
);
3320 } else if(yab
->fname
) {
3321 bud
->real_name
= strdup(yab
->fname
);
3329 YAHOO_CALLBACK(ext_yahoo_got_buddies
)(yd
->client_id
, yd
->buddies
);
3332 static void yahoo_process_search_connection(struct yahoo_input_data
*yid
, int over
)
3334 struct yahoo_found_contact
*yct
=NULL
;
3335 char *p
= (char *)yid
->rxqueue
, *np
, *cp
;
3337 int start
=0, found
=0, total
=0;
3338 YList
*contacts
=NULL
;
3339 struct yahoo_input_data
*pyid
= find_input_by_id_and_type(yid
->yd
->client_id
, YAHOO_CONNECTION_PAGER
);
3344 if(p
&& (p
=strstr(p
, "\r\n\r\n"))) {
3347 for(k
= 0; (p
= strchr(p
, 4)) && (k
< 4); k
++) {
3351 case 0: found
= pyid
->ys
->lsearch_nfound
= n
; break;
3352 case 2: start
= pyid
->ys
->lsearch_nstart
= n
; break;
3353 case 3: total
= pyid
->ys
->lsearch_ntotal
= n
; break;
3372 if(strlen(cp
) > 2 && y_list_length(contacts
) < total
) {
3373 yct
= y_new0(struct yahoo_found_contact
, 1);
3374 contacts
= y_list_append(contacts
, yct
);
3381 yct
->online
= !strcmp(cp
, "2") ? 1 : 0;
3387 yct
->age
= atoi(cp
);
3390 if( strcmp(cp
,"\005") != 0)
3398 YAHOO_CALLBACK(ext_yahoo_got_search_result
)(yid
->yd
->client_id
, found
, start
, total
, contacts
);
3401 YList
*node
= contacts
;
3402 contacts
= y_list_remove_link(contacts
, node
);
3404 y_list_free_1(node
);
3408 static void _yahoo_webcam_connected(int fd
, int error
, void *d
)
3410 struct yahoo_input_data
*yid
= d
;
3411 struct yahoo_webcam
*wcm
= yid
->wcm
;
3412 struct yahoo_data
*yd
= yid
->yd
;
3413 char conn_type
[100];
3416 unsigned char magic_nr
[] = {1, 0, 0, 0, 1};
3417 unsigned header_len
=0;
3421 if(error
|| fd
<= 0) {
3427 inputs
= y_list_prepend(inputs
, yid
);
3430 /* send initial packet */
3431 switch (wcm
->direction
)
3433 case YAHOO_WEBCAM_DOWNLOAD
:
3434 data
= strdup("<REQIMG>");
3436 case YAHOO_WEBCAM_UPLOAD
:
3437 data
= strdup("<SNDIMG>");
3442 yahoo_add_to_send_queue(yid
, data
, strlen(data
));
3446 switch (wcm
->direction
)
3448 case YAHOO_WEBCAM_DOWNLOAD
:
3450 data
= strdup("a=2\r\nc=us\r\ne=21\r\nu=");
3451 data
= y_string_append(data
, yd
->user
);
3452 data
= y_string_append(data
, "\r\nt=");
3453 data
= y_string_append(data
, wcm
->key
);
3454 data
= y_string_append(data
, "\r\ni=");
3455 data
= y_string_append(data
, wcm
->my_ip
);
3456 data
= y_string_append(data
, "\r\ng=");
3457 data
= y_string_append(data
, wcm
->user
);
3458 data
= y_string_append(data
, "\r\no=w-2-5-1\r\np=");
3459 snprintf(conn_type
, sizeof(conn_type
), "%d", wcm
->conn_type
);
3460 data
= y_string_append(data
, conn_type
);
3461 data
= y_string_append(data
, "\r\n");
3463 case YAHOO_WEBCAM_UPLOAD
:
3465 data
= strdup("a=2\r\nc=us\r\nu=");
3466 data
= y_string_append(data
, yd
->user
);
3467 data
= y_string_append(data
, "\r\nt=");
3468 data
= y_string_append(data
, wcm
->key
);
3469 data
= y_string_append(data
, "\r\ni=");
3470 data
= y_string_append(data
, wcm
->my_ip
);
3471 data
= y_string_append(data
, "\r\no=w-2-5-1\r\np=");
3472 snprintf(conn_type
, sizeof(conn_type
), "%d", wcm
->conn_type
);
3473 data
= y_string_append(data
, conn_type
);
3474 data
= y_string_append(data
, "\r\nb=");
3475 data
= y_string_append(data
, wcm
->description
);
3476 data
= y_string_append(data
, "\r\n");
3481 packet
= y_new0(char, header_len
+ len
);
3482 packet
[pos
++] = header_len
;
3484 switch (wcm
->direction
)
3486 case YAHOO_WEBCAM_DOWNLOAD
:
3490 case YAHOO_WEBCAM_UPLOAD
:
3496 pos
+= yahoo_put32(packet
+ pos
, len
);
3497 if (wcm
->direction
== YAHOO_WEBCAM_UPLOAD
)
3499 memcpy(packet
+ pos
, magic_nr
, sizeof(magic_nr
));
3500 pos
+= sizeof(magic_nr
);
3502 memcpy(packet
+ pos
, data
, len
);
3503 yahoo_add_to_send_queue(yid
, packet
, header_len
+ len
);
3507 yid
->read_tag
=YAHOO_CALLBACK(ext_yahoo_add_handler
)(yid
->yd
->client_id
, yid
->fd
, YAHOO_INPUT_READ
, yid
);
3510 static void yahoo_webcam_connect(struct yahoo_input_data
*y
)
3512 struct yahoo_webcam
*wcm
= y
->wcm
;
3513 struct yahoo_input_data
*yid
;
3514 struct yahoo_server_settings
*yss
;
3516 if (!wcm
|| !wcm
->server
|| !wcm
->key
)
3519 yid
= y_new0(struct yahoo_input_data
, 1);
3520 yid
->type
= YAHOO_CONNECTION_WEBCAM
;
3523 /* copy webcam data to new connection */
3527 yss
= y
->yd
->server_settings
;
3529 yid
->wcd
= y_new0(struct yahoo_webcam_data
, 1);
3531 LOG(("Connecting to: %s:%d", wcm
->server
, wcm
->port
));
3532 YAHOO_CALLBACK(ext_yahoo_connect_async
)(y
->yd
->client_id
, wcm
->server
, wcm
->port
,
3533 _yahoo_webcam_connected
, yid
);
3537 static void yahoo_process_webcam_master_connection(struct yahoo_input_data
*yid
, int over
)
3540 struct yahoo_server_settings
*yss
;
3545 server
= yahoo_getwebcam_master(yid
);
3549 yss
= yid
->yd
->server_settings
;
3550 yid
->wcm
->server
= strdup(server
);
3551 yid
->wcm
->port
= yss
->webcam_port
;
3552 yid
->wcm
->conn_type
= yss
->conn_type
;
3553 yid
->wcm
->my_ip
= strdup(yss
->local_host
);
3554 if (yid
->wcm
->direction
== YAHOO_WEBCAM_UPLOAD
)
3555 yid
->wcm
->description
= strdup(yss
->webcam_description
);
3556 yahoo_webcam_connect(yid
);
3561 static void yahoo_process_webcam_connection(struct yahoo_input_data
*yid
, int over
)
3563 int id
= yid
->yd
->client_id
;
3569 /* as long as we still have packets available keep processing them */
3570 while (find_input_by_id_and_fd(id
, fd
)
3571 && yahoo_get_webcam_data(yid
) == 1);
3574 static void (*yahoo_process_connection
[])(struct yahoo_input_data
*, int over
) = {
3575 yahoo_process_pager_connection
,
3576 yahoo_process_ft_connection
,
3577 yahoo_process_yab_connection
,
3578 yahoo_process_webcam_master_connection
,
3579 yahoo_process_webcam_connection
,
3580 yahoo_process_chatcat_connection
,
3581 yahoo_process_search_connection
3584 int yahoo_read_ready(int id
, int fd
, void *data
)
3586 struct yahoo_input_data
*yid
= data
;
3590 LOG(("read callback: id=%d fd=%d data=%p", id
, fd
, data
));
3596 len
= read(fd
, buf
, sizeof(buf
));
3597 } while(len
== -1 && errno
== EINTR
);
3599 if(len
== -1 && errno
== EAGAIN
) /* we'll try again later */
3604 DEBUG_MSG(("len == %d (<= 0)", len
));
3606 if(yid
->type
== YAHOO_CONNECTION_PAGER
) {
3607 YAHOO_CALLBACK(ext_yahoo_error
)(yid
->yd
->client_id
, "Connection closed by server", 1, E_CONNECTION
);
3610 yahoo_process_connection
[yid
->type
](yid
, 1);
3611 yahoo_input_close(yid
);
3613 /* no need to return an error, because we've already fixed it */
3618 LOG(("read error: %s", strerror(errno
)));
3622 yid
->rxqueue
= y_renew(unsigned char, yid
->rxqueue
, len
+ yid
->rxlen
);
3623 memcpy(yid
->rxqueue
+ yid
->rxlen
, buf
, len
);
3626 yahoo_process_connection
[yid
->type
](yid
, 0);
3631 int yahoo_init_with_attributes(const char *username
, const char *password
, ...)
3634 struct yahoo_data
*yd
;
3636 yd
= y_new0(struct yahoo_data
, 1);
3641 yd
->user
= strdup(username
);
3642 yd
->password
= strdup(password
);
3644 yd
->initial_status
= -1;
3645 yd
->current_status
= -1;
3647 yd
->client_id
= ++last_id
;
3651 va_start(ap
, password
);
3652 yd
->server_settings
= _yahoo_assign_server_settings(ap
);
3655 return yd
->client_id
;
3658 int yahoo_init(const char *username
, const char *password
)
3660 return yahoo_init_with_attributes(username
, password
, (char *)NULL
);
3663 struct connect_callback_data
{
3664 struct yahoo_data
*yd
;
3669 static void yahoo_connected(int fd
, int error
, void *data
)
3671 struct connect_callback_data
*ccd
= data
;
3672 struct yahoo_data
*yd
= ccd
->yd
;
3673 struct yahoo_packet
*pkt
;
3674 struct yahoo_input_data
*yid
;
3675 struct yahoo_server_settings
*yss
= yd
->server_settings
;
3678 if(fallback_ports
[ccd
->i
]) {
3680 yss
->pager_port
= fallback_ports
[ccd
->i
++];
3681 tag
= YAHOO_CALLBACK(ext_yahoo_connect_async
)(yd
->client_id
, yss
->pager_host
,
3682 yss
->pager_port
, yahoo_connected
, ccd
);
3688 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_SOCK
, NULL
);
3695 /* fd < 0 && error == 0 means connect was cancelled */
3699 pkt
= yahoo_packet_new(YAHOO_SERVICE_AUTH
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
3700 NOTICE(("Sending initial packet"));
3702 yahoo_packet_hash(pkt
, 1, yd
->user
);
3704 yid
= y_new0(struct yahoo_input_data
, 1);
3707 inputs
= y_list_prepend(inputs
, yid
);
3709 yahoo_send_packet(yid
, pkt
, 0);
3711 yahoo_packet_free(pkt
);
3713 yid
->read_tag
=YAHOO_CALLBACK(ext_yahoo_add_handler
)(yid
->yd
->client_id
, yid
->fd
, YAHOO_INPUT_READ
, yid
);
3716 void yahoo_login(int id
, int initial
)
3718 struct yahoo_data
*yd
= find_conn_by_id(id
);
3719 struct connect_callback_data
*ccd
;
3720 struct yahoo_server_settings
*yss
;
3726 yss
= yd
->server_settings
;
3728 yd
->initial_status
= initial
;
3730 ccd
= y_new0(struct connect_callback_data
, 1);
3732 tag
= YAHOO_CALLBACK(ext_yahoo_connect_async
)(yd
->client_id
, yss
->pager_host
, yss
->pager_port
,
3733 yahoo_connected
, ccd
);
3736 * if tag <= 0, then callback has already been called
3737 * so ccd will have been freed
3742 YAHOO_CALLBACK(ext_yahoo_login_response
)(yd
->client_id
, YAHOO_LOGIN_SOCK
, NULL
);
3746 int yahoo_get_fd(int id
)
3748 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
3755 void yahoo_send_im(int id
, const char *from
, const char *who
, const char *what
, int utf8
, int picture
)
3757 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
3758 struct yahoo_packet
*pkt
= NULL
;
3759 struct yahoo_data
*yd
;
3767 pkt
= yahoo_packet_new(YAHOO_SERVICE_MESSAGE
, YAHOO_STATUS_OFFLINE
, yd
->session_id
);
3769 snprintf(pic_str
, sizeof(pic_str
), "%d", picture
);
3771 if(from
&& strcmp(from
, yd
->user
))
3772 yahoo_packet_hash(pkt
, 0, yd
->user
);
3773 yahoo_packet_hash(pkt
, 1, from
?from
:yd
->user
);
3774 yahoo_packet_hash(pkt
, 5, who
);
3775 yahoo_packet_hash(pkt
, 14, what
);
3778 yahoo_packet_hash(pkt
, 97, "1");
3780 yahoo_packet_hash(pkt
, 63, ";0"); /* imvironment name; or ;0 */
3781 yahoo_packet_hash(pkt
, 64, "0");
3782 yahoo_packet_hash(pkt
, 206, pic_str
);
3785 yahoo_send_packet(yid
, pkt
, 0);
3787 yahoo_packet_free(pkt
);
3790 void yahoo_send_typing(int id
, const char *from
, const char *who
, int typ
)
3792 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
3793 struct yahoo_data
*yd
;
3794 struct yahoo_packet
*pkt
= NULL
;
3799 pkt
= yahoo_packet_new(YAHOO_SERVICE_NOTIFY
, YAHOO_STATUS_NOTIFY
, yd
->session_id
);
3801 yahoo_packet_hash(pkt
, 5, who
);
3802 yahoo_packet_hash(pkt
, 4, from
?from
:yd
->user
);
3803 yahoo_packet_hash(pkt
, 14, " ");
3804 yahoo_packet_hash(pkt
, 13, typ
? "1" : "0");
3805 yahoo_packet_hash(pkt
, 49, "TYPING");
3807 yahoo_send_packet(yid
, pkt
, 0);
3809 yahoo_packet_free(pkt
);
3812 void yahoo_set_away(int id
, enum yahoo_status state
, const char *msg
, int away
)
3814 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
3815 struct yahoo_data
*yd
;
3816 struct yahoo_packet
*pkt
= NULL
;
3826 yd
->current_status
= YAHOO_STATUS_CUSTOM
;
3828 yd
->current_status
= state
;
3831 if (yd
->current_status
== YAHOO_STATUS_AVAILABLE
)
3832 service
= YAHOO_SERVICE_ISBACK
;
3834 service
= YAHOO_SERVICE_ISAWAY
;
3836 if ((away
== 2) && (yd
->current_status
== YAHOO_STATUS_AVAILABLE
)) {
3837 pkt
= yahoo_packet_new(YAHOO_SERVICE_ISAWAY
, YAHOO_STATUS_BRB
, yd
->session_id
);
3838 yahoo_packet_hash(pkt
, 10, "999");
3839 yahoo_packet_hash(pkt
, 47, "2");
3841 pkt
= yahoo_packet_new(service
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
3842 snprintf(s
, sizeof(s
), "%d", yd
->current_status
);
3843 yahoo_packet_hash(pkt
, 10, s
);
3844 if (yd
->current_status
== YAHOO_STATUS_CUSTOM
) {
3845 yahoo_packet_hash(pkt
, 19, msg
);
3846 yahoo_packet_hash(pkt
, 47, (away
== 2)? "2": (away
) ?"1":"0");
3848 yahoo_packet_hash(pkt
, 47, (away
== 2)? "2": (away
) ?"1":"0");
3855 yahoo_send_packet(yid
, pkt
, 0);
3856 yahoo_packet_free(pkt
);
3859 void yahoo_logoff(int id
)
3861 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
3862 struct yahoo_data
*yd
;
3863 struct yahoo_packet
*pkt
= NULL
;
3869 LOG(("yahoo_logoff: current status: %d", yd
->current_status
));
3871 if(yd
->current_status
!= -1) {
3872 pkt
= yahoo_packet_new(YAHOO_SERVICE_LOGOFF
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
3873 yd
->current_status
= -1;
3876 yahoo_send_packet(yid
, pkt
, 0);
3877 yahoo_packet_free(pkt
);
3883 yahoo_input_close(yid);
3884 } while((yid = find_input_by_id(id)));*/
3888 void yahoo_get_list(int id
)
3890 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
3891 struct yahoo_data
*yd
;
3892 struct yahoo_packet
*pkt
= NULL
;
3898 pkt
= yahoo_packet_new(YAHOO_SERVICE_LIST
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
3899 yahoo_packet_hash(pkt
, 1, yd
->user
);
3901 yahoo_send_packet(yid
, pkt
, 0);
3902 yahoo_packet_free(pkt
);
3906 static void _yahoo_http_connected(int id
, int fd
, int error
, void *data
)
3908 struct yahoo_input_data
*yid
= data
;
3910 inputs
= y_list_remove(inputs
, yid
);
3916 yid
->read_tag
=YAHOO_CALLBACK(ext_yahoo_add_handler
)(yid
->yd
->client_id
, fd
, YAHOO_INPUT_READ
, yid
);
3919 void yahoo_get_yab(int id
)
3921 struct yahoo_data
*yd
= find_conn_by_id(id
);
3922 struct yahoo_input_data
*yid
;
3929 yid
= y_new0(struct yahoo_input_data
, 1);
3931 yid
->type
= YAHOO_CONNECTION_YAB
;
3933 snprintf(url
, 1024, "http://insider.msg.yahoo.com/ycontent/?ab2=0");
3935 snprintf(buff
, sizeof(buff
), "Y=%s; T=%s",
3936 yd
->cookie_y
, yd
->cookie_t
);
3938 inputs
= y_list_prepend(inputs
, yid
);
3940 yahoo_http_get(yid
->yd
->client_id
, url
, buff
,
3941 _yahoo_http_connected
, yid
);
3944 void yahoo_set_yab(int id
, struct yab
* yab
)
3946 struct yahoo_data
*yd
= find_conn_by_id(id
);
3947 struct yahoo_input_data
*yid
;
3951 int size
= sizeof(url
)-1;
3956 yid
= y_new0(struct yahoo_input_data
, 1);
3957 yid
->type
= YAHOO_CONNECTION_YAB
;
3960 strncpy(url
, "http://insider.msg.yahoo.com/ycontent/?addab2=0", size
);
3963 /* change existing yab */
3965 strncat(url
, "&ee=1&ow=1&id=", size
- strlen(url
));
3966 snprintf(tmp
, sizeof(tmp
), "%d", yab
->dbid
);
3967 strncat(url
, tmp
, size
- strlen(url
));
3971 strncat(url
, "&fn=", size
- strlen(url
));
3972 temp
= yahoo_urlencode(yab
->fname
);
3973 strncat(url
, temp
, size
- strlen(url
));
3977 strncat(url
, "&ln=", size
- strlen(url
));
3978 temp
= yahoo_urlencode(yab
->lname
);
3979 strncat(url
, temp
, size
- strlen(url
));
3982 strncat(url
, "&yid=", size
- strlen(url
));
3983 temp
= yahoo_urlencode(yab
->id
);
3984 strncat(url
, temp
, size
- strlen(url
));
3987 strncat(url
, "&nn=", size
- strlen(url
));
3988 temp
= yahoo_urlencode(yab
->nname
);
3989 strncat(url
, temp
, size
- strlen(url
));
3993 strncat(url
, "&e=", size
- strlen(url
));
3994 temp
= yahoo_urlencode(yab
->email
);
3995 strncat(url
, temp
, size
- strlen(url
));
3999 strncat(url
, "&hp=", size
- strlen(url
));
4000 temp
= yahoo_urlencode(yab
->hphone
);
4001 strncat(url
, temp
, size
- strlen(url
));
4005 strncat(url
, "&wp=", size
- strlen(url
));
4006 temp
= yahoo_urlencode(yab
->wphone
);
4007 strncat(url
, temp
, size
- strlen(url
));
4011 strncat(url
, "&mp=", size
- strlen(url
));
4012 temp
= yahoo_urlencode(yab
->mphone
);
4013 strncat(url
, temp
, size
- strlen(url
));
4016 strncat(url
, "&pp=0", size
- strlen(url
));
4018 snprintf(buff
, sizeof(buff
), "Y=%s; T=%s",
4019 yd
->cookie_y
, yd
->cookie_t
);
4021 inputs
= y_list_prepend(inputs
, yid
);
4023 yahoo_http_get(yid
->yd
->client_id
, url
, buff
,
4024 _yahoo_http_connected
, yid
);
4027 void yahoo_set_identity_status(int id
, const char * identity
, int active
)
4029 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4030 struct yahoo_data
*yd
;
4031 struct yahoo_packet
*pkt
= NULL
;
4037 pkt
= yahoo_packet_new(active
?YAHOO_SERVICE_IDACT
:YAHOO_SERVICE_IDDEACT
,
4038 YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4039 yahoo_packet_hash(pkt
, 3, identity
);
4041 yahoo_send_packet(yid
, pkt
, 0);
4042 yahoo_packet_free(pkt
);
4046 void yahoo_refresh(int id
)
4048 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4049 struct yahoo_data
*yd
;
4050 struct yahoo_packet
*pkt
= NULL
;
4056 pkt
= yahoo_packet_new(YAHOO_SERVICE_USERSTAT
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4058 yahoo_send_packet(yid
, pkt
, 0);
4059 yahoo_packet_free(pkt
);
4063 void yahoo_keepalive(int id
)
4065 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4066 struct yahoo_data
*yd
;
4067 struct yahoo_packet
*pkt
=NULL
;
4072 pkt
= yahoo_packet_new(YAHOO_SERVICE_PING
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4073 yahoo_send_packet(yid
, pkt
, 0);
4074 yahoo_packet_free(pkt
);
4077 void yahoo_chat_keepalive (int id
)
4079 struct yahoo_input_data
*yid
= find_input_by_id_and_type (id
, YAHOO_CONNECTION_PAGER
);
4080 struct yahoo_data
*yd
;
4081 struct yahoo_packet
*pkt
= NULL
;
4088 pkt
= yahoo_packet_new (YAHOO_SERVICE_CHATPING
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4089 yahoo_send_packet (yid
, pkt
, 0);
4090 yahoo_packet_free (pkt
);
4093 void yahoo_add_buddy(int id
, const char *who
, const char *group
, const char *msg
)
4095 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4096 struct yahoo_data
*yd
;
4097 struct yahoo_packet
*pkt
;
4106 pkt
= yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4107 yahoo_packet_hash(pkt
, 1, yd
->user
);
4108 yahoo_packet_hash(pkt
, 7, who
);
4109 yahoo_packet_hash(pkt
, 65, group
);
4111 yahoo_packet_hash(pkt
, 14, msg
);
4113 yahoo_send_packet(yid
, pkt
, 0);
4114 yahoo_packet_free(pkt
);
4117 void yahoo_remove_buddy(int id
, const char *who
, const char *group
)
4119 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4120 struct yahoo_data
*yd
;
4121 struct yahoo_packet
*pkt
= NULL
;
4127 pkt
= yahoo_packet_new(YAHOO_SERVICE_REMBUDDY
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4129 yahoo_packet_hash(pkt
, 1, yd
->user
);
4130 yahoo_packet_hash(pkt
, 7, who
);
4131 yahoo_packet_hash(pkt
, 65, group
);
4132 yahoo_send_packet(yid
, pkt
, 0);
4133 yahoo_packet_free(pkt
);
4136 void yahoo_reject_buddy(int id
, const char *who
, const char *msg
)
4138 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4139 struct yahoo_data
*yd
;
4140 struct yahoo_packet
*pkt
;
4149 pkt
= yahoo_packet_new(YAHOO_SERVICE_REJECTCONTACT
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4150 yahoo_packet_hash(pkt
, 1, yd
->user
);
4151 yahoo_packet_hash(pkt
, 7, who
);
4152 yahoo_packet_hash(pkt
, 14, msg
);
4153 yahoo_send_packet(yid
, pkt
, 0);
4154 yahoo_packet_free(pkt
);
4157 void yahoo_ignore_buddy(int id
, const char *who
, int unignore
)
4159 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4160 struct yahoo_data
*yd
;
4161 struct yahoo_packet
*pkt
;
4170 pkt
= yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4171 yahoo_packet_hash(pkt
, 1, yd
->user
);
4172 yahoo_packet_hash(pkt
, 7, who
);
4173 yahoo_packet_hash(pkt
, 13, unignore
?"2":"1");
4174 yahoo_send_packet(yid
, pkt
, 0);
4175 yahoo_packet_free(pkt
);
4178 void yahoo_stealth_buddy(int id
, const char *who
, int unstealth
)
4180 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4181 struct yahoo_data
*yd
;
4182 struct yahoo_packet
*pkt
;
4191 pkt
= yahoo_packet_new(YAHOO_SERVICE_STEALTH
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4192 yahoo_packet_hash(pkt
, 1, yd
->user
);
4193 yahoo_packet_hash(pkt
, 7, who
);
4194 yahoo_packet_hash(pkt
, 31, unstealth
?"2":"1");
4195 yahoo_packet_hash(pkt
, 13, "2");
4196 yahoo_send_packet(yid
, pkt
, 0);
4197 yahoo_packet_free(pkt
);
4200 void yahoo_change_buddy_group(int id
, const char *who
, const char *old_group
, const char *new_group
)
4202 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4203 struct yahoo_data
*yd
;
4204 struct yahoo_packet
*pkt
= NULL
;
4210 pkt
= yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4211 yahoo_packet_hash(pkt
, 1, yd
->user
);
4212 yahoo_packet_hash(pkt
, 7, who
);
4213 yahoo_packet_hash(pkt
, 65, new_group
);
4214 yahoo_packet_hash(pkt
, 14, " ");
4216 yahoo_send_packet(yid
, pkt
, 0);
4217 yahoo_packet_free(pkt
);
4219 pkt
= yahoo_packet_new(YAHOO_SERVICE_REMBUDDY
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4220 yahoo_packet_hash(pkt
, 1, yd
->user
);
4221 yahoo_packet_hash(pkt
, 7, who
);
4222 yahoo_packet_hash(pkt
, 65, old_group
);
4223 yahoo_send_packet(yid
, pkt
, 0);
4224 yahoo_packet_free(pkt
);
4227 void yahoo_group_rename(int id
, const char *old_group
, const char *new_group
)
4229 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4230 struct yahoo_data
*yd
;
4231 struct yahoo_packet
*pkt
= NULL
;
4237 pkt
= yahoo_packet_new(YAHOO_SERVICE_GROUPRENAME
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4238 yahoo_packet_hash(pkt
, 1, yd
->user
);
4239 yahoo_packet_hash(pkt
, 65, old_group
);
4240 yahoo_packet_hash(pkt
, 67, new_group
);
4242 yahoo_send_packet(yid
, pkt
, 0);
4243 yahoo_packet_free(pkt
);
4246 void yahoo_conference_addinvite(int id
, const char * from
, const char *who
, const char *room
, const YList
* members
, const char *msg
)
4248 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4249 struct yahoo_data
*yd
;
4250 struct yahoo_packet
*pkt
;
4256 pkt
= yahoo_packet_new(YAHOO_SERVICE_CONFADDINVITE
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4258 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4259 yahoo_packet_hash(pkt
, 51, who
);
4260 yahoo_packet_hash(pkt
, 57, room
);
4261 yahoo_packet_hash(pkt
, 58, msg
);
4262 yahoo_packet_hash(pkt
, 13, "0");
4263 for(; members
; members
= members
->next
) {
4264 yahoo_packet_hash(pkt
, 52, (char *)members
->data
);
4265 yahoo_packet_hash(pkt
, 53, (char *)members
->data
);
4267 /* 52, 53 -> other members? */
4269 yahoo_send_packet(yid
, pkt
, 0);
4271 yahoo_packet_free(pkt
);
4274 void yahoo_conference_invite(int id
, const char * from
, YList
*who
, const char *room
, const char *msg
)
4276 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4277 struct yahoo_data
*yd
;
4278 struct yahoo_packet
*pkt
;
4284 pkt
= yahoo_packet_new(YAHOO_SERVICE_CONFINVITE
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4286 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4287 yahoo_packet_hash(pkt
, 50, yd
->user
);
4288 for(; who
; who
= who
->next
) {
4289 yahoo_packet_hash(pkt
, 52, (char *)who
->data
);
4291 yahoo_packet_hash(pkt
, 57, room
);
4292 yahoo_packet_hash(pkt
, 58, msg
);
4293 yahoo_packet_hash(pkt
, 13, "0");
4295 yahoo_send_packet(yid
, pkt
, 0);
4297 yahoo_packet_free(pkt
);
4300 void yahoo_conference_logon(int id
, const char *from
, YList
*who
, const char *room
)
4302 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4303 struct yahoo_data
*yd
;
4304 struct yahoo_packet
*pkt
;
4310 pkt
= yahoo_packet_new(YAHOO_SERVICE_CONFLOGON
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4312 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4313 for(; who
; who
= who
->next
) {
4314 yahoo_packet_hash(pkt
, 3, (char *)who
->data
);
4316 yahoo_packet_hash(pkt
, 57, room
);
4318 yahoo_send_packet(yid
, pkt
, 0);
4320 yahoo_packet_free(pkt
);
4323 void yahoo_conference_decline(int id
, const char * from
, YList
*who
, const char *room
, const char *msg
)
4325 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4326 struct yahoo_data
*yd
;
4327 struct yahoo_packet
*pkt
;
4333 pkt
= yahoo_packet_new(YAHOO_SERVICE_CONFDECLINE
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4335 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4336 for(; who
; who
= who
->next
) {
4337 yahoo_packet_hash(pkt
, 3, (char *)who
->data
);
4339 yahoo_packet_hash(pkt
, 57, room
);
4340 yahoo_packet_hash(pkt
, 14, msg
);
4342 yahoo_send_packet(yid
, pkt
, 0);
4344 yahoo_packet_free(pkt
);
4347 void yahoo_conference_logoff(int id
, const char * from
, YList
*who
, const char *room
)
4349 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4350 struct yahoo_data
*yd
;
4351 struct yahoo_packet
*pkt
;
4357 pkt
= yahoo_packet_new(YAHOO_SERVICE_CONFLOGOFF
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4359 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4360 for(; who
; who
= who
->next
) {
4361 yahoo_packet_hash(pkt
, 3, (char *)who
->data
);
4363 yahoo_packet_hash(pkt
, 57, room
);
4365 yahoo_send_packet(yid
, pkt
, 0);
4367 yahoo_packet_free(pkt
);
4370 void yahoo_conference_message(int id
, const char * from
, YList
*who
, const char *room
, const char *msg
, int utf8
)
4372 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4373 struct yahoo_data
*yd
;
4374 struct yahoo_packet
*pkt
;
4380 pkt
= yahoo_packet_new(YAHOO_SERVICE_CONFMSG
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4382 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4383 for(; who
; who
= who
->next
) {
4384 yahoo_packet_hash(pkt
, 53, (char *)who
->data
);
4386 yahoo_packet_hash(pkt
, 57, room
);
4387 yahoo_packet_hash(pkt
, 14, msg
);
4390 yahoo_packet_hash(pkt
, 97, "1");
4392 yahoo_send_packet(yid
, pkt
, 0);
4394 yahoo_packet_free(pkt
);
4397 void yahoo_get_chatrooms(int id
, int chatroomid
)
4399 struct yahoo_data
*yd
= find_conn_by_id(id
);
4400 struct yahoo_input_data
*yid
;
4407 yid
= y_new0(struct yahoo_input_data
, 1);
4409 yid
->type
= YAHOO_CONNECTION_CHATCAT
;
4411 if (chatroomid
== 0) {
4412 snprintf(url
, 1024, "http://insider.msg.yahoo.com/ycontent/?chatcat=0");
4414 snprintf(url
, 1024, "http://insider.msg.yahoo.com/ycontent/?chatroom_%d=0",chatroomid
);
4417 snprintf(buff
, sizeof(buff
), "Y=%s; T=%s", yd
->cookie_y
, yd
->cookie_t
);
4419 inputs
= y_list_prepend(inputs
, yid
);
4421 yahoo_http_get(yid
->yd
->client_id
, url
, buff
, _yahoo_http_connected
, yid
);
4424 void yahoo_chat_logon(int id
, const char *from
, const char *room
, const char *roomid
)
4426 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4427 struct yahoo_data
*yd
;
4428 struct yahoo_packet
*pkt
;
4435 pkt
= yahoo_packet_new(YAHOO_SERVICE_CHATONLINE
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4437 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4438 yahoo_packet_hash(pkt
, 109, yd
->user
);
4439 yahoo_packet_hash(pkt
, 6, "abcde");
4441 yahoo_send_packet(yid
, pkt
, 0);
4443 yahoo_packet_free(pkt
);
4445 pkt
= yahoo_packet_new(YAHOO_SERVICE_CHATJOIN
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4447 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4448 yahoo_packet_hash(pkt
, 104, room
);
4449 yahoo_packet_hash(pkt
, 129, roomid
);
4450 yahoo_packet_hash(pkt
, 62, "2"); /* ??? */
4452 yahoo_send_packet(yid
, pkt
, 0);
4454 yahoo_packet_free(pkt
);
4458 void yahoo_chat_message(int id
, const char *from
, const char *room
, const char *msg
, const int msgtype
, const int utf8
)
4460 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4461 struct yahoo_data
*yd
;
4462 struct yahoo_packet
*pkt
;
4470 pkt
= yahoo_packet_new(YAHOO_SERVICE_COMMENT
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4472 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4473 yahoo_packet_hash(pkt
, 104, room
);
4474 yahoo_packet_hash(pkt
, 117, msg
);
4476 snprintf(buf
, sizeof(buf
), "%d", msgtype
);
4477 yahoo_packet_hash(pkt
, 124, buf
);
4480 yahoo_packet_hash(pkt
, 97, "1");
4482 yahoo_send_packet(yid
, pkt
, 0);
4484 yahoo_packet_free(pkt
);
4488 void yahoo_chat_logoff(int id
, const char *from
)
4490 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4491 struct yahoo_data
*yd
;
4492 struct yahoo_packet
*pkt
;
4499 pkt
= yahoo_packet_new(YAHOO_SERVICE_CHATLOGOUT
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4501 yahoo_packet_hash(pkt
, 1, (from
?from
:yd
->user
));
4503 yahoo_send_packet(yid
, pkt
, 0);
4505 yahoo_packet_free(pkt
);
4508 void yahoo_buddyicon_request(int id
, const char *who
)
4510 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4511 struct yahoo_data
*yd
;
4512 struct yahoo_packet
*pkt
;
4519 pkt
= yahoo_packet_new(YAHOO_SERVICE_PICTURE
, YAHOO_STATUS_AVAILABLE
, 0);
4520 yahoo_packet_hash(pkt
, 4, yd
->user
);
4521 yahoo_packet_hash(pkt
, 5, who
);
4522 yahoo_packet_hash(pkt
, 13, "1");
4523 yahoo_send_packet(yid
, pkt
, 0);
4525 yahoo_packet_free(pkt
);
4528 void yahoo_send_picture_info(int id
, const char *who
, const char *url
, int checksum
)
4530 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4531 struct yahoo_data
*yd
;
4532 struct yahoo_packet
*pkt
;
4533 char checksum_str
[10];
4540 snprintf(checksum_str
, sizeof(checksum_str
), "%d", checksum
);
4542 pkt
= yahoo_packet_new(YAHOO_SERVICE_PICTURE
, YAHOO_STATUS_AVAILABLE
, 0);
4543 yahoo_packet_hash(pkt
, 1, yd
->user
);
4544 yahoo_packet_hash(pkt
, 4, yd
->user
);
4545 yahoo_packet_hash(pkt
, 5, who
);
4546 yahoo_packet_hash(pkt
, 13, "2");
4547 yahoo_packet_hash(pkt
, 20, url
);
4548 yahoo_packet_hash(pkt
, 192, checksum_str
);
4549 yahoo_send_packet(yid
, pkt
, 0);
4551 yahoo_packet_free(pkt
);
4554 void yahoo_send_picture_update(int id
, const char *who
, int type
)
4556 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4557 struct yahoo_data
*yd
;
4558 struct yahoo_packet
*pkt
;
4566 snprintf(type_str
, sizeof(type_str
), "%d", type
);
4568 pkt
= yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPDATE
, YAHOO_STATUS_AVAILABLE
, 0);
4569 yahoo_packet_hash(pkt
, 1, yd
->user
);
4570 yahoo_packet_hash(pkt
, 5, who
);
4571 yahoo_packet_hash(pkt
, 206, type_str
);
4572 yahoo_send_packet(yid
, pkt
, 0);
4574 yahoo_packet_free(pkt
);
4577 void yahoo_send_picture_checksum(int id
, const char *who
, int checksum
)
4579 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4580 struct yahoo_data
*yd
;
4581 struct yahoo_packet
*pkt
;
4582 char checksum_str
[10];
4589 snprintf(checksum_str
, sizeof(checksum_str
), "%d", checksum
);
4591 pkt
= yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM
, YAHOO_STATUS_AVAILABLE
, 0);
4592 yahoo_packet_hash(pkt
, 1, yd
->user
);
4594 yahoo_packet_hash(pkt
, 5, who
);
4595 yahoo_packet_hash(pkt
, 192, checksum_str
);
4596 yahoo_packet_hash(pkt
, 212, "1");
4597 yahoo_send_packet(yid
, pkt
, 0);
4599 yahoo_packet_free(pkt
);
4602 void yahoo_webcam_close_feed(int id
, const char *who
)
4604 struct yahoo_input_data
*yid
= find_input_by_id_and_webcam_user(id
, who
);
4607 yahoo_input_close(yid
);
4610 void yahoo_webcam_get_feed(int id
, const char *who
)
4612 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4613 struct yahoo_data
*yd
;
4614 struct yahoo_packet
*pkt
;
4620 * add the user to the queue. this is a dirty hack, since
4621 * the yahoo server doesn't tell us who's key it's returning,
4622 * we have to just hope that it sends back keys in the same
4623 * order that we request them.
4624 * The queue is popped in yahoo_process_webcam_key
4626 webcam_queue
= y_list_append(webcam_queue
, who
?strdup(who
):NULL
);
4630 pkt
= yahoo_packet_new(YAHOO_SERVICE_WEBCAM
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4632 yahoo_packet_hash(pkt
, 1, yd
->user
);
4634 yahoo_packet_hash(pkt
, 5, who
);
4635 yahoo_send_packet(yid
, pkt
, 0);
4637 yahoo_packet_free(pkt
);
4640 void yahoo_webcam_send_image(int id
, unsigned char *image
, unsigned int length
, unsigned int timestamp
)
4642 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_WEBCAM
);
4643 unsigned char *packet
;
4644 unsigned char header_len
= 13;
4645 unsigned int pos
= 0;
4650 packet
= y_new0(unsigned char, header_len
);
4652 packet
[pos
++] = header_len
;
4654 packet
[pos
++] = 5; /* version byte?? */
4656 pos
+= yahoo_put32(packet
+ pos
, length
);
4657 packet
[pos
++] = 2; /* packet type, image */
4658 pos
+= yahoo_put32(packet
+ pos
, timestamp
);
4659 yahoo_add_to_send_queue(yid
, packet
, header_len
);
4663 yahoo_add_to_send_queue(yid
, image
, length
);
4666 void yahoo_webcam_accept_viewer(int id
, const char* who
, int accept
)
4668 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_WEBCAM
);
4669 char *packet
= NULL
;
4671 unsigned char header_len
= 13;
4672 unsigned int pos
= 0;
4673 unsigned int len
= 0;
4678 data
= strdup("u=");
4679 data
= y_string_append(data
, (char*)who
);
4680 data
= y_string_append(data
, "\r\n");
4683 packet
= y_new0(char, header_len
+ len
);
4684 packet
[pos
++] = header_len
;
4686 packet
[pos
++] = 5; /* version byte?? */
4688 pos
+= yahoo_put32(packet
+ pos
, len
);
4689 packet
[pos
++] = 0; /* packet type */
4690 pos
+= yahoo_put32(packet
+ pos
, accept
);
4691 memcpy(packet
+ pos
, data
, len
);
4693 yahoo_add_to_send_queue(yid
, packet
, header_len
+ len
);
4697 void yahoo_webcam_invite(int id
, const char *who
)
4699 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4700 struct yahoo_packet
*pkt
;
4705 pkt
= yahoo_packet_new(YAHOO_SERVICE_NOTIFY
, YAHOO_STATUS_NOTIFY
, yid
->yd
->session_id
);
4707 yahoo_packet_hash(pkt
, 49, "WEBCAMINVITE");
4708 yahoo_packet_hash(pkt
, 14, " ");
4709 yahoo_packet_hash(pkt
, 13, "0");
4710 yahoo_packet_hash(pkt
, 1, yid
->yd
->user
);
4711 yahoo_packet_hash(pkt
, 5, who
);
4712 yahoo_send_packet(yid
, pkt
, 0);
4714 yahoo_packet_free(pkt
);
4717 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
)
4719 struct yahoo_data
*yd
= find_conn_by_id(id
);
4720 struct yahoo_input_data
*yid
;
4728 yid
= y_new0(struct yahoo_input_data
, 1);
4730 yid
->type
= YAHOO_CONNECTION_SEARCH
;
4734 .ar=1 - 13-18, 2 - 18-25, 3 - 25-35, 4 - 35-50, 5 - 50-70, 6 - 70+
4737 snprintf(buff
, sizeof(buff
), "&.sq=%%20&.tt=%d&.ss=%d", total
, startpos
);
4739 ctext
= strdup(text
);
4740 while((p
= strchr(ctext
, ' ')))
4743 snprintf(url
, 1024, "http://members.yahoo.com/interests?.oc=m&.kw=%s&.sb=%d&.g=%d&.ar=0%s%s%s",
4744 ctext
, t
, g
, photo
? "&.p=y" : "", yahoo_only
? "&.pg=y" : "",
4745 startpos
? buff
: "");
4749 snprintf(buff
, sizeof(buff
), "Y=%s; T=%s", yd
->cookie_y
, yd
->cookie_t
);
4751 inputs
= y_list_prepend(inputs
, yid
);
4752 yahoo_http_get(yid
->yd
->client_id
, url
, buff
, _yahoo_http_connected
, yid
);
4755 void yahoo_search(int id
, enum yahoo_search_type t
, const char *text
, enum yahoo_search_gender g
, enum yahoo_search_agerange ar
,
4756 int photo
, int yahoo_only
)
4758 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4759 struct yahoo_search_state
*yss
;
4765 yid
->ys
= y_new0(struct yahoo_search_state
, 1);
4769 FREE(yss
->lsearch_text
);
4770 yss
->lsearch_type
= t
;
4771 yss
->lsearch_text
= strdup(text
);
4772 yss
->lsearch_gender
= g
;
4773 yss
->lsearch_agerange
= ar
;
4774 yss
->lsearch_photo
= photo
;
4775 yss
->lsearch_yahoo_only
= yahoo_only
;
4777 yahoo_search_internal(id
, t
, text
, g
, ar
, photo
, yahoo_only
, 0, 0);
4780 void yahoo_search_again(int id
, int start
)
4782 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4783 struct yahoo_search_state
*yss
;
4785 if(!yid
|| !yid
->ys
)
4791 start
= yss
->lsearch_nstart
+ yss
->lsearch_nfound
;
4793 yahoo_search_internal(id
, yss
->lsearch_type
, yss
->lsearch_text
,
4794 yss
->lsearch_gender
, yss
->lsearch_agerange
,
4795 yss
->lsearch_photo
, yss
->lsearch_yahoo_only
,
4796 start
, yss
->lsearch_ntotal
);
4799 struct send_file_data
{
4800 struct yahoo_packet
*pkt
;
4801 yahoo_get_fd_callback callback
;
4805 static void _yahoo_send_picture_connected(int id
, int fd
, int error
, void *data
)
4807 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_FT
);
4808 struct send_file_data
*sfd
= data
;
4809 struct yahoo_packet
*pkt
= sfd
->pkt
;
4810 unsigned char buff
[1024];
4813 sfd
->callback(id
, fd
, error
, sfd
->user_data
);
4815 yahoo_packet_free(pkt
);
4816 inputs
= y_list_remove(inputs
, yid
);
4822 yahoo_send_packet(yid
, pkt
, 8);
4823 yahoo_packet_free(pkt
);
4825 snprintf((char *)buff
, sizeof(buff
), "29");
4829 write(yid
->fd
, buff
, 4);
4831 /* YAHOO_CALLBACK(ext_yahoo_add_handler)(nyd->fd, YAHOO_INPUT_READ); */
4833 sfd
->callback(id
, fd
, error
, sfd
->user_data
);
4835 inputs
= y_list_remove(inputs
, yid
);
4837 while(yahoo_tcp_readline(buff, sizeof(buff), nyd->fd) > 0) {
4838 if(!strcmp(buff, ""))
4843 yahoo_input_close(yid
);
4846 void yahoo_send_picture(int id
, const char *name
, unsigned long size
,
4847 yahoo_get_fd_callback callback
, void *data
)
4849 struct yahoo_data
*yd
= find_conn_by_id(id
);
4850 struct yahoo_input_data
*yid
;
4851 struct yahoo_server_settings
*yss
;
4852 struct yahoo_packet
*pkt
= NULL
;
4854 char expire_str
[10];
4855 long content_length
=0;
4856 unsigned char buff
[1024];
4858 struct send_file_data
*sfd
;
4863 yss
= yd
->server_settings
;
4865 yid
= y_new0(struct yahoo_input_data
, 1);
4867 yid
->type
= YAHOO_CONNECTION_FT
;
4869 pkt
= yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPLOAD
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4871 snprintf(size_str
, sizeof(size_str
), "%ld", size
);
4872 snprintf(expire_str
, sizeof(expire_str
), "%ld", (long)604800);
4874 yahoo_packet_hash(pkt
, 0, yd
->user
);
4875 yahoo_packet_hash(pkt
, 1, yd
->user
);
4876 yahoo_packet_hash(pkt
, 14, "");
4877 yahoo_packet_hash(pkt
, 27, name
);
4878 yahoo_packet_hash(pkt
, 28, size_str
);
4879 yahoo_packet_hash(pkt
, 38, expire_str
);
4882 content_length
= YAHOO_PACKET_HDRLEN
+ yahoo_packet_length(pkt
);
4884 snprintf(url
, sizeof(url
), "http://%s:%d/notifyft",
4885 yss
->filetransfer_host
, yss
->filetransfer_port
);
4886 snprintf((char *)buff
, sizeof(buff
), "Y=%s; T=%s",
4887 yd
->cookie_y
, yd
->cookie_t
);
4888 inputs
= y_list_prepend(inputs
, yid
);
4890 sfd
= y_new0(struct send_file_data
, 1);
4892 sfd
->callback
= callback
;
4893 sfd
->user_data
= data
;
4894 yahoo_http_post(yid
->yd
->client_id
, url
, (char *)buff
, content_length
+4+size
,
4895 _yahoo_send_picture_connected
, sfd
);
4898 static void _yahoo_send_file_connected(int id
, int fd
, int error
, void *data
)
4900 struct yahoo_input_data
*yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_FT
);
4901 struct send_file_data
*sfd
= data
;
4902 struct yahoo_packet
*pkt
= sfd
->pkt
;
4903 unsigned char buff
[1024];
4906 sfd
->callback(id
, fd
, error
, sfd
->user_data
);
4908 yahoo_packet_free(pkt
);
4909 inputs
= y_list_remove(inputs
, yid
);
4915 yahoo_send_packet(yid
, pkt
, 8);
4916 yahoo_packet_free(pkt
);
4918 snprintf((char *)buff
, sizeof(buff
), "29");
4922 write(yid
->fd
, buff
, 4);
4924 /* YAHOO_CALLBACK(ext_yahoo_add_handler)(nyd->fd, YAHOO_INPUT_READ); */
4926 sfd
->callback(id
, fd
, error
, sfd
->user_data
);
4928 inputs
= y_list_remove(inputs
, yid
);
4930 while(yahoo_tcp_readline(buff, sizeof(buff), nyd->fd) > 0) {
4931 if(!strcmp(buff, ""))
4936 yahoo_input_close(yid
);
4939 void yahoo_send_file(int id
, const char *who
, const char *msg
,
4940 const char *name
, unsigned long size
,
4941 yahoo_get_fd_callback callback
, void *data
)
4943 struct yahoo_data
*yd
= find_conn_by_id(id
);
4944 struct yahoo_input_data
*yid
;
4945 struct yahoo_server_settings
*yss
;
4946 struct yahoo_packet
*pkt
= NULL
;
4948 long content_length
=0;
4949 unsigned char buff
[1024];
4951 struct send_file_data
*sfd
;
4956 yss
= yd
->server_settings
;
4958 yid
= y_new0(struct yahoo_input_data
, 1);
4960 yid
->type
= YAHOO_CONNECTION_FT
;
4962 pkt
= yahoo_packet_new(YAHOO_SERVICE_FILETRANSFER
, YAHOO_STATUS_AVAILABLE
, yd
->session_id
);
4964 snprintf(size_str
, sizeof(size_str
), "%ld", size
);
4966 yahoo_packet_hash(pkt
, 0, yd
->user
);
4967 yahoo_packet_hash(pkt
, 5, who
);
4968 yahoo_packet_hash(pkt
, 14, msg
);
4969 yahoo_packet_hash(pkt
, 27, name
);
4970 yahoo_packet_hash(pkt
, 28, size_str
);
4972 content_length
= YAHOO_PACKET_HDRLEN
+ yahoo_packet_length(pkt
);
4974 snprintf(url
, sizeof(url
), "http://%s:%d/notifyft",
4975 yss
->filetransfer_host
, yss
->filetransfer_port
);
4976 snprintf((char *)buff
, sizeof(buff
), "Y=%s; T=%s",
4977 yd
->cookie_y
, yd
->cookie_t
);
4978 inputs
= y_list_prepend(inputs
, yid
);
4980 sfd
= y_new0(struct send_file_data
, 1);
4982 sfd
->callback
= callback
;
4983 sfd
->user_data
= data
;
4984 yahoo_http_post(yid
->yd
->client_id
, url
, (char *)buff
, content_length
+4+size
,
4985 _yahoo_send_file_connected
, sfd
);
4989 enum yahoo_status
yahoo_current_status(int id
)
4991 struct yahoo_data
*yd
= find_conn_by_id(id
);
4993 return YAHOO_STATUS_OFFLINE
;
4994 return yd
->current_status
;
4997 const YList
* yahoo_get_buddylist(int id
)
4999 struct yahoo_data
*yd
= find_conn_by_id(id
);
5005 const YList
* yahoo_get_ignorelist(int id
)
5007 struct yahoo_data
*yd
= find_conn_by_id(id
);
5013 const YList
* yahoo_get_identities(int id
)
5015 struct yahoo_data
*yd
= find_conn_by_id(id
);
5018 return yd
->identities
;
5021 const char * yahoo_get_cookie(int id
, const char *which
)
5023 struct yahoo_data
*yd
= find_conn_by_id(id
);
5026 if(!strncasecmp(which
, "y", 1))
5027 return yd
->cookie_y
;
5028 if(!strncasecmp(which
, "t", 1))
5029 return yd
->cookie_t
;
5030 if(!strncasecmp(which
, "c", 1))
5031 return yd
->cookie_c
;
5032 if(!strncasecmp(which
, "login", 5))
5033 return yd
->login_cookie
;
5037 void yahoo_get_url_handle(int id
, const char *url
,
5038 yahoo_get_url_handle_callback callback
, void *data
)
5040 struct yahoo_data
*yd
= find_conn_by_id(id
);
5044 yahoo_get_url_fd(id
, url
, yd
, callback
, data
);
5047 const char * yahoo_get_profile_url( void )