2 * libyahoo2: libyahoo2.c
4 * Some code copyright (C) 2002-2004, Philip S Tellis <philip.tellis AT gmx.net>
5 * YMSG16 code copyright (C) 2009,
6 * Siddhesh Poyarekar <siddhesh dot poyarekar at gmail dot com>
8 * Yahoo Search copyright (C) 2003, Konstantin Klyagin <konst AT konst.org.ua>
10 * Much of this code was taken and adapted from the yahoo module for
11 * gaim released under the GNU GPL. This code is also released under the
14 * This code is derivitive of Gaim <http://gaim.sourceforge.net>
15 * copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
16 * 1998-1999, Adam Fritzler <afritz@marko.net>
17 * 1998-2002, Rob Flynn <rob@marko.net>
18 * 2000-2002, Eric Warmenhoven <eric@warmenhoven.org>
19 * 2001-2002, Brian Macke <macke@strangelove.net>
20 * 2001, Anand Biligiri S <abiligiri@users.sf.net>
21 * 2001, Valdis Kletnieks
22 * 2002, Sean Egan <bj91704@binghamton.edu>
23 * 2002, Toby Gray <toby.gray@ntlworld.com>
25 * This library also uses code from other libraries, namely:
26 * Portions from libfaim copyright 1998, 1999 Adam Fritzler
28 * Portions of Sylpheed copyright 2000-2002 Hiroyuki Yamamoto
31 * YMSG16 authentication code based mostly on write-up at:
32 * http://www.carbonize.co.uk/ymsg16.html
34 * This program is free software; you can redistribute it and/or modify
35 * it under the terms of the GNU General Public License as published by
36 * the Free Software Foundation; either version 2 of the License, or
37 * (at your option) any later version.
39 * This program is distributed in the hope that it will be useful,
40 * but WITHOUT ANY WARRANTY; without even the implied warranty of
41 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42 * GNU General Public License for more details.
44 * You should have received a copy of the GNU General Public License
45 * along with this program; if not, write to the Free Software
46 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
66 # define strrchr rindex
68 char *strchr(), *strrchr();
70 # define memcpy(d, s, n) bcopy ((s), (d), (n))
71 # define memmove(d, s, n) bcopy ((s), (d), (n))
75 #include <sys/types.h>
83 #include "yahoo_httplib.h"
84 #include "yahoo_util.h"
87 #include "yahoo2_callbacks.h"
88 #include "yahoo_debug.h"
90 #define snprintf _snprintf
91 #define vsnprintf _vsnprintf
94 struct yahoo_callbacks
*yc
= NULL
;
96 void yahoo_register_callbacks(struct yahoo_callbacks
*tyc
)
101 #define YAHOO_CALLBACK(x) yc->x
103 static int yahoo_send_data(void *fd
, void *data
, int len
);
104 static void _yahoo_http_connected(int id
, void *fd
, int error
, void *data
);
105 static void yahoo_connected(void *fd
, int error
, void *data
);
107 int yahoo_log_message(char *fmt
, ...)
112 vsnprintf(out
, sizeof(out
), fmt
, ap
);
114 return YAHOO_CALLBACK(ext_yahoo_log
) ("%s", out
);
117 int yahoo_connect(char *host
, int port
)
119 return YAHOO_CALLBACK(ext_yahoo_connect
) (host
, port
);
122 static enum yahoo_log_level log_level
= YAHOO_LOG_NONE
;
124 enum yahoo_log_level
yahoo_get_log_level()
129 int yahoo_set_log_level(enum yahoo_log_level level
)
131 enum yahoo_log_level l
= log_level
;
136 /* default values for servers */
137 static char *default_pager_hosts
[] = { "scs.msg.yahoo.com",
138 "scsa.msg.yahoo.com",
139 "scsb.msg.yahoo.com",
140 "scsc.msg.yahoo.com",
143 static int pager_port
= 5050;
144 static int fallback_ports
[] = { 23, 25, 80, 20, 119, 8001, 8002, 5050, 0 };
146 static char filetransfer_host
[] = "filetransfer.msg.yahoo.com";
147 static int filetransfer_port
= 80;
148 static char webcam_host
[] = "webcam.yahoo.com";
149 static int webcam_port
= 5100;
150 static char webcam_description
[] = "";
151 static char local_host
[] = "";
152 static int conn_type
= Y_WCM_DSL
;
154 static char profile_url
[] = "http://profiles.yahoo.com/";
156 struct connect_callback_data
{
157 struct yahoo_data
*yd
;
168 struct yahoo_packet
{
169 unsigned short int service
;
175 struct yahoo_search_state
{
179 int lsearch_agerange
;
181 int lsearch_yahoo_only
;
188 unsigned char *queue
;
192 struct yahoo_input_data
{
193 struct yahoo_data
*yd
;
194 struct yahoo_webcam
*wcm
;
195 struct yahoo_webcam_data
*wcd
;
196 struct yahoo_search_state
*ys
;
199 enum yahoo_connection_type type
;
201 unsigned char *rxqueue
;
209 struct yahoo_server_settings
{
212 char *filetransfer_host
;
213 int filetransfer_port
;
216 char *webcam_description
;
219 char **pager_host_list
;
222 static void yahoo_process_ft_connection(struct yahoo_input_data
*yid
, int over
);
224 static void yahoo_process_filetransfer(struct yahoo_input_data
*yid
,
225 struct yahoo_packet
*pkt
);
226 static void yahoo_process_filetransferinfo(struct yahoo_input_data
*yid
,
227 struct yahoo_packet
*pkt
);
228 static void yahoo_process_filetransferaccept(struct yahoo_input_data
*yid
,
229 struct yahoo_packet
*pkt
);
231 static void *_yahoo_default_server_settings()
233 struct yahoo_server_settings
*yss
=
234 y_new0(struct yahoo_server_settings
, 1);
236 /* Give preference to the default host list
237 * Make sure that only one of the two is set at any time
239 yss
->pager_host
= NULL
;
240 yss
->pager_host_list
= default_pager_hosts
;
242 yss
->pager_port
= pager_port
;
243 yss
->filetransfer_host
= strdup(filetransfer_host
);
244 yss
->filetransfer_port
= filetransfer_port
;
245 yss
->webcam_host
= strdup(webcam_host
);
246 yss
->webcam_port
= webcam_port
;
247 yss
->webcam_description
= strdup(webcam_description
);
248 yss
->local_host
= strdup(local_host
);
249 yss
->conn_type
= conn_type
;
254 static void *_yahoo_assign_server_settings(va_list ap
)
256 struct yahoo_server_settings
*yss
= _yahoo_default_server_settings();
263 key
= va_arg(ap
, char *);
267 if (!strcmp(key
, "pager_host")) {
268 svalue
= va_arg(ap
, char *);
269 free(yss
->pager_host
);
270 yss
->pager_host
= strdup(svalue
);
271 yss
->pager_host_list
= NULL
;
272 } else if (!strcmp(key
, "pager_host_list")) {
273 pvalue
= va_arg(ap
, char **);
274 yss
->pager_host_list
= pvalue
;
275 free(yss
->pager_host
);
276 yss
->pager_host
= NULL
;
277 } else if (!strcmp(key
, "pager_port")) {
278 nvalue
= va_arg(ap
, int);
279 yss
->pager_port
= nvalue
;
280 } else if (!strcmp(key
, "filetransfer_host")) {
281 svalue
= va_arg(ap
, char *);
282 free(yss
->filetransfer_host
);
283 yss
->filetransfer_host
= strdup(svalue
);
284 } else if (!strcmp(key
, "filetransfer_port")) {
285 nvalue
= va_arg(ap
, int);
286 yss
->filetransfer_port
= nvalue
;
287 } else if (!strcmp(key
, "webcam_host")) {
288 svalue
= va_arg(ap
, char *);
289 free(yss
->webcam_host
);
290 yss
->webcam_host
= strdup(svalue
);
291 } else if (!strcmp(key
, "webcam_port")) {
292 nvalue
= va_arg(ap
, int);
293 yss
->webcam_port
= nvalue
;
294 } else if (!strcmp(key
, "webcam_description")) {
295 svalue
= va_arg(ap
, char *);
296 free(yss
->webcam_description
);
297 yss
->webcam_description
= strdup(svalue
);
298 } else if (!strcmp(key
, "local_host")) {
299 svalue
= va_arg(ap
, char *);
300 free(yss
->local_host
);
301 yss
->local_host
= strdup(svalue
);
302 } else if (!strcmp(key
, "conn_type")) {
303 nvalue
= va_arg(ap
, int);
304 yss
->conn_type
= nvalue
;
306 WARNING(("Unknown key passed to yahoo_init, "
307 "perhaps you didn't terminate the list "
315 static void yahoo_free_server_settings(struct yahoo_server_settings
*yss
)
320 free(yss
->pager_host
);
321 free(yss
->filetransfer_host
);
322 free(yss
->webcam_host
);
323 free(yss
->webcam_description
);
324 free(yss
->local_host
);
329 static YList
*conns
= NULL
;
330 static YList
*inputs
= NULL
;
331 static int last_id
= 0;
333 static void add_to_list(struct yahoo_data
*yd
)
335 conns
= y_list_prepend(conns
, yd
);
338 static struct yahoo_data
*find_conn_by_id(int id
)
341 for (l
= conns
; l
; l
= y_list_next(l
)) {
342 struct yahoo_data
*yd
= l
->data
;
343 if (yd
->client_id
== id
)
349 static void del_from_list(struct yahoo_data
*yd
)
351 conns
= y_list_remove(conns
, yd
);
354 /* call repeatedly to get the next one */
356 static struct yahoo_input_data * find_input_by_id(int id)
359 for(l = inputs; l; l = y_list_next(l)) {
360 struct yahoo_input_data *yid = l->data;
361 if(yid->yd->client_id == id)
368 static struct yahoo_input_data
*find_input_by_id_and_webcam_user(int id
,
372 LOG(("find_input_by_id_and_webcam_user"));
373 for (l
= inputs
; l
; l
= y_list_next(l
)) {
374 struct yahoo_input_data
*yid
= l
->data
;
375 if (yid
->type
== YAHOO_CONNECTION_WEBCAM
376 && yid
->yd
->client_id
== id
&& yid
->wcm
&& ((who
378 && !strcmp(who
, yid
->wcm
->user
))
379 || !(yid
->wcm
->user
&& !who
)))
385 static struct yahoo_input_data
*find_input_by_id_and_type(int id
,
386 enum yahoo_connection_type type
)
389 LOG(("find_input_by_id_and_type"));
390 for (l
= inputs
; l
; l
= y_list_next(l
)) {
391 struct yahoo_input_data
*yid
= l
->data
;
392 if (yid
->type
== type
&& yid
->yd
->client_id
== id
)
398 static struct yahoo_input_data
*find_input_by_id_and_fd(int id
, void *fd
)
401 LOG(("find_input_by_id_and_fd"));
402 for (l
= inputs
; l
; l
= y_list_next(l
)) {
403 struct yahoo_input_data
*yid
= l
->data
;
404 if (yid
->fd
== fd
&& yid
->yd
->client_id
== id
)
410 static int count_inputs_with_id(int id
)
414 LOG(("counting %d", id
));
415 for (l
= inputs
; l
; l
= y_list_next(l
)) {
416 struct yahoo_input_data
*yid
= l
->data
;
417 if (yid
->yd
->client_id
== id
)
424 extern char *yahoo_crypt(char *, char *);
426 /* Free a buddy list */
427 static void yahoo_free_buddies(YList
*list
)
431 for (l
= list
; l
; l
= l
->next
) {
432 struct yahoo_buddy
*bud
= l
->data
;
438 FREE(bud
->real_name
);
439 if (bud
->yab_entry
) {
440 FREE(bud
->yab_entry
->fname
);
441 FREE(bud
->yab_entry
->lname
);
442 FREE(bud
->yab_entry
->nname
);
443 FREE(bud
->yab_entry
->id
);
444 FREE(bud
->yab_entry
->email
);
445 FREE(bud
->yab_entry
->hphone
);
446 FREE(bud
->yab_entry
->wphone
);
447 FREE(bud
->yab_entry
->mphone
);
448 FREE(bud
->yab_entry
);
451 l
->data
= bud
= NULL
;
457 /* Free an identities list */
458 static void yahoo_free_identities(YList
*list
)
463 list
= y_list_remove_link(list
, list
);
468 /* Free webcam data */
469 static void yahoo_free_webcam(struct yahoo_webcam
*wcm
)
475 FREE(wcm
->description
);
481 static void yahoo_free_data(struct yahoo_data
*yd
)
489 FREE(yd
->login_cookie
);
492 yahoo_free_buddies(yd
->buddies
);
493 yahoo_free_buddies(yd
->ignore
);
494 yahoo_free_identities(yd
->identities
);
496 yahoo_free_server_settings(yd
->server_settings
);
501 #define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4)
503 static struct yahoo_packet
*yahoo_packet_new(enum yahoo_service service
,
504 enum ypacket_status status
, int id
)
506 struct yahoo_packet
*pkt
= y_new0(struct yahoo_packet
, 1);
508 pkt
->service
= service
;
509 pkt
->status
= status
;
515 static void yahoo_packet_hash(struct yahoo_packet
*pkt
, int key
,
518 struct yahoo_pair
*pair
= y_new0(struct yahoo_pair
, 1);
520 pair
->value
= strdup(value
);
521 pkt
->hash
= y_list_append(pkt
->hash
, pair
);
524 static int yahoo_packet_length(struct yahoo_packet
*pkt
)
530 for (l
= pkt
->hash
; l
; l
= l
->next
) {
531 struct yahoo_pair
*pair
= l
->data
;
538 len
+= strlen(pair
->value
);
545 #define yahoo_put16(buf, data) ( \
546 (*(buf) = (unsigned char)((data)>>8)&0xff), \
547 (*((buf)+1) = (unsigned char)(data)&0xff), \
549 #define yahoo_get16(buf) ((((*(buf))&0xff)<<8) + ((*((buf)+1)) & 0xff))
550 #define yahoo_put32(buf, data) ( \
551 (*((buf)) = (unsigned char)((data)>>24)&0xff), \
552 (*((buf)+1) = (unsigned char)((data)>>16)&0xff), \
553 (*((buf)+2) = (unsigned char)((data)>>8)&0xff), \
554 (*((buf)+3) = (unsigned char)(data)&0xff), \
556 #define yahoo_get32(buf) ((((*(buf) )&0xff)<<24) + \
557 (((*((buf)+1))&0xff)<<16) + \
558 (((*((buf)+2))&0xff)<< 8) + \
559 (((*((buf)+3))&0xff)))
561 static void yahoo_packet_read(struct yahoo_packet
*pkt
, unsigned char *data
,
566 while (pos
+ 1 < len
) {
567 char *key
, *value
= NULL
;
571 struct yahoo_pair
*pair
= y_new0(struct yahoo_pair
, 1);
573 key
= malloc(len
+ 1);
575 while (pos
+ 1 < len
) {
576 if (data
[pos
] == 0xc0 && data
[pos
+ 1] == 0x80)
578 key
[x
++] = data
[pos
++];
582 pair
->key
= strtol(key
, NULL
, 10);
588 /* Malformed packet! (Truncated--garbage or something) */
592 /* if x is 0 there was no key, so don't accept it */
594 value
= malloc(len
- pos
+ 1);
596 while (pos
+ 1 < len
) {
597 if (data
[pos
] == 0xc0 && data
[pos
+ 1] == 0x80)
600 value
[x
++] = data
[pos
++];
606 pair
->value
= strdup(value
);
608 pkt
->hash
= y_list_append(pkt
->hash
, pair
);
609 DEBUG_MSG(("Key: %d \tValue: %s", pair
->key
,
617 static void yahoo_packet_write(struct yahoo_packet
*pkt
, unsigned char *data
)
622 for (l
= pkt
->hash
; l
; l
= l
->next
) {
623 struct yahoo_pair
*pair
= l
->data
;
624 unsigned char buf
[100];
626 snprintf((char *)buf
, sizeof(buf
), "%d", pair
->key
);
627 strcpy((char *)data
+ pos
, (char *)buf
);
628 pos
+= strlen((char *)buf
);
632 strcpy((char *)data
+ pos
, pair
->value
);
633 pos
+= strlen(pair
->value
);
639 static void yahoo_dump_unhandled(struct yahoo_packet
*pkt
)
643 NOTICE(("Service: 0x%02x\tStatus: %d", pkt
->service
, pkt
->status
));
644 for (l
= pkt
->hash
; l
; l
= l
->next
) {
645 struct yahoo_pair
*pair
= l
->data
;
646 NOTICE(("\t%d => %s", pair
->key
, pair
->value
));
650 static void yahoo_packet_dump(unsigned char *data
, int len
)
652 if (yahoo_get_log_level() >= YAHOO_LOG_DEBUG
) {
654 for (i
= 0; i
< len
; i
++) {
655 if ((i
% 8 == 0) && i
)
656 YAHOO_CALLBACK(ext_yahoo_log
) (" ");
657 if ((i
% 16 == 0) && i
)
658 YAHOO_CALLBACK(ext_yahoo_log
) ("\n");
659 YAHOO_CALLBACK(ext_yahoo_log
) ("%02x ", data
[i
]);
661 YAHOO_CALLBACK(ext_yahoo_log
) ("\n");
662 for (i
= 0; i
< len
; i
++) {
663 if ((i
% 8 == 0) && i
)
664 YAHOO_CALLBACK(ext_yahoo_log
) (" ");
665 if ((i
% 16 == 0) && i
)
666 YAHOO_CALLBACK(ext_yahoo_log
) ("\n");
667 if (isprint(data
[i
]))
668 YAHOO_CALLBACK(ext_yahoo_log
) (" %c ", data
[i
]);
670 YAHOO_CALLBACK(ext_yahoo_log
) (" . ");
672 YAHOO_CALLBACK(ext_yahoo_log
) ("\n");
676 static const char base64digits
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
677 "abcdefghijklmnopqrstuvwxyz" "0123456789._";
678 static void to_y64(unsigned char *out
, const unsigned char *in
, int inlen
)
679 /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
681 for (; inlen
>= 3; inlen
-= 3) {
682 *out
++ = base64digits
[in
[0] >> 2];
683 *out
++ = base64digits
[((in
[0] << 4) & 0x30) | (in
[1] >> 4)];
684 *out
++ = base64digits
[((in
[1] << 2) & 0x3c) | (in
[2] >> 6)];
685 *out
++ = base64digits
[in
[2] & 0x3f];
689 unsigned char fragment
;
691 *out
++ = base64digits
[in
[0] >> 2];
692 fragment
= (in
[0] << 4) & 0x30;
694 fragment
|= in
[1] >> 4;
695 *out
++ = base64digits
[fragment
];
696 *out
++ = (inlen
< 2) ? '-' : base64digits
[(in
[1] << 2) & 0x3c];
702 static void yahoo_add_to_send_queue(struct yahoo_input_data
*yid
, void *data
,
705 struct data_queue
*tx
= y_new0(struct data_queue
, 1);
706 tx
->queue
= y_new0(unsigned char, length
);
708 memcpy(tx
->queue
, data
, length
);
710 yid
->txqueues
= y_list_append(yid
->txqueues
, tx
);
714 YAHOO_CALLBACK(ext_yahoo_add_handler
) (yid
->yd
->
715 client_id
, yid
->fd
, YAHOO_INPUT_WRITE
, yid
);
718 static void yahoo_send_packet(struct yahoo_input_data
*yid
,
719 struct yahoo_packet
*pkt
, int extra_pad
)
721 int pktlen
= yahoo_packet_length(pkt
);
722 int len
= YAHOO_PACKET_HDRLEN
+ pktlen
;
729 data
= y_new0(unsigned char, len
+ 1);
731 memcpy(data
+ pos
, "YMSG", 4);
733 pos
+= yahoo_put16(data
+ pos
, YAHOO_PROTO_VER
); /* version [latest 12 0x000c] */
734 pos
+= yahoo_put16(data
+ pos
, 0x0000); /* HIWORD pkt length??? */
735 pos
+= yahoo_put16(data
+ pos
, pktlen
+ extra_pad
); /* LOWORD pkt length? */
736 pos
+= yahoo_put16(data
+ pos
, pkt
->service
); /* service */
737 pos
+= yahoo_put32(data
+ pos
, pkt
->status
); /* status [4bytes] */
738 pos
+= yahoo_put32(data
+ pos
, pkt
->id
); /* session [4bytes] */
740 yahoo_packet_write(pkt
, data
+ pos
);
742 yahoo_packet_dump(data
, len
);
744 if (yid
->type
== YAHOO_CONNECTION_FT
)
745 yahoo_send_data(yid
->fd
, data
, len
);
747 yahoo_add_to_send_queue(yid
, data
, len
);
751 static void yahoo_packet_free(struct yahoo_packet
*pkt
)
754 struct yahoo_pair
*pair
= pkt
->hash
->data
;
759 pkt
->hash
= y_list_remove_link(pkt
->hash
, pkt
->hash
);
765 static int yahoo_send_data(void *fd
, void *data
, int len
)
773 yahoo_packet_dump(data
, len
);
776 ret
= YAHOO_CALLBACK(ext_yahoo_write
) (fd
, data
, len
);
777 } while (ret
== -1 && errno
== EINTR
);
781 LOG(("wrote data: ERR %s", strerror(errno
)));
783 LOG(("wrote data: OK"));
790 void yahoo_close(int id
)
792 struct yahoo_data
*yd
= find_conn_by_id(id
);
803 static void yahoo_input_close(struct yahoo_input_data
*yid
)
805 inputs
= y_list_remove(inputs
, yid
);
807 LOG(("yahoo_input_close(read)"));
808 YAHOO_CALLBACK(ext_yahoo_remove_handler
) (yid
->yd
->client_id
,
810 LOG(("yahoo_input_close(write)"));
811 YAHOO_CALLBACK(ext_yahoo_remove_handler
) (yid
->yd
->client_id
,
813 yid
->read_tag
= yid
->write_tag
= 0;
815 YAHOO_CALLBACK(ext_yahoo_close
) (yid
->fd
);
818 if (count_inputs_with_id(yid
->yd
->client_id
) == 0) {
819 LOG(("closing %d", yid
->yd
->client_id
));
820 yahoo_close(yid
->yd
->client_id
);
822 yahoo_free_webcam(yid
->wcm
);
826 FREE(yid
->ys
->lsearch_text
);
832 static int is_same_bud(const void *a
, const void *b
)
834 const struct yahoo_buddy
*subject
= a
;
835 const struct yahoo_buddy
*object
= b
;
837 return strcmp(subject
->id
, object
->id
);
840 static char *getcookie(char *rawcookie
)
846 if (strlen(rawcookie
) < 2)
849 tmpcookie
= strdup(rawcookie
+ 2);
850 cookieend
= strchr(tmpcookie
, ';');
855 cookie
= strdup(tmpcookie
);
857 /* cookieend=NULL; not sure why this was there since the value is not preserved in the stack -dd */
862 static char *getlcookie(char *cookie
)
866 char *login_cookie
= NULL
;
868 tmpend
= strstr(cookie
, "n=");
870 tmp
= strdup(tmpend
+ 2);
871 tmpend
= strchr(tmp
, '&');
874 login_cookie
= strdup(tmp
);
881 static void yahoo_process_notify(struct yahoo_input_data
*yid
,
882 struct yahoo_packet
*pkt
)
884 struct yahoo_data
*yd
= yid
->yd
;
892 for (l
= pkt
->hash
; l
; l
= l
->next
) {
893 struct yahoo_pair
*pair
= l
->data
;
901 stat
= atoi(pair
->value
);
904 if (pair
->key
== 16) { /* status == -1 */
905 NOTICE((pair
->value
));
914 if (!strncasecmp(msg
, "TYPING", strlen("TYPING")))
915 YAHOO_CALLBACK(ext_yahoo_typing_notify
) (yd
->client_id
, to
,
917 else if (!strncasecmp(msg
, "GAME", strlen("GAME")))
918 YAHOO_CALLBACK(ext_yahoo_game_notify
) (yd
->client_id
, to
, from
,
920 else if (!strncasecmp(msg
, "WEBCAMINVITE", strlen("WEBCAMINVITE"))) {
921 if (!strcmp(ind
, " ")) {
922 YAHOO_CALLBACK(ext_yahoo_webcam_invite
) (yd
->client_id
,
926 /* accept the invitation (-1 = deny 1 = accept) */
929 YAHOO_CALLBACK(ext_yahoo_webcam_invite_reply
) (yd
->
930 client_id
, to
, from
, accept
);
933 LOG(("Got unknown notification: %s", msg
));
936 static void yahoo_process_conference(struct yahoo_input_data
*yid
,
937 struct yahoo_packet
*pkt
)
939 struct yahoo_data
*yd
= yid
->yd
;
946 YList
*members
= NULL
;
949 for (l
= pkt
->hash
; l
; l
= l
->next
) {
950 struct yahoo_pair
*pair
= l
->data
;
954 if (pair
->key
== 52) { /* invite */
955 members
= y_list_append(members
, strdup(pair
->value
));
957 if (pair
->key
== 53) /* logon */
959 if (pair
->key
== 54) /* decline */
961 if (pair
->key
== 55) /* unavailable (status == 2) */
963 if (pair
->key
== 56) /* logoff */
969 if (pair
->key
== 58) /* join message */
971 if (pair
->key
== 14) /* decline/conf message */
974 if (pair
->key
== 13) ;
975 if (pair
->key
== 16) /* error */
978 if (pair
->key
== 1) /* my id */
980 if (pair
->key
== 3) /* message sender */
984 utf8
= atoi(pair
->value
);
991 for (l
= members
; l
; l
= l
->next
) {
993 if (!strcmp(w
, host
))
997 members
= y_list_append(members
, strdup(host
));
999 /* invite, decline, join, left, message -> status == 1 */
1001 switch (pkt
->service
) {
1002 case YAHOO_SERVICE_CONFINVITE
:
1003 if (pkt
->status
== 2) ;
1005 YAHOO_CALLBACK(ext_yahoo_got_conf_invite
) (yd
->
1006 client_id
, id
, host
, room
, msg
, members
);
1008 YAHOO_CALLBACK(ext_yahoo_error
) (yd
->client_id
, msg
, 0,
1011 case YAHOO_SERVICE_CONFADDINVITE
:
1012 if (pkt
->status
== 1)
1013 YAHOO_CALLBACK(ext_yahoo_got_conf_invite
) (yd
->
1014 client_id
, id
, host
, room
, msg
, members
);
1016 case YAHOO_SERVICE_CONFDECLINE
:
1018 YAHOO_CALLBACK(ext_yahoo_conf_userdecline
) (yd
->
1019 client_id
, id
, who
, room
, msg
);
1021 case YAHOO_SERVICE_CONFLOGON
:
1023 YAHOO_CALLBACK(ext_yahoo_conf_userjoin
) (yd
->client_id
,
1026 case YAHOO_SERVICE_CONFLOGOFF
:
1028 YAHOO_CALLBACK(ext_yahoo_conf_userleave
) (yd
->client_id
,
1031 case YAHOO_SERVICE_CONFMSG
:
1033 YAHOO_CALLBACK(ext_yahoo_conf_message
) (yd
->client_id
,
1034 id
, who
, room
, msg
, utf8
);
1039 static void yahoo_process_chat(struct yahoo_input_data
*yid
,
1040 struct yahoo_packet
*pkt
)
1047 YList
*members
= NULL
;
1048 struct yahoo_chat_member
*currentmember
= NULL
;
1052 int membercount
= 0;
1056 yahoo_dump_unhandled(pkt
);
1057 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1058 struct yahoo_pair
*pair
= l
->data
;
1060 if (pair
->key
== 1) {
1065 if (pair
->key
== 104) {
1070 if (pair
->key
== 105) {
1072 topic
= pair
->value
;
1075 if (pair
->key
== 108) {
1076 /* Number of members in this packet */
1077 membercount
= atoi(pair
->value
);
1080 if (pair
->key
== 109) {
1081 /* message sender */
1084 if (pkt
->service
== YAHOO_SERVICE_CHATJOIN
) {
1086 y_new0(struct yahoo_chat_member
, 1);
1087 currentmember
->id
= strdup(pair
->value
);
1088 members
= y_list_append(members
, currentmember
);
1092 if (pair
->key
== 110) {
1094 if (pkt
->service
== YAHOO_SERVICE_CHATJOIN
)
1095 currentmember
->age
= atoi(pair
->value
);
1098 if (pair
->key
== 113) {
1100 if (pkt
->service
== YAHOO_SERVICE_CHATJOIN
)
1101 currentmember
->attribs
= atoi(pair
->value
);
1104 if (pair
->key
== 141) {
1106 if (pkt
->service
== YAHOO_SERVICE_CHATJOIN
)
1107 currentmember
->alias
= strdup(pair
->value
);
1110 if (pair
->key
== 142) {
1112 if (pkt
->service
== YAHOO_SERVICE_CHATJOIN
)
1113 currentmember
->location
= strdup(pair
->value
);
1116 if (pair
->key
== 130) {
1121 if (pair
->key
== 117) {
1126 if (pair
->key
== 124) {
1128 msgtype
= atoi(pair
->value
);
1130 if (pair
->key
== 114) {
1131 /* message error not sure what all the pair values mean */
1132 /* but -1 means no session in room */
1133 chaterr
= atoi(pair
->value
);
1138 if (pkt
->service
== YAHOO_SERVICE_CHATLOGOUT
) { /* yahoo originated chat logout */
1139 YAHOO_CALLBACK(ext_yahoo_chat_yahoologout
) (yid
->yd
->
1143 if (pkt
->service
== YAHOO_SERVICE_COMMENT
&& chaterr
) {
1144 YAHOO_CALLBACK(ext_yahoo_chat_yahooerror
) (yid
->yd
->
1149 WARNING(("We didn't get a room name, ignoring packet"));
1153 switch (pkt
->service
) {
1154 case YAHOO_SERVICE_CHATJOIN
:
1155 if (y_list_length(members
) != membercount
) {
1156 WARNING(("Count of members doesn't match No. of members we got"));
1158 if (firstjoin
&& members
) {
1159 YAHOO_CALLBACK(ext_yahoo_chat_join
) (yid
->yd
->client_id
,
1160 id
, room
, topic
, members
, yid
->fd
);
1162 if (y_list_length(members
) != 1) {
1163 WARNING(("Got more than 1 member on a normal join"));
1165 /* this should only ever have one, but just in case */
1167 YList
*n
= members
->next
;
1168 currentmember
= members
->data
;
1169 YAHOO_CALLBACK(ext_yahoo_chat_userjoin
) (yid
->
1170 yd
->client_id
, id
, room
, currentmember
);
1171 y_list_free_1(members
);
1176 case YAHOO_SERVICE_CHATEXIT
:
1178 YAHOO_CALLBACK(ext_yahoo_chat_userleave
) (yid
->yd
->
1179 client_id
, id
, room
, who
);
1182 case YAHOO_SERVICE_COMMENT
:
1184 YAHOO_CALLBACK(ext_yahoo_chat_message
) (yid
->yd
->
1185 client_id
, id
, who
, room
, msg
, msgtype
, utf8
);
1191 static void yahoo_process_message(struct yahoo_input_data
*yid
,
1192 struct yahoo_packet
*pkt
)
1194 struct yahoo_data
*yd
= yid
->yd
;
1196 YList
*messages
= NULL
;
1207 } *message
= y_new0(struct m
, 1);
1209 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1210 struct yahoo_pair
*pair
= l
->data
;
1211 if (pair
->key
== 1 || pair
->key
== 4) {
1213 message
->from
= pair
->value
;
1214 } else if (pair
->key
== 5)
1215 message
->to
= pair
->value
;
1216 else if (pair
->key
== 15)
1217 message
->tm
= strtol(pair
->value
, NULL
, 10);
1218 else if (pair
->key
== 97)
1219 message
->utf8
= atoi(pair
->value
);
1220 /* This comes when the official client sends us a message */
1221 else if (pair
->key
== 429)
1222 message
->gunk
= pair
->value
;
1223 /* user message *//* sys message */
1224 else if (pair
->key
== 14 || pair
->key
== 16)
1225 message
->msg
= pair
->value
;
1226 else if (pair
->key
== 31) {
1227 if (message
->i_31
) {
1228 messages
= y_list_append(messages
, message
);
1229 message
= y_new0(struct m
, 1);
1231 message
->i_31
= atoi(pair
->value
);
1232 } else if (pair
->key
== 32)
1233 message
->i_32
= atoi(pair
->value
);
1235 LOG(("yahoo_process_message: status: %d, key: %d, value: %s", pkt
->status
, pair
->key
, pair
->value
));
1238 messages
= y_list_append(messages
, message
);
1240 for (l
= messages
; l
; l
= l
->next
) {
1242 if (pkt
->service
== YAHOO_SERVICE_SYSMESSAGE
) {
1243 YAHOO_CALLBACK(ext_yahoo_system_message
) (yd
->client_id
,
1244 message
->to
, message
->from
, message
->msg
);
1245 } else if (pkt
->status
<= 2 || pkt
->status
== 5) {
1246 /* Confirm message receipt if we got the gunk */
1248 struct yahoo_packet
*outpkt
;
1250 outpkt
= yahoo_packet_new(YAHOO_SERVICE_MESSAGE_CONFIRM
,
1251 YPACKET_STATUS_DEFAULT
, 0);
1252 yahoo_packet_hash(outpkt
, 1, yd
->user
);
1253 yahoo_packet_hash(outpkt
, 5, message
->from
);
1254 yahoo_packet_hash(outpkt
, 302, "430");
1255 yahoo_packet_hash(outpkt
, 430, message
->gunk
);
1256 yahoo_packet_hash(outpkt
, 303, "430");
1257 yahoo_packet_hash(outpkt
, 450, "0");
1258 yahoo_send_packet(yid
, outpkt
, 0);
1260 yahoo_packet_free(outpkt
);
1263 if (!strcmp(message
->msg
, "<ding>"))
1264 YAHOO_CALLBACK(ext_yahoo_got_buzz
) (yd
->client_id
,
1265 message
->to
, message
->from
, message
->tm
);
1267 YAHOO_CALLBACK(ext_yahoo_got_im
) (yd
->client_id
,
1268 message
->to
, message
->from
, message
->msg
,
1269 message
->tm
, pkt
->status
, message
->utf8
);
1270 } else if (pkt
->status
== 0xffffffff) {
1271 YAHOO_CALLBACK(ext_yahoo_error
) (yd
->client_id
,
1272 message
->msg
, 0, E_SYSTEM
);
1277 y_list_free(messages
);
1281 * Here's what multi-level packets look like. Data in brackets is the value.
1286 * 302 (318) - Beginning level 1
1287 * 300 (318) - Begin level 2
1288 * 302 (319) - End level 2 header
1289 * 300 (319) - Begin level 3
1290 * 301 (319) - End level 3
1291 * 303 (319) - End level 2
1292 * 303 (318) - End level 1
1297 * 302 (315) - Beginning level 1
1298 * 300 (315) - Begin level 2
1299 * 301 (315) - End level 2
1300 * 303 (315) - End level 1
1303 static void yahoo_process_status(struct yahoo_input_data
*yid
,
1304 struct yahoo_packet
*pkt
)
1307 struct yahoo_data
*yd
= yid
->yd
;
1309 struct yahoo_process_status_entry
*u
;
1313 if (pkt
->service
== YAHOO_SERVICE_LOGOFF
&& pkt
->status
== -1) {
1314 YAHOO_CALLBACK(ext_yahoo_login_response
) (yd
->client_id
,
1315 YAHOO_LOGIN_DUPL
, NULL
);
1320 * Status updates may be spread accross multiple packets and not
1321 * even on buddy boundaries, so keeping some state is important.
1322 * So, continue where we left off, and only add a user entry to
1323 * the list once it's complete (301-315 End buddy).
1327 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1328 struct yahoo_pair
*pair
= l
->data
;
1330 switch (pair
->key
) {
1331 case 300: /* Begin buddy */
1332 if (!strcmp(pair
->value
, "315") && !u
) {
1333 u
= yd
->half_user
= y_new0(struct yahoo_process_status_entry
, 1);
1336 case 301: /* End buddy */
1337 if (!strcmp(pair
->value
, "315") && u
) {
1338 users
= y_list_prepend(users
, u
);
1339 u
= yd
->half_user
= NULL
;
1342 case 0: /* we won't actually do anything with this */
1343 NOTICE(("key %d:%s", pair
->key
, pair
->value
));
1345 case 1: /* we don't get the full buddy list here. */
1346 if (!yd
->logged_in
) {
1348 if (yd
->current_status
< 0)
1349 yd
->current_status
= yd
->initial_status
;
1350 YAHOO_CALLBACK(ext_yahoo_login_response
) (yd
->
1351 client_id
, YAHOO_LOGIN_OK
, NULL
);
1354 case 8: /* how many online buddies we have */
1355 NOTICE(("key %d:%s", pair
->key
, pair
->value
));
1357 case 7: /* the current buddy */
1359 /* This will only happen in case of a single level message */
1360 u
= y_new0(struct yahoo_process_status_entry
, 1);
1361 users
= y_list_prepend(users
, u
);
1363 u
->name
= pair
->value
;
1365 case 10: /* state */
1366 u
->state
= strtol(pair
->value
, NULL
, 10);
1368 case 19: /* custom status message */
1369 u
->msg
= pair
->value
;
1371 case 47: /* is it an away message or not. Not applicable for YMSG16 anymore */
1372 u
->away
= atoi(pair
->value
);
1374 case 137: /* seconds idle */
1375 u
->idle
= atoi(pair
->value
);
1377 case 11: /* this is the buddy's session id */
1378 u
->buddy_session
= atoi(pair
->value
);
1380 case 17: /* in chat? */
1381 u
->f17
= atoi(pair
->value
);
1383 case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */
1384 u
->flags
= atoi(pair
->value
);
1386 case 60: /* SMS -> 1 MOBILE USER */
1387 /* sometimes going offline makes this 2, but invisible never sends it */
1388 u
->mobile
= atoi(pair
->value
);
1391 u
->f138
= atoi(pair
->value
);
1394 u
->f184
= pair
->value
;
1397 u
->f192
= atoi(pair
->value
);
1400 u
->f10001
= atoi(pair
->value
);
1403 u
->f10002
= atoi(pair
->value
);
1406 u
->f198
= atoi(pair
->value
);
1409 u
->f197
= pair
->value
;
1412 u
->f205
= pair
->value
;
1415 u
->f213
= atoi(pair
->value
);
1417 case 16: /* Custom error message */
1418 YAHOO_CALLBACK(ext_yahoo_error
) (yd
->client_id
,
1419 pair
->value
, 0, E_CUSTOM
);
1422 WARNING(("unknown status key %d:%s", pair
->key
,
1430 struct yahoo_process_status_entry
*u
= users
->data
;
1432 if (u
->name
!= NULL
) {
1434 YAHOO_SERVICE_LOGOFF
1435 /*|| u->flags == 0 No flags for YMSG16 */ ) {
1436 YAHOO_CALLBACK(ext_yahoo_status_changed
) (yd
->
1438 YAHOO_STATUS_OFFLINE
, NULL
, 1, 0, 0);
1440 /* Key 47 always seems to be 1 for YMSG16 */
1446 YAHOO_CALLBACK(ext_yahoo_status_changed
) (yd
->
1447 client_id
, u
->name
, u
->state
, u
->msg
,
1448 u
->away
, u
->idle
, u
->mobile
);
1452 users
= y_list_remove_link(users
, users
);
1458 static void yahoo_process_buddy_list(struct yahoo_input_data
*yid
,
1459 struct yahoo_packet
*pkt
)
1461 struct yahoo_data
*yd
= yid
->yd
;
1463 int last_packet
= 0;
1464 char *cur_group
= NULL
;
1465 struct yahoo_buddy
*newbud
= NULL
;
1467 /* we could be getting multiple packets here */
1468 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1469 struct yahoo_pair
*pair
= l
->data
;
1471 switch (pair
->key
) {
1475 break; /* Separators. Our logic does not need them */
1477 if (318 == atoi(pair
->value
))
1481 cur_group
= strdup(pair
->value
);
1484 newbud
= y_new0(struct yahoo_buddy
, 1);
1485 newbud
->id
= strdup(pair
->value
);
1487 newbud
->group
= strdup(cur_group
);
1488 else if (yd
->buddies
) {
1489 struct yahoo_buddy
*lastbud
=
1490 (struct yahoo_buddy
*)y_list_nth(yd
->
1492 y_list_length(yd
->buddies
) - 1)->data
;
1493 newbud
->group
= strdup(lastbud
->group
);
1495 newbud
->group
= strdup("Buddies");
1497 yd
->buddies
= y_list_append(yd
->buddies
, newbud
);
1503 /* we could be getting multiple packets here */
1504 if (pkt
->hash
&& !last_packet
)
1508 if (!yd
->logged_in
) {
1510 if (yd
->current_status
< 0)
1511 yd
->current_status
= yd
->initial_status
;
1512 YAHOO_CALLBACK(ext_yahoo_login_response
) (yd
->client_id
,
1513 YAHOO_LOGIN_OK
, NULL
);
1515 yahoo_set_away(yd
->client_id
, yd
->initial_status
, NULL
,
1516 (yd
->initial_status
== YAHOO_STATUS_AVAILABLE
) ? 0 : 1);
1518 yahoo_get_yab(yd
->client_id
);
1521 YAHOO_CALLBACK(ext_yahoo_got_buddies
) (yd
->client_id
, yd
->buddies
);
1525 static void yahoo_process_list(struct yahoo_input_data
*yid
,
1526 struct yahoo_packet
*pkt
)
1528 struct yahoo_data
*yd
= yid
->yd
;
1531 /* we could be getting multiple packets here */
1532 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1533 struct yahoo_pair
*pair
= l
->data
;
1535 switch (pair
->key
) {
1536 case 89: /* identities */
1539 y_strsplit(pair
->value
, ",", -1);
1541 for (i
= 0; identities
[i
]; i
++)
1543 y_list_append(yd
->identities
,
1544 strdup(identities
[i
]));
1545 y_strfreev(identities
);
1547 YAHOO_CALLBACK(ext_yahoo_got_identities
) (yd
->client_id
,
1550 case 59: /* cookies */
1551 if (pair
->value
[0] == 'Y') {
1553 FREE(yd
->login_cookie
);
1555 yd
->cookie_y
= getcookie(pair
->value
);
1556 yd
->login_cookie
= getlcookie(yd
->cookie_y
);
1558 } else if (pair
->value
[0] == 'T') {
1560 yd
->cookie_t
= getcookie(pair
->value
);
1562 } else if (pair
->value
[0] == 'C') {
1564 yd
->cookie_c
= getcookie(pair
->value
);
1571 case 101: /* NULL */
1572 case 102: /* NULL */
1573 case 93: /* 86400/1440 */
1578 if (yd
->cookie_y
&& yd
->cookie_t
) /* We don't get cookie_c anymore */
1579 YAHOO_CALLBACK(ext_yahoo_got_cookies
) (yd
->client_id
);
1582 static void yahoo_process_verify(struct yahoo_input_data
*yid
,
1583 struct yahoo_packet
*pkt
)
1585 struct yahoo_data
*yd
= yid
->yd
;
1587 if (pkt
->status
!= 0x01) {
1588 DEBUG_MSG(("expected status: 0x01, got: %d", pkt
->status
));
1589 YAHOO_CALLBACK(ext_yahoo_login_response
) (yd
->client_id
,
1590 YAHOO_LOGIN_LOCK
, "");
1594 pkt
= yahoo_packet_new(YAHOO_SERVICE_AUTH
, YPACKET_STATUS_DEFAULT
,
1597 yahoo_packet_hash(pkt
, 1, yd
->user
);
1598 yahoo_send_packet(yid
, pkt
, 0);
1600 yahoo_packet_free(pkt
);
1604 static void yahoo_process_picture_checksum(struct yahoo_input_data
*yid
,
1605 struct yahoo_packet
*pkt
)
1607 struct yahoo_data
*yd
= yid
->yd
;
1613 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1614 struct yahoo_pair
*pair
= l
->data
;
1616 switch (pair
->key
) {
1626 checksum
= atoi(pair
->value
);
1631 YAHOO_CALLBACK(ext_yahoo_got_buddyicon_checksum
) (yd
->client_id
, to
,
1635 static void yahoo_process_picture(struct yahoo_input_data
*yid
,
1636 struct yahoo_packet
*pkt
)
1638 struct yahoo_data
*yd
= yid
->yd
;
1646 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1647 struct yahoo_pair
*pair
= l
->data
;
1649 switch (pair
->key
) {
1651 case 4: /* sender */
1657 case 13: /* request / sending */
1658 status
= atoi(pair
->value
);
1663 case 192: /*checksum */
1664 checksum
= atoi(pair
->value
);
1670 case 1: /* this is a request, ignore for now */
1671 YAHOO_CALLBACK(ext_yahoo_got_buddyicon_request
) (yd
->client_id
,
1674 case 2: /* this is cool - we get a picture :) */
1675 YAHOO_CALLBACK(ext_yahoo_got_buddyicon
) (yd
->client_id
, to
,
1676 from
, url
, checksum
);
1681 static void yahoo_process_picture_upload(struct yahoo_input_data
*yid
,
1682 struct yahoo_packet
*pkt
)
1684 struct yahoo_data
*yd
= yid
->yd
;
1688 if (pkt
->status
!= 1)
1689 return; /* something went wrong */
1691 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1692 struct yahoo_pair
*pair
= l
->data
;
1694 switch (pair
->key
) {
1700 case 27: /* local filename */
1707 YAHOO_CALLBACK(ext_yahoo_buddyicon_uploaded
) (yd
->client_id
, url
);
1710 void yahoo_login(int id
, int initial
)
1712 struct yahoo_data
*yd
= find_conn_by_id(id
);
1713 struct connect_callback_data
*ccd
;
1714 struct yahoo_server_settings
*yss
;
1719 struct yahoo_input_data
*yid
= y_new0(struct yahoo_input_data
, 1);
1721 yid
->type
= YAHOO_CONNECTION_PAGER
;
1722 inputs
= y_list_prepend(inputs
, yid
);
1724 yd
->initial_status
= initial
;
1725 yss
= yd
->server_settings
;
1727 ccd
= y_new0(struct connect_callback_data
, 1);
1730 host
= yss
->pager_host
;
1733 host
= yss
->pager_host_list
[0];
1735 tag
= YAHOO_CALLBACK(ext_yahoo_connect_async
) (yd
->client_id
,
1736 host
, yss
->pager_port
, yahoo_connected
, ccd
, 0);
1739 * if tag <= 0, then callback has already been called
1740 * so ccd will have been freed
1745 YAHOO_CALLBACK(ext_yahoo_login_response
) (yd
->client_id
,
1746 YAHOO_LOGIN_SOCK
, NULL
);
1749 static void yahoo_auth_https(struct yahoo_data
*yd
)
1752 char *user_encoded
, *pass_encoded
, *seed_encoded
;
1754 struct yahoo_input_data
*yid
= y_new0(struct yahoo_input_data
, 1);
1757 yid
->type
= YAHOO_CONNECTION_AUTH
;
1759 inputs
= y_list_prepend(inputs
, yid
);
1761 user_encoded
= yahoo_urlencode(yid
->yd
->user
);
1762 pass_encoded
= yahoo_urlencode(yid
->yd
->password
);
1763 seed_encoded
= yahoo_urlencode(yid
->yd
->seed
);
1765 snprintf(url
, sizeof(url
),
1766 "https://login.yahoo.com/config/pwtoken_get?src=ymsgr&ts="
1767 "&login=%s&passwd=%s&chal=%s", user_encoded
, pass_encoded
,
1770 yahoo_http_get(yid
->yd
->client_id
, url
, NULL
, 1, 0,
1771 _yahoo_http_connected
, yid
);
1778 static void yahoo_process_auth(struct yahoo_input_data
*yid
,
1779 struct yahoo_packet
*pkt
)
1783 YList
*l
= pkt
->hash
;
1785 struct yahoo_data
*yd
= yid
->yd
;
1788 struct yahoo_pair
*pair
= l
->data
;
1790 switch (pair
->key
) {
1798 m
= atoi(pair
->value
);
1807 yd
->seed
= strdup(seed
);
1810 yahoo_auth_https(yd
);
1813 WARNING(("unknown auth type %d", m
));
1814 YAHOO_CALLBACK(ext_yahoo_login_response
) (yd
->client_id
,
1815 YAHOO_LOGIN_UNKNOWN
, NULL
);
1819 static void yahoo_send_auth(struct yahoo_data
*yd
)
1822 struct yahoo_packet
*packet
;
1824 unsigned char crypt_hash
[25];
1826 md5_byte_t result
[16];
1829 struct yahoo_input_data
*yid
=
1830 find_input_by_id_and_type(yd
->client_id
,
1831 YAHOO_CONNECTION_PAGER
);
1835 md5_append(&ctx
, (md5_byte_t
*)yd
->crumb
, strlen(yd
->crumb
));
1836 md5_append(&ctx
, (md5_byte_t
*)yd
->seed
, strlen(yd
->seed
));
1837 md5_finish(&ctx
, result
);
1839 to_y64(crypt_hash
, result
, 16);
1841 packet
= yahoo_packet_new(YAHOO_SERVICE_AUTHRESP
,
1842 yd
->initial_status
, yd
->session_id
);
1843 yahoo_packet_hash(packet
, 1, yd
->user
);
1844 yahoo_packet_hash(packet
, 0, yd
->user
);
1845 yahoo_packet_hash(packet
, 277, yd
->cookie_y
);
1846 yahoo_packet_hash(packet
, 278, yd
->cookie_t
);
1847 yahoo_packet_hash(packet
, 307, (char *)crypt_hash
);
1848 yahoo_packet_hash(packet
, 244, "4194239"); /* Rekkanoryo says this is the build number */
1849 yahoo_packet_hash(packet
, 2, yd
->user
);
1850 yahoo_packet_hash(packet
, 2, "1");
1851 yahoo_packet_hash(packet
, 59, yd
->cookie_b
);
1852 yahoo_packet_hash(packet
, 98, "us"); /* TODO Put country code */
1853 yahoo_packet_hash(packet
, 135, "9.0.0.2152");
1855 yahoo_send_packet(yid
, packet
, 0);
1857 yahoo_packet_free(packet
);
1860 static void yahoo_process_auth_resp(struct yahoo_input_data
*yid
,
1861 struct yahoo_packet
*pkt
)
1863 struct yahoo_data
*yd
= yid
->yd
;
1867 int login_status
= -1;
1871 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1872 struct yahoo_pair
*pair
= l
->data
;
1874 login_id
= pair
->value
;
1875 else if (pair
->key
== 1)
1876 handle
= pair
->value
;
1877 else if (pair
->key
== 20)
1879 else if (pair
->key
== 66)
1880 login_status
= atoi(pair
->value
);
1883 if (pkt
->status
== YPACKET_STATUS_DISCONNECTED
) {
1884 YAHOO_CALLBACK(ext_yahoo_login_response
) (yd
->client_id
,
1886 /* yahoo_logoff(yd->client_id); */
1890 static void yahoo_process_mail(struct yahoo_input_data
*yid
,
1891 struct yahoo_packet
*pkt
)
1893 struct yahoo_data
*yd
= yid
->yd
;
1900 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1901 struct yahoo_pair
*pair
= l
->data
;
1903 count
= strtol(pair
->value
, NULL
, 10);
1904 else if (pair
->key
== 43)
1906 else if (pair
->key
== 42)
1907 email
= pair
->value
;
1908 else if (pair
->key
== 18)
1911 LOG(("key: %d => value: %s", pair
->key
, pair
->value
));
1914 if (who
&& email
&& subj
) {
1916 snprintf(from
, sizeof(from
), "%s (%s)", who
, email
);
1917 YAHOO_CALLBACK(ext_yahoo_mail_notify
) (yd
->client_id
, from
,
1919 } else if (count
> 0)
1920 YAHOO_CALLBACK(ext_yahoo_mail_notify
) (yd
->client_id
, NULL
,
1924 static void yahoo_process_new_contact(struct yahoo_input_data
*yid
,
1925 struct yahoo_packet
*pkt
)
1927 struct yahoo_data
*yd
= yid
->yd
;
1934 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1935 struct yahoo_pair
*pair
= l
->data
;
1938 else if (pair
->key
== 5)
1940 else if (pair
->key
== 14)
1942 else if (pair
->key
== 13)
1943 online
= strtol(pair
->value
, NULL
, 10);
1946 if (pkt
->status
== 3) { // auth request
1947 YAHOO_CALLBACK(ext_yahoo_auth_request
) (yd
->client_id
, who
, msg
);
1949 else if (pkt
->status
== 1) {
1950 /* if (who && online == 1)
1951 YAHOO_CALLBACK(ext_yahoo_contact_added) (yd->client_id, me, who,
1953 else */if (online
== 2)
1954 YAHOO_CALLBACK(ext_yahoo_rejected
) (yd
->client_id
, who
, msg
);
1959 static void yahoo_process_contact(struct yahoo_input_data
*yid
,
1960 struct yahoo_packet
*pkt
)
1962 struct yahoo_data
*yd
= yid
->yd
;
1968 int state
= YAHOO_STATUS_AVAILABLE
;
1976 for (l
= pkt
->hash
; l
; l
= l
->next
) {
1977 struct yahoo_pair
*pair
= l
->data
;
1980 else if (pair
->key
== 3)
1982 else if (pair
->key
== 14)
1984 else if (pair
->key
== 7)
1986 else if (pair
->key
== 10)
1987 state
= strtol(pair
->value
, NULL
, 10);
1988 else if (pair
->key
== 15)
1989 tm
= strtol(pair
->value
, NULL
, 10);
1990 else if (pair
->key
== 13)
1991 online
= strtol(pair
->value
, NULL
, 10);
1992 else if (pair
->key
== 47)
1993 away
= strtol(pair
->value
, NULL
, 10);
1994 else if (pair
->key
== 137)
1995 idle
= strtol(pair
->value
, NULL
, 10);
1996 else if (pair
->key
== 60)
1997 mobile
= strtol(pair
->value
, NULL
, 10);
2002 YAHOO_CALLBACK(ext_yahoo_contact_added
) (yd
->client_id
, id
, who
,
2005 YAHOO_CALLBACK(ext_yahoo_status_changed
) (yd
->client_id
, name
,
2006 state
, msg
, away
, idle
, mobile
);
2007 else if (pkt
->status
== 0x07)
2008 YAHOO_CALLBACK(ext_yahoo_rejected
) (yd
->client_id
, who
, msg
);
2011 static void yahoo_process_buddyadd(struct yahoo_input_data
*yid
,
2012 struct yahoo_packet
*pkt
)
2014 struct yahoo_data
*yd
= yid
->yd
;
2020 struct yahoo_buddy
*bud
= NULL
;
2023 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2024 struct yahoo_pair
*pair
= l
->data
;
2029 if (pair
->key
== 65)
2030 where
= pair
->value
;
2031 if (pair
->key
== 66)
2032 status
= strtol(pair
->value
, NULL
, 10);
2040 bud
= y_new0(struct yahoo_buddy
, 1);
2041 bud
->id
= strdup(who
);
2042 bud
->group
= strdup(where
);
2043 bud
->real_name
= NULL
;
2045 yd
->buddies
= y_list_append(yd
->buddies
, bud
);
2047 /* A non-zero status (i've seen 2) seems to mean the buddy is already
2048 * added and is online */
2050 LOG(("Setting online see packet for info"));
2051 yahoo_dump_unhandled(pkt
);
2052 YAHOO_CALLBACK(ext_yahoo_status_changed
) (yd
->client_id
, who
,
2053 YAHOO_STATUS_AVAILABLE
, NULL
, 0, 0, 0);
2057 static void yahoo_process_buddydel(struct yahoo_input_data
*yid
,
2058 struct yahoo_packet
*pkt
)
2060 struct yahoo_data
*yd
= yid
->yd
;
2065 struct yahoo_buddy
*bud
;
2070 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2071 struct yahoo_pair
*pair
= l
->data
;
2074 else if (pair
->key
== 7)
2076 else if (pair
->key
== 65)
2077 where
= pair
->value
;
2078 else if (pair
->key
== 66)
2079 unk_66
= strtol(pair
->value
, NULL
, 10);
2081 DEBUG_MSG(("unknown key: %d = %s", pair
->key
,
2088 bud
= y_new0(struct yahoo_buddy
, 1);
2089 bud
->id
= strdup(who
);
2090 bud
->group
= strdup(where
);
2092 buddy
= y_list_find_custom(yd
->buddies
, bud
, is_same_bud
);
2100 yd
->buddies
= y_list_remove_link(yd
->buddies
, buddy
);
2101 y_list_free_1(buddy
);
2105 FREE(bud
->real_name
);
2112 static void yahoo_process_ignore(struct yahoo_input_data
*yid
,
2113 struct yahoo_packet
*pkt
)
2121 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2122 struct yahoo_pair
*pair
= l
->data
;
2127 if (pair
->key
== 13) /* 1 == ignore, 2 == unignore */
2128 un_ignore
= strtol(pair
->value
, NULL
, 10);
2129 if (pair
->key
== 66)
2130 status
= strtol(pair
->value
, NULL
, 10);
2136 * 2 - already in ignore list, could not add
2137 * 3 - not in ignore list, could not delete
2138 * 12 - is a buddy, could not add
2142 YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, who, 0, status);
2146 static void yahoo_process_voicechat(struct yahoo_input_data
*yid
,
2147 struct yahoo_packet
*pkt
)
2152 char *voice_room
= NULL
;
2155 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2156 struct yahoo_pair
*pair
= l
->data
;
2161 if (pair
->key
== 13)
2162 voice_room
= pair
->value
;
2163 if (pair
->key
== 57)
2167 NOTICE(("got voice chat invite from %s in %s to identity %s", who
, room
,
2170 * send: s:0 1:me 5:who 57:room 13:1
2171 * ???? s:4 5:who 10:99 19:-1615114531
2172 * gotr: s:4 5:who 10:99 19:-1615114615
2173 * ???? s:1 5:me 4:who 57:room 13:3room
2174 * got: s:1 5:me 4:who 57:room 13:1room
2175 * rej: s:0 1:me 5:who 57:room 13:3
2176 * rejr: s:4 5:who 10:99 19:-1617114599
2180 static void yahoo_process_ping(struct yahoo_input_data
*yid
,
2181 struct yahoo_packet
*pkt
)
2183 char *errormsg
= NULL
;
2186 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2187 struct yahoo_pair
*pair
= l
->data
;
2188 if (pair
->key
== 16)
2189 errormsg
= pair
->value
;
2192 NOTICE(("got ping packet"));
2193 YAHOO_CALLBACK(ext_yahoo_got_ping
) (yid
->yd
->client_id
, errormsg
);
2196 static void yahoo_process_buddy_change_group(struct yahoo_input_data
*yid
,
2197 struct yahoo_packet
*pkt
)
2202 char *old_group
= NULL
;
2203 char *new_group
= NULL
;
2205 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2206 struct yahoo_pair
*pair
= l
->data
;
2211 if (pair
->key
== 224)
2212 old_group
= pair
->value
;
2213 if (pair
->key
== 264)
2214 new_group
= pair
->value
;
2217 YAHOO_CALLBACK(ext_yahoo_got_buddy_change_group
) (yid
->yd
->client_id
,
2218 me
, who
, old_group
, new_group
);
2221 static void _yahoo_webcam_get_server_connected(void *fd
, int error
, void *d
)
2223 struct yahoo_input_data
*yid
= d
;
2224 char *who
= yid
->wcm
->user
;
2226 char *packet
= NULL
;
2227 unsigned char magic_nr
[] = { 0, 1, 0 };
2228 unsigned char header_len
= 8;
2229 unsigned int len
= 0;
2230 unsigned int pos
= 0;
2239 inputs
= y_list_prepend(inputs
, yid
);
2241 /* send initial packet */
2243 data
= strdup("<RVWCFG>");
2245 data
= strdup("<RUPCFG>");
2246 yahoo_add_to_send_queue(yid
, data
, strlen(data
));
2251 data
= strdup("g=");
2252 data
= y_string_append(data
, who
);
2253 data
= y_string_append(data
, "\r\n");
2255 data
= strdup("f=1\r\n");
2258 packet
= y_new0(char, header_len
+ len
);
2259 packet
[pos
++] = header_len
;
2260 memcpy(packet
+ pos
, magic_nr
, sizeof(magic_nr
));
2261 pos
+= sizeof(magic_nr
);
2262 pos
+= yahoo_put32(packet
+ pos
, len
);
2263 memcpy(packet
+ pos
, data
, len
);
2265 yahoo_add_to_send_queue(yid
, packet
, pos
);
2270 YAHOO_CALLBACK(ext_yahoo_add_handler
) (yid
->yd
->client_id
, fd
,
2271 YAHOO_INPUT_READ
, yid
);
2274 static void yahoo_webcam_get_server(struct yahoo_input_data
*y
, char *who
,
2277 struct yahoo_input_data
*yid
= y_new0(struct yahoo_input_data
, 1);
2278 struct yahoo_server_settings
*yss
= y
->yd
->server_settings
;
2280 yid
->type
= YAHOO_CONNECTION_WEBCAM_MASTER
;
2282 yid
->wcm
= y_new0(struct yahoo_webcam
, 1);
2283 yid
->wcm
->user
= who
? strdup(who
) : NULL
;
2284 yid
->wcm
->direction
= who
? YAHOO_WEBCAM_DOWNLOAD
: YAHOO_WEBCAM_UPLOAD
;
2285 yid
->wcm
->key
= strdup(key
);
2287 YAHOO_CALLBACK(ext_yahoo_connect_async
) (yid
->yd
->client_id
,
2288 yss
->webcam_host
, yss
->webcam_port
,
2289 _yahoo_webcam_get_server_connected
, yid
, 0);
2293 static YList
*webcam_queue
= NULL
;
2294 static void yahoo_process_webcam_key(struct yahoo_input_data
*yid
,
2295 struct yahoo_packet
*pkt
)
2302 yahoo_dump_unhandled(pkt
);
2303 for (l
= pkt
->hash
; l
; l
= l
->next
) {
2304 struct yahoo_pair
*pair
= l
->data
;
2307 if (pair
->key
== 61)
2315 webcam_queue
= y_list_remove_link(webcam_queue
, webcam_queue
);
2317 yahoo_webcam_get_server(yid
, who
, key
);
2321 static void yahoo_packet_process(struct yahoo_input_data
*yid
,
2322 struct yahoo_packet
*pkt
)
2324 DEBUG_MSG(("yahoo_packet_process: 0x%02x", pkt
->service
));
2325 switch (pkt
->service
) {
2326 case YAHOO_SERVICE_USERSTAT
:
2327 case YAHOO_SERVICE_LOGON
:
2328 case YAHOO_SERVICE_LOGOFF
:
2329 case YAHOO_SERVICE_ISAWAY
:
2330 case YAHOO_SERVICE_ISBACK
:
2331 case YAHOO_SERVICE_GAMELOGON
:
2332 case YAHOO_SERVICE_GAMELOGOFF
:
2333 case YAHOO_SERVICE_IDACT
:
2334 case YAHOO_SERVICE_IDDEACT
:
2335 case YAHOO_SERVICE_Y6_STATUS_UPDATE
:
2336 case YAHOO_SERVICE_Y8_STATUS
:
2337 yahoo_process_status(yid
, pkt
);
2339 case YAHOO_SERVICE_NOTIFY
:
2340 yahoo_process_notify(yid
, pkt
);
2342 case YAHOO_SERVICE_MESSAGE
:
2343 case YAHOO_SERVICE_GAMEMSG
:
2344 case YAHOO_SERVICE_SYSMESSAGE
:
2345 yahoo_process_message(yid
, pkt
);
2347 case YAHOO_SERVICE_NEWMAIL
:
2348 yahoo_process_mail(yid
, pkt
);
2350 case YAHOO_SERVICE_Y7_AUTHORIZATION
:
2351 yahoo_process_new_contact(yid
, pkt
);
2353 case YAHOO_SERVICE_NEWCONTACT
:
2354 yahoo_process_contact(yid
, pkt
);
2356 case YAHOO_SERVICE_LIST
:
2357 yahoo_process_list(yid
, pkt
);
2359 case YAHOO_SERVICE_VERIFY
:
2360 yahoo_process_verify(yid
, pkt
);
2362 case YAHOO_SERVICE_AUTH
:
2363 yahoo_process_auth(yid
, pkt
);
2365 case YAHOO_SERVICE_AUTHRESP
:
2366 yahoo_process_auth_resp(yid
, pkt
);
2368 case YAHOO_SERVICE_CONFINVITE
:
2369 case YAHOO_SERVICE_CONFADDINVITE
:
2370 case YAHOO_SERVICE_CONFDECLINE
:
2371 case YAHOO_SERVICE_CONFLOGON
:
2372 case YAHOO_SERVICE_CONFLOGOFF
:
2373 case YAHOO_SERVICE_CONFMSG
:
2374 yahoo_process_conference(yid
, pkt
);
2376 case YAHOO_SERVICE_CHATONLINE
:
2377 case YAHOO_SERVICE_CHATGOTO
:
2378 case YAHOO_SERVICE_CHATJOIN
:
2379 case YAHOO_SERVICE_CHATLEAVE
:
2380 case YAHOO_SERVICE_CHATEXIT
:
2381 case YAHOO_SERVICE_CHATLOGOUT
:
2382 case YAHOO_SERVICE_CHATPING
:
2383 case YAHOO_SERVICE_COMMENT
:
2384 yahoo_process_chat(yid
, pkt
);
2386 case YAHOO_SERVICE_P2PFILEXFER
:
2387 case YAHOO_SERVICE_Y7_FILETRANSFER
:
2388 yahoo_process_filetransfer(yid
, pkt
);
2390 case YAHOO_SERVICE_Y7_FILETRANSFERINFO
:
2391 yahoo_process_filetransferinfo(yid
, pkt
);
2393 case YAHOO_SERVICE_Y7_FILETRANSFERACCEPT
:
2394 yahoo_process_filetransferaccept(yid
, pkt
);
2396 case YAHOO_SERVICE_ADDBUDDY
:
2397 yahoo_process_buddyadd(yid
, pkt
);
2399 case YAHOO_SERVICE_REMBUDDY
:
2400 yahoo_process_buddydel(yid
, pkt
);
2402 case YAHOO_SERVICE_IGNORECONTACT
:
2403 yahoo_process_ignore(yid
, pkt
);
2405 case YAHOO_SERVICE_VOICECHAT
:
2406 yahoo_process_voicechat(yid
, pkt
);
2408 case YAHOO_SERVICE_WEBCAM
:
2409 yahoo_process_webcam_key(yid
, pkt
);
2411 case YAHOO_SERVICE_PING
:
2412 yahoo_process_ping(yid
, pkt
);
2414 case YAHOO_SERVICE_Y7_CHANGE_GROUP
:
2415 yahoo_process_buddy_change_group(yid
, pkt
);
2417 case YAHOO_SERVICE_IDLE
:
2418 case YAHOO_SERVICE_MAILSTAT
:
2419 case YAHOO_SERVICE_CHATINVITE
:
2420 case YAHOO_SERVICE_CALENDAR
:
2421 case YAHOO_SERVICE_NEWPERSONALMAIL
:
2422 case YAHOO_SERVICE_ADDIDENT
:
2423 case YAHOO_SERVICE_ADDIGNORE
:
2424 case YAHOO_SERVICE_GOTGROUPRENAME
:
2425 case YAHOO_SERVICE_GROUPRENAME
:
2426 case YAHOO_SERVICE_PASSTHROUGH2
:
2427 case YAHOO_SERVICE_CHATLOGON
:
2428 case YAHOO_SERVICE_CHATLOGOFF
:
2429 case YAHOO_SERVICE_CHATMSG
:
2430 case YAHOO_SERVICE_REJECTCONTACT
:
2431 case YAHOO_SERVICE_PEERTOPEER
:
2432 WARNING(("unhandled service 0x%02x", pkt
->service
));
2433 yahoo_dump_unhandled(pkt
);
2435 case YAHOO_SERVICE_PICTURE
:
2436 yahoo_process_picture(yid
, pkt
);
2438 case YAHOO_SERVICE_PICTURE_CHECKSUM
:
2439 yahoo_process_picture_checksum(yid
, pkt
);
2441 case YAHOO_SERVICE_PICTURE_UPLOAD
:
2442 yahoo_process_picture_upload(yid
, pkt
);
2444 case YAHOO_SERVICE_Y8_LIST
: /* Buddy List */
2445 yahoo_process_buddy_list(yid
, pkt
);
2448 WARNING(("unknown service 0x%02x", pkt
->service
));
2449 yahoo_dump_unhandled(pkt
);
2454 static struct yahoo_packet
*yahoo_getdata(struct yahoo_input_data
*yid
)
2456 struct yahoo_packet
*pkt
;
2457 struct yahoo_data
*yd
= yid
->yd
;
2464 DEBUG_MSG(("rxlen is %d", yid
->rxlen
));
2465 if (yid
->rxlen
< YAHOO_PACKET_HDRLEN
) {
2466 DEBUG_MSG(("len < YAHOO_PACKET_HDRLEN"));
2470 pos
+= 4; /* YMSG */
2474 pktlen
= yahoo_get16(yid
->rxqueue
+ pos
);
2476 DEBUG_MSG(("%d bytes to read, rxlen is %d", pktlen
, yid
->rxlen
));
2478 if (yid
->rxlen
< (YAHOO_PACKET_HDRLEN
+ pktlen
)) {
2479 DEBUG_MSG(("len < YAHOO_PACKET_HDRLEN + pktlen"));
2483 LOG(("reading packet"));
2484 yahoo_packet_dump(yid
->rxqueue
, YAHOO_PACKET_HDRLEN
+ pktlen
);
2486 pkt
= yahoo_packet_new(0, 0, 0);
2488 pkt
->service
= yahoo_get16(yid
->rxqueue
+ pos
);
2490 pkt
->status
= yahoo_get32(yid
->rxqueue
+ pos
);
2492 DEBUG_MSG(("Yahoo Service: 0x%02x Status: %d", pkt
->service
,
2494 pkt
->id
= yahoo_get32(yid
->rxqueue
+ pos
);
2497 yd
->session_id
= pkt
->id
;
2499 yahoo_packet_read(pkt
, yid
->rxqueue
+ pos
, pktlen
);
2501 yid
->rxlen
-= YAHOO_PACKET_HDRLEN
+ pktlen
;
2502 DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
2503 if (yid
->rxlen
> 0) {
2504 unsigned char *tmp
= y_memdup(yid
->rxqueue
+ YAHOO_PACKET_HDRLEN
2505 + pktlen
, yid
->rxlen
);
2508 DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid
->rxlen
,
2511 DEBUG_MSG(("freed rxqueue == %p", yid
->rxqueue
));
2518 static struct yab
*yahoo_yab_read(unsigned char *d
, int len
)
2521 char *data
= (char *)d
;
2522 struct yab
*yab
= NULL
;
2526 DEBUG_MSG(("Got yab: %s", data
));
2527 st
= en
= strstr(data
, "e0=\"");
2529 yab
= y_new0(struct yab
, 1);
2531 st
+= strlen("e0=\"");
2532 en
= strchr(st
, '"');
2534 yab
->email
= yahoo_xmldecode(st
);
2540 st
= strstr(en
, "id=\"");
2542 st
+= strlen("id=\"");
2543 en
= strchr(st
, '"');
2545 yab
->yid
= atoi(yahoo_xmldecode(st
));
2548 st
= strstr(en
, "fn=\"");
2550 st
+= strlen("fn=\"");
2551 en
= strchr(st
, '"');
2553 yab
->fname
= yahoo_xmldecode(st
);
2556 st
= strstr(en
, "ln=\"");
2558 st
+= strlen("ln=\"");
2559 en
= strchr(st
, '"');
2561 yab
->lname
= yahoo_xmldecode(st
);
2564 st
= strstr(en
, "nn=\"");
2566 st
+= strlen("nn=\"");
2567 en
= strchr(st
, '"');
2569 yab
->nname
= yahoo_xmldecode(st
);
2572 st
= strstr(en
, "yi=\"");
2574 st
+= strlen("yi=\"");
2575 en
= strchr(st
, '"');
2577 yab
->id
= yahoo_xmldecode(st
);
2580 st
= strstr(en
, "hphone=\"");
2582 st
+= strlen("hphone=\"");
2583 en
= strchr(st
, '"');
2585 yab
->hphone
= yahoo_xmldecode(st
);
2588 st
= strstr(en
, "wphone=\"");
2590 st
+= strlen("wphone=\"");
2591 en
= strchr(st
, '"');
2593 yab
->wphone
= yahoo_xmldecode(st
);
2596 st
= strstr(en
, "mphone=\"");
2598 st
+= strlen("mphone=\"");
2599 en
= strchr(st
, '"');
2601 yab
->mphone
= yahoo_xmldecode(st
);
2604 st
= strstr(en
, "dbid=\"");
2606 st
+= strlen("dbid=\"");
2607 en
= strchr(st
, '"');
2609 yab
->dbid
= atoi(st
);
2615 static struct yab
*yahoo_getyab(struct yahoo_input_data
*yid
)
2617 struct yab
*yab
= NULL
;
2618 int pos
= 0, end
= 0;
2619 struct yahoo_data
*yd
= yid
->yd
;
2625 DEBUG_MSG(("rxlen is %d", yid
->rxlen
));
2627 if (yid
->rxlen
<= strlen("<ct"))
2630 /* start with <ct */
2631 while (pos
< yid
->rxlen
- strlen("<ct") + 1
2632 && memcmp(yid
->rxqueue
+ pos
, "<ct", strlen("<ct")))
2635 if (pos
>= yid
->rxlen
- 1)
2640 while (end
< yid
->rxlen
- strlen(">")
2641 && memcmp(yid
->rxqueue
+ end
, ">", strlen(">")))
2644 if (end
>= yid
->rxlen
- 1)
2647 yab
= yahoo_yab_read(yid
->rxqueue
+ pos
, end
+ 2 - pos
);
2649 yid
->rxlen
-= end
+ 1;
2650 DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid
->rxlen
,
2652 if (yid
->rxlen
> 0) {
2653 unsigned char *tmp
=
2654 y_memdup(yid
->rxqueue
+ end
+ 1, yid
->rxlen
);
2657 DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid
->rxlen
,
2660 DEBUG_MSG(("freed rxqueue == %p", yid
->rxqueue
));
2664 } while (!yab
&& end
< yid
->rxlen
- 1);
2669 static char *yahoo_getwebcam_master(struct yahoo_input_data
*yid
)
2671 unsigned int pos
= 0;
2672 unsigned int len
= 0;
2673 unsigned int status
= 0;
2674 char *server
= NULL
;
2675 struct yahoo_data
*yd
= yid
->yd
;
2680 DEBUG_MSG(("rxlen is %d", yid
->rxlen
));
2682 len
= yid
->rxqueue
[pos
++];
2683 if (yid
->rxlen
< len
)
2686 /* extract status (0 = ok, 6 = webcam not online) */
2687 status
= yid
->rxqueue
[pos
++];
2690 pos
+= 2; /* skip next 2 bytes */
2691 server
= y_memdup(yid
->rxqueue
+ pos
, 16);
2693 } else if (status
== 6) {
2694 YAHOO_CALLBACK(ext_yahoo_webcam_closed
)
2695 (yd
->client_id
, yid
->wcm
->user
, 4);
2698 /* skip rest of the data */
2701 DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
2702 if (yid
->rxlen
> 0) {
2703 unsigned char *tmp
= y_memdup(yid
->rxqueue
+ pos
, yid
->rxlen
);
2706 DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid
->rxlen
,
2709 DEBUG_MSG(("freed rxqueue == %p", yid
->rxqueue
));
2716 static int yahoo_get_webcam_data(struct yahoo_input_data
*yid
)
2718 unsigned char reason
= 0;
2719 unsigned int pos
= 0;
2720 unsigned int begin
= 0;
2721 unsigned int end
= 0;
2722 unsigned int closed
= 0;
2723 unsigned char header_len
= 0;
2726 struct yahoo_data
*yd
= yid
->yd
;
2731 if (!yid
->wcm
|| !yid
->wcd
|| !yid
->rxlen
)
2734 DEBUG_MSG(("rxlen is %d", yid
->rxlen
));
2736 /* if we are not reading part of image then read header */
2737 if (!yid
->wcd
->to_read
) {
2738 header_len
= yid
->rxqueue
[pos
++];
2739 yid
->wcd
->packet_type
= 0;
2741 if (yid
->rxlen
< header_len
)
2744 if (header_len
>= 8) {
2745 reason
= yid
->rxqueue
[pos
++];
2746 /* next 2 bytes should always be 05 00 */
2748 yid
->wcd
->data_size
= yahoo_get32(yid
->rxqueue
+ pos
);
2750 yid
->wcd
->to_read
= yid
->wcd
->data_size
;
2752 if (header_len
>= 13) {
2753 yid
->wcd
->packet_type
= yid
->rxqueue
[pos
++];
2754 yid
->wcd
->timestamp
= yahoo_get32(yid
->rxqueue
+ pos
);
2758 /* skip rest of header */
2763 pos
+= yid
->wcd
->to_read
;
2764 if (pos
> yid
->rxlen
)
2767 /* if it is not an image then make sure we have the whole packet */
2768 if (yid
->wcd
->packet_type
!= 0x02) {
2769 if ((pos
- begin
) != yid
->wcd
->data_size
) {
2770 yid
->wcd
->to_read
= 0;
2773 yahoo_packet_dump(yid
->rxqueue
+ begin
, pos
- begin
);
2777 DEBUG_MSG(("packet type %.2X, data length %d", yid
->wcd
->packet_type
,
2778 yid
->wcd
->data_size
));
2780 /* find out what kind of packet we got */
2781 switch (yid
->wcd
->packet_type
) {
2783 /* user requests to view webcam (uploading) */
2784 if (yid
->wcd
->data_size
&&
2785 yid
->wcm
->direction
== YAHOO_WEBCAM_UPLOAD
) {
2787 while (end
<= yid
->rxlen
&& yid
->rxqueue
[end
++] != 13) ;
2789 who
= y_memdup(yid
->rxqueue
+ begin
,
2791 who
[end
- begin
- 1] = 0;
2792 YAHOO_CALLBACK(ext_yahoo_webcam_viewer
) (yd
->
2793 client_id
, who
+ 2, 2);
2798 if (yid
->wcm
->direction
== YAHOO_WEBCAM_DOWNLOAD
) {
2799 /* timestamp/status field */
2800 /* 0 = declined viewing permission */
2801 /* 1 = accepted viewing permission */
2802 if (yid
->wcd
->timestamp
== 0) {
2803 YAHOO_CALLBACK(ext_yahoo_webcam_closed
) (yd
->
2804 client_id
, yid
->wcm
->user
, 3);
2808 case 0x01: /* status packets?? */
2809 /* timestamp contains status info */
2810 /* 00 00 00 01 = we have data?? */
2812 case 0x02: /* image data */
2813 YAHOO_CALLBACK(ext_yahoo_got_webcam_image
) (yd
->client_id
,
2814 yid
->wcm
->user
, yid
->rxqueue
+ begin
,
2815 yid
->wcd
->data_size
, pos
- begin
, yid
->wcd
->timestamp
);
2817 case 0x05: /* response packets when uploading */
2818 if (!yid
->wcd
->data_size
) {
2819 YAHOO_CALLBACK(ext_yahoo_webcam_data_request
) (yd
->
2820 client_id
, yid
->wcd
->timestamp
);
2823 case 0x07: /* connection is closing */
2825 case 0x01: /* user closed connection */
2828 case 0x0F: /* user cancelled permission */
2832 YAHOO_CALLBACK(ext_yahoo_webcam_closed
) (yd
->client_id
,
2833 yid
->wcm
->user
, closed
);
2835 case 0x0C: /* user connected */
2836 case 0x0D: /* user disconnected */
2837 if (yid
->wcd
->data_size
) {
2838 who
= y_memdup(yid
->rxqueue
+ begin
, pos
- begin
+ 1);
2839 who
[pos
- begin
] = 0;
2840 if (yid
->wcd
->packet_type
== 0x0C)
2844 YAHOO_CALLBACK(ext_yahoo_webcam_viewer
) (yd
->client_id
,
2849 case 0x13: /* user data */
2850 /* i=user_ip (ip of the user we are viewing) */
2851 /* j=user_ext_ip (external ip of the user we */
2857 yid
->wcd
->to_read
-= pos
- begin
;
2860 DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid
->rxlen
, yid
->rxqueue
));
2861 if (yid
->rxlen
> 0) {
2862 unsigned char *tmp
= y_memdup(yid
->rxqueue
+ pos
, yid
->rxlen
);
2865 DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid
->rxlen
,
2868 DEBUG_MSG(("freed rxqueue == %p", yid
->rxqueue
));
2872 /* If we read a complete packet return success */
2873 if (!yid
->wcd
->to_read
)
2879 int yahoo_write_ready(int id
, void *fd
, void *data
)
2881 struct yahoo_input_data
*yid
= data
;
2883 struct data_queue
*tx
;
2885 LOG(("write callback: id=%d fd=%p data=%p", id
, fd
, data
));
2886 if (!yid
|| !yid
->txqueues
)
2889 tx
= yid
->txqueues
->data
;
2890 LOG(("writing %d bytes", tx
->len
));
2891 len
= yahoo_send_data(fd
, tx
->queue
, MIN(1024, tx
->len
));
2893 if (len
== -1 && errno
== EAGAIN
)
2898 DEBUG_MSG(("len == %d (<= 0)", len
));
2899 while (yid
->txqueues
) {
2900 YList
*l
= yid
->txqueues
;
2905 y_list_remove_link(yid
->txqueues
,
2909 LOG(("yahoo_write_ready(%d, %p) len < 0", id
, fd
));
2910 YAHOO_CALLBACK(ext_yahoo_remove_handler
) (id
, yid
->write_tag
);
2918 unsigned char *tmp
= y_memdup(tx
->queue
+ len
, tx
->len
);
2922 YList
*l
= yid
->txqueues
;
2926 y_list_remove_link(yid
->txqueues
, yid
->txqueues
);
2930 LOG(("yahoo_write_ready(%d, %d) !yxqueues", id, fd));
2932 if (!yid
->txqueues
) {
2933 LOG(("yahoo_write_ready(%d, %p) !txqueues", id
, fd
));
2934 YAHOO_CALLBACK(ext_yahoo_remove_handler
) (id
,
2943 static void yahoo_process_pager_connection(struct yahoo_input_data
*yid
,
2946 struct yahoo_packet
*pkt
;
2947 struct yahoo_data
*yd
= yid
->yd
;
2948 int id
= yd
->client_id
;
2953 while (find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
)
2954 && (pkt
= yahoo_getdata(yid
)) != NULL
) {
2956 yahoo_packet_process(yid
, pkt
);
2958 yahoo_packet_free(pkt
);
2962 static void yahoo_process_chatcat_connection(struct yahoo_input_data
*yid
,
2968 if (strstr((char *)yid
->rxqueue
+ (yid
->rxlen
- 20), "</content>")) {
2969 YAHOO_CALLBACK(ext_yahoo_chat_cat_xml
) (yid
->yd
->client_id
,
2970 (char *)yid
->rxqueue
);
2974 static void yahoo_process_yab_connection(struct yahoo_input_data
*yid
, int over
)
2976 struct yahoo_data
*yd
= yid
->yd
;
2980 int id
= yd
->client_id
;
2983 LOG(("Got data for YAB"));
2988 while (find_input_by_id_and_type(id
, YAHOO_CONNECTION_YAB
)
2989 && (yab
= yahoo_getyab(yid
)) != NULL
) {
2995 for (buds
= yd
->buddies
; buds
; buds
= buds
->next
) {
2996 struct yahoo_buddy
*bud
= buds
->data
;
2997 if (!strcmp(bud
->id
, yab
->id
)) {
2999 bud
->yab_entry
= yab
;
3001 bud
->real_name
= strdup(yab
->nname
);
3002 } else if (yab
->fname
&& yab
->lname
) {
3003 bud
->real_name
= y_new0(char,
3004 strlen(yab
->fname
) +
3005 strlen(yab
->lname
) + 2);
3006 sprintf(bud
->real_name
, "%s %s",
3007 yab
->fname
, yab
->lname
);
3008 } else if (yab
->fname
) {
3009 bud
->real_name
= strdup(yab
->fname
);
3030 YAHOO_CALLBACK(ext_yahoo_got_buddies
) (yd
->client_id
,
3034 static void yahoo_process_search_connection(struct yahoo_input_data
*yid
,
3037 struct yahoo_found_contact
*yct
= NULL
;
3038 char *p
= (char *)yid
->rxqueue
, *np
, *cp
;
3040 int start
= 0, found
= 0, total
= 0;
3041 YList
*contacts
= NULL
;
3042 struct yahoo_input_data
*pyid
=
3043 find_input_by_id_and_type(yid
->yd
->client_id
,
3044 YAHOO_CONNECTION_PAGER
);
3049 if (p
&& (p
= strstr(p
, "\r\n\r\n"))) {
3052 for (k
= 0; (p
= strchr(p
, 4)) && (k
< 4); k
++) {
3057 found
= pyid
->ys
->lsearch_nfound
= n
;
3060 start
= pyid
->ys
->lsearch_nstart
= n
;
3063 total
= pyid
->ys
->lsearch_ntotal
= n
;
3084 && y_list_length(contacts
) < total
) {
3085 yct
= y_new0(struct yahoo_found_contact
,
3087 contacts
= y_list_append(contacts
, yct
);
3094 yct
->online
= !strcmp(cp
, "2") ? 1 : 0;
3100 yct
->age
= atoi(cp
);
3103 /* not worth the context switch for strcmp */
3104 if (cp
[0] != '\005' || cp
[1] != '\000')
3112 YAHOO_CALLBACK(ext_yahoo_got_search_result
) (yid
->yd
->client_id
, found
,
3113 start
, total
, contacts
);
3116 YList
*node
= contacts
;
3117 contacts
= y_list_remove_link(contacts
, node
);
3119 y_list_free_1(node
);
3123 static void _yahoo_webcam_connected(void *fd
, int error
, void *d
)
3125 struct yahoo_input_data
*yid
= d
;
3126 struct yahoo_webcam
*wcm
= yid
->wcm
;
3127 struct yahoo_data
*yd
= yid
->yd
;
3128 char conn_type
[100];
3130 char *packet
= NULL
;
3131 unsigned char magic_nr
[] = { 1, 0, 0, 0, 1 };
3132 unsigned header_len
= 0;
3133 unsigned int len
= 0;
3134 unsigned int pos
= 0;
3142 inputs
= y_list_prepend(inputs
, yid
);
3145 /* send initial packet */
3146 switch (wcm
->direction
) {
3147 case YAHOO_WEBCAM_DOWNLOAD
:
3148 data
= strdup("<REQIMG>");
3150 case YAHOO_WEBCAM_UPLOAD
:
3151 data
= strdup("<SNDIMG>");
3156 yahoo_add_to_send_queue(yid
, data
, strlen(data
));
3160 switch (wcm
->direction
) {
3161 case YAHOO_WEBCAM_DOWNLOAD
:
3163 data
= strdup("a=2\r\nc=us\r\ne=21\r\nu=");
3164 data
= y_string_append(data
, yd
->user
);
3165 data
= y_string_append(data
, "\r\nt=");
3166 data
= y_string_append(data
, wcm
->key
);
3167 data
= y_string_append(data
, "\r\ni=");
3168 data
= y_string_append(data
, wcm
->my_ip
);
3169 data
= y_string_append(data
, "\r\ng=");
3170 data
= y_string_append(data
, wcm
->user
);
3171 data
= y_string_append(data
, "\r\no=w-2-5-1\r\np=");
3172 snprintf(conn_type
, sizeof(conn_type
), "%d", wcm
->conn_type
);
3173 data
= y_string_append(data
, conn_type
);
3174 data
= y_string_append(data
, "\r\n");
3176 case YAHOO_WEBCAM_UPLOAD
:
3178 data
= strdup("a=2\r\nc=us\r\nu=");
3179 data
= y_string_append(data
, yd
->user
);
3180 data
= y_string_append(data
, "\r\nt=");
3181 data
= y_string_append(data
, wcm
->key
);
3182 data
= y_string_append(data
, "\r\ni=");
3183 data
= y_string_append(data
, wcm
->my_ip
);
3184 data
= y_string_append(data
, "\r\no=w-2-5-1\r\np=");
3185 snprintf(conn_type
, sizeof(conn_type
), "%d", wcm
->conn_type
);
3186 data
= y_string_append(data
, conn_type
);
3187 data
= y_string_append(data
, "\r\nb=");
3188 data
= y_string_append(data
, wcm
->description
);
3189 data
= y_string_append(data
, "\r\n");
3194 packet
= y_new0(char, header_len
+ len
);
3195 packet
[pos
++] = header_len
;
3197 switch (wcm
->direction
) {
3198 case YAHOO_WEBCAM_DOWNLOAD
:
3202 case YAHOO_WEBCAM_UPLOAD
:
3208 pos
+= yahoo_put32(packet
+ pos
, len
);
3209 if (wcm
->direction
== YAHOO_WEBCAM_UPLOAD
) {
3210 memcpy(packet
+ pos
, magic_nr
, sizeof(magic_nr
));
3211 pos
+= sizeof(magic_nr
);
3213 memcpy(packet
+ pos
, data
, len
);
3214 yahoo_add_to_send_queue(yid
, packet
, header_len
+ len
);
3219 YAHOO_CALLBACK(ext_yahoo_add_handler
) (yid
->yd
->client_id
,
3220 yid
->fd
, YAHOO_INPUT_READ
, yid
);
3223 static void yahoo_webcam_connect(struct yahoo_input_data
*y
)
3225 struct yahoo_webcam
*wcm
= y
->wcm
;
3226 struct yahoo_input_data
*yid
;
3227 struct yahoo_server_settings
*yss
;
3229 if (!wcm
|| !wcm
->server
|| !wcm
->key
)
3232 yid
= y_new0(struct yahoo_input_data
, 1);
3233 yid
->type
= YAHOO_CONNECTION_WEBCAM
;
3236 /* copy webcam data to new connection */
3240 yss
= y
->yd
->server_settings
;
3242 yid
->wcd
= y_new0(struct yahoo_webcam_data
, 1);
3244 LOG(("Connecting to: %s:%d", wcm
->server
, wcm
->port
));
3245 YAHOO_CALLBACK(ext_yahoo_connect_async
) (y
->yd
->client_id
, wcm
->server
,
3246 wcm
->port
, _yahoo_webcam_connected
, yid
, 0);
3250 static void yahoo_process_webcam_master_connection(struct yahoo_input_data
*yid
,
3254 struct yahoo_server_settings
*yss
;
3259 server
= yahoo_getwebcam_master(yid
);
3262 yss
= yid
->yd
->server_settings
;
3263 yid
->wcm
->server
= strdup(server
);
3264 yid
->wcm
->port
= yss
->webcam_port
;
3265 yid
->wcm
->conn_type
= yss
->conn_type
;
3266 yid
->wcm
->my_ip
= strdup(yss
->local_host
);
3267 if (yid
->wcm
->direction
== YAHOO_WEBCAM_UPLOAD
)
3268 yid
->wcm
->description
= strdup(yss
->webcam_description
);
3269 yahoo_webcam_connect(yid
);
3274 static void yahoo_process_webcam_connection(struct yahoo_input_data
*yid
,
3277 int id
= yid
->yd
->client_id
;
3283 /* as long as we still have packets available keep processing them */
3284 while (find_input_by_id_and_fd(id
, fd
)
3285 && yahoo_get_webcam_data(yid
) == 1) ;
3288 static void yahoo_process_auth_connection(struct yahoo_input_data
*yid
,
3298 /* Wait till we get everything */
3302 if (!yid
->rxqueue
) {
3303 LOG(("Whoops! Closed it just like that??\n"));
3304 YAHOO_CALLBACK(ext_yahoo_login_response
) (yid
->yd
->client_id
,
3305 YAHOO_LOGIN_UNKNOWN
, NULL
);
3309 token
= strstr((char *)yid
->rxqueue
, "\r\n\r\n");
3312 LOG(("Could not find anything after the HTTP headers? huh?\n"));
3313 YAHOO_CALLBACK(ext_yahoo_login_response
) (yid
->yd
->client_id
,
3314 YAHOO_LOGIN_UNKNOWN
, NULL
);
3321 /* Skip the first number */
3322 token
= strstr(token
, "\r\n");
3325 LOG(("Well I tried to skip the first number and found... nothing\n"));
3326 YAHOO_CALLBACK(ext_yahoo_login_response
) (yid
->yd
->client_id
,
3327 YAHOO_LOGIN_UNKNOWN
, NULL
);
3333 line_end
= strstr(token
, "\r\n");
3341 error_code
= atoi((char *)token
);
3343 switch (error_code
) {
3348 /* Incorrect ID or password */
3349 LOG(("Incorrect ID or password\n"));
3350 YAHOO_CALLBACK(ext_yahoo_login_response
) (yid
->yd
->client_id
,
3351 YAHOO_LOGIN_PASSWD
, NULL
);
3355 /* Security lock from too many failed login attempts */
3356 LOG(("Security lock from too many failed login attempts\n"));
3357 YAHOO_CALLBACK(ext_yahoo_login_response
) (yid
->yd
->client_id
,
3358 YAHOO_LOGIN_LOCK
, "");
3364 LOG(("Security lock\n"));
3365 YAHOO_CALLBACK(ext_yahoo_login_response
) (yid
->yd
->client_id
,
3366 YAHOO_LOGIN_LOCK
, "");
3371 /* User ID not taken yet */
3372 LOG(("User ID not taken yet\n"));
3373 YAHOO_CALLBACK(ext_yahoo_login_response
) (yid
->yd
->client_id
,
3374 YAHOO_LOGIN_UNAME
, NULL
);
3379 /* Seems to be a lock, but shows the same generic User ID/Password failure */
3380 LOG(("Seems to be a lock, but shows the same generic User ID/Password failure\n"));
3381 YAHOO_CALLBACK(ext_yahoo_login_response
) (yid
->yd
->client_id
,
3382 YAHOO_LOGIN_PASSWD
, NULL
);
3386 /* Username and password cannot be blank */
3387 LOG(("Username and password cannot be blank\n"));
3388 YAHOO_CALLBACK(ext_yahoo_login_response
) (yid
->yd
->client_id
,
3389 YAHOO_LOGIN_PASSWD
, NULL
);
3393 /* Unknown error code */
3394 LOG(("Unknown Error\n"));
3395 YAHOO_CALLBACK(ext_yahoo_login_response
) (yid
->yd
->client_id
,
3396 YAHOO_LOGIN_UNKNOWN
, NULL
);
3401 if (line_end
&& !strncmp(line_end
, "ymsgr=", 6)) {
3403 } else if (strncmp(line_end
, "crumb=", 6)) {
3404 LOG(("Oops! There was no ymsgr=. Where do I get my token from now :("));
3405 LOG(("I got this:\n\n%s\n", line_end
));
3406 YAHOO_CALLBACK(ext_yahoo_login_response
) (yid
->yd
->client_id
,
3407 YAHOO_LOGIN_UNKNOWN
, NULL
);
3412 token
= line_end
+ 6;
3414 line_end
= strstr(token
, "\r\n");
3421 /* Go for the crumb */
3425 struct yahoo_input_data
*crumb_yid
=
3426 y_new0(struct yahoo_input_data
, 1);
3428 crumb_yid
->yd
= yid
->yd
;
3429 crumb_yid
->type
= YAHOO_CONNECTION_AUTH
;
3431 inputs
= y_list_prepend(inputs
, crumb_yid
);
3433 token_enc
= yahoo_urlencode(token
);
3435 snprintf(url
, sizeof(url
),
3436 "https://login.yahoo.com/config/pwtoken_login?src=ymsgr&ts="
3437 "&token=%s", token_enc
);
3439 yahoo_http_get(crumb_yid
->yd
->client_id
, url
, NULL
, 1, 0,
3440 _yahoo_http_connected
, crumb_yid
);
3447 /* token is actually crumb */
3450 /* We did not get our cookies. Cry. */
3451 LOG(("NO Cookies!"));
3452 YAHOO_CALLBACK(ext_yahoo_login_response
) (yid
->yd
->client_id
,
3453 YAHOO_LOGIN_UNKNOWN
, NULL
);
3457 cookie
= strstr((char *)yid
->rxqueue
, "Set-Cookie: Y=");
3461 LOG(("NO Y Cookie!"));
3462 YAHOO_CALLBACK(ext_yahoo_login_response
) (yid
->yd
->client_id
,
3463 YAHOO_LOGIN_UNKNOWN
, NULL
);
3469 line_end
= strstr(cookie
, "\r\n");
3472 yid
->yd
->cookie_y
= strdup(cookie
);
3475 cookie
= strstr((char *)yid
->rxqueue
, "Set-Cookie: T=");
3478 LOG(("NO T Cookie!"));
3479 YAHOO_CALLBACK(ext_yahoo_login_response
) (yid
->yd
->client_id
,
3480 YAHOO_LOGIN_UNKNOWN
, NULL
);
3486 line_end
= strstr(cookie
, "\r\n");
3489 yid
->yd
->cookie_t
= strdup(cookie
);
3492 cookie
= strstr((char *)yid
->rxqueue
, "Set-Cookie: B=");
3495 LOG(("NO B Cookie!"));
3496 YAHOO_CALLBACK(ext_yahoo_login_response
) (yid
->yd
->client_id
,
3497 YAHOO_LOGIN_UNKNOWN
, NULL
);
3503 line_end
= strstr(cookie
, "\r\n");
3506 yid
->yd
->cookie_b
= strdup(cookie
);
3508 yid
->yd
->crumb
= strdup(token
);
3510 yahoo_send_auth(yid
->yd
);
3513 static void (*yahoo_process_connection
[]) (struct yahoo_input_data
*,
3515 yahoo_process_pager_connection
, yahoo_process_ft_connection
,
3516 yahoo_process_yab_connection
,
3517 yahoo_process_webcam_master_connection
,
3518 yahoo_process_webcam_connection
,
3519 yahoo_process_chatcat_connection
,
3520 yahoo_process_search_connection
, yahoo_process_auth_connection
};
3522 int yahoo_read_ready(int id
, void *fd
, void *data
)
3524 struct yahoo_input_data
*yid
= data
;
3528 LOG(("read callback: id=%d fd=%p data=%p", id
, fd
, data
));
3533 len
= YAHOO_CALLBACK(ext_yahoo_read
) (fd
, buf
, sizeof(buf
));
3534 } while (len
== -1 && errno
== EINTR
);
3536 if (len
== -1 && (errno
== EAGAIN
|| errno
== EINTR
)) /* we'll try again later */
3541 DEBUG_MSG(("len == %d (<= 0)", len
));
3543 if (yid
->type
== YAHOO_CONNECTION_PAGER
) {
3544 YAHOO_CALLBACK(ext_yahoo_login_response
) (yid
->yd
->
3545 client_id
, YAHOO_LOGIN_SOCK
, NULL
);
3548 yahoo_process_connection
[yid
->type
] (yid
, 1);
3549 yahoo_input_close(yid
);
3551 /* no need to return an error, because we've already fixed it */
3556 LOG(("read error: %s", strerror(errno
)));
3561 y_renew(unsigned char, yid
->rxqueue
, len
+ yid
->rxlen
+ 1);
3562 memcpy(yid
->rxqueue
+ yid
->rxlen
, buf
, len
);
3564 yid
->rxqueue
[yid
->rxlen
] = 0;
3566 yahoo_process_connection
[yid
->type
] (yid
, 0);
3571 int yahoo_init_with_attributes(const char *username
, const char *password
, ...)
3574 struct yahoo_data
*yd
;
3576 yd
= y_new0(struct yahoo_data
, 1);
3581 yd
->user
= strdup(username
);
3582 yd
->password
= strdup(password
);
3584 yd
->initial_status
= -1;
3585 yd
->current_status
= -1;
3587 yd
->client_id
= ++last_id
;
3591 va_start(ap
, password
);
3592 yd
->server_settings
= _yahoo_assign_server_settings(ap
);
3595 return yd
->client_id
;
3598 int yahoo_init(const char *username
, const char *password
)
3600 return yahoo_init_with_attributes(username
, password
, NULL
);
3603 static void yahoo_connected(void *fd
, int error
, void *data
)
3605 struct connect_callback_data
*ccd
= data
;
3606 struct yahoo_data
*yd
= ccd
->yd
;
3607 struct yahoo_packet
*pkt
;
3608 struct yahoo_input_data
*yid
;
3609 struct yahoo_server_settings
*yss
= yd
->server_settings
;
3613 if (fallback_ports
[ccd
->i
]) {
3614 char *host
= yss
->pager_host
;
3617 host
= yss
->pager_host_list
[ccd
->server_i
];
3619 yss
->pager_port
= fallback_ports
[ccd
->i
++];
3620 tag
= YAHOO_CALLBACK(ext_yahoo_connect_async
) (yd
->
3621 client_id
, host
, yss
->pager_port
,
3622 yahoo_connected
, ccd
, 0);
3626 } else if (yss
->pager_host_list
3627 && yss
->pager_host_list
[ccd
->server_i
]) {
3629 /* Get back to the default port */
3630 yss
->pager_port
= pager_port
;
3632 LOG(("Fallback: Connecting to %s:%d", yss
->pager_host_list
[ccd
->server_i
], yss
->pager_port
));
3635 tag
= YAHOO_CALLBACK(ext_yahoo_connect_async
) (yd
->client_id
,
3636 yss
->pager_host_list
[ccd
->server_i
], yss
->pager_port
,
3637 yahoo_connected
, ccd
, 0);
3640 YAHOO_CALLBACK(ext_yahoo_login_response
) (yd
->client_id
,
3641 YAHOO_LOGIN_SOCK
, NULL
);
3648 /* fd == NULL && error == 0 means connect was cancelled */
3652 pkt
= yahoo_packet_new(YAHOO_SERVICE_AUTH
, YPACKET_STATUS_DEFAULT
,
3654 NOTICE(("Sending initial packet"));
3656 yahoo_packet_hash(pkt
, 1, yd
->user
);
3658 yid
= find_input_by_id_and_type(yd
->client_id
, YAHOO_CONNECTION_PAGER
);
3661 yahoo_send_packet(yid
, pkt
, 0);
3663 yahoo_packet_free(pkt
);
3666 YAHOO_CALLBACK(ext_yahoo_add_handler
) (yid
->yd
->client_id
,
3667 yid
->fd
, YAHOO_INPUT_READ
, yid
);
3670 void *yahoo_get_fd(int id
)
3672 struct yahoo_input_data
*yid
=
3673 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
3680 void yahoo_send_buzz(int id
, const char *from
, const char *who
)
3682 yahoo_send_im(id
, from
, who
, "<ding>", 1, 0);
3685 void yahoo_send_im(int id
, const char *from
, const char *who
, const char *what
,
3686 int utf8
, int picture
)
3688 struct yahoo_input_data
*yid
=
3689 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
3690 struct yahoo_packet
*pkt
= NULL
;
3691 struct yahoo_data
*yd
;
3699 pkt
= yahoo_packet_new(YAHOO_SERVICE_MESSAGE
, YAHOO_STATUS_OFFLINE
,
3702 snprintf(pic_str
, sizeof(pic_str
), "%d", picture
);
3704 if (from
&& strcmp(from
, yd
->user
))
3705 yahoo_packet_hash(pkt
, 0, yd
->user
);
3706 yahoo_packet_hash(pkt
, 1, from
? from
: yd
->user
);
3707 yahoo_packet_hash(pkt
, 5, who
);
3708 yahoo_packet_hash(pkt
, 14, what
);
3711 yahoo_packet_hash(pkt
, 97, "1");
3713 yahoo_packet_hash(pkt
, 63, ";0"); /* imvironment name; or ;0 */
3714 yahoo_packet_hash(pkt
, 64, "0");
3715 yahoo_packet_hash(pkt
, 206, pic_str
);
3717 yahoo_send_packet(yid
, pkt
, 0);
3719 yahoo_packet_free(pkt
);
3722 void yahoo_send_typing(int id
, const char *from
, const char *who
, int typ
)
3724 struct yahoo_input_data
*yid
=
3725 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
3726 struct yahoo_data
*yd
;
3727 struct yahoo_packet
*pkt
= NULL
;
3732 pkt
= yahoo_packet_new(YAHOO_SERVICE_NOTIFY
, YPACKET_STATUS_NOTIFY
,
3735 yahoo_packet_hash(pkt
, 5, who
);
3736 yahoo_packet_hash(pkt
, 1, from
? from
: yd
->user
);
3737 yahoo_packet_hash(pkt
, 14, " ");
3738 yahoo_packet_hash(pkt
, 13, typ
? "1" : "0");
3739 yahoo_packet_hash(pkt
, 49, "TYPING");
3741 yahoo_send_packet(yid
, pkt
, 0);
3743 yahoo_packet_free(pkt
);
3746 void yahoo_set_away(int id
, enum yahoo_status state
, const char *msg
, int away
)
3748 struct yahoo_input_data
*yid
=
3749 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
3750 struct yahoo_data
*yd
;
3751 struct yahoo_packet
*pkt
= NULL
;
3760 old_status
= yd
->current_status
;
3763 yd
->current_status
= YAHOO_STATUS_CUSTOM
;
3765 yd
->current_status
= state
;
3768 /* Thank you libpurple :) */
3769 if (yd
->current_status
== YAHOO_STATUS_INVISIBLE
) {
3770 pkt
= yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBLE_TOGGLE
,
3771 YAHOO_STATUS_AVAILABLE
, 0);
3772 yahoo_packet_hash(pkt
, 13, "2");
3773 yahoo_send_packet(yid
, pkt
, 0);
3774 yahoo_packet_free(pkt
);
3779 pkt
= yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE
,
3780 yd
->current_status
, yd
->session_id
);
3781 snprintf(s
, sizeof(s
), "%d", yd
->current_status
);
3782 yahoo_packet_hash(pkt
, 10, s
);
3784 if (yd
->current_status
== YAHOO_STATUS_CUSTOM
) {
3785 yahoo_packet_hash(pkt
, 19, msg
);
3787 yahoo_packet_hash(pkt
, 19, "");
3790 yahoo_packet_hash(pkt
, 47, (away
== 2) ? "2" : (away
) ? "1" : "0");
3792 yahoo_send_packet(yid
, pkt
, 0);
3793 yahoo_packet_free(pkt
);
3795 if (old_status
== YAHOO_STATUS_INVISIBLE
) {
3796 pkt
= yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBLE_TOGGLE
,
3797 YAHOO_STATUS_AVAILABLE
, 0);
3798 yahoo_packet_hash(pkt
, 13, "1");
3799 yahoo_send_packet(yid
, pkt
, 0);
3800 yahoo_packet_free(pkt
);
3804 void yahoo_logoff(int id
)
3806 struct yahoo_input_data
*yid
=
3807 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
3808 struct yahoo_data
*yd
;
3809 struct yahoo_packet
*pkt
= NULL
;
3815 LOG(("yahoo_logoff: current status: %d", yd
->current_status
));
3817 if (yd
->current_status
!= -1) {
3818 pkt
= yahoo_packet_new(YAHOO_SERVICE_LOGOFF
,
3819 YPACKET_STATUS_DEFAULT
, yd
->session_id
);
3820 yd
->current_status
= -1;
3823 yahoo_send_packet(yid
, pkt
, 0);
3824 yahoo_packet_free(pkt
);
3829 yahoo_input_close(yid);
3830 } while((yid = find_input_by_id(id)));*/
3834 void yahoo_get_list(int id
)
3836 struct yahoo_input_data
*yid
=
3837 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
3838 struct yahoo_data
*yd
;
3839 struct yahoo_packet
*pkt
= NULL
;
3845 pkt
= yahoo_packet_new(YAHOO_SERVICE_LIST
, YPACKET_STATUS_DEFAULT
,
3847 yahoo_packet_hash(pkt
, 1, yd
->user
);
3849 yahoo_send_packet(yid
, pkt
, 0);
3850 yahoo_packet_free(pkt
);
3854 static void _yahoo_http_connected(int id
, void *fd
, int error
, void *data
)
3856 struct yahoo_input_data
*yid
= data
;
3857 if (fd
== NULL
|| error
) {
3858 inputs
= y_list_remove(inputs
, yid
);
3865 YAHOO_CALLBACK(ext_yahoo_add_handler
) (yid
->yd
->client_id
, fd
,
3866 YAHOO_INPUT_READ
, yid
);
3869 /* FIXME Get address book from address.yahoo.com instead */
3870 void yahoo_get_yab(int id
)
3872 struct yahoo_data
*yd
= find_conn_by_id(id
);
3873 struct yahoo_input_data
*yid
;
3880 yid
= y_new0(struct yahoo_input_data
, 1);
3882 yid
->type
= YAHOO_CONNECTION_YAB
;
3884 LOG(("Sending request for Address Book"));
3887 "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us"
3888 "&diffs=1&t=0&tags=short&rt=0&prog-ver=8.1.0.249&useutf8=1&legenc=codepage-1252");
3890 snprintf(buff
, sizeof(buff
), "Y=%s; T=%s", yd
->cookie_y
, yd
->cookie_t
);
3892 inputs
= y_list_prepend(inputs
, yid
);
3894 yahoo_http_get(yid
->yd
->client_id
, url
, buff
, 0, 0,
3895 _yahoo_http_connected
, yid
);
3898 struct yahoo_post_data
{
3899 struct yahoo_input_data
*yid
;
3903 static void _yahoo_http_post_connected(int id
, void *fd
, int error
, void *data
)
3905 struct yahoo_post_data
*yad
= data
;
3906 struct yahoo_input_data
*yid
= yad
->yid
;
3907 char *buff
= yad
->data
;
3910 inputs
= y_list_remove(inputs
, yid
);
3915 YAHOO_CALLBACK(ext_yahoo_write
) (fd
, buff
, strlen(buff
));
3919 YAHOO_CALLBACK(ext_yahoo_add_handler
) (yid
->yd
->client_id
, fd
,
3920 YAHOO_INPUT_READ
, yid
);
3926 /* FIXME This is also likely affected */
3927 void yahoo_set_yab(int id
, struct yab
*yab
)
3929 struct yahoo_post_data
*yad
= y_new0(struct yahoo_post_data
, 1);
3930 struct yahoo_data
*yd
= find_conn_by_id(id
);
3931 struct yahoo_input_data
*yid
;
3940 yid
= y_new0(struct yahoo_input_data
, 1);
3941 yid
->type
= YAHOO_CONNECTION_YAB
;
3945 size
= snprintf(post
, sizeof(post
), "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
3946 "<ab k=\"%s\" cc=\"%d\">"
3947 "<ct id=\"%d\" e=\"1\" yi=\"%s\" nn=\"%s\" />"
3948 "</ab>", yd
->user
, 9, yab
->yid
, /* Don't know why */
3949 yab
->id
, yab
->nname
?yab
->nname
:"");
3951 size
= snprintf(post
, sizeof(post
), "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
3952 "<ab k=\"%s\" cc=\"%d\">"
3953 "<ct a=\"1\" yi=\"%s\" nn=\"%s\" />"
3954 "</ab>", yd
->user
, 1, /* Don't know why */
3955 yab
->id
, yab
->nname
?yab
->nname
:"");
3958 yad
->data
= strdup(post
);
3960 strcpy(url
, "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us"
3961 "&sync=1&tags=short&noclear=1&useutf8=1&legenc=codepage-1252");
3963 snprintf(buff
, sizeof(buff
), "Y=%s; T=%s", yd
->cookie_y
, yd
->cookie_t
);
3965 inputs
= y_list_prepend(inputs
, yid
);
3967 yahoo_http_post(yid
->yd
->client_id
, url
, buff
, size
,
3968 _yahoo_http_post_connected
, yad
);
3971 void yahoo_set_identity_status(int id
, const char *identity
, int active
)
3973 struct yahoo_input_data
*yid
=
3974 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
3975 struct yahoo_data
*yd
;
3976 struct yahoo_packet
*pkt
= NULL
;
3982 pkt
= yahoo_packet_new(active
? YAHOO_SERVICE_IDACT
:
3983 YAHOO_SERVICE_IDDEACT
, YPACKET_STATUS_DEFAULT
, yd
->session_id
);
3984 yahoo_packet_hash(pkt
, 3, identity
);
3986 yahoo_send_packet(yid
, pkt
, 0);
3987 yahoo_packet_free(pkt
);
3991 void yahoo_refresh(int id
)
3993 struct yahoo_input_data
*yid
=
3994 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
3995 struct yahoo_data
*yd
;
3996 struct yahoo_packet
*pkt
= NULL
;
4002 pkt
= yahoo_packet_new(YAHOO_SERVICE_USERSTAT
, YPACKET_STATUS_DEFAULT
,
4005 yahoo_send_packet(yid
, pkt
, 0);
4006 yahoo_packet_free(pkt
);
4010 void yahoo_keepalive(int id
)
4012 struct yahoo_input_data
*yid
=
4013 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4014 struct yahoo_data
*yd
;
4015 struct yahoo_packet
*pkt
= NULL
;
4020 pkt
= yahoo_packet_new(YAHOO_SERVICE_PING
, YPACKET_STATUS_DEFAULT
,
4022 yahoo_send_packet(yid
, pkt
, 0);
4023 yahoo_packet_free(pkt
);
4026 void yahoo_chat_keepalive(int id
)
4028 struct yahoo_input_data
*yid
=
4029 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4030 struct yahoo_data
*yd
;
4031 struct yahoo_packet
*pkt
= NULL
;
4038 pkt
= yahoo_packet_new(YAHOO_SERVICE_CHATPING
, YPACKET_STATUS_DEFAULT
,
4040 yahoo_send_packet(yid
, pkt
, 0);
4041 yahoo_packet_free(pkt
);
4044 void yahoo_add_buddy(int id
, const char *who
, const char *group
,
4047 struct yahoo_input_data
*yid
=
4048 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4049 struct yahoo_data
*yd
;
4050 struct yahoo_packet
*pkt
;
4059 pkt
= yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY
, YPACKET_STATUS_DEFAULT
,
4061 if (msg
!= NULL
) /* add message/request "it's me add me" */
4062 yahoo_packet_hash(pkt
, 14, msg
);
4064 yahoo_packet_hash(pkt
, 14, "");
4065 yahoo_packet_hash(pkt
, 65, group
);
4066 yahoo_packet_hash(pkt
, 97, "1");
4067 yahoo_packet_hash(pkt
, 1, yd
->user
);
4068 yahoo_packet_hash(pkt
, 302, "319");
4069 yahoo_packet_hash(pkt
, 300, "319");
4070 yahoo_packet_hash(pkt
, 7, who
);
4071 yahoo_packet_hash(pkt
, 334, "0");
4072 yahoo_packet_hash(pkt
, 301, "319");
4073 yahoo_packet_hash(pkt
, 303, "319");
4074 yahoo_send_packet(yid
, pkt
, 0);
4075 yahoo_packet_free(pkt
);
4078 void yahoo_remove_buddy(int id
, const char *who
, const char *group
)
4080 struct yahoo_input_data
*yid
=
4081 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4082 struct yahoo_data
*yd
;
4083 struct yahoo_packet
*pkt
= NULL
;
4089 pkt
= yahoo_packet_new(YAHOO_SERVICE_REMBUDDY
, YPACKET_STATUS_DEFAULT
,
4092 yahoo_packet_hash(pkt
, 1, yd
->user
);
4093 yahoo_packet_hash(pkt
, 7, who
);
4094 yahoo_packet_hash(pkt
, 65, group
);
4095 yahoo_send_packet(yid
, pkt
, 0);
4096 yahoo_packet_free(pkt
);
4099 void yahoo_confirm_buddy(int id
, const char *who
, int reject
, const char *msg
)
4101 struct yahoo_input_data
*yid
=
4102 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4103 struct yahoo_data
*yd
;
4104 struct yahoo_packet
*pkt
;
4113 pkt
= yahoo_packet_new(YAHOO_SERVICE_Y7_AUTHORIZATION
,
4114 YPACKET_STATUS_DEFAULT
, yd
->session_id
);
4115 yahoo_packet_hash(pkt
, 1, yd
->user
);
4116 yahoo_packet_hash(pkt
, 5, who
);
4118 yahoo_packet_hash(pkt
, 13, "2");
4120 yahoo_packet_hash(pkt
, 241, "0");
4121 yahoo_packet_hash(pkt
, 13, "1");
4124 yahoo_packet_hash(pkt
, 334, "0");
4127 yahoo_packet_hash(pkt
, 14, msg
? msg
: "");
4128 yahoo_packet_hash(pkt
, 97, "1");
4131 yahoo_send_packet(yid
, pkt
, 0);
4132 yahoo_packet_free(pkt
);
4135 void yahoo_ignore_buddy(int id
, const char *who
, int unignore
)
4137 struct yahoo_input_data
*yid
=
4138 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_IGNORECONTACT
,
4150 YPACKET_STATUS_DEFAULT
, yd
->session_id
);
4151 yahoo_packet_hash(pkt
, 1, yd
->user
);
4152 yahoo_packet_hash(pkt
, 7, who
);
4153 yahoo_packet_hash(pkt
, 13, unignore
? "2" : "1");
4154 yahoo_send_packet(yid
, pkt
, 0);
4155 yahoo_packet_free(pkt
);
4158 void yahoo_stealth_buddy(int id
, const char *who
, int unstealth
)
4160 struct yahoo_input_data
*yid
=
4161 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4162 struct yahoo_data
*yd
;
4163 struct yahoo_packet
*pkt
;
4172 pkt
= yahoo_packet_new(YAHOO_SERVICE_STEALTH_PERM
,
4173 YPACKET_STATUS_DEFAULT
, yd
->session_id
);
4174 yahoo_packet_hash(pkt
, 1, yd
->user
);
4175 yahoo_packet_hash(pkt
, 7, who
);
4176 yahoo_packet_hash(pkt
, 31, unstealth
? "2" : "1");
4177 yahoo_packet_hash(pkt
, 13, "2");
4178 yahoo_send_packet(yid
, pkt
, 0);
4179 yahoo_packet_free(pkt
);
4182 void yahoo_change_buddy_group(int id
, const char *who
, const char *old_group
,
4183 const char *new_group
)
4185 struct yahoo_input_data
*yid
=
4186 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4187 struct yahoo_data
*yd
;
4188 struct yahoo_packet
*pkt
= NULL
;
4194 pkt
= yahoo_packet_new(YAHOO_SERVICE_Y7_CHANGE_GROUP
,
4195 YPACKET_STATUS_DEFAULT
, yd
->session_id
);
4196 yahoo_packet_hash(pkt
, 1, yd
->user
);
4197 yahoo_packet_hash(pkt
, 302, "240");
4198 yahoo_packet_hash(pkt
, 300, "240");
4199 yahoo_packet_hash(pkt
, 7, who
);
4200 yahoo_packet_hash(pkt
, 224, old_group
);
4201 yahoo_packet_hash(pkt
, 264, new_group
);
4202 yahoo_packet_hash(pkt
, 301, "240");
4203 yahoo_packet_hash(pkt
, 303, "240");
4205 yahoo_send_packet(yid
, pkt
, 0);
4206 yahoo_packet_free(pkt
);
4209 void yahoo_group_rename(int id
, const char *old_group
, const char *new_group
)
4211 struct yahoo_input_data
*yid
=
4212 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4213 struct yahoo_data
*yd
;
4214 struct yahoo_packet
*pkt
= NULL
;
4220 pkt
= yahoo_packet_new(YAHOO_SERVICE_GROUPRENAME
,
4221 YPACKET_STATUS_DEFAULT
, yd
->session_id
);
4222 yahoo_packet_hash(pkt
, 1, yd
->user
);
4223 yahoo_packet_hash(pkt
, 65, old_group
);
4224 yahoo_packet_hash(pkt
, 67, new_group
);
4226 yahoo_send_packet(yid
, pkt
, 0);
4227 yahoo_packet_free(pkt
);
4230 void yahoo_conference_addinvite(int id
, const char *from
, const char *who
,
4231 const char *room
, const YList
*members
, const char *msg
)
4233 struct yahoo_input_data
*yid
=
4234 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4235 struct yahoo_data
*yd
;
4236 struct yahoo_packet
*pkt
;
4242 pkt
= yahoo_packet_new(YAHOO_SERVICE_CONFADDINVITE
,
4243 YPACKET_STATUS_DEFAULT
, yd
->session_id
);
4245 yahoo_packet_hash(pkt
, 1, (from
? from
: yd
->user
));
4246 yahoo_packet_hash(pkt
, 51, who
);
4247 yahoo_packet_hash(pkt
, 57, room
);
4248 yahoo_packet_hash(pkt
, 58, msg
);
4249 yahoo_packet_hash(pkt
, 13, "0");
4250 for (; members
; members
= members
->next
) {
4251 yahoo_packet_hash(pkt
, 52, (char *)members
->data
);
4252 yahoo_packet_hash(pkt
, 53, (char *)members
->data
);
4254 /* 52, 53 -> other members? */
4256 yahoo_send_packet(yid
, pkt
, 0);
4258 yahoo_packet_free(pkt
);
4261 void yahoo_conference_invite(int id
, const char *from
, YList
*who
,
4262 const char *room
, const char *msg
)
4264 struct yahoo_input_data
*yid
=
4265 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4266 struct yahoo_data
*yd
;
4267 struct yahoo_packet
*pkt
;
4273 pkt
= yahoo_packet_new(YAHOO_SERVICE_CONFINVITE
, YPACKET_STATUS_DEFAULT
,
4276 yahoo_packet_hash(pkt
, 1, (from
? from
: yd
->user
));
4277 yahoo_packet_hash(pkt
, 50, yd
->user
);
4278 for (; who
; who
= who
->next
) {
4279 yahoo_packet_hash(pkt
, 52, (char *)who
->data
);
4281 yahoo_packet_hash(pkt
, 57, room
);
4282 yahoo_packet_hash(pkt
, 58, msg
);
4283 yahoo_packet_hash(pkt
, 13, "0");
4285 yahoo_send_packet(yid
, pkt
, 0);
4287 yahoo_packet_free(pkt
);
4290 void yahoo_conference_logon(int id
, const char *from
, YList
*who
,
4293 struct yahoo_input_data
*yid
=
4294 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4295 struct yahoo_data
*yd
;
4296 struct yahoo_packet
*pkt
;
4302 pkt
= yahoo_packet_new(YAHOO_SERVICE_CONFLOGON
, YPACKET_STATUS_DEFAULT
,
4305 yahoo_packet_hash(pkt
, 1, (from
? from
: yd
->user
));
4306 yahoo_packet_hash(pkt
, 3, (from
? from
: yd
->user
));
4307 yahoo_packet_hash(pkt
, 57, room
);
4308 for (; who
; who
= who
->next
)
4309 yahoo_packet_hash(pkt
, 3, (char *)who
->data
);
4311 yahoo_send_packet(yid
, pkt
, 0);
4313 yahoo_packet_free(pkt
);
4316 void yahoo_conference_decline(int id
, const char *from
, YList
*who
,
4317 const char *room
, const char *msg
)
4319 struct yahoo_input_data
*yid
=
4320 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4321 struct yahoo_data
*yd
;
4322 struct yahoo_packet
*pkt
;
4328 pkt
= yahoo_packet_new(YAHOO_SERVICE_CONFDECLINE
,
4329 YPACKET_STATUS_DEFAULT
, yd
->session_id
);
4331 yahoo_packet_hash(pkt
, 1, (from
? from
: yd
->user
));
4332 yahoo_packet_hash(pkt
, 3, (from
? from
: yd
->user
));
4333 for (; who
; who
= who
->next
)
4334 yahoo_packet_hash(pkt
, 3, (char *)who
->data
);
4335 yahoo_packet_hash(pkt
, 57, room
);
4336 yahoo_packet_hash(pkt
, 14, msg
);
4338 yahoo_send_packet(yid
, pkt
, 0);
4340 yahoo_packet_free(pkt
);
4343 void yahoo_conference_logoff(int id
, const char *from
, YList
*who
,
4346 struct yahoo_input_data
*yid
=
4347 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4348 struct yahoo_data
*yd
;
4349 struct yahoo_packet
*pkt
;
4355 pkt
= yahoo_packet_new(YAHOO_SERVICE_CONFLOGOFF
, YPACKET_STATUS_DEFAULT
,
4358 yahoo_packet_hash(pkt
, 1, (from
? from
: yd
->user
));
4359 yahoo_packet_hash(pkt
, 3, (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
,
4371 const char *room
, const char *msg
, int utf8
)
4373 struct yahoo_input_data
*yid
=
4374 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4375 struct yahoo_data
*yd
;
4376 struct yahoo_packet
*pkt
;
4382 pkt
= yahoo_packet_new(YAHOO_SERVICE_CONFMSG
, YPACKET_STATUS_DEFAULT
,
4385 yahoo_packet_hash(pkt
, 1, (from
? from
: yd
->user
));
4386 yahoo_packet_hash(pkt
, 53, (from
? from
: yd
->user
));
4387 for (; who
; who
= who
->next
)
4388 yahoo_packet_hash(pkt
, 53, (char *)who
->data
);
4390 yahoo_packet_hash(pkt
, 57, room
);
4391 yahoo_packet_hash(pkt
, 14, msg
);
4394 yahoo_packet_hash(pkt
, 97, "1");
4396 yahoo_send_packet(yid
, pkt
, 0);
4398 yahoo_packet_free(pkt
);
4401 void yahoo_get_chatrooms(int id
, int chatroomid
)
4403 struct yahoo_data
*yd
= find_conn_by_id(id
);
4404 struct yahoo_input_data
*yid
;
4411 yid
= y_new0(struct yahoo_input_data
, 1);
4413 yid
->type
= YAHOO_CONNECTION_CHATCAT
;
4415 if (chatroomid
== 0) {
4417 "http://insider.msg.yahoo.com/ycontent/?chatcat=0");
4420 "http://insider.msg.yahoo.com/ycontent/?chatroom_%d=0",
4424 snprintf(buff
, sizeof(buff
), "Y=%s; T=%s", yd
->cookie_y
, yd
->cookie_t
);
4426 inputs
= y_list_prepend(inputs
, yid
);
4428 yahoo_http_get(yid
->yd
->client_id
, url
, buff
, 0, 0,
4429 _yahoo_http_connected
, yid
);
4432 void yahoo_chat_logon(int id
, const char *from
, const char *room
,
4435 struct yahoo_input_data
*yid
=
4436 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4437 struct yahoo_data
*yd
;
4438 struct yahoo_packet
*pkt
;
4445 pkt
= yahoo_packet_new(YAHOO_SERVICE_CHATONLINE
, YPACKET_STATUS_DEFAULT
,
4448 yahoo_packet_hash(pkt
, 1, (from
? from
: yd
->user
));
4449 yahoo_packet_hash(pkt
, 109, yd
->user
);
4450 yahoo_packet_hash(pkt
, 6, "abcde");
4452 yahoo_send_packet(yid
, pkt
, 0);
4454 yahoo_packet_free(pkt
);
4456 pkt
= yahoo_packet_new(YAHOO_SERVICE_CHATJOIN
, YPACKET_STATUS_DEFAULT
,
4459 yahoo_packet_hash(pkt
, 1, (from
? from
: yd
->user
));
4460 yahoo_packet_hash(pkt
, 104, room
);
4461 yahoo_packet_hash(pkt
, 129, roomid
);
4462 yahoo_packet_hash(pkt
, 62, "2"); /* ??? */
4464 yahoo_send_packet(yid
, pkt
, 0);
4466 yahoo_packet_free(pkt
);
4469 void yahoo_chat_message(int id
, const char *from
, const char *room
,
4470 const char *msg
, const int msgtype
, const int utf8
)
4472 struct yahoo_input_data
*yid
=
4473 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4474 struct yahoo_data
*yd
;
4475 struct yahoo_packet
*pkt
;
4483 pkt
= yahoo_packet_new(YAHOO_SERVICE_COMMENT
, YPACKET_STATUS_DEFAULT
,
4486 yahoo_packet_hash(pkt
, 1, (from
? from
: yd
->user
));
4487 yahoo_packet_hash(pkt
, 104, room
);
4488 yahoo_packet_hash(pkt
, 117, msg
);
4490 snprintf(buf
, sizeof(buf
), "%d", msgtype
);
4491 yahoo_packet_hash(pkt
, 124, buf
);
4494 yahoo_packet_hash(pkt
, 97, "1");
4496 yahoo_send_packet(yid
, pkt
, 0);
4498 yahoo_packet_free(pkt
);
4501 void yahoo_chat_logoff(int id
, const char *from
)
4503 struct yahoo_input_data
*yid
=
4504 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4505 struct yahoo_data
*yd
;
4506 struct yahoo_packet
*pkt
;
4513 pkt
= yahoo_packet_new(YAHOO_SERVICE_CHATLOGOUT
, YPACKET_STATUS_DEFAULT
,
4516 yahoo_packet_hash(pkt
, 1, (from
? from
: yd
->user
));
4518 yahoo_send_packet(yid
, pkt
, 0);
4520 yahoo_packet_free(pkt
);
4523 void yahoo_buddyicon_request(int id
, const char *who
)
4525 struct yahoo_input_data
*yid
=
4526 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4527 struct yahoo_data
*yd
;
4528 struct yahoo_packet
*pkt
;
4535 pkt
= yahoo_packet_new(YAHOO_SERVICE_PICTURE
, YPACKET_STATUS_DEFAULT
,
4537 yahoo_packet_hash(pkt
, 4, yd
->user
);
4538 yahoo_packet_hash(pkt
, 5, who
);
4539 yahoo_packet_hash(pkt
, 13, "1");
4540 yahoo_send_packet(yid
, pkt
, 0);
4542 yahoo_packet_free(pkt
);
4545 void yahoo_send_picture_info(int id
, const char *who
, const char *url
,
4548 struct yahoo_input_data
*yid
=
4549 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4550 struct yahoo_data
*yd
;
4551 struct yahoo_packet
*pkt
;
4552 char checksum_str
[10];
4559 snprintf(checksum_str
, sizeof(checksum_str
), "%d", checksum
);
4561 pkt
= yahoo_packet_new(YAHOO_SERVICE_PICTURE
, YPACKET_STATUS_DEFAULT
,
4563 yahoo_packet_hash(pkt
, 1, yd
->user
);
4564 yahoo_packet_hash(pkt
, 4, yd
->user
);
4565 yahoo_packet_hash(pkt
, 5, who
);
4566 yahoo_packet_hash(pkt
, 13, "2");
4567 yahoo_packet_hash(pkt
, 20, url
);
4568 yahoo_packet_hash(pkt
, 192, checksum_str
);
4569 yahoo_send_packet(yid
, pkt
, 0);
4571 yahoo_packet_free(pkt
);
4574 void yahoo_send_picture_update(int id
, const char *who
, int type
)
4576 struct yahoo_input_data
*yid
=
4577 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4578 struct yahoo_data
*yd
;
4579 struct yahoo_packet
*pkt
;
4587 snprintf(type_str
, sizeof(type_str
), "%d", type
);
4589 pkt
= yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPDATE
,
4590 YPACKET_STATUS_DEFAULT
, 0);
4591 yahoo_packet_hash(pkt
, 1, yd
->user
);
4592 yahoo_packet_hash(pkt
, 5, who
);
4593 yahoo_packet_hash(pkt
, 206, type_str
);
4594 yahoo_send_packet(yid
, pkt
, 0);
4596 yahoo_packet_free(pkt
);
4599 void yahoo_send_picture_checksum(int id
, const char *who
, int checksum
)
4601 struct yahoo_input_data
*yid
=
4602 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4603 struct yahoo_data
*yd
;
4604 struct yahoo_packet
*pkt
;
4605 char checksum_str
[10];
4612 snprintf(checksum_str
, sizeof(checksum_str
), "%d", checksum
);
4614 pkt
= yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM
,
4615 YPACKET_STATUS_DEFAULT
, 0);
4616 yahoo_packet_hash(pkt
, 1, yd
->user
);
4618 yahoo_packet_hash(pkt
, 5, who
);
4619 yahoo_packet_hash(pkt
, 192, checksum_str
);
4620 yahoo_packet_hash(pkt
, 212, "1");
4621 yahoo_send_packet(yid
, pkt
, 0);
4623 yahoo_packet_free(pkt
);
4626 void yahoo_webcam_close_feed(int id
, const char *who
)
4628 struct yahoo_input_data
*yid
=
4629 find_input_by_id_and_webcam_user(id
, who
);
4632 yahoo_input_close(yid
);
4635 void yahoo_webcam_get_feed(int id
, const char *who
)
4637 struct yahoo_input_data
*yid
=
4638 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4639 struct yahoo_data
*yd
;
4640 struct yahoo_packet
*pkt
;
4646 * add the user to the queue. this is a dirty hack, since
4647 * the yahoo server doesn't tell us who's key it's returning,
4648 * we have to just hope that it sends back keys in the same
4649 * order that we request them.
4650 * The queue is popped in yahoo_process_webcam_key
4652 webcam_queue
= y_list_append(webcam_queue
, who
? strdup(who
) : NULL
);
4656 pkt
= yahoo_packet_new(YAHOO_SERVICE_WEBCAM
, YPACKET_STATUS_DEFAULT
,
4659 yahoo_packet_hash(pkt
, 1, yd
->user
);
4661 yahoo_packet_hash(pkt
, 5, who
);
4662 yahoo_send_packet(yid
, pkt
, 0);
4664 yahoo_packet_free(pkt
);
4667 void yahoo_webcam_send_image(int id
, unsigned char *image
, unsigned int length
,
4668 unsigned int timestamp
)
4670 struct yahoo_input_data
*yid
=
4671 find_input_by_id_and_type(id
, YAHOO_CONNECTION_WEBCAM
);
4672 unsigned char *packet
;
4673 unsigned char header_len
= 13;
4674 unsigned int pos
= 0;
4679 packet
= y_new0(unsigned char, header_len
);
4681 packet
[pos
++] = header_len
;
4683 packet
[pos
++] = 5; /* version byte?? */
4685 pos
+= yahoo_put32(packet
+ pos
, length
);
4686 packet
[pos
++] = 2; /* packet type, image */
4687 pos
+= yahoo_put32(packet
+ pos
, timestamp
);
4688 yahoo_add_to_send_queue(yid
, packet
, header_len
);
4692 yahoo_add_to_send_queue(yid
, image
, length
);
4695 void yahoo_webcam_accept_viewer(int id
, const char *who
, int accept
)
4697 struct yahoo_input_data
*yid
=
4698 find_input_by_id_and_type(id
, YAHOO_CONNECTION_WEBCAM
);
4699 char *packet
= NULL
;
4701 unsigned char header_len
= 13;
4702 unsigned int pos
= 0;
4703 unsigned int len
= 0;
4708 data
= strdup("u=");
4709 data
= y_string_append(data
, (char *)who
);
4710 data
= y_string_append(data
, "\r\n");
4713 packet
= y_new0(char, header_len
+ len
);
4714 packet
[pos
++] = header_len
;
4716 packet
[pos
++] = 5; /* version byte?? */
4718 pos
+= yahoo_put32(packet
+ pos
, len
);
4719 packet
[pos
++] = 0; /* packet type */
4720 pos
+= yahoo_put32(packet
+ pos
, accept
);
4721 memcpy(packet
+ pos
, data
, len
);
4723 yahoo_add_to_send_queue(yid
, packet
, header_len
+ len
);
4727 void yahoo_webcam_invite(int id
, const char *who
)
4729 struct yahoo_input_data
*yid
=
4730 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4731 struct yahoo_packet
*pkt
;
4736 pkt
= yahoo_packet_new(YAHOO_SERVICE_NOTIFY
, YPACKET_STATUS_NOTIFY
,
4737 yid
->yd
->session_id
);
4739 yahoo_packet_hash(pkt
, 49, "WEBCAMINVITE");
4740 yahoo_packet_hash(pkt
, 14, " ");
4741 yahoo_packet_hash(pkt
, 13, "0");
4742 yahoo_packet_hash(pkt
, 1, yid
->yd
->user
);
4743 yahoo_packet_hash(pkt
, 5, who
);
4744 yahoo_send_packet(yid
, pkt
, 0);
4746 yahoo_packet_free(pkt
);
4749 static void yahoo_search_internal(int id
, int t
, const char *text
, int g
,
4750 int ar
, int photo
, int yahoo_only
, int startpos
, int total
)
4752 struct yahoo_data
*yd
= find_conn_by_id(id
);
4753 struct yahoo_input_data
*yid
;
4761 yid
= y_new0(struct yahoo_input_data
, 1);
4763 yid
->type
= YAHOO_CONNECTION_SEARCH
;
4767 .ar=1 - 13-18, 2 - 18-25, 3 - 25-35, 4 - 35-50, 5 - 50-70, 6 - 70+
4770 snprintf(buff
, sizeof(buff
), "&.sq=%%20&.tt=%d&.ss=%d", total
,
4773 ctext
= strdup(text
);
4774 while ((p
= strchr(ctext
, ' ')))
4778 "http://members.yahoo.com/interests?.oc=m&.kw=%s&.sb=%d&.g=%d&.ar=0%s%s%s",
4779 ctext
, t
, g
, photo
? "&.p=y" : "", yahoo_only
? "&.pg=y" : "",
4780 startpos
? buff
: "");
4784 snprintf(buff
, sizeof(buff
), "Y=%s; T=%s", yd
->cookie_y
, yd
->cookie_t
);
4786 inputs
= y_list_prepend(inputs
, yid
);
4787 yahoo_http_get(yid
->yd
->client_id
, url
, buff
, 0, 0,
4788 _yahoo_http_connected
, yid
);
4791 void yahoo_search(int id
, enum yahoo_search_type t
, const char *text
,
4792 enum yahoo_search_gender g
, enum yahoo_search_agerange ar
, int photo
,
4795 struct yahoo_input_data
*yid
=
4796 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4797 struct yahoo_search_state
*yss
;
4803 yid
->ys
= y_new0(struct yahoo_search_state
, 1);
4807 FREE(yss
->lsearch_text
);
4808 yss
->lsearch_type
= t
;
4809 yss
->lsearch_text
= strdup(text
);
4810 yss
->lsearch_gender
= g
;
4811 yss
->lsearch_agerange
= ar
;
4812 yss
->lsearch_photo
= photo
;
4813 yss
->lsearch_yahoo_only
= yahoo_only
;
4815 yahoo_search_internal(id
, t
, text
, g
, ar
, photo
, yahoo_only
, 0, 0);
4818 void yahoo_search_again(int id
, int start
)
4820 struct yahoo_input_data
*yid
=
4821 find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
4822 struct yahoo_search_state
*yss
;
4824 if (!yid
|| !yid
->ys
)
4830 start
= yss
->lsearch_nstart
+ yss
->lsearch_nfound
;
4832 yahoo_search_internal(id
, yss
->lsearch_type
, yss
->lsearch_text
,
4833 yss
->lsearch_gender
, yss
->lsearch_agerange
,
4834 yss
->lsearch_photo
, yss
->lsearch_yahoo_only
,
4835 start
, yss
->lsearch_ntotal
);
4838 void yahoo_send_picture(int id
, const char *name
, unsigned long size
,
4839 yahoo_get_fd_callback callback
, void *data
)
4841 /* Not Implemented */
4845 static YList
*active_file_transfers
= NULL
;
4850 FT_STATE_RECV_START
,
4854 struct send_file_data
{
4863 struct yahoo_input_data
*yid
;
4866 yahoo_get_fd_callback callback
;
4870 static char *yahoo_get_random(void)
4881 for (i
= 0; i
< 22; i
++) {
4890 out
[i
] = c
- 26 + 'A';
4892 out
[i
] = c
- 52 + '0';
4900 static int _are_same_id(const void *sfd1
, const void *id
)
4902 return strcmp(((struct send_file_data
*)sfd1
)->id
, (char *)id
);
4905 static int _are_same_yid(const void *sfd1
, const void *yid
)
4907 if(((struct send_file_data
*)sfd1
)->yid
== yid
)
4913 static struct send_file_data
*yahoo_get_active_transfer(char *id
)
4915 YList
*l
= y_list_find_custom(active_file_transfers
, id
,
4919 return (struct send_file_data
*)l
->data
;
4924 static struct send_file_data
*yahoo_get_active_transfer_with_yid(void *yid
)
4926 YList
*l
= y_list_find_custom(active_file_transfers
, yid
,
4930 return (struct send_file_data
*)l
->data
;
4935 static void yahoo_add_active_transfer(struct send_file_data
*sfd
)
4937 active_file_transfers
= y_list_prepend(active_file_transfers
, sfd
);
4940 static void yahoo_remove_active_transfer(struct send_file_data
*sfd
)
4942 active_file_transfers
= y_list_remove(active_file_transfers
, sfd
);
4945 free(sfd
->filename
);
4950 static void _yahoo_ft_upload_connected(int id
, void *fd
, int error
, void *data
)
4952 struct send_file_data
*sfd
= data
;
4953 struct yahoo_input_data
*yid
= sfd
->yid
;
4956 inputs
= y_list_remove(inputs
, yid
);
4961 sfd
->callback(id
, fd
, error
, sfd
->data
);
4965 YAHOO_CALLBACK(ext_yahoo_add_handler
) (yid
->yd
->client_id
, fd
,
4966 YAHOO_INPUT_READ
, yid
);
4969 static void yahoo_file_transfer_upload(struct yahoo_data
*yd
,
4970 struct send_file_data
*sfd
)
4974 char *sender_enc
= NULL
, *recv_enc
= NULL
, *token_enc
= NULL
;
4976 struct yahoo_input_data
*yid
= y_new0(struct yahoo_input_data
, 1);
4979 yid
->type
= YAHOO_CONNECTION_FT
;
4981 inputs
= y_list_prepend(inputs
, yid
);
4983 sfd
->state
= FT_STATE_SEND
;
4985 token_enc
= yahoo_urlencode(sfd
->token
);
4986 sender_enc
= yahoo_urlencode(yd
->user
);
4987 recv_enc
= yahoo_urlencode(sfd
->who
);
4989 snprintf(url
, sizeof(url
),
4990 "http://%s/relay?token=%s&sender=%s&recver=%s", sfd
->ip_addr
,
4991 token_enc
, sender_enc
, recv_enc
);
4993 snprintf(buff
, sizeof(buff
), "T=%s; Y=%s", yd
->cookie_t
, yd
->cookie_y
);
4995 yahoo_http_post(yd
->client_id
, url
, buff
, sfd
->size
,
4996 _yahoo_ft_upload_connected
, sfd
);
5003 static void yahoo_init_ft_recv(struct yahoo_data
*yd
,
5004 struct send_file_data
*sfd
)
5008 char *sender_enc
= NULL
, *recv_enc
= NULL
, *token_enc
= NULL
;
5010 struct yahoo_input_data
*yid
= y_new0(struct yahoo_input_data
, 1);
5013 yid
->type
= YAHOO_CONNECTION_FT
;
5015 inputs
= y_list_prepend(inputs
, yid
);
5017 sfd
->state
= FT_STATE_HEAD
;
5019 token_enc
= yahoo_urlencode(sfd
->token
);
5020 sender_enc
= yahoo_urlencode(sfd
->who
);
5021 recv_enc
= yahoo_urlencode(yd
->user
);
5023 snprintf(url
, sizeof(url
),
5024 "http://%s/relay?token=%s&sender=%s&recver=%s", sfd
->ip_addr
,
5025 token_enc
, sender_enc
, recv_enc
);
5027 snprintf(buff
, sizeof(buff
), "Y=%s; T=%s", yd
->cookie_y
, yd
->cookie_t
);
5029 yahoo_http_head(yid
->yd
->client_id
, url
, buff
, 0, NULL
,
5030 _yahoo_http_connected
, yid
);
5037 static void yahoo_file_transfer_accept(struct yahoo_input_data
*yid
,
5038 struct send_file_data
*sfd
)
5040 struct yahoo_packet
*pkt
;
5042 pkt
= yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFERACCEPT
,
5043 YPACKET_STATUS_DEFAULT
, yid
->yd
->session_id
);
5045 yahoo_packet_hash(pkt
, 1, yid
->yd
->user
);
5046 yahoo_packet_hash(pkt
, 5, sfd
->who
);
5047 yahoo_packet_hash(pkt
, 265, sfd
->id
);
5048 yahoo_packet_hash(pkt
, 27, sfd
->filename
);
5049 yahoo_packet_hash(pkt
, 249, "3");
5050 yahoo_packet_hash(pkt
, 251, sfd
->token
);
5052 yahoo_send_packet(yid
, pkt
, 0);
5054 yahoo_packet_free(pkt
);
5056 yahoo_init_ft_recv(yid
->yd
, sfd
);
5059 static void yahoo_process_filetransferaccept(struct yahoo_input_data
*yid
,
5060 struct yahoo_packet
*pkt
)
5063 struct send_file_data
*sfd
;
5065 char *filename
= NULL
;
5069 for (l
= pkt
->hash
; l
; l
= l
->next
) {
5070 struct yahoo_pair
*pair
= l
->data
;
5071 switch (pair
->key
) {
5076 /* Me... don't care */
5084 token
= pair
->value
;
5087 filename
= pair
->value
;
5092 sfd
= yahoo_get_active_transfer(id
);
5095 sfd
->token
= strdup(token
);
5097 yahoo_file_transfer_upload(yid
->yd
, sfd
);
5100 YAHOO_CALLBACK(ext_yahoo_file_transfer_done
)
5101 (yid
->yd
->client_id
, YAHOO_FILE_TRANSFER_UNKNOWN
,
5104 yahoo_remove_active_transfer(sfd
);
5108 static void yahoo_process_filetransferinfo(struct yahoo_input_data
*yid
,
5109 struct yahoo_packet
*pkt
)
5113 char *filename
= NULL
;
5116 char *ip_addr
= NULL
;
5118 struct send_file_data
*sfd
;
5120 for (l
= pkt
->hash
; l
; l
= l
->next
) {
5121 struct yahoo_pair
*pair
= l
->data
;
5122 switch (pair
->key
) {
5128 /* Me... don't care */
5136 ip_addr
= pair
->value
;
5139 token
= pair
->value
;
5142 filename
= pair
->value
;
5147 sfd
= yahoo_get_active_transfer(id
);
5150 sfd
->token
= strdup(token
);
5151 sfd
->ip_addr
= strdup(ip_addr
);
5153 yahoo_file_transfer_accept(yid
, sfd
);
5156 YAHOO_CALLBACK(ext_yahoo_file_transfer_done
)
5157 (yid
->yd
->client_id
, YAHOO_FILE_TRANSFER_UNKNOWN
,
5160 yahoo_remove_active_transfer(sfd
);
5164 static void yahoo_send_filetransferinfo(struct yahoo_data
*yd
,
5165 struct send_file_data
*sfd
)
5167 struct yahoo_input_data
*yid
;
5168 struct yahoo_packet
*pkt
;
5170 yid
= find_input_by_id_and_type(yd
->client_id
, YAHOO_CONNECTION_PAGER
);
5171 sfd
->ip_addr
= YAHOO_CALLBACK(ext_yahoo_get_ip_addr
)("relay.yahoo.com");
5173 if (!sfd
->ip_addr
) {
5174 YAHOO_CALLBACK(ext_yahoo_file_transfer_done
)
5175 (yd
->client_id
, YAHOO_FILE_TRANSFER_RELAY
, sfd
->data
);
5177 yahoo_remove_active_transfer(sfd
);
5182 pkt
= yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFERINFO
,
5183 YPACKET_STATUS_DEFAULT
, yd
->session_id
);
5185 yahoo_packet_hash(pkt
, 1, yd
->user
);
5186 yahoo_packet_hash(pkt
, 5, sfd
->who
);
5187 yahoo_packet_hash(pkt
, 265, sfd
->id
);
5188 yahoo_packet_hash(pkt
, 27, sfd
->filename
);
5189 yahoo_packet_hash(pkt
, 249, "3");
5190 yahoo_packet_hash(pkt
, 250, sfd
->ip_addr
);
5192 yahoo_send_packet(yid
, pkt
, 0);
5194 yahoo_packet_free(pkt
);
5197 static void yahoo_process_filetransfer(struct yahoo_input_data
*yid
,
5198 struct yahoo_packet
*pkt
)
5202 char *filename
= NULL
;
5207 struct yahoo_data
*yd
= yid
->yd
;
5209 struct send_file_data
*sfd
;
5211 for (l
= pkt
->hash
; l
; l
= l
->next
) {
5212 struct yahoo_pair
*pair
= l
->data
;
5213 switch (pair
->key
) {
5218 /* Me... don't care */
5221 action
= atoi(pair
->value
);
5226 case 266: /* Don't know */
5228 case 302: /* Start Data? */
5233 filename
= pair
->value
;
5236 size
= atoi(pair
->value
);
5240 case 301: /* End Data? */
5248 if (action
== YAHOO_FILE_TRANSFER_INIT
) {
5249 /* Received a FT request from buddy */
5250 sfd
= y_new0(struct send_file_data
, 1);
5252 sfd
->client_id
= yd
->client_id
;
5253 sfd
->id
= strdup(id
);
5254 sfd
->who
= strdup(who
);
5255 sfd
->filename
= strdup(filename
);
5258 yahoo_add_active_transfer(sfd
);
5260 YAHOO_CALLBACK(ext_yahoo_got_file
) (yd
->client_id
, yd
->user
,
5261 who
, msg
, filename
, size
, sfd
->id
);
5264 /* Response to our request */
5265 sfd
= yahoo_get_active_transfer(id
);
5267 if (sfd
&& action
== YAHOO_FILE_TRANSFER_ACCEPT
) {
5268 yahoo_send_filetransferinfo(yd
, sfd
);
5270 else if (!sfd
|| action
== YAHOO_FILE_TRANSFER_REJECT
) {
5271 YAHOO_CALLBACK(ext_yahoo_file_transfer_done
)
5272 (yd
->client_id
, YAHOO_FILE_TRANSFER_REJECT
,
5275 yahoo_remove_active_transfer(sfd
);
5280 void yahoo_send_file(int id
, const char *who
, const char *msg
,
5281 const char *name
, unsigned long size
,
5282 yahoo_get_fd_callback callback
, void *data
)
5284 struct yahoo_packet
*pkt
= NULL
;
5286 struct yahoo_input_data
*yid
;
5287 struct yahoo_data
*yd
;
5288 struct send_file_data
*sfd
;
5290 yid
= find_input_by_id_and_type(id
, YAHOO_CONNECTION_PAGER
);
5291 yd
= find_conn_by_id(id
);
5292 sfd
= y_new0(struct send_file_data
, 1);
5294 sfd
->client_id
= id
;
5295 sfd
->id
= yahoo_get_random();
5296 sfd
->who
= strdup(who
);
5297 sfd
->filename
= strdup(name
);
5299 sfd
->callback
= callback
;
5302 yahoo_add_active_transfer(sfd
);
5307 pkt
= yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER
,
5308 YPACKET_STATUS_DEFAULT
, yd
->session_id
);
5310 snprintf(size_str
, sizeof(size_str
), "%ld", size
);
5312 yahoo_packet_hash(pkt
, 1, yd
->user
);
5313 yahoo_packet_hash(pkt
, 5, who
);
5314 yahoo_packet_hash(pkt
, 265, sfd
->id
);
5315 yahoo_packet_hash(pkt
, 222, "1");
5316 yahoo_packet_hash(pkt
, 266, "1");
5317 yahoo_packet_hash(pkt
, 302, "268");
5318 yahoo_packet_hash(pkt
, 300, "268");
5319 yahoo_packet_hash(pkt
, 27, name
);
5320 yahoo_packet_hash(pkt
, 28, size_str
);
5321 yahoo_packet_hash(pkt
, 301, "268");
5322 yahoo_packet_hash(pkt
, 303, "268");
5324 yahoo_send_packet(yid
, pkt
, 0);
5326 yahoo_packet_free(pkt
);
5329 void yahoo_send_file_transfer_response(int client_id
, int response
, char *id
, void *data
)
5331 struct yahoo_packet
*pkt
= NULL
;
5333 struct yahoo_input_data
*yid
;
5335 struct send_file_data
*sfd
= yahoo_get_active_transfer(id
);
5339 yid
= find_input_by_id_and_type(client_id
, YAHOO_CONNECTION_PAGER
);
5341 pkt
= yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER
,
5342 YPACKET_STATUS_DEFAULT
, yid
->yd
->session_id
);
5344 snprintf(resp
, sizeof(resp
), "%d", response
);
5346 yahoo_packet_hash(pkt
, 1, yid
->yd
->user
);
5347 yahoo_packet_hash(pkt
, 5, sfd
->who
);
5348 yahoo_packet_hash(pkt
, 265, sfd
->id
);
5349 yahoo_packet_hash(pkt
, 222, resp
);
5351 yahoo_send_packet(yid
, pkt
, 0);
5353 yahoo_packet_free(pkt
);
5355 if(response
== YAHOO_FILE_TRANSFER_REJECT
)
5356 yahoo_remove_active_transfer(sfd
);
5359 static void yahoo_process_ft_connection(struct yahoo_input_data
*yid
, int over
)
5361 struct send_file_data
*sfd
;
5362 struct yahoo_data
*yd
= yid
->yd
;
5364 sfd
= yahoo_get_active_transfer_with_yid(yid
);
5367 LOG(("Something funny happened. yid %p has no sfd.\n", yid
));
5372 * We want to handle only the complete data with HEAD since we don't
5373 * want a situation where both the GET and HEAD are active.
5374 * With SEND, we really can't do much with partial response
5376 if ((sfd
->state
== FT_STATE_HEAD
|| sfd
->state
== FT_STATE_SEND
)
5380 if (sfd
->state
== FT_STATE_HEAD
) {
5384 char *sender_enc
= NULL
, *recv_enc
= NULL
, *token_enc
= NULL
;
5386 struct yahoo_input_data
*yid_ft
=
5387 y_new0(struct yahoo_input_data
, 1);
5389 yid_ft
->yd
= yid
->yd
;
5390 yid_ft
->type
= YAHOO_CONNECTION_FT
;
5392 inputs
= y_list_prepend(inputs
, yid_ft
);
5394 sfd
->state
= FT_STATE_RECV
;
5396 token_enc
= yahoo_urlencode(sfd
->token
);
5397 sender_enc
= yahoo_urlencode(sfd
->who
);
5398 recv_enc
= yahoo_urlencode(yd
->user
);
5400 snprintf(url
, sizeof(url
),
5401 "http://%s/relay?token=%s&sender=%s&recver=%s", sfd
->ip_addr
,
5402 token_enc
, sender_enc
, recv_enc
);
5404 snprintf(buff
, sizeof(buff
), "Y=%s; T=%s", yd
->cookie_y
,
5408 yahoo_http_get(yd
->client_id
, url
, buff
, 1, 1,
5409 _yahoo_http_connected
, yid_ft
);
5415 else if (sfd
->state
== FT_STATE_RECV
||
5416 sfd
->state
== FT_STATE_RECV_START
) {
5418 unsigned char *data_begin
= NULL
;
5420 if (yid
->rxlen
== 0)
5421 yahoo_remove_active_transfer(sfd
);
5423 if (sfd
->state
!= FT_STATE_RECV_START
&&
5425 (unsigned char *)strstr((char *)yid
->rxqueue
,
5428 sfd
->state
= FT_STATE_RECV_START
;
5430 yid
->rxlen
-= 4+(data_begin
-yid
->rxqueue
)/sizeof(char);
5434 YAHOO_CALLBACK(ext_yahoo_got_ft_data
)
5435 (yd
->client_id
, data_begin
,
5436 yid
->rxlen
, sfd
->data
);
5438 else if (sfd
->state
== FT_STATE_RECV_START
)
5439 YAHOO_CALLBACK(ext_yahoo_got_ft_data
) (yd
->client_id
,
5440 yid
->rxqueue
, yid
->rxlen
, sfd
->data
);
5443 yid
->rxqueue
= NULL
;
5446 else if (sfd
->state
== FT_STATE_SEND
) {
5447 /* Sent file completed */
5449 char *off
= strstr((char *)yid
->rxqueue
, "Content-Length: ");
5456 if (len
< sfd
->size
)
5457 YAHOO_CALLBACK(ext_yahoo_file_transfer_done
)
5459 YAHOO_FILE_TRANSFER_FAILED
, sfd
->data
);
5461 YAHOO_CALLBACK(ext_yahoo_file_transfer_done
)
5463 YAHOO_FILE_TRANSFER_DONE
, sfd
->data
);
5465 yahoo_remove_active_transfer(sfd
);
5469 /* End File Transfer */
5471 enum yahoo_status
yahoo_current_status(int id
)
5473 struct yahoo_data
*yd
= find_conn_by_id(id
);
5475 return YAHOO_STATUS_OFFLINE
;
5476 return yd
->current_status
;
5479 const YList
*yahoo_get_buddylist(int id
)
5481 struct yahoo_data
*yd
= find_conn_by_id(id
);
5487 const YList
*yahoo_get_ignorelist(int id
)
5489 struct yahoo_data
*yd
= find_conn_by_id(id
);
5495 const YList
*yahoo_get_identities(int id
)
5497 struct yahoo_data
*yd
= find_conn_by_id(id
);
5500 return yd
->identities
;
5503 const char *yahoo_get_cookie(int id
, const char *which
)
5505 struct yahoo_data
*yd
= find_conn_by_id(id
);
5508 if (!strncasecmp(which
, "y", 1))
5509 return yd
->cookie_y
;
5510 if (!strncasecmp(which
, "b", 1))
5511 return yd
->cookie_b
;
5512 if (!strncasecmp(which
, "t", 1))
5513 return yd
->cookie_t
;
5514 if (!strncasecmp(which
, "c", 1))
5515 return yd
->cookie_c
;
5516 if (!strncasecmp(which
, "login", 5))
5517 return yd
->login_cookie
;
5521 const char *yahoo_get_profile_url(void)